libpq-binary-format-doc-v0.patch

text/plain

Filename: libpq-binary-format-doc-v0.patch
Type: text/plain
Part: 0
Message: Re: real/float example for testlibpq3

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch v0
File+
doc/src/sgml/libpq.sgml 103 0
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 37ec3cb4e5..44c60223ee 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -8874,6 +8874,109 @@ int PQisthreadsafe();
   </para>
  </sect1>
 
+ <sect1 id="libpq-binary-format">
+  <title>Binary Format</title>
+  <para>
+    Various <application>libpq</application> functions support sending or
+    receiving data in binary format.  Data in binary format requires the
+    application to be handle any differences between the system and the network
+    byte order.
+  </para>
+
+  <para>
+    <xref linkend="libpq-example-3"/> demonstrates how to write a complete
+    program that uses <application>libpq</application> functions that request
+    data in binary foramt.  This example shows how to handle only a few data
+    types.  This section will detail the handling of as many of the data types
+    as possible.  See <xref linkend="datatype"/> for descriptions of each of the
+    built-in data types.
+  </para>
+
+  <sect2 id="libpq-binary-boolean">
+   <title><type>boolean</type></title>
+    <para>
+       A <type>boolean</type> is transmitted as single byte that, when cast to
+       an <literal>int</literal>, will be <literal>0</literal> for
+       <literal>false</literal> and <literal>1</literal> for
+       <literal>true</literal>.
+    </para>
+<programlisting>
+<![CDATA[
+int         value;
+
+ptr = PQgetvalue(res, row_number, column_number);
+value = (int) *ptr;
+printf("%d\n", value);
+]]>
+</programlisting>
+  </sect2>
+
+  <sect2 id="libpq-binary-real">
+   <title><type>real</type></title>
+    <para>
+      A <type>real</type> is composed of 4 bytes and needs to be handled
+      correctly for byte order.
+    </para>
+<programlisting>
+<![CDATA[
+union {
+    int     i;
+    float   f;
+}           value;
+
+ptr = PQgetvalue(res, row_number, column_number);
+val.i = ntohl(*((uint32_t *) ptr));
+printf("%f\n", value.f);
+]]>
+</programlisting>
+  </sect2>
+
+  <sect2 id="libpq-binary-timestamp-without-time-zone">
+   <title><type>timestamp without time zone</type></title>
+    <para>
+      A <type>timestamp without time zone</type> is a 64-bit data type
+      representing the number of microseconds since January 1, 2000.  It can be
+      converted into a broken-down time representation by converting the time
+      into seconds and saving the microseconds elsewhere.
+    </para>
+    <para>
+      Note that in C time is counted from January 1, 1970 so this discrepency
+      needs to be accounted for in addition to handling the network byte order.
+    </para>
+<programlisting>
+<![CDATA[
+#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
+#define UNIX_EPOCH_JDATE 2440588 /* == date2j(1970, 1, 1) */
+#define SECS_PER_DAY 86400
+
+uint64_t    value;
+
+struct tm  *tm;
+time_t      timep;
+uint32_t    mantissa;
+
+ptr = PQgetvalue(res, column_number, row_number);
+/* Note ntohll() is not implemented on all platforms. */
+val = ntohll(*((uint64_t *) ptr));
+
+timep = val / (uint64_t) 1000000 +
+        (uint64_t) (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) *
+        (uint64_t) SECS_PER_DAY;
+mantissa = val - (uint64_t) (timep -
+        (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY) *
+        (uint64_t) 1000000;
+
+/* Assume and print timestamps in GMT for simplicity. */
+tm = gmtime(&timep);
+
+printf("%04d-%02d-%02d %02d:%02d:%02d.%06d\n",
+        tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
+        tm->tm_min, tm->tm_sec, mantissa);
+]]>
+</programlisting>
+  </sect2>
+
+ </sect1>
 
  <sect1 id="libpq-build">
   <title>Building <application>libpq</application> Programs</title>