]>
Commit | Line | Data |
---|---|---|
7ac48069 | 1 | /* $Id$ |
68bbc9c3 | 2 | * |
3 | * User interface routines for dbck (Moira database consistency checker) | |
4 | * | |
7ac48069 | 5 | * (c) Copyright 1988-1998 by the Massachusetts Institute of Technology. |
6 | * For copying and distribution information, please see the file | |
7 | * <mit-copyright.h>. | |
68bbc9c3 | 8 | */ |
9 | ||
10 | #include <mit-copyright.h> | |
11 | #include <moira.h> | |
68bbc9c3 | 12 | #include "dbck.h" |
13 | ||
7ac48069 | 14 | #include <stdio.h> |
15 | ||
208a4f4a | 16 | EXEC SQL INCLUDE sqlca; /* SQL Communications Area */ |
17 | EXEC SQL INCLUDE sqlda; /* SQL Descriptor Area */ | |
18 | ||
7ac48069 | 19 | RCSID("$Header$"); |
68bbc9c3 | 20 | |
5eaef520 | 21 | EXEC SQL BEGIN DECLARE SECTION; |
208a4f4a | 22 | char *_table; |
23 | char *_idfield; | |
24 | char stmt_buf[500]; | |
5eaef520 | 25 | EXEC SQL END DECLARE SECTION; |
68bbc9c3 | 26 | |
4b9e5c72 | 27 | extern SQLDA *mr_sqlda; |
7ac48069 | 28 | void generic_ffunc(void *id); |
4b9e5c72 | 29 | |
7ac48069 | 30 | void generic_ffunc(void *id) |
208a4f4a | 31 | { |
5eaef520 | 32 | int rowcount; |
33 | ||
34 | sprintf(stmt_buf, "DELETE FROM %s WHERE %s.%s = %d", | |
7ac48069 | 35 | _table, _table, _idfield, (int)id); |
5eaef520 | 36 | EXEC SQL EXECUTE IMMEDIATE :stmt_buf; |
37 | rowcount = sqlca.sqlerrd[2]; | |
38 | if (rowcount > 0) | |
39 | printf("%d entr%s deleted\n", rowcount, rowcount == 1 ? "y" : "ies"); | |
40 | else | |
41 | printf("Not deleted\n"); | |
42 | modified(_table); | |
208a4f4a | 43 | } |
68bbc9c3 | 44 | |
45 | ||
7ac48069 | 46 | void generic_delete(struct save_queue *sq, int (*pfunc)(void *), char *table, |
47 | char *idfield, int preen) | |
68bbc9c3 | 48 | { |
5eaef520 | 49 | _table = table; |
50 | _idfield = idfield; | |
51 | generic_fix(sq, pfunc, "Delete", generic_ffunc, preen); | |
68bbc9c3 | 52 | } |
53 | ||
54 | ||
7ac48069 | 55 | void single_delete(char *table, char *idfield, int id) |
68bbc9c3 | 56 | { |
5eaef520 | 57 | _table = table; |
58 | _idfield = idfield; | |
7ac48069 | 59 | generic_ffunc((void *)id); |
68bbc9c3 | 60 | } |
61 | ||
62 | ||
7ac48069 | 63 | void zero_fix(char *tbl, char *zrfield, char *idfield, int id) |
208a4f4a | 64 | { |
5eaef520 | 65 | int rowcount; |
66 | ||
67 | sprintf(stmt_buf, "UPDATE %s SET %s = 0 WHERE %s.%s = %d", | |
68 | tbl, zrfield, tbl, idfield, id); | |
69 | EXEC SQL EXECUTE IMMEDIATE :stmt_buf; | |
70 | rowcount = sqlca.sqlerrd[2]; | |
71 | if (rowcount > 0) | |
72 | printf("%d entr%s fixed\n", rowcount, rowcount == 1 ? "y" : "ies"); | |
73 | else | |
74 | printf("Not fixed\n"); | |
75 | modified(tbl); | |
208a4f4a | 76 | } |
68bbc9c3 | 77 | |
78 | ||
5eaef520 | 79 | int single_fix(char *msg, int preen) |
68bbc9c3 | 80 | { |
5eaef520 | 81 | if (mode == MODE_PREEN) |
82 | return preen; | |
68bbc9c3 | 83 | |
5eaef520 | 84 | switch (mode) |
85 | { | |
68bbc9c3 | 86 | case MODE_ASK: |
5eaef520 | 87 | if (!prompt(msg)) |
68bbc9c3 | 88 | break; |
5eaef520 | 89 | case MODE_YES: |
90 | return 1; | |
91 | break; | |
68bbc9c3 | 92 | case MODE_NO: |
5eaef520 | 93 | ; |
68bbc9c3 | 94 | } |
5eaef520 | 95 | return 0; |
68bbc9c3 | 96 | } |
97 | ||
98 | ||
7ac48069 | 99 | void generic_fix(struct save_queue *sq, int (*pfunc)(void *), char *msg, |
100 | void (*ffunc)(void *), int preen) | |
68bbc9c3 | 101 | { |
5eaef520 | 102 | int id; |
68bbc9c3 | 103 | |
5eaef520 | 104 | while (sq_get_data(sq, &id)) |
105 | { | |
7ac48069 | 106 | if ((*pfunc)((void *)id) == 0 && single_fix(msg, preen)) |
107 | (*ffunc)((void *)id); | |
68bbc9c3 | 108 | } |
5eaef520 | 109 | sq_destroy(sq); |
68bbc9c3 | 110 | } |
111 | ||
112 | ||
5eaef520 | 113 | int prompt(char *msg) |
68bbc9c3 | 114 | { |
5eaef520 | 115 | char buf[BUFSIZ]; |
116 | EXEC SQL BEGIN DECLARE SECTION; | |
117 | extern int dcmenable; | |
118 | EXEC SQL END DECLARE SECTION; | |
119 | ||
120 | while (1) | |
121 | { | |
122 | printf("%s (Y/N/Q)? ", msg); | |
123 | fflush(stdout); | |
124 | gets(buf); | |
125 | if (buf[0] == 'Y' || buf[0] == 'y') | |
126 | return 1; | |
127 | if (buf[0] == 'N' || buf[0] == 'n') | |
128 | return 0; | |
129 | if (buf[0] == 'Q' || buf[0] == 'q') | |
130 | { | |
131 | if (prompt("Are you sure you want to quit")) | |
132 | { | |
133 | if (prompt("Save database changes")) | |
134 | { | |
135 | EXEC SQL COMMIT WORK; | |
136 | cleanup(); | |
137 | exit(0); | |
138 | } | |
139 | else | |
140 | { | |
141 | EXEC SQL ROLLBACK WORK; | |
142 | EXEC SQL UPDATE numvalues SET value = :dcmenable | |
143 | WHERE name = 'dcm_enable'; | |
144 | exit(1); | |
68bbc9c3 | 145 | } |
146 | } | |
147 | } | |
148 | } | |
149 | } | |
150 | ||
151 | ||
152 | /** | |
153 | ** set_next_object_id - set next object id in values table | |
154 | ** | |
155 | ** Inputs: object - object name in values table and in objects | |
156 | ** table - name of table objects are found in | |
157 | ** | |
158 | ** - called before an APPEND operation to set the next object id to | |
159 | ** be used for the new record to the next free value | |
160 | ** | |
161 | **/ | |
162 | ||
5eaef520 | 163 | int set_next_object_id(char *object, char *tablename) |
208a4f4a | 164 | { |
5eaef520 | 165 | EXEC SQL BEGIN DECLARE SECTION; |
166 | int value; | |
167 | char stmt_buf[256], out_buf[256]; | |
168 | EXEC SQL END DECLARE SECTION; | |
169 | int starting_value, errcode = 0; | |
170 | ||
171 | EXEC SQL SELECT value INTO :value FROM numvalues WHERE name = :object; | |
172 | if (sqlca.sqlerrd[2] != 1) | |
173 | return MR_NO_ID; | |
174 | ||
175 | starting_value = value; | |
176 | while (1) | |
177 | { | |
178 | if (value > MAX_ID_VALUE) | |
179 | value = MIN_ID_VALUE; | |
180 | ||
181 | sprintf(stmt_buf, "SELECT %s FROM %s WHERE %s = %d", | |
182 | object, tablename, object, value); | |
183 | EXEC SQL PREPARE inc_stmt FROM :stmt_buf; | |
184 | EXEC SQL DECLARE inc_crs CURSOR FOR inc_stmt; | |
185 | EXEC SQL OPEN inc_crs; | |
186 | mr_sqlda->N = 1; | |
187 | EXEC SQL DESCRIBE SELECT LIST FOR inc_stmt INTO mr_sqlda; | |
188 | mr_sqlda->N = mr_sqlda->F; | |
189 | mr_sqlda->V[0] = out_buf; | |
190 | mr_sqlda->T[0] = 97; | |
191 | mr_sqlda->L[0] = 255; | |
192 | EXEC SQL FETCH inc_crs USING DESCRIPTOR mr_sqlda; | |
193 | ||
194 | /* if we got an error from the FETCH, we have to preserve it or the | |
195 | close will reset it and the caller with think nothing happened */ | |
196 | if (sqlca.sqlcode) | |
197 | errcode = sqlca.sqlcode; | |
198 | ||
199 | EXEC SQL CLOSE inc_crs; | |
200 | if (errcode < 0) | |
201 | return MR_DBMS_ERR; | |
202 | if (errcode == 1403) | |
203 | break; | |
204 | ||
205 | value++; | |
206 | if (value == starting_value) | |
207 | return MR_NO_ID; | |
68bbc9c3 | 208 | } |
209 | ||
5eaef520 | 210 | printf("setting ID %s to %d\n", object, value); |
211 | EXEC SQL UPDATE numvalues SET value = :value WHERE name = :object; | |
212 | modified("values"); | |
213 | return MR_SUCCESS; | |
208a4f4a | 214 | } |
215 | ||
216 | ||
5eaef520 | 217 | int generic_fix_id(char *tbl, char *idfield, char *txtfield, |
218 | int oldid, char *name) | |
208a4f4a | 219 | { |
5eaef520 | 220 | EXEC SQL BEGIN DECLARE SECTION; |
221 | int rowcount, id; | |
222 | EXEC SQL END DECLARE SECTION; | |
223 | ||
224 | set_next_object_id(tbl, idfield); | |
225 | EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = :idfield; | |
226 | sprintf(stmt_buf, "UPDATE %s SET %s = %d WHERE %s = %d AND %s = '%s'", | |
227 | tbl, idfield, id, idfield, oldid, txtfield, name); | |
228 | EXEC SQL EXECUTE IMMEDIATE :stmt_buf; | |
229 | rowcount = sqlca.sqlerrd[2]; | |
230 | if (rowcount == 1) | |
231 | printf("Fixed\n"); | |
232 | else | |
233 | printf("Not fixed, rowcount = %d\n", rowcount); | |
234 | modified(tbl); | |
235 | return id; | |
208a4f4a | 236 | } |