terom@56: #ifndef EVSQL_INTERNAL_H terom@56: #define EVSQL_INTERNAL_H terom@56: terom@56: /* terom@56: * Internal interfaces terom@56: */ terom@56: terom@56: #include terom@56: terom@56: #include terom@56: terom@59: #include "include/evsql.h" terom@56: #include "evpq.h" terom@56: terom@56: /* terom@56: * The engine type terom@56: */ terom@56: enum evsql_type { terom@56: EVSQL_EVPQ, // evpq terom@56: }; terom@56: terom@56: /* terom@56: * Contains the type, engine configuration, list of connections and waiting query queue. terom@56: */ terom@56: struct evsql { terom@56: // what event_base to use terom@56: struct event_base *ev_base; terom@56: terom@56: // what engine we use terom@56: enum evsql_type type; terom@56: terom@56: // callbacks terom@56: evsql_error_cb error_fn; terom@56: void *cb_arg; terom@56: terom@56: // engine-specific connection configuration terom@56: union { terom@56: const char *evpq; terom@56: } engine_conf; terom@56: terom@56: // list of connections that are open terom@56: LIST_HEAD(evsql_conn_list, evsql_conn) conn_list; terom@56: terom@56: // list of queries running or waiting to run terom@56: TAILQ_HEAD(evsql_query_queue, evsql_query) query_queue; terom@56: }; terom@56: terom@56: /* terom@56: * A single connection to the server. terom@56: * terom@56: * Contains the engine connection, may have a transaction associated, and may have a query associated. terom@56: */ terom@56: struct evsql_conn { terom@56: // evsql we belong to terom@56: struct evsql *evsql; terom@56: terom@56: // engine-specific connection info terom@56: union { terom@56: struct evpq_conn *evpq; terom@56: } engine; terom@56: terom@56: // our position in the conn list terom@56: LIST_ENTRY(evsql_conn) entry; terom@56: terom@56: // are we running a transaction? terom@56: struct evsql_trans *trans; terom@56: terom@56: // are we running a transactionless query? terom@56: struct evsql_query *query; terom@56: }; terom@56: terom@56: /* terom@56: * A single transaction. terom@56: * terom@56: * Has a connection associated and possibly a query (which will also be associated with the connection) terom@56: */ terom@56: struct evsql_trans { terom@56: // our evsql_conn/evsql terom@56: struct evsql *evsql; terom@56: struct evsql_conn *conn; terom@56: terom@56: // callbacks terom@56: evsql_trans_error_cb error_fn; terom@56: evsql_trans_ready_cb ready_fn; terom@56: evsql_trans_done_cb done_fn; terom@56: void *cb_arg; terom@56: terom@56: // the transaction type terom@56: enum evsql_trans_type type; terom@56: terom@56: // has evsql_trans_commit be called? terom@56: int has_commit : 1; terom@56: terom@56: // our current query terom@56: struct evsql_query *query; terom@56: terom@56: }; terom@56: terom@56: /* terom@45: * Backend result handle terom@45: */ terom@45: union evsql_result_handle { terom@45: PGresult *pq; terom@45: }; terom@45: terom@45: /* terom@56: * A single query. terom@56: * terom@56: * Has the info needed to exec the query (as these may be queued), and the callback/result info. terom@56: */ terom@56: struct evsql_query { terom@56: // the actual SQL query, this may or may not be ours, see _evsql_query_exec terom@56: char *command; terom@56: terom@56: // possible query params terom@44: struct evsql_query_params_pq { terom@56: int count; terom@56: terom@56: Oid *types; terom@56: const char **values; terom@56: int *lengths; terom@56: int *formats; terom@56: terom@45: // storage for numeric values terom@45: union evsql_item_value *item_vals; terom@45: terom@56: int result_format; terom@56: } params; terom@56: terom@56: // our callback terom@56: evsql_query_cb cb_fn; terom@56: void *cb_arg; terom@45: terom@45: // the result we get terom@45: union evsql_result_handle result; terom@56: terom@56: // our position in the query list terom@56: TAILQ_ENTRY(evsql_query) entry; terom@44: }; terom@56: terom@44: // the result terom@44: struct evsql_result { terom@45: struct evsql *evsql; terom@44: terom@45: // possible error code terom@45: int error; terom@45: terom@45: // the actual result terom@45: union evsql_result_handle result; terom@44: terom@44: // result_* state terom@44: struct evsql_result_info *info; terom@44: size_t row_offset; terom@56: }; terom@56: terom@44: terom@56: // maximum length for a 'BEGIN TRANSACTION ...' query terom@56: #define EVSQL_QUERY_BEGIN_BUF 512 terom@56: terom@56: // the should the OID of some valid psql type... *ANY* valid psql type, doesn't matter, only used for NULLs terom@56: // 16 = bool in 8.3 terom@56: #define EVSQL_PQ_ARBITRARY_TYPE_OID 16 terom@56: terom@44: /* terom@44: * Core query-submission interface. terom@44: * terom@44: * This performs some error-checking on the trans, allocates the evsql_query and does some basic initialization. terom@44: * terom@44: * This does not actually enqueue the query anywhere, no reference is stored anywhere. terom@44: * terom@44: * Returns the new evsql_query on success, NULL on failure. terom@44: */ terom@45: struct evsql_query *_evsql_query_new (struct evsql *evsql, struct evsql_trans *trans, evsql_query_cb query_fn, void *cb_arg); terom@44: terom@44: /* terom@44: * Begin processing the given query, which should now be fully filled out. terom@44: * terom@44: * If trans is given, it MUST be idle, and the query will be executed. Otherwise, it will either be executed directly terom@44: * or enqueued for future execution. terom@44: * terom@44: * Returns zero on success, nonzero on failure. terom@44: */ terom@45: int _evsql_query_enqueue (struct evsql *evsql, struct evsql_trans *trans, struct evsql_query *query, const char *command); terom@44: terom@44: /* terom@45: * Free the query and related resources, doesn't trigger any callbacks or remove from any queues. terom@45: * terom@45: * The command should already be taken care of (NULL). terom@44: */ terom@45: void _evsql_query_free (struct evsql_query *query); terom@44: terom@56: #endif /* EVSQL_INTERNAL_H */