core-legacy/src/database.c

281 lines
6.1 KiB
C
Raw Normal View History

2020-05-05 09:42:02 +00:00
#include <stdint.h>
#include <stddef.h>
#include <logger.h>
#include <database.h>
2020-08-13 09:26:06 +00:00
#include <sql/migration_0.h>
#include <sql/migration_1.h>
2020-05-05 09:42:02 +00:00
sqlite3 *global_database;
static database_transaction_lock *transaction_lock;
2020-08-15 10:13:03 +00:00
void
database_init()
{
int rc = sqlite3_open(global_config.database, &global_database);
if(rc)
{
LOGGER_CRIT("can't open database: %s\n", sqlite3_errmsg(global_database));
exit(1);
}
database_migrate();
2020-08-15 10:13:03 +00:00
sqlite3_exec(global_database, "PRAGMA foreign_keys = ON", 0, 0, 0);
transaction_lock = NULL;
2020-08-15 10:13:03 +00:00
}
void
database_free()
{
sqlite3_close(global_database);
}
2020-05-05 09:42:02 +00:00
static void
database_migrate_step_simple(int level, const char* sql_migration)
{
LOGGER_INFO("migrating LEVEL %d\n", level);
char* err_msg;
sqlite3_exec(global_database, "BEGIN TRANSACTION;", NULL, NULL, NULL);
int rc = sqlite3_exec(global_database, sql_migration, NULL, NULL, &err_msg);
if(rc)
{
LOGGER_CRIT("couldn't migrate LEVEL %d (%s)\n", level, err_msg);
sqlite3_exec(global_database, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
exit(1);
}
LOGGER_DEBUG("storing new user_version %d\n", level + 1);
char pragma_query[32];
sprintf(pragma_query, "PRAGMA user_version=%d;", level + 1);
sqlite3_exec(global_database, pragma_query, 0, 0, 0);
sqlite3_exec(global_database, "COMMIT TRANSACTION;", NULL, NULL, NULL);
}
void
2020-05-05 09:42:02 +00:00
database_migrate()
{
uint16_t version_num = 0;
int s;
2020-05-05 09:42:02 +00:00
sqlite3_stmt *stmt;
sqlite3_prepare_v2(global_database, "PRAGMA user_version;", -1, &stmt, NULL);
2020-05-05 09:42:02 +00:00
s = sqlite3_step(stmt);
if (s == SQLITE_ROW)
{
version_num = sqlite3_column_int(stmt, 0);
}
else
{
version_num = 0;
}
sqlite3_finalize(stmt);
switch(version_num)
{
case 0:
database_migrate_step_simple(0, (const char*)sql_migration_0_sql);
__attribute__ ((fallthrough));
case 1:
database_migrate_step_simple(1, (const char*)sql_migration_1_sql);
__attribute__ ((fallthrough));
2020-05-05 09:42:02 +00:00
default:
break;
}
return;
2020-05-05 09:42:02 +00:00
}
2020-08-15 10:13:03 +00:00
void
database_transaction_begin(database_transaction_lock *lock)
2020-08-15 10:13:03 +00:00
{
if(transaction_lock == NULL)
2020-08-15 10:13:03 +00:00
{
LOGGER_DEBUG("beginning transaction\n");
sqlite3_exec(global_database, "BEGIN TRANSACTION;", NULL, NULL, NULL);
transaction_lock = lock;
2020-08-15 10:13:03 +00:00
}
}
void
database_transaction_commit(database_transaction_lock *lock)
2020-08-15 10:13:03 +00:00
{
if(transaction_lock == lock)
{
LOGGER_DEBUG("commiting transaction\n");
sqlite3_exec(global_database, "COMMIT TRANSACTION;", NULL, NULL, NULL);
transaction_lock = NULL;
}
2020-08-15 10:13:03 +00:00
}
void
database_transaction_rollback(database_transaction_lock *lock)
2020-08-15 10:13:03 +00:00
{
if(transaction_lock == lock)
{
LOGGER_DEBUG("rolling back transaction\n");
sqlite3_exec(global_database, "ROLLBACK TRANSACTION;", NULL, NULL, NULL);
transaction_lock = NULL;
}
2020-08-15 10:13:03 +00:00
}
int
database_helper_get_id(sqlite3_stmt *stmt)
{
int result = 0;
for(;;)
{
int s;
s = sqlite3_step(stmt);
if (s == SQLITE_ROW)
{
result = sqlite3_column_int(stmt, 0);
}
else
{
if (s == SQLITE_DONE)
{
break;
}
else
{
LOGGER_ERR("error selecting id from database: %s\n", sqlite3_errstr(s));
sqlite3_finalize(stmt);
return 0;
}
}
}
sqlite3_finalize(stmt);
return result;
}
int*
database_helper_get_ids(sqlite3_stmt *stmt)
{
int *result = malloc(sizeof(int));
int new_id;
int row = 0;
for(;;)
{
int s;
s = sqlite3_step(stmt);
if (s == SQLITE_ROW)
{
new_id = sqlite3_column_int(stmt, 0);
if(new_id != 0) // found row for other target (relay <> schedule)
{
row++;
result = (int*)realloc(result, sizeof(int) * (row + 1));
result[row - 1] = new_id;
}
}
else
{
if (s == SQLITE_DONE)
{
break;
}
else
{
LOGGER_ERR("error selecting ids from database: %s\n", sqlite3_errstr(s));
sqlite3_finalize(stmt);
return NULL;
}
}
}
sqlite3_finalize(stmt);
result[row] = 0;
return result;
}
char*
database_helper_get_string(sqlite3_stmt *stmt)
{
char *result = NULL;
for(;;)
{
int s;
s = sqlite3_step(stmt);
if (s == SQLITE_ROW)
{
const char *found_string = (const char *)sqlite3_column_text(stmt, 0);
result = (char*)malloc(sizeof(char) * (strlen(found_string) + 1));
strcpy(result, found_string);
}
else
{
if (s == SQLITE_DONE)
{
break;
}
else
{
LOGGER_ERR("error selecting string from database: %s\n", sqlite3_errstr(s));
sqlite3_finalize(stmt);
return NULL;
}
}
}
sqlite3_finalize(stmt);
return result;
}
char**
database_helper_get_strings(sqlite3_stmt *stmt)
{
char **result = malloc(sizeof(char*));
int row = 0;
for(;;)
{
int s;
s = sqlite3_step(stmt);
if (s == SQLITE_ROW)
{
const char *new_string = (const char *)sqlite3_column_text(stmt, 0);
int new_string_len = strlen(new_string);
row++;
result = (char**)realloc(result, sizeof(char*) * (row + 1));
result[row - 1] = malloc(sizeof(char) * (new_string_len + 1));
strcpy(result[row - 1], new_string);
}
else
{
if(s == SQLITE_DONE)
{
break;
}
else
{
LOGGER_ERR("error selecting strings from database: %s\n", sqlite3_errstr(s));
break;
}
}
}
sqlite3_finalize(stmt);
result[row] = NULL;
return result;
}