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:
parent
96b2395daa
commit
4a483777bf
1 changed files with 129 additions and 135 deletions
200
src/data.c
200
src/data.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue