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