Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / tt / mini_isam / ischange1key.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                   */
24 /*%%  (c) Copyright 1993, 1994 International Business Machines Corp.     */
25 /*%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                    */
26 /*%%  (c) Copyright 1993, 1994 Novell, Inc.                              */
27 /*%%  $XConsortium: ischange1key.c /main/3 1995/10/23 11:36:41 rswiston $                                                        */
28 #ifndef lint
29 static char sccsid[] = "@(#)ischange1key.c 1.3 89/07/17 Copyr 1988 Sun Micro";
30 #endif
31 /*
32  * Copyright (c) 1988 by Sun Microsystems, Inc.
33  */
34
35 /*
36  * ischange1key.c
37  *
38  * Description: 
39  *      Update an index if necessary.
40  *      
41  *
42  */
43
44 #include "isam_impl.h"
45
46 extern long *ismaxlong;
47
48 int
49 _change1key(fcb, pkeydesc2, record, oldrecord, recnum, newkey)
50     Fcb                 *fcb;   
51     Keydesc2            *pkeydesc2;
52     char                *record;
53     char                *oldrecord;
54     Recno               recnum;
55     char                *newkey;
56 {
57     char                keybuf1[MAXKEYSIZE];
58     char                keybuf2[MAXKEYSIZE];
59     Btree               *btree;
60     char                *pkey;
61
62     /*
63      * Special case when there is no primary key.
64      */
65     if (pkeydesc2->k2_nparts == 0)
66         return (ISOK);
67
68     /* Get old key value. */
69     memset((char *)keybuf1, 0, pkeydesc2->k2_len);
70     _iskey_extract(pkeydesc2, oldrecord, keybuf1);
71     strecno(recnum, keybuf1);
72     
73     /* Get new key value. */
74     memset((char *)keybuf2, 0, pkeydesc2->k2_len);
75     _iskey_extract(pkeydesc2, record, keybuf2);
76     strecno(recnum, keybuf2);
77
78   
79     /*
80      * See if the key changed.
81      */
82     if (memcmp(keybuf1, keybuf2, pkeydesc2->k2_len)) {
83         
84         /*
85          * Delete the old key entry from B tree.
86          */
87         btree = _isbtree_create(fcb, pkeydesc2);
88         _isbtree_search(btree, keybuf1);
89
90         if (ALLOWS_DUPS2(pkeydesc2)) {
91             
92             /*
93              * We must now scan all the duplicates till we found one with
94              * matching recno. We are positioned just before the first duplicate.
95              * Remember that the duplicates are ordered by their serial number.
96              *
97              * If too many duplicate entries exists, the performance will be
98              * poor.
99              */
100             while ((pkey = _isbtree_next(btree)) != NULL) {
101                 if (ldrecno(pkey + KEY_RECNO_OFF) == recnum)
102                     break;                           /* We found the entry */
103             }
104             
105             if (pkey == NULL) 
106                 _isfatal_error("_del1key() cannot find entry in B tree");
107             
108             _isbtree_remove(btree);
109         }
110         else {
111             
112             if ((pkey = _isbtree_current(btree)) == NULL ||
113                 ldrecno(pkey + KEY_RECNO_OFF) != recnum)
114                 _isfatal_error("_del1key() cannot find entry in B tree");
115             
116             _isbtree_remove(btree);
117         }
118         _isbtree_destroy(btree);
119
120         /*
121          * Insert new key entry into B tree.
122          */
123         
124         btree = _isbtree_create(fcb, pkeydesc2);
125         
126         if (ALLOWS_DUPS2(pkeydesc2)) {
127             
128             /* 
129              * Duplicates allowed on this key. 
130              * Try to read the last duplicate (with the highest serial number).
131              * If such duplicate exists, the inserted key entry will be
132              * assigned next higher value for duplicate serial number.
133              * If there is no such duplicate, assign duplicate serial number 1.
134              */
135             strecno(recnum, keybuf2 + KEY_RECNO_OFF);
136             memcpy( keybuf2 + KEY_DUPS_OFF,(char *)ismaxlong, LONGSIZE);
137             _isbtree_search(btree, keybuf2);
138             
139             if ((pkey = _isbtree_current(btree)) != NULL &&
140                 memcmp(pkey + RECNOSIZE + DUPIDSIZE, 
141                        keybuf2 + RECNOSIZE + DUPIDSIZE,
142                        pkeydesc2->k2_len - RECNOSIZE - DUPIDSIZE) == 0) {
143                 
144                 /*
145                  * A duplicate exists. Assign +1 value for the new serial
146                  * number.
147                  */
148                 stlong(ldlong(pkey + KEY_DUPS_OFF) + 1, keybuf2 + KEY_DUPS_OFF);
149
150                 /*
151                  * Indicate that there are allowed duplicate key values.
152                  */
153                 isdupl = 1;
154             }
155             else {
156                 
157                 /*
158                  * This is the first duplicate. Assign serial number 1.
159                  */
160                 stlong(1L, keybuf2 + KEY_DUPS_OFF);
161             }
162             
163             _isbtree_insert(btree, keybuf2);
164             _isbtree_destroy(btree);
165         }
166
167         
168         
169         else {
170             
171             /* Duplicates not allowed on this key.
172              * Set TID part to maximum value, causing the search path 
173              * to point just past the possible duplicate in the key file 
174              * If there is no duplicate, this is the correct spot to 
175              * insert the new key entry.                              
176              */
177             
178             memcpy( keybuf2 + KEY_RECNO_OFF,(char *)ismaxlong, LONGSIZE);
179             _isbtree_search (btree, keybuf2);
180             
181             if ((pkey = _isbtree_current(btree)) != NULL &&
182                 memcmp(pkey + RECNOSIZE, keybuf2 + RECNOSIZE,
183                        pkeydesc2->k2_len - RECNOSIZE) == 0) {
184                 _isbtree_destroy(btree);
185                 return (EDUPL);
186             }
187             
188             strecno(recnum, keybuf2 + KEY_RECNO_OFF);
189             _isbtree_insert(btree, keybuf2);
190             _isbtree_destroy(btree);
191         }
192     }
193
194     /*
195      * Return new key position.
196      */
197     if (newkey != NULL)
198         memcpy( newkey,keybuf2, pkeydesc2->k2_len);
199         
200     return (ISOK);
201 }
202