Bring in Leo's <lsh@lubrizol.com> massive changes to libpq++

This commit is contained in:
Marc G. Fournier 1997-02-13 10:01:05 +00:00
parent d62267c707
commit eacd0fd938
25 changed files with 1335 additions and 606 deletions

View File

@ -7,12 +7,16 @@
# #
# #
# IDENTIFICATION # 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= .. SRCDIR= ..
include ../Makefile.global include ../Makefile.global
SRCHEADERDIR = ../include
LIBPQHEADERDIR = $(SRCHEADERDIR)/libpq
LIBNAME= libpq++
# We have to override -Werror, which makes warnings, fatal, because we # We have to override -Werror, which makes warnings, fatal, because we
# inevitably get the warning, "abstract declarator used as declaration" # inevitably get the warning, "abstract declarator used as declaration"
@ -22,48 +26,72 @@ CXXFLAGS= $(CFLAGS) -Wno-error
INCLUDE_OPT= \ INCLUDE_OPT= \
-I../backend \ -I../backend \
-I../include \ -I$(SRCHEADERDIR) \
-I$(LIBPQDIR) -I$(LIBPQDIR)
CXXFLAGS+= $(INCLUDE_OPT) CXXFLAGS+= $(INCLUDE_OPT)
#CXXFLAGS+= -DDEBUG
ifdef KRBVERS ifdef KRBVERS
CXXFLAGS+= $(KRBFLAGS) CXXFLAGS+= $(KRBFLAGS)
endif endif
OBJS= pgenv.o pgconnection.o pglobject.o
all: libpq++.a examples OBJS = pgenv.o pgconnection.o pgtransdb.o pgcursordb.o pglobject.o
libpq++.a: $(OBJS) all: $(LIBNAME).a install examples
$(LIBNAME).a: $(OBJS)
ifdef MK_NO_LORDER ifdef MK_NO_LORDER
$(AR) $(AROPT) libpq++.a $(OBJS) $(AR) $(AROPT) $(LIBNAME).a $(OBJS)
else else
$(AR) $(AROPT) libpq++.a `lorder $(OBJS) | tsort` $(AR) $(AROPT) $(LIBNAME).a `lorder $(OBJS) | tsort`
endif endif
$(RANLIB) libpq++.a $(RANLIB) $(LIBNAME).a
.PHONY: examples .PHONY: examples
examples: examples:
$(MAKE) -C examples all $(MAKE) -C examples all
.PHONY: beforeinstall-headers install-headers .PHONY: beforeinstall-headers install-headers
.PHONY: install install-libpq++ doc .PHONY: install install-$(LIBNAME) doc
install: install-headers install-libpq++ doc install: install-headers install-$(LIBNAME) doc
install-headers: beforeinstall-headers libpq++.H LIBPGXXDIR = $(LIBNAME)
$(INSTALL) $(INSTLOPTS) libpq++.H $(HEADERDIR)/libpq++.H 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: beforeinstall-headers:
@if [ ! -d $(HEADERDIR) ]; then mkdir $(HEADERDIR); fi @if [ ! -d $(HEADERDIR) ]; then mkdir $(HEADERDIR); fi
@if [ ! -d $(LIBPGXXHEADERDIR) ]; then mkdir $(LIBPGXXHEADERDIR); fi
install-libpq++: libpq++.a install-$(LIBNAME): $(LIBNAME).a
$(INSTALL) $(INSTL_LIB_OPTS) libpq++.a $(DESTDIR)$(LIBDIR)/libpq++.a $(INSTALL) $(INSTL_LIB_OPTS) $(LIBNAME).a $(DESTDIR)$(LIBDIR)/$(LIBNAME).a
doc: doc:
$(MAKE) -C man install $(MAKE) -C man install
clean: clean:
rm libpq++.a $(OBJS) rm $(LIBNAME).a $(OBJS)
$(MAKE) -C examples clean $(MAKE) -C examples clean
###########################################################################
# Dependencies for the library
###########################################################################
include ./dependencies

View File

@ -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

View File

@ -5,6 +5,8 @@
SRCDIR= ../.. SRCDIR= ../..
include ../../Makefile.global include ../../Makefile.global
LIBNAME= libpq++
# We have to override -Werror, which makes warnings, fatal, because we # We have to override -Werror, which makes warnings, fatal, because we
# inevitably get the warning, "abstract declarator used as declaration" # 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. # because of our inclusion of c.h and we don't know how to stop that.
@ -15,8 +17,8 @@ INCLUDE_OPT= \
-I.. \ -I.. \
-I../../backend \ -I../../backend \
-I../../include \ -I../../include \
-I$(LIBPQDIR) -I$(LIBPQDIR) \
-I$(HEADERDIR)
CXXFLAGS+= $(INCLUDE_OPT) CXXFLAGS+= $(INCLUDE_OPT)
LD_ADD+= -L.. -lpq++ -L$(LIBPQDIR) -lpq LD_ADD+= -L.. -lpq++ -L$(LIBPQDIR) -lpq
@ -29,19 +31,21 @@ LD_ADD+= $(KRBLIBS)
CXXFLAGS+= $(KRBFLAGS) CXXFLAGS+= $(KRBFLAGS)
endif endif
PROGS= testlibpq0 testlibpq1 testlibpq2 testlibpq3 testlibpq4 testlo PROGS= testlibpq0 testlibpq1 testlibpq2 testlibpq3 \
testlibpq4 testlibpq5 testlibpq6 testlo
all: submake $(PROGS) all: submake $(PROGS)
$(PROGS): % : %.cc ../libpq++.a $(PROGS): % : %.cc ../$(LIBNAME).a
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $@.cc $(LD_ADD) $(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $@.cc $(LD_ADD)
.PHONY: submake .PHONY: submake
submake: submake:
$(MAKE) -C.. libpq++.a $(MAKE) -C.. $(LIBNAME).a
../libpq++.a: ../$(LIBNAME).a:
$(MAKE) -C.. libpq++.a $(MAKE) -C.. $(LIBNAME).a
clean: clean:
rm -f $(PROGS) rm -f $(PROGS)

View File

@ -9,41 +9,44 @@
* *
* *
* IDENTIFICATION * 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 <iostream.h>
#include "libpq++.H" #include <libpq++.h>
int int main()
main()
{ {
ExecStatusType status; // Open the connection to the database and make sure it's OK
PGenv env; PgDatabase data("template1");
PGdatabase* data; if ( data.ConnectionBad() ) {
cout << "Connection was unsuccessful..." << endl
char buf[10000]; << "Error message returned: " << data.ErrorMessage() << endl;
int done = 0; return 1;
}
data = new PGdatabase(&env, "template1");
if (data->status() == CONNECTION_BAD)
printf("connection was unsuccessful\n%s\n", data->errormessage());
else else
printf("connection successful\n"); cout << "Connection successful... Enter queries below:" << endl;
// Interactively obtain and execute queries
ExecStatusType status;
string buf;
int done = 0;
while (!done) while (!done)
{ {
printf("> ");fflush(stdout); cout << "> ";
if (gets(buf) && buf[0]!='\0') cout.flush();
if((status = data->exec(buf)) == PGRES_TUPLES_OK) getline(cin, buf);
data->printtuples(stdout, 1, "|", 1, 0); if ( buf != "" )
if ( (status = data.Exec( buf.c_str() )) == PGRES_TUPLES_OK )
data.DisplayTuples();
else else
printf("status = %d\nerrorMessage = %s\n", status, cout << "No tuples returned..." << endl
data->errormessage()); << "status = " << status << endl
<< "Error returned: " << data.ErrorMessage() << endl;
else else
done = 1; done = 1;
} }
} return 0;
} // End main()

View File

@ -1,84 +1,67 @@
/* /*
* testlibpq.cc * testlibpq1.cc
* Test the C++ version of LIBPQ, the POSTGRES frontend library. * Test the C++ version of LIBPQ, the POSTGRES frontend library.
* *
* queries the template1 database for a list of database names * queries the template1 database for a list of database names
* *
*/ */
#include <stdio.h>
#include "libpq++.H"
main() #include <iostream.h>
#include <iomanip.h>
#include <libpq++.h>
int main()
{ {
char* dbName; // Begin, by establishing a connection to the backend.
int nFields; // When no parameters are given then the system will
int i,j; // try to use reasonable defaults by looking up environment variables
// or, failing that, using hardwired constants
const char* dbName = "template1";
PgDatabase data(dbName);
/* begin, by creating the parameter environtment for a backend // check to see that the backend connection was successfully made
connection. When no parameters are given then the system will if ( data.ConnectionBad() ) {
try to use reasonable defaults by looking up environment variables cerr << "Connection to database '" << dbName << "' failed." << endl
or, failing that, using hardwired constants */ << "Error returned: " << data.ErrorMessage() << endl;
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); exit(1);
} }
/* start a transaction block */ // start a transaction block
if(data->exec("BEGIN") != PGRES_COMMAND_OK) { if ( !data.ExecCommandOk("BEGIN") ) {
fprintf(stderr,"BEGIN command failed\n"); cerr << "BEGIN command failed" << endl;
delete data;
exit(1); exit(1);
} }
/* fetch instances from the pg_database, the system catalog of databases*/ // submit command to the backend
if (data->exec("DECLARE myportal CURSOR FOR select * from pg_database") if ( !data.ExecCommandOk("DECLARE myportal CURSOR FOR select * from pg_database") ) {
!= PGRES_COMMAND_OK) { cerr << "DECLARE CURSOR command failed" << endl;
fprintf(stderr,"DECLARE CURSOR command failed\n");
delete data;
exit(1); exit(1);
} }
if(data->exec("FETCH ALL in myportal") != PGRES_TUPLES_OK) { // fetch instances from the pg_database, the system catalog of databases
fprintf(stderr,"FETCH ALL command didn't return tuples properly\n"); if ( !data.ExecTuplesOk("FETCH ALL in myportal") ) {
delete data; cerr << "FETCH ALL command didn't return tuples properly" << endl;
exit(1); exit(1);
} }
/* first, print out the attribute names */ // first, print out the attribute names
nFields = data->nfields(); int nFields = data.Fields();
for (i=0; i < nFields; i++) { for (int i=0; i < nFields; i++)
printf("%-15s",data->fieldname(i)); cout << setiosflags(ios::right) << setw(15) << data.FieldName(i);
} cout << endl << endl;
printf("\n\n");
/* next, print out the instances */ // next, print out the instances
for (i=0; i < data->ntuples(); i++) { for (int i=0; i < data.Tuples(); i++) {
for (j=0 ; j < nFields; j++) { for (int j=0; j < nFields; j++)
printf("%-15s", data->getvalue(i,j)); cout << setiosflags(ios::right) << setw(15) << data.GetValue(i,j);
} cout << endl;
printf("\n");
} }
/* close the portal */ // Close the portal
data->exec("CLOSE myportal"); data.Exec("CLOSE myportal");
/* end the transaction */ // End the transaction
data->exec("END"); data.Exec("END");
/* close the connection to the database and cleanup */
delete data;
} }

View File

@ -1,69 +1,56 @@
/* /*
* testlibpq2.cc * testlibpq2.cc
* Test of the asynchronous notification interface * Test the C++ version of LIBPQ, the POSTGRES frontend library.
*
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);
* *
* queries the template1 database for a list of database names using transaction block
* *
*/ */
#include <stdio.h>
#include "libpq++.H"
main() #include <iostream.h>
#include <iomanip.h>
#include <libpq++.h>
int main()
{ {
char* dbName; // 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);
/* begin, by creating the parameter environtment for a backend // check to see that the backend connection was successfully made
connection. When no parameters are given then the system will if ( data.ConnectionBad() ) {
try to use reasonable defaults by looking up environment variables cerr << "Connection to database '" << dbName << "' failed." << endl
or, failing that, using hardwired constants */ << "Error returned: " << data.ErrorMessage() << endl;
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); exit(1);
} }
if (data->exec("LISTEN TBL2") != PGRES_COMMAND_OK) { // submit command to the backend
fprintf(stderr,"LISTEN command failed\n"); if ( !data.ExecCommandOk("DECLARE myportal CURSOR FOR select * from pg_database") ) {
delete data; cerr << "DECLARE CURSOR command failed" << endl;
exit(1); exit(1);
} }
while (1) { // fetch instances from the pg_database, the system catalog of databases
/* check for asynchronous returns */ if ( !data.ExecTuplesOk("FETCH ALL in myportal") ) {
notify = data->notifies(); cerr << "FETCH ALL command didn't return tuples properly" << endl;
if (notify) { exit(1);
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 */ // first, print out the attribute names
delete data; 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 portal
data.Exec("CLOSE myportal");
} }

View File

@ -1,130 +1,56 @@
/* /*
* testlibpq3.cc * testlibpq3.cc
* Test the C++ version of LIBPQ, the POSTGRES frontend library. * Test the C++ version of LIBPQ, the POSTGRES frontend library.
* tests the binary cursor interface
* *
* * queries the template1 database for a list of database names using transaction block
* * and 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() #include <iostream.h>
#include <iomanip.h>
#include <libpq++.h>
int main()
{ {
char* dbName; // Begin, by establishing a connection to the backend.
int i_fnum, d_fnum, p_fnum; // When no parameters are given then the system will
int i; // 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");
/* begin, by creating the parameter environtment for a backend // check to see that the backend connection was successfully made
connection. When no parameters are given then the system will if ( cData.ConnectionBad() ) {
try to use reasonable defaults by looking up environment variables cerr << "Connection to database '" << dbName << "' failed." << endl
or, failing that, using hardwired constants */ << "Error returned: " << cData.ErrorMessage() << endl;
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); exit(1);
} }
/* start a transaction block */ // submit command to the backend
if (data->exec("BEGIN") != PGRES_COMMAND_OK) { if ( !cData.Declare("select * from pg_database") ) {
fprintf(stderr,"BEGIN command failed\n"); cerr << "DECLARE CURSOR command failed" << endl;
delete data;
exit(1); exit(1);
} }
/* fetch instances from the pg_database, the system catalog of databases*/ // fetch instances from the pg_cDatabase, the system catalog of cDatabases
if (data->exec("DECLARE mycursor BINARY CURSOR FOR select * from test1") if ( !cData.Fetch() ) {
!= PGRES_COMMAND_OK) { cerr << "FETCH ALL command didn't return tuples properly" << endl;
fprintf(stderr,"DECLARE CURSOR command failed\n");
delete data;
exit(1); exit(1);
} }
if (data->exec("FETCH ALL in mycursor") != PGRES_TUPLES_OK) { // first, print out the attribute names
fprintf(stderr,"FETCH ALL command didn't return tuples properly\n"); int nFields = cData.Fields();
delete data; for (int i=0; i < nFields; i++)
exit(1); 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;
} }
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;
} }

View File

@ -1,66 +1,58 @@
/* /*
* testlibpq4.cc * testlibpq4.cc
* Test the C++ version of LIBPQ, the POSTGRES frontend library. * Test of the asynchronous notification interface
* tests the copy in features *
populate a test database with the following (use testlibpq4.sql):
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 <iostream.h>
#include "libpq++.H" #include <libpq++.h>
#include <stdlib.h>
main() main()
{ {
char* dbName; // 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);
/* begin, by creating the parameter environment for a backend // Check to see that the backend connection was successfully made
connection. When no parameters are given then the system will if ( data.ConnectionBad() ) {
try to use reasonable defaults by looking up environment variables cerr << "Connection to database '" << dbName << "' failed." << endl
or, failing that, using hardwired constants */ << data.ErrorMessage() << endl;
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); exit(1);
} }
/* start a transaction block */ // Listen to a table
if(data->exec("BEGIN") != PGRES_COMMAND_OK) { if ( !data.ExecCommandOk("LISTEN TBL2") ) {
fprintf(stderr,"BEGIN command failed\n"); cerr << "LISTEN command failed" << endl;
delete data;
exit(1); exit(1);
} }
if (data->exec("CREATE TABLE foo (a int4, b char16, d float8)") != // Test asynchronous notification
PGRES_COMMAND_OK) { while (1) {
fprintf(stderr,"CREATE TABLE foo command failed\n"); // check for asynchronous returns
delete data; PGnotify* notify = data.Notifies();
exit(1); if (notify) {
cerr << "ASYNC NOTIFY of '" << notify->relname
<< "' from backend pid '" << notify->be_pid
<< "' received" << endl;
free(notify);
break;
} }
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;
} }

View File

@ -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];

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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");
}

View File

@ -7,56 +7,43 @@
* *
* *
* IDENTIFICATION * 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 <iostream.h>
#include "libpq++.H" #include <libpq++.h>
extern "C" { #include <stdlib.h>
#include "libpq/libpq-fs.h"
}
int int main(int argc, char **argv)
main(int argc, char **argv)
{ {
char *in_filename, *out_filename; // Check if the program was invoked correctly; if not, signal error
char *database;
PGenv env;
PGlobj *object;
if (argc < 4 || argc > 5) { if (argc < 4 || argc > 5) {
fprintf(stderr, "Usage: %s database_name in_filename out_filename [oid]\n", cerr << "Usage: " << argv[0] << " database_name in_filename out_filename [oid]" << endl;
argv[0]);
exit(1); exit(1);
} }
database = argv[1]; // Get the arguments passed to the program
in_filename = argv[2]; char* database = argv[1];
out_filename = argv[3]; char* in_filename = argv[2];
char* out_filename = argv[3];
/* // Set up the connection and create a large object
* set up the connection and create a largeobject for us int lobjId = ( argc == 4 ? 0 : atoi(argv[4]) );
*/ PgLargeObject object(lobjId, database);
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 */ // check to see that the backend connection was successfully made
if (object->status() == CONNECTION_BAD) { if ( object.ConnectionBad() ) {
fprintf(stderr,"Connection to database '%s' failed.\n", database); cerr << "Connection to database '" << database << "' failed." << endl
fprintf(stderr,"%s",object->errormessage()); << object.ErrorMessage();
delete object;
exit(1); exit(1);
} }
object->exec("BEGIN"); // Test the import and export features of the Large Object interface
printf("importing file \"%s\" ...\n", in_filename); object.Exec("BEGIN");
object->import(in_filename); cout << "Importing file \"" << in_filename << "\"..." << endl;
printf("exporting large object to file \"%s\" ...\n", out_filename); object.Import(in_filename);
object->export(out_filename); cout << "Exporting large object to file \"" << out_filename << "\"..." << endl;
object->exec("END"); // WHY DOES IT CORE DUMP HERE ??? object.Export(out_filename);
delete object; object.Exec("END"); // WHY DOES IT CORE DUMP HERE ???
} }

View File

@ -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

View File

@ -1,94 +1,169 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* FILE * FILE
* pgconnection.cc * pgconnection.cpp
* *
* DESCRIPTION * DESCRIPTION
* implementation of the PGconnection class. * implementation of the PgConnection class.
* PGconnection encapsulates a frontend to backend connection * PgConnection encapsulates a frontend to backend connection
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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"
// default constructor extern "C" {
// checks environment variable for database name #include "fe-auth.h"
PGconnection::PGconnection() }
// ****************************************************************
//
// PgConnection Implementation
//
// ****************************************************************
// default constructor -- initialize everything
PgConnection::PgConnection()
: pgConn(NULL), pgResult(NULL), pgCloseConnection(0)
{}
// 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)
{ {
char* name; // Get a default database name to connect to
PGenv* newenv; char* defDB = (char*)dbName;
if ( !dbName )
conn = NULL; if ( !(defDB = getenv(ENV_DEFAULT_DBASE)) )
result = NULL;
errorMessage[0] = '\0';
newenv = new PGenv(); // use reasonable defaults for the environment
if (!(name = getenv(ENV_DEFAULT_DBASE)))
return; return;
connect(newenv, name);
// Connect to the database
Connect( defDB );
} }
// constructor -- for given environment and database name // 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; Connect( dbName );
result = NULL;
errorMessage[0] = '\0';
connect(env, dbName);
} }
// destructor - closes down the connection and cleanup // destructor - closes down the connection and cleanup
PGconnection::~PGconnection() PgConnection::~PgConnection()
{ {
if (result) PQclear(result); // Terminate the debugging output if it was turned on
if (conn) PQfinish(conn); #if defined(DEBUG)
} PQuntrace(pgConn);
// 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 #endif
env = newenv; // Close the conneciton only if needed
fe_setauthsvc(env->pgauth, errorMessage); // This feature will most probably be used by the derived classes that
conn = PQsetdb(env->pghost, env->pgport, env->pgoption, env->pgtty, dbName); // need not close the connection after they are destructed.
if(strlen(errorMessage)) if ( pgCloseConnection ) {
if (pgResult) PQclear(pgResult);
if (pgConn) PQfinish(pgConn);
}
}
// PgConnection::connect
// establish a connection to a backend
ConnStatusType PgConnection::Connect(const char* dbName)
{
// 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; return CONNECTION_BAD;
}
else else
return status(); return Status();
} }
// PGconnection::status -- return connection or result status // PgConnection::status -- return connection or result status
ConnStatusType ConnStatusType PgConnection::Status()
PGconnection::status()
{ {
return PQstatus(conn); return PQstatus(pgConn);
} }
// PGconnection::exec -- send a query to the backend // PgConnection::exec -- send a query to the backend
ExecStatusType ExecStatusType PgConnection::Exec(const char* query)
PGconnection::exec(char* query)
{ {
if (result) // Clear the Result Stucture if needed
PQclear(result); if (pgResult)
PQclear(pgResult);
result = PQexec(conn, query); // Execute the given query
if (result) pgResult = PQexec(pgConn, query);
return PQresultStatus(result);
// Return the status
if (pgResult)
return PQresultStatus(pgResult);
else { else {
strcpy(errorMessage, PQerrorMessage(conn)); SetErrorMessage( PQerrorMessage(pgConn) );
return PGRES_FATAL_ERROR; 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;
}

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -1,10 +1,10 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* FILE * FILE
* PGenv.cc * PgEnv.cc
* *
* DESCRIPTION * 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 * postgres backend, captures the host, port, tty, options and
* authentication type. * authentication type.
* *
@ -14,94 +14,55 @@
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 <stdlib.h>
#include "libpq++.H" #include "pgenv.h"
#define DefaultAuth DEFAULT_CLIENT_AUTHSVC #define DefaultAuth DEFAULT_CLIENT_AUTHSVC
#define DefaultPort "5432" #define DefaultPort POSTPORT
// default constructor for PGenv
// ****************************************************************
//
// PgEnv Implementation
//
// ****************************************************************
// Default constructor for PgEnv
// checks the environment variables // checks the environment variables
PGenv::PGenv() PgEnv::PgEnv()
{ {
pgauth = NULL; SetValues(getenv(ENV_DEFAULT_AUTH), getenv(ENV_DEFAULT_HOST),
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_PORT), getenv(ENV_DEFAULT_OPTION),
getenv(ENV_DEFAULT_TTY)); getenv(ENV_DEFAULT_TTY));
} }
// constructor for given environment // 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; SetValues(auth, host, port, option, tty);
pghost = NULL;
pgport = NULL;
pgoption = NULL;
pgtty = NULL;
setValues(auth, host, port, option, tty);
} }
// allocate memory and set internal structures to match // allocate memory and set internal structures to match
// required environment // required environment
void void PgEnv::SetValues(const string& auth, const string& host, const string& port,
PGenv::setValues(char* auth, char* host, char* port, char* option, char* tty) const string& option, const string& tty)
{ {
char* temp; Auth( auth );
Host( host );
temp = (auth) ? auth : DefaultAuth; Port( port );
Option( option );
if (pgauth) TTY( tty );
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 // read a string from the environment and convert it to string
// frees allocated memory for internal structures string PgEnv::getenv(const char* name)
PGenv::~PGenv()
{ {
if (pgauth) char* env = ::getenv(name);
free(pgauth); return (env ? env : "");
if (pghost)
free(pghost);
if (pgport)
free(pgport);
if (pgoption)
free(pgoption);
if (pgtty)
free(pgtty);
} }

View File

@ -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

View File

@ -1,154 +1,129 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* FILE * FILE
* pglobject.cc * pglobject.cc
* *
* DESCRIPTION * DESCRIPTION
* implementation of the PGlobj class. * implementation of the PgLargeObject class.
* PGlobj encapsulates a frontend to backend connection * PgLargeObject encapsulates a frontend to backend connection
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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" { extern "C" {
#include <unistd.h>
#include <fcntl.h>
#include "libpq/libpq-fs.h" #include "libpq/libpq-fs.h"
} }
#include "pglobject.h"
// ****************************************************************
//
// PgLargeObject Implementation
//
// ****************************************************************
// default constructor // default constructor
// creates a large object in the default database // creates a large object in the default database
PGlobj::PGlobj() : PGconnection::PGconnection() { PgLargeObject::PgLargeObject(const char* dbName)
object = lo_creat(conn, INV_READ|INV_WRITE); : PgConnection(dbName)
if (object == 0) { {
sprintf(errorMessage, "PGlobj: can't create large object"); Init();
} Create();
fd = lo_open(conn, object, INV_READ|INV_WRITE); Open();
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 // constructor
// open an existing large object in the default database // open an existing large object in the default database
PGlobj::PGlobj(Oid lobjId) : PGconnection::PGconnection() { PgLargeObject::PgLargeObject(Oid lobjId, const char* dbName)
object = lobjId; : PgConnection(dbName)
fd = lo_open(conn, object, INV_READ|INV_WRITE); {
if (fd < 0) { Init(lobjId);
sprintf(errorMessage, "PGlobj: can't open large object %d", object); if ( !pgObject )
} else Create();
sprintf(errorMessage, "PGlobj: opened large object %d", Open();
object);
} }
// constructor // constructor
// create a large object in the given database // create a large object in the given database
PGlobj::PGlobj(PGenv* env, char* dbName) : PGconnection::PGconnection(env,dbName) { PgLargeObject::PgLargeObject(const PgEnv& env, const char* dbName)
object = lo_creat(conn, INV_READ|INV_WRITE); : PgConnection(env, dbName)
if (object == 0) { {
sprintf(errorMessage, "PGlobj: can't create large object"); Init();
} Create();
fd = lo_open(conn, object, INV_READ|INV_WRITE); Open();
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 // constructor
// open an existing large object in the given database // open an existing large object in the given database
PGlobj::PGlobj(PGenv* env, char* dbName, Oid lobjId) : PGconnection::PGconnection(env,dbName) { PgLargeObject::PgLargeObject(const PgEnv& env, const char* dbName, Oid lobjId)
object = lobjId; : PgConnection(env, dbName)
fd = lo_open(conn, object, INV_READ|INV_WRITE); {
if (fd < 0) { Init(lobjId);
sprintf(errorMessage, "PGlobj: can't open large object %d", object); if ( !pgObject )
} else Create();
sprintf(errorMessage, "PGlobj: created and opened large object %d", Open();
object);
} }
// PGlobj::unlink // destructor -- closes large object
PgLargeObject::~PgLargeObject()
{
Close();
}
// PgLargeObject::Init
// Initialize the variables
void PgLargeObject::Init(Oid lobjId)
{
pgFd = -1;
pgObject = lobjId;
}
// 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" );
}
// 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 );
}
// PgLargeObject::unlink
// destruct large object and delete from it from the database // destruct large object and delete from it from the database
int int PgLargeObject::Unlink()
PGlobj::unlink() { {
int temp = lo_unlink(conn, object); // Unlink the object
if (temp) { int temp = lo_unlink(pgConn, pgObject);
return temp;
} else { // Initialize the large object upon success
delete this; if (!temp) {
Close();
Init();
}
// Return the status
return temp; 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);
}

View File

@ -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

View File

@ -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()

View File

@ -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