3 #include "lib/signals.h"
6 #include <event2/event.h>
7 #include <event2/event_struct.h>
10 #define CONNINFO_DEFAULT "dbname=dbfs port=5433"
12 struct evsql_test_ctx {
14 struct evsql_trans *trans;
18 void query_send (struct evsql *db, struct evsql_trans *trans);
21 void query_timer (int fd, short what, void *arg) {
22 struct evsql *db = arg;
24 INFO("[evsql_test.timer] *tick*");
29 void query_start (struct event_base *base, struct evsql *db) {
30 static struct event ev;
31 struct timeval tv = { 5, 0 };
33 evperiodic_assign(&ev, base, &tv, &query_timer, db);
36 INFO("[evsql_test.timer_start] started timer");
39 void query_results (struct evsql_result *result, void *arg) {
40 struct evsql *db = arg;
45 static struct evsql_result_info result_info = {
47 { EVSQL_FMT_BINARY, EVSQL_TYPE_UINT32 },
53 assert(evsql_result_begin(&result_info, result) == 0);
56 assert(evsql_result_next(result,
61 INFO("[evsql_test.results] got result: %p: val=%lu", result, (unsigned long) val);
64 evsql_result_end(result);
67 void query_send (struct evsql *db, struct evsql_trans *trans) {
68 struct evsql_query *query = NULL;
69 static int query_id = 0;
71 static struct evsql_query_info query_info = {
72 .sql = "SELECT $1::int4 + 5",
75 { EVSQL_FMT_BINARY, EVSQL_TYPE_UINT32 },
81 if ((query = evsql_query_exec(db, trans, &query_info, query_results, db,
84 WARNING("evsql_query_exec failed");
86 INFO("[evsql_test.query_send] enqueued query, trans=%p: %p: %d", trans, query, query_id);
89 void trans_commit (struct evsql_test_ctx *ctx) {
90 if (evsql_trans_commit(ctx->trans))
91 FATAL("evsql_trans_commit failed");
93 INFO("[evsql_test.trans_commit] commiting transaction");
96 void trans_insert_result (struct evsql_result *res, void *arg) {
97 struct evsql_test_ctx *ctx = arg;
104 static struct evsql_result_info result_info = {
106 { EVSQL_FMT_BINARY, EVSQL_TYPE_UINT32 },
107 { EVSQL_FMT_BINARY, EVSQL_TYPE_STRING },
113 if ((err = evsql_result_begin(&result_info, res)))
114 EFATAL(err, "query failed%s", err == EIO ? evsql_result_error(res) : "");
116 INFO("[evsql_test.insert] got %zu rows:", evsql_result_rows(res));
119 while ((err = evsql_result_next(res, &id, &str)) > 0) {
120 INFO("\t%-4lu %s", (unsigned long) id, str);
124 EFATAL(err, "evsql_result_next failed");
129 evsql_result_end(res);
131 // commit the transaction
135 void trans_insert (struct evsql_test_ctx *ctx) {
136 struct evsql_query *query = NULL;
139 static struct evsql_query_info query_info = {
140 .sql = "INSERT INTO evsql_test (str) VALUES ($1::varchar), ($2::varchar) RETURNING id, str",
143 { EVSQL_FMT_BINARY, EVSQL_TYPE_STRING },
144 { EVSQL_FMT_BINARY, EVSQL_TYPE_STRING },
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"
155 INFO("[evsql_test.insert] enqueued query: %p", query);
158 void trans_create_result (struct evsql_result *res, void *arg) {
159 struct evsql_test_ctx *ctx = arg;
162 if (evsql_result_check(res))
163 FATAL("query failed: %s", evsql_result_error(res));
165 INFO("[evsql_test.create_result] table created succesfully: %p", res);
168 evsql_result_free(res);
174 void trans_create_query (struct evsql_test_ctx *ctx) {
175 struct evsql_query *query = NULL;
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",
182 // { EVSQL_FMT_BINARY, EVSQL_TYPE_STRING },
188 assert((query = evsql_query_exec(ctx->db, ctx->trans, &query_info, trans_create_result, ctx
189 // (const char *) "foobar"
192 INFO("[evsql_test.trans_create_query] enqueued query: %p", query);
195 void trans_error (struct evsql_trans *trans, void *arg) {
196 struct evsql_test_ctx *ctx = arg;
198 FATAL("[evsql_test.trans_error] failure: trans=%p: %s", ctx->trans, evsql_trans_error(trans));
201 void trans_ready (struct evsql_trans *trans, void *arg) {
202 struct evsql_test_ctx *ctx = arg;
204 INFO("[evsql_test.trans_ready] ready");
206 trans_create_query(ctx);
209 void trans_done (struct evsql_trans *trans, void *arg) {
210 struct evsql_test_ctx *ctx = arg;
212 INFO("[evsql_test.trans_done] done: trans=%p", ctx->trans);
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,
221 INFO("[evsql_test.begin_trans] created transaction");
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;
229 const char *db_conninfo;
232 db_conninfo = CONNINFO_DEFAULT;
235 if ((ev_base = event_base_new()) == NULL)
236 ERROR("event_base_new");
239 if ((signals = signals_default(ev_base)) == NULL)
240 ERROR("signals_default");
243 if ((ctx.db = evsql_new_pq(ev_base, db_conninfo, NULL, NULL)) == NULL)
244 ERROR("evsql_new_pq");
247 query_send(ctx.db, NULL);
250 begin_transaction(&ctx);
253 query_send(ctx.db, NULL);
256 query_start(ev_base, ctx.db);
259 INFO("[evsql_test.main] running libevent loop");
261 if (event_base_dispatch(ev_base))
262 PERROR("event_base_dispatch");
268 /* evsql_close(db); */
272 signals_free(signals);
275 event_base_free(ev_base);