comparison deita/d_sqlite.c @ 75:ae6a88e6e484

[Deita] Simple DB connection lib.
author June Park <parkjune1995@gmail.com>
date Wed, 31 Dec 2025 11:20:08 -0800
parents
children
comparison
equal deleted inserted replaced
74:4b96794c8d59 75:ae6a88e6e484
1 #include "deita_internal.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5
6 Deita_Connection* deita__sqlite_connection_create(const char *connection_string)
7 {
8 Deita_Connection *p_connection = (Deita_Connection*)malloc(sizeof(Deita_Connection));
9 if (!p_connection)
10 {
11 fprintf(stderr, "deita__sqlite_connection_create: Failed to allocate connection\n");
12 return NULL;
13 }
14
15 p_connection->database_type = DEITA_DATABASE_TYPE_SQLITE3;
16 p_connection->native_handle = NULL;
17 p_connection->is_open = FALSE;
18
19 sqlite3 *p_db = NULL;
20 int32 result = sqlite3_open(connection_string, &p_db);
21
22 if (result != SQLITE_OK)
23 {
24 fprintf(stderr, "deita__sqlite_connection_create: Failed to open database: %s\n", sqlite3_errmsg(p_db));
25 sqlite3_close(p_db);
26 free(p_connection);
27 return NULL;
28 }
29
30 p_connection->native_handle = p_db;
31 p_connection->is_open = TRUE;
32
33 return p_connection;
34 }
35
36 void deita__sqlite_connection_close(Deita_Connection *p_connection)
37 {
38 if (!p_connection)
39 return;
40
41 if (p_connection->native_handle)
42 {
43 sqlite3 *p_db = (sqlite3*)p_connection->native_handle;
44 sqlite3_close(p_db);
45 p_connection->native_handle = NULL;
46 }
47
48 p_connection->is_open = FALSE;
49 free(p_connection);
50 }
51
52 boolean deita__sqlite_connection_is_open(Deita_Connection *p_connection)
53 {
54 if (!p_connection)
55 return FALSE;
56
57 return p_connection->is_open;
58 }
59
60 Deita_Result_Set* deita__sqlite_query_execute(
61 Deita_Connection *p_connection,
62 const char *query,
63 Dowa_Arena *p_arena)
64 {
65 if (!p_connection || !p_connection->native_handle || !query)
66 return NULL;
67
68 sqlite3 *p_db = (sqlite3*)p_connection->native_handle;
69 sqlite3_stmt *p_stmt = NULL;
70
71 int32 result = sqlite3_prepare_v2(p_db, query, -1, &p_stmt, NULL);
72 if (result != SQLITE_OK)
73 {
74 fprintf(stderr, "deita__sqlite_query_execute: Failed to prepare statement: %s\n", sqlite3_errmsg(p_db));
75 return NULL;
76 }
77
78 Deita_Result_Set *p_result_set = (Deita_Result_Set*)Dowa_Arena_Allocate(p_arena, sizeof(Deita_Result_Set));
79 if (!p_result_set)
80 {
81 fprintf(stderr, "deita__sqlite_query_execute: Failed to allocate result set\n");
82 sqlite3_finalize(p_stmt);
83 return NULL;
84 }
85
86 p_result_set->database_type = DEITA_DATABASE_TYPE_SQLITE3;
87 p_result_set->native_result = p_stmt;
88 p_result_set->column_count = sqlite3_column_count(p_stmt);
89 p_result_set->has_data = FALSE;
90 p_result_set->is_done = FALSE;
91
92 return p_result_set;
93 }
94
95 Deita_Result_Set* deita__sqlite_query_execute_prepared(
96 Deita_Connection *p_connection,
97 const char *query,
98 int32 parameter_count,
99 const char **parameter_values,
100 Dowa_Arena *p_arena)
101 {
102 if (!p_connection || !p_connection->native_handle || !query)
103 return NULL;
104
105 sqlite3 *p_db = (sqlite3*)p_connection->native_handle;
106 sqlite3_stmt *p_stmt = NULL;
107
108 int32 result = sqlite3_prepare_v2(p_db, query, -1, &p_stmt, NULL);
109 if (result != SQLITE_OK)
110 {
111 fprintf(stderr, "deita__sqlite_query_execute_prepared: Failed to prepare statement: %s\n", sqlite3_errmsg(p_db));
112 return NULL;
113 }
114
115 for (int32 i = 0; i < parameter_count; i++)
116 {
117 result = sqlite3_bind_text(p_stmt, i + 1, parameter_values[i], -1, SQLITE_TRANSIENT);
118 if (result != SQLITE_OK)
119 {
120 fprintf(stderr, "deita__sqlite_query_execute_prepared: Failed to bind parameter %d: %s\n", i, sqlite3_errmsg(p_db));
121 sqlite3_finalize(p_stmt);
122 return NULL;
123 }
124 }
125
126 Deita_Result_Set *p_result_set = (Deita_Result_Set*)Dowa_Arena_Allocate(p_arena, sizeof(Deita_Result_Set));
127 if (!p_result_set)
128 {
129 fprintf(stderr, "deita__sqlite_query_execute_prepared: Failed to allocate result set\n");
130 sqlite3_finalize(p_stmt);
131 return NULL;
132 }
133
134 p_result_set->database_type = DEITA_DATABASE_TYPE_SQLITE3;
135 p_result_set->native_result = p_stmt;
136 p_result_set->column_count = sqlite3_column_count(p_stmt);
137 p_result_set->has_data = FALSE;
138 p_result_set->is_done = FALSE;
139
140 return p_result_set;
141 }
142
143 int32 deita__sqlite_query_execute_update(
144 Deita_Connection *p_connection,
145 const char *query)
146 {
147 if (!p_connection || !p_connection->native_handle || !query)
148 return -1;
149
150 sqlite3 *p_db = (sqlite3*)p_connection->native_handle;
151 char *error_message = NULL;
152
153 int32 result = sqlite3_exec(p_db, query, NULL, NULL, &error_message);
154 if (result != SQLITE_OK)
155 {
156 fprintf(stderr, "deita__sqlite_query_execute_update: Failed to execute: %s\n", error_message);
157 sqlite3_free(error_message);
158 return -1;
159 }
160
161 return sqlite3_changes(p_db);
162 }
163
164 int32 deita__sqlite_query_execute_update_prepared(
165 Deita_Connection *p_connection,
166 const char *query,
167 int32 parameter_count,
168 const char **parameter_values)
169 {
170 if (!p_connection || !p_connection->native_handle || !query)
171 return -1;
172
173 sqlite3 *p_db = (sqlite3*)p_connection->native_handle;
174 sqlite3_stmt *p_stmt = NULL;
175
176 int32 result = sqlite3_prepare_v2(p_db, query, -1, &p_stmt, NULL);
177 if (result != SQLITE_OK)
178 {
179 fprintf(stderr, "deita__sqlite_query_execute_update_prepared: Failed to prepare statement: %s\n", sqlite3_errmsg(p_db));
180 return -1;
181 }
182
183 for (int32 i = 0; i < parameter_count; i++)
184 {
185 result = sqlite3_bind_text(p_stmt, i + 1, parameter_values[i], -1, SQLITE_TRANSIENT);
186 if (result != SQLITE_OK)
187 {
188 fprintf(stderr, "deita__sqlite_query_execute_update_prepared: Failed to bind parameter %d: %s\n", i, sqlite3_errmsg(p_db));
189 sqlite3_finalize(p_stmt);
190 return -1;
191 }
192 }
193
194 result = sqlite3_step(p_stmt);
195 if (result != SQLITE_DONE)
196 {
197 fprintf(stderr, "deita__sqlite_query_execute_update_prepared: Failed to execute: %s\n", sqlite3_errmsg(p_db));
198 sqlite3_finalize(p_stmt);
199 return -1;
200 }
201
202 int32 changes = sqlite3_changes(p_db);
203 sqlite3_finalize(p_stmt);
204
205 return changes;
206 }
207
208 boolean deita__sqlite_result_set_next(Deita_Result_Set *p_result_set)
209 {
210 if (!p_result_set || !p_result_set->native_result || p_result_set->is_done)
211 return FALSE;
212
213 sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result;
214 int32 result = sqlite3_step(p_stmt);
215
216 if (result == SQLITE_ROW)
217 {
218 p_result_set->has_data = TRUE;
219 return TRUE;
220 }
221 else if (result == SQLITE_DONE)
222 {
223 p_result_set->has_data = FALSE;
224 p_result_set->is_done = TRUE;
225 return FALSE;
226 }
227 else
228 {
229 fprintf(stderr, "deita__sqlite_result_set_next: Error stepping through results\n");
230 p_result_set->has_data = FALSE;
231 p_result_set->is_done = TRUE;
232 return FALSE;
233 }
234 }
235
236 int32 deita__sqlite_result_set_get_column_count(Deita_Result_Set *p_result_set)
237 {
238 if (!p_result_set)
239 return 0;
240
241 return p_result_set->column_count;
242 }
243
244 const char* deita__sqlite_result_set_get_column_name(
245 Deita_Result_Set *p_result_set,
246 int32 column_index)
247 {
248 if (!p_result_set || !p_result_set->native_result)
249 return NULL;
250
251 sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result;
252 return sqlite3_column_name(p_stmt, column_index);
253 }
254
255 Deita_Column_Type deita__sqlite_result_set_get_column_type(
256 Deita_Result_Set *p_result_set,
257 int32 column_index)
258 {
259 if (!p_result_set || !p_result_set->native_result)
260 return DEITA_COLUMN_TYPE_NULL;
261
262 sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result;
263 int32 sqlite_type = sqlite3_column_type(p_stmt, column_index);
264
265 switch (sqlite_type)
266 {
267 case SQLITE_INTEGER:
268 return DEITA_COLUMN_TYPE_INTEGER;
269 case SQLITE_FLOAT:
270 return DEITA_COLUMN_TYPE_REAL;
271 case SQLITE_TEXT:
272 return DEITA_COLUMN_TYPE_TEXT;
273 case SQLITE_BLOB:
274 return DEITA_COLUMN_TYPE_BLOB;
275 case SQLITE_NULL:
276 default:
277 return DEITA_COLUMN_TYPE_NULL;
278 }
279 }
280
281 const char* deita__sqlite_result_set_get_text(
282 Deita_Result_Set *p_result_set,
283 int32 column_index)
284 {
285 if (!p_result_set || !p_result_set->native_result)
286 return NULL;
287
288 sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result;
289 const unsigned char *text = sqlite3_column_text(p_stmt, column_index);
290
291 return (const char*)text;
292 }
293
294 int64 deita__sqlite_result_set_get_integer(
295 Deita_Result_Set *p_result_set,
296 int32 column_index)
297 {
298 if (!p_result_set || !p_result_set->native_result)
299 return 0;
300
301 sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result;
302 return sqlite3_column_int64(p_stmt, column_index);
303 }
304
305 double deita__sqlite_result_set_get_real(
306 Deita_Result_Set *p_result_set,
307 int32 column_index)
308 {
309 if (!p_result_set || !p_result_set->native_result)
310 return 0.0;
311
312 sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result;
313 return sqlite3_column_double(p_stmt, column_index);
314 }
315
316 void deita__sqlite_result_set_free(Deita_Result_Set *p_result_set)
317 {
318 if (!p_result_set)
319 return;
320
321 if (p_result_set->native_result)
322 {
323 sqlite3_stmt *p_stmt = (sqlite3_stmt*)p_result_set->native_result;
324 sqlite3_finalize(p_stmt);
325 p_result_set->native_result = NULL;
326 }
327 }