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
aa7f0046
Commit
aa7f0046
authored
Dec 07, 2008
by
Alvaro Herrera
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Desultorily enclose programlisting tags in CDATA, to get rid of some obnoxious
SGML-escaping.
parent
b2971e20
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
238 additions
and
209 deletions
+238
-209
doc/src/sgml/auto-explain.sgml
doc/src/sgml/auto-explain.sgml
+7
-6
doc/src/sgml/ecpg.sgml
doc/src/sgml/ecpg.sgml
+23
-18
doc/src/sgml/libpq.sgml
doc/src/sgml/libpq.sgml
+47
-39
doc/src/sgml/lobj.sgml
doc/src/sgml/lobj.sgml
+41
-40
doc/src/sgml/trigger.sgml
doc/src/sgml/trigger.sgml
+17
-16
doc/src/sgml/xfunc.sgml
doc/src/sgml/xfunc.sgml
+33
-27
doc/src/sgml/xindex.sgml
doc/src/sgml/xindex.sgml
+53
-49
doc/src/sgml/xtypes.sgml
doc/src/sgml/xtypes.sgml
+17
-14
No files found.
doc/src/sgml/auto-explain.sgml
View file @
aa7f0046
<!-- $PostgreSQL: pgsql/doc/src/sgml/auto-explain.sgml,v 1.
1 2008/11/19 02:59:28 tgl
Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/auto-explain.sgml,v 1.
2 2008/12/07 23:46:39 alvherre
Exp $ -->
<sect1 id="auto-explain">
<sect1 id="auto-explain">
<title>auto_explain</title>
<title>auto_explain</title>
...
@@ -150,18 +150,19 @@ explain.log_min_duration = '3s'
...
@@ -150,18 +150,19 @@ explain.log_min_duration = '3s'
This might produce log output such as:
This might produce log output such as:
</para>
</para>
<programlisting>
<programlisting>
<![CDATA[
LOG: duration: 0.986 ms plan:
LOG: duration: 0.986 ms plan:
Aggregate (cost=14.90..14.91 rows=1 width=0)
Aggregate (cost=14.90..14.91 rows=1 width=0)
-
>
Hash Join (cost=3.91..14.70 rows=81 width=0)
-
>
Hash Join (cost=3.91..14.70 rows=81 width=0)
Hash Cond: (pg_class.oid = pg_index.indrelid)
Hash Cond: (pg_class.oid = pg_index.indrelid)
-
>
Seq Scan on pg_class (cost=0.00..8.27 rows=227 width=4)
-
>
Seq Scan on pg_class (cost=0.00..8.27 rows=227 width=4)
-
>
Hash (cost=2.90..2.90 rows=81 width=4)
-
>
Hash (cost=2.90..2.90 rows=81 width=4)
-
>
Seq Scan on pg_index (cost=0.00..2.90 rows=81 width=4)
-
>
Seq Scan on pg_index (cost=0.00..2.90 rows=81 width=4)
Filter: indisunique
Filter: indisunique
STATEMENT: SELECT count(*)
STATEMENT: SELECT count(*)
FROM pg_class, pg_index
FROM pg_class, pg_index
WHERE oid = indrelid AND indisunique;
WHERE oid = indrelid AND indisunique;
]]>
</programlisting>
</programlisting>
</sect2>
</sect2>
...
...
doc/src/sgml/ecpg.sgml
View file @
aa7f0046
<!-- $PostgreSQL: pgsql/doc/src/sgml/ecpg.sgml,v 1.8
6 2008/06/12 19:15:40 momjian
Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/ecpg.sgml,v 1.8
7 2008/12/07 23:46:39 alvherre
Exp $ -->
<chapter id="ecpg">
<chapter id="ecpg">
<title><application>ECPG</application> - Embedded <acronym>SQL</acronym> in C</title>
<title><application>ECPG</application> - Embedded <acronym>SQL</acronym> in C</title>
...
@@ -717,9 +717,9 @@ EXEC SQL EXECUTE mystmt USING 42, 'foobar';
...
@@ -717,9 +717,9 @@ EXEC SQL EXECUTE mystmt USING 42, 'foobar';
</programlisting>
</programlisting>
If the statement you are executing returns values, then add an
If the statement you are executing returns values, then add an
<literal>INTO</literal> clause:
<literal>INTO</literal> clause:
<programlisting>
<programlisting>
<![CDATA[
EXEC SQL BEGIN DECLARE SECTION;
EXEC SQL BEGIN DECLARE SECTION;
const char *stmt = "SELECT a, b, c FROM test1 WHERE a
>
?";
const char *stmt = "SELECT a, b, c FROM test1 WHERE a
>
?";
int v1, v2;
int v1, v2;
VARCHAR v3;
VARCHAR v3;
EXEC SQL END DECLARE SECTION;
EXEC SQL END DECLARE SECTION;
...
@@ -727,6 +727,7 @@ EXEC SQL END DECLARE SECTION;
...
@@ -727,6 +727,7 @@ EXEC SQL END DECLARE SECTION;
EXEC SQL PREPARE mystmt FROM :stmt;
EXEC SQL PREPARE mystmt FROM :stmt;
...
...
EXEC SQL EXECUTE mystmt INTO v1, v2, v3 USING 37;
EXEC SQL EXECUTE mystmt INTO v1, v2, v3 USING 37;
]]>
</programlisting>
</programlisting>
An <command>EXECUTE</command> command can have an
An <command>EXECUTE</command> command can have an
<literal>INTO</literal> clause, a <literal>USING</literal> clause,
<literal>INTO</literal> clause, a <literal>USING</literal> clause,
...
@@ -752,7 +753,7 @@ EXEC SQL DEALLOCATE PREPARE <replaceable>name</replaceable>;
...
@@ -752,7 +753,7 @@ EXEC SQL DEALLOCATE PREPARE <replaceable>name</replaceable>;
functions to do basic calculations with those types within C, i.e. without
functions to do basic calculations with those types within C, i.e. without
the help of the <productname>PostgreSQL</productname> server. See the
the help of the <productname>PostgreSQL</productname> server. See the
following example:
following example:
<programlisting>
<programlisting>
<![CDATA[
EXEC SQL BEGIN DECLARE SECTION;
EXEC SQL BEGIN DECLARE SECTION;
date date1;
date date1;
timestamp ts1, tsout;
timestamp ts1, tsout;
...
@@ -760,12 +761,13 @@ EXEC SQL BEGIN DECLARE SECTION;
...
@@ -760,12 +761,13 @@ EXEC SQL BEGIN DECLARE SECTION;
char *out;
char *out;
EXEC SQL END DECLARE SECTION;
EXEC SQL END DECLARE SECTION;
PGTYPESdate_today(&
amp;
date1);
PGTYPESdate_today(&date1);
EXEC SQL SELECT started, duration INTO :ts1, :iv1 FROM datetbl WHERE d=:date1;
EXEC SQL SELECT started, duration INTO :ts1, :iv1 FROM datetbl WHERE d=:date1;
PGTYPEStimestamp_add_interval(&
amp;ts1, &iv1, &
tsout);
PGTYPEStimestamp_add_interval(&
ts1, &iv1, &
tsout);
out = PGTYPEStimestamp_to_asc(&
amp;
tsout);
out = PGTYPEStimestamp_to_asc(&tsout);
printf("Started + duration: %s\n", out);
printf("Started + duration: %s\n", out);
free(out);
free(out);
]]>
</programlisting>
</programlisting>
</para>
</para>
...
@@ -3449,14 +3451,15 @@ int rsetnull(int t, char *ptr);
...
@@ -3449,14 +3451,15 @@ int rsetnull(int t, char *ptr);
<para>
<para>
Here is an example of a call to this function:
Here is an example of a call to this function:
<programlisting>
<programlisting>
<![CDATA[
$char c[] = "abc ";
$char c[] = "abc ";
$short s = 17;
$short s = 17;
$int i = -74874;
$int i = -74874;
rsetnull(CCHARTYPE, (char *) c);
rsetnull(CCHARTYPE, (char *) c);
rsetnull(CSHORTTYPE, (char *) &s);
rsetnull(CSHORTTYPE, (char *) &s);
rsetnull(CINTTYPE, (char *) &i);
rsetnull(CINTTYPE, (char *) &i);
]]>
</programlisting>
</programlisting>
</para>
</para>
</listitem>
</listitem>
...
@@ -3477,14 +3480,15 @@ int risnull(int t, char *ptr);
...
@@ -3477,14 +3480,15 @@ int risnull(int t, char *ptr);
</para>
</para>
<para>
<para>
Here is an example of how to use this function:
Here is an example of how to use this function:
<programlisting>
<programlisting>
<![CDATA[
$char c[] = "abc ";
$char c[] = "abc ";
$short s = 17;
$short s = 17;
$int i = -74874;
$int i = -74874;
risnull(CCHARTYPE, (char *) c);
risnull(CCHARTYPE, (char *) c);
risnull(CSHORTTYPE, (char *) &s);
risnull(CSHORTTYPE, (char *) &s);
risnull(CINTTYPE, (char *) &i);
risnull(CINTTYPE, (char *) &i);
]]>
</programlisting>
</programlisting>
</para>
</para>
</listitem>
</listitem>
...
@@ -4960,11 +4964,11 @@ EXEC SQL END DECLARE SECTION;
...
@@ -4960,11 +4964,11 @@ EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT res INTO :result FROM mytable WHERE index = :index;
EXEC SQL SELECT res INTO :result FROM mytable WHERE index = :index;
</programlisting>
</programlisting>
is translated into:
is translated into:
<programlisting>
<programlisting>
<![CDATA[
/* Processed by ecpg (2.6.0) */
/* Processed by ecpg (2.6.0) */
/* These two include files are added by the preprocessor */
/* These two include files are added by the preprocessor */
#include
<ecpgtype.h>
;
#include
<ecpgtype.h>
;
#include
<ecpglib.h>
;
#include
<ecpglib.h>
;
/* exec sql begin declare section */
/* exec sql begin declare section */
...
@@ -4975,11 +4979,12 @@ EXEC SQL SELECT res INTO :result FROM mytable WHERE index = :index;
...
@@ -4975,11 +4979,12 @@ EXEC SQL SELECT res INTO :result FROM mytable WHERE index = :index;
/* exec sql end declare section */
/* exec sql end declare section */
...
...
ECPGdo(__LINE__, NULL, "SELECT res FROM mytable WHERE index = ? ",
ECPGdo(__LINE__, NULL, "SELECT res FROM mytable WHERE index = ? ",
ECPGt_int,&
amp;
(index),1L,1L,sizeof(int),
ECPGt_int,&(index),1L,1L,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_int,&
amp;
(result),1L,1L,sizeof(int),
ECPGt_int,&(result),1L,1L,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 147 "foo.pgc"
#line 147 "foo.pgc"
]]>
</programlisting>
</programlisting>
(The indentation here is added for readability and not
(The indentation here is added for readability and not
something the preprocessor does.)
something the preprocessor does.)
...
...
doc/src/sgml/libpq.sgml
View file @
aa7f0046
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.27
2 2008/12/02 12:42:11 mha
Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/libpq.sgml,v 1.27
3 2008/12/07 23:46:39 alvherre
Exp $ -->
<chapter id="libpq">
<chapter id="libpq">
<title><application>libpq</application> - C Library</title>
<title><application>libpq</application> - C Library</title>
...
@@ -5415,8 +5415,9 @@ int eventproc(PGEventId evtId, void *evtInfo, void *passThrough)
...
@@ -5415,8 +5415,9 @@ int eventproc(PGEventId evtId, void *evtInfo, void *passThrough)
</para>
</para>
<programlisting>
<programlisting>
<![CDATA[
/* required header for libpq events (note: includes libpq-fe.h) */
/* required header for libpq events (note: includes libpq-fe.h) */
#include
<libpq-events.h>
#include
<libpq-events.h>
/* The instanceData */
/* The instanceData */
typedef struct
typedef struct
...
@@ -5488,17 +5489,17 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
...
@@ -5488,17 +5489,17 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
case PGEVT_REGISTER:
case PGEVT_REGISTER:
{
{
PGEventRegister *e = (PGEventRegister *)evtInfo;
PGEventRegister *e = (PGEventRegister *)evtInfo;
mydata *data = get_mydata(e-
>
conn);
mydata *data = get_mydata(e-
>
conn);
/* associate app specific data with connection */
/* associate app specific data with connection */
PQsetInstanceData(e-
>
conn, myEventProc, data);
PQsetInstanceData(e-
>
conn, myEventProc, data);
break;
break;
}
}
case PGEVT_CONNRESET:
case PGEVT_CONNRESET:
{
{
PGEventConnReset *e = (PGEventConnReset *)evtInfo;
PGEventConnReset *e = (PGEventConnReset *)evtInfo;
mydata *data = PQinstanceData(e-
>
conn, myEventProc);
mydata *data = PQinstanceData(e-
>
conn, myEventProc);
if (data)
if (data)
memset(data, 0, sizeof(mydata));
memset(data, 0, sizeof(mydata));
...
@@ -5508,7 +5509,7 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
...
@@ -5508,7 +5509,7 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
case PGEVT_CONNDESTROY:
case PGEVT_CONNDESTROY:
{
{
PGEventConnDestroy *e = (PGEventConnDestroy *)evtInfo;
PGEventConnDestroy *e = (PGEventConnDestroy *)evtInfo;
mydata *data = PQinstanceData(e-
>
conn, myEventProc);
mydata *data = PQinstanceData(e-
>
conn, myEventProc);
/* free instance data because the conn is being destroyed */
/* free instance data because the conn is being destroyed */
if (data)
if (data)
...
@@ -5519,29 +5520,29 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
...
@@ -5519,29 +5520,29 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
case PGEVT_RESULTCREATE:
case PGEVT_RESULTCREATE:
{
{
PGEventResultCreate *e = (PGEventResultCreate *)evtInfo;
PGEventResultCreate *e = (PGEventResultCreate *)evtInfo;
mydata *conn_data = PQinstanceData(e-
>
conn, myEventProc);
mydata *conn_data = PQinstanceData(e-
>
conn, myEventProc);
mydata *res_data = dup_mydata(conn_data);
mydata *res_data = dup_mydata(conn_data);
/* associate app specific data with result (copy it from conn) */
/* associate app specific data with result (copy it from conn) */
PQsetResultInstanceData(e-
>
result, myEventProc, res_data);
PQsetResultInstanceData(e-
>
result, myEventProc, res_data);
break;
break;
}
}
case PGEVT_RESULTCOPY:
case PGEVT_RESULTCOPY:
{
{
PGEventResultCopy *e = (PGEventResultCopy *)evtInfo;
PGEventResultCopy *e = (PGEventResultCopy *)evtInfo;
mydata *src_data = PQresultInstanceData(e-
>
src, myEventProc);
mydata *src_data = PQresultInstanceData(e-
>
src, myEventProc);
mydata *dest_data = dup_mydata(src_data);
mydata *dest_data = dup_mydata(src_data);
/* associate app specific data with result (copy it from a result) */
/* associate app specific data with result (copy it from a result) */
PQsetResultInstanceData(e-
>
dest, myEventProc, dest_data);
PQsetResultInstanceData(e-
>
dest, myEventProc, dest_data);
break;
break;
}
}
case PGEVT_RESULTDESTROY:
case PGEVT_RESULTDESTROY:
{
{
PGEventResultDestroy *e = (PGEventResultDestroy *)evtInfo;
PGEventResultDestroy *e = (PGEventResultDestroy *)evtInfo;
mydata *data = PQresultInstanceData(e-
>
result, myEventProc);
mydata *data = PQresultInstanceData(e-
>
result, myEventProc);
/* free instance data because the result is being destroyed */
/* free instance data because the result is being destroyed */
if (data)
if (data)
...
@@ -5556,6 +5557,7 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
...
@@ -5556,6 +5557,7 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
return TRUE; /* event processing succeeded */
return TRUE; /* event processing succeeded */
}
}
]]>
</programlisting>
</programlisting>
</sect2>
</sect2>
</sect1>
</sect1>
...
@@ -6407,13 +6409,14 @@ testlibpq.o(.text+0xa4): undefined reference to `PQerrorMessage'
...
@@ -6407,13 +6409,14 @@ testlibpq.o(.text+0xa4): undefined reference to `PQerrorMessage'
<title><application>libpq</application> Example Program 1</title>
<title><application>libpq</application> Example Program 1</title>
<programlisting>
<programlisting>
<![CDATA[
/*
/*
* testlibpq.c
* testlibpq.c
*
*
* Test the C version of libpq, the PostgreSQL frontend library.
* Test the C version of libpq, the PostgreSQL frontend library.
*/
*/
#include
<stdio.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<stdlib.h>
#include "libpq-fe.h"
#include "libpq-fe.h"
static void
static void
...
@@ -6438,7 +6441,7 @@ main(int argc, char **argv)
...
@@ -6438,7 +6441,7 @@ main(int argc, char **argv)
* conninfo string; otherwise default to setting dbname=postgres and using
* conninfo string; otherwise default to setting dbname=postgres and using
* environment variables or defaults for all other connection parameters.
* environment variables or defaults for all other connection parameters.
*/
*/
if (argc
>
1)
if (argc
>
1)
conninfo = argv[1];
conninfo = argv[1];
else
else
conninfo = "dbname = postgres";
conninfo = "dbname = postgres";
...
@@ -6498,14 +6501,14 @@ main(int argc, char **argv)
...
@@ -6498,14 +6501,14 @@ main(int argc, char **argv)
/* first, print out the attribute names */
/* first, print out the attribute names */
nFields = PQnfields(res);
nFields = PQnfields(res);
for (i = 0; i
<
nFields; i++)
for (i = 0; i
<
nFields; i++)
printf("%-15s", PQfname(res, i));
printf("%-15s", PQfname(res, i));
printf("\n\n");
printf("\n\n");
/* next, print out the rows */
/* next, print out the rows */
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++)
printf("%-15s", PQgetvalue(res, i, j));
printf("%-15s", PQgetvalue(res, i, j));
printf("\n");
printf("\n");
}
}
...
@@ -6525,6 +6528,7 @@ main(int argc, char **argv)
...
@@ -6525,6 +6528,7 @@ main(int argc, char **argv)
return 0;
return 0;
}
}
]]>
</programlisting>
</programlisting>
</example>
</example>
...
@@ -6532,6 +6536,7 @@ main(int argc, char **argv)
...
@@ -6532,6 +6536,7 @@ main(int argc, char **argv)
<title><application>libpq</application> Example Program 2</title>
<title><application>libpq</application> Example Program 2</title>
<programlisting>
<programlisting>
<![CDATA[
/*
/*
* testlibpq2.c
* testlibpq2.c
* Test of the asynchronous notification interface
* Test of the asynchronous notification interface
...
@@ -6555,11 +6560,11 @@ main(int argc, char **argv)
...
@@ -6555,11 +6560,11 @@ main(int argc, char **argv)
*
*
* INSERT INTO TBL1 VALUES (10);
* INSERT INTO TBL1 VALUES (10);
*/
*/
#include
<stdio.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<stdlib.h>
#include
<string.h>
#include
<string.h>
#include
<errno.h>
#include
<errno.h>
#include
<sys/time.h>
#include
<sys/time.h>
#include "libpq-fe.h"
#include "libpq-fe.h"
static void
static void
...
@@ -6583,7 +6588,7 @@ main(int argc, char **argv)
...
@@ -6583,7 +6588,7 @@ main(int argc, char **argv)
* conninfo string; otherwise default to setting dbname=postgres and using
* conninfo string; otherwise default to setting dbname=postgres and using
* environment variables or defaults for all other connection parameters.
* environment variables or defaults for all other connection parameters.
*/
*/
if (argc
>
1)
if (argc
>
1)
conninfo = argv[1];
conninfo = argv[1];
else
else
conninfo = "dbname = postgres";
conninfo = "dbname = postgres";
...
@@ -6618,7 +6623,7 @@ main(int argc, char **argv)
...
@@ -6618,7 +6623,7 @@ main(int argc, char **argv)
/* Quit after four notifies are received. */
/* Quit after four notifies are received. */
nnotifies = 0;
nnotifies = 0;
while (nnotifies
<
4)
while (nnotifies
<
4)
{
{
/*
/*
* Sleep until something happens on the connection. We use select(2)
* Sleep until something happens on the connection. We use select(2)
...
@@ -6630,13 +6635,13 @@ main(int argc, char **argv)
...
@@ -6630,13 +6635,13 @@ main(int argc, char **argv)
sock = PQsocket(conn);
sock = PQsocket(conn);
if (sock
<
0)
if (sock
<
0)
break; /* shouldn't happen */
break; /* shouldn't happen */
FD_ZERO(&
amp;
input_mask);
FD_ZERO(&input_mask);
FD_SET(sock, &
amp;
input_mask);
FD_SET(sock, &input_mask);
if (select(sock + 1, &
amp;input_mask, NULL, NULL, NULL) <
0)
if (select(sock + 1, &
input_mask, NULL, NULL, NULL) <
0)
{
{
fprintf(stderr, "select() failed: %s\n", strerror(errno));
fprintf(stderr, "select() failed: %s\n", strerror(errno));
exit_nicely(conn);
exit_nicely(conn);
...
@@ -6648,7 +6653,7 @@ main(int argc, char **argv)
...
@@ -6648,7 +6653,7 @@ main(int argc, char **argv)
{
{
fprintf(stderr,
fprintf(stderr,
"ASYNC NOTIFY of '%s' received from backend pid %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);
nnotifies++;
nnotifies++;
}
}
...
@@ -6661,6 +6666,7 @@ main(int argc, char **argv)
...
@@ -6661,6 +6666,7 @@ main(int argc, char **argv)
return 0;
return 0;
}
}
]]>
</programlisting>
</programlisting>
</example>
</example>
...
@@ -6668,6 +6674,7 @@ main(int argc, char **argv)
...
@@ -6668,6 +6674,7 @@ main(int argc, char **argv)
<title><application>libpq</application> Example Program 3</>
<title><application>libpq</application> Example Program 3</>
<programlisting>
<programlisting>
<![CDATA[
/*
/*
* testlibpq3.c
* testlibpq3.c
* Test out-of-line parameters and binary I/O.
* Test out-of-line parameters and binary I/O.
...
@@ -6692,15 +6699,15 @@ main(int argc, char **argv)
...
@@ -6692,15 +6699,15 @@ main(int argc, char **argv)
* t = (8 bytes) 'ho there'
* t = (8 bytes) 'ho there'
* b = (5 bytes) \004\003\002\001\000
* b = (5 bytes) \004\003\002\001\000
*/
*/
#include
<stdio.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<stdlib.h>
#include
<string.h>
#include
<string.h>
#include
<sys/types.h>
#include
<sys/types.h>
#include "libpq-fe.h"
#include "libpq-fe.h"
/* for ntohl/htonl */
/* for ntohl/htonl */
#include
<netinet/in.h>
#include
<netinet/in.h>
#include
<arpa/inet.h>
#include
<arpa/inet.h>
static void
static void
...
@@ -6729,7 +6736,7 @@ show_binary_results(PGresult *res)
...
@@ -6729,7 +6736,7 @@ show_binary_results(PGresult *res)
t_fnum = PQfnumber(res, "t");
t_fnum = PQfnumber(res, "t");
b_fnum = PQfnumber(res, "b");
b_fnum = PQfnumber(res, "b");
for (i = 0; i
<
PQntuples(res); i++)
for (i = 0; i
<
PQntuples(res); i++)
{
{
char *iptr;
char *iptr;
char *tptr;
char *tptr;
...
@@ -6764,7 +6771,7 @@ show_binary_results(PGresult *res)
...
@@ -6764,7 +6771,7 @@ show_binary_results(PGresult *res)
printf(" t = (%d bytes) '%s'\n",
printf(" t = (%d bytes) '%s'\n",
PQgetlength(res, i, t_fnum), tptr);
PQgetlength(res, i, t_fnum), tptr);
printf(" b = (%d bytes) ", blen);
printf(" b = (%d bytes) ", blen);
for (j = 0; j
<
blen; j++)
for (j = 0; j
<
blen; j++)
printf("\\%03o", bptr[j]);
printf("\\%03o", bptr[j]);
printf("\n\n");
printf("\n\n");
}
}
...
@@ -6786,7 +6793,7 @@ main(int argc, char **argv)
...
@@ -6786,7 +6793,7 @@ main(int argc, char **argv)
* conninfo string; otherwise default to setting dbname=postgres and using
* conninfo string; otherwise default to setting dbname=postgres and using
* environment variables or defaults for all other connection parameters.
* environment variables or defaults for all other connection parameters.
*/
*/
if (argc
>
1)
if (argc
>
1)
conninfo = argv[1];
conninfo = argv[1];
else
else
conninfo = "dbname = postgres";
conninfo = "dbname = postgres";
...
@@ -6850,7 +6857,7 @@ main(int argc, char **argv)
...
@@ -6850,7 +6857,7 @@ main(int argc, char **argv)
binaryIntVal = htonl((uint32_t) 2);
binaryIntVal = htonl((uint32_t) 2);
/* Set up parameter arrays for PQexecParams */
/* Set up parameter arrays for PQexecParams */
paramValues[0] = (char *) &
amp;
binaryIntVal;
paramValues[0] = (char *) &binaryIntVal;
paramLengths[0] = sizeof(binaryIntVal);
paramLengths[0] = sizeof(binaryIntVal);
paramFormats[0] = 1; /* binary */
paramFormats[0] = 1; /* binary */
...
@@ -6879,6 +6886,7 @@ main(int argc, char **argv)
...
@@ -6879,6 +6886,7 @@ main(int argc, char **argv)
return 0;
return 0;
}
}
]]>
</programlisting>
</programlisting>
</example>
</example>
...
...
doc/src/sgml/lobj.sgml
View file @
aa7f0046
<!-- $PostgreSQL: pgsql/doc/src/sgml/lobj.sgml,v 1.4
8 2008/03/22 01:55:14 ishii
Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/lobj.sgml,v 1.4
9 2008/12/07 23:46:39 alvherre
Exp $ -->
<chapter id="largeObjects">
<chapter id="largeObjects">
<title id="largeObjects-title">Large Objects</title>
<title id="largeObjects-title">Large Objects</title>
...
@@ -457,7 +457,7 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image
...
@@ -457,7 +457,7 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image
<example id="lo-example">
<example id="lo-example">
<title>Large Objects with <application>libpq</application> Example Program</title>
<title>Large Objects with <application>libpq</application> Example Program</title>
<programlisting>
<programlisting>
<![CDATA[
/*--------------------------------------------------------------
/*--------------------------------------------------------------
*
*
* testlo.c--
* testlo.c--
...
@@ -467,15 +467,15 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image
...
@@ -467,15 +467,15 @@ SELECT lo_export(image.raster, '/tmp/motd') FROM image
*
*
*--------------------------------------------------------------
*--------------------------------------------------------------
*/
*/
#include
<stdio.h>
#include
<stdio.h>
#include
"libpq-fe.h"
#include
"libpq-fe.h"
#include
"libpq/libpq-fs.h"
#include
"libpq/libpq-fs.h"
#define BUFSIZE 1024
#define BUFSIZE 1024
/*
/*
* importFile
* importFile
* import file
"in_filename" into database as large object "lobjOid"
* import file
"in_filename" into database as large object "lobjOid"
*
*
*/
*/
Oid
Oid
...
@@ -492,9 +492,9 @@ importFile(PGconn *conn, char *filename)
...
@@ -492,9 +492,9 @@ importFile(PGconn *conn, char *filename)
* open the file to be read in
* open the file to be read in
*/
*/
fd = open(filename, O_RDONLY, 0666);
fd = open(filename, O_RDONLY, 0666);
if (fd
<
0)
if (fd
<
0)
{ /* error */
{ /* error */
fprintf(stderr,
"cannot open unix file %s\n"
, filename);
fprintf(stderr,
"cannot open unix file %s\n"
, filename);
}
}
/*
/*
...
@@ -502,18 +502,18 @@ importFile(PGconn *conn, char *filename)
...
@@ -502,18 +502,18 @@ importFile(PGconn *conn, char *filename)
*/
*/
lobjId = lo_creat(conn, INV_READ | INV_WRITE);
lobjId = lo_creat(conn, INV_READ | INV_WRITE);
if (lobjId == 0)
if (lobjId == 0)
fprintf(stderr,
"cannot create large object\n"
);
fprintf(stderr,
"cannot create large object\n"
);
lobj_fd = lo_open(conn, lobjId, INV_WRITE);
lobj_fd = lo_open(conn, lobjId, INV_WRITE);
/*
/*
* read in from the Unix file and write to the inversion file
* read in from the Unix file and write to the inversion file
*/
*/
while ((nbytes = read(fd, buf, BUFSIZE))
>
0)
while ((nbytes = read(fd, buf, BUFSIZE))
>
0)
{
{
tmp = lo_write(conn, lobj_fd, buf, nbytes);
tmp = lo_write(conn, lobj_fd, buf, nbytes);
if (tmp
<
nbytes)
if (tmp
<
nbytes)
fprintf(stderr,
"error while reading large object\n"
);
fprintf(stderr,
"error while reading large object\n"
);
}
}
(void) close(fd);
(void) close(fd);
...
@@ -531,9 +531,9 @@ pickout(PGconn *conn, Oid lobjId, int start, int len)
...
@@ -531,9 +531,9 @@ pickout(PGconn *conn, Oid lobjId, int start, int len)
int nread;
int nread;
lobj_fd = lo_open(conn, lobjId, INV_READ);
lobj_fd = lo_open(conn, lobjId, INV_READ);
if (lobj_fd
<
0)
if (lobj_fd
<
0)
{
{
fprintf(stderr,
"cannot open large object %d\n"
,
fprintf(stderr,
"cannot open large object %d\n"
,
lobjId);
lobjId);
}
}
...
@@ -541,15 +541,15 @@ pickout(PGconn *conn, Oid lobjId, int start, int len)
...
@@ -541,15 +541,15 @@ pickout(PGconn *conn, Oid lobjId, int start, int len)
buf = malloc(len + 1);
buf = malloc(len + 1);
nread = 0;
nread = 0;
while (len - nread
>
0)
while (len - nread
>
0)
{
{
nbytes = lo_read(conn, lobj_fd, buf, len - nread);
nbytes = lo_read(conn, lobj_fd, buf, len - nread);
buf[nbytes] = ' ';
buf[nbytes] = ' ';
fprintf(stderr,
">>> %s"
, buf);
fprintf(stderr,
">>> %s"
, buf);
nread += nbytes;
nread += nbytes;
}
}
free(buf);
free(buf);
fprintf(stderr,
"\n"
);
fprintf(stderr,
"\n"
);
lo_close(conn, lobj_fd);
lo_close(conn, lobj_fd);
}
}
...
@@ -563,33 +563,33 @@ overwrite(PGconn *conn, Oid lobjId, int start, int len)
...
@@ -563,33 +563,33 @@ overwrite(PGconn *conn, Oid lobjId, int start, int len)
int i;
int i;
lobj_fd = lo_open(conn, lobjId, INV_WRITE);
lobj_fd = lo_open(conn, lobjId, INV_WRITE);
if (lobj_fd
<
0)
if (lobj_fd
<
0)
{
{
fprintf(stderr,
"cannot open large object %d\n"
,
fprintf(stderr,
"cannot open large object %d\n"
,
lobjId);
lobjId);
}
}
lo_lseek(conn, lobj_fd, start, SEEK_SET);
lo_lseek(conn, lobj_fd, start, SEEK_SET);
buf = malloc(len + 1);
buf = malloc(len + 1);
for (i = 0; i
<
len; i++)
for (i = 0; i
<
len; i++)
buf[i] = 'X';
buf[i] = 'X';
buf[i] = ' ';
buf[i] = ' ';
nwritten = 0;
nwritten = 0;
while (len - nwritten
>
0)
while (len - nwritten
>
0)
{
{
nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten);
nbytes = lo_write(conn, lobj_fd, buf + nwritten, len - nwritten);
nwritten += nbytes;
nwritten += nbytes;
}
}
free(buf);
free(buf);
fprintf(stderr,
"\n"
);
fprintf(stderr,
"\n"
);
lo_close(conn, lobj_fd);
lo_close(conn, lobj_fd);
}
}
/*
/*
* exportFile
* exportFile
* export large object
"lobjOid" to file "out_filename"
* export large object
"lobjOid" to file "out_filename"
*
*
*/
*/
void
void
...
@@ -605,9 +605,9 @@ exportFile(PGconn *conn, Oid lobjId, char *filename)
...
@@ -605,9 +605,9 @@ exportFile(PGconn *conn, Oid lobjId, char *filename)
* open the large object
* open the large object
*/
*/
lobj_fd = lo_open(conn, lobjId, INV_READ);
lobj_fd = lo_open(conn, lobjId, INV_READ);
if (lobj_fd
<
0)
if (lobj_fd
<
0)
{
{
fprintf(stderr,
"cannot open large object %d\n"
,
fprintf(stderr,
"cannot open large object %d\n"
,
lobjId);
lobjId);
}
}
...
@@ -615,21 +615,21 @@ exportFile(PGconn *conn, Oid lobjId, char *filename)
...
@@ -615,21 +615,21 @@ exportFile(PGconn *conn, Oid lobjId, char *filename)
* open the file to be written to
* open the file to be written to
*/
*/
fd = open(filename, O_CREAT | O_WRONLY, 0666);
fd = open(filename, O_CREAT | O_WRONLY, 0666);
if (fd
<
0)
if (fd
<
0)
{ /* error */
{ /* error */
fprintf(stderr,
"cannot open unix file %s\n"
,
fprintf(stderr,
"cannot open unix file %s\n"
,
filename);
filename);
}
}
/*
/*
* read in from the inversion file and write to the Unix file
* read in from the inversion file and write to the Unix file
*/
*/
while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE))
>
0)
while ((nbytes = lo_read(conn, lobj_fd, buf, BUFSIZE))
>
0)
{
{
tmp = write(fd, buf, nbytes);
tmp = write(fd, buf, nbytes);
if (tmp
<
nbytes)
if (tmp
<
nbytes)
{
{
fprintf(stderr,
"error while writing %s\n"
,
fprintf(stderr,
"error while writing %s\n"
,
filename);
filename);
}
}
}
}
...
@@ -659,7 +659,7 @@ main(int argc, char **argv)
...
@@ -659,7 +659,7 @@ main(int argc, char **argv)
if (argc != 4)
if (argc != 4)
{
{
fprintf(stderr,
"Usage: %s database_name in_filename out_filename\n"
,
fprintf(stderr,
"Usage: %s database_name in_filename out_filename\n"
,
argv[0]);
argv[0]);
exit(1);
exit(1);
}
}
...
@@ -676,36 +676,37 @@ main(int argc, char **argv)
...
@@ -676,36 +676,37 @@ main(int argc, char **argv)
/* check to see that the backend connection was successfully made */
/* check to see that the backend connection was successfully made */
if (PQstatus(conn) == CONNECTION_BAD)
if (PQstatus(conn) == CONNECTION_BAD)
{
{
fprintf(stderr,
"Connection to database '%s' failed.\n"
, database);
fprintf(stderr,
"Connection to database '%s' failed.\n"
, database);
fprintf(stderr,
"%s"
, PQerrorMessage(conn));
fprintf(stderr,
"%s"
, PQerrorMessage(conn));
exit_nicely(conn);
exit_nicely(conn);
}
}
res = PQexec(conn,
"begin"
);
res = PQexec(conn,
"begin"
);
PQclear(res);
PQclear(res);
printf(
"importing file %s\n"
, in_filename);
printf(
"importing file %s\n"
, in_filename);
/* lobjOid = importFile(conn, in_filename); */
/* lobjOid = importFile(conn, in_filename); */
lobjOid = lo_import(conn, in_filename);
lobjOid = lo_import(conn, in_filename);
/*
/*
printf(
"as large object %d.\n"
, lobjOid);
printf(
"as large object %d.\n"
, lobjOid);
printf(
"picking out bytes 1000-2000 of the large object\n"
);
printf(
"picking out bytes 1000-2000 of the large object\n"
);
pickout(conn, lobjOid, 1000, 1000);
pickout(conn, lobjOid, 1000, 1000);
printf(
"overwriting bytes 1000-2000 of the large object with X's\n"
);
printf(
"overwriting bytes 1000-2000 of the large object with X's\n"
);
overwrite(conn, lobjOid, 1000, 1000);
overwrite(conn, lobjOid, 1000, 1000);
*/
*/
printf(
"exporting large object to file %s\n"
, out_filename);
printf(
"exporting large object to file %s\n"
, out_filename);
/* exportFile(conn, lobjOid, out_filename); */
/* exportFile(conn, lobjOid, out_filename); */
lo_export(conn, lobjOid, out_filename);
lo_export(conn, lobjOid, out_filename);
res = PQexec(conn,
"end"
);
res = PQexec(conn,
"end"
);
PQclear(res);
PQclear(res);
PQfinish(conn);
PQfinish(conn);
exit(0);
exit(0);
}
}
]]>
</programlisting>
</programlisting>
</example>
</example>
...
...
doc/src/sgml/trigger.sgml
View file @
aa7f0046
<!-- $PostgreSQL: pgsql/doc/src/sgml/trigger.sgml,v 1.5
2 2008/03/28 00:21:55 tgl
Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/trigger.sgml,v 1.5
3 2008/12/07 23:46:39 alvherre
Exp $ -->
<chapter id="triggers">
<chapter id="triggers">
<title>Triggers</title>
<title>Triggers</title>
...
@@ -559,7 +559,7 @@ CREATE TABLE ttest (
...
@@ -559,7 +559,7 @@ CREATE TABLE ttest (
<para>
<para>
This is the source code of the trigger function:
This is the source code of the trigger function:
<programlisting>
<programlisting>
<![CDATA[
#include "postgres.h"
#include "postgres.h"
#include "executor/spi.h" /* this is what you need to work with SPI */
#include "executor/spi.h" /* this is what you need to work with SPI */
#include "commands/trigger.h" /* ... and triggers */
#include "commands/trigger.h" /* ... and triggers */
...
@@ -571,7 +571,7 @@ PG_FUNCTION_INFO_V1(trigf);
...
@@ -571,7 +571,7 @@ PG_FUNCTION_INFO_V1(trigf);
Datum
Datum
trigf(PG_FUNCTION_ARGS)
trigf(PG_FUNCTION_ARGS)
{
{
TriggerData *trigdata = (TriggerData *) fcinfo-
>
context;
TriggerData *trigdata = (TriggerData *) fcinfo-
>
context;
TupleDesc tupdesc;
TupleDesc tupdesc;
HeapTuple rettuple;
HeapTuple rettuple;
char *when;
char *when;
...
@@ -584,38 +584,38 @@ trigf(PG_FUNCTION_ARGS)
...
@@ -584,38 +584,38 @@ trigf(PG_FUNCTION_ARGS)
elog(ERROR, "trigf: not called by trigger manager");
elog(ERROR, "trigf: not called by trigger manager");
/* tuple to return to executor */
/* tuple to return to executor */
if (TRIGGER_FIRED_BY_UPDATE(trigdata-
>
tg_event))
if (TRIGGER_FIRED_BY_UPDATE(trigdata-
>
tg_event))
rettuple = trigdata-
>
tg_newtuple;
rettuple = trigdata-
>
tg_newtuple;
else
else
rettuple = trigdata-
>
tg_trigtuple;
rettuple = trigdata-
>
tg_trigtuple;
/* check for null values */
/* check for null values */
if (!TRIGGER_FIRED_BY_DELETE(trigdata-
>
tg_event)
if (!TRIGGER_FIRED_BY_DELETE(trigdata-
>
tg_event)
&
amp;& TRIGGER_FIRED_BEFORE(trigdata->
tg_event))
&
& TRIGGER_FIRED_BEFORE(trigdata->
tg_event))
checknull = true;
checknull = true;
if (TRIGGER_FIRED_BEFORE(trigdata-
>
tg_event))
if (TRIGGER_FIRED_BEFORE(trigdata-
>
tg_event))
when = "before";
when = "before";
else
else
when = "after ";
when = "after ";
tupdesc = trigdata-
>tg_relation->
rd_att;
tupdesc = trigdata-
>tg_relation->
rd_att;
/* connect to SPI manager */
/* connect to SPI manager */
if ((ret = SPI_connect())
<
0)
if ((ret = SPI_connect())
<
0)
elog(INFO, "trigf (fired %s): SPI_connect returned %d", when, ret);
elog(INFO, "trigf (fired %s): SPI_connect returned %d", when, ret);
/* get number of rows in table */
/* get number of rows in table */
ret = SPI_exec("SELECT count(*) FROM ttest", 0);
ret = SPI_exec("SELECT count(*) FROM ttest", 0);
if (ret
<
0)
if (ret
<
0)
elog(NOTICE, "trigf (fired %s): SPI_exec returned %d", when, ret);
elog(NOTICE, "trigf (fired %s): SPI_exec returned %d", when, ret);
/* count(*) returns int8, so be careful to convert */
/* count(*) returns int8, so be careful to convert */
i = DatumGetInt64(SPI_getbinval(SPI_tuptable-
>
vals[0],
i = DatumGetInt64(SPI_getbinval(SPI_tuptable-
>
vals[0],
SPI_tuptable-
>
tupdesc,
SPI_tuptable-
>
tupdesc,
1,
1,
&
amp;
isnull));
&isnull));
elog (INFO, "trigf (fired %s): there are %d rows in ttest", when, i);
elog (INFO, "trigf (fired %s): there are %d rows in ttest", when, i);
...
@@ -623,13 +623,14 @@ trigf(PG_FUNCTION_ARGS)
...
@@ -623,13 +623,14 @@ trigf(PG_FUNCTION_ARGS)
if (checknull)
if (checknull)
{
{
SPI_getbinval(rettuple, tupdesc, 1, &
amp;
isnull);
SPI_getbinval(rettuple, tupdesc, 1, &isnull);
if (isnull)
if (isnull)
rettuple = NULL;
rettuple = NULL;
}
}
return PointerGetDatum(rettuple);
return PointerGetDatum(rettuple);
}
}
]]>
</programlisting>
</programlisting>
</para>
</para>
...
...
doc/src/sgml/xfunc.sgml
View file @
aa7f0046
<!-- $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.13
4 2008/12/04 17:51:26 pete
re Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/xfunc.sgml,v 1.13
5 2008/12/07 23:46:39 alvher
re Exp $ -->
<sect1 id="xfunc">
<sect1 id="xfunc">
<title>User-Defined Functions</title>
<title>User-Defined Functions</title>
...
@@ -1621,15 +1621,16 @@ typedef struct {
...
@@ -1621,15 +1621,16 @@ typedef struct {
For example, if we wanted to store 40 bytes in a <structname>text</>
For example, if we wanted to store 40 bytes in a <structname>text</>
structure, we might use a code fragment like this:
structure, we might use a code fragment like this:
<programlisting>
<programlisting>
<![CDATA[
#include "postgres.h"
#include "postgres.h"
...
...
char buffer[40]; /* our source data */
char buffer[40]; /* our source data */
...
...
text *destination = (text *) palloc(VARHDRSZ + 40);
text *destination = (text *) palloc(VARHDRSZ + 40);
destination-
>
length = VARHDRSZ + 40;
destination-
>
length = VARHDRSZ + 40;
memcpy(destination-
>
data, buffer, 40);
memcpy(destination-
>
data, buffer, 40);
...
...
]]>
</programlisting>
</programlisting>
<literal>VARHDRSZ</> is the same as <literal>sizeof(int4)</>, but
<literal>VARHDRSZ</> is the same as <literal>sizeof(int4)</>, but
...
@@ -1842,9 +1843,9 @@ memcpy(destination->data, buffer, 40);
...
@@ -1842,9 +1843,9 @@ memcpy(destination->data, buffer, 40);
<para>
<para>
Here are some examples:
Here are some examples:
<programlisting>
<programlisting>
<![CDATA[
#include "postgres.h"
#include "postgres.h"
#include
<string.h>
#include
<string.h>
/* by value */
/* by value */
...
@@ -1871,8 +1872,8 @@ makepoint(Point *pointx, Point *pointy)
...
@@ -1871,8 +1872,8 @@ makepoint(Point *pointx, Point *pointy)
{
{
Point *new_point = (Point *) palloc(sizeof(Point));
Point *new_point = (Point *) palloc(sizeof(Point));
new_point-
>x = pointx->
x;
new_point-
>x = pointx->
x;
new_point-
>y = pointy->
y;
new_point-
>y = pointy->
y;
return new_point;
return new_point;
}
}
...
@@ -1908,6 +1909,7 @@ concat_text(text *arg1, text *arg2)
...
@@ -1908,6 +1909,7 @@ concat_text(text *arg1, text *arg2)
VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ);
VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ);
return new_text;
return new_text;
}
}
]]>
</programlisting>
</programlisting>
</para>
</para>
...
@@ -2014,9 +2016,9 @@ PG_FUNCTION_INFO_V1(funcname);
...
@@ -2014,9 +2016,9 @@ PG_FUNCTION_INFO_V1(funcname);
<para>
<para>
Here we show the same functions as above, coded in version-1 style:
Here we show the same functions as above, coded in version-1 style:
<programlisting>
<programlisting>
<![CDATA[
#include "postgres.h"
#include "postgres.h"
#include
<string.h>
#include
<string.h>
#include "fmgr.h"
#include "fmgr.h"
/* by value */
/* by value */
...
@@ -2054,8 +2056,8 @@ makepoint(PG_FUNCTION_ARGS)
...
@@ -2054,8 +2056,8 @@ makepoint(PG_FUNCTION_ARGS)
Point *pointy = PG_GETARG_POINT_P(1);
Point *pointy = PG_GETARG_POINT_P(1);
Point *new_point = (Point *) palloc(sizeof(Point));
Point *new_point = (Point *) palloc(sizeof(Point));
new_point-
>x = pointx->
x;
new_point-
>x = pointx->
x;
new_point-
>y = pointy->
y;
new_point-
>y = pointy->
y;
PG_RETURN_POINT_P(new_point);
PG_RETURN_POINT_P(new_point);
}
}
...
@@ -2098,6 +2100,7 @@ concat_text(PG_FUNCTION_ARGS)
...
@@ -2098,6 +2100,7 @@ concat_text(PG_FUNCTION_ARGS)
VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ);
VARDATA(arg2), VARSIZE(arg2) - VARHDRSZ);
PG_RETURN_TEXT_P(new_text);
PG_RETURN_TEXT_P(new_text);
}
}
]]>
</programlisting>
</programlisting>
</para>
</para>
...
@@ -2552,7 +2555,7 @@ SELECT name, c_overpaid(emp, 1500) AS overpaid
...
@@ -2552,7 +2555,7 @@ SELECT name, c_overpaid(emp, 1500) AS overpaid
Using call conventions version 0, we can define
Using call conventions version 0, we can define
<function>c_overpaid</> as:
<function>c_overpaid</> as:
<programlisting>
<programlisting>
<![CDATA[
#include "postgres.h"
#include "postgres.h"
#include "executor/executor.h" /* for GetAttributeByName() */
#include "executor/executor.h" /* for GetAttributeByName() */
...
@@ -2563,16 +2566,17 @@ c_overpaid(HeapTupleHeader t, /* the current row of emp */
...
@@ -2563,16 +2566,17 @@ c_overpaid(HeapTupleHeader t, /* the current row of emp */
bool isnull;
bool isnull;
int32 salary;
int32 salary;
salary = DatumGetInt32(GetAttributeByName(t, "salary", &
amp;
isnull));
salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull));
if (isnull)
if (isnull)
return false;
return false;
return salary
>
limit;
return salary
>
limit;
}
}
]]>
</programlisting>
</programlisting>
In version-1 coding, the above would look like this:
In version-1 coding, the above would look like this:
<programlisting>
<programlisting>
<![CDATA[
#include "postgres.h"
#include "postgres.h"
#include "executor/executor.h" /* for GetAttributeByName() */
#include "executor/executor.h" /* for GetAttributeByName() */
...
@@ -2586,13 +2590,14 @@ c_overpaid(PG_FUNCTION_ARGS)
...
@@ -2586,13 +2590,14 @@ c_overpaid(PG_FUNCTION_ARGS)
bool isnull;
bool isnull;
Datum salary;
Datum salary;
salary = GetAttributeByName(t, "salary", &
amp;
isnull);
salary = GetAttributeByName(t, "salary", &isnull);
if (isnull)
if (isnull)
PG_RETURN_BOOL(false);
PG_RETURN_BOOL(false);
/* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */
/* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */
PG_RETURN_BOOL(DatumGetInt32(salary)
>
limit);
PG_RETURN_BOOL(DatumGetInt32(salary)
>
limit);
}
}
]]>
</programlisting>
</programlisting>
</para>
</para>
...
@@ -2974,7 +2979,7 @@ my_set_returning_function(PG_FUNCTION_ARGS)
...
@@ -2974,7 +2979,7 @@ my_set_returning_function(PG_FUNCTION_ARGS)
<para>
<para>
A complete example of a simple <acronym>SRF</> returning a composite type
A complete example of a simple <acronym>SRF</> returning a composite type
looks like:
looks like:
<programlisting>
<programlisting>
<![CDATA[
PG_FUNCTION_INFO_V1(retcomposite);
PG_FUNCTION_INFO_V1(retcomposite);
Datum
Datum
...
@@ -2995,13 +3000,13 @@ retcomposite(PG_FUNCTION_ARGS)
...
@@ -2995,13 +3000,13 @@ retcomposite(PG_FUNCTION_ARGS)
funcctx = SRF_FIRSTCALL_INIT();
funcctx = SRF_FIRSTCALL_INIT();
/* switch to memory context appropriate for multiple function calls */
/* switch to memory context appropriate for multiple function calls */
oldcontext = MemoryContextSwitchTo(funcctx-
>
multi_call_memory_ctx);
oldcontext = MemoryContextSwitchTo(funcctx-
>
multi_call_memory_ctx);
/* total number of tuples to be returned */
/* total number of tuples to be returned */
funcctx-
>
max_calls = PG_GETARG_UINT32(0);
funcctx-
>
max_calls = PG_GETARG_UINT32(0);
/* Build a tuple descriptor for our result type */
/* Build a tuple descriptor for our result type */
if (get_call_result_type(fcinfo, NULL, &
amp;
tupdesc) != TYPEFUNC_COMPOSITE)
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
ereport(ERROR,
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("function returning record called in context "
errmsg("function returning record called in context "
...
@@ -3012,7 +3017,7 @@ retcomposite(PG_FUNCTION_ARGS)
...
@@ -3012,7 +3017,7 @@ retcomposite(PG_FUNCTION_ARGS)
* C strings
* C strings
*/
*/
attinmeta = TupleDescGetAttInMetadata(tupdesc);
attinmeta = TupleDescGetAttInMetadata(tupdesc);
funcctx-
>
attinmeta = attinmeta;
funcctx-
>
attinmeta = attinmeta;
MemoryContextSwitchTo(oldcontext);
MemoryContextSwitchTo(oldcontext);
}
}
...
@@ -3020,11 +3025,11 @@ retcomposite(PG_FUNCTION_ARGS)
...
@@ -3020,11 +3025,11 @@ retcomposite(PG_FUNCTION_ARGS)
/* stuff done on every call of the function */
/* stuff done on every call of the function */
funcctx = SRF_PERCALL_SETUP();
funcctx = SRF_PERCALL_SETUP();
call_cntr = funcctx-
>
call_cntr;
call_cntr = funcctx-
>
call_cntr;
max_calls = funcctx-
>
max_calls;
max_calls = funcctx-
>
max_calls;
attinmeta = funcctx-
>
attinmeta;
attinmeta = funcctx-
>
attinmeta;
if (call_cntr
<
max_calls) /* do when there is more left to send */
if (call_cntr
<
max_calls) /* do when there is more left to send */
{
{
char **values;
char **values;
HeapTuple tuple;
HeapTuple tuple;
...
@@ -3063,6 +3068,7 @@ retcomposite(PG_FUNCTION_ARGS)
...
@@ -3063,6 +3068,7 @@ retcomposite(PG_FUNCTION_ARGS)
SRF_RETURN_DONE(funcctx);
SRF_RETURN_DONE(funcctx);
}
}
}
}
]]>
</programlisting>
</programlisting>
One way to declare this function in SQL is:
One way to declare this function in SQL is:
...
...
doc/src/sgml/xindex.sgml
View file @
aa7f0046
<!-- $PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.6
3 2008/05/16 16:31:01 tgl
Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/xindex.sgml,v 1.6
4 2008/12/07 23:46:39 alvherre
Exp $ -->
<sect1 id="xindex">
<sect1 id="xindex">
<title>Interfacing Extensions To Indexes</title>
<title>Interfacing Extensions To Indexes</title>
...
@@ -499,8 +499,8 @@
...
@@ -499,8 +499,8 @@
reduces the odds of getting inconsistent results for corner cases.
reduces the odds of getting inconsistent results for corner cases.
Following this approach, we first write:
Following this approach, we first write:
<programlisting>
<programlisting>
<![CDATA[
#define Mag(c) ((c)-
>x*(c)->x + (c)->y*(c)->
y)
#define Mag(c) ((c)-
>x*(c)->x + (c)->y*(c)->
y)
static int
static int
complex_abs_cmp_internal(Complex *a, Complex *b)
complex_abs_cmp_internal(Complex *a, Complex *b)
...
@@ -508,17 +508,18 @@ complex_abs_cmp_internal(Complex *a, Complex *b)
...
@@ -508,17 +508,18 @@ complex_abs_cmp_internal(Complex *a, Complex *b)
double amag = Mag(a),
double amag = Mag(a),
bmag = Mag(b);
bmag = Mag(b);
if (amag
<
bmag)
if (amag
<
bmag)
return -1;
return -1;
if (amag
>
bmag)
if (amag
>
bmag)
return 1;
return 1;
return 0;
return 0;
}
}
]]>
</programlisting>
</programlisting>
Now the less-than function looks like:
Now the less-than function looks like:
<programlisting>
<programlisting>
<![CDATA[
PG_FUNCTION_INFO_V1(complex_abs_lt);
PG_FUNCTION_INFO_V1(complex_abs_lt);
Datum
Datum
...
@@ -527,8 +528,9 @@ complex_abs_lt(PG_FUNCTION_ARGS)
...
@@ -527,8 +528,9 @@ complex_abs_lt(PG_FUNCTION_ARGS)
Complex *a = (Complex *) PG_GETARG_POINTER(0);
Complex *a = (Complex *) PG_GETARG_POINTER(0);
Complex *b = (Complex *) PG_GETARG_POINTER(1);
Complex *b = (Complex *) PG_GETARG_POINTER(1);
PG_RETURN_BOOL(complex_abs_cmp_internal(a, b)
<
0);
PG_RETURN_BOOL(complex_abs_cmp_internal(a, b)
<
0);
}
}
]]>
</programlisting>
</programlisting>
The other four functions differ only in how they compare the internal
The other four functions differ only in how they compare the internal
...
@@ -617,15 +619,16 @@ CREATE FUNCTION complex_abs_cmp(complex, complex)
...
@@ -617,15 +619,16 @@ CREATE FUNCTION complex_abs_cmp(complex, complex)
Now that we have the required operators and support routine,
Now that we have the required operators and support routine,
we can finally create the operator class:
we can finally create the operator class:
<programlisting>
<programlisting>
<![CDATA[
CREATE OPERATOR CLASS complex_abs_ops
CREATE OPERATOR CLASS complex_abs_ops
DEFAULT FOR TYPE complex USING btree AS
DEFAULT FOR TYPE complex USING btree AS
OPERATOR 1
<
,
OPERATOR 1
<
,
OPERATOR 2
<
= ,
OPERATOR 2
<
= ,
OPERATOR 3 = ,
OPERATOR 3 = ,
OPERATOR 4
>
= ,
OPERATOR 4
>
= ,
OPERATOR 5
>
,
OPERATOR 5
>
,
FUNCTION 1 complex_abs_cmp(complex, complex);
FUNCTION 1 complex_abs_cmp(complex, complex);
]]>
</programlisting>
</programlisting>
</para>
</para>
...
@@ -708,87 +711,88 @@ CREATE OPERATOR CLASS complex_abs_ops
...
@@ -708,87 +711,88 @@ CREATE OPERATOR CLASS complex_abs_ops
on one of these types can be searched using a comparison value of another
on one of these types can be searched using a comparison value of another
type. The family could be duplicated by these definitions:
type. The family could be duplicated by these definitions:
<programlisting>
<programlisting>
<![CDATA[
CREATE OPERATOR FAMILY integer_ops USING btree;
CREATE OPERATOR FAMILY integer_ops USING btree;
CREATE OPERATOR CLASS int8_ops
CREATE OPERATOR CLASS int8_ops
DEFAULT FOR TYPE int8 USING btree FAMILY integer_ops AS
DEFAULT FOR TYPE int8 USING btree FAMILY integer_ops AS
-- standard int8 comparisons
-- standard int8 comparisons
OPERATOR 1
<
,
OPERATOR 1
<
,
OPERATOR 2
<
= ,
OPERATOR 2
<
= ,
OPERATOR 3 = ,
OPERATOR 3 = ,
OPERATOR 4
>
= ,
OPERATOR 4
>
= ,
OPERATOR 5
>
,
OPERATOR 5
>
,
FUNCTION 1 btint8cmp(int8, int8) ;
FUNCTION 1 btint8cmp(int8, int8) ;
CREATE OPERATOR CLASS int4_ops
CREATE OPERATOR CLASS int4_ops
DEFAULT FOR TYPE int4 USING btree FAMILY integer_ops AS
DEFAULT FOR TYPE int4 USING btree FAMILY integer_ops AS
-- standard int4 comparisons
-- standard int4 comparisons
OPERATOR 1
<
,
OPERATOR 1
<
,
OPERATOR 2
<
= ,
OPERATOR 2
<
= ,
OPERATOR 3 = ,
OPERATOR 3 = ,
OPERATOR 4
>
= ,
OPERATOR 4
>
= ,
OPERATOR 5
>
,
OPERATOR 5
>
,
FUNCTION 1 btint4cmp(int4, int4) ;
FUNCTION 1 btint4cmp(int4, int4) ;
CREATE OPERATOR CLASS int2_ops
CREATE OPERATOR CLASS int2_ops
DEFAULT FOR TYPE int2 USING btree FAMILY integer_ops AS
DEFAULT FOR TYPE int2 USING btree FAMILY integer_ops AS
-- standard int2 comparisons
-- standard int2 comparisons
OPERATOR 1
<
,
OPERATOR 1
<
,
OPERATOR 2
<
= ,
OPERATOR 2
<
= ,
OPERATOR 3 = ,
OPERATOR 3 = ,
OPERATOR 4
>
= ,
OPERATOR 4
>
= ,
OPERATOR 5
>
,
OPERATOR 5
>
,
FUNCTION 1 btint2cmp(int2, int2) ;
FUNCTION 1 btint2cmp(int2, int2) ;
ALTER OPERATOR FAMILY integer_ops USING btree ADD
ALTER OPERATOR FAMILY integer_ops USING btree ADD
-- cross-type comparisons int8 vs int2
-- cross-type comparisons int8 vs int2
OPERATOR 1
<
(int8, int2) ,
OPERATOR 1
<
(int8, int2) ,
OPERATOR 2
<
= (int8, int2) ,
OPERATOR 2
<
= (int8, int2) ,
OPERATOR 3 = (int8, int2) ,
OPERATOR 3 = (int8, int2) ,
OPERATOR 4
>
= (int8, int2) ,
OPERATOR 4
>
= (int8, int2) ,
OPERATOR 5
>
(int8, int2) ,
OPERATOR 5
>
(int8, int2) ,
FUNCTION 1 btint82cmp(int8, int2) ,
FUNCTION 1 btint82cmp(int8, int2) ,
-- cross-type comparisons int8 vs int4
-- cross-type comparisons int8 vs int4
OPERATOR 1
<
(int8, int4) ,
OPERATOR 1
<
(int8, int4) ,
OPERATOR 2
<
= (int8, int4) ,
OPERATOR 2
<
= (int8, int4) ,
OPERATOR 3 = (int8, int4) ,
OPERATOR 3 = (int8, int4) ,
OPERATOR 4
>
= (int8, int4) ,
OPERATOR 4
>
= (int8, int4) ,
OPERATOR 5
>
(int8, int4) ,
OPERATOR 5
>
(int8, int4) ,
FUNCTION 1 btint84cmp(int8, int4) ,
FUNCTION 1 btint84cmp(int8, int4) ,
-- cross-type comparisons int4 vs int2
-- cross-type comparisons int4 vs int2
OPERATOR 1
<
(int4, int2) ,
OPERATOR 1
<
(int4, int2) ,
OPERATOR 2
<
= (int4, int2) ,
OPERATOR 2
<
= (int4, int2) ,
OPERATOR 3 = (int4, int2) ,
OPERATOR 3 = (int4, int2) ,
OPERATOR 4
>
= (int4, int2) ,
OPERATOR 4
>
= (int4, int2) ,
OPERATOR 5
>
(int4, int2) ,
OPERATOR 5
>
(int4, int2) ,
FUNCTION 1 btint42cmp(int4, int2) ,
FUNCTION 1 btint42cmp(int4, int2) ,
-- cross-type comparisons int4 vs int8
-- cross-type comparisons int4 vs int8
OPERATOR 1
<
(int4, int8) ,
OPERATOR 1
<
(int4, int8) ,
OPERATOR 2
<
= (int4, int8) ,
OPERATOR 2
<
= (int4, int8) ,
OPERATOR 3 = (int4, int8) ,
OPERATOR 3 = (int4, int8) ,
OPERATOR 4
>
= (int4, int8) ,
OPERATOR 4
>
= (int4, int8) ,
OPERATOR 5
>
(int4, int8) ,
OPERATOR 5
>
(int4, int8) ,
FUNCTION 1 btint48cmp(int4, int8) ,
FUNCTION 1 btint48cmp(int4, int8) ,
-- cross-type comparisons int2 vs int8
-- cross-type comparisons int2 vs int8
OPERATOR 1
<
(int2, int8) ,
OPERATOR 1
<
(int2, int8) ,
OPERATOR 2
<
= (int2, int8) ,
OPERATOR 2
<
= (int2, int8) ,
OPERATOR 3 = (int2, int8) ,
OPERATOR 3 = (int2, int8) ,
OPERATOR 4
>
= (int2, int8) ,
OPERATOR 4
>
= (int2, int8) ,
OPERATOR 5
>
(int2, int8) ,
OPERATOR 5
>
(int2, int8) ,
FUNCTION 1 btint28cmp(int2, int8) ,
FUNCTION 1 btint28cmp(int2, int8) ,
-- cross-type comparisons int2 vs int4
-- cross-type comparisons int2 vs int4
OPERATOR 1
<
(int2, int4) ,
OPERATOR 1
<
(int2, int4) ,
OPERATOR 2
<
= (int2, int4) ,
OPERATOR 2
<
= (int2, int4) ,
OPERATOR 3 = (int2, int4) ,
OPERATOR 3 = (int2, int4) ,
OPERATOR 4
>
= (int2, int4) ,
OPERATOR 4
>
= (int2, int4) ,
OPERATOR 5
>
(int2, int4) ,
OPERATOR 5
>
(int2, int4) ,
FUNCTION 1 btint24cmp(int2, int4) ;
FUNCTION 1 btint24cmp(int2, int4) ;
]]>
</programlisting>
</programlisting>
Notice that this definition <quote>overloads</> the operator strategy and
Notice that this definition <quote>overloads</> the operator strategy and
...
...
doc/src/sgml/xtypes.sgml
View file @
aa7f0046
<!-- $PostgreSQL: pgsql/doc/src/sgml/xtypes.sgml,v 1.3
0 2008/02/23 19:11:45 tgl
Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/xtypes.sgml,v 1.3
1 2008/12/07 23:46:39 alvherre
Exp $ -->
<sect1 id="xtypes">
<sect1 id="xtypes">
<title>User-Defined Types</title>
<title>User-Defined Types</title>
...
@@ -75,7 +75,7 @@ typedef struct Complex {
...
@@ -75,7 +75,7 @@ typedef struct Complex {
write a complete and robust parser for that representation as your
write a complete and robust parser for that representation as your
input function. For instance:
input function. For instance:
<programlisting>
<programlisting>
<![CDATA[
PG_FUNCTION_INFO_V1(complex_in);
PG_FUNCTION_INFO_V1(complex_in);
Datum
Datum
...
@@ -86,22 +86,23 @@ complex_in(PG_FUNCTION_ARGS)
...
@@ -86,22 +86,23 @@ complex_in(PG_FUNCTION_ARGS)
y;
y;
Complex *result;
Complex *result;
if (sscanf(str, " ( %lf , %lf )", &
amp;x, &
y) != 2)
if (sscanf(str, " ( %lf , %lf )", &
x, &
y) != 2)
ereport(ERROR,
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for complex: \"%s\"",
errmsg("invalid input syntax for complex: \"%s\"",
str)));
str)));
result = (Complex *) palloc(sizeof(Complex));
result = (Complex *) palloc(sizeof(Complex));
result-
>
x = x;
result-
>
x = x;
result-
>
y = y;
result-
>
y = y;
PG_RETURN_POINTER(result);
PG_RETURN_POINTER(result);
}
}
]]>
</programlisting>
</programlisting>
The output function can simply be:
The output function can simply be:
<programlisting>
<programlisting>
<![CDATA[
PG_FUNCTION_INFO_V1(complex_out);
PG_FUNCTION_INFO_V1(complex_out);
Datum
Datum
...
@@ -111,9 +112,10 @@ complex_out(PG_FUNCTION_ARGS)
...
@@ -111,9 +112,10 @@ complex_out(PG_FUNCTION_ARGS)
char *result;
char *result;
result = (char *) palloc(100);
result = (char *) palloc(100);
snprintf(result, 100, "(%g,%g)", complex-
>x, complex->
y);
snprintf(result, 100, "(%g,%g)", complex-
>x, complex->
y);
PG_RETURN_CSTRING(result);
PG_RETURN_CSTRING(result);
}
}
]]>
</programlisting>
</programlisting>
</para>
</para>
...
@@ -134,7 +136,7 @@ complex_out(PG_FUNCTION_ARGS)
...
@@ -134,7 +136,7 @@ complex_out(PG_FUNCTION_ARGS)
<type>complex</type>, we will piggy-back on the binary I/O converters
<type>complex</type>, we will piggy-back on the binary I/O converters
for type <type>float8</>:
for type <type>float8</>:
<programlisting>
<programlisting>
<![CDATA[
PG_FUNCTION_INFO_V1(complex_recv);
PG_FUNCTION_INFO_V1(complex_recv);
Datum
Datum
...
@@ -144,8 +146,8 @@ complex_recv(PG_FUNCTION_ARGS)
...
@@ -144,8 +146,8 @@ complex_recv(PG_FUNCTION_ARGS)
Complex *result;
Complex *result;
result = (Complex *) palloc(sizeof(Complex));
result = (Complex *) palloc(sizeof(Complex));
result-
>
x = pq_getmsgfloat8(buf);
result-
>
x = pq_getmsgfloat8(buf);
result-
>
y = pq_getmsgfloat8(buf);
result-
>
y = pq_getmsgfloat8(buf);
PG_RETURN_POINTER(result);
PG_RETURN_POINTER(result);
}
}
...
@@ -157,11 +159,12 @@ complex_send(PG_FUNCTION_ARGS)
...
@@ -157,11 +159,12 @@ complex_send(PG_FUNCTION_ARGS)
Complex *complex = (Complex *) PG_GETARG_POINTER(0);
Complex *complex = (Complex *) PG_GETARG_POINTER(0);
StringInfoData buf;
StringInfoData buf;
pq_begintypsend(&
amp;
buf);
pq_begintypsend(&buf);
pq_sendfloat8(&
amp;buf, complex->
x);
pq_sendfloat8(&
buf, complex->
x);
pq_sendfloat8(&
amp;buf, complex->
y);
pq_sendfloat8(&
buf, complex->
y);
PG_RETURN_BYTEA_P(pq_endtypsend(&
amp;
buf));
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
}
]]>
</programlisting>
</programlisting>
</para>
</para>
...
...
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