src/evsql.h
changeset 56 9dfc861273e5
parent 42 40a3b13ffc9d
child 57 527d23bf6441
equal deleted inserted replaced
42:40a3b13ffc9d 56:9dfc861273e5
     1 #ifndef EVSQL_H
       
     2 #define EVSQL_H
       
     3 
       
     4 /*
       
     5  * An event-based (Postgre)SQL client API using libevent
       
     6  */
       
     7 
       
     8 // XXX: libpq
       
     9 #include <stdint.h>
       
    10 #include <postgresql/libpq-fe.h>
       
    11 #include <event2/event.h>
       
    12 
       
    13 /*
       
    14  * The generic context handle
       
    15  */
       
    16 struct evsql;
       
    17 
       
    18 /*
       
    19  * A query handle
       
    20  */
       
    21 struct evsql_query;
       
    22 
       
    23 /*
       
    24  * Transaction handle
       
    25  */
       
    26 struct evsql_trans;
       
    27 
       
    28 /*
       
    29  * Transaction type
       
    30  */
       
    31 enum evsql_trans_type {
       
    32     EVSQL_TRANS_DEFAULT,
       
    33     EVSQL_TRANS_SERIALIZABLE,
       
    34     EVSQL_TRANS_REPEATABLE_READ,
       
    35     EVSQL_TRANS_READ_COMMITTED,
       
    36     EVSQL_TRANS_READ_UNCOMMITTED,
       
    37 };
       
    38 
       
    39 /*
       
    40  * Parameter type
       
    41  */
       
    42 enum evsql_param_format {
       
    43     EVSQL_FMT_TEXT,
       
    44     EVSQL_FMT_BINARY,
       
    45 };
       
    46 
       
    47 enum evsql_param_type {
       
    48     EVSQL_PARAM_INVALID,
       
    49 
       
    50     EVSQL_PARAM_NULL_,
       
    51     
       
    52     EVSQL_PARAM_BINARY,
       
    53     EVSQL_PARAM_STRING,
       
    54     EVSQL_PARAM_UINT16,
       
    55     EVSQL_PARAM_UINT32,
       
    56     EVSQL_PARAM_UINT64,
       
    57 };
       
    58 
       
    59 /*
       
    60  * Query parameter info.
       
    61  *
       
    62  * Use the EVSQL_PARAM_* macros to define the value of list
       
    63  */
       
    64 struct evsql_query_params {
       
    65     // nonzero to get results in binary format
       
    66     enum evsql_param_format result_fmt;
       
    67     
       
    68     // the list of parameters, terminated by { 0, 0 }
       
    69     struct evsql_query_param {
       
    70         // the param type
       
    71         enum evsql_param_type type;
       
    72         
       
    73         // pointer to the raw data
       
    74         const char *data_raw;
       
    75         
       
    76         // the value
       
    77         union {
       
    78             uint16_t uint16;
       
    79             uint32_t uint32;
       
    80             uint64_t uint64;
       
    81         } data;
       
    82 
       
    83         // the explicit length of the parameter if it's binary, zero for text.
       
    84         // set to -1 to indicate that the value is still missing
       
    85         ssize_t length;
       
    86     } list[];
       
    87 };
       
    88 
       
    89 // macros for defining evsql_query_params
       
    90 #define EVSQL_PARAMS(result_fmt)            { result_fmt, 
       
    91 #define EVSQL_PARAM(typenam)                    { EVSQL_PARAM_ ## typenam, NULL }
       
    92 #define EVSQL_PARAMS_END                        { EVSQL_PARAM_INVALID, NULL } \
       
    93                                               } // <<<
       
    94 
       
    95 /*
       
    96  * Result type
       
    97  */
       
    98 struct evsql_result_info {
       
    99     struct evsql *evsql;
       
   100     struct evsql_trans *trans;
       
   101     
       
   102     int error;
       
   103 
       
   104     union evsql_result {
       
   105         // libpq
       
   106         PGresult *pq;
       
   107     } result;
       
   108 };
       
   109 
       
   110 /*
       
   111  * Callback for handling query results.
       
   112  *
       
   113  * The query has completed, either succesfully or unsuccesfully (nonzero .error).
       
   114  *
       
   115  * Use the evsql_result_* functions to manipulate the results.
       
   116  */
       
   117 typedef void (*evsql_query_cb)(const struct evsql_result_info *res, void *arg);
       
   118 
       
   119 /*
       
   120  * Callback for handling global-level errors.
       
   121  *
       
   122  * The evsql is not useable anymore.
       
   123  *
       
   124  * XXX: this is not actually called yet, no retry logic implemented.
       
   125  */
       
   126 typedef void (*evsql_error_cb)(struct evsql *evsql, void *arg);
       
   127 
       
   128 /*
       
   129  * Callback for handling transaction-level errors.
       
   130  *
       
   131  * The transaction is not useable anymore.
       
   132  */
       
   133 typedef void (*evsql_trans_error_cb)(struct evsql_trans *trans, void *arg);
       
   134 
       
   135 /*
       
   136  * The transaction is ready for use.
       
   137  */
       
   138 typedef void (*evsql_trans_ready_cb)(struct evsql_trans *trans, void *arg);
       
   139 
       
   140 /*
       
   141  * The transaction was commited, and should not be used anymore.
       
   142  */
       
   143 typedef void (*evsql_trans_done_cb)(struct evsql_trans *trans, void *arg);
       
   144 
       
   145 /*
       
   146  * Create a new PostgreSQL/libpq(evpq) -based evsql using the given conninfo.
       
   147  *
       
   148  * The given conninfo must stay valid for the duration of the evsql's lifetime.
       
   149  */
       
   150 struct evsql *evsql_new_pq (struct event_base *ev_base, const char *pq_conninfo, evsql_error_cb error_fn, void *cb_arg);
       
   151 
       
   152 /*
       
   153  * Create a new transaction.
       
   154  *
       
   155  * Transactions are separate connections that provide transaction-isolation.
       
   156  *
       
   157  * Once the transaction is ready for use, ready_fn will be called. If the transaction fails, any pending query will be
       
   158  * forgotten, and error_fn called. This also includes some (but not all) cases where evsql_query returns nonzero.
       
   159  *
       
   160  */
       
   161 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);
       
   162 
       
   163 /*
       
   164  * Queue the given query for execution.
       
   165  *
       
   166  * If trans is specified (not NULL), then the transaction must be idle, and the query will be executed in that
       
   167  * transaction's context. Otherwise, the query will be executed without a transaction, andmay be executed immediately,
       
   168  * or if other similar queries are running, it will be queued for later execution.
       
   169  *
       
   170  * Once the query is complete (got a result, got an error, the connection failed), then the query_cb will be triggered.
       
   171  */
       
   172 struct evsql_query *evsql_query (struct evsql *evsql, struct evsql_trans *trans, const char *command, evsql_query_cb query_fn, void *cb_arg);
       
   173 
       
   174 /*
       
   175  * Same as evsql_query, but uses the SQL-level support for binding parameters.
       
   176  */
       
   177 struct evsql_query *evsql_query_params (struct evsql *evsql, struct evsql_trans *trans, const char *command, const struct evsql_query_params *params, evsql_query_cb query_fn, void *cb_arg);
       
   178 
       
   179 /*
       
   180  * Abort a query, the query callback will not be called, the query and any possible results will be discarded.
       
   181  *
       
   182  * This does not garuntee that the query will not execute, simply that you won't get the results.
       
   183  *
       
   184  * If the query is part of a transaction, then trans must be given, and the query must be the query that is currently
       
   185  * executing on that trans. The transaction's ready_fn will be called once the query has been aborted.
       
   186  */
       
   187 void evsql_query_abort (struct evsql_trans *trans, struct evsql_query *query);
       
   188 
       
   189 /*
       
   190  * Commit a transaction, calling done_fn if it was succesfull (error_fn otherwise).
       
   191  *
       
   192  * trans must be idle, just like for evsql_query.
       
   193  *
       
   194  * done_fn will never be called directly, always via the event loop.
       
   195  *
       
   196  * You cannot abort a COMMIT, calling trans_abort on trans after a succesful trans_commit is a FATAL error.
       
   197  */
       
   198 int evsql_trans_commit (struct evsql_trans *trans);
       
   199 
       
   200 /*
       
   201  * Abort a transaction, rolling it back. No callbacks will be called.
       
   202  *
       
   203  * You cannot abort a COMMIT, calling trans_abort on trans after a succesful trans_commit is a FATAL error.
       
   204  */
       
   205 void evsql_trans_abort (struct evsql_trans *trans);
       
   206 
       
   207 /*
       
   208  * Transaction-handling functions
       
   209  */
       
   210 
       
   211 // error string, meant to be called from evsql_trans_error_cb
       
   212 const char *evsql_trans_error (struct evsql_trans *trans);
       
   213 
       
   214 /*
       
   215  * Param-building functions
       
   216  */
       
   217 int evsql_param_binary (struct evsql_query_params *params, size_t param, const char *ptr, size_t len);
       
   218 int evsql_param_string (struct evsql_query_params *params, size_t param, const char *ptr);
       
   219 int evsql_param_uint16 (struct evsql_query_params *params, size_t param, uint16_t uval);
       
   220 int evsql_param_uint32 (struct evsql_query_params *params, size_t param, uint32_t uval);
       
   221 int evsql_param_null   (struct evsql_query_params *params, size_t param);
       
   222 int evsql_params_clear (struct evsql_query_params *params);
       
   223 
       
   224 /*
       
   225  * Query-handling functions
       
   226  */
       
   227 
       
   228 // print out a textual repr of the given query/params via DEBUG
       
   229 void evsql_query_debug (const char *sql, const struct evsql_query_params *params);
       
   230 
       
   231 /*
       
   232  * Result-handling functions
       
   233  */
       
   234 
       
   235 // get error message associated with function
       
   236 const char *evsql_result_error (const struct evsql_result_info *res);
       
   237 
       
   238 // number of rows in the result
       
   239 size_t evsql_result_rows (const struct evsql_result_info *res);
       
   240 
       
   241 // number of columns in the result
       
   242 size_t evsql_result_cols (const struct evsql_result_info *res);
       
   243 
       
   244 // number of affected rows for UPDATE/INSERT
       
   245 size_t evsql_result_affected (const struct evsql_result_info *res);
       
   246 
       
   247 // fetch the raw binary value from a result set, and return it via ptr
       
   248 // if size is nonzero, check that the size of the field data matches
       
   249 int evsql_result_binary (const struct evsql_result_info *res, size_t row, size_t col, const char **ptr, size_t *size, int nullok);
       
   250 int evsql_result_string (const struct evsql_result_info *res, size_t row, size_t col, const char **ptr, int nullok);
       
   251 
       
   252 // fetch certain kinds of values from a binary result set
       
   253 int evsql_result_uint16 (const struct evsql_result_info *res, size_t row, size_t col, uint16_t *uval, int nullok);
       
   254 int evsql_result_uint32 (const struct evsql_result_info *res, size_t row, size_t col, uint32_t *uval, int nullok);
       
   255 int evsql_result_uint64 (const struct evsql_result_info *res, size_t row, size_t col, uint64_t *uval, int nullok);
       
   256 
       
   257 // release the result set, freeing its memory
       
   258 void evsql_result_free (const struct evsql_result_info *res);
       
   259 
       
   260 // platform-dependant aliases
       
   261 #define evsql_result_ushort evsql_result_uint16
       
   262 
       
   263 #if _LP64
       
   264 #define evsql_result_ulong evsql_result_uint64
       
   265 #else
       
   266 #define evsql_result_ulong evsql_result_uint32
       
   267 #endif /* _LP64 */
       
   268 
       
   269 /*
       
   270  * Close a connection. Callbacks for waiting queries will not be run.
       
   271  *
       
   272  * XXX: not implemented yet.
       
   273  */
       
   274 void evsql_close (struct evsql *evsql);
       
   275 
       
   276 #endif /* EVSQL_H */