Line | Branch | Exec | Source |
---|---|---|---|
1 | /* GATE PROJECT LICENSE: | ||
2 | +----------------------------------------------------------------------------+ | ||
3 | | Copyright(c) 2018-2025, Stefan Meislinger | | ||
4 | | All rights reserved. | | ||
5 | | | | ||
6 | | Redistribution and use in source and binary forms, with or without | | ||
7 | | modification, are permitted provided that the following conditions are met:| | ||
8 | | | | ||
9 | | 1. Redistributions of source code must retain the above copyright notice, | | ||
10 | | this list of conditions and the following disclaimer. | | ||
11 | | 2. Redistributions in binary form must reproduce the above copyright | | ||
12 | | notice, this list of conditions and the following disclaimer in the | | ||
13 | | documentation and/or other materials provided with the distribution. | | ||
14 | | | | ||
15 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"| | ||
16 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | ||
17 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | ||
18 | | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | | ||
19 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | ||
20 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | ||
21 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | ||
22 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | ||
23 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | ||
24 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | ||
25 | | THE POSSIBILITY OF SUCH DAMAGE. | | ||
26 | +----------------------------------------------------------------------------+ | ||
27 | */ | ||
28 | |||
29 | /** @file | ||
30 | * @brief Data adapter generator utilities | ||
31 | * @ingroup gatedata | ||
32 | */ | ||
33 | |||
34 | #ifndef GATE_DATA_ADAPTER_BASE_H_INCLUDED | ||
35 | #define GATE_DATA_ADAPTER_BASE_H_INCLUDED | ||
36 | |||
37 | #include "gate/data/adapter.h" | ||
38 | #include "gate/results.h" | ||
39 | |||
40 | #if defined(__cplusplus) | ||
41 | extern "C" { | ||
42 | #endif | ||
43 | |||
44 | |||
45 | /*********************************** | ||
46 | * data reader base implementation * | ||
47 | ***********************************/ | ||
48 | |||
49 | #define GATE_DATA_ADAPTER_BASE_READER_MAX_FIELDS 64 | ||
50 | typedef void* gate_data_handles_t[4]; | ||
51 | |||
52 | typedef struct gate_data_reader_base_class gate_data_reader_base_t; | ||
53 | |||
54 | struct gate_data_reader_base_class | ||
55 | { | ||
56 | GATE_INTERFACE_VTBL(gate_data_reader) const* vtbl; | ||
57 | |||
58 | gate_atomic_int_t ref_counter; | ||
59 | |||
60 | gate_data_statement_t* statement; | ||
61 | gate_data_handles_t native_handles; /* DB native query handles */ | ||
62 | gate_size_t field_count; /* amount of data fields (columns) in query result */ | ||
63 | |||
64 | gate_string_t names[GATE_DATA_ADAPTER_BASE_READER_MAX_FIELDS]; /* column names */ | ||
65 | gate_type_id_t types[GATE_DATA_ADAPTER_BASE_READER_MAX_FIELDS]; /* column field data types */ | ||
66 | gate_value_t values[GATE_DATA_ADAPTER_BASE_READER_MAX_FIELDS]; /* currently loaded column field values */ | ||
67 | void* params[GATE_DATA_ADAPTER_BASE_READER_MAX_FIELDS]; /* additional column parameters */ | ||
68 | |||
69 | gate_result_t(*init)(gate_data_reader_base_t* reader); /* prepares names, types and params fields*/ | ||
70 | gate_bool_t(*is_valid)(gate_data_reader_base_t* reader); /* returns true if data row is loaded and valid */ | ||
71 | gate_result_t(*next)(gate_data_reader_base_t* reader); /* discards current data row and loads next one int values */ | ||
72 | gate_result_t(*close)(gate_data_reader_base_t* reader); /* closes DB query resources and releases field values */ | ||
73 | }; | ||
74 | |||
75 | |||
76 | 4 | static gate_bool_t gate_data_reader_base_is_valid(void* This) | |
77 | { | ||
78 | 4 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
79 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (self->is_valid) |
80 | { | ||
81 | 4 | return self->is_valid(self); | |
82 | } | ||
83 | ✗ | return false; | |
84 | } | ||
85 | |||
86 | 3 | static gate_result_t gate_data_reader_base_close(void* This) | |
87 | { | ||
88 | 3 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
89 | 3 | gate_result_t ret = GATE_RESULT_NOTSUPPORTED; | |
90 | gate_size_t ndx; | ||
91 | do | ||
92 | { | ||
93 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (self->close) |
94 | { | ||
95 | 3 | ret = self->close(self); | |
96 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | GATE_BREAK_IF_FAILED(ret); |
97 | } | ||
98 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (ndx = 0; ndx != self->field_count; ++ndx) |
99 | { | ||
100 | 3 | gate_string_release(&self->names[ndx]); | |
101 | 3 | gate_value_release(&self->values[ndx]); | |
102 | } | ||
103 | 3 | gate_mem_clear(self->names, sizeof(self->names)); | |
104 | 3 | gate_mem_clear(self->values, sizeof(self->values)); | |
105 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if (self->statement) |
106 | { | ||
107 | 1 | gate_object_release(self->statement); | |
108 | 1 | self->statement = NULL; | |
109 | } | ||
110 | 3 | ret = GATE_RESULT_OK; | |
111 | } while (0); | ||
112 | 3 | return ret; | |
113 | } | ||
114 | |||
115 | 2 | static gate_result_t gate_data_reader_base_next(void* This) | |
116 | { | ||
117 | 2 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
118 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (self->next) |
119 | { | ||
120 | 2 | return self->next(self); | |
121 | } | ||
122 | ✗ | return GATE_RESULT_NOTSUPPORTED; | |
123 | } | ||
124 | |||
125 | ✗ | static gate_size_t gate_data_reader_base_get_field_count(void* This) | |
126 | { | ||
127 | ✗ | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
128 | ✗ | return self->field_count; | |
129 | } | ||
130 | 1 | static gate_result_t gate_data_reader_base_get_field_type(void* This, gate_size_t field_index, gate_type_id_t* ptr_type) | |
131 | { | ||
132 | 1 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
133 | 1 | gate_result_t ret = GATE_RESULT_FAILED; | |
134 | do | ||
135 | { | ||
136 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!gate_data_reader_base_is_valid(self)) |
137 | { | ||
138 | ✗ | ret = GATE_RESULT_ENDOFSTREAM; | |
139 | ✗ | break; | |
140 | } | ||
141 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (field_index >= self->field_count) |
142 | { | ||
143 | ✗ | ret = GATE_RESULT_OUTOFBOUNDS; | |
144 | ✗ | break; | |
145 | } | ||
146 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (ptr_type) |
147 | { | ||
148 | 1 | *ptr_type = self->values[field_index].value_type; | |
149 | } | ||
150 | 1 | ret = GATE_RESULT_OK; | |
151 | } while (0); | ||
152 | 1 | return ret; | |
153 | } | ||
154 | ✗ | static gate_result_t gate_data_reader_base_get_field_name(void* This, gate_size_t field_index, gate_string_t const** ptr_name) | |
155 | { | ||
156 | ✗ | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
157 | ✗ | gate_result_t ret = GATE_RESULT_FAILED; | |
158 | do | ||
159 | { | ||
160 | ✗ | if (!gate_data_reader_base_is_valid(self)) | |
161 | { | ||
162 | ✗ | ret = GATE_RESULT_ENDOFSTREAM; | |
163 | ✗ | break; | |
164 | } | ||
165 | ✗ | if (field_index >= self->field_count) | |
166 | { | ||
167 | ✗ | ret = GATE_RESULT_OUTOFBOUNDS; | |
168 | ✗ | break; | |
169 | } | ||
170 | ✗ | if (ptr_name) | |
171 | { | ||
172 | ✗ | *ptr_name = &self->names[field_index]; | |
173 | } | ||
174 | ✗ | ret = GATE_RESULT_OK; | |
175 | } while (0); | ||
176 | ✗ | return ret; | |
177 | } | ||
178 | 1 | static gate_result_t gate_data_reader_base_get_field_value(void* This, gate_size_t field_index, gate_value_t const** ptr_value) | |
179 | { | ||
180 | 1 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
181 | 1 | gate_result_t ret = GATE_RESULT_FAILED; | |
182 | do | ||
183 | { | ||
184 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!gate_data_reader_base_is_valid(self)) |
185 | { | ||
186 | ✗ | ret = GATE_RESULT_ENDOFSTREAM; | |
187 | ✗ | break; | |
188 | } | ||
189 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (field_index >= self->field_count) |
190 | { | ||
191 | ✗ | ret = GATE_RESULT_OUTOFBOUNDS; | |
192 | ✗ | break; | |
193 | } | ||
194 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (ptr_value) |
195 | { | ||
196 | 1 | *ptr_value = &self->values[field_index]; | |
197 | } | ||
198 | 1 | ret = GATE_RESULT_OK; | |
199 | } while (0); | ||
200 | 1 | return ret; | |
201 | } | ||
202 | |||
203 | ✗ | static char const* gate_data_reader_base_get_interface_name(void* This) | |
204 | { | ||
205 | GATE_UNUSED_ARG(This); | ||
206 | ✗ | return GATE_INTERFACE_NAME_DATA_READER; | |
207 | } | ||
208 | |||
209 | 1 | static void gate_data_reader_base_release(void* This) | |
210 | { | ||
211 | 1 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
212 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | if (0 == gate_atomic_int_dec(&self->ref_counter)) |
213 | { | ||
214 | 1 | gate_data_reader_base_close(This); | |
215 | 1 | gate_mem_dealloc(self); | |
216 | } | ||
217 | 1 | } | |
218 | |||
219 | ✗ | static int gate_data_reader_base_retain(void* This) | |
220 | { | ||
221 | ✗ | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
222 | ✗ | return gate_atomic_int_inc(&self->ref_counter); | |
223 | } | ||
224 | |||
225 | |||
226 | 1 | static GATE_INTERFACE_VTBL(gate_data_reader) const* gate_init_data_reader_base_vtbl() | |
227 | { | ||
228 | static GATE_INTERFACE_VTBL(gate_data_reader) gate_data_reader_base_vtbl; | ||
229 | |||
230 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (!gate_data_reader_base_vtbl.get_interface_name) |
231 | { | ||
232 | GATE_INTERFACE_VTBL(gate_data_reader) const local_vtbl = | ||
233 | { | ||
234 | &gate_data_reader_base_get_interface_name, | ||
235 | &gate_data_reader_base_release, | ||
236 | &gate_data_reader_base_retain, | ||
237 | |||
238 | &gate_data_reader_base_is_valid, | ||
239 | &gate_data_reader_base_next, | ||
240 | &gate_data_reader_base_close, | ||
241 | &gate_data_reader_base_get_field_count, | ||
242 | &gate_data_reader_base_get_field_type, | ||
243 | &gate_data_reader_base_get_field_name, | ||
244 | &gate_data_reader_base_get_field_value | ||
245 | }; | ||
246 | |||
247 | 1 | gate_data_reader_base_vtbl = local_vtbl; | |
248 | } | ||
249 | 1 | return &gate_data_reader_base_vtbl; | |
250 | } | ||
251 | |||
252 | 1 | static gate_data_reader_t* gate_data_reader_base_create(gate_data_statement_t* statement, | |
253 | gate_data_handles_t handles, | ||
254 | gate_result_t(*init)(gate_data_reader_base_t* reader), | ||
255 | gate_bool_t(*is_valid)(gate_data_reader_base_t* reader), | ||
256 | gate_result_t(*next)(gate_data_reader_base_t* reader), | ||
257 | gate_result_t(*close)(gate_data_reader_base_t* reader)) | ||
258 | { | ||
259 | 1 | gate_data_reader_t* ret = NULL; | |
260 | 1 | gate_data_reader_base_t* reader = NULL; | |
261 | gate_result_t res; | ||
262 | |||
263 | do | ||
264 | { | ||
265 | 1 | reader = (gate_data_reader_base_t*)gate_mem_alloc(sizeof(gate_data_reader_base_t)); | |
266 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (reader == NULL) |
267 | { | ||
268 | ✗ | break; | |
269 | } | ||
270 | 1 | gate_mem_clear(reader, sizeof(gate_data_reader_base_t)); | |
271 | 1 | reader->vtbl = gate_init_data_reader_base_vtbl(); | |
272 | 1 | gate_atomic_int_init(&reader->ref_counter, 1); | |
273 | |||
274 | 1 | gate_mem_copy(reader->native_handles, handles, sizeof(reader->native_handles)); | |
275 | 1 | reader->statement = statement; | |
276 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (reader->statement) |
277 | { | ||
278 | 1 | gate_object_retain(reader->statement); | |
279 | } | ||
280 | 1 | reader->field_count = 0; | |
281 | |||
282 | 1 | reader->init = init; | |
283 | 1 | reader->is_valid = is_valid; | |
284 | 1 | reader->next = next; | |
285 | 1 | reader->close = close; | |
286 | |||
287 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (reader->init) |
288 | { | ||
289 | 1 | res = reader->init(reader); | |
290 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (GATE_FAILED(res)) |
291 | { | ||
292 | ✗ | gate_mem_dealloc(reader); | |
293 | ✗ | break; | |
294 | } | ||
295 | } | ||
296 | |||
297 | 1 | ret = (gate_data_reader_t*)reader; | |
298 | 1 | reader = NULL; | |
299 | } while (0); | ||
300 | 1 | return ret; | |
301 | } | ||
302 | |||
303 | |||
304 | |||
305 | /*************************************** | ||
306 | * data connection base implementation * | ||
307 | ***************************************/ | ||
308 | |||
309 | typedef struct gate_data_connection_base_class gate_data_connection_base_t; | ||
310 | |||
311 | struct gate_data_connection_base_class | ||
312 | { | ||
313 | GATE_INTERFACE_VTBL(gate_data_connection) const* vtbl; | ||
314 | |||
315 | gate_atomic_int_t ref_counter; | ||
316 | gate_data_handles_t native_handles; | ||
317 | |||
318 | gate_result_t(*init)(gate_data_connection_base_t* self); | ||
319 | void(*close)(gate_data_connection_base_t* self); | ||
320 | gate_result_t(*create_statement)(gate_data_connection_base_t* self, gate_string_t const* sql, gate_data_statement_t** ptr_stmt); | ||
321 | }; | ||
322 | |||
323 | ✗ | static char const* gate_data_connection_base_get_interface_name(void* This) | |
324 | { | ||
325 | GATE_UNUSED_ARG(This); | ||
326 | ✗ | return GATE_INTERFACE_NAME_DATA_CONNECTION; | |
327 | } | ||
328 | 3 | static void gate_data_connection_base_release(void* This) | |
329 | { | ||
330 | 3 | gate_data_connection_base_t* self = (gate_data_connection_base_t*)This; | |
331 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
|
3 | if (0 == gate_atomic_int_dec(&self->ref_counter)) |
332 | { | ||
333 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (self->close) |
334 | { | ||
335 | 1 | self->close(self); | |
336 | } | ||
337 | 1 | gate_mem_dealloc(self); | |
338 | } | ||
339 | 3 | } | |
340 | 2 | static int gate_data_connection_base_retain(void* This) | |
341 | { | ||
342 | 2 | gate_data_connection_base_t* self = (gate_data_connection_base_t*)This; | |
343 | 2 | return (int)gate_atomic_int_inc(&self->ref_counter); | |
344 | } | ||
345 | |||
346 | 2 | static gate_result_t gate_data_connection_base_create_statement(void* This, gate_string_t const* sql, gate_data_statement_t** ptr_stmt) | |
347 | { | ||
348 | 2 | gate_data_connection_base_t* self = (gate_data_connection_base_t*)This; | |
349 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (self->create_statement) |
350 | { | ||
351 | 2 | return self->create_statement(self, sql, ptr_stmt); | |
352 | } | ||
353 | ✗ | return GATE_RESULT_NOTSUPPORTED; | |
354 | } | ||
355 | |||
356 | static GATE_INTERFACE_VTBL(gate_data_connection) gate_data_connection_base_vtbl; | ||
357 | 1 | static void gate_init_data_connection_base_vtbl() | |
358 | { | ||
359 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (!gate_data_connection_base_vtbl.get_interface_name) |
360 | { | ||
361 | GATE_INTERFACE_VTBL(gate_data_connection) const local_vtbl = | ||
362 | { | ||
363 | &gate_data_connection_base_get_interface_name, | ||
364 | &gate_data_connection_base_release, | ||
365 | &gate_data_connection_base_retain, | ||
366 | |||
367 | &gate_data_connection_base_create_statement | ||
368 | }; | ||
369 | 1 | gate_data_connection_base_vtbl = local_vtbl; | |
370 | } | ||
371 | 1 | } | |
372 | |||
373 | 1 | static gate_result_t gate_data_connection_base_create(gate_data_handles_t handles, | |
374 | gate_result_t(*init)(gate_data_connection_base_t* self), | ||
375 | void(*close)(gate_data_connection_base_t* self), | ||
376 | gate_result_t(*create_stmt)(gate_data_connection_base_t* self, gate_string_t const* sql, gate_data_statement_t** ptr_stmt), | ||
377 | gate_data_connection_t** ptr_connection) | ||
378 | { | ||
379 | 1 | gate_result_t ret = GATE_RESULT_FAILED; | |
380 | 1 | gate_data_connection_base_t* conn = NULL; | |
381 | |||
382 | do | ||
383 | { | ||
384 | 1 | conn = (gate_data_connection_base_t*)gate_mem_alloc(sizeof(gate_data_connection_base_t)); | |
385 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (conn == NULL) |
386 | { | ||
387 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
388 | ✗ | break; | |
389 | } | ||
390 | 1 | gate_mem_clear(conn, sizeof(gate_data_connection_base_t)); | |
391 | 1 | gate_init_data_connection_base_vtbl(); | |
392 | 1 | conn->vtbl = &gate_data_connection_base_vtbl; | |
393 | 1 | gate_atomic_int_init(&conn->ref_counter, 1); | |
394 | 1 | gate_mem_copy(conn->native_handles, handles, sizeof(conn->native_handles)); | |
395 | |||
396 | 1 | conn->init = init; | |
397 | 1 | conn->close = close; | |
398 | 1 | conn->create_statement = create_stmt; | |
399 | |||
400 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (conn->init) |
401 | { | ||
402 | 1 | ret = conn->init(conn); | |
403 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | GATE_BREAK_IF_FAILED(ret); |
404 | } | ||
405 | |||
406 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (ptr_connection) |
407 | { | ||
408 | 1 | *ptr_connection = (gate_data_connection_t*)conn; | |
409 | 1 | conn = NULL; | |
410 | } | ||
411 | 1 | ret = GATE_RESULT_OK; | |
412 | } while (0); | ||
413 | |||
414 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (conn != NULL) |
415 | { | ||
416 | ✗ | gate_object_release(conn); | |
417 | } | ||
418 | 1 | return ret; | |
419 | } | ||
420 | |||
421 | |||
422 | |||
423 | /************************************** | ||
424 | * data statement base implementation * | ||
425 | **************************************/ | ||
426 | |||
427 | typedef struct gate_data_statement_base_class gate_data_statement_base_t; | ||
428 | |||
429 | struct gate_data_statement_base_class | ||
430 | { | ||
431 | GATE_INTERFACE_VTBL(gate_data_statement) const* vtbl; | ||
432 | |||
433 | gate_atomic_int_t ref_counter; | ||
434 | gate_data_handles_t native_handles; | ||
435 | gate_data_connection_t* connection; | ||
436 | gate_string_t sql; | ||
437 | gate_size_t param_count; | ||
438 | |||
439 | void(*close)(gate_data_statement_base_t* self); | ||
440 | |||
441 | gate_result_t(*set_param)(gate_data_statement_base_t* self, gate_size_t index, gate_value_t const* value); | ||
442 | gate_result_t(*set_named_param)(gate_data_statement_base_t* self, gate_string_t const* name, gate_value_t const* value); | ||
443 | |||
444 | gate_result_t(*reset)(gate_data_statement_base_t* self); | ||
445 | gate_result_t(*execute)(gate_data_statement_base_t* self, gate_int32_t* affected_rows); | ||
446 | gate_result_t(*query)(gate_data_statement_base_t* self, gate_data_reader_t** ptr_reader); | ||
447 | }; | ||
448 | |||
449 | 2 | static void statement_base_close(gate_data_statement_base_t* self) | |
450 | { | ||
451 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (self->close) |
452 | { | ||
453 | 2 | self->close(self); | |
454 | } | ||
455 | 2 | gate_string_release(&self->sql); | |
456 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (self->connection) |
457 | { | ||
458 | 2 | gate_object_release(self->connection); | |
459 | 2 | self->connection = NULL; | |
460 | } | ||
461 | 2 | } | |
462 | |||
463 | ✗ | static char const* statement_base_get_interface_name(void* This) | |
464 | { | ||
465 | GATE_UNUSED_ARG(This); | ||
466 | ✗ | return GATE_INTERFACE_NAME_DATA_STATEMENT; | |
467 | } | ||
468 | |||
469 | 3 | static void statement_base_release(void* This) | |
470 | { | ||
471 | 3 | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
472 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
|
3 | if (0 == gate_atomic_int_dec(&self->ref_counter)) |
473 | { | ||
474 | 2 | statement_base_close(self); | |
475 | 2 | gate_mem_dealloc(self); | |
476 | } | ||
477 | 3 | } | |
478 | |||
479 | 1 | static int statement_base_retain(void* This) | |
480 | { | ||
481 | 1 | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
482 | 1 | return gate_atomic_int_inc(&self->ref_counter); | |
483 | } | ||
484 | |||
485 | ✗ | static gate_result_t statement_base_get_param_count(void* This, gate_size_t* ptr_count) | |
486 | { | ||
487 | ✗ | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
488 | ✗ | if (ptr_count) | |
489 | { | ||
490 | ✗ | *ptr_count = self->param_count; | |
491 | ✗ | return GATE_RESULT_OK; | |
492 | } | ||
493 | ✗ | return GATE_RESULT_INVALIDARG; | |
494 | |||
495 | } | ||
496 | ✗ | static gate_result_t statement_base_set_param(void* This, gate_size_t index, gate_value_t const* value) | |
497 | { | ||
498 | ✗ | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
499 | ✗ | if (self->set_param) | |
500 | { | ||
501 | ✗ | return self->set_param(self, index, value); | |
502 | } | ||
503 | ✗ | return GATE_RESULT_NOTSUPPORTED; | |
504 | } | ||
505 | ✗ | static gate_result_t statement_base_set_named_param(void* This, gate_string_t const* name, gate_value_t const* value) | |
506 | { | ||
507 | ✗ | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
508 | ✗ | if (self->set_named_param) | |
509 | { | ||
510 | ✗ | return self->set_named_param(self, name, value); | |
511 | } | ||
512 | ✗ | return GATE_RESULT_NOTSUPPORTED; | |
513 | } | ||
514 | |||
515 | ✗ | static gate_result_t statement_base_reset(void* This) | |
516 | { | ||
517 | ✗ | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
518 | ✗ | if (self->reset) | |
519 | { | ||
520 | ✗ | return self->reset(self); | |
521 | } | ||
522 | ✗ | return GATE_RESULT_NOTSUPPORTED; | |
523 | } | ||
524 | 1 | static gate_result_t statement_base_execute(void* This, gate_int32_t* affected_rows) | |
525 | { | ||
526 | 1 | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
527 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (self->execute) |
528 | { | ||
529 | 1 | return self->execute(self, affected_rows); | |
530 | } | ||
531 | ✗ | return GATE_RESULT_NOTSUPPORTED; | |
532 | } | ||
533 | 1 | static gate_result_t statement_base_query(void* This, gate_data_reader_t** ptr_reader) | |
534 | { | ||
535 | 1 | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
536 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (self->query) |
537 | { | ||
538 | 1 | return self->query(self, ptr_reader); | |
539 | } | ||
540 | ✗ | return GATE_RESULT_NOTSUPPORTED; | |
541 | } | ||
542 | |||
543 | |||
544 | 2 | static GATE_INTERFACE_VTBL(gate_data_statement) const* statement_base_vtbl() | |
545 | { | ||
546 | static GATE_INTERFACE_VTBL(gate_data_statement) vtbl; | ||
547 | |||
548 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (vtbl.get_interface_name == NULL) |
549 | { | ||
550 | 1 | vtbl.get_interface_name = &statement_base_get_interface_name; | |
551 | 1 | vtbl.release = &statement_base_release; | |
552 | 1 | vtbl.retain = &statement_base_retain; | |
553 | |||
554 | 1 | vtbl.get_param_count = &statement_base_get_param_count; | |
555 | 1 | vtbl.set_param = &statement_base_set_param; | |
556 | 1 | vtbl.set_named_param = &statement_base_set_named_param; | |
557 | |||
558 | 1 | vtbl.reset = &statement_base_reset; | |
559 | 1 | vtbl.execute = &statement_base_execute; | |
560 | 1 | vtbl.query = &statement_base_query; | |
561 | } | ||
562 | 2 | return &vtbl; | |
563 | } | ||
564 | |||
565 | 2 | static gate_result_t gate_data_statement_base_create( | |
566 | gate_data_connection_base_t* connection, | ||
567 | gate_data_handles_t handles, | ||
568 | gate_string_t const* sql, | ||
569 | gate_result_t(*init)(gate_data_statement_base_t* self), | ||
570 | void(*close)(gate_data_statement_base_t* self), | ||
571 | gate_result_t(*set_param)(gate_data_statement_base_t* self, gate_size_t index, gate_value_t const* value), | ||
572 | gate_result_t(*set_named_param)(gate_data_statement_base_t* self, gate_string_t const* name, gate_value_t const* value), | ||
573 | gate_result_t(*reset)(gate_data_statement_base_t* self), | ||
574 | gate_result_t(*execute)(gate_data_statement_base_t* self, gate_int32_t* affected_rows), | ||
575 | gate_result_t(*query)(gate_data_statement_base_t* self, gate_data_reader_t** ptr_reader), | ||
576 | gate_data_statement_base_t** ptr_output | ||
577 | ) | ||
578 | { | ||
579 | 2 | gate_result_t ret = GATE_RESULT_FAILED; | |
580 | 2 | gate_data_statement_base_t* impl = NULL; | |
581 | do | ||
582 | { | ||
583 | 2 | impl = (gate_data_statement_base_t*)gate_mem_alloc(sizeof(gate_data_statement_base_t)); | |
584 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (impl == NULL) |
585 | { | ||
586 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
587 | ✗ | break; | |
588 | } | ||
589 | |||
590 | 2 | gate_mem_clear(impl, sizeof(gate_data_statement_base_t)); | |
591 | 2 | impl->vtbl = statement_base_vtbl(); | |
592 | 2 | gate_atomic_int_init(&impl->ref_counter, 1); | |
593 | |||
594 | 2 | impl->connection = (gate_data_connection_t*)connection; | |
595 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (impl->connection != NULL) |
596 | { | ||
597 | 2 | gate_object_retain(impl->connection); | |
598 | } | ||
599 | |||
600 | 2 | gate_mem_copy(impl->native_handles, handles, sizeof(impl->native_handles)); | |
601 | |||
602 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if (NULL == gate_string_clone(&impl->sql, sql)) |
603 | { | ||
604 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
605 | ✗ | break; | |
606 | } | ||
607 | |||
608 | 2 | impl->close = close; | |
609 | 2 | impl->set_param = set_param; | |
610 | 2 | impl->set_named_param = set_named_param; | |
611 | 2 | impl->reset = reset; | |
612 | 2 | impl->execute = execute; | |
613 | 2 | impl->query = query; | |
614 | |||
615 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (init) |
616 | { | ||
617 | 2 | ret = init(impl); | |
618 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | GATE_BREAK_IF_FAILED(ret); |
619 | } | ||
620 | |||
621 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (ptr_output) |
622 | { | ||
623 | 2 | *ptr_output = impl; | |
624 | 2 | impl = NULL; | |
625 | } | ||
626 | |||
627 | /* success case */ | ||
628 | 2 | ret = GATE_RESULT_OK; | |
629 | } while (0); | ||
630 | |||
631 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (impl) |
632 | { | ||
633 | ✗ | statement_base_release(impl); | |
634 | } | ||
635 | |||
636 | 2 | return ret; | |
637 | } | ||
638 | |||
639 | |||
640 | #if defined(__cplusplus) | ||
641 | } | ||
642 | #endif | ||
643 | |||
644 | #endif | ||
645 |