]> granicus.if.org Git - postgresql/commitdiff
Bring in Leo's <lsh@lubrizol.com> massive changes to libpq++
authorMarc G. Fournier <scrappy@hub.org>
Thu, 13 Feb 1997 10:01:05 +0000 (10:01 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Thu, 13 Feb 1997 10:01:05 +0000 (10:01 +0000)
25 files changed:
src/interfaces/libpq++/Makefile
src/interfaces/libpq++/dependencies [new file with mode: 0644]
src/interfaces/libpq++/examples/Makefile
src/interfaces/libpq++/examples/testlibpq0.cc
src/interfaces/libpq++/examples/testlibpq1.cc
src/interfaces/libpq++/examples/testlibpq2.cc
src/interfaces/libpq++/examples/testlibpq3.cc
src/interfaces/libpq++/examples/testlibpq4.cc
src/interfaces/libpq++/examples/testlibpq4.sql [new file with mode: 0644]
src/interfaces/libpq++/examples/testlibpq5.cc [new file with mode: 0644]
src/interfaces/libpq++/examples/testlibpq5.sql [new file with mode: 0644]
src/interfaces/libpq++/examples/testlibpq6.cc [new file with mode: 0644]
src/interfaces/libpq++/examples/testlo.cc
src/interfaces/libpq++/libpq++.h [new file with mode: 0644]
src/interfaces/libpq++/pgconnection.cc
src/interfaces/libpq++/pgconnection.h [new file with mode: 0644]
src/interfaces/libpq++/pgcursordb.cc [new file with mode: 0644]
src/interfaces/libpq++/pgcursordb.h [new file with mode: 0644]
src/interfaces/libpq++/pgdatabase.h [new file with mode: 0644]
src/interfaces/libpq++/pgenv.cc
src/interfaces/libpq++/pgenv.h [new file with mode: 0644]
src/interfaces/libpq++/pglobject.cc
src/interfaces/libpq++/pglobject.h [new file with mode: 0644]
src/interfaces/libpq++/pgtransdb.cc [new file with mode: 0644]
src/interfaces/libpq++/pgtransdb.h [new file with mode: 0644]

index 941c07da4f226ca4f281bc3949448fb9d4cf490a..7707c186a31fe3107b2b2847f47455d17e08334b 100644 (file)
@@ -7,12 +7,16 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/Makefile,v 1.5 1996/11/18 01:43:54 bryanh Exp $
+#    $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/Makefile,v 1.6 1997/02/13 10:00:23 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
 SRCDIR= ..
 include ../Makefile.global
+SRCHEADERDIR = ../include
+LIBPQHEADERDIR = $(SRCHEADERDIR)/libpq
+
+LIBNAME= libpq++
 
 # We have to override -Werror, which makes warnings, fatal, because we
 # inevitably get the warning, "abstract declarator used as declaration"
@@ -22,48 +26,72 @@ CXXFLAGS= $(CFLAGS) -Wno-error
 
 INCLUDE_OPT= \
              -I../backend \
-             -I../include \
-             -I$(LIBPQDIR) 
+             -I$(SRCHEADERDIR) \
+             -I$(LIBPQDIR)
 
 CXXFLAGS+= $(INCLUDE_OPT)
+#CXXFLAGS+= -DDEBUG
 
 ifdef KRBVERS
 CXXFLAGS+= $(KRBFLAGS)
 endif
 
-OBJS= pgenv.o pgconnection.o pglobject.o
 
-all: libpq++.a examples
+OBJS = pgenv.o pgconnection.o pgtransdb.o pgcursordb.o pglobject.o
+
+all: $(LIBNAME).a install examples
 
-libpq++.a: $(OBJS)
+$(LIBNAME).a: $(OBJS)
 ifdef MK_NO_LORDER
-       $(AR) $(AROPT) libpq++.a $(OBJS)
+       $(AR) $(AROPT) $(LIBNAME).a $(OBJS)
 else
-       $(AR) $(AROPT) libpq++.a `lorder $(OBJS) | tsort`
+       $(AR) $(AROPT) $(LIBNAME).a `lorder $(OBJS) | tsort`
 endif
-       $(RANLIB) libpq++.a
+       $(RANLIB) $(LIBNAME).a
 
 .PHONY: examples
 examples:
        $(MAKE) -C examples all
 
 .PHONY: beforeinstall-headers install-headers 
-.PHONY: install install-libpq++ doc
-
-install: install-headers install-libpq++ doc
-
-install-headers: beforeinstall-headers libpq++.H
-       $(INSTALL) $(INSTLOPTS) libpq++.H $(HEADERDIR)/libpq++.H
+.PHONY: install install-$(LIBNAME) doc
+
+install: install-headers install-$(LIBNAME) doc
+
+LIBPGXXDIR = $(LIBNAME)
+LIBPGXXHEADERDIR = $(HEADERDIR)/$(LIBPGXXDIR)
+MAINHEADER = $(LIBNAME).h
+LIBPGXXHEADERS = pgenv.h \
+                pgconnection.h \
+                pgdatabase.h \
+                pgtransdb.h \
+                pgcursordb.h \
+                pglobject.h
+
+install-headers: beforeinstall-headers $(MAINHEADER)
+       @$(INSTALL) $(INSTLOPTS) $(MAINHEADER) $(HEADERDIR)/$(MAINHEADER)
+       @for i in ${LIBPGXXHEADERS}; do \
+               echo "Installing $(LIBPGXXHEADERDIR)/$$i."; \
+               $(INSTALL) $(INSTLOPTS) $$i $(LIBPGXXHEADERDIR)/$$i; \
+       done
 
 beforeinstall-headers:
        @if [ ! -d $(HEADERDIR) ]; then mkdir $(HEADERDIR); fi
+       @if [ ! -d $(LIBPGXXHEADERDIR) ]; then mkdir $(LIBPGXXHEADERDIR); fi
 
-install-libpq++: libpq++.a
-       $(INSTALL) $(INSTL_LIB_OPTS) libpq++.a $(DESTDIR)$(LIBDIR)/libpq++.a
+install-$(LIBNAME): $(LIBNAME).a
+       $(INSTALL) $(INSTL_LIB_OPTS) $(LIBNAME).a $(DESTDIR)$(LIBDIR)/$(LIBNAME).a
 
 doc:
        $(MAKE) -C man install
 
 clean:
-       rm libpq++.a $(OBJS)
+       rm $(LIBNAME).a $(OBJS)
        $(MAKE) -C examples clean
+
+
+###########################################################################
+# Dependencies for the library
+###########################################################################
+include ./dependencies
+
diff --git a/src/interfaces/libpq++/dependencies b/src/interfaces/libpq++/dependencies
new file mode 100644 (file)
index 0000000..89633e1
--- /dev/null
@@ -0,0 +1,36 @@
+###########################################################################
+# Dependencies for libpq++ C++ library for Postgres SQL
+# 
+# Author: Leo Shuster (lsh@lubrizol.com)
+###########################################################################
+pgenv.o ::     pgenv.cc \
+               pgenv.h
+
+pgconnection.o :: pgconnection.cc \
+                 pgconnection.h \
+                 pgenv.h \
+                 $(LIBPQDIR)/libpq-fe.h \
+                 $(LIBPQDIR)/fe-auth.h
+
+pgtransdb.o    :: pgtransdb.cc \
+                 pgtransdb.h \
+                 pgdatabase.h \
+                 pgconnection.h \
+                  pgenv.h \
+                  $(LIBPQDIR)/libpq-fe.h \
+                  $(LIBPQDIR)/fe-auth.h
+                  
+pgcursordb.o    :: pgcursordb.cc \
+                  pgcursordb.h \
+                  pgdatabase.h \
+                  pgconnection.h \
+                   pgenv.h \
+                   $(LIBPQDIR)/libpq-fe.h \
+                   $(LIBPQDIR)/fe-auth.h
+
+pglobject.o :: pglobject.cc \
+               pglobject.h \
+               pgconnection.h \
+               pgenv.h \
+               $(LIBPQDIR)/libpq-fe.h \
+               $(LIBPQHEADERDIR)/libpq-fs.h
index 21e0f38b7c4caf6917758715ac7a3e61f54469dd..c08806002b2ff670f7ff3fae4a32ad3ef8ac8a32 100644 (file)
@@ -5,6 +5,8 @@
 SRCDIR= ../..
 include ../../Makefile.global
 
+LIBNAME= libpq++
+
 # We have to override -Werror, which makes warnings, fatal, because we
 # inevitably get the warning, "abstract declarator used as declaration"
 # because of our inclusion of c.h and we don't know how to stop that.
@@ -15,8 +17,8 @@ INCLUDE_OPT= \
              -I.. \
              -I../../backend \
              -I../../include \
-             -I$(LIBPQDIR) 
-
+             -I$(LIBPQDIR) \
+             -I$(HEADERDIR)
 CXXFLAGS+= $(INCLUDE_OPT)
 
 LD_ADD+= -L.. -lpq++ -L$(LIBPQDIR) -lpq 
@@ -29,19 +31,21 @@ LD_ADD+= $(KRBLIBS)
 CXXFLAGS+= $(KRBFLAGS)
 endif
 
-PROGS= testlibpq0 testlibpq1 testlibpq2 testlibpq3 testlibpq4 testlo
+PROGS= testlibpq0 testlibpq1 testlibpq2 testlibpq3 \
+       testlibpq4 testlibpq5 testlibpq6 testlo
 
 all: submake $(PROGS)
 
-$(PROGS): % : %.cc ../libpq++.a
+$(PROGS): % : %.cc ../$(LIBNAME).a
        $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $@.cc $(LD_ADD)
 
 .PHONY: submake
 submake: 
-       $(MAKE) -C.. libpq++.a
+       $(MAKE) -C.. $(LIBNAME).a
 
-../libpq++.a:
-       $(MAKE) -C.. libpq++.a
+../$(LIBNAME).a:
+       $(MAKE) -C.. $(LIBNAME).a
 
 clean: 
        rm -f $(PROGS)
+
index e8adb21f1bef981dd54db7bc1341f1f075a20366..43f8e93d15ed031f9cf8167bbaa8af7732c0ba05 100644 (file)
@@ -9,41 +9,44 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/examples/Attic/testlibpq0.cc,v 1.2 1996/11/18 01:44:23 bryanh Exp $
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/examples/Attic/testlibpq0.cc,v 1.3 1997/02/13 10:00:42 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 
-#include <stdio.h>
-#include "libpq++.H"
+#include <iostream.h>
+#include <libpq++.h>
 
-int 
-main()
+int main()
 {
+  // Open the connection to the database and make sure it's OK
+  PgDatabase data("template1");
+  if ( data.ConnectionBad() ) {
+      cout << "Connection was unsuccessful..." << endl
+           << "Error message returned: " << data.ErrorMessage() << endl;
+      return 1;
+  }
+  else
+      cout << "Connection successful...  Enter queries below:" << endl;
+    
+  // Interactively obtain and execute queries
   ExecStatusType status;
-  PGenv env;
-  PGdatabase* data;
-
-  char buf[10000];
+  string buf;
   int done = 0;
-  data = new PGdatabase(&env, "template1");
-
-  if (data->status() == CONNECTION_BAD)
-    printf("connection was unsuccessful\n%s\n", data->errormessage());
-  else
-    printf("connection successful\n");
-
   while (!done)
     {
-      printf("> ");fflush(stdout);
-      if (gets(buf) && buf[0]!='\0')
-       if((status = data->exec(buf)) == PGRES_TUPLES_OK) 
-            data->printtuples(stdout, 1, "|", 1, 0);
-       else
-            printf("status = %d\nerrorMessage = %s\n", status,
-                                                  data->errormessage());
+      cout << "> ";
+      cout.flush();
+      getline(cin, buf);
+      if ( buf != "" )
+              if ( (status = data.Exec( buf.c_str() )) == PGRES_TUPLES_OK ) 
+                 data.DisplayTuples();
+              else
+                 cout << "No tuples returned..." << endl
+                      << "status = " << status << endl
+                      << "Error returned: " << data.ErrorMessage() << endl;
       else
-       done = 1;
-    }
-}
+              done = 1;
+      }
+  return 0;
+} // End main()
index 1d71f795583988620192489ea8be93bdbfaa009b..ef63cf70778377f3d5c0ccf8ba0bde00bc2c204b 100644 (file)
@@ -1,84 +1,67 @@
 /*
- * testlibpq.cc
+ * testlibpq1.cc
  *     Test the C++ version of LIBPQ, the POSTGRES frontend library.
  *
  *  queries the template1 database for a list of database names 
  *
  */
-#include <stdio.h>
-#include "libpq++.H"
 
-main()
-{
-  char* dbName;
-  int nFields;
-  int i,j;
-
-  /* begin, by creating the parameter environtment for a backend
-     connection. When no parameters are given then the system will
-     try to use reasonable defaults by looking up environment variables 
-     or, failing that, using hardwired constants */
-  PGenv env;
-  PGdatabase* data;
+#include <iostream.h>
+#include <iomanip.h>
+#include <libpq++.h>
 
-  /* Select a database */
-  dbName = "template1";
-
-  /* make a connection to the database */
-  data = new PGdatabase(&env, dbName);
+int main()
+{
+  // Begin, by establishing a connection to the backend.
+  // When no parameters are given then the system will
+  // try to use reasonable defaults by looking up environment variables 
+  // or, failing that, using hardwired constants
+  const char* dbName = "template1";
+  PgDatabase data(dbName);
 
-  /* check to see that the backend connection was successfully made */
-  if (data->status() == CONNECTION_BAD) {
-    fprintf(stderr,"Connection to database '%s' failed.\n", dbName);
-    fprintf(stderr,"%s",data->errormessage());
-    delete data;
-    exit(1);
+  // check to see that the backend connection was successfully made
+  if ( data.ConnectionBad() ) {
+      cerr << "Connection to database '" << dbName << "' failed." << endl
+           << "Error returned: " << data.ErrorMessage() << endl;
+      exit(1);
   }
 
-  /* start a transaction block */
-  if(data->exec("BEGIN") != PGRES_COMMAND_OK) {
-    fprintf(stderr,"BEGIN command failed\n");
-    delete data;
+  // start a transaction block
+  if ( !data.ExecCommandOk("BEGIN") ) {
+    cerr << "BEGIN command failed" << endl;
     exit(1);
   }
 
-  /* fetch instances from the pg_database, the system catalog of databases*/
-  if (data->exec("DECLARE myportal CURSOR FOR select * from pg_database")
-      != PGRES_COMMAND_OK) {
-    fprintf(stderr,"DECLARE CURSOR command failed\n");
-    delete data;
+  // submit command to the backend
+  if ( !data.ExecCommandOk("DECLARE myportal CURSOR FOR select * from pg_database") ) {
+    cerr << "DECLARE CURSOR command failed" << endl;
     exit(1);
   }
 
-  if(data->exec("FETCH ALL in myportal") != PGRES_TUPLES_OK) {
-    fprintf(stderr,"FETCH ALL command didn't return tuples properly\n");
-    delete data;
+  // fetch instances from the pg_database, the system catalog of databases
+  if ( !data.ExecTuplesOk("FETCH ALL in myportal") ) {
+    cerr << "FETCH ALL command didn't return tuples properly" << endl;
     exit(1);
   }
  
-  /* first, print out the attribute names */
-  nFields = data->nfields();
-  for (i=0; i < nFields; i++) {
-    printf("%-15s",data->fieldname(i));
-  }
-  printf("\n\n");
+  // first, print out the attribute names
+  int nFields = data.Fields();
+  for (int i=0; i < nFields; i++)
+      cout << setiosflags(ios::right) << setw(15) << data.FieldName(i);
+  cout << endl << endl;
 
-  /* next, print out the instances */
-  for (i=0; i < data->ntuples(); i++) {
-    for (j=0  ; j < nFields; j++) {
-      printf("%-15s", data->getvalue(i,j));
-    }
-    printf("\n");
+  // next, print out the instances
+  for (int i=0; i < data.Tuples(); i++) {
+       for (int j=0; j < nFields; j++)
+            cout << setiosflags(ios::right) << setw(15) << data.GetValue(i,j);
+       cout << endl;
   }
 
-  /* close the portal */
-  data->exec("CLOSE myportal");
-
-  /* end the transaction */
-  data->exec("END");
+  // Close the portal
+  data.Exec("CLOSE myportal");
 
-  /* close the connection to the database and cleanup */
-  delete data;
+  // End the transaction
+  data.Exec("END");
 }
   
 
index 5acba9666cd55eba7da5f43381714c948a31405e..c6f6215bbcce33d07954f2a080f2dc8e1d4197b7 100644 (file)
@@ -1,69 +1,56 @@
 /*
  * testlibpq2.cc
- *     Test of the asynchronous notification interface
- *
-   populate a database with the following:
-
-CREATE TABLE TBL1 (i int4);
-
-CREATE TABLE TBL2 (i int4);
-
-CREATE RULE r1 AS ON INSERT TO TBL1 DO [INSERT INTO TBL2 values (new.i); NOTIFY TBL2];
-
- * Then start up this program
- * After the program has begun, do
-
-INSERT INTO TBL1 values (10);
-
+ *     Test the C++ version of LIBPQ, the POSTGRES frontend library.
  *
+ *  queries the template1 database for a list of database names using transaction block
  *
  */
-#include <stdio.h>
-#include "libpq++.H"
 
-main()
-{
-  char* dbName;
-
-  /* begin, by creating the parameter environtment for a backend
-     connection. When no parameters are given then the system will
-     try to use reasonable defaults by looking up environment variables 
-     or, failing that, using hardwired constants */
-  PGenv env;
-  PGdatabase* data;
-  PGnotify* notify;
+#include <iostream.h>
+#include <iomanip.h>
+#include <libpq++.h>
 
-  dbName = getenv("USER"); /* change this to the name of your test database */
-
-  /* make a connection to the database */
-  data = new PGdatabase(&env, dbName);
+int main()
+{
+  // Begin, by establishing a connection to the backend.
+  // When no parameters are given then the system will
+  // try to use reasonable defaults by looking up environment variables 
+  // or, failing that, using hardwired constants
+  const char* dbName = "template1";
+  PgTransaction data(dbName);
+
+  // check to see that the backend connection was successfully made
+  if ( data.ConnectionBad() ) {
+      cerr << "Connection to database '" << dbName << "' failed." << endl
+           << "Error returned: " << data.ErrorMessage() << endl;
+      exit(1);
+  }
 
-  /* check to see that the backend connection was successfully made */
-  if (data->status() == CONNECTION_BAD) {
-    fprintf(stderr,"Connection to database '%s' failed.\n", dbName);
-    fprintf(stderr,"%s",data->errormessage());
-    delete data;
+  // submit command to the backend
+  if ( !data.ExecCommandOk("DECLARE myportal CURSOR FOR select * from pg_database") ) {
+    cerr << "DECLARE CURSOR command failed" << endl;
     exit(1);
   }
 
-  if (data->exec("LISTEN TBL2") != PGRES_COMMAND_OK) {
-    fprintf(stderr,"LISTEN command failed\n");
-    delete data;
+  // fetch instances from the pg_database, the system catalog of databases
+  if ( !data.ExecTuplesOk("FETCH ALL in myportal") ) {
+    cerr << "FETCH ALL command didn't return tuples properly" << endl;
     exit(1);
   }
-
-  while (1) {
-      /* check for asynchronous returns */
-      notify = data->notifies();
-      if (notify) {
-         fprintf(stderr,
-                 "ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
-                 notify->relname, notify->be_pid);
-         free(notify);
-         break;
-      }
+  // first, print out the attribute names
+  int nFields = data.Fields();
+  for (int i=0; i < nFields; i++)
+      cout << setiosflags(ios::right) << setw(15) << data.FieldName(i);
+  cout << endl << endl;
+
+  // next, print out the instances
+  for (int i=0; i < data.Tuples(); i++) {
+       for (int j=0; j < nFields; j++)
+            cout << setiosflags(ios::right) << setw(15) << data.GetValue(i,j);
+       cout << endl;
   }
-      
-  /* close the connection to the database and cleanup */
-  delete data;
+
+  // close the portal
+  data.Exec("CLOSE myportal");
 }
index b1e94e487e316dffd5fe231f4b1f9333ad6ed59a..3c4e6ec429f52bfa2bebc85f308ee68f941cf6e9 100644 (file)
 /*
  * testlibpq3.cc
  *     Test the C++ version of LIBPQ, the POSTGRES frontend library.
- *   tests the binary cursor interface
  *
- *
- *
- populate a database by doing the following:
-CREATE TABLE test1 (i int4, d float4, p polygon);
-
-INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0, 2.0)'::polygon);
-
-INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0, 1.0)'::polygon);
-
- the expected output is:
-
-tuple 0: got
- i = (4 bytes) 1,
- d = (4 bytes) 3.567000,
- p = (4 bytes) 2 points         boundbox = (hi=3.000000/4.000000, lo = 1.000000,2.000000)
-tuple 1: got
- i = (4 bytes) 2,
- d = (4 bytes) 89.050003,
- p = (4 bytes) 2 points         boundbox = (hi=4.000000/3.000000, lo = 2.000000,1.000000)
-
+ *  queries the template1 database for a list of database names using transaction block
+ *  and cursor interface.
  *
  */
-#include <stdio.h>
-#include "libpq++.H"
-extern "C" {
-#include "utils/geo-decls.h" /* for the POLYGON type */
-}
-
-main()
-{
-  char* dbName;
-  int i_fnum, d_fnum, p_fnum;
-  int i;
-
-  /* begin, by creating the parameter environtment for a backend
-     connection. When no parameters are given then the system will
-     try to use reasonable defaults by looking up environment variables 
-     or, failing that, using hardwired constants */
-  PGenv env;
-  PGdatabase* data;
-
-  dbName = getenv("USER"); /* change this to the name of your test database */
-
-  /* make a connection to the database */
-  data = new PGdatabase(&env, dbName);
 
-  /* check to see that the backend connection was successfully made */
-  if (data->status() == CONNECTION_BAD) {
-    fprintf(stderr,"Connection to database '%s' failed.\n", dbName);
-    fprintf(stderr,"%s",data->errormessage());
-    delete data;
-    exit(1);
-  }
+#include <iostream.h>
+#include <iomanip.h>
+#include <libpq++.h>
 
-  /* start a transaction block */
-  if (data->exec("BEGIN") != PGRES_COMMAND_OK) {
-    fprintf(stderr,"BEGIN command failed\n");
-    delete data;
-    exit(1);
+int main()
+{
+  // Begin, by establishing a connection to the backend.
+  // When no parameters are given then the system will
+  // try to use reasonable defaults by looking up environment variables 
+  // or, failing that, using hardwired constants.
+  // Create a cursor database query object.
+  // All queries using cursor will be performed through this object.
+  const char* dbName = "template1";
+  PgCursor cData(dbName, "myportal");
+
+  // check to see that the backend connection was successfully made
+  if ( cData.ConnectionBad() ) {
+      cerr << "Connection to database '" << dbName << "' failed." << endl
+           << "Error returned: " << cData.ErrorMessage() << endl;
+      exit(1);
   }
-
-  /* fetch instances from the pg_database, the system catalog of databases*/
-  if (data->exec("DECLARE mycursor BINARY CURSOR FOR select * from test1")
-      != PGRES_COMMAND_OK) {
-    fprintf(stderr,"DECLARE CURSOR command failed\n");
-    delete data;
+  
+  // submit command to the backend
+  if ( !cData.Declare("select * from pg_database") ) {
+    cerr << "DECLARE CURSOR command failed" << endl;
     exit(1);
   }
 
-  if (data->exec("FETCH ALL in mycursor") != PGRES_TUPLES_OK) {
-    fprintf(stderr,"FETCH ALL command didn't return tuples properly\n");
-    delete data;
+  // fetch instances from the pg_cDatabase, the system catalog of cDatabases
+  if ( !cData.Fetch() ) {
+    cerr << "FETCH ALL command didn't return tuples properly" << endl;
     exit(1);
   }
  
-  i_fnum = data->fieldnum("i");
-  d_fnum = data->fieldnum("d");
-  p_fnum = data->fieldnum("p");
-  
-/*
-  for (i=0;i<3;i++) {
-      printf("type[%d] = %d, size[%d] = %d\n",
-            i, data->fieldtype(i), 
-            i, data->fieldsize(i));
-  }
-*/
-
-  for (i=0; i < data->ntuples(); i++) {
-    int *ival; 
-    float *dval;
-    int plen;
-    POLYGON* pval;
-    /* we hard-wire this to the 3 fields we know about */
-    ival = (int*)data->getvalue(i,i_fnum);
-    dval = (float*)data->getvalue(i,d_fnum);
-    plen = data->getlength(i,p_fnum);
-
-    /* plen doesn't include the length field so need to increment by VARHDSZ*/
-    pval = (POLYGON*) malloc(plen + VARHDRSZ); 
-    pval->size = plen;
-    memmove((char*)&pval->npts, data->getvalue(i,p_fnum), plen);
-    printf("tuple %d: got\n", i);
-    printf(" i = (%d bytes) %d,\n",
-          data->getlength(i,i_fnum), *ival);
-    printf(" d = (%d bytes) %f,\n",
-          data->getlength(i,d_fnum), *dval);
-    printf(" p = (%d bytes) %d points \tboundbox = (hi=%f/%f, lo = %f,%f)\n",
-          data->getlength(i,d_fnum),
-          pval->npts,
-          pval->boundbox.xh,
-          pval->boundbox.yh,
-          pval->boundbox.xl,
-          pval->boundbox.yl);
+  // first, print out the attribute names
+  int nFields = cData.Fields();
+  for (int i=0; i < nFields; i++)
+      cout << setiosflags(ios::right) << setw(15) << cData.FieldName(i);
+  cout << endl << endl;
+
+  // next, print out the instances
+  for (int i=0; i < cData.Tuples(); i++) {
+       for (int j=0; j < nFields; j++)
+            cout << setiosflags(ios::right) << setw(15) << cData.GetValue(i,j);
+       cout << endl;
   }
-  
-  /* close the portal */
-  data->exec("CLOSE mycursor");
-
-  /* end the transaction */
-  data->exec("END");
-
-  /* close the connection to the database and cleanup */
-  delete data;
 }
index dc78031843f892dca9df88bea875f9345152c058..a1b21d33a9d7781920db9772dd785fd9f90740bd 100644 (file)
@@ -1,66 +1,58 @@
 /*
  * testlibpq4.cc
- *     Test the C++ version of LIBPQ, the POSTGRES frontend library.
- * tests the copy in features
+ *     Test of the asynchronous notification interface
  *
- */
-#include <stdio.h>
-#include "libpq++.H"
+   populate a test database with the following (use testlibpq4.sql):
 
-main()
-{
-  char* dbName;
+CREATE TABLE TBL1 (i int4);
 
-  /* begin, by creating the parameter environment for a backend
-     connection. When no parameters are given then the system will
-     try to use reasonable defaults by looking up environment variables 
-     or, failing that, using hardwired constants */
-  PGenv env;
-  PGdatabase* data;
+CREATE TABLE TBL2 (i int4);
 
-  dbName = getenv("USER"); /* change this to the name of your test database */
+CREATE RULE r1 AS ON INSERT TO TBL1 DO [INSERT INTO TBL2 values (new.i); NOTIFY TBL2];
 
-  /* make a connection to the database */
-  data = new PGdatabase(&env, dbName);
+ * Then start up this program
+ * After the program has begun, do
 
-  /* check to see that the backend connection was successfully made */
-  if (data->status() == CONNECTION_BAD) {
-    fprintf(stderr,"Connection to database '%s' failed.\n", dbName);
-    fprintf(stderr,"%s",data->errormessage());
-    delete data;
-    exit(1);
-  }
+INSERT INTO TBL1 values (10);
+
+ *
+ *
+ */
+#include <iostream.h>
+#include <libpq++.h>
+#include <stdlib.h>
 
-  /* start a transaction block */
-  if(data->exec("BEGIN") != PGRES_COMMAND_OK) {
-    fprintf(stderr,"BEGIN command failed\n");
-    delete data;
+main()
+{
+  // Begin, by connecting to the backend using hardwired constants
+  // and a test database created by the user prior to the invokation
+  // of this test program.
+  char* dbName = getenv("USER"); // change this to the name of your test database
+  PgDatabase data(dbName);
+
+  // Check to see that the backend connection was successfully made
+  if ( data.ConnectionBad() ) {
+    cerr << "Connection to database '" << dbName << "' failed." << endl
+         << data.ErrorMessage() << endl;
     exit(1);
   }
 
-  if (data->exec("CREATE TABLE foo (a int4, b char16, d float8)") != 
-      PGRES_COMMAND_OK) {
-      fprintf(stderr,"CREATE TABLE foo command failed\n");
-      delete data;
-      exit(1);
+  // Listen to a table
+  if ( !data.ExecCommandOk("LISTEN TBL2") ) {
+    cerr << "LISTEN command failed" << endl;
+    exit(1);
   }
 
-  if (data->exec("COPY foo FROM STDIN") != PGRES_COMMAND_OK) {
-      fprintf(stderr,"COPY foo FROM STDIN\n");
-      delete data;
-      exit(1);      
+  // Test asynchronous notification
+  while (1) {
+      // check for asynchronous returns
+      PGnotify* notify = data.Notifies();
+      if (notify) {
+         cerr << "ASYNC NOTIFY of '" << notify->relname 
+              << "' from backend pid '" << notify->be_pid 
+              << "' received" << endl;
+         free(notify);
+         break;
+      }
   }
-
-  data->putline("3\thello world\t4.5\n");
-  data->putline("4\tgoodbye word\t7.11\n");
-  data->putline(".\n");
-  data->endcopy();
-  data->exec("SELECT * FROM foo");
-  data->printtuples(stdout,1,"|",1,0);
-  data->exec("DROP TABLE foo");
-  // end the transaction 
-  data->exec("END");
-
-  // close the connection to the database and cleanup 
-  delete data;
 }
diff --git a/src/interfaces/libpq++/examples/testlibpq4.sql b/src/interfaces/libpq++/examples/testlibpq4.sql
new file mode 100644 (file)
index 0000000..f9c7410
--- /dev/null
@@ -0,0 +1,5 @@
+CREATE TABLE TBL1 (i int4);
+
+CREATE TABLE TBL2 (i int4);
+
+CREATE RULE r1 AS ON INSERT TO TBL1 DO [INSERT INTO TBL2 values (new.i); NOTIFY TBL2];
diff --git a/src/interfaces/libpq++/examples/testlibpq5.cc b/src/interfaces/libpq++/examples/testlibpq5.cc
new file mode 100644 (file)
index 0000000..8c299fe
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * testlibpq5.cc
+ *     Test the C++ version of LIBPQ, the POSTGRES frontend library.
+ *   tests the binary cursor interface
+ *
+ *
+ *
+ populate a database by doing the following (use testlibpq5.sql):
+CREATE TABLE test1 (i int4, d float4, p polygon);
+
+INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0, 2.0)'::polygon);
+
+INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0, 1.0)'::polygon);
+
+ the expected output is:
+
+tuple 0: got
+ i = (4 bytes) 1,
+ d = (4 bytes) 3.567000,
+ p = (4 bytes) 2 points         boundbox = (hi=3.000000/4.000000, lo = 1.000000,2.000000)
+tuple 1: got
+ i = (4 bytes) 2,
+ d = (4 bytes) 89.050003,
+ p = (4 bytes) 2 points         boundbox = (hi=4.000000/3.000000, lo = 2.000000,1.000000)
+
+ *
+ */
+#include <iostream.h>
+#include <libpq++.h>
+#include <stdlib.h>
+extern "C" {
+#include "postgres.h"          // for Postgres types
+#include "utils/geo-decls.h" // for the POLYGON type
+}
+
+main()
+{
+  // Begin, by connecting to the backend using hardwired constants
+  // and a test database created by the user prior to the invokation
+  // of this test program.  Connect using cursor interface.
+  char* dbName = getenv("USER"); // change this to the name of your test database
+  PgCursor data(dbName, "mycursor");
+
+  // check to see that the backend connection was successfully made
+  if ( data.ConnectionBad() ) {
+    cerr << "Connection to database '" << dbName << "' failed." << endl
+         << data.ErrorMessage();
+    exit(1);
+  }
+
+  // Declare a binary cursor for all the tuples in database 'test1'
+  if ( !data.Declare("select * from test1", 1) ) {
+    cerr << "DECLARE CURSOR command failed" << endl;
+    exit(1);
+  }
+
+  // fetch all instances from the current cursor
+  if ( !data.Fetch() ) {
+    cerr << "FETCH ALL command didn't return tuples properly" << endl;
+    exit(1);
+  }
+  // Find the field numbers for the columns 'i', 'd', and 'p'
+  int i_fnum = data.FieldNum("i");
+  int d_fnum = data.FieldNum("d");
+  int p_fnum = data.FieldNum("p");
+  
+/*
+  for (i=0;i<3;i++) {
+      printf("type[%d] = %d, size[%d] = %d\n",
+            i, data.FieldType(i), 
+            i, data.FieldSize(i));
+  }
+*/
+
+  // Print out the information about the extracted tuple
+  for (int i=0; i < data.Tuples(); i++) {
+    // we hard-wire this to the 3 fields we know about
+    int* ival = (int*)data.GetValue(i,i_fnum);
+    float* dval = (float*)data.GetValue(i,d_fnum);
+    int plen = data.GetLength(i,p_fnum);
+
+    // Allocate correct memory space for the Polygon struct and copy
+    // the extracted data into it.
+    // plen doesn't include the length field so need to increment by VARHDSZ
+    POLYGON* pval = (POLYGON*) malloc(plen + VARHDRSZ); 
+    pval->size = plen;
+    memmove((char*)&pval->npts, data.GetValue(i,p_fnum), plen);
+    
+    // Display Polygon Information
+    cout << "tuple " << i << ": got" << endl
+         << " i = (" << data.GetLength(i,i_fnum) << " bytes) " << *ival << "," << endl
+         << " d = (" << data.GetLength(i,d_fnum) << " bytes) " << *dval << "," << endl
+         << " p = (" << data.GetLength(i,d_fnum) << " bytes) " << pval->npts << " points"
+         << "\tboundbox = (hi=" << pval->boundbox.xh << "/" << pval->boundbox.yh << ","
+         << "lo = " << pval->boundbox.xl << "," << pval->boundbox.yl << ")" << endl;
+          
+    // Deallocate memory allocated for the Polygon structure
+    free(pval);
+  }
+}
diff --git a/src/interfaces/libpq++/examples/testlibpq5.sql b/src/interfaces/libpq++/examples/testlibpq5.sql
new file mode 100644 (file)
index 0000000..f024c0b
--- /dev/null
@@ -0,0 +1,6 @@
+CREATE TABLE test1 (i int4, d float4, p polygon);
+
+INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0, 2.0)'::polygon);
+
+INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0, 1.0)'::polygon);
+
diff --git a/src/interfaces/libpq++/examples/testlibpq6.cc b/src/interfaces/libpq++/examples/testlibpq6.cc
new file mode 100644 (file)
index 0000000..bbf1043
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * testlibpq4.cc
+ *     Test the C++ version of LIBPQ, the POSTGRES frontend library.
+ * tests the copy in features
+ *
+ */
+#include <iostream.h>
+#include <libpq++.h>
+#include <stdlib.h>
+
+main()
+{
+  // Begin, by connecting to the backend using hardwired constants
+  // and a test database created by the user prior to the invokation
+  // of this test program.  Connect using transaction interface.
+  char* dbName = getenv("USER"); // change this to the name of your test database
+  PgTransaction data(dbName);
+
+  // check to see that the backend connection was successfully made
+  if ( data.ConnectionBad() ) {
+    cerr << "Connection to database '" << dbName << "' failed." << endl
+         << data.ErrorMessage();
+    exit(1);
+  }
+  else cout << "Connected to database '" << dbName << "'..." << endl;
+
+  // Create a new table
+  if ( !data.ExecCommandOk("CREATE TABLE foo (a int4, b char16, d float8)") ) {
+      cerr << "CREATE TABLE foo command failed" << endl;
+      exit(1);
+  }
+  else cout << "CREATEd TABLE foo successfully.." <<  endl;
+
+  // Initiate Copy command
+  if ( data.ExecCommandOk("COPY foo FROM STDIN") ) {
+      cerr << "COPY foo FROM STDIN" << endl;
+      exit(1);      
+  }
+  else cout << "COPY foo FROM STDIN was successful.." <<  endl;
+
+  // Put some test data into the table
+  data.PutLine("3\thello world\t4.5\n");
+  cout << "Line: \"3\thello world\t4.5\" copied..." << endl;
+  data.PutLine("4\tgoodbye word\t7.11\n");
+  cout << "Line: \"4\tgoodbye word\t7.11\" copied..." << endl;
+  data.PutLine(".\n");
+  cout << "Line: \".\" copied..." << endl;
+  if ( !data.EndCopy() )
+       cout << "Ended COPY succesfully..." << endl;
+  else cerr << "End Copy failed..." << endl;
+  
+  // Print the data that was inserted into the table
+  if ( data.ExecTuplesOk("SELECT * FROM foo") )
+       data.PrintTuples();
+  else cerr << "SELECT * FROM foo failed..." << endl;
+  
+  // Drop the test table
+  data.Exec("DROP TABLE foo");
+}
index 8e9b4757dffe4d2bb93f4a10cc0ab087d3540e80..df1dc6c3609b42dcf770c0acd391c78a1c6d6fa8 100644 (file)
@@ -7,56 +7,43 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/examples/Attic/testlo.cc,v 1.2 1996/11/18 01:44:28 bryanh Exp $
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/examples/Attic/testlo.cc,v 1.3 1997/02/13 10:01:05 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
-#include <stdio.h>
-#include "libpq++.H"
-extern "C" {
-#include "libpq/libpq-fs.h"
-}
+#include <iostream.h>
+#include <libpq++.h>
+#include <stdlib.h>
 
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
 {
-    char *in_filename, *out_filename;
-    char *database;
-    PGenv env;
-    PGlobj *object;
-
+    // Check if the program was invoked correctly; if not, signal error
     if (argc < 4 || argc > 5) {
-       fprintf(stderr, "Usage: %s database_name in_filename out_filename [oid]\n",
-               argv[0]);
+       cerr << "Usage: " << argv[0] << " database_name in_filename out_filename [oid]" << endl;
        exit(1);
     }
 
-    database = argv[1];
-    in_filename = argv[2];
-    out_filename = argv[3];
+    // Get the arguments passed to the program
+    char* database = argv[1];
+    char* in_filename = argv[2];
+    char* out_filename = argv[3];
 
-    /*
-     * set up the connection and create a largeobject for us
-     */
-    if (argc == 4) {
-      object = new PGlobj(&env, database);
-    } else {
-      object = new PGlobj(&env, database, atoi(argv[4]));
-    }
+    // Set up the connection and create a large object
+    int lobjId = ( argc == 4 ? 0 : atoi(argv[4]) );
+    PgLargeObject object(lobjId, database);
 
-    /* check to see that the backend connection was successfully made */
-    if (object->status() == CONNECTION_BAD) {
-       fprintf(stderr,"Connection to database '%s' failed.\n", database);
-       fprintf(stderr,"%s",object->errormessage());
-       delete object;
-       exit(1);
+    // check to see that the backend connection was successfully made
+    if ( object.ConnectionBad() ) {
+         cerr << "Connection to database '" << database << "' failed." << endl
+              << object.ErrorMessage();
+        exit(1);
     }
-       
-    object->exec("BEGIN");
-    printf("importing file \"%s\" ...\n", in_filename);
-    object->import(in_filename);
-    printf("exporting large object to file \"%s\" ...\n", out_filename);
-    object->export(out_filename);
-    object->exec("END"); // WHY DOES IT CORE DUMP HERE ???
-    delete object;
+
+    // Test the import and export features of the Large Object interface
+    object.Exec("BEGIN");
+    cout << "Importing file \"" << in_filename << "\"..." << endl;
+    object.Import(in_filename);
+    cout << "Exporting large object to file \"" << out_filename << "\"..." << endl;
+    object.Export(out_filename);
+    object.Exec("END"); // WHY DOES IT CORE DUMP HERE ???
 }
diff --git a/src/interfaces/libpq++/libpq++.h b/src/interfaces/libpq++/libpq++.h
new file mode 100644 (file)
index 0000000..ee257bf
--- /dev/null
@@ -0,0 +1,33 @@
+/*-------------------------------------------------------------------------
+ *
+ * libpq++.H
+ *    
+ *
+ *   DESCRIPTION
+ *     C++ client interface to Postgres
+ *   used for building front-end applications
+ *
+ *   NOTES
+ *      Currently under construction.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *   IDENTIFICATION
+ *
+ * $Id: libpq++.h,v 1.1 1997/02/13 10:00:25 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef LIBPQXX_H
+#define LIBPQXX_H
+
+#include "libpq++/pgenv.h"
+#include "libpq++/pgconnection.h"
+#include "libpq++/pgdatabase.h"
+#include "libpq++/pgtransdb.h"
+#include "libpq++/pgcursordb.h"
+#include "libpq++/pglobject.h"
+
+#endif // LIBPQXX_H
+
index 777a12e8e7ac24346bcac12a9f895fed1060748e..96ef215700f36a011fad460d807c5df8f3941c87 100644 (file)
 /*-------------------------------------------------------------------------
  *
  *   FILE
- *     pgconnection.cc
+ *     pgconnection.cpp
  *
  *   DESCRIPTION
- *      implementation of the PGconnection class.
- *   PGconnection encapsulates a frontend to backend connection
+ *      implementation of the PgConnection class.
+ *   PgConnection encapsulates a frontend to backend connection
  *
  * Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pgconnection.cc,v 1.1.1.1 1996/07/09 06:22:18 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pgconnection.cc,v 1.2 1997/02/13 10:00:27 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 
-#include "libpq++.H"
+#include <stdlib.h>
+#include <string.h>
+#include "pgconnection.h"
+
+extern "C" {
+#include "fe-auth.h"
+}
 
-// default constructor
-// checks environment variable for database name
-PGconnection::PGconnection()
-{
-  char* name;
-  PGenv* newenv;
 
-  conn = NULL;
-  result = NULL;
-  errorMessage[0] = '\0';
+// ****************************************************************
+//
+// PgConnection Implementation
+//
+// ****************************************************************
+// default constructor -- initialize everything
+PgConnection::PgConnection()
+       : pgConn(NULL), pgResult(NULL), pgCloseConnection(0)
+{}
 
-  newenv = new PGenv(); // use reasonable defaults for the environment
-  if (!(name = getenv(ENV_DEFAULT_DBASE)))
-    return;
-  connect(newenv, name);
+// copy constructor -- copy the pointers; no deep copy required
+PgConnection::PgConnection(const PgConnection& conn)
+       : pgEnv(conn.pgEnv), pgConn(conn.pgConn), pgResult(conn.pgResult), 
+         pgCloseConnection(conn.pgCloseConnection)
+{}
+
+// constructor -- checks environment variable for database name
+PgConnection::PgConnection(const char* dbName)
+       : pgConn(NULL), pgResult(NULL), pgCloseConnection(1)
+{
+  // Get a default database name to connect to
+  char* defDB = (char*)dbName;
+  if ( !dbName )
+       if ( !(defDB = getenv(ENV_DEFAULT_DBASE)) )
+            return;
+    
+  // Connect to the database
+  Connect( defDB );
 }
 
 // constructor -- for given environment and database name
-PGconnection::PGconnection(PGenv* env, char* dbName)
+PgConnection::PgConnection(const PgEnv& env, const char* dbName)
+       : pgEnv(env), pgConn(NULL), pgResult(NULL), pgCloseConnection(1)
 {
-  conn = NULL;
-  result = NULL;
-  errorMessage[0] = '\0';
-  connect(env, dbName);
+  Connect( dbName );
 }
 
 // destructor - closes down the connection and cleanup
-PGconnection::~PGconnection()
+PgConnection::~PgConnection()
 {
-  if (result)  PQclear(result);
-  if (conn)    PQfinish(conn);
+  // Terminate the debugging output if it was turned on
+  #if defined(DEBUG)
+       PQuntrace(pgConn);
+  #endif
+  
+  // Close the conneciton only if needed
+  // This feature will most probably be used by the derived classes that
+  // need not close the connection after they are destructed.
+  if ( pgCloseConnection ) {
+       if (pgResult)   PQclear(pgResult);
+       if (pgConn)     PQfinish(pgConn);
+  }
 }
 
-// PGconnection::connect
+// PgConnection::connect
 // establish a connection to a backend
-ConnStatusType
-PGconnection::connect(PGenv* newenv, char* dbName)
+ConnStatusType PgConnection::Connect(const char* dbName)
 {
-#if 0
-    FILE *debug;
-    debug = fopen("/tmp/trace.out","w");
-    PQtrace(conn, debug);
-#endif
-
-    env = newenv;
-    fe_setauthsvc(env->pgauth, errorMessage); 
-    conn = PQsetdb(env->pghost, env->pgport, env->pgoption, env->pgtty, dbName);
-    if(strlen(errorMessage))
-      return CONNECTION_BAD;
+    // Turn the trace on
+    #if defined(DEBUG)
+       FILE *debug = fopen("/tmp/trace.out","w");
+       PQtrace(pgConn, debug);
+    #endif
+
+    // Set Host Authentication service
+    char errorMessage[ERROR_MSG_LENGTH];
+    memset(errorMessage, 0, sizeof(errorMessage));
+    fe_setauthsvc(pgEnv.Auth(), errorMessage);
+    
+    // Connect to the database
+    pgConn = PQsetdb(pgEnv.Host(), pgEnv.Port(), pgEnv.Option(), pgEnv.TTY(), dbName);
+    
+    // Return the connection status
+    if (errorMessage) {
+       SetErrorMessage( errorMessage );
+        return CONNECTION_BAD;
+    }
     else
-      return status();
+        return Status();
 }
 
-// PGconnection::status -- return connection or result status
-ConnStatusType
-PGconnection::status()
+// PgConnection::status -- return connection or result status
+ConnStatusType PgConnection::Status()
 {
-    return PQstatus(conn);
+    return PQstatus(pgConn);
 }
 
-// PGconnection::exec  -- send a query to the backend
-ExecStatusType
-PGconnection::exec(char* query)
+// PgConnection::exec  -- send a query to the backend
+ExecStatusType PgConnection::Exec(const char* query)
 {
-  if (result)
-    PQclear(result); 
+  // Clear the Result Stucture if needed
+  if (pgResult)
+    PQclear(pgResult); 
 
-  result = PQexec(conn, query);
-  if (result)
-      return PQresultStatus(result);
+  // Execute the given query
+  pgResult = PQexec(pgConn, query);
+  
+  // Return the status
+  if (pgResult)
+      return PQresultStatus(pgResult);
   else {
-      strcpy(errorMessage, PQerrorMessage(conn));
+      SetErrorMessage( PQerrorMessage(pgConn) );
       return PGRES_FATAL_ERROR;
   }
 }
+
+// Return true if the Postgres command was executed OK
+int PgConnection::ExecCommandOk(const char* query)
+{
+       return Exec(query) == PGRES_COMMAND_OK;
+} // End ExecCommandOk()
+
+int PgConnection::ExecTuplesOk(const char* query)
+{
+       return Exec(query) == PGRES_TUPLES_OK;
+} // End ExecTuplesOk()
+
+
+// PgConnection::notifies() -- returns a notification from a list of unhandled notifications
+PGnotify* PgConnection::Notifies()
+{
+  Exec(" "); 
+  return PQnotifies(pgConn);
+}
+
+// PgConnection::SetErrorMessage
+// sets error message to the given string
+void PgConnection::SetErrorMessage(const string& msg, int append)
+{
+  if ( append )
+     pgErrorMessage += msg;
+  else
+     pgErrorMessage = msg;
+}
+
+// From Integer To String Conversion Function
+string PgConnection::IntToString(int n)
+{
+  char buffer [32];
+  memset(buffer, 0, sizeof(buffer));
+  sprintf(buffer, "%d", n);
+  return buffer;
+}
diff --git a/src/interfaces/libpq++/pgconnection.h b/src/interfaces/libpq++/pgconnection.h
new file mode 100644 (file)
index 0000000..125c942
--- /dev/null
@@ -0,0 +1,75 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgconnection.h
+ *    
+ *
+ *   DESCRIPTION
+ *             Postgres Connection Class: 
+ *                Manage Postgres backend connection
+ *
+ *   NOTES
+ *      Currently under construction.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PGCONN_H
+#define PGCONN_H
+
+#include <stdio.h>
+#include "pgenv.h"
+
+extern "C" {
+#include "libpq-fe.h"
+}
+
+
+// ****************************************************************
+//
+// PgConnection - a connection made to a postgres backend
+//
+// ****************************************************************
+// This class contains all the information about the connection
+// to the backend process.  All the database classes should be
+// derived from this class to obtain the connection interface.
+class PgConnection {
+protected:
+  PgEnv pgEnv;         // Current connection environment
+  PGconn* pgConn;      // Connection Structures
+  PGresult* pgResult;  // Query Result
+  string pgErrorMessage; // Error messages container
+  int pgCloseConnection; // Flag indicating whether the connection should be closed or not
+  
+public:
+   PgConnection(const char* dbName); // use reasonable defaults
+   PgConnection(const PgEnv& env, const char* dbName); // connect to the database with 
+                                    // given environment and database name
+   virtual ~PgConnection(); // close connection and clean up
+   
+   // Connection status and error messages
+   ConnStatusType Status();
+   int ConnectionBad() { return Status() == CONNECTION_BAD; }
+   const char* ErrorMessage() const { return pgErrorMessage.c_str(); }
+  
+   // returns the database name of the connection
+   const char* DBName() const { return PQdb(pgConn); }
+
+   // Query Execution interface
+   ExecStatusType Exec(const char* query);  // send a query to the backend
+   int ExecCommandOk(const char* query);    // send a command and check if it's OK
+   int ExecTuplesOk(const char* query);     // send a command and check if tuples are returned
+   PGnotify* Notifies();
+    
+protected:
+   ConnStatusType Connect(const char* dbName);
+   void SetErrorMessage(const string&, int append = 0);
+   string IntToString(int);
+   
+protected:
+   PgConnection();
+   PgConnection(const PgConnection&);
+};
+
+#endif // PGCONN_H
diff --git a/src/interfaces/libpq++/pgcursordb.cc b/src/interfaces/libpq++/pgcursordb.cc
new file mode 100644 (file)
index 0000000..0589996
--- /dev/null
@@ -0,0 +1,90 @@
+/*-------------------------------------------------------------------------
+ *
+ *   FILE
+ *     pgcursordb.cpp
+ *
+ *   DESCRIPTION
+ *      implementation of the PgCursor class.
+ *   PgCursor encapsulates a cursor interface to the backend
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pgcursordb.cc,v 1.1 1997/02/13 10:00:30 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+ #include "pgcursordb.h"
+// ****************************************************************
+//
+// PgCursor Implementation
+//
+// ****************************************************************
+// Make a connection to the specified database with default environment
+PgCursor::PgCursor(const char* dbName, const char* cursor)
+   : PgTransaction(dbName), pgCursor(cursor)
+{}
+
+// Make a connection to the specified database with the given environment
+PgCursor::PgCursor(const PgEnv& env, const char* dbName, const char* cursor)
+   : PgTransaction(env, dbName), pgCursor(cursor)
+{}
+
+// Do not make a connection to the backend -- just query
+// Connection should not be closed after the object destructs since some
+// other object is using the connection
+PgCursor::PgCursor(const PgConnection& conn, const char* cursor)
+   : PgTransaction(conn), pgCursor(cursor)
+{}
+
+// Destructor: End the transaction block
+PgCursor::~PgCursor()
+{
+       Close();
+}
+
+
+// ****************************************************************
+//
+// PgCursor: Cursor Interface Implementation
+//
+// ****************************************************************
+// Declare a cursor: name has already been supplied in the constructor
+int PgCursor::Declare(const string& query, int binary)
+{
+       string cmd = "DECLARE " + pgCursor;
+       if ( binary )
+            cmd += " BINARY";
+       cmd += " CURSOR FOR " + query;
+       return ExecCommandOk( cmd.c_str() );
+} // End Declare()
+
+// Fetch ALL tuples in given direction
+int PgCursor::Fetch(const char* dir)
+{
+       return Fetch("ALL", dir);
+} // End Fetch()
+
+// Fetch specified amount of tuples in given direction
+int PgCursor::Fetch(unsigned num, const char* dir)
+{
+       return Fetch( IntToString(num), dir );
+} // End Fetch()
+
+// Create and execute the actual fetch command with the given arguments
+int PgCursor::Fetch(const string& num, const string& dir)
+{
+       string cmd = "FETCH " + dir + " " + num + " IN " + pgCursor;
+       return ExecTuplesOk( cmd.c_str() );
+} // End Fetch()
+
+// Close the cursor: no more queries using the cursor should be allowed
+// Actually, the backend should take care of it.
+int PgCursor::Close()
+{
+       string cmd = "CLOSE " + pgCursor;
+       return ExecCommandOk( cmd.c_str() );
+} // End CloseCursor()
diff --git a/src/interfaces/libpq++/pgcursordb.h b/src/interfaces/libpq++/pgcursordb.h
new file mode 100644 (file)
index 0000000..de1adaf
--- /dev/null
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgcursordb.h
+ *    
+ *
+ *   DESCRIPTION
+ *             Postgres Cursor Database Class: 
+ *                Query Postgres backend using a cursor
+ *
+ *   NOTES
+ *      Currently under construction.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PGCURSOR_H
+#define PGCURSOR_H
+
+#include "pgtransdb.h"
+
+
+// ****************************************************************
+//
+// PgCursor - a class for querying databases using a cursor
+//
+// ****************************************************************
+// This is the database access class that declares a cursor and
+// manipulates data through it.  The interface will introduce some
+// ease of use through the methods that will allow cursor specific
+// operations, like fetch, forward, etc.
+class PgCursor : public PgTransaction {
+public:
+  PgCursor(const char* dbName, const char* cursor);    // use reasonable defaults
+  // connect to the database with given environment and database name
+  PgCursor(const PgEnv& env, const char* dbName, const char* cursor);
+  PgCursor(const PgConnection&, const char* cursor);
+  virtual ~PgCursor(); // close connection and clean up
+  
+  // Commands associated with cursor interface
+  int Declare(const string& query, int binary = 0);    // Declare a cursor with given name
+  int Fetch(const char* dir = "FORWARD");              // Fetch ALL tuples in given direction
+  int Fetch(unsigned num, const char* dir = "FORWARD");        // Fetch specified amount of tuples
+  int Close(); // Close the cursor
+  
+  // Accessors to the cursor name
+  const char* Cursor() const { return pgCursor.c_str(); }
+  void Cursor(const string& cursor) { pgCursor = cursor; }
+  
+protected:
+  int Fetch(const string& num, const string& dir);
+  
+protected:
+  string pgCursor;
+  
+protected:
+  PgCursor() : PgTransaction() {}      // Do not connect
+}; // End PgCursor Class Declaration
+
+#endif // PGCURSOR_H
diff --git a/src/interfaces/libpq++/pgdatabase.h b/src/interfaces/libpq++/pgdatabase.h
new file mode 100644 (file)
index 0000000..c3c9042
--- /dev/null
@@ -0,0 +1,85 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgdatabase.h
+ *    
+ *
+ *   DESCRIPTION
+ *             Postgres Database Class: 
+ *                Query Postgres backend to obtain query results
+ *
+ *   NOTES
+ *      Currently under construction.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PGDATABASE_H
+#define PGDATABASE_H
+#include "pgconnection.h"
+
+
+// ****************************************************************
+//
+// PgDatabase - a class for accessing databases
+//
+// ****************************************************************
+// This is the basic database access class.  Its interface should 
+// be used only after a query has been sent to the backend and
+// results are being received.
+class PgDatabase : public PgConnection {
+public:
+  PgDatabase(const char* dbName) : PgConnection(dbName) {} // use reasonable defaults
+  // connect to the database with given environment and database name
+  PgDatabase(const PgEnv& env, const char* dbName) : PgConnection(env, dbName) {}
+  PgDatabase(const PgConnection& conn) : PgConnection(conn) {pgCloseConnection = 0;}
+  ~PgDatabase() {} // close connection and clean up
+  
+  // query result access
+  int Tuples()
+    { return PQntuples(pgResult); }
+  int Fields()
+    { return PQnfields(pgResult); }
+  const char* FieldName(int field_num)
+    { return PQfname(pgResult, field_num); }
+  int FieldNum(const char* field_name)
+    { return PQfnumber(pgResult, field_name); }
+  Oid FieldType(int field_num)
+    { return PQftype(pgResult, field_num); }
+  Oid FieldType(const char* field_name)
+    { return PQftype(pgResult, FieldNum(field_name)); }
+  short FieldSize(int field_num)
+    { return PQfsize(pgResult, field_num); }
+  short FieldSize(const char* field_name)
+    { return PQfsize(pgResult, FieldNum(field_name)); }
+  const char* GetValue(int tup_num, int field_num)
+    { return PQgetvalue(pgResult, tup_num, field_num); }
+  const char* GetValue(int tup_num, const char* field_name)
+    { return PQgetvalue(pgResult, tup_num, FieldNum(field_name)); }
+  int GetLength(int tup_num, int field_num)
+    { return PQgetlength(pgResult, tup_num, field_num); }
+  int GetLength(int tup_num, const char* field_name)
+    { return PQgetlength(pgResult, tup_num, FieldNum(field_name)); }
+  void DisplayTuples(FILE *out = 0, int fillAlign = 1, const char* fieldSep = "|",
+                  int printHeader = 1, int quiet = 0)
+    { PQdisplayTuples(pgResult, (out ? out : stdout), fillAlign, fieldSep, printHeader, quiet); }
+  void PrintTuples(FILE *out = 0, int printAttName = 1, int terseOutput = 0, int width = 0)
+    { PQprintTuples(pgResult, (out ? out : stdout), printAttName, terseOutput, width); }
+
+  // copy command related access
+  int GetLine(char* string, int length)
+    { return PQgetline(pgConn, string, length); }
+  void PutLine(const char* string)
+    { PQputline(pgConn, string); }
+  const char* OidStatus()
+    { return PQoidStatus(pgResult); }
+  int EndCopy()
+    { return PQendcopy(pgConn); }
+    
+protected:
+  PgDatabase() : PgConnection() {}     // Do not connect
+};
+
+#endif // PGDATABASE_H
index 7d696cf043f3c7573f192eaefc97ffe3832f5ef5..451a4f3fde3a90e9fe7642a5701e7b1b15864fba 100644 (file)
@@ -1,10 +1,10 @@
 /*-------------------------------------------------------------------------
  *
  *   FILE
- *     PGenv.cc
+ *     PgEnv.cc
  *
  *   DESCRIPTION
- *      PGenv is the environment for setting up a connection to a 
+ *      PgEnv is the environment for setting up a connection to a 
  *   postgres backend,  captures the host, port, tty, options and
  *   authentication type.
  *
  * Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pgenv.cc,v 1.2 1996/11/18 01:43:55 bryanh Exp $
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pgenv.cc,v 1.3 1997/02/13 10:00:33 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include <stdlib.h>
-#include "libpq++.H"
+#include "pgenv.h"
 
-#define DefaultAuth DEFAULT_CLIENT_AUTHSVC 
-#define DefaultPort "5432"
 
-// default constructor for PGenv
+#define DefaultAuth DEFAULT_CLIENT_AUTHSVC
+#define DefaultPort POSTPORT
+
+
+// ****************************************************************
+//
+// PgEnv Implementation
+//
+// ****************************************************************
+// Default constructor for PgEnv
 // checks the environment variables
-PGenv::PGenv()
+PgEnv::PgEnv()
 {
-  pgauth = NULL;
-  pghost = NULL;
-  pgport = NULL;
-  pgoption = NULL;
-  pgtty = NULL;
-
-  setValues(getenv(ENV_DEFAULT_AUTH), getenv(ENV_DEFAULT_HOST),
+  SetValues(getenv(ENV_DEFAULT_AUTH), getenv(ENV_DEFAULT_HOST),
             getenv(ENV_DEFAULT_PORT), getenv(ENV_DEFAULT_OPTION),
-           getenv(ENV_DEFAULT_TTY));
+            getenv(ENV_DEFAULT_TTY));
 }
 
 // constructor for given environment
-PGenv::PGenv(char* auth, char* host, char* port, char* option, char* tty)
+PgEnv::PgEnv(const string& auth, const string& host, const string& port, 
+             const string& option, const string& tty)
 {
-  pgauth = NULL;
-  pghost = NULL;
-  pgport = NULL;
-  pgoption = NULL;
-  pgtty = NULL;
-
-  setValues(auth, host, port, option, tty);
+  SetValues(auth, host, port, option, tty);
 }
 
 // allocate memory and set internal structures to match
 // required environment
-void
-PGenv::setValues(char* auth, char* host, char* port, char* option, char* tty)
+void PgEnv::SetValues(const string& auth, const string& host, const string& port, 
+                      const string& option, const string& tty)
 {
-  char* temp;
-
-  temp = (auth) ? auth : DefaultAuth;
-
-  if (pgauth)
-    free(pgauth);
-  pgauth = strdup(temp);
-
-  temp = (host) ? host : DefaultHost;
-
-  if (pghost)
-    free(pghost);
-  pghost = strdup(temp);
-
-  temp = (port) ? port : DefaultPort;
-
-  if (pgport)
-    free(pgport);
-  pgport = strdup(temp);
-  
-  temp = (option) ? option : DefaultOption;
-
-  if (pgoption)
-    free(pgoption);
-  pgoption = strdup(temp);
-
-  temp = (tty) ? tty : DefaultTty;
-
-  if (pgtty)
-    free(pgtty);
-  pgtty = strdup(temp);
+  Auth( auth );
+  Host( host );
+  Port( port );
+  Option( option );
+  TTY( tty );
 }
 
-// default destrutor
-// frees allocated memory for internal structures
-PGenv::~PGenv()
+// read a string from the environment and convert it to string
+string PgEnv::getenv(const char* name)
 {
-  if (pgauth)
-    free(pgauth);
-  if (pghost)
-    free(pghost);
-  if (pgport)
-    free(pgport);
-  if (pgoption)
-    free(pgoption);
-  if (pgtty)
-    free(pgtty);
+  char* env = ::getenv(name);
+  return (env ? env : "");
 }
diff --git a/src/interfaces/libpq++/pgenv.h b/src/interfaces/libpq++/pgenv.h
new file mode 100644 (file)
index 0000000..768c5d8
--- /dev/null
@@ -0,0 +1,79 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgenv.h
+ *    
+ *
+ *   DESCRIPTION
+ *             Postgres Environment Class: manages and stores all the required
+ *             connection variables.
+ *
+ *   NOTES
+ *      Currently under construction.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PGENV_H
+#define PGENV_H
+
+#include <string>
+
+
+//
+// these are the environment variables used for getting defaults
+//
+
+#define ENV_DEFAULT_AUTH   "PGAUTH"
+#define ENV_DEFAULT_DBASE  "PGDATABASE"
+#define ENV_DEFAULT_HOST   "PGHOST"
+#define ENV_DEFAULT_OPTION "PGOPTION"
+#define ENV_DEFAULT_PORT   "PGPORT"
+#define ENV_DEFAULT_TTY    "PGTTY"
+
+// ****************************************************************
+//
+// PgEnv - the environment for setting up a connection to postgres
+//
+// ****************************************************************
+class PgEnv {
+private:
+  string pgAuth;
+  string pgHost;
+  string pgPort;
+  string pgOption;
+  string pgTty;
+  
+public:
+  PgEnv();  // default ctor will use reasonable defaults
+            // will use environment  variables PGHOST, PGPORT,
+            // PGOPTION, PGTTY
+  PgEnv(const string& auth, const string& host, const string& port, 
+        const string& option, const string& tty);
+  
+  // Access methods to all the environment variables
+  const char* Auth() { return pgAuth.c_str(); }
+  void Auth(const string& auth) { pgAuth = auth; }
+  
+  const char* Host() { return pgHost.c_str(); }
+  void Host(const string& host) { pgHost = host; }
+  
+  const char* Port() { return pgPort.c_str(); }
+  void Port(const string& port) { pgPort = port; }
+  
+  const char* Option() { return pgOption.c_str(); }
+  void Option(const string& option) { pgOption = option; }
+  
+  const char* TTY() { return pgTty.c_str(); }
+  void TTY(const string& tty) { pgTty = tty; }
+  
+  void SetValues(const string& auth, const string& host, const string& port, 
+                 const string& option, const string& tty);
+                 
+protected:
+  string getenv(const char*);
+};
+
+#endif // PGENV_H
index 4de4a1f0d9e7a81a5ecc4c76b4c96638e9f8863e..917a368f50c7931a320e1e52aa1c002a6b74532d 100644 (file)
-
 /*-------------------------------------------------------------------------
  *
  *   FILE
  *     pglobject.cc
  *
  *   DESCRIPTION
- *      implementation of the PGlobj class.
- *   PGlobj encapsulates a frontend to backend connection
+ *      implementation of the PgLargeObject class.
+ *   PgLargeObject encapsulates a frontend to backend connection
  *
  * Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pglobject.cc,v 1.2 1996/11/12 11:42:31 bryanh Exp $
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pglobject.cc,v 1.3 1997/02/13 10:00:34 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
-#include "libpq++.H"
-
 extern "C" {
-#include <unistd.h>
-#include <fcntl.h>
 #include "libpq/libpq-fs.h"
 }
 
+#include "pglobject.h"
+
+
+
+// ****************************************************************
+//
+// PgLargeObject Implementation
+//
+// ****************************************************************
 // default constructor
 // creates a large object in the default database
-PGlobj::PGlobj() : PGconnection::PGconnection() {
-  object = lo_creat(conn, INV_READ|INV_WRITE);
-  if (object == 0) {
-    sprintf(errorMessage, "PGlobj: can't create large object");
-  }
-  fd = lo_open(conn, object, INV_READ|INV_WRITE);
-  if (fd < 0) {
-    sprintf(errorMessage, "PGlobj: can't open large object %d", object);
-  } else
-    sprintf(errorMessage, "PGlobj: created and opened large object %d",
-           object);
-   
+PgLargeObject::PgLargeObject(const char* dbName)
+       : PgConnection(dbName)
+{
+  Init();
+  Create();
+  Open();
 }
 
 // constructor
 // open an existing large object in the default database
-PGlobj::PGlobj(Oid lobjId) : PGconnection::PGconnection() {
-  object = lobjId;
-  fd = lo_open(conn, object, INV_READ|INV_WRITE);
-  if (fd < 0) {
-    sprintf(errorMessage, "PGlobj: can't open large object %d", object);
-  } else
-    sprintf(errorMessage, "PGlobj: opened large object %d",
-           object);
+PgLargeObject::PgLargeObject(Oid lobjId, const char* dbName) 
+       : PgConnection(dbName)
+{
+  Init(lobjId);
+  if ( !pgObject )
+       Create();
+  Open();
 }
 
 // constructor
 // create a large object in the given database
-PGlobj::PGlobj(PGenv* env, char* dbName) : PGconnection::PGconnection(env,dbName) {
-  object = lo_creat(conn, INV_READ|INV_WRITE);
-  if (object == 0) {
-    sprintf(errorMessage, "PGlobj: can't create large object");
-  }
-  fd = lo_open(conn, object, INV_READ|INV_WRITE);
-  if (fd < 0) {
-    sprintf(errorMessage, "PGlobj: can't open large object %d", object);
-  } else
-    sprintf(errorMessage, "PGlobj: created and opened large object %d",
-           object);
+PgLargeObject::PgLargeObject(const PgEnv& env, const char* dbName)
+       : PgConnection(env, dbName)
+{
+  Init();
+  Create();
+  Open();
 }
 
 // constructor
 // open an existing large object in the given database
-PGlobj::PGlobj(PGenv* env, char* dbName, Oid lobjId) : PGconnection::PGconnection(env,dbName) {
-  object = lobjId;
-  fd = lo_open(conn, object, INV_READ|INV_WRITE);
-  if (fd < 0) {
-    sprintf(errorMessage, "PGlobj: can't open large object %d", object);
-  } else
-    sprintf(errorMessage, "PGlobj: created and opened large object %d",
-           object);
+PgLargeObject::PgLargeObject(const PgEnv& env, const char* dbName, Oid lobjId)
+       : PgConnection(env, dbName)
+{
+  Init(lobjId);
+  if ( !pgObject )
+       Create();
+  Open();
 }
 
-// PGlobj::unlink
-// destruct large object and delete from it from the database
-int
-PGlobj::unlink() {
-  int temp = lo_unlink(conn, object);
-  if (temp) {
-    return temp;
-  } else {
-    delete this;
-    return temp;
-  }
+// destructor -- closes large object
+PgLargeObject::~PgLargeObject()
+{
+  Close();
 }
 
-// PGlobj::import -- import a given file into the large object
-int
-PGlobj::import(char* filename) {
-    char buf[BUFSIZE];
-    int nbytes, tmp;
-    int in_fd;
-
-    // open the file to be read in
-    in_fd = open(filename, O_RDONLY, 0666);
-    if (in_fd < 0)  {   /* error */
-       sprintf(errorMessage, "PGlobj::import: can't open unix file\"%s\"", filename);
-       return -1;
-    }
-
-    // read in from the Unix file and write to the inversion file
-    while ((nbytes = ::read(in_fd, buf, BUFSIZE)) > 0) {
-      tmp = lo_write(conn, fd, buf, nbytes);
-      if (tmp < nbytes) {
-       sprintf(errorMessage, "PGlobj::import: error while reading \"%s\"",
-         filename);
-         return -1;
-      }
-    }
-    
-    (void) close(in_fd);
-    return 0;
+// PgLargeObject::Init
+// Initialize the variables
+void PgLargeObject::Init(Oid lobjId)
+{
+  pgFd = -1;
+  pgObject = lobjId;
 }
 
-// PGlobj::export -- export large object to given file
-int
-PGlobj::export(char* filename) {
-    int out_fd;
-    char buf[BUFSIZE];
-    int nbytes, tmp;
-
-    // open the file to be written to
-    out_fd = open(filename, O_CREAT|O_WRONLY, 0666);
-    if (out_fd < 0)  {   /* error */
-       sprintf(errorMessage, "PGlobj::export: can't open unix file\"%s\"",
-               filename);
-       return -1;
-    }
+// PgLargeObject::create
+// create large object and check for errors
+void PgLargeObject::Create()
+{
+  // Create the object
+  pgObject = lo_creat(pgConn, INV_READ|INV_WRITE);
+  
+  // Check for possible errors
+  if (!pgObject)
+      SetErrorMessage( "PgLargeObject: can't create large object" );
+}
 
-    // read in from the Unix file and write to the inversion file
-    while ((nbytes = lo_read(conn, fd, buf, BUFSIZE)) > 0) {
-      tmp = ::write(out_fd, buf, nbytes);
-      if (tmp < nbytes) {
-        sprintf(errorMessage,"PGlobj::export: error while writing \"%s\"",
-           filename);
-       return -1;
-      }
-    }
-    (void) close(out_fd);
-    return 0;
+// PgLargeObject::open
+// open large object and check for errors
+void PgLargeObject::Open()
+{
+  // Open the object
+  pgFd = lo_open(pgConn, pgObject, INV_READ|INV_WRITE);
+  
+  // Check for possible errors
+  string objStr( IntToString(pgObject) );
+  if (pgFd < 0)
+      SetErrorMessage( "PgLargeObject: can't open large object " + objStr );
+  else
+      SetErrorMessage( "PgLargeObject: created and opened large object " + objStr );
 }
 
-// default destructor -- closes large object
-PGlobj::~PGlobj() {
-  if (fd >= 0)
-    lo_close(conn, fd);
+// PgLargeObject::unlink
+// destruct large object and delete from it from the database
+int PgLargeObject::Unlink()
+{
+  // Unlink the object
+  int temp = lo_unlink(pgConn, pgObject);
+  
+  // Initialize the large object upon success
+  if (!temp) {
+      Close();
+      Init();
+  }
+  
+  // Return the status
+  return temp;
 }
diff --git a/src/interfaces/libpq++/pglobject.h b/src/interfaces/libpq++/pglobject.h
new file mode 100644 (file)
index 0000000..9fcd344
--- /dev/null
@@ -0,0 +1,64 @@
+/*-------------------------------------------------------------------------
+ *
+ *   FILE
+ *     pglobject.h
+ *
+ *   DESCRIPTION
+ *      declaration of the PGlobj class.
+ *   PGlobj encapsulates a large object interface to Postgres backend 
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pglobject.h,v 1.1 1997/02/13 10:00:35 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PGLOBJ_H
+#define PGLOBJ_H
+
+#include "pgconnection.h"
+
+// buffer size
+#define BUFSIZE 1024
+
+
+// ****************************************************************
+//
+// PgLargeObject - a class for accessing Large Object in a database
+//
+// ****************************************************************
+class PgLargeObject : public PgConnection {
+private:
+  int pgFd;
+  Oid pgObject;
+
+public:
+  PgLargeObject(const char* dbName = 0);   // use reasonable defaults and create large object
+  PgLargeObject(Oid lobjId, const char* dbName = 0); // use reasonable defaults and open large object
+  PgLargeObject(const PgEnv& env, const char* dbName);            // create large object
+  PgLargeObject(const PgEnv& env, const char* dbName, Oid lobjId); // open large object
+  ~PgLargeObject(); // close connection and clean up
+  
+  void Create();
+  void Open();
+  void Close()
+    { if (pgFd >= 0) lo_close(pgConn, pgFd); }
+  int Read(char* buf, int len)
+    { return lo_read(pgConn, pgFd, buf, len); }
+  int Write(const char* buf, int len)
+    { return lo_write(pgConn, pgFd, (char*)buf, len); }
+  int LSeek(int offset, int whence)
+    { return lo_lseek(pgConn, pgFd, offset, whence); }
+  int Tell()
+    { return lo_tell(pgConn, pgFd); }
+  int Unlink();
+  Oid Import(const char* filename) { return pgObject = lo_import(pgConn, (char*)filename); }
+  int Export(const char* filename) { return lo_export(pgConn, pgObject, (char*)filename); }
+  
+private:
+   void Init(Oid lobjId = 0);
+};
+
+#endif // PGLOBJ_H
diff --git a/src/interfaces/libpq++/pgtransdb.cc b/src/interfaces/libpq++/pgtransdb.cc
new file mode 100644 (file)
index 0000000..cef16a2
--- /dev/null
@@ -0,0 +1,65 @@
+/*-------------------------------------------------------------------------
+ *
+ *   FILE
+ *     pgtransdb.cpp
+ *
+ *   DESCRIPTION
+ *      implementation of the PgTransaction class.
+ *   PgConnection encapsulates a transaction querying to backend
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *    $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pgtransdb.cc,v 1.1 1997/02/13 10:00:36 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+ #include "pgtransdb.h"
+// ****************************************************************
+//
+// PgTransaction Implementation
+//
+// ****************************************************************
+// Make a connection to the specified database with default environment
+PgTransaction::PgTransaction(const char* dbName)
+   : PgDatabase(dbName)
+{
+       BeginTransaction();
+}
+
+// Make a connection to the specified database with the given environment
+PgTransaction::PgTransaction(const PgEnv& env, const char* dbName)
+   : PgDatabase(env, dbName)
+{
+       BeginTransaction();
+}
+
+// Do not make a connection to the backend -- just query
+// Connection should not be closed after the object destructs since some
+// other object is using the connection
+PgTransaction::PgTransaction(const PgConnection& conn) 
+   : PgDatabase(conn) 
+{
+       BeginTransaction();
+}
+
+// Destructor: End the transaction block
+PgTransaction::~PgTransaction()
+{
+       EndTransaction();
+}
+
+// Begin the transaction block
+ExecStatusType PgTransaction::BeginTransaction()
+{
+       return Exec("BEGIN");
+} // End BeginTransaction()
+
+// Begin the transaction block
+ExecStatusType PgTransaction::EndTransaction()
+{
+       return Exec("END");
+} // End EndTransaction()
diff --git a/src/interfaces/libpq++/pgtransdb.h b/src/interfaces/libpq++/pgtransdb.h
new file mode 100644 (file)
index 0000000..4bce4b1
--- /dev/null
@@ -0,0 +1,48 @@
+/*-------------------------------------------------------------------------
+ *
+ * pgtransdb.h
+ *    
+ *
+ *   DESCRIPTION
+ *             Postgres Transaction Database Class: 
+ *                Query Postgres backend using a transaction block
+ *
+ *   NOTES
+ *      Currently under construction.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PGTRANSDB_H
+#define PGTRANSDB_H
+
+#include "pgdatabase.h"
+
+
+// ****************************************************************
+//
+// PgTransaction - a class for running transactions against databases
+//
+// ****************************************************************
+// This is the database access class that keeps an open
+// transaction block during its lifetime.  The block is ENDed when
+// the object is destroyed.
+class PgTransaction : public PgDatabase {
+public:
+  PgTransaction(const char* dbName);   // use reasonable defaults
+  // connect to the database with given environment and database name
+  PgTransaction(const PgEnv& env, const char* dbName);
+  PgTransaction(const PgConnection&);
+  virtual ~PgTransaction();    // close connection and clean up
+  
+protected:
+  ExecStatusType BeginTransaction();
+  ExecStatusType EndTransaction();
+  
+protected:
+  PgTransaction() : PgDatabase() {}    // Do not connect
+}; // End PgTransaction Class Declaration
+
+#endif // PGTRANSDB_H