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 */ |
|