source: trunk/third/moira/dbck/fix.pc @ 24319

Revision 24319, 5.4 KB checked in by broder, 14 years ago (diff)
New Moira snapshot from SVN.
Line 
1/* $Id: fix.pc 3956 2010-01-05 20:56:56Z zacheiss $
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("$HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/dbck/fix.pc $ $Id: fix.pc 3956 2010-01-05 20:56:56Z zacheiss $");
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)(long)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 *)(long)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 *)(long)id) == 0 && single_fix(msg, preen))
107        (*ffunc)((void *)(long)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      fgets(buf, sizeof(buf), stdin);
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}
Note: See TracBrowser for help on using the repository browser.