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