src/evsql.h
branchnew-evsql
changeset 45 424ce5ab82fd
parent 44 9e76ee9729b6
child 48 8b019d191353
equal deleted inserted replaced
44:9e76ee9729b6 45:424ce5ab82fd
     3 
     3 
     4 /*
     4 /*
     5  * An event-based (Postgre)SQL client API using libevent
     5  * An event-based (Postgre)SQL client API using libevent
     6  */
     6  */
     7 
     7 
     8 // XXX: remove libpq?
       
     9 #include <stdint.h>
     8 #include <stdint.h>
    10 #include <postgresql/libpq-fe.h>
       
    11 #include <event2/event.h>
     9 #include <event2/event.h>
    12 
    10 
    13 #include <lib/err.h>
    11 #include "lib/err.h"
    14 
    12 
    15 /*
    13 /*
    16  * The generic context handle
    14  * The generic context handle
    17  */
    15  */
    18 struct evsql;
    16 struct evsql;
    84         uint8_t null_ok : 1;
    82         uint8_t null_ok : 1;
    85     } flags;
    83     } flags;
    86 };
    84 };
    87 
    85 
    88 /*
    86 /*
       
    87  * Storage for various scalar values
       
    88  */
       
    89 union evsql_item_value {
       
    90     uint16_t uint16;
       
    91     uint32_t uint32;
       
    92     uint64_t uint64;
       
    93 };
       
    94 
       
    95 /*
    89  * The type and value of an item
    96  * The type and value of an item
    90  */
    97  */
    91 struct evsql_item {
    98 struct evsql_item {
    92     // "header"
    99     // "header"
    93     struct evsql_item_info info;
   100     struct evsql_item_info info;
    94 
   101 
    95     // pointer to the raw databytes. Set to NULL to indicate SQL-NULL
   102     // pointer to the raw databytes. Set to NULL to indicate SQL-NULL, &value, or an external buf
    96     const char *bytes;
   103     const char *bytes;
    97 
   104 
    98     // size of byte array pointed to by bytes, zero for text
   105     // size of byte array pointed to by bytes, zero for text
    99     size_t length;
   106     size_t length;
   100 
   107 
   101     // the decoded value
   108     // the decoded value
   102     union {
   109     union evsql_item_value value;
   103         uint16_t uint16;
   110     
   104         uint32_t uint32;
   111     // (internal) flags
   105         uint64_t uint64;
   112     struct {
   106     } value;
   113         char has_value : 1;
       
   114     } flags;
   107 };
   115 };
   108 
   116 
   109 /*
   117 /*
   110  * Query info, similar to prepared statements
   118  * Query info, similar to prepared statements
   111  *
   119  *
   144 };
   152 };
   145 
   153 
   146 /*
   154 /*
   147  * Callback for handling query results.
   155  * Callback for handling query results.
   148  *
   156  *
   149  * The query has completed, either succesfully or unsuccesfully (nonzero .error).
   157  * The query has completed, either succesfully or unsuccesfully.
   150  *
   158  *
   151  * Use the evsql_result_* functions to manipulate the results.
   159  * Use the evsql_result_* functions to manipulate the results, and call evsql_result_free (or equivalent) once done.
   152  */
   160  */
   153 typedef void (*evsql_query_cb)(struct evsql_result *res, void *arg);
   161 typedef void (*evsql_query_cb)(struct evsql_result *res, void *arg);
   154 
   162 
   155 /*
   163 /*
   156  * Callback for handling global-level errors.
   164  * Callback for handling global-level errors.
   160  * XXX: this is not actually called yet, no retry logic implemented.
   168  * XXX: this is not actually called yet, no retry logic implemented.
   161  */
   169  */
   162 typedef void (*evsql_error_cb)(struct evsql *evsql, void *arg);
   170 typedef void (*evsql_error_cb)(struct evsql *evsql, void *arg);
   163 
   171 
   164 /*
   172 /*
   165  * Callback for handling transaction-level errors.
   173  * Callback for handling transaction-level errors. This may be called at any time during a transaction's lifetime,
       
   174  * including from within the evsql_query_* functions.
   166  *
   175  *
   167  * The transaction is not useable anymore.
   176  * The transaction is not useable anymore.
   168  */
   177  */
   169 typedef void (*evsql_trans_error_cb)(struct evsql_trans *trans, void *arg);
   178 typedef void (*evsql_trans_error_cb)(struct evsql_trans *trans, void *arg);
   170 
   179 
   171 /*
   180 /*
   172  * The transaction is ready for use.
   181  * Callback for handling evsql_trans/evsql_query_abort completion. The transaction is ready for use with evsql_query_*.
   173  */
   182  */
   174 typedef void (*evsql_trans_ready_cb)(struct evsql_trans *trans, void *arg);
   183 typedef void (*evsql_trans_ready_cb)(struct evsql_trans *trans, void *arg);
   175 
   184 
   176 /*
   185 /*
   177  * The transaction was commited, and should not be used anymore.
   186  * Callback for handling evsql_trans_commit completion. The transaction was commited, and should not be used anymore.
   178  */
   187  */
   179 typedef void (*evsql_trans_done_cb)(struct evsql_trans *trans, void *arg);
   188 typedef void (*evsql_trans_done_cb)(struct evsql_trans *trans, void *arg);
   180 
   189 
   181 /*
   190 /*
   182  * Create a new PostgreSQL/libpq(evpq) -based evsql using the given conninfo.
   191  * Create a new PostgreSQL/libpq(evpq) -based evsql using the given conninfo.
   183  *
   192  *
   184  * The given conninfo must stay valid for the duration of the evsql's lifetime.
   193  * The given conninfo must stay valid for the duration of the evsql's lifetime.
   185  */
   194  */
   186 struct evsql *evsql_new_pq (struct event_base *ev_base, const char *pq_conninfo, evsql_error_cb error_fn, void *cb_arg);
   195 struct evsql *evsql_new_pq (struct event_base *ev_base, const char *pq_conninfo, 
       
   196     evsql_error_cb error_fn, 
       
   197     void *cb_arg
       
   198 );
   187 
   199 
   188 /*
   200 /*
   189  * Create a new transaction.
   201  * Create a new transaction.
   190  *
   202  *
   191  * Transactions are separate connections that provide transaction-isolation.
   203  * A transaction will be allocated its own connection, and the "BEGIN TRANSACTION ..." query will be sent (use the
   192  *
   204  * evsql_trans_type argument to specify this). 
   193  * Once the transaction is ready for use, ready_fn will be called. If the transaction fails, any pending query will be
   205  *
   194  * forgotten, and error_fn called. This also includes some (but not all) cases where evsql_query returns nonzero.
   206  * Once the transaction has been opened, the given evsql_trans_ready_cb will be triggered, and the transaction can then
   195  *
   207  * be used (see evsql_query_*).
   196  */
   208  *
   197 struct evsql_trans *evsql_trans (struct evsql *evsql, enum evsql_trans_type type, evsql_trans_error_cb error_fn, evsql_trans_ready_cb ready_fn, evsql_trans_done_cb done_fn, void *cb_arg);
   209  * If, at any point, the transaction-connection fails, and pending query will be forgotten (i.e. the query callback
       
   210  * will NOT be called), and the given evsql_trans_error_cb will be called. Note that this includes some, but not all,
       
   211  * cases where evsql_query_* returns an error.
       
   212  *
       
   213  * Once you are done with the transaction, call either evsql_trans_commit or evsql_trans_abort.
       
   214  */
       
   215 struct evsql_trans *evsql_trans (struct evsql *evsql, enum evsql_trans_type type, 
       
   216     evsql_trans_error_cb error_fn, 
       
   217     evsql_trans_ready_cb ready_fn, 
       
   218     evsql_trans_done_cb done_fn, 
       
   219     void *cb_arg
       
   220 );
   198 
   221 
   199 /*
   222 /*
   200  * Queue the given query for execution.
   223  * Queue the given query for execution.
   201  *
   224  *
   202  * If trans is specified (not NULL), then the transaction must be idle, and the query will be executed in that
   225  * If trans is specified (not NULL), then the transaction must be idle, and the query will be executed in that
   203  * transaction's context. Otherwise, the query will be executed without a transaction, andmay be executed immediately,
   226  * transaction's context. Otherwise, the query will be executed without a transaction using an idle connection, or
   204  * or if other similar queries are running, it will be queued for later execution.
   227  * enqueued for later execution.
   205  *
   228  *
   206  * Once the query is complete (got a result, got an error, the connection failed), then the query_cb will be triggered.
   229  * Once the query is complete (got a result, got an error, the connection failed), then the query_cb will be called.
       
   230  * The callback can used the evsql_result_* functions to manipulate it.
       
   231  *
       
   232  * The returned evsql_query handle can be passed to evsql_query_abort at any point before query_fn being called. 
       
   233  *
   207  */
   234  */
   208 struct evsql_query *evsql_query (struct evsql *evsql, struct evsql_trans *trans, const char *command, evsql_query_cb query_fn, void *cb_arg);
   235 struct evsql_query *evsql_query (struct evsql *evsql, struct evsql_trans *trans, const char *command, evsql_query_cb query_fn, void *cb_arg);
   209 
   236 
   210 /*
   237 /*
   211  * Same as evsql_query, but uses the SQL-level support for binding parameters.
   238  * Execute the given SQL query using the list of parameter types/values given via evsql_query_params.
       
   239  *
       
   240  * See evsql_query for more info about behaviour.
   212  */
   241  */
   213 struct evsql_query *evsql_query_params (struct evsql *evsql, struct evsql_trans *trans, 
   242 struct evsql_query *evsql_query_params (struct evsql *evsql, struct evsql_trans *trans, 
   214     const char *command, const struct evsql_query_params *params, 
   243     const char *command, const struct evsql_query_params *params, 
   215     evsql_query_cb query_fn, void *cb_arg
   244     evsql_query_cb query_fn, void *cb_arg
   216 );
   245 );
   217 
   246 
   218 /*
   247 /*
   219  * Execute the given query_info, using the parameter list in query_info to resolve the given variable arugments
   248  * Execute the given query_info's SQL query using the values given as variable arguments, using the evsql_query_info to
       
   249  * resolve the types.
       
   250  *
       
   251  * See evsql_query for more info about behaviour.
   220  */
   252  */
   221 struct evsql_query *evsql_query_exec (struct evsql *evsql, struct evsql_trans *trans, 
   253 struct evsql_query *evsql_query_exec (struct evsql *evsql, struct evsql_trans *trans, 
   222     const struct evsql_query_info *query_info,
   254     const struct evsql_query_info *query_info,
   223     evsql_query_cb query_fn, void *cb_arg,
   255     evsql_query_cb query_fn, void *cb_arg,
   224     ...
   256     ...
   225 );
   257 );
   226 
   258 
   227 /*
   259 /*
   228  * Abort a query, the query callback will not be called, the query and any possible results will be discarded.
   260  * Abort a query returned by evsql_query_* that has not yet completed (query_fn has not been called yet).
   229  *
   261  *
   230  * This does not garuntee that the query will not execute, simply that you won't get the results.
   262  * The actual query itself may or may not be aborted (and hence may or may not be executed on the server), but query_fn
       
   263  * will not be called anymore, and the query will dispose of itself and any results returned.
   231  *
   264  *
   232  * If the query is part of a transaction, then trans must be given, and the query must be the query that is currently
   265  * If the query is part of a transaction, then trans must be given, and the query must be the query that is currently
   233  * executing on that trans. The transaction's ready_fn will be called once the query has been aborted.
   266  * executing on that trans. The transaction's ready_fn will be called once the query has been aborted and the
       
   267  * transaction is now idle again.
   234  */
   268  */
   235 void evsql_query_abort (struct evsql_trans *trans, struct evsql_query *query);
   269 void evsql_query_abort (struct evsql_trans *trans, struct evsql_query *query);
   236 
   270 
   237 /*
   271 /*
   238  * Commit a transaction, calling done_fn if it was succesfull (error_fn otherwise).
   272  * Commit a transaction using "COMMIT TRANSACTION".
   239  *
   273  *
   240  * trans must be idle, just like for evsql_query.
   274  * The transaction must be idle, just like for evsql_query. Once the transaction has been commited, the transaction's
   241  *
   275  * done_fn will be called, after which the transaction must not be used.
   242  * done_fn will never be called directly, always via the event loop.
       
   243  *
   276  *
   244  * You cannot abort a COMMIT, calling trans_abort on trans after a succesful trans_commit is a FATAL error.
   277  * You cannot abort a COMMIT, calling trans_abort on trans after a succesful trans_commit is a FATAL error.
       
   278  *
       
   279  * Note that done_fn will never be called directly, always indirectly via the event loop.
   245  */
   280  */
   246 int evsql_trans_commit (struct evsql_trans *trans);
   281 int evsql_trans_commit (struct evsql_trans *trans);
   247 
   282 
   248 /*
   283 /*
   249  * Abort a transaction, rolling it back. No callbacks will be called.
   284  * Abort a transaction, using "ROLLBACK TRANSACTION".
       
   285  *
       
   286  * No more transaction callbacks will be called, if there was a query running, it will be aborted, and the transaction
       
   287  * then rollback'd.
   250  *
   288  *
   251  * You cannot abort a COMMIT, calling trans_abort on trans after a succesful trans_commit is a FATAL error.
   289  * You cannot abort a COMMIT, calling trans_abort on trans after a succesful trans_commit is a FATAL error.
       
   290  * 
       
   291  * Do not call evsql_trans_abort from within evsql_trans_error_cb!
   252  */
   292  */
   253 void evsql_trans_abort (struct evsql_trans *trans);
   293 void evsql_trans_abort (struct evsql_trans *trans);
   254 
   294 
   255 /*
   295 /*
   256  * Transaction-handling functions
   296  * Transaction-handling functions
   278 
   318 
   279 /*
   319 /*
   280  * Result-handling functions
   320  * Result-handling functions
   281  */
   321  */
   282 
   322 
       
   323 /*
       
   324  * Check the result for errors. Intended for use with non-data queries, i.e. CREATE, etc.
       
   325  *
       
   326  * Returns zero if the query was OK, err otherwise. EIO indicates an SQL error, the error message can be retrived
       
   327  * using evsql_result_error.
       
   328  */
       
   329 err_t evsql_result_check (struct evsql_result *res);
       
   330 
       
   331 /*
       
   332  * The iterator-based interface results interface.
       
   333  *
       
   334  * Define an evsql_result_info struct that describes the columns returned by the query, and call evsql_result_begin on
       
   335  * the evsql_result. This verifies the query result, and then prepares it for iteration using evsql_result_next.
       
   336  *
       
   337  * Call evsql_result_end once you've stopped iteration.
       
   338  *
       
   339  * Returns zero if the evsql_result is ready for iteration, err otherwise. EIO indicates an SQL error, the error
       
   340  * message can be retreived using evsql_result_error.
       
   341  *
       
   342  * Note: currently the iterator state is simply stored in evsql_result, so only one iterator at a time per evsql_result.
       
   343  */
       
   344 err_t evsql_result_begin (struct evsql_result_info *info, struct evsql_result *res);
       
   345 
       
   346 /*
       
   347  * Reads the next result row, storing the field values into the pointer arguments given. The types are resolved using
       
   348  * the evsql_result_info given to evsql_result_begin.
       
   349  *
       
   350  * Returns >0 when a row was read, 0 when there are no more rows, and -err if there was an error.
       
   351  */
       
   352 int evsql_result_next (struct evsql_result *res, ...);
       
   353 
       
   354 /*
       
   355  * Ends the result iteration, releasing any associated resources and the result itself.
       
   356  *
       
   357  * The result should not be iterated or accessed anymore.
       
   358  *
       
   359  * Note: this does the same thing as evsql_result_free, and works regardless of evsql_result_begin returning
       
   360  * succesfully or not.
       
   361  */
       
   362 void evsql_result_end (struct evsql_result *res);
       
   363 
       
   364 
   283 // get error message associated with function
   365 // get error message associated with function
   284 const char *evsql_result_error (const struct evsql_result *res);
   366 const char *evsql_result_error (const struct evsql_result *res);
   285 
       
   286 /*
       
   287  * Iterator-based interface.
       
   288  *
       
   289  * Call result_begin to check for errors, then result_next to fetch rows, and finally result_end to release.
       
   290  */
       
   291 err_t evsql_result_begin (struct evsql_result_info *info, struct evsql_result *res);
       
   292 int evsql_result_next (struct evsql_result *res, ...);
       
   293 void evsql_result_end (struct evsql_result *res);
       
   294 
   367 
   295 // number of rows in the result
   368 // number of rows in the result
   296 size_t evsql_result_rows (const struct evsql_result *res);
   369 size_t evsql_result_rows (const struct evsql_result *res);
   297 
   370 
   298 // number of columns in the result
   371 // number of columns in the result