1 package org.postgresql.jdbc1;
5 import java.math.BigDecimal;
7 import java.util.Vector;
8 import org.postgresql.largeobject.*;
9 import org.postgresql.util.*;
11 /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.17 2003/02/09 23:14:55 barry Exp $
12 * This class defines methods of the jdbc1 specification. This class is
13 * extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2
14 * methods. The real Statement class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Statement
16 public abstract class AbstractJdbc1Statement implements org.postgresql.PGStatement
19 // The connection who created us
20 protected AbstractJdbc1Connection connection;
22 public org.postgresql.PGConnection getPGConnection() {
26 /** The warnings chain. */
27 protected SQLWarning warnings = null;
29 /** Maximum number of rows to return, 0 = unlimited */
30 protected int maxrows = 0;
32 /** Number of rows to get in a batch. */
33 protected int fetchSize = 0;
35 /** Timeout (in seconds) for a query (not used) */
36 protected int timeout = 0;
38 protected boolean replaceProcessingEnabled = true;
40 /** The current results */
41 protected java.sql.ResultSet result = null;
43 // Static variables for parsing SQL when replaceProcessing is true.
44 private static final short IN_SQLCODE = 0;
45 private static final short IN_STRING = 1;
46 private static final short BACKSLASH = 2;
47 private static final short ESC_TIMEDATE = 3;
49 // Some performance caches
50 private StringBuffer sbuf = new StringBuffer(32);
52 //Used by the preparedstatement style methods
53 protected String[] m_sqlFragments;
54 private String[] m_origSqlFragments;
55 private String[] m_executeSqlFragments;
56 protected Object[] m_binds = new Object[0];
58 protected String[] m_bindTypes = new String[0];
59 protected String m_statementName = null;
61 private boolean m_useServerPrepare = false;
62 private static int m_preparedCount = 1;
64 //Used by the callablestatement style methods
65 private static final String JDBC_SYNTAX = "{[? =] call <some_function> ([? [,?]*]) }";
66 private static final String RESULT_ALIAS = "result";
67 private String originalSql = "";
68 private boolean isFunction;
69 // functionReturnType contains the user supplied value to check
70 // testReturn contains a modified version to make it easier to
71 // check the getXXX methods..
72 private int functionReturnType;
73 private int testReturn;
74 // returnTypeSet is true when a proper call to registerOutParameter has been made
75 private boolean returnTypeSet;
76 protected Object callResult;
79 public abstract java.sql.ResultSet createResultSet(org.postgresql.Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException;
81 public AbstractJdbc1Statement (AbstractJdbc1Connection connection)
83 this.connection = connection;
86 public AbstractJdbc1Statement (AbstractJdbc1Connection connection, String p_sql) throws SQLException
88 this.connection = connection;
89 parseSqlStmt(p_sql); // this allows Callable stmt to override
92 protected void parseSqlStmt (String p_sql) throws SQLException
96 l_sql = replaceProcessing(l_sql);
98 if (this instanceof CallableStatement)
100 l_sql = modifyJdbcCall(l_sql);
103 Vector v = new Vector();
104 boolean inQuotes = false;
105 int lastParmEnd = 0, i;
107 for (i = 0; i < l_sql.length(); ++i)
109 int c = l_sql.charAt(i);
112 inQuotes = !inQuotes;
113 if (c == '?' && !inQuotes)
115 v.addElement(l_sql.substring (lastParmEnd, i));
119 v.addElement(l_sql.substring (lastParmEnd, l_sql.length()));
121 m_sqlFragments = new String[v.size()];
122 m_binds = new String[v.size() - 1];
123 m_bindTypes = new String[v.size() - 1];
125 for (i = 0 ; i < m_sqlFragments.length; ++i)
126 m_sqlFragments[i] = (String)v.elementAt(i);
132 * Execute a SQL statement that retruns a single ResultSet
134 * @param sql typically a static SQL SELECT statement
135 * @return a ResulSet that contains the data produced by the query
136 * @exception SQLException if a database access error occurs
138 public java.sql.ResultSet executeQuery(String p_sql) throws SQLException
140 String l_sql = replaceProcessing(p_sql);
141 m_sqlFragments = new String[] {l_sql};
142 m_binds = new Object[0];
143 //If we have already created a server prepared statement, we need
144 //to deallocate the existing one
145 if (m_statementName != null)
149 ((AbstractJdbc1Connection)connection).execSQL("DEALLOCATE " + m_statementName);
156 m_statementName = null;
157 m_origSqlFragments = null;
158 m_executeSqlFragments = null;
161 return executeQuery();
165 * A Prepared SQL query is executed and its ResultSet is returned
167 * @return a ResultSet that contains the data produced by the
168 * * query - never null
169 * @exception SQLException if a database access error occurs
171 public java.sql.ResultSet executeQuery() throws SQLException
174 this.executeWithCursor();
178 while (result != null && !((AbstractJdbc1ResultSet)result).reallyResultSet())
179 result = ((AbstractJdbc1ResultSet)result).getNext();
181 throw new PSQLException("postgresql.stat.noresult");
186 * Execute a SQL INSERT, UPDATE or DELETE statement. In addition
187 * SQL statements that return nothing such as SQL DDL statements
190 * @param sql a SQL statement
191 * @return either a row count, or 0 for SQL commands
192 * @exception SQLException if a database access error occurs
194 public int executeUpdate(String p_sql) throws SQLException
196 String l_sql = replaceProcessing(p_sql);
197 m_sqlFragments = new String[] {l_sql};
198 m_binds = new Object[0];
199 //If we have already created a server prepared statement, we need
200 //to deallocate the existing one
201 if (m_statementName != null) {
202 ((AbstractJdbc1Connection)connection).execSQL("DEALLOCATE " + m_statementName);
203 m_statementName = null;
204 m_origSqlFragments = null;
205 m_executeSqlFragments = null;
207 return executeUpdate();
211 * Execute a SQL INSERT, UPDATE or DELETE statement. In addition,
212 * SQL statements that return nothing such as SQL DDL statements can
215 * @return either the row count for INSERT, UPDATE or DELETE; or
216 * * 0 for SQL statements that return nothing.
217 * @exception SQLException if a database access error occurs
219 public int executeUpdate() throws SQLException
222 if (((AbstractJdbc1ResultSet)result).reallyResultSet())
223 throw new PSQLException("postgresql.stat.result");
224 return this.getUpdateCount();
228 * Execute a SQL statement that may return multiple results. We
229 * don't have to worry about this since we do not support multiple
230 * ResultSets. You can use getResultSet or getUpdateCount to
231 * retrieve the result.
233 * @param sql any SQL statement
234 * @return true if the next result is a ResulSet, false if it is
235 * an update count or there are no more results
236 * @exception SQLException if a database access error occurs
238 public boolean execute(String p_sql) throws SQLException
240 String l_sql = replaceProcessing(p_sql);
241 m_sqlFragments = new String[] {l_sql};
242 m_binds = new Object[0];
243 //If we have already created a server prepared statement, we need
244 //to deallocate the existing one
245 if (m_statementName != null) {
246 ((AbstractJdbc1Connection)connection).execSQL("DEALLOCATE " + m_statementName);
247 m_statementName = null;
248 m_origSqlFragments = null;
249 m_executeSqlFragments = null;
255 * Some prepared statements return multiple results; the execute method
256 * handles these complex statements as well as the simpler form of
257 * statements handled by executeQuery and executeUpdate
259 * @return true if the next result is a ResultSet; false if it is an
260 * * update count or there are no more results
261 * @exception SQLException if a database access error occurs
263 public boolean execute() throws SQLException
265 if (isFunction && !returnTypeSet)
266 throw new PSQLException("postgresql.call.noreturntype");
268 { // set entry 1 to dummy entry..
269 m_binds[0] = ""; // dummy entry which ensured that no one overrode
270 m_bindTypes[0] = PG_TEXT;
271 // and calls to setXXX (2,..) really went to first arg in a function call..
274 // New in 7.1, if we have a previous resultset then force it to close
275 // This brings us nearer to compliance, and helps memory management.
276 // Internal stuff will call ExecSQL directly, bypassing this.
280 java.sql.ResultSet rs = getResultSet();
285 //Use server prepared statements if directed
286 if (m_useServerPrepare)
288 if (m_statementName == null)
290 m_statementName = "JDBC_STATEMENT_" + m_preparedCount++;
291 m_origSqlFragments = new String[m_sqlFragments.length];
292 m_executeSqlFragments = new String[m_sqlFragments.length];
293 System.arraycopy(m_sqlFragments, 0, m_origSqlFragments, 0, m_sqlFragments.length);
294 m_executeSqlFragments[0] = "EXECUTE " + m_statementName;
295 if (m_sqlFragments.length > 1)
297 m_executeSqlFragments[0] = m_executeSqlFragments[0] + "(";
298 for (int i = 1; i < m_bindTypes.length; i++)
300 m_executeSqlFragments[i] = ", ";
302 m_executeSqlFragments[m_bindTypes.length] = ")";
307 sbuf.append("PREPARE ");
308 sbuf.append(m_statementName);
309 if (m_origSqlFragments.length > 1)
312 for (int i = 0; i < m_bindTypes.length - 1; i++)
314 sbuf.append(m_bindTypes[i]);
317 sbuf.append(m_bindTypes[m_bindTypes.length - 1]);
321 sbuf.append(m_origSqlFragments[0]);
322 for (int i = 1; i < m_origSqlFragments.length; i++)
327 sbuf.append(m_origSqlFragments[i]);
331 sbuf.append(m_executeSqlFragments[0]);
332 m_sqlFragments[0] = sbuf.toString();
333 System.arraycopy(m_executeSqlFragments, 1, m_sqlFragments, 1, m_sqlFragments.length - 1);
339 m_sqlFragments = m_executeSqlFragments;
343 // New in 7.1, pass Statement so that ExecSQL can customise to it
344 result = org.postgresql.core.QueryExecutor.execute(m_sqlFragments,
346 (java.sql.Statement)this);
348 //If we are executing a callable statement function set the return data
351 if (!((AbstractJdbc1ResultSet)result).reallyResultSet())
352 throw new PSQLException("postgresql.call.noreturnval");
354 throw new PSQLException ("postgresql.call.noreturnval");
355 callResult = result.getObject(1);
356 int columnType = result.getMetaData().getColumnType(1);
357 if (columnType != functionReturnType)
358 throw new PSQLException ("postgresql.call.wrongrtntype",
360 "java.sql.Types=" + columnType, "java.sql.Types=" + functionReturnType });
366 return (result != null && ((AbstractJdbc1ResultSet)result).reallyResultSet());
370 /** version of execute which converts the query to a cursor.
372 public boolean executeWithCursor() throws SQLException
374 if (isFunction && !returnTypeSet)
375 throw new PSQLException("postgresql.call.noreturntype");
377 { // set entry 1 to dummy entry..
378 m_binds[0] = ""; // dummy entry which ensured that no one overrode
379 m_bindTypes[0] = PG_TEXT;
380 // and calls to setXXX (2,..) really went to first arg in a function call..
383 // New in 7.1, if we have a previous resultset then force it to close
384 // This brings us nearer to compliance, and helps memory management.
385 // Internal stuff will call ExecSQL directly, bypassing this.
388 java.sql.ResultSet rs = getResultSet();
393 // I've pretty much ignored server prepared statements... can declare and prepare be
395 // It's trivial to change this: you just have to resolve this issue
396 // of how to work out whether there's a function call. If there isn't then the first
397 // element of the array must be the bit that you extend to become the cursor
399 // The last thing that can go wrong is when the user supplies a cursor statement
400 // directly: the translation takes no account of that. I think we should just look
401 // for declare and stop the translation if we find it.
403 // The first thing to do is transform the statement text into the cursor form.
404 String[] origSqlFragments = m_sqlFragments;
405 m_sqlFragments = new String[origSqlFragments.length];
406 System.arraycopy(origSqlFragments, 0, m_sqlFragments, 0, origSqlFragments.length);
407 // Pinch the prepared count for our own nefarious purposes.
408 m_statementName = "JDBC_CURS_" + m_preparedCount++;
409 // The static bit to prepend to all querys.
410 String cursDecl = "BEGIN; DECLARE " + m_statementName + " CURSOR FOR ";
411 String endCurs = " FETCH FORWARD " + fetchSize + " FROM " + m_statementName + ";";
413 // Add the real query to the curs decleration.
414 // This is the bit that really makes the presumption about
415 // m_sqlFragments not being a function call.
416 if (m_sqlFragments.length < 1)
417 m_sqlFragments[0] = cursDecl + "SELECT NULL;";
419 else if (m_sqlFragments.length < 2)
421 if (m_sqlFragments[0].endsWith(";"))
422 m_sqlFragments[0] = cursDecl + m_sqlFragments[0] + endCurs;
424 m_sqlFragments[0] = cursDecl + m_sqlFragments[0] + ";" + endCurs;
428 m_sqlFragments[0] = cursDecl + m_sqlFragments[0];
429 if (m_sqlFragments[m_sqlFragments.length - 1].endsWith(";"))
430 m_sqlFragments[m_sqlFragments.length - 1] += endCurs;
432 m_sqlFragments[m_sqlFragments.length - 1] += (";" + endCurs);
435 result = org.postgresql.core.QueryExecutor.execute(m_sqlFragments,
437 (java.sql.Statement)this);
439 //If we are executing a callable statement function set the return data
442 if (!((AbstractJdbc1ResultSet)result).reallyResultSet())
443 throw new PSQLException("postgresql.call.noreturnval");
445 throw new PSQLException ("postgresql.call.noreturnval");
446 callResult = result.getObject(1);
447 int columnType = result.getMetaData().getColumnType(1);
448 if (columnType != functionReturnType)
451 { "java.sql.Types=" + columnType,
452 "java.sql.Types=" + functionReturnType
454 throw new PSQLException ("postgresql.call.wrongrtntype",arr);
461 return (result != null && ((AbstractJdbc1ResultSet)result).reallyResultSet());
467 * setCursorName defines the SQL cursor name that will be used by
468 * subsequent execute methods. This name can then be used in SQL
469 * positioned update/delete statements to identify the current row
470 * in the ResultSet generated by this statement. If a database
471 * doesn't support positioned update/delete, this method is a
474 * <p><B>Note:</B> By definition, positioned update/delete execution
475 * must be done by a different Statement than the one which
476 * generated the ResultSet being used for positioning. Also, cursor
477 * names must be unique within a Connection.
479 * <p>We throw an additional constriction. There can only be one
480 * cursor active at any one time.
482 * @param name the new cursor name
483 * @exception SQLException if a database access error occurs
485 public void setCursorName(String name) throws SQLException
487 ((AbstractJdbc1Connection)connection).setCursorName(name);
492 * getUpdateCount returns the current result as an update count,
493 * if the result is a ResultSet or there are no more results, -1
494 * is returned. It should only be called once per result.
496 * @return the current result as an update count.
497 * @exception SQLException if a database access error occurs
499 public int getUpdateCount() throws SQLException
505 if (((AbstractJdbc1ResultSet)result).reallyResultSet())
507 return ((AbstractJdbc1ResultSet)result).getResultCount();
511 * getMoreResults moves to a Statement's next result. If it returns
512 * true, this result is a ResulSet.
514 * @return true if the next ResultSet is valid
515 * @exception SQLException if a database access error occurs
517 public boolean getMoreResults() throws SQLException
519 result = ((AbstractJdbc1ResultSet)result).getNext();
520 return (result != null && ((AbstractJdbc1ResultSet)result).reallyResultSet());
526 * Returns the status message from the current Result.<p>
527 * This is used internally by the driver.
529 * @return status message from backend
531 public String getResultStatusString()
535 return ((AbstractJdbc1ResultSet)result).getStatusString();
539 * The maxRows limit is set to limit the number of rows that
540 * any ResultSet can contain. If the limit is exceeded, the
541 * excess rows are silently dropped.
543 * @return the current maximum row limit; zero means unlimited
544 * @exception SQLException if a database access error occurs
546 public int getMaxRows() throws SQLException
552 * Set the maximum number of rows
554 * @param max the new max rows limit; zero means unlimited
555 * @exception SQLException if a database access error occurs
558 public void setMaxRows(int max) throws SQLException
564 * If escape scanning is on (the default), the driver will do escape
565 * substitution before sending the SQL to the database.
567 * @param enable true to enable; false to disable
568 * @exception SQLException if a database access error occurs
570 public void setEscapeProcessing(boolean enable) throws SQLException
572 replaceProcessingEnabled = enable;
576 * The queryTimeout limit is the number of seconds the driver
577 * will wait for a Statement to execute. If the limit is
578 * exceeded, a SQLException is thrown.
580 * @return the current query timeout limit in seconds; 0 = unlimited
581 * @exception SQLException if a database access error occurs
583 public int getQueryTimeout() throws SQLException
589 * Sets the queryTimeout limit
591 * @param seconds - the new query timeout limit in seconds
592 * @exception SQLException if a database access error occurs
594 public void setQueryTimeout(int seconds) throws SQLException
600 * This adds a warning to the warning chain.
601 * @param msg message to add
603 public void addWarning(String msg)
605 if (warnings != null)
606 warnings.setNextWarning(new SQLWarning(msg));
608 warnings = new SQLWarning(msg);
612 * The first warning reported by calls on this Statement is
613 * returned. A Statement's execute methods clear its SQLWarning
614 * chain. Subsequent Statement warnings will be chained to this
617 * <p>The Warning chain is automatically cleared each time a statement
620 * <p><B>Note:</B> If you are processing a ResultSet then any warnings
621 * associated with ResultSet reads will be chained on the ResultSet
624 * @return the first SQLWarning on null
625 * @exception SQLException if a database access error occurs
627 public SQLWarning getWarnings() throws SQLException
633 * The maxFieldSize limit (in bytes) is the maximum amount of
634 * data returned for any column value; it only applies to
635 * BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR
636 * columns. If the limit is exceeded, the excess data is silently
639 * @return the current max column size limit; zero means unlimited
640 * @exception SQLException if a database access error occurs
642 public int getMaxFieldSize() throws SQLException
644 return 8192; // We cannot change this
648 * Sets the maxFieldSize - NOT! - We throw an SQLException just
649 * to inform them to stop doing this.
651 * @param max the new max column size limit; zero means unlimited
652 * @exception SQLException if a database access error occurs
654 public void setMaxFieldSize(int max) throws SQLException
656 throw new PSQLException("postgresql.stat.maxfieldsize");
660 * After this call, getWarnings returns null until a new warning
661 * is reported for this Statement.
663 * @exception SQLException if a database access error occurs
665 public void clearWarnings() throws SQLException
671 * Cancel can be used by one thread to cancel a statement that
672 * is being executed by another thread.
674 * Not implemented, this method is a no-op.
676 * @exception SQLException only because thats the spec.
678 public void cancel() throws SQLException
680 throw new PSQLException("postgresql.unimplemented");
684 * getResultSet returns the current result as a ResultSet. It
685 * should only be called once per result.
687 * @return the current result set; null if there are no more
688 * @exception SQLException if a database access error occurs (why?)
690 public java.sql.ResultSet getResultSet() throws SQLException
692 if (result != null && ((AbstractJdbc1ResultSet) result).reallyResultSet())
698 * In many cases, it is desirable to immediately release a
699 * Statement's database and JDBC resources instead of waiting
700 * for this to happen when it is automatically closed. The
701 * close method provides this immediate release.
703 * <p><B>Note:</B> A Statement is automatically closed when it is
704 * garbage collected. When a Statement is closed, its current
705 * ResultSet, if one exists, is also closed.
707 * @exception SQLException if a database access error occurs (why?)
709 public void close() throws SQLException
711 // Force the ResultSet to close
712 java.sql.ResultSet rs = getResultSet();
716 // If using server prepared statements deallocate them
717 if (m_useServerPrepare && m_statementName != null) {
718 ((AbstractJdbc1Connection)connection).execSQL("DEALLOCATE " + m_statementName);
721 // Disasociate it from us (For Garbage Collection)
726 * Filter the SQL string of Java SQL Escape clauses.
728 * Currently implemented Escape clauses are those mentioned in 11.3
729 * in the specification. Basically we look through the sql string for
730 * {d xxx}, {t xxx} or {ts xxx} in non-string sql code. When we find
731 * them, we just strip the escape part leaving only the xxx part.
732 * So, something like "select * from x where d={d '2001-10-09'}" would
733 * return "select * from x where d= '2001-10-09'".
735 protected String replaceProcessing(String p_sql)
737 if (replaceProcessingEnabled)
739 // Since escape codes can only appear in SQL CODE, we keep track
740 // of if we enter a string or not.
741 StringBuffer newsql = new StringBuffer(p_sql.length());
742 short state = IN_SQLCODE;
745 int len = p_sql.length();
748 char c = p_sql.charAt(i);
752 if (c == '\'') // start of a string?
754 else if (c == '{') // start of an escape code?
757 char next = p_sql.charAt(i + 1);
760 state = ESC_TIMEDATE;
764 else if (next == 't')
766 state = ESC_TIMEDATE;
767 i += (i + 2 < len && p_sql.charAt(i + 2) == 's') ? 2 : 1;
775 if (c == '\'') // end of string?
777 else if (c == '\\') // a backslash?
791 state = IN_SQLCODE; // end of escape code.
798 return newsql.toString();
808 * The following methods are postgres extensions and are defined
809 * in the interface org.postgresql.Statement
814 * Returns the Last inserted/updated oid. Deprecated in 7.2 because
815 * range of OID values is greater than a java signed int.
816 * @deprecated Replaced by getLastOID in 7.2
818 public int getInsertedOID() throws SQLException
822 return (int)((AbstractJdbc1ResultSet)result).getLastOID();
826 * Returns the Last inserted/updated oid.
827 * @return OID of last insert
830 public long getLastOID() throws SQLException
834 return ((AbstractJdbc1ResultSet)result).getLastOID();
838 * Set a parameter to SQL NULL
840 * <p><B>Note:</B> You must specify the parameters SQL type (although
841 * PostgreSQL ignores it)
843 * @param parameterIndex the first parameter is 1, etc...
844 * @param sqlType the SQL type code defined in java.sql.Types
845 * @exception SQLException if a database access error occurs
847 public void setNull(int parameterIndex, int sqlType) throws SQLException
853 l_pgType = PG_INTEGER;
867 l_pgType = PG_DOUBLE;
871 l_pgType = PG_NUMERIC;
875 case Types.LONGVARCHAR:
884 case Types.TIMESTAMP:
885 l_pgType = PG_TIMESTAMPTZ;
888 case Types.VARBINARY:
897 bind(parameterIndex, "null", l_pgType);
901 * Set a parameter to a Java boolean value. The driver converts this
902 * to a SQL BIT value when it sends it to the database.
904 * @param parameterIndex the first parameter is 1...
905 * @param x the parameter value
906 * @exception SQLException if a database access error occurs
908 public void setBoolean(int parameterIndex, boolean x) throws SQLException
910 bind(parameterIndex, x ? "'t'" : "'f'", PG_BOOLEAN);
914 * Set a parameter to a Java byte value. The driver converts this to
915 * a SQL TINYINT value when it sends it to the database.
917 * @param parameterIndex the first parameter is 1...
918 * @param x the parameter value
919 * @exception SQLException if a database access error occurs
921 public void setByte(int parameterIndex, byte x) throws SQLException
923 bind(parameterIndex, Integer.toString(x), PG_TEXT);
927 * Set a parameter to a Java short value. The driver converts this
928 * to a SQL SMALLINT value when it sends it to the database.
930 * @param parameterIndex the first parameter is 1...
931 * @param x the parameter value
932 * @exception SQLException if a database access error occurs
934 public void setShort(int parameterIndex, short x) throws SQLException
936 bind(parameterIndex, Integer.toString(x), PG_INT2);
940 * Set a parameter to a Java int value. The driver converts this to
941 * a SQL INTEGER value when it sends it to the database.
943 * @param parameterIndex the first parameter is 1...
944 * @param x the parameter value
945 * @exception SQLException if a database access error occurs
947 public void setInt(int parameterIndex, int x) throws SQLException
949 bind(parameterIndex, Integer.toString(x), PG_INTEGER);
953 * Set a parameter to a Java long value. The driver converts this to
954 * a SQL BIGINT value when it sends it to the database.
956 * @param parameterIndex the first parameter is 1...
957 * @param x the parameter value
958 * @exception SQLException if a database access error occurs
960 public void setLong(int parameterIndex, long x) throws SQLException
962 bind(parameterIndex, Long.toString(x), PG_INT8);
966 * Set a parameter to a Java float value. The driver converts this
967 * to a SQL FLOAT value when it sends it to the database.
969 * @param parameterIndex the first parameter is 1...
970 * @param x the parameter value
971 * @exception SQLException if a database access error occurs
973 public void setFloat(int parameterIndex, float x) throws SQLException
975 bind(parameterIndex, Float.toString(x), PG_FLOAT);
979 * Set a parameter to a Java double value. The driver converts this
980 * to a SQL DOUBLE value when it sends it to the database
982 * @param parameterIndex the first parameter is 1...
983 * @param x the parameter value
984 * @exception SQLException if a database access error occurs
986 public void setDouble(int parameterIndex, double x) throws SQLException
988 bind(parameterIndex, Double.toString(x), PG_DOUBLE);
992 * Set a parameter to a java.lang.BigDecimal value. The driver
993 * converts this to a SQL NUMERIC value when it sends it to the
996 * @param parameterIndex the first parameter is 1...
997 * @param x the parameter value
998 * @exception SQLException if a database access error occurs
1000 public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
1003 setNull(parameterIndex, Types.DECIMAL);
1006 bind(parameterIndex, x.toString(), PG_NUMERIC);
1011 * Set a parameter to a Java String value. The driver converts this
1012 * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
1013 * size relative to the driver's limits on VARCHARs) when it sends it
1016 * @param parameterIndex the first parameter is 1...
1017 * @param x the parameter value
1018 * @exception SQLException if a database access error occurs
1020 public void setString(int parameterIndex, String x) throws SQLException
1022 setString(parameterIndex, x, PG_TEXT);
1025 public void setString(int parameterIndex, String x, String type) throws SQLException
1027 // if the passed string is null, then set this column to null
1029 setNull(parameterIndex, Types.VARCHAR);
1032 // use the shared buffer object. Should never clash but this makes
1037 sbuf.ensureCapacity(x.length());
1041 for (i = 0 ; i < x.length() ; ++i)
1043 char c = x.charAt(i);
1044 if (c == '\\' || c == '\'')
1045 sbuf.append((char)'\\');
1049 bind(parameterIndex, sbuf.toString(), type);
1055 * Set a parameter to a Java array of bytes. The driver converts this
1056 * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
1057 * size relative to the driver's limits on VARBINARYs) when it sends
1058 * it to the database.
1060 * <p>Implementation note:
1061 * <br>With org.postgresql, this creates a large object, and stores the
1062 * objects oid in this column.
1064 * @param parameterIndex the first parameter is 1...
1065 * @param x the parameter value
1066 * @exception SQLException if a database access error occurs
1068 public void setBytes(int parameterIndex, byte x[]) throws SQLException
1070 if (connection.haveMinimumCompatibleVersion("7.2"))
1072 //Version 7.2 supports the bytea datatype for byte arrays
1075 setNull(parameterIndex, Types.VARBINARY);
1079 setString(parameterIndex, PGbytea.toPGString(x), PG_TEXT);
1084 //Version 7.1 and earlier support done as LargeObjects
1085 LargeObjectManager lom = connection.getLargeObjectAPI();
1086 int oid = lom.create();
1087 LargeObject lob = lom.open(oid);
1090 setInt(parameterIndex, oid);
1095 * Set a parameter to a java.sql.Date value. The driver converts this
1096 * to a SQL DATE value when it sends it to the database.
1098 * @param parameterIndex the first parameter is 1...
1099 * @param x the parameter value
1100 * @exception SQLException if a database access error occurs
1102 public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
1106 setNull(parameterIndex, Types.DATE);
1110 bind(parameterIndex, "'" + x.toString() + "'", PG_DATE);
1115 * Set a parameter to a java.sql.Time value. The driver converts
1116 * this to a SQL TIME value when it sends it to the database.
1118 * @param parameterIndex the first parameter is 1...));
1119 * @param x the parameter value
1120 * @exception SQLException if a database access error occurs
1122 public void setTime(int parameterIndex, Time x) throws SQLException
1126 setNull(parameterIndex, Types.TIME);
1130 bind(parameterIndex, "'" + x.toString() + "'", PG_TIME);
1135 * Set a parameter to a java.sql.Timestamp value. The driver converts
1136 * this to a SQL TIMESTAMP value when it sends it to the database.
1138 * @param parameterIndex the first parameter is 1...
1139 * @param x the parameter value
1140 * @exception SQLException if a database access error occurs
1142 public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
1146 setNull(parameterIndex, Types.TIMESTAMP);
1150 // Use the shared StringBuffer
1154 sbuf.ensureCapacity(32);
1156 //format the timestamp
1157 //we do our own formating so that we can get a format
1158 //that works with both timestamp with time zone and
1159 //timestamp without time zone datatypes.
1160 //The format is '2002-01-01 23:59:59.123456-0130'
1161 //we need to include the local time and timezone offset
1162 //so that timestamp without time zone works correctly
1163 int l_year = x.getYear() + 1900;
1164 sbuf.append(l_year);
1166 int l_month = x.getMonth() + 1;
1169 sbuf.append(l_month);
1171 int l_day = x.getDate();
1176 int l_hours = x.getHours();
1179 sbuf.append(l_hours);
1181 int l_minutes = x.getMinutes();
1184 sbuf.append(l_minutes);
1186 int l_seconds = x.getSeconds();
1189 sbuf.append(l_seconds);
1190 // Make decimal from nanos.
1191 char[] l_decimal = {'0', '0', '0', '0', '0', '0', '0', '0', '0'};
1192 char[] l_nanos = Integer.toString(x.getNanos()).toCharArray();
1193 System.arraycopy(l_nanos, 0, l_decimal, l_decimal.length - l_nanos.length, l_nanos.length);
1195 if (connection.haveMinimumServerVersion("7.2"))
1197 sbuf.append(l_decimal, 0, 6);
1201 // Because 7.1 include bug that "hh:mm:59.999" becomes "hh:mm:60.00".
1202 sbuf.append(l_decimal, 0, 2);
1204 //add timezone offset
1205 int l_offset = -(x.getTimezoneOffset());
1206 int l_houros = l_offset / 60;
1215 if (l_houros > -10 && l_houros < 10)
1219 sbuf.append(l_houros);
1223 sbuf.append( -l_houros);
1225 int l_minos = l_offset - (l_houros * 60);
1230 sbuf.append(l_minos);
1233 bind(parameterIndex, sbuf.toString(), PG_TIMESTAMPTZ);
1240 * When a very large ASCII value is input to a LONGVARCHAR parameter,
1241 * it may be more practical to send it via a java.io.InputStream.
1242 * JDBC will read the data from the stream as needed, until it reaches
1243 * end-of-file. The JDBC driver will do any necessary conversion from
1244 * ASCII to the database char format.
1246 * <P><B>Note:</B> This stream object can either be a standard Java
1247 * stream object or your own subclass that implements the standard
1250 * @param parameterIndex the first parameter is 1...
1251 * @param x the parameter value
1252 * @param length the number of bytes in the stream
1253 * @exception SQLException if a database access error occurs
1255 public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
1257 if (connection.haveMinimumCompatibleVersion("7.2"))
1259 //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
1260 //As the spec/javadoc for this method indicate this is to be used for
1261 //large String values (i.e. LONGVARCHAR) PG doesn't have a separate
1262 //long varchar datatype, but with toast all text datatypes are capable of
1263 //handling very large values. Thus the implementation ends up calling
1264 //setString() since there is no current way to stream the value to the server
1267 InputStreamReader l_inStream = new InputStreamReader(x, "ASCII");
1268 char[] l_chars = new char[length];
1269 int l_charsRead = l_inStream.read(l_chars, 0, length);
1270 setString(parameterIndex, new String(l_chars, 0, l_charsRead), PG_TEXT);
1272 catch (UnsupportedEncodingException l_uee)
1274 throw new PSQLException("postgresql.unusual", l_uee);
1276 catch (IOException l_ioe)
1278 throw new PSQLException("postgresql.unusual", l_ioe);
1283 //Version 7.1 supported only LargeObjects by treating everything
1285 setBinaryStream(parameterIndex, x, length);
1290 * When a very large Unicode value is input to a LONGVARCHAR parameter,
1291 * it may be more practical to send it via a java.io.InputStream.
1292 * JDBC will read the data from the stream as needed, until it reaches
1293 * end-of-file. The JDBC driver will do any necessary conversion from
1294 * UNICODE to the database char format.
1296 * <P><B>Note:</B> This stream object can either be a standard Java
1297 * stream object or your own subclass that implements the standard
1300 * @param parameterIndex the first parameter is 1...
1301 * @param x the parameter value
1302 * @exception SQLException if a database access error occurs
1304 public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
1306 if (connection.haveMinimumCompatibleVersion("7.2"))
1308 //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
1309 //As the spec/javadoc for this method indicate this is to be used for
1310 //large String values (i.e. LONGVARCHAR) PG doesn't have a separate
1311 //long varchar datatype, but with toast all text datatypes are capable of
1312 //handling very large values. Thus the implementation ends up calling
1313 //setString() since there is no current way to stream the value to the server
1316 InputStreamReader l_inStream = new InputStreamReader(x, "UTF-8");
1317 char[] l_chars = new char[length];
1318 int l_charsRead = l_inStream.read(l_chars, 0, length);
1319 setString(parameterIndex, new String(l_chars, 0, l_charsRead), PG_TEXT);
1321 catch (UnsupportedEncodingException l_uee)
1323 throw new PSQLException("postgresql.unusual", l_uee);
1325 catch (IOException l_ioe)
1327 throw new PSQLException("postgresql.unusual", l_ioe);
1332 //Version 7.1 supported only LargeObjects by treating everything
1334 setBinaryStream(parameterIndex, x, length);
1339 * When a very large binary value is input to a LONGVARBINARY parameter,
1340 * it may be more practical to send it via a java.io.InputStream.
1341 * JDBC will read the data from the stream as needed, until it reaches
1344 * <P><B>Note:</B> This stream object can either be a standard Java
1345 * stream object or your own subclass that implements the standard
1348 * @param parameterIndex the first parameter is 1...
1349 * @param x the parameter value
1350 * @exception SQLException if a database access error occurs
1352 public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
1354 if (connection.haveMinimumCompatibleVersion("7.2"))
1356 //Version 7.2 supports BinaryStream for for the PG bytea type
1357 //As the spec/javadoc for this method indicate this is to be used for
1358 //large binary values (i.e. LONGVARBINARY) PG doesn't have a separate
1359 //long binary datatype, but with toast the bytea datatype is capable of
1360 //handling very large values. Thus the implementation ends up calling
1361 //setBytes() since there is no current way to stream the value to the server
1362 byte[] l_bytes = new byte[length];
1366 l_bytesRead = x.read(l_bytes, 0, length);
1368 catch (IOException l_ioe)
1370 throw new PSQLException("postgresql.unusual", l_ioe);
1372 if (l_bytesRead == length)
1374 setBytes(parameterIndex, l_bytes);
1378 //the stream contained less data than they said
1379 byte[] l_bytes2 = new byte[l_bytesRead];
1380 System.arraycopy(l_bytes, 0, l_bytes2, 0, l_bytesRead);
1381 setBytes(parameterIndex, l_bytes2);
1386 //Version 7.1 only supported streams for LargeObjects
1387 //but the jdbc spec indicates that streams should be
1388 //available for LONGVARBINARY instead
1389 LargeObjectManager lom = connection.getLargeObjectAPI();
1390 int oid = lom.create();
1391 LargeObject lob = lom.open(oid);
1392 OutputStream los = lob.getOutputStream();
1395 // could be buffered, but then the OutputStream returned by LargeObject
1396 // is buffered internally anyhow, so there would be no performance
1397 // boost gained, if anything it would be worse!
1400 while (c > -1 && p < length)
1408 catch (IOException se)
1410 throw new PSQLException("postgresql.unusual", se);
1412 // lob is closed by the stream so don't call lob.close()
1413 setInt(parameterIndex, oid);
1419 * In general, parameter values remain in force for repeated used of a
1420 * Statement. Setting a parameter value automatically clears its
1421 * previous value. However, in coms cases, it is useful to immediately
1422 * release the resources used by the current parameter values; this
1423 * can be done by calling clearParameters
1425 * @exception SQLException if a database access error occurs
1427 public void clearParameters() throws SQLException
1431 for (i = 0 ; i < m_binds.length ; i++)
1434 m_bindTypes[i] = null;
1439 * Set the value of a parameter using an object; use the java.lang
1440 * equivalent objects for integral values.
1442 * <P>The given Java object will be converted to the targetSqlType before
1443 * being sent to the database.
1445 * <P>note that this method may be used to pass database-specific
1446 * abstract data types. This is done by using a Driver-specific
1447 * Java type and using a targetSqlType of java.sql.Types.OTHER
1449 * @param parameterIndex the first parameter is 1...
1450 * @param x the object containing the input parameter value
1451 * @param targetSqlType The SQL type to be send to the database
1452 * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
1453 * * types this is the number of digits after the decimal. For
1454 * * all other types this value will be ignored.
1455 * @exception SQLException if a database access error occurs
1457 public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
1461 setNull(parameterIndex, targetSqlType);
1464 switch (targetSqlType)
1467 bind(parameterIndex, x.toString(), PG_INTEGER);
1470 case Types.SMALLINT:
1477 if (x instanceof Boolean)
1478 bind(parameterIndex, ((Boolean)x).booleanValue() ? "1" : "0", PG_BOOLEAN);
1480 bind(parameterIndex, x.toString(), PG_NUMERIC);
1484 case Types.LONGVARCHAR:
1485 setString(parameterIndex, x.toString());
1488 setDate(parameterIndex, (java.sql.Date)x);
1491 setTime(parameterIndex, (Time)x);
1493 case Types.TIMESTAMP:
1494 setTimestamp(parameterIndex, (Timestamp)x);
1497 if (x instanceof Boolean)
1499 bind(parameterIndex, ((Boolean)x).booleanValue() ? "TRUE" : "FALSE", PG_TEXT);
1503 throw new PSQLException("postgresql.prep.type");
1507 case Types.VARBINARY:
1508 setObject(parameterIndex, x);
1511 setString(parameterIndex, ((PGobject)x).getValue(), PG_TEXT);
1514 throw new PSQLException("postgresql.prep.type");
1518 public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
1520 setObject(parameterIndex, x, targetSqlType, 0);
1524 * This stores an Object into a parameter.
1525 * <p>New for 6.4, if the object is not recognised, but it is
1526 * Serializable, then the object is serialised using the
1527 * org.postgresql.util.Serialize class.
1529 public void setObject(int parameterIndex, Object x) throws SQLException
1534 if (x instanceof String)
1535 l_sqlType = Types.VARCHAR;
1536 else if (x instanceof BigDecimal)
1537 l_sqlType = Types.DECIMAL;
1538 else if (x instanceof Short)
1539 l_sqlType = Types.SMALLINT;
1540 else if (x instanceof Integer)
1541 l_sqlType = Types.INTEGER;
1542 else if (x instanceof Long)
1543 l_sqlType = Types.BIGINT;
1544 else if (x instanceof Float)
1545 l_sqlType = Types.FLOAT;
1546 else if (x instanceof Double)
1547 l_sqlType = Types.DOUBLE;
1548 else if (x instanceof byte[])
1549 l_sqlType = Types.BINARY;
1550 else if (x instanceof java.sql.Date)
1551 l_sqlType = Types.DATE;
1552 else if (x instanceof Time)
1553 l_sqlType = Types.TIME;
1554 else if (x instanceof Timestamp)
1555 l_sqlType = Types.TIMESTAMP;
1556 else if (x instanceof Boolean)
1557 l_sqlType = Types.OTHER;
1559 l_sqlType = Types.OTHER;
1561 setNull(parameterIndex, l_sqlType);
1564 if (x instanceof String)
1565 setString(parameterIndex, (String)x);
1566 else if (x instanceof BigDecimal)
1567 setBigDecimal(parameterIndex, (BigDecimal)x);
1568 else if (x instanceof Short)
1569 setShort(parameterIndex, ((Short)x).shortValue());
1570 else if (x instanceof Integer)
1571 setInt(parameterIndex, ((Integer)x).intValue());
1572 else if (x instanceof Long)
1573 setLong(parameterIndex, ((Long)x).longValue());
1574 else if (x instanceof Float)
1575 setFloat(parameterIndex, ((Float)x).floatValue());
1576 else if (x instanceof Double)
1577 setDouble(parameterIndex, ((Double)x).doubleValue());
1578 else if (x instanceof byte[])
1579 setBytes(parameterIndex, (byte[])x);
1580 else if (x instanceof java.sql.Date)
1581 setDate(parameterIndex, (java.sql.Date)x);
1582 else if (x instanceof Time)
1583 setTime(parameterIndex, (Time)x);
1584 else if (x instanceof Timestamp)
1585 setTimestamp(parameterIndex, (Timestamp)x);
1586 else if (x instanceof Boolean)
1587 setBoolean(parameterIndex, ((Boolean)x).booleanValue());
1588 else if (x instanceof PGobject)
1589 setString(parameterIndex, ((PGobject)x).getValue(), PG_TEXT);
1591 // Try to store java object in database
1592 setSerialize(parameterIndex, connection.storeObject(x), x.getClass().getName() );
1596 * Before executing a stored procedure call you must explicitly
1597 * call registerOutParameter to register the java.sql.Type of each
1600 * <p>Note: When reading the value of an out parameter, you must use
1601 * the getXXX method whose Java type XXX corresponds to the
1602 * parameter's registered SQL type.
1604 * ONLY 1 RETURN PARAMETER if {?= call ..} syntax is used
1606 * @param parameterIndex the first parameter is 1, the second is 2,...
1607 * @param sqlType SQL type code defined by java.sql.Types; for
1608 * parameters of type Numeric or Decimal use the version of
1609 * registerOutParameter that accepts a scale value
1610 * @exception SQLException if a database-access error occurs.
1612 public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException
1614 if (parameterIndex != 1)
1615 throw new PSQLException ("postgresql.call.noinout");
1617 throw new PSQLException ("postgresql.call.procasfunc", originalSql);
1619 // functionReturnType contains the user supplied value to check
1620 // testReturn contains a modified version to make it easier to
1621 // check the getXXX methods..
1622 functionReturnType = sqlType;
1623 testReturn = sqlType;
1624 if (functionReturnType == Types.CHAR ||
1625 functionReturnType == Types.LONGVARCHAR)
1626 testReturn = Types.VARCHAR;
1627 else if (functionReturnType == Types.FLOAT)
1628 testReturn = Types.REAL; // changes to streamline later error checking
1629 returnTypeSet = true;
1633 * You must also specify the scale for numeric/decimal types:
1635 * <p>Note: When reading the value of an out parameter, you must use
1636 * the getXXX method whose Java type XXX corresponds to the
1637 * parameter's registered SQL type.
1639 * @param parameterIndex the first parameter is 1, the second is 2,...
1640 * @param sqlType use either java.sql.Type.NUMERIC or java.sql.Type.DECIMAL
1641 * @param scale a value greater than or equal to zero representing the
1642 * desired number of digits to the right of the decimal point
1643 * @exception SQLException if a database-access error occurs.
1645 public void registerOutParameter(int parameterIndex, int sqlType,
1646 int scale) throws SQLException
1648 registerOutParameter (parameterIndex, sqlType); // ignore for now..
1652 * An OUT parameter may have the value of SQL NULL; wasNull
1653 * reports whether the last value read has this special value.
1655 * <p>Note: You must first call getXXX on a parameter to read its
1656 * value and then call wasNull() to see if the value was SQL NULL.
1657 * @return true if the last parameter read was SQL NULL
1658 * @exception SQLException if a database-access error occurs.
1660 public boolean wasNull() throws SQLException
1662 // check to see if the last access threw an exception
1663 return (callResult == null);
1667 * Get the value of a CHAR, VARCHAR, or LONGVARCHAR parameter as a
1670 * @param parameterIndex the first parameter is 1, the second is 2,...
1671 * @return the parameter value; if the value is SQL NULL, the result is null
1672 * @exception SQLException if a database-access error occurs.
1674 public String getString(int parameterIndex) throws SQLException
1676 checkIndex (parameterIndex, Types.VARCHAR, "String");
1677 return (String)callResult;
1682 * Get the value of a BIT parameter as a Java boolean.
1684 * @param parameterIndex the first parameter is 1, the second is 2,...
1685 * @return the parameter value; if the value is SQL NULL, the result is false
1686 * @exception SQLException if a database-access error occurs.
1688 public boolean getBoolean(int parameterIndex) throws SQLException
1690 checkIndex (parameterIndex, Types.BIT, "Boolean");
1691 if (callResult == null)
1693 return ((Boolean)callResult).booleanValue ();
1697 * Get the value of a TINYINT parameter as a Java byte.
1699 * @param parameterIndex the first parameter is 1, the second is 2,...
1700 * @return the parameter value; if the value is SQL NULL, the result is 0
1701 * @exception SQLException if a database-access error occurs.
1703 public byte getByte(int parameterIndex) throws SQLException
1705 checkIndex (parameterIndex, Types.TINYINT, "Byte");
1706 if (callResult == null)
1708 return (byte)((Integer)callResult).intValue ();
1712 * Get the value of a SMALLINT parameter as a Java short.
1714 * @param parameterIndex the first parameter is 1, the second is 2,...
1715 * @return the parameter value; if the value is SQL NULL, the result is 0
1716 * @exception SQLException if a database-access error occurs.
1718 public short getShort(int parameterIndex) throws SQLException
1720 checkIndex (parameterIndex, Types.SMALLINT, "Short");
1721 if (callResult == null)
1723 return (short)((Integer)callResult).intValue ();
1728 * Get the value of an INTEGER parameter as a Java int.
1730 * @param parameterIndex the first parameter is 1, the second is 2,...
1731 * @return the parameter value; if the value is SQL NULL, the result is 0
1732 * @exception SQLException if a database-access error occurs.
1734 public int getInt(int parameterIndex) throws SQLException
1736 checkIndex (parameterIndex, Types.INTEGER, "Int");
1737 if (callResult == null)
1739 return ((Integer)callResult).intValue ();
1743 * Get the value of a BIGINT parameter as a Java long.
1745 * @param parameterIndex the first parameter is 1, the second is 2,...
1746 * @return the parameter value; if the value is SQL NULL, the result is 0
1747 * @exception SQLException if a database-access error occurs.
1749 public long getLong(int parameterIndex) throws SQLException
1751 checkIndex (parameterIndex, Types.BIGINT, "Long");
1752 if (callResult == null)
1754 return ((Long)callResult).longValue ();
1758 * Get the value of a FLOAT parameter as a Java float.
1760 * @param parameterIndex the first parameter is 1, the second is 2,...
1761 * @return the parameter value; if the value is SQL NULL, the result is 0
1762 * @exception SQLException if a database-access error occurs.
1764 public float getFloat(int parameterIndex) throws SQLException
1766 checkIndex (parameterIndex, Types.REAL, "Float");
1767 if (callResult == null)
1769 return ((Float)callResult).floatValue ();
1773 * Get the value of a DOUBLE parameter as a Java double.
1775 * @param parameterIndex the first parameter is 1, the second is 2,...
1776 * @return the parameter value; if the value is SQL NULL, the result is 0
1777 * @exception SQLException if a database-access error occurs.
1779 public double getDouble(int parameterIndex) throws SQLException
1781 checkIndex (parameterIndex, Types.DOUBLE, "Double");
1782 if (callResult == null)
1784 return ((Double)callResult).doubleValue ();
1788 * Get the value of a NUMERIC parameter as a java.math.BigDecimal
1791 * @param parameterIndex the first parameter is 1, the second is 2,...
1792 * @param scale a value greater than or equal to zero representing the
1793 * desired number of digits to the right of the decimal point
1794 * @return the parameter value; if the value is SQL NULL, the result is null
1795 * @exception SQLException if a database-access error occurs.
1796 * @deprecated in Java2.0
1798 public BigDecimal getBigDecimal(int parameterIndex, int scale)
1801 checkIndex (parameterIndex, Types.NUMERIC, "BigDecimal");
1802 return ((BigDecimal)callResult);
1806 * Get the value of a SQL BINARY or VARBINARY parameter as a Java
1809 * @param parameterIndex the first parameter is 1, the second is 2,...
1810 * @return the parameter value; if the value is SQL NULL, the result is null
1811 * @exception SQLException if a database-access error occurs.
1813 public byte[] getBytes(int parameterIndex) throws SQLException
1815 checkIndex (parameterIndex, Types.VARBINARY, Types.BINARY, "Bytes");
1816 return ((byte [])callResult);
1821 * Get the value of a SQL DATE parameter as a java.sql.Date object
1823 * @param parameterIndex the first parameter is 1, the second is 2,...
1824 * @return the parameter value; if the value is SQL NULL, the result is null
1825 * @exception SQLException if a database-access error occurs.
1827 public java.sql.Date getDate(int parameterIndex) throws SQLException
1829 checkIndex (parameterIndex, Types.DATE, "Date");
1830 return (java.sql.Date)callResult;
1834 * Get the value of a SQL TIME parameter as a java.sql.Time object.
1836 * @param parameterIndex the first parameter is 1, the second is 2,...
1837 * @return the parameter value; if the value is SQL NULL, the result is null
1838 * @exception SQLException if a database-access error occurs.
1840 public java.sql.Time getTime(int parameterIndex) throws SQLException
1842 checkIndex (parameterIndex, Types.TIME, "Time");
1843 return (java.sql.Time)callResult;
1847 * Get the value of a SQL TIMESTAMP parameter as a java.sql.Timestamp object.
1849 * @param parameterIndex the first parameter is 1, the second is 2,...
1850 * @return the parameter value; if the value is SQL NULL, the result is null
1851 * @exception SQLException if a database-access error occurs.
1853 public java.sql.Timestamp getTimestamp(int parameterIndex)
1856 checkIndex (parameterIndex, Types.TIMESTAMP, "Timestamp");
1857 return (java.sql.Timestamp)callResult;
1860 // getObject returns a Java object for the parameter.
1861 // See the JDBC spec's "Dynamic Programming" chapter for details.
1863 * Get the value of a parameter as a Java object.
1865 * <p>This method returns a Java object whose type coresponds to the
1866 * SQL type that was registered for this parameter using
1867 * registerOutParameter.
1869 * <P>Note that this method may be used to read datatabase-specific,
1870 * abstract data types. This is done by specifying a targetSqlType
1871 * of java.sql.types.OTHER, which allows the driver to return a
1872 * database-specific Java type.
1874 * <p>See the JDBC spec's "Dynamic Programming" chapter for details.
1876 * @param parameterIndex the first parameter is 1, the second is 2,...
1877 * @return A java.lang.Object holding the OUT parameter value.
1878 * @exception SQLException if a database-access error occurs.
1880 public Object getObject(int parameterIndex)
1883 checkIndex (parameterIndex);
1888 * Returns the SQL statement with the current template values
1891 public String toString()
1893 if (m_sqlFragments == null)
1901 for (i = 0 ; i < m_binds.length ; ++i)
1903 sbuf.append (m_sqlFragments[i]);
1904 if (m_binds[i] == null)
1907 sbuf.append (m_binds[i]);
1909 sbuf.append(m_sqlFragments[m_binds.length]);
1910 return sbuf.toString();
1915 * There are a lot of setXXX classes which all basically do
1916 * the same thing. We need a method which actually does the
1919 * @param paramIndex the index into the inString
1920 * @param s a string to be stored
1921 * @exception SQLException if something goes wrong
1923 protected void bind(int paramIndex, Object s, String type) throws SQLException
1925 if (paramIndex < 1 || paramIndex > m_binds.length)
1926 throw new PSQLException("postgresql.prep.range");
1927 if (paramIndex == 1 && isFunction) // need to registerOut instead
1928 throw new PSQLException ("postgresql.call.funcover");
1929 m_binds[paramIndex - 1] = s;
1930 m_bindTypes[paramIndex - 1] = type;
1934 * Set a parameter to a tablerow-type oid reference.
1936 * @param parameterIndex the first parameter is 1...
1937 * @param x the oid of the object from org.postgresql.util.Serialize.store
1938 * @param classname the classname of the java object x
1939 * @exception SQLException if a database access error occurs
1941 private void setSerialize(int parameterIndex, long x, String classname) throws SQLException
1943 // converts . to _, toLowerCase, and ensures length < max name length
1944 String tablename = Serialize.toPostgreSQL((java.sql.Connection)connection, classname );
1945 DriverManager.println("setSerialize: setting " + x + "::" + tablename );
1947 // OID reference to tablerow-type must be cast like: <oid>::<tablename>
1948 // Note that postgres support for tablerow data types is incomplete/broken.
1949 // This cannot be just a plain OID because then there would be ambiguity
1950 // between when you want the oid itself and when you want the object
1951 // an oid references.
1952 bind(parameterIndex, Long.toString(x) + "::" + tablename, PG_TEXT );
1956 * this method will turn a string of the form
1957 * {? = call <some_function> (?, [?,..]) }
1958 * into the PostgreSQL format which is
1959 * select <some_function> (?, [?, ...]) as result
1960 * or select * from <some_function> (?, [?, ...]) as result (7.3)
1963 private String modifyJdbcCall(String p_sql) throws SQLException
1965 //Check that this is actually a call which should start with a {
1966 //if not do nothing and treat this as a standard prepared sql
1967 if (!p_sql.trim().startsWith("{")) {
1971 // syntax checking is not complete only a few basics :(
1972 originalSql = p_sql; // save for error msgs..
1973 String l_sql = p_sql;
1974 int index = l_sql.indexOf ("="); // is implied func or proc?
1975 boolean isValid = true;
1979 isValid = l_sql.indexOf ("?") < index; // ? before =
1981 l_sql = l_sql.trim ();
1982 if (l_sql.startsWith ("{") && l_sql.endsWith ("}"))
1984 l_sql = l_sql.substring (1, l_sql.length() - 1);
1988 index = l_sql.indexOf ("call");
1989 if (index == -1 || !isValid)
1990 throw new PSQLException ("postgresql.call.malformed",
1991 new Object[]{l_sql, JDBC_SYNTAX});
1992 l_sql = l_sql.replace ('{', ' '); // replace these characters
1993 l_sql = l_sql.replace ('}', ' ');
1994 l_sql = l_sql.replace (';', ' ');
1996 // this removes the 'call' string and also puts a hidden '?'
1997 // at the front of the line for functions, this will
1998 // allow the registerOutParameter to work correctly
1999 // because in the source sql there was one more ? for the return
2000 // value that is not needed by the postgres syntax. But to make
2001 // sure that the parameter numbers are the same as in the original
2002 // sql we add a dummy parameter in this case
2003 l_sql = (isFunction ? "?" : "") + l_sql.substring (index + 4);
2004 if (connection.haveMinimumServerVersion("7.3")) {
2005 l_sql = "select * from " + l_sql + " as " + RESULT_ALIAS + ";";
2007 l_sql = "select " + l_sql + " as " + RESULT_ALIAS + ";";
2012 /** helperfunction for the getXXX calls to check isFunction and index == 1
2013 * Compare BOTH type fields against the return type.
2015 protected void checkIndex (int parameterIndex, int type1, int type2, String getName)
2018 checkIndex (parameterIndex);
2019 if (type1 != this.testReturn && type2 != this.testReturn)
2020 throw new PSQLException("postgresql.call.wrongget",
2021 new Object[]{"java.sql.Types=" + testReturn,
2023 "java.sql.Types=" + type1});
2026 /** helperfunction for the getXXX calls to check isFunction and index == 1
2028 protected void checkIndex (int parameterIndex, int type, String getName)
2031 checkIndex (parameterIndex);
2032 if (type != this.testReturn)
2033 throw new PSQLException("postgresql.call.wrongget",
2034 new Object[]{"java.sql.Types=" + testReturn,
2036 "java.sql.Types=" + type});
2039 /** helperfunction for the getXXX calls to check isFunction and index == 1
2040 * @param parameterIndex index of getXXX (index)
2041 * check to make sure is a function and index == 1
2043 private void checkIndex (int parameterIndex) throws SQLException
2046 throw new PSQLException("postgresql.call.noreturntype");
2047 if (parameterIndex != 1)
2048 throw new PSQLException("postgresql.call.noinout");
2053 public void setUseServerPrepare(boolean flag) throws SQLException {
2054 //Server side prepared statements were introduced in 7.3
2055 if (connection.haveMinimumServerVersion("7.3")) {
2056 //If turning server prepared statements off deallocate statement
2057 //and reset statement name
2058 if (m_useServerPrepare != flag && !flag)
2059 ((AbstractJdbc1Connection)connection).execSQL("DEALLOCATE " + m_statementName);
2060 m_statementName = null;
2061 m_useServerPrepare = flag;
2063 //This is a pre 7.3 server so no op this method
2064 //which means we will never turn on the flag to use server
2065 //prepared statements and thus regular processing will continue
2069 public boolean isUseServerPrepare()
2071 return m_useServerPrepare;
2075 private static final String PG_TEXT = "text";
2076 private static final String PG_INTEGER = "integer";
2077 private static final String PG_INT2 = "int2";
2078 private static final String PG_INT8 = "int8";
2079 private static final String PG_NUMERIC = "numeric";
2080 private static final String PG_FLOAT = "float";
2081 private static final String PG_DOUBLE = "double precision";
2082 private static final String PG_BOOLEAN = "boolean";
2083 private static final String PG_DATE = "date";
2084 private static final String PG_TIME = "time";
2085 private static final String PG_TIMESTAMPTZ = "timestamptz";
2086 private static final String PG_BYTEA = "bytea";