diff --git a/mps/code/eventsql.c b/mps/code/eventsql.c index 753a8aafc08..23a50f8063f 100644 --- a/mps/code/eventsql.c +++ b/mps/code/eventsql.c @@ -17,183 +17,215 @@ unsigned int verbosity = 4; static void vlog(unsigned int level, const char *format, va_list args) { - if (level <= verbosity) { - fflush(stderr); /* sync */ - fprintf(stderr, "log %d: ", level); - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); - } + if (level <= verbosity) { + fflush(stderr); /* sync */ + fprintf(stderr, "log %d: ", level); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); + } } static void log(unsigned int level, const char *format, ...) { - va_list args; - va_start(args, format); - vlog(level, format, args); - va_end(args); + va_list args; + va_start(args, format); + vlog(level, format, args); + va_end(args); } #if 0 /* UNUSED */ static void error(const char *format, ...) { - va_list args; - fprintf(stderr, "Fatal error: "); - va_start(args, format); - vlog(LOG_ALWAYS, format, args); - va_end(args); - exit(1); + va_list args; + fprintf(stderr, "Fatal error: "); + va_start(args, format); + vlog(LOG_ALWAYS, format, args); + va_end(args); + exit(1); } #endif /* UNUSED */ - + static void sqlite_error(int res, sqlite3 *db, const char *format, ...) { - log(LOG_ALWAYS, "Fatal SQL error %d", res); - va_list args; - va_start(args, format); - vlog(LOG_ALWAYS, format, args); - va_end(args); - log(LOG_ALWAYS, "SQLite message: %s\n", sqlite3_errmsg(db)); - exit(1); + log(LOG_ALWAYS, "Fatal SQL error %d", res); + va_list args; + va_start(args, format); + vlog(LOG_ALWAYS, format, args); + va_end(args); + log(LOG_ALWAYS, "SQLite message: %s\n", sqlite3_errmsg(db)); + exit(1); } static void openDatabase(sqlite3 **dbReturn) { - sqlite3 *db; - int res; - - const char *filename = getenv("MPS_EVENT_DATABASE"); - if(filename == NULL) - filename = "mpsevent.db"; - log(LOG_OFTEN, "Opening %s.", filename); - - res = sqlite3_open_v2(filename, - &db, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, - NULL); /* use default sqlite_vfs object */ - - if (res != SQLITE_OK) - sqlite_error(res, db, "Opening %s failed", filename); - *dbReturn = db; - return; + sqlite3 *db; + int res; + + const char *filename = getenv("MPS_EVENT_DATABASE"); + if(filename == NULL) + filename = "mpsevent.db"; + log(LOG_OFTEN, "Opening %s.", filename); + + res = sqlite3_open_v2(filename, + &db, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, + NULL); /* use default sqlite_vfs object */ + + if (res != SQLITE_OK) + sqlite_error(res, db, "Opening %s failed", filename); + *dbReturn = db; + return; } +/* Macro magic to make a CREATE TABLE statement for each event type. */ + +#define EVENT_PARAM_SQL_TYPE_A "INTEGER" +#define EVENT_PARAM_SQL_TYPE_P "INTEGER" +#define EVENT_PARAM_SQL_TYPE_U "INTEGER" +#define EVENT_PARAM_SQL_TYPE_W "INTEGER" +#define EVENT_PARAM_SQL_TYPE_D "REAL " +#define EVENT_PARAM_SQL_TYPE_S "TEXT " +#define EVENT_PARAM_SQL_TYPE_B "INTEGER" + +#define EVENT_PARAM_SQL_COLUMN(X, index, sort, ident) \ + "\"" #ident "\" " EVENT_PARAM_SQL_TYPE_##sort ", " + +#define EVENT_TABLE_CREATE(X, name, code, always, kind) \ + "CREATE TABLE IF NOT EXISTS EVENT_" #name " ( " \ + EVENT_##name##_PARAMS(EVENT_PARAM_SQL_COLUMN, X) \ + "time INTEGER ) ", + const char *createStatements[] = { - "CREATE TABLE IF NOT EXISTS event_kind (name TEXT," - " description TEXT," - " enum INTEGER PRIMARY KEY)", - "CREATE TABLE IF NOT EXISTS event_type (name TEXT," - " code INTEGER PRIMARY KEY," - " always INTEGER," - " kind INTEGER," - " FOREIGN KEY (kind) REFERENCES event_kind(enum));", + "CREATE TABLE IF NOT EXISTS event_kind (name TEXT," + " description TEXT," + " enum INTEGER PRIMARY KEY)", + + "CREATE TABLE IF NOT EXISTS event_type (name TEXT," + " code INTEGER PRIMARY KEY," + " always INTEGER," + " kind INTEGER," + " FOREIGN KEY (kind) REFERENCES event_kind(enum));", + +EVENT_LIST(EVENT_TABLE_CREATE, X) }; const char *populateStatements[] = { }; #define EVENT_KIND_DO_INSERT(X, name, description) \ - res = sqlite3_bind_text(statement, 1, #name, -1, SQLITE_STATIC); \ - if (res != SQLITE_OK) \ - sqlite_error(res, db, "event_kind bind of name \"" #name "\" failed."); \ - res = sqlite3_bind_text(statement, 2, description, -1, SQLITE_STATIC); \ - if (res != SQLITE_OK) \ - sqlite_error(res, db, "event_kind bind of description \"" description "\" failed."); \ - res = sqlite3_bind_int(statement, 3, i); \ - if (res != SQLITE_OK) \ - sqlite_error(res, db, "event_kind bind of enum %d failed.", i); \ - ++i; \ - res = sqlite3_step(statement); \ - if (res != SQLITE_DONE) \ - sqlite_error(res, db, "event_kind insert of name \"" #name "\" failed."); \ - if (sqlite3_changes(db) != 0)\ - log(LOG_SOMETIMES, "Insert of event_kind row for \"" #name "\" affected %d rows.", sqlite3_changes(db)); \ - res = sqlite3_reset(statement); \ - if (res != SQLITE_OK) \ - sqlite_error(res, db, "Couldn't reset event_kind insert statement."); + res = sqlite3_bind_text(statement, 1, #name, -1, SQLITE_STATIC); \ + if (res != SQLITE_OK) \ + sqlite_error(res, db, "event_kind bind of name \"" #name "\" failed."); \ + res = sqlite3_bind_text(statement, 2, description, -1, SQLITE_STATIC); \ + if (res != SQLITE_OK) \ + sqlite_error(res, db, "event_kind bind of description \"" description "\" failed."); \ + res = sqlite3_bind_int(statement, 3, i); \ + if (res != SQLITE_OK) \ + sqlite_error(res, db, "event_kind bind of enum %d failed.", i); \ + ++i; \ + res = sqlite3_step(statement); \ + if (res != SQLITE_DONE) \ + sqlite_error(res, db, "event_kind insert of name \"" #name "\" failed."); \ + if (sqlite3_changes(db) != 0) \ + log(LOG_SOMETIMES, "Insert of event_kind row for \"" #name "\" affected %d rows.", sqlite3_changes(db)); \ + res = sqlite3_reset(statement); \ + if (res != SQLITE_OK) \ + sqlite_error(res, db, "Couldn't reset event_kind insert statement."); -#define EVENT_TYPE_DO_INSERT(X, name, code, always, kind) \ - res = sqlite3_bind_text(statement, 1, #name, -1, SQLITE_STATIC); \ - if (res != SQLITE_OK) \ - sqlite_error(res, db, "event_type bind of name \"" #name "\" failed."); \ - res = sqlite3_bind_int(statement, 2, code); \ - if (res != SQLITE_OK) \ - sqlite_error(res, db, "event_type bind of code %d failed.", code); \ - res = sqlite3_bind_int(statement, 3, always); \ - if (res != SQLITE_OK) \ - sqlite_error(res, db, "event_type bind of always for name \"" #name "\" failed."); \ - res = sqlite3_bind_int(statement, 4, EventKind##kind); \ - if (res != SQLITE_OK) \ - sqlite_error(res, db, "event_type bind of kind for name \"" #name "\" failed."); \ - res = sqlite3_step(statement); \ - if (res != SQLITE_DONE) \ - sqlite_error(res, db, "event_type insert of name \"" #name "\" failed."); \ - if (sqlite3_changes(db) != 0) \ - log(LOG_SOMETIMES, "Insert of event_type row for \"" #name "\" affected %d rows.", sqlite3_changes(db)); \ - res = sqlite3_reset(statement); \ - if (res != SQLITE_OK) \ - sqlite_error(res, db, "Couldn't reset event_type insert statement."); +#define EVENT_TYPE_DO_INSERT(X, name, code, always, kind) \ + res = sqlite3_bind_text(statement, 1, #name, -1, SQLITE_STATIC); \ + if (res != SQLITE_OK) \ + sqlite_error(res, db, "event_type bind of name \"" #name "\" failed."); \ + res = sqlite3_bind_int(statement, 2, code); \ + if (res != SQLITE_OK) \ + sqlite_error(res, db, "event_type bind of code %d failed.", code); \ + res = sqlite3_bind_int(statement, 3, always); \ + if (res != SQLITE_OK) \ + sqlite_error(res, db, "event_type bind of always for name \"" #name "\" failed."); \ + res = sqlite3_bind_int(statement, 4, EventKind##kind); \ + if (res != SQLITE_OK) \ + sqlite_error(res, db, "event_type bind of kind for name \"" #name "\" failed."); \ + res = sqlite3_step(statement); \ + if (res != SQLITE_DONE) \ + sqlite_error(res, db, "event_type insert of name \"" #name "\" failed."); \ + if (sqlite3_changes(db) != 0) \ + log(LOG_SOMETIMES, "Insert of event_type row for \"" #name "\" affected %d rows.", sqlite3_changes(db)); \ + res = sqlite3_reset(statement); \ + if (res != SQLITE_OK) \ + sqlite_error(res, db, "Couldn't reset event_type insert statement."); static void fillTables(sqlite3 *db) { - int i; - sqlite3_stmt *statement; - - int res = sqlite3_prepare_v2(db, - "INSERT OR IGNORE INTO event_kind (name, description, enum)" - "VALUES (?, ?, ?)", - -1, /* prepare whole string as statement */ - &statement, - NULL); - if (res != SQLITE_OK) - sqlite_error(res, db, "event_kind preparation failed"); - - i = 0; - EventKindENUM(EVENT_KIND_DO_INSERT, X); - - res = sqlite3_finalize(statement); - if (res != SQLITE_OK) - sqlite_error(res, db, "event_kind finalize failed"); - - res = sqlite3_prepare_v2(db, - "INSERT OR IGNORE INTO event_type (name, code, always, kind)" - "VALUES (?, ?, ?, ?)", - -1, /* prepare whole string as statement */ - &statement, - NULL); - if (res != SQLITE_OK) - sqlite_error(res, db, "event_type preparation failed"); - - EVENT_LIST(EVENT_TYPE_DO_INSERT, X); - - res = sqlite3_finalize(statement); - if (res != SQLITE_OK) - sqlite_error(res, db, "event_type finalize failed"); + int i; + sqlite3_stmt *statement; + int res; + + res = sqlite3_prepare_v2(db, + "INSERT OR IGNORE INTO event_kind (name, description, enum)" + "VALUES (?, ?, ?)", + -1, /* prepare whole string as statement */ + &statement, + NULL); + if (res != SQLITE_OK) + sqlite_error(res, db, "event_kind preparation failed"); + + i = 0; + EventKindENUM(EVENT_KIND_DO_INSERT, X); + + res = sqlite3_finalize(statement); + if (res != SQLITE_OK) + sqlite_error(res, db, "event_kind finalize failed"); + + res = sqlite3_prepare_v2(db, + "INSERT OR IGNORE INTO event_type (name, code, always, kind)" + "VALUES (?, ?, ?, ?)", + -1, /* prepare whole string as statement */ + &statement, + NULL); + if (res != SQLITE_OK) + sqlite_error(res, db, "event_type preparation failed"); + + EVENT_LIST(EVENT_TYPE_DO_INSERT, X); + + res = sqlite3_finalize(statement); + if (res != SQLITE_OK) + sqlite_error(res, db, "event_type finalize failed"); } static void makeTables(sqlite3 *db) { - int i; + int i; + int res; + + for (i=0; i < (sizeof(createStatements)/sizeof(createStatements[0])); ++i) { + log(LOG_SOMETIMES, "Creating tables. SQL command: %s", createStatements[i]); + res = sqlite3_exec(db, + createStatements[i], + NULL, /* No callback */ + NULL, /* No callback closure */ + NULL); /* error messages handled by sqlite_error */ + if (res != SQLITE_OK) + sqlite_error(res, db, "Table creation failed: %s", createStatements[i]); + } +} - for (i=0; i < (sizeof(createStatements)/sizeof(createStatements[0])); ++i) { - log(LOG_SOMETIMES, "Creating tables. SQL command: %s", createStatements[i]); - int res = sqlite3_exec(db, - createStatements[i], - NULL, /* No callback */ - NULL, /* No callback closure */ - NULL); /* error messages handled by sqlite_error */ - if (res != SQLITE_OK) - sqlite_error(res, db, "Table creation failed: %s", createStatements[i]); - } +void closeDatabase(sqlite3 *db) +{ + int res = sqlite3_close(db); + if (res != SQLITE_OK) + sqlite_error(res, db, "Closing database failed"); + log(LOG_ALWAYS, "Closed database."); } int main(void) { - sqlite3 *db; - - openDatabase(&db); - makeTables(db); - fillTables(db); - return 0; + sqlite3 *db; + + openDatabase(&db); + makeTables(db); + fillTables(db); + closeDatabase(db); + return 0; }