Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
e92dc1e1
Commit
e92dc1e1
authored
Jun 22, 2003
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Bring the libpq example programs into the 21st century.
parent
21e0b7b8
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
574 additions
and
602 deletions
+574
-602
doc/src/sgml/libpq.sgml
doc/src/sgml/libpq.sgml
+356
-358
src/test/examples/Makefile
src/test/examples/Makefile
+1
-2
src/test/examples/testlibpq.c
src/test/examples/testlibpq.c
+35
-49
src/test/examples/testlibpq2.c
src/test/examples/testlibpq2.c
+75
-56
src/test/examples/testlibpq2.sql
src/test/examples/testlibpq2.sql
+2
-1
src/test/examples/testlibpq3.c
src/test/examples/testlibpq3.c
+100
-129
src/test/examples/testlibpq3.sql
src/test/examples/testlibpq3.sql
+3
-5
src/test/examples/testlibpq4.c
src/test/examples/testlibpq4.c
+2
-2
No files found.
doc/src/sgml/libpq.sgml
View file @
e92dc1e1
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.12
5 2003/06/21 21:51:30
tgl Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.12
6 2003/06/22 00:29:29
tgl Exp $
-->
-->
<chapter id="libpq">
<chapter id="libpq">
...
@@ -3431,6 +3431,12 @@ testlibpq.o(.text+0xa4): undefined reference to `PQerrorMessage'
...
@@ -3431,6 +3431,12 @@ testlibpq.o(.text+0xa4): undefined reference to `PQerrorMessage'
<sect1 id="libpq-example">
<sect1 id="libpq-example">
<title>Example Programs</title>
<title>Example Programs</title>
<para>
These examples and others can be found in the
directory <filename>src/test/examples</filename> in the source code
distribution.
</para>
<example id="libpq-example-1">
<example id="libpq-example-1">
<title><application>libpq</application> Example Program 1</title>
<title><application>libpq</application> Example Program 1</title>
...
@@ -3438,128 +3444,121 @@ testlibpq.o(.text+0xa4): undefined reference to `PQerrorMessage'
...
@@ -3438,128 +3444,121 @@ testlibpq.o(.text+0xa4): undefined reference to `PQerrorMessage'
/*
/*
* testlibpq.c
* testlibpq.c
*
*
* Test the C version of libpq, the <productname>PostgreSQL</> frontend
* Test the C version of LIBPQ, the POSTGRES frontend library.
* library.
*/
*/
#include <stdio.h>
#include <stdio.h>
#include <libpq-fe.h>
#include <stdlib.h>
#include "libpq-fe.h"
void
static
void
exit_nicely(PGconn *conn)
exit_nicely(PGconn *conn)
{
{
PQfinish(conn);
PQfinish(conn);
exit(1);
exit(1);
}
}
main()
int
main(int argc, char **argv)
{
{
char *pghost,
const char *conninfo;
*pgport,
PGconn *conn;
*pgoptions,
PGresult *res;
*pgtty;
int nFields;
char *dbName;
int i,
int nFields;
j;
int i,
j;
/*
* If the user supplies a parameter on the command line, use it as
/* FILE *debug; */
* the conninfo string; otherwise default to setting dbname=template1
* and using environment variables or defaults for all other connection
PGconn *conn;
* parameters.
PGresult *res;
*/
if (argc > 1)
/*
conninfo = argv[1];
* begin, by setting the parameters for a backend connection if the
else
* parameters are null, then the system will try to use reasonable
conninfo = "dbname = template1";
* defaults by looking up environment variables or, failing that,
* using hardwired constants
/* Make a connection to the database */
*/
conn = PQconnectdb(conninfo);
pghost = NULL; /* host name of the backend server */
pgport = NULL; /* port of the backend server */
/* Check to see that the backend connection was successfully made */
pgoptions = NULL; /* special options to start up the backend
if (PQstatus(conn) != CONNECTION_OK)
* server */
{
pgtty = NULL; /* unused */
fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn));
dbName = "template1";
fprintf(stderr, "%s", PQerrorMessage(conn));
exit_nicely(conn);
/* make a connection to the database */
}
conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
/*
/*
* Our test case here involves using a cursor, for which we must be
* check to see that the backend connection was successfully made
* inside a transaction block. We could do the whole thing with a
*/
* single PQexec() of "select * from pg_database", but that's too
if (PQstatus(conn) == CONNECTION_BAD)
* trivial to make a good example.
{
*/
fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
fprintf(stderr, "%s", PQerrorMessage(conn));
/* Start a transaction block */
exit_nicely(conn);
res = PQexec(conn, "BEGIN");
}
if (PQresultStatus(res) != PGRES_COMMAND_OK)
{
/* debug = fopen("/tmp/trace.out","w"); */
fprintf(stderr, "BEGIN command failed: %s", PQerrorMessage(conn));
/* PQtrace(conn, debug); */
PQclear(res);
exit_nicely(conn);
/* start a transaction block */
}
res = PQexec(conn, "BEGIN");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
/*
{
* Should PQclear PGresult whenever it is no longer needed to avoid
fprintf(stderr, "BEGIN command failed\n");
* memory leaks
PQclear(res);
*/
exit_nicely(conn);
PQclear(res);
}
/*
/*
* Fetch rows from pg_database, the system catalog of databases
* should PQclear PGresult whenever it is no longer needed to avoid
*/
* memory leaks
res = PQexec(conn, "DECLARE myportal CURSOR FOR select * from pg_database");
*/
if (PQresultStatus(res) != PGRES_COMMAND_OK)
PQclear(res);
{
fprintf(stderr, "DECLARE CURSOR failed: %s", PQerrorMessage(conn));
/*
PQclear(res);
* fetch rows from the pg_database, the system catalog of
exit_nicely(conn);
* databases
}
*/
PQclear(res);
res = PQexec(conn, "DECLARE mycursor CURSOR FOR SELECT * FROM pg_database");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
res = PQexec(conn, "FETCH ALL in myportal");
{
if (PQresultStatus(res) != PGRES_TUPLES_OK)
fprintf(stderr, "DECLARE CURSOR command failed\n");
{
PQclear(res);
fprintf(stderr, "FETCH ALL failed: %s", PQerrorMessage(conn));
exit_nicely(conn);
PQclear(res);
}
exit_nicely(conn);
PQclear(res);
}
res = PQexec(conn, "FETCH ALL in mycursor");
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
/* first, print out the attribute names */
{
nFields = PQnfields(res);
fprintf(stderr, "FETCH ALL command didn't return tuples properly\n");
for (i = 0; i < nFields; i++)
PQclear(res);
printf("%-15s", PQfname(res, i));
exit_nicely(conn);
printf("\n\n");
}
/* next, print out the rows */
/* first, print out the attribute names */
for (i = 0; i < PQntuples(res); i++)
nFields = PQnfields(res);
{
for (i = 0; i < nFields; i++)
for (j = 0; j < nFields; j++)
printf("%-15s", PQfname(res, i));
printf("%-15s", PQgetvalue(res, i, j));
printf("\n\n");
printf("\n");
}
/* next, print out the rows */
for (i = 0; i < PQntuples(res); i++)
PQclear(res);
{
for (j = 0; j < nFields; j++)
/* close the portal ... we don't bother to check for errors ... */
printf("%-15s", PQgetvalue(res, i, j));
res = PQexec(conn, "CLOSE myportal");
printf("\n");
PQclear(res);
}
PQclear(res);
/* end the transaction */
res = PQexec(conn, "END");
/* close the cursor */
PQclear(res);
res = PQexec(conn, "CLOSE mycursor");
PQclear(res);
/* close the connection to the database and cleanup */
PQfinish(conn);
/* commit the transaction */
res = PQexec(conn, "COMMIT");
return 0;
PQclear(res);
/* close the connection to the database and cleanup */
PQfinish(conn);
/* fclose(debug); */
return 0;
}
}
</programlisting>
</programlisting>
</example>
</example>
...
@@ -3570,116 +3569,133 @@ main()
...
@@ -3570,116 +3569,133 @@ main()
<programlisting>
<programlisting>
/*
/*
* testlibpq2.c
* testlibpq2.c
*
Test of the asynchronous notification interface
*
Test of the asynchronous notification interface
*
*
* Start this program, then from psql in another window do
* Start this program, then from psql in another window do
* NOTIFY TBL2;
* NOTIFY TBL2;
* Repeat four times to get this program to exit.
*
*
* Or, if you want to get fancy, try this:
* Or, if you want to get fancy, try this:
* Populate a database with the following:
* populate a database with the following commands
* (provided in src/test/examples/testlibpq2.sql):
*
*
* CREATE TABLE TBL1 (i int4);
* CREATE TABLE TBL1 (i int4);
*
*
* CREATE TABLE TBL2 (i int4);
* CREATE TABLE TBL2 (i int4);
*
*
* CREATE RULE r1 AS ON INSERT TO TBL1 DO
* CREATE RULE r1 AS ON INSERT TO TBL1 DO
* (INSERT INTO TBL2 values (new.i); NOTIFY TBL2);
* (INSERT INTO TBL2 VALUES (new.i); NOTIFY TBL2);
*
* and do
*
*
*
INSERT INTO TBL1 values (10);
*
and do this four times:
*
*
* INSERT INTO TBL1 VALUES (10);
*/
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include "libpq-fe.h"
#include "libpq-fe.h"
void
static
void
exit_nicely(PGconn *conn)
exit_nicely(PGconn *conn)
{
{
PQfinish(conn);
PQfinish(conn);
exit(1);
exit(1);
}
}
main()
int
main(int argc, char **argv)
{
{
char *pghost,
const char *conninfo;
*pgport,
PGconn *conn;
*pgoptions,
PGresult *res;
*pgtty;
PGnotify *notify;
char *dbName;
int nnotifies;
int nFields;
int i,
/*
j;
* If the user supplies a parameter on the command line, use it as
* the conninfo string; otherwise default to setting dbname=template1
PGconn *conn;
* and using environment variables or defaults for all other connection
PGresult *res;
* parameters.
PGnotify *notify;
*/
if (argc > 1)
/*
conninfo = argv[1];
* begin, by setting the parameters for a backend connection if the
else
* parameters are null, then the system will try to use reasonable
conninfo = "dbname = template1";
* defaults by looking up environment variables or, failing that,
* using hardwired constants
/* Make a connection to the database */
*/
conn = PQconnectdb(conninfo);
pghost = NULL; /* host name of the backend server */
pgport = NULL; /* port of the backend server */
/* Check to see that the backend connection was successfully made */
pgoptions = NULL; /* special options to start up the backend
if (PQstatus(conn) != CONNECTION_OK)
* server */
{
pgtty = NULL; /* unused */
fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn));
dbName = getenv("USER"); /* change this to the name of your test
fprintf(stderr, "%s", PQerrorMessage(conn));
* database */
exit_nicely(conn);
}
/* make a connection to the database */
conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
/*
* Issue LISTEN command to enable notifications from the rule's NOTIFY.
/*
*/
* check to see that the backend connection was successfully made
res = PQexec(conn, "LISTEN TBL2");
*/
if (PQresultStatus(res) != PGRES_COMMAND_OK)
if (PQstatus(conn) == CONNECTION_BAD)
{
{
fprintf(stderr, "LISTEN command failed: %s", PQerrorMessage(conn));
fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
PQclear(res);
fprintf(stderr, "%s", PQerrorMessage(conn));
exit_nicely(conn);
exit_nicely(conn);
}
}
/*
res = PQexec(conn, "LISTEN TBL2");
* should PQclear PGresult whenever it is no longer needed to avoid
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
* memory leaks
{
*/
fprintf(stderr, "LISTEN command failed\n");
PQclear(res);
PQclear(res);
exit_nicely(conn);
/* Quit after four notifies are received. */
}
nnotifies = 0;
while (nnotifies < 4)
/*
{
* should PQclear PGresult whenever it is no longer needed to avoid
/*
* memory leaks
* Sleep until something happens on the connection. We use select(2)
*/
* to wait for input, but you could also use poll() or similar
PQclear(res);
* facilities.
*/
while (1)
int sock;
{
fd_set input_mask;
/*
sock = PQsocket(conn);
* wait a little bit between checks; waiting with select()
* would be more efficient.
if (sock < 0)
*/
break; /* shouldn't happen */
sleep(1);
/* collect any asynchronous backend messages */
FD_ZERO(&input_mask);
PQconsumeInput(conn);
FD_SET(sock, &input_mask);
/* check for asynchronous notify messages */
while ((notify = PQnotifies(conn)) != NULL)
if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0)
{
{
fprintf(stderr,
fprintf(stderr, "select() failed: %s\n", strerror(errno));
"ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
exit_nicely(conn);
notify->relname, notify->be_pid);
}
PQfreemem(notify);
}
/* Now check for input */
}
PQconsumeInput(conn);
while ((notify = PQnotifies(conn)) != NULL)
/* close the connection to the database and cleanup */
{
PQfinish(conn);
fprintf(stderr,
"ASYNC NOTIFY of '%s' received from backend pid %d\n",
return 0;
notify->relname, notify->be_pid);
PQfreemem(notify);
nnotifies++;
}
}
fprintf(stderr, "Done.\n");
/* close the connection to the database and cleanup */
PQfinish(conn);
return 0;
}
}
</programlisting>
</programlisting>
</example>
</example>
...
@@ -3689,176 +3705,158 @@ main()
...
@@ -3689,176 +3705,158 @@ main()
<programlisting>
<programlisting>
/*
/*
* testlibpq3.c Test the C version of Libpq, the <productname>PostgreSQL</> frontend
* testlibpq3.c
* library. tests the binary cursor interface
* Test out-of-line parameters and binary I/O.
*
*
*
* populate a database by doing the following:
*
*
* CREATE TABLE test1 (i int4, d real, p polygon);
* Before running this, populate a database with the following commands
* (provided in src/test/examples/testlibpq3.sql):
*
*
*
INSERT INTO test1 values (1, 3.567, polygon '(3.0, 4.0, 1.0, 2.0)'
);
*
CREATE TABLE test1 (i int4, t text, b bytea
);
*
*
* INSERT INTO test1 values (2, 89.05, polygon '(4.0, 3.0, 2.0, 1.0)');
* INSERT INTO test1 values (1, 'joe''s place', '\\000\\001\\002\\003\\004');
* INSERT INTO test1 values (2, 'ho there', '\\004\\003\\002\\001\\000');
*
*
* the expected output is:
* 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)
*
*
* tuple 0: got
* i = (4 bytes) 1
* t = (11 bytes) 'joe's place'
* b = (5 bytes) \000\001\002\003\004
*
*
*/
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "libpq-fe.h"
#include "libpq-fe.h"
#include "utils/geo_decls.h" /* for the POLYGON type */
void
/* for ntohl/htonl */
#include <netinet/in.h>
#include <arpa/inet.h>
static void
exit_nicely(PGconn *conn)
exit_nicely(PGconn *conn)
{
{
PQfinish(conn);
PQfinish(conn);
exit(1);
exit(1);
}
}
main()
int
main(int argc, char **argv)
{
{
char *pghost,
const char *conninfo;
*pgport,
PGconn *conn;
*pgoptions,
PGresult *res;
*pgtty;
const char *paramValues[1];
char *dbName;
int i,
int nFields;
j;
int i,
int i_fnum,
j;
t_fnum,
int i_fnum,
b_fnum;
d_fnum,
p_fnum;
/*
PGconn *conn;
* If the user supplies a parameter on the command line, use it as
PGresult *res;
* the conninfo string; otherwise default to setting dbname=template1
* and using environment variables or defaults for all other connection
/*
* parameters.
* begin, by setting the parameters for a backend connection if the
*/
* parameters are null, then the system will try to use reasonable
if (argc > 1)
* defaults by looking up environment variables or, failing that,
conninfo = argv[1];
* using hardwired constants
else
*/
conninfo = "dbname = template1";
pghost = NULL; /* host name of the backend server */
pgport = NULL; /* port of the backend server */
/* Make a connection to the database */
pgoptions = NULL; /* special options to start up the backend
conn = PQconnectdb(conninfo);
* server */
pgtty = NULL; /* unused */
/* Check to see that the backend connection was successfully made */
if (PQstatus(conn) != CONNECTION_OK)
dbName = getenv("USER"); /* change this to the name of your test
{
* database */
fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn));
fprintf(stderr, "%s", PQerrorMessage(conn));
/* make a connection to the database */
exit_nicely(conn);
conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName);
}
/*
/*
* check to see that the backend connection was successfully made
* The point of this program is to illustrate use of PQexecParams()
*/
* with out-of-line parameters, as well as binary transmission of
if (PQstatus(conn) == CONNECTION_BAD)
* results. By using out-of-line parameters we can avoid a lot of
{
* tedious mucking about with quoting and escaping. Notice how we
fprintf(stderr, "Connection to database '%s' failed.\n", dbName);
* don't have to do anything special with the quote mark in the
fprintf(stderr, "%s", PQerrorMessage(conn));
* parameter value.
exit_nicely(conn);
*/
}
/* Here is our out-of-line parameter value */
/* start a transaction block */
paramValues[0] = "joe's place";
res = PQexec(conn, "BEGIN");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
res = PQexecParams(conn,
{
"SELECT * FROM test1 WHERE t = $1",
fprintf(stderr, "BEGIN command failed\n");
1, /* one param */
PQclear(res);
NULL, /* let the backend deduce param type */
exit_nicely(conn);
paramValues,
}
NULL, /* don't need param lengths since text */
NULL, /* default to all text params */
/*
1); /* ask for binary results */
* should PQclear PGresult whenever it is no longer needed to avoid
* memory leaks
if (PQresultStatus(res) != PGRES_TUPLES_OK)
*/
{
PQclear(res);
fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
PQclear(res);
/*
exit_nicely(conn);
* fetch rows from the pg_database, the system catalog of
}
* databases
*/
/* Use PQfnumber to avoid assumptions about field order in result */
res = PQexec(conn, "DECLARE mycursor BINARY CURSOR FOR SELECT * FROM test1");
i_fnum = PQfnumber(res, "i");
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
t_fnum = PQfnumber(res, "t");
{
b_fnum = PQfnumber(res, "b");
fprintf(stderr, "DECLARE CURSOR command failed\n");
PQclear(res);
for (i = 0; i < PQntuples(res); i++)
exit_nicely(conn);
{
}
char *iptr;
PQclear(res);
char *tptr;
char *bptr;
res = PQexec(conn, "FETCH ALL in mycursor");
int blen;
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
int ival;
{
fprintf(stderr, "FETCH ALL command didn't return tuples properly\n");
/* Get the field values (we ignore possibility they are null!) */
PQclear(res);
iptr = PQgetvalue(res, i, i_fnum);
exit_nicely(conn);
tptr = PQgetvalue(res, i, t_fnum);
}
bptr = PQgetvalue(res, i, b_fnum);
i_fnum = PQfnumber(res, "i");
/*
d_fnum = PQfnumber(res, "d");
* The binary representation of INT4 is in network byte order,
p_fnum = PQfnumber(res, "p");
* which we'd better coerce to the local byte order.
*/
for (i = 0; i < 3; i++)
ival = ntohl(*((uint32_t *) iptr));
{
printf("type[%d] = %d, size[%d] = %d\n",
/*
i, PQftype(res, i),
* The binary representation of TEXT is, well, text, and since
i, PQfsize(res, i));
* libpq was nice enough to append a zero byte to it, it'll work
}
* just fine as a C string.
for (i = 0; i < PQntuples(res); i++)
*
{
* The binary representation of BYTEA is a bunch of bytes, which
int *ival;
* could include embedded nulls so we have to pay attention to
float *dval;
* field length.
int plen;
*/
POLYGON *pval;
blen = PQgetlength(res, i, b_fnum);
/* we hard-wire this to the 3 fields we know about */
printf("tuple %d: got\n", i);
ival = (int *) PQgetvalue(res, i, i_fnum);
printf(" i = (%d bytes) %d\n",
dval = (float *) PQgetvalue(res, i, d_fnum);
PQgetlength(res, i, i_fnum), ival);
plen = PQgetlength(res, i, p_fnum);
printf(" t = (%d bytes) '%s'\n",
PQgetlength(res, i, t_fnum), tptr);
/*
printf(" b = (%d bytes) ", blen);
* plen doesn't include the length field so need to
for (j = 0; j < blen; j++)
* increment by VARHDSZ
printf("\\%03o", bptr[j]);
*/
printf("\n\n");
pval = (POLYGON *) malloc(plen + VARHDRSZ);
}
pval->size = plen;
memmove((char *) &pval->npts, PQgetvalue(res, i, p_fnum), plen);
PQclear(res);
printf("tuple %d: got\n", i);
printf(" i = (%d bytes) %d,\n",
/* close the connection to the database and cleanup */
PQgetlength(res, i, i_fnum), *ival);
PQfinish(conn);
printf(" d = (%d bytes) %f,\n",
PQgetlength(res, i, d_fnum), *dval);
return 0;
printf(" p = (%d bytes) %d points \tboundbox = (hi=%f/%f, lo = %f,%f)\n",
PQgetlength(res, i, d_fnum),
pval->npts,
pval->boundbox.xh,
pval->boundbox.yh,
pval->boundbox.xl,
pval->boundbox.yl);
}
PQclear(res);
/* close the cursor */
res = PQexec(conn, "CLOSE mycursor");
PQclear(res);
/* commit the transaction */
res = PQexec(conn, "COMMIT");
PQclear(res);
/* close the connection to the database and cleanup */
PQfinish(conn);
return 0;
}
}
</programlisting>
</programlisting>
</example>
</example>
...
...
src/test/examples/Makefile
View file @
e92dc1e1
...
@@ -7,10 +7,9 @@ top_builddir = ../../..
...
@@ -7,10 +7,9 @@ top_builddir = ../../..
include
$(top_builddir)/src/Makefile.global
include
$(top_builddir)/src/Makefile.global
override CPPFLAGS
:
= -I$(libpq_srcdir) $(CPPFLAGS)
override CPPFLAGS
:
= -I$(libpq_srcdir) $(CPPFLAGS)
L
IB
S
+=
$(libpq)
L
DFLAG
S
+=
$(libpq)
# PROGS= testlibpq0 testlibpq1 testlibpq2 testlibpq3 testlibpq4 testlo
PROGS
=
testlibpq testlibpq2 testlibpq3 testlibpq4 testlo
PROGS
=
testlibpq testlibpq2 testlibpq3 testlibpq4 testlo
all
:
$(PROGS)
all
:
$(PROGS)
...
...
src/test/examples/testlibpq.c
View file @
e92dc1e1
/*
/*
* testlibpq.c
* testlibpq.c
* Test the C version of LIBPQ, the POSTGRES frontend library.
*
*
*
* Test the C version of LIBPQ, the POSTGRES frontend library.
*/
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"
#include "libpq-fe.h"
static
void
static
void
...
@@ -15,76 +15,66 @@ exit_nicely(PGconn *conn)
...
@@ -15,76 +15,66 @@ exit_nicely(PGconn *conn)
}
}
int
int
main
()
main
(
int
argc
,
char
**
argv
)
{
{
char
*
pghost
,
const
char
*
conninfo
;
*
pgport
,
PGconn
*
conn
;
*
pgoptions
,
PGresult
*
res
;
*
pgtty
;
char
*
dbName
;
int
nFields
;
int
nFields
;
int
i
,
int
i
,
j
;
j
;
#ifdef DEBUG
FILE
*
debug
;
#endif
/* DEBUG */
PGconn
*
conn
;
PGresult
*
res
;
/*
/*
*
begin, by setting the parameters for a backend connection if the
*
If the user supplies a parameter on the command line, use it as
*
parameters are null, then the system will try to use reasonable
*
the conninfo string; otherwise default to setting dbname=template1
*
defaults by looking up environment variables or, failing that,
*
and using environment variables or defaults for all other connection
*
using hardwired constants
*
parameters.
*/
*/
pghost
=
NULL
;
/* host name of the backend server */
if
(
argc
>
1
)
pgport
=
NULL
;
/* port of the backend server */
conninfo
=
argv
[
1
];
pgoptions
=
NULL
;
/* special options to start up the backend
else
* server */
conninfo
=
"dbname = template1"
;
pgtty
=
NULL
;
/* debugging tty for the backend server */
dbName
=
"template1"
;
/* Make a connection to the database */
conn
=
PQconnectdb
(
conninfo
);
/* make a connection to the database */
conn
=
PQsetdb
(
pghost
,
pgport
,
pgoptions
,
pgtty
,
dbName
);
/* Check to see that the backend connection was successfully made */
if
(
PQstatus
(
conn
)
!=
CONNECTION_OK
)
/* check to see that the backend connection was successfully made */
if
(
PQstatus
(
conn
)
==
CONNECTION_BAD
)
{
{
fprintf
(
stderr
,
"Connection to database '%s' failed.
\n
"
,
dbName
);
fprintf
(
stderr
,
"Connection to database '%s' failed.
\n
"
,
PQdb
(
conn
)
);
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
exit_nicely
(
conn
);
exit_nicely
(
conn
);
}
}
#ifdef DEBUG
/*
debug
=
fopen
(
"/tmp/trace.out"
,
"w"
);
* Our test case here involves using a cursor, for which we must be
PQtrace
(
conn
,
debug
);
* inside a transaction block. We could do the whole thing with a
#endif
/* DEBUG */
* single PQexec() of "select * from pg_database", but that's too
* trivial to make a good example.
*/
/*
s
tart a transaction block */
/*
S
tart a transaction block */
res
=
PQexec
(
conn
,
"BEGIN"
);
res
=
PQexec
(
conn
,
"BEGIN"
);
if
(
PQresultStatus
(
res
)
!=
PGRES_COMMAND_OK
)
if
(
PQresultStatus
(
res
)
!=
PGRES_COMMAND_OK
)
{
{
fprintf
(
stderr
,
"BEGIN command failed
\n
"
);
fprintf
(
stderr
,
"BEGIN command failed
: %s"
,
PQerrorMessage
(
conn
)
);
PQclear
(
res
);
PQclear
(
res
);
exit_nicely
(
conn
);
exit_nicely
(
conn
);
}
}
/*
/*
*
s
hould PQclear PGresult whenever it is no longer needed to avoid
*
S
hould PQclear PGresult whenever it is no longer needed to avoid
* memory leaks
* memory leaks
*/
*/
PQclear
(
res
);
PQclear
(
res
);
/*
/*
* fetch instances from the pg_database, the system catalog of
* Fetch rows from pg_database, the system catalog of databases
* databases
*/
*/
res
=
PQexec
(
conn
,
"DECLARE myportal CURSOR FOR select * from pg_database"
);
res
=
PQexec
(
conn
,
"DECLARE myportal CURSOR FOR select * from pg_database"
);
if
(
PQresultStatus
(
res
)
!=
PGRES_COMMAND_OK
)
if
(
PQresultStatus
(
res
)
!=
PGRES_COMMAND_OK
)
{
{
fprintf
(
stderr
,
"DECLARE CURSOR
command failed
\n
"
);
fprintf
(
stderr
,
"DECLARE CURSOR
failed: %s"
,
PQerrorMessage
(
conn
)
);
PQclear
(
res
);
PQclear
(
res
);
exit_nicely
(
conn
);
exit_nicely
(
conn
);
}
}
...
@@ -93,7 +83,7 @@ main()
...
@@ -93,7 +83,7 @@ main()
res
=
PQexec
(
conn
,
"FETCH ALL in myportal"
);
res
=
PQexec
(
conn
,
"FETCH ALL in myportal"
);
if
(
PQresultStatus
(
res
)
!=
PGRES_TUPLES_OK
)
if
(
PQresultStatus
(
res
)
!=
PGRES_TUPLES_OK
)
{
{
fprintf
(
stderr
,
"FETCH ALL
command didn't return tuples properly
\n
"
);
fprintf
(
stderr
,
"FETCH ALL
failed: %s"
,
PQerrorMessage
(
conn
)
);
PQclear
(
res
);
PQclear
(
res
);
exit_nicely
(
conn
);
exit_nicely
(
conn
);
}
}
...
@@ -104,7 +94,7 @@ main()
...
@@ -104,7 +94,7 @@ main()
printf
(
"%-15s"
,
PQfname
(
res
,
i
));
printf
(
"%-15s"
,
PQfname
(
res
,
i
));
printf
(
"
\n\n
"
);
printf
(
"
\n\n
"
);
/* next, print out the
instance
s */
/* next, print out the
row
s */
for
(
i
=
0
;
i
<
PQntuples
(
res
);
i
++
)
for
(
i
=
0
;
i
<
PQntuples
(
res
);
i
++
)
{
{
for
(
j
=
0
;
j
<
nFields
;
j
++
)
for
(
j
=
0
;
j
<
nFields
;
j
++
)
...
@@ -114,7 +104,7 @@ main()
...
@@ -114,7 +104,7 @@ main()
PQclear
(
res
);
PQclear
(
res
);
/* close the portal */
/* close the portal
... we don't bother to check for errors ...
*/
res
=
PQexec
(
conn
,
"CLOSE myportal"
);
res
=
PQexec
(
conn
,
"CLOSE myportal"
);
PQclear
(
res
);
PQclear
(
res
);
...
@@ -125,9 +115,5 @@ main()
...
@@ -125,9 +115,5 @@ main()
/* close the connection to the database and cleanup */
/* close the connection to the database and cleanup */
PQfinish
(
conn
);
PQfinish
(
conn
);
#ifdef DEBUG
fclose
(
debug
);
#endif
/* DEBUG */
return
0
;
return
0
;
}
}
src/test/examples/testlibpq2.c
View file @
e92dc1e1
...
@@ -2,24 +2,30 @@
...
@@ -2,24 +2,30 @@
* testlibpq2.c
* testlibpq2.c
* Test of the asynchronous notification interface
* Test of the asynchronous notification interface
*
*
populate a database with the following:
* Start this program, then from psql in another window do
* NOTIFY TBL2;
CREATE TABLE TBL1 (i int4);
* Repeat four times to get this program to exit.
*
CREATE TABLE TBL2 (i int4);
* Or, if you want to get fancy, try this:
* populate a database with the following commands
CREATE RULE r1 AS ON INSERT TO TBL1 DO [INSERT INTO TBL2 values (new.i); NOTIFY TBL2];
* (provided in src/test/examples/testlibpq2.sql):
* Then start up this program
* After the program has begun, do
INSERT INTO TBL1 values (10);
*
*
* 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);
*
* and do this four times:
*
* INSERT INTO TBL1 VALUES (10);
*/
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include "libpq-fe.h"
#include "libpq-fe.h"
static
void
static
void
...
@@ -30,51 +36,43 @@ exit_nicely(PGconn *conn)
...
@@ -30,51 +36,43 @@ exit_nicely(PGconn *conn)
}
}
int
int
main
()
main
(
int
argc
,
char
**
argv
)
{
{
char
*
pghost
,
const
char
*
conninfo
;
*
pgport
,
*
pgoptions
,
*
pgtty
;
char
*
dbName
;
/*
* int nFields; int i, j;
*/
PGconn
*
conn
;
PGconn
*
conn
;
PGresult
*
res
;
PGresult
*
res
;
PGnotify
*
notify
;
PGnotify
*
notify
;
int
nnotifies
;
/*
/*
*
begin, by setting the parameters for a backend connection if the
*
If the user supplies a parameter on the command line, use it as
*
parameters are null, then the system will try to use reasonable
*
the conninfo string; otherwise default to setting dbname=template1
*
defaults by looking up environment variables or, failing that,
*
and using environment variables or defaults for all other connection
*
using hardwired constants
*
parameters.
*/
*/
pghost
=
NULL
;
/* host name of the backend server */
if
(
argc
>
1
)
pgport
=
NULL
;
/* port of the backend server */
conninfo
=
argv
[
1
];
pgoptions
=
NULL
;
/* special options to start up the backend
else
* server */
conninfo
=
"dbname = template1"
;
pgtty
=
NULL
;
/* debugging tty for the backend server */
dbName
=
getenv
(
"USER"
);
/* change this to the name of your test
/* Make a connection to the database */
* database */
conn
=
PQconnectdb
(
conninfo
);
/* make a connection to the database */
/* Check to see that the backend connection was successfully made */
conn
=
PQsetdb
(
pghost
,
pgport
,
pgoptions
,
pgtty
,
dbName
);
if
(
PQstatus
(
conn
)
!=
CONNECTION_OK
)
/* check to see that the backend connection was successfully made */
if
(
PQstatus
(
conn
)
==
CONNECTION_BAD
)
{
{
fprintf
(
stderr
,
"Connection to database '%s' failed.
\n
"
,
dbName
);
fprintf
(
stderr
,
"Connection to database '%s' failed.
\n
"
,
PQdb
(
conn
)
);
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
exit_nicely
(
conn
);
exit_nicely
(
conn
);
}
}
/*
* Issue LISTEN command to enable notifications from the rule's NOTIFY.
*/
res
=
PQexec
(
conn
,
"LISTEN TBL2"
);
res
=
PQexec
(
conn
,
"LISTEN TBL2"
);
if
(
PQresultStatus
(
res
)
!=
PGRES_COMMAND_OK
)
if
(
PQresultStatus
(
res
)
!=
PGRES_COMMAND_OK
)
{
{
fprintf
(
stderr
,
"LISTEN command failed
\n
"
);
fprintf
(
stderr
,
"LISTEN command failed
: %s"
,
PQerrorMessage
(
conn
)
);
PQclear
(
res
);
PQclear
(
res
);
exit_nicely
(
conn
);
exit_nicely
(
conn
);
}
}
...
@@ -85,27 +83,48 @@ main()
...
@@ -85,27 +83,48 @@ main()
*/
*/
PQclear
(
res
);
PQclear
(
res
);
while
(
1
)
/* Quit after four notifies are received. */
nnotifies
=
0
;
while
(
nnotifies
<
4
)
{
{
/* async notification only come back as a result of a query */
/*
/* we can send empty queries */
* Sleep until something happens on the connection. We use select(2)
res
=
PQexec
(
conn
,
" "
);
* to wait for input, but you could also use poll() or similar
/* printf("res->status = %s\n", PQresStatus(PQresultStatus(res))); */
* facilities.
/* check for asynchronous returns */
*/
notify
=
PQnotifies
(
conn
);
int
sock
;
if
(
notify
)
fd_set
input_mask
;
sock
=
PQsocket
(
conn
);
if
(
sock
<
0
)
break
;
/* shouldn't happen */
FD_ZERO
(
&
input_mask
);
FD_SET
(
sock
,
&
input_mask
);
if
(
select
(
sock
+
1
,
&
input_mask
,
NULL
,
NULL
,
NULL
)
<
0
)
{
fprintf
(
stderr
,
"select() failed: %s
\n
"
,
strerror
(
errno
));
exit_nicely
(
conn
);
}
/* Now check for input */
PQconsumeInput
(
conn
);
while
((
notify
=
PQnotifies
(
conn
))
!=
NULL
)
{
{
fprintf
(
stderr
,
fprintf
(
stderr
,
"ASYNC NOTIFY of '%s' from backend pid '%d' receive
d
\n
"
,
"ASYNC NOTIFY of '%s' received from backend pid %
d
\n
"
,
notify
->
relname
,
notify
->
be_pid
);
notify
->
relname
,
notify
->
be_pid
);
PQfreemem
(
notify
);
PQfreemem
(
notify
);
break
;
nnotifies
++
;
}
}
PQclear
(
res
);
}
}
fprintf
(
stderr
,
"Done.
\n
"
);
/* close the connection to the database and cleanup */
/* close the connection to the database and cleanup */
PQfinish
(
conn
);
PQfinish
(
conn
);
return
0
;
/* Though PQfinish(conn1) has called
* exit(1) */
return
0
;
}
}
src/test/examples/testlibpq2.sql
View file @
e92dc1e1
...
@@ -2,4 +2,5 @@ CREATE TABLE TBL1 (i int4);
...
@@ -2,4 +2,5 @@ CREATE TABLE TBL1 (i int4);
CREATE
TABLE
TBL2
(
i
int4
);
CREATE
TABLE
TBL2
(
i
int4
);
CREATE
RULE
r1
AS
ON
INSERT
TO
TBL1
DO
[
INSERT
INTO
TBL2
values
(
new
.
i
);
NOTIFY
TBL2
];
CREATE
RULE
r1
AS
ON
INSERT
TO
TBL1
DO
(
INSERT
INTO
TBL2
VALUES
(
new
.
i
);
NOTIFY
TBL2
);
src/test/examples/testlibpq3.c
View file @
e92dc1e1
/*
/*
* testlibpq3.c
* testlibpq3.c
* Test the C version of LIBPQ, the POSTGRES frontend library.
* Test out-of-line parameters and binary I/O.
* tests the binary cursor interface
*
*
* Before running this, populate a database with the following commands
* (provided in src/test/examples/testlibpq3.sql):
*
*
* CREATE TABLE test1 (i int4, t text, b bytea);
*
*
populate a database by doing the following:
* INSERT INTO test1 values (1, 'joe''s place', '\\000\\001\\002\\003\\004');
* INSERT INTO test1 values (2, 'ho there', '\\004\\003\\002\\001\\000');
CREATE TABLE test1 (i int4, d float4, p polygon);
*
* The expected output is:
INSERT INTO test1 values (1, 3.567, '(3.0, 4.0, 1.0, 2.0)'::polygon);
*
* tuple 0: got
INSERT INTO test1 values (2, 89.05, '(4.0, 3.0, 2.0, 1.0)'::polygon);
* i = (4 bytes) 1
* t = (11 bytes) 'joe's place'
the expected output is:
* b = (5 bytes) \000\001\002\003\004
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 "postgres.h"
/* -> "c.h" -> int16, in access/attnum.h */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "libpq-fe.h"
#include "libpq-fe.h"
#include "utils/geo_decls.h"
/* for the POLYGON type */
/* for ntohl/htonl */
#include <netinet/in.h>
#include <arpa/inet.h>
static
void
static
void
exit_nicely
(
PGconn
*
conn
)
exit_nicely
(
PGconn
*
conn
)
...
@@ -38,146 +37,118 @@ exit_nicely(PGconn *conn)
...
@@ -38,146 +37,118 @@ exit_nicely(PGconn *conn)
}
}
int
int
main
()
main
(
int
argc
,
char
**
argv
)
{
{
char
*
pghost
,
const
char
*
conninfo
;
*
pgport
,
*
pgoptions
,
*
pgtty
;
char
*
dbName
;
/*
* int nFields; int i, j;
*/
int
i
;
int
i_fnum
,
d_fnum
,
p_fnum
;
PGconn
*
conn
;
PGconn
*
conn
;
PGresult
*
res
;
PGresult
*
res
;
const
char
*
paramValues
[
1
];
int
i
,
j
;
int
i_fnum
,
t_fnum
,
b_fnum
;
/*
/*
*
begin, by setting the parameters for a backend connection if the
*
If the user supplies a parameter on the command line, use it as
*
parameters are null, then the system will try to use reasonable
*
the conninfo string; otherwise default to setting dbname=template1
*
defaults by looking up environment variables or, failing that,
*
and using environment variables or defaults for all other connection
*
using hardwired constants
*
parameters.
*/
*/
pghost
=
NULL
;
/* host name of the backend server */
if
(
argc
>
1
)
pgport
=
NULL
;
/* port of the backend server */
conninfo
=
argv
[
1
];
pgoptions
=
NULL
;
/* special options to start up the backend
else
* server */
conninfo
=
"dbname = template1"
;
pgtty
=
NULL
;
/* debugging tty for the backend server */
dbName
=
getenv
(
"USER"
);
/* change this to the name of your test
/* Make a connection to the database */
* database */
conn
=
PQconnectdb
(
conninfo
);
/* make a connection to the database */
/* Check to see that the backend connection was successfully made */
conn
=
PQsetdb
(
pghost
,
pgport
,
pgoptions
,
pgtty
,
dbName
);
if
(
PQstatus
(
conn
)
!=
CONNECTION_OK
)
/* check to see that the backend connection was successfully made */
if
(
PQstatus
(
conn
)
==
CONNECTION_BAD
)
{
{
fprintf
(
stderr
,
"Connection to database '%s' failed.
\n
"
,
dbName
);
fprintf
(
stderr
,
"Connection to database '%s' failed.
\n
"
,
PQdb
(
conn
)
);
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
fprintf
(
stderr
,
"%s"
,
PQerrorMessage
(
conn
));
exit_nicely
(
conn
);
exit_nicely
(
conn
);
}
}
/* start a transaction block */
res
=
PQexec
(
conn
,
"BEGIN"
);
if
(
PQresultStatus
(
res
)
!=
PGRES_COMMAND_OK
)
{
fprintf
(
stderr
,
"BEGIN command failed
\n
"
);
PQclear
(
res
);
exit_nicely
(
conn
);
}
/*
/*
* should PQclear PGresult whenever it is no longer needed to avoid
* The point of this program is to illustrate use of PQexecParams()
* memory leaks
* with out-of-line parameters, as well as binary transmission of
* results. By using out-of-line parameters we can avoid a lot of
* tedious mucking about with quoting and escaping. Notice how we
* don't have to do anything special with the quote mark in the
* parameter value.
*/
*/
PQclear
(
res
);
/*
/* Here is our out-of-line parameter value */
* fetch instances from the pg_database, the system catalog of
paramValues
[
0
]
=
"joe's place"
;
* databases
*/
res
=
PQexecParams
(
conn
,
res
=
PQexec
(
conn
,
"DECLARE mycursor BINARY CURSOR FOR select * from test1"
);
"SELECT * FROM test1 WHERE t = $1"
,
if
(
res
==
NULL
||
1
,
/* one param */
PQresultStatus
(
res
)
!=
PGRES_COMMAND_OK
)
NULL
,
/* let the backend deduce param type */
{
paramValues
,
fprintf
(
stderr
,
"DECLARE CURSOR command failed
\n
"
);
NULL
,
/* don't need param lengths since text */
if
(
res
)
NULL
,
/* default to all text params */
PQclear
(
res
);
1
);
/* ask for binary results */
exit_nicely
(
conn
);
}
PQclear
(
res
);
res
=
PQexec
(
conn
,
"FETCH ALL in mycursor"
);
if
(
PQresultStatus
(
res
)
!=
PGRES_TUPLES_OK
)
if
(
res
==
NULL
||
PQresultStatus
(
res
)
!=
PGRES_TUPLES_OK
)
{
{
fprintf
(
stderr
,
"FETCH ALL command didn't return tuples properly
\n
"
);
fprintf
(
stderr
,
"SELECT failed: %s"
,
PQerrorMessage
(
conn
));
if
(
res
)
PQclear
(
res
);
PQclear
(
res
);
exit_nicely
(
conn
);
exit_nicely
(
conn
);
}
}
/* Use PQfnumber to avoid assumptions about field order in result */
i_fnum
=
PQfnumber
(
res
,
"i"
);
i_fnum
=
PQfnumber
(
res
,
"i"
);
d_fnum
=
PQfnumber
(
res
,
"d
"
);
t_fnum
=
PQfnumber
(
res
,
"t
"
);
p_fnum
=
PQfnumber
(
res
,
"p
"
);
b_fnum
=
PQfnumber
(
res
,
"b
"
);
for
(
i
=
0
;
i
<
3
;
i
++
)
{
printf
(
"type[%d] = %d, size[%d] = %d
\n
"
,
i
,
PQftype
(
res
,
i
),
i
,
PQfsize
(
res
,
i
));
}
for
(
i
=
0
;
i
<
PQntuples
(
res
);
i
++
)
for
(
i
=
0
;
i
<
PQntuples
(
res
);
i
++
)
{
{
int
*
ival
;
char
*
iptr
;
float
*
dval
;
char
*
tptr
;
int
plen
;
char
*
bptr
;
POLYGON
*
pval
;
int
blen
;
int
ival
;
/*
we hard-wire this to the 3 fields we know about
*/
/*
Get the field values (we ignore possibility they are null!)
*/
i
val
=
(
int
*
)
PQgetvalue
(
res
,
i
,
i_fnum
);
i
ptr
=
PQgetvalue
(
res
,
i
,
i_fnum
);
dval
=
(
float
*
)
PQgetvalue
(
res
,
i
,
d
_fnum
);
tptr
=
PQgetvalue
(
res
,
i
,
t
_fnum
);
plen
=
PQgetlength
(
res
,
i
,
p
_fnum
);
bptr
=
PQgetvalue
(
res
,
i
,
b
_fnum
);
/*
/*
*
plen doesn't include the length field so need to increment by
*
The binary representation of INT4 is in network byte order,
*
VARHDSZ
*
which we'd better coerce to the local byte order.
*/
*/
pval
=
(
POLYGON
*
)
malloc
(
plen
+
VARHDRSZ
);
ival
=
ntohl
(
*
((
uint32_t
*
)
iptr
));
pval
->
size
=
plen
;
memmove
((
char
*
)
&
pval
->
npts
,
PQgetvalue
(
res
,
i
,
p_fnum
),
plen
);
printf
(
"tuple %d: got
\n
"
,
i
);
printf
(
" i = (%d bytes) %d,
\n
"
,
PQgetlength
(
res
,
i
,
i_fnum
),
*
ival
);
printf
(
" d = (%d bytes) %f,
\n
"
,
PQgetlength
(
res
,
i
,
d_fnum
),
*
dval
);
printf
(
" p = (%d bytes) %d points
\t
boundbox = (hi=%f/%f, lo = %f,%f)
\n
"
,
PQgetlength
(
res
,
i
,
d_fnum
),
pval
->
npts
,
pval
->
boundbox
.
high
.
x
,
pval
->
boundbox
.
high
.
y
,
pval
->
boundbox
.
low
.
x
,
pval
->
boundbox
.
low
.
y
);
}
PQclear
(
res
);
/*
* The binary representation of TEXT is, well, text, and since
* libpq was nice enough to append a zero byte to it, it'll work
* just fine as a C string.
*
* The binary representation of BYTEA is a bunch of bytes, which
* could include embedded nulls so we have to pay attention to
* field length.
*/
blen
=
PQgetlength
(
res
,
i
,
b_fnum
);
/* close the portal */
printf
(
"tuple %d: got
\n
"
,
i
);
res
=
PQexec
(
conn
,
"CLOSE mycursor"
);
printf
(
" i = (%d bytes) %d
\n
"
,
PQclear
(
res
);
PQgetlength
(
res
,
i
,
i_fnum
),
ival
);
printf
(
" t = (%d bytes) '%s'
\n
"
,
PQgetlength
(
res
,
i
,
t_fnum
),
tptr
);
printf
(
" b = (%d bytes) "
,
blen
);
for
(
j
=
0
;
j
<
blen
;
j
++
)
printf
(
"
\\
%03o"
,
bptr
[
j
]);
printf
(
"
\n\n
"
);
}
/* end the transaction */
res
=
PQexec
(
conn
,
"END"
);
PQclear
(
res
);
PQclear
(
res
);
/* close the connection to the database and cleanup */
/* close the connection to the database and cleanup */
PQfinish
(
conn
);
PQfinish
(
conn
);
return
0
;
/* Though PQfinish(conn1) has called
* exit(1) */
return
0
;
}
}
src/test/examples/testlibpq3.sql
View file @
e92dc1e1
CREATE
TABLE
test1
(
i
int4
,
d
float4
,
p
polygon
);
CREATE
TABLE
test1
(
i
int4
,
t
text
,
b
bytea
);
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
);
INSERT
INTO
test1
values
(
1
,
'joe
''
s place'
,
'
\\
000
\\
001
\\
002
\\
003
\\
004'
);
INSERT
INTO
test1
values
(
2
,
'ho there'
,
'
\\
004
\\
003
\\
002
\\
001
\\
000'
);
src/test/examples/testlibpq4.c
View file @
e92dc1e1
/*
/*
* testlibpq4.c
* testlibpq4.c
* this test program
s
shows to use LIBPQ to make multiple backend
* this test program shows to use LIBPQ to make multiple backend
* connections
* connections
*
*
*
*/
*/
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include "libpq-fe.h"
#include "libpq-fe.h"
static
void
static
void
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment