package org.postgresql.jdbc1;
+import java.io.*;
+
+import java.math.BigDecimal;
import java.sql.*;
-import org.postgresql.util.PSQLException;
+import java.util.Vector;
+import org.postgresql.largeobject.*;
+import org.postgresql.util.*;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.2 2002/07/24 22:08:39 barry Exp $
* This class defines methods of the jdbc1 specification. This class is
* extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2
* methods. The real Statement class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Statement
private static final short BACKSLASH = 2;
private static final short ESC_TIMEDATE = 3;
+ // Some performance caches
+ private StringBuffer sbuf = new StringBuffer();
+
+ //Used by the preparedstatement style methods
+ protected String sql;
+ protected String[] templateStrings;
+ protected String[] inStrings;
+
+
+
+ public AbstractJdbc1Statement (AbstractJdbc1Connection connection)
+ {
+ this.connection = connection;
+ }
+
+ public AbstractJdbc1Statement (AbstractJdbc1Connection connection, String sql) throws SQLException
+ {
+ this.sql = sql;
+ this.connection = connection;
+ parseSqlStmt(); // this allows Callable stmt to override
+ }
+
+ protected void parseSqlStmt () throws SQLException {
+ Vector v = new Vector();
+ boolean inQuotes = false;
+ int lastParmEnd = 0, i;
+
+ for (i = 0; i < sql.length(); ++i)
+ {
+ int c = sql.charAt(i);
+
+ if (c == '\'')
+ inQuotes = !inQuotes;
+ if (c == '?' && !inQuotes)
+ {
+ v.addElement(sql.substring (lastParmEnd, i));
+ lastParmEnd = i + 1;
+ }
+ }
+ v.addElement(sql.substring (lastParmEnd, sql.length()));
+
+ templateStrings = new String[v.size()];
+ inStrings = new String[v.size() - 1];
+ clearParameters();
+
+ for (i = 0 ; i < templateStrings.length; ++i)
+ templateStrings[i] = (String)v.elementAt(i);
+ }
+
+
/*
* Execute a SQL statement that retruns a single ResultSet
*
return result;
}
+ /*
+ * A Prepared SQL query is executed and its ResultSet is returned
+ *
+ * @return a ResultSet that contains the data produced by the
+ * * query - never null
+ * @exception SQLException if a database access error occurs
+ */
+ public java.sql.ResultSet executeQuery() throws SQLException
+ {
+ return executeQuery(compileQuery());
+ }
+
/*
* Execute a SQL INSERT, UPDATE or DELETE statement. In addition
* SQL statements that return nothing such as SQL DDL statements
return this.getUpdateCount();
}
+ /*
+ * Execute a SQL INSERT, UPDATE or DELETE statement. In addition,
+ * SQL statements that return nothing such as SQL DDL statements can
+ * be executed.
+ *
+ * @return either the row count for INSERT, UPDATE or DELETE; or
+ * * 0 for SQL statements that return nothing.
+ * @exception SQLException if a database access error occurs
+ */
+ public int executeUpdate() throws SQLException
+ {
+ return executeUpdate(compileQuery());
+ }
+
/*
* Execute a SQL statement that may return multiple results. We
* don't have to worry about this since we do not support multiple
return (result != null && ((AbstractJdbc1ResultSet)result).reallyResultSet());
}
+ /*
+ * Some prepared statements return multiple results; the execute method
+ * handles these complex statements as well as the simpler form of
+ * statements handled by executeQuery and executeUpdate
+ *
+ * @return true if the next result is a ResultSet; false if it is an
+ * * update count or there are no more results
+ * @exception SQLException if a database access error occurs
+ */
+ public boolean execute() throws SQLException
+ {
+ return execute(compileQuery());
+ }
+
/*
* setCursorName defines the SQL cursor name that will be used by
* subsequent execute methods. This name can then be used in SQL
return ((AbstractJdbc1ResultSet)result).getLastOID();
}
+ /*
+ * Set a parameter to SQL NULL
+ *
+ *
Note: You must specify the parameters SQL type (although
+ * PostgreSQL ignores it)
+ *
+ * @param parameterIndex the first parameter is 1, etc...
+ * @param sqlType the SQL type code defined in java.sql.Types
+ * @exception SQLException if a database access error occurs
+ */
+ public void setNull(int parameterIndex, int sqlType) throws SQLException
+ {
+ set(parameterIndex, "null");
+ }
+
+ /*
+ * Set a parameter to a Java boolean value. The driver converts this
+ * to a SQL BIT value when it sends it to the database.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setBoolean(int parameterIndex, boolean x) throws SQLException
+ {
+ set(parameterIndex, x ? "'t'" : "'f'");
+ }
+
+ /*
+ * Set a parameter to a Java byte value. The driver converts this to
+ * a SQL TINYINT value when it sends it to the database.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setByte(int parameterIndex, byte x) throws SQLException
+ {
+ set(parameterIndex, Integer.toString(x));
+ }
+
+ /*
+ * Set a parameter to a Java short value. The driver converts this
+ * to a SQL SMALLINT value when it sends it to the database.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setShort(int parameterIndex, short x) throws SQLException
+ {
+ set(parameterIndex, Integer.toString(x));
+ }
+
+ /*
+ * Set a parameter to a Java int value. The driver converts this to
+ * a SQL INTEGER value when it sends it to the database.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setInt(int parameterIndex, int x) throws SQLException
+ {
+ set(parameterIndex, Integer.toString(x));
+ }
+
+ /*
+ * Set a parameter to a Java long value. The driver converts this to
+ * a SQL BIGINT value when it sends it to the database.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setLong(int parameterIndex, long x) throws SQLException
+ {
+ set(parameterIndex, Long.toString(x));
+ }
+
+ /*
+ * Set a parameter to a Java float value. The driver converts this
+ * to a SQL FLOAT value when it sends it to the database.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setFloat(int parameterIndex, float x) throws SQLException
+ {
+ set(parameterIndex, Float.toString(x));
+ }
+
+ /*
+ * Set a parameter to a Java double value. The driver converts this
+ * to a SQL DOUBLE value when it sends it to the database
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setDouble(int parameterIndex, double x) throws SQLException
+ {
+ set(parameterIndex, Double.toString(x));
+ }
+
+ /*
+ * Set a parameter to a java.lang.BigDecimal value. The driver
+ * converts this to a SQL NUMERIC value when it sends it to the
+ * database.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
+ {
+ if (x == null)
+ setNull(parameterIndex, Types.OTHER);
+ else
+ {
+ set(parameterIndex, x.toString());
+ }
+ }
+
+ /*
+ * Set a parameter to a Java String value. The driver converts this
+ * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
+ * size relative to the driver's limits on VARCHARs) when it sends it
+ * to the database.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setString(int parameterIndex, String x) throws SQLException
+ {
+ // if the passed string is null, then set this column to null
+ if (x == null)
+ setNull(parameterIndex, Types.OTHER);
+ else
+ {
+ // use the shared buffer object. Should never clash but this makes
+ // us thread safe!
+ synchronized (sbuf)
+ {
+ sbuf.setLength(0);
+ int i;
+
+ sbuf.append('\'');
+ for (i = 0 ; i < x.length() ; ++i)
+ {
+ char c = x.charAt(i);
+ if (c == '\\' || c == '\'')
+ sbuf.append((char)'\\');
+ sbuf.append(c);
+ }
+ sbuf.append('\'');
+ set(parameterIndex, sbuf.toString());
+ }
+ }
+ }
+
+ /*
+ * Set a parameter to a Java array of bytes. The driver converts this
+ * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
+ * size relative to the driver's limits on VARBINARYs) when it sends
+ * it to the database.
+ *
+ *
With org.postgresql, this creates a large object, and stores the
+ * objects oid in this column.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setBytes(int parameterIndex, byte x[]) throws SQLException
+ {
+ if (connection.haveMinimumCompatibleVersion("7.2"))
+ {
+ //Version 7.2 supports the bytea datatype for byte arrays
+ if (null == x)
+ {
+ setNull(parameterIndex, Types.OTHER);
+ }
+ else
+ {
+ setString(parameterIndex, PGbytea.toPGString(x));
+ }
+ }
+ else
+ {
+ //Version 7.1 and earlier support done as LargeObjects
+ LargeObjectManager lom = connection.getLargeObjectAPI();
+ int oid = lom.create();
+ LargeObject lob = lom.open(oid);
+ lob.write(x);
+ lob.close();
+ setInt(parameterIndex, oid);
+ }
+ }
+
+ /*
+ * Set a parameter to a java.sql.Date value. The driver converts this
+ * to a SQL DATE value when it sends it to the database.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
+ {
+ if (null == x)
+ {
+ setNull(parameterIndex, Types.OTHER);
+ }
+ else
+ {
+ set(parameterIndex, "'" + x.toString() + "'");
+ }
+ }
+
+ /*
+ * Set a parameter to a java.sql.Time value. The driver converts
+ * this to a SQL TIME value when it sends it to the database.
+ *
+ * @param parameterIndex the first parameter is 1...));
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setTime(int parameterIndex, Time x) throws SQLException
+ {
+ if (null == x)
+ {
+ setNull(parameterIndex, Types.OTHER);
+ }
+ else
+ {
+ set(parameterIndex, "'" + x.toString() + "'");
+ }
+ }
+
+ /*
+ * Set a parameter to a java.sql.Timestamp value. The driver converts
+ * this to a SQL TIMESTAMP value when it sends it to the database.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
+ {
+ if (null == x)
+ {
+ setNull(parameterIndex, Types.OTHER);
+ }
+ else
+ {
+ // Use the shared StringBuffer
+ synchronized (sbuf)
+ {
+ sbuf.setLength(0);
+ sbuf.append("'");
+ //format the timestamp
+ //we do our own formating so that we can get a format
+ //that works with both timestamp with time zone and
+ //timestamp without time zone datatypes.
+ //The format is '2002-01-01 23:59:59.123456-0130'
+ //we need to include the local time and timezone offset
+ //so that timestamp without time zone works correctly
+ int l_year = x.getYear() + 1900;
+ sbuf.append(l_year);
+ sbuf.append('-');
+ int l_month = x.getMonth() + 1;
+ if (l_month < 10) sbuf.append('0');
+ sbuf.append(l_month);
+ sbuf.append('-');
+ int l_day = x.getDate();
+ if (l_day < 10) sbuf.append('0');
+ sbuf.append(l_day);
+ sbuf.append(' ');
+ int l_hours = x.getHours();
+ if (l_hours < 10) sbuf.append('0');
+ sbuf.append(l_hours);
+ sbuf.append(':');
+ int l_minutes = x.getMinutes();
+ if (l_minutes < 10) sbuf.append('0');
+ sbuf.append(l_minutes);
+ sbuf.append(':');
+ int l_seconds = x.getSeconds();
+ if (l_seconds < 10) sbuf.append('0');
+ sbuf.append(l_seconds);
+ // Make decimal from nanos.
+ char[] l_decimal = {'0','0','0','0','0','0','0','0','0'};
+ char[] l_nanos = Integer.toString(x.getNanos()).toCharArray();
+ System.arraycopy(l_nanos, 0, l_decimal, l_decimal.length - l_nanos.length, l_nanos.length);
+ sbuf.append('.');
+ if (connection.haveMinimumServerVersion("7.2")) {
+ sbuf.append(l_decimal,0,6);
+ } else {
+ // Because 7.1 include bug that "hh:mm:59.999" becomes "hh:mm:60.00".
+ sbuf.append(l_decimal,0,2);
+ }
+ //add timezone offset
+ int l_offset = -(x.getTimezoneOffset());
+ int l_houros = l_offset/60;
+ if (l_houros >= 0) {
+ sbuf.append('+');
+ } else {
+ sbuf.append('-');
+ }
+ if (l_houros > -10 && l_houros < 10) sbuf.append('0');
+ if (l_houros >= 0) {
+ sbuf.append(l_houros);
+ } else {
+ sbuf.append(-l_houros);
+ }
+ int l_minos = l_offset - (l_houros *60);
+ if (l_minos != 0) {
+ if (l_minos < 10) sbuf.append('0');
+ sbuf.append(l_minos);
+ }
+ sbuf.append("'");
+ set(parameterIndex, sbuf.toString());
+ }
+
+ }
+ }
+
+ /*
+ * When a very large ASCII value is input to a LONGVARCHAR parameter,
+ * it may be more practical to send it via a java.io.InputStream.
+ * JDBC will read the data from the stream as needed, until it reaches
+ * end-of-file. The JDBC driver will do any necessary conversion from
+ * ASCII to the database char format.
+ *
+ *
Note: This stream object can either be a standard Java
+ * stream object or your own subclass that implements the standard
+ * interface.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @param length the number of bytes in the stream
+ * @exception SQLException if a database access error occurs
+ */
+ public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
+ {
+ if (connection.haveMinimumCompatibleVersion("7.2"))
+ {
+ //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
+ //As the spec/javadoc for this method indicate this is to be used for
+ //large String values (i.e. LONGVARCHAR) PG doesn't have a separate
+ //long varchar datatype, but with toast all text datatypes are capable of
+ //handling very large values. Thus the implementation ends up calling
+ //setString() since there is no current way to stream the value to the server
+ try
+ {
+ InputStreamReader l_inStream = new InputStreamReader(x, "ASCII");
+ char[] l_chars = new char[length];
+ int l_charsRead = l_inStream.read(l_chars, 0, length);
+ setString(parameterIndex, new String(l_chars, 0, l_charsRead));
+ }
+ catch (UnsupportedEncodingException l_uee)
+ {
+ throw new PSQLException("postgresql.unusual", l_uee);
+ }
+ catch (IOException l_ioe)
+ {
+ throw new PSQLException("postgresql.unusual", l_ioe);
+ }
+ }
+ else
+ {
+ //Version 7.1 supported only LargeObjects by treating everything
+ //as binary data
+ setBinaryStream(parameterIndex, x, length);
+ }
+ }
+
+ /*
+ * When a very large Unicode value is input to a LONGVARCHAR parameter,
+ * it may be more practical to send it via a java.io.InputStream.
+ * JDBC will read the data from the stream as needed, until it reaches
+ * end-of-file. The JDBC driver will do any necessary conversion from
+ * UNICODE to the database char format.
+ *
+ *
Note: This stream object can either be a standard Java
+ * stream object or your own subclass that implements the standard
+ * interface.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
+ {
+ if (connection.haveMinimumCompatibleVersion("7.2"))
+ {
+ //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
+ //As the spec/javadoc for this method indicate this is to be used for
+ //large String values (i.e. LONGVARCHAR) PG doesn't have a separate
+ //long varchar datatype, but with toast all text datatypes are capable of
+ //handling very large values. Thus the implementation ends up calling
+ //setString() since there is no current way to stream the value to the server
+ try
+ {
+ InputStreamReader l_inStream = new InputStreamReader(x, "UTF-8");
+ char[] l_chars = new char[length];
+ int l_charsRead = l_inStream.read(l_chars, 0, length);
+ setString(parameterIndex, new String(l_chars, 0, l_charsRead));
+ }
+ catch (UnsupportedEncodingException l_uee)
+ {
+ throw new PSQLException("postgresql.unusual", l_uee);
+ }
+ catch (IOException l_ioe)
+ {
+ throw new PSQLException("postgresql.unusual", l_ioe);
+ }
+ }
+ else
+ {
+ //Version 7.1 supported only LargeObjects by treating everything
+ //as binary data
+ setBinaryStream(parameterIndex, x, length);
+ }
+ }
+
+ /*
+ * When a very large binary value is input to a LONGVARBINARY parameter,
+ * it may be more practical to send it via a java.io.InputStream.
+ * JDBC will read the data from the stream as needed, until it reaches
+ * end-of-file.
+ *
+ *
Note: This stream object can either be a standard Java
+ * stream object or your own subclass that implements the standard
+ * interface.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the parameter value
+ * @exception SQLException if a database access error occurs
+ */
+ public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
+ {
+ if (connection.haveMinimumCompatibleVersion("7.2"))
+ {
+ //Version 7.2 supports BinaryStream for for the PG bytea type
+ //As the spec/javadoc for this method indicate this is to be used for
+ //large binary values (i.e. LONGVARBINARY) PG doesn't have a separate
+ //long binary datatype, but with toast the bytea datatype is capable of
+ //handling very large values. Thus the implementation ends up calling
+ //setBytes() since there is no current way to stream the value to the server
+ byte[] l_bytes = new byte[length];
+ int l_bytesRead;
+ try
+ {
+ l_bytesRead = x.read(l_bytes, 0, length);
+ }
+ catch (IOException l_ioe)
+ {
+ throw new PSQLException("postgresql.unusual", l_ioe);
+ }
+ if (l_bytesRead == length)
+ {
+ setBytes(parameterIndex, l_bytes);
+ }
+ else
+ {
+ //the stream contained less data than they said
+ byte[] l_bytes2 = new byte[l_bytesRead];
+ System.arraycopy(l_bytes, 0, l_bytes2, 0, l_bytesRead);
+ setBytes(parameterIndex, l_bytes2);
+ }
+ }
+ else
+ {
+ //Version 7.1 only supported streams for LargeObjects
+ //but the jdbc spec indicates that streams should be
+ //available for LONGVARBINARY instead
+ LargeObjectManager lom = connection.getLargeObjectAPI();
+ int oid = lom.create();
+ LargeObject lob = lom.open(oid);
+ OutputStream los = lob.getOutputStream();
+ try
+ {
+ // could be buffered, but then the OutputStream returned by LargeObject
+ // is buffered internally anyhow, so there would be no performance
+ // boost gained, if anything it would be worse!
+ int c = x.read();
+ int p = 0;
+ while (c > -1 && p < length)
+ {
+ los.write(c);
+ c = x.read();
+ p++;
+ }
+ los.close();
+ }
+ catch (IOException se)
+ {
+ throw new PSQLException("postgresql.unusual", se);
+ }
+ // lob is closed by the stream so don't call lob.close()
+ setInt(parameterIndex, oid);
+ }
+ }
+
+
+ /*
+ * In general, parameter values remain in force for repeated used of a
+ * Statement. Setting a parameter value automatically clears its
+ * previous value. However, in coms cases, it is useful to immediately
+ * release the resources used by the current parameter values; this
+ * can be done by calling clearParameters
+ *
+ * @exception SQLException if a database access error occurs
+ */
+ public void clearParameters() throws SQLException
+ {
+ int i;
+
+ for (i = 0 ; i < inStrings.length ; i++)
+ inStrings[i] = null;
+ }
+
+ /*
+ * Set the value of a parameter using an object; use the java.lang
+ * equivalent objects for integral values.
+ *
+ *
The given Java object will be converted to the targetSqlType before
+ * being sent to the database.
+ *
+ *
note that this method may be used to pass database-specific
+ * abstract data types. This is done by using a Driver-specific
+ * Java type and using a targetSqlType of java.sql.Types.OTHER
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the object containing the input parameter value
+ * @param targetSqlType The SQL type to be send to the database
+ * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
+ * * types this is the number of digits after the decimal. For
+ * * all other types this value will be ignored.
+ * @exception SQLException if a database access error occurs
+ */
+ public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
+ {
+ if (x == null)
+ {
+ setNull(parameterIndex, Types.OTHER);
+ return;
+ }
+ switch (targetSqlType)
+ {
+ case Types.TINYINT:
+ case Types.SMALLINT:
+ case Types.INTEGER:
+ case Types.BIGINT:
+ case Types.REAL:
+ case Types.FLOAT:
+ case Types.DOUBLE:
+ case Types.DECIMAL:
+ case Types.NUMERIC:
+ if (x instanceof Boolean)
+ set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
+ else
+ set(parameterIndex, x.toString());
+ break;
+ case Types.CHAR:
+ case Types.VARCHAR:
+ case Types.LONGVARCHAR:
+ setString(parameterIndex, x.toString());
+ break;
+ case Types.DATE:
+ setDate(parameterIndex, (java.sql.Date)x);
+ break;
+ case Types.TIME:
+ setTime(parameterIndex, (Time)x);
+ break;
+ case Types.TIMESTAMP:
+ setTimestamp(parameterIndex, (Timestamp)x);
+ break;
+ case Types.BIT:
+ if (x instanceof Boolean)
+ {
+ set(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE");
+ }
+ else
+ {
+ throw new PSQLException("postgresql.prep.type");
+ }
+ break;
+ case Types.BINARY:
+ case Types.VARBINARY:
+ setObject(parameterIndex, x);
+ break;
+ case Types.OTHER:
+ setString(parameterIndex, ((PGobject)x).getValue());
+ break;
+ default:
+ throw new PSQLException("postgresql.prep.type");
+ }
+ }
+
+ public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
+ {
+ setObject(parameterIndex, x, targetSqlType, 0);
+ }
+
+ /*
+ * This stores an Object into a parameter.
+ *
New for 6.4, if the object is not recognised, but it is
+ * Serializable, then the object is serialised using the
+ * org.postgresql.util.Serialize class.
+ */
+ public void setObject(int parameterIndex, Object x) throws SQLException
+ {
+ if (x == null)
+ {
+ setNull(parameterIndex, Types.OTHER);
+ return;
+ }
+ if (x instanceof String)
+ setString(parameterIndex, (String)x);
+ else if (x instanceof BigDecimal)
+ setBigDecimal(parameterIndex, (BigDecimal)x);
+ else if (x instanceof Short)
+ setShort(parameterIndex, ((Short)x).shortValue());
+ else if (x instanceof Integer)
+ setInt(parameterIndex, ((Integer)x).intValue());
+ else if (x instanceof Long)
+ setLong(parameterIndex, ((Long)x).longValue());
+ else if (x instanceof Float)
+ setFloat(parameterIndex, ((Float)x).floatValue());
+ else if (x instanceof Double)
+ setDouble(parameterIndex, ((Double)x).doubleValue());
+ else if (x instanceof byte[])
+ setBytes(parameterIndex, (byte[])x);
+ else if (x instanceof java.sql.Date)
+ setDate(parameterIndex, (java.sql.Date)x);
+ else if (x instanceof Time)
+ setTime(parameterIndex, (Time)x);
+ else if (x instanceof Timestamp)
+ setTimestamp(parameterIndex, (Timestamp)x);
+ else if (x instanceof Boolean)
+ setBoolean(parameterIndex, ((Boolean)x).booleanValue());
+ else if (x instanceof PGobject)
+ setString(parameterIndex, ((PGobject)x).getValue());
+ else
+ // Try to store java object in database
+ setSerialize(parameterIndex, connection.storeObject(x), x.getClass().getName() );
+ }
+
+ /*
+ * Returns the SQL statement with the current template values
+ * substituted.
+ * NB: This is identical to compileQuery() except instead of throwing
+ * SQLException if a parameter is null, it places ? instead.
+ */
+ public String toString()
+ {
+ synchronized (sbuf)
+ {
+ sbuf.setLength(0);
+ int i;
+
+ for (i = 0 ; i < inStrings.length ; ++i)
+ {
+ if (inStrings[i] == null)
+ sbuf.append( '?' );
+ else
+ sbuf.append (templateStrings[i]);
+ sbuf.append (inStrings[i]);
+ }
+ sbuf.append(templateStrings[inStrings.length]);
+ return sbuf.toString();
+ }
+ }
+
+ /*
+ * There are a lot of setXXX classes which all basically do
+ * the same thing. We need a method which actually does the
+ * set for us.
+ *
+ * @param paramIndex the index into the inString
+ * @param s a string to be stored
+ * @exception SQLException if something goes wrong
+ */
+ protected void set(int paramIndex, String s) throws SQLException
+ {
+ if (paramIndex < 1 || paramIndex > inStrings.length)
+ throw new PSQLException("postgresql.prep.range");
+ inStrings[paramIndex - 1] = s;
+ }
+
+ /*
+ * Helper - this compiles the SQL query from the various parameters
+ * This is identical to toString() except it throws an exception if a
+ * parameter is unused.
+ */
+ protected synchronized String compileQuery()
+ throws SQLException
+ {
+ sbuf.setLength(0);
+ int i;
+
+ for (i = 0 ; i < inStrings.length ; ++i)
+ {
+ if (inStrings[i] == null)
+ throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
+ sbuf.append (templateStrings[i]).append (inStrings[i]);
+ }
+ sbuf.append(templateStrings[inStrings.length]);
+ return sbuf.toString();
+ }
+
+ /*
+ * Set a parameter to a tablerow-type oid reference.
+ *
+ * @param parameterIndex the first parameter is 1...
+ * @param x the oid of the object from org.postgresql.util.Serialize.store
+ * @param classname the classname of the java object x
+ * @exception SQLException if a database access error occurs
+ */
+ private void setSerialize(int parameterIndex, long x, String classname) throws SQLException
+ {
+ // converts . to _, toLowerCase, and ensures length<32
+ String tablename = Serialize.toPostgreSQL( classname );
+ DriverManager.println("setSerialize: setting " + x + "::" + tablename );
+
+ // OID reference to tablerow-type must be cast like:
::
+ // Note that postgres support for tablerow data types is incomplete/broken.
+ // This cannot be just a plain OID because then there would be ambiguity
+ // between when you want the oid itself and when you want the object
+ // an oid references.
+ set(parameterIndex, Long.toString(x) + "::" + tablename );
+ }
}
* @see ResultSet
*/
-public class CallableStatement extends PreparedStatement implements java.sql.CallableStatement
+public class CallableStatement extends Jdbc1PreparedStatement implements java.sql.CallableStatement
{
/*
* @exception SQLException on failure
import org.postgresql.Field;
import org.postgresql.util.PSQLException;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Connection.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Connection.java,v 1.2 2002/07/24 22:08:40 barry Exp $
* This class implements the java.sql.Connection interface for JDBC1.
* However most of the implementation is really done in
* org.postgresql.jdbc1.AbstractJdbc1Connection
public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
{
- return new org.postgresql.jdbc1.PreparedStatement(this, sql);
+ return new org.postgresql.jdbc1.Jdbc1PreparedStatement(this, sql);
}
//BJL TODO - merge callable statement logic from jdbc2 to jdbc1
--- /dev/null
+package org.postgresql.jdbc1;
+
+
+import java.sql.*;
+
+public class Jdbc1PreparedStatement extends AbstractJdbc1Statement implements PreparedStatement
+{
+
+ public Jdbc1PreparedStatement(Jdbc1Connection connection, String sql) throws SQLException
+ {
+ super(connection, sql);
+ }
+
+}
import java.sql.*;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Statement.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Statement.java,v 1.2 2002/07/24 22:08:40 barry Exp $
* This class implements the java.sql.Statement interface for JDBC1.
* However most of the implementation is really done in
* org.postgresql.jdbc1.AbstractJdbc1Statement
public Jdbc1Statement (Jdbc1Connection c)
{
- connection = c;
+ super(c);
}
}
+++ /dev/null
-package org.postgresql.jdbc1;
-
-// IMPORTANT NOTE: This file implements the JDBC 1 version of the driver.
-// If you make any modifications to this file, you must make sure that the
-// changes are also made (if relevent) to the related JDBC 2 class in the
-// org.postgresql.jdbc2 package.
-
-import java.io.*;
-import java.math.*;
-import java.sql.*;
-import java.text.*;
-import java.util.*;
-import org.postgresql.largeobject.*;
-import org.postgresql.util.*;
-
-/*
- * A SQL Statement is pre-compiled and stored in a PreparedStatement object.
- * This object can then be used to efficiently execute this statement multiple
- * times.
- *
- *
Note: The setXXX methods for setting IN parameter values must
- * specify types that are compatible with the defined SQL type of the input
- * parameter. For instance, if the IN parameter has SQL type Integer, then
- * setInt should be used.
- *
- *
If arbitrary parameter type conversions are required, then the setObject
- * method should be used with a target SQL type.
- *
- * @see ResultSet
- * @see java.sql.PreparedStatement
- */
-public class PreparedStatement extends Jdbc1Statement implements java.sql.PreparedStatement
-{
- String sql;
- String[] templateStrings;
- String[] inStrings;
- Jdbc1Connection connection;
-
- // Some performance caches
- private StringBuffer sbuf = new StringBuffer();
-
- /*
- * Constructor for the PreparedStatement class.
- * Split the SQL statement into segments - separated by the arguments.
- * When we rebuild the thing with the arguments, we can substitute the
- * args and join the whole thing together.
- *
- * @param conn the instanatiating connection
- * @param sql the SQL statement with ? for IN markers
- * @exception SQLException if something bad occurs
- */
- public PreparedStatement(Jdbc1Connection connection, String sql) throws SQLException
- {
- super(connection);
-
- Vector v = new Vector();
- boolean inQuotes = false;
- int lastParmEnd = 0, i;
-
- this.sql = sql;
- this.connection = connection;
- for (i = 0; i < sql.length(); ++i)
- {
- int c = sql.charAt(i);
-
- if (c == '\'')
- inQuotes = !inQuotes;
- if (c == '?' && !inQuotes)
- {
- v.addElement(sql.substring (lastParmEnd, i));
- lastParmEnd = i + 1;
- }
- }
- v.addElement(sql.substring (lastParmEnd, sql.length()));
-
- templateStrings = new String[v.size()];
- inStrings = new String[v.size() - 1];
- clearParameters();
-
- for (i = 0 ; i < templateStrings.length; ++i)
- templateStrings[i] = (String)v.elementAt(i);
- }
-
- /*
- * A Prepared SQL query is executed and its ResultSet is returned
- *
- * @return a ResultSet that contains the data produced by the
- * * query - never null
- * @exception SQLException if a database access error occurs
- */
- public java.sql.ResultSet executeQuery() throws SQLException
- {
- StringBuffer s = new StringBuffer();
- int i;
-
- for (i = 0 ; i < inStrings.length ; ++i)
- {
- if (inStrings[i] == null)
- throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
- s.append (templateStrings[i]);
- s.append (inStrings[i]);
- }
- s.append(templateStrings[inStrings.length]);
- return super.executeQuery(s.toString()); // in Statement class
- }
-
- /*
- * Execute a SQL INSERT, UPDATE or DELETE statement. In addition,
- * SQL statements that return nothing such as SQL DDL statements can
- * be executed.
- *
- * @return either the row count for INSERT, UPDATE or DELETE; or
- * * 0 for SQL statements that return nothing.
- * @exception SQLException if a database access error occurs
- */
- public int executeUpdate() throws SQLException
- {
- StringBuffer s = new StringBuffer();
- int i;
-
- for (i = 0 ; i < inStrings.length ; ++i)
- {
- if (inStrings[i] == null)
- throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
- s.append (templateStrings[i]);
- s.append (inStrings[i]);
- }
- s.append(templateStrings[inStrings.length]);
- return super.executeUpdate(s.toString()); // in Statement class
- }
-
- /*
- * Set a parameter to SQL NULL
- *
- *
Note: You must specify the parameters SQL type (although
- * PostgreSQL ignores it)
- *
- * @param parameterIndex the first parameter is 1, etc...
- * @param sqlType the SQL type code defined in java.sql.Types
- * @exception SQLException if a database access error occurs
- */
- public void setNull(int parameterIndex, int sqlType) throws SQLException
- {
- set(parameterIndex, "null");
- }
-
- /*
- * Set a parameter to a Java boolean value. The driver converts this
- * to a SQL BIT value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setBoolean(int parameterIndex, boolean x) throws SQLException
- {
- set(parameterIndex, x ? "'t'" : "'f'");
- }
-
- /*
- * Set a parameter to a Java byte value. The driver converts this to
- * a SQL TINYINT value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setByte(int parameterIndex, byte x) throws SQLException
- {
- set(parameterIndex, Integer.toString(x));
- }
-
- /*
- * Set a parameter to a Java short value. The driver converts this
- * to a SQL SMALLINT value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setShort(int parameterIndex, short x) throws SQLException
- {
- set(parameterIndex, Integer.toString(x));
- }
-
- /*
- * Set a parameter to a Java int value. The driver converts this to
- * a SQL INTEGER value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setInt(int parameterIndex, int x) throws SQLException
- {
- set(parameterIndex, Integer.toString(x));
- }
-
- /*
- * Set a parameter to a Java long value. The driver converts this to
- * a SQL BIGINT value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setLong(int parameterIndex, long x) throws SQLException
- {
- set(parameterIndex, Long.toString(x));
- }
-
- /*
- * Set a parameter to a Java float value. The driver converts this
- * to a SQL FLOAT value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setFloat(int parameterIndex, float x) throws SQLException
- {
- set(parameterIndex, Float.toString(x));
- }
-
- /*
- * Set a parameter to a Java double value. The driver converts this
- * to a SQL DOUBLE value when it sends it to the database
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setDouble(int parameterIndex, double x) throws SQLException
- {
- set(parameterIndex, Double.toString(x));
- }
-
- /*
- * Set a parameter to a java.lang.BigDecimal value. The driver
- * converts this to a SQL NUMERIC value when it sends it to the
- * database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
- {
- if (x == null)
- setNull(parameterIndex, Types.OTHER);
- else
- {
- set(parameterIndex, x.toString());
- }
- }
-
- /*
- * Set a parameter to a Java String value. The driver converts this
- * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
- * size relative to the driver's limits on VARCHARs) when it sends it
- * to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setString(int parameterIndex, String x) throws SQLException
- {
- // if the passed string is null, then set this column to null
- if (x == null)
- setNull(parameterIndex, Types.OTHER);
- else
- {
- StringBuffer b = new StringBuffer();
- int i;
-
- b.append('\'');
- for (i = 0 ; i < x.length() ; ++i)
- {
- char c = x.charAt(i);
- if (c == '\\' || c == '\'')
- b.append((char)'\\');
- b.append(c);
- }
- b.append('\'');
- set(parameterIndex, b.toString());
- }
- }
-
- /*
- * Set a parameter to a Java array of bytes. The driver converts this
- * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
- * size relative to the driver's limits on VARBINARYs) when it sends
- * it to the database.
- *
- *
With org.postgresql, this creates a large object, and stores the
- * objects oid in this column.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setBytes(int parameterIndex, byte x[]) throws SQLException
- {
- if (connection.haveMinimumCompatibleVersion("7.2"))
- {
- //Version 7.2 supports the bytea datatype for byte arrays
- if (null == x)
- {
- setNull(parameterIndex, Types.OTHER);
- }
- else
- {
- setString(parameterIndex, PGbytea.toPGString(x));
- }
- }
- else
- {
- //Version 7.1 and earlier support done as LargeObjects
- LargeObjectManager lom = connection.getLargeObjectAPI();
- int oid = lom.create();
- LargeObject lob = lom.open(oid);
- lob.write(x);
- lob.close();
- setInt(parameterIndex, oid);
- }
- }
-
- /*
- * Set a parameter to a java.sql.Date value. The driver converts this
- * to a SQL DATE value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
- {
- if (null == x)
- {
- setNull(parameterIndex, Types.OTHER);
- }
- else
- {
- set(parameterIndex, "'" + x.toString() + "'");
- }
- }
-
- /*
- * Set a parameter to a java.sql.Time value. The driver converts
- * this to a SQL TIME value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...));
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setTime(int parameterIndex, Time x) throws SQLException
- {
- if (null == x)
- {
- setNull(parameterIndex, Types.OTHER);
- }
- else
- {
- set(parameterIndex, "'" + x.toString() + "'");
- }
- }
-
- /*
- * Set a parameter to a java.sql.Timestamp value. The driver converts
- * this to a SQL TIMESTAMP value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
- {
- if (null == x)
- {
- setNull(parameterIndex, Types.OTHER);
- }
- else
- {
- // Use the shared StringBuffer
- synchronized (sbuf)
- {
- sbuf.setLength(0);
- sbuf.append("'");
- //format the timestamp
- //we do our own formating so that we can get a format
- //that works with both timestamp with time zone and
- //timestamp without time zone datatypes.
- //The format is '2002-01-01 23:59:59.123456-0130'
- //we need to include the local time and timezone offset
- //so that timestamp without time zone works correctly
- int l_year = x.getYear() + 1900;
- sbuf.append(l_year);
- sbuf.append('-');
- int l_month = x.getMonth() + 1;
- if (l_month < 10) sbuf.append('0');
- sbuf.append(l_month);
- sbuf.append('-');
- int l_day = x.getDate();
- if (l_day < 10) sbuf.append('0');
- sbuf.append(l_day);
- sbuf.append(' ');
- int l_hours = x.getHours();
- if (l_hours < 10) sbuf.append('0');
- sbuf.append(l_hours);
- sbuf.append(':');
- int l_minutes = x.getMinutes();
- if (l_minutes < 10) sbuf.append('0');
- sbuf.append(l_minutes);
- sbuf.append(':');
- int l_seconds = x.getSeconds();
- if (l_seconds < 10) sbuf.append('0');
- sbuf.append(l_seconds);
- // Make decimal from nanos.
- char[] l_decimal = {'0','0','0','0','0','0','0','0','0'};
- char[] l_nanos = Integer.toString(x.getNanos()).toCharArray();
- System.arraycopy(l_nanos, 0, l_decimal, l_decimal.length - l_nanos.length, l_nanos.length);
- sbuf.append('.');
- if (connection.haveMinimumServerVersion("7.2")) {
- sbuf.append(l_decimal,0,6);
- } else {
- // Because 7.1 include bug that "hh:mm:59.999" becomes "hh:mm:60.00".
- sbuf.append(l_decimal,0,2);
- }
- //add timezone offset
- int l_offset = -(x.getTimezoneOffset());
- int l_houros = l_offset/60;
- if (l_houros >= 0) {
- sbuf.append('+');
- } else {
- sbuf.append('-');
- }
- if (l_houros > -10 && l_houros < 10) sbuf.append('0');
- if (l_houros >= 0) {
- sbuf.append(l_houros);
- } else {
- sbuf.append(-l_houros);
- }
- int l_minos = l_offset - (l_houros *60);
- if (l_minos != 0) {
- if (l_minos < 10) sbuf.append('0');
- sbuf.append(l_minos);
- }
- sbuf.append("'");
- set(parameterIndex, sbuf.toString());
- }
-
- }
- }
-
- /*
- * When a very large ASCII value is input to a LONGVARCHAR parameter,
- * it may be more practical to send it via a java.io.InputStream.
- * JDBC will read the data from the stream as needed, until it reaches
- * end-of-file. The JDBC driver will do any necessary conversion from
- * ASCII to the database char format.
- *
- *
Note: This stream object can either be a standard Java
- * stream object or your own subclass that implements the standard
- * interface.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @param length the number of bytes in the stream
- * @exception SQLException if a database access error occurs
- */
- public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
- {
- if (connection.haveMinimumCompatibleVersion("7.2"))
- {
- //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
- //As the spec/javadoc for this method indicate this is to be used for
- //large String values (i.e. LONGVARCHAR) PG doesn't have a separate
- //long varchar datatype, but with toast all text datatypes are capable of
- //handling very large values. Thus the implementation ends up calling
- //setString() since there is no current way to stream the value to the server
- try
- {
- InputStreamReader l_inStream = new InputStreamReader(x, "ASCII");
- char[] l_chars = new char[length];
- int l_charsRead = l_inStream.read(l_chars, 0, length);
- setString(parameterIndex, new String(l_chars, 0, l_charsRead));
- }
- catch (UnsupportedEncodingException l_uee)
- {
- throw new PSQLException("postgresql.unusual", l_uee);
- }
- catch (IOException l_ioe)
- {
- throw new PSQLException("postgresql.unusual", l_ioe);
- }
- }
- else
- {
- //Version 7.1 supported only LargeObjects by treating everything
- //as binary data
- setBinaryStream(parameterIndex, x, length);
- }
- }
-
- /*
- * When a very large Unicode value is input to a LONGVARCHAR parameter,
- * it may be more practical to send it via a java.io.InputStream.
- * JDBC will read the data from the stream as needed, until it reaches
- * end-of-file. The JDBC driver will do any necessary conversion from
- * UNICODE to the database char format.
- *
- *
Note: This stream object can either be a standard Java
- * stream object or your own subclass that implements the standard
- * interface.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
- {
- if (connection.haveMinimumCompatibleVersion("7.2"))
- {
- //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
- //As the spec/javadoc for this method indicate this is to be used for
- //large String values (i.e. LONGVARCHAR) PG doesn't have a separate
- //long varchar datatype, but with toast all text datatypes are capable of
- //handling very large values. Thus the implementation ends up calling
- //setString() since there is no current way to stream the value to the server
- try
- {
- InputStreamReader l_inStream = new InputStreamReader(x, "UTF-8");
- char[] l_chars = new char[length];
- int l_charsRead = l_inStream.read(l_chars, 0, length);
- setString(parameterIndex, new String(l_chars, 0, l_charsRead));
- }
- catch (UnsupportedEncodingException l_uee)
- {
- throw new PSQLException("postgresql.unusual", l_uee);
- }
- catch (IOException l_ioe)
- {
- throw new PSQLException("postgresql.unusual", l_ioe);
- }
- }
- else
- {
- //Version 7.1 supported only LargeObjects by treating everything
- //as binary data
- setBinaryStream(parameterIndex, x, length);
- }
- }
-
- /*
- * When a very large binary value is input to a LONGVARBINARY parameter,
- * it may be more practical to send it via a java.io.InputStream.
- * JDBC will read the data from the stream as needed, until it reaches
- * end-of-file.
- *
- *
Note: This stream object can either be a standard Java
- * stream object or your own subclass that implements the standard
- * interface.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
- {
- if (connection.haveMinimumCompatibleVersion("7.2"))
- {
- //Version 7.2 supports BinaryStream for for the PG bytea type
- //As the spec/javadoc for this method indicate this is to be used for
- //large binary values (i.e. LONGVARBINARY) PG doesn't have a separate
- //long binary datatype, but with toast the bytea datatype is capable of
- //handling very large values. Thus the implementation ends up calling
- //setBytes() since there is no current way to stream the value to the server
- byte[] l_bytes = new byte[length];
- int l_bytesRead;
- try
- {
- l_bytesRead = x.read(l_bytes, 0, length);
- }
- catch (IOException l_ioe)
- {
- throw new PSQLException("postgresql.unusual", l_ioe);
- }
- if (l_bytesRead == length)
- {
- setBytes(parameterIndex, l_bytes);
- }
- else
- {
- //the stream contained less data than they said
- byte[] l_bytes2 = new byte[l_bytesRead];
- System.arraycopy(l_bytes, 0, l_bytes2, 0, l_bytesRead);
- setBytes(parameterIndex, l_bytes2);
- }
- }
- else
- {
- //Version 7.1 only supported streams for LargeObjects
- //but the jdbc spec indicates that streams should be
- //available for LONGVARBINARY instead
- LargeObjectManager lom = connection.getLargeObjectAPI();
- int oid = lom.create();
- LargeObject lob = lom.open(oid);
- OutputStream los = lob.getOutputStream();
- try
- {
- // could be buffered, but then the OutputStream returned by LargeObject
- // is buffered internally anyhow, so there would be no performance
- // boost gained, if anything it would be worse!
- int c = x.read();
- int p = 0;
- while (c > -1 && p < length)
- {
- los.write(c);
- c = x.read();
- p++;
- }
- los.close();
- }
- catch (IOException se)
- {
- throw new PSQLException("postgresql.unusual", se);
- }
- // lob is closed by the stream so don't call lob.close()
- setInt(parameterIndex, oid);
- }
- }
-
- /*
- * In general, parameter values remain in force for repeated used of a
- * Statement. Setting a parameter value automatically clears its
- * previous value. However, in coms cases, it is useful to immediately
- * release the resources used by the current parameter values; this
- * can be done by calling clearParameters
- *
- * @exception SQLException if a database access error occurs
- */
- public void clearParameters() throws SQLException
- {
- int i;
-
- for (i = 0 ; i < inStrings.length ; i++)
- inStrings[i] = null;
- }
-
- /*
- * Set the value of a parameter using an object; use the java.lang
- * equivalent objects for integral values.
- *
- *
The given Java object will be converted to the targetSqlType before
- * being sent to the database.
- *
- *
note that this method may be used to pass database-specific
- * abstract data types. This is done by using a Driver-specific
- * Java type and using a targetSqlType of java.sql.Types.OTHER
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the object containing the input parameter value
- * @param targetSqlType The SQL type to be send to the database
- * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
- * * types this is the number of digits after the decimal. For
- * * all other types this value will be ignored.
- * @exception SQLException if a database access error occurs
- */
- public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
- {
- if (x == null)
- {
- setNull(parameterIndex, Types.OTHER);
- return;
- }
- switch (targetSqlType)
- {
- case Types.TINYINT:
- case Types.SMALLINT:
- case Types.INTEGER:
- case Types.BIGINT:
- case Types.REAL:
- case Types.FLOAT:
- case Types.DOUBLE:
- case Types.DECIMAL:
- case Types.NUMERIC:
- if (x instanceof Boolean)
- set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
- else
- set(parameterIndex, x.toString());
- break;
- case Types.CHAR:
- case Types.VARCHAR:
- case Types.LONGVARCHAR:
- setString(parameterIndex, x.toString());
- break;
- case Types.DATE:
- setDate(parameterIndex, (java.sql.Date)x);
- break;
- case Types.TIME:
- setTime(parameterIndex, (Time)x);
- break;
- case Types.TIMESTAMP:
- setTimestamp(parameterIndex, (Timestamp)x);
- break;
- case Types.BIT:
- if (x instanceof Boolean)
- {
- set(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE");
- }
- else
- {
- throw new PSQLException("postgresql.prep.type");
- }
- break;
- case Types.BINARY:
- case Types.VARBINARY:
- setObject(parameterIndex, x);
- break;
- case Types.OTHER:
- setString(parameterIndex, ((PGobject)x).getValue());
- break;
- default:
- throw new PSQLException("postgresql.prep.type");
- }
- }
-
- public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
- {
- setObject(parameterIndex, x, targetSqlType, 0);
- }
-
- /*
- * This stores an Object into a parameter.
- *
New for 6.4, if the object is not recognised, but it is
- * Serializable, then the object is serialised using the
- * org.postgresql.util.Serialize class.
- */
- public void setObject(int parameterIndex, Object x) throws SQLException
- {
- if (x == null)
- {
- setNull(parameterIndex, Types.OTHER);
- return;
- }
- if (x instanceof String)
- setString(parameterIndex, (String)x);
- else if (x instanceof BigDecimal)
- setBigDecimal(parameterIndex, (BigDecimal)x);
- else if (x instanceof Short)
- setShort(parameterIndex, ((Short)x).shortValue());
- else if (x instanceof Integer)
- setInt(parameterIndex, ((Integer)x).intValue());
- else if (x instanceof Long)
- setLong(parameterIndex, ((Long)x).longValue());
- else if (x instanceof Float)
- setFloat(parameterIndex, ((Float)x).floatValue());
- else if (x instanceof Double)
- setDouble(parameterIndex, ((Double)x).doubleValue());
- else if (x instanceof byte[])
- setBytes(parameterIndex, (byte[])x);
- else if (x instanceof java.sql.Date)
- setDate(parameterIndex, (java.sql.Date)x);
- else if (x instanceof Time)
- setTime(parameterIndex, (Time)x);
- else if (x instanceof Timestamp)
- setTimestamp(parameterIndex, (Timestamp)x);
- else if (x instanceof Boolean)
- setBoolean(parameterIndex, ((Boolean)x).booleanValue());
- else if (x instanceof PGobject)
- setString(parameterIndex, ((PGobject)x).getValue());
- else
- setLong(parameterIndex, connection.storeObject(x));
- }
-
- /*
- * Some prepared statements return multiple results; the execute method
- * handles these complex statements as well as the simpler form of
- * statements handled by executeQuery and executeUpdate
- *
- * @return true if the next result is a ResultSet; false if it is an
- * * update count or there are no more results
- * @exception SQLException if a database access error occurs
- */
- public boolean execute() throws SQLException
- {
- StringBuffer s = new StringBuffer();
- int i;
-
- for (i = 0 ; i < inStrings.length ; ++i)
- {
- if (inStrings[i] == null)
- throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
- s.append (templateStrings[i]);
- s.append (inStrings[i]);
- }
- s.append(templateStrings[inStrings.length]);
- return super.execute(s.toString()); // in Statement class
- }
-
- /*
- * Returns the SQL statement with the current template values
- * substituted.
- */
- public String toString()
- {
- StringBuffer s = new StringBuffer();
- int i;
-
- for (i = 0 ; i < inStrings.length ; ++i)
- {
- if (inStrings[i] == null)
- s.append( '?' );
- else
- s.append (templateStrings[i]);
- s.append (inStrings[i]);
- }
- s.append(templateStrings[inStrings.length]);
- return s.toString();
- }
-
- // **************************************************************
- // END OF PUBLIC INTERFACE
- // **************************************************************
-
- /*
- * There are a lot of setXXX classes which all basically do
- * the same thing. We need a method which actually does the
- * set for us.
- *
- * @param paramIndex the index into the inString
- * @param s a string to be stored
- * @exception SQLException if something goes wrong
- */
- private void set(int paramIndex, String s) throws SQLException
- {
- if (paramIndex < 1 || paramIndex > inStrings.length)
- throw new PSQLException("postgresql.prep.range");
- inStrings[paramIndex - 1] = s;
- }
-}
import org.postgresql.util.PGbytea;
import org.postgresql.util.PSQLException;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.2 2002/07/24 22:08:42 barry Exp $
* This class defines methods of the jdbc2 specification. This class extends
* org.postgresql.jdbc1.AbstractJdbc1ResultSet which provides the jdbc1
* methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2ResultSet
*/
public class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet
{
- protected Jdbc2Statement statement;
+ protected Statement statement;
protected String sqlQuery=null;
}
// This one needs some thought, as not all ResultSets come from a statement
- public java.sql.Statement getStatement() throws SQLException
+ public Statement getStatement() throws SQLException
{
return statement;
}
* It's used currently by getStatement() but may also with the new core
* package.
*/
- public void setStatement(Jdbc2Statement statement)
+ public void setStatement(Statement statement)
{
this.statement = statement;
}
package org.postgresql.jdbc2;
+import java.io.*;
import java.sql.*;
import java.util.Vector;
+import org.postgresql.largeobject.*;
import org.postgresql.util.PSQLException;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.2 2002/07/24 22:08:42 barry Exp $
* This class defines methods of the jdbc2 specification. This class extends
* org.postgresql.jdbc1.AbstractJdbc1Statement which provides the jdbc1
* methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Statement
protected int resultsettype; // the resultset type to return
protected int concurrency; // is it updateable or not?
+ public AbstractJdbc2Statement (AbstractJdbc2Connection c)
+ {
+ super(c);
+ resultsettype = java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
+ concurrency = java.sql.ResultSet.CONCUR_READ_ONLY;
+ }
+
+ public AbstractJdbc2Statement(AbstractJdbc2Connection connection, String sql) throws SQLException
+ {
+ super(connection, sql);
+ }
+
/*
* Execute a SQL statement that may return multiple results. We
* don't have to worry about this since we do not support multiple
public boolean execute(String sql) throws SQLException
{
boolean l_return = super.execute(sql);
-
//Now do the jdbc2 specific stuff
//required for ResultSet.getStatement() to work
- ((AbstractJdbc2ResultSet)result).setStatement((Jdbc2Statement)this);
+ ((AbstractJdbc2ResultSet)result).setStatement((Statement)this);
// Added this so that the Updateable resultset knows the query that gave this
((AbstractJdbc2ResultSet)result).setSQLQuery(sql);
resultsettype = value;
}
+ public void addBatch() throws SQLException
+ {
+ addBatch(compileQuery());
+ }
+
+ public java.sql.ResultSetMetaData getMetaData() throws SQLException
+ {
+ java.sql.ResultSet rs = getResultSet();
+ if (rs != null)
+ return rs.getMetaData();
+
+ // Does anyone really know what this method does?
+ return null;
+ }
+
+ public void setArray(int i, java.sql.Array x) throws SQLException
+ {
+ setString(i, x.toString());
+ }
+
+ public void setBlob(int i, Blob x) throws SQLException
+ {
+ InputStream l_inStream = x.getBinaryStream();
+ int l_length = (int) x.length();
+ LargeObjectManager lom = connection.getLargeObjectAPI();
+ int oid = lom.create();
+ LargeObject lob = lom.open(oid);
+ OutputStream los = lob.getOutputStream();
+ try
+ {
+ // could be buffered, but then the OutputStream returned by LargeObject
+ // is buffered internally anyhow, so there would be no performance
+ // boost gained, if anything it would be worse!
+ int c = l_inStream.read();
+ int p = 0;
+ while (c > -1 && p < l_length)
+ {
+ los.write(c);
+ c = l_inStream.read();
+ p++;
+ }
+ los.close();
+ }
+ catch (IOException se)
+ {
+ throw new PSQLException("postgresql.unusual", se);
+ }
+ // lob is closed by the stream so don't call lob.close()
+ setInt(i, oid);
+ }
+
+ public void setCharacterStream(int i, java.io.Reader x, int length) throws SQLException
+ {
+ if (connection.haveMinimumCompatibleVersion("7.2"))
+ {
+ //Version 7.2 supports CharacterStream for for the PG text types
+ //As the spec/javadoc for this method indicate this is to be used for
+ //large text values (i.e. LONGVARCHAR) PG doesn't have a separate
+ //long varchar datatype, but with toast all the text datatypes are capable of
+ //handling very large values. Thus the implementation ends up calling
+ //setString() since there is no current way to stream the value to the server
+ char[] l_chars = new char[length];
+ int l_charsRead;
+ try
+ {
+ l_charsRead = x.read(l_chars, 0, length);
+ }
+ catch (IOException l_ioe)
+ {
+ throw new PSQLException("postgresql.unusual", l_ioe);
+ }
+ setString(i, new String(l_chars, 0, l_charsRead));
+ }
+ else
+ {
+ //Version 7.1 only supported streams for LargeObjects
+ //but the jdbc spec indicates that streams should be
+ //available for LONGVARCHAR instead
+ LargeObjectManager lom = connection.getLargeObjectAPI();
+ int oid = lom.create();
+ LargeObject lob = lom.open(oid);
+ OutputStream los = lob.getOutputStream();
+ try
+ {
+ // could be buffered, but then the OutputStream returned by LargeObject
+ // is buffered internally anyhow, so there would be no performance
+ // boost gained, if anything it would be worse!
+ int c = x.read();
+ int p = 0;
+ while (c > -1 && p < length)
+ {
+ los.write(c);
+ c = x.read();
+ p++;
+ }
+ los.close();
+ }
+ catch (IOException se)
+ {
+ throw new PSQLException("postgresql.unusual", se);
+ }
+ // lob is closed by the stream so don't call lob.close()
+ setInt(i, oid);
+ }
+ }
+
+ public void setClob(int i, Clob x) throws SQLException
+ {
+ InputStream l_inStream = x.getAsciiStream();
+ int l_length = (int) x.length();
+ LargeObjectManager lom = connection.getLargeObjectAPI();
+ int oid = lom.create();
+ LargeObject lob = lom.open(oid);
+ OutputStream los = lob.getOutputStream();
+ try
+ {
+ // could be buffered, but then the OutputStream returned by LargeObject
+ // is buffered internally anyhow, so there would be no performance
+ // boost gained, if anything it would be worse!
+ int c = l_inStream.read();
+ int p = 0;
+ while (c > -1 && p < l_length)
+ {
+ los.write(c);
+ c = l_inStream.read();
+ p++;
+ }
+ los.close();
+ }
+ catch (IOException se)
+ {
+ throw new PSQLException("postgresql.unusual", se);
+ }
+ // lob is closed by the stream so don't call lob.close()
+ setInt(i, oid);
+ }
+
+ public void setNull(int i, int t, String s) throws SQLException
+ {
+ setNull(i, t);
+ }
+
+ public void setRef(int i, Ref x) throws SQLException
+ {
+ throw org.postgresql.Driver.notImplemented();
+ }
+
+ public void setDate(int i, java.sql.Date d, java.util.Calendar cal) throws SQLException
+ {
+ if (cal == null)
+ setDate(i, d);
+ else
+ {
+ cal.setTime(d);
+ setDate(i, new java.sql.Date(cal.getTime().getTime()));
+ }
+ }
+
+ public void setTime(int i, Time t, java.util.Calendar cal) throws SQLException
+ {
+ if (cal == null)
+ setTime(i, t);
+ else
+ {
+ cal.setTime(t);
+ setTime(i, new java.sql.Time(cal.getTime().getTime()));
+ }
+ }
+
+ public void setTimestamp(int i, Timestamp t, java.util.Calendar cal) throws SQLException
+ {
+ if (cal == null)
+ setTimestamp(i, t);
+ else
+ {
+ cal.setTime(t);
+ setTimestamp(i, new java.sql.Timestamp(cal.getTime().getTime()));
+ }
+ }
}
* @author Paul Bethe (implementer)
*/
-public class CallableStatement extends org.postgresql.jdbc2.PreparedStatement implements java.sql.CallableStatement
+public class CallableStatement extends org.postgresql.jdbc2.Jdbc2PreparedStatement implements java.sql.CallableStatement
{
/*
* @exception SQLException on failure
import java.util.Vector;
import org.postgresql.Field;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.2 2002/07/24 22:08:42 barry Exp $
* This class implements the java.sql.Connection interface for JDBC2.
* However most of the implementation is really done in
* org.postgresql.jdbc2.AbstractJdbc2Connection or one of it's parents
public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{
- org.postgresql.jdbc2.PreparedStatement s = new org.postgresql.jdbc2.PreparedStatement(this, sql);
+ Jdbc2PreparedStatement s = new Jdbc2PreparedStatement(this, sql);
s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
--- /dev/null
+package org.postgresql.jdbc2;
+
+
+import java.sql.*;
+
+public class Jdbc2PreparedStatement extends AbstractJdbc2Statement implements java.sql.PreparedStatement
+{
+
+ public Jdbc2PreparedStatement(Jdbc2Connection connection, String sql) throws SQLException
+ {
+ super(connection, sql);
+ }
+
+}
+
import java.sql.*;
-/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Statement.java,v 1.1 2002/07/23 03:59:55 barry Exp $
+/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Statement.java,v 1.2 2002/07/24 22:08:43 barry Exp $
* This class implements the java.sql.Statement interface for JDBC2.
* However most of the implementation is really done in
* org.postgresql.jdbc2.AbstractJdbc2Statement or one of it's parents
public Jdbc2Statement (Jdbc2Connection c)
{
- connection = c;
- resultsettype = java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
- concurrency = java.sql.ResultSet.CONCUR_READ_ONLY;
+ super(c);
}
}
+++ /dev/null
-package org.postgresql.jdbc2;
-
-// IMPORTANT NOTE: This file implements the JDBC 2 version of the driver.
-// If you make any modifications to this file, you must make sure that the
-// changes are also made (if relevent) to the related JDBC 1 class in the
-// org.postgresql.jdbc1 package.
-
-import java.io.*;
-import java.math.*;
-import java.sql.*;
-import java.text.*;
-import java.util.*;
-import org.postgresql.largeobject.*;
-import org.postgresql.util.*;
-
-/*
- * A SQL Statement is pre-compiled and stored in a PreparedStatement object.
- * This object can then be used to efficiently execute this statement multiple
- * times.
- *
- *
Note: The setXXX methods for setting IN parameter values must
- * specify types that are compatible with the defined SQL type of the input
- * parameter. For instance, if the IN parameter has SQL type Integer, then
- * setInt should be used.
- *
- *
If arbitrary parameter type conversions are required, then the setObject
- * method should be used with a target SQL type.
- *
- * @see ResultSet
- * @see java.sql.PreparedStatement
- */
-public class PreparedStatement extends Jdbc2Statement implements java.sql.PreparedStatement
-{
- String sql;
- String[] templateStrings;
- String[] inStrings;
- Jdbc2Connection connection;
-
- // Some performance caches
- private StringBuffer sbuf = new StringBuffer();
-
- /*
- * Constructor for the PreparedStatement class.
- * Split the SQL statement into segments - separated by the arguments.
- * When we rebuild the thing with the arguments, we can substitute the
- * args and join the whole thing together.
- *
- * @param conn the instanatiating connection
- * @param sql the SQL statement with ? for IN markers
- * @exception SQLException if something bad occurs
- */
- public PreparedStatement(Jdbc2Connection connection, String sql) throws SQLException
- {
- super(connection);
-
- this.sql = sql;
- this.connection = connection;
- parseSqlStmt (); // this allows Callable stmt to override
- }
-
- protected void parseSqlStmt () throws SQLException {
- Vector v = new Vector();
- boolean inQuotes = false;
- int lastParmEnd = 0, i;
-
- for (i = 0; i < sql.length(); ++i)
- {
- int c = sql.charAt(i);
-
- if (c == '\'')
- inQuotes = !inQuotes;
- if (c == '?' && !inQuotes)
- {
- v.addElement(sql.substring (lastParmEnd, i));
- lastParmEnd = i + 1;
- }
- }
- v.addElement(sql.substring (lastParmEnd, sql.length()));
-
- templateStrings = new String[v.size()];
- inStrings = new String[v.size() - 1];
- clearParameters();
-
- for (i = 0 ; i < templateStrings.length; ++i)
- templateStrings[i] = (String)v.elementAt(i);
- }
-
- /*
- * A Prepared SQL query is executed and its ResultSet is returned
- *
- * @return a ResultSet that contains the data produced by the
- * * query - never null
- * @exception SQLException if a database access error occurs
- */
- public java.sql.ResultSet executeQuery() throws SQLException
- {
- return super.executeQuery(compileQuery()); // in Statement class
- }
-
- /*
- * Execute a SQL INSERT, UPDATE or DELETE statement. In addition,
- * SQL statements that return nothing such as SQL DDL statements can
- * be executed.
- *
- * @return either the row count for INSERT, UPDATE or DELETE; or
- * * 0 for SQL statements that return nothing.
- * @exception SQLException if a database access error occurs
- */
- public int executeUpdate() throws SQLException
- {
- return super.executeUpdate(compileQuery()); // in Statement class
- }
-
- /*
- * Helper - this compiles the SQL query from the various parameters
- * This is identical to toString() except it throws an exception if a
- * parameter is unused.
- */
- protected synchronized String compileQuery()
- throws SQLException
- {
- sbuf.setLength(0);
- int i;
-
- for (i = 0 ; i < inStrings.length ; ++i)
- {
- if (inStrings[i] == null)
- throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
- sbuf.append (templateStrings[i]).append (inStrings[i]);
- }
- sbuf.append(templateStrings[inStrings.length]);
- return sbuf.toString();
- }
-
- /*
- * Set a parameter to SQL NULL
- *
- *
Note: You must specify the parameters SQL type (although
- * PostgreSQL ignores it)
- *
- * @param parameterIndex the first parameter is 1, etc...
- * @param sqlType the SQL type code defined in java.sql.Types
- * @exception SQLException if a database access error occurs
- */
- public void setNull(int parameterIndex, int sqlType) throws SQLException
- {
- set(parameterIndex, "null");
- }
-
- /*
- * Set a parameter to a Java boolean value. The driver converts this
- * to a SQL BIT value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setBoolean(int parameterIndex, boolean x) throws SQLException
- {
- set(parameterIndex, x ? "'t'" : "'f'");
- }
-
- /*
- * Set a parameter to a Java byte value. The driver converts this to
- * a SQL TINYINT value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setByte(int parameterIndex, byte x) throws SQLException
- {
- set(parameterIndex, Integer.toString(x));
- }
-
- /*
- * Set a parameter to a Java short value. The driver converts this
- * to a SQL SMALLINT value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setShort(int parameterIndex, short x) throws SQLException
- {
- set(parameterIndex, Integer.toString(x));
- }
-
- /*
- * Set a parameter to a Java int value. The driver converts this to
- * a SQL INTEGER value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setInt(int parameterIndex, int x) throws SQLException
- {
- set(parameterIndex, Integer.toString(x));
- }
-
- /*
- * Set a parameter to a Java long value. The driver converts this to
- * a SQL BIGINT value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setLong(int parameterIndex, long x) throws SQLException
- {
- set(parameterIndex, Long.toString(x));
- }
-
- /*
- * Set a parameter to a Java float value. The driver converts this
- * to a SQL FLOAT value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setFloat(int parameterIndex, float x) throws SQLException
- {
- set(parameterIndex, Float.toString(x));
- }
-
- /*
- * Set a parameter to a Java double value. The driver converts this
- * to a SQL DOUBLE value when it sends it to the database
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setDouble(int parameterIndex, double x) throws SQLException
- {
- set(parameterIndex, Double.toString(x));
- }
-
- /*
- * Set a parameter to a java.lang.BigDecimal value. The driver
- * converts this to a SQL NUMERIC value when it sends it to the
- * database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
- {
- if (x == null) {
- setNull(parameterIndex, Types.OTHER);
- } else {
- set(parameterIndex, x.toString());
- }
- }
-
- /*
- * Set a parameter to a Java String value. The driver converts this
- * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
- * size relative to the driver's limits on VARCHARs) when it sends it
- * to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setString(int parameterIndex, String x) throws SQLException
- {
- // if the passed string is null, then set this column to null
- if (x == null)
- setNull(parameterIndex, Types.OTHER);
- else
- {
- // use the shared buffer object. Should never clash but this makes
- // us thread safe!
- synchronized (sbuf)
- {
- sbuf.setLength(0);
- int i;
-
- sbuf.append('\'');
- for (i = 0 ; i < x.length() ; ++i)
- {
- char c = x.charAt(i);
- if (c == '\\' || c == '\'')
- sbuf.append((char)'\\');
- sbuf.append(c);
- }
- sbuf.append('\'');
- set(parameterIndex, sbuf.toString());
- }
- }
- }
-
- /*
- * Set a parameter to a Java array of bytes. The driver converts this
- * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
- * size relative to the driver's limits on VARBINARYs) when it sends
- * it to the database.
- *
- *
With org.postgresql, this creates a large object, and stores the
- * objects oid in this column.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setBytes(int parameterIndex, byte x[]) throws SQLException
- {
- if (connection.haveMinimumCompatibleVersion("7.2"))
- {
- //Version 7.2 supports the bytea datatype for byte arrays
- if (null == x)
- {
- setNull(parameterIndex, Types.OTHER);
- }
- else
- {
- setString(parameterIndex, PGbytea.toPGString(x));
- }
- }
- else
- {
- //Version 7.1 and earlier support done as LargeObjects
- LargeObjectManager lom = connection.getLargeObjectAPI();
- int oid = lom.create();
- LargeObject lob = lom.open(oid);
- lob.write(x);
- lob.close();
- setInt(parameterIndex, oid);
- }
- }
-
- /*
- * Set a parameter to a java.sql.Date value. The driver converts this
- * to a SQL DATE value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
- {
- if (null == x)
- {
- setNull(parameterIndex, Types.OTHER);
- }
- else
- {
- set(parameterIndex, "'" + x.toString() + "'");
- }
- }
-
- /*
- * Set a parameter to a java.sql.Time value. The driver converts
- * this to a SQL TIME value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...));
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setTime(int parameterIndex, Time x) throws SQLException
- {
- if (null == x)
- {
- setNull(parameterIndex, Types.OTHER);
- }
- else
- {
- set(parameterIndex, "'" + x.toString() + "'");
- }
- }
-
- /*
- * Set a parameter to a java.sql.Timestamp value. The driver converts
- * this to a SQL TIMESTAMP value when it sends it to the database.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
- {
- if (null == x)
- {
- setNull(parameterIndex, Types.OTHER);
- }
- else
- {
- // Use the shared StringBuffer
- synchronized (sbuf)
- {
- sbuf.setLength(0);
- sbuf.append("'");
- //format the timestamp
- //we do our own formating so that we can get a format
- //that works with both timestamp with time zone and
- //timestamp without time zone datatypes.
- //The format is '2002-01-01 23:59:59.123456-0130'
- //we need to include the local time and timezone offset
- //so that timestamp without time zone works correctly
- int l_year = x.getYear() + 1900;
- sbuf.append(l_year);
- sbuf.append('-');
- int l_month = x.getMonth() + 1;
- if (l_month < 10) sbuf.append('0');
- sbuf.append(l_month);
- sbuf.append('-');
- int l_day = x.getDate();
- if (l_day < 10) sbuf.append('0');
- sbuf.append(l_day);
- sbuf.append(' ');
- int l_hours = x.getHours();
- if (l_hours < 10) sbuf.append('0');
- sbuf.append(l_hours);
- sbuf.append(':');
- int l_minutes = x.getMinutes();
- if (l_minutes < 10) sbuf.append('0');
- sbuf.append(l_minutes);
- sbuf.append(':');
- int l_seconds = x.getSeconds();
- if (l_seconds < 10) sbuf.append('0');
- sbuf.append(l_seconds);
- // Make decimal from nanos.
- char[] l_decimal = {'0','0','0','0','0','0','0','0','0'};
- char[] l_nanos = Integer.toString(x.getNanos()).toCharArray();
- System.arraycopy(l_nanos, 0, l_decimal, l_decimal.length - l_nanos.length, l_nanos.length);
- sbuf.append('.');
- if (connection.haveMinimumServerVersion("7.2")) {
- sbuf.append(l_decimal,0,6);
- } else {
- // Because 7.1 include bug that "hh:mm:59.999" becomes "hh:mm:60.00".
- sbuf.append(l_decimal,0,2);
- }
- //add timezone offset
- int l_offset = -(x.getTimezoneOffset());
- int l_houros = l_offset/60;
- if (l_houros >= 0) {
- sbuf.append('+');
- } else {
- sbuf.append('-');
- }
- if (l_houros > -10 && l_houros < 10) sbuf.append('0');
- if (l_houros >= 0) {
- sbuf.append(l_houros);
- } else {
- sbuf.append(-l_houros);
- }
- int l_minos = l_offset - (l_houros *60);
- if (l_minos != 0) {
- if (l_minos < 10) sbuf.append('0');
- sbuf.append(l_minos);
- }
- sbuf.append("'");
- set(parameterIndex, sbuf.toString());
- }
-
- }
- }
-
- /*
- * When a very large ASCII value is input to a LONGVARCHAR parameter,
- * it may be more practical to send it via a java.io.InputStream.
- * JDBC will read the data from the stream as needed, until it reaches
- * end-of-file. The JDBC driver will do any necessary conversion from
- * ASCII to the database char format.
- *
- *
Note: This stream object can either be a standard Java
- * stream object or your own subclass that implements the standard
- * interface.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @param length the number of bytes in the stream
- * @exception SQLException if a database access error occurs
- */
- public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
- {
- if (connection.haveMinimumCompatibleVersion("7.2"))
- {
- //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
- //As the spec/javadoc for this method indicate this is to be used for
- //large String values (i.e. LONGVARCHAR) PG doesn't have a separate
- //long varchar datatype, but with toast all text datatypes are capable of
- //handling very large values. Thus the implementation ends up calling
- //setString() since there is no current way to stream the value to the server
- try
- {
- InputStreamReader l_inStream = new InputStreamReader(x, "ASCII");
- char[] l_chars = new char[length];
- int l_charsRead = l_inStream.read(l_chars, 0, length);
- setString(parameterIndex, new String(l_chars, 0, l_charsRead));
- }
- catch (UnsupportedEncodingException l_uee)
- {
- throw new PSQLException("postgresql.unusual", l_uee);
- }
- catch (IOException l_ioe)
- {
- throw new PSQLException("postgresql.unusual", l_ioe);
- }
- }
- else
- {
- //Version 7.1 supported only LargeObjects by treating everything
- //as binary data
- setBinaryStream(parameterIndex, x, length);
- }
- }
-
- /*
- * When a very large Unicode value is input to a LONGVARCHAR parameter,
- * it may be more practical to send it via a java.io.InputStream.
- * JDBC will read the data from the stream as needed, until it reaches
- * end-of-file. The JDBC driver will do any necessary conversion from
- * UNICODE to the database char format.
- *
- * ** DEPRECIATED IN JDBC 2 **
- *
- *
Note: This stream object can either be a standard Java
- * stream object or your own subclass that implements the standard
- * interface.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- * @deprecated
- */
- public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
- {
- if (connection.haveMinimumCompatibleVersion("7.2"))
- {
- //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
- //As the spec/javadoc for this method indicate this is to be used for
- //large String values (i.e. LONGVARCHAR) PG doesn't have a separate
- //long varchar datatype, but with toast all text datatypes are capable of
- //handling very large values. Thus the implementation ends up calling
- //setString() since there is no current way to stream the value to the server
- try
- {
- InputStreamReader l_inStream = new InputStreamReader(x, "UTF-8");
- char[] l_chars = new char[length];
- int l_charsRead = l_inStream.read(l_chars, 0, length);
- setString(parameterIndex, new String(l_chars, 0, l_charsRead));
- }
- catch (UnsupportedEncodingException l_uee)
- {
- throw new PSQLException("postgresql.unusual", l_uee);
- }
- catch (IOException l_ioe)
- {
- throw new PSQLException("postgresql.unusual", l_ioe);
- }
- }
- else
- {
- //Version 7.1 supported only LargeObjects by treating everything
- //as binary data
- setBinaryStream(parameterIndex, x, length);
- }
- }
-
- /*
- * When a very large binary value is input to a LONGVARBINARY parameter,
- * it may be more practical to send it via a java.io.InputStream.
- * JDBC will read the data from the stream as needed, until it reaches
- * end-of-file.
- *
- *
Note: This stream object can either be a standard Java
- * stream object or your own subclass that implements the standard
- * interface.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the parameter value
- * @exception SQLException if a database access error occurs
- */
- public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
- {
- if (connection.haveMinimumCompatibleVersion("7.2"))
- {
- //Version 7.2 supports BinaryStream for for the PG bytea type
- //As the spec/javadoc for this method indicate this is to be used for
- //large binary values (i.e. LONGVARBINARY) PG doesn't have a separate
- //long binary datatype, but with toast the bytea datatype is capable of
- //handling very large values. Thus the implementation ends up calling
- //setBytes() since there is no current way to stream the value to the server
- byte[] l_bytes = new byte[length];
- int l_bytesRead;
- try
- {
- l_bytesRead = x.read(l_bytes, 0, length);
- }
- catch (IOException l_ioe)
- {
- throw new PSQLException("postgresql.unusual", l_ioe);
- }
- if (l_bytesRead == length)
- {
- setBytes(parameterIndex, l_bytes);
- }
- else
- {
- //the stream contained less data than they said
- byte[] l_bytes2 = new byte[l_bytesRead];
- System.arraycopy(l_bytes, 0, l_bytes2, 0, l_bytesRead);
- setBytes(parameterIndex, l_bytes2);
- }
- }
- else
- {
- //Version 7.1 only supported streams for LargeObjects
- //but the jdbc spec indicates that streams should be
- //available for LONGVARBINARY instead
- LargeObjectManager lom = connection.getLargeObjectAPI();
- int oid = lom.create();
- LargeObject lob = lom.open(oid);
- OutputStream los = lob.getOutputStream();
- try
- {
- // could be buffered, but then the OutputStream returned by LargeObject
- // is buffered internally anyhow, so there would be no performance
- // boost gained, if anything it would be worse!
- int c = x.read();
- int p = 0;
- while (c > -1 && p < length)
- {
- los.write(c);
- c = x.read();
- p++;
- }
- los.close();
- }
- catch (IOException se)
- {
- throw new PSQLException("postgresql.unusual", se);
- }
- // lob is closed by the stream so don't call lob.close()
- setInt(parameterIndex, oid);
- }
- }
-
- /*
- * In general, parameter values remain in force for repeated used of a
- * Statement. Setting a parameter value automatically clears its
- * previous value. However, in coms cases, it is useful to immediately
- * release the resources used by the current parameter values; this
- * can be done by calling clearParameters
- *
- * @exception SQLException if a database access error occurs
- */
- public void clearParameters() throws SQLException
- {
- int i;
-
- for (i = 0 ; i < inStrings.length ; i++)
- inStrings[i] = null;
- }
-
- /*
- * Set the value of a parameter using an object; use the java.lang
- * equivalent objects for integral values.
- *
- *
The given Java object will be converted to the targetSqlType before
- * being sent to the database.
- *
- *
note that this method may be used to pass database-specific
- * abstract data types. This is done by using a Driver-specific
- * Java type and using a targetSqlType of java.sql.Types.OTHER
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the object containing the input parameter value
- * @param targetSqlType The SQL type to be send to the database
- * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
- * types this is the number of digits after the decimal. For
- * all other types this value will be ignored.
- * @exception SQLException if a database access error occurs
- */
- public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
- {
- if (x == null)
- {
- setNull(parameterIndex, Types.OTHER);
- return;
- }
- switch (targetSqlType)
- {
- case Types.TINYINT:
- case Types.SMALLINT:
- case Types.INTEGER:
- case Types.BIGINT:
- case Types.REAL:
- case Types.FLOAT:
- case Types.DOUBLE:
- case Types.DECIMAL:
- case Types.NUMERIC:
- if (x instanceof Boolean)
- set(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0");
- else
- set(parameterIndex, x.toString());
- break;
- case Types.CHAR:
- case Types.VARCHAR:
- case Types.LONGVARCHAR:
- setString(parameterIndex, x.toString());
- break;
- case Types.DATE:
- setDate(parameterIndex, (java.sql.Date)x);
- break;
- case Types.TIME:
- setTime(parameterIndex, (Time)x);
- break;
- case Types.TIMESTAMP:
- setTimestamp(parameterIndex, (Timestamp)x);
- break;
- case Types.BIT:
- if (x instanceof Boolean)
- {
- set(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE");
- }
- else
- {
- throw new PSQLException("postgresql.prep.type");
- }
- break;
- case Types.BINARY:
- case Types.VARBINARY:
- setObject(parameterIndex, x);
- break;
- case Types.OTHER:
- setString(parameterIndex, ((PGobject)x).getValue());
- break;
- default:
- throw new PSQLException("postgresql.prep.type");
- }
- }
-
- public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
- {
- setObject(parameterIndex, x, targetSqlType, 0);
- }
-
- /*
- * This stores an Object into a parameter.
- *
New for 6.4, if the object is not recognised, but it is
- * Serializable, then the object is serialised using the
- * org.postgresql.util.Serialize class.
- */
- public void setObject(int parameterIndex, Object x) throws SQLException
- {
- if (x == null)
- {
- setNull(parameterIndex, Types.OTHER);
- return;
- }
- if (x instanceof String)
- setString(parameterIndex, (String)x);
- else if (x instanceof BigDecimal)
- setBigDecimal(parameterIndex, (BigDecimal)x);
- else if (x instanceof Short)
- setShort(parameterIndex, ((Short)x).shortValue());
- else if (x instanceof Integer)
- setInt(parameterIndex, ((Integer)x).intValue());
- else if (x instanceof Long)
- setLong(parameterIndex, ((Long)x).longValue());
- else if (x instanceof Float)
- setFloat(parameterIndex, ((Float)x).floatValue());
- else if (x instanceof Double)
- setDouble(parameterIndex, ((Double)x).doubleValue());
- else if (x instanceof byte[])
- setBytes(parameterIndex, (byte[])x);
- else if (x instanceof java.sql.Date)
- setDate(parameterIndex, (java.sql.Date)x);
- else if (x instanceof Time)
- setTime(parameterIndex, (Time)x);
- else if (x instanceof Timestamp)
- setTimestamp(parameterIndex, (Timestamp)x);
- else if (x instanceof Boolean)
- setBoolean(parameterIndex, ((Boolean)x).booleanValue());
- else if (x instanceof PGobject)
- setString(parameterIndex, ((PGobject)x).getValue());
- else
- // Try to store java object in database
- setSerialize(parameterIndex, connection.storeObject(x), x.getClass().getName() );
- }
-
- /*
- * Some prepared statements return multiple results; the execute method
- * handles these complex statements as well as the simpler form of
- * statements handled by executeQuery and executeUpdate
- *
- * @return true if the next result is a ResultSet; false if it is an
- * update count or there are no more results
- * @exception SQLException if a database access error occurs
- */
- public boolean execute() throws SQLException
- {
- return super.execute(compileQuery()); // in Statement class
- }
-
- /*
- * Returns the SQL statement with the current template values
- * substituted.
- * NB: This is identical to compileQuery() except instead of throwing
- * SQLException if a parameter is null, it places ? instead.
- */
- public String toString()
- {
- synchronized (sbuf)
- {
- sbuf.setLength(0);
- int i;
-
- for (i = 0 ; i < inStrings.length ; ++i)
- {
- if (inStrings[i] == null)
- sbuf.append( '?' );
- else
- sbuf.append (templateStrings[i]);
- sbuf.append (inStrings[i]);
- }
- sbuf.append(templateStrings[inStrings.length]);
- return sbuf.toString();
- }
- }
-
- // **************************************************************
- // END OF PUBLIC INTERFACE
- // **************************************************************
-
- /*
- * There are a lot of setXXX classes which all basically do
- * the same thing. We need a method which actually does the
- * set for us.
- *
- * @param paramIndex the index into the inString
- * @param s a string to be stored
- * @exception SQLException if something goes wrong
- */
- protected void set(int paramIndex, String s) throws SQLException
- {
- if (paramIndex < 1 || paramIndex > inStrings.length)
- throw new PSQLException("postgresql.prep.range");
- inStrings[paramIndex - 1] = s;
- }
-
- /*
- * Set a parameter to a tablerow-type oid reference.
- *
- * @param parameterIndex the first parameter is 1...
- * @param x the oid of the object from org.postgresql.util.Serialize.store
- * @param classname the classname of the java object x
- * @exception SQLException if a database access error occurs
- */
- private void setSerialize(int parameterIndex, long x, String classname) throws SQLException
- {
- // converts . to _, toLowerCase, and ensures length<32
- String tablename = Serialize.toPostgreSQL( classname );
- DriverManager.println("setSerialize: setting " + x + "::" + tablename );
-
- // OID reference to tablerow-type must be cast like:
::
- // Note that postgres support for tablerow data types is incomplete/broken.
- // This cannot be just a plain OID because then there would be ambiguity
- // between when you want the oid itself and when you want the object
- // an oid references.
- set(parameterIndex, Long.toString(x) + "::" + tablename );
- }
-
-
- // ** JDBC 2 Extensions **
-
- /*
- * This parses the query and adds it to the current batch
- */
- public void addBatch() throws SQLException
- {
- super.addBatch(compileQuery());
- }
-
- /*
- * Not sure what this one does, so I'm saying this returns the MetaData for
- * the last ResultSet returned!
- */
- public java.sql.ResultSetMetaData getMetaData() throws SQLException
- {
- java.sql.ResultSet rs = getResultSet();
- if (rs != null)
- return rs.getMetaData();
-
- // Does anyone really know what this method does?
- return null;
- }
-
- public void setArray(int i, java.sql.Array x) throws SQLException
- {
- setString(i, x.toString());
- }
-
- /*
- * Sets a Blob
- */
- public void setBlob(int i, Blob x) throws SQLException
- {
- InputStream l_inStream = x.getBinaryStream();
- int l_length = (int) x.length();
- LargeObjectManager lom = connection.getLargeObjectAPI();
- int oid = lom.create();
- LargeObject lob = lom.open(oid);
- OutputStream los = lob.getOutputStream();
- try
- {
- // could be buffered, but then the OutputStream returned by LargeObject
- // is buffered internally anyhow, so there would be no performance
- // boost gained, if anything it would be worse!
- int c = l_inStream.read();
- int p = 0;
- while (c > -1 && p < l_length)
- {
- los.write(c);
- c = l_inStream.read();
- p++;
- }
- los.close();
- }
- catch (IOException se)
- {
- throw new PSQLException("postgresql.unusual", se);
- }
- // lob is closed by the stream so don't call lob.close()
- setInt(i, oid);
- }
-
- /*
- * This is similar to setBinaryStream except it uses a Reader instead of
- * InputStream.
- */
- public void setCharacterStream(int i, java.io.Reader x, int length) throws SQLException
- {
- if (connection.haveMinimumCompatibleVersion("7.2"))
- {
- //Version 7.2 supports CharacterStream for for the PG text types
- //As the spec/javadoc for this method indicate this is to be used for
- //large text values (i.e. LONGVARCHAR) PG doesn't have a separate
- //long varchar datatype, but with toast all the text datatypes are capable of
- //handling very large values. Thus the implementation ends up calling
- //setString() since there is no current way to stream the value to the server
- char[] l_chars = new char[length];
- int l_charsRead;
- try
- {
- l_charsRead = x.read(l_chars, 0, length);
- }
- catch (IOException l_ioe)
- {
- throw new PSQLException("postgresql.unusual", l_ioe);
- }
- setString(i, new String(l_chars, 0, l_charsRead));
- }
- else
- {
- //Version 7.1 only supported streams for LargeObjects
- //but the jdbc spec indicates that streams should be
- //available for LONGVARCHAR instead
- LargeObjectManager lom = connection.getLargeObjectAPI();
- int oid = lom.create();
- LargeObject lob = lom.open(oid);
- OutputStream los = lob.getOutputStream();
- try
- {
- // could be buffered, but then the OutputStream returned by LargeObject
- // is buffered internally anyhow, so there would be no performance
- // boost gained, if anything it would be worse!
- int c = x.read();
- int p = 0;
- while (c > -1 && p < length)
- {
- los.write(c);
- c = x.read();
- p++;
- }
- los.close();
- }
- catch (IOException se)
- {
- throw new PSQLException("postgresql.unusual", se);
- }
- // lob is closed by the stream so don't call lob.close()
- setInt(i, oid);
- }
- }
-
- /*
- * New in 7.1
- */
- public void setClob(int i, Clob x) throws SQLException
- {
- InputStream l_inStream = x.getAsciiStream();
- int l_length = (int) x.length();
- LargeObjectManager lom = connection.getLargeObjectAPI();
- int oid = lom.create();
- LargeObject lob = lom.open(oid);
- OutputStream los = lob.getOutputStream();
- try
- {
- // could be buffered, but then the OutputStream returned by LargeObject
- // is buffered internally anyhow, so there would be no performance
- // boost gained, if anything it would be worse!
- int c = l_inStream.read();
- int p = 0;
- while (c > -1 && p < l_length)
- {
- los.write(c);
- c = l_inStream.read();
- p++;
- }
- los.close();
- }
- catch (IOException se)
- {
- throw new PSQLException("postgresql.unusual", se);
- }
- // lob is closed by the stream so don't call lob.close()
- setInt(i, oid);
- }
-
- /*
- * At least this works as in PostgreSQL null represents anything null ;-)
- *
- * New in 7,1
- */
- public void setNull(int i, int t, String s) throws SQLException
- {
- setNull(i, t);
- }
-
- public void setRef(int i, Ref x) throws SQLException
- {
- throw org.postgresql.Driver.notImplemented();
- }
-
- /*
- * New in 7,1
- */
- public void setDate(int i, java.sql.Date d, java.util.Calendar cal) throws SQLException
- {
- if (cal == null)
- setDate(i, d);
- else
- {
- cal.setTime(d);
- setDate(i, new java.sql.Date(cal.getTime().getTime()));
- }
- }
-
- /*
- * New in 7,1
- */
- public void setTime(int i, Time t, java.util.Calendar cal) throws SQLException
- {
- if (cal == null)
- setTime(i, t);
- else
- {
- cal.setTime(t);
- setTime(i, new java.sql.Time(cal.getTime().getTime()));
- }
- }
-
- /*
- * New in 7,1
- */
- public void setTimestamp(int i, Timestamp t, java.util.Calendar cal) throws SQLException
- {
- if (cal == null)
- setTimestamp(i, t);
- else
- {
- cal.setTime(t);
- setTimestamp(i, new java.sql.Timestamp(cal.getTime().getTime()));
- }
- }
-
-}
-