1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
|
/***************************************************************************
* *
* _____ ____ *
* | __ \ / __ \ _ _ _____ *
* | | \ \ / / \_\ | | | | _ \ *
* | | \ \| | | | | | |_| | *
* | | | || | | | | | ___/ *
* | | / /| | __ | | | | _ \ *
* | |__/ / \ \__/ / | |___| | |_| | *
* |_____/ \____/ |_____|_|_____/ *
* *
* Wiimms source code library *
* *
***************************************************************************
* *
* Copyright (c) 2012-2020 by Dirk Clemens <wiimm@wiimm.de> *
* *
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt *
* *
***************************************************************************/
#ifndef DCLIB_MYSQL_H
#define DCLIB_MYSQL_H 1
#include <mysql/mysql.h>
#include "dclib-types.h"
#include "dclib-debug.h"
#include "dclib-basics.h"
//
///////////////////////////////////////////////////////////////////////////////
/////////////// mysql definitions ///////////////
///////////////////////////////////////////////////////////////////////////////
typedef struct st_mysql st_mysql;
typedef struct st_mysql_res st_mysql_res;
typedef struct st_mysql_field st_mysql_field;
#define MYSQL_DEFAULT_PORT 3306
struct MySql_t;
typedef enum LogLevelMYSQL
{
MYLL_SILENT,
MYLL_ERROR,
MYLL_QUERY_ON_ERROR,
MYLL_QUERY_ALWAYS,
MYLL_ALL
}
LogLevelMYSQL;
//
///////////////////////////////////////////////////////////////////////////////
/////////////// struct MySqlStatus_t ///////////////
///////////////////////////////////////////////////////////////////////////////
typedef struct MySqlStatus_t
{
int status; // status of last operation
ccp message; // pointer to last error message
bool alloced; // 'message' is alloced
char msgbuf[120]; // buffer for short messages
}
MySqlStatus_t;
//
///////////////////////////////////////////////////////////////////////////////
/////////////// struct MySqlResult_t ///////////////
///////////////////////////////////////////////////////////////////////////////
// [[MySqlResult_t]]
typedef struct MySqlResult_t
{
//--- linked double-list for management
struct MySqlResult_t *prev_result; // NULL or link to previous result
struct MySqlResult_t *next_result; // NULL or link to next result
struct MySql_t *mysql; // related MySql_t struct
//--- mysql result and status
MYSQL_RES *myres; // mysql result
LogLevelMYSQL loglevel; // log level for mysql errors and queries
MySqlStatus_t status; // last error status
//--- rows and fields
int row_count; // number of read rows
int field_count; // number of fields in a row
mem_t *row; // list with 'field_count' entries
MYSQL_ROW myrow; // mysql row
}
MySqlResult_t;
//
///////////////////////////////////////////////////////////////////////////////
/////////////// struct MySql_t ///////////////
///////////////////////////////////////////////////////////////////////////////
// [[MySql_t]]
typedef struct MySql_t
{
//--- database definitions, strings are alloced
ccp server; // server
ccp user; // user
ccp password; // password
ccp database; // database name
ccp prefix; // default prefix, only for external usage
bool auto_connect; // true: auto connect if closed
bool auto_reconnect; // true(default): try 1 reconnect on connection lost
//--- mysql data
MYSQL *mysql; // mysql connection
uint field_count; // mysql_field_count() of last query
MySqlStatus_t status; // last error status
MySqlResult_t *first_result; // pointer to first result
MySqlResult_t *pool_result; // list with unused objects
//--- a small temporary buffer for e.g. small results
char tempbuf[120]; // temporary buffer
bool tempbuf_used; // true: 'tempbuf' is used
//--- statistics
uint total_connect_count; // total number of connections (usualy 1)
uint total_query_count; // total number of queries
u64 total_query_size; // total size of all queries
uint total_result_count; // total number of fetched results
u64 total_row_count; // total number of fetched rows
u64 total_field_count; // total number of fetched fields
u64 total_field_size; // total size of all fetched fields
//--- both timers count the execution time of DoQueryMYSQL()
//--- inclusive database reopen and error handling.
u64 last_duration_usec; // duration of last query
u64 max_duration_usec; // max duration of all queries
u64 total_duration_usec; // total duration of all queries
}
MySql_t;
//
///////////////////////////////////////////////////////////////////////////////
/////////////// interface for MySql_t ///////////////
///////////////////////////////////////////////////////////////////////////////
void InitializeMYSQL ( MySql_t *my );
void ResetMYSQL ( MySql_t *my );
enumError OpenMYSQL ( MySql_t *my, uint loglevel );
void CloseMYSQL ( MySql_t *my );
void DefineDatabase
(
MySql_t *my, // valid struct
ccp server, // NULL or server name
ccp user, // NULL or user name
ccp password, // NULL or user password
ccp database // NULL or name of database
);
void DefineDatabasePrefix
(
MySql_t *my, // valid struct
ccp prefix // NULL or default prefix, only for external usage
);
//-----------------------------------------------------------------------------
static inline bool IsOpenMYSQL ( MySql_t *my ) // 'my' may be NULL
{
return my && my->mysql;
}
static inline bool AutoOpenMYSQL ( MySql_t *my, uint loglevel ) // 'my' may be NULL
{
return my
&& ( my->mysql || my->auto_connect && OpenMYSQL(my,loglevel) == ERR_OK );
}
//-----------------------------------------------------------------------------
enumError DoQueryMYSQL
(
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
ccp query, // query string
int query_length // length of 'query', -1 if unknown
);
enumError PrintArgQueryMYSQL
(
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
ccp format, // format string for vsnprintf()
va_list arg // parameters for 'format'
);
enumError PrintQueryMYSQL
(
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
ccp format, // format string for vsnprintf()
... // parameters for 'format'
)
__attribute__ ((__format__(__printf__,3,4)));
//-----------------------------------------------------------------------------
// multi queries
mem_t GetFirstQuery ( ccp src, int src_len );
enumError DoMultiQueryMYSQL
(
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
ccp query, // query string
int query_length // length of 'query', -1 if unknown
);
enumError PrintMultiQueryMYSQL
(
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
ccp format, // format string for vsnprintf()
... // parameters for 'format'
)
__attribute__ ((__format__(__printf__,3,4)));
//-----------------------------------------------------------------------------
// temp buffer for small results as optimization
mem_t CopyMemMYSQL ( MySql_t * my, mem_t * src ); // 'src' may be NULL
void FreeMemMYSQL ( MySql_t * my, mem_t mem );
//-----------------------------------------------------------------------------
// fetch single value as result of a query
mem_t FetchScalarMYSQL // call FreeScalarMYSQL() for the result
(
MySql_t *my, // valid struct
LogLevelMYSQL loglevel // log level for mysql errors and queries
);
s64 FetchIntMYSQL
(
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
s64 return_default // return this value on non existent result
);
u64 FetchUIntMYSQL
(
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
u64 return_default // return this value on non existent result
);
//-----------------------------------------------------------------------------
// print query & fetch single value as result
mem_t PrintArgFetchScalarMYSQL
(
// if res.len>0: FREE the result using FreeMemMYSQL(my,mem)
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
ccp format, // format string for vsnprintf()
va_list arg // parameters for 'format'
);
mem_t PrintFetchScalarMYSQL
(
// if res.len>0: FREE the result using FreeMemMYSQL(my,mem)
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
ccp format, // format string for vsnprintf()
... // parameters for 'format'
)
__attribute__ ((__format__(__printf__,3,4)));
s64 PrintFetchIntMYSQL
(
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
s64 return_default, // return this value on non existent result
ccp format, // format string for vsnprintf()
... // parameters for 'format'
)
__attribute__ ((__format__(__printf__,4,5)));
u64 PrintFetchUIntMYSQL
(
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
u64 return_default, // return this value on non existent result
ccp format, // format string for vsnprintf()
... // parameters for 'format'
)
__attribute__ ((__format__(__printf__,4,5)));
//-----------------------------------------------------------------------------
// fetch single row
void * FetchSingleRowN
(
// returns NULL on error or emtpy result,
// or a temporary buffer => call FREE(result)
// following rows will be skipped
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
mem_t *dest, // dest buffer, unused elements are set to {0,0}
uint n_dest // number of elements in 'dest'
);
int FetchSingleRowList
(
// returns -1 on error, 0 on empty result or the number of retrieved field
// following rows will be skipped
MySql_t *my, // valid struct
LogLevelMYSQL loglevel, // log level for mysql errors and queries
mem_list_t *dest, // destination list
bool init_dest, // true: initialize 'dest'
bool replace_null // true: replace NULL by EmptyString
);
//-----------------------------------------------------------------------------
// count tables and columns
int CountTablesMYSQL
(
MySql_t *my, // valid DB connection
ccp table, // like "table"; if NULL|EMPTY: count tables
ccp database // database name; if NULL|EMPTY: use default DB
);
int CountColumnsMYSQL
(
MySql_t *my, // valid DB connection
ccp column, // column name; if NULL|EMPTY: count columns
ccp table, // like "table"; if NULL|EMPTY: all tables
ccp database // database name; if NULL|EMPTY: use default DB
);
//-----------------------------------------------------------------------------
// helpers
static inline int LastInsertIdMYSQL ( MySql_t *my )
{ return mysql_insert_id(my->mysql); }
struct TransferStats_t GetStatsMYSQL ( MySql_t *my );
//-----------------------------------------------------------------------------
// escaping and quoting
// All functions are robust for NULL pointers.
// If len<0 und ptr!=0, then strlen(ptr) is used.
// The `circ´ variants return a buffer alloced by GetCircBuf() with
// valid pointer and null terminated. If result is too large
// (>CIRC_BUF_MAX_ALLOC) then (0,0) is returned.
// The result of `circ´ variants must not be freed!
// All others results must be freed by `FreeString(mem.ptr)´.
//---------------------------------------------------
// In general: Use faster `circ´ variants if you can
// guarantee, that src_len < CIRC_BUF_MAX_ALLOC/2.
//---------------------------------------------------
mem_t EscapeMYSQL ( MySql_t *my, cvp ptr, int len );
mem_t EscapeMYSQLCirc ( MySql_t *my, cvp ptr, int len );
static inline mem_t EscapeMemMYSQL ( MySql_t *my, mem_t src );
static inline mem_t EscapeMemMYSQLCirc ( MySql_t *my, mem_t src );
static inline mem_t EscapeStringMYSQL ( MySql_t *my, ccp src );
static inline mem_t EscapeStringMYSQLCirc(MySql_t *my, ccp src );
mem_t QuoteMYSQL ( MySql_t *my, cvp ptr, int len, bool null_if_empty );
mem_t QuoteMYSQLCirc ( MySql_t *my, cvp ptr, int len, bool null_if_empty );
static inline mem_t QuoteMemMYSQL ( MySql_t *my, mem_t src, bool null_if_empty );
static inline mem_t QuoteMemMYSQLCirc ( MySql_t *my, mem_t src, bool null_if_empty );
static inline mem_t QuoteStringMYSQL ( MySql_t *my, ccp src, bool null_if_empty );
static inline mem_t QuoteStringMYSQLCirc( MySql_t *my, ccp src, bool null_if_empty );
//-----------------------------------------------------------------------------
// inlines of escaping and quoting
static inline mem_t EscapeMemMYSQL ( MySql_t *my, mem_t src )
{ return EscapeMYSQL(my,src.ptr,src.len); }
static inline mem_t EscapeMemMYSQLCirc ( MySql_t *my, mem_t src )
{ return EscapeMYSQLCirc(my,src.ptr,src.len); }
static inline mem_t EscapeStringMYSQL ( MySql_t *my, ccp src )
{ return EscapeMYSQL(my,src,-1); }
static inline mem_t EscapeStringMYSQLCirc( MySql_t *my, ccp src )
{ return EscapeMYSQLCirc(my,src,-1); }
static inline mem_t QuoteMemMYSQL ( MySql_t *my, mem_t src, bool null_if_empty )
{ return QuoteMYSQL(my,src.ptr,src.len,null_if_empty); }
static inline mem_t QuoteMemMYSQLCirc ( MySql_t *my, mem_t src, bool null_if_empty )
{ return QuoteMYSQLCirc(my,src.ptr,src.len,null_if_empty); }
static inline mem_t QuoteStringMYSQL ( MySql_t *my, ccp src, bool null_if_empty )
{ return QuoteMYSQL(my,src,-1,null_if_empty); }
static inline mem_t QuoteStringMYSQLCirc ( MySql_t *my, ccp src, bool null_if_empty )
{ return QuoteMYSQLCirc(my,src,-1,null_if_empty); }
//
///////////////////////////////////////////////////////////////////////////////
/////////////// interface MySqlResult_t ///////////////
///////////////////////////////////////////////////////////////////////////////
MySqlResult_t * UseResultMYSQL ( MySql_t * my, uint loglevel );
void FreeResultMYSQL ( MySqlResult_t * res ); // res maybe NULL
void CloseResultMYSQL ( MySqlResult_t * res );
void FreeResultListMYSQL ( MySqlResult_t * first_result );
mem_t * GetNextRowMYSQL ( MySqlResult_t * res );
//
///////////////////////////////////////////////////////////////////////////////
/////////////// interface for MySqlStatus_t ///////////////
///////////////////////////////////////////////////////////////////////////////
static inline void InitializeStatusMYSQL ( MySqlStatus_t *stat )
{
DASSERT(stat);
memset(stat,0,sizeof(*stat));
stat->message = stat->msgbuf;
}
void ClearStatusMYSQL ( MySqlStatus_t *stat );
uint GetStatusMYSQL ( MySqlStatus_t *stat, MYSQL *my );
void AssignStatusMYSQL
(
MySqlStatus_t *stat, // valid struct
int stat_code, // error status to assign
ccp message, // NULL or pointer to message
int copy_mode // 0:copy message, 1:use ptr, 2:use+free ptr
);
void CopyStatusMYSQL
(
MySqlStatus_t *dest, // NULL or initialized status
bool init_dest, // true: initialize 'dest'
const MySqlStatus_t *src // NULL (clear dest)
// or initialized status (assign to dest)
);
void MoveStatusMYSQL
(
MySqlStatus_t *dest, // NULL or initialized status
bool init_dest, // true: initialize 'dest'
MySqlStatus_t *src // NULL (clear dest)
// or initialized status (move to dest)
);
void PrintStatusMYSQL
(
MySqlStatus_t *stat, // valid struct
int stat_code, // error status to assign
ccp format, // format string for vsnprintf()
... // parameters for 'format'
)
__attribute__ ((__format__(__printf__,3,4)));
//
///////////////////////////////////////////////////////////////////////////////
/////////////// test_mysql_stats() ///////////////
///////////////////////////////////////////////////////////////////////////////
// [[MySqlServerStats_t]]
typedef struct MySqlServerStats_t
{
u32 max_connections; // maximal used connections
s32 uptime; // uptime in seconds
s64 connections; // number of total connections
s64 queries; // number of total queries
}
MySqlServerStats_t;
///////////////////////////////////////////////////////////////////////////////
static inline void InitializeMySqlServerStats ( MySqlServerStats_t *stat )
{ DASSERT(stat); memset(stat,0,sizeof(*stat)); }
enumError GetMySqlServerStats ( MySql_t *my, MySqlServerStats_t *stat );
MySqlServerStats_t * Add3MySqlServerStats
(
// return dest
// calculate: dest = src1 + src2
MySqlServerStats_t *dest, // NULL or destination (maybe same as source)
const MySqlServerStats_t *src1, // NULL or first source
const MySqlServerStats_t *src2 // NULL or second source
);
MySqlServerStats_t * Sub3MySqlServerStats
(
// return dest
// calculate: dest = src1 - src2
MySqlServerStats_t *dest, // NULL or destination (maybe same as source)
const MySqlServerStats_t *src1, // NULL or first source
const MySqlServerStats_t *src2 // NULL or second source
);
MySqlServerStats_t * Max2MySqlServerStats
(
// return dest
// calculate: dest := max(dest,src)
MySqlServerStats_t *dest, // NULL or destination (maybe same as source)
const MySqlServerStats_t *src // NULL or source
);
//
///////////////////////////////////////////////////////////////////////////////
/////////////// E N D ///////////////
///////////////////////////////////////////////////////////////////////////////
#endif // DCLIB_MYSQL_H
|