aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code
diff options
context:
space:
mode:
authorNick Barnes2012-10-20 20:34:30 +0100
committerNick Barnes2012-10-20 20:34:30 +0100
commit1822b236377d1801c141b19014e751046e596a84 (patch)
tree31c06084255221885da134bb2ec894c8c16053ba /mps/code
parentf0757a16404b0d4e90facee261b78101568a66cd (diff)
downloademacs-1822b236377d1801c141b19014e751046e596a84.tar.gz
emacs-1822b236377d1801c141b19014e751046e596a84.zip
Better table existence test.
Copied from Perforce Change: 179985 ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
-rw-r--r--mps/code/eventsql.c127
1 files changed, 60 insertions, 67 deletions
diff --git a/mps/code/eventsql.c b/mps/code/eventsql.c
index 1e995bb0f67..d7cf6a3e3f5 100644
--- a/mps/code/eventsql.c
+++ b/mps/code/eventsql.c
@@ -252,73 +252,6 @@ static void closeDatabase(sqlite3 *db)
252 log(LOG_SOMETIMES, "Closed %s.", databaseName); 252 log(LOG_SOMETIMES, "Closed %s.", databaseName);
253} 253}
254 254
255/* We need to be able to test for the existence of a table. The
256 * SQLite3 API seems to have no way to explore metadata like this,
257 * unless it is compiled in a particular way (in which case the
258 * function sqlite3_table_column_metadata could be used). Without
259 * that assistance, we can use a simple SQL trick (which could also
260 * tell us the number of rows in the table if we cared).
261 *
262 * TODO: Update this to use the sqlite_master table:
263 * SELECT FROM sqlite_master WHERE type='table' AND name=?
264 * and fix the above comment.
265 */
266
267static int tableExists(sqlite3* db, const char *tableName)
268{
269 const char *format = "SELECT SUM(1) FROM %s";
270 char *sql;
271 int res;
272
273 sql = malloc(strlen(format) + strlen(tableName));
274 if (!sql)
275 error("Out of memory.");
276 sprintf(sql, format, tableName);
277 log(LOG_SELDOM, "Testing for existence of table '%s' with SQL: %s", tableName, sql);
278 res = sqlite3_exec(db,
279 sql,
280 NULL, /* put in a callback here if we really want to know the number of rows */
281 NULL, /* callback closure */
282 NULL); /* error messages handled by sqlite_error */
283 free(sql);
284
285 switch(res) {
286 case SQLITE_OK:
287 log(LOG_SELDOM, "Table '%s' exists.", tableName);
288
289 return 1; /* table exists */
290 break;
291 case SQLITE_ERROR:
292 log(LOG_SELDOM, "Table '%s' does not exist.", tableName);
293 return 0; /* table does not exist; we can
294 probably do a better test for this case. */
295 break;
296 default:
297 sqlite_error(res, db, "Table test failed: %s", tableName);
298 }
299 /* UNREACHED */
300 return 0;
301}
302
303/* Unit test for tableExists() */
304
305static const char *tableTests[] = {
306 "event_kind",
307 "spong",
308 "EVENT_SegSplit",
309};
310
311static void testTableExists(sqlite3 *db)
312{
313 int i;
314 for (i=0; i < (sizeof(tableTests)/sizeof(tableTests[0])); ++i) {
315 if (tableExists(db, tableTests[i]))
316 printf("Table exists: %s\n", tableTests[i]);
317 else
318 printf("Table does not exist: %s\n", tableTests[i]);
319 }
320}
321
322/* Utility functions for SQLite statements. */ 255/* Utility functions for SQLite statements. */
323 256
324static sqlite3_stmt *prepareStatement(sqlite3 *db, 257static sqlite3_stmt *prepareStatement(sqlite3 *db,
@@ -360,6 +293,66 @@ static void runStatement(sqlite3 *db,
360 sqlite_error(res, db, "%s failed - statement %s", description, sql); 293 sqlite_error(res, db, "%s failed - statement %s", description, sql);
361} 294}
362 295
296/* Test for the existence of a table using sqlite_master table.
297 */
298
299static int tableExists(sqlite3* db, const char *tableName)
300{
301 int res;
302 int exists;
303 sqlite3_stmt *statement;
304
305 statement = prepareStatement(db,
306 "SELECT 1 FROM sqlite_master WHERE type='table' AND name=?");
307 res = sqlite3_bind_text(statement, 1, tableName, -1, SQLITE_STATIC);
308 if (res != SQLITE_OK)
309 sqlite_error(res, db, "table existence bind of name failed.");
310 res = sqlite3_step(statement);
311 switch(res) {
312 case SQLITE_DONE:
313 exists = 0;
314 break;
315 case SQLITE_ROW:
316 exists = 1;
317 break;
318 default:
319 sqlite_error(res, db, "select from sqlite_master failed.");
320 }
321 finalizeStatement(db, statement);
322 return exists;
323}
324
325/* Unit test for tableExists() */
326
327static struct {
328 const char* name;
329 int exists;
330} tableTests[] = {
331 {"event_kind", TRUE},
332 {"spong", FALSE},
333 {"EVENT_SegSplit", TRUE}
334};
335
336static void testTableExists(sqlite3 *db)
337{
338 int i;
339 int defects = 0;
340 int tests = 0;
341 for (i=0; i < (sizeof(tableTests)/sizeof(tableTests[0])); ++i) {
342 const char *name = tableTests[i].name;
343 int exists = tableExists(db, name);
344 if (exists)
345 log(LOG_OFTEN, "Table exists: %s", name);
346 else
347 log(LOG_OFTEN, "Table does not exist: %s", name);
348 if (exists != tableTests[i].exists) {
349 log(LOG_ALWAYS, "tableExists test failed on table %s", name);
350 ++ defects;
351 }
352 ++ tests;
353 }
354 log(LOG_ALWAYS, "%d tests, %d defects found.", tests, defects);
355}
363 356
364/* Every time we put events from a log file into a database file, we 357/* Every time we put events from a log file into a database file, we
365 * add the log file to the event_log table, and get a serial number 358 * add the log file to the event_log table, and get a serial number