/* */ #define _POSIX_C_SOURCE 200809L /* strtok_r, strndup */ #include #include /* assert */ #include #include /* size_t */ #include /* free */ #include "data.h" #include "io.h" #include "i18n.h" #include "unused.h" #define FINISH_UP() \ rc = sqlite3_reset(stmt); \ if (SQLITE_OK != rc) { \ fprintf(stderr, string_errmsg_reset, sqlite3_errmsg(db)); \ } \ rc = sqlite3_clear_bindings(stmt); \ if (SQLITE_OK != rc) { \ fprintf(stderr, string_errmsg_clear, sqlite3_errmsg(db)); \ } \ return sqlite3_finalize(stmt) static const char string_errmsg_bind[] = _("Error binding parameter: %s\n"); static const char string_errmsg_clear[] = _("Error clearing bindings: %s\n"); static const char string_errmsg_delete[] = _("Error deleting data: %s\n"); static const char string_errmsg_insert[] = _("Error inserting data: %s\n"); static const char string_errmsg_prepare[] = _("Error preparing data: %s\n"); static const char string_errmsg_readfile[] = _("Error reading file: %s\n"); static const char string_errmsg_reset[] = _("Error resetting statement: %s\n"); static const char string_errmsg_update[] = _("Error updating data: %s\n"); static const char string_null_msg[] = _("(null)\n"); static const char string_sqlite_version[] = _("SQLite version: %s\n"); static const char string_unmatched_comment[] = _("Unmatched comment: %d\n"); int run_script_callback(void *NotUsed, int argc, char **argv, char **azColName) { int i; UNUSED(NotUsed); for (i = 0; i < argc; i++) { printf(" => %s = %s\n", azColName[i], (argv[i] ? argv[i] : string_null_msg)); } return SQLITE_OK; } int run_script(sqlite3 * db, int (*callback)(void *, int, char **, char **), const char *script_filename) { int j, rc, incomment; char *statements, *zErrMsg; char *str1, *saveptr1, *token; zErrMsg = 0; if (!(statements = file_read(script_filename, NULL))) { fprintf(stderr, string_errmsg_readfile, script_filename); return -1; } incomment = 0; for (j = 1, str1 = statements;; j++, str1 = NULL) { token = strtok_r(str1, "\n", &saveptr1); if (token == NULL) break; if (strlen(token) > 2 && token[0] == '-' && token[1] == '-') continue; /* Comment line; TODO multiline comment */ if (strstr(token, "/*")) { incomment = 1; } if (strstr(token, "*/")) { if (!incomment) { fprintf(stderr, string_unmatched_comment, j); } incomment = 0; } if (incomment) continue; printf("%d: %s\n", j, token); rc = sqlite3_exec(db, token, callback, 0, &zErrMsg); if (SQLITE_OK != rc) { fprintf(stderr, "!! SQL error: %s\n", zErrMsg); sqlite3_free(zErrMsg); break; } } free(statements); fprintf(stderr, "Bye!\n"); return SQLITE_OK; } int run_one(sqlite3 * db, int (*callback)(void *, int, char **, char **), const char *query) { int rc = SQLITE_ERROR; char *zErrMsg = NULL; if (SQLITE_OK != (rc = sqlite3_exec(db, query, callback, 0, &zErrMsg))) { fprintf(stderr, "!! SQL error: %s\n", zErrMsg); sqlite3_free(zErrMsg); } return rc; } int insert_new_definition(sqlite3 * db, const char *channel, const char *name, const char *word, const char *definition) { const char insert_stmt[] = "insert into dictionarydb (date_added , channel , added_by, word , definition ) values (datetime('now'), ?, ?, ?, ?)"; int n, rc; sqlite3_stmt *stmt = NULL; rc = sqlite3_prepare_v2(db, insert_stmt, -1, &stmt, 0); if (SQLITE_OK != rc) { fprintf(stderr, string_errmsg_prepare, sqlite3_errmsg(db)); goto _out; } n = 0; #define S(x) \ rc = sqlite3_bind_text(stmt, ++n, x, (int)strnlen(x, 4096), SQLITE_STATIC); \ if (SQLITE_OK != rc) { \ fprintf(stderr, string_errmsg_bind, sqlite3_errmsg(db)); \ goto _out; \ } S(channel); S(name); S(word); S(definition); #undef S if (SQLITE_DONE != (rc = sqlite3_step(stmt))) { fprintf(stderr, string_errmsg_insert, sqlite3_errmsg(db)); } _out: FINISH_UP(); } int delete_from_table_by_rowid(sqlite3 * db, int rowid) { int rc; const char insert_stmt[] = "delete from dictionarydb where rowid = ?"; sqlite3_stmt *stmt = NULL; rc = sqlite3_prepare_v2(db, insert_stmt, -1, &stmt, 0); if (SQLITE_OK != rc) { fprintf(stderr, string_errmsg_prepare, sqlite3_errmsg(db)); goto _out; } rc = sqlite3_bind_int(stmt, 1, rowid); if (SQLITE_OK != rc) { fprintf(stderr, string_errmsg_bind, sqlite3_errmsg(db)); goto _out; } if (SQLITE_DONE != (rc = sqlite3_step(stmt))) { fprintf(stderr, string_errmsg_delete, sqlite3_errmsg(db)); } _out: FINISH_UP(); } int sqlite_version(sqlite3 * db) { int rc; sqlite3_stmt *stmt = NULL; rc = sqlite3_prepare_v2(db, "SELECT SQLITE_VERSION()", -1, &stmt, 0); if (SQLITE_OK != rc) { fprintf(stderr, string_errmsg_prepare, sqlite3_errmsg(db)); goto _out; } while (SQLITE_ROW == (rc = sqlite3_step(stmt))) { printf(string_sqlite_version, sqlite3_column_text(stmt, 0)); } if (SQLITE_DONE != rc) { fprintf(stderr, string_errmsg_update, sqlite3_errmsg(db)); } _out: FINISH_UP(); } /* * table_exists(tbl) => * 0 => table does not exist * 1 => table exists */ int table_exists(sqlite3 * db, int (*callback)(void *, int, char **, char **), const char *table) { int ret, rc; char buf[BUFSIZ]; const char table_exists_query[] = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = '%s'"; char *zErrMsg; ret = 0; memset(buf, 0, BUFSIZ); sprintf(buf, table_exists_query, table); rc = sqlite3_exec(db, buf, callback, 0, &zErrMsg); if (SQLITE_OK == rc) { ret = 1; } return ret; }