]>
Commit | Line | Data |
---|---|---|
68bbc9c3 | 1 | /* $Header$ |
2 | * | |
3 | * User interface routines for dbck (Moira database consistency checker) | |
4 | * | |
5 | * (c) Copyright 1988 by the Massachusetts Institute of Technology. | |
6 | * For copying and distribution information, please see the file | |
7 | * <mit-copyright.h>. | |
8 | */ | |
9 | ||
10 | #include <mit-copyright.h> | |
11 | #include <moira.h> | |
12 | #include <stdio.h> | |
13 | #include "dbck.h" | |
14 | ||
208a4f4a | 15 | EXEC SQL INCLUDE sqlca; /* SQL Communications Area */ |
16 | EXEC SQL INCLUDE sqlda; /* SQL Descriptor Area */ | |
17 | ||
18 | #define SQLDA_RETVALS | |
19 | typedef IISQLDA_TYPE(DBCK_SQLDA,DBCK_SQLDA_T,SQLDA_RETVALS); | |
20 | DBCK_SQLDA_T SQLDA; | |
68bbc9c3 | 21 | |
208a4f4a | 22 | static char fix_qc_rcsid[] = "$Header$"; |
68bbc9c3 | 23 | |
208a4f4a | 24 | EXEC SQL BEGIN DECLARE SECTION; |
25 | char *_table; | |
26 | char *_idfield; | |
27 | char stmt_buf[500]; | |
28 | EXEC SQL END DECLARE SECTION; | |
68bbc9c3 | 29 | |
208a4f4a | 30 | generic_ffunc(id) |
31 | EXEC SQL BEGIN DECLARE SECTION; | |
32 | int id; | |
33 | EXEC SQL END DECLARE SECTION; | |
34 | { | |
35 | EXEC SQL BEGIN DECLARE SECTION; | |
36 | int rowcount; | |
37 | EXEC SQL END DECLARE SECTION; | |
68bbc9c3 | 38 | |
208a4f4a | 39 | /* delete _table where _table._idfield = id */ |
40 | sprintf(stmt_buf,"DELETE FROM %s WHERE %s.%s = %d", | |
41 | _table,_table,_idfield,id); | |
42 | EXEC SQL EXECUTE IMMEDIATE :stmt_buf; | |
43 | /* inquire_equel(rowcount = "rowcount") */ | |
44 | EXEC SQL INQUIRE_SQL(:rowcount = rowcount); | |
68bbc9c3 | 45 | if (rowcount > 0) |
46 | printf("%d entr%s deleted\n", rowcount, rowcount==1?"y":"ies"); | |
47 | else | |
48 | printf("Not deleted\n"); | |
49 | modified(_table); | |
208a4f4a | 50 | } |
68bbc9c3 | 51 | |
52 | ||
53 | generic_delete(sq, pfunc, table, idfield, preen) | |
54 | struct save_queue *sq; | |
55 | void (*pfunc)(); | |
56 | char *table, *idfield; | |
57 | int preen; | |
58 | { | |
59 | _table = table; | |
60 | _idfield = idfield; | |
61 | generic_fix(sq, pfunc, "Delete", generic_ffunc, preen); | |
62 | } | |
63 | ||
64 | ||
65 | single_delete(table, idfield, id) | |
66 | char *table, *idfield; | |
67 | int id; | |
68 | { | |
69 | _table = table; | |
70 | _idfield = idfield; | |
71 | generic_ffunc(id); | |
72 | } | |
73 | ||
74 | ||
208a4f4a | 75 | zero_fix(tbl, zrfield, idfield, id) |
76 | EXEC SQL BEGIN DECLARE SECTION; | |
77 | char *tbl, *zrfield, *idfield; | |
78 | int id; | |
79 | EXEC SQL END DECLARE SECTION; | |
80 | { | |
81 | EXEC SQL BEGIN DECLARE SECTION; | |
82 | int rowcount; | |
83 | EXEC SQL END DECLARE SECTION; | |
68bbc9c3 | 84 | |
208a4f4a | 85 | /* replace tbl (zrfield = 0) where table.idfield = id */ |
86 | sprintf(stmt_buf,"UPDATE %s SET %d = 0 WHERE %s.%s = %d", | |
87 | tbl,zrfield,tbl,idfield,id); | |
88 | EXEC SQL EXECUTE IMMEDIATE :stmt_buf; | |
89 | /* inquire_equel(rowcount = "rowcount") */ | |
90 | EXEC SQL INQUIRE_SQL(:rowcount = rowcount); | |
68bbc9c3 | 91 | if (rowcount > 0) |
92 | printf("%d entr%s fixed\n", rowcount, rowcount==1?"y":"ies"); | |
93 | else | |
94 | printf("Not fixed\n"); | |
208a4f4a | 95 | modified(tbl); |
96 | } | |
68bbc9c3 | 97 | |
98 | ||
99 | int single_fix(msg, preen) | |
100 | char *msg; | |
101 | int preen; | |
102 | { | |
103 | if (mode == MODE_PREEN) | |
104 | return(preen); | |
105 | ||
106 | switch (mode) { | |
107 | case MODE_ASK: | |
108 | if (!prompt(msg)) | |
109 | break; | |
110 | case MODE_YES: | |
111 | return(1); | |
112 | break; | |
113 | case MODE_NO: | |
114 | ; | |
115 | } | |
116 | return(0); | |
117 | } | |
118 | ||
119 | ||
120 | generic_fix(sq, pfunc, msg, ffunc, preen) | |
121 | struct save_queue *sq; | |
122 | char *msg; | |
123 | int (*pfunc)(), (*ffunc)(); | |
124 | int preen; | |
125 | { | |
126 | int id; | |
127 | ||
128 | while (sq_get_data(sq, &id)) { | |
129 | if ((*pfunc)(id) == 0 && single_fix(msg, preen)) | |
130 | (*ffunc)(id); | |
131 | } | |
132 | sq_destroy(sq); | |
133 | } | |
134 | ||
135 | ||
136 | int prompt(msg) | |
137 | char *msg; | |
138 | { | |
139 | char buf[BUFSIZ]; | |
208a4f4a | 140 | EXEC SQL BEGIN DECLARE SECTION; |
141 | extern int dcmenable; | |
142 | EXEC SQL END DECLARE SECTION; | |
68bbc9c3 | 143 | |
144 | while (1) { | |
145 | printf("%s (Y/N/Q)? ", msg); | |
146 | fflush(stdout); | |
147 | gets(buf); | |
148 | if (buf[0] == 'Y' || buf[0] == 'y') | |
149 | return(1); | |
150 | if (buf[0] == 'N' || buf[0] == 'n') | |
151 | return(0); | |
152 | if (buf[0] == 'Q' || buf[0] == 'q') { | |
153 | if (prompt("Are you sure you want to quit")) { | |
154 | if (prompt("Save database changes")) { | |
208a4f4a | 155 | /* end transaction */ |
156 | EXEC SQL COMMIT WORK; | |
68bbc9c3 | 157 | cleanup(); |
158 | exit(0); | |
159 | } else { | |
208a4f4a | 160 | /* abort */ |
161 | EXEC SQL ROLLBACK WORK; | |
162 | /* replace values (value = dcmenable) | |
163 | * where values.name = "dcm_enable" */ | |
164 | EXEC SQL UPDATE numvalues SET value = :dcmenable | |
165 | WHERE name='dcm_enable'; | |
166 | /* exit */ | |
167 | /* No equivalent (?) */ | |
68bbc9c3 | 168 | exit(1); |
169 | } | |
170 | } | |
171 | } | |
172 | } | |
173 | } | |
174 | ||
175 | ||
176 | /** | |
177 | ** set_next_object_id - set next object id in values table | |
178 | ** | |
179 | ** Inputs: object - object name in values table and in objects | |
180 | ** table - name of table objects are found in | |
181 | ** | |
182 | ** - called before an APPEND operation to set the next object id to | |
183 | ** be used for the new record to the next free value | |
184 | ** | |
185 | **/ | |
186 | ||
208a4f4a | 187 | int set_next_object_id(object, tablename) |
68bbc9c3 | 188 | char *object; |
208a4f4a | 189 | char *tablename; |
190 | { | |
191 | EXEC SQL BEGIN DECLARE SECTION; | |
192 | char *name, *tbl; | |
193 | int rowcount, existence, value; | |
194 | EXEC SQL END DECLARE SECTION; | |
68bbc9c3 | 195 | |
196 | name = object; | |
208a4f4a | 197 | tbl = tablename; |
198 | /* range of v is values | |
199 | * repeat retrieve (value = v.#value) where v.#name = @name */ | |
200 | EXEC SQL REPEATED SELECT value INTO :value FROM numvalues | |
201 | WHERE name = :name; | |
202 | EXEC SQL INQUIRE_SQL(:rowcount = rowcount); | |
68bbc9c3 | 203 | if (rowcount != 1) |
204 | return(MR_NO_ID); | |
205 | ||
208a4f4a | 206 | /* retrieve (existence = any(tbl.name where tbl.name = value)) */ |
207 | SQLDA.sqlvar[0].sqldata=(void *)&rowcount; | |
208 | sprintf(stmt_buf,"SELECT COUNT (*) FROM %s WHERE %s=%d",tbl,name,value); | |
209 | EXEC SQL PREPARE stmt INTO :&SQLDA USING NAMES FROM :stmt_buf; | |
210 | if(sqlca.sqlcode) | |
211 | return(MR_INTERNAL); | |
212 | EXEC SQL DECLARE foo CURSOR FOR stmt; | |
213 | EXEC SQL OPEN foo; | |
214 | EXEC SQL FETCH foo USING DESCRIPTOR :&SQLDA; | |
215 | if (sqlca.sqlcode < 0) return(MR_INTERNAL); | |
216 | if (sqlca.sqlcode == 100) existence=0; else existence=1; | |
217 | EXEC SQL CLOSE foo; | |
218 | ||
68bbc9c3 | 219 | if (rowcount != 1) |
220 | return(MR_NO_ID); | |
208a4f4a | 221 | while (existence) { |
68bbc9c3 | 222 | value++; |
223 | if (value > MAX_ID_VALUE) | |
224 | value = MIN_ID_VALUE; | |
208a4f4a | 225 | /* retrieve (existence = any(tbl.name where tbl.name = value)) */ |
226 | sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s=%d",name,tbl,name,value); | |
227 | EXEC SQL PREPARE stmt INTO :&SQLDA USING NAMES FROM :stmt_buf; | |
228 | if(sqlca.sqlcode) | |
229 | return(MR_INTERNAL); | |
230 | EXEC SQL DECLARE bar CURSOR FOR stmt; | |
231 | EXEC SQL OPEN bar; | |
232 | EXEC SQL FETCH bar USING DESCRIPTOR :&SQLDA; | |
233 | if (sqlca.sqlcode != 0) break; | |
234 | EXEC SQL CLOSE bar; | |
68bbc9c3 | 235 | } |
208a4f4a | 236 | EXEC SQL CLOSE bar; |
68bbc9c3 | 237 | |
238 | printf("setting ID %s to %d\n", name, value); | |
208a4f4a | 239 | /* repeat replace v (#value = @value) where v.#name = @name */ |
240 | EXEC SQL REPEATED UPDATE numvalues SET value = :value | |
241 | WHERE name = :name; | |
68bbc9c3 | 242 | modified("values"); |
243 | return(MR_SUCCESS); | |
208a4f4a | 244 | } |
245 | ||
246 | ||
247 | generic_fix_id(tbl, idfield, txtfield, oldid, name) | |
248 | EXEC SQL BEGIN DECLARE SECTION; | |
249 | char *tbl; | |
250 | char *idfield; | |
251 | char *txtfield; | |
252 | int oldid; | |
253 | char *name; | |
254 | EXEC SQL END DECLARE SECTION; | |
255 | { | |
256 | EXEC SQL BEGIN DECLARE SECTION; | |
257 | int rowcount, id, temp; | |
258 | EXEC SQL END DECLARE SECTION; | |
259 | ||
260 | set_next_object_id(tbl, idfield); | |
261 | /* retrieve (id = values.value) where values.#name = idfield */ | |
262 | EXEC SQL SELECT value INTO :id FROM numvalues | |
263 | WHERE name = :idfield; | |
264 | /* replace tbl (idfield = values.value) where values.#name = idfield and | |
265 | * tbl.idfield = oldid and tbl.txtfield = name | |
266 | */ | |
267 | EXEC SQL SELECT value INTO :temp FROM numvalues | |
268 | WHERE name = :idfield; | |
269 | sprintf(stmt_buf,"UPDATE %s SET %s = %d WHERE %s=%d AND %s='%s'", | |
270 | tbl,idfield,temp,idfield,oldid,txtfield,name); | |
271 | EXEC SQL EXECUTE IMMEDIATE :stmt_buf; | |
272 | EXEC SQL INQUIRE_SQL(:rowcount = rowcount); | |
68bbc9c3 | 273 | if (rowcount == 1) |
274 | printf("Fixed\n"); | |
275 | else | |
276 | printf("Not fixed, rowcount = %d\n", rowcount); | |
208a4f4a | 277 | modified(tbl); |
68bbc9c3 | 278 | return(id); |
208a4f4a | 279 | } |