]> andersk Git - moira.git/blob - dbck/fix.dc
SQL port completed.
[moira.git] / dbck / fix.dc
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
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;
21
22 static char fix_qc_rcsid[] = "$Header$";
23
24 EXEC SQL BEGIN DECLARE SECTION; 
25 char *_table;
26 char *_idfield;
27 char stmt_buf[500];
28 EXEC SQL END DECLARE SECTION; 
29
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; 
38
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); 
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);
50 }
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
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; 
84
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); 
91     if (rowcount > 0)
92       printf("%d entr%s fixed\n", rowcount, rowcount==1?"y":"ies");
93     else
94       printf("Not fixed\n");
95     modified(tbl);
96 }
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];
140     EXEC SQL BEGIN DECLARE SECTION; 
141     extern int dcmenable;
142     EXEC SQL END DECLARE SECTION; 
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")) {
155 /*                  end transaction */
156                     EXEC SQL COMMIT WORK;
157                     cleanup();
158                     exit(0);
159                 } else {
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 (?) */
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
187 int set_next_object_id(object, tablename)
188     char *object;
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; 
195
196     name = object;
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); 
203     if (rowcount != 1)
204         return(MR_NO_ID);
205
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
219     if (rowcount != 1)
220         return(MR_NO_ID);
221     while (existence) {
222         value++;
223         if (value > MAX_ID_VALUE)
224             value = MIN_ID_VALUE;
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;
235     }
236     EXEC SQL CLOSE bar; 
237
238     printf("setting ID %s to %d\n", name, value);
239 /*  repeat replace v (#value = @value) where v.#name = @name */
240     EXEC SQL REPEATED UPDATE numvalues SET value = :value
241         WHERE name = :name;
242     modified("values");
243     return(MR_SUCCESS);
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); 
273     if (rowcount == 1)
274       printf("Fixed\n");
275     else
276       printf("Not fixed, rowcount = %d\n", rowcount);
277     modified(tbl);
278     return(id);
279 }
This page took 0.057571 seconds and 5 git commands to generate.