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