src/evsql_test.c
branchnew-evsql
changeset 46 75cecfc4603b
parent 45 424ce5ab82fd
child 47 8c6c459eacb7
equal deleted inserted replaced
45:424ce5ab82fd 46:75cecfc4603b
     3 #include "lib/log.h"
     3 #include "lib/log.h"
     4 #include "lib/signals.h"
     4 #include "lib/signals.h"
     5 #include "lib/misc.h"
     5 #include "lib/misc.h"
     6 
     6 
     7 #include <event2/event.h>
     7 #include <event2/event.h>
       
     8 #include <event2/event_struct.h>
     8 #include <assert.h>
     9 #include <assert.h>
     9 
    10 
    10 #define CONNINFO_DEFAULT "dbname=dbfs port=5433"
    11 #define CONNINFO_DEFAULT "dbname=dbfs port=5433"
    11 
    12 
       
    13 struct evsql_test_ctx {
       
    14     struct evsql *db;
       
    15     struct evsql_trans *trans;
       
    16 };
       
    17 
       
    18 // forward-declare
       
    19 void query_send (struct evsql *db, struct evsql_trans *trans);
       
    20 
       
    21 
       
    22 void query_timer (int fd, short what, void *arg) {
       
    23     struct evsql *db = arg;
       
    24     
       
    25     INFO("[evsql_test.timer] *tick*");
       
    26 
       
    27     query_send(db, NULL);
       
    28 }
       
    29 
       
    30 void query_start (struct event_base *base, struct evsql *db) {
       
    31     static struct event ev;
       
    32     struct timeval tv = { 5, 0 };
       
    33 
       
    34     evperiodic_assign(&ev, base, &tv, &query_timer, db);
       
    35     event_add(&ev, &tv);
       
    36 
       
    37     INFO("[evsql_test.timer_start] started timer");
       
    38 }
       
    39 
    12 void query_results (struct evsql_result *result, void *arg) {
    40 void query_results (struct evsql_result *result, void *arg) {
       
    41     struct evsql *db = arg;
    13     uint32_t val;
    42     uint32_t val;
       
    43 
       
    44     (void) db;
    14 
    45 
    15     static struct evsql_result_info result_info = {
    46     static struct evsql_result_info result_info = {
    16         0, {
    47         0, {
    17             {   EVSQL_FMT_BINARY,   EVSQL_TYPE_UINT32   },
    48             {   EVSQL_FMT_BINARY,   EVSQL_TYPE_UINT32   },
    18             {   0,                  0                   }
    49             {   0,                  0                   }
    46             {   0,                  0                   }
    77             {   0,                  0                   }
    47         }
    78         }
    48     };
    79     };
    49 
    80 
    50     // query
    81     // query
    51     assert((query = evsql_query_exec(db, trans, &query_info, query_results, NULL,
    82     if ((query = evsql_query_exec(db, trans, &query_info, query_results, db,
    52         (uint32_t) ++query_id
    83         (uint32_t) ++query_id
       
    84     )) == NULL)
       
    85         WARNING("evsql_query_exec failed");
       
    86 
       
    87     INFO("[evsql_test.query_send] enqueued query, trans=%p: %p: %d", trans, query, query_id);
       
    88 }
       
    89 
       
    90 void trans_insert_result (struct evsql_result *res, void *arg) {
       
    91     struct evsql_test_ctx *ctx = arg;
       
    92     err_t err;
       
    93     
       
    94     // the result info
       
    95     uint32_t id;
       
    96     const char *str;
       
    97 
       
    98     static struct evsql_result_info result_info = {
       
    99         0, {
       
   100             {   EVSQL_FMT_BINARY,   EVSQL_TYPE_UINT32   },
       
   101             {   EVSQL_FMT_BINARY,   EVSQL_TYPE_STRING   },
       
   102             {   0,                  0                   }
       
   103         }
       
   104     };
       
   105 
       
   106     // begin
       
   107     if ((err = evsql_result_begin(&result_info, res)))
       
   108         EFATAL(err, "query failed%s", err == EIO ? evsql_result_error(res) : "");
       
   109     
       
   110     INFO("[evsql_test.insert] got %zu rows:", evsql_result_rows(res));
       
   111 
       
   112     // iterate over rows
       
   113     while ((err = evsql_result_next(res, &id, &str)) > 0) {
       
   114         INFO("\t%-4lu %s", (unsigned long) id, str);
       
   115     }
       
   116 
       
   117     if (err)
       
   118         EFATAL(err, "evsql_result_next failed");
       
   119     
       
   120     INFO("\t(done)");
       
   121 
       
   122     // done
       
   123     evsql_result_end(res);
       
   124 }
       
   125 
       
   126 void trans_insert (struct evsql_test_ctx *ctx) {
       
   127     struct evsql_query *query = NULL;
       
   128 
       
   129     // the query info
       
   130     static struct evsql_query_info query_info = {
       
   131         .sql    = "INSERT INTO evsql_test (str) VALUES ($1::varchar), ($2::varchar) RETURNING id, str",
       
   132 
       
   133         .params = {
       
   134             {   EVSQL_FMT_BINARY,   EVSQL_TYPE_STRING   },
       
   135             {   EVSQL_FMT_BINARY,   EVSQL_TYPE_STRING   },
       
   136             {   0,                  0                   }
       
   137         }
       
   138     };
       
   139 
       
   140     // run the query
       
   141     assert((query = evsql_query_exec(ctx->db, ctx->trans, &query_info, trans_insert_result, ctx,
       
   142         (const char *) "row A",
       
   143         (const char *) "row B"
    53     )) != NULL);
   144     )) != NULL);
    54 
   145 
    55     INFO("[evsql_test.query_send] enqueued query, trans=%p: %p: %d", trans, query, query_id);
   146     INFO("[evsql_test.insert] enqueued query: %p", query);
    56 }
   147 }
    57 
   148 
    58 void trans_create_result (struct evsql_result *res, void *arg) {
   149 void trans_create_result (struct evsql_result *res, void *arg) {
       
   150     struct evsql_test_ctx *ctx = arg;
       
   151 
    59     // check
   152     // check
    60     if (evsql_result_check(res))
   153     if (evsql_result_check(res))
    61         FATAL("query failed: %s", evsql_result_error(res));
   154         FATAL("query failed: %s", evsql_result_error(res));
    62     
   155     
    63     INFO("[evsql_test.create_result] table created succesfully: %p", res);
   156     INFO("[evsql_test.create_result] table created succesfully: %p", res);
    64 
   157 
    65     // free
   158     // free result
    66     evsql_result_free(res);
   159     evsql_result_free(res);
    67 }
   160 
    68 
   161     // insert
    69 void trans_create_query (struct evsql *db, struct evsql_trans *trans) {
   162     trans_insert(ctx);
       
   163 }
       
   164 
       
   165 void trans_create_query (struct evsql_test_ctx *ctx) {
    70     struct evsql_query *query = NULL;
   166     struct evsql_query *query = NULL;
    71 
   167 
    72     // the query info
   168     // the query info
    73     static struct evsql_query_info query_info = {
   169     static struct evsql_query_info query_info = {
    74         .sql    = "CREATE TEMPORARY TABLE evsql_test ( id serial4, str varchar(32) DEFAULT $1::varchar ) ON COMMIT DROP",
   170         .sql    = "CREATE TEMPORARY TABLE evsql_test ( id serial4, str varchar(32) DEFAULT 'foobar' ) ON COMMIT DROP",
    75 
   171 
    76         .params = {
   172         .params = {
    77             {   EVSQL_FMT_BINARY,   EVSQL_TYPE_STRING   },
   173 //            {   EVSQL_FMT_BINARY,   EVSQL_TYPE_STRING   },
    78             {   0,                  0,                  }
   174             {   0,                  0,                  }
    79         }
   175         }
    80     };
   176     };
    81 
   177 
    82     // run the query
   178     // run the query
    83     assert((query = evsql_query_exec(db, trans, &query_info, trans_create_result, NULL,
   179     assert((query = evsql_query_exec(ctx->db, ctx->trans, &query_info, trans_create_result, ctx
    84         (const char *) "foobar"
   180 //        (const char *) "foobar"
    85     )) != NULL);
   181     )) != NULL);
    86 
   182 
    87     INFO("[evsql_test.trans_create_query] enqueued query: %p", query);
   183     INFO("[evsql_test.trans_create_query] enqueued query: %p", query);
    88 }
   184 }
    89 
   185 
    90 void trans_error (struct evsql_trans *trans, void *arg) {
   186 void trans_error (struct evsql_trans *trans, void *arg) {
    91     struct evsql *db = arg;
   187     struct evsql_test_ctx *ctx = arg;
    92 
   188 
    93     FATAL("[evsql_test.trans_error] failure: %s", evsql_trans_error(trans));
   189     FATAL("[evsql_test.trans_error] failure: %s", evsql_trans_error(trans));
    94 }
   190 }
    95 
   191 
    96 void trans_ready (struct evsql_trans *trans, void *arg) {
   192 void trans_ready (struct evsql_trans *trans, void *arg) {
    97     struct evsql *db = arg;
   193     struct evsql_test_ctx *ctx = arg;
    98 
   194 
    99     INFO("[evsql_test.trans_ready] ready");
   195     INFO("[evsql_test.trans_ready] ready");
   100     
   196     
   101     trans_create_query(db, trans);
   197     trans_create_query(ctx);
   102 }
   198 }
   103 
   199 
   104 void trans_done (struct evsql_trans *trans, void *arg) {
   200 void trans_done (struct evsql_trans *trans, void *arg) {
   105     struct evsql *db = arg;
   201     struct evsql_test_ctx *ctx = arg;
   106 
   202 
   107     INFO("[evsql_test.trans_done] done");
   203     INFO("[evsql_test.trans_done] done");
   108 }
   204 }
   109 
   205 
   110 void begin_transaction (struct evsql *db) {
   206 void begin_transaction (struct evsql_test_ctx *ctx) {
   111     struct evsql_trans *trans;
   207     assert((ctx->trans = evsql_trans(ctx->db, EVSQL_TRANS_DEFAULT, 
   112 
       
   113     assert((trans = evsql_trans(db, EVSQL_TRANS_DEFAULT, 
       
   114         &trans_error, &trans_ready, &trans_done,
   208         &trans_error, &trans_ready, &trans_done,
   115         db
   209         ctx
   116     )) != NULL);
   210     )) != NULL);
   117 
   211 
   118     INFO("[evsql_test.begin_trans] created transaction");
   212     INFO("[evsql_test.begin_trans] created transaction");
   119  }
   213  }
   120 
   214 
   121 int main (int argc, char **argv) {
   215 int main (int argc, char **argv) {
       
   216     struct evsql_test_ctx ctx;
   122     struct event_base *ev_base = NULL;
   217     struct event_base *ev_base = NULL;
   123     struct signals *signals = NULL;
   218     struct signals *signals = NULL;
   124     struct evsql *db = NULL;
       
   125 
   219 
   126     const char *db_conninfo;
   220     const char *db_conninfo;
   127     
   221     
   128     // parse args
   222     // parse args
   129     db_conninfo = CONNINFO_DEFAULT;
   223     db_conninfo = CONNINFO_DEFAULT;
   135     // setup signals
   229     // setup signals
   136     if ((signals = signals_default(ev_base)) == NULL)
   230     if ((signals = signals_default(ev_base)) == NULL)
   137         ERROR("signals_default");
   231         ERROR("signals_default");
   138 
   232 
   139     // setup evsql
   233     // setup evsql
   140     if ((db = evsql_new_pq(ev_base, db_conninfo, NULL, NULL)) == NULL)
   234     if ((ctx.db = evsql_new_pq(ev_base, db_conninfo, NULL, NULL)) == NULL)
   141         ERROR("evsql_new_pq");
   235         ERROR("evsql_new_pq");
   142 
   236 
   143     // send query
   237     // send query
   144     query_send(db, NULL);
   238     query_send(ctx.db, NULL);
   145 
   239 
   146     // being transaction
   240     // being transaction
   147     begin_transaction(db);
   241     begin_transaction(&ctx);
   148 
   242 
   149     // send query
   243     // send query
   150     query_send(db, NULL);
   244     query_send(ctx.db, NULL);
       
   245 
       
   246     // start query timer
       
   247     query_start(ev_base, ctx.db);
   151 
   248 
   152     // run libevent
   249     // run libevent
   153     INFO("running libevent loop");
   250     INFO("[evsql_test.main] running libevent loop");
   154 
   251 
   155     if (event_base_dispatch(ev_base))
   252     if (event_base_dispatch(ev_base))
   156         PERROR("event_base_dispatch");
   253         PERROR("event_base_dispatch");
   157     
   254     
   158     // clean shutdown
   255     // clean shutdown
   159 
   256 
   160 error :
   257 error :
   161     if (db) {
   258     if (ctx.db) {
   162         /* evsql_close(db); */
   259         /* evsql_close(db); */
   163     }
   260     }
   164 
   261 
   165     if (signals)
   262     if (signals)
   166         signals_free(signals);
   263         signals_free(signals);