dclib-mysql.h 20 KB

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