summaryrefslogtreecommitdiff
path: root/libpqpp/pq-cursorselectcommand.cpp
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2016-04-24 14:34:16 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2016-04-24 14:40:20 +0100
commitedddd401b6a658613fd5058b6ba0fad30813402d (patch)
tree228efaa682b23f1b0f6821efae7d298ffe65fe1a /libpqpp/pq-cursorselectcommand.cpp
parentDon't attempt to close cursors when in failed transaction (it's failed and re... (diff)
downloadlibdbpp-postgresql-edddd401b6a658613fd5058b6ba0fad30813402d.tar.bz2
libdbpp-postgresql-edddd401b6a658613fd5058b6ba0fad30813402d.tar.xz
libdbpp-postgresql-edddd401b6a658613fd5058b6ba0fad30813402d.zip
Rename SelectCommand to CursorSelectCommand
Diffstat (limited to 'libpqpp/pq-cursorselectcommand.cpp')
-rw-r--r--libpqpp/pq-cursorselectcommand.cpp113
1 files changed, 113 insertions, 0 deletions
diff --git a/libpqpp/pq-cursorselectcommand.cpp b/libpqpp/pq-cursorselectcommand.cpp
new file mode 100644
index 0000000..fe097a5
--- /dev/null
+++ b/libpqpp/pq-cursorselectcommand.cpp
@@ -0,0 +1,113 @@
+#include "pq-cursorselectcommand.h"
+#include "pq-connection.h"
+#include "pq-column.h"
+#include "pq-error.h"
+
+PQ::CursorSelectCommand::CursorSelectCommand(Connection * conn, const std::string & sql, unsigned int no) :
+ DB::Command(sql),
+ DB::SelectCommand(sql),
+ PQ::Command(conn, sql, no),
+ executed(false),
+ txOpened(false),
+ nTuples(0),
+ tuple(0),
+ fTuples(35),
+ execRes(NULL),
+ s_declare(mkdeclare()),
+ s_fetch(mkfetch()),
+ s_close(mkclose())
+{
+}
+
+PQ::CursorSelectCommand::~CursorSelectCommand()
+{
+ if (execRes) {
+ PQclear(execRes);
+ }
+ if (executed && PQtransactionStatus(c->conn) != PQTRANS_INERROR) {
+ c->checkResultFree((PQexec(c->conn, s_close.c_str())), PGRES_COMMAND_OK);
+ }
+ if (txOpened) {
+ c->commitTx();
+ }
+}
+
+std::string
+PQ::CursorSelectCommand::mkdeclare() const
+{
+ std::string psql;
+ psql.reserve(sql.length() + 40);
+ psql += "DECLARE ";
+ psql += stmntName;
+ psql += " CURSOR FOR ";
+ prepareSql(psql, sql);
+ return psql;
+}
+
+std::string
+PQ::CursorSelectCommand::mkfetch() const
+{
+ char buf[BUFSIZ];
+ snprintf(buf, sizeof(buf), "FETCH %d IN %s", fTuples, stmntName.c_str());
+ return buf;
+}
+
+std::string
+PQ::CursorSelectCommand::mkclose() const
+{
+ char buf[BUFSIZ];
+ snprintf(buf, sizeof(buf), "CLOSE %s", stmntName.c_str());
+ return buf;
+}
+
+void
+PQ::CursorSelectCommand::execute()
+{
+ if (!executed) {
+ if (!c->inTx()) {
+ c->beginTx();
+ txOpened = true;
+ }
+ execRes = c->checkResult(
+ PQexecParams(c->conn, s_declare.c_str(), values.size(), NULL, &values.front(), &lengths.front(), NULL, 0),
+ PGRES_COMMAND_OK);
+ fetchTuples();
+ unsigned int nFields = PQnfields(execRes);
+ for (unsigned int f = 0; f < nFields; f += 1) {
+ insertColumn(DB::ColumnPtr(new Column(this, f)));
+ }
+ executed = true;
+ }
+}
+
+void
+PQ::CursorSelectCommand::fetchTuples()
+{
+ if (execRes) {
+ PQclear(execRes);
+ }
+ execRes = NULL;
+ execRes = c->checkResult(PQexec(c->conn, s_fetch.c_str()), PGRES_TUPLES_OK);
+ nTuples = PQntuples(execRes);
+ tuple = -1;
+}
+
+bool
+PQ::CursorSelectCommand::fetch()
+{
+ execute();
+ if ((tuple >= (nTuples - 1)) && (nTuples == fTuples)) {
+ fetchTuples();
+ }
+ if (tuple++ < (nTuples - 1)) {
+ return true;
+ }
+ else {
+ PQclear(PQexec(c->conn, s_close.c_str()));
+ PQclear(execRes);
+ execRes = NULL;
+ executed = false;
+ return false;
+ }
+}
+