diff -r 527d23bf6441 -r 02e539965ef4 src/evsql_test.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/evsql_test.c Sun Mar 08 01:33:45 2009 +0200 @@ -0,0 +1,279 @@ + +#include "evsql.h" +#include "lib/log.h" +#include "lib/signals.h" +#include "lib/misc.h" + +#include +#include +#include + +#define CONNINFO_DEFAULT "dbname=dbfs port=5433" + +struct evsql_test_ctx { + struct evsql *db; + struct evsql_trans *trans; +}; + +// forward-declare +void query_send (struct evsql *db, struct evsql_trans *trans); + + +void query_timer (int fd, short what, void *arg) { + struct evsql *db = arg; + + INFO("[evsql_test.timer] *tick*"); + + query_send(db, NULL); +} + +void query_start (struct event_base *base, struct evsql *db) { + static struct event ev; + struct timeval tv = { 5, 0 }; + + evperiodic_assign(&ev, base, &tv, &query_timer, db); + event_add(&ev, &tv); + + INFO("[evsql_test.timer_start] started timer"); +} + +void query_results (struct evsql_result *result, void *arg) { + struct evsql *db = arg; + uint32_t val; + + (void) db; + + static struct evsql_result_info result_info = { + 0, { + { EVSQL_FMT_BINARY, EVSQL_TYPE_UINT32 }, + { 0, 0 } + } + }; + + // begin + assert(evsql_result_begin(&result_info, result) == 0); + + // one row + assert(evsql_result_next(result, + &val + ) > 0); + + // print + INFO("[evsql_test.results] got result: %p: val=%lu", result, (unsigned long) val); + + // done + evsql_result_end(result); +} + +void query_send (struct evsql *db, struct evsql_trans *trans) { + struct evsql_query *query = NULL; + static int query_id = 0; + + static struct evsql_query_info query_info = { + .sql = "SELECT $1::int4 + 5", + + .params = { + { EVSQL_FMT_BINARY, EVSQL_TYPE_UINT32 }, + { 0, 0 } + } + }; + + // query + if ((query = evsql_query_exec(db, trans, &query_info, query_results, db, + (uint32_t) ++query_id + )) == NULL) + WARNING("evsql_query_exec failed"); + + INFO("[evsql_test.query_send] enqueued query, trans=%p: %p: %d", trans, query, query_id); +} + +void trans_commit (struct evsql_test_ctx *ctx) { + if (evsql_trans_commit(ctx->trans)) + FATAL("evsql_trans_commit failed"); + + INFO("[evsql_test.trans_commit] commiting transaction"); +} + +void trans_insert_result (struct evsql_result *res, void *arg) { + struct evsql_test_ctx *ctx = arg; + err_t err; + + // the result info + uint32_t id; + const char *str; + + static struct evsql_result_info result_info = { + 0, { + { EVSQL_FMT_BINARY, EVSQL_TYPE_UINT32 }, + { EVSQL_FMT_BINARY, EVSQL_TYPE_STRING }, + { 0, 0 } + } + }; + + // begin + if ((err = evsql_result_begin(&result_info, res))) + EFATAL(err, "query failed%s", err == EIO ? evsql_result_error(res) : ""); + + INFO("[evsql_test.insert] got %zu rows:", evsql_result_rows(res)); + + // iterate over rows + while ((err = evsql_result_next(res, &id, &str)) > 0) { + INFO("\t%-4lu %s", (unsigned long) id, str); + } + + if (err) + EFATAL(err, "evsql_result_next failed"); + + INFO("\t(done)"); + + // done + evsql_result_end(res); + + // commit the transaction + trans_commit(ctx); +} + +void trans_insert (struct evsql_test_ctx *ctx) { + struct evsql_query *query = NULL; + + // the query info + static struct evsql_query_info query_info = { + .sql = "INSERT INTO evsql_test (str) VALUES ($1::varchar), ($2::varchar) RETURNING id, str", + + .params = { + { EVSQL_FMT_BINARY, EVSQL_TYPE_STRING }, + { EVSQL_FMT_BINARY, EVSQL_TYPE_STRING }, + { 0, 0 } + } + }; + + // run the query + assert((query = evsql_query_exec(ctx->db, ctx->trans, &query_info, trans_insert_result, ctx, + (const char *) "row A", + (const char *) "row B" + )) != NULL); + + INFO("[evsql_test.insert] enqueued query: %p", query); +} + +void trans_create_result (struct evsql_result *res, void *arg) { + struct evsql_test_ctx *ctx = arg; + + // check + if (evsql_result_check(res)) + FATAL("query failed: %s", evsql_result_error(res)); + + INFO("[evsql_test.create_result] table created succesfully: %p", res); + + // free result + evsql_result_free(res); + + // insert + trans_insert(ctx); +} + +void trans_create_query (struct evsql_test_ctx *ctx) { + struct evsql_query *query = NULL; + + // the query info + static struct evsql_query_info query_info = { + .sql = "CREATE TEMPORARY TABLE evsql_test ( id serial4, str varchar(32) DEFAULT 'foobar' ) ON COMMIT DROP", + + .params = { +// { EVSQL_FMT_BINARY, EVSQL_TYPE_STRING }, + { 0, 0, } + } + }; + + // run the query + assert((query = evsql_query_exec(ctx->db, ctx->trans, &query_info, trans_create_result, ctx +// (const char *) "foobar" + )) != NULL); + + INFO("[evsql_test.trans_create_query] enqueued query: %p", query); +} + +void trans_error (struct evsql_trans *trans, void *arg) { + struct evsql_test_ctx *ctx = arg; + + FATAL("[evsql_test.trans_error] failure: trans=%p: %s", ctx->trans, evsql_trans_error(trans)); +} + +void trans_ready (struct evsql_trans *trans, void *arg) { + struct evsql_test_ctx *ctx = arg; + + INFO("[evsql_test.trans_ready] ready"); + + trans_create_query(ctx); +} + +void trans_done (struct evsql_trans *trans, void *arg) { + struct evsql_test_ctx *ctx = arg; + + INFO("[evsql_test.trans_done] done: trans=%p", ctx->trans); +} + +void begin_transaction (struct evsql_test_ctx *ctx) { + assert((ctx->trans = evsql_trans(ctx->db, EVSQL_TRANS_DEFAULT, + &trans_error, &trans_ready, &trans_done, + ctx + )) != NULL); + + INFO("[evsql_test.begin_trans] created transaction"); + } + +int main (int argc, char **argv) { + struct evsql_test_ctx ctx; + struct event_base *ev_base = NULL; + struct signals *signals = NULL; + + const char *db_conninfo; + + // parse args + db_conninfo = CONNINFO_DEFAULT; + + // init libevent + if ((ev_base = event_base_new()) == NULL) + ERROR("event_base_new"); + + // setup signals + if ((signals = signals_default(ev_base)) == NULL) + ERROR("signals_default"); + + // setup evsql + if ((ctx.db = evsql_new_pq(ev_base, db_conninfo, NULL, NULL)) == NULL) + ERROR("evsql_new_pq"); + + // send query + query_send(ctx.db, NULL); + + // being transaction + begin_transaction(&ctx); + + // send query + query_send(ctx.db, NULL); + + // start query timer + query_start(ev_base, ctx.db); + + // run libevent + INFO("[evsql_test.main] running libevent loop"); + + if (event_base_dispatch(ev_base)) + PERROR("event_base_dispatch"); + + // clean shutdown + +error : + if (ctx.db) { + /* evsql_close(db); */ + } + + if (signals) + signals_free(signals); + + if (ev_base) + event_base_free(ev_base); + +} +