src/evsql.h
author Tero Marttila <terom@fixme.fi>
Sat, 13 Dec 2008 20:58:27 +0200
branchnew-evsql
changeset 55 0b92d553400a
parent 54 7dc8ff496da1
permissions -rw-r--r--
evsql: more improvements
     1 #ifndef EVSQL_H
     2 #define EVSQL_H
     3 
     4 /**
     5  * @file src/evsql.h
     6  *
     7  * A SQL library designed for use with libevent and PostgreSQL's libpq. Provides support for queueing non-transactional
     8  * requests, transaction support, parametrized queries and result iteration.
     9  *
    10  * Currently, the API does not expose the underlying libpq data structures, but since it is currently the only
    11  * underlying implementation, there is no guarantee that the same API will actually work with other databases' interface
    12  * libraries...
    13  *
    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(), \ref evsql_param_ + evsql_query_params(), evsql_query_exec()
    24  *      -   evsql_query_abort()
    25  *      -   evsql_query_cb()
    26  *          -   \ref evsql_result_
    27  *          -   evsql_result_free()
    28  *
    29  *  -   evsql_trans_commit()
    30  *      -   evsql_trans_done_cb()
    31  *
    32  */
    33 
    34 /**
    35  * System includes
    36  */
    37 #include <stdint.h>
    38 #include <stdbool.h>
    39 #include <event2/event.h>
    40 
    41 /**
    42  * For err_t.
    43  */
    44 #include "lib/err.h"
    45 
    46 /**
    47  * @struct evsql
    48  *
    49  * The generic session handle used to manage a single "database connector" with multiple queries/transactions.
    50  *
    51  * @see \ref evsql_
    52  */
    53 struct evsql;
    54 
    55 /**
    56  * @struct evsql_trans
    57  *
    58  * Opaque transaction handle returned by evsql_trans() and used for the \ref evsql_query_ functions
    59  *
    60  * @see \ref evsql_trans_
    61  */
    62 struct evsql_trans;
    63 
    64 /**
    65  * @struct evsql_query
    66  *
    67  * Opaque query handle returned by the \ref evsql_query_ functions and used for evsql_query_abort()
    68  *
    69  * @see \ref evsql_query_
    70  */
    71 struct evsql_query;
    72 
    73 /**
    74  * @struct evsql_result
    75  *
    76  * Opaque result handle received by evsql_query_cb(), and used with the \ref evsql_result_ functions
    77  *
    78  * @see evsql_query_cb
    79  * @see \ref evsql_result_
    80  */
    81 struct evsql_result;
    82 
    83 /**
    84  * Various transaction isolation levels for conveniance
    85  *
    86  * @see evsql_trans
    87  */
    88 enum evsql_trans_type {
    89     EVSQL_TRANS_DEFAULT,
    90     EVSQL_TRANS_SERIALIZABLE,
    91     EVSQL_TRANS_REPEATABLE_READ,
    92     EVSQL_TRANS_READ_COMMITTED,
    93     EVSQL_TRANS_READ_UNCOMMITTED,
    94 };
    95 
    96 /**
    97  * An item can be in different formats, the classical text-based format (i.e. snprintf "1234") or a more low-level
    98  * binary format (i.e uint16_t 0x04F9 in network-byte order).
    99  */
   100 enum evsql_item_format {
   101     /** Format values as text strings */
   102     EVSQL_FMT_TEXT,
   103 
   104     /** Type-specific binary encoding */
   105     EVSQL_FMT_BINARY,
   106 };
   107 
   108 /**
   109  * An item has a specific type, these correspond somewhat to the native database types.
   110  */
   111 enum evsql_item_type {
   112     /** End marker, zero */
   113     EVSQL_TYPE_INVALID,
   114     
   115     /** A SQL NULL */
   116     EVSQL_TYPE_NULL_,
   117     
   118     /** A `struct evsql_item_binary` */
   119     EVSQL_TYPE_BINARY,
   120 
   121     /** A NUL-terminated char* */
   122     EVSQL_TYPE_STRING,
   123 
   124     /** A uint16_t value */
   125     EVSQL_TYPE_UINT16,
   126 
   127     /** A uint32_t value */
   128     EVSQL_TYPE_UINT32,
   129 
   130     /** A uint64_t value */
   131     EVSQL_TYPE_UINT64,
   132 
   133     EVSQL_TYPE_MAX
   134 };
   135 
   136 /**
   137  * Value for use with EVSQL_TYPE_BINARY, this just a non-NUL-terminated char* and an explicit length
   138  */
   139 struct evsql_item_binary {
   140     /** The binary data */
   141     const char *ptr;
   142 
   143     /** Number of bytes pointed to by ptr */
   144     size_t len;
   145 };
   146 
   147 /**
   148  * Metadata about the format and type of an item, this does not hold any actual value.
   149  */
   150 struct evsql_item_info {
   151     /** The format */
   152     enum evsql_item_format format;
   153     
   154     /** The type type */
   155     enum evsql_item_type type;
   156 
   157     /** Various flags */
   158     struct evsql_item_flags {
   159         /** The value may be NULL @see evsql_result_next */
   160         bool null_ok : 1;
   161     } flags;
   162 };
   163 
   164 /**
   165  * An union to provide storage for the values of small types
   166  *
   167  * @see evsql_item
   168  */
   169 union evsql_item_value {
   170     /** 16-bit unsigned integer */
   171     uint16_t uint16;
   172 
   173     /** 32-bit unsigned integer */
   174     uint32_t uint32;
   175 
   176     /** 64-bit unsigned integer */
   177     uint64_t uint64;
   178 };
   179 
   180 /**
   181  * A generic structure containing the type and value of a query parameter or a result field.
   182  *
   183  * @see evsql_query_info
   184  * @see evsql_query_params
   185  * @see evsql_result_info
   186  */
   187 struct evsql_item {
   188     /** The "header" containing the type and format */
   189     struct evsql_item_info info;
   190 
   191     /**
   192      * Pointer to the raw databytes. 
   193      * Set to NULL for SQL NULLs, otherwise &value or an external buf 
   194      */
   195     const char *bytes;
   196 
   197     /**
   198      * Size of the byte array pointed to by bytes, zero for EVSQL_FMT_TEXT data.
   199      */
   200     size_t length;
   201 
   202     /**
   203      * Inline storage for small values
   204      */
   205     union evsql_item_value value;
   206     
   207     /** Internal flags */
   208     struct {
   209         /**
   210          * The item has a value stored in `value`
   211          */
   212         bool has_value : 1;
   213     } flags;
   214 };
   215 
   216 /**
   217  * Query meta-info, similar to a prepared statement.
   218  *
   219  * Contains the literal SQL query and the types of the parameters, but no more.
   220  *
   221  * @see evsql_query_exec
   222  */
   223 struct evsql_query_info {
   224     /** The SQL query itself */
   225     const char *sql;
   226 
   227     /** 
   228      * A variable-length array of the item_info parameters, terminated by an EVSQL_TYPE_INVALID entry.
   229      */
   230     struct evsql_item_info params[];
   231 };
   232 
   233 /**
   234  * Contains the query parameter types and their actual values
   235  *
   236  * @see evsql_query_params
   237  */
   238 struct evsql_query_params {
   239     /** Requested result format for this query. XXX: move elsewhere */
   240     enum evsql_item_format result_format;
   241     
   242     /**
   243      * A variable-length array of the item parameter-values, terminated by an EVSQL_TYPE_INVALID entry.
   244      */
   245     struct evsql_item list[];
   246 };
   247 
   248 /**
   249  * Result layout metadata. This contains the stucture needed to decode result rows.
   250  *
   251  * @see evsql_result_begin
   252  */
   253 struct evsql_result_info {
   254     /** XXX: make up something useful to stick here */
   255     int _unused;
   256 
   257     /**
   258      * A variable-length array of the item_info column types.
   259      */
   260     struct evsql_item_info columns[];
   261 };
   262 
   263 /**
   264  * Magic macros for defining param/result info -lists
   265  *  
   266  * @code
   267  *  static struct evsql_query_params params = EVSQL_PARAMS(EVSQL_FMT_BINARY) {
   268  *      EVSQL_PARAM( UINT32 ),
   269  *      ...,
   270  *
   271  *      EVSQL_PARAMS_END
   272  *  };
   273  * @endcode
   274  *
   275  * @name EVSQL_TYPE/PARAM_*
   276  * @{
   277  */
   278 
   279 /**
   280  * A `struct evsql_item_info` initializer, using FMT_BINARY and the given EVSQL_TYPE_ -suffix.
   281  *
   282  * @param typenam the suffix of an evsql_item_type name
   283  *
   284  * @see struct evsql_item_info
   285  * @see enum evsql_item_type
   286  */
   287 #define EVSQL_TYPE(typenam)                     { EVSQL_FMT_BINARY, EVSQL_TYPE_ ## typenam  }
   288 
   289 /**
   290  * End marker for a `struct evsql_item_info` array.
   291  *
   292  * @see struct evsql_item_info
   293  */
   294 #define EVSQL_TYPE_END                          { EVSQL_FMT_BINARY, EVSQL_TYPE_INVALID      }
   295 
   296 /**
   297  * Initializer block for an evsql_query_params struct
   298  */
   299 #define EVSQL_PARAMS(result_fmt)            { result_fmt, 
   300 
   301 /**
   302  * An evsql_item initializer
   303  */
   304 #define EVSQL_PARAM(typenam)                    { EVSQL_TYPE(typenam) }
   305 
   306 /**
   307  * Include the ending item and terminate the pseudo-block started using #EVSQL_PARAMS
   308  */
   309 #define EVSQL_PARAMS_END                        { EVSQL_TYPE_END } \
   310                                               } // <<<
   311 
   312 // @}
   313 
   314 /**
   315  * Callback definitions
   316  *
   317  * @name evsql_*_cb
   318  * @{
   319  */
   320 
   321 /**
   322  * Callback for handling query results.
   323  *
   324  * The query has completed, either succesfully or unsuccesfully.
   325  *
   326  * Use the \ref evsql_result_ functions to manipulate the results, and call evsql_result_free() (or equivalent) once done.
   327  *
   328  * @param res The result handle that must be result_free'd after use
   329  * @param arg The void* passed to \ref evsql_query_
   330  *
   331  * @see evsql_query
   332  */
   333 typedef void (*evsql_query_cb)(struct evsql_result *res, void *arg);
   334 
   335 /**
   336  * Callback for handling global-level errors.
   337  *
   338  * The evsql is not useable anymore.
   339  *
   340  * XXX: this is not actually called yet, as no retry logic is implemented, so an evsql itself never fails.
   341  *
   342  * @see evsql_new_pq
   343  */
   344 typedef void (*evsql_error_cb)(struct evsql *evsql, void *arg);
   345 
   346 /**
   347  * Callback for handling transaction-level errors. This may be called at any time during a transaction's lifetime,
   348  * including from within the \ref evsql_query_ functions (but not always).
   349  *
   350  * The transaction is not useable anymore.
   351  *
   352  * @param trans the transaction in question
   353  * @param arg the void* passed to evsql_trans
   354  *
   355  * @see evsql_trans
   356  */
   357 typedef void (*evsql_trans_error_cb)(struct evsql_trans *trans, void *arg);
   358 
   359 /**
   360  * Callback for handling evsql_trans/evsql_query_abort completion. The transaction is ready for use with \ref evsql_query_.
   361  *
   362  * @param trans the transaction in question
   363  * @param arg the void* passed to evsql_trans
   364  *
   365  * @see evsql_trans
   366  * @see evsql_query_abort
   367  */
   368 typedef void (*evsql_trans_ready_cb)(struct evsql_trans *trans, void *arg);
   369 
   370 /**
   371  * Callback for handling evsql_trans_commit completion. The transaction was commited, and should not be used anymore.
   372  *
   373  * @param trans the transaction in question
   374  * @param arg the void* passed to evsql_trans
   375  *
   376  * @see evsql_trans
   377  * @see evsql_trans_commit
   378  */
   379 typedef void (*evsql_trans_done_cb)(struct evsql_trans *trans, void *arg);
   380 
   381 // @}
   382 
   383 /**
   384  * Session functions
   385  *
   386  * @defgroup evsql_* Session interface
   387  * @see evsql.h
   388  * @{
   389  */
   390 
   391 /**
   392  * Session creation functions
   393  *
   394  * @defgroup evsql_new_* Session creation interface
   395  * @see evsql.h
   396  * @{
   397  */
   398 
   399 /**
   400  * Create a new PostgreSQL/libpq (evpq) -based evsql using the given conninfo.
   401  *
   402  * The given \a pq_conninfo pointer must stay valid for the duration of the evsql's lifetime.
   403  *
   404  * See the libpq reference manual for the syntax of pq_conninfo
   405  *
   406  * @param ev_base the libevent base to use
   407  * @param pq_conninfo the libpq connection information
   408  * @param error_fn XXX: not used, may be NULL
   409  * @param cb_arg: XXX: not used, argument for error_fn
   410  * @return the evsql context handle for use with other functions
   411  */
   412 struct evsql *evsql_new_pq (struct event_base *ev_base, const char *pq_conninfo, 
   413     evsql_error_cb error_fn, 
   414     void *cb_arg
   415 );
   416 
   417 // @}
   418 
   419 /**
   420  * Close a connection. Callbacks for waiting queries will not be run.
   421  *
   422  * XXX: not implemented yet.
   423  *
   424  * @param evsql the context handle from \ref evsql_new_
   425  */
   426 void evsql_close (struct evsql *evsql);
   427 
   428 // @}
   429 
   430 /**
   431  * Query API
   432  *
   433  * @defgroup evsql_query_* Query interface
   434  * @see evsql.h
   435  * @{
   436  */
   437 
   438 /**
   439  * Queue the given query for execution.
   440  *
   441  * If \a trans is given (i.e. not NULL), then the transaction must be idle, and the query will be executed in that
   442  * transaction's context. Otherwise, the query will be executed without a transaction using an idle connection, or
   443  * enqueued for later execution.
   444  *
   445  * Once the query is complete (got a result, got an error, the connection failed), then \a query_fn will be called.
   446  * The callback can use the \ref evsql_result_ functions to manipulate the query results.
   447  *
   448  * The returned evsql_query handle can be passed to evsql_query_abort at any point before \a query_fn being called. 
   449  *
   450  * @param evsql the context handle from \ref evsql_new_
   451  * @param trans the optional transaction handle from evsql_trans
   452  * @param command the raw SQL command itself
   453  * @param query_fn the evsql_query_cb() to call once the query is complete
   454  * @param cb_arg the void* passed to the above
   455  * @return the evsql_query handle that can be used to abort the query
   456  */
   457 struct evsql_query *evsql_query (struct evsql *evsql, struct evsql_trans *trans, const char *command, evsql_query_cb query_fn, void *cb_arg);
   458 
   459 /**
   460  * Execute the given SQL query using the list of parameter types/values given via evsql_query_params.
   461  *
   462  * Use the EVSQL_PARAMS macros to declare \a params, and the \ref evsql_param_ functions to populate the values.
   463  *
   464  * See evsql_query() for more info about behaviour.
   465  *
   466  * See the <a href="http://www.postgresql.org/docs/8.3/static/libpq-exec.html#LIBPQ-EXEC-MAIN">libpq PQexecParams tip</a>
   467  * for the parameter syntax to use.
   468  *
   469  * @param evsql the context handle from \ref evsql_new_
   470  * @param trans the optional transaction handle from evsql_trans
   471  * @param command the SQL command to bind the parameters to
   472  * @param params the parameter types and values
   473  * @param query_fn the evsql_query_cb() to call once the query is complete
   474  * @param cb_arg the void* passed to the above
   475  * @see evsql_query
   476  */
   477 struct evsql_query *evsql_query_params (struct evsql *evsql, struct evsql_trans *trans, 
   478     const char *command, const struct evsql_query_params *params, 
   479     evsql_query_cb query_fn, void *cb_arg
   480 );
   481 
   482 /**
   483  * Execute the given \a query_info's SQL query with the values given as variable arguments, using the \a query_info to
   484  * resolve the types.
   485  *
   486  * See evsql_query() for more info about behaviour.
   487  *
   488  * @param evsql the context handle from \ref evsql_new_
   489  * @param trans the optional transaction handle from evsql_trans
   490  * @param query_info the SQL query information
   491  * @param query_fn the evsql_query_cb() to call once the query is complete
   492  * @param cb_arg the void* passed to the above
   493  * @see evsql_query
   494  */
   495 struct evsql_query *evsql_query_exec (struct evsql *evsql, struct evsql_trans *trans, 
   496     const struct evsql_query_info *query_info,
   497     evsql_query_cb query_fn, void *cb_arg,
   498     ...
   499 );
   500 
   501 /**
   502  * Abort a \a query returned by \ref evsql_query_ that has not yet completed (query_fn has not been called yet).
   503  *
   504  * The actual query itself may or may not be aborted (and hence may or may not be executed on the server), but \a query_fn
   505  * will not be called anymore, and the query will dispose of itself and any results returned.
   506  *
   507  * If the \a query is part of a transaction, then \a trans must be given, and the query must be the query that is currently
   508  * executing on that trans. The transaction's \a ready_fn will be called once the query has been aborted and the
   509  * transaction is now idle again.
   510  *
   511  * @param trans if the query is part of a transaction, then it MUST be given here
   512  * @param query the in-progress query to abort
   513  */
   514 void evsql_query_abort (struct evsql_trans *trans, struct evsql_query *query);
   515 
   516 /**
   517  * Print out a textual dump of the given \a sql query and \a params using DEBUG
   518  *
   519  * @param sql the SQL query command
   520  * @param params the list of parameter types and values
   521  */
   522 void evsql_query_debug (const char *sql, const struct evsql_query_params *params);
   523 
   524 // @}
   525 
   526 /**
   527  * Transaction API
   528  *
   529  * @defgroup evsql_trans_* Transaction interface
   530  * @see evsql.h
   531  * @{
   532  */
   533 
   534 /**
   535  * Create a new transaction.
   536  *
   537  * A transaction will be allocated its own connection, and the "BEGIN TRANSACTION ..." query will be sent (use the
   538  * \a type argument to specify this). 
   539  *
   540  * Once the transaction has been opened, the given \a ready_fn will be triggered, and the transaction can then
   541  * be used (see \ref evsql_query_).
   542  *
   543  * If, at any point, the transaction-connection fails, any pending query will be forgotten (i.e. the query callback
   544  * will NOT be called), and the given \a error_fn will be called. Note that this includes some, but not all,
   545  * cases where \ref evsql_query_ returns an error.
   546  *
   547  * Once you are done with the transaction, call either evsql_trans_commit() or evsql_trans_abort().
   548  *
   549  * @param evsql the context handle from \ref evsql_new_
   550  * @param type the type of transaction to create
   551  * @param error_fn the evsql_trans_error_cb() to call if this transaction fails
   552  * @param ready_fn the evsql_trans_ready_cb() to call once this transaction is ready for use
   553  * @param done_fn the evsql_trans_done_cb() to call once this transaction has been commmited
   554  * @param cb_arg the void* to pass to the above
   555  * @return the evsql_trans handle for use with other functions
   556  */
   557 struct evsql_trans *evsql_trans (struct evsql *evsql, enum evsql_trans_type type, 
   558     evsql_trans_error_cb error_fn, 
   559     evsql_trans_ready_cb ready_fn, 
   560     evsql_trans_done_cb done_fn, 
   561     void *cb_arg
   562 );
   563 
   564 /**
   565  * Commit a transaction using "COMMIT TRANSACTION".
   566  *
   567  * The transaction must be idle, just like for evsql_query. Once the transaction has been commited, the transaction's
   568  * \a done_fn will be called, after which the transaction must not be used anymore.
   569  *
   570  * You cannot abort a COMMIT, calling trans_abort() on trans after a succesful trans_commit is an error.
   571  *
   572  * Note that \a done_fn will never be called directly, always indirectly via the event loop.
   573  *
   574  * @param trans the transaction handle from evsql_trans to commit
   575  * @see evsql_trans
   576  */
   577 int evsql_trans_commit (struct evsql_trans *trans);
   578 
   579 /**
   580  * Abort a transaction, using "ROLLBACK TRANSACTION".
   581  *
   582  * No more transaction callbacks will be called. If there was a query running, it will be aborted, and the transaction
   583  * then rollback'd.
   584  *
   585  * You cannot abort a COMMIT, calling trans_abort on \a trans after a call to trans_commit is an error.
   586  * 
   587  * Do not call evsql_trans_abort from within evsql_trans_error_cb()!
   588  *
   589  * @param trans the transaction from evsql_trans to abort
   590  * @see evsql_trans
   591  */
   592 void evsql_trans_abort (struct evsql_trans *trans);
   593 
   594 /** 
   595  * Retrieve the transaction-specific error message from the underlying engine.
   596  *
   597  * Intended to be called from evsql_trans_error_cb()
   598  */
   599 const char *evsql_trans_error (struct evsql_trans *trans);
   600 
   601 // @}
   602 
   603 /**
   604  * Parameter-building functions.
   605  *
   606  * These manipulate the value of the given parameter index.
   607  *
   608  * @defgroup evsql_param_* Parameter interface
   609  * @see evsql.h
   610  * @{
   611  */
   612 
   613 /**
   614  * Sets the value of the parameter at the given index
   615  *
   616  * @param params the evsql_query_params struct
   617  * @param param the parameter index
   618  * @param ptr pointer to the binary data
   619  * @param len size of the binary data in bytes
   620  * @return zero on success, <0 on error
   621  */
   622 int evsql_param_binary (struct evsql_query_params *params, size_t param, const char *ptr, size_t len);
   623 
   624 /** @see evsql_param_binary */
   625 int evsql_param_string (struct evsql_query_params *params, size_t param, const char *ptr);
   626 
   627 /** @see evsql_param_binary */
   628 int evsql_param_uint16 (struct evsql_query_params *params, size_t param, uint16_t uval);
   629 
   630 /** @see evsql_param_binary */
   631 int evsql_param_uint32 (struct evsql_query_params *params, size_t param, uint32_t uval);
   632 
   633 /**
   634  * Sets the given parameter to NULL
   635  *
   636  * @param params the evsql_query_params struct
   637  * @param param the parameter index
   638  * @return zero on success, <0 on error
   639  */
   640 int evsql_param_null (struct evsql_query_params *params, size_t param);
   641 
   642 /**
   643  * Clears all the parameter values (sets them to NULL)
   644  *
   645  * @param params the evsql_query_params struct
   646  * @return zero on success, <0 on error
   647  */
   648 int evsql_params_clear (struct evsql_query_params *params);
   649 
   650 // @}
   651 
   652 /**
   653  * Result-handling functions
   654  *
   655  * @defgroup evsql_result_* Result interface
   656  * @see evsql.h
   657  * @see evsql_result
   658  * @{
   659  */
   660 
   661 /**
   662  * Check the result for errors. Intended for use with non-data queries, i.e. CREATE, etc.
   663  *
   664  * Returns zero if the query was OK, err otherwise. EIO indicates an SQL error, the error message can be retrived
   665  * using evsql_result_error.
   666  *
   667  * @param res the result handle passed to evsql_query_cb()
   668  * @return zero on success, EIO on SQL error, positive error code otherwise
   669  */
   670 err_t evsql_result_check (struct evsql_result *res);
   671 
   672 /**
   673  * The iterator-based interface results interface.
   674  *
   675  * Define an evsql_result_info struct that describes the columns returned by the query, and call evsql_result_begin on
   676  * the evsql_result. This verifies the query result, and then prepares it for iteration using evsql_result_next.
   677  *
   678  * Call evsql_result_end once you've stopped iteration.
   679  *
   680  * Returns zero if the evsql_result is ready for iteration, err otherwise. EIO indicates an SQL error, the error
   681  * message can be retreived using evsql_result_error. The result must be released in both cases.
   682  *
   683  * Note: currently the iterator state is simply stored in evsql_result, so only one iterator at a time per evsql_result.
   684  *
   685  * @param info the metadata to use to handle the result row columns
   686  * @param res the result handle passed to evsql_query_cb()
   687  * @return zero on success, +err on error
   688  */
   689 err_t evsql_result_begin (struct evsql_result_info *info, struct evsql_result *res);
   690 
   691 /**
   692  * Reads the next result row from the result prepared using evsql_result_begin. Stores the field values into to given
   693  * pointer arguments based on the evsql_result_info given to evsql_result_begin.
   694  *
   695  * If a field is NULL, and the result_info's evsql_item_type has flags.null_ok set, the given pointer is left
   696  * untouched, otherwise, an error is returned.
   697  *
   698  * @param res the result handle previous prepared using evsql_result_begin
   699  * @param ... a set of pointers corresponding to the evsql_result_info specified using evsql_result_begin
   700  * @return >0 when a row was read, zero when there are no more rows left, and -err on error
   701  */
   702 int evsql_result_next (struct evsql_result *res, ...);
   703 
   704 /**
   705  * Ends the result iteration, releasing any associated resources and the result itself.
   706  *
   707  * The result should not be iterated or accessed anymore.
   708  *
   709  * Note: this does the same thing as evsql_result_free, and works regardless of evsql_result_begin returning
   710  * succesfully or not.
   711  *
   712  * @param res the result handle passed to evsql_query_cb()
   713  * @see evsql_result_free
   714  */
   715 void evsql_result_end (struct evsql_result *res);
   716 
   717 /**
   718  * Get the error message associated with the result, intended for use after evsql_result_check/begin return an error
   719  * code.
   720  * 
   721  * @param res the result handle passed to evsql_query_cb()
   722  * @return a char* containing the NUL-terminated error string. Valid until evsql_result_free is called.
   723  */
   724 const char *evsql_result_error (const struct evsql_result *res);
   725 
   726 /**
   727  * Get the number of data rows returned by the query
   728  *
   729  * @param res the result handle passed to evsql_query_cb()
   730  * @return the number of rows, >= 0
   731  */
   732 size_t evsql_result_rows (const struct evsql_result *res);
   733 
   734 /**
   735  * Get the number of columns in the data results from the query
   736  *
   737  * @param res the result handle passed to evsql_query_cb()
   738  * @return the number of columns, presumeably zero if there were no results
   739  */
   740 size_t evsql_result_cols (const struct evsql_result *res);
   741 
   742 /**
   743  * Get the number of rows affected by an UPDATE/INSERT/etc query.
   744  *
   745  * @param res the result handle passed to evsql_query_cb()
   746  * @return the number of rows affected, >= 0
   747  */
   748 size_t evsql_result_affected (const struct evsql_result *res);
   749 
   750 /**
   751  * Fetch the raw binary value for the given field, returning it via ptr/size.
   752  *
   753  * The given row/col must be within bounds as returned by evsql_result_rows/cols.
   754  *
   755  * *ptr will point to *size bytes of read-only memory allocated internally.
   756  *
   757  * @param res the result handle passed to evsql_query_cb()
   758  * @param row the row index to access
   759  * @param col the column index to access
   760  * @param ptr where to store a pointer to the read-only field data, free'd upon evsql_result_free
   761  * @param size updated to the size of the field value pointed to by ptr
   762  * @param nullok when true and the field value is NULL, *ptr and *size are not modified, otherwise NULL means an error
   763  * @return zero on success, <0 on error
   764  */
   765 int evsql_result_binary (const struct evsql_result *res, size_t row, size_t col, const char **ptr, size_t *size, bool nullok);
   766 
   767 /**
   768  * Fetch the textual value of the given field, returning it via ptr.
   769  *
   770  * The given row/col must be within bounds as returned by evsql_result_rows/cols.
   771  *
   772  * *ptr will point to a NUL-terminated string allocated internally.
   773  *
   774  * @param res the result handle passed to evsql_query_cb()
   775  * @param row the row index to access
   776  * @param col the column index to access
   777  * @param ptr where to store a pointer to the read-only field data, free'd upon evsql_result_free
   778  * @param nullok when true and the field value is NULL, *ptr and *size are not modified, otherwise NULL means an error
   779  * @return zero on success, <0 on error
   780  */
   781 int evsql_result_string (const struct evsql_result *res, size_t row, size_t col, const char **ptr, int nullok);
   782 
   783 /**
   784  * Use evsql_result_binary to read a binary field value, and then convert it using ntoh[slq], storing the value in
   785  * *val.
   786  *
   787  * The given row/col must be within bounds as returned by evsql_result_rows/cols.
   788  *
   789  * @param res the result handle passed to evsql_query_cb()
   790  * @param row the row index to access
   791  * @param col the column index to access
   792  * @param uval where to store the decoded value
   793  * @param nullok when true and the field value is NULL, *ptr and *size are not modified, otherwise NULL means an error
   794  * @return zero on success, <0 on error
   795  */
   796 int evsql_result_uint16 (const struct evsql_result *res, size_t row, size_t col, uint16_t *uval, int nullok);
   797 
   798 /** @see evsql_result_uint16 */
   799 int evsql_result_uint32 (const struct evsql_result *res, size_t row, size_t col, uint32_t *uval, int nullok);
   800 
   801 /** @see evsql_result_uint16 */
   802 int evsql_result_uint64 (const struct evsql_result *res, size_t row, size_t col, uint64_t *uval, int nullok);
   803 
   804 /**
   805  * Every result handle passed to evsql_query_cb() MUST be released by the user, using this function.
   806  *
   807  * @param res the result handle passed to evsql_query_cb()
   808  */
   809 void evsql_result_free (struct evsql_result *res);
   810 
   811 // @}
   812 
   813 #endif /* EVSQL_H */