]> andersk Git - moira.git/blame_incremental - dbck/fix.pc
Deal with tracking creation times for users.
[moira.git] / dbck / fix.pc
... / ...
CommitLineData
1/* $Id$
2 *
3 * User interface routines for dbck (Moira database consistency checker)
4 *
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>.
8 */
9
10#include <mit-copyright.h>
11#include <moira.h>
12#include "dbck.h"
13
14#include <stdio.h>
15
16EXEC SQL INCLUDE sqlca; /* SQL Communications Area */
17EXEC SQL INCLUDE sqlda; /* SQL Descriptor Area */
18
19RCSID("$Header$");
20
21EXEC SQL BEGIN DECLARE SECTION;
22char *_table;
23char *_idfield;
24char stmt_buf[500];
25EXEC SQL END DECLARE SECTION;
26
27extern SQLDA *mr_sqlda;
28void generic_ffunc(void *id);
29
30void generic_ffunc(void *id)
31{
32 int rowcount;
33
34 sprintf(stmt_buf, "DELETE FROM %s WHERE %s.%s = %d",
35 _table, _table, _idfield, (int)id);
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);
43}
44
45
46void generic_delete(struct save_queue *sq, int (*pfunc)(void *), char *table,
47 char *idfield, int preen)
48{
49 _table = table;
50 _idfield = idfield;
51 generic_fix(sq, pfunc, "Delete", generic_ffunc, preen);
52}
53
54
55void single_delete(char *table, char *idfield, int id)
56{
57 _table = table;
58 _idfield = idfield;
59 generic_ffunc((void *)id);
60}
61
62
63void zero_fix(char *tbl, char *zrfield, char *idfield, int id)
64{
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);
76}
77
78
79int single_fix(char *msg, int preen)
80{
81 if (mode == MODE_PREEN)
82 return preen;
83
84 switch (mode)
85 {
86 case MODE_ASK:
87 if (!prompt(msg))
88 break;
89 case MODE_YES:
90 return 1;
91 break;
92 case MODE_NO:
93 ;
94 }
95 return 0;
96}
97
98
99void generic_fix(struct save_queue *sq, int (*pfunc)(void *), char *msg,
100 void (*ffunc)(void *), int preen)
101{
102 int id;
103
104 while (sq_get_data(sq, &id))
105 {
106 if ((*pfunc)((void *)id) == 0 && single_fix(msg, preen))
107 (*ffunc)((void *)id);
108 }
109 sq_destroy(sq);
110}
111
112
113int prompt(char *msg)
114{
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);
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
163int set_next_object_id(char *object, char *tablename)
164{
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;
208 }
209
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;
214}
215
216
217int generic_fix_id(char *tbl, char *idfield, char *txtfield,
218 int oldid, char *name)
219{
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;
236}
This page took 0.033892 seconds and 5 git commands to generate.