9ab54f1008b466de2d4384b68d7ce5abb572e80b
[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 libraries 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 *fcb, Keydesc2 *pkeydesc2, char *record,
50             char *oldrecord, Recno recnum, char *newkey)
51 {
52     char                keybuf1[MAXKEYSIZE];
53     char                keybuf2[MAXKEYSIZE];
54     Btree               *btree;
55     char                *pkey;
56
57     /*
58      * Special case when there is no primary key.
59      */
60     if (pkeydesc2->k2_nparts == 0)
61         return (ISOK);
62
63     /* Get old key value. */
64     memset((char *)keybuf1, 0, pkeydesc2->k2_len);
65     _iskey_extract(pkeydesc2, oldrecord, keybuf1);
66     strecno(recnum, keybuf1);
67     
68     /* Get new key value. */
69     memset((char *)keybuf2, 0, pkeydesc2->k2_len);
70     _iskey_extract(pkeydesc2, record, keybuf2);
71     strecno(recnum, keybuf2);
72
73   
74     /*
75      * See if the key changed.
76      */
77     if (memcmp(keybuf1, keybuf2, pkeydesc2->k2_len)) {
78         
79         /*
80          * Delete the old key entry from B tree.
81          */
82         btree = _isbtree_create(fcb, pkeydesc2);
83         _isbtree_search(btree, keybuf1);
84
85         if (ALLOWS_DUPS2(pkeydesc2)) {
86             
87             /*
88              * We must now scan all the duplicates till we found one with
89              * matching recno. We are positioned just before the first duplicate.
90              * Remember that the duplicates are ordered by their serial number.
91              *
92              * If too many duplicate entries exists, the performance will be
93              * poor.
94              */
95             while ((pkey = _isbtree_next(btree)) != NULL) {
96                 if (ldrecno(pkey + KEY_RECNO_OFF) == recnum)
97                     break;                           /* We found the entry */
98             }
99             
100             if (pkey == NULL) 
101                 _isfatal_error("_del1key() cannot find entry in B tree");
102             
103             _isbtree_remove(btree);
104         }
105         else {
106             
107             if ((pkey = _isbtree_current(btree)) == NULL ||
108                 ldrecno(pkey + KEY_RECNO_OFF) != recnum)
109                 _isfatal_error("_del1key() cannot find entry in B tree");
110             
111             _isbtree_remove(btree);
112         }
113         _isbtree_destroy(btree);
114
115         /*
116          * Insert new key entry into B tree.
117          */
118         
119         btree = _isbtree_create(fcb, pkeydesc2);
120         
121         if (ALLOWS_DUPS2(pkeydesc2)) {
122             
123             /* 
124              * Duplicates allowed on this key. 
125              * Try to read the last duplicate (with the highest serial number).
126              * If such duplicate exists, the inserted key entry will be
127              * assigned next higher value for duplicate serial number.
128              * If there is no such duplicate, assign duplicate serial number 1.
129              */
130             strecno(recnum, keybuf2 + KEY_RECNO_OFF);
131             memcpy( keybuf2 + KEY_DUPS_OFF,(char *)ismaxlong, LONGSIZE);
132             _isbtree_search(btree, keybuf2);
133             
134             if ((pkey = _isbtree_current(btree)) != NULL &&
135                 memcmp(pkey + RECNOSIZE + DUPIDSIZE, 
136                        keybuf2 + RECNOSIZE + DUPIDSIZE,
137                        pkeydesc2->k2_len - RECNOSIZE - DUPIDSIZE) == 0) {
138                 
139                 /*
140                  * A duplicate exists. Assign +1 value for the new serial
141                  * number.
142                  */
143                 stlong(ldlong(pkey + KEY_DUPS_OFF) + 1, keybuf2 + KEY_DUPS_OFF);
144
145                 /*
146                  * Indicate that there are allowed duplicate key values.
147                  */
148                 isdupl = 1;
149             }
150             else {
151                 
152                 /*
153                  * This is the first duplicate. Assign serial number 1.
154                  */
155                 stlong(1L, keybuf2 + KEY_DUPS_OFF);
156             }
157             
158             _isbtree_insert(btree, keybuf2);
159             _isbtree_destroy(btree);
160         }
161
162         
163         
164         else {
165             
166             /* Duplicates not allowed on this key.
167              * Set TID part to maximum value, causing the search path 
168              * to point just past the possible duplicate in the key file 
169              * If there is no duplicate, this is the correct spot to 
170              * insert the new key entry.                              
171              */
172             
173             memcpy( keybuf2 + KEY_RECNO_OFF,(char *)ismaxlong, LONGSIZE);
174             _isbtree_search (btree, keybuf2);
175             
176             if ((pkey = _isbtree_current(btree)) != NULL &&
177                 memcmp(pkey + RECNOSIZE, keybuf2 + RECNOSIZE,
178                        pkeydesc2->k2_len - RECNOSIZE) == 0) {
179                 _isbtree_destroy(btree);
180                 return (EDUPL);
181             }
182             
183             strecno(recnum, keybuf2 + KEY_RECNO_OFF);
184             _isbtree_insert(btree, keybuf2);
185             _isbtree_destroy(btree);
186         }
187     }
188
189     /*
190      * Return new key position.
191      */
192     if (newkey != NULL)
193         memcpy( newkey,keybuf2, pkeydesc2->k2_len);
194         
195     return (ISOK);
196 }
197