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