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
# $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/Makefile,v 1.5 1996/11/18 01:43:54 bryanh Exp $
# $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/Makefile,v 1.6 1997/02/13 10:00:23 scrappy Exp $
#
#-------------------------------------------------------------------------
SRCDIR= ..
include ../Makefile.global
SRCHEADERDIR = ../include
LIBPQHEADERDIR = $(SRCHEADERDIR)/libpq
LIBNAME= libpq++
# We have to override -Werror, which makes warnings, fatal, because we
# inevitably get the warning, "abstract declarator used as declaration"
@ -22,48 +26,72 @@ CXXFLAGS= $(CFLAGS) -Wno-error
INCLUDE_OPT= \
-I../backend \
-I../include \
-I$(LIBPQDIR)
-I$(SRCHEADERDIR) \
-I$(LIBPQDIR)
CXXFLAGS+= $(INCLUDE_OPT)
#CXXFLAGS+= -DDEBUG
ifdef KRBVERS
CXXFLAGS+= $(KRBFLAGS)
endif
OBJS= pgenv.o pgconnection.o pglobject.o
all: libpq++.a examples
OBJS = pgenv.o pgconnection.o pgtransdb.o pgcursordb.o pglobject.o
libpq++.a: $(OBJS)
all: $(LIBNAME).a install examples
$(LIBNAME).a: $(OBJS)
ifdef MK_NO_LORDER
$(AR) $(AROPT) libpq++.a $(OBJS)
$(AR) $(AROPT) $(LIBNAME).a $(OBJS)
else
$(AR) $(AROPT) libpq++.a `lorder $(OBJS) | tsort`
$(AR) $(AROPT) $(LIBNAME).a `lorder $(OBJS) | tsort`
endif
$(RANLIB) libpq++.a
$(RANLIB) $(LIBNAME).a
.PHONY: examples
examples:
$(MAKE) -C examples all
.PHONY: beforeinstall-headers install-headers
.PHONY: install install-libpq++ doc
.PHONY: install install-$(LIBNAME) doc
install: install-headers install-libpq++ doc
install: install-headers install-$(LIBNAME) doc
install-headers: beforeinstall-headers libpq++.H
$(INSTALL) $(INSTLOPTS) libpq++.H $(HEADERDIR)/libpq++.H
LIBPGXXDIR = $(LIBNAME)
LIBPGXXHEADERDIR = $(HEADERDIR)/$(LIBPGXXDIR)
MAINHEADER = $(LIBNAME).h
LIBPGXXHEADERS = pgenv.h \
pgconnection.h \
pgdatabase.h \
pgtransdb.h \
pgcursordb.h \
pglobject.h
install-headers: beforeinstall-headers $(MAINHEADER)
@$(INSTALL) $(INSTLOPTS) $(MAINHEADER) $(HEADERDIR)/$(MAINHEADER)
@for i in ${LIBPGXXHEADERS}; do \
echo "Installing $(LIBPGXXHEADERDIR)/$$i."; \
$(INSTALL) $(INSTLOPTS) $$i $(LIBPGXXHEADERDIR)/$$i; \
done
beforeinstall-headers:
@if [ ! -d $(HEADERDIR) ]; then mkdir $(HEADERDIR); fi
@if [ ! -d $(LIBPGXXHEADERDIR) ]; then mkdir $(LIBPGXXHEADERDIR); fi
install-libpq++: libpq++.a
$(INSTALL) $(INSTL_LIB_OPTS) libpq++.a $(DESTDIR)$(LIBDIR)/libpq++.a
install-$(LIBNAME): $(LIBNAME).a
$(INSTALL) $(INSTL_LIB_OPTS) $(LIBNAME).a $(DESTDIR)$(LIBDIR)/$(LIBNAME).a
doc:
$(MAKE) -C man install
clean:
rm libpq++.a $(OBJS)
rm $(LIBNAME).a $(OBJS)
$(MAKE) -C examples clean
###########################################################################
# Dependencies for the library
###########################################################################
include ./dependencies

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

View File

@ -9,41 +9,44 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq++/examples/Attic/testlibpq0.cc,v 1.2 1996/11/18 01:44:23 bryanh Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq++/examples/Attic/testlibpq0.cc,v 1.3 1997/02/13 10:00:42 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include <stdio.h>
#include "libpq++.H"
#include <iostream.h>
#include <libpq++.h>
int
main()
int main()
{
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());
// Open the connection to the database and make sure it's OK
PgDatabase data("template1");
if ( data.ConnectionBad() ) {
cout << "Connection was unsuccessful..." << endl
<< "Error message returned: " << data.ErrorMessage() << endl;
return 1;
}
else
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)
{
printf("> ");fflush(stdout);
if (gets(buf) && buf[0]!='\0')
if((status = data->exec(buf)) == PGRES_TUPLES_OK)
data->printtuples(stdout, 1, "|", 1, 0);
else
printf("status = %d\nerrorMessage = %s\n", status,
data->errormessage());
cout << "> ";
cout.flush();
getline(cin, buf);
if ( buf != "" )
if ( (status = data.Exec( buf.c_str() )) == PGRES_TUPLES_OK )
data.DisplayTuples();
else
cout << "No tuples returned..." << endl
<< "status = " << status << endl
<< "Error returned: " << data.ErrorMessage() << endl;
else
done = 1;
}
}
done = 1;
}
return 0;
} // End main()

View File

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

View File

@ -1,69 +1,56 @@
/*
* testlibpq2.cc
* Test of the asynchronous notification interface
*
populate a database with the following:
CREATE TABLE TBL1 (i int4);
CREATE TABLE TBL2 (i int4);
CREATE RULE r1 AS ON INSERT TO TBL1 DO [INSERT INTO TBL2 values (new.i); NOTIFY TBL2];
* Then start up this program
* After the program has begun, do
INSERT INTO TBL1 values (10);
* Test the C++ version of LIBPQ, the POSTGRES frontend library.
*
* queries the template1 database for a list of database names using transaction block
*
*/
#include <stdio.h>
#include "libpq++.H"
main()
#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
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;
// check to see that the backend connection was successfully made
if ( data.ConnectionBad() ) {
cerr << "Connection to database '" << dbName << "' failed." << endl
<< "Error returned: " << data.ErrorMessage() << endl;
exit(1);
}
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;
// submit command to the backend
if ( !data.ExecCommandOk("DECLARE myportal CURSOR FOR select * from pg_database") ) {
cerr << "DECLARE CURSOR command failed" << endl;
exit(1);
}
if (data->exec("LISTEN TBL2") != PGRES_COMMAND_OK) {
fprintf(stderr,"LISTEN command failed\n");
delete data;
// fetch instances from the pg_database, the system catalog of databases
if ( !data.ExecTuplesOk("FETCH ALL in myportal") ) {
cerr << "FETCH ALL command didn't return tuples properly" << endl;
exit(1);
}
// first, print out the attribute names
int nFields = data.Fields();
for (int i=0; i < nFields; i++)
cout << setiosflags(ios::right) << setw(15) << data.FieldName(i);
cout << endl << endl;
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;
}
// next, print out the instances
for (int i=0; i < data.Tuples(); i++) {
for (int j=0; j < nFields; j++)
cout << setiosflags(ios::right) << setw(15) << data.GetValue(i,j);
cout << endl;
}
/* close the connection to the database and cleanup */
delete data;
// close the portal
data.Exec("CLOSE myportal");
}

View File

@ -1,130 +1,56 @@
/*
* testlibpq3.cc
* Test the C++ version of LIBPQ, the POSTGRES frontend library.
* tests the binary cursor interface
*
*
*
populate a database by doing the following:
CREATE TABLE test1 (i int4, d float4, p polygon);
INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0, 2.0)'::polygon);
INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0, 1.0)'::polygon);
the expected output is:
tuple 0: got
i = (4 bytes) 1,
d = (4 bytes) 3.567000,
p = (4 bytes) 2 points boundbox = (hi=3.000000/4.000000, lo = 1.000000,2.000000)
tuple 1: got
i = (4 bytes) 2,
d = (4 bytes) 89.050003,
p = (4 bytes) 2 points boundbox = (hi=4.000000/3.000000, lo = 2.000000,1.000000)
* queries the template1 database for a list of database names using transaction block
* and cursor interface.
*
*/
#include <stdio.h>
#include "libpq++.H"
extern "C" {
#include "utils/geo-decls.h" /* for the POLYGON type */
}
main()
#include <iostream.h>
#include <iomanip.h>
#include <libpq++.h>
int main()
{
char* dbName;
int i_fnum, d_fnum, p_fnum;
int i;
// Begin, by establishing a connection to the backend.
// When no parameters are given then the system will
// try to use reasonable defaults by looking up environment variables
// or, failing that, using hardwired constants.
// Create a cursor database query object.
// All queries using cursor will be performed through this object.
const char* dbName = "template1";
PgCursor cData(dbName, "myportal");
/* 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;
// check to see that the backend connection was successfully made
if ( cData.ConnectionBad() ) {
cerr << "Connection to database '" << dbName << "' failed." << endl
<< "Error returned: " << cData.ErrorMessage() << endl;
exit(1);
}
// submit command to the backend
if ( !cData.Declare("select * from pg_database") ) {
cerr << "DECLARE CURSOR command failed" << endl;
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;
// fetch instances from the pg_cDatabase, the system catalog of cDatabases
if ( !cData.Fetch() ) {
cerr << "FETCH ALL command didn't return tuples properly" << endl;
exit(1);
}
i_fnum = data->fieldnum("i");
d_fnum = data->fieldnum("d");
p_fnum = data->fieldnum("p");
/*
for (i=0;i<3;i++) {
printf("type[%d] = %d, size[%d] = %d\n",
i, data->fieldtype(i),
i, data->fieldsize(i));
// first, print out the attribute names
int nFields = cData.Fields();
for (int i=0; i < nFields; i++)
cout << setiosflags(ios::right) << setw(15) << cData.FieldName(i);
cout << endl << endl;
// next, print out the instances
for (int i=0; i < cData.Tuples(); i++) {
for (int j=0; j < nFields; j++)
cout << setiosflags(ios::right) << setw(15) << cData.GetValue(i,j);
cout << endl;
}
*/
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
* Test the C++ version of LIBPQ, the POSTGRES frontend library.
* tests the copy in features
* Test of the asynchronous notification interface
*
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 "libpq++.H"
#include <iostream.h>
#include <libpq++.h>
#include <stdlib.h>
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
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;
// Check to see that the backend connection was successfully made
if ( data.ConnectionBad() ) {
cerr << "Connection to database '" << dbName << "' failed." << endl
<< data.ErrorMessage() << endl;
exit(1);
}
/* start a transaction block */
if(data->exec("BEGIN") != PGRES_COMMAND_OK) {
fprintf(stderr,"BEGIN command failed\n");
delete data;
// Listen to a table
if ( !data.ExecCommandOk("LISTEN TBL2") ) {
cerr << "LISTEN command failed" << endl;
exit(1);
}
if (data->exec("CREATE TABLE foo (a int4, b char16, d float8)") !=
PGRES_COMMAND_OK) {
fprintf(stderr,"CREATE TABLE foo command failed\n");
delete data;
exit(1);
// Test asynchronous notification
while (1) {
// check for asynchronous returns
PGnotify* notify = data.Notifies();
if (notify) {
cerr << "ASYNC NOTIFY of '" << notify->relname
<< "' from backend pid '" << notify->be_pid
<< "' received" << endl;
free(notify);
break;
}
}
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
* $Header: /cvsroot/pgsql/src/interfaces/libpq++/examples/Attic/testlo.cc,v 1.2 1996/11/18 01:44:28 bryanh Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq++/examples/Attic/testlo.cc,v 1.3 1997/02/13 10:01:05 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include <stdio.h>
#include "libpq++.H"
extern "C" {
#include "libpq/libpq-fs.h"
}
#include <iostream.h>
#include <libpq++.h>
#include <stdlib.h>
int
main(int argc, char **argv)
int main(int argc, char **argv)
{
char *in_filename, *out_filename;
char *database;
PGenv env;
PGlobj *object;
// Check if the program was invoked correctly; if not, signal error
if (argc < 4 || argc > 5) {
fprintf(stderr, "Usage: %s database_name in_filename out_filename [oid]\n",
argv[0]);
cerr << "Usage: " << argv[0] << " database_name in_filename out_filename [oid]" << endl;
exit(1);
}
database = argv[1];
in_filename = argv[2];
out_filename = argv[3];
// Get the arguments passed to the program
char* database = argv[1];
char* in_filename = argv[2];
char* out_filename = argv[3];
/*
* set up the connection and create a largeobject for us
*/
if (argc == 4) {
object = new PGlobj(&env, database);
} else {
object = new PGlobj(&env, database, atoi(argv[4]));
// Set up the connection and create a large object
int lobjId = ( argc == 4 ? 0 : atoi(argv[4]) );
PgLargeObject object(lobjId, database);
// check to see that the backend connection was successfully made
if ( object.ConnectionBad() ) {
cerr << "Connection to database '" << database << "' failed." << endl
<< object.ErrorMessage();
exit(1);
}
/* 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;
// Test the import and export features of the Large Object interface
object.Exec("BEGIN");
cout << "Importing file \"" << in_filename << "\"..." << endl;
object.Import(in_filename);
cout << "Exporting large object to file \"" << out_filename << "\"..." << endl;
object.Export(out_filename);
object.Exec("END"); // WHY DOES IT CORE DUMP HERE ???
}

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
* pgconnection.cc
* pgconnection.cpp
*
* DESCRIPTION
* implementation of the PGconnection class.
* PGconnection encapsulates a frontend to backend connection
* implementation of the PgConnection class.
* PgConnection encapsulates a frontend to backend connection
*
* Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pgconnection.cc,v 1.1.1.1 1996/07/09 06:22:18 scrappy Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pgconnection.cc,v 1.2 1997/02/13 10:00:27 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include "libpq++.H"
#include <stdlib.h>
#include <string.h>
#include "pgconnection.h"
// default constructor
// checks environment variable for database name
PGconnection::PGconnection()
extern "C" {
#include "fe-auth.h"
}
// ****************************************************************
//
// 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;
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);
// Get a default database name to connect to
char* defDB = (char*)dbName;
if ( !dbName )
if ( !(defDB = getenv(ENV_DEFAULT_DBASE)) )
return;
// Connect to the database
Connect( defDB );
}
// constructor -- for given environment and database name
PGconnection::PGconnection(PGenv* env, char* dbName)
PgConnection::PgConnection(const PgEnv& env, const char* dbName)
: pgEnv(env), pgConn(NULL), pgResult(NULL), pgCloseConnection(1)
{
conn = NULL;
result = NULL;
errorMessage[0] = '\0';
connect(env, dbName);
Connect( dbName );
}
// destructor - closes down the connection and cleanup
PGconnection::~PGconnection()
PgConnection::~PgConnection()
{
if (result) PQclear(result);
if (conn) PQfinish(conn);
// Terminate the debugging output if it was turned on
#if defined(DEBUG)
PQuntrace(pgConn);
#endif
// Close the conneciton only if needed
// This feature will most probably be used by the derived classes that
// need not close the connection after they are destructed.
if ( pgCloseConnection ) {
if (pgResult) PQclear(pgResult);
if (pgConn) PQfinish(pgConn);
}
}
// PGconnection::connect
// PgConnection::connect
// establish a connection to a backend
ConnStatusType
PGconnection::connect(PGenv* newenv, char* dbName)
ConnStatusType PgConnection::Connect(const char* dbName)
{
#if 0
FILE *debug;
debug = fopen("/tmp/trace.out","w");
PQtrace(conn, debug);
#endif
// Turn the trace on
#if defined(DEBUG)
FILE *debug = fopen("/tmp/trace.out","w");
PQtrace(pgConn, 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;
// Set Host Authentication service
char errorMessage[ERROR_MSG_LENGTH];
memset(errorMessage, 0, sizeof(errorMessage));
fe_setauthsvc(pgEnv.Auth(), errorMessage);
// Connect to the database
pgConn = PQsetdb(pgEnv.Host(), pgEnv.Port(), pgEnv.Option(), pgEnv.TTY(), dbName);
// Return the connection status
if (errorMessage) {
SetErrorMessage( errorMessage );
return CONNECTION_BAD;
}
else
return status();
return Status();
}
// PGconnection::status -- return connection or result status
ConnStatusType
PGconnection::status()
// PgConnection::status -- return connection or result status
ConnStatusType PgConnection::Status()
{
return PQstatus(conn);
return PQstatus(pgConn);
}
// PGconnection::exec -- send a query to the backend
ExecStatusType
PGconnection::exec(char* query)
// PgConnection::exec -- send a query to the backend
ExecStatusType PgConnection::Exec(const char* query)
{
if (result)
PQclear(result);
// Clear the Result Stucture if needed
if (pgResult)
PQclear(pgResult);
result = PQexec(conn, query);
if (result)
return PQresultStatus(result);
// Execute the given query
pgResult = PQexec(pgConn, query);
// Return the status
if (pgResult)
return PQresultStatus(pgResult);
else {
strcpy(errorMessage, PQerrorMessage(conn));
SetErrorMessage( PQerrorMessage(pgConn) );
return PGRES_FATAL_ERROR;
}
}
// Return true if the Postgres command was executed OK
int PgConnection::ExecCommandOk(const char* query)
{
return Exec(query) == PGRES_COMMAND_OK;
} // End ExecCommandOk()
int PgConnection::ExecTuplesOk(const char* query)
{
return Exec(query) == PGRES_TUPLES_OK;
} // End ExecTuplesOk()
// PgConnection::notifies() -- returns a notification from a list of unhandled notifications
PGnotify* PgConnection::Notifies()
{
Exec(" ");
return PQnotifies(pgConn);
}
// PgConnection::SetErrorMessage
// sets error message to the given string
void PgConnection::SetErrorMessage(const string& msg, int append)
{
if ( append )
pgErrorMessage += msg;
else
pgErrorMessage = msg;
}
// From Integer To String Conversion Function
string PgConnection::IntToString(int n)
{
char buffer [32];
memset(buffer, 0, sizeof(buffer));
sprintf(buffer, "%d", n);
return buffer;
}

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
* PGenv.cc
* PgEnv.cc
*
* DESCRIPTION
* PGenv is the environment for setting up a connection to a
* PgEnv is the environment for setting up a connection to a
* postgres backend, captures the host, port, tty, options and
* authentication type.
*
@ -14,94 +14,55 @@
* Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pgenv.cc,v 1.2 1996/11/18 01:43:55 bryanh Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pgenv.cc,v 1.3 1997/02/13 10:00:33 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include <stdlib.h>
#include "libpq++.H"
#include "pgenv.h"
#define DefaultAuth DEFAULT_CLIENT_AUTHSVC
#define DefaultPort "5432"
// default constructor for PGenv
#define DefaultAuth DEFAULT_CLIENT_AUTHSVC
#define DefaultPort POSTPORT
// ****************************************************************
//
// PgEnv Implementation
//
// ****************************************************************
// Default constructor for PgEnv
// checks the environment variables
PGenv::PGenv()
PgEnv::PgEnv()
{
pgauth = NULL;
pghost = NULL;
pgport = NULL;
pgoption = NULL;
pgtty = NULL;
setValues(getenv(ENV_DEFAULT_AUTH), getenv(ENV_DEFAULT_HOST),
SetValues(getenv(ENV_DEFAULT_AUTH), getenv(ENV_DEFAULT_HOST),
getenv(ENV_DEFAULT_PORT), getenv(ENV_DEFAULT_OPTION),
getenv(ENV_DEFAULT_TTY));
getenv(ENV_DEFAULT_TTY));
}
// constructor for given environment
PGenv::PGenv(char* auth, char* host, char* port, char* option, char* tty)
PgEnv::PgEnv(const string& auth, const string& host, const string& port,
const string& option, const string& tty)
{
pgauth = NULL;
pghost = NULL;
pgport = NULL;
pgoption = NULL;
pgtty = NULL;
setValues(auth, host, port, option, tty);
SetValues(auth, host, port, option, tty);
}
// allocate memory and set internal structures to match
// required environment
void
PGenv::setValues(char* auth, char* host, char* port, char* option, char* tty)
void PgEnv::SetValues(const string& auth, const string& host, const string& port,
const string& option, const string& tty)
{
char* temp;
temp = (auth) ? auth : DefaultAuth;
if (pgauth)
free(pgauth);
pgauth = strdup(temp);
temp = (host) ? host : DefaultHost;
if (pghost)
free(pghost);
pghost = strdup(temp);
temp = (port) ? port : DefaultPort;
if (pgport)
free(pgport);
pgport = strdup(temp);
temp = (option) ? option : DefaultOption;
if (pgoption)
free(pgoption);
pgoption = strdup(temp);
temp = (tty) ? tty : DefaultTty;
if (pgtty)
free(pgtty);
pgtty = strdup(temp);
Auth( auth );
Host( host );
Port( port );
Option( option );
TTY( tty );
}
// default destrutor
// frees allocated memory for internal structures
PGenv::~PGenv()
// read a string from the environment and convert it to string
string PgEnv::getenv(const char* name)
{
if (pgauth)
free(pgauth);
if (pghost)
free(pghost);
if (pgport)
free(pgport);
if (pgoption)
free(pgoption);
if (pgtty)
free(pgtty);
char* env = ::getenv(name);
return (env ? env : "");
}

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
* pglobject.cc
*
* DESCRIPTION
* implementation of the PGlobj class.
* PGlobj encapsulates a frontend to backend connection
* implementation of the PgLargeObject class.
* PgLargeObject encapsulates a frontend to backend connection
*
* Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pglobject.cc,v 1.2 1996/11/12 11:42:31 bryanh Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq++/Attic/pglobject.cc,v 1.3 1997/02/13 10:00:34 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include "libpq++.H"
extern "C" {
#include <unistd.h>
#include <fcntl.h>
#include "libpq/libpq-fs.h"
}
#include "pglobject.h"
// ****************************************************************
//
// PgLargeObject Implementation
//
// ****************************************************************
// default constructor
// creates a large object in the default database
PGlobj::PGlobj() : PGconnection::PGconnection() {
object = lo_creat(conn, INV_READ|INV_WRITE);
if (object == 0) {
sprintf(errorMessage, "PGlobj: can't create large object");
}
fd = lo_open(conn, object, INV_READ|INV_WRITE);
if (fd < 0) {
sprintf(errorMessage, "PGlobj: can't open large object %d", object);
} else
sprintf(errorMessage, "PGlobj: created and opened large object %d",
object);
PgLargeObject::PgLargeObject(const char* dbName)
: PgConnection(dbName)
{
Init();
Create();
Open();
}
// constructor
// open an existing large object in the default database
PGlobj::PGlobj(Oid lobjId) : PGconnection::PGconnection() {
object = lobjId;
fd = lo_open(conn, object, INV_READ|INV_WRITE);
if (fd < 0) {
sprintf(errorMessage, "PGlobj: can't open large object %d", object);
} else
sprintf(errorMessage, "PGlobj: opened large object %d",
object);
PgLargeObject::PgLargeObject(Oid lobjId, const char* dbName)
: PgConnection(dbName)
{
Init(lobjId);
if ( !pgObject )
Create();
Open();
}
// constructor
// create a large object in the given database
PGlobj::PGlobj(PGenv* env, char* dbName) : PGconnection::PGconnection(env,dbName) {
object = lo_creat(conn, INV_READ|INV_WRITE);
if (object == 0) {
sprintf(errorMessage, "PGlobj: can't create large object");
}
fd = lo_open(conn, object, INV_READ|INV_WRITE);
if (fd < 0) {
sprintf(errorMessage, "PGlobj: can't open large object %d", object);
} else
sprintf(errorMessage, "PGlobj: created and opened large object %d",
object);
PgLargeObject::PgLargeObject(const PgEnv& env, const char* dbName)
: PgConnection(env, dbName)
{
Init();
Create();
Open();
}
// constructor
// open an existing large object in the given database
PGlobj::PGlobj(PGenv* env, char* dbName, Oid lobjId) : PGconnection::PGconnection(env,dbName) {
object = lobjId;
fd = lo_open(conn, object, INV_READ|INV_WRITE);
if (fd < 0) {
sprintf(errorMessage, "PGlobj: can't open large object %d", object);
} else
sprintf(errorMessage, "PGlobj: created and opened large object %d",
object);
PgLargeObject::PgLargeObject(const PgEnv& env, const char* dbName, Oid lobjId)
: PgConnection(env, dbName)
{
Init(lobjId);
if ( !pgObject )
Create();
Open();
}
// PGlobj::unlink
// 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
int
PGlobj::unlink() {
int temp = lo_unlink(conn, object);
if (temp) {
return temp;
} else {
delete this;
return temp;
int PgLargeObject::Unlink()
{
// Unlink the object
int temp = lo_unlink(pgConn, pgObject);
// Initialize the large object upon success
if (!temp) {
Close();
Init();
}
}
// 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);
// Return the status
return temp;
}

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