summaryrefslogtreecommitdiff
path: root/src/interfaces/libpq++
diff options
context:
space:
mode:
authorMarc G. Fournier <scrappy@hub.org>1996-07-09 06:22:35 +0000
committerMarc G. Fournier <scrappy@hub.org>1996-07-09 06:22:35 +0000
commitd31084e9d1118b25fd16580d9d8c2924b5740dff (patch)
tree3179e66307d54df9c7b966543550e601eb55e668 /src/interfaces/libpq++
downloadpostgresql-d31084e9d1118b25fd16580d9d8c2924b5740dff.tar.gz
Postgres95 1.01 Distribution - Virgin SourcesPG95-1_01
Diffstat (limited to 'src/interfaces/libpq++')
-rw-r--r--src/interfaces/libpq++/Makefile54
-rw-r--r--src/interfaces/libpq++/README22
-rw-r--r--src/interfaces/libpq++/examples/Makefile70
-rw-r--r--src/interfaces/libpq++/examples/testlibpq0.cc49
-rw-r--r--src/interfaces/libpq++/examples/testlibpq1.cc84
-rw-r--r--src/interfaces/libpq++/examples/testlibpq2.cc71
-rw-r--r--src/interfaces/libpq++/examples/testlibpq2.sql5
-rw-r--r--src/interfaces/libpq++/examples/testlibpq3.cc131
-rw-r--r--src/interfaces/libpq++/examples/testlibpq3.sql6
-rw-r--r--src/interfaces/libpq++/examples/testlibpq4.cc69
-rw-r--r--src/interfaces/libpq++/examples/testlo.cc63
-rw-r--r--src/interfaces/libpq++/libpq++.H173
-rw-r--r--src/interfaces/libpq++/man/libpq++.3434
-rw-r--r--src/interfaces/libpq++/pgconnection.cc94
-rw-r--r--src/interfaces/libpq++/pgenv.cc109
-rw-r--r--src/interfaces/libpq++/pglobject.cc152
16 files changed, 1586 insertions, 0 deletions
diff --git a/src/interfaces/libpq++/Makefile b/src/interfaces/libpq++/Makefile
new file mode 100644
index 0000000000..e1d58847ee
--- /dev/null
+++ b/src/interfaces/libpq++/Makefile
@@ -0,0 +1,54 @@
+#-------------------------------------------------------------------------
+#
+# Makefile
+# Makefile for libpq++ library
+#
+# Copyright (c) 1994, Regents of the University of California
+#
+#
+# IDENTIFICATION
+# $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/Makefile,v 1.1.1.1 1996/07/09 06:22:18 scrappy Exp $
+#
+#-------------------------------------------------------------------------
+
+CPP_LIB= true
+
+LIB= pq++
+
+MKDIR= ../mk
+include $(MKDIR)/postgres.mk
+
+CXXFLAGS = $(CFLAGS)
+
+CXXFLAGS+= -I$(srcdir)/backend/include \
+ -I$(srcdir)/backend \
+ -I$(srcdir)/libpq \
+ -I$(CURDIR) \
+
+ifdef KRBVERS
+CXXFLAGS+= $(KRBFLAGS)
+endif
+
+
+LIBSRCS = pgenv.cc pgconnection.cc pglobject.cc
+
+.PHONY: beforeinstall-headers install-headers
+
+ifndef NO_BEFOREINSTL
+beforeinstall-headers:
+ @-if [ ! -d $(HEADERDIR) ]; then mkdir $(HEADERDIR); fi
+else
+beforeinstall-headers: .dosomething
+endif
+
+HEADERFILES = libpq++.H
+
+install-headers: beforeinstall-headers
+ @for i in ${HEADERFILES}; do \
+ echo "Installing $(HEADERDIR)/$$i."; \
+ $(INSTALL) -c -m 444 $$i $(HEADERDIR)/$$i; \
+ done
+
+install:: install-headers
+
+include $(MKDIR)/postgres.lib.mk
diff --git a/src/interfaces/libpq++/README b/src/interfaces/libpq++/README
new file mode 100644
index 0000000000..cb5d0aeddb
--- /dev/null
+++ b/src/interfaces/libpq++/README
@@ -0,0 +1,22 @@
+This directory contains libpq++, the C++ language interface to POSTGRES95.
+libpq++ is implemented on of the libpq library. Users would benefit
+from reading the chapter on libpq in the postgres95 users manual
+before using libpq++.
+
+The initial version of this implementation was done by William Wanders
+(wwanders@sci.kun.nl)
+
+This is only a preliminary attempt at providing something useful for
+people who would like to use C++ to build frontend applications to
+postgres95. The API provided herein is subject to change in later
+versions of postgres95.
+
+For details on how to to use libpq++, see the man page in the man/
+subdirectory and the test programs in the examples/ subdirectory.
+
+libpq++ has been tested with g++, version 2.7.0
+
+- Jolly Chen
+jolly@cs.berkeley.edu
+
+Tue Sep 5 11:09:51 PDT 1995
diff --git a/src/interfaces/libpq++/examples/Makefile b/src/interfaces/libpq++/examples/Makefile
new file mode 100644
index 0000000000..5e51d91587
--- /dev/null
+++ b/src/interfaces/libpq++/examples/Makefile
@@ -0,0 +1,70 @@
+#
+# Makefile for example programs
+#
+
+CPP_PROG = true
+
+MKDIR= ../../mk
+include $(MKDIR)/postgres.mk
+
+CXXFLAGS+= -I$(HEADERDIR) -I$(srcdir)/libpq -I$(srcdir)/backend \
+ -I$(srcdir)/backend/include
+
+LD_ADD+=-L$(LIBDIR) -lpq++ -lpq
+
+#
+# And where libpq goes, so goes the authentication stuff...
+#
+ifdef KRBVERS
+LD_ADD+= $(KRBLIBS)
+CXXFLAGS+= $(KRBFLAGS)
+endif
+
+P0_PROG:= testlibpq0
+P0_OBJS:= testlibpq0.o
+
+$(P0_PROG): $(addprefix $(objdir)/,$(P0_OBJS))
+ $(CXX) $(CDEBUG) -o $(objdir)/$(@F) $< $(LD_ADD)
+
+P1_PROG:= testlibpq1
+P1_OBJS:= testlibpq1.o
+
+$(P1_PROG): $(addprefix $(objdir)/,$(P1_OBJS))
+ $(CXX) $(CDEBUG) -o $(objdir)/$(@F) $< $(LD_ADD)
+
+P2_PROG:= testlibpq2
+P2_OBJS:= testlibpq2.o
+
+$(P2_PROG): $(addprefix $(objdir)/,$(P2_OBJS))
+ $(CXX) $(CDEBUG) -o $(objdir)/$(@F) $< $(LD_ADD)
+
+P3_PROG:= testlibpq3
+P3_OBJS:= testlibpq3.o
+
+$(P3_PROG): $(addprefix $(objdir)/,$(P3_OBJS))
+ $(CXX) $(CDEBUG) -o $(objdir)/$(@F) $< $(LD_ADD)
+
+P4_PROG:= testlibpq4
+P4_OBJS:= testlibpq4.o
+
+$(P4_PROG): $(addprefix $(objdir)/,$(P4_OBJS))
+ $(CXX) $(CDEBUG) -o $(objdir)/$(@F) $< $(LD_ADD)
+
+P5_PROG:= testlo
+P5_OBJS:= testlo.o
+
+$(P5_PROG): $(addprefix $(objdir)/,$(P5_OBJS))
+ $(CXX) $(CDEBUG) -o $(objdir)/$(@F) $< $(LD_ADD)
+
+OBJS:= $(P0_OBJS) $(P1_OBJS) $(P2_OBJS) $(P3_OBJS) $(P4_OBJS) $(P5_OBJS)
+PROGS:= $(P0_PROG) $(P1_PROG) $(P2_PROG) $(P3_PROG) $(P4_PROG) $(P5_PROG)
+
+CLEANFILES+= $(OBJS) $(PROGS)
+
+all:: $(PROGS)
+
+install:: $(PROGS)
+ @for i in ${PROGS}; do \
+ echo "Installing $$i"; \
+ $(INSTALL) $(objdir)/$$i $(DESTDIR)$(BINDIR)/$$i;\
+ done
diff --git a/src/interfaces/libpq++/examples/testlibpq0.cc b/src/interfaces/libpq++/examples/testlibpq0.cc
new file mode 100644
index 0000000000..76f3ea8071
--- /dev/null
+++ b/src/interfaces/libpq++/examples/testlibpq0.cc
@@ -0,0 +1,49 @@
+/*-------------------------------------------------------------------------
+ *
+ * testlibpq0.c--
+ * small test program for libpq++,
+ * small interactive loop where queries can be entered interactively
+ * and sent to the backend
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq++/examples/Attic/testlibpq0.cc,v 1.1.1.1 1996/07/09 06:22:18 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include <stdio.h>
+#include "libpq++.H"
+
+int
+main(int argc, char** argv)
+{
+ ExecStatusType status;
+ PGenv env;
+ PGdatabase* data;
+
+ char buf[10000];
+ 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 = %s\nerrorMessage = %s\n", status,
+ data->errormessage());
+ else
+ done = 1;
+ }
+}
diff --git a/src/interfaces/libpq++/examples/testlibpq1.cc b/src/interfaces/libpq++/examples/testlibpq1.cc
new file mode 100644
index 0000000000..1d71f79558
--- /dev/null
+++ b/src/interfaces/libpq++/examples/testlibpq1.cc
@@ -0,0 +1,84 @@
+/*
+ * testlibpq.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;
+
+ /* Select a database */
+ dbName = "template1";
+
+ /* 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);
+ }
+
+ /* start a transaction block */
+ if(data->exec("BEGIN") != PGRES_COMMAND_OK) {
+ fprintf(stderr,"BEGIN command failed\n");
+ delete data;
+ 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;
+ 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;
+ 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");
+
+ /* 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");
+ }
+
+ /* close the portal */
+ data->exec("CLOSE myportal");
+
+ /* end the transaction */
+ data->exec("END");
+
+ /* close the connection to the database and cleanup */
+ delete data;
+}
+
+
diff --git a/src/interfaces/libpq++/examples/testlibpq2.cc b/src/interfaces/libpq++/examples/testlibpq2.cc
new file mode 100644
index 0000000000..8eafea00b7
--- /dev/null
+++ b/src/interfaces/libpq++/examples/testlibpq2.cc
@@ -0,0 +1,71 @@
+/*
+ * 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);
+
+ *
+ *
+ */
+#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;
+ PGnotify* notify;
+
+ 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);
+ }
+
+ if (data->exec("LISTEN TBL2") != PGRES_COMMAND_OK) {
+ fprintf(stderr,"LISTEN command failed\n");
+ delete data;
+ 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;
+ }
+ }
+
+ /* close the connection to the database and cleanup */
+ delete data;
+}
diff --git a/src/interfaces/libpq++/examples/testlibpq2.sql b/src/interfaces/libpq++/examples/testlibpq2.sql
new file mode 100644
index 0000000000..f9c7410932
--- /dev/null
+++ b/src/interfaces/libpq++/examples/testlibpq2.sql
@@ -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/testlibpq3.cc b/src/interfaces/libpq++/examples/testlibpq3.cc
new file mode 100644
index 0000000000..1146dffac9
--- /dev/null
+++ b/src/interfaces/libpq++/examples/testlibpq3.cc
@@ -0,0 +1,131 @@
+/*
+ * 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)
+
+ *
+ */
+#include <stdio.h>
+#include "libpq++.H"
+extern "C" {
+#include "utils/geo-decls.h" /* for the POLYGON type */
+}
+
+main()
+{
+ char* dbName;
+ int nFields;
+ int i,j;
+ int i_fnum, d_fnum, p_fnum;
+
+ /* 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);
+ }
+
+ /* start a transaction block */
+ if (data->exec("BEGIN") != PGRES_COMMAND_OK) {
+ fprintf(stderr,"BEGIN command failed\n");
+ delete data;
+ 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;
+ 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;
+ 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);
+ }
+
+ /* close the portal */
+ data->exec("CLOSE mycursor");
+
+ /* end the transaction */
+ data->exec("END");
+
+ /* close the connection to the database and cleanup */
+ delete data;
+}
diff --git a/src/interfaces/libpq++/examples/testlibpq3.sql b/src/interfaces/libpq++/examples/testlibpq3.sql
new file mode 100644
index 0000000000..f024c0b071
--- /dev/null
+++ b/src/interfaces/libpq++/examples/testlibpq3.sql
@@ -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/testlibpq4.cc b/src/interfaces/libpq++/examples/testlibpq4.cc
new file mode 100644
index 0000000000..9d5ca3ec76
--- /dev/null
+++ b/src/interfaces/libpq++/examples/testlibpq4.cc
@@ -0,0 +1,69 @@
+/*
+ * testlibpq4.cc
+ * Test the C++ version of LIBPQ, the POSTGRES frontend library.
+ * tests the copy in features
+ *
+ */
+#include <stdio.h>
+#include "libpq++.H"
+
+#define DEBUG printf("Got here %d\n", __LINE__);
+main()
+{
+ char* dbName;
+ int nFields;
+ int i,j;
+
+ /* 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;
+
+ 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);
+ }
+
+ /* start a transaction block */
+ if(data->exec("BEGIN") != PGRES_COMMAND_OK) {
+ fprintf(stderr,"BEGIN command failed\n");
+ delete data;
+ 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);
+ }
+
+ if (data->exec("COPY foo FROM STDIN") != PGRES_COMMAND_OK) {
+ fprintf(stderr,"COPY foo FROM STDIN\n");
+ delete data;
+ exit(1);
+ }
+
+ 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/testlo.cc b/src/interfaces/libpq++/examples/testlo.cc
new file mode 100644
index 0000000000..be3459794f
--- /dev/null
+++ b/src/interfaces/libpq++/examples/testlo.cc
@@ -0,0 +1,63 @@
+/*-------------------------------------------------------------------------
+ *
+ * lotest.cc--
+ * test using large objects with libpq
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq++/examples/Attic/testlo.cc,v 1.1.1.1 1996/07/09 06:22:19 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include <stdio.h>
+#include "libpq++.H"
+extern "C" {
+#include "libpq/libpq-fs.h"
+}
+
+int
+main(int argc, char **argv)
+{
+ char *in_filename, *out_filename;
+ char *database;
+ Oid lobjOid;
+ PGenv env;
+ PGlobj *object;
+
+ if (argc < 4 || argc > 5) {
+ fprintf(stderr, "Usage: %s database_name in_filename out_filename [oid]\n",
+ argv[0]);
+ exit(1);
+ }
+
+ database = argv[1];
+ in_filename = argv[2];
+ 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]));
+ }
+
+ /* 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);
+ }
+
+ 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;
+}
diff --git a/src/interfaces/libpq++/libpq++.H b/src/interfaces/libpq++/libpq++.H
new file mode 100644
index 0000000000..9b3e173900
--- /dev/null
+++ b/src/interfaces/libpq++/libpq++.H
@@ -0,0 +1,173 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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.1.1 1996/07/09 06:22:18 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef LIBPQXX_H
+#define LIBPQXX_H
+
+#include <stdio.h>
+#include <strings.h>
+
+extern "C" {
+#include "libpq-fe.h"
+#include "fe-auth.h"
+}
+
+// ****************************************************************
+//
+// PGenv - the environment for setting up a connection to postgres
+//
+// ****************************************************************
+class PGenv {
+ friend class PGconnection;
+ char* pgauth;
+ char* pghost;
+ char* pgport;
+ char* pgoption;
+ char* pgtty;
+public:
+ PGenv(); // default ctor will use reasonable defaults
+ // will use environment variables PGHOST, PGPORT,
+ // PGOPTION, PGTTY
+ PGenv(char* auth, char* host, char* port, char* option, char* tty);
+ void setValues(char* auth, char* host, char* port, char* option, char* tty);
+ ~PGenv();
+};
+
+// ****************************************************************
+//
+// PGconnection - a connection made to a postgres backend
+//
+// ****************************************************************
+class PGconnection {
+ friend class PGdatabase;
+ friend class PGlobj;
+ PGenv* env;
+ PGconn* conn;
+ PGresult* result;
+
+ char errorMessage[ERROR_MSG_LENGTH];
+public:
+ PGconnection(); // use reasonable defaults
+ PGconnection(PGenv* env, char* dbName); // connect to the database with
+ // given environment and database name
+ ConnStatusType status();
+ char* errormessage() {return errorMessage;};
+
+ // returns the database name of the connection
+ char* dbName() {return PQdb(conn);};
+
+ ExecStatusType exec(char* query); // send a query to the backend
+ PGnotify* notifies() {exec(" "); return PQnotifies(conn);};
+ ~PGconnection(); // close connection and clean up
+protected:
+ ConnStatusType connect(PGenv* env, char* dbName);
+};
+
+// ****************************************************************
+//
+// PGdatabase - a class for accessing databases
+//
+// ****************************************************************
+class PGdatabase : public PGconnection {
+public:
+ PGdatabase() : PGconnection() {}; // use reasonable defaults
+ // connect to the database with
+ PGdatabase(PGenv* env, char* dbName) : PGconnection(env, dbName) {};
+ // query result access
+ int ntuples()
+ {return PQntuples(result);};
+ int nfields()
+ {return PQnfields(result);};
+ char* fieldname(int field_num)
+ {return PQfname(result, field_num);};
+ int fieldnum(char* field_name)
+ {return PQfnumber(result, field_name);};
+ Oid fieldtype(int field_num)
+ {return PQftype(result, field_num);};
+ Oid fieldtype(char* field_name)
+ {return PQftype(result, fieldnum(field_name));};
+ int2 fieldsize(int field_num)
+ {return PQfsize(result, field_num);};
+ int2 fieldsize(char* field_name)
+ {return PQfsize(result, fieldnum(field_name));};
+ char* getvalue(int tup_num, int field_num)
+ {return PQgetvalue(result, tup_num, field_num);};
+ char* getvalue(int tup_num, char* field_name)
+ {return PQgetvalue(result, tup_num, fieldnum(field_name));};
+ int getlength(int tup_num, int field_num)
+ {return PQgetlength(result, tup_num, field_num);};
+ int getlength(int tup_num, char* field_name)
+ {return PQgetlength(result, tup_num, fieldnum(field_name));};
+ void printtuples(FILE *out, int fillAlign, char *fieldSep,
+ int printHeader, int quiet)
+ {PQdisplayTuples(result, out, fillAlign, fieldSep, printHeader, quiet);};
+ // copy command related access
+ int getline(char* string, int length)
+ {return PQgetline(conn, string, length);};
+ void putline(char* string)
+ {PQputline(conn, string);};
+ int endcopy()
+ {return PQendcopy(conn);};
+ ~PGdatabase() {}; // close connection and clean up
+};
+
+// ****************************************************************
+//
+// PGlobj - a class for accessing Large Object in a database
+//
+// ****************************************************************
+class PGlobj : public PGconnection {
+ int fd;
+ Oid object;
+public:
+ PGlobj(); // use reasonable defaults and create large object
+ PGlobj(Oid lobjId); // use reasonable defaults and open large object
+ PGlobj(PGenv* env, char* dbName); // create large object
+ PGlobj(PGenv* env, char* dbName, Oid lobjId); // open large object
+ int read(char* buf, int len)
+ {return lo_read(conn, fd, buf, len);};
+ int write(char* buf, int len)
+ {return lo_write(conn, fd, buf, len);};
+ int lseek(int offset, int whence)
+ {return lo_lseek(conn, fd, offset, whence);};
+ int tell()
+ {return lo_tell(conn, fd);};
+ int unlink();
+ int import(char* filename);
+ int export(char* filename);
+ ~PGlobj(); // close connection and clean up
+};
+
+//
+// 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"
+
+// buffer size
+#define BUFSIZE 1024
+
+#endif /* LIBPQXX_H */
diff --git a/src/interfaces/libpq++/man/libpq++.3 b/src/interfaces/libpq++/man/libpq++.3
new file mode 100644
index 0000000000..ebca7ab7bb
--- /dev/null
+++ b/src/interfaces/libpq++/man/libpq++.3
@@ -0,0 +1,434 @@
+.\"
+.\" POSTGRES95 Data Base Management System
+.\"
+.\" Copyright (c) 1994-5 Regents of the University of California
+.\"
+.\" POSTGRES Data Base Management System
+.\" Copyright (c) 1988,1994 Regents of the University of California
+.\"
+.\" Permission to use, copy, modify, and distribute this software and its
+.\" documentation for any purpose, without fee, and without a written agreement
+.\" is hereby granted, provided that the above copyright notice and this
+.\" paragraph and the following two paragraphs appear in all copies.
+.\"
+.\" IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+.\" DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+.\" LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+.\" DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+.\" ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
+.\" PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+.\"
+.\"
+.\" $Id: libpq++.3,v 1.1.1.1 1996/07/09 06:22:19 scrappy Exp $
+.\"
+.\" ------------------------------------------------------------------
+.\" .(l, .)l
+.\" fake "-me"-style lists
+.de (l
+.nf
+.ie '\\$1'M' .in +0n
+.el .in +5n
+..
+.de )l
+.fi
+.in
+..
+.\" .(C, .)C
+.\" constant-width font blocks
+.de (C
+.ft C
+.(b
+.(l \\$1
+.sp
+..
+.de )C
+.sp
+.)l
+.)b
+.ft R
+..
+.\" ------------------------------------------------------------------
+.de SE
+.nr si 0
+.nr so 0
+.nr $0 0
+.nr $i \\n(si*\\n($0
+.in \\n($i+\\n(po
+..
+.\" ------------------------------------------------------------------
+.de SP
+.he '\fB\\$1 (\\$2)'\\$3'\\$1 (\\$2)\fR'
+..
+.\" ------------------------------------------------------------------
+.de SS
+.PP
+.B \\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8
+.PP
+..
+.\" ------------------------------------------------------------------
+.SB
+.ds II \s-1INGRES\s0
+.ds PG \s-1POSTGRES95\s0
+.ds UU \s-1UNIX\s0
+.ds PQ \s-1POSTQUEL\s0
+.ds LI \s-1LIBPQ++\s0
+.ds PV 4.2
+.SB
+.TH INTRODUCTION LIBPQ++ 07/24/95
+.XA 0 "Libpq++"
+.BH "LIBPQ++"
+.SH DESCRIPTION
+\*(LI is the C++ API to \*(PG. \*(LI is a set of classes which allow
+client programs to connect to the \*(PG backend server. These connections
+come in two forms: a Database Class and a Large Object class.
+.PP
+The Database Class is intended for manipulating a database. You can
+send all sorts of SQL queries to the \*(PG backend server and retrieve
+the responses of the server.
+.PP
+The Large Object Class is intended for manipulating a large object
+in a database. Although a Large Object instance can send normal
+queries to the \*(PG backend server it is only intended for simple
+queries that do not return any data. A large object should be seen
+as a file stream. In future it should behave much like the C++ file
+streams
+.IR cin ,
+.IR cout
+and
+.IR cerr .
+This version of the documentation is based on the C library. Three
+short programs are listed at the end of this section as examples of
+\*(LI programming (though not necessarily of good programming).
+.PP
+There are several examples of \*(LI applications in the following
+directory:
+.(C
+\&.../src/libpq++/examples
+.)C
+.XA 1 "Control and Initialization"
+.SH "CONTROL AND INITIALIZATION"
+.XA 2 "Environment Variables"
+.SS "Environment Variables"
+The following environment variables can be used to set up default
+values for an environment and to avoid hard-coding database names into
+an application program:
+.TP 15n
+.BR PGDATABASE
+sets the default \*(PG database name.
+.TP 15n
+.BR PGHOST
+sets the default server name.
+.TP 15n
+.BR PGOPTIONS
+sets additional runtime options for the \*(PG backend.
+.TP 15n
+.BR PGPORT
+sets the default communication port with the \*(PG backend.
+.TP 15n
+.BR PGTTY
+sets the file or tty on which debugging messages from the backend server
+are displayed.
+.TP 15n
+.BR PGREALM
+sets the
+.IR Kerberos
+realm to use with \*(PG, if it is different from the local realm. If
+.SM PGREALM
+is set, \*(PG applications will attempt authentication with servers
+for this realm and use separate ticket files to avoid conflicts with
+local ticket files. This environment variable is only used if
+.IR Kerberos
+authentication is enabled.
+.TP 15n
+.BR PGAUTH
+sets the type of authentication which should be used. Currently
+only
+.IR unauth ,
+.IR krb4 ,
+and
+.IR krb5 .
+are supported. Depending on whether you compiled in support for those.
+.XA 1 "Database Connection Functions"
+.SH "DATABASE ENVIRONMENT CLASS: PGenv"
+The database environment class provides C++ objects for manipulating the
+above environment variables.
+.TP 15n
+.BR PGenv
+Create an environment for the running program.
+.(C
+PGenv()
+PGenv(char* auth, char* host, char* port, char* option, char* tty)
+.)C
+The first form of this object's constructor sets up the defaults for
+the program from the environment variables listed above.
+The second allows the programmer to hardcode the values into the program.
+The values of the second form relate directly to the environment variables
+above.
+.SH "DATABASE CLASS: PGdatabase"
+The database class is a provides C++ objects that have a connection
+to a backend server. To create such an object one first need
+the apropriate environment for the backend to access.
+The following constructors deal with making a connection to a backend
+server from a C++ program.
+.TP 15n
+.BR PGdatabase
+Make a new connection to a backend database server.
+.(C
+PGdatabase(PGenv *env, char *dbName);
+.)C
+After a PGdatabase has been created it should be checked to make sure
+the connection to the database succeded before sending
+queries to the object. This can easily be done by
+retrieving the current status of the PGdatabase object with the
+.IR status
+command.
+.BR PGdatabase::status
+Returns the status of the PGdatabase object.
+
+.(C
+ConnStatus PGdatabase::status()
+.)C
+
+the following values are allowed
+
+.(C
+CONNECTION_OK
+CONNECTION_BAD
+.)C
+
+.XA 1 "Query Execution Functions"
+.SH "QUERY EXECUTION FUNCTIONS"
+.TP 15n
+.BR PGdatabase::exec
+Submits a query to \*(PG and returns result status. In case of an error
+.IR PGdatabase::errormessage
+can be used to get more information on the error.
+.(C
+void
+ExecStatusType PGdatabase::exec(char *query);
+.)C
+The following status results can be expected.
+.(C
+PGRES_EMPTY_QUERY,
+PGRES_COMMAND_OK, /* the query was a command */
+PGRES_TUPLES_OK, /* the query successfully returned tuples */
+PGRES_COPY_OUT,
+PGRES_COPY_IN,
+PGRES_BAD_RESPONSE, /* an unexpected response was received */
+PGRES_NONFATAL_ERROR,
+PGRES_FATAL_ERROR
+.)C
+.IP
+If the result status is PGRES_TUPLES_OK, then the following routines can
+be used to retrieve the tuples returned by the query.
+.IP
+.BR PGdatabase::ntuples
+returns the number of tuples (instances) in the query result.
+.(C
+int PGdatabase::ntuples();
+.)C
+.BR PGdatabase::nfields
+returns the number of fields (attributes) in the query result.
+.(C
+int PGdatabase::nfields();
+.)C
+.BR PGdatabase::fieldname
+returns the field (attribute) name associated with the given field index.
+Field indices start at 0.
+.(C
+char* PGdatabase::fieldname(int field_index);
+.)C
+.BR PGdatabase::fieldnum
+returns the field (attribute) index associated with the given field name.
+.(C
+int PGdatabase::fieldnum(char* field_name);
+.)C
+.BR PGdatabase::fieldtype
+returns the field type of associated with the given field index or name.
+The integer returned is an internal coding of the type. Field indices start
+at 0.
+.(C
+Oid PGdatabase::fieldtype(int field_index);
+Oid PGdatabase::fieldtype(char* field_name);
+.)C
+.BR PGdatabase::fieldsize
+returns the size in bytes of the field associated with the given field
+index or name. If the size returned is -1, the field is a variable length
+field. Field indices start at 0.
+.(C
+int2 PGdatabase::fieldsize(int field_index);
+int2 PGdatabase::fieldsize(char* field_name);
+.)C
+.BR PGdatabase::getvalue
+returns the field (attribute) value. For most queries, the values
+returned by
+.IR PGdatabase::getvalue
+is a null-terminated ASCII string representation
+of the attribute value. If the query was a result of a
+.BR BINARY
+cursor, then the values returned by
+.IR PGdatabase::getvalue
+is the binary representation of the type in the internal format of the
+backend server. It is the programmer's responsibility to cast and
+convert the data to the correct C++ type. The value return by
+.IR PGdatabase::getvalue
+points to storage that is part of the PGdatabase structure. One must
+explicitly copy the value into other storage if it is to be used past
+the next query.
+.(C
+char* PGdatabase::getvalue(int tup_num, int field_index);
+char* PGdatabase::getvalue(int tup_num, char* field_name);
+.)C
+.BR PGdatabase::getlength
+returns the length of a field (attribute) in bytes. If the field
+is a
+.IR "struct varlena" ,
+the length returned here does
+.BR not
+include the size field of the varlena, i.e., it is 4 bytes less.
+.(C
+int PGdatabase::getlength(int tup_num, int field_index);
+int PGdatabase::getlength(int tup_num, char* field_name);
+.)C
+.BR PGdatabase::printtuples
+prints out all the tuples and, optionally, the attribute names to the
+specified output stream.
+.(C
+void PGdatabase::printtuples(
+ FILE* fout, /* output stream */
+ int printAttName,/* print attribute names or not*/
+ int terseOutput, /* delimiter bars or not?*/
+ int width /* width of column, variable width if 0*/
+ );
+.)C
+.XA 1 "Asynchronous Notification"
+.SH "ASYNCHRONOUS NOTIFICATION"
+\*(PG supports asynchronous notification via the
+.IR LISTEN
+and
+.IR NOTIFY
+commands. A backend registers its interest in a particular relation
+with the LISTEN command. All backends that are listening on a
+particular relation will be notified asynchronously when a NOTIFY of
+that relation name is executed by another backend. No additional
+information is passed from the notifier to the listener. Thus,
+typically, any actual data that needs to be communicated is transferred
+through the relation.
+.PP
+\*(LI applications are notified whenever a connected backend has
+received an asynchronous notification. However, the communication from
+the backend to the frontend is not asynchronous. The \*(LI application
+must poll the backend to see if there is any pending notification
+information. After the execution of a query, a frontend may call
+.IR PGdatabase::notifies
+to see if any notification data is currently available from the backend.
+.TP 15n
+.BR PGdatabase::notifies
+returns the notification from a list of unhandled notifications from the
+backend. Returns NULL if there is no pending notifications from the
+backend.
+.IR PGdatabase::notifies
+behaves like the popping of a stack. Once a notification is returned
+from
+.IR PGdatabase::notifies,
+it is considered handled and will be removed from the list of
+notifications.
+.(C
+PGnotify* PGdatabase::notifies()
+.)C
+.PP
+The second sample program gives an example of the use of asynchronous
+notification.
+.XA 1 "Functions Associated with the COPY Command"
+.SH "FUNCTIONS ASSOCIATED WITH THE COPY COMMAND"
+The
+.IR copy
+command in \*(PG has options to read from or write to the network
+connection used by \*(LI. Therefore, functions are necessary to
+access this network connection directly so applications may take full
+advantage of this capability.
+.TP 15n
+.BR PGdatabase::getline
+Reads a newline-terminated line of characters (transmitted by the
+backend server) into a buffer
+.IR string
+of size
+.IR length .
+Like
+.IR fgets (3),
+this routine copies up to
+.IR length "-1"
+characters into
+.IR string .
+It is like
+.IR gets (3),
+however, in that it converts the terminating newline into a null
+character.
+.IP
+.IR PGdatabase::getline
+returns EOF at EOF, 0 if the entire line has been read, and 1 if the
+buffer is full but the terminating newline has not yet been read.
+.IP
+Notice that the application must check to see if a new line consists
+of the single character \*(lq.\*(rq, which indicates that the backend
+server has finished sending the results of the
+.IR copy
+command. Therefore, if the application ever expects to receive lines
+that are more than
+.IR length "-1"
+characters long, the application must be sure to check the return
+value of
+.IR PGdatabase::getline
+very carefully.
+.IP
+.(C
+int PGdatabase::getline(char* string, int length)
+.)C
+.TP 15n
+.BR PGdatabase::putline
+Sends a null-terminated
+.IR string
+to the backend server.
+.IP
+The application must explicitly send the single character \*(lq.\*(rq
+to indicate to the backend that it has finished sending its data.
+.(C
+void PGdatabase::putline(char* string)
+.)C
+.TP 15n
+.BR PGdatabase::endcopy
+Syncs with the backend. This function waits until the backend has
+finished processing the copy. It should either be issued when the
+last string has been sent to the backend using
+.IR PGdatabase::putline
+or when the last string has been received from the backend using
+.IR PGdatabase::getline .
+It must be issued or the backend may get \*(lqout of sync\*(rq with
+the frontend. Upon return from this function, the backend is ready to
+receive the next query.
+.IP
+The return value is 0 on successful completion, nonzero otherwise.
+.(C
+int PGdatabase::endcopy()
+.)C
+As an example:
+.(C
+PGdatabase data;
+data.exec("create table foo (a int4, b char16, d float8)");
+data.exec("copy foo from stdin");
+data.putline("3\etHello World\et4.5\en");
+data.putline("4\etGoodbye World\et7.11\en");
+\&...
+data.putline(".\en");
+data.endcopy();
+.)C
+.SH BUGS
+The query buffer is 8192 bytes long, and queries over that length will
+be silently truncated.
+.bp
+The PGlobj class is largely untested. Use with caution.
diff --git a/src/interfaces/libpq++/pgconnection.cc b/src/interfaces/libpq++/pgconnection.cc
new file mode 100644
index 0000000000..777a12e8e7
--- /dev/null
+++ b/src/interfaces/libpq++/pgconnection.cc
@@ -0,0 +1,94 @@
+/*-------------------------------------------------------------------------
+ *
+ * FILE
+ * pgconnection.cc
+ *
+ * DESCRIPTION
+ * 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 $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "libpq++.H"
+
+// default constructor
+// checks environment variable for database name
+PGconnection::PGconnection()
+{
+ char* name;
+ PGenv* newenv;
+
+ conn = NULL;
+ result = NULL;
+ errorMessage[0] = '\0';
+
+ newenv = new PGenv(); // use reasonable defaults for the environment
+ if (!(name = getenv(ENV_DEFAULT_DBASE)))
+ return;
+ connect(newenv, name);
+}
+
+// constructor -- for given environment and database name
+PGconnection::PGconnection(PGenv* env, char* dbName)
+{
+ conn = NULL;
+ result = NULL;
+ errorMessage[0] = '\0';
+ connect(env, dbName);
+}
+
+// destructor - closes down the connection and cleanup
+PGconnection::~PGconnection()
+{
+ if (result) PQclear(result);
+ if (conn) PQfinish(conn);
+}
+
+// PGconnection::connect
+// establish a connection to a backend
+ConnStatusType
+PGconnection::connect(PGenv* newenv, 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;
+ else
+ return status();
+}
+
+// PGconnection::status -- return connection or result status
+ConnStatusType
+PGconnection::status()
+{
+ return PQstatus(conn);
+}
+
+// PGconnection::exec -- send a query to the backend
+ExecStatusType
+PGconnection::exec(char* query)
+{
+ if (result)
+ PQclear(result);
+
+ result = PQexec(conn, query);
+ if (result)
+ return PQresultStatus(result);
+ else {
+ strcpy(errorMessage, PQerrorMessage(conn));
+ return PGRES_FATAL_ERROR;
+ }
+}
diff --git a/src/interfaces/libpq++/pgenv.cc b/src/interfaces/libpq++/pgenv.cc
new file mode 100644
index 0000000000..aab4f213eb
--- /dev/null
+++ b/src/interfaces/libpq++/pgenv.cc
@@ -0,0 +1,109 @@
+/*-------------------------------------------------------------------------
+ *
+ * FILE
+ * PGenv.cc
+ *
+ * DESCRIPTION
+ * PGenv is the environment for setting up a connection to a
+ * postgres backend, captures the host, port, tty, options and
+ * authentication type.
+ *
+ * NOTES
+ * Currently under construction.
+ *
+ * Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pgenv.cc,v 1.1.1.1 1996/07/09 06:22:18 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include <stdlib.h>
+#include "libpq++.H"
+
+#define DefaultAuth DEFAULT_CLIENT_AUTHSVC
+#define DefaultPort POSTPORT
+
+// default constructor for PGenv
+// checks the environment variables
+PGenv::PGenv()
+{
+ char* temp;
+
+ pgauth = NULL;
+ pghost = NULL;
+ pgport = NULL;
+ pgoption = NULL;
+ pgtty = NULL;
+
+ setValues(getenv(ENV_DEFAULT_AUTH), getenv(ENV_DEFAULT_HOST),
+ getenv(ENV_DEFAULT_PORT), getenv(ENV_DEFAULT_OPTION),
+ getenv(ENV_DEFAULT_TTY));
+}
+
+// constructor for given environment
+PGenv::PGenv(char* auth, char* host, char* port, char* option, char* tty)
+{
+ pgauth = NULL;
+ pghost = NULL;
+ pgport = NULL;
+ pgoption = NULL;
+ pgtty = NULL;
+
+ 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)
+{
+ 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);
+}
+
+// default destrutor
+// frees allocated memory for internal structures
+PGenv::~PGenv()
+{
+ if (pgauth)
+ free(pgauth);
+ if (pghost)
+ free(pghost);
+ if (pgport)
+ free(pgport);
+ if (pgoption)
+ free(pgoption);
+ if (pgtty)
+ free(pgtty);
+}
diff --git a/src/interfaces/libpq++/pglobject.cc b/src/interfaces/libpq++/pglobject.cc
new file mode 100644
index 0000000000..20c7ad5e22
--- /dev/null
+++ b/src/interfaces/libpq++/pglobject.cc
@@ -0,0 +1,152 @@
+
+/*-------------------------------------------------------------------------
+ *
+ * FILE
+ * pglobject.cc
+ *
+ * DESCRIPTION
+ * implementation of the PGlobj class.
+ * PGlobj 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.1.1.1 1996/07/09 06:22:18 scrappy Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "libpq++.H"
+
+extern "C" {
+#include "libpq/libpq-fs.h"
+}
+
+// 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);
+
+}
+
+// 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);
+}
+
+// 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);
+}
+
+// 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);
+}
+
+// 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;
+ }
+}
+
+// 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;
+}
+
+// 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;
+ }
+
+ // 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;
+}
+
+// default destructor -- closes large object
+PGlobj::~PGlobj() {
+ if (fd >= 0)
+ lo_close(conn, fd);
+}