src/internal.h
author Tero Marttila <terom@fixme.fi>
Sun, 08 Mar 2009 01:40:26 +0200
changeset 59 54a2e6be81a7
parent 58 02e539965ef4
child 64 83d53afa2551
permissions -rw-r--r--
move include to src/include
#ifndef EVSQL_INTERNAL_H
#define EVSQL_INTERNAL_H

/*
 * Internal interfaces
 */

#include <sys/queue.h>

#include <event2/event.h>

#include "include/evsql.h"
#include "evpq.h"

/*
 * The engine type
 */
enum evsql_type {
    EVSQL_EVPQ,     // evpq
};

/*
 * Contains the type, engine configuration, list of connections and waiting query queue.
 */
struct evsql {
    // what event_base to use
    struct event_base *ev_base;

    // what engine we use
    enum evsql_type type;

    // callbacks
    evsql_error_cb error_fn;
    void *cb_arg;
    
    // engine-specific connection configuration
    union {
        const char *evpq;
    } engine_conf;

    // list of connections that are open
    LIST_HEAD(evsql_conn_list, evsql_conn) conn_list;
   
    // list of queries running or waiting to run
    TAILQ_HEAD(evsql_query_queue, evsql_query) query_queue;
};

/*
 * A single connection to the server.
 *
 * Contains the engine connection, may have a transaction associated, and may have a query associated.
 */
struct evsql_conn {
    // evsql we belong to
    struct evsql *evsql;

    // engine-specific connection info
    union {
        struct evpq_conn *evpq;
    } engine;

    // our position in the conn list
    LIST_ENTRY(evsql_conn) entry;

    // are we running a transaction?
    struct evsql_trans *trans;

    // are we running a transactionless query?
    struct evsql_query *query;
};

/*
 * A single transaction.
 *
 * Has a connection associated and possibly a query (which will also be associated with the connection)
 */
struct evsql_trans {
    // our evsql_conn/evsql
    struct evsql *evsql;
    struct evsql_conn *conn;
    
    // callbacks
    evsql_trans_error_cb error_fn;
    evsql_trans_ready_cb ready_fn;
    evsql_trans_done_cb done_fn;
    void *cb_arg;

    // the transaction type
    enum evsql_trans_type type;

    // has evsql_trans_commit be called?
    int has_commit : 1;

    // our current query
    struct evsql_query *query;

};

/*
 * Backend result handle
 */
union evsql_result_handle {
    PGresult *pq;
};

/*
 * A single query.
 *
 * Has the info needed to exec the query (as these may be queued), and the callback/result info.
 */
struct evsql_query {
    // the actual SQL query, this may or may not be ours, see _evsql_query_exec
    char *command;
    
    // possible query params
    struct evsql_query_params_pq {
        int count;

        Oid *types;
        const char **values;
        int *lengths;
        int *formats;

        // storage for numeric values
        union evsql_item_value *item_vals;

        int result_format;
    } params;

    // our callback
    evsql_query_cb cb_fn;
    void *cb_arg;
        
    // the result we get
    union evsql_result_handle result;

    // our position in the query list
    TAILQ_ENTRY(evsql_query) entry;
};

// the result
struct evsql_result {
    struct evsql *evsql;

    // possible error code
    int error;
    
    // the actual result
    union evsql_result_handle result;

    // result_* state
    struct evsql_result_info *info;
    size_t row_offset;
};


// maximum length for a 'BEGIN TRANSACTION ...' query
#define EVSQL_QUERY_BEGIN_BUF 512

// the should the OID of some valid psql type... *ANY* valid psql type, doesn't matter, only used for NULLs
// 16 = bool in 8.3
#define EVSQL_PQ_ARBITRARY_TYPE_OID 16

/*
 * Core query-submission interface.
 *
 * This performs some error-checking on the trans, allocates the evsql_query and does some basic initialization.
 *
 * This does not actually enqueue the query anywhere, no reference is stored anywhere.
 *
 * Returns the new evsql_query on success, NULL on failure.
 */
struct evsql_query *_evsql_query_new (struct evsql *evsql, struct evsql_trans *trans, evsql_query_cb query_fn, void *cb_arg);

/*
 * Begin processing the given query, which should now be fully filled out.
 *
 * If trans is given, it MUST be idle, and the query will be executed. Otherwise, it will either be executed directly
 * or enqueued for future execution.
 *
 * Returns zero on success, nonzero on failure.
 */
int _evsql_query_enqueue (struct evsql *evsql, struct evsql_trans *trans, struct evsql_query *query, const char *command);

/*
 * 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).
 */
void _evsql_query_free (struct evsql_query *query);

#endif /* EVSQL_INTERNAL_H */