/* sql.c */ #include #include #include #include #include #include "sqlite3.h" #include "vm.h" sqlite3 *sql_db; int sql_initialised = 0; #define SQL_FILENAME ".lsdata" void sql_error(char *msg) { fprintf(stderr, "sql error: %s: %s\n", msg, sqlite3_errmsg(sql_db)); } int sql_init(void) { if (sqlite3_open(SQL_FILENAME, &sql_db) != SQLITE_OK) { sql_error("can't open sql database"); sql_initialised = 0; return 0; } sql_initialised = 1; return 1; } void sql_close(void) { sqlite3_close(sql_db); /* * XXX technically, this could return SQLITE_BUSY, which we ought * to deal with */ sql_initialised = 0; } /* * We return 0 for failure, 1 for query with no rows, 2 for query with * a valid return value. */ int sql_query(char *query, int qlen, int *result) { sqlite3_stmt *stmt; const char *ztail; int done; int rows; if (!sql_initialised) return 0; *result = 0; done = 0; rows = 0; if (sqlite3_prepare_v2(sql_db, query, qlen, &stmt, &ztail) != SQLITE_OK) { sql_error("error from sqlite3_prepare"); return 0; } while (1) { int rv = sqlite3_step(stmt); if (rv == SQLITE_DONE) { done = 1; break; } if (rv == SQLITE_ROW) { /* XXX we just deal with one return value for now */ *result = sqlite3_column_int(stmt, 0); rows++; continue; } if (rv == SQLITE_OK) continue; break; } if (!done) { sql_error("error after sqlite3_step"); } if (sqlite3_finalize(stmt) != SQLITE_OK) { sql_error("error from sqlite3_finalize"); return 0; } if (done) return (rows ? 2 : 1); return 0; }