Mstdlib-1.24.0
|
Enumerations | |
enum | M_sql_query_updlock_type_t { M_SQL_QUERY_UPDLOCK_TABLE = 1 , M_SQL_QUERY_UPDLOCK_QUERYEND = 2 } |
enum | M_sql_query_bitop_t { M_SQL_BITOP_AND = 1 , M_SQL_BITOP_OR = 2 } |
Functions | |
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_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) |
SQL Query Extension/Portability Helpers are used to assist in ensuring queries are portable across various database servers utilizing extensions they offer.
Row lock type to append to query to lock rows returned from a select statement for a future update with in a transaction. All values must be used within a single query
Enumerator | |
---|---|
M_SQL_QUERY_UPDLOCK_TABLE | Apply SQL-specific lock to rows in the table being updated. This must be appended immediately after every referenced table name when row locking is desired. Must be used in conjunction with a later call for M_SQL_QUERY_UPDLOCK_QUERYEND |
M_SQL_QUERY_UPDLOCK_QUERYEND | Apply the SQL-specific lock to the rows referenced by query, this must always be applied at the END of a query string. Must be used in conjunction with an earlier call for M_SQL_QUERY_UPDLOCK_TABLE |
enum M_sql_query_bitop_t |
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 | ||
) |
Append the SQL-server-specific row lock method to the proper point in the query to be updated by a later call within the same transaction.
Row locks are intended to block conflicting select statements until the current transaction has completed. It is an optimization to assist in reducing deadlocks which force rollback and retry cycles. For some database clustering solutions, like MySQL/MariaDB with Galera, it is necessary to use to prevent lost updates since updates cross-node lack the serializable isolation level guarantees.
Different databases utilize different row locking methods and the methods appear at different points in the query. Due to the complexity of SQL queries, it is not viable to offer automatic rewrite ability for such queries, and instead we provide methods for simply inserting the locking statements in a DB-specific way into your query.
Locking is for the duration of an SQL transaction, so row locking can only occur within a transaction, please see M_sql_trans_begin().
An example query that you want to lock the rows might look like:
For a row lock for Microsoft SQL Server, the desired query with locks would look like:
For the equivalent on MySQL, it would look like this:
For PostgreSQL it may either be like MySQL, or on instances where an outer left join is used a table name must also be specified, e.g.
Clearly as the above example indicates, it would be undesirable to need to rewrite the query manually by detecting the database in use, using helpers makes this easier so you do not need to have SQL-server-specific logic in your own code. Converting that query above using the helpers could be done as the below:
[in] | pool | Initialized M_sql_connpool_t object |
[in,out] | query | A pointer to an already populated M_buf_t with a partial (or complete for M_SQL_QUERY_UPDLOCK_QUERYEND) request. |
[in] | type | Type of sql-specific lock to append to the query. |
[in] | table_name | Optional. For databases that support "FOR UPDATE OF" this will specify the explicit table name to use. If NULL, then will not emit the "OF" clause. This may be necessary for left outer joins on PostgreSQL. Multiple tables may be referenced in a comma-delimited manner, if table aliases are used the alias must be referenced not the actual table name. Table names are NOT automatically quoted. |
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 | ||
) |
Perform a bitwise operation on the database using an SQL-server-specific format.
A classic bitwise operation checking to see if a bit is set may look like the below:
Or a bitwise operation, setting a bit or set of bits may look like:
Some database servers take the expressions listed above exactly, however, others may require functions like BITAND() and BITOR() to accomplish the same thing.
Taking an example of selecting all rows where "bar" has bit 4 (0x8) set:
Might look like this:
Of course, more complex things are possible as well, such as unsetting bits and setting others in a single request by embedding operations within eachother. Take the below example that keeps bits 2 (0x2) and 3 (0x4) while clearing the rest and also sets bit 4 (0x8):
Might look like this:
[in] | pool | Initialized M_sql_connpool_t object |
[in,out] | query | A pointer to an already populated M_buf_t with a partial request. |
[in] | op | Bitwise operation to perform. |
[in] | exp1 | Left-hand side of SQL expression. |
[in] | exp2 | Right-hande size of SQL expression. |
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 | ||
) |
It may be necessary to know the data type name mapping for an mstdlib datatype. This function can be used to retrieve that value. Data types may differ depending on an operation. For instance, MySQL can use VARCHAR for column creation but only CHAR for CAST operations
[in] | pool | Initialized M_sql_connpool_t object |
[in,out] | query | A pointer to an already populated M_buf_t with a partial request. |
[in] | type | mstdlib datatype |
[in] | max_len | Maximum length of data type if a TEXT or BINARY type. |
[in] | is_cast | If this datatype is used during a CAST operation. |