Mercurial
changeset 75:ae6a88e6e484
[Deita] Simple DB connection lib.
| author | June Park <parkjune1995@gmail.com> |
|---|---|
| date | Wed, 31 Dec 2025 11:20:08 -0800 |
| parents | 4b96794c8d59 |
| children | 35b1abc37969 |
| files | deita/BUILD deita/d_connection.c deita/d_query.c deita/d_sqlite.c deita/deita.h deita/deita_internal.h deita/deita_test.c raylib_examples/BUILD raylib_examples/main.c |
| diffstat | 9 files changed, 856 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deita/BUILD Wed Dec 31 11:20:08 2025 -0800 @@ -0,0 +1,26 @@ +load("@rules_cc//cc:cc_library.bzl", "cc_library") +load("@rules_cc//cc:cc_test.bzl", "cc_test") + +cc_library( + name = "deita", + srcs = [ + "d_connection.c", + "d_query.c", + "d_sqlite.c", + ], + hdrs = [ + "deita.h", + "deita_internal.h", + ], + deps = [ + "//dowa:dowa", + ], + linkopts = ["-lsqlite3"], + visibility = ["//visibility:public"], +) + +cc_test( + name = "deita_test", + srcs = ["deita_test.c"], + deps = [":deita"], +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deita/d_connection.c Wed Dec 31 11:20:08 2025 -0800 @@ -0,0 +1,40 @@ +#include "deita_internal.h" +#include <stdio.h> +#include <stdlib.h> + +Deita_Connection* Deita_Connection_Create( + Deita_Database_Type database_type, + const char *connection_string) +{ + if (database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_connection_create(connection_string); + + fprintf(stderr, "Deita_Connection_Create: Unsupported database type %d\n", database_type); + return NULL; +} + +void Deita_Connection_Close(Deita_Connection *p_connection) +{ + if (!p_connection) + return; + + if (p_connection->database_type == DEITA_DATABASE_TYPE_SQLITE3) + { + deita__sqlite_connection_close(p_connection); + return; + } + + fprintf(stderr, "Deita_Connection_Close: Unsupported database type %d\n", p_connection->database_type); +} + +boolean Deita_Connection_Is_Open(Deita_Connection *p_connection) +{ + if (!p_connection) + return FALSE; + + if (p_connection->database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_connection_is_open(p_connection); + + fprintf(stderr, "Deita_Connection_Is_Open: Unsupported database type %d\n", p_connection->database_type); + return FALSE; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deita/d_query.c Wed Dec 31 11:20:08 2025 -0800 @@ -0,0 +1,172 @@ +#include "deita_internal.h" +#include <stdio.h> + +Deita_Result_Set* Deita_Query_Execute( + Deita_Connection *p_connection, + const char *query, + Dowa_Arena *p_arena) +{ + if (!p_connection || !query) + return NULL; + + if (p_connection->database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_query_execute(p_connection, query, p_arena); + + fprintf(stderr, "Deita_Query_Execute: Unsupported database type %d\n", p_connection->database_type); + return NULL; +} + +Deita_Result_Set* Deita_Query_Execute_Prepared( + Deita_Connection *p_connection, + const char *query, + int32 parameter_count, + const char **parameter_values, + Dowa_Arena *p_arena) +{ + if (!p_connection || !query) + return NULL; + + if (p_connection->database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_query_execute_prepared(p_connection, query, parameter_count, parameter_values, p_arena); + + fprintf(stderr, "Deita_Query_Execute_Prepared: Unsupported database type %d\n", p_connection->database_type); + return NULL; +} + +int32 Deita_Query_Execute_Update( + Deita_Connection *p_connection, + const char *query) +{ + if (!p_connection || !query) + return -1; + + if (p_connection->database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_query_execute_update(p_connection, query); + + fprintf(stderr, "Deita_Query_Execute_Update: Unsupported database type %d\n", p_connection->database_type); + return -1; +} + +int32 Deita_Query_Execute_Update_Prepared( + Deita_Connection *p_connection, + const char *query, + int32 parameter_count, + const char **parameter_values) +{ + if (!p_connection || !query) + return -1; + + if (p_connection->database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_query_execute_update_prepared(p_connection, query, parameter_count, parameter_values); + + fprintf(stderr, "Deita_Query_Execute_Update_Prepared: Unsupported database type %d\n", p_connection->database_type); + return -1; +} + +boolean Deita_Result_Set_Next(Deita_Result_Set *p_result_set) +{ + if (!p_result_set) + return FALSE; + + if (p_result_set->database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_result_set_next(p_result_set); + + fprintf(stderr, "Deita_Result_Set_Next: Unsupported database type %d\n", p_result_set->database_type); + return FALSE; +} + +int32 Deita_Result_Set_Get_Column_Count(Deita_Result_Set *p_result_set) +{ + if (!p_result_set) + return 0; + + if (p_result_set->database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_result_set_get_column_count(p_result_set); + + fprintf(stderr, "Deita_Result_Set_Get_Column_Count: Unsupported database type %d\n", p_result_set->database_type); + return 0; +} + +const char* Deita_Result_Set_Get_Column_Name( + Deita_Result_Set *p_result_set, + int32 column_index) +{ + if (!p_result_set) + return NULL; + + if (p_result_set->database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_result_set_get_column_name(p_result_set, column_index); + + fprintf(stderr, "Deita_Result_Set_Get_Column_Name: Unsupported database type %d\n", p_result_set->database_type); + return NULL; +} + +Deita_Column_Type Deita_Result_Set_Get_Column_Type( + Deita_Result_Set *p_result_set, + int32 column_index) +{ + if (!p_result_set) + return DEITA_COLUMN_TYPE_NULL; + + if (p_result_set->database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_result_set_get_column_type(p_result_set, column_index); + + fprintf(stderr, "Deita_Result_Set_Get_Column_Type: Unsupported database type %d\n", p_result_set->database_type); + return DEITA_COLUMN_TYPE_NULL; +} + +const char* Deita_Result_Set_Get_Text( + Deita_Result_Set *p_result_set, + int32 column_index) +{ + if (!p_result_set) + return NULL; + + if (p_result_set->database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_result_set_get_text(p_result_set, column_index); + + fprintf(stderr, "Deita_Result_Set_Get_Text: Unsupported database type %d\n", p_result_set->database_type); + return NULL; +} + +int64 Deita_Result_Set_Get_Integer( + Deita_Result_Set *p_result_set, + int32 column_index) +{ + if (!p_result_set) + return 0; + + if (p_result_set->database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_result_set_get_integer(p_result_set, column_index); + + fprintf(stderr, "Deita_Result_Set_Get_Integer: Unsupported database type %d\n", p_result_set->database_type); + return 0; +} + +double Deita_Result_Set_Get_Real( + Deita_Result_Set *p_result_set, + int32 column_index) +{ + if (!p_result_set) + return 0.0; + + if (p_result_set->database_type == DEITA_DATABASE_TYPE_SQLITE3) + return deita__sqlite_result_set_get_real(p_result_set, column_index); + + fprintf(stderr, "Deita_Result_Set_Get_Real: Unsupported database type %d\n", p_result_set->database_type); + return 0.0; +} + +void Deita_Result_Set_Free(Deita_Result_Set *p_result_set) +{ + if (!p_result_set) + return; + + if (p_result_set->database_type == DEITA_DATABASE_TYPE_SQLITE3) + { + deita__sqlite_result_set_free(p_result_set); + return; + } + + fprintf(stderr, "Deita_Result_Set_Free: Unsupported database type %d\n", p_result_set->database_type); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deita/d_sqlite.c Wed Dec 31 11:20:08 2025 -0800 @@ -0,0 +1,327 @@ +#include "deita_internal.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +Deita_Connection* deita__sqlite_connection_create(const char *connection_string) +{ + Deita_Connection *p_connection = (Deita_Connection*)malloc(sizeof(Deita_Connection)); + if (!p_connection) + { + fprintf(stderr, "deita__sqlite_connection_create: Failed to allocate connection\n"); + return NULL; + } + + p_connection->database_type = DEITA_DATABASE_TYPE_SQLITE3; + p_connection->native_handle = NULL; + p_connection->is_open = FALSE; + + sqlite3 *p_db = NULL; + int32 result = sqlite3_open(connection_string, &p_db); + + if (result != SQLITE_OK) + { + fprintf(stderr, "deita__sqlite_connection_create: Failed to open database: %s\n", sqlite3_errmsg(p_db)); + sqlite3_close(p_db); + free(p_connection); + return NULL; + } + + p_connection->native_handle = p_db; + p_connection->is_open = TRUE; + + return p_connection; +} + +void deita__sqlite_connection_close(Deita_Connection *p_connection) +{ + if (!p_connection) + return; + + if (p_connection->native_handle) + { + sqlite3 *p_db = (sqlite3*)p_connection->native_handle; + sqlite3_close(p_db); + p_connection->native_handle = NULL; + } + + p_connection->is_open = FALSE; + free(p_connection); +} + +boolean deita__sqlite_connection_is_open(Deita_Connection *p_connection) +{ + if (!p_connection) + return FALSE; + + return p_connection->is_open; +} + +Deita_Result_Set* deita__sqlite_query_execute( + Deita_Connection *p_connection, + const char *query, + Dowa_Arena *p_arena) +{ + if (!p_connection || !p_connection->native_handle || !query) + return NULL; + + sqlite3 *p_db = (sqlite3*)p_connection->native_handle; + sqlite3_stmt *p_stmt = NULL; + + int32 result = sqlite3_prepare_v2(p_db, query, -1, &p_stmt, NULL); + if (result != SQLITE_OK) + { + fprintf(stderr, "deita__sqlite_query_execute: Failed to prepare statement: %s\n", sqlite3_errmsg(p_db)); + return NULL; + } + + Deita_Result_Set *p_result_set = (Deita_Result_Set*)Dowa_Arena_Allocate(p_arena, sizeof(Deita_Result_Set)); + if (!p_result_set) + { + fprintf(stderr, "deita__sqlite_query_execute: Failed to allocate result set\n"); + sqlite3_finalize(p_stmt); + return NULL; + } + + p_result_set->database_type = DEITA_DATABASE_TYPE_SQLITE3; + p_result_set->native_result = p_stmt; + p_result_set->column_count = sqlite3_column_count(p_stmt); + p_result_set->has_data = FALSE; + p_result_set->is_done = FALSE; + + return p_result_set; +} + +Deita_Result_Set* deita__sqlite_query_execute_prepared( + Deita_Connection *p_connection, + const char *query, + int32 parameter_count, + const char **parameter_values, + Dowa_Arena *p_arena) +{ + if (!p_connection || !p_connection->native_handle || !query) + return NULL; + + sqlite3 *p_db = (sqlite3*)p_connection->native_handle; + sqlite3_stmt *p_stmt = NULL; + + int32 result = sqlite3_prepare_v2(p_db, query, -1, &p_stmt, NULL); + if (result != SQLITE_OK) + { + fprintf(stderr, "deita__sqlite_query_execute_prepared: Failed to prepare statement: %s\n", sqlite3_errmsg(p_db)); + return NULL; + } + + for (int32 i = 0; i < parameter_count; i++) + { + result = sqlite3_bind_text(p_stmt, i + 1, parameter_values[i], -1, SQLITE_TRANSIENT); + if (result != SQLITE_OK) + { + fprintf(stderr, "deita__sqlite_query_execute_prepared: Failed to bind parameter %d: %s\n", i, sqlite3_errmsg(p_db)); + sqlite3_finalize(p_stmt); + return NULL; + } + } + + Deita_Result_Set *p_result_set = (Deita_Result_Set*)Dowa_Arena_Allocate(p_arena, sizeof(Deita_Result_Set)); + if (!p_result_set) + { + fprintf(stderr, "deita__sqlite_query_execute_prepared: Failed to allocate result set\n"); + sqlite3_finalize(p_stmt); + return NULL; + } + + p_result_set->database_type = DEITA_DATABASE_TYPE_SQLITE3; + p_result_set->native_result = p_stmt; + p_result_set->column_count = sqlite3_column_count(p_stmt); + p_result_set->has_data = FALSE; + p_result_set->is_done = FALSE; + + return p_result_set; +} + +int32 deita__sqlite_query_execute_update( + Deita_Connection *p_connection, + const char *query) +{ + if (!p_connection || !p_connection->native_handle || !query) + return -1; + + sqlite3 *p_db = (sqlite3*)p_connection->native_handle; + char *error_message = NULL; + + int32 result = sqlite3_exec(p_db, query, NULL, NULL, &error_message); + if (result != SQLITE_OK) + { + fprintf(stderr, "deita__sqlite_query_execute_update: Failed to execute: %s\n", error_message); + sqlite3_free(error_message); + return -1; + } + + return sqlite3_changes(p_db); +} + +int32 deita__sqlite_query_execute_update_prepared( + Deita_Connection *p_connection, + const char *query, + int32 parameter_count, + const char **parameter_values) +{ + if (!p_connection || !p_connection->native_handle || !query) + return -1; + + sqlite3 *p_db = (sqlite3*)p_connection->native_handle; + sqlite3_stmt *p_stmt = NULL; + + int32 result = sqlite3_prepare_v2(p_db, query, -1, &p_stmt, NULL); + if (result != SQLITE_OK) + { + fprintf(stderr, "deita__sqlite_query_execute_update_prepared: Failed to prepare statement: %s\n", sqlite3_errmsg(p_db)); + return -1; + } + + for (int32 i = 0; i < parameter_count; i++) + { + result = sqlite3_bind_text(p_stmt, i + 1, parameter_values[i], -1, SQLITE_TRANSIENT); + if (result != SQLITE_OK) + { + fprintf(stderr, "deita__sqlite_query_execute_update_prepared: Failed to bind parameter %d: %s\n", i, sqlite3_errmsg(p_db)); + sqlite3_finalize(p_stmt); + return -1; + } + } + + result = sqlite3_step(p_stmt); + if (result != SQLITE_DONE) + { + fprintf(stderr, "deita__sqlite_query_execute_update_prepared: Failed to execute: %s\n", sqlite3_errmsg(p_db)); + sqlite3_finalize(p_stmt); + return -1; + } + + int32 changes = sqlite3_changes(p_db); + sqlite3_finalize(p_stmt); + + return changes; +} + +boolean deita__sqlite_result_set_next(Deita_Result_Set *p_result_set) +{ + if (!p_result_set || !p_result_set->native_result || p_result_set->is_done) + return FALSE; + + sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result; + int32 result = sqlite3_step(p_stmt); + + if (result == SQLITE_ROW) + { + p_result_set->has_data = TRUE; + return TRUE; + } + else if (result == SQLITE_DONE) + { + p_result_set->has_data = FALSE; + p_result_set->is_done = TRUE; + return FALSE; + } + else + { + fprintf(stderr, "deita__sqlite_result_set_next: Error stepping through results\n"); + p_result_set->has_data = FALSE; + p_result_set->is_done = TRUE; + return FALSE; + } +} + +int32 deita__sqlite_result_set_get_column_count(Deita_Result_Set *p_result_set) +{ + if (!p_result_set) + return 0; + + return p_result_set->column_count; +} + +const char* deita__sqlite_result_set_get_column_name( + Deita_Result_Set *p_result_set, + int32 column_index) +{ + if (!p_result_set || !p_result_set->native_result) + return NULL; + + sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result; + return sqlite3_column_name(p_stmt, column_index); +} + +Deita_Column_Type deita__sqlite_result_set_get_column_type( + Deita_Result_Set *p_result_set, + int32 column_index) +{ + if (!p_result_set || !p_result_set->native_result) + return DEITA_COLUMN_TYPE_NULL; + + sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result; + int32 sqlite_type = sqlite3_column_type(p_stmt, column_index); + + switch (sqlite_type) + { + case SQLITE_INTEGER: + return DEITA_COLUMN_TYPE_INTEGER; + case SQLITE_FLOAT: + return DEITA_COLUMN_TYPE_REAL; + case SQLITE_TEXT: + return DEITA_COLUMN_TYPE_TEXT; + case SQLITE_BLOB: + return DEITA_COLUMN_TYPE_BLOB; + case SQLITE_NULL: + default: + return DEITA_COLUMN_TYPE_NULL; + } +} + +const char* deita__sqlite_result_set_get_text( + Deita_Result_Set *p_result_set, + int32 column_index) +{ + if (!p_result_set || !p_result_set->native_result) + return NULL; + + sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result; + const unsigned char *text = sqlite3_column_text(p_stmt, column_index); + + return (const char*)text; +} + +int64 deita__sqlite_result_set_get_integer( + Deita_Result_Set *p_result_set, + int32 column_index) +{ + if (!p_result_set || !p_result_set->native_result) + return 0; + + sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result; + return sqlite3_column_int64(p_stmt, column_index); +} + +double deita__sqlite_result_set_get_real( + Deita_Result_Set *p_result_set, + int32 column_index) +{ + if (!p_result_set || !p_result_set->native_result) + return 0.0; + + sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result; + return sqlite3_column_double(p_stmt, column_index); +} + +void deita__sqlite_result_set_free(Deita_Result_Set *p_result_set) +{ + if (!p_result_set) + return; + + if (p_result_set->native_result) + { + sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result; + sqlite3_finalize(p_stmt); + p_result_set->native_result = NULL; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deita/deita.h Wed Dec 31 11:20:08 2025 -0800 @@ -0,0 +1,101 @@ +#ifndef DEITA +#define DEITA + +#include "dowa/dowa.h" + +// Database types +typedef enum +{ + DEITA_DATABASE_TYPE_SQLITE3 = 0 + // Future: DEITA_DATABASE_TYPE_POSTGRES, DEITA_DATABASE_TYPE_MYSQL +} Deita_Database_Type; + +// Connection handle (opaque) +typedef struct Deita_Connection Deita_Connection; + +// Result set (opaque) +typedef struct Deita_Result_Set Deita_Result_Set; + +// Column value type +typedef enum +{ + DEITA_COLUMN_TYPE_NULL = 0, + DEITA_COLUMN_TYPE_INTEGER, + DEITA_COLUMN_TYPE_REAL, + DEITA_COLUMN_TYPE_TEXT, + DEITA_COLUMN_TYPE_BLOB +} Deita_Column_Type; + +// --- Connection Management --- // + +extern Deita_Connection* Deita_Connection_Create( + Deita_Database_Type database_type, + const char *connection_string +); + +extern void Deita_Connection_Close(Deita_Connection *p_connection); + +extern boolean Deita_Connection_Is_Open(Deita_Connection *p_connection); + +// --- Query Execution --- // + +extern Deita_Result_Set* Deita_Query_Execute( + Deita_Connection *p_connection, + const char *query, + Dowa_Arena *p_arena +); + +extern Deita_Result_Set* Deita_Query_Execute_Prepared( + Deita_Connection *p_connection, + const char *query, + int32 parameter_count, + const char **parameter_values, + Dowa_Arena *p_arena +); + +extern int32 Deita_Query_Execute_Update( + Deita_Connection *p_connection, + const char *query +); + +extern int32 Deita_Query_Execute_Update_Prepared( + Deita_Connection *p_connection, + const char *query, + int32 parameter_count, + const char **parameter_values +); + +// --- Result Set Access --- // + +extern boolean Deita_Result_Set_Next(Deita_Result_Set *p_result_set); + +extern int32 Deita_Result_Set_Get_Column_Count(Deita_Result_Set *p_result_set); + +extern const char* Deita_Result_Set_Get_Column_Name( + Deita_Result_Set *p_result_set, + int32 column_index +); + +extern Deita_Column_Type Deita_Result_Set_Get_Column_Type( + Deita_Result_Set *p_result_set, + int32 column_index +); + +extern const char* Deita_Result_Set_Get_Text( + Deita_Result_Set *p_result_set, + int32 column_index +); + +extern int64 Deita_Result_Set_Get_Integer( + Deita_Result_Set *p_result_set, + int32 column_index +); + +extern double Deita_Result_Set_Get_Real( + Deita_Result_Set *p_result_set, + int32 column_index +); + +extern void Deita_Result_Set_Free(Deita_Result_Set *p_result_set); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deita/deita_internal.h Wed Dec 31 11:20:08 2025 -0800 @@ -0,0 +1,63 @@ +#ifndef DEITA_INTERNAL +#define DEITA_INTERNAL + +#include <sqlite3.h> +#include "deita.h" + +struct Deita_Connection +{ + Deita_Database_Type database_type; + void *native_handle; + boolean is_open; +}; + +struct Deita_Result_Set +{ + Deita_Database_Type database_type; + void *native_result; + int32 column_count; + boolean has_data; + boolean is_done; +}; + +// SQLite3-specific functions (implemented in d_sqlite.c) +extern Deita_Connection* deita__sqlite_connection_create(const char *connection_string); +extern void deita__sqlite_connection_close(Deita_Connection *p_connection); +extern boolean deita__sqlite_connection_is_open(Deita_Connection *p_connection); + +extern Deita_Result_Set* deita__sqlite_query_execute( + Deita_Connection *p_connection, + const char *query, + Dowa_Arena *p_arena +); + +extern Deita_Result_Set* deita__sqlite_query_execute_prepared( + Deita_Connection *p_connection, + const char *query, + int32 parameter_count, + const char **parameter_values, + Dowa_Arena *p_arena +); + +extern int32 deita__sqlite_query_execute_update( + Deita_Connection *p_connection, + const char *query +); + +extern int32 deita__sqlite_query_execute_update_prepared( + Deita_Connection *p_connection, + const char *query, + int32 parameter_count, + const char **parameter_values +); + +extern boolean deita__sqlite_result_set_next(Deita_Result_Set *p_result_set); +extern int32 deita__sqlite_result_set_get_column_count(Deita_Result_Set *p_result_set); +extern const char* deita__sqlite_result_set_get_column_name(Deita_Result_Set *p_result_set, int32 column_index); +extern Deita_Column_Type deita__sqlite_result_set_get_column_type(Deita_Result_Set *p_result_set, int32 column_index); +extern const char* deita__sqlite_result_set_get_text(Deita_Result_Set *p_result_set, int32 column_index); +extern int64 deita__sqlite_result_set_get_integer(Deita_Result_Set *p_result_set, int32 column_index); +extern double deita__sqlite_result_set_get_real(Deita_Result_Set *p_result_set, int32 column_index); +extern void deita__sqlite_result_set_free(Deita_Result_Set *p_result_set); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deita/deita_test.c Wed Dec 31 11:20:08 2025 -0800 @@ -0,0 +1,127 @@ +#include "deita.h" +#include <stdio.h> +#include <assert.h> +#include <unistd.h> + +int main(void) +{ + printf("=== Deita Library Tests ===\n\n"); + + const char *test_db_path = "/tmp/deita_test.db"; + unlink(test_db_path); + + // Test 1: Connection creation + printf("Test 1: Creating SQLite3 connection...\n"); + Deita_Connection *p_connection = Deita_Connection_Create(DEITA_DATABASE_TYPE_SQLITE3, test_db_path); + assert(p_connection != NULL); + assert(Deita_Connection_Is_Open(p_connection) == TRUE); + printf(" PASSED: Connection created successfully\n\n"); + + // Test 2: Create table + printf("Test 2: Creating test table...\n"); + const char *create_table_query = + "CREATE TABLE IF NOT EXISTS test_users (" + " id INTEGER PRIMARY KEY AUTOINCREMENT," + " username TEXT NOT NULL," + " age INTEGER" + ")"; + int32 result = Deita_Query_Execute_Update(p_connection, create_table_query); + assert(result == 0); + printf(" PASSED: Table created\n\n"); + + // Test 3: Insert data + printf("Test 3: Inserting test data...\n"); + const char *insert_query = "INSERT INTO test_users (username, age) VALUES ('alice', 25)"; + result = Deita_Query_Execute_Update(p_connection, insert_query); + assert(result == 1); + printf(" PASSED: Inserted 1 row\n\n"); + + // Test 4: Insert with prepared statement + printf("Test 4: Inserting with prepared statement...\n"); + const char *insert_prepared_query = "INSERT INTO test_users (username, age) VALUES (?, ?)"; + const char *params[] = {"bob", "30"}; + result = Deita_Query_Execute_Update_Prepared(p_connection, insert_prepared_query, 2, params); + assert(result == 1); + printf(" PASSED: Inserted 1 row with prepared statement\n\n"); + + // Test 5: Query data + printf("Test 5: Querying test data...\n"); + Dowa_Arena *p_arena = Dowa_Arena_Create(ONE_MEGA_BYTE); + const char *select_query = "SELECT id, username, age FROM test_users ORDER BY id"; + Deita_Result_Set *p_result_set = Deita_Query_Execute(p_connection, select_query, p_arena); + assert(p_result_set != NULL); + + int32 row_count = 0; + while (Deita_Result_Set_Next(p_result_set)) + { + row_count++; + int64 id = Deita_Result_Set_Get_Integer(p_result_set, 0); + const char *username = Deita_Result_Set_Get_Text(p_result_set, 1); + int64 age = Deita_Result_Set_Get_Integer(p_result_set, 2); + + printf(" Row %d: id=%lld, username=%s, age=%lld\n", row_count, id, username, age); + + if (row_count == 1) + { + assert(id == 1); + assert(strcmp(username, "alice") == 0); + assert(age == 25); + } + else if (row_count == 2) + { + assert(id == 2); + assert(strcmp(username, "bob") == 0); + assert(age == 30); + } + } + assert(row_count == 2); + Deita_Result_Set_Free(p_result_set); + printf(" PASSED: Retrieved 2 rows\n\n"); + + // Test 6: Query with prepared statement + printf("Test 6: Querying with prepared statement...\n"); + const char *select_prepared_query = "SELECT username, age FROM test_users WHERE username = ?"; + const char *query_params[] = {"alice"}; + p_result_set = Deita_Query_Execute_Prepared(p_connection, select_prepared_query, 1, query_params, p_arena); + assert(p_result_set != NULL); + + assert(Deita_Result_Set_Next(p_result_set) == TRUE); + const char *username = Deita_Result_Set_Get_Text(p_result_set, 0); + int64 age = Deita_Result_Set_Get_Integer(p_result_set, 1); + assert(strcmp(username, "alice") == 0); + assert(age == 25); + assert(Deita_Result_Set_Next(p_result_set) == FALSE); + Deita_Result_Set_Free(p_result_set); + printf(" PASSED: Retrieved correct row with prepared statement\n\n"); + + // Test 7: Column metadata + printf("Test 7: Testing column metadata...\n"); + p_result_set = Deita_Query_Execute(p_connection, "SELECT id, username FROM test_users LIMIT 1", p_arena); + assert(p_result_set != NULL); + + int32 column_count = Deita_Result_Set_Get_Column_Count(p_result_set); + assert(column_count == 2); + + const char *col_name_0 = Deita_Result_Set_Get_Column_Name(p_result_set, 0); + const char *col_name_1 = Deita_Result_Set_Get_Column_Name(p_result_set, 1); + assert(strcmp(col_name_0, "id") == 0); + assert(strcmp(col_name_1, "username") == 0); + + assert(Deita_Result_Set_Next(p_result_set) == TRUE); + Deita_Column_Type type_0 = Deita_Result_Set_Get_Column_Type(p_result_set, 0); + Deita_Column_Type type_1 = Deita_Result_Set_Get_Column_Type(p_result_set, 1); + assert(type_0 == DEITA_COLUMN_TYPE_INTEGER); + assert(type_1 == DEITA_COLUMN_TYPE_TEXT); + + Deita_Result_Set_Free(p_result_set); + printf(" PASSED: Column metadata correct\n\n"); + + // Cleanup + printf("Cleanup: Closing connection and freeing arena...\n"); + Dowa_Arena_Free(p_arena); + Deita_Connection_Close(p_connection); + unlink(test_db_path); + + printf("\n=== All tests passed! ===\n"); + return 0; +}
--- a/raylib_examples/BUILD Wed Dec 31 11:17:24 2025 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,11 +0,0 @@ -load("//third_party/raylib:raylib.bzl", "raylib_binary") - -raylib_binary( - name = "hello_world", - srcs = ["main.c"], - deps = [ - "//dowa:dowa", - "//third_party/raylib:raylib", - ], -) -
--- a/raylib_examples/main.c Wed Dec 31 11:17:24 2025 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -#include <stdio.h> -#include "dowa/dowa.h" -#include "third_party/raylib/include/raylib.h" - -int main() -{ - InitWindow(800, 450, "raylib [core] example - basic window"); - while (!WindowShouldClose()) - { - BeginDrawing(); - ClearBackground(RAYWHITE); - DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY); - EndDrawing(); - } - CloseWindow(); - return 0; -}