aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code
diff options
context:
space:
mode:
authorNick Barnes2012-10-13 12:16:24 +0100
committerNick Barnes2012-10-13 12:16:24 +0100
commit54a4a5568f783e01cafabe1aa110697aaf9b5c9a (patch)
tree45f435706cc6cdfa56bb98dde28380ca3cdd83af /mps/code
parentd26c0518f1f812290bb0188d6014a962fc048ca6 (diff)
downloademacs-54a4a5568f783e01cafabe1aa110697aaf9b5c9a.tar.gz
emacs-54a4a5568f783e01cafabe1aa110697aaf9b5c9a.zip
Event sql interface now creates a table for each type of event.
Copied from Perforce Change: 179868 ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
-rw-r--r--mps/code/eventsql.c312
1 files changed, 172 insertions, 140 deletions
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;
17 17
18static void vlog(unsigned int level, const char *format, va_list args) 18static void vlog(unsigned int level, const char *format, va_list args)
19{ 19{
20 if (level <= verbosity) { 20 if (level <= verbosity) {
21 fflush(stderr); /* sync */ 21 fflush(stderr); /* sync */
22 fprintf(stderr, "log %d: ", level); 22 fprintf(stderr, "log %d: ", level);
23 vfprintf(stderr, format, args); 23 vfprintf(stderr, format, args);
24 fprintf(stderr, "\n"); 24 fprintf(stderr, "\n");
25 } 25 }
26} 26}
27 27
28static void log(unsigned int level, const char *format, ...) 28static void log(unsigned int level, const char *format, ...)
29{ 29{
30 va_list args; 30 va_list args;
31 va_start(args, format); 31 va_start(args, format);
32 vlog(level, format, args); 32 vlog(level, format, args);
33 va_end(args); 33 va_end(args);
34} 34}
35 35
36#if 0 /* UNUSED */ 36#if 0 /* UNUSED */
37 37
38static void error(const char *format, ...) 38static void error(const char *format, ...)
39{ 39{
40 va_list args; 40 va_list args;
41 fprintf(stderr, "Fatal error: "); 41 fprintf(stderr, "Fatal error: ");
42 va_start(args, format); 42 va_start(args, format);
43 vlog(LOG_ALWAYS, format, args); 43 vlog(LOG_ALWAYS, format, args);
44 va_end(args); 44 va_end(args);
45 exit(1); 45 exit(1);
46} 46}
47#endif /* UNUSED */ 47#endif /* UNUSED */
48 48
49static void sqlite_error(int res, sqlite3 *db, const char *format, ...) 49static void sqlite_error(int res, sqlite3 *db, const char *format, ...)
50{ 50{
51 log(LOG_ALWAYS, "Fatal SQL error %d", res); 51 log(LOG_ALWAYS, "Fatal SQL error %d", res);
52 va_list args; 52 va_list args;
53 va_start(args, format); 53 va_start(args, format);
54 vlog(LOG_ALWAYS, format, args); 54 vlog(LOG_ALWAYS, format, args);
55 va_end(args); 55 va_end(args);
56 log(LOG_ALWAYS, "SQLite message: %s\n", sqlite3_errmsg(db)); 56 log(LOG_ALWAYS, "SQLite message: %s\n", sqlite3_errmsg(db));
57 exit(1); 57 exit(1);
58} 58}
59 59
60static void openDatabase(sqlite3 **dbReturn) 60static void openDatabase(sqlite3 **dbReturn)
61{ 61{
62 sqlite3 *db; 62 sqlite3 *db;
63 int res; 63 int res;
64 64
65 const char *filename = getenv("MPS_EVENT_DATABASE"); 65 const char *filename = getenv("MPS_EVENT_DATABASE");
66 if(filename == NULL) 66 if(filename == NULL)
67 filename = "mpsevent.db"; 67 filename = "mpsevent.db";
68 log(LOG_OFTEN, "Opening %s.", filename); 68 log(LOG_OFTEN, "Opening %s.", filename);
69 69
70 res = sqlite3_open_v2(filename, 70 res = sqlite3_open_v2(filename,
71 &db, 71 &db,
72 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 72 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
73 NULL); /* use default sqlite_vfs object */ 73 NULL); /* use default sqlite_vfs object */
74 74
75 if (res != SQLITE_OK) 75 if (res != SQLITE_OK)
76 sqlite_error(res, db, "Opening %s failed", filename); 76 sqlite_error(res, db, "Opening %s failed", filename);
77 *dbReturn = db; 77 *dbReturn = db;
78 return; 78 return;
79} 79}
80 80
81/* Macro magic to make a CREATE TABLE statement for each event type. */
82
83#define EVENT_PARAM_SQL_TYPE_A "INTEGER"
84#define EVENT_PARAM_SQL_TYPE_P "INTEGER"
85#define EVENT_PARAM_SQL_TYPE_U "INTEGER"
86#define EVENT_PARAM_SQL_TYPE_W "INTEGER"
87#define EVENT_PARAM_SQL_TYPE_D "REAL "
88#define EVENT_PARAM_SQL_TYPE_S "TEXT "
89#define EVENT_PARAM_SQL_TYPE_B "INTEGER"
90
91#define EVENT_PARAM_SQL_COLUMN(X, index, sort, ident) \
92 "\"" #ident "\" " EVENT_PARAM_SQL_TYPE_##sort ", "
93
94#define EVENT_TABLE_CREATE(X, name, code, always, kind) \
95 "CREATE TABLE IF NOT EXISTS EVENT_" #name " ( " \
96 EVENT_##name##_PARAMS(EVENT_PARAM_SQL_COLUMN, X) \
97 "time INTEGER ) ",
98
81const char *createStatements[] = { 99const char *createStatements[] = {
82 "CREATE TABLE IF NOT EXISTS event_kind (name TEXT," 100 "CREATE TABLE IF NOT EXISTS event_kind (name TEXT,"
83 " description TEXT," 101 " description TEXT,"
84 " enum INTEGER PRIMARY KEY)", 102 " enum INTEGER PRIMARY KEY)",
85 "CREATE TABLE IF NOT EXISTS event_type (name TEXT," 103
86 " code INTEGER PRIMARY KEY," 104 "CREATE TABLE IF NOT EXISTS event_type (name TEXT,"
87 " always INTEGER," 105 " code INTEGER PRIMARY KEY,"
88 " kind INTEGER," 106 " always INTEGER,"
89 " FOREIGN KEY (kind) REFERENCES event_kind(enum));", 107 " kind INTEGER,"
108 " FOREIGN KEY (kind) REFERENCES event_kind(enum));",
109
110EVENT_LIST(EVENT_TABLE_CREATE, X)
90}; 111};
91 112
92const char *populateStatements[] = { 113const char *populateStatements[] = {
93}; 114};
94 115
95#define EVENT_KIND_DO_INSERT(X, name, description) \ 116#define EVENT_KIND_DO_INSERT(X, name, description) \
96 res = sqlite3_bind_text(statement, 1, #name, -1, SQLITE_STATIC); \ 117 res = sqlite3_bind_text(statement, 1, #name, -1, SQLITE_STATIC); \
97 if (res != SQLITE_OK) \ 118 if (res != SQLITE_OK) \
98 sqlite_error(res, db, "event_kind bind of name \"" #name "\" failed."); \ 119 sqlite_error(res, db, "event_kind bind of name \"" #name "\" failed."); \
99 res = sqlite3_bind_text(statement, 2, description, -1, SQLITE_STATIC); \ 120 res = sqlite3_bind_text(statement, 2, description, -1, SQLITE_STATIC); \
100 if (res != SQLITE_OK) \ 121 if (res != SQLITE_OK) \
101 sqlite_error(res, db, "event_kind bind of description \"" description "\" failed."); \ 122 sqlite_error(res, db, "event_kind bind of description \"" description "\" failed."); \
102 res = sqlite3_bind_int(statement, 3, i); \ 123 res = sqlite3_bind_int(statement, 3, i); \
103 if (res != SQLITE_OK) \ 124 if (res != SQLITE_OK) \
104 sqlite_error(res, db, "event_kind bind of enum %d failed.", i); \ 125 sqlite_error(res, db, "event_kind bind of enum %d failed.", i); \
105 ++i; \ 126 ++i; \
106 res = sqlite3_step(statement); \ 127 res = sqlite3_step(statement); \
107 if (res != SQLITE_DONE) \ 128 if (res != SQLITE_DONE) \
108 sqlite_error(res, db, "event_kind insert of name \"" #name "\" failed."); \ 129 sqlite_error(res, db, "event_kind insert of name \"" #name "\" failed."); \
109 if (sqlite3_changes(db) != 0)\ 130 if (sqlite3_changes(db) != 0) \
110 log(LOG_SOMETIMES, "Insert of event_kind row for \"" #name "\" affected %d rows.", sqlite3_changes(db)); \ 131 log(LOG_SOMETIMES, "Insert of event_kind row for \"" #name "\" affected %d rows.", sqlite3_changes(db)); \
111 res = sqlite3_reset(statement); \ 132 res = sqlite3_reset(statement); \
112 if (res != SQLITE_OK) \ 133 if (res != SQLITE_OK) \
113 sqlite_error(res, db, "Couldn't reset event_kind insert statement."); 134 sqlite_error(res, db, "Couldn't reset event_kind insert statement.");
114 135
115#define EVENT_TYPE_DO_INSERT(X, name, code, always, kind) \ 136#define EVENT_TYPE_DO_INSERT(X, name, code, always, kind) \
116 res = sqlite3_bind_text(statement, 1, #name, -1, SQLITE_STATIC); \ 137 res = sqlite3_bind_text(statement, 1, #name, -1, SQLITE_STATIC); \
117 if (res != SQLITE_OK) \ 138 if (res != SQLITE_OK) \
118 sqlite_error(res, db, "event_type bind of name \"" #name "\" failed."); \ 139 sqlite_error(res, db, "event_type bind of name \"" #name "\" failed."); \
119 res = sqlite3_bind_int(statement, 2, code); \ 140 res = sqlite3_bind_int(statement, 2, code); \
120 if (res != SQLITE_OK) \ 141 if (res != SQLITE_OK) \
121 sqlite_error(res, db, "event_type bind of code %d failed.", code); \ 142 sqlite_error(res, db, "event_type bind of code %d failed.", code); \
122 res = sqlite3_bind_int(statement, 3, always); \ 143 res = sqlite3_bind_int(statement, 3, always); \
123 if (res != SQLITE_OK) \ 144 if (res != SQLITE_OK) \
124 sqlite_error(res, db, "event_type bind of always for name \"" #name "\" failed."); \ 145 sqlite_error(res, db, "event_type bind of always for name \"" #name "\" failed."); \
125 res = sqlite3_bind_int(statement, 4, EventKind##kind); \ 146 res = sqlite3_bind_int(statement, 4, EventKind##kind); \
126 if (res != SQLITE_OK) \ 147 if (res != SQLITE_OK) \
127 sqlite_error(res, db, "event_type bind of kind for name \"" #name "\" failed."); \ 148 sqlite_error(res, db, "event_type bind of kind for name \"" #name "\" failed."); \
128 res = sqlite3_step(statement); \ 149 res = sqlite3_step(statement); \
129 if (res != SQLITE_DONE) \ 150 if (res != SQLITE_DONE) \
130 sqlite_error(res, db, "event_type insert of name \"" #name "\" failed."); \ 151 sqlite_error(res, db, "event_type insert of name \"" #name "\" failed."); \
131 if (sqlite3_changes(db) != 0) \ 152 if (sqlite3_changes(db) != 0) \
132 log(LOG_SOMETIMES, "Insert of event_type row for \"" #name "\" affected %d rows.", sqlite3_changes(db)); \ 153 log(LOG_SOMETIMES, "Insert of event_type row for \"" #name "\" affected %d rows.", sqlite3_changes(db)); \
133 res = sqlite3_reset(statement); \ 154 res = sqlite3_reset(statement); \
134 if (res != SQLITE_OK) \ 155 if (res != SQLITE_OK) \
135 sqlite_error(res, db, "Couldn't reset event_type insert statement."); 156 sqlite_error(res, db, "Couldn't reset event_type insert statement.");
136 157
137static void fillTables(sqlite3 *db) 158static void fillTables(sqlite3 *db)
138{ 159{
139 int i; 160 int i;
140 sqlite3_stmt *statement; 161 sqlite3_stmt *statement;
141 162 int res;
142 int res = sqlite3_prepare_v2(db, 163
143 "INSERT OR IGNORE INTO event_kind (name, description, enum)" 164 res = sqlite3_prepare_v2(db,
144 "VALUES (?, ?, ?)", 165 "INSERT OR IGNORE INTO event_kind (name, description, enum)"
145 -1, /* prepare whole string as statement */ 166 "VALUES (?, ?, ?)",
146 &statement, 167 -1, /* prepare whole string as statement */
147 NULL); 168 &statement,
148 if (res != SQLITE_OK) 169 NULL);
149 sqlite_error(res, db, "event_kind preparation failed"); 170 if (res != SQLITE_OK)
150 171 sqlite_error(res, db, "event_kind preparation failed");
151 i = 0; 172
152 EventKindENUM(EVENT_KIND_DO_INSERT, X); 173 i = 0;
153 174 EventKindENUM(EVENT_KIND_DO_INSERT, X);
154 res = sqlite3_finalize(statement); 175
155 if (res != SQLITE_OK) 176 res = sqlite3_finalize(statement);
156 sqlite_error(res, db, "event_kind finalize failed"); 177 if (res != SQLITE_OK)
157 178 sqlite_error(res, db, "event_kind finalize failed");
158 res = sqlite3_prepare_v2(db, 179
159 "INSERT OR IGNORE INTO event_type (name, code, always, kind)" 180 res = sqlite3_prepare_v2(db,
160 "VALUES (?, ?, ?, ?)", 181 "INSERT OR IGNORE INTO event_type (name, code, always, kind)"
161 -1, /* prepare whole string as statement */ 182 "VALUES (?, ?, ?, ?)",
162 &statement, 183 -1, /* prepare whole string as statement */
163 NULL); 184 &statement,
164 if (res != SQLITE_OK) 185 NULL);
165 sqlite_error(res, db, "event_type preparation failed"); 186 if (res != SQLITE_OK)
166 187 sqlite_error(res, db, "event_type preparation failed");
167 EVENT_LIST(EVENT_TYPE_DO_INSERT, X); 188
168 189 EVENT_LIST(EVENT_TYPE_DO_INSERT, X);
169 res = sqlite3_finalize(statement); 190
170 if (res != SQLITE_OK) 191 res = sqlite3_finalize(statement);
171 sqlite_error(res, db, "event_type finalize failed"); 192 if (res != SQLITE_OK)
193 sqlite_error(res, db, "event_type finalize failed");
172} 194}
173 195
174static void makeTables(sqlite3 *db) 196static void makeTables(sqlite3 *db)
175{ 197{
176 int i; 198 int i;
177 199 int res;
178 for (i=0; i < (sizeof(createStatements)/sizeof(createStatements[0])); ++i) { 200
179 log(LOG_SOMETIMES, "Creating tables. SQL command: %s", createStatements[i]); 201 for (i=0; i < (sizeof(createStatements)/sizeof(createStatements[0])); ++i) {
180 int res = sqlite3_exec(db, 202 log(LOG_SOMETIMES, "Creating tables. SQL command: %s", createStatements[i]);
181 createStatements[i], 203 res = sqlite3_exec(db,
182 NULL, /* No callback */ 204 createStatements[i],
183 NULL, /* No callback closure */ 205 NULL, /* No callback */
184 NULL); /* error messages handled by sqlite_error */ 206 NULL, /* No callback closure */
185 if (res != SQLITE_OK) 207 NULL); /* error messages handled by sqlite_error */
186 sqlite_error(res, db, "Table creation failed: %s", createStatements[i]); 208 if (res != SQLITE_OK)
187 } 209 sqlite_error(res, db, "Table creation failed: %s", createStatements[i]);
210 }
211}
212
213void closeDatabase(sqlite3 *db)
214{
215 int res = sqlite3_close(db);
216 if (res != SQLITE_OK)
217 sqlite_error(res, db, "Closing database failed");
218 log(LOG_ALWAYS, "Closed database.");
188} 219}
189 220
190 221
191int main(void) 222int main(void)
192{ 223{
193 sqlite3 *db; 224 sqlite3 *db;
194 225
195 openDatabase(&db); 226 openDatabase(&db);
196 makeTables(db); 227 makeTables(db);
197 fillTables(db); 228 fillTables(db);
198 return 0; 229 closeDatabase(db);
230 return 0;
199} 231}