Use (real) prepared statements for all db actions

Prepared statements were already being used, but wrong. Instead of
creating a string with the right information the SQL should contain
parameters which should be bound by other functions.
This commit is contained in:
Tom Willemse 2013-09-14 15:21:53 +02:00
parent 96b2395daa
commit 4a483777bf

View file

@ -53,44 +53,51 @@ data_add_manga(const gchar *name, gint total_qty)
gboolean gboolean
data_add_to_manga(gint manga_id, gint count) data_add_to_manga(gint manga_id, gint count)
{ {
gchar *sql = char sql[] = "UPDATE manga "
g_strdup_printf(" UPDATE manga " "SET current_qty = current_qty + ? "
" SET current_qty = current_qty + %d " "WHERE id = ?";
" WHERE id = %d", count, manga_id);
gboolean ret = execute_non_query(sql, NULL);
g_free(sql); int bind_variables(sqlite3_stmt *stmt) {
return (sqlite3_bind_int(stmt, 1, count) == SQLITE_OK)
&& (sqlite3_bind_int(stmt, 2, manga_id) == SQLITE_OK);
}
return ret; return execute_non_query(sql, bind_variables);
} }
gboolean gboolean
data_add_volume_to_manga(gint manga_id, gint volume) data_add_volume_to_manga(gint manga_id, gint volume)
{ {
char *sql = g_strdup_printf(" INSERT INTO volume " char sql[] = "INSERT INTO volume "
" VALUES (%d, %d, 0) ", "VALUES (?, ?, 0)";
manga_id, volume);
gboolean ret = execute_non_query(sql, NULL);
g_free(sql); int bind_variables(sqlite3_stmt *stmt) {
return (sqlite3_bind_int(stmt, 1, manga_id) == SQLITE_OK)
&& (sqlite3_bind_int(stmt, 2, volume) == SQLITE_OK);
}
return ret; return execute_non_query(sql, bind_variables);
} }
gboolean gboolean
data_delete_manga(gint manga_id) data_delete_manga(gint manga_id)
{ {
char *sql = g_strdup_printf("DELETE FROM volume " gboolean ret;
"WHERE manga_id = %d", manga_id);
gboolean ret = execute_non_query(sql, NULL);
g_free(sql); char *sql = "DELETE FROM volume "
"WHERE manga_id = ?";
int bind_variables(sqlite3_stmt *stmt) {
return sqlite3_bind_int(stmt, 1, manga_id) == SQLITE_OK;
}
ret = execute_non_query(sql, bind_variables);
if (ret) { if (ret) {
sql = g_strdup_printf("DELETE FROM manga " sql = "DELETE FROM manga "
"WHERE id = %d", manga_id); "WHERE id = ?";
ret = execute_non_query(sql, NULL);
g_free(sql); ret = execute_non_query(sql, bind_variables);
} }
return ret; return ret;
@ -130,35 +137,25 @@ data_get_manga(void)
Manga * Manga *
data_get_manga_by_id(gint manga_id) data_get_manga_by_id(gint manga_id)
{ {
sqlite3 *db; sqlite3 *db = get_database();
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
gchar *data_file;
Manga *manga = NULL; Manga *manga = NULL;
data_file = eom_get_data_file(); if (db) {
if (check_and_create_database(data_file)) {
if (sqlite3_open(data_file, &db) == SQLITE_OK) {
int res; int res;
char *sql = char *sql =
g_strdup_printf(" SELECT id, " "SELECT id, name, current_qty, total_qty "
" name, " "FROM manga "
" current_qty, " "WHERE id = ?";
" total_qty "
" FROM manga "
" WHERE id = %d ", manga_id);
res = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL); res = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL);
g_free(sql);
if (res == SQLITE_OK) { if (res == SQLITE_OK
if (sqlite3_step(stmt) == SQLITE_ROW) { && (sqlite3_bind_int(stmt, 1, manga_id) == SQLITE_OK)
&& sqlite3_step(stmt) == SQLITE_ROW)
manga = get_manga_from_statement(stmt); manga = get_manga_from_statement(stmt);
}
}
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
}
sqlite3_close(db); sqlite3_close(db);
} }
@ -188,45 +185,38 @@ data_get_volumes_for_manga(Manga *manga)
{ {
gint count; gint count;
Volume *volumes = NULL; Volume *volumes = NULL;
sqlite3 *db; sqlite3 *db = get_database();
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
gchar *data_file;
data_file = eom_get_data_file();
count = 0; count = 0;
if (check_and_create_database(data_file)) { if (db) {
if (sqlite3_open(data_file, &db) == SQLITE_OK) {
int res; int res;
char *sql = g_strdup_printf(" SELECT COUNT(id) " char *sql =
" FROM volume " "SELECT COUNT(id) "
" WHERE manga_id = %d ", "FROM volume "
manga->id); "WHERE manga_id = ?";
res = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL); res = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL);
g_free(sql);
if (res == SQLITE_OK) { if (res == SQLITE_OK
if (sqlite3_step(stmt) == SQLITE_ROW) { && (sqlite3_bind_int(stmt, 1, manga->id) == SQLITE_OK)
&& sqlite3_step(stmt) == SQLITE_ROW)
count = sqlite3_column_int(stmt, 0); count = sqlite3_column_int(stmt, 0);
}
}
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
volumes = calloc(sizeof(Volume), count); volumes = calloc(sizeof(Volume), count);
if (count > 0) { if (count > 0) {
sql = g_strdup_printf(" SELECT id, " sql =
" read " "SELECT id, read "
" FROM volume " "FROM volume "
" WHERE manga_id = %d ", "WHERE manga_id = ?";
manga->id);
res = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, res = sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL);
NULL);
g_free(sql);
if (res == SQLITE_OK) { if (res == SQLITE_OK
&& (sqlite3_bind_int(stmt, 1, manga->id) == SQLITE_OK)) {
gint i = 0; gint i = 0;
while (sqlite3_step(stmt) == SQLITE_ROW) { while (sqlite3_step(stmt) == SQLITE_ROW) {
volumes[i].number = sqlite3_column_int(stmt, 0); volumes[i].number = sqlite3_column_int(stmt, 0);
@ -238,7 +228,6 @@ data_get_volumes_for_manga(Manga *manga)
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
} }
}
sqlite3_close(db); sqlite3_close(db);
} }
@ -249,52 +238,63 @@ data_get_volumes_for_manga(Manga *manga)
gboolean gboolean
data_mark_volume_read(int read, gint manga_id, gint volume) data_mark_volume_read(int read, gint manga_id, gint volume)
{ {
gchar *sql = g_strdup_printf(" UPDATE volume " char sql[] = "UPDATE volume "
" SET read = %d " "SET read = ? "
" WHERE manga_id = %d " "WHERE manga_id = ? "
" AND id = %d ", "AND id = ?";
read, manga_id, volume);
gboolean ret = execute_non_query(sql, NULL);
g_free(sql); int bind_variables(sqlite3_stmt *stmt) {
return (sqlite3_bind_int(stmt, 1, read) == SQLITE_OK)
&& (sqlite3_bind_int(stmt, 2, manga_id) == SQLITE_OK)
&& (sqlite3_bind_int(stmt, 3, volume) == SQLITE_OK);
}
return ret; return execute_non_query(sql, bind_variables);
} }
gboolean gboolean
data_remove_volume_from_manga(gint manga_id, gint volume) data_remove_volume_from_manga(gint manga_id, gint volume)
{ {
char *sql = g_strdup_printf(" DELETE FROM volume " char sql[] = "DELETE FROM volume "
" WHERE manga_id = %d " "WHERE manga_id = ? "
" AND id = %d ", manga_id, volume); "AND id = ?";
gboolean ret = execute_non_query(sql, NULL);
g_free(sql); int bind_variables(sqlite3_stmt *stmt) {
return (sqlite3_bind_int(stmt, 1, manga_id) == SQLITE_OK)
&& (sqlite3_bind_int(stmt, 2, volume) == SQLITE_OK);
}
return ret; return execute_non_query(sql, bind_variables);
} }
gboolean gboolean
data_update_manga(gint manga_id, const gchar *name, gint total_qty) data_update_manga(gint manga_id, const gchar *name, gint total_qty)
{ {
gchar *sql = gboolean ret;
g_strdup_printf("UPDATE manga SET " char *sql = "UPDATE manga "
" name = '%s', " "SET name = ?001, total_qty = ?002, "
" total_qty = %d, " " current_qty = MIN(current_qty, ?002) "
" current_qty = MIN(current_qty, %d) " "WHERE id = ?003";
"WHERE id = %d", name, total_qty, total_qty,
manga_id);
gboolean ret = execute_non_query(sql, NULL);
g_free(sql); int bind_variables(sqlite3_stmt *stmt) {
return (sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC) == SQLITE_OK)
&& (sqlite3_bind_int(stmt, 2, total_qty) == SQLITE_OK)
&& (sqlite3_bind_int(stmt, 3, manga_id) == SQLITE_OK);
}
ret = execute_non_query(sql, bind_variables);
if (ret) { if (ret) {
sql = g_strdup_printf("DELETE FROM volume " sql = "DELETE FROM volume "
"WHERE manga_id = %d " "WHERE manga_id = ?"
"AND id > %d", "AND id > ?";
manga_id, total_qty);
ret = execute_non_query(sql, NULL); int bind_variables(sqlite3_stmt *stmt) {
g_free(sql); return (sqlite3_bind_int(stmt, 1, manga_id) == SQLITE_OK)
&& (sqlite3_bind_int(stmt, 2, total_qty) == SQLITE_OK);
}
ret = execute_non_query(sql, bind_variables);
} }
return ret; return ret;
@ -384,10 +384,9 @@ execute_non_query(const gchar *sql, int (*bind)(sqlite3_stmt *))
int res = int res =
sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL); sqlite3_prepare_v2(db, sql, strlen(sql), &stmt, NULL);
if (res == SQLITE_OK) { result = (res == SQLITE_OK
if (bind && bind(stmt) && sqlite3_step(stmt) == SQLITE_DONE) && (!bind || bind(stmt))
result = TRUE; && sqlite3_step(stmt) == SQLITE_DONE);
}
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
sqlite3_close(db); sqlite3_close(db);
@ -415,15 +414,11 @@ get_database(void)
static GList * static GList *
get_manga_for_query(const gchar *query) get_manga_for_query(const gchar *query)
{ {
sqlite3 *database; sqlite3 *database = get_database();
sqlite3_stmt *statement; sqlite3_stmt *statement;
gchar *data_file;
GList *list = NULL; GList *list = NULL;
data_file = eom_get_data_file(); if (database) {
if (check_and_create_database(data_file)) {
if (sqlite3_open(data_file, &database) == SQLITE_OK) {
int res = sqlite3_prepare_v2(database, query, strlen(query), int res = sqlite3_prepare_v2(database, query, strlen(query),
&statement, NULL); &statement, NULL);
@ -438,7 +433,6 @@ get_manga_for_query(const gchar *query)
/* Release the compiled statement from memory */ /* Release the compiled statement from memory */
sqlite3_finalize(statement); sqlite3_finalize(statement);
}
sqlite3_close(database); sqlite3_close(database);
} }