PageRenderTime 104ms CodeModel.GetById 35ms app.highlight 31ms RepoModel.GetById 35ms app.codeStats 0ms

/mordor/pq/connection.h

http://github.com/mozy/mordor
C Header | 173 lines | 125 code | 30 blank | 18 comment | 0 complexity | b79c66da14f1263150fd97160ba47c26 MD5 | raw file
  1#ifndef __MORDOR_PQ_CONNECTION_H__
  2#define __MORDOR_PQ_CONNECTION_H__
  3// Copyright (c) 2010 Mozy, Inc.
  4
  5#include <boost/noncopyable.hpp>
  6#include <boost/date_time/posix_time/posix_time_types.hpp>
  7
  8#include "exception.h"
  9#include "preparedstatement.h"
 10
 11namespace Mordor {
 12
 13class Stream;
 14
 15namespace PQ {
 16
 17class Connection : boost::noncopyable
 18{
 19public:
 20    Connection(const std::string &conninfo, IOManager *ioManager = NULL,
 21        Scheduler *scheduler = NULL,
 22        bool connectImmediately = true);
 23
 24    ConnStatusType status();
 25
 26    void connect();
 27    /// @brief Resets the communication channel to the server.
 28    /// This function will close the connection to the server and attempt to
 29    /// reestablish a new connection to the same server, using all the same
 30    /// parameters previously used. This may be useful for error recovery if a
 31    /// working connection is lost.
 32    void reset();
 33
 34    std::string escape(const std::string &string);
 35    std::string escapeBinary(const std::string &blob);
 36
 37    /// @param name If non-empty, specifies to prepare this command on the
 38    /// server.  Statements prepared on the server msut have unique names
 39    /// (per-connection)
 40    PreparedStatement prepare(const std::string &command,
 41        const std::string &name = std::string(), PreparedStatement::ResultFormat = PreparedStatement::BINARY);
 42    /// Create a PreparedStatement object representing a previously prepared
 43    /// statement on the server
 44    PreparedStatement find(const std::string &name);
 45
 46#define PQ_EXCEPTION_WRAPPER_EXECUTE(code) \
 47    try {                                  \
 48        return code;                       \
 49    } catch (Mordor::PQ::Exception &) {    \
 50        m_exceptioned = true;              \
 51        throw;                             \
 52    }
 53
 54    Result execute(const std::string &command)
 55    { PQ_EXCEPTION_WRAPPER_EXECUTE(prepare(command).execute()); }
 56    template <class T1>
 57    Result execute(const std::string &command, const T1 &param1)
 58    { PQ_EXCEPTION_WRAPPER_EXECUTE(prepare(command).execute(param1)); }
 59    template <class T1, class T2>
 60    Result execute(const std::string &command, const T1 &param1, const T2 &param2)
 61    { PQ_EXCEPTION_WRAPPER_EXECUTE(prepare(command).execute(param1, param2)); }
 62    template <class T1, class T2, class T3>
 63    Result execute(const std::string &command, const T1 &param1, const T2 &param2, const T3 &param3)
 64    { PQ_EXCEPTION_WRAPPER_EXECUTE(prepare(command).execute(param1, param2, param3)); }
 65    template <class T1, class T2, class T3, class T4>
 66    Result execute(const std::string &command, const T1 &param1, const T2 &param2, const T3 &param3, const T4 &param4)
 67    { PQ_EXCEPTION_WRAPPER_EXECUTE(prepare(command).execute(param1, param2, param3, param4)); }
 68    template <class T1, class T2, class T3, class T4, class T5>
 69    Result execute(const std::string &command, const T1 &param1, const T2 &param2, const T3 &param3, const T4 &param4, const T5 &param5)
 70    { PQ_EXCEPTION_WRAPPER_EXECUTE(prepare(command).execute(param1, param2, param3, param4, param5)); }
 71    template <class T1, class T2, class T3, class T4, class T5, class T6>
 72    Result execute(const std::string &command, const T1 &param1, const T2 &param2, const T3 &param3, const T4 &param4, const T5 &param5, const T6 &param6)
 73    { PQ_EXCEPTION_WRAPPER_EXECUTE(prepare(command).execute(param1, param2, param3, param4, param5, param6)); }
 74    template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
 75    Result execute(const std::string &command, const T1 &param1, const T2 &param2, const T3 &param3, const T4 &param4, const T5 &param5, const T6 &param6, const T7 &param7)
 76    { PQ_EXCEPTION_WRAPPER_EXECUTE(prepare(command).execute(param1, param2, param3, param4, param5, param6, param7)); }
 77    template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
 78    Result execute(const std::string &command, const T1 &param1, const T2 &param2, const T3 &param3, const T4 &param4, const T5 &param5, const T6 &param6, const T7 &param7, const T8 &param8)
 79    { PQ_EXCEPTION_WRAPPER_EXECUTE(prepare(command).execute(param1, param2, param3, param4, param5, param6, param7, param8)); }
 80    template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
 81    Result execute(const std::string &command, const T1 &param1, const T2 &param2, const T3 &param3, const T4 &param4, const T5 &param5, const T6 &param6, const T7 &param7, const T8 &param8, const T9 &param9)
 82    { PQ_EXCEPTION_WRAPPER_EXECUTE(prepare(command).execute(param1, param2, param3, param4, param5, param6, param7, param8, param9)); }
 83
 84#undef PQ_EXCEPTION_WRAPPER_EXECUTE
 85
 86    /// Bulk copy data to the server
 87    struct CopyParams
 88    {
 89    protected:
 90        CopyParams(const std::string &table, boost::shared_ptr<PGconn> conn,
 91            SchedulerType *scheduler);
 92
 93    public:
 94        /// Execute
 95        virtual boost::shared_ptr<Stream> operator()() = 0;
 96
 97        CopyParams &columns(const std::vector<std::string> &columns);
 98
 99        CopyParams &binary();
100        CopyParams &csv();
101
102        CopyParams &delimiter(char delimiter);
103        CopyParams &nullString(const std::string &nullString);
104        CopyParams &header();
105        CopyParams &quote(char quote);
106        CopyParams &escape(char escape);
107        CopyParams &notNullQuoteColumns(const std::vector<std::string> &columns);
108
109    protected:
110        boost::shared_ptr<Stream> execute(bool out);
111
112    private:
113        std::string m_table;
114        SchedulerType *m_scheduler;
115        boost::shared_ptr<PGconn> m_conn;
116        std::vector<std::string> m_columns, m_notNullQuoteColumns;
117        bool m_binary, m_csv, m_header;
118        char m_delimiter, m_quote, m_escape;
119        std::string m_nullString;
120    };
121
122    struct CopyInParams : public CopyParams
123    {
124    private:
125        friend class Connection;
126        CopyInParams(const std::string &table, boost::shared_ptr<PGconn> conn,
127            SchedulerType *scheduler)
128            : CopyParams(table, conn, scheduler)
129        {}
130
131    public:
132        /// Execute
133        boost::shared_ptr<Stream> operator()();
134    };
135
136    struct CopyOutParams : public CopyParams
137    {
138    private:
139        friend class Connection;
140        CopyOutParams(const std::string &table, boost::shared_ptr<PGconn> conn,
141            SchedulerType *scheduler)
142            : CopyParams(table, conn, scheduler)
143        {}
144
145    public:
146        /// Execute
147        boost::shared_ptr<Stream> operator()();
148    };
149
150    /// See http://www.postgresql.org/docs/current/static/sql-copy.html for the
151    /// data format the server is expecting
152    CopyInParams copyIn(const std::string &table);
153    CopyOutParams copyOut(const std::string &table);
154
155    const PGconn *conn() const { return m_conn.get(); }
156
157private:
158    std::string m_conninfo;
159    SchedulerType *m_scheduler;
160    boost::shared_ptr<PGconn> m_conn;
161    bool m_exceptioned;
162};
163
164// Internal functions
165#ifndef WIN32
166void flush(PGconn *conn, SchedulerType *scheduler);
167PGresult *nextResult(PGconn *conn, SchedulerType *scheduler);
168#endif
169std::string escape(PGconn *conn, const std::string &string);
170
171}}
172
173#endif