Mstdlib-1.24.0
m_sql.h
1/* The MIT License (MIT)
2 *
3 * Copyright (c) 2017 Monetra Technologies, LLC.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#ifndef __M_SQL_H__
25#define __M_SQL_H__
26
27/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
28
29#include <mstdlib/base/m_defs.h>
30#include <mstdlib/base/m_types.h>
31
32/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
33
34__BEGIN_DECLS
35
36/*! \addtogroup m_sql_drivers SQL Drivers
37 * \ingroup m_sql
38 *
39 * SQL Drivers and Configuration Options
40 */
41
42/*! \addtogroup m_sql_driver_sqlite SQLite Driver
43 * \ingroup m_sql_drivers
44 *
45 * SQLite Driver
46 *
47 * Driver Name: sqlite
48 *
49 * Driver Connection String Options:
50 * - path: Required. Filesystem path to SQLite database.
51 * - journal_mode: Optional. Defaults to "WAL" if not specified, other
52 * options include "DELETE".
53 * - analyze: Optional. Defaults to "TRUE" if not specified. On first connect,
54 * automatically runs an analyze to update index statistics if set to "TRUE".
55 * - integrity_check: Optional. Defaults to "FALSE" if not specified. On first
56 * connect, automatically runs an integrity check to verify the database
57 * integrity if set to "TRUE".
58 * - shared_cache: Optional. Defaults to "TRUE" if not specified. Enables
59 * shared cache mode for multiple connections to the same database.
60 * - autocreate: Optional. Defaults to "TRUE" if not specified. The default is
61 * to auto-create the database if not found, set this to "FALSE" to error if
62 * the database does not exist.
63 */
64
65/*! \addtogroup m_sql_driver_mysql MySQL/MariaDB Driver
66 * \ingroup m_sql_drivers
67 *
68 * MySQL/MariaDB Driver
69 *
70 * Driver Name: mysql
71 *
72 * Driver Connection String Options:
73 * - db: Required. Database Name.
74 * - socketpath: Conditional. If using Unix Domain Sockets to connect to MySQL,
75 * this is the path to the Unix Domain Socket. Use the keyword of 'search'
76 * to search for the socket based on standard known paths. Cannot be used
77 * with host.
78 * - host: Conditional. If using IP or SSL/TLS to connect to MySQL, this is the
79 * hostname or IP address of the server. If not using the default port of
80 * 3306, may append a ":port#" to the end of the host. For specifying multiple
81 * hosts in a pool, hosts should be comma delimited. Cannot be used with socketpath.
82 * \code host=10.40.30.2,10.50.30.2:13306 \endcode
83 * - aurora: Optional. Defaults to false. If true, enables the MariaDB Aurora Connection
84 * handler plugin.
85 * - ssl: Optional. Defaults to false, if true enables SSL/TLS to the server.
86 * - mysql_engine: Optional. Used during table creation, defaults to INNODB. The default
87 * data storage engine to use with mysql. Typically it is recommended to leave
88 * this at the default.
89 * - mysql_charset: Optional. Used during table creation, defaults to utfmb4.
90 * - max_isolation: Optional. Sets the maximum isolation level used for transactions.
91 * This is used to overwrite requests for SERIALIZABLE isolation levels,
92 * useful with Galera-based clusters that do not truly support Serializable
93 * isolation. Should use "SELECT ... FOR UPDATE" type syntax for row locking.
94 * Available settings: "REPEATABLE READ", READ COMMITTED"
95 */
96
97/*! \addtogroup m_sql_driver_postgresql PostgreSQL Driver
98 * \ingroup m_sql_drivers
99 *
100 * PostgreSQL Driver
101 *
102 * Driver Name: postgresql
103 *
104 * Driver Connection String Options:
105 * - db: Required. Database Name.
106 * - host: Required. This is the hostname or IP address of the server. If not using
107 * the default port of 5432, may append a ":port#" to the end of the host. For specifying multiple
108 * hosts in a pool, hosts should be comma delimited. Cannot be used with socketpath.
109 * \code host=10.40.30.2,10.50.30.2:15432 \endcode
110 * - application_name: Optional. Application name to register with the server for debugging
111 * purposes.
112 *
113 * Minimum supported server version is v9.5.0. Earlier versions did not support 'ON CONFLICT'
114 * conflict resolution for INSERT.
115 */
116
117/*! \addtogroup m_sql_driver_oracle Oracle Driver
118 * \ingroup m_sql_drivers
119 *
120 * Oracle Driver
121 *
122 * Driver Name: oracle
123 *
124 * Driver Connection String Options:
125 * - dsn: Conditional. Data Source Name as specified in tnsnames.ora, or a fully
126 * qualified connection string. If not specified, both host and service_name must both
127 * be specified and a connection string will be dynamically generated. Use of this
128 * parameter negates the ability to use mstdlib's load balancing and failover logic,
129 * but facilitates the use of Oracle's equivalent functionality.
130 * An example of a fully qualified connection string would be:
131 * \code
132 * (DESCRIPTION =
133 * (ADDRESS = (PROTOCOL = TCP)(Host = 10.100.10.168)(Port = 1521))
134 * (CONNECT_DATA = (SERVICE_NAME = orcl))
135 * )
136 * \endcode
137 * - host: Conditional. If dsn is not specified, this parameter must be specified along
138 * with the service_name parameter.
139 * This is the hostname or IP address of the server. If not using the default port
140 * of 1521, may append a ":port#" to the end of the host. For specifying multiple
141 * hosts in a pool, hosts should be comma delimited. Cannot be used with dsn.
142 * \code host=10.40.30.2,10.50.30.2:11521 \endcode
143 * - service_name: Conditional. If dsn is not specified, this parameter must be specified
144 * along with the host parameter. Cannot be used with dsn.
145 * \code service_name=orcl \endcode
146 *
147 * Example with dsn:
148 * \code
149 * dsn='(DESCRIPTION =
150 * (ADDRESS = (PROTOCOL = TCP)(Host = 10.100.10.168)(Port = 1521))
151 * (CONNECT_DATA = (SERVICE_NAME = orcl))
152 * )'
153 * \endcode
154 *
155 * Example without dsn:
156 * \code
157 * host=10.100.10.168;service_name=orcl
158 * \endcode
159 */
160
161/*! \addtogroup m_sql_driver_odbc ODBC and DB2 Driver
162 * \ingroup m_sql_drivers
163 *
164 * ODBC and DB2 Driver
165 *
166 * Driver Name(s):
167 * - odbc (for Microsoft Windows, iODBC, or UnixODBC)
168 * - db2 (for direct DB2 connectivity)
169 * - db2pase (for direct DB2 connectivity on OS/400 PASE)
170 *
171 * Driver Connection String Options:
172 * - dsn: Required. Data Source Name
173 * - mysql_engine: Optional. Used during table creation when the destination
174 * database is MySQL, defaults to INNODB. The default data storage engine
175 * to use with mysql. Typically it is recommended to leave this at the
176 * default.
177 * - mysql_charset: Optional. Used during table creation when the destination
178 * database is MySQL, defaults to utf8mb4.
179 */
180
181/*! \addtogroup m_sql_error SQL Error handling functions
182 * \ingroup m_sql
183 *
184 * SQL Error handling
185 *
186 * @{
187 */
188
189/*! Possible error conditions */
190typedef enum {
191 M_SQL_ERROR_SUCCESS = 0, /*!< No error, success. If returned by M_sql_stmt_fetch(), there
192 * are guaranteed to not be any rows in the result set. However,
193 * for an M_sql_stmt_execute() or M_sql_trans_execute() if
194 * M_sql_stmt_set_max_fetch_rows() was not set, there may be
195 * rows available. */
196 M_SQL_ERROR_SUCCESS_ROW = 1, /*!< No error, success, rows may be available to be fetched */
197
198 /* Connectivity failures */
199 M_SQL_ERROR_CONN_NODRIVER = 100, /*!< Driver not found for specified driver name. */
200 M_SQL_ERROR_CONN_DRIVERLOAD = 101, /*!< Failed to dynamically load driver module. */
201 M_SQL_ERROR_CONN_DRIVERVER = 102, /*!< Driver version invalid */
202 M_SQL_ERROR_CONN_PARAMS = 103, /*!< Connection string parameter validation failed */
203 M_SQL_ERROR_CONN_FAILED = 104, /*!< Failed to establish connection to server. */
204 M_SQL_ERROR_CONN_BADAUTH = 105, /*!< Failed to authenticate against server. */
205 M_SQL_ERROR_CONN_LOST = 106, /*!< Connection to server has been lost (remote disconnect). */
206
207 /* Prepare errors */
208 M_SQL_ERROR_PREPARE_INVALID = 200, /*!< Invalid query format */
209 M_SQL_ERROR_PREPARE_STRNOTBOUND = 201, /*!< A string was detected in the query that was not bound */
210 M_SQL_ERROR_PREPARE_NOMULITQUERY = 202, /*!< Multiple requests in a single query are not allowed */
211
212 /* Execute query */
213 M_SQL_ERROR_QUERY_NOTPREPARED = 300, /*!< Can't execute query as statement hasn't been prepared */
214 M_SQL_ERROR_QUERY_WRONGNUMPARAMS = 301, /*!< Wrong number of bound parameters provided for query */
215 M_SQL_ERROR_QUERY_PREPARE = 302, /*!< DB Driver failed to prepare the query for execution */
216
217 /* Other errors */
218 M_SQL_ERROR_QUERY_DEADLOCK = 400, /*!< Deadlock (must rollback), cannot continue. */
219 M_SQL_ERROR_QUERY_CONSTRAINT = 410, /*!< Constraint failed (e.g. Unique key or primary key conflict) */
220 M_SQL_ERROR_QUERY_FAILURE = 499, /*!< Failure (uncategorized) */
221
222
223
224 /* Failure options for Disconnect */
225 M_SQL_ERROR_INUSE = 500, /*!< Resource in use, invalid action */
226 /* Generic Failures */
227 M_SQL_ERROR_INVALID_USE = 600, /*!< Invalid use */
228 M_SQL_ERROR_INVALID_TYPE = 601, /*!< Invalid Data Type for conversion */
229
230 /* User-generated errors or conditions via M_sql_trans_process() */
231 M_SQL_ERROR_USER_SUCCESS = 700, /*!< Return code a User can generate in M_sql_trans_process() to
232 * Indicate the operation is complete and the system can
233 * commit any pending data. This is equivalent to #M_SQL_ERROR_SUCCESS
234 * but can be used in its place if a user needs to have the
235 * ability to differentiate how M_sql_trans_process() returned
236 * success. */
237 M_SQL_ERROR_USER_BYPASS = 703, /*!< Return code a User can generate in M_sql_trans_process() to
238 * indicate the operation should be bypassed. This can be used to
239 * differentiate a traditional tristate error message. Otherwise
240 * this is classified as success. */
241 M_SQL_ERROR_USER_RETRY = 701, /*!< Return code a User can generate in M_sql_trans_process() to
242 * request the system to rollback and retry the entire sequence
243 * of events. This is equivalent to #M_SQL_ERROR_QUERY_DEADLOCK
244 * but more accurately indicates the failure was due to user-logic
245 * rather than a condition triggered internally to the SQL system */
246 M_SQL_ERROR_USER_FAILURE = 702, /*!< Return code a User can generate in M_sql_trans_process() to
247 * request the system to rollback and return the error to the
248 * caller. This is equivalent to #M_SQL_ERROR_QUERY_FAILURE
249 * but more accurately indicates the failure was due to user-logic
250 * rather than a condition triggered internally to the SQL system */
251
252 M_SQL_ERROR_UNSET = 999 /*!< Error message not set. Internal use only. */
254
255/*! Possible SQL data types */
256typedef enum {
257 M_SQL_DATA_TYPE_UNKNOWN = 0, /*!< Not Known, not yet set, most likely an error */
258 M_SQL_DATA_TYPE_BOOL = 1, /*!< Implemented as an 8bit integer */
259 M_SQL_DATA_TYPE_INT16 = 2, /*!< 16bit signed integer */
260 M_SQL_DATA_TYPE_INT32 = 3, /*!< 32bit signed integer */
261 M_SQL_DATA_TYPE_INT64 = 4, /*!< 64bit signed integer */
262 M_SQL_DATA_TYPE_TEXT = 5, /*!< Textual data type such as VARCHAR or TEXT, with possible length */
263 M_SQL_DATA_TYPE_BINARY = 6 /*!< Binary data type such as BLOB or BINARY, with possible length */
265
266
267/*! Retrieve generic error string associated with error code.
268 *
269 * Often the error message returned by the calling function or M_sql_stmt_get_error_string()
270 * is more useful for human display purposes.
271 *
272 * \param[in] err Error to evaluate
273 * \return string representation of error message.
274 */
275M_API const char *M_sql_error_string(M_sql_error_t err);
276
277/*! Returns if error code is a failure or not.
278 *
279 * Currently this returns true if the error condition is any error other than
280 * #M_SQL_ERROR_SUCCESS or #M_SQL_ERROR_SUCCESS_ROW.
281 *
282 * \param[in] err Error to evaluate
283 * \return M_TRUE if error, M_FALSE if not.
284 */
286
287/*! Returns if the error code is due to a fatal communications error.
288 * If this occurs, the connection will be automatically destroyed and
289 * next use will try to establish a new connection
290 *
291 * \param[in] err Error to evaluate.
292 * \return M_TRUE if connectivity failure, M_FALSE if not.
293 */
295
296/*! Returns if the error code represents a rollback condition.
297 *
298 * There may be multiple types of failures that are rollback conditions such
299 * as unexpected disconnects from the database, deadlocks, and consistency
300 * failures. This function checks for all known conditions where a rollback
301 * should be performed.
302 *
303 * \param[in] err Error to evaluate.
304 * \return M_TRUE if rollback condition, M_FALSE if not.
305 */
307
308/*! Returns if the error code represents a fatal error returned from the server
309 * that is unlikely to succeed if simply re-attempted. Often this is the
310 * result of a poorly formed query that can't be parsed or prepared.
311 *
312 * Currently this is equivelent to:
313 * \code{.c}
314 * (M_sql_error_is_error(err) && !M_sql_error_is_rollback(err) && !M_sql_error_is_disconnect(err))
315 * \endcode
316 *
317 * \param[in] err Error to evaluate.
318 * \return M_TRUE if fatal error, M_FALSE if not.
319 */
321
322
323/*! @} */
324
325/*! \addtogroup m_sql_conn SQL Connection Management
326 * \ingroup m_sql
327 *
328 * SQL Connection Management
329 *
330 * @{
331 */
332
333struct M_sql_connpool;
334/*! Connection pool object */
335typedef struct M_sql_connpool M_sql_connpool_t;
336
337/*! Flags controlling behavior of the connection pool */
338typedef enum {
339 M_SQL_CONNPOOL_FLAG_NONE = 0, /*!< No special pool flags */
340 M_SQL_CONNPOOL_FLAG_PRESPAWN_ALL = 1 << 0, /*!< Pre-spawn all connections, not just the first.
341 * Without this, the remaining connections are on-demand */
342 M_SQL_CONNPOOL_FLAG_NO_AUTORETRY_QUERY = 1 << 1, /*!< If a non-transactional query is rolled back due to a deadlock
343 * or connectivity failure, the default behavior is to automatically
344 * retry the query, indefinitely. For queries executed as part of
345 * a transaction, rollbacks must be handled by the caller as they
346 * may be dependent on prior queries in the transaction. This flag
347 * will turn off the auto-retry logic */
348 M_SQL_CONNPOOL_FLAG_LOAD_BALANCE = 1 << 2, /*!< If there are multiple servers specified for the connection string,
349 * this will load balance requests across the servers instead of using
350 * them for failover. */
352
353
354/*! Create an SQL connection pool.
355 *
356 * A connection pool is required to be able to run SQL transactions. An internal
357 * connection is automatically claimed for a transaction or statement, or will
358 * wait on an available connection.
359 *
360 * \note The pool is not started untile M_sql_connpool_start() is called, which must
361 * occur before the pool can be used by M_sql_stmt_execute() or M_sql_trans_begin().
362 *
363 * \warning Pool modifications such as M_sql_connpool_add_readonly_pool() and M_sql_connpool_add_trace()
364 * must be called prior to M_sql_connpool_start().
365 *
366 * \param[out] pool Newly initialized pool object
367 * \param[in] driver Name of driver to use. If the driver is not already loaded, will attempt
368 * to load the driver module automatically. Driver modules are named
369 * mstdlib_sql_$driver.dll or mstdlib_sql_$driver.so as appropriate.
370 * \param[in] conn_str A driver-specific connection string or DSN. This string often configures
371 * the host/port, and available options for the driver in use. The connection
372 * strings are a set of key/value pairs, with keys seperated from the values
373 * with an equal sign (=), and values separated by a semi-colon (;). If quoting
374 * is in use, a single-quote (') is recognized, and an escape character of a
375 * single quote (') can be used such that to use a real single quote, you would
376 * use two single quotes. E.g. :
377 * \code host=10.130.40.5:3306;ssl=yes \endcode
378 * Please see the documentation for your driver for available configuration options.
379 * \param[in] username Connection username.
380 * \param[in] password Connection password.
381 * \param[in] max_conns Maximum number of SQL connections to attempt to create. Valid range 1-1000.
382 * \param[in] flags Bitmap of #M_sql_connpool_flags_t options to configure.
383 * \param[out] error Buffer to hold error message.
384 * \param[in] error_size Size of error buffer passed in.
385 * \return #M_SQL_ERROR_SUCCESS on successful pool creation, otherwise one of the #M_sql_error_t errors.
386 */
387M_API M_sql_error_t M_sql_connpool_create(M_sql_connpool_t **pool, const char *driver, const char *conn_str, const char *username, const char *password, size_t max_conns, M_uint32 flags, char *error, size_t error_size);
388
389
390/*! Create a read-only pool attached to our already-created pool.
391 *
392 * The read-only pool will automatically route SELECT transactions, not part of a
393 * transaction (e.g. not within a M_sql_trans_begin() ... M_sql_trans_commit() block)
394 * to the read-only pool. This can be useful for report generation, where the data
395 * is coming from an asyncronous replication pool for reducing load on the master.
396 *
397 * \note The caller can optionally use M_sql_stmt_set_master_only() to enforce routing of
398 * SELECT transactions to the read/write pool instead.
399 *
400 * The read-only pool must share the same driver, username, password, and usage flags as
401 * specified via M_sql_connpool_create(), and must be called before M_sql_connpool_start().
402 *
403 * Only a single read-only pool per pool object is allowed, repeated calls to this function
404 * will result in a failure.
405 *
406 * \param[in] pool Initialized pool object by M_sql_connpool_create().
407 * \param[in] conn_str A driver-specific connection string or DSN. This string often configures
408 * the host/port, and available options for the driver in use. The connection
409 * strings are a set of key/value pairs, with keys seperated from the values
410 * with an equal sign (=), and values separated by a semi-colon (;). If quoting
411 * is in use, a single-quote (') is recognized, and an escape character of a
412 * single quote (') can be used such that to use a real single quote, you would
413 * use two single quotes. E.g. :
414 * \code host=10.130.40.5:3306;ssl=yes \endcode
415 * Please see the documentation for your driver for available configuration options.
416 * \param[in] max_conns Maximum number of SQL connections to attempt to create. Valid range 1-1000.
417 * \param[out] error Buffer to hold error message.
418 * \param[in] error_size Size of error buffer passed in.
419 * \return #M_SQL_ERROR_SUCCESS on successful readonly pool creation, otherwise one of the #M_sql_error_t errors.
420 */
421M_API M_sql_error_t M_sql_connpool_add_readonly_pool(M_sql_connpool_t *pool, const char *conn_str, size_t max_conns, char *error, size_t error_size);
422
423
424/*! Set timeouts for connections on the pool. Timeouts can be used to prevent
425 * stale connections from being used if known firewall timers expire, or to
426 * force reconnects to possibly rebalance connections across multiple servers.
427 *
428 * Typically these should be set before M_sql_connpool_start() however it is
429 * safe to change these on an active pool.
430 *
431 * \param[in] pool Initialized connection pool object
432 * \param[in] reconnect_time_s How many seconds to allow a connection to be used before a disconnection
433 * is forced. The connection will be terminated even if not idle, termination
434 * will occur when a connection is returned to the pool instead of prior to use
435 * to prevent unexpected delays. This can be used to either redistribute load
436 * after a node failure when load balancing, or to fall back to a prior host.
437 * Set to 0 for infinite, set to -1 to not change the current value. Default is 0.
438 * \param[in] max_idle_time_s Maximum amount of time a connection can have been idle to be used. Some
439 * firewalls may lose connection state after a given duration, so it may be
440 * advisable to set this to below that threshold so the connection will be
441 * forcibly terminated rather than use. The connection will be terminated
442 * before use and the consumer will attempt to grab a different connection
443 * from the pool, or start a new one if none are available. Set to 0 for infinite,
444 * set to -1 to not change the current value. Default is 0.
445 * \param[in] fallback_s Number of seconds when a connection error occurs to a host before it is
446 * eligible for "fallback". If this isn't set, the only time the first host
447 * will be re-used is if the secondary host(s) also fail. This should be used
448 * in conjunction with reconnect_time_s. Set to 0 to never fallback, or -1 to
449 * not change the current value. Not relevant for load balancing, the host will
450 * always be in the attempt pool. Default is 0.
451 */
452M_API void M_sql_connpool_set_timeouts(M_sql_connpool_t *pool, M_time_t reconnect_time_s, M_time_t max_idle_time_s, M_time_t fallback_s);
453
454
455/*! Start the connection pool and make it ready for use.
456 *
457 * At least one connection from the primary pool, and optionally the read-only pool will be
458 * started, controlled via the #M_SQL_CONNPOOL_FLAG_PRESPAWN_ALL flag.
459 *
460 * If this returns a failure, either it can be attempted to be started again, or should be
461 * destroyed with M_sql_connpool_destroy(). No other functions are eligible for use after a failed start.
462 *
463 * \note This must be called once prior to being able to use M_sql_stmt_execute() or M_sql_trans_begin(),
464 * but must be called after M_sql_connpool_add_readonly_pool() or M_sql_connpool_add_trace().
465 *
466 * \param[in] pool Initialized pool object by M_sql_connpool_create().
467 * \param[out] error Buffer to hold error message.
468 * \param[in] error_size Size of error buffer passed in.
469 * \return #M_SQL_ERROR_SUCCESS on successful readonly pool creation, otherwise one of the #M_sql_error_t errors.
470 */
471M_API M_sql_error_t M_sql_connpool_start(M_sql_connpool_t *pool, char *error, size_t error_size);
472
473
474/*! Destroy the SQL connection pool and close all open connections.
475 *
476 * All connections must be idle/unused or will return a failure.
477 *
478 * \param[in] pool Pool object to be destroyed
479 * \return #M_SQL_ERROR_SUCCESS on successful pool destruction, otherwise one of the #M_sql_error_t errors.
480 */
482
483
484/*! Count of active/connected SQL connections (but not ones that are in process of being brought online).
485 *
486 * \param[in] pool Initialized pool object
487 * \param[in] readonly M_TRUE if querying for readonly connections, M_FALSE for primary
488 *
489 * \return count of active/connected SQL connections.
490 */
491M_API size_t M_sql_connpool_active_conns(M_sql_connpool_t *pool, M_bool readonly);
492
493/*! SQL server name and version
494 *
495 * \param[in] pool Initialized pool object
496 *
497 * \return SQL server name and version
498 */
500
501/*! SQL driver display (pretty) name
502 *
503 * \param[in] pool Initialized pool object
504 *
505 * \return SQL driver pretty name
506 */
508
509/*! SQL driver internal/short name
510 *
511 * \param[in] pool Initialized pool object
512 *
513 * \return SQL driver internal/short name
514 */
516
517/*! SQL driver version (not db version)
518 *
519 * \param[in] pool Initialized pool object
520 *
521 * \return SQL driver version (not db version)
522 */
524
525/*! @} */
526
527
528/*! \addtogroup m_sql_helpers SQL Helpers
529 * \ingroup m_sql
530 *
531 * SQL Helpers for various situations
532 *
533 * @{
534 */
535
536/*! Generate a time-based + random unique id suitable for primary key use rather
537 * than using an auto-increment column.
538 *
539 * It is not recommended to use auto-increment columns for portability reasons,
540 * therefore a suitable unique id needs to be chosen that has a low probability
541 * of conflict. There is no guarantee this key is unique, so integrators
542 * should handle conflicts by regenerating the key and re-attempting the
543 * operation (even though this may be an extremely low probability).
544 *
545 * The generated key is a combination of the current timestamp in UTC and
546 * a random suffix. The reason for a timestamp prefix is some databases
547 * cannot handle purely random numbers as they cause index splits that cause
548 * exponential slowdown as the number of rows increase. This can be observed
549 * with MySQL in particular.
550 *
551 * Where possible, a 64bit (signed) column should be used for the unique id,
552 * which has a maximum length of 18 digits where all digits can contain any
553 * value. A 32bit signed integer has a maximum of 9 digits where all digits
554 * can contain any value. 32bit integers are strongly discouraged as the possibility for
555 * conflict is much higher and would limit the total number of possible rows
556 * considerably (max 99,000 rows per day, but conflicts will be highly probable
557 * over a couple of thousand rows per day).
558 *
559 * The current formats based on length are listed below:
560 * - 17-18+ digits : YYYJJJSSSSS{6-7R}
561 * - 16 digits : YYJJJSSSSS{6R}
562 * - 14-15 digits : YJJJSSSSS{5-6R}
563 * - 13 digits : YJJJSSSS{6R}
564 * - 11-12 digits : YJJJSS{6-7R}
565 * - 9-10 digits : YJJJ{5-6R}
566 * - <9 : {1-8R}
567 *
568 * Where:
569 * - Y = last digit of year
570 * - YY = last 2 digits of year
571 * - YYY = last 3 digits of year
572 * - JJJ = Julian day of year (0-365)
573 * - SSSSS = Second of day (0-86399)
574 * - SSSS = Second of day divided by 10 (0-8639) (more fine grained than alternative of HHMM 0-2359)
575 * - SS = Second of day divided by 1000 (0-86) (more fine grained than alternative of HH 0-23)
576 * - {\#R},{\#-\#R} = number of random digits
577 *
578 * \note A time prefix is used solely for the purpose of reducing database load
579 * by making the values as incremental as possible, while still having a
580 * random portion to avoid conflicts. These are not meant to be
581 * human-interpretable numbers, and formats may change in the future. These
582 * should essentially appear completely random to a human.
583 *
584 * \param[in] pool Initialized pool object
585 * \param[in] max_len Length of unique id to generate in digits. Valid range
586 * is 9-18. May return fewer digits only when the time
587 * prefix begins with zero.
588 * \return 64bit signed integer representation of usable unique id, or 0 on
589 * misuse.
590 */
591M_API M_int64 M_sql_gen_timerand_id(M_sql_connpool_t *pool, size_t max_len);
592
593
594/*! Random delay to use for a rollback to assist in preventing
595 * continual deadlocks and rollbacks.
596 *
597 * A random delay is returned in milliseconds that can be used
598 * when a rollback condition is necessary to help break deadlock
599 * loops.
600 *
601 * \param[in] pool Initialized pool object
602 * \return delay to use in milliseconds.
603 */
605
606
607/*! @} */
608
609
610
611/*! \addtogroup m_sql_query SQL Query Extension/Portability Helpers
612 * \ingroup m_sql
613 *
614 * SQL Query Extension/Portability Helpers are used to assist in ensuring queries are portable across
615 * various database servers utilizing extensions they offer.
616 *
617 * @{
618 */
619
620/*! Row lock type to append to query to lock rows returned from a select statement
621 * for a future update with in a transaction. All values must be used within a
622 * single query */
623typedef enum {
624 M_SQL_QUERY_UPDLOCK_TABLE = 1, /*!< Apply SQL-specific lock to rows in the table being updated.
625 * This must be appended immediately after every referenced table
626 * name when row locking is desired. Must be used in conjunction
627 * with a later call for #M_SQL_QUERY_UPDLOCK_QUERYEND */
628 M_SQL_QUERY_UPDLOCK_QUERYEND = 2 /*!< Apply the SQL-specific lock to the rows referenced by query, this
629 * must always be applied at the END of a query string. Must be
630 * used in conjunction with an earlier call for #M_SQL_QUERY_UPDLOCK_TABLE */
632
633
634/*! Append the SQL-server-specific row lock method to the proper point in the query
635 * to be updated by a later call within the same transaction.
636 *
637 * Row locks are intended to block conflicting select statements until the current
638 * transaction has completed. It is an optimization to assist in reducing deadlocks
639 * which force rollback and retry cycles. For some database clustering solutions,
640 * like MySQL/MariaDB with Galera, it is necessary to use to prevent lost updates since
641 * updates cross-node lack the serializable isolation level guarantees.
642 *
643 * Different databases utilize different row locking methods and the methods appear
644 * at different points in the query. Due to the complexity of SQL queries, it is not
645 * viable to offer automatic rewrite ability for such queries, and instead we provide
646 * methods for simply inserting the locking statements in a DB-specific way into your
647 * query.
648 *
649 * Locking is for the duration of an SQL transaction, so row locking can only occur
650 * within a transaction, please see M_sql_trans_begin().
651 *
652 * An example query that you want to lock the rows might look like:
653 * \code SELECT * FROM "foo" WHERE "bar" = ? \endcode
654 * For a row lock for Microsoft SQL Server, the desired query with locks would look like:
655 * \code SELECT * FROM "foo" WITH (ROWLOCK, XLOCK, HOLDLOCK) WHERE "bar" = ? \endcode
656 * For the equivalent on MySQL, it would look like this:
657 * \code SELECT * FROM "foo" WHERE "bar" = ? FOR UPDATE \endcode
658 * For PostgreSQL it may either be like MySQL, or on instances where an outer left join is used
659 * a table name must also be specified, e.g.
660 * \code SELECT * FROM "foo" WHERE "bar" = ? FOR UPDATE OF "foo" \endcode
661 *
662 * Clearly as the above example indicates, it would be undesirable to need to rewrite
663 * the query manually by detecting the database in use, using helpers makes this
664 * easier so you do not need to have SQL-server-specific logic in your own code. Converting
665 * that query above using the helpers could be done as the below:
666 * \code{.c}
667 * M_sql_stmt_t *stmt = M_sql_stmt_create();
668 * M_buf_t *query = M_buf_create();
669 * M_sql_error_t err;
670 *
671 * M_buf_add_str(query, "SELECT * FROM \"foo\"");
672 * M_sql_query_append_updlock(pool, query, M_SQL_QUERY_UPDLOCK_TABLE, NULL);
673 * M_buf_add_str(query, " WHERE \"bar\" = ?");
674 * M_sql_stmt_bind_int32(stmt, 1);
675 * M_sql_query_append_updlock(pool, query, M_SQL_QUERY_UPDLOCK_QUERYEND, NULL);
676 * M_sql_stmt_prepare_buf(stmt, query);
677 * err = M_sql_stmt_execute(pool, stmt);
678 * //...
679 * M_sql_stmt_destroy(stmt);
680 * \endcode
681 *
682 * \note At least one #M_SQL_QUERY_UPDLOCK_TABLE must be appended per query. They will
683 * be appended immediately after each table reference (SELECT FROM ... table, or
684 * JOIN table). For the same query, at the end of the query, #M_SQL_QUERY_UPDLOCK_QUERYEND
685 * must be appended.
686 *
687 * \warning Not all databases support row-lock hints and instead rely on consistency
688 * guarantees by the underlying database for the isolation method in use. If you
689 * need these guarantees, please ensure you are using the #M_SQL_ISOLATION_SERIALIZABLE
690 * isolation method as well.
691 *
692 * \param[in] pool Initialized #M_sql_connpool_t object
693 * \param[in,out] query A pointer to an already populated M_buf_t with a partial (or complete
694 * for #M_SQL_QUERY_UPDLOCK_QUERYEND) request.
695 * \param[in] type Type of sql-specific lock to append to the query.
696 * \param[in] table_name Optional. For databases that support "FOR UPDATE OF" this will specify the explicit
697 * table name to use. If NULL, then will not emit the "OF" clause. This may be necessary
698 * for left outer joins on PostgreSQL. Multiple tables may be referenced in a comma-delimited
699 * manner, if table aliases are used the alias must be referenced not the actual table name.
700 * Table names are NOT automatically quoted.
701 */
702M_API void M_sql_query_append_updlock(M_sql_connpool_t *pool, M_buf_t *query, M_sql_query_updlock_type_t type, const char *table_name);
703
704
705/*! Type of bitwise operation to perform. */
706typedef enum {
707 M_SQL_BITOP_AND = 1, /*!< Perform a bitwise AND (&) operation */
708 M_SQL_BITOP_OR = 2 /*!< Perform a bitwise OR (|) operation */
710
711
712/*! Perform a bitwise operation on the database using an SQL-server-specific format.
713 *
714 * A classic bitwise operation checking to see if a bit is set may look like the below:
715 * \code (exp1 & exp2) != 0 \endcode
716 *
717 * Or a bitwise operation, setting a bit or set of bits may look like:
718 * \code exp1 = exp1 | exp2 \endcode
719 *
720 * Some database servers take the expressions listed above exactly, however, others
721 * may require functions like BITAND() and BITOR() to accomplish the same thing.
722 *
723 * Taking an example of selecting all rows where "bar" has bit 4 (0x8) set:
724 * \code SELECT * FROM "foo" WHERE ("bar" & 8) <> 0 \endcode
725 * Might look like this:
726 * \code{.c}
727 * M_buf_t *buf = M_buf_create();
728 * M_sql_stmt_t *stmt = M_sql_stmt_create();
729 * M_sql_error_t err;
730 *
731 * M_buf_add_str(buf, "SELECT * FROM \"foo\" WHERE (");
732 * M_sql_query_append_bitop(pool, buf, M_SQL_BITOP_AND, "\"bar\"", "?");
733 * M_sql_stmt_bind_int32(stmt, 8);
734 * M_buf_add_str(buf, ") <> 0");
735 * M_sql_stmt_prepare_buf(stmt, buf);
736 * err = M_sql_stmt_execute(pool, stmt);
737 * //...
738 * M_sql_stmt_destroy(stmt);
739 * \endcode
740 *
741 * Of course, more complex things are possible as well, such as unsetting bits and
742 * setting others in a single request by embedding operations within eachother. Take
743 * the below example that keeps bits 2 (0x2) and 3 (0x4) while clearing the rest and
744 * also sets bit 4 (0x8):
745 * \code UPDATE "foo" SET "bar" = ( "bar" & 6 ) | 8; \endcode
746 * Might look like this:
747 * \code{.c}
748 * M_buf_t *buf = M_buf_create();
749 * M_sql_stmt_t *stmt = M_sql_stmt_create();
750 * M_sql_error_t err;
751 *
752 * M_buf_add_str(buf, "UPDATE \"foo\" SET \"bar\" = ");
753 *
754 * // Do inner-first ( "bar" & 6 )
755 * M_buf_t *inner = M_buf_create();
756 * M_buf_add_str(inner, "( ");
757 * M_sql_query_append_bitop(pool, inner, M_SQL_BITOP_AND, "\"bar\"", "?");
758 * M_sql_stmt_bind_int32(stmt, 6);
759 * M_buf_add_str(inner, " )");
760 *
761 * // Do outer, embedding inner
762 * M_sql_query_append_bitop(pool, buf, M_SQL_BITOP_OR, M_buf_peek(inner), "?");
763 * M_sql_stmt_bind_int32(stmt, 8);
764 * M_buf_cancel(inner); // We peeked, throw it away
765 *
766 * M_sql_stmt_prepare_buf(stmt, buf);
767 * err = M_sql_stmt_execute(pool, stmt);
768 * //...
769 * M_sql_stmt_destroy(stmt);
770 * \endcode
771 *
772 * \warning Most databases do not allow bitwise operations to be used for 'truth' values
773 * (e.g as a boolean). Instead, an integrator should compare the result to 0
774 * to turn it into a boolean operation if needed.
775 *
776 * \param[in] pool Initialized #M_sql_connpool_t object
777 * \param[in,out] query A pointer to an already populated M_buf_t with a partial request.
778 * \param[in] op Bitwise operation to perform.
779 * \param[in] exp1 Left-hand side of SQL expression.
780 * \param[in] exp2 Right-hande size of SQL expression.
781 * \return M_TRUE on success, M_FALSE on misuse
782 */
783M_API M_bool M_sql_query_append_bitop(M_sql_connpool_t *pool, M_buf_t *query, M_sql_query_bitop_t op, const char *exp1, const char *exp2);
784
785
786/*! It may be necessary to know the data type name mapping for an mstdlib datatype.
787 * This function can be used to retrieve that value. Data types may differ depending
788 * on an operation. For instance, MySQL can use VARCHAR for column creation but only
789 * CHAR for CAST operations
790 * \param[in] pool Initialized #M_sql_connpool_t object
791 * \param[in,out] query A pointer to an already populated M_buf_t with a partial request.
792 * \param[in] type mstdlib datatype
793 * \param[in] max_len Maximum length of data type if a TEXT or BINARY type.
794 * \param[in] is_cast If this datatype is used during a CAST operation.
795 */
796M_API void M_sql_query_append_datatype(M_sql_connpool_t *pool, M_buf_t *query, M_sql_data_type_t type, size_t max_len, M_bool is_cast);
797
798/*! @} */
799
800__END_DECLS
801
802#endif /* __M_SQL_H__ */
struct M_buf M_buf_t
Definition: m_buf.h:77
M_sql_connpool_flags_t
Definition: m_sql.h:338
const char * M_sql_connpool_driver_name(M_sql_connpool_t *pool)
struct M_sql_connpool M_sql_connpool_t
Definition: m_sql.h:335
M_sql_error_t M_sql_connpool_add_readonly_pool(M_sql_connpool_t *pool, const char *conn_str, size_t max_conns, char *error, size_t error_size)
M_sql_error_t M_sql_connpool_create(M_sql_connpool_t **pool, const char *driver, const char *conn_str, const char *username, const char *password, size_t max_conns, M_uint32 flags, char *error, size_t error_size)
void M_sql_connpool_set_timeouts(M_sql_connpool_t *pool, M_time_t reconnect_time_s, M_time_t max_idle_time_s, M_time_t fallback_s)
size_t M_sql_connpool_active_conns(M_sql_connpool_t *pool, M_bool readonly)
const char * M_sql_connpool_driver_version(M_sql_connpool_t *pool)
M_sql_error_t M_sql_connpool_start(M_sql_connpool_t *pool, char *error, size_t error_size)
const char * M_sql_connpool_server_version(M_sql_connpool_t *pool)
const char * M_sql_connpool_driver_display_name(M_sql_connpool_t *pool)
M_sql_error_t M_sql_connpool_destroy(M_sql_connpool_t *pool)
@ M_SQL_CONNPOOL_FLAG_NONE
Definition: m_sql.h:339
@ M_SQL_CONNPOOL_FLAG_PRESPAWN_ALL
Definition: m_sql.h:340
@ M_SQL_CONNPOOL_FLAG_NO_AUTORETRY_QUERY
Definition: m_sql.h:342
@ M_SQL_CONNPOOL_FLAG_LOAD_BALANCE
Definition: m_sql.h:348
M_bool M_sql_error_is_fatal(M_sql_error_t err)
const char * M_sql_error_string(M_sql_error_t err)
M_bool M_sql_error_is_rollback(M_sql_error_t err)
M_bool M_sql_error_is_disconnect(M_sql_error_t err)
M_sql_error_t
Definition: m_sql.h:190
M_bool M_sql_error_is_error(M_sql_error_t err)
M_sql_data_type_t
Definition: m_sql.h:256
@ M_SQL_ERROR_CONN_PARAMS
Definition: m_sql.h:202
@ M_SQL_ERROR_SUCCESS_ROW
Definition: m_sql.h:196
@ M_SQL_ERROR_CONN_BADAUTH
Definition: m_sql.h:204
@ M_SQL_ERROR_USER_BYPASS
Definition: m_sql.h:237
@ M_SQL_ERROR_CONN_DRIVERVER
Definition: m_sql.h:201
@ M_SQL_ERROR_INVALID_TYPE
Definition: m_sql.h:228
@ M_SQL_ERROR_UNSET
Definition: m_sql.h:252
@ M_SQL_ERROR_QUERY_CONSTRAINT
Definition: m_sql.h:219
@ M_SQL_ERROR_PREPARE_NOMULITQUERY
Definition: m_sql.h:210
@ M_SQL_ERROR_SUCCESS
Definition: m_sql.h:191
@ M_SQL_ERROR_CONN_FAILED
Definition: m_sql.h:203
@ M_SQL_ERROR_CONN_DRIVERLOAD
Definition: m_sql.h:200
@ M_SQL_ERROR_INUSE
Definition: m_sql.h:225
@ M_SQL_ERROR_USER_SUCCESS
Definition: m_sql.h:231
@ M_SQL_ERROR_QUERY_DEADLOCK
Definition: m_sql.h:218
@ M_SQL_ERROR_USER_FAILURE
Definition: m_sql.h:246
@ M_SQL_ERROR_CONN_LOST
Definition: m_sql.h:205
@ M_SQL_ERROR_CONN_NODRIVER
Definition: m_sql.h:199
@ M_SQL_ERROR_QUERY_WRONGNUMPARAMS
Definition: m_sql.h:214
@ M_SQL_ERROR_INVALID_USE
Definition: m_sql.h:227
@ M_SQL_ERROR_QUERY_FAILURE
Definition: m_sql.h:220
@ M_SQL_ERROR_QUERY_NOTPREPARED
Definition: m_sql.h:213
@ M_SQL_ERROR_USER_RETRY
Definition: m_sql.h:241
@ M_SQL_ERROR_PREPARE_INVALID
Definition: m_sql.h:208
@ M_SQL_ERROR_PREPARE_STRNOTBOUND
Definition: m_sql.h:209
@ M_SQL_ERROR_QUERY_PREPARE
Definition: m_sql.h:215
@ M_SQL_DATA_TYPE_UNKNOWN
Definition: m_sql.h:257
@ M_SQL_DATA_TYPE_TEXT
Definition: m_sql.h:262
@ M_SQL_DATA_TYPE_INT32
Definition: m_sql.h:260
@ M_SQL_DATA_TYPE_INT64
Definition: m_sql.h:261
@ M_SQL_DATA_TYPE_INT16
Definition: m_sql.h:259
@ M_SQL_DATA_TYPE_BINARY
Definition: m_sql.h:263
@ M_SQL_DATA_TYPE_BOOL
Definition: m_sql.h:258
M_int64 M_sql_gen_timerand_id(M_sql_connpool_t *pool, size_t max_len)
M_uint64 M_sql_rollback_delay_ms(M_sql_connpool_t *pool)
M_sql_query_bitop_t
Definition: m_sql.h:706
M_sql_query_updlock_type_t
Definition: m_sql.h:623
M_bool M_sql_query_append_bitop(M_sql_connpool_t *pool, M_buf_t *query, M_sql_query_bitop_t op, const char *exp1, const char *exp2)
void M_sql_query_append_datatype(M_sql_connpool_t *pool, M_buf_t *query, M_sql_data_type_t type, size_t max_len, M_bool is_cast)
void M_sql_query_append_updlock(M_sql_connpool_t *pool, M_buf_t *query, M_sql_query_updlock_type_t type, const char *table_name)
@ M_SQL_BITOP_AND
Definition: m_sql.h:707
@ M_SQL_BITOP_OR
Definition: m_sql.h:708
@ M_SQL_QUERY_UPDLOCK_TABLE
Definition: m_sql.h:624
@ M_SQL_QUERY_UPDLOCK_QUERYEND
Definition: m_sql.h:628
M_int64 M_time_t
Definition: m_time.h:161