src/evsql.h
branchnew-evsql
changeset 52 f5037572c326
parent 51 c65d0f4c3bff
child 53 0d6e07f4c9a1
equal deleted inserted replaced
51:c65d0f4c3bff 52:f5037572c326
     1 #ifndef EVSQL_H
     1 #ifndef EVSQL_H
     2 #define EVSQL_H
     2 #define EVSQL_H
     3 
     3 
     4 /**
     4 /**
       
     5  * @file src/evsql.h
       
     6  *
     5  * A SQL library designed for use with libevent and PostgreSQL's libpq. Provides support for queueing non-transactional
     7  * A SQL library designed for use with libevent and PostgreSQL's libpq. Provides support for queueing non-transactional
     6  * requests, transaction support, parametrized queries and result iteration.
     8  * requests, transaction support, parametrized queries and result iteration.
     7  *
     9  *
     8  * Currently, the API does not expose the underlying libpq data structures, but since it is currently the only
    10  * Currently, the API does not expose the underlying libpq data structures, but since it is currently the only
     9  * underlying implementation, there is no garuntee that the same API will actually work with other databases' interface
    11  * underlying implementation, there is no guarantee that the same API will actually work with other databases' interface
    10  * libraries...
    12  * libraries...
    11  */
    13  *
    12 
    14  * The order of function calls and callbacks goes something like this:
       
    15  *
       
    16  *  -   evsql_new_pq 
       
    17  *
       
    18  *  -   evsql_trans 
       
    19  *      -   evsql_trans_abort
       
    20  *      -   evsql_trans_error_cb
       
    21  *      -   evsql_trans_ready_cb
       
    22  *
       
    23  *  -   evsql_query, evsql_params_* + evsql_query_params, evsql_query_exec 
       
    24  *      -   evsql_query_abort
       
    25  *      -   evsql_query_cb
       
    26  *          -   evsql_result_*
       
    27  *          -   evsql_result_free
       
    28  *
       
    29  *  -   evsql_trans_commit
       
    30  *      -   evsql_trans_done_cb
       
    31  *
       
    32  */
       
    33 
       
    34 /**
       
    35  * System includes
       
    36  */
    13 #include <stdint.h>
    37 #include <stdint.h>
    14 #include <stdbool.h>
    38 #include <stdbool.h>
    15 #include <event2/event.h>
    39 #include <event2/event.h>
    16 
    40 
    17 /**
    41 /**
    92 
   116 
    93 /**
   117 /**
    94  * Value for use with EVSQL_TYPE_BINARY, this just a non-NUL-terminated char* and an explicit length
   118  * Value for use with EVSQL_TYPE_BINARY, this just a non-NUL-terminated char* and an explicit length
    95  */
   119  */
    96 struct evsql_item_binary {
   120 struct evsql_item_binary {
       
   121     /** The binary data */
    97     const char *ptr;
   122     const char *ptr;
       
   123 
       
   124     /** Number of bytes pointed to by ptr */
    98     size_t len;
   125     size_t len;
    99 };
   126 };
   100 
   127 
   101 /**
   128 /**
   102  * Metadata about the format and type of an item, this does not hold any actual value.
   129  * Metadata about the format and type of an item, this does not hold any actual value.
   120 
   147 
   121 /**
   148 /**
   122  * An union to provide storage for the values of small types
   149  * An union to provide storage for the values of small types
   123  */
   150  */
   124 union evsql_item_value {
   151 union evsql_item_value {
       
   152     /** 16-bit unsigned integer */
   125     uint16_t uint16;
   153     uint16_t uint16;
       
   154 
       
   155     /** 32-bit unsigned integer */
   126     uint32_t uint32;
   156     uint32_t uint32;
       
   157 
       
   158     /** 64-bit unsigned integer */
   127     uint64_t uint64;
   159     uint64_t uint64;
   128 };
   160 };
   129 
   161 
   130 /**
   162 /**
   131  * A generic structure containing the type and value of a query parameter or a result field.
   163  * A generic structure containing the type and value of a query parameter or a result field.
   189 
   221 
   190 /**
   222 /**
   191  * Result layout metadata. This contains the stucture needed to decode result rows.
   223  * Result layout metadata. This contains the stucture needed to decode result rows.
   192  */
   224  */
   193 struct evsql_result_info {
   225 struct evsql_result_info {
   194     // XXX: make up something useful to stick here
   226     /** XXX: make up something useful to stick here */
   195     int _unused;
   227     int _unused;
   196 
   228 
   197     /**
   229     /**
   198      * A variable-length array of the item_info column types.
   230      * A variable-length array of the item_info column types.
   199      */
   231      */
   200     struct evsql_item_info columns[];
   232     struct evsql_item_info columns[];
   201 };
   233 };
   202 
   234 
   203 /**
   235 /**
   204  * Magic macros for defining param/result info -lists
   236  * Magic macros for defining param/result info -lists
       
   237  *
       
   238  * @name EVSQL_TYPE/PARAM_*
       
   239  * @{
   205  */
   240  */
   206 
   241 
   207 /**
   242 /**
   208  * A `struct evsql_item_info` initializer, using FMT_BINARY and the given EVSQL_TYPE_ -suffix.
   243  * A `struct evsql_item_info` initializer, using FMT_BINARY and the given EVSQL_TYPE_ -suffix.
   209  *
   244  *
   233 #define EVSQL_PARAMS(result_fmt)            { result_fmt, 
   268 #define EVSQL_PARAMS(result_fmt)            { result_fmt, 
   234 #define EVSQL_PARAM(typenam)                    { EVSQL_TYPE(typenam) }
   269 #define EVSQL_PARAM(typenam)                    { EVSQL_TYPE(typenam) }
   235 #define EVSQL_PARAMS_END                        { EVSQL_TYPE_END } \
   270 #define EVSQL_PARAMS_END                        { EVSQL_TYPE_END } \
   236                                               } // <<<
   271                                               } // <<<
   237 
   272 
       
   273 // @}
       
   274 
       
   275 /**
       
   276  * Callback definitions
       
   277  *
       
   278  * @name evsql_*_cb
       
   279  *
       
   280  * @{
       
   281  */
   238 
   282 
   239 /**
   283 /**
   240  * Callback for handling query results.
   284  * Callback for handling query results.
   241  *
   285  *
   242  * The query has completed, either succesfully or unsuccesfully.
   286  * The query has completed, either succesfully or unsuccesfully.
   293  *
   337  *
   294  * @see evsql_trans
   338  * @see evsql_trans
   295  * @see evsql_trans_commit
   339  * @see evsql_trans_commit
   296  */
   340  */
   297 typedef void (*evsql_trans_done_cb)(struct evsql_trans *trans, void *arg);
   341 typedef void (*evsql_trans_done_cb)(struct evsql_trans *trans, void *arg);
       
   342 
       
   343 // @}
   298 
   344 
   299 /**
   345 /**
   300  * Create a new PostgreSQL/libpq (evpq) -based evsql using the given conninfo.
   346  * Create a new PostgreSQL/libpq (evpq) -based evsql using the given conninfo.
   301  *
   347  *
   302  * The given conninfo must stay valid for the duration of the evsql's lifetime.
   348  * The given conninfo must stay valid for the duration of the evsql's lifetime.
   313     evsql_error_cb error_fn, 
   359     evsql_error_cb error_fn, 
   314     void *cb_arg
   360     void *cb_arg
   315 );
   361 );
   316 
   362 
   317 /**
   363 /**
       
   364  * Query API
       
   365  *
       
   366  * @name evsql_query_*
       
   367  * @{
       
   368  */
       
   369 
       
   370 /**
       
   371  * Queue the given query for execution.
       
   372  *
       
   373  * If a trans is given (i.e. not NULL), then the transaction must be idle, and the query will be executed in that
       
   374  * transaction's context. Otherwise, the query will be executed without a transaction using an idle connection, or
       
   375  * enqueued for later execution.
       
   376  *
       
   377  * Once the query is complete (got a result, got an error, the connection failed), then the query_cb will be called.
       
   378  * The callback can use the evsql_result_* functions to manipulate it.
       
   379  *
       
   380  * The returned evsql_query handle can be passed to evsql_query_abort at any point before query_fn being called. 
       
   381  *
       
   382  * @param evsql the context handle from evsql_new_*
       
   383  * @param trans the optional transaction handle from evsql_trans
       
   384  * @param command the raw SQL command itself
       
   385  * @param query_fn the query_cb to call once the query is complete
       
   386  * @param cb_arg the void* passed to the above
       
   387  * @return the evsql_query handle that can be used to abort the query
       
   388  */
       
   389 struct evsql_query *evsql_query (struct evsql *evsql, struct evsql_trans *trans, const char *command, evsql_query_cb query_fn, void *cb_arg);
       
   390 
       
   391 /**
       
   392  * Execute the given SQL query using the list of parameter types/values given via evsql_query_params.
       
   393  *
       
   394  * Use the EVSQL_PARAMS macros to declare the struct, and the evsql_param_* functions to populate the values.
       
   395  *
       
   396  * See evsql_query for more info about behaviour.
       
   397  *
       
   398  * XXX: explain SQL param syntax...
       
   399  *
       
   400  * @param evsql the context handle from evsql_new_*
       
   401  * @param trans the optional transaction handle from evsql_trans
       
   402  * @param command the SQL command to bind the parameters to
       
   403  * @param params the parameter types and values
       
   404  * @param query_fn the query_cb to call once the query is complete
       
   405  * @param cb_arg the void* passed to the above
       
   406  * @see evsql_query
       
   407  */
       
   408 struct evsql_query *evsql_query_params (struct evsql *evsql, struct evsql_trans *trans, 
       
   409     const char *command, const struct evsql_query_params *params, 
       
   410     evsql_query_cb query_fn, void *cb_arg
       
   411 );
       
   412 
       
   413 /**
       
   414  * Execute the given query_info's SQL query with the values given as variable arguments, using the evsql_query_info to
       
   415  * resolve the types.
       
   416  *
       
   417  * See evsql_query for more info about behaviour.
       
   418  *
       
   419  * @param evsql the context handle from evsql_new_*
       
   420  * @param trans the optional transaction handle from evsql_trans
       
   421  * @param query_info the SQL query information
       
   422  * @param query_fn the query_cb to call once the query is complete
       
   423  * @param cb_arg the void* passed to the above
       
   424  * @see evsql_query
       
   425  */
       
   426 struct evsql_query *evsql_query_exec (struct evsql *evsql, struct evsql_trans *trans, 
       
   427     const struct evsql_query_info *query_info,
       
   428     evsql_query_cb query_fn, void *cb_arg,
       
   429     ...
       
   430 );
       
   431 
       
   432 /**
       
   433  * Abort a query returned by evsql_query_* that has not yet completed (query_fn has not been called yet).
       
   434  *
       
   435  * The actual query itself may or may not be aborted (and hence may or may not be executed on the server), but query_fn
       
   436  * will not be called anymore, and the query will dispose of itself and any results returned.
       
   437  *
       
   438  * If the query is part of a transaction, then trans must be given, and the query must be the query that is currently
       
   439  * executing on that trans. The transaction's ready_fn will be called once the query has been aborted and the
       
   440  * transaction is now idle again.
       
   441  *
       
   442  * @param trans if the query is part of a transaction, then it MUST be given here
       
   443  * @param query the in-progress query to abort
       
   444  */
       
   445 void evsql_query_abort (struct evsql_trans *trans, struct evsql_query *query);
       
   446 
       
   447 /**
       
   448  * Print out a textual dump of the given query and parameters using DEBUG
       
   449  *
       
   450  * @param sql the SQL query command
       
   451  * @param params the list of parameter types and values
       
   452  */
       
   453 void evsql_query_debug (const char *sql, const struct evsql_query_params *params);
       
   454 
       
   455 // @}
       
   456 
       
   457 /**
       
   458  * Transaction API
       
   459  *
       
   460  * @name evsql_trans_*
       
   461  * @{
       
   462  */
       
   463 
       
   464 /**
   318  * Create a new transaction.
   465  * Create a new transaction.
   319  *
   466  *
   320  * A transaction will be allocated its own connection, and the "BEGIN TRANSACTION ..." query will be sent (use the
   467  * A transaction will be allocated its own connection, and the "BEGIN TRANSACTION ..." query will be sent (use the
   321  * trans_type argument to specify this). 
   468  * trans_type argument to specify this). 
   322  *
   469  *
   327  * will NOT be called), and the given trans_error_cb will be called. Note that this includes some, but not all,
   474  * will NOT be called), and the given trans_error_cb will be called. Note that this includes some, but not all,
   328  * cases where evsql_query_* returns an error.
   475  * cases where evsql_query_* returns an error.
   329  *
   476  *
   330  * Once you are done with the transaction, call either evsql_trans_commit or evsql_trans_abort.
   477  * Once you are done with the transaction, call either evsql_trans_commit or evsql_trans_abort.
   331  *
   478  *
       
   479  * @ingroup evsql_trans_*
   332  * @param evsql the context handle from evsql_new_*
   480  * @param evsql the context handle from evsql_new_*
   333  * @param type the type of transaction to create
   481  * @param type the type of transaction to create
   334  * @param error_fn the trans_error_cb to call if this transaction fails
   482  * @param error_fn the trans_error_cb to call if this transaction fails
   335  * @param ready_fn the trans_ready_cb to call once this transaction is ready for use
   483  * @param ready_fn the trans_ready_cb to call once this transaction is ready for use
   336  * @param done_fn the trans_done_cb to call once this transaction has been commmited
   484  * @param done_fn the trans_done_cb to call once this transaction has been commmited
   343     evsql_trans_done_cb done_fn, 
   491     evsql_trans_done_cb done_fn, 
   344     void *cb_arg
   492     void *cb_arg
   345 );
   493 );
   346 
   494 
   347 /**
   495 /**
   348  * Queue the given query for execution.
       
   349  *
       
   350  * If a trans is given (i.e. not NULL), then the transaction must be idle, and the query will be executed in that
       
   351  * transaction's context. Otherwise, the query will be executed without a transaction using an idle connection, or
       
   352  * enqueued for later execution.
       
   353  *
       
   354  * Once the query is complete (got a result, got an error, the connection failed), then the query_cb will be called.
       
   355  * The callback can use the evsql_result_* functions to manipulate it.
       
   356  *
       
   357  * The returned evsql_query handle can be passed to evsql_query_abort at any point before query_fn being called. 
       
   358  *
       
   359  * @param evsql the context handle from evsql_new_*
       
   360  * @param trans the optional transaction handle from evsql_trans
       
   361  * @param command the raw SQL command itself
       
   362  * @param query_fn the query_cb to call once the query is complete
       
   363  * @param cb_arg the void* passed to the above
       
   364  * @return the evsql_query handle that can be used to abort the query
       
   365  */
       
   366 struct evsql_query *evsql_query (struct evsql *evsql, struct evsql_trans *trans, const char *command, evsql_query_cb query_fn, void *cb_arg);
       
   367 
       
   368 /**
       
   369  * Execute the given SQL query using the list of parameter types/values given via evsql_query_params.
       
   370  *
       
   371  * Use the EVSQL_PARAMS macros to declare the struct, and the evsql_param_* functions to populate the values.
       
   372  *
       
   373  * See evsql_query for more info about behaviour.
       
   374  *
       
   375  * XXX: explain SQL param syntax...
       
   376  *
       
   377  * @param command the SQL command to bind the parameters to
       
   378  * @param params the parameter types and values
       
   379  * @see evsql_query
       
   380  */
       
   381 struct evsql_query *evsql_query_params (struct evsql *evsql, struct evsql_trans *trans, 
       
   382     const char *command, const struct evsql_query_params *params, 
       
   383     evsql_query_cb query_fn, void *cb_arg
       
   384 );
       
   385 
       
   386 /**
       
   387  * Execute the given query_info's SQL query with the values given as variable arguments, using the evsql_query_info to
       
   388  * resolve the types.
       
   389  *
       
   390  * See evsql_query for more info about behaviour.
       
   391  *
       
   392  * @param query_info the SQL query information
       
   393  * @see evsql_query
       
   394  */
       
   395 struct evsql_query *evsql_query_exec (struct evsql *evsql, struct evsql_trans *trans, 
       
   396     const struct evsql_query_info *query_info,
       
   397     evsql_query_cb query_fn, void *cb_arg,
       
   398     ...
       
   399 );
       
   400 
       
   401 /**
       
   402  * Abort a query returned by evsql_query_* that has not yet completed (query_fn has not been called yet).
       
   403  *
       
   404  * The actual query itself may or may not be aborted (and hence may or may not be executed on the server), but query_fn
       
   405  * will not be called anymore, and the query will dispose of itself and any results returned.
       
   406  *
       
   407  * If the query is part of a transaction, then trans must be given, and the query must be the query that is currently
       
   408  * executing on that trans. The transaction's ready_fn will be called once the query has been aborted and the
       
   409  * transaction is now idle again.
       
   410  *
       
   411  * @param trans if the query is part of a transaction, then it MUST be given here
       
   412  * @param query the in-progress query to abort
       
   413  */
       
   414 void evsql_query_abort (struct evsql_trans *trans, struct evsql_query *query);
       
   415 
       
   416 /**
       
   417  * Commit a transaction using "COMMIT TRANSACTION".
   496  * Commit a transaction using "COMMIT TRANSACTION".
   418  *
   497  *
   419  * The transaction must be idle, just like for evsql_query. Once the transaction has been commited, the transaction's
   498  * The transaction must be idle, just like for evsql_query. Once the transaction has been commited, the transaction's
   420  * done_fn will be called, after which the transaction must not be used anymore.
   499  * done_fn will be called, after which the transaction must not be used anymore.
   421  *
   500  *
   441  * @param trans the transaction from evsql_trans to abort
   520  * @param trans the transaction from evsql_trans to abort
   442  * @see evsql_trans
   521  * @see evsql_trans
   443  */
   522  */
   444 void evsql_trans_abort (struct evsql_trans *trans);
   523 void evsql_trans_abort (struct evsql_trans *trans);
   445 
   524 
   446 // @{
       
   447 /**
       
   448  * Transaction-handling functions
       
   449  */
       
   450 
       
   451 /** 
   525 /** 
   452  * Retrieve the transaction-specific error message from the underlying engine.
   526  * Retrieve the transaction-specific error message from the underlying engine.
   453  *
   527  *
   454  * Intended to be called from trans_error_cb
   528  * Intended to be called from trans_error_cb
   455  */
   529  */
   456 const char *evsql_trans_error (struct evsql_trans *trans);
   530 const char *evsql_trans_error (struct evsql_trans *trans);
   457 
   531 
   458 // @}
   532 // @}
   459 
   533 
   460 // @{
       
   461 /**
   534 /**
   462  * Parameter-building functions.
   535  * Parameter-building functions.
   463  *
   536  *
   464  * These manipulate the value of the given parameter index.
   537  * These manipulate the value of the given parameter index.
       
   538  *
       
   539  * @name evsql_param_*
       
   540  * @{
   465  */
   541  */
   466 int evsql_param_binary (struct evsql_query_params *params, size_t param, const char *ptr, size_t len);
   542 int evsql_param_binary (struct evsql_query_params *params, size_t param, const char *ptr, size_t len);
   467 int evsql_param_string (struct evsql_query_params *params, size_t param, const char *ptr);
   543 int evsql_param_string (struct evsql_query_params *params, size_t param, const char *ptr);
   468 int evsql_param_uint16 (struct evsql_query_params *params, size_t param, uint16_t uval);
   544 int evsql_param_uint16 (struct evsql_query_params *params, size_t param, uint16_t uval);
   469 int evsql_param_uint32 (struct evsql_query_params *params, size_t param, uint32_t uval);
   545 int evsql_param_uint32 (struct evsql_query_params *params, size_t param, uint32_t uval);
   470 int evsql_param_null   (struct evsql_query_params *params, size_t param);
   546 int evsql_param_null   (struct evsql_query_params *params, size_t param);
   471 int evsql_params_clear (struct evsql_query_params *params);
   547 int evsql_params_clear (struct evsql_query_params *params);
   472 
   548 
   473 // @}
   549 // @}
   474 
   550 
   475 // @{
       
   476 /**
       
   477  * Query-handling functions
       
   478  */
       
   479 
       
   480 /**
       
   481  * Print out a textual dump of the given query and parameters using DEBUG
       
   482  */
       
   483 void evsql_query_debug (const char *sql, const struct evsql_query_params *params);
       
   484 
       
   485 // @}
       
   486 
       
   487 // @{
       
   488 /**
   551 /**
   489  * Result-handling functions
   552  * Result-handling functions
       
   553  *
       
   554  * @name evsql_result_*
       
   555  * @{
   490  */
   556  */
   491 
   557 
   492 /**
   558 /**
   493  * Check the result for errors. Intended for use with non-data queries, i.e. CREATE, etc.
   559  * Check the result for errors. Intended for use with non-data queries, i.e. CREATE, etc.
   494  *
   560  *
   606  * @param nullok when true and the field value is NULL, *ptr and *size are not modified, otherwise NULL means an error
   672  * @param nullok when true and the field value is NULL, *ptr and *size are not modified, otherwise NULL means an error
   607  * @return zero on success, <0 on error
   673  * @return zero on success, <0 on error
   608  */
   674  */
   609 int evsql_result_string (const struct evsql_result *res, size_t row, size_t col, const char **ptr, int nullok);
   675 int evsql_result_string (const struct evsql_result *res, size_t row, size_t col, const char **ptr, int nullok);
   610 
   676 
   611 // @{
       
   612 /**
   677 /**
   613  * Use evsql_result_binary to read a binary field value, and then convert it using ntoh[slq], storing the value in
   678  * Use evsql_result_binary to read a binary field value, and then convert it using ntoh[slq], storing the value in
   614  * *val.
   679  * *val.
   615  *
   680  *
   616  * The given row/col must be within bounds as returned by evsql_result_rows/cols.
   681  * The given row/col must be within bounds as returned by evsql_result_rows/cols.
   617  *
   682  *
   618  * @param res the result handle passed to query_cb
   683  * @param res the result handle passed to query_cb
   619  * @param row the row index to access
   684  * @param row the row index to access
   620  * @param col the column index to access
   685  * @param col the column index to access
   621  * @param val where to store the decoded value
   686  * @param uval where to store the decoded value
   622  * @param nullok when true and the field value is NULL, *ptr and *size are not modified, otherwise NULL means an error
   687  * @param nullok when true and the field value is NULL, *ptr and *size are not modified, otherwise NULL means an error
   623  * @return zero on success, <0 on error
   688  * @return zero on success, <0 on error
   624  */
   689  */
   625 int evsql_result_uint16 (const struct evsql_result *res, size_t row, size_t col, uint16_t *uval, int nullok);
   690 int evsql_result_uint16 (const struct evsql_result *res, size_t row, size_t col, uint16_t *uval, int nullok);
   626 int evsql_result_uint32 (const struct evsql_result *res, size_t row, size_t col, uint32_t *uval, int nullok);
   691 int evsql_result_uint32 (const struct evsql_result *res, size_t row, size_t col, uint32_t *uval, int nullok);
   627 int evsql_result_uint64 (const struct evsql_result *res, size_t row, size_t col, uint64_t *uval, int nullok);
   692 int evsql_result_uint64 (const struct evsql_result *res, size_t row, size_t col, uint64_t *uval, int nullok);
   628 
   693 
       
   694 /**
       
   695  * Every result handle passed to query_cb MUST be released by the user, using this function.
       
   696  *
       
   697  * @param res the result handle passed to query_cb
       
   698  */
       
   699 void evsql_result_free (struct evsql_result *res);
       
   700 
   629 // @}
   701 // @}
   630 
   702 
   631 /**
   703 /**
   632  * Every result handle passed to query_cb MUST be released by the user, using this function.
       
   633  *
       
   634  * @param res the result handle passed to query_cb
       
   635  */
       
   636 void evsql_result_free (struct evsql_result *res);
       
   637 
       
   638 // @}
       
   639 
       
   640 /**
       
   641  * Close a connection. Callbacks for waiting queries will not be run.
   704  * Close a connection. Callbacks for waiting queries will not be run.
   642  *
   705  *
   643  * XXX: not implemented yet.
   706  * XXX: not implemented yet.
   644  *
   707  *
       
   708  * @ingroup evsql_*
   645  * @param evsql the context handle from evsql_new_*
   709  * @param evsql the context handle from evsql_new_*
   646  */
   710  */
   647 void evsql_close (struct evsql *evsql);
   711 void evsql_close (struct evsql *evsql);
   648 
   712 
   649 #endif /* EVSQL_H */
   713 #endif /* EVSQL_H */