#pragma once #include #include #include #include #include #include namespace Pgsql { class Connection; /* This library has multiple layers. Layer 1 delivers lowlevel C++ wrappers for the basic libpq functionality. Adding automatic resource management. */ class ConnectionParams { public: std::string host; std::string hostaddr; unsigned short port = 5432; std::string dbname; std::string user; std::string password; int connect_timeout = -1; ///< -1 omit (ie uses default) std::string application_name; }; class ErrorDetails { public: static ErrorDetails createErrorDetailsFromPGresult(const PGresult *res); std::string state; ///< PG_DIAG_SQLSTATE Error code as listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html std::string severity; std::string messagePrimary; std::string messageDetail; std::string messageHint; int statementPosition; ///< First character is one, measured in characters not bytes! int internalPosition; std::string internalQuery; std::string context; std::string schemaName; std::string tableName; std::string columnName; std::string datatypeName; std::string constraintName; std::string sourceFile; std::string sourceLine; std::string sourceFunction; }; /** Non-copyable but movable wrapper for a postgresql result. */ class Result { public: // class iterator { // public: // iterator(Result &r, int rw) // : result(r), row(rw) // {} // iterator operator++() // { // iterator t(*this); // ++row; // return t; // } // iterator& operator++(int) // { // ++row; // return *this; // } // bool operator!=(const iterator &rhs) // { // assert() // } // private: // Result &result; // int row; // }; Result() = default; Result(PGresult *result); ~Result(); Result(const Result &rhs) = delete; Result& operator=(const Result &rhs) = delete; Result(Result &&rhs); Result& operator=(Result &&rhs); operator bool() const; ExecStatusType resultStatus(); std::string getResStatus(); /** Use this to retrieve an error code when this is an error result * * The possible code are listed in https://www.postgresql.org/docs/9.5/static/errcodes-appendix.html */ std::string diagSqlState(); /** Retrieves all the error fields. */ ErrorDetails diagDetails(); int getRows() const; int getCols() const; const char* const getColName(int idx) const; const char * getVal(int col, int row) const; // iterator begin(); private: PGresult *result = nullptr; }; class Canceller { public: Canceller(PGcancel *c); Canceller(const Canceller&) = delete; Canceller& operator=(const Canceller&) = delete; Canceller(Canceller&& rhs); Canceller& operator=(Canceller&& rhs); ~Canceller(); void cancel(); private: PGcancel *m_cancel; }; class Connection { public: Connection(); ~Connection(); Connection(const Connection &rhs) = delete; Connection& operator=(const Connection &rhs) = delete; Connection(Connection &&rhs); Connection& operator=(Connection &&rhs); // void connect(const ConnectionParams ¶ms); bool connect(const char *params); bool connect(const QString ¶ms) { return connect(params.toUtf8().data()); } bool connectStart(const char *params); bool connectStart(const QString ¶ms) { return connectStart(params.toUtf8().data()); } PostgresPollingStatusType connectPoll(); ConnStatusType status(); int socket(); void close(); Canceller getCancel(); std::string getErrorMessage() const; Result query(const char * command); Result query(const QString &command) { return query(command.toUtf8().data()); } bool sendQuery(const char * query); bool sendQuery(const QString &command) { return sendQuery(command.toUtf8().data()); } std::unique_ptr getResult(); bool consumeInput(); bool isBusy(); void setNoticeReceiver(std::function callback); private: PGconn *conn = nullptr; std::function notifyReceiver; static void notifyReceiveFunc(void *arg, const PGresult *result); }; class Field { public: std::string getName() const; private: //Tuples tuples; int field; // }; class Tuples { public: int getRowCount() const; int getColCount() const; Field getField(const std::string &fname); Field getField(const int idx); class const_iterator { public: const_iterator& operator++(); }; void rewind(); }; class OkResult: public Result { public: /** If the result is a data result then returns an interface for processing this data. The returned interface remains valid as long as this OkResult exists. */ Tuples* hasTuples(); }; // class ErrorResult: public Result { // // }; // class ITransaction { // public: // // Canceller Query(std::string query, // std::function on_success, // std::function on_cancelled, // std::function on_error); // // Canceller Query(std::string query, // std::function on_success, // std::function on_cancelled, // std::function on_error); // // // void Rollback( // std::function on_success, // std::function on_error); // void Commit( // std::function on_success, // std::function on_cancelled, // std::function on_error); // // }; }