GCC Code Coverage Report


Directory: src/gate/
File: src/gate/data/mysql_adapter.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 0 233 0.0%
Functions: 0 16 0.0%
Branches: 0 87 0.0%

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 #include "gate/data/mysql_adapter.h"
30 #include "gate/data/adapter_base.h"
31
32 #include "gate/libraries.h"
33 #include "gate/results.h"
34 #include "gate/uris.h"
35
36 #if defined(GATE_SYS_WIN)
37 #define MYSQL_API __stdcall
38 #else
39 #define MYSQL_API
40 #endif
41
42 typedef struct MYSQL_struct MYSQL;
43 typedef struct MYSQL_RES_struct MYSQL_RES;
44 typedef struct MYSQL_STMT_struct MYSQL_STMT;
45 typedef struct NET_struct NET;
46
47 enum enum_field_types
48 {
49 MYSQL_TYPE_DECIMAL = 0,
50 MYSQL_TYPE_TINY = 1,
51 MYSQL_TYPE_SHORT = 2,
52 MYSQL_TYPE_LONG = 3,
53 MYSQL_TYPE_FLOAT = 4,
54 MYSQL_TYPE_DOUBLE = 5,
55 MYSQL_TYPE_NULL = 6,
56 MYSQL_TYPE_TIMESTAMP = 7,
57 MYSQL_TYPE_LONGLONG = 8,
58 MYSQL_TYPE_INT24 = 9,
59 MYSQL_TYPE_DATE = 10,
60 MYSQL_TYPE_TIME = 11,
61 MYSQL_TYPE_DATETIME = 12,
62 MYSQL_TYPE_YEAR = 13,
63 MYSQL_TYPE_NEWDATE = 14,
64 MYSQL_TYPE_VARCHAR = 15,
65 MYSQL_TYPE_BIT = 16,
66 MYSQL_TYPE_TIMESTAMP2 = 17,
67 MYSQL_TYPE_DATETIME2 = 18,
68 MYSQL_TYPE_TIME2 = 19,
69 MYSQL_TYPE_TYPED_ARRAY = 20,
70
71 MYSQL_TYPE_INVALID = 243,
72 MYSQL_TYPE_BOOL = 244,
73 MYSQL_TYPE_JSON = 245,
74 MYSQL_TYPE_NEWDECIMAL = 246,
75 MYSQL_TYPE_ENUM = 247,
76 MYSQL_TYPE_SET = 248,
77 MYSQL_TYPE_TINY_BLOB = 249,
78 MYSQL_TYPE_MEDIUM_BLOB = 250,
79 MYSQL_TYPE_LONG_BLOB = 251,
80 MYSQL_TYPE_BLOB = 252,
81 MYSQL_TYPE_VAR_STRING = 253,
82 MYSQL_TYPE_STRING = 254,
83 MYSQL_TYPE_GEOMETRY = 255
84 };
85
86 typedef struct MYSQL_FIELD
87 {
88 char* name;
89 char* org_name;
90 char* table;
91 char* org_table;
92 char* db;
93 char* catalog;
94 char* def;
95 unsigned long length;
96 unsigned long max_length;
97 unsigned int name_length;
98 unsigned int org_name_length;
99 unsigned int table_length;
100 unsigned int org_table_length;
101 unsigned int db_length;
102 unsigned int catalog_length;
103 unsigned int def_length;
104 unsigned int flags;
105 unsigned int decimals;
106 unsigned int charsetnr;
107 enum enum_field_types type;
108 void* extension;
109 } MYSQL_FIELD;
110
111 typedef struct MYSQL_BIND
112 {
113 unsigned long* length;
114 bool* is_null;
115 void* buffer;
116 bool* error;
117 unsigned char* row_ptr;
118 void (*store_param_func)(NET* net, struct MYSQL_BIND* param);
119 void (*fetch_result)(struct MYSQL_BIND*, MYSQL_FIELD*, unsigned char** row);
120 void (*skip_result)(struct MYSQL_BIND*, MYSQL_FIELD*, unsigned char** row);
121 unsigned long buffer_length;
122 unsigned long offset;
123 unsigned long length_value;
124 unsigned int param_number;
125 unsigned int pack_length;
126 enum enum_field_types buffer_type;
127 bool error_value;
128 bool is_unsigned;
129 bool long_data_used;
130 bool is_null_value;
131 void* extension;
132 } MYSQL_BIND;
133
134 typedef char** MYSQL_ROW; /* return data as array of strings */
135
136 typedef struct gate_mysql_api_class
137 {
138 MYSQL* (MYSQL_API* init) (MYSQL* mysql);
139 void (MYSQL_API* close) (MYSQL* mysql);
140 MYSQL* (MYSQL_API* real_connect) (MYSQL* mysql, const char* host,
141 const char* user, const char* passwd,
142 const char* db, unsigned int port,
143 const char* unix_socket,
144 unsigned long clientflag);
145 int (MYSQL_API* query) (MYSQL* mysql, const char* q);
146 MYSQL_RES* (MYSQL_API* use_result) (MYSQL* mysql);
147 MYSQL_ROW(MYSQL_API* fetch_row) (MYSQL_RES* result);
148 void (MYSQL_API* free_result) (MYSQL_RES* result);
149 unsigned int (MYSQL_API* num_fields) (MYSQL_RES* res);
150 unsigned long* (MYSQL_API* fetch_lengths) (MYSQL_RES* result);
151 unsigned int (MYSQL_API* field_count) (MYSQL* mysql);
152 gate_uint64_t(MYSQL_API* affected_rows) (MYSQL* mysql);
153 MYSQL_FIELD* (MYSQL_API* fetch_field) (MYSQL_RES* result);
154
155 MYSQL_STMT* (MYSQL_API* stmt_init)(MYSQL* mysql);
156 gate_bool_t(MYSQL_API* stmt_close)(MYSQL_STMT* stmt);
157 int (MYSQL_API* stmt_prepare)(MYSQL_STMT* stmt, const char* query, unsigned long length);
158 int (MYSQL_API* stmt_execute)(MYSQL_STMT* stmt);
159 gate_bool_t(MYSQL_API* stmt_bind_result)(MYSQL_STMT* stmt, MYSQL_BIND* bnd);
160 int (MYSQL_API* stmt_fetch)(MYSQL_STMT* stmt);
161 int (MYSQL_API* stmt_fetch_column)(MYSQL_STMT* stmt, MYSQL_BIND* bind_arg, unsigned int column, unsigned long offset);
162 int (MYSQL_API* stmt_store_result)(MYSQL_STMT* stmt);
163 MYSQL_RES* (MYSQL_API* stmt_result_metadata)(MYSQL_STMT* stmt);
164 unsigned long (MYSQL_API* stmt_param_count)(MYSQL_STMT* stmt);
165 unsigned int (MYSQL_API* stmt_field_count)(MYSQL_STMT* stmt);
166 gate_uint64_t(MYSQL_API* stmt_affected_rows)(MYSQL_STMT* stmt);
167 gate_bool_t(MYSQL_API* stmt_bind_param)(MYSQL_STMT* stmt, MYSQL_BIND* bnd);
168
169 } gate_mysql_api_t;
170
171 static gate_mysql_api_t mysql;
172
173 static gate_string_t const mysql_library_names[] =
174 {
175 GATE_STRING_INIT_STATIC("libmysql"),
176 };
177 static gate_size_t const mysql_library_names_count = sizeof(mysql_library_names) / sizeof(mysql_library_names[0]);
178
179 static gate_result_t gate_mysql_load_api()
180 {
181 static gate_library_t mysql_lib = NULL;
182 static gate_atomic_int_t mysql_lib_loaded = 0;
183 gate_result_t result;
184 gate_int32_t state;
185 gate_size_t ndx;
186
187 do
188 {
189 state = gate_atomic_int_xchg_if(&mysql_lib_loaded, 0, 1);
190 if (state != 0)
191 {
192 break;
193 }
194
195 state = 1;
196
197 result = GATE_RESULT_FAILED;
198 for (ndx = 0; (ndx != mysql_library_names_count) && GATE_FAILED(result); ++ndx)
199 {
200 result = gate_library_open(&mysql_library_names[ndx], &mysql_lib, 0);
201 }
202 GATE_BREAK_IF_FAILED(result);
203
204 result |= gate_library_get_function_name(mysql_lib, "mysql_init", &mysql.init);
205 result |= gate_library_get_function_name(mysql_lib, "mysql_close", &mysql.close);
206 result |= gate_library_get_function_name(mysql_lib, "mysql_real_connect", &mysql.real_connect);
207 result |= gate_library_get_function_name(mysql_lib, "mysql_query", &mysql.query);
208 result |= gate_library_get_function_name(mysql_lib, "mysql_use_result", &mysql.use_result);
209 result |= gate_library_get_function_name(mysql_lib, "mysql_fetch_row", &mysql.fetch_row);
210 result |= gate_library_get_function_name(mysql_lib, "mysql_free_result", &mysql.free_result);
211 result |= gate_library_get_function_name(mysql_lib, "mysql_num_fields", &mysql.num_fields);
212 result |= gate_library_get_function_name(mysql_lib, "mysql_fetch_lengths", &mysql.fetch_lengths);
213 result |= gate_library_get_function_name(mysql_lib, "mysql_field_count", &mysql.field_count);
214 result |= gate_library_get_function_name(mysql_lib, "mysql_affected_rows", &mysql.affected_rows);
215 result |= gate_library_get_function_name(mysql_lib, "mysql_fetch_field", &mysql.fetch_field);
216
217 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_init", &mysql.stmt_init);
218 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_close", &mysql.stmt_close);
219 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_prepare", &mysql.stmt_prepare);
220 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_execute", &mysql.stmt_execute);
221 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_bind_result", &mysql.stmt_bind_result);
222 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_fetch", &mysql.stmt_fetch);
223 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_fetch_column", &mysql.stmt_fetch_column);
224 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_store_result", &mysql.stmt_store_result);
225 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_result_metadata", &mysql.stmt_result_metadata);
226 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_param_count", &mysql.stmt_param_count);
227 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_field_count", &mysql.stmt_field_count);
228 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_affected_rows", &mysql.stmt_affected_rows);
229 result |= gate_library_get_function_name(mysql_lib, "mysql_stmt_bind_param", &mysql.stmt_bind_param);
230
231
232
233 GATE_BREAK_IF_FAILED(result);
234
235 gate_atomic_int_set(&mysql_lib_loaded, 2);
236 } while (0);
237
238 state = gate_atomic_int_xchg_if(&mysql_lib_loaded, 1, 0);
239
240 if (state == 2)
241 {
242 return GATE_RESULT_OK;
243 }
244 return GATE_RESULT_FAILED;
245 }
246
247
248
249 static gate_result_t mysqlconn_init(gate_data_connection_base_t* self)
250 {
251 GATE_UNUSED_ARG(self);
252 return GATE_RESULT_OK;
253 }
254
255 static void mysqlconn_close(gate_data_connection_base_t* self)
256 {
257 MYSQL* ptr_mysql = (MYSQL*)self->native_handles[0];
258 if (ptr_mysql)
259 {
260 self->native_handles[0] = NULL;
261 mysql.close(ptr_mysql);
262 }
263 }
264
265 static gate_result_t mysqlreader_init(gate_data_reader_base_t* reader)
266 {
267 MYSQL_RES* ptr_meta = (MYSQL_RES*)reader->native_handles[2];
268 MYSQL_FIELD* ptr_field;
269 gate_size_t field_count = 0;
270 gate_type_id_t gate_type;
271
272 while ((ptr_field = mysql.fetch_field(ptr_meta)))
273 {
274 if (field_count >= 64)
275 {
276 break;
277 }
278 gate_string_create(&reader->names[field_count], ptr_field->name, ptr_field->name_length);
279 switch (ptr_field->type)
280 {
281 case MYSQL_TYPE_INVALID:
282 case MYSQL_TYPE_NULL: gate_type = GATE_TYPE_EMPTY; break;
283 case MYSQL_TYPE_BIT:
284 case MYSQL_TYPE_BOOL: gate_type = GATE_TYPE_BOOL; break;
285 case MYSQL_TYPE_TINY: gate_type = GATE_TYPE_I8; break;
286 case MYSQL_TYPE_SHORT: gate_type = GATE_TYPE_I16; break;
287 case MYSQL_TYPE_ENUM:
288 case MYSQL_TYPE_INT24:
289 case MYSQL_TYPE_LONG: gate_type = GATE_TYPE_I32; break;
290 case MYSQL_TYPE_LONGLONG: gate_type = GATE_TYPE_I64; break;
291 case MYSQL_TYPE_FLOAT: gate_type = GATE_TYPE_R32; break;
292 case MYSQL_TYPE_DECIMAL:
293 case MYSQL_TYPE_NEWDECIMAL:
294 case MYSQL_TYPE_DOUBLE: gate_type = GATE_TYPE_R64; break;
295 case MYSQL_TYPE_TIME:
296 case MYSQL_TYPE_TIME2:
297 case MYSQL_TYPE_TIMESTAMP2:
298 case MYSQL_TYPE_TIMESTAMP: gate_type = GATE_TYPE_TIME; break;
299 case MYSQL_TYPE_YEAR:
300 case MYSQL_TYPE_NEWDATE:
301 case MYSQL_TYPE_DATE: gate_type = GATE_TYPE_DATE; break;
302 case MYSQL_TYPE_DATETIME2:
303 case MYSQL_TYPE_DATETIME: gate_type = GATE_TYPE_DATETIME; break;
304 case MYSQL_TYPE_JSON:
305 case MYSQL_TYPE_SET:
306 case MYSQL_TYPE_VARCHAR:
307 case MYSQL_TYPE_VAR_STRING:
308 case MYSQL_TYPE_STRING: gate_type = GATE_TYPE_STRING; break;
309 case MYSQL_TYPE_TINY_BLOB:
310 case MYSQL_TYPE_MEDIUM_BLOB:
311 case MYSQL_TYPE_LONG_BLOB:
312 case MYSQL_TYPE_BLOB: gate_type = GATE_TYPE_BLOB; break;
313 case MYSQL_TYPE_GEOMETRY:
314 case MYSQL_TYPE_TYPED_ARRAY:
315 {
316 gate_type = GATE_TYPE_ARRAY; break;
317 }
318
319 }
320 ++field_count;
321 }
322
323 return GATE_RESULT_FAILED;
324 }
325 static gate_bool_t mysqlreader_is_valid(gate_data_reader_base_t* reader)
326 {
327 MYSQL_STMT* ptr_stmt = (MYSQL_STMT*)reader->native_handles[1];
328 return ptr_stmt == NULL;
329 }
330 static gate_result_t mysqlreader_next(gate_data_reader_base_t* reader)
331 {
332 MYSQL* ptr_mysql = (MYSQL*)reader->native_handles[0];
333 MYSQL_STMT* ptr_stmt = (MYSQL_STMT*)reader->native_handles[1];
334 MYSQL_RES* ptr_meta = (MYSQL_RES*)reader->native_handles[2];
335
336 MYSQL_BIND fields[64];
337 unsigned int fields_count;
338
339 if (!ptr_stmt)
340 {
341 return GATE_RESULT_ENDOFSTREAM;
342 }
343
344 /*
345 fields_count = mysql.stmt_field_count(ptr_stmt);
346
347
348 MYSQL_RES* ptr_meta = (MYSQL_RES*)reader->native_handles[2];
349 MYSQL_FIELD* ptr_field;
350 gate_size_t field_count = 0;
351
352 while((ptr_field = mysql.fetch_field(ptr_meta)))
353 {
354 gate_string_create(&reader->names[field_count], ptr_field->name, ptr_field->name_length);
355 ++field_count;
356 }
357 */
358 return GATE_RESULT_FAILED;
359 }
360 static gate_result_t mysqlreader_close(gate_data_reader_base_t* reader)
361 {
362 MYSQL_STMT* ptr_stmt = (MYSQL_STMT*)reader->native_handles[1];
363 MYSQL_RES* ptr_meta = (MYSQL_RES*)reader->native_handles[2];
364 if (ptr_meta)
365 {
366 mysql.free_result(ptr_meta);
367 }
368 if (ptr_stmt)
369 {
370 mysql.stmt_close(ptr_stmt);
371 }
372 reader->native_handles[0] = NULL;
373 reader->native_handles[1] = NULL;
374 reader->native_handles[2] = NULL;
375 return GATE_RESULT_OK;
376 }
377
378 /*
379 static gate_result_t gate_mysql_execute(gate_data_connection_base_t* self, gate_string_t const* command, gate_int32_t* affected_rows)
380 {
381 MYSQL* ptr_mysql = (MYSQL*)self->native_handles[0];
382 if(!ptr_mysql)
383 {
384 return GATE_RESULT_INVALIDSTATE;
385
386 }
387 return GATE_RESULT_FAILED;
388 }
389
390 static gate_result_t gate_mysql_query(gate_data_connection_base_t* self, gate_string_t const* query, gate_data_reader_t** ptr_reader)
391 {
392 gate_result_t ret = GATE_RESULT_FAILED;
393 int result;
394 gate_cstrbuffer_t sql = GATE_INIT_EMPTY;
395 gate_data_handles_t reader_handles;
396 MYSQL_STMT* ptr_stmt = NULL;
397 MYSQL* ptr_mysql = (MYSQL*)self->native_handles[0];
398 MYSQL_RES* ptr_meta_result = NULL;
399 gate_data_reader_t* data_reader = NULL;
400
401 do
402 {
403 if(!ptr_mysql || gate_string_is_empty(query))
404 {
405 ret = GATE_RESULT_INVALIDSTATE;
406 break;
407 }
408
409 if(NULL == gate_cstrbuffer_create_string(&sql, query, false))
410 {
411 ret = GATE_RESULT_OUTOFMEMORY;
412 break;
413 }
414
415 ptr_stmt = mysql.stmt_init(ptr_mysql);
416 if(!ptr_stmt)
417 {
418 ret = GATE_RESULT_OUTOFMEMORY;
419 break;
420 }
421
422 result = mysql.stmt_prepare(ptr_stmt, gate_cstrbuffer_get(&sql), gate_cstrbuffer_length(&sql));
423 if(0 != result)
424 {
425 ret = GATE_RESULT_INVALIDINPUT;
426 break;
427 }
428
429 result = mysql.stmt_execute(ptr_stmt);
430 if(0 != result)
431 {
432 ret = GATE_RESULT_FAILED;
433 break;
434 }
435
436 ptr_meta_result = mysql.stmt_result_metadata(ptr_stmt);
437 if(!ptr_meta_result)
438 {
439 ret = GATE_RESULT_INVALIDOUTPUT;
440 break;
441 }
442
443 gate_mem_clear(reader_handles, sizeof(reader_handles));
444 reader_handles[0] = ptr_mysql;
445 reader_handles[1] = ptr_stmt;
446 reader_handles[2] = ptr_meta_result;
447
448 data_reader = gate_data_reader_base_create(reader_handles, &gate_mysql_reader_init, gate_mysql_reader_is_valid, gate_mysql_reader_next, gate_mysql_reader_close);
449 if(data_reader == NULL)
450 {
451 ret = GATE_RESULT_OUTOFMEMORY;
452 }
453
454 ptr_stmt = NULL;
455 ptr_meta_result = NULL;
456
457 if(ptr_reader)
458 {
459 *ptr_reader = data_reader;
460 data_reader = NULL;
461 }
462 ret = GATE_RESULT_OK;
463
464 } while(0);
465
466 if(data_reader)
467 {
468 gate_object_release(data_reader);
469 }
470
471 gate_cstrbuffer_destroy(&sql);
472 if(ptr_meta_result)
473 {
474 mysql.free_result(ptr_meta_result);
475 }
476
477 if(ptr_stmt)
478 {
479 mysql.stmt_close(ptr_stmt);
480 }
481
482 return ret;
483 }
484 */
485
486 static gate_result_t mysqlstmt_init(gate_data_statement_base_t* self)
487 {
488 GATE_UNUSED_ARG(self);
489 return GATE_RESULT_OK;
490 }
491
492 static void mysqlstmt_close(gate_data_statement_base_t* self)
493 {
494 GATE_UNUSED_ARG(self);
495 }
496 static gate_result_t mysqlstmt_set_param(gate_data_statement_base_t* self, gate_size_t index, gate_value_t const* value)
497 {
498 /* TODO implementation */
499 return GATE_RESULT_NOTSUPPORTED;
500 }
501 static gate_result_t mysqlstmt_set_named_param(gate_data_statement_base_t* self, gate_string_t const* name, gate_value_t const* value)
502 {
503 /* TODO implementation */
504 return GATE_RESULT_NOTSUPPORTED;
505 }
506 static gate_result_t mysqlstmt_reset(gate_data_statement_base_t* self)
507 {
508 /* TODO implementation */
509 return GATE_RESULT_NOTSUPPORTED;
510 }
511 static gate_result_t mysqlstmt_execute(gate_data_statement_base_t* self, gate_int32_t* affected_rows)
512 {
513 /* TODO implementation */
514 return GATE_RESULT_NOTSUPPORTED;
515 }
516 static gate_result_t mysqlstmt_query(gate_data_statement_base_t* self, gate_data_reader_t** ptr_reader)
517 {
518 gate_result_t ret = GATE_RESULT_FAILED;
519 MYSQL* const ptr_mysql = (MYSQL*)self->native_handles[0];
520 MYSQL_STMT* const ptr_stmt = (MYSQL_STMT*)self->native_handles[1];
521 MYSQL_RES* ptr_meta_result = NULL;
522 int my_result;
523 gate_data_handles_t reader_handles;
524
525 do
526 {
527 my_result = mysql.stmt_execute(ptr_stmt);
528 if (0 != my_result)
529 {
530 ret = GATE_RESULT_FAILED;
531 break;
532 }
533
534 ptr_meta_result = mysql.stmt_result_metadata(ptr_stmt);
535 if (!ptr_meta_result)
536 {
537 ret = GATE_RESULT_INVALIDOUTPUT;
538 break;
539 }
540
541 ret = GATE_RESULT_OK;
542 if (ptr_reader)
543 {
544 gate_mem_clear(&reader_handles[0], sizeof(reader_handles));
545 reader_handles[0] = ptr_mysql;
546 reader_handles[1] = ptr_stmt;
547 reader_handles[2] = ptr_meta_result;
548
549 *ptr_reader = gate_data_reader_base_create(
550 (gate_data_statement_t*)self, reader_handles,
551 &mysqlreader_init,
552 &mysqlreader_is_valid,
553 &mysqlreader_next,
554 &mysqlreader_close);
555 if (*ptr_reader == NULL)
556 {
557 ret = GATE_RESULT_OUTOFMEMORY;
558 break;
559 }
560 ptr_meta_result = NULL;
561 }
562 } while (0);
563
564 if (ptr_meta_result != NULL)
565 {
566 mysql.free_result(ptr_meta_result);
567 }
568
569 return ret;
570 }
571
572
573
574
575
576 static gate_result_t mysqlconn_create_statement(gate_data_connection_base_t* self, gate_string_t const* sql, gate_data_statement_t** ptr_statement)
577 {
578 gate_result_t ret = GATE_RESULT_FAILED;
579 int result;
580 gate_cstrbuffer_t sql_cmd = GATE_INIT_EMPTY;
581 gate_data_handles_t reader_handles;
582 MYSQL* const ptr_mysql = (MYSQL*)self->native_handles[0];
583 MYSQL_STMT* ptr_stmt = NULL;
584 gate_data_statement_base_t* ptr_statement_base = NULL;
585
586 do
587 {
588 if (!ptr_mysql || gate_string_is_empty(sql))
589 {
590 ret = GATE_RESULT_INVALIDSTATE;
591 break;
592 }
593
594 if (NULL == gate_cstrbuffer_create_string(&sql_cmd, sql, false))
595 {
596 ret = GATE_RESULT_OUTOFMEMORY;
597 break;
598 }
599
600 ptr_stmt = mysql.stmt_init(ptr_mysql);
601 if (!ptr_stmt)
602 {
603 ret = GATE_RESULT_OUTOFMEMORY;
604 break;
605 }
606
607 result = mysql.stmt_prepare(ptr_stmt,
608 gate_cstrbuffer_get(&sql_cmd),
609 (unsigned long)gate_cstrbuffer_length(&sql_cmd));
610 if (0 != result)
611 {
612 ret = GATE_RESULT_INVALIDINPUT;
613 break;
614 }
615
616 gate_mem_clear(&reader_handles[0], sizeof(reader_handles));
617 reader_handles[0] = ptr_mysql;
618 reader_handles[1] = ptr_stmt;
619
620 ret = gate_data_statement_base_create(
621 self, reader_handles, sql,
622 &mysqlstmt_init,
623 &mysqlstmt_close,
624 &mysqlstmt_set_param,
625 &mysqlstmt_set_named_param,
626 &mysqlstmt_reset,
627 &mysqlstmt_execute,
628 &mysqlstmt_query,
629 &ptr_statement_base);
630
631 if (GATE_FAILED(ret))
632 {
633 mysql.stmt_close(ptr_stmt);
634 break;
635 }
636
637 ret = GATE_RESULT_OK;
638 ptr_stmt = NULL;
639
640
641 } while (0);
642
643 if (ptr_statement_base != NULL)
644 {
645 gate_object_release(ptr_statement_base);
646 }
647
648 gate_cstrbuffer_destroy(&sql_cmd);
649 if (ptr_stmt != NULL)
650 {
651 mysql.stmt_close(ptr_stmt);
652 }
653 return ret;
654 }
655
656
657
658
659 static gate_string_t const mysql_uri_scheme = GATE_STRING_INIT_STATIC("mysql");
660
661 gate_result_t gate_data_adapter_mysql_create(gate_string_t const* path, gate_enumint_t flags,
662 gate_data_connection_t** ptr_connection)
663 {
664 gate_result_t result;
665 gate_data_handles_t data_handles = GATE_INIT_EMPTY;
666 gate_uri_t uri = GATE_INIT_EMPTY;
667 gate_uint16_t mysql_port = 0;
668 gate_string_t username = GATE_STRING_INIT_EMPTY;
669 gate_string_t password = GATE_STRING_INIT_EMPTY;
670 gate_cstrbuffer_t mysql_host = GATE_INIT_EMPTY;
671 gate_cstrbuffer_t mysql_user = GATE_INIT_EMPTY;
672 gate_cstrbuffer_t mysql_pass = GATE_INIT_EMPTY;
673 gate_cstrbuffer_t mysql_db = GATE_INIT_EMPTY;
674 char const* mysql_db_ptr = NULL;
675 MYSQL* ptr_mysql = NULL;
676
677 do
678 {
679 result = gate_uri_parse(&uri, path);
680 GATE_BREAK_IF_FAILED(result);
681
682 if (!gate_string_equals(&uri.scheme, &mysql_uri_scheme))
683 {
684 result = GATE_RESULT_INVALIDINPUT;
685 break;
686 }
687 gate_cstrbuffer_create_string(&mysql_host, &uri.host, false);
688 mysql_port = uri.port ? uri.port : 3306;
689 gate_uri_parse_user_info(&uri.user_info, &username, &password);
690 gate_cstrbuffer_create_string(&mysql_user, &username, false);
691 gate_cstrbuffer_create_string(&mysql_pass, &password, false);
692 gate_cstrbuffer_create_string(&mysql_db, &uri.absolute_path, false);
693
694 mysql_db_ptr = gate_cstrbuffer_get(&mysql_db);
695 if (mysql_db_ptr && mysql_db_ptr[0] == '/')
696 {
697 mysql_db_ptr = &mysql_db_ptr[1];
698 if (gate_str_length(mysql_db_ptr) == 0)
699 {
700 mysql_db_ptr = NULL;
701 }
702 }
703
704 result = gate_mysql_load_api();
705 GATE_BREAK_IF_FAILED(result);
706
707 ptr_mysql = mysql.init(NULL);
708 if (NULL == ptr_mysql)
709 {
710 result = GATE_RESULT_FAILED;
711 break;
712 }
713
714 if (NULL == mysql.real_connect(ptr_mysql,
715 gate_cstrbuffer_get(&mysql_host),
716 gate_cstrbuffer_get(&mysql_user),
717 gate_cstrbuffer_get(&mysql_pass),
718 mysql_db_ptr, mysql_port, NULL, 0))
719 {
720 result = GATE_RESULT_FAILED;
721 break;
722 }
723
724 data_handles[0] = (void*)ptr_mysql;
725
726 result = gate_data_connection_base_create(data_handles,
727 &mysqlconn_init,
728 &mysqlconn_close,
729 &mysqlconn_create_statement,
730 ptr_connection);
731 GATE_BREAK_IF_FAILED(result);
732
733 /* success, handles transfered to ptr_connection! */
734 ptr_mysql = NULL;
735 } while (0);
736
737 if (ptr_mysql)
738 {
739 mysql.close(ptr_mysql);
740 }
741
742 gate_string_release(&username);
743 gate_string_release(&password);
744 gate_cstrbuffer_destroy(&mysql_host);
745 gate_cstrbuffer_destroy(&mysql_user);
746 gate_cstrbuffer_destroy(&mysql_pass);
747 gate_cstrbuffer_destroy(&mysql_db);
748 gate_uri_destroy(&uri);
749
750 return result;
751 }
752
753