mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-28 00:34:06 +02:00
350 lines
8.9 KiB
C
350 lines
8.9 KiB
C
#include "db_sqlite.h"
|
|
#include "../models/models.h"
|
|
#include "../str_util.h"
|
|
#include "db.h"
|
|
#include <assert.h>
|
|
#include <sqlite3.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
static inline char* get_str_safe(sqlite3_stmt* stmt, int col)
|
|
{
|
|
const char* val = (const char*)sqlite3_column_text(stmt, col);
|
|
if (!val)
|
|
return str_dup("NULL");
|
|
return str_dup((const char*)val);
|
|
}
|
|
|
|
#define GET_INT(COL) sqlite3_column_int64(stmt, COL)
|
|
#define GET_STR(COL) get_str_safe(stmt, COL)
|
|
|
|
Db* db_sqlite_new(void)
|
|
{
|
|
Db* db = malloc(sizeof(Db));
|
|
|
|
sqlite3* connection;
|
|
int res = sqlite3_open("database.db", &connection);
|
|
if (res != SQLITE_OK) {
|
|
fprintf(stderr, "error: could not open sqlite 'database.db'\n");
|
|
return NULL;
|
|
}
|
|
sqlite3_close(connection);
|
|
|
|
return db;
|
|
}
|
|
|
|
void db_sqlite_free(Db* db)
|
|
{
|
|
// sqlite3_close(db->connection);
|
|
free(db);
|
|
}
|
|
|
|
static inline DbRes connect(sqlite3** connection)
|
|
{
|
|
int res = sqlite3_open("database.db", connection);
|
|
if (res != SQLITE_OK) {
|
|
fprintf(stderr,
|
|
"error: could not open sqlite 'database.db'\n %s\n",
|
|
sqlite3_errmsg(*connection));
|
|
return DbRes_Error;
|
|
}
|
|
return DbRes_Ok;
|
|
}
|
|
|
|
static inline void disconnect(sqlite3* connection)
|
|
{
|
|
sqlite3_close(connection);
|
|
}
|
|
|
|
#define CONNECT \
|
|
{ \
|
|
if (connect(&connection) != DbRes_Ok) { \
|
|
return DbRes_Error; \
|
|
} \
|
|
}
|
|
|
|
#define DISCONNECT \
|
|
{ \
|
|
disconnect(connection); \
|
|
}
|
|
|
|
DbRes db_user_insert(Db* db, const User* user)
|
|
{
|
|
static_assert(sizeof(User) == 40, "model has changed");
|
|
|
|
sqlite3* connection;
|
|
CONNECT;
|
|
DbRes res;
|
|
|
|
sqlite3_stmt* stmt;
|
|
sqlite3_prepare_v2(connection,
|
|
"INSERT INTO users (name, email, password_hash, balance_dkk_cent) "
|
|
"VALUES (?, ?, ?, ?)",
|
|
-1,
|
|
&stmt,
|
|
NULL);
|
|
|
|
sqlite3_bind_text(stmt, 1, user->name, -1, SQLITE_STATIC);
|
|
sqlite3_bind_text(stmt, 2, user->email, -1, SQLITE_STATIC);
|
|
sqlite3_bind_text(stmt, 3, user->password_hash, -1, SQLITE_STATIC);
|
|
sqlite3_bind_int64(stmt, 4, user->balance_dkk_cent);
|
|
|
|
int step_res = sqlite3_step(stmt);
|
|
if (step_res != SQLITE_DONE) {
|
|
fprintf(stderr, "error: %s\n", sqlite3_errmsg(connection));
|
|
res = DbRes_Error;
|
|
goto l0_return;
|
|
}
|
|
|
|
res = DbRes_Ok;
|
|
l0_return:
|
|
if (stmt)
|
|
sqlite3_finalize(stmt);
|
|
DISCONNECT;
|
|
return res;
|
|
}
|
|
|
|
DbRes db_user_with_id(Db* db, User* user, int64_t id)
|
|
{
|
|
static_assert(sizeof(User) == 40, "model has changed");
|
|
|
|
sqlite3* connection;
|
|
CONNECT;
|
|
DbRes res;
|
|
|
|
sqlite3_stmt* stmt;
|
|
sqlite3_prepare_v2(connection,
|
|
"SELECT id, name, email, password_hash, balance_dkk_cent"
|
|
" FROM users WHERE id = ?",
|
|
-1,
|
|
&stmt,
|
|
NULL);
|
|
sqlite3_bind_int64(stmt, 1, id);
|
|
|
|
int step_res = sqlite3_step(stmt);
|
|
if (step_res == SQLITE_DONE) {
|
|
res = DbRes_NotFound;
|
|
goto l0_return;
|
|
} else if (step_res != SQLITE_ROW) {
|
|
fprintf(stderr, "error: %s\n", sqlite3_errmsg(connection));
|
|
res = DbRes_Error;
|
|
goto l0_return;
|
|
}
|
|
*user = (User) {
|
|
.id = GET_INT(0),
|
|
.name = GET_STR(1),
|
|
.email = GET_STR(2),
|
|
.password_hash = GET_STR(3),
|
|
.balance_dkk_cent = GET_INT(4),
|
|
};
|
|
|
|
res = DbRes_Ok;
|
|
l0_return:
|
|
if (stmt)
|
|
sqlite3_finalize(stmt);
|
|
DISCONNECT;
|
|
return res;
|
|
}
|
|
|
|
DbRes db_users_with_email(Db* db, Ids* ids, const char* email)
|
|
{
|
|
static_assert(sizeof(User) == 40, "model has changed");
|
|
|
|
sqlite3* connection;
|
|
CONNECT;
|
|
DbRes res;
|
|
int sqlite_res;
|
|
|
|
sqlite3_stmt* stmt;
|
|
sqlite_res = sqlite3_prepare_v2(
|
|
connection, "SELECT id FROM users WHERE email = ?", -1, &stmt, NULL);
|
|
sqlite3_bind_text(stmt, 1, email, -1, NULL);
|
|
|
|
while ((sqlite_res = sqlite3_step(stmt)) == SQLITE_ROW) {
|
|
int64_t id = GET_INT(0);
|
|
ids_push(ids, id);
|
|
}
|
|
if (sqlite_res != SQLITE_DONE) {
|
|
fprintf(stderr, "error: %s\n", sqlite3_errmsg(connection));
|
|
res = DbRes_Error;
|
|
goto l0_return;
|
|
}
|
|
|
|
res = DbRes_Ok;
|
|
l0_return:
|
|
if (stmt)
|
|
sqlite3_finalize(stmt);
|
|
DISCONNECT;
|
|
return res;
|
|
}
|
|
|
|
DbRes db_user_with_email(Db* db, User* user, const char* email)
|
|
{
|
|
static_assert(sizeof(User) == 40, "model has changed");
|
|
|
|
sqlite3* connection;
|
|
CONNECT;
|
|
DbRes res;
|
|
|
|
sqlite3_stmt* stmt;
|
|
int prepare_res = sqlite3_prepare_v2(connection,
|
|
"SELECT id, name, email, password_hash, balance_dkk_cent"
|
|
" FROM users WHERE email = ?",
|
|
-1,
|
|
&stmt,
|
|
NULL);
|
|
if (prepare_res != SQLITE_OK) {
|
|
fprintf(stderr,
|
|
"error: %s\n at %s:%d\n",
|
|
sqlite3_errmsg(connection),
|
|
__func__,
|
|
__LINE__);
|
|
res = DbRes_Error;
|
|
goto l0_return;
|
|
}
|
|
sqlite3_bind_text(stmt, 1, email, -1, NULL);
|
|
|
|
int step_res = sqlite3_step(stmt);
|
|
if (step_res == SQLITE_DONE) {
|
|
res = DbRes_NotFound;
|
|
goto l0_return;
|
|
} else if (step_res != SQLITE_ROW) {
|
|
printf("step_res = %d, email = '%s'\n", step_res, email);
|
|
fprintf(stderr,
|
|
"error: %s\n at %s:%d\n",
|
|
sqlite3_errmsg(connection),
|
|
__func__,
|
|
__LINE__);
|
|
res = DbRes_Error;
|
|
goto l0_return;
|
|
}
|
|
*user = (User) {
|
|
.id = GET_INT(0),
|
|
.name = GET_STR(1),
|
|
.email = GET_STR(2),
|
|
.password_hash = GET_STR(3),
|
|
.balance_dkk_cent = GET_INT(4),
|
|
};
|
|
|
|
res = DbRes_Ok;
|
|
l0_return:
|
|
if (stmt)
|
|
sqlite3_finalize(stmt);
|
|
DISCONNECT;
|
|
return res;
|
|
}
|
|
|
|
DbRes db_product_all(Db* db, ProductVec* vec)
|
|
{
|
|
static_assert(sizeof(Product) == 48, "model has changed");
|
|
sqlite3* connection;
|
|
CONNECT;
|
|
DbRes res;
|
|
int sqlite_res;
|
|
|
|
sqlite3_stmt* stmt;
|
|
sqlite_res = sqlite3_prepare_v2(connection,
|
|
"SELECT id, name, description, price_dkk_cent, coord, barcode FROM "
|
|
"products",
|
|
-1,
|
|
&stmt,
|
|
NULL);
|
|
if (sqlite_res != SQLITE_OK) {
|
|
fprintf(stderr, "error: %s\n", sqlite3_errmsg(connection));
|
|
res = DbRes_Error;
|
|
goto l0_return;
|
|
}
|
|
|
|
while ((sqlite_res = sqlite3_step(stmt)) == SQLITE_ROW) {
|
|
Product product = {
|
|
.id = GET_INT(0),
|
|
.name = GET_STR(1),
|
|
.description = GET_STR(2),
|
|
.price_dkk_cent = GET_INT(3),
|
|
.coord_id = GET_INT(4),
|
|
.barcode = GET_STR(5),
|
|
};
|
|
product_vec_push(vec, product);
|
|
}
|
|
if (sqlite_res != SQLITE_DONE) {
|
|
fprintf(stderr, "error: %s\n", sqlite3_errmsg(connection));
|
|
res = DbRes_Error;
|
|
goto l0_return;
|
|
}
|
|
|
|
res = DbRes_Ok;
|
|
l0_return:
|
|
if (stmt)
|
|
sqlite3_finalize(stmt);
|
|
DISCONNECT;
|
|
return res;
|
|
}
|
|
|
|
DbRes db_cart_items_with_user_id(Db* db, CartItemVec* vec, int64_t user_id)
|
|
{
|
|
static_assert(sizeof(Cart) == 16, "model has changed");
|
|
static_assert(sizeof(CartItem) == 32, "model has changed");
|
|
|
|
sqlite3* connection;
|
|
CONNECT;
|
|
DbRes res;
|
|
|
|
sqlite3_stmt* stmt;
|
|
int sqlite_res = sqlite3_prepare_v2(connection,
|
|
"SELECT id "
|
|
" FROM carts WHERE user = ?",
|
|
-1,
|
|
&stmt,
|
|
NULL);
|
|
if (sqlite_res != SQLITE_OK) {
|
|
fprintf(stderr,
|
|
"error: %s\n at %s:%d\n",
|
|
sqlite3_errmsg(connection),
|
|
__func__,
|
|
__LINE__);
|
|
res = DbRes_Error;
|
|
goto l0_return;
|
|
}
|
|
sqlite3_bind_int64(stmt, 1, user_id);
|
|
|
|
int step_res = sqlite3_step(stmt);
|
|
if (step_res == SQLITE_DONE) {
|
|
res = DbRes_NotFound;
|
|
goto l0_return;
|
|
} else if (step_res != SQLITE_ROW) {
|
|
fprintf(stderr, "error: %s\n", sqlite3_errmsg(connection));
|
|
res = DbRes_Error;
|
|
goto l0_return;
|
|
}
|
|
int64_t cart_id = GET_INT(0);
|
|
|
|
sqlite_res = sqlite3_prepare_v2(connection,
|
|
"SELECT id, cart, product, amount FROM cart_items WHERE cart = ?",
|
|
-1,
|
|
&stmt,
|
|
NULL);
|
|
sqlite3_bind_int64(stmt, 1, cart_id);
|
|
|
|
while ((sqlite_res = sqlite3_step(stmt)) == SQLITE_ROW) {
|
|
CartItem cart_item = {
|
|
.id = GET_INT(0),
|
|
.cart_id = GET_INT(1),
|
|
.product_id = GET_INT(2),
|
|
.amount = GET_INT(3),
|
|
};
|
|
cart_item_vec_push(vec, cart_item);
|
|
}
|
|
if (sqlite_res != SQLITE_DONE) {
|
|
fprintf(stderr, "error: %s\n", sqlite3_errmsg(connection));
|
|
res = DbRes_Error;
|
|
goto l0_return;
|
|
}
|
|
|
|
res = DbRes_Ok;
|
|
l0_return:
|
|
if (stmt)
|
|
sqlite3_finalize(stmt);
|
|
DISCONNECT;
|
|
return res;
|
|
}
|