mirror of
https://github.com/postgres/postgres.git
synced 2025-05-28 05:21:27 +03:00
2985 lines
87 KiB
Plaintext
2985 lines
87 KiB
Plaintext
<!--
|
|
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/jdbc.sgml,v 1.44 2003/04/07 01:29:25 petere Exp $
|
|
-->
|
|
|
|
<chapter id="jdbc">
|
|
<title><acronym>JDBC</acronym> Interface</title>
|
|
|
|
<para>
|
|
<acronym>JDBC</acronym> is a core <acronym>API</acronym> of Java 1.1 and later.
|
|
It provides a standard set of
|
|
interfaces to <acronym>SQL</acronym>-compliant databases.
|
|
</para>
|
|
|
|
<para>
|
|
<productname>PostgreSQL</> provides a <firstterm>type
|
|
4</firstterm> <acronym>JDBC</acronym> driver. Type 4 indicates
|
|
that the driver is written in Pure Java, and communicates in the
|
|
database system's own network protocol. Because of this, the driver
|
|
is platform independent; once compiled, the driver can be used on
|
|
any system.
|
|
</para>
|
|
|
|
<para>
|
|
This chapter is not intended as a complete guide to
|
|
<acronym>JDBC</acronym> programming, but should help to get you
|
|
started. For more information refer to the standard
|
|
<acronym>JDBC</acronym> <acronym>API</acronym> documentation.
|
|
Also, take a look at the examples included with the source.
|
|
</para>
|
|
|
|
<sect1 id="jdbc-setup">
|
|
<title>Setting up the <acronym>JDBC</acronym> Driver</title>
|
|
|
|
<para>
|
|
This section describes the steps you need to take before you can
|
|
write or run programs that use the JDBC interface.
|
|
</para>
|
|
|
|
<sect2 id="jdbc-build">
|
|
<title>Getting the Driver</title>
|
|
|
|
<para>
|
|
Precompiled versions of the driver can be downloaded from
|
|
the <ulink
|
|
url="http://jdbc.postgresql.org"><productname>PostgreSQL</productname>
|
|
<acronym>JDBC</acronym> web site</ulink>.
|
|
</para>
|
|
|
|
<para>
|
|
Alternatively you can build the driver from source, but you should
|
|
only need to do this if you are making changes to the source code.
|
|
For details, refer to the <productname>PostgreSQL</> installation
|
|
instructions. After installation, the driver should be found in
|
|
<filename><replaceable>PREFIX</>/share/java/postgresql.jar</filename>.
|
|
The resulting driver will be built for the version of Java you are
|
|
running. If you build with a 1.1 <acronym>JDK</> you will build a
|
|
version that supports the JDBC 1 specification, if you build with
|
|
a Java 2 <acronym>JDK</> (e.g., <acronym>JDK</> 1.2 or
|
|
<acronym>JDK</> 1.3) you will build a version that supports the
|
|
JDBC 2 specification.
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 id="jdbc-classpath">
|
|
<title>Setting up the Class Path</title>
|
|
|
|
<para>
|
|
To use the driver, the JAR archive (named
|
|
<filename>postgresql.jar</filename> if you built from source, otherwise
|
|
it will likely be named <filename>jdbc&majorversion;-1.1.jar</filename> or
|
|
<filename>jdbc&majorversion;-1.2.jar</filename> for the JDBC 1 and JDBC 2 versions
|
|
respectively)
|
|
needs to be included in the
|
|
class path, either by putting it in the <envar>CLASSPATH</envar>
|
|
environment variable, or by using flags on the
|
|
<command>java</command> command line.
|
|
</para>
|
|
|
|
<para>
|
|
For instance, assume we have an application that uses the
|
|
<acronym>JDBC</acronym> driver to access a database, and that
|
|
application is installed as
|
|
<filename>/usr/local/lib/myapp.jar</filename>. The PostgreSQL
|
|
JDBC driver installed as
|
|
<filename>/usr/local/pgsql/share/java/postgresql.jar</>. To run
|
|
the application, we would use:
|
|
<programlisting>
|
|
export CLASSPATH=/usr/local/lib/myapp.jar:/usr/local/pgsql/share/java/postgresql.jar:.
|
|
java MyApp
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
Loading the driver from within the application is covered in
|
|
<xref linkend="jdbc-use">.
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 id="jdbc-prepare">
|
|
<title>Preparing the Database Server for <acronym>JDBC</acronym></title>
|
|
|
|
<para>
|
|
Because Java only uses TCP/IP connections, the
|
|
<application>PostgreSQL</application> server must be configured to
|
|
accept TCP/IP connections. This can be done by setting
|
|
<literal>tcpip_socket = true</literal> in the
|
|
<filename>postgresql.conf</filename> file or by supplying the
|
|
<option>-i</option> option flag when starting
|
|
<command>postmaster</command>.
|
|
</para>
|
|
|
|
<para>
|
|
Also, the client authentication setup in the
|
|
<filename>pg_hba.conf</filename> file may need to be configured.
|
|
Refer to <xref linkend="client-authentication"> for details. The
|
|
<acronym>JDBC</acronym> driver supports the trust, ident,
|
|
password, md5, and crypt authentication methods.
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 id="jdbc-use">
|
|
<title>Initializing the Driver</title>
|
|
|
|
<para>
|
|
This section describes how to load and initialize the JDBC driver
|
|
in your programs.
|
|
</para>
|
|
|
|
<sect2 id="jdbc-import">
|
|
<title>Importing <acronym>JDBC</acronym></title>
|
|
|
|
<para>
|
|
Any source that uses <acronym>JDBC</acronym> needs to import the
|
|
<literal>java.sql</literal> package, using:
|
|
|
|
<programlisting>
|
|
import java.sql.*;
|
|
</programlisting>
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
Do not import the <literal>org.postgresql</literal> package. If
|
|
you do, your source will not compile, as
|
|
<command>javac</command> will get confused.
|
|
</para>
|
|
</note>
|
|
</sect2>
|
|
|
|
<sect2 id="jdbc-load">
|
|
<title>Loading the Driver</title>
|
|
|
|
<para>
|
|
Before you can connect to a database, you need to load the
|
|
driver. There are two methods available, and it depends on your
|
|
code which is the best one to use.
|
|
</para>
|
|
|
|
<para>
|
|
In the first method, your code implicitly loads the driver using the
|
|
<function>Class.forName()</function> method.
|
|
For <productname>PostgreSQL</>, you would use:
|
|
|
|
<programlisting>
|
|
Class.forName("org.postgresql.Driver");
|
|
</programlisting>
|
|
|
|
This will load the driver, and while loading, the driver will automatically
|
|
register itself with <acronym>JDBC</acronym>.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
The <function>forName()</function> method can throw a
|
|
<classname>ClassNotFoundException</classname> if the driver is
|
|
not available.
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
This is the most common method to use, but restricts your code to
|
|
use just <productname>PostgreSQL</productname>. If your code may
|
|
access another database system in the future, and you do not use
|
|
any <productname>PostgreSQL</productname>-specific extensions, then
|
|
the second method is advisable.
|
|
</para>
|
|
|
|
<para>
|
|
The second method passes the driver as a parameter to the
|
|
<acronym>JVM</acronym> as it starts, using the <option>-D</option>
|
|
argument. Example:
|
|
<programlisting>
|
|
java -Djdbc.drivers=org.postgresql.Driver example.ImageViewer
|
|
</programlisting>
|
|
In this example, the <acronym>JVM</acronym> will attempt to load
|
|
the driver as part of its initialization. Once done, the
|
|
<classname>ImageViewer</classname> is started.
|
|
</para>
|
|
|
|
<para>
|
|
Now, this method is the better one to use because it allows your
|
|
code to be used with other database packages without recompiling
|
|
the code. The only thing that would also change is the connection
|
|
<acronym>URL</acronym>, which is covered next.
|
|
</para>
|
|
|
|
<para>
|
|
One last thing: When your code then tries to open a
|
|
<classname>Connection</classname>, and you get a <errorname>No
|
|
driver available</errorname> <classname>SQLException</classname>
|
|
being thrown, this is probably caused by the driver not being in
|
|
the class path, or the value in the parameter not being correct.
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 id="jdbc-connect">
|
|
<title>Connecting to the Database</title>
|
|
|
|
<para>
|
|
With <acronym>JDBC</acronym>, a database is represented by a
|
|
<acronym>URL</acronym> (Uniform Resource Locator). With
|
|
<application>PostgreSQL</application>, this takes one of the
|
|
following forms:
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<synopsis>
|
|
jdbc:postgresql:<replaceable class="parameter">database</replaceable>
|
|
</synopsis>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
jdbc:postgresql://<replaceable class="parameter">host</replaceable>/<replaceable class="parameter">database</replaceable>
|
|
</synopsis>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
jdbc:postgresql://<replaceable class="parameter">host</replaceable>:<replaceable class="parameter">port</replaceable>/<replaceable class="parameter">database</replaceable>
|
|
</synopsis>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
The parametes have the following meanings:
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term>
|
|
<replaceable class="parameter">host</replaceable>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
The host name of the server. Defaults to <literal>localhost</literal>.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>
|
|
<replaceable class="parameter">port</replaceable>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
The port number the server is listening on. Defaults to the
|
|
<productname>PostgreSQL</productname> standard port number (5432).
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>
|
|
<replaceable class="parameter">database</replaceable>
|
|
</term>
|
|
<listitem>
|
|
<para>
|
|
The database name.
|
|
</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
|
|
<para>
|
|
To connect, you need to get a <classname>Connection</classname> instance from
|
|
<acronym>JDBC</acronym>. To do this,
|
|
you use the <function>DriverManager.getConnection()</function> method:
|
|
|
|
<programlisting>
|
|
Connection db = DriverManager.getConnection(url, username, password);
|
|
</programlisting>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 id="jdbc-disconnect">
|
|
<title>Closing the Connection</title>
|
|
|
|
<para>
|
|
To close the database connection, simply call the
|
|
<function>close()</function> method to the <classname>Connection</classname>:
|
|
<programlisting>
|
|
db.close();
|
|
</programlisting>
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
|
|
<sect1 id="jdbc-query">
|
|
<title>Issuing a Query and Processing the Result</title>
|
|
|
|
<para>
|
|
Any time you want to issue <acronym>SQL</acronym> statements to
|
|
the database, you require a <classname>Statement</classname> or
|
|
<classname>PreparedStatement</classname> instance. Once you have
|
|
a <classname>Statement</classname> or
|
|
<classname>PreparedStatement</classname>, you can use issue a
|
|
query. This will return a <classname>ResultSet</classname>
|
|
instance, which contains the entire result. <xref
|
|
linkend="jdbc-query-example"> illustrates this process.
|
|
</para>
|
|
|
|
<example id="jdbc-query-example">
|
|
<title>Processing a Simple Query in <acronym>JDBC</acronym></title>
|
|
|
|
<para>
|
|
This example will issue a simple query and print out the first
|
|
column of each row using a <classname>Statement</classname>.
|
|
<programlisting>
|
|
Statement st = db.createStatement();
|
|
ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE columnfoo = 500");
|
|
while (rs.next()) {
|
|
System.out.print("Column 1 returned ");
|
|
System.out.println(rs.getString(1));
|
|
}
|
|
rs.close();
|
|
st.close();
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
This example issues the same query as before but uses
|
|
a <classname>PreparedStatement</classname>
|
|
and a bind value in the query.
|
|
<programlisting>
|
|
int foovalue = 500;
|
|
PreparedStatement st = db.prepareStatement("SELECT * FROM mytable WHERE columnfoo = ?");
|
|
st.setInt(1, foovalue);
|
|
ResultSet rs = st.executeQuery();
|
|
while (rs.next()) {
|
|
System.out.print("Column 1 returned ");
|
|
System.out.println(rs.getString(1));
|
|
}
|
|
rs.close();
|
|
st.close();
|
|
</programlisting>
|
|
</para>
|
|
</example>
|
|
|
|
<sect2>
|
|
<title>Using the <classname>Statement</classname> or <classname>PreparedStatement</classname> Interface</title>
|
|
|
|
<para>
|
|
The following must be considered when using the
|
|
<classname>Statement</classname> or
|
|
<classname>PreparedStatement</classname> interface:
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
You can use a single <classname>Statement</classname> instance
|
|
as many times as you want. You could create one as soon as you
|
|
open the connection and use it for the connection's
|
|
lifetime. But you have to remember that only one
|
|
<classname>ResultSet</classname> can exist per
|
|
<classname>Statement</classname> or
|
|
<classname>PreparedStatement</classname> at a given time.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
If you need to perform a query while processing a
|
|
<classname>ResultSet</classname>, you can simply create and
|
|
use another <classname>Statement</classname>.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
If you are using threads, and several are using the database,
|
|
you must use a separate <classname>Statement</classname> for
|
|
each thread. Refer to <xref linkend="jdbc-thread"> if you are
|
|
thinking of using threads, as it covers some important points.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
When you are done using the <classname>Statement</classname>
|
|
or <classname>PreparedStatement</classname>
|
|
you should close it.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2>
|
|
<title>Using the <classname>ResultSet</classname> Interface</title>
|
|
|
|
<para>
|
|
The following must be considered when using the
|
|
<classname>ResultSet</classname> interface:
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
Before reading any values, you must call
|
|
<function>next()</function>. This returns true if there is a
|
|
result, but more importantly, it prepares the row for
|
|
processing.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Under the <acronym>JDBC</acronym> specification, you should
|
|
access a field only once. It is safest to stick to this rule,
|
|
although at the current time, the
|
|
<productname>PostgreSQL</productname> driver will allow you to
|
|
access a field as many times as you want.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
You must close a <classname>ResultSet</classname> by calling
|
|
<function>close()</function> once you have finished using it.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Once you make another query with the
|
|
<classname>Statement</classname> used to create a
|
|
<classname>ResultSet</classname>, the currently open
|
|
<classname>ResultSet</classname> instance is closed
|
|
automatically.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
<classname>ResultSet</classname> is currently read only.
|
|
You can not update data through the <classname>ResultSet</classname>.
|
|
If you want to update data you need to do it the normal way
|
|
by using the <acronym>SQL</acronym> statement <command>UPDATE</command>. This is
|
|
in conformance with the <acronym>JDBC</acronym> specification
|
|
which does not require drivers to provide updatable result sets.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</sect2>
|
|
</sect1>
|
|
|
|
<sect1 id="jdbc-update">
|
|
<title>Performing Updates</title>
|
|
|
|
<para>
|
|
To change data (perform an <command>INSERT</command>,
|
|
<command>UPDATE</command>, or <command>DELETE</command>) you use
|
|
the <function>executeUpdate()</function> method. This method is
|
|
similar to the method <function>executeQuery()</function> used to
|
|
issue a <command>SELECT</command> statement, but it doesn't return
|
|
a <classname>ResultSet</classname>; instead it returns the number
|
|
of rows affected by the <command>INSERT</command>,
|
|
<command>UPDATE</command>, or <command>DELETE</command> statement.
|
|
<xref linkend="jdbc-delete-example"> illustrates the usage.
|
|
</para>
|
|
|
|
<example id="jdbc-delete-example">
|
|
<title>Deleting Rows in <acronym>JDBC</acronym></title>
|
|
<para>
|
|
This example will issue a simple <command>DELETE</command>
|
|
statement and print out the number of rows deleted.
|
|
<programlisting>
|
|
int foovalue = 500;
|
|
PreparedStatement st = db.prepareStatement("DELETE FROM mytable WHERE columnfoo = ?");
|
|
st.setInt(1, foovalue);
|
|
int rowsDeleted = st.executeUpdate();
|
|
System.out.println(rowsDeleted + " rows deleted");
|
|
st.close();
|
|
</programlisting>
|
|
</para>
|
|
</example>
|
|
</sect1>
|
|
|
|
<sect1 id="jdbc-ddl">
|
|
<title>Creating and Modifying Database Objects</title>
|
|
|
|
<para>
|
|
To create, modify or drop a database object like a table or view
|
|
you use the <function>execute()</function> method. This method is
|
|
similar to the method <function>executeQuery()</function>, but it
|
|
doesn't return a result. <xref linkend="jdbc-drop-table-example">
|
|
illustrates the usage.
|
|
</para>
|
|
|
|
<example id="jdbc-drop-table-example">
|
|
<title>Dropping a Table in JDBC</title>
|
|
<para>
|
|
This example will drop a table.
|
|
<programlisting>
|
|
Statement st = db.createStatement();
|
|
st.execute("DROP TABLE mytable");
|
|
st.close();
|
|
</programlisting>
|
|
</para>
|
|
</example>
|
|
</sect1>
|
|
|
|
<sect1 id="jdbc-binary-data">
|
|
<title>Storing Binary Data</title>
|
|
|
|
<para>
|
|
<application>PostgreSQL</application> provides two distinct ways to
|
|
store binary data. Binary data can be stored in a table using
|
|
the data type <type>bytea</type> 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
|
|
<type>oid</type> in your table.
|
|
</para>
|
|
|
|
<para>
|
|
In order to determine which method is appropriate you
|
|
need to understand the limitations of each method. The
|
|
<type>bytea</type> data type is not well suited for storing very
|
|
large amounts of binary data. While a column of type
|
|
<type>bytea</type> 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 cann view
|
|
and/or modify any Large Object, even if they don't have
|
|
permissions to view/update the row containing the Large Object reference.
|
|
</para>
|
|
|
|
<para>
|
|
Version 7.2 was the first release of the <acronym>JDBC</acronym> driver
|
|
that supports the <type>bytea</type> 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
|
|
<function>getBytes()</function>, <function>setBytes()</function>,
|
|
<function>getBinaryStream()</function>, and
|
|
<function>setBinaryStream()</function> operate on
|
|
the <type>bytea</type> data type. In 7.1 and earlier, these methods operated
|
|
on the <type>oid</type> data type associated with Large Objects.
|
|
It is possible to revert the driver back to the old 7.1 behavior
|
|
by setting the property <literal>compatible</literal> on
|
|
the <classname>Connection</classname> object to the value
|
|
<literal>7.1</literal>.
|
|
</para>
|
|
|
|
<para>
|
|
To use the <type>bytea</type> data type you should simply use
|
|
the <function>getBytes()</function>, <function>setBytes()</function>,
|
|
<function>getBinaryStream()</function>, or
|
|
<function>setBinaryStream()</function> methods.
|
|
</para>
|
|
|
|
<para>
|
|
To use the Large Object functionality you can use either the
|
|
<classname>LargeObject</classname> class
|
|
provided by the <application>PostgreSQL</application>
|
|
<acronym>JDBC</acronym> driver, or by using the
|
|
<function>getBLOB()</function> and <function>setBLOB()</function>
|
|
methods.
|
|
</para>
|
|
|
|
<important>
|
|
<para>
|
|
You must access Large Objects within an <acronym>SQL</acronym>
|
|
transaction block. You can start a transaction block by calling
|
|
<function>setAutoCommit(false)</function>.
|
|
</para>
|
|
</important>
|
|
|
|
<note>
|
|
<para>
|
|
In a future release of the
|
|
<acronym>JDBC</acronym> driver, the <function>getBLOB()</function>
|
|
and <function>setBLOB()</function> methods may no longer
|
|
interact with Large Objects and will instead work on the data type
|
|
<type>bytea</type>. So it is recommended that you
|
|
use the <classname>LargeObject</classname> <acronym>API</acronym>
|
|
if you intend to use Large Objects.
|
|
</para>
|
|
</note>
|
|
|
|
<para>
|
|
<xref linkend="jdbc-binary-data-example"> contains some examples on
|
|
how to process binary data using the PostgreSQL JDBC driver.
|
|
</para>
|
|
|
|
<example id="jdbc-binary-data-example">
|
|
<title>Processing Binary Data in JDBC</title>
|
|
|
|
<para>
|
|
For example, suppose you have a table containing the file names of
|
|
images and you also want to store the image in a <type>bytea</type>
|
|
column:
|
|
<programlisting>
|
|
CREATE TABLE images (imgname text, img bytea);
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
To insert an image, you would use:
|
|
<programlisting>
|
|
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, file.length());
|
|
ps.executeUpdate();
|
|
ps.close();
|
|
fis.close();
|
|
</programlisting>
|
|
|
|
Here, <function>setBinaryStream()</function> transfers a set number
|
|
of bytes from a stream into the column of type <type>bytea</type>.
|
|
This also could have been done using the <function>setBytes()</function>
|
|
method if the contents of the image was already in a
|
|
<classname>byte[]</classname>.
|
|
</para>
|
|
|
|
<para>
|
|
Retrieving an image is even easier. (We use
|
|
<classname>PreparedStatement</classname> here, but the
|
|
<classname>Statement</classname> class can equally be used.)
|
|
|
|
<programlisting>
|
|
PreparedStatement ps = con.prepareStatement("SELECT img FROM images WHERE imgname = ?");
|
|
ps.setString(1, "myimage.gif");
|
|
ResultSet rs = ps.executeQuery();
|
|
if (rs != null) {
|
|
while (rs.next()) {
|
|
byte[] imgBytes = rs.getBytes(1);
|
|
// use the data in some way here
|
|
}
|
|
rs.close();
|
|
}
|
|
ps.close();
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
Here the binary data was retrieved as an
|
|
<classname>byte[]</classname>. You could have used a
|
|
<classname>InputStream</classname> object instead.
|
|
</para>
|
|
|
|
<para>
|
|
Alternatively you could be storing a very large file and want to use
|
|
the <classname>LargeObject</classname> <acronym>API</acronym> to
|
|
store the file:
|
|
<programlisting>
|
|
CREATE TABLE imageslo (imgname text, imgoid oid);
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
To insert an image, you would use:
|
|
<programlisting>
|
|
// All LargeObject API calls must be within a transaction block
|
|
conn.setAutoCommit(false);
|
|
|
|
// Get the Large Object Manager to perform operations with
|
|
LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI();
|
|
|
|
// Create a new large object
|
|
int oid = lobj.create(LargeObjectManager.READ | LargeObjectManager.WRITE);
|
|
|
|
// Open the large object for writing
|
|
LargeObject obj = lobj.open(oid, LargeObjectManager.WRITE);
|
|
|
|
// Now open the file
|
|
File file = new File("myimage.gif");
|
|
FileInputStream fis = new FileInputStream(file);
|
|
|
|
// Copy the data from the file to the large object
|
|
byte buf[] = new byte[2048];
|
|
int s, tl = 0;
|
|
while ((s = fis.read(buf, 0, 2048)) > 0) {
|
|
obj.write(buf, 0, s);
|
|
tl += s;
|
|
}
|
|
|
|
// Close the large object
|
|
obj.close();
|
|
|
|
// Now insert the row into imageslo
|
|
PreparedStatement ps = conn.prepareStatement("INSERT INTO imageslo VALUES (?, ?)");
|
|
ps.setString(1, file.getName());
|
|
ps.setInt(2, oid);
|
|
ps.executeUpdate();
|
|
ps.close();
|
|
fis.close();
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
Retrieving the image from the Large Object:
|
|
|
|
<programlisting>
|
|
// All LargeObject API calls must be within a transaction block
|
|
conn.setAutoCommit(false);
|
|
|
|
// Get the Large Object Manager to perform operations with
|
|
LargeObjectManager lobj = ((org.postgresql.PGConnection)conn).getLargeObjectAPI();
|
|
|
|
PreparedStatement ps = con.prepareStatement("SELECT imgoid FROM imageslo WHERE imgname = ?");
|
|
ps.setString(1, "myimage.gif");
|
|
ResultSet rs = ps.executeQuery();
|
|
if (rs != null) {
|
|
while (rs.next()) {
|
|
// Open the large object for reading
|
|
int oid = rs.getInt(1);
|
|
LargeObject obj = lobj.open(oid, LargeObjectManager.READ);
|
|
|
|
// Read the data
|
|
byte buf[] = new byte[obj.size()];
|
|
obj.read(buf, 0, obj.size());
|
|
// Do something with the data read here
|
|
|
|
// Close the object
|
|
obj.close();
|
|
}
|
|
rs.close();
|
|
}
|
|
ps.close();
|
|
</programlisting>
|
|
</para>
|
|
|
|
</example>
|
|
</sect1>
|
|
|
|
|
|
<sect1 id="jdbc-ext">
|
|
<title><application>PostgreSQL</application> Extensions to the
|
|
<acronym>JDBC</acronym> <acronym>API</acronym></title>
|
|
|
|
<para>
|
|
<productname>PostgreSQL</productname> is an extensible database
|
|
system. You can add your own functions to the backend, which can
|
|
then be called from queries, or even add your own data types. As
|
|
these are facilities unique to <productname>PostgreSQL</productname>,
|
|
we support them from Java, with a set of extension
|
|
<acronym>API</acronym>'s. Some features within the core of the
|
|
standard driver actually use these extensions to implement Large
|
|
Objects, etc.
|
|
</para>
|
|
|
|
<sect2>
|
|
<title>Accessing the Extensions</title>
|
|
|
|
<para>
|
|
To access some of the extensions, you need to use some extra
|
|
methods in the <classname>org.postgresql.PGConnection</classname>
|
|
class. In this case, you would need to case the return value of
|
|
<function>Driver.getConnection()</function>. For example:
|
|
<programlisting>
|
|
Connection db = Driver.getConnection(url, username, password);
|
|
// ...
|
|
// later on
|
|
Fastpath fp = ((org.postgresql.PGConnection)db).getFastpathAPI();
|
|
</programlisting>
|
|
</para>
|
|
|
|
<sect3>
|
|
<title>Class <classname>org.postgresql.PGConnection</classname></title>
|
|
|
|
<synopsis>
|
|
public class PGConnection
|
|
</synopsis>
|
|
|
|
<para>
|
|
These are the extra methods used to gain access to
|
|
<productname>PostgreSQL</productname>'s extensions.
|
|
</para>
|
|
|
|
<sect4>
|
|
<title>Methods</title>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<synopsis>
|
|
public Fastpath getFastpathAPI() throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
This returns the Fastpath <acronym>API</acronym> for the
|
|
current connection. It is primarily used by the Large Object
|
|
<acronym>API</acronym>.
|
|
</para>
|
|
|
|
<para>
|
|
The best way to use this is as follows:
|
|
<programlisting>
|
|
import org.postgresql.fastpath.*;
|
|
...
|
|
Fastpath fp = ((org.postgresql.PGConnection)myconn).getFastpathAPI();
|
|
</programlisting>
|
|
where <varname>myconn</> is an open <classname>Connection</> to <productname>PostgreSQL</productname>.
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>Returns:</title>
|
|
<para>
|
|
Fastpath object allowing access to functions on the
|
|
<productname>PostgreSQL</productname> backend.
|
|
</para>
|
|
</formalpara>
|
|
|
|
<formalpara>
|
|
<title>Throws:</title>
|
|
<para>
|
|
<classname>SQLException</> by Fastpath when initializing for first time
|
|
</para>
|
|
</formalpara>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
<synopsis>
|
|
public LargeObjectManager getLargeObjectAPI() throws SQLException
|
|
</synopsis>
|
|
This returns the Large Object <acronym>API</acronym> for the
|
|
current connection.
|
|
</para>
|
|
|
|
<para>
|
|
The best way to use this is as follows:
|
|
<programlisting>
|
|
import org.postgresql.largeobject.*;
|
|
...
|
|
LargeObjectManager lo = ((org.postgresql.PGConnection)myconn).getLargeObjectAPI();
|
|
</programlisting>
|
|
where <varname>myconn</> is an open <classname>Connection</> to
|
|
<productname>PostgreSQL</productname>.
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>Returns:</title>
|
|
<para>
|
|
<classname>LargeObject</classname> object that implements the <acronym>API</acronym>
|
|
</para>
|
|
</formalpara>
|
|
|
|
<formalpara>
|
|
<title>Throws:</title>
|
|
<para>
|
|
<classname>SQLException</classname> by <classname>LargeObject</classname> when initializing for first time
|
|
</para>
|
|
</formalpara>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
<synopsis>
|
|
public void addDataType(String type, String name)
|
|
</synopsis>
|
|
This allows client code to add a handler for one of
|
|
<productname>PostgreSQL</productname>'s more unique data types. Normally, a data type not
|
|
known by the driver is returned by <literal>ResultSet.getObject()</literal> as a
|
|
<classname>PGobject</> instance. This method allows you to write a class
|
|
that extends <classname>PGobject</>, and tell the driver the type name, and
|
|
class name to use. The down side to this, is that you must
|
|
call this method each time a connection is made.
|
|
</para>
|
|
|
|
<para>
|
|
The best way to use this is as follows:
|
|
<programlisting>
|
|
...
|
|
((org.postgresql.PGConnection)myconn).addDataType("mytype","my.class.name");
|
|
...
|
|
</programlisting>
|
|
where <varname>myconn</varname> is an open <classname>Connection</> to
|
|
<productname>PostgreSQL</productname>. The handling class must
|
|
extend <classname>org.postgresql.util.PGobject</classname>.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect4>
|
|
</sect3>
|
|
|
|
|
|
<sect3>
|
|
<title>Class <classname>org.postgresql.Fastpath</classname></title>
|
|
|
|
<synopsis>
|
|
public class Fastpath extends Object
|
|
|
|
java.lang.Object
|
|
|
|
|
+----org.postgresql.fastpath.Fastpath
|
|
</synopsis>
|
|
|
|
<para>
|
|
<classname>Fastpath</classname> is an <acronym>API</acronym> that
|
|
exists within the <application>libpq</application> C interface, and allows a client machine
|
|
to execute a function on the database backend. Most client code
|
|
will not need to use this method, but it is provided because the
|
|
Large Object <acronym>API</acronym> uses it.
|
|
</para>
|
|
|
|
<para>
|
|
To use, you need to import the
|
|
<classname>org.postgresql.fastpath</classname> package, using the
|
|
line:
|
|
<programlisting>
|
|
import org.postgresql.fastpath.*;
|
|
</programlisting>
|
|
Then, in your code, you need to get a
|
|
<classname>FastPath</classname> object:
|
|
<programlisting>
|
|
Fastpath fp = ((org.postgresql.PGConnection)conn).getFastpathAPI();
|
|
</programlisting>
|
|
This will return an instance associated with the database
|
|
connection that you can use to issue commands. The casing of
|
|
<classname>Connection</classname> to
|
|
<classname>org.postgresql.PGConnection</classname> is required, as
|
|
the <function>getFastpathAPI()</function> is an extension method,
|
|
not part of <acronym>JDBC</acronym>. Once you have a
|
|
<classname>Fastpath</classname> instance, you can use the
|
|
<function>fastpath()</function> methods to execute a backend
|
|
function.
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>See Also:</title>
|
|
<para>
|
|
<classname>FastpathFastpathArg</classname>, <classname>LargeObject</classname>
|
|
</para>
|
|
</formalpara>
|
|
|
|
<sect4>
|
|
<title>Methods</title>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<synopsis>
|
|
public Object fastpath(int fnid,
|
|
boolean resulttype,
|
|
FastpathArg args[]) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
Send a function call to the <productname>PostgreSQL</productname> backend.
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>Parameters:</title>
|
|
<para>
|
|
<parameter>fnid</> - Function id
|
|
<parameter>resulttype</> - True if the result is an integer, false
|
|
for
|
|
other results
|
|
<parameter>args</> - <classname>FastpathArguments</classname> to pass to fastpath
|
|
</para>
|
|
</formalpara>
|
|
|
|
<formalpara>
|
|
<title>Returns:</title>
|
|
<para>
|
|
null if no data, Integer if an integer result, or byte[]
|
|
otherwise
|
|
</para>
|
|
</formalpara>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public Object fastpath(String name,
|
|
boolean resulttype,
|
|
FastpathArg args[]) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
Send a function call to the <productname>PostgreSQL</productname> backend by name.
|
|
</para>
|
|
|
|
<note>
|
|
<para>
|
|
The mapping for the procedure name to function id needs to
|
|
exist, usually to an earlier call to <function>addfunction()</function>. This is
|
|
the preferred method to call, as function id's can/may change
|
|
between versions of the backend. For an example of how this
|
|
works, refer to org.postgresql.LargeObject
|
|
</para>
|
|
</note>
|
|
|
|
<formalpara>
|
|
<title>Parameters:</title>
|
|
<para>
|
|
<parameter>name</> - Function name
|
|
<parameter>resulttype</> - True if the result is an integer, false
|
|
for
|
|
other results
|
|
<parameter>args</> - <classname>FastpathArguments</classname> to pass to fastpath
|
|
</para>
|
|
</formalpara>
|
|
|
|
<formalpara>
|
|
<title>Returns:</title>
|
|
<para>
|
|
null if no data, Integer if an integer result, or byte[]
|
|
otherwise
|
|
</para>
|
|
</formalpara>
|
|
|
|
<formalpara>
|
|
<title>See Also:</title>
|
|
<para><classname>LargeObject</classname></para>
|
|
</formalpara>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public int getInteger(String name,
|
|
FastpathArg args[]) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
This convenience method assumes that the return value is an Integer
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>Parameters:</title>
|
|
<para>
|
|
<parameter>name</parameter> - Function name
|
|
<parameter>args</parameter> - Function arguments
|
|
</para>
|
|
</formalpara>
|
|
|
|
<formalpara>
|
|
<title>Returns:</title>
|
|
<para>integer result</para>
|
|
</formalpara>
|
|
|
|
<formalpara>
|
|
<title>Throws:</title>
|
|
<para>
|
|
<classname>SQLException</classname> if a database-access error occurs or no result
|
|
</para>
|
|
</formalpara>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public byte[] getData(String name,
|
|
FastpathArg args[]) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
This convenience method assumes that the return value is binary
|
|
data.
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>Parameters:</title>
|
|
<para>
|
|
<parameter>name</parameter> - Function name
|
|
<parameter>args</parameter> - Function arguments
|
|
</para>
|
|
</formalpara>
|
|
|
|
<formalpara>
|
|
<title>Returns:</title>
|
|
<para>byte[] array containing result</para>
|
|
</formalpara>
|
|
|
|
<formalpara>
|
|
<title>Throws:</title>
|
|
<para>
|
|
<classname>SQLException</classname> if a database-access error occurs or no result
|
|
</para>
|
|
</formalpara>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public void addFunction(String name,
|
|
int fnid)
|
|
</synopsis>
|
|
<para>
|
|
This adds a function to our look-up table. User code should
|
|
use the <function>addFunctions</function> method, which is based upon a query,
|
|
rather than hard coding the OID. The OID for a function is not
|
|
guaranteed to remain static, even on different servers of the
|
|
same version.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public void addFunctions(ResultSet rs) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
This takes a <classname>ResultSet</classname> containing two columns. Column 1
|
|
contains the function name, Column 2 the OID. It reads the
|
|
entire <classname>ResultSet</classname>, loading the values into the function table.
|
|
</para>
|
|
|
|
<important>
|
|
<para>
|
|
Remember to <function>close()</function> the
|
|
<classname>ResultSet</classname> after calling this!
|
|
</para>
|
|
</important>
|
|
|
|
<note>
|
|
<title>Implementation note about function name look-ups</title>
|
|
|
|
<para>
|
|
<productname>PostgreSQL</productname> stores the function id's and their corresponding
|
|
names in the <classname>pg_proc</> table. To speed things up locally,
|
|
instead of querying each function from that table when
|
|
required, a <classname>Hashtable</classname> is used. Also, only the function's
|
|
required are entered into this table, keeping connection
|
|
times as fast as possible.
|
|
</para>
|
|
|
|
<para>
|
|
The <classname>org.postgresql.LargeObject</classname> class
|
|
performs a query upon its start-up, and passes the returned
|
|
<classname>ResultSet</classname> to the
|
|
<function>addFunctions()</function> method here. Once this
|
|
has been done, the Large Object <acronym>API</acronym> refers
|
|
to the functions by name.
|
|
</para>
|
|
|
|
<para>
|
|
Do not think that manually converting them to the OIDs will
|
|
work. OK, they will for now, but they can change during
|
|
development (there was some discussion about this for V7.0),
|
|
so this is implemented to prevent any unwarranted headaches
|
|
in the future.
|
|
</para>
|
|
</note>
|
|
|
|
<formalpara>
|
|
<title>See Also:</title>
|
|
<para>
|
|
<classname>LargeObjectManager</classname>
|
|
</para>
|
|
</formalpara>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public int getID(String name) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
This returns the function id associated by its name If
|
|
<function>addFunction()</function> or <function>addFunctions()</function> have not been called for this
|
|
name, then an <classname>SQLException</classname> is thrown.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect4>
|
|
</sect3>
|
|
|
|
|
|
<sect3>
|
|
<title>Class <classname>org.postgresql.fastpath.FastpathArg</classname></title>
|
|
|
|
<synopsis>
|
|
public class FastpathArg extends Object
|
|
|
|
java.lang.Object
|
|
|
|
|
+----org.postgresql.fastpath.FastpathArg
|
|
</synopsis>
|
|
|
|
<para>
|
|
Each fastpath call requires an array of arguments, the number and
|
|
type dependent on the function being called. This class
|
|
implements methods needed to provide this capability.
|
|
</para>
|
|
|
|
<para>
|
|
For an example on how to use this, refer to the
|
|
<classname>org.postgresql.LargeObject</classname> package.
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>See Also:</title>
|
|
<para>
|
|
<classname>Fastpath</classname>, <classname>LargeObjectManager</classname>, <classname>LargeObject</classname>
|
|
</para>
|
|
</formalpara>
|
|
|
|
<sect4>
|
|
<title>Constructors</title>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<synopsis>
|
|
public FastpathArg(int value)
|
|
</synopsis>
|
|
<para>
|
|
Constructs an argument that consists of an integer value
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>Parameters:</title>
|
|
<para>
|
|
value - int value to set
|
|
</para>
|
|
</formalpara>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public FastpathArg(byte bytes[])
|
|
</synopsis>
|
|
<para>
|
|
Constructs an argument that consists of an array of bytes
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>Parameters:</title>
|
|
<para>
|
|
bytes - array to store
|
|
</para>
|
|
</formalpara>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public FastpathArg(byte buf[],
|
|
int off,
|
|
int len)
|
|
</synopsis>
|
|
<para>
|
|
Constructs an argument that consists of part of a byte array
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>Parameters:</title>
|
|
<para>
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><parameter>buf</></term>
|
|
<listitem>
|
|
<simpara>source array</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><parameter>off</parameter></term>
|
|
<listitem>
|
|
<simpara>offset within array</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><parameter>len</parameter></term>
|
|
<listitem>
|
|
<simpara>length of data to include</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
</formalpara>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public FastpathArg(String s)
|
|
</synopsis>
|
|
<para>
|
|
Constructs an argument that consists of a String.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect4>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
|
|
<sect2>
|
|
<title>Geometric Data Types</title>
|
|
|
|
<para>
|
|
<productname>PostgreSQL</productname> has a set of data types that
|
|
can store geometric features into a table. These include single
|
|
points, lines, and polygons. We support these types in Java with
|
|
the org.postgresql.geometric package. It contains classes that
|
|
extend the org.postgresql.util.PGobject class. Refer to that
|
|
class for details on how to implement your own data type handlers.
|
|
</para>
|
|
|
|
<programlisting>
|
|
Class org.postgresql.geometric.PGbox
|
|
|
|
java.lang.Object
|
|
|
|
|
+----org.postgresql.util.PGobject
|
|
|
|
|
+----org.postgresql.geometric.PGbox
|
|
|
|
public class PGbox extends PGobject implements Serializable,
|
|
Cloneable
|
|
|
|
This represents the box data type within <productname>PostgreSQL</productname>.
|
|
|
|
Variables
|
|
|
|
public PGpoint point[]
|
|
|
|
These are the two corner points of the box.
|
|
|
|
Constructors
|
|
|
|
public PGbox(double x1,
|
|
double y1,
|
|
double x2,
|
|
double y2)
|
|
|
|
Parameters:
|
|
x1 - first x coordinate
|
|
y1 - first y coordinate
|
|
x2 - second x coordinate
|
|
y2 - second y coordinate
|
|
|
|
public PGbox(PGpoint p1,
|
|
PGpoint p2)
|
|
|
|
Parameters:
|
|
p1 - first point
|
|
p2 - second point
|
|
|
|
public PGbox(String s) throws SQLException
|
|
|
|
Parameters:
|
|
s - Box definition in <productname>PostgreSQL</productname> syntax
|
|
|
|
Throws: SQLException
|
|
if definition is invalid
|
|
|
|
public PGbox()
|
|
|
|
Required constructor
|
|
|
|
Methods
|
|
|
|
public void setValue(String value) throws SQLException
|
|
|
|
This method sets the value of this object. It should be
|
|
overridden, but still called by subclasses.
|
|
|
|
Parameters:
|
|
value - a string representation of the value of the
|
|
object
|
|
Throws: SQLException
|
|
thrown if value is invalid for this type
|
|
|
|
Overrides:
|
|
setValue in class PGobject
|
|
|
|
public boolean equals(Object obj)
|
|
|
|
Parameters:
|
|
obj - Object to compare with
|
|
|
|
Returns:
|
|
true if the two boxes are identical
|
|
|
|
Overrides:
|
|
equals in class PGobject
|
|
|
|
public Object clone()
|
|
|
|
This must be overridden to allow the object to be cloned
|
|
|
|
Overrides:
|
|
clone in class PGobject
|
|
|
|
public String getValue()
|
|
|
|
Returns:
|
|
the PGbox in the syntax expected by <productname>PostgreSQL</productname>
|
|
|
|
Overrides:
|
|
getValue in class PGobject
|
|
|
|
<!-- **************************************************************** -->
|
|
Class org.postgresql.geometric.PGcircle
|
|
|
|
java.lang.Object
|
|
|
|
|
+----org.postgresql.util.PGobject
|
|
|
|
|
+----org.postgresql.geometric.PGcircle
|
|
|
|
public class PGcircle extends PGobject implements Serializable,
|
|
Cloneable
|
|
|
|
This represents <productname>PostgreSQL</productname>'s circle data type, consisting of a point
|
|
and a radius
|
|
|
|
Variables
|
|
|
|
public PGpoint center
|
|
|
|
This is the center point
|
|
|
|
double radius
|
|
|
|
This is the radius
|
|
|
|
Constructors
|
|
|
|
public PGcircle(double x,
|
|
double y,
|
|
double r)
|
|
|
|
Parameters:
|
|
x - coordinate of center
|
|
y - coordinate of center
|
|
r - radius of circle
|
|
|
|
public PGcircle(PGpoint c,
|
|
double r)
|
|
|
|
Parameters:
|
|
c - PGpoint describing the circle's center
|
|
r - radius of circle
|
|
|
|
public PGcircle(String s) throws SQLException
|
|
|
|
Parameters:
|
|
s - definition of the circle in <productname>PostgreSQL</productname>'s syntax.
|
|
|
|
Throws: SQLException
|
|
on conversion failure
|
|
|
|
public PGcircle()
|
|
|
|
This constructor is used by the driver.
|
|
|
|
Methods
|
|
|
|
public void setValue(String s) throws SQLException
|
|
|
|
Parameters:
|
|
s - definition of the circle in <productname>PostgreSQL</productname>'s syntax.
|
|
|
|
Throws: SQLException
|
|
on conversion failure
|
|
|
|
Overrides:
|
|
setValue in class PGobject
|
|
|
|
public boolean equals(Object obj)
|
|
|
|
Parameters:
|
|
obj - Object to compare with
|
|
|
|
Returns:
|
|
true if the two circles are identical
|
|
|
|
Overrides:
|
|
equals in class PGobject
|
|
|
|
public Object clone()
|
|
|
|
This must be overridden to allow the object to be cloned
|
|
|
|
Overrides:
|
|
clone in class PGobject
|
|
|
|
public String getValue()
|
|
|
|
Returns:
|
|
the PGcircle in the syntax expected by <productname>PostgreSQL</productname>
|
|
|
|
Overrides:
|
|
getValue in class PGobject
|
|
|
|
<!-- **************************************************************** -->
|
|
Class org.postgresql.geometric.PGline
|
|
|
|
java.lang.Object
|
|
|
|
|
+----org.postgresql.util.PGobject
|
|
|
|
|
+----org.postgresql.geometric.PGline
|
|
|
|
public class PGline extends PGobject implements Serializable,
|
|
Cloneable
|
|
|
|
This implements a line consisting of two points. Currently line is
|
|
not yet implemented in the backend, but this class ensures that when
|
|
it's done were ready for it.
|
|
|
|
Variables
|
|
|
|
public PGpoint point[]
|
|
|
|
These are the two points.
|
|
|
|
Constructors
|
|
|
|
public PGline(double x1,
|
|
double y1,
|
|
double x2,
|
|
double y2)
|
|
|
|
Parameters:
|
|
x1 - coordinate for first point
|
|
y1 - coordinate for first point
|
|
x2 - coordinate for second point
|
|
y2 - coordinate for second point
|
|
|
|
public PGline(PGpoint p1,
|
|
PGpoint p2)
|
|
|
|
Parameters:
|
|
p1 - first point
|
|
p2 - second point
|
|
|
|
public PGline(String s) throws SQLException
|
|
|
|
Parameters:
|
|
s - definition of the line in <productname>PostgreSQL</productname>'s syntax.
|
|
|
|
Throws: SQLException
|
|
on conversion failure
|
|
|
|
public PGline()
|
|
|
|
required by the driver
|
|
|
|
Methods
|
|
|
|
public void setValue(String s) throws SQLException
|
|
|
|
Parameters:
|
|
s - Definition of the line segment in <productname>PostgreSQL</productname>'s
|
|
syntax
|
|
|
|
Throws: SQLException
|
|
on conversion failure
|
|
|
|
Overrides:
|
|
setValue in class PGobject
|
|
|
|
public boolean equals(Object obj)
|
|
|
|
Parameters:
|
|
obj - Object to compare with
|
|
|
|
Returns:
|
|
true if the two lines are identical
|
|
|
|
Overrides:
|
|
equals in class PGobject
|
|
|
|
public Object clone()
|
|
|
|
This must be overridden to allow the object to be cloned
|
|
|
|
Overrides:
|
|
clone in class PGobject
|
|
|
|
public String getValue()
|
|
|
|
Returns:
|
|
the PGline in the syntax expected by <productname>PostgreSQL</productname>
|
|
|
|
Overrides:
|
|
getValue in class PGobject
|
|
|
|
<!-- **************************************************************** -->
|
|
Class org.postgresql.geometric.PGlseg
|
|
|
|
java.lang.Object
|
|
|
|
|
+----org.postgresql.util.PGobject
|
|
|
|
|
+----org.postgresql.geometric.PGlseg
|
|
|
|
public class PGlseg extends PGobject implements Serializable,
|
|
Cloneable
|
|
|
|
This implements a lseg (line segment) consisting of two points
|
|
|
|
Variables
|
|
|
|
public PGpoint point[]
|
|
|
|
These are the two points.
|
|
|
|
Constructors
|
|
|
|
public PGlseg(double x1,
|
|
double y1,
|
|
double x2,
|
|
double y2)
|
|
|
|
Parameters:
|
|
|
|
x1 - coordinate for first point
|
|
y1 - coordinate for first point
|
|
x2 - coordinate for second point
|
|
y2 - coordinate for second point
|
|
|
|
public PGlseg(PGpoint p1,
|
|
PGpoint p2)
|
|
|
|
Parameters:
|
|
p1 - first point
|
|
p2 - second point
|
|
|
|
public PGlseg(String s) throws SQLException
|
|
|
|
Parameters:
|
|
s - Definition of the line segment in <productname>PostgreSQL</productname>'s syntax.
|
|
|
|
Throws: SQLException
|
|
on conversion failure
|
|
|
|
public PGlseg()
|
|
|
|
required by the driver
|
|
|
|
Methods
|
|
|
|
public void setValue(String s) throws SQLException
|
|
|
|
Parameters:
|
|
s - Definition of the line segment in <productname>PostgreSQL</productname>'s
|
|
syntax
|
|
|
|
Throws: SQLException
|
|
on conversion failure
|
|
|
|
Overrides:
|
|
setValue in class PGobject
|
|
|
|
public boolean equals(Object obj)
|
|
|
|
Parameters:
|
|
obj - Object to compare with
|
|
|
|
Returns:
|
|
true if the two line segments are identical
|
|
|
|
Overrides:
|
|
equals in class PGobject
|
|
|
|
public Object clone()
|
|
|
|
This must be overridden to allow the object to be cloned
|
|
|
|
Overrides:
|
|
clone in class PGobject
|
|
|
|
public String getValue()
|
|
|
|
Returns:
|
|
the PGlseg in the syntax expected by <productname>PostgreSQL</productname>
|
|
|
|
Overrides:
|
|
getValue in class PGobject
|
|
|
|
<!-- **************************************************************** -->
|
|
Class org.postgresql.geometric.PGpath
|
|
|
|
java.lang.Object
|
|
|
|
|
+----org.postgresql.util.PGobject
|
|
|
|
|
+----org.postgresql.geometric.PGpath
|
|
|
|
public class PGpath extends PGobject implements Serializable,
|
|
Cloneable
|
|
|
|
This implements a path (a multiply segmented line, which may be
|
|
closed)
|
|
|
|
Variables
|
|
|
|
public boolean open
|
|
|
|
True if the path is open, false if closed
|
|
|
|
public PGpoint points[]
|
|
|
|
The points defining this path
|
|
|
|
Constructors
|
|
|
|
public PGpath(PGpoint points[],
|
|
boolean open)
|
|
|
|
Parameters:
|
|
points - the PGpoints that define the path
|
|
open - True if the path is open, false if closed
|
|
|
|
public PGpath()
|
|
|
|
Required by the driver
|
|
|
|
public PGpath(String s) throws SQLException
|
|
|
|
Parameters:
|
|
s - definition of the path in <productname>PostgreSQL</productname>'s syntax.
|
|
|
|
Throws: SQLException
|
|
on conversion failure
|
|
|
|
Methods
|
|
|
|
public void setValue(String s) throws SQLException
|
|
|
|
Parameters:
|
|
s - Definition of the path in <productname>PostgreSQL</productname>'s syntax
|
|
|
|
Throws: SQLException
|
|
on conversion failure
|
|
|
|
Overrides:
|
|
setValue in class PGobject
|
|
|
|
public boolean equals(Object obj)
|
|
|
|
Parameters:
|
|
obj - Object to compare with
|
|
|
|
Returns:
|
|
true if the two pathes are identical
|
|
|
|
Overrides:
|
|
equals in class PGobject
|
|
|
|
public Object clone()
|
|
|
|
This must be overridden to allow the object to be cloned
|
|
|
|
Overrides:
|
|
clone in class PGobject
|
|
|
|
public String getValue()
|
|
|
|
This returns the path in the syntax expected by
|
|
<productname>PostgreSQL</productname>
|
|
|
|
Overrides:
|
|
getValue in class PGobject
|
|
|
|
public boolean isOpen()
|
|
|
|
This returns true if the path is open
|
|
|
|
public boolean isClosed()
|
|
|
|
This returns true if the path is closed
|
|
|
|
public void closePath()
|
|
|
|
Marks the path as closed
|
|
|
|
public void openPath()
|
|
|
|
Marks the path as open
|
|
|
|
<!-- **************************************************************** -->
|
|
Class org.postgresql.geometric.PGpoint
|
|
|
|
java.lang.Object
|
|
|
|
|
+----org.postgresql.util.PGobject
|
|
|
|
|
+----org.postgresql.geometric.PGpoint
|
|
|
|
public class PGpoint extends PGobject implements Serializable,
|
|
Cloneable
|
|
|
|
This implements a version of java.awt.Point, except it uses double
|
|
to represent the coordinates.
|
|
|
|
It maps to the point data type in <productname>PostgreSQL</productname>.
|
|
|
|
Variables
|
|
|
|
public double x
|
|
|
|
The X coordinate of the point
|
|
|
|
public double y
|
|
|
|
The Y coordinate of the point
|
|
|
|
Constructors
|
|
|
|
public PGpoint(double x,
|
|
double y)
|
|
|
|
Parameters:
|
|
x - coordinate
|
|
y - coordinate
|
|
|
|
public PGpoint(String value) throws SQLException
|
|
|
|
This is called mainly from the other geometric types, when a
|
|
point is embedded within their definition.
|
|
|
|
Parameters:
|
|
value - Definition of this point in <productname>PostgreSQL</productname>'s
|
|
syntax
|
|
|
|
public PGpoint()
|
|
|
|
Required by the driver
|
|
|
|
Methods
|
|
|
|
public void setValue(String s) throws SQLException
|
|
|
|
Parameters:
|
|
s - Definition of this point in <productname>PostgreSQL</productname>'s syntax
|
|
|
|
Throws: SQLException
|
|
on conversion failure
|
|
|
|
Overrides:
|
|
setValue in class PGobject
|
|
|
|
public boolean equals(Object obj)
|
|
|
|
Parameters:
|
|
obj - Object to compare with
|
|
|
|
Returns:
|
|
true if the two points are identical
|
|
|
|
Overrides:
|
|
equals in class PGobject
|
|
|
|
public Object clone()
|
|
|
|
This must be overridden to allow the object to be cloned
|
|
|
|
Overrides:
|
|
clone in class PGobject
|
|
|
|
public String getValue()
|
|
|
|
Returns:
|
|
the PGpoint in the syntax expected by <productname>PostgreSQL</productname>
|
|
|
|
Overrides:
|
|
getValue in class PGobject
|
|
|
|
public void translate(int x,
|
|
int y)
|
|
|
|
Translate the point with the supplied amount.
|
|
|
|
Parameters:
|
|
x - integer amount to add on the x axis
|
|
y - integer amount to add on the y axis
|
|
|
|
public void translate(double x,
|
|
double y)
|
|
|
|
Translate the point with the supplied amount.
|
|
|
|
Parameters:
|
|
x - double amount to add on the x axis
|
|
y - double amount to add on the y axis
|
|
|
|
public void move(int x,
|
|
int y)
|
|
|
|
Moves the point to the supplied coordinates.
|
|
|
|
Parameters:
|
|
x - integer coordinate
|
|
y - integer coordinate
|
|
|
|
public void move(double x,
|
|
double y)
|
|
|
|
Moves the point to the supplied coordinates.
|
|
|
|
Parameters:
|
|
x - double coordinate
|
|
y - double coordinate
|
|
|
|
public void setLocation(int x,
|
|
int y)
|
|
|
|
Moves the point to the supplied coordinates. refer to
|
|
java.awt.Point for description of this
|
|
|
|
Parameters:
|
|
x - integer coordinate
|
|
y - integer coordinate
|
|
|
|
See Also:
|
|
Point
|
|
|
|
public void setLocation(Point p)
|
|
|
|
Moves the point to the supplied java.awt.Point refer to
|
|
java.awt.Point for description of this
|
|
|
|
Parameters:
|
|
p - Point to move to
|
|
|
|
See Also:
|
|
Point
|
|
|
|
<!-- **************************************************************** -->
|
|
Class org.postgresql.geometric.PGpolygon
|
|
|
|
java.lang.Object
|
|
|
|
|
+----org.postgresql.util.PGobject
|
|
|
|
|
+----org.postgresql.geometric.PGpolygon
|
|
|
|
public class PGpolygon extends PGobject implements Serializable,
|
|
Cloneable
|
|
|
|
This implements the polygon data type within <productname>PostgreSQL</productname>.
|
|
|
|
Variables
|
|
|
|
public PGpoint points[]
|
|
|
|
The points defining the polygon
|
|
|
|
Constructors
|
|
|
|
public PGpolygon(PGpoint points[])
|
|
|
|
Creates a polygon using an array of PGpoints
|
|
|
|
Parameters:
|
|
points - the points defining the polygon
|
|
|
|
public PGpolygon(String s) throws SQLException
|
|
|
|
Parameters:
|
|
s - definition of the polygon in <productname>PostgreSQL</productname>'s syntax.
|
|
|
|
Throws: SQLException
|
|
on conversion failure
|
|
|
|
public PGpolygon()
|
|
|
|
Required by the driver
|
|
|
|
Methods
|
|
|
|
public void setValue(String s) throws SQLException
|
|
|
|
Parameters:
|
|
s - Definition of the polygon in <productname>PostgreSQL</productname>'s syntax
|
|
|
|
Throws: SQLException
|
|
on conversion failure
|
|
|
|
Overrides:
|
|
setValue in class PGobject
|
|
|
|
public boolean equals(Object obj)
|
|
|
|
Parameters:
|
|
obj - Object to compare with
|
|
|
|
Returns:
|
|
true if the two polygons are identical
|
|
|
|
Overrides:
|
|
equals in class PGobject
|
|
|
|
public Object clone()
|
|
|
|
This must be overridden to allow the object to be cloned
|
|
|
|
Overrides:
|
|
clone in class PGobject
|
|
|
|
public String getValue()
|
|
|
|
Returns:
|
|
the PGpolygon in the syntax expected by <productname>PostgreSQL</productname>
|
|
|
|
Overrides:
|
|
getValue in class PGobject
|
|
</programlisting>
|
|
</sect2>
|
|
|
|
|
|
<sect2>
|
|
<title>Large Objects</title>
|
|
|
|
<para>
|
|
Large objects are supported in the standard
|
|
<acronym>JDBC</acronym> specification. However, that interface is
|
|
limited, and the <acronym>API</acronym> provided by <productname>PostgreSQL</productname> allows for random
|
|
access to the objects contents, as if it was a local file.
|
|
</para>
|
|
|
|
<para>
|
|
The org.postgresql.largeobject package provides to Java the <application>libpq</application>
|
|
C interface's large object <acronym>API</acronym>. It consists of
|
|
two classes, <classname>LargeObjectManager</classname>, which deals with creating,
|
|
opening and deleting large objects, and <classname>LargeObject</classname> which deals
|
|
with an individual object.
|
|
</para>
|
|
|
|
<sect3>
|
|
<title>Class <classname>org.postgresql.largeobject.LargeObject</classname></title>
|
|
|
|
<synopsis>
|
|
public class LargeObject extends Object
|
|
|
|
java.lang.Object
|
|
|
|
|
+----org.postgresql.largeobject.LargeObject
|
|
</synopsis>
|
|
|
|
<para>
|
|
This class implements the large object interface to
|
|
<productname>PostgreSQL</productname>.
|
|
</para>
|
|
|
|
<para>
|
|
It provides the basic methods required to run the interface, plus
|
|
a pair of methods that provide <classname>InputStream</classname> and <classname>OutputStream</classname>
|
|
classes for this object.
|
|
</para>
|
|
|
|
<para>
|
|
Normally, client code would use the methods in
|
|
<classname>BLOB</classname> to access large objects.
|
|
</para>
|
|
|
|
<para>
|
|
However, sometimes lower level access to Large Objects is
|
|
required, that is not supported by the <acronym>JDBC</acronym>
|
|
specification.
|
|
</para>
|
|
|
|
<para>
|
|
Refer to org.postgresql.largeobject.LargeObjectManager on how to
|
|
gain access to a Large Object, or how to create one.
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>See Also:</title>
|
|
<para><classname>LargeObjectManager</classname></para>
|
|
</formalpara>
|
|
|
|
<sect4>
|
|
<title>Variables</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term>public static final int SEEK_SET</term>
|
|
<listitem>
|
|
<para>Indicates a seek from the beginning of a file</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>public static final int SEEK_CUR</term>
|
|
<listitem>
|
|
<para>Indicates a seek from the current position</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term>public static final int SEEK_END</term>
|
|
<listitem>
|
|
<para>Indicates a seek from the end of a file</para>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</sect4>
|
|
|
|
<sect4>
|
|
<title>Methods</title>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<synopsis>
|
|
public int getOID()
|
|
</synopsis>
|
|
<para>
|
|
Returns the OID of this <classname>LargeObject</classname>
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public void close() throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
This method closes the object. You must not call methods in
|
|
this object after this is called.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public byte[] read(int len) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
Reads some data from the object, and return as a byte[] array
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public int read(byte buf[],
|
|
int off,
|
|
int len) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
Reads some data from the object into an existing array
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>Parameters:</title>
|
|
<para>
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><parameter>buf</></term>
|
|
<listitem>
|
|
<simpara>destination array</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><parameter>off</></term>
|
|
<listitem>
|
|
<simpara>offset within array</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><parameter>len</></term>
|
|
<listitem>
|
|
<simpara>number of bytes to read</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
</formalpara>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public void write(byte buf[]) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
Writes an array to the object
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public void write(byte buf[],
|
|
int off,
|
|
int len) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
Writes some data from an array to the object
|
|
</para>
|
|
|
|
<formalpara>
|
|
<title>Parameters:</title>
|
|
<para>
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><parameter>buf</></term>
|
|
<listitem>
|
|
<simpara>destination array</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><parameter>off</></term>
|
|
<listitem>
|
|
<simpara>offset within array</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><parameter>len</></term>
|
|
<listitem>
|
|
<simpara>number of bytes to write</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</para>
|
|
</formalpara>
|
|
</listitem>
|
|
|
|
<!--
|
|
public void seek(int pos,
|
|
int ref) throws SQLException
|
|
|
|
Sets the current position within the object.
|
|
|
|
This is similar to the fseek() call in the standard C
|
|
library.It allows you to have random access to the large object.
|
|
|
|
Parameters:
|
|
pos - position within object
|
|
ref - Either SEEK_SET, SEEK_CUR or SEEK_END
|
|
Throws: SQLException
|
|
if a database-access error occurs.
|
|
|
|
public void seek(int pos) throws SQLException
|
|
|
|
Sets the current position within the object.
|
|
|
|
This is similar to the fseek() call in the standard C
|
|
library.It allows you to have random access to the large object.
|
|
|
|
Parameters:
|
|
pos - position within object from begining
|
|
|
|
Throws: SQLException
|
|
if a database-access error occurs.
|
|
|
|
public int tell() throws SQLException
|
|
|
|
Returns:
|
|
the current position within the object
|
|
|
|
Throws: SQLException
|
|
if a database-access error occurs.
|
|
|
|
public int size() throws SQLException
|
|
|
|
This method is inefficient, as the only way to find out the
|
|
size of the object is to seek to the end, record the current position,
|
|
then return to the original position.
|
|
|
|
A better method will be found in the future.
|
|
|
|
Returns:
|
|
the size of the large object
|
|
|
|
Throws: SQLException
|
|
if a database-access error occurs.
|
|
|
|
public InputStream getInputStream() throws SQLException
|
|
|
|
Returns an InputStream from this object.
|
|
|
|
This InputStream can then be used in any method that
|
|
requires an InputStream.
|
|
|
|
Throws: SQLException
|
|
if a database-access error occurs.
|
|
|
|
public OutputStream getOutputStream() throws SQLException
|
|
|
|
Returns an OutputStream to this object
|
|
|
|
This OutputStream can then be used in any method that
|
|
requires an OutputStream.
|
|
|
|
Throws: SQLException
|
|
if a database-access error occurs.
|
|
-->
|
|
</itemizedlist>
|
|
</sect4>
|
|
</sect3>
|
|
|
|
|
|
<sect3>
|
|
<title>Class <classname>org.postgresql.largeobject.LargeObjectManager</classname></title>
|
|
|
|
<synopsis>
|
|
public class LargeObjectManager extends Object
|
|
|
|
java.lang.Object
|
|
|
|
|
+----org.postgresql.largeobject.LargeObjectManager
|
|
</synopsis>
|
|
|
|
<para>
|
|
This class implements the large object interface to
|
|
<productname>PostgreSQL</productname>. It provides methods that
|
|
allow client code to create, open and delete large objects from
|
|
the database. When opening an object, an instance of
|
|
<classname>org.postgresql.largeobject.LargeObject</classname> is
|
|
returned, and its methods then allow access to the object.
|
|
</para>
|
|
|
|
<para>
|
|
This class can only be created by org.postgresql.PGConnection. To
|
|
get access to this class, use the following segment of code:
|
|
<programlisting>
|
|
import org.postgresql.largeobject.*;
|
|
Connection conn;
|
|
LargeObjectManager lobj;
|
|
// ... code that opens a connection ...
|
|
lobj = ((org.postgresql.PGConnection)myconn).getLargeObjectAPI();
|
|
</programlisting>
|
|
</para>
|
|
|
|
<para>
|
|
Normally, client code would use the <classname>BLOB</classname>
|
|
methods to access large objects. However, sometimes
|
|
lower level access to Large Objects is required, that is not
|
|
supported by the <acronym>JDBC</acronym> specification.
|
|
</para>
|
|
|
|
<para>
|
|
Refer to org.postgresql.largeobject.LargeObject on how to
|
|
manipulate the contents of a Large Object.
|
|
</para>
|
|
|
|
<sect4>
|
|
<title>Variables</title>
|
|
|
|
<variablelist>
|
|
<varlistentry>
|
|
<term><literal>public static final int WRITE</></term>
|
|
<listitem>
|
|
<simpara>This mode indicates we want to write to an object.</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>public static final int READ</></term>
|
|
<listitem>
|
|
<simpara>This mode indicates we want to read an object.</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><literal>public static final int READWRITE</></term>
|
|
<listitem>
|
|
<simpara>This mode is the default. It indicates we want read and write access to a large object.</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
</sect4>
|
|
|
|
<sect4>
|
|
<title>Methods</title>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<synopsis>
|
|
public LargeObject open(int oid) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
This opens an existing large object, based on its OID. This
|
|
method assumes that <symbol>READ</> and
|
|
<symbol>WRITE</> access is required (the default).
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public LargeObject open(int oid,
|
|
int mode) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
This opens an existing large object, based on its OID, and
|
|
allows setting the access mode.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public int create() throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
This creates a large object, returning its OID.
|
|
It defaults to <symbol>READWRITE</> for the new object's attributes.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public int create(int mode) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
This creates a large object, returning its OID, and sets the
|
|
access mode.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public void delete(int oid) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
This deletes a large object.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<synopsis>
|
|
public void unlink(int oid) throws SQLException
|
|
</synopsis>
|
|
<para>
|
|
This deletes a large object. It is identical to the delete
|
|
method, and is supplied as the C <acronym>API</acronym> uses
|
|
<quote>unlink</quote>.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</sect4>
|
|
</sect3>
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
|
|
<sect1 id="jdbc-thread">
|
|
<title>Using the Driver in a Multithreaded or a Servlet Environment</title>
|
|
|
|
<para>
|
|
A problem with many <acronym>JDBC</acronym> drivers is that only
|
|
one thread can use a <classname>Connection</classname> at any one
|
|
time --- otherwise a thread could send a query while another one is
|
|
receiving results, and this could cause severe confusion.
|
|
</para>
|
|
|
|
<para>
|
|
The <productname>PostgreSQL</productname> <acronym>JDBC</acronym> driver
|
|
is thread safe.
|
|
Consequently, if your application uses multiple threads then you do
|
|
not have to worry about complex algorithms to ensure that only one thread
|
|
uses the database at a time.
|
|
</para>
|
|
|
|
<para>
|
|
If a thread attempts to use the connection while another one is
|
|
using it, it will wait until the other thread has finished its
|
|
current operation. If the operation is a regular <acronym>SQL</acronym>
|
|
statement, then the operation consists of sending the statement and
|
|
retrieving any <classname>ResultSet</classname> (in full). If it
|
|
is a fast-path call (e.g., reading a block
|
|
from a large object) then it consists of
|
|
sending and retrieving the respective data.
|
|
</para>
|
|
|
|
<para>
|
|
This is fine for applications and applets but can cause a
|
|
performance problem with servlets. If you have several threads
|
|
performing queries then each but one will pause.
|
|
To solve this, you are advised to create a pool of connections.
|
|
When ever a thread needs to use the database, it asks a manager
|
|
class for a <classname>Connection</classname> object. The manager
|
|
hands a free connection to the thread and marks it as busy. If a
|
|
free connection is not available, it opens one. Once the thread
|
|
has finished using the connection, it returns it to the manager
|
|
which can then either close it or add it to the pool. The manager
|
|
would also check that the connection is still alive and remove it
|
|
from the pool if it is dead. The down side of a connection pool is
|
|
that it increases the load on the server because a new session is
|
|
created for each <classname>Connection</classname> object. It is
|
|
up to you and your applications' requirements.
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1 id="jdbc-datasource">
|
|
<title>Connection Pools and Data Sources</title>
|
|
|
|
<para>
|
|
JDBC 2 introduced standard connection pooling features in an
|
|
add-on API known as the <acronym>JDBC</acronym> 2.0 Optional
|
|
Package (also known as the <acronym>JDBC</acronym> 2.0
|
|
Standard Extension). These features have since been included in
|
|
the core JDBC 3 API. The <productname>PostgreSQL</productname>
|
|
<acronym>JDBC</acronym> drivers support these features if it has been compiled with
|
|
<acronym>JDK</acronym> 1.3.x in combination with the
|
|
<acronym>JDBC</acronym> 2.0 Optional Package
|
|
(<acronym>JDBC</acronym> 2), or with <acronym>JDK</acronym> 1.4 or higher
|
|
(<acronym>JDBC</acronym> 3). Most application servers include
|
|
the <acronym>JDBC</acronym> 2.0 Optional Package, but it is
|
|
also available separately from the Sun
|
|
<ulink
|
|
url="http://java.sun.com/products/jdbc/download.html#spec"><acronym>JDBC</acronym> download site</ulink>.
|
|
</para>
|
|
|
|
<sect2 id="jdbc-ds-intro">
|
|
<title>Overview</title>
|
|
|
|
<para>
|
|
The <acronym>JDBC</acronym> API provides a client
|
|
and a server interface for connection pooling. The client
|
|
interface is <literal>javax.sql.DataSource</literal>,
|
|
which is what application code will typically use to
|
|
acquire a pooled database connection. The server interface
|
|
is <literal>javax.sql.ConnectionPoolDataSource</literal>,
|
|
which is how most application servers will interface with
|
|
the <productname>PostgreSQL</productname> <acronym>JDBC</acronym>
|
|
driver.
|
|
</para>
|
|
|
|
<para>
|
|
In an application server environment, the
|
|
application server configuration will typically refer to
|
|
the <productname>PostgreSQL</productname>
|
|
<literal>ConnectionPoolDataSource</literal> implementation,
|
|
while the application component code will typically acquire a
|
|
<literal>DataSource</literal> implementation provided by
|
|
the application server (not by
|
|
<productname>PostgreSQL</productname>).
|
|
</para>
|
|
|
|
<para>
|
|
For an environment without an application server,
|
|
<productname>PostgreSQL</productname> provides two implementations
|
|
of <literal>DataSource</literal> which an application can use
|
|
directly. One implementation performs connection pooling,
|
|
while the other simply provides access to database connections
|
|
through the <literal>DataSource</literal> interface without
|
|
any pooling. Again, these implementations should not be used
|
|
in an application server environment unless the application
|
|
server does not support the
|
|
<literal>ConnectionPoolDataSource</literal> interface.
|
|
</para>
|
|
</sect2>
|
|
|
|
<sect2 id="jdbc-ds-cpds">
|
|
<title>Application Servers: <classname>ConnectionPoolDataSource</classname></title>
|
|
|
|
<para>
|
|
<productname>PostgreSQL</productname> includes one implementation
|
|
of <classname>ConnectionPoolDataSource</classname> for
|
|
<acronym>JDBC</acronym> 2 and one for <acronym>JDBC</acronym> 3,
|
|
as shown in <xref linkend="jdbc-ds-cpds-imp-table">.
|
|
</para>
|
|
|
|
|
|
<table id="jdbc-ds-cpds-imp-table">
|
|
<title><classname>ConnectionPoolDataSource</classname> Implementations</title>
|
|
|
|
<tgroup cols=2>
|
|
<thead>
|
|
<row>
|
|
<entry><acronym>JDBC</acronym></entry>
|
|
<entry>Implementation Class</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>2</entry>
|
|
<entry><literal>org.postgresql.jdbc2.optional.ConnectionPool</literal></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>3</entry>
|
|
<entry><literal>org.postgresql.jdbc3.Jdbc3ConnectionPool</literal></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>
|
|
Both implementations use the same configuration scheme.
|
|
<acronym>JDBC</acronym> requires that a
|
|
<classname>ConnectionPoolDataSource</classname> be configured via
|
|
JavaBean properties, shown in <xref linkend="jdbc-ds-cpds-props">,
|
|
so there are get and set methods for each of these properties.
|
|
</para>
|
|
|
|
<table id="jdbc-ds-cpds-props">
|
|
<title><classname>ConnectionPoolDataSource</> Configuration Properties</title>
|
|
|
|
<tgroup cols=3>
|
|
<thead>
|
|
<row>
|
|
<entry>Property</entry>
|
|
<entry>Type</entry>
|
|
<entry>Description</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><literal>serverName</literal></entry>
|
|
<entry><type>String</type></entry>
|
|
<entry><productname>PostgreSQL</productname> database server
|
|
host name</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>databaseName</literal></entry>
|
|
<entry><type>String</type></entry>
|
|
<entry><productname>PostgreSQL</productname> database name</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>portNumber</literal></entry>
|
|
<entry><type>int</type></entry>
|
|
<entry>
|
|
TCP port which the <productname>PostgreSQL</productname>
|
|
database server is listening on (or 0 to use the default port)
|
|
</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>user</literal></entry>
|
|
<entry><type>String</type></entry>
|
|
<entry>User used to make database connections</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>password</literal></entry>
|
|
<entry><type>String</type></entry>
|
|
<entry>Password used to make database connections</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>defaultAutoCommit</literal></entry>
|
|
<entry><type>boolean</type></entry>
|
|
<entry>
|
|
Whether connections should have autocommit enabled or disabled
|
|
when they are supplied to the caller. The default is
|
|
<literal>false</literal>, to disable autocommit.
|
|
</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>
|
|
Many application servers use a properties-style syntax to
|
|
configure these properties, so it would not be unusual to enter
|
|
properties as a block of text. If the application server provides
|
|
a single area to enter all the properties, they might be listed
|
|
like this:
|
|
<programlisting>
|
|
serverName=localhost
|
|
databaseName=test
|
|
user=testuser
|
|
password=testpassword
|
|
</programlisting>
|
|
Or, if semicolons are used as separators instead of newlines, it
|
|
could look like this:
|
|
<programlisting>
|
|
serverName=localhost;databaseName=test;user=testuser;password=testpassword
|
|
</programlisting>
|
|
</para>
|
|
|
|
</sect2>
|
|
|
|
<sect2 id="jdbc-ds-ds">
|
|
<title>Applications: <classname>DataSource</></title>
|
|
|
|
<para><productname>PostgreSQL</productname> includes two
|
|
implementations of <literal>DataSource</literal>
|
|
for <acronym>JDBC</acronym> 2 and two for <acronym>JDBC</acronym>
|
|
3, as shown in <xref linkend="jdbc-ds-ds-imp">.
|
|
The pooling implementations do not actually close connections
|
|
when the client calls the <literal>close</literal> method, but
|
|
instead return the connections to a pool of available connections
|
|
for other clients to use. This avoids any overhead of repeatedly
|
|
opening and closing connections, and allows a large number of
|
|
clients to share a small number of database connections.</para>
|
|
<para>The pooling data-source implementation provided here is not
|
|
the most feature-rich in the world. Among other things,
|
|
connections are never closed until the pool itself is closed;
|
|
there is no way to shrink the pool. As well, connections
|
|
requested for users other than the default configured user are
|
|
not pooled. Many application servers
|
|
provide more advanced pooling features and use the
|
|
<literal>ConnectionPoolDataSource</literal> implementation
|
|
instead.</para>
|
|
|
|
<table id="jdbc-ds-ds-imp">
|
|
<title><classname>DataSource</> Implementations</title>
|
|
|
|
<tgroup cols=3>
|
|
<thead>
|
|
<row>
|
|
<entry><acronym>JDBC</acronym></entry>
|
|
<entry>Pooling</entry>
|
|
<entry>Implementation Class</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry>2</entry>
|
|
<entry>No</entry>
|
|
<entry><literal>org.postgresql.jdbc2.optional.SimpleDataSource</literal></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>2</entry>
|
|
<entry>Yes</entry>
|
|
<entry><literal>org.postgresql.jdbc2.optional.PoolingDataSource</literal></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>3</entry>
|
|
<entry>No</entry>
|
|
<entry><literal>org.postgresql.jdbc3.Jdbc3SimpleDataSource</literal></entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry>3</entry>
|
|
<entry>Yes</entry>
|
|
<entry><literal>org.postgresql.jdbc3.Jdbc3PoolingDataSource</literal></entry>
|
|
</row>
|
|
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>
|
|
All the implementations use the same configuration scheme.
|
|
<acronym>JDBC</acronym> requires that a
|
|
<literal>DataSource</literal> be configured via JavaBean
|
|
properties, shown in <xref linkend="jdbc-ds-ds-props">, so there
|
|
are get and set methods for each of these properties.
|
|
</para>
|
|
|
|
<table id="jdbc-ds-ds-props">
|
|
<title><classname>DataSource</> Configuration Properties</title>
|
|
|
|
<tgroup cols=3>
|
|
<thead>
|
|
<row>
|
|
<entry>Property</entry>
|
|
<entry>Type</entry>
|
|
<entry>Description</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><literal>serverName</literal></entry>
|
|
<entry><type>String</type></entry>
|
|
<entry><productname>PostgreSQL</productname> database server
|
|
host name</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>databaseName</literal></entry>
|
|
<entry><type>String</type></entry>
|
|
<entry><productname>PostgreSQL</productname> database name</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>portNumber</literal></entry>
|
|
<entry><type>int</type></entry>
|
|
<entry>TCP port which the
|
|
<productname>PostgreSQL</productname> database server is
|
|
listening on (or 0 to use the default port)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>user</literal></entry>
|
|
<entry><type>String</type></entry>
|
|
<entry>User used to make database connections</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>password</literal></entry>
|
|
<entry><type>String</type></entry>
|
|
<entry>Password used to make database connections</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para>The pooling implementations require some additional
|
|
configuration properties, which are shown in <xref linkend="jdbc-ds-ds-xprops">.</para>
|
|
|
|
<table id="jdbc-ds-ds-xprops">
|
|
<title>Additional Pooling <classname>DataSource</> Configuration Properties</title>
|
|
|
|
<tgroup cols=3>
|
|
<thead>
|
|
<row>
|
|
<entry>Property</entry>
|
|
<entry>Type</entry>
|
|
<entry>Description</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry><literal>dataSourceName</literal></entry>
|
|
<entry><type>String</type></entry>
|
|
<entry>Every pooling <literal>DataSource</literal> must have a
|
|
unique name.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>initialConnections</literal></entry>
|
|
<entry><type>int</type></entry>
|
|
<entry>The number of database connections to be created
|
|
when the pool is initialized.</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry><literal>maxConnections</literal></entry>
|
|
<entry><type>int</type></entry>
|
|
<entry>The maximum number of open database connections to
|
|
allow. When more connections are requested, the caller
|
|
will hang until a connection is returned to the pool.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<para><xref linkend="jdbc-ds-example"> shows an example of typical application code using a
|
|
pooling <literal>DataSource</literal>.</para>
|
|
|
|
<example id="jdbc-ds-example">
|
|
<title><literal>DataSource</literal> Code Example</title>
|
|
|
|
<para>
|
|
Code to initialize a pooling <classname>DataSource</classname> might look like this:
|
|
<programlisting>
|
|
Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource();
|
|
source.setDataSourceName("A Data Source");
|
|
source.setServerName("localhost");
|
|
source.setDatabaseName("test");
|
|
source.setUser("testuser");
|
|
source.setPassword("testpassword");
|
|
source.setMaxConnections(10);
|
|
</programlisting>
|
|
Then code to use a connection from the pool might look
|
|
like this. Note that it is critical that the connections
|
|
are eventually closed. Else the pool will <quote>leak</> connections and
|
|
will eventually lock all the clients out.
|
|
<programlisting>
|
|
Connection con = null;
|
|
try {
|
|
con = source.getConnection();
|
|
// use connection
|
|
} catch (SQLException e) {
|
|
// log error
|
|
} finally {
|
|
if (con != null) {
|
|
try { con.close(); } catch (SQLException e) {}
|
|
}
|
|
}
|
|
</programlisting>
|
|
</para>
|
|
</example>
|
|
</sect2>
|
|
|
|
<sect2 id="jdbc-jndi">
|
|
<title>Data Sources and <acronym>JNDI</acronym></title>
|
|
|
|
<para>
|
|
All the <literal>ConnectionPoolDataSource</literal> and
|
|
<literal>DataSource</literal> implementations can be stored
|
|
in <acronym>JNDI</acronym>. In the case of the nonpooling
|
|
implementations, a new instance will be created every time the
|
|
object is retrieved from <acronym>JNDI</acronym>, with the
|
|
same settings as the instance that was stored. For the
|
|
pooling implementations, the same instance will be retrieved
|
|
as long as it is available (e.g., not a different
|
|
<acronym>JVM</acronym> retrieving the pool from
|
|
<acronym>JNDI</acronym>), or a new instance with the same
|
|
settings created otherwise.
|
|
</para>
|
|
|
|
<para>
|
|
In the application server environment, typically the
|
|
application server's <literal>DataSource</literal> instance
|
|
will be stored in <acronym>JNDI</acronym>, instead of the
|
|
<productname>PostgreSQL</productname>
|
|
<literal>ConnectionPoolDataSource</literal> implementation.
|
|
</para>
|
|
|
|
<para>
|
|
In an application environment, the application may store
|
|
the <literal>DataSource</literal> in <acronym>JNDI</acronym>
|
|
so that it doesn't have to make a reference to the
|
|
<literal>DataSource</literal> available to all application
|
|
components that may need to use it. An example of this is
|
|
shown in <xref linkend="jdbc-ds-jndi">.
|
|
</para>
|
|
|
|
<example id="jdbc-ds-jndi">
|
|
<title><classname>DataSource</classname> <acronym>JNDI</acronym> Code Example</title>
|
|
|
|
<para>
|
|
Application code to initialize a pooling <classname>DataSource</classname> and add
|
|
it to <acronym>JNDI</acronym> might look like this:
|
|
<programlisting>
|
|
Jdbc3PoolingDataSource source = new Jdbc3PoolingDataSource();
|
|
source.setDataSourceName("A Data Source");
|
|
source.setServerName("localhost");
|
|
source.setDatabaseName("test");
|
|
source.setUser("testuser");
|
|
source.setPassword("testpassword");
|
|
source.setMaxConnections(10);
|
|
new InitialContext().rebind("DataSource", source);
|
|
</programlisting>
|
|
Then code to use a connection from the pool might look
|
|
like this:
|
|
<programlisting>
|
|
Connection con = null;
|
|
try {
|
|
DataSource source = (DataSource)new InitialContext().lookup("DataSource");
|
|
con = source.getConnection();
|
|
// use connection
|
|
} catch (SQLException e) {
|
|
// log error
|
|
} catch (NamingException e) {
|
|
// DataSource wasn't found in JNDI
|
|
} finally {
|
|
if (con != null) {
|
|
try { con.close(); } catch (SQLException e) {}
|
|
}
|
|
}
|
|
</programlisting>
|
|
</para>
|
|
</example>
|
|
</sect2>
|
|
|
|
</sect1>
|
|
|
|
<sect1 id="jdbc-reading">
|
|
<title>Further Reading</title>
|
|
|
|
<para>
|
|
If you have not yet read it, you are advised you read the
|
|
<acronym>JDBC</acronym> <acronym>API</acronym> Documentation
|
|
(supplied with Sun's <acronym>JDK</acronym>) and the
|
|
<acronym>JDBC</acronym> Specification. Both are available from
|
|
<ulink
|
|
url="http://java.sun.com/products/jdbc/index.html"></ulink>.
|
|
</para>
|
|
|
|
<para>
|
|
<ulink
|
|
url="http://jdbc.postgresql.org"></ulink>
|
|
contains updated information not included in this chapter and
|
|
also offers precompiled drivers.
|
|
</para>
|
|
</sect1>
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode:sgml
|
|
sgml-omittag:nil
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"./reference.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:("/usr/lib/sgml/catalog")
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
-->
|