/* $Header$ * * User interface routines for dbck (Moira database consistency checker) * * (c) Copyright 1988 by the Massachusetts Institute of Technology. * For copying and distribution information, please see the file * . */ #include #include #include #include "dbck.h" EXEC SQL INCLUDE sqlca; /* SQL Communications Area */ EXEC SQL INCLUDE sqlda; /* SQL Descriptor Area */ #define SQLDA_RETVALS typedef IISQLDA_TYPE(DBCK_SQLDA,DBCK_SQLDA_T,SQLDA_RETVALS); DBCK_SQLDA_T SQLDA; static char fix_qc_rcsid[] = "$Header$"; EXEC SQL BEGIN DECLARE SECTION; char *_table; char *_idfield; char stmt_buf[500]; EXEC SQL END DECLARE SECTION; generic_ffunc(id) EXEC SQL BEGIN DECLARE SECTION; int id; EXEC SQL END DECLARE SECTION; { EXEC SQL BEGIN DECLARE SECTION; int rowcount; EXEC SQL END DECLARE SECTION; /* delete _table where _table._idfield = id */ sprintf(stmt_buf,"DELETE FROM %s WHERE %s.%s = %d", _table,_table,_idfield,id); EXEC SQL EXECUTE IMMEDIATE :stmt_buf; /* inquire_equel(rowcount = "rowcount") */ EXEC SQL INQUIRE_SQL(:rowcount = rowcount); if (rowcount > 0) printf("%d entr%s deleted\n", rowcount, rowcount==1?"y":"ies"); else printf("Not deleted\n"); modified(_table); } generic_delete(sq, pfunc, table, idfield, preen) struct save_queue *sq; void (*pfunc)(); char *table, *idfield; int preen; { _table = table; _idfield = idfield; generic_fix(sq, pfunc, "Delete", generic_ffunc, preen); } single_delete(table, idfield, id) char *table, *idfield; int id; { _table = table; _idfield = idfield; generic_ffunc(id); } zero_fix(tbl, zrfield, idfield, id) EXEC SQL BEGIN DECLARE SECTION; char *tbl, *zrfield, *idfield; int id; EXEC SQL END DECLARE SECTION; { EXEC SQL BEGIN DECLARE SECTION; int rowcount; EXEC SQL END DECLARE SECTION; /* replace tbl (zrfield = 0) where table.idfield = id */ sprintf(stmt_buf,"UPDATE %s SET %s = 0 WHERE %s.%s = %d", tbl,zrfield,tbl,idfield,id); EXEC SQL EXECUTE IMMEDIATE :stmt_buf; /* inquire_equel(rowcount = "rowcount") */ EXEC SQL INQUIRE_SQL(:rowcount = rowcount); if (rowcount > 0) printf("%d entr%s fixed\n", rowcount, rowcount==1?"y":"ies"); else printf("Not fixed\n"); modified(tbl); } int single_fix(msg, preen) char *msg; int preen; { if (mode == MODE_PREEN) return(preen); switch (mode) { case MODE_ASK: if (!prompt(msg)) break; case MODE_YES: return(1); break; case MODE_NO: ; } return(0); } generic_fix(sq, pfunc, msg, ffunc, preen) struct save_queue *sq; char *msg; int (*pfunc)(), (*ffunc)(); int preen; { int id; while (sq_get_data(sq, &id)) { if ((*pfunc)(id) == 0 && single_fix(msg, preen)) (*ffunc)(id); } sq_destroy(sq); } int prompt(msg) char *msg; { char buf[BUFSIZ]; EXEC SQL BEGIN DECLARE SECTION; extern int dcmenable; EXEC SQL END DECLARE SECTION; while (1) { printf("%s (Y/N/Q)? ", msg); fflush(stdout); gets(buf); if (buf[0] == 'Y' || buf[0] == 'y') return(1); if (buf[0] == 'N' || buf[0] == 'n') return(0); if (buf[0] == 'Q' || buf[0] == 'q') { if (prompt("Are you sure you want to quit")) { if (prompt("Save database changes")) { /* end transaction */ EXEC SQL COMMIT WORK; cleanup(); exit(0); } else { /* abort */ EXEC SQL ROLLBACK WORK; /* replace values (value = dcmenable) * where values.name = "dcm_enable" */ EXEC SQL UPDATE numvalues SET value = :dcmenable WHERE name='dcm_enable'; /* exit */ /* No equivalent (?) */ exit(1); } } } } } /** ** set_next_object_id - set next object id in values table ** ** Inputs: object - object name in values table and in objects ** table - name of table objects are found in ** ** - called before an APPEND operation to set the next object id to ** be used for the new record to the next free value ** **/ int set_next_object_id(object, tablename) char *object; char *tablename; { EXEC SQL BEGIN DECLARE SECTION; char *name, *tbl; int rowcount, existence, value; EXEC SQL END DECLARE SECTION; name = object; tbl = tablename; /* range of v is values * repeat retrieve (value = v.#value) where v.#name = @name */ EXEC SQL REPEATED SELECT value INTO :value FROM numvalues WHERE name = :name; EXEC SQL INQUIRE_SQL(:rowcount = rowcount); if (rowcount != 1) return(MR_NO_ID); /* retrieve (existence = any(tbl.name where tbl.name = value)) */ SQLDA.sqlvar[0].sqldata=(void *)&rowcount; sprintf(stmt_buf,"SELECT COUNT (*) FROM %s WHERE %s=%d",tbl,name,value); EXEC SQL PREPARE stmt INTO :&SQLDA USING NAMES FROM :stmt_buf; if(sqlca.sqlcode) return(MR_INTERNAL); EXEC SQL DECLARE foo CURSOR FOR stmt; EXEC SQL OPEN foo; EXEC SQL FETCH foo USING DESCRIPTOR :&SQLDA; if (sqlca.sqlcode < 0) return(MR_INTERNAL); if (sqlca.sqlcode == 100) existence=0; else existence=1; EXEC SQL CLOSE foo; if (rowcount != 1) return(MR_NO_ID); while (existence) { value++; if (value > MAX_ID_VALUE) value = MIN_ID_VALUE; /* retrieve (existence = any(tbl.name where tbl.name = value)) */ sprintf(stmt_buf,"SELECT %s FROM %s WHERE %s=%d",name,tbl,name,value); EXEC SQL PREPARE stmt INTO :&SQLDA USING NAMES FROM :stmt_buf; if(sqlca.sqlcode) return(MR_INTERNAL); EXEC SQL DECLARE bar CURSOR FOR stmt; EXEC SQL OPEN bar; EXEC SQL FETCH bar USING DESCRIPTOR :&SQLDA; if (sqlca.sqlcode != 0) break; EXEC SQL CLOSE bar; } EXEC SQL CLOSE bar; printf("setting ID %s to %d\n", name, value); /* repeat replace v (#value = @value) where v.#name = @name */ EXEC SQL REPEATED UPDATE numvalues SET value = :value WHERE name = :name; modified("values"); return(MR_SUCCESS); } generic_fix_id(tbl, idfield, txtfield, oldid, name) EXEC SQL BEGIN DECLARE SECTION; char *tbl; char *idfield; char *txtfield; int oldid; char *name; EXEC SQL END DECLARE SECTION; { EXEC SQL BEGIN DECLARE SECTION; int rowcount, id, temp; EXEC SQL END DECLARE SECTION; set_next_object_id(tbl, idfield); /* retrieve (id = values.value) where values.#name = idfield */ EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = :idfield; /* replace tbl (idfield = values.value) where values.#name = idfield and * tbl.idfield = oldid and tbl.txtfield = name */ EXEC SQL SELECT value INTO :temp FROM numvalues WHERE name = :idfield; sprintf(stmt_buf,"UPDATE %s SET %s = %d WHERE %s=%d AND %s='%s'", tbl,idfield,temp,idfield,oldid,txtfield,name); EXEC SQL EXECUTE IMMEDIATE :stmt_buf; EXEC SQL INQUIRE_SQL(:rowcount = rowcount); if (rowcount == 1) printf("Fixed\n"); else printf("Not fixed, rowcount = %d\n", rowcount); modified(tbl); return(id); } de_dup( tbl, idfield, id, dupfield, correct_val ) EXEC SQL BEGIN DECLARE SECTION; char *tbl, *idfield, *dupfield; int id, correct_val; EXEC SQL END DECLARE SECTION; { int size, i; EXEC SQL BEGIN DECLARE SECTION; int rowcount; EXEC SQL END DECLARE SECTION; /* replace tbl.dupfield with correct_val where tbl.idfield = id */ sprintf( stmt_buf,"UPDATE %s SET %d = %d WHERE %s = %d", tbl, dupfield, correct_val, idfield, id ); size = strlen( stmt_buf ); for( i=0; i!=NULL && i<500; i++ ) { ; } /* Move to an unused string. */ }