Skip to content
Browse files

docs: move docs from www/documentation/head (#744)

* docs: move docs from www/documentation/head

Move documentation from www/documentation/head/ to pgjdbc/docs/

This makes easy to update the documentation when a change is
made to the driver.

[skip ci]

* update intro
  • Loading branch information
jorsol authored and davecramer committed Feb 7, 2017
1 parent 8437f6c commit 70e23c45c904ebded42ab1b5efc10d66f34ab68c
@@ -0,0 +1 @@
@@ -0,0 +1,77 @@
layout: default_docs
title: Using Java 8 Date and Time classes
header: Chapter 5. Using Java 8 Date and Time classes
resource: media
previoustitle: Creating and Modifying Database Objects
previous: ddl.html
nexttitle: Chapter 6. Calling Stored Functions
next: callproc.html

The PostgreSQL™ JDBC driver implements native support for the
[Java 8 Date and Time API](
(JSR-310) using JDBC 4.2.

<a name="8-date-time-supported-data-types"></a>
**Table 5.1. Supported escaped numeric functions**

<table summary="Supported data type" border="1">
<th>Java SE 8</th>

This is closely aligned with tables B-4 and B-5 of the JDBC 4.2 specification.
Note that `ZonedDateTime`, `Instant` and
`OffsetTime / TIME [ WITHOUT TIMEZONE ]` are not supported. Also note
that all `OffsetDateTime` will instances will have be in UTC (have offset 0).
This is because the backend stores them as UTC.

<a name="reading-example"></a>
**Example 5.5. Reading Java 8 Date and Time values using JDBC**

`Statement st = conn.createStatement();`
`ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE columnfoo = 500");`
`while (`
&nbsp;&nbsp;&nbsp;`System.out.print("Column 1 returned ");`
&nbsp;&nbsp;&nbsp;`LocalDate localDate = rs.getObject(1, LocalDate.class));`

For other data types simply pass other classes to `#getObject`.
Note that the Java data types needs to match the SQL data types in table 7.1.

<a name="writing-example"></a>
**Example 5.5. Writing Java 8 Date and Time values using JDBC**

`LocalDate localDate =;`
`PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");`
`st.setObject(1, localDate);`

@@ -0,0 +1,3 @@
name: PostgreSQL JDBC Driver HEAD documentation
markdown: kramdown
highlighter: rouge
@@ -0,0 +1,90 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">
<html xmlns="" lang="en" xml:lang="en" dir="ltr">
<title>{{ page.title }}</title>
<meta http-equiv="Content-Type" content="text/xhtml; charset=utf-8" />
<meta name="description" content="The official site for the PostgreSQL JDBC Driver" />
<meta name="copyright" content="The PostgreSQL Global Development Group" />

<style type="text/css" media="screen" title="Normal Text">@import url("{{ page.resource }}/css/docs.css");</style>

<link rel="shortcut icon" href="media/favicon.ico" />

<div id="docHeader">
<div id="docHeaderLogo">
<a href="" title="PostgreSQL"><img src="media/img/layout/hdr_left3a.png" alt="PostgreSQL" height="80" width="390" /></a>

<div id="docContainerWrap">
<div id="docContainer">
<div id="docContent">

<div class="NAVHEADER">
<table summary="Header navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<th colspan="3" valign="bottom" align="center">
<h2 class="TITLE">{{ page.header }}</h2>
<td valign="top" width="20%" align="left">
<a title="{{ page.previoustitle }}" href="{{ page.previous }}" accesskey="P">Prev</a>
<td valign="bottom" width="60%" align="center">&nbsp;</td>
<td valign="top" width="20%" align="right">
<a title="{{ page.nexttitle }}" href="{{ }}" accesskey="N">Next</a>
<hr class="c1" width="100%" />
</div> <!-- NAVHEADER -->

<div class="CHAPTER">
<h1>{{ page.title }}</h1>

{{ content }}

<div class="NAVFOOTER">
<hr class="c1" width="100%" />
<table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<td valign="top" width="33%" align="left">
<a href="{{ page.previous }}" accesskey="P">Prev</a>
<td valign="top" width="34%" align="center">
<a href="index.html" accesskey="H">Home</a>
<td valign="top" width="33%" align="right">
<a href="{{ }}" accesskey="N">Next</a>
<td valign="top" width="33%" align="left">{{ page.previoustitle }}</td>
<td valign="top" width="34%" align="center">&nbsp;</td>
<td valign="top" width="33%" align="right">{{ page.nexttitle }}</td>
</div> <!-- NAVFOOTER -->

</div> <!-- docContent -->

<div id="docComments"></div>

<div id="docFooter">
<a class="navFooter" href="">Privacy Policy</a> |
<a class="navFooter" href="">About PostgreSQL</a><br/>
Copyright &copy; 1996-{{ site.time | date: "%Y" }} The PostgreSQL Global Development Group
</div> <!-- pgFooter -->
</div> <!-- docContainer -->
</div> <!-- docContainer -->
@@ -0,0 +1,179 @@
layout: default_docs
title: Chapter 7. Storing Binary Data
header: Chapter 7. Storing Binary Data
resource: media
previoustitle: Chapter 6. Calling Stored Functions
previous: callproc.html
nexttitle: Chapter 8. JDBC escapes
next: escapes.html

PostgreSQL™ provides two distinct ways to store binary data. Binary data can be
stored in a table using the data type BYTEA or by using the Large Object feature
which stores the binary data in a separate table in a special format and refers
to that table by storing a value of type OID in your table.

In order to determine which method is appropriate you need to understand the
limitations of each method. The BYTEA data type is not well suited for storing
very large amounts of binary data. While a column of type BYTEA can hold up to
1 GB of binary data, it would require a huge amount of memory to process such a
large value. The Large Object method for storing binary data is better suited to
storing very large values, but it has its own limitations. Specifically deleting
a row that contains a Large Object reference does not delete the Large Object.
Deleting the Large Object is a separate operation that needs to be performed.
Large Objects also have some security issues since anyone connected to the
database can view and/or modify any Large Object, even if they don't have
permissions to view/update the row containing the Large Object reference.

Version 7.2 was the first release of the JDBC driver that supports the BYTEA
data type. The introduction of this functionality in 7.2 has introduced a change
in behavior as compared to previous releases. Since 7.2, the methods `getBytes()`,
`setBytes()`, `getBinaryStream()`, and `setBinaryStream()` operate on the BYTEA
data type. In 7.1 and earlier, these methods operated on the OID data type
associated with Large Objects. It is possible to revert the driver back to the
old 7.1 behavior by setting the property `compatible` on the `Connection` object
to the value `7.1`. More details on connection properties are available in the
section called [“Connection Parameters”](connect.html#connection-parameters).

To use the BYTEA data type you should simply use the `getBytes()`, `setBytes()`,
`getBinaryStream()`, or `setBinaryStream()` methods.

To use the Large Object functionality you can use either the `LargeObject` class
provided by the PostgreSQL™ JDBC driver, or by using the `getBLOB()` and `setBLOB()`

### Important

> You must access Large Objects within an SQL transaction block. You can start a
transaction block by calling `setAutoCommit(false)`.
[Example 7.1, “Processing Binary Data in JDBC”](binary-data.html#binary-data-example)
contains some examples on how to process binary data using the PostgreSQL™ JDBC

<a name="binary-data-example"></a>
***Example 7.1. Processing Binary Data in JDBC***

For example, suppose you have a table containing the file names of images and you
also want to store the image in a BYTEA column:

`CREATE TABLE images (imgname text, img bytea);`

To insert an image, you would use:

`File file = new File("myimage.gif");`
`FileInputStream fis = new FileInputStream(file);`
`PreparedStatement ps = conn.prepareStatement("INSERT INTO images VALUES (?, ?)");`
`ps.setString(1, file.getName());`
`ps.setBinaryStream(2, fis, (int)file.length());`

Here, `setBinaryStream()` transfers a set number of bytes from a stream into the
column of type BYTEA. This also could have been done using the `setBytes()` method
if the contents of the image was already in a `byte[]`.

### Note

> The length parameter to `setBinaryStream` must be correct. There is no way to
indicate that the stream is of unknown length. If you are in this situation, you
must read the stream yourself into temporary storage and determine the length.
Now with the correct length you may send the data from temporary storage on to
the driver.
Retrieving an image is even easier. (We use `PreparedStatement` here, but the
`Statement` class can equally be used.)

`PreparedStatement ps = conn.prepareStatement("SELECT img FROM images WHERE imgname = ?");`
`ps.setString(1, "myimage.gif");`
`ResultSet rs = ps.executeQuery();`
`while (`
&nbsp;&nbsp;&nbsp;`byte[] imgBytes = rs.getBytes(1);`
&nbsp;&nbsp;&nbsp;`// use the data in some way here`

Here the binary data was retrieved as an `byte[]`. You could have used a
`InputStream` object instead.

Alternatively you could be storing a very large file and want to use the
`LargeObject` API to store the file:

`CREATE TABLE imageslo (imgname text, imgoid oid);`

To insert an image, you would use:

`// All LargeObject API calls must be within a transaction block`
`conn.setAutoCommit(false);``<br />
`// Get the Large Object Manager to perform operations with`
`LargeObjectManager lobj = conn.unwrap(org.postgresql.PGConnection.class).getLargeObjectAPI();`<br />
`// Create a new large object`
`long oid = lobj.createLO(LargeObjectManager.READ | LargeObjectManager.WRITE);`<br />
`// Open the large object for writing`
`LargeObject obj =, LargeObjectManager.WRITE);`<br />
`// Now open the file`
`File file = new File("myimage.gif");`
`FileInputStream fis = new FileInputStream(file);`<br />
`// Copy the data from the file to the large object`
`byte buf[] = new byte[2048];`
`int s, tl = 0;`
`while ((s =, 0, 2048)) > 0)`
&nbsp;&nbsp;&nbsp;`obj.write(buf, 0, s);`
&nbsp;&nbsp;&nbsp;`tl += s;`
`}`<br />

`// Close the large object`
`obj.close();`<br />

`// Now insert the row into imageslo`
`PreparedStatement ps = conn.prepareStatement("INSERT INTO imageslo VALUES (?, ?)");`
`ps.setString(1, file.getName());`
`ps.setLong(2, oid);`
`fis.close();`<br />

`// Finally, commit the transaction.`

Retrieving the image from the Large Object:

`// All LargeObject API calls must be within a transaction block`
`conn.setAutoCommit(false);`<br />

`// Get the Large Object Manager to perform operations with`
`LargeObjectManager lobj = conn.unwrap(org.postgresql.PGConnection.class).getLargeObjectAPI();`<br />

`PreparedStatement ps = conn.prepareStatement("SELECT imgoid FROM imageslo WHERE imgname = ?");`
`ps.setString(1, "myimage.gif");`
`ResultSet rs = ps.executeQuery();`
`while (`
&nbsp;&nbsp;&nbsp;`// Open the large object for reading`
&nbsp;&nbsp;&nbsp;`long oid = rs.getLong(1);`
&nbsp;&nbsp;&nbsp;`LargeObject obj =, LargeObjectManager.READ);`<br />

&nbsp;&nbsp;&nbsp;`// Read the data`
&nbsp;&nbsp;&nbsp;`byte buf[] = new byte[obj.size()];`
&nbsp;&nbsp;&nbsp;`, 0, obj.size());`
&nbsp;&nbsp;&nbsp;`// Do something with the data read here`<br />

&nbsp;&nbsp;&nbsp;`// Close the object`
`ps.close();`<br />

`// Finally, commit the transaction.`

0 comments on commit 70e23c4

Please sign in to comment.