| 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 | 22 | static gate_bool_t gate_data_reader_base_is_valid(void* This) | |
| 77 | { | ||
| 78 | 22 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
| 79 |
1/2✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
|
22 | if (self->is_valid) |
| 80 | { | ||
| 81 | 22 | return self->is_valid(self); | |
| 82 | } | ||
| 83 | ✗ | return false; | |
| 84 | } | ||
| 85 | |||
| 86 | 6 | static gate_result_t gate_data_reader_base_close(void* This) | |
| 87 | { | ||
| 88 | 6 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
| 89 | 6 | gate_result_t ret = GATE_RESULT_NOTSUPPORTED; | |
| 90 | gate_size_t ndx; | ||
| 91 | do | ||
| 92 | { | ||
| 93 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (self->close) |
| 94 | { | ||
| 95 | 6 | ret = self->close(self); | |
| 96 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | GATE_BREAK_IF_FAILED(ret); |
| 97 | } | ||
| 98 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
|
24 | for (ndx = 0; ndx != self->field_count; ++ndx) |
| 99 | { | ||
| 100 | 18 | gate_string_release(&self->names[ndx]); | |
| 101 | 18 | gate_value_release(&self->values[ndx]); | |
| 102 | } | ||
| 103 | 6 | gate_mem_clear(self->names, sizeof(self->names)); | |
| 104 | 6 | gate_mem_clear(self->values, sizeof(self->values)); | |
| 105 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
|
6 | if (self->statement) |
| 106 | { | ||
| 107 | 2 | gate_object_release(self->statement); | |
| 108 | 2 | self->statement = NULL; | |
| 109 | } | ||
| 110 | 6 | ret = GATE_RESULT_OK; | |
| 111 | } while (0); | ||
| 112 | 6 | return ret; | |
| 113 | } | ||
| 114 | |||
| 115 | 4 | static gate_result_t gate_data_reader_base_next(void* This) | |
| 116 | { | ||
| 117 | 4 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
| 118 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (self->next) |
| 119 | { | ||
| 120 | 4 | return self->next(self); | |
| 121 | } | ||
| 122 | ✗ | return GATE_RESULT_NOTSUPPORTED; | |
| 123 | } | ||
| 124 | |||
| 125 | 1 | static gate_size_t gate_data_reader_base_get_field_count(void* This) | |
| 126 | { | ||
| 127 | 1 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
| 128 | 1 | return self->field_count; | |
| 129 | } | ||
| 130 | 6 | 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 | 6 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
| 133 | 6 | gate_result_t ret = GATE_RESULT_FAILED; | |
| 134 | do | ||
| 135 | { | ||
| 136 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | 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 6 times.
|
6 | if (field_index >= self->field_count) |
| 142 | { | ||
| 143 | ✗ | ret = GATE_RESULT_OUTOFBOUNDS; | |
| 144 | ✗ | break; | |
| 145 | } | ||
| 146 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (ptr_type) |
| 147 | { | ||
| 148 | 6 | *ptr_type = self->values[field_index].value_type; | |
| 149 | } | ||
| 150 | 6 | ret = GATE_RESULT_OK; | |
| 151 | } while (0); | ||
| 152 | 6 | return ret; | |
| 153 | } | ||
| 154 | 5 | 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 | 5 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
| 157 | 5 | gate_result_t ret = GATE_RESULT_FAILED; | |
| 158 | do | ||
| 159 | { | ||
| 160 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
|
5 | if (!gate_data_reader_base_is_valid(self)) |
| 161 | { | ||
| 162 | ✗ | ret = GATE_RESULT_ENDOFSTREAM; | |
| 163 | ✗ | break; | |
| 164 | } | ||
| 165 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (field_index >= self->field_count) |
| 166 | { | ||
| 167 | ✗ | ret = GATE_RESULT_OUTOFBOUNDS; | |
| 168 | ✗ | break; | |
| 169 | } | ||
| 170 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (ptr_name) |
| 171 | { | ||
| 172 | 5 | *ptr_name = &self->names[field_index]; | |
| 173 | } | ||
| 174 | 5 | ret = GATE_RESULT_OK; | |
| 175 | } while (0); | ||
| 176 | 5 | return ret; | |
| 177 | } | ||
| 178 | 6 | 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 | 6 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
| 181 | 6 | gate_result_t ret = GATE_RESULT_FAILED; | |
| 182 | do | ||
| 183 | { | ||
| 184 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | 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 6 times.
|
6 | if (field_index >= self->field_count) |
| 190 | { | ||
| 191 | ✗ | ret = GATE_RESULT_OUTOFBOUNDS; | |
| 192 | ✗ | break; | |
| 193 | } | ||
| 194 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (ptr_value) |
| 195 | { | ||
| 196 | 6 | *ptr_value = &self->values[field_index]; | |
| 197 | } | ||
| 198 | 6 | ret = GATE_RESULT_OK; | |
| 199 | } while (0); | ||
| 200 | 6 | 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 | 2 | static void gate_data_reader_base_release(void* This) | |
| 210 | { | ||
| 211 | 2 | gate_data_reader_base_t* self = (gate_data_reader_base_t*)This; | |
| 212 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | if (0 == gate_atomic_int_dec(&self->ref_counter)) |
| 213 | { | ||
| 214 | 2 | gate_data_reader_base_close(This); | |
| 215 | 2 | gate_mem_dealloc(self); | |
| 216 | } | ||
| 217 | 2 | } | |
| 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 | 2 | static GATE_INTERFACE_VTBL(gate_data_reader) const* gate_init_data_reader_base_vtbl(void) | |
| 227 | { | ||
| 228 | static GATE_INTERFACE_VTBL(gate_data_reader) gate_data_reader_base_vtbl; | ||
| 229 | |||
| 230 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | 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 | 2 | gate_data_reader_base_vtbl = local_vtbl; | |
| 248 | } | ||
| 249 | 2 | return &gate_data_reader_base_vtbl; | |
| 250 | } | ||
| 251 | |||
| 252 | 2 | 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 | 2 | gate_data_reader_t* ret = NULL; | |
| 260 | 2 | gate_data_reader_base_t* reader = NULL; | |
| 261 | gate_result_t res; | ||
| 262 | |||
| 263 | do | ||
| 264 | { | ||
| 265 | 2 | 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 2 times.
|
2 | if (reader == NULL) |
| 267 | { | ||
| 268 | ✗ | break; | |
| 269 | } | ||
| 270 | 2 | gate_mem_clear(reader, sizeof(gate_data_reader_base_t)); | |
| 271 | 2 | reader->vtbl = gate_init_data_reader_base_vtbl(); | |
| 272 | 2 | gate_atomic_int_init(&reader->ref_counter, 1); | |
| 273 | |||
| 274 | 2 | gate_mem_copy(reader->native_handles, handles, sizeof(reader->native_handles)); | |
| 275 | 2 | reader->statement = statement; | |
| 276 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (reader->statement) |
| 277 | { | ||
| 278 | 2 | gate_object_retain(reader->statement); | |
| 279 | } | ||
| 280 | 2 | reader->field_count = 0; | |
| 281 | |||
| 282 | 2 | reader->init = init; | |
| 283 | 2 | reader->is_valid = is_valid; | |
| 284 | 2 | reader->next = next; | |
| 285 | 2 | reader->close = close; | |
| 286 | |||
| 287 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (reader->init) |
| 288 | { | ||
| 289 | 2 | res = reader->init(reader); | |
| 290 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (GATE_FAILED(res)) |
| 291 | { | ||
| 292 | ✗ | gate_mem_dealloc(reader); | |
| 293 | ✗ | break; | |
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | 2 | ret = (gate_data_reader_t*)reader; | |
| 298 | 2 | reader = NULL; | |
| 299 | } while (0); | ||
| 300 | 2 | 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 | 1 | static char const* gate_data_connection_base_get_interface_name(void* This) | |
| 324 | { | ||
| 325 | GATE_UNUSED_ARG(This); | ||
| 326 | 1 | return GATE_INTERFACE_NAME_DATA_CONNECTION; | |
| 327 | } | ||
| 328 | 11 | static void gate_data_connection_base_release(void* This) | |
| 329 | { | ||
| 330 | 11 | gate_data_connection_base_t* self = (gate_data_connection_base_t*)This; | |
| 331 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 8 times.
|
11 | if (0 == gate_atomic_int_dec(&self->ref_counter)) |
| 332 | { | ||
| 333 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (self->close) |
| 334 | { | ||
| 335 | 3 | self->close(self); | |
| 336 | } | ||
| 337 | 3 | gate_mem_dealloc(self); | |
| 338 | } | ||
| 339 | 11 | } | |
| 340 | 8 | static int gate_data_connection_base_retain(void* This) | |
| 341 | { | ||
| 342 | 8 | gate_data_connection_base_t* self = (gate_data_connection_base_t*)This; | |
| 343 | 8 | return (int)gate_atomic_int_inc(&self->ref_counter); | |
| 344 | } | ||
| 345 | |||
| 346 | 5 | 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 | 5 | gate_data_connection_base_t* self = (gate_data_connection_base_t*)This; | |
| 349 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (self->create_statement) |
| 350 | { | ||
| 351 | 5 | 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 | 3 | static void gate_init_data_connection_base_vtbl(void) | |
| 358 | { | ||
| 359 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | 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 | 2 | gate_data_connection_base_vtbl = local_vtbl; | |
| 370 | } | ||
| 371 | 3 | } | |
| 372 | |||
| 373 | 3 | 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 | 3 | gate_result_t ret = GATE_RESULT_FAILED; | |
| 380 | 3 | gate_data_connection_base_t* conn = NULL; | |
| 381 | |||
| 382 | do | ||
| 383 | { | ||
| 384 | 3 | 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 3 times.
|
3 | if (conn == NULL) |
| 386 | { | ||
| 387 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 388 | ✗ | break; | |
| 389 | } | ||
| 390 | 3 | gate_mem_clear(conn, sizeof(gate_data_connection_base_t)); | |
| 391 | 3 | gate_init_data_connection_base_vtbl(); | |
| 392 | 3 | conn->vtbl = &gate_data_connection_base_vtbl; | |
| 393 | 3 | gate_atomic_int_init(&conn->ref_counter, 1); | |
| 394 | 3 | gate_mem_copy(conn->native_handles, handles, sizeof(conn->native_handles)); | |
| 395 | |||
| 396 | 3 | conn->init = init; | |
| 397 | 3 | conn->close = close; | |
| 398 | 3 | conn->create_statement = create_stmt; | |
| 399 | |||
| 400 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (conn->init) |
| 401 | { | ||
| 402 | 3 | ret = conn->init(conn); | |
| 403 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | GATE_BREAK_IF_FAILED(ret); |
| 404 | } | ||
| 405 | |||
| 406 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (ptr_connection) |
| 407 | { | ||
| 408 | 3 | *ptr_connection = (gate_data_connection_t*)conn; | |
| 409 | 3 | conn = NULL; | |
| 410 | } | ||
| 411 | 3 | ret = GATE_RESULT_OK; | |
| 412 | } while (0); | ||
| 413 | |||
| 414 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (conn != NULL) |
| 415 | { | ||
| 416 | ✗ | gate_object_release(conn); | |
| 417 | } | ||
| 418 | 3 | 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 | 5 | static void statement_base_close(gate_data_statement_base_t* self) | |
| 450 | { | ||
| 451 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (self->close) |
| 452 | { | ||
| 453 | 5 | self->close(self); | |
| 454 | } | ||
| 455 | 5 | gate_string_release(&self->sql); | |
| 456 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (self->connection) |
| 457 | { | ||
| 458 | 5 | gate_object_release(self->connection); | |
| 459 | 5 | self->connection = NULL; | |
| 460 | } | ||
| 461 | 5 | } | |
| 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 | 7 | static void statement_base_release(void* This) | |
| 470 | { | ||
| 471 | 7 | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
| 472 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
|
7 | if (0 == gate_atomic_int_dec(&self->ref_counter)) |
| 473 | { | ||
| 474 | 5 | statement_base_close(self); | |
| 475 | 5 | gate_mem_dealloc(self); | |
| 476 | } | ||
| 477 | 7 | } | |
| 478 | |||
| 479 | 2 | static int statement_base_retain(void* This) | |
| 480 | { | ||
| 481 | 2 | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
| 482 | 2 | return gate_atomic_int_inc(&self->ref_counter); | |
| 483 | } | ||
| 484 | |||
| 485 | 1 | static gate_result_t statement_base_get_param_count(void* This, gate_size_t* ptr_count) | |
| 486 | { | ||
| 487 | 1 | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
| 488 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (ptr_count) |
| 489 | { | ||
| 490 | 1 | *ptr_count = self->param_count; | |
| 491 | 1 | return GATE_RESULT_OK; | |
| 492 | } | ||
| 493 | ✗ | return GATE_RESULT_INVALIDARG; | |
| 494 | |||
| 495 | } | ||
| 496 | 4 | static gate_result_t statement_base_set_param(void* This, gate_size_t index, gate_value_t const* value) | |
| 497 | { | ||
| 498 | 4 | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
| 499 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (self->set_param) |
| 500 | { | ||
| 501 | 4 | 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 | 1 | static gate_result_t statement_base_reset(void* This) | |
| 516 | { | ||
| 517 | 1 | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
| 518 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (self->reset) |
| 519 | { | ||
| 520 | 1 | return self->reset(self); | |
| 521 | } | ||
| 522 | ✗ | return GATE_RESULT_NOTSUPPORTED; | |
| 523 | } | ||
| 524 | 3 | static gate_result_t statement_base_execute(void* This, gate_int32_t* affected_rows) | |
| 525 | { | ||
| 526 | 3 | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
| 527 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (self->execute) |
| 528 | { | ||
| 529 | 3 | return self->execute(self, affected_rows); | |
| 530 | } | ||
| 531 | ✗ | return GATE_RESULT_NOTSUPPORTED; | |
| 532 | } | ||
| 533 | 2 | static gate_result_t statement_base_query(void* This, gate_data_reader_t** ptr_reader) | |
| 534 | { | ||
| 535 | 2 | gate_data_statement_base_t* self = (gate_data_statement_base_t*)This; | |
| 536 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (self->query) |
| 537 | { | ||
| 538 | 2 | return self->query(self, ptr_reader); | |
| 539 | } | ||
| 540 | ✗ | return GATE_RESULT_NOTSUPPORTED; | |
| 541 | } | ||
| 542 | |||
| 543 | |||
| 544 | 5 | static GATE_INTERFACE_VTBL(gate_data_statement) const* statement_base_vtbl(void) | |
| 545 | { | ||
| 546 | static GATE_INTERFACE_VTBL(gate_data_statement) vtbl; | ||
| 547 | |||
| 548 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
|
5 | if (vtbl.get_interface_name == NULL) |
| 549 | { | ||
| 550 | 2 | vtbl.get_interface_name = &statement_base_get_interface_name; | |
| 551 | 2 | vtbl.release = &statement_base_release; | |
| 552 | 2 | vtbl.retain = &statement_base_retain; | |
| 553 | |||
| 554 | 2 | vtbl.get_param_count = &statement_base_get_param_count; | |
| 555 | 2 | vtbl.set_param = &statement_base_set_param; | |
| 556 | 2 | vtbl.set_named_param = &statement_base_set_named_param; | |
| 557 | |||
| 558 | 2 | vtbl.reset = &statement_base_reset; | |
| 559 | 2 | vtbl.execute = &statement_base_execute; | |
| 560 | 2 | vtbl.query = &statement_base_query; | |
| 561 | } | ||
| 562 | 5 | return &vtbl; | |
| 563 | } | ||
| 564 | |||
| 565 | 5 | 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 | 5 | gate_result_t ret = GATE_RESULT_FAILED; | |
| 580 | 5 | gate_data_statement_base_t* impl = NULL; | |
| 581 | do | ||
| 582 | { | ||
| 583 | 5 | 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 5 times.
|
5 | if (impl == NULL) |
| 585 | { | ||
| 586 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 587 | ✗ | break; | |
| 588 | } | ||
| 589 | |||
| 590 | 5 | gate_mem_clear(impl, sizeof(gate_data_statement_base_t)); | |
| 591 | 5 | impl->vtbl = statement_base_vtbl(); | |
| 592 | 5 | gate_atomic_int_init(&impl->ref_counter, 1); | |
| 593 | |||
| 594 | 5 | impl->connection = (gate_data_connection_t*)connection; | |
| 595 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (impl->connection != NULL) |
| 596 | { | ||
| 597 | 5 | gate_object_retain(impl->connection); | |
| 598 | } | ||
| 599 | |||
| 600 | 5 | gate_mem_copy(impl->native_handles, handles, sizeof(impl->native_handles)); | |
| 601 | |||
| 602 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
|
5 | if (NULL == gate_string_clone(&impl->sql, sql)) |
| 603 | { | ||
| 604 | ✗ | ret = GATE_RESULT_OUTOFMEMORY; | |
| 605 | ✗ | break; | |
| 606 | } | ||
| 607 | |||
| 608 | 5 | impl->close = close; | |
| 609 | 5 | impl->set_param = set_param; | |
| 610 | 5 | impl->set_named_param = set_named_param; | |
| 611 | 5 | impl->reset = reset; | |
| 612 | 5 | impl->execute = execute; | |
| 613 | 5 | impl->query = query; | |
| 614 | |||
| 615 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (init) |
| 616 | { | ||
| 617 | 5 | ret = init(impl); | |
| 618 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | GATE_BREAK_IF_FAILED(ret); |
| 619 | } | ||
| 620 | |||
| 621 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (ptr_output) |
| 622 | { | ||
| 623 | 5 | *ptr_output = impl; | |
| 624 | 5 | impl = NULL; | |
| 625 | } | ||
| 626 | |||
| 627 | /* success case */ | ||
| 628 | 5 | ret = GATE_RESULT_OK; | |
| 629 | } while (0); | ||
| 630 | |||
| 631 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (impl) |
| 632 | { | ||
| 633 | ✗ | statement_base_release(impl); | |
| 634 | } | ||
| 635 | |||
| 636 | 5 | return ret; | |
| 637 | } | ||
| 638 | |||
| 639 | |||
| 640 | #if defined(__cplusplus) | ||
| 641 | } | ||
| 642 | #endif | ||
| 643 | |||
| 644 | #endif | ||
| 645 |