Skip to content

Commit ed63a4d

Browse files
markwkmhackorum
authored andcommitted
doc: Add binary data format descriptions
Create a new chapter called "Binary Format of Data Types", describing how the native data types are represented in binary format. Remove testlibpq3, which had a few code examples. Discussion: https://postgr.es/m/Yqu1MmYGrOQLsD7D%40workstation-mark-wong
1 parent 44056f6 commit ed63a4d

10 files changed

Lines changed: 981 additions & 478 deletions

File tree

doc/src/sgml/binary-format.sgml

Lines changed: 970 additions & 0 deletions
Large diffs are not rendered by default.

doc/src/sgml/datatype.sgml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@
2828
but are not listed here.
2929
</para>
3030

31+
<para>
32+
For the binary (as opposed to textual) on-the-wire representation of
33+
these types, used when transmitting values in binary format, see
34+
<xref linkend="binary-format"/>.
35+
</para>
36+
3137
<table id="datatype-table">
3238
<title>Data Types</title>
3339
<tgroup cols="3">

doc/src/sgml/filelist.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
<!ENTITY ecpg SYSTEM "ecpg.sgml">
6060
<!ENTITY extend SYSTEM "extend.sgml">
6161
<!ENTITY external-projects SYSTEM "external-projects.sgml">
62+
<!ENTITY binaryformat SYSTEM "binary-format.sgml">
6263
<!ENTITY func-ref SYSTEM "func-ref.sgml">
6364
<!ENTITY infoschema SYSTEM "information_schema.sgml">
6465
<!ENTITY libpq SYSTEM "libpq.sgml">

doc/src/sgml/libpq.sgml

Lines changed: 0 additions & 239 deletions
Original file line numberDiff line numberDiff line change
@@ -11290,245 +11290,6 @@ main(int argc, char **argv)
1129011290
return 0;
1129111291
}
1129211292
]]>
11293-
</programlisting>
11294-
</example>
11295-
11296-
<example id="libpq-example-3">
11297-
<title><application>libpq</application> Example Program 3</title>
11298-
11299-
<programlisting>
11300-
<![CDATA[
11301-
/*
11302-
* src/test/examples/testlibpq3.c
11303-
*
11304-
*
11305-
* testlibpq3.c
11306-
* Test out-of-line parameters and binary I/O.
11307-
*
11308-
* Before running this, populate a database with the following commands
11309-
* (provided in src/test/examples/testlibpq3.sql):
11310-
*
11311-
* CREATE SCHEMA testlibpq3;
11312-
* SET search_path = testlibpq3;
11313-
* CREATE TABLE test1 (i int4, t text, b bytea);
11314-
* INSERT INTO test1 values (1, 'joe''s place', '\000\001\002\003\004');
11315-
* INSERT INTO test1 values (2, 'ho there', '\004\003\002\001\000');
11316-
*
11317-
* The expected output is:
11318-
*
11319-
* tuple 0: got
11320-
* i = (4 bytes) 1
11321-
* t = (11 bytes) 'joe's place'
11322-
* b = (5 bytes) \000\001\002\003\004
11323-
*
11324-
* tuple 0: got
11325-
* i = (4 bytes) 2
11326-
* t = (8 bytes) 'ho there'
11327-
* b = (5 bytes) \004\003\002\001\000
11328-
*/
11329-
11330-
#ifdef WIN32
11331-
#include <windows.h>
11332-
#endif
11333-
11334-
#include <stdio.h>
11335-
#include <stdlib.h>
11336-
#include <stdint.h>
11337-
#include <string.h>
11338-
#include <sys/types.h>
11339-
#include "libpq-fe.h"
11340-
11341-
/* for ntohl/htonl */
11342-
#include <netinet/in.h>
11343-
#include <arpa/inet.h>
11344-
11345-
11346-
static void
11347-
exit_nicely(PGconn *conn)
11348-
{
11349-
PQfinish(conn);
11350-
exit(1);
11351-
}
11352-
11353-
/*
11354-
* This function prints a query result that is a binary-format fetch from
11355-
* a table defined as in the comment above. We split it out because the
11356-
* main() function uses it twice.
11357-
*/
11358-
static void
11359-
show_binary_results(PGresult *res)
11360-
{
11361-
int i,
11362-
j;
11363-
int i_fnum,
11364-
t_fnum,
11365-
b_fnum;
11366-
11367-
/* Use PQfnumber to avoid assumptions about field order in result */
11368-
i_fnum = PQfnumber(res, "i");
11369-
t_fnum = PQfnumber(res, "t");
11370-
b_fnum = PQfnumber(res, "b");
11371-
11372-
for (i = 0; i < PQntuples(res); i++)
11373-
{
11374-
char *iptr;
11375-
char *tptr;
11376-
char *bptr;
11377-
int blen;
11378-
int ival;
11379-
11380-
/* Get the field values (we ignore possibility they are null!) */
11381-
iptr = PQgetvalue(res, i, i_fnum);
11382-
tptr = PQgetvalue(res, i, t_fnum);
11383-
bptr = PQgetvalue(res, i, b_fnum);
11384-
11385-
/*
11386-
* The binary representation of INT4 is in network byte order, which
11387-
* we'd better coerce to the local byte order.
11388-
*/
11389-
ival = ntohl(*((uint32_t *) iptr));
11390-
11391-
/*
11392-
* The binary representation of TEXT is, well, text, and since libpq
11393-
* was nice enough to append a zero byte to it, it'll work just fine
11394-
* as a C string.
11395-
*
11396-
* The binary representation of BYTEA is a bunch of bytes, which could
11397-
* include embedded nulls so we have to pay attention to field length.
11398-
*/
11399-
blen = PQgetlength(res, i, b_fnum);
11400-
11401-
printf("tuple %d: got\n", i);
11402-
printf(" i = (%d bytes) %d\n",
11403-
PQgetlength(res, i, i_fnum), ival);
11404-
printf(" t = (%d bytes) '%s'\n",
11405-
PQgetlength(res, i, t_fnum), tptr);
11406-
printf(" b = (%d bytes) ", blen);
11407-
for (j = 0; j < blen; j++)
11408-
printf("\\%03o", bptr[j]);
11409-
printf("\n\n");
11410-
}
11411-
}
11412-
11413-
int
11414-
main(int argc, char **argv)
11415-
{
11416-
const char *conninfo;
11417-
PGconn *conn;
11418-
PGresult *res;
11419-
const char *paramValues[1];
11420-
int paramLengths[1];
11421-
int paramFormats[1];
11422-
uint32_t binaryIntVal;
11423-
11424-
/*
11425-
* If the user supplies a parameter on the command line, use it as the
11426-
* conninfo string; otherwise default to setting dbname=postgres and using
11427-
* environment variables or defaults for all other connection parameters.
11428-
*/
11429-
if (argc > 1)
11430-
conninfo = argv[1];
11431-
else
11432-
conninfo = "dbname = postgres";
11433-
11434-
/* Make a connection to the database */
11435-
conn = PQconnectdb(conninfo);
11436-
11437-
/* Check to see that the backend connection was successfully made */
11438-
if (PQstatus(conn) != CONNECTION_OK)
11439-
{
11440-
fprintf(stderr, "%s", PQerrorMessage(conn));
11441-
exit_nicely(conn);
11442-
}
11443-
11444-
/* Set always-secure search path, so malicious users can't take control. */
11445-
res = PQexec(conn, "SET search_path = testlibpq3");
11446-
if (PQresultStatus(res) != PGRES_COMMAND_OK)
11447-
{
11448-
fprintf(stderr, "SET failed: %s", PQerrorMessage(conn));
11449-
PQclear(res);
11450-
exit_nicely(conn);
11451-
}
11452-
PQclear(res);
11453-
11454-
/*
11455-
* The point of this program is to illustrate use of PQexecParams() with
11456-
* out-of-line parameters, as well as binary transmission of data.
11457-
*
11458-
* This first example transmits the parameters as text, but receives the
11459-
* results in binary format. By using out-of-line parameters we can avoid
11460-
* a lot of tedious mucking about with quoting and escaping, even though
11461-
* the data is text. Notice how we don't have to do anything special with
11462-
* the quote mark in the parameter value.
11463-
*/
11464-
11465-
/* Here is our out-of-line parameter value */
11466-
paramValues[0] = "joe's place";
11467-
11468-
res = PQexecParams(conn,
11469-
"SELECT * FROM test1 WHERE t = $1",
11470-
1, /* one param */
11471-
NULL, /* let the backend deduce param type */
11472-
paramValues,
11473-
NULL, /* don't need param lengths since text */
11474-
NULL, /* default to all text params */
11475-
1); /* ask for binary results */
11476-
11477-
if (PQresultStatus(res) != PGRES_TUPLES_OK)
11478-
{
11479-
fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
11480-
PQclear(res);
11481-
exit_nicely(conn);
11482-
}
11483-
11484-
show_binary_results(res);
11485-
11486-
PQclear(res);
11487-
11488-
/*
11489-
* In this second example we transmit an integer parameter in binary form,
11490-
* and again retrieve the results in binary form.
11491-
*
11492-
* Although we tell PQexecParams we are letting the backend deduce
11493-
* parameter type, we really force the decision by casting the parameter
11494-
* symbol in the query text. This is a good safety measure when sending
11495-
* binary parameters.
11496-
*/
11497-
11498-
/* Convert integer value "2" to network byte order */
11499-
binaryIntVal = htonl((uint32_t) 2);
11500-
11501-
/* Set up parameter arrays for PQexecParams */
11502-
paramValues[0] = (char *) &binaryIntVal;
11503-
paramLengths[0] = sizeof(binaryIntVal);
11504-
paramFormats[0] = 1; /* binary */
11505-
11506-
res = PQexecParams(conn,
11507-
"SELECT * FROM test1 WHERE i = $1::int4",
11508-
1, /* one param */
11509-
NULL, /* let the backend deduce param type */
11510-
paramValues,
11511-
paramLengths,
11512-
paramFormats,
11513-
1); /* ask for binary results */
11514-
11515-
if (PQresultStatus(res) != PGRES_TUPLES_OK)
11516-
{
11517-
fprintf(stderr, "SELECT failed: %s", PQerrorMessage(conn));
11518-
PQclear(res);
11519-
exit_nicely(conn);
11520-
}
11521-
11522-
show_binary_results(res);
11523-
11524-
PQclear(res);
11525-
11526-
/* close the connection to the database and cleanup */
11527-
PQfinish(conn);
11528-
11529-
return 0;
11530-
}
11531-
]]>
1153211293
</programlisting>
1153311294
</example>
1153411295

doc/src/sgml/postgres.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ break is not needed in a wider output rendering.
191191
&lobj;
192192
&ecpg;
193193
&infoschema;
194+
&binaryformat;
194195

195196
</part>
196197

doc/src/sgml/protocol.sgml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,9 @@
181181

182182
<para>
183183
Binary representations for integers use network byte order (most
184-
significant byte first). For other data types consult the documentation
185-
or source code to learn about the binary representation. Keep in mind
184+
significant byte first). The binary representation of each built-in
185+
data type is documented in <xref linkend="binary-format"/>; for other
186+
types, consult the type's documentation or source code. Keep in mind
186187
that binary representations for complex data types might change across
187188
server versions; the text format is usually the more portable choice.
188189
</para>

src/test/examples/.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/testlibpq
22
/testlibpq2
3-
/testlibpq3
43
/testlibpq4
54
/testlo
65
/testlo64

src/test/examples/Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ LDFLAGS_INTERNAL += $(libpq_pgport)
1717
PROGS = \
1818
testlibpq \
1919
testlibpq2 \
20-
testlibpq3 \
2120
testlibpq4 \
2221
testlo \
2322
testlo64

0 commit comments

Comments
 (0)