diff options
Diffstat (limited to 'src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java')
| -rw-r--r-- | src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java | 1086 |
1 files changed, 0 insertions, 1086 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java b/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java deleted file mode 100644 index 21aba8d9ee..0000000000 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java +++ /dev/null @@ -1,1086 +0,0 @@ -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. - * - * <p><B>Note:</B> 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. - * - * <p>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 - * - * <p><B>Note:</B> 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. - * - * <p>Implementation note: - * <br>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. - * - * <P><B>Note:</B> 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 ** - * - * <P><B>Note:</B> 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. - * - * <P><B>Note:</B> 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. - * - * <P>The given Java object will be converted to the targetSqlType before - * being sent to the database. - * - * <P>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. - * <p>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: <oid>::<tablename> - // 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())); - } - } - -} - |
