]> andersk Git - moira.git/blob - dbck/fix.pc
Do something sensible with MACHINE members of lists.
[moira.git] / dbck / fix.pc
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
16 EXEC SQL INCLUDE sqlca;  /* SQL Communications Area */
17 EXEC SQL INCLUDE sqlda;  /* SQL Descriptor Area */
18
19 RCSID("$Header$");
20
21 EXEC SQL BEGIN DECLARE SECTION;
22 char *_table;
23 char *_idfield;
24 char stmt_buf[500];
25 EXEC SQL END DECLARE SECTION;
26
27 extern SQLDA *mr_sqlda;
28 void generic_ffunc(void *id);
29
30 void 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
46 void 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
55 void single_delete(char *table, char *idfield, int id)
56 {
57   _table = table;
58   _idfield = idfield;
59   generic_ffunc((void *)id);
60 }
61
62
63 void 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
79 int 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
99 void 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
113 int 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
163 int 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
217 int 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.064157 seconds and 5 git commands to generate.