--- a/src/core.c Sun Mar 08 01:16:54 2009 +0200
+++ b/src/core.c Sun Mar 08 01:33:45 2009 +0200
@@ -63,12 +63,7 @@
return err;
}
-/*
- * Free the query and related resources, doesn't trigger any callbacks or remove from any queues.
- *
- * The command should already be taken care of (NULL).
- */
-static void _evsql_query_free (struct evsql_query *query) {
+void _evsql_query_free (struct evsql_query *query) {
if (!query)
return;
@@ -89,13 +84,17 @@
*
* The query has been aborted, it will simply be freed
*/
-static void _evsql_query_done (struct evsql_query *query, const struct evsql_result_info *res) {
+static void _evsql_query_done (struct evsql_query *query, struct evsql_result *res) {
if (res) {
if (query->cb_fn)
// call the callback
query->cb_fn(res, query->cb_arg);
- else
+ else {
WARNING("supressing cb_fn because query was aborted");
+
+ // free the results
+ evsql_result_free(res);
+ }
}
// free
@@ -105,7 +104,7 @@
/*
* XXX:
* /
-static void _evsql_destroy (struct evsql *evsql, const struct evsql_result_info *res) {
+static void _evsql_destroy (struct evsql *evsql, const struct evsql_result *res) {
struct evsql_query *query;
// clear the queue
@@ -184,11 +183,10 @@
* NOTE: Only for *TRANSACTIONLESS* queries.
*/
static void _evsql_query_fail (struct evsql* evsql, struct evsql_query *query) {
- struct evsql_result_info res; ZINIT(res);
+ struct evsql_result res; ZINIT(res);
// set up the result_info
res.evsql = evsql;
- res.trans = NULL;
res.error = 1;
// finish off the query
@@ -260,6 +258,9 @@
// look for waiting queries
while ((query = TAILQ_FIRST(&evsql->query_queue)) != NULL) {
+ // zero err
+ err = 0;
+
// dequeue
TAILQ_REMOVE(&evsql->query_queue, query, entry);
@@ -303,23 +304,23 @@
/*
* Callback for a trans's 'BEGIN' query, which means the transaction is now ready for use.
*/
-static void _evsql_trans_ready (const struct evsql_result_info *res, void *arg) {
- (void) arg;
+static void _evsql_trans_ready (struct evsql_result *res, void *arg) {
+ struct evsql_trans *trans = arg;
- assert(res->trans);
+ assert(trans != NULL);
// check for errors
if (res->error)
ERROR("transaction 'BEGIN' failed: %s", evsql_result_error(res));
// transaction is now ready for use
- res->trans->ready_fn(res->trans, res->trans->cb_arg);
+ trans->ready_fn(trans, trans->cb_arg);
// good
return;
error:
- _evsql_trans_fail(res->trans);
+ _evsql_trans_fail(trans);
}
/*
@@ -364,7 +365,7 @@
ERROR("trans_sql overflow: %d >= %d", ret, EVSQL_QUERY_BEGIN_BUF);
// execute the query
- if (evsql_query(evsql, trans, trans_sql, _evsql_trans_ready, NULL) == NULL)
+ if (evsql_query(evsql, trans, trans_sql, _evsql_trans_ready, trans) == NULL)
ERROR("evsql_query");
// success
@@ -403,14 +404,14 @@
assert(query != NULL);
// if we get multiple results, only return the first one
- if (query->result.evpq) {
+ if (query->result.pq) {
WARNING("[evsql] evpq query returned multiple results, discarding previous one");
- PQclear(query->result.evpq); query->result.evpq = NULL;
+ PQclear(query->result.pq); query->result.pq = NULL;
}
// remember the result
- query->result.evpq = result;
+ query->result.pq = result;
}
/*
@@ -419,28 +420,27 @@
static void _evsql_evpq_done (struct evpq_conn *_conn, void *arg) {
struct evsql_conn *conn = arg;
struct evsql_query *query = conn->query;
- struct evsql_result_info res; ZINIT(res);
+ struct evsql_result res; ZINIT(res);
assert(query != NULL);
// set up the result_info
res.evsql = conn->evsql;
- res.trans = conn->trans;
+ res.result = query->result;
- if (query->result.evpq == NULL) {
+ if (query->result.pq == NULL) {
// if a query didn't return any results (bug?), warn and fail the query
WARNING("[evsql] evpq query didn't return any results");
res.error = 1;
- } else if (strcmp(PQresultErrorMessage(query->result.evpq), "") != 0) {
+ } else if (strcmp(PQresultErrorMessage(query->result.pq), "") != 0) {
// the query failed with some error
res.error = 1;
- res.result.pq = query->result.evpq;
} else {
+ // the query succeeded \o/
res.error = 0;
- res.result.pq = query->result.evpq;
}
@@ -731,9 +731,9 @@
}
/*
- * Validate and allocate the basic stuff for a new query.
+ * Internal query functions
*/
-static struct evsql_query *_evsql_query_new (struct evsql *evsql, struct evsql_trans *trans, evsql_query_cb query_fn, void *cb_arg) {
+struct evsql_query *_evsql_query_new (struct evsql *evsql, struct evsql_trans *trans, evsql_query_cb query_fn, void *cb_arg) {
struct evsql_query *query = NULL;
// if it's part of a trans, then make sure the trans is idle
@@ -755,13 +755,7 @@
return NULL;
}
-/*
- * Handle a new query.
- *
- * For transactions this will associate the query and then execute it, otherwise this will either find an idle
- * connection and send the query, or enqueue it.
- */
-static int _evsql_query_enqueue (struct evsql *evsql, struct evsql_trans *trans, struct evsql_query *query, const char *command) {
+int _evsql_query_enqueue (struct evsql *evsql, struct evsql_trans *trans, struct evsql_query *query, const char *command) {
// transaction queries are handled differently
if (trans) {
// it's an in-transaction query
@@ -818,127 +812,25 @@
return -1;
}
-struct evsql_query *evsql_query (struct evsql *evsql, struct evsql_trans *trans, const char *command, evsql_query_cb query_fn, void *cb_arg) {
- struct evsql_query *query = NULL;
-
- // alloc new query
- if ((query = _evsql_query_new(evsql, trans, query_fn, cb_arg)) == NULL)
- goto error;
-
- // just execute the command string directly
- if (_evsql_query_enqueue(evsql, trans, query, command))
- goto error;
-
- // ok
- return query;
-
-error:
- _evsql_query_free(query);
-
- return NULL;
-}
-
-struct evsql_query *evsql_query_params (struct evsql *evsql, struct evsql_trans *trans, const char *command, const struct evsql_query_params *params, evsql_query_cb query_fn, void *cb_arg) {
- struct evsql_query *query = NULL;
- const struct evsql_query_param *param;
- int idx;
-
- // alloc new query
- if ((query = _evsql_query_new(evsql, trans, query_fn, cb_arg)) == NULL)
- goto error;
-
- // count the params
- for (param = params->list; param->type; param++)
- query->params.count++;
-
- // allocate the vertical storage for the parameters
- if (0
-
- || !(query->params.types = calloc(query->params.count, sizeof(Oid)))
- || !(query->params.values = calloc(query->params.count, sizeof(char *)))
- || !(query->params.lengths = calloc(query->params.count, sizeof(int)))
- || !(query->params.formats = calloc(query->params.count, sizeof(int)))
- )
- ERROR("calloc");
-
- // transform
- for (param = params->list, idx = 0; param->type; param++, idx++) {
- // `set for NULLs, otherwise not
- query->params.types[idx] = param->data_raw ? 0 : EVSQL_PQ_ARBITRARY_TYPE_OID;
-
- // values
- query->params.values[idx] = param->data_raw;
- // lengths
- query->params.lengths[idx] = param->length;
-
- // formats, binary if length is nonzero, but text for NULLs
- query->params.formats[idx] = param->length && param->data_raw ? 1 : 0;
- }
-
- // result format
- switch (params->result_fmt) {
- case EVSQL_FMT_TEXT:
- query->params.result_format = 0; break;
-
- case EVSQL_FMT_BINARY:
- query->params.result_format = 1; break;
-
- default:
- FATAL("params.result_fmt: %d", params->result_fmt);
- }
-
- // execute it
- if (_evsql_query_enqueue(evsql, trans, query, command))
- goto error;
-
-#ifdef DEBUG_ENABLED
- // debug it?
- DEBUG("evsql.%p: enqueued query=%p on trans=%p", evsql, query, trans);
- evsql_query_debug(command, params);
-#endif /* DEBUG_ENABLED */
-
- // ok
- return query;
-
-error:
- _evsql_query_free(query);
-
- return NULL;
-}
-
-void evsql_query_abort (struct evsql_trans *trans, struct evsql_query *query) {
- assert(query);
-
- if (trans) {
- // must be the right query
- assert(trans->query == query);
- }
-
- // just strip the callback and wait for it to complete as normal
- query->cb_fn = NULL;
-}
-
-void _evsql_trans_commit_res (const struct evsql_result_info *res, void *arg) {
- (void) arg;
-
- assert(res->trans);
+void _evsql_trans_commit_res (struct evsql_result *res, void *arg) {
+ struct evsql_trans *trans = arg;
// check for errors
if (res->error)
ERROR("transaction 'COMMIT' failed: %s", evsql_result_error(res));
// transaction is now done
- res->trans->done_fn(res->trans, res->trans->cb_arg);
+ trans->done_fn(trans, trans->cb_arg);
// release it
- _evsql_trans_release(res->trans);
+ _evsql_trans_release(trans);
// success
return;
error:
- _evsql_trans_fail(res->trans);
+ _evsql_trans_fail(trans);
}
int evsql_trans_commit (struct evsql_trans *trans) {
@@ -948,7 +840,7 @@
ERROR("cannot COMMIT because transaction is still busy");
// query
- if (evsql_query(trans->evsql, trans, sql, _evsql_trans_commit_res, NULL) == NULL)
+ if (evsql_query(trans->evsql, trans, sql, _evsql_trans_commit_res, trans) == NULL)
goto error;
// mark it as commited in case someone wants to abort it
@@ -961,37 +853,35 @@
return -1;
}
-void _evsql_trans_rollback_res (const struct evsql_result_info *res, void *arg) {
- (void) arg;
-
- assert(res->trans);
+void _evsql_trans_rollback_res (struct evsql_result *res, void *arg) {
+ struct evsql_trans *trans = arg;
// fail the connection on errors
if (res->error)
ERROR("transaction 'ROLLBACK' failed: %s", evsql_result_error(res));
// release it
- _evsql_trans_release(res->trans);
+ _evsql_trans_release(trans);
// success
return;
error:
// fail the connection too, errors are supressed
- _evsql_trans_fail(res->trans);
+ _evsql_trans_fail(trans);
}
/*
* Used as the ready_fn callback in case of abort, otherwise directly
*/
-void _evsql_trans_rollback (struct evsql_trans *trans, void *unused) {
+void _evsql_trans_rollback (struct evsql_trans *trans, void *arg) {
static const char *sql = "ROLLBACK TRANSACTION";
- (void) unused;
+ (void) arg;
// query
- if (evsql_query(trans->evsql, trans, sql, _evsql_trans_rollback_res, NULL) == NULL) {
- // fail the transaction/connection
+ if (evsql_query(trans->evsql, trans, sql, _evsql_trans_rollback_res, trans) == NULL) {
+ // fail the transaction/connection, errors are supressed
_evsql_trans_fail(trans);
}
@@ -1010,7 +900,7 @@
// gah, some query is running
WARNING("aborting pending query");
- // prepare to rollback once complete
+ // prepare to rollback once complete by hijacking ready_fn
trans->ready_fn = _evsql_trans_rollback;
// abort