Source Code Cross Referenced for AbstractJdbc2Statement.java in  » Database-JDBC-Connection-Pool » postgresql » org » postgresql » jdbc2 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database JDBC Connection Pool » postgresql » org.postgresql.jdbc2 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*-------------------------------------------------------------------------
0002:         *
0003:         * Copyright (c) 2004-2005, PostgreSQL Global Development Group
0004:         *
0005:         * IDENTIFICATION
0006:         *   $PostgreSQL: pgjdbc/org/postgresql/jdbc2/AbstractJdbc2Statement.java,v 1.104 2007/07/27 10:15:32 jurka Exp $
0007:         *
0008:         *-------------------------------------------------------------------------
0009:         */
0010:        package org.postgresql.jdbc2;
0011:
0012:        import java.io.*;
0013:        import java.lang.reflect.InvocationTargetException;
0014:        import java.lang.reflect.Method;
0015:        import java.math.*;
0016:        import java.sql.*;
0017:        import java.util.ArrayList;
0018:        import java.util.Vector;
0019:        import java.util.Calendar;
0020:
0021:        import org.postgresql.Driver;
0022:        import org.postgresql.largeobject.*;
0023:        import org.postgresql.core.*;
0024:        import org.postgresql.core.types.*;
0025:        import org.postgresql.util.PSQLException;
0026:        import org.postgresql.util.PSQLState;
0027:        import org.postgresql.util.PGobject;
0028:        import org.postgresql.util.GT;
0029:
0030:        /**
0031:         * This class defines methods of the jdbc2 specification.
0032:         * The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Statement
0033:         */
0034:        public abstract class AbstractJdbc2Statement implements  BaseStatement {
0035:            protected ArrayList batchStatements = null;
0036:            protected ArrayList batchParameters = null;
0037:            protected final int resultsettype; // the resultset type to return (ResultSet.TYPE_xxx)
0038:            protected final int concurrency; // is it updateable or not?     (ResultSet.CONCUR_xxx)
0039:            protected int fetchdirection = ResultSet.FETCH_FORWARD; // fetch direction hint (currently ignored)
0040:
0041:            // The connection who created us
0042:            protected BaseConnection connection;
0043:
0044:            /** The warnings chain. */
0045:            protected SQLWarning warnings = null;
0046:
0047:            /** Maximum number of rows to return, 0 = unlimited */
0048:            protected int maxrows = 0;
0049:
0050:            /** Number of rows to get in a batch. */
0051:            protected int fetchSize = 0;
0052:
0053:            /** Timeout (in seconds) for a query (not used) */
0054:            protected int timeout = 0;
0055:
0056:            protected boolean replaceProcessingEnabled = true;
0057:
0058:            /** The current results. */
0059:            protected ResultWrapper result = null;
0060:
0061:            /** The first unclosed result. */
0062:            protected ResultWrapper firstUnclosedResult = null;
0063:
0064:            /** used to differentiate between new function call
0065:             * logic and old function call logic
0066:             * will be set to true if the server is < 8.1 or 
0067:             * if we are using v2 protocol
0068:             * There is an exception to this where we are using v3, and the
0069:             * call does not have an out parameter before the call
0070:             */
0071:            protected boolean adjustIndex = false;
0072:
0073:            /*
0074:             * Used to set adjustIndex above
0075:             */
0076:            protected boolean outParmBeforeFunc = false;
0077:
0078:            // Static variables for parsing SQL when replaceProcessing is true.
0079:            private static final short IN_SQLCODE = 0;
0080:            private static final short IN_STRING = 1;
0081:            private static final short IN_IDENTIFIER = 6;
0082:            private static final short BACKSLASH = 2;
0083:            private static final short ESC_TIMEDATE = 3;
0084:            private static final short ESC_FUNCTION = 4;
0085:            private static final short ESC_OUTERJOIN = 5;
0086:            private static final short ESC_ESCAPECHAR = 7;
0087:
0088:            protected final Query preparedQuery; // Query fragments for prepared statement.
0089:            protected final ParameterList preparedParameters; // Parameter values for prepared statement.
0090:            protected Query lastSimpleQuery;
0091:
0092:            protected int m_prepareThreshold; // Reuse threshold to enable use of PREPARE
0093:            protected int m_useCount = 0; // Number of times this statement has been used
0094:
0095:            //Used by the callablestatement style methods
0096:            private boolean isFunction;
0097:            // functionReturnType contains the user supplied value to check
0098:            // testReturn contains a modified version to make it easier to
0099:            // check the getXXX methods..
0100:            private int[] functionReturnType;
0101:            private int[] testReturn;
0102:            // returnTypeSet is true when a proper call to registerOutParameter has been made
0103:            private boolean returnTypeSet;
0104:            protected Object[] callResult;
0105:            protected int maxfieldSize = 0;
0106:
0107:            public ResultSet createDriverResultSet(Field[] fields, Vector tuples)
0108:                    throws SQLException {
0109:                return createResultSet(null, fields, tuples, null);
0110:            }
0111:
0112:            public AbstractJdbc2Statement(AbstractJdbc2Connection c,
0113:                    int rsType, int rsConcurrency) throws SQLException {
0114:                this .connection = c;
0115:                this .preparedQuery = null;
0116:                this .preparedParameters = null;
0117:                this .lastSimpleQuery = null;
0118:                resultsettype = rsType;
0119:                concurrency = rsConcurrency;
0120:            }
0121:
0122:            public AbstractJdbc2Statement(AbstractJdbc2Connection connection,
0123:                    String sql, boolean isCallable, int rsType,
0124:                    int rsConcurrency) throws SQLException {
0125:                this .connection = connection;
0126:                this .lastSimpleQuery = null;
0127:
0128:                String parsed_sql = replaceProcessing(sql);
0129:                if (isCallable)
0130:                    parsed_sql = modifyJdbcCall(parsed_sql);
0131:
0132:                this .preparedQuery = connection.getQueryExecutor()
0133:                        .createParameterizedQuery(parsed_sql);
0134:                this .preparedParameters = preparedQuery.createParameterList();
0135:
0136:                int inParamCount = preparedParameters.getInParameterCount() + 1;
0137:                this .testReturn = new int[inParamCount];
0138:                this .functionReturnType = new int[inParamCount];
0139:
0140:                resultsettype = rsType;
0141:                concurrency = rsConcurrency;
0142:            }
0143:
0144:            public abstract ResultSet createResultSet(Query originalQuery,
0145:                    Field[] fields, Vector tuples, ResultCursor cursor)
0146:                    throws SQLException;
0147:
0148:            public BaseConnection getPGConnection() {
0149:                return connection;
0150:            }
0151:
0152:            public String getFetchingCursorName() {
0153:                return null;
0154:            }
0155:
0156:            public int getFetchSize() {
0157:                return fetchSize;
0158:            }
0159:
0160:            protected boolean wantsScrollableResultSet() {
0161:                return resultsettype != ResultSet.TYPE_FORWARD_ONLY;
0162:            }
0163:
0164:            protected boolean wantsHoldableResultSet() {
0165:                return false;
0166:            }
0167:
0168:            //
0169:            // ResultHandler implementations for updates, queries, and either-or.
0170:            //
0171:
0172:            public class StatementResultHandler implements  ResultHandler {
0173:                private SQLException error;
0174:                private ResultWrapper results;
0175:
0176:                ResultWrapper getResults() {
0177:                    return results;
0178:                }
0179:
0180:                private void append(ResultWrapper newResult) {
0181:                    if (results == null)
0182:                        results = newResult;
0183:                    else
0184:                        results.append(newResult);
0185:                }
0186:
0187:                public void handleResultRows(Query fromQuery, Field[] fields,
0188:                        Vector tuples, ResultCursor cursor) {
0189:                    try {
0190:                        ResultSet rs = AbstractJdbc2Statement.this 
0191:                                .createResultSet(fromQuery, fields, tuples,
0192:                                        cursor);
0193:                        append(new ResultWrapper(rs));
0194:                    } catch (SQLException e) {
0195:                        handleError(e);
0196:                    }
0197:                }
0198:
0199:                public void handleCommandStatus(String status, int updateCount,
0200:                        long insertOID) {
0201:                    append(new ResultWrapper(updateCount, insertOID));
0202:                }
0203:
0204:                public void handleWarning(SQLWarning warning) {
0205:                    AbstractJdbc2Statement.this .addWarning(warning);
0206:                }
0207:
0208:                public void handleError(SQLException newError) {
0209:                    if (error == null)
0210:                        error = newError;
0211:                    else
0212:                        error.setNextException(newError);
0213:                }
0214:
0215:                public void handleCompletion() throws SQLException {
0216:                    if (error != null)
0217:                        throw error;
0218:                }
0219:            }
0220:
0221:            /*
0222:             * Execute a SQL statement that retruns a single ResultSet
0223:             *
0224:             * @param sql typically a static SQL SELECT statement
0225:             * @return a ResulSet that contains the data produced by the query
0226:             * @exception SQLException if a database access error occurs
0227:             */
0228:            public java.sql.ResultSet executeQuery(String p_sql)
0229:                    throws SQLException {
0230:                if (preparedQuery != null)
0231:                    throw new PSQLException(
0232:                            GT
0233:                                    .tr("Can''t use query methods that take a query string on a PreparedStatement."),
0234:                            PSQLState.WRONG_OBJECT_TYPE);
0235:
0236:                if (!executeWithFlags(p_sql, 0))
0237:                    throw new PSQLException(GT
0238:                            .tr("No results were returned by the query."),
0239:                            PSQLState.NO_DATA);
0240:
0241:                if (result.getNext() != null)
0242:                    throw new PSQLException(
0243:                            GT
0244:                                    .tr("Multiple ResultSets were returned by the query."),
0245:                            PSQLState.TOO_MANY_RESULTS);
0246:
0247:                return (ResultSet) result.getResultSet();
0248:            }
0249:
0250:            /*
0251:             * A Prepared SQL query is executed and its ResultSet is returned
0252:             *
0253:             * @return a ResultSet that contains the data produced by the
0254:             *   * query - never null
0255:             * @exception SQLException if a database access error occurs
0256:             */
0257:            public java.sql.ResultSet executeQuery() throws SQLException {
0258:                if (!executeWithFlags(0))
0259:                    throw new PSQLException(GT
0260:                            .tr("No results were returned by the query."),
0261:                            PSQLState.NO_DATA);
0262:
0263:                if (result.getNext() != null)
0264:                    throw new PSQLException(
0265:                            GT
0266:                                    .tr("Multiple ResultSets were returned by the query."),
0267:                            PSQLState.TOO_MANY_RESULTS);
0268:
0269:                return (ResultSet) result.getResultSet();
0270:            }
0271:
0272:            /*
0273:             * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition
0274:             * SQL statements that return nothing such as SQL DDL statements
0275:             * can be executed
0276:             *
0277:             * @param sql a SQL statement
0278:             * @return either a row count, or 0 for SQL commands
0279:             * @exception SQLException if a database access error occurs
0280:             */
0281:            public int executeUpdate(String p_sql) throws SQLException {
0282:                if (preparedQuery != null)
0283:                    throw new PSQLException(
0284:                            GT
0285:                                    .tr("Can''t use query methods that take a query string on a PreparedStatement."),
0286:                            PSQLState.WRONG_OBJECT_TYPE);
0287:                if (isFunction) {
0288:                    executeWithFlags(p_sql, 0);
0289:                    return 0;
0290:                }
0291:                if (executeWithFlags(p_sql, QueryExecutor.QUERY_NO_RESULTS))
0292:                    throw new PSQLException(
0293:                            GT
0294:                                    .tr("A result was returned when none was expected."),
0295:                            PSQLState.TOO_MANY_RESULTS);
0296:                return getUpdateCount();
0297:            }
0298:
0299:            /*
0300:             * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition,
0301:             * SQL statements that return nothing such as SQL DDL statements can
0302:             * be executed.
0303:             *
0304:             * @return either the row count for INSERT, UPDATE or DELETE; or
0305:             *   * 0 for SQL statements that return nothing.
0306:             * @exception SQLException if a database access error occurs
0307:             */
0308:            public int executeUpdate() throws SQLException {
0309:                if (isFunction) {
0310:                    executeWithFlags(0);
0311:                    return 0;
0312:                }
0313:                if (executeWithFlags(QueryExecutor.QUERY_NO_RESULTS))
0314:                    throw new PSQLException(
0315:                            GT
0316:                                    .tr("A result was returned when none was expected."),
0317:                            PSQLState.TOO_MANY_RESULTS);
0318:
0319:                return getUpdateCount();
0320:            }
0321:
0322:            /*
0323:             * Execute a SQL statement that may return multiple results. We
0324:             * don't have to worry about this since we do not support multiple
0325:             * ResultSets.  You can use getResultSet or getUpdateCount to
0326:             * retrieve the result.
0327:             *
0328:             * @param sql any SQL statement
0329:             * @return true if the next result is a ResulSet, false if it is
0330:             * an update count or there are no more results
0331:             * @exception SQLException if a database access error occurs
0332:             */
0333:            public boolean execute(String p_sql) throws SQLException {
0334:                if (preparedQuery != null)
0335:                    throw new PSQLException(
0336:                            GT
0337:                                    .tr("Can''t use query methods that take a query string on a PreparedStatement."),
0338:                            PSQLState.WRONG_OBJECT_TYPE);
0339:
0340:                return executeWithFlags(p_sql, 0);
0341:            }
0342:
0343:            public boolean executeWithFlags(String p_sql, int flags)
0344:                    throws SQLException {
0345:                checkClosed();
0346:                p_sql = replaceProcessing(p_sql);
0347:                Query simpleQuery = connection.getQueryExecutor()
0348:                        .createSimpleQuery(p_sql);
0349:                execute(simpleQuery, null, QueryExecutor.QUERY_ONESHOT | flags);
0350:                this .lastSimpleQuery = simpleQuery;
0351:                return (result != null && result.getResultSet() != null);
0352:            }
0353:
0354:            public boolean execute() throws SQLException {
0355:                return executeWithFlags(0);
0356:            }
0357:
0358:            public boolean executeWithFlags(int flags) throws SQLException {
0359:                checkClosed();
0360:
0361:                execute(preparedQuery, preparedParameters, flags);
0362:
0363:                // If we are executing and there are out parameters 
0364:                // callable statement function set the return data
0365:
0366:                if (isFunction && returnTypeSet) {
0367:                    if (result == null || result.getResultSet() == null)
0368:                        throw new PSQLException(
0369:                                GT
0370:                                        .tr("A CallableStatement was executed with nothing returned."),
0371:                                PSQLState.NO_DATA);
0372:
0373:                    ResultSet rs = result.getResultSet();
0374:                    if (!rs.next())
0375:                        throw new PSQLException(
0376:                                GT
0377:                                        .tr("A CallableStatement was executed with nothing returned."),
0378:                                PSQLState.NO_DATA);
0379:
0380:                    // figure out how many columns
0381:                    int cols = rs.getMetaData().getColumnCount();
0382:
0383:                    int outParameterCount = preparedParameters
0384:                            .getOutParameterCount();
0385:
0386:                    if (cols != outParameterCount)
0387:                        throw new PSQLException(
0388:                                GT
0389:                                        .tr("A CallableStatement was excecuted with an invalid number of parameters"),
0390:                                PSQLState.SYNTAX_ERROR);
0391:
0392:                    // reset last result fetched (for wasNull)
0393:                    lastIndex = 0;
0394:
0395:                    // allocate enough space for all possible parameters without regard to in/out            
0396:                    callResult = new Object[preparedParameters
0397:                            .getParameterCount() + 1];
0398:
0399:                    // move them into the result set
0400:                    for (int i = 0, j = 0; i < cols; i++, j++) {
0401:                        // find the next out parameter, the assumption is that the functionReturnType 
0402:                        // array will be initialized with 0 and only out parameters will have values
0403:                        // other than 0. 0 is the value for java.sql.Types.NULL, which should not 
0404:                        // conflict
0405:                        while (j < functionReturnType.length
0406:                                && functionReturnType[j] == 0)
0407:                            j++;
0408:
0409:                        callResult[j] = rs.getObject(i + 1);
0410:                        int columnType = rs.getMetaData().getColumnType(i + 1);
0411:
0412:                        if (columnType != functionReturnType[j]) {
0413:                            // this is here for the sole purpose of passing the cts
0414:                            if (columnType == Types.DOUBLE
0415:                                    && functionReturnType[j] == Types.REAL) {
0416:                                // return it as a float
0417:                                if (callResult[j] != null)
0418:                                    callResult[j] = new Float(
0419:                                            ((Double) callResult[j])
0420:                                                    .floatValue());
0421:                            } else {
0422:                                throw new PSQLException(
0423:                                        GT
0424:                                                .tr(
0425:                                                        "A CallableStatement function was executed and the out parameter {0} was of type {1} however type {2} was registered.",
0426:                                                        new Object[] {
0427:                                                                new Integer(
0428:                                                                        i + 1),
0429:                                                                "java.sql.Types="
0430:                                                                        + columnType,
0431:                                                                "java.sql.Types="
0432:                                                                        + functionReturnType[j] }),
0433:                                        PSQLState.DATA_TYPE_MISMATCH);
0434:                            }
0435:                        }
0436:
0437:                    }
0438:                    rs.close();
0439:                    result = null;
0440:                    return false;
0441:                }
0442:
0443:                return (result != null && result.getResultSet() != null);
0444:            }
0445:
0446:            protected void execute(Query queryToExecute,
0447:                    ParameterList queryParameters, int flags)
0448:                    throws SQLException {
0449:                // Every statement execution clears any previous warnings.
0450:                clearWarnings();
0451:
0452:                // Close any existing resultsets associated with this statement.
0453:                while (firstUnclosedResult != null) {
0454:                    if (firstUnclosedResult.getResultSet() != null)
0455:                        firstUnclosedResult.getResultSet().close();
0456:                    firstUnclosedResult = firstUnclosedResult.getNext();
0457:                }
0458:
0459:                if (lastSimpleQuery != null) {
0460:                    lastSimpleQuery.close();
0461:                    lastSimpleQuery = null;
0462:                }
0463:
0464:                // Enable cursor-based resultset if possible.
0465:                if (fetchSize > 0 && !wantsScrollableResultSet()
0466:                        && !connection.getAutoCommit()
0467:                        && !wantsHoldableResultSet())
0468:                    flags |= QueryExecutor.QUERY_FORWARD_CURSOR;
0469:
0470:                // Only use named statements after we hit the threshold
0471:                if (preparedQuery != null) {
0472:                    ++m_useCount; // We used this statement once more.
0473:                    if (m_prepareThreshold == 0
0474:                            || m_useCount < m_prepareThreshold)
0475:                        flags |= QueryExecutor.QUERY_ONESHOT;
0476:                }
0477:
0478:                if (connection.getAutoCommit())
0479:                    flags |= QueryExecutor.QUERY_SUPPRESS_BEGIN;
0480:
0481:                StatementResultHandler handler = new StatementResultHandler();
0482:                result = null;
0483:                connection.getQueryExecutor().execute(queryToExecute,
0484:                        queryParameters, handler, maxrows, fetchSize, flags);
0485:                result = firstUnclosedResult = handler.getResults();
0486:            }
0487:
0488:            /*
0489:             * setCursorName defines the SQL cursor name that will be used by
0490:             * subsequent execute methods. This name can then be used in SQL
0491:             * positioned update/delete statements to identify the current row
0492:             * in the ResultSet generated by this statement.  If a database
0493:             * doesn't support positioned update/delete, this method is a
0494:             * no-op.
0495:             *
0496:             * <p><B>Note:</B> By definition, positioned update/delete execution
0497:             * must be done by a different Statement than the one which
0498:             * generated the ResultSet being used for positioning. Also, cursor
0499:             * names must be unique within a Connection.
0500:             *
0501:             * @param name the new cursor name
0502:             * @exception SQLException if a database access error occurs
0503:             */
0504:            public void setCursorName(String name) throws SQLException {
0505:                checkClosed();
0506:                // No-op.
0507:            }
0508:
0509:            protected boolean isClosed = false;
0510:            private int lastIndex = 0;
0511:
0512:            /*
0513:             * getUpdateCount returns the current result as an update count,
0514:             * if the result is a ResultSet or there are no more results, -1
0515:             * is returned.  It should only be called once per result.
0516:             *
0517:             * @return the current result as an update count.
0518:             * @exception SQLException if a database access error occurs
0519:             */
0520:            public int getUpdateCount() throws SQLException {
0521:                checkClosed();
0522:                if (result == null)
0523:                    return -1;
0524:
0525:                if (isFunction)
0526:                    return 1;
0527:
0528:                if (result.getResultSet() != null)
0529:                    return -1;
0530:
0531:                return result.getUpdateCount();
0532:            }
0533:
0534:            /*
0535:             * getMoreResults moves to a Statement's next result.  If it returns
0536:             * true, this result is a ResulSet.
0537:             *
0538:             * @return true if the next ResultSet is valid
0539:             * @exception SQLException if a database access error occurs
0540:             */
0541:            public boolean getMoreResults() throws SQLException {
0542:                if (result == null)
0543:                    return false;
0544:
0545:                result = result.getNext();
0546:
0547:                // Close preceding resultsets.
0548:                while (firstUnclosedResult != result) {
0549:                    if (firstUnclosedResult.getResultSet() != null)
0550:                        firstUnclosedResult.getResultSet().close();
0551:                    firstUnclosedResult = firstUnclosedResult.getNext();
0552:                }
0553:
0554:                return (result != null && result.getResultSet() != null);
0555:            }
0556:
0557:            /*
0558:             * The maxRows limit is set to limit the number of rows that
0559:             * any ResultSet can contain.  If the limit is exceeded, the
0560:             * excess rows are silently dropped.
0561:             *
0562:             * @return the current maximum row limit; zero means unlimited
0563:             * @exception SQLException if a database access error occurs
0564:             */
0565:            public int getMaxRows() throws SQLException {
0566:                checkClosed();
0567:                return maxrows;
0568:            }
0569:
0570:            /*
0571:             * Set the maximum number of rows
0572:             *
0573:             * @param max the new max rows limit; zero means unlimited
0574:             * @exception SQLException if a database access error occurs
0575:             * @see getMaxRows
0576:             */
0577:            public void setMaxRows(int max) throws SQLException {
0578:                checkClosed();
0579:                if (max < 0)
0580:                    throw new PSQLException(
0581:                            GT
0582:                                    .tr("Maximum number of rows must be a value grater than or equal to 0."),
0583:                            PSQLState.INVALID_PARAMETER_VALUE);
0584:                maxrows = max;
0585:            }
0586:
0587:            /*
0588:             * If escape scanning is on (the default), the driver will do escape
0589:             * substitution before sending the SQL to the database.
0590:             *
0591:             * @param enable true to enable; false to disable
0592:             * @exception SQLException if a database access error occurs
0593:             */
0594:            public void setEscapeProcessing(boolean enable) throws SQLException {
0595:                checkClosed();
0596:                replaceProcessingEnabled = enable;
0597:            }
0598:
0599:            /*
0600:             * The queryTimeout limit is the number of seconds the driver
0601:             * will wait for a Statement to execute.  If the limit is
0602:             * exceeded, a SQLException is thrown.
0603:             *
0604:             * @return the current query timeout limit in seconds; 0 = unlimited
0605:             * @exception SQLException if a database access error occurs
0606:             */
0607:            public int getQueryTimeout() throws SQLException {
0608:                checkClosed();
0609:                return timeout;
0610:            }
0611:
0612:            /*
0613:             * Sets the queryTimeout limit
0614:             *
0615:             * @param seconds - the new query timeout limit in seconds
0616:             * @exception SQLException if a database access error occurs
0617:             */
0618:            public void setQueryTimeout(int seconds) throws SQLException {
0619:                checkClosed();
0620:                if (seconds < 0)
0621:                    throw new PSQLException(
0622:                            GT
0623:                                    .tr("Query timeout must be a value greater than or equals to 0."),
0624:                            PSQLState.INVALID_PARAMETER_VALUE);
0625:                timeout = seconds;
0626:            }
0627:
0628:            /**
0629:             * This adds a warning to the warning chain.
0630:             * @param warn warning to add
0631:             */
0632:            public void addWarning(SQLWarning warn) {
0633:                if (warnings != null)
0634:                    warnings.setNextWarning(warn);
0635:                else
0636:                    warnings = warn;
0637:            }
0638:
0639:            /*
0640:             * The first warning reported by calls on this Statement is
0641:             * returned.  A Statement's execute methods clear its SQLWarning
0642:             * chain.  Subsequent Statement warnings will be chained to this
0643:             * SQLWarning.
0644:             *
0645:             * <p>The Warning chain is automatically cleared each time a statement
0646:             * is (re)executed.
0647:             *
0648:             * <p><B>Note:</B> If you are processing a ResultSet then any warnings
0649:             * associated with ResultSet reads will be chained on the ResultSet
0650:             * object.
0651:             *
0652:             * @return the first SQLWarning on null
0653:             * @exception SQLException if a database access error occurs
0654:             */
0655:            public SQLWarning getWarnings() throws SQLException {
0656:                checkClosed();
0657:                return warnings;
0658:            }
0659:
0660:            /*
0661:             * The maxFieldSize limit (in bytes) is the maximum amount of
0662:             * data returned for any column value; it only applies to
0663:             * BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR
0664:             * columns.  If the limit is exceeded, the excess data is silently
0665:             * discarded.
0666:             *
0667:             * @return the current max column size limit; zero means unlimited
0668:             * @exception SQLException if a database access error occurs
0669:             */
0670:            public int getMaxFieldSize() throws SQLException {
0671:                return maxfieldSize;
0672:            }
0673:
0674:            /*
0675:             * Sets the maxFieldSize
0676:             *
0677:             * @param max the new max column size limit; zero means unlimited
0678:             * @exception SQLException if a database access error occurs
0679:             */
0680:            public void setMaxFieldSize(int max) throws SQLException {
0681:                checkClosed();
0682:                if (max < 0)
0683:                    throw new PSQLException(
0684:                            GT
0685:                                    .tr("The maximum field size must be a value greater than or equal to 0."),
0686:                            PSQLState.INVALID_PARAMETER_VALUE);
0687:                maxfieldSize = max;
0688:            }
0689:
0690:            /*
0691:             * After this call, getWarnings returns null until a new warning
0692:             * is reported for this Statement.
0693:             *
0694:             * @exception SQLException if a database access error occurs
0695:             */
0696:            public void clearWarnings() throws SQLException {
0697:                warnings = null;
0698:            }
0699:
0700:            /*
0701:             * getResultSet returns the current result as a ResultSet. It
0702:             * should only be called once per result.
0703:             *
0704:             * @return the current result set; null if there are no more
0705:             * @exception SQLException if a database access error occurs (why?)
0706:             */
0707:            public java.sql.ResultSet getResultSet() throws SQLException {
0708:                checkClosed();
0709:
0710:                if (result == null)
0711:                    return null;
0712:
0713:                return (ResultSet) result.getResultSet();
0714:            }
0715:
0716:            /*
0717:             * In many cases, it is desirable to immediately release a
0718:             * Statement's database and JDBC resources instead of waiting
0719:             * for this to happen when it is automatically closed. The
0720:             * close method provides this immediate release.
0721:             *
0722:             * <p><B>Note:</B> A Statement is automatically closed when it is
0723:             * garbage collected.  When a Statement is closed, its current
0724:             * ResultSet, if one exists, is also closed.
0725:             *
0726:             * @exception SQLException if a database access error occurs (why?)
0727:             */
0728:            public void close() throws SQLException {
0729:                // closing an already closed Statement is a no-op.
0730:                if (isClosed)
0731:                    return;
0732:
0733:                // Force the ResultSet(s) to close
0734:                while (firstUnclosedResult != null) {
0735:                    if (firstUnclosedResult.getResultSet() != null)
0736:                        firstUnclosedResult.getResultSet().close();
0737:                    firstUnclosedResult = firstUnclosedResult.getNext();
0738:                }
0739:
0740:                if (lastSimpleQuery != null)
0741:                    lastSimpleQuery.close();
0742:
0743:                if (preparedQuery != null)
0744:                    preparedQuery.close();
0745:
0746:                // Disasociate it from us
0747:                result = firstUnclosedResult = null;
0748:                isClosed = true;
0749:            }
0750:
0751:            /**
0752:             * This finalizer ensures that statements that have allocated server-side
0753:             * resources free them when they become unreferenced.
0754:             */
0755:            protected void finalize() {
0756:                try {
0757:                    close();
0758:                } catch (SQLException e) {
0759:                }
0760:            }
0761:
0762:            /*
0763:             * Filter the SQL string of Java SQL Escape clauses.
0764:             *
0765:             * Currently implemented Escape clauses are those mentioned in 11.3
0766:             * in the specification. Basically we look through the sql string for
0767:             * {d xxx}, {t xxx}, {ts xxx}, {oj xxx} or {fn xxx} in non-string sql 
0768:             * code. When we find them, we just strip the escape part leaving only
0769:             * the xxx part.
0770:             * So, something like "select * from x where d={d '2001-10-09'}" would
0771:             * return "select * from x where d= '2001-10-09'".
0772:             */
0773:            protected String replaceProcessing(String p_sql)
0774:                    throws SQLException {
0775:                if (replaceProcessingEnabled) {
0776:                    // Since escape codes can only appear in SQL CODE, we keep track
0777:                    // of if we enter a string or not.
0778:                    int len = p_sql.length();
0779:                    StringBuffer newsql = new StringBuffer(len);
0780:                    int i = 0;
0781:                    while (i < len) {
0782:                        i = parseSql(p_sql, i, newsql, false, connection
0783:                                .getStandardConformingStrings());
0784:                        // We need to loop here in case we encounter invalid
0785:                        // SQL, consider: SELECT a FROM t WHERE (1 > 0)) ORDER BY a
0786:                        // We can't ending replacing after the extra closing paren
0787:                        // because that changes a syntax error to a valid query
0788:                        // that isn't what the user specified.
0789:                        if (i < len) {
0790:                            newsql.append(p_sql.charAt(i));
0791:                            i++;
0792:                        }
0793:                    }
0794:                    return newsql.toString();
0795:                } else {
0796:                    return p_sql;
0797:                }
0798:            }
0799:
0800:            /**
0801:             * parse the given sql from index i, appending it to the gven buffer
0802:             * until we hit an unmatched right parentheses or end of string.  When
0803:             * the stopOnComma flag is set we also stop processing when a comma is
0804:             * found in sql text that isn't inside nested parenthesis.
0805:             *
0806:             * @param p_sql the original query text
0807:             * @param i starting position for replacing
0808:             * @param newsql where to write the replaced output
0809:             * @param stopOnComma should we stop after hitting the first comma in sql text?
0810:             * @param stdStrings whether standard_conforming_strings is on
0811:             * @return the position we stopped processing at
0812:             */
0813:            protected static int parseSql(String p_sql, int i,
0814:                    StringBuffer newsql, boolean stopOnComma, boolean stdStrings)
0815:                    throws SQLException {
0816:                short state = IN_SQLCODE;
0817:                int len = p_sql.length();
0818:                int nestedParenthesis = 0;
0819:                boolean endOfNested = false;
0820:
0821:                // because of the ++i loop
0822:                i--;
0823:                while (!endOfNested && ++i < len) {
0824:                    char c = p_sql.charAt(i);
0825:                    switch (state) {
0826:                    case IN_SQLCODE:
0827:                        if (c == '\'') // start of a string?
0828:                            state = IN_STRING;
0829:                        else if (c == '"') // start of a identifer?
0830:                            state = IN_IDENTIFIER;
0831:                        else if (c == '(') { // begin nested sql
0832:                            nestedParenthesis++;
0833:                        } else if (c == ')') { // end of nested sql
0834:                            nestedParenthesis--;
0835:                            if (nestedParenthesis < 0) {
0836:                                endOfNested = true;
0837:                                break;
0838:                            }
0839:                        } else if (stopOnComma && c == ','
0840:                                && nestedParenthesis == 0) {
0841:                            endOfNested = true;
0842:                            break;
0843:                        } else if (c == '{') { // start of an escape code?
0844:                            if (i + 1 < len) {
0845:                                char next = p_sql.charAt(i + 1);
0846:                                char nextnext = (i + 2 < len) ? p_sql
0847:                                        .charAt(i + 2) : '\0';
0848:                                if (next == 'd' || next == 'D') {
0849:                                    state = ESC_TIMEDATE;
0850:                                    i++;
0851:                                    newsql.append("DATE ");
0852:                                    break;
0853:                                } else if (next == 't' || next == 'T') {
0854:                                    state = ESC_TIMEDATE;
0855:                                    if (nextnext == 's' || nextnext == 'S') {
0856:                                        // timestamp constant
0857:                                        i += 2;
0858:                                        newsql.append("TIMESTAMP ");
0859:                                    } else {
0860:                                        // time constant
0861:                                        i++;
0862:                                        newsql.append("TIME ");
0863:                                    }
0864:                                    break;
0865:                                } else if (next == 'f' || next == 'F') {
0866:                                    state = ESC_FUNCTION;
0867:                                    i += (nextnext == 'n' || nextnext == 'N') ? 2
0868:                                            : 1;
0869:                                    break;
0870:                                } else if (next == 'o' || next == 'O') {
0871:                                    state = ESC_OUTERJOIN;
0872:                                    i += (nextnext == 'j' || nextnext == 'J') ? 2
0873:                                            : 1;
0874:                                    break;
0875:                                } else if (next == 'e' || next == 'E') { // we assume that escape is the only escape sequence beginning with e
0876:                                    state = ESC_ESCAPECHAR;
0877:                                    break;
0878:                                }
0879:                            }
0880:                        }
0881:                        newsql.append(c);
0882:                        break;
0883:
0884:                    case IN_STRING:
0885:                        if (c == '\'') // end of string?
0886:                            state = IN_SQLCODE;
0887:                        else if (c == '\\' && !stdStrings) // a backslash?
0888:                            state = BACKSLASH;
0889:
0890:                        newsql.append(c);
0891:                        break;
0892:
0893:                    case IN_IDENTIFIER:
0894:                        if (c == '"') // end of identifier
0895:                            state = IN_SQLCODE;
0896:                        newsql.append(c);
0897:                        break;
0898:
0899:                    case BACKSLASH:
0900:                        state = IN_STRING;
0901:
0902:                        newsql.append(c);
0903:                        break;
0904:
0905:                    case ESC_FUNCTION:
0906:                        // extract function name
0907:                        String functionName;
0908:                        int posArgs = p_sql.indexOf('(', i);
0909:                        if (posArgs != -1) {
0910:                            functionName = p_sql.substring(i, posArgs).trim();
0911:                            // extract arguments
0912:                            i = posArgs + 1;// we start the scan after the first (
0913:                            StringBuffer args = new StringBuffer();
0914:                            i = parseSql(p_sql, i, args, false, stdStrings);
0915:                            // translate the function and parse arguments
0916:                            newsql.append(escapeFunction(functionName, args
0917:                                    .toString(), stdStrings));
0918:                        }
0919:                        // go to the end of the function copying anything found
0920:                        i++;
0921:                        while (i < len && p_sql.charAt(i) != '}')
0922:                            newsql.append(p_sql.charAt(i++));
0923:                        state = IN_SQLCODE; // end of escaped function (or query)
0924:                        break;
0925:                    case ESC_TIMEDATE:
0926:                    case ESC_OUTERJOIN:
0927:                    case ESC_ESCAPECHAR:
0928:                        if (c == '}')
0929:                            state = IN_SQLCODE; // end of escape code.
0930:                        else
0931:                            newsql.append(c);
0932:                        break;
0933:                    } // end switch
0934:                }
0935:                return i;
0936:            }
0937:
0938:            /**
0939:             * generate sql for escaped functions
0940:             * @param functionName the escaped function name
0941:             * @param args the arguments for this functin
0942:             * @param stdStrings whether standard_conforming_strings is on
0943:             * @return the right postgreSql sql
0944:             */
0945:            protected static String escapeFunction(String functionName,
0946:                    String args, boolean stdStrings) throws SQLException {
0947:                // parse function arguments
0948:                int len = args.length();
0949:                int i = 0;
0950:                ArrayList parsedArgs = new ArrayList();
0951:                while (i < len) {
0952:                    StringBuffer arg = new StringBuffer();
0953:                    int lastPos = i;
0954:                    i = parseSql(args, i, arg, true, stdStrings);
0955:                    if (lastPos != i) {
0956:                        parsedArgs.add(arg);
0957:                    }
0958:                    i++;
0959:                }
0960:                // we can now tranlate escape functions
0961:                try {
0962:                    Method escapeMethod = EscapedFunctions
0963:                            .getFunction(functionName);
0964:                    return (String) escapeMethod.invoke(null,
0965:                            new Object[] { parsedArgs });
0966:                } catch (InvocationTargetException e) {
0967:                    if (e.getTargetException() instanceof  SQLException)
0968:                        throw (SQLException) e.getTargetException();
0969:                    else
0970:                        throw new PSQLException(e.getTargetException()
0971:                                .getMessage(), PSQLState.SYSTEM_ERROR);
0972:                } catch (Exception e) {
0973:                    // by default the function name is kept unchanged
0974:                    StringBuffer buf = new StringBuffer();
0975:                    buf.append(functionName).append('(');
0976:                    for (int iArg = 0; iArg < parsedArgs.size(); iArg++) {
0977:                        buf.append(parsedArgs.get(iArg));
0978:                        if (iArg != (parsedArgs.size() - 1))
0979:                            buf.append(',');
0980:                    }
0981:                    buf.append(')');
0982:                    return buf.toString();
0983:                }
0984:            }
0985:
0986:            /*
0987:             *
0988:             * The following methods are postgres extensions and are defined
0989:             * in the interface BaseStatement
0990:             *
0991:             */
0992:
0993:            /*
0994:             * Returns the Last inserted/updated oid.  Deprecated in 7.2 because
0995:             * range of OID values is greater than a java signed int.
0996:             * @deprecated Replaced by getLastOID in 7.2
0997:             */
0998:            public int getInsertedOID() throws SQLException {
0999:                checkClosed();
1000:                if (result == null)
1001:                    return 0;
1002:                return (int) result.getInsertOID();
1003:            }
1004:
1005:            /*
1006:             * Returns the Last inserted/updated oid.
1007:             * @return OID of last insert
1008:             * @since 7.2
1009:             */
1010:            public long getLastOID() throws SQLException {
1011:                checkClosed();
1012:                if (result == null)
1013:                    return 0;
1014:                return result.getInsertOID();
1015:            }
1016:
1017:            /*
1018:             * Set a parameter to SQL NULL
1019:             *
1020:             * <p><B>Note:</B> You must specify the parameter's SQL type.
1021:             *
1022:             * @param parameterIndex the first parameter is 1, etc...
1023:             * @param sqlType the SQL type code defined in java.sql.Types
1024:             * @exception SQLException if a database access error occurs
1025:             */
1026:            public void setNull(int parameterIndex, int sqlType)
1027:                    throws SQLException {
1028:                checkClosed();
1029:
1030:                int oid;
1031:                switch (sqlType) {
1032:                case Types.INTEGER:
1033:                    oid = Oid.INT4;
1034:                    break;
1035:                case Types.TINYINT:
1036:                case Types.SMALLINT:
1037:                    oid = Oid.INT2;
1038:                    break;
1039:                case Types.BIGINT:
1040:                    oid = Oid.INT8;
1041:                    break;
1042:                case Types.REAL:
1043:                    oid = Oid.FLOAT4;
1044:                    break;
1045:                case Types.DOUBLE:
1046:                case Types.FLOAT:
1047:                    oid = Oid.FLOAT8;
1048:                    break;
1049:                case Types.DECIMAL:
1050:                case Types.NUMERIC:
1051:                    oid = Oid.NUMERIC;
1052:                    break;
1053:                case Types.CHAR:
1054:                    oid = Oid.BPCHAR;
1055:                    break;
1056:                case Types.VARCHAR:
1057:                case Types.LONGVARCHAR:
1058:                    oid = Oid.VARCHAR;
1059:                    break;
1060:                case Types.DATE:
1061:                    oid = Oid.DATE;
1062:                    break;
1063:                case Types.TIME:
1064:                    oid = Oid.TIME;
1065:                    break;
1066:                case Types.TIMESTAMP:
1067:                    oid = Oid.TIMESTAMPTZ;
1068:                    break;
1069:                case Types.BIT:
1070:                    oid = Oid.BOOL;
1071:                    break;
1072:                case Types.BINARY:
1073:                case Types.VARBINARY:
1074:                case Types.LONGVARBINARY:
1075:                    if (connection.haveMinimumCompatibleVersion("7.2")) {
1076:                        oid = Oid.BYTEA;
1077:                    } else {
1078:                        oid = Oid.OID;
1079:                    }
1080:                    break;
1081:                case Types.BLOB:
1082:                case Types.CLOB:
1083:                    oid = Oid.OID;
1084:                    break;
1085:                case Types.ARRAY:
1086:                case Types.DISTINCT:
1087:                case Types.STRUCT:
1088:                case Types.NULL:
1089:                case Types.OTHER:
1090:                    oid = Oid.UNSPECIFIED;
1091:                    break;
1092:                default:
1093:                    // Bad Types value.
1094:                    throw new PSQLException(GT.tr("Unknown Types value."),
1095:                            PSQLState.INVALID_PARAMETER_TYPE);
1096:                }
1097:                if (adjustIndex)
1098:                    parameterIndex--;
1099:                preparedParameters.setNull(parameterIndex, oid);
1100:            }
1101:
1102:            /*
1103:             * Set a parameter to a Java boolean value.  The driver converts this
1104:             * to a SQL BIT value when it sends it to the database.
1105:             *
1106:             * @param parameterIndex the first parameter is 1...
1107:             * @param x the parameter value
1108:             * @exception SQLException if a database access error occurs
1109:             */
1110:            public void setBoolean(int parameterIndex, boolean x)
1111:                    throws SQLException {
1112:                checkClosed();
1113:                bindString(parameterIndex, x ? "1" : "0", Oid.BOOL);
1114:            }
1115:
1116:            /*
1117:             * Set a parameter to a Java byte value.  The driver converts this to
1118:             * a SQL TINYINT value when it sends it to the database.
1119:             *
1120:             * @param parameterIndex the first parameter is 1...
1121:             * @param x the parameter value
1122:             * @exception SQLException if a database access error occurs
1123:             */
1124:            public void setByte(int parameterIndex, byte x) throws SQLException {
1125:                checkClosed();
1126:                bindLiteral(parameterIndex, Integer.toString(x), Oid.INT2);
1127:            }
1128:
1129:            /*
1130:             * Set a parameter to a Java short value.  The driver converts this
1131:             * to a SQL SMALLINT value when it sends it to the database.
1132:             *
1133:             * @param parameterIndex the first parameter is 1...
1134:             * @param x the parameter value
1135:             * @exception SQLException if a database access error occurs
1136:             */
1137:            public void setShort(int parameterIndex, short x)
1138:                    throws SQLException {
1139:                checkClosed();
1140:                bindLiteral(parameterIndex, Integer.toString(x), Oid.INT2);
1141:            }
1142:
1143:            /*
1144:             * Set a parameter to a Java int value.  The driver converts this to
1145:             * a SQL INTEGER value when it sends it to the database.
1146:             *
1147:             * @param parameterIndex the first parameter is 1...
1148:             * @param x the parameter value
1149:             * @exception SQLException if a database access error occurs
1150:             */
1151:            public void setInt(int parameterIndex, int x) throws SQLException {
1152:                checkClosed();
1153:                bindLiteral(parameterIndex, Integer.toString(x), Oid.INT4);
1154:            }
1155:
1156:            /*
1157:             * Set a parameter to a Java long value.  The driver converts this to
1158:             * a SQL BIGINT value when it sends it to the database.
1159:             *
1160:             * @param parameterIndex the first parameter is 1...
1161:             * @param x the parameter value
1162:             * @exception SQLException if a database access error occurs
1163:             */
1164:            public void setLong(int parameterIndex, long x) throws SQLException {
1165:                checkClosed();
1166:                bindLiteral(parameterIndex, Long.toString(x), Oid.INT8);
1167:            }
1168:
1169:            /*
1170:             * Set a parameter to a Java float value.  The driver converts this
1171:             * to a SQL FLOAT value when it sends it to the database.
1172:             *
1173:             * @param parameterIndex the first parameter is 1...
1174:             * @param x the parameter value
1175:             * @exception SQLException if a database access error occurs
1176:             */
1177:            public void setFloat(int parameterIndex, float x)
1178:                    throws SQLException {
1179:                checkClosed();
1180:                bindLiteral(parameterIndex, Float.toString(x), Oid.FLOAT8);
1181:            }
1182:
1183:            /*
1184:             * Set a parameter to a Java double value. The driver converts this
1185:             * to a SQL DOUBLE value when it sends it to the database
1186:             *
1187:             * @param parameterIndex the first parameter is 1...
1188:             * @param x the parameter value
1189:             * @exception SQLException if a database access error occurs
1190:             */
1191:            public void setDouble(int parameterIndex, double x)
1192:                    throws SQLException {
1193:                checkClosed();
1194:                bindLiteral(parameterIndex, Double.toString(x), Oid.FLOAT8);
1195:            }
1196:
1197:            /*
1198:             * Set a parameter to a java.lang.BigDecimal value.  The driver
1199:             * converts this to a SQL NUMERIC value when it sends it to the
1200:             * database.
1201:             *
1202:             * @param parameterIndex the first parameter is 1...
1203:             * @param x the parameter value
1204:             * @exception SQLException if a database access error occurs
1205:             */
1206:            public void setBigDecimal(int parameterIndex, BigDecimal x)
1207:                    throws SQLException {
1208:                checkClosed();
1209:                if (x == null)
1210:                    setNull(parameterIndex, Types.DECIMAL);
1211:                else
1212:                    bindLiteral(parameterIndex, x.toString(), Oid.NUMERIC);
1213:            }
1214:
1215:            /*
1216:             * Set a parameter to a Java String value. The driver converts this
1217:             * to a SQL VARCHAR or LONGVARCHAR value (depending on the arguments
1218:             * size relative to the driver's limits on VARCHARs) when it sends it
1219:             * to the database.
1220:             *
1221:             * @param parameterIndex the first parameter is 1...
1222:             * @param x the parameter value
1223:             * @exception SQLException if a database access error occurs
1224:             */
1225:            public void setString(int parameterIndex, String x)
1226:                    throws SQLException {
1227:                checkClosed();
1228:                setString(parameterIndex, x,
1229:                        (connection.getStringVarcharFlag() ? Oid.VARCHAR
1230:                                : Oid.UNSPECIFIED));
1231:            }
1232:
1233:            protected void setString(int parameterIndex, String x, int oid)
1234:                    throws SQLException {
1235:                // if the passed string is null, then set this column to null
1236:                checkClosed();
1237:                if (x == null) {
1238:                    if (adjustIndex)
1239:                        parameterIndex--;
1240:                    preparedParameters.setNull(parameterIndex, oid);
1241:                } else
1242:                    bindString(parameterIndex, x, oid);
1243:            }
1244:
1245:            /*
1246:             * Set a parameter to a Java array of bytes.  The driver converts this
1247:             * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
1248:             * size relative to the driver's limits on VARBINARYs) when it sends
1249:             * it to the database.
1250:             *
1251:             * <p>Implementation note:
1252:             * <br>With org.postgresql, this creates a large object, and stores the
1253:             * objects oid in this column.
1254:             *
1255:             * @param parameterIndex the first parameter is 1...
1256:             * @param x the parameter value
1257:             * @exception SQLException if a database access error occurs
1258:             */
1259:            public void setBytes(int parameterIndex, byte[] x)
1260:                    throws SQLException {
1261:                checkClosed();
1262:
1263:                if (null == x) {
1264:                    setNull(parameterIndex, Types.VARBINARY);
1265:                    return;
1266:                }
1267:
1268:                if (connection.haveMinimumCompatibleVersion("7.2")) {
1269:                    //Version 7.2 supports the bytea datatype for byte arrays
1270:                    byte[] copy = new byte[x.length];
1271:                    System.arraycopy(x, 0, copy, 0, x.length);
1272:                    preparedParameters.setBytea(parameterIndex, copy, 0,
1273:                            x.length);
1274:                } else {
1275:                    //Version 7.1 and earlier support done as LargeObjects
1276:                    LargeObjectManager lom = connection.getLargeObjectAPI();
1277:                    long oid = lom.createLO();
1278:                    LargeObject lob = lom.open(oid);
1279:                    lob.write(x);
1280:                    lob.close();
1281:                    setLong(parameterIndex, oid);
1282:                }
1283:            }
1284:
1285:            /*
1286:             * Set a parameter to a java.sql.Date value.  The driver converts this
1287:             * to a SQL DATE value when it sends it to the database.
1288:             *
1289:             * @param parameterIndex the first parameter is 1...
1290:             * @param x the parameter value
1291:             * @exception SQLException if a database access error occurs
1292:             */
1293:            public void setDate(int parameterIndex, java.sql.Date x)
1294:                    throws SQLException {
1295:                setDate(parameterIndex, x, null);
1296:            }
1297:
1298:            /*
1299:             * Set a parameter to a java.sql.Time value.  The driver converts
1300:             * this to a SQL TIME value when it sends it to the database.
1301:             *
1302:             * @param parameterIndex the first parameter is 1...));
1303:             * @param x the parameter value
1304:             * @exception SQLException if a database access error occurs
1305:             */
1306:            public void setTime(int parameterIndex, Time x) throws SQLException {
1307:                setTime(parameterIndex, x, null);
1308:            }
1309:
1310:            /*
1311:             * Set a parameter to a java.sql.Timestamp value.  The driver converts
1312:             * this to a SQL TIMESTAMP value when it sends it to the database.
1313:             *
1314:             * @param parameterIndex the first parameter is 1...
1315:             * @param x the parameter value
1316:             * @exception SQLException if a database access error occurs
1317:             */
1318:            public void setTimestamp(int parameterIndex, Timestamp x)
1319:                    throws SQLException {
1320:                setTimestamp(parameterIndex, x, null);
1321:            }
1322:
1323:            private void setCharacterStreamPost71(int parameterIndex,
1324:                    InputStream x, int length, String encoding)
1325:                    throws SQLException {
1326:
1327:                if (x == null) {
1328:                    setNull(parameterIndex, Types.VARCHAR);
1329:                    return;
1330:                }
1331:                if (length < 0)
1332:                    throw new PSQLException(GT.tr("Invalid stream length {0}.",
1333:                            new Integer(length)),
1334:                            PSQLState.INVALID_PARAMETER_VALUE);
1335:
1336:                //Version 7.2 supports AsciiStream for all PG text types (char, varchar, text)
1337:                //As the spec/javadoc for this method indicate this is to be used for
1338:                //large String values (i.e. LONGVARCHAR)  PG doesn't have a separate
1339:                //long varchar datatype, but with toast all text datatypes are capable of
1340:                //handling very large values.  Thus the implementation ends up calling
1341:                //setString() since there is no current way to stream the value to the server
1342:                try {
1343:                    InputStreamReader l_inStream = new InputStreamReader(x,
1344:                            encoding);
1345:                    char[] l_chars = new char[length];
1346:                    int l_charsRead = 0;
1347:                    while (true) {
1348:                        int n = l_inStream.read(l_chars, l_charsRead, length
1349:                                - l_charsRead);
1350:                        if (n == -1)
1351:                            break;
1352:
1353:                        l_charsRead += n;
1354:
1355:                        if (l_charsRead == length)
1356:                            break;
1357:                    }
1358:
1359:                    setString(parameterIndex, new String(l_chars, 0,
1360:                            l_charsRead), Oid.VARCHAR);
1361:                } catch (UnsupportedEncodingException l_uee) {
1362:                    throw new PSQLException(GT.tr(
1363:                            "The JVM claims not to support the {0} encoding.",
1364:                            encoding), PSQLState.UNEXPECTED_ERROR, l_uee);
1365:                } catch (IOException l_ioe) {
1366:                    throw new PSQLException(GT
1367:                            .tr("Provided InputStream failed."),
1368:                            PSQLState.UNEXPECTED_ERROR, l_ioe);
1369:                }
1370:            }
1371:
1372:            /*
1373:             * When a very large ASCII value is input to a LONGVARCHAR parameter,
1374:             * it may be more practical to send it via a java.io.InputStream.
1375:             * JDBC will read the data from the stream as needed, until it reaches
1376:             * end-of-file.  The JDBC driver will do any necessary conversion from
1377:             * ASCII to the database char format.
1378:             *
1379:             * <P><B>Note:</B> This stream object can either be a standard Java
1380:             * stream object or your own subclass that implements the standard
1381:             * interface.
1382:             *
1383:             * @param parameterIndex the first parameter is 1...
1384:             * @param x the parameter value
1385:             * @param length the number of bytes in the stream
1386:             * @exception SQLException if a database access error occurs
1387:             */
1388:            public void setAsciiStream(int parameterIndex, InputStream x,
1389:                    int length) throws SQLException {
1390:                checkClosed();
1391:                if (connection.haveMinimumCompatibleVersion("7.2")) {
1392:                    setCharacterStreamPost71(parameterIndex, x, length, "ASCII");
1393:                } else {
1394:                    //Version 7.1 supported only LargeObjects by treating everything
1395:                    //as binary data
1396:                    setBinaryStream(parameterIndex, x, length);
1397:                }
1398:            }
1399:
1400:            /*
1401:             * When a very large Unicode value is input to a LONGVARCHAR parameter,
1402:             * it may be more practical to send it via a java.io.InputStream.
1403:             * JDBC will read the data from the stream as needed, until it reaches
1404:             * end-of-file.  The JDBC driver will do any necessary conversion from
1405:             * UNICODE to the database char format.
1406:             *
1407:             * <P><B>Note:</B> This stream object can either be a standard Java
1408:             * stream object or your own subclass that implements the standard
1409:             * interface.
1410:             *
1411:             * @param parameterIndex the first parameter is 1...
1412:             * @param x the parameter value
1413:             * @exception SQLException if a database access error occurs
1414:             */
1415:            public void setUnicodeStream(int parameterIndex, InputStream x,
1416:                    int length) throws SQLException {
1417:                checkClosed();
1418:                if (connection.haveMinimumCompatibleVersion("7.2")) {
1419:                    setCharacterStreamPost71(parameterIndex, x, length, "UTF-8");
1420:                } else {
1421:                    //Version 7.1 supported only LargeObjects by treating everything
1422:                    //as binary data
1423:                    setBinaryStream(parameterIndex, x, length);
1424:                }
1425:            }
1426:
1427:            /*
1428:             * When a very large binary value is input to a LONGVARBINARY parameter,
1429:             * it may be more practical to send it via a java.io.InputStream.
1430:             * JDBC will read the data from the stream as needed, until it reaches
1431:             * end-of-file.
1432:             *
1433:             * <P><B>Note:</B> This stream object can either be a standard Java
1434:             * stream object or your own subclass that implements the standard
1435:             * interface.
1436:             *
1437:             * @param parameterIndex the first parameter is 1...
1438:             * @param x the parameter value
1439:             * @exception SQLException if a database access error occurs
1440:             */
1441:            public void setBinaryStream(int parameterIndex, InputStream x,
1442:                    int length) throws SQLException {
1443:                checkClosed();
1444:
1445:                if (x == null) {
1446:                    setNull(parameterIndex, Types.VARBINARY);
1447:                    return;
1448:                }
1449:
1450:                if (length < 0)
1451:                    throw new PSQLException(GT.tr("Invalid stream length {0}.",
1452:                            new Integer(length)),
1453:                            PSQLState.INVALID_PARAMETER_VALUE);
1454:
1455:                if (connection.haveMinimumCompatibleVersion("7.2")) {
1456:                    //Version 7.2 supports BinaryStream for for the PG bytea type
1457:                    //As the spec/javadoc for this method indicate this is to be used for
1458:                    //large binary values (i.e. LONGVARBINARY) PG doesn't have a separate
1459:                    //long binary datatype, but with toast the bytea datatype is capable of
1460:                    //handling very large values.
1461:
1462:                    preparedParameters.setBytea(parameterIndex, x, length);
1463:                } else {
1464:                    //Version 7.1 only supported streams for LargeObjects
1465:                    //but the jdbc spec indicates that streams should be
1466:                    //available for LONGVARBINARY instead
1467:                    LargeObjectManager lom = connection.getLargeObjectAPI();
1468:                    long oid = lom.createLO();
1469:                    LargeObject lob = lom.open(oid);
1470:                    OutputStream los = lob.getOutputStream();
1471:                    try {
1472:                        // could be buffered, but then the OutputStream returned by LargeObject
1473:                        // is buffered internally anyhow, so there would be no performance
1474:                        // boost gained, if anything it would be worse!
1475:                        int c = x.read();
1476:                        int p = 0;
1477:                        while (c > -1 && p < length) {
1478:                            los.write(c);
1479:                            c = x.read();
1480:                            p++;
1481:                        }
1482:                        los.close();
1483:                    } catch (IOException se) {
1484:                        throw new PSQLException(GT
1485:                                .tr("Provided InputStream failed."),
1486:                                PSQLState.UNEXPECTED_ERROR, se);
1487:                    }
1488:                    // lob is closed by the stream so don't call lob.close()
1489:                    setLong(parameterIndex, oid);
1490:                }
1491:            }
1492:
1493:            /*
1494:             * In general, parameter values remain in force for repeated used of a
1495:             * Statement.  Setting a parameter value automatically clears its
1496:             * previous value. However, in coms cases, it is useful to immediately
1497:             * release the resources used by the current parameter values; this
1498:             * can be done by calling clearParameters
1499:             *
1500:             * @exception SQLException if a database access error occurs
1501:             */
1502:            public void clearParameters() throws SQLException {
1503:                preparedParameters.clear();
1504:            }
1505:
1506:            private PGType createInternalType(Object x, int targetType)
1507:                    throws PSQLException {
1508:                if (x instanceof  Byte)
1509:                    return PGByte.castToServerType((Byte) x, targetType);
1510:                if (x instanceof  Short)
1511:                    return PGShort.castToServerType((Short) x, targetType);
1512:                if (x instanceof  Integer)
1513:                    return PGInteger.castToServerType((Integer) x, targetType);
1514:                if (x instanceof  Long)
1515:                    return PGLong.castToServerType((Long) x, targetType);
1516:                if (x instanceof  Double)
1517:                    return PGDouble.castToServerType((Double) x, targetType);
1518:                if (x instanceof  Float)
1519:                    return PGFloat.castToServerType((Float) x, targetType);
1520:                if (x instanceof  BigDecimal)
1521:                    return PGBigDecimal.castToServerType((BigDecimal) x,
1522:                            targetType);
1523:                // since all of the above are instances of Number make sure this is after them
1524:                if (x instanceof  Number)
1525:                    return PGNumber.castToServerType((Number) x, targetType);
1526:                if (x instanceof  Boolean)
1527:                    return PGBoolean.castToServerType((Boolean) x, targetType);
1528:                return new PGUnknown(x);
1529:
1530:            }
1531:
1532:            // Helper method for setting parameters to PGobject subclasses.
1533:            private void setPGobject(int parameterIndex, PGobject x)
1534:                    throws SQLException {
1535:                String typename = x.getType();
1536:                int oid = connection.getPGType(typename);
1537:                if (oid == Oid.UNSPECIFIED)
1538:                    throw new PSQLException(GT
1539:                            .tr("Unknown type {0}.", typename),
1540:                            PSQLState.INVALID_PARAMETER_TYPE);
1541:
1542:                setString(parameterIndex, x.getValue(), oid);
1543:            }
1544:
1545:            /*
1546:             * Set the value of a parameter using an object; use the java.lang
1547:             * equivalent objects for integral values.
1548:             *
1549:             * <P>The given Java object will be converted to the targetSqlType before
1550:             * being sent to the database.
1551:             *
1552:             * <P>note that this method may be used to pass database-specific
1553:             * abstract data types.  This is done by using a Driver-specific
1554:             * Java type and using a targetSqlType of java.sql.Types.OTHER
1555:             *
1556:             * @param parameterIndex the first parameter is 1...
1557:             * @param x the object containing the input parameter value
1558:             * @param targetSqlType The SQL type to be send to the database
1559:             * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC
1560:             *   * types this is the number of digits after the decimal.  For
1561:             *   * all other types this value will be ignored.
1562:             * @exception SQLException if a database access error occurs
1563:             */
1564:            public void setObject(int parameterIndex, Object in,
1565:                    int targetSqlType, int scale) throws SQLException {
1566:                checkClosed();
1567:
1568:                if (in == null) {
1569:                    setNull(parameterIndex, targetSqlType);
1570:                    return;
1571:                }
1572:
1573:                Object pgType = createInternalType(in, targetSqlType);
1574:                switch (targetSqlType) {
1575:                case Types.INTEGER:
1576:                    bindLiteral(parameterIndex, pgType.toString(), Oid.INT4);
1577:                    break;
1578:                case Types.TINYINT:
1579:                case Types.SMALLINT:
1580:                    bindLiteral(parameterIndex, pgType.toString(), Oid.INT2);
1581:                    break;
1582:                case Types.BIGINT:
1583:                    bindLiteral(parameterIndex, pgType.toString(), Oid.INT8);
1584:                    break;
1585:                case Types.REAL:
1586:                    //TODO: is this really necessary ?
1587:                    //bindLiteral(parameterIndex, new Float(pgType.toString()).toString(), Oid.FLOAT4);
1588:                    bindLiteral(parameterIndex, pgType.toString(), Oid.FLOAT4);
1589:                    break;
1590:                case Types.DOUBLE:
1591:                case Types.FLOAT:
1592:                    bindLiteral(parameterIndex, pgType.toString(), Oid.FLOAT8);
1593:                    break;
1594:                case Types.DECIMAL:
1595:                case Types.NUMERIC:
1596:                    bindLiteral(parameterIndex, pgType.toString(), Oid.NUMERIC);
1597:                    break;
1598:                case Types.CHAR:
1599:                    setString(parameterIndex, pgType.toString(), Oid.BPCHAR);
1600:                    break;
1601:                case Types.VARCHAR:
1602:                case Types.LONGVARCHAR:
1603:                    setString(parameterIndex, pgType.toString(), Oid.VARCHAR);
1604:                    break;
1605:                case Types.DATE:
1606:                    if (in instanceof  java.sql.Date)
1607:                        setDate(parameterIndex, (java.sql.Date) in);
1608:                    else {
1609:                        java.sql.Date tmpd;
1610:                        if (in instanceof  java.util.Date) {
1611:                            tmpd = new java.sql.Date(((java.util.Date) in)
1612:                                    .getTime());
1613:                        } else {
1614:                            tmpd = connection.getTimestampUtils().toDate(null,
1615:                                    in.toString());
1616:                        }
1617:                        setDate(parameterIndex, tmpd);
1618:                    }
1619:                    break;
1620:                case Types.TIME:
1621:                    if (in instanceof  java.sql.Time)
1622:                        setTime(parameterIndex, (java.sql.Time) in);
1623:                    else {
1624:                        java.sql.Time tmpt;
1625:                        if (in instanceof  java.util.Date) {
1626:                            tmpt = new java.sql.Time(((java.util.Date) in)
1627:                                    .getTime());
1628:                        } else {
1629:                            tmpt = connection.getTimestampUtils().toTime(null,
1630:                                    in.toString());
1631:                        }
1632:                        setTime(parameterIndex, tmpt);
1633:                    }
1634:                    break;
1635:                case Types.TIMESTAMP:
1636:                    if (in instanceof  java.sql.Timestamp)
1637:                        setTimestamp(parameterIndex, (java.sql.Timestamp) in);
1638:                    else {
1639:                        java.sql.Timestamp tmpts;
1640:                        if (in instanceof  java.util.Date) {
1641:                            tmpts = new java.sql.Timestamp(
1642:                                    ((java.util.Date) in).getTime());
1643:                        } else {
1644:                            tmpts = connection.getTimestampUtils().toTimestamp(
1645:                                    null, in.toString());
1646:                        }
1647:                        setTimestamp(parameterIndex, tmpts);
1648:                    }
1649:                    break;
1650:                case Types.BIT:
1651:                    bindLiteral(parameterIndex, pgType.toString(), Oid.BOOL);
1652:                    break;
1653:                case Types.BINARY:
1654:                case Types.VARBINARY:
1655:                case Types.LONGVARBINARY:
1656:                    setObject(parameterIndex, in);
1657:                    break;
1658:                case Types.BLOB:
1659:                    if (in instanceof  Blob)
1660:                        setBlob(parameterIndex, (Blob) in);
1661:                    else
1662:                        throw new PSQLException(GT.tr(
1663:                                "Cannot cast an instance of {0} to type {1}",
1664:                                new Object[] { in.getClass().getName(),
1665:                                        "Types.BLOB" }),
1666:                                PSQLState.INVALID_PARAMETER_TYPE);
1667:                    break;
1668:                case Types.CLOB:
1669:                    if (in instanceof  Clob)
1670:                        setClob(parameterIndex, (Clob) in);
1671:                    else
1672:                        throw new PSQLException(GT.tr(
1673:                                "Cannot cast an instance of {0} to type {1}",
1674:                                new Object[] { in.getClass().getName(),
1675:                                        "Types.CLOB" }),
1676:                                PSQLState.INVALID_PARAMETER_TYPE);
1677:                    break;
1678:                case Types.ARRAY:
1679:                    if (in instanceof  Array)
1680:                        setArray(parameterIndex, (Array) in);
1681:                    else
1682:                        throw new PSQLException(GT.tr(
1683:                                "Cannot cast an instance of {0} to type {1}",
1684:                                new Object[] { in.getClass().getName(),
1685:                                        "Types.ARRAY" }),
1686:                                PSQLState.INVALID_PARAMETER_TYPE);
1687:                    break;
1688:                case Types.OTHER:
1689:                    if (in instanceof  PGobject)
1690:                        setPGobject(parameterIndex, (PGobject) in);
1691:                    else
1692:                        throw new PSQLException(GT.tr(
1693:                                "Cannot cast an instance of {0} to type {1}",
1694:                                new Object[] { in.getClass().getName(),
1695:                                        "Types.OTHER" }),
1696:                                PSQLState.INVALID_PARAMETER_TYPE);
1697:                    break;
1698:                default:
1699:                    throw new PSQLException(GT.tr(
1700:                            "Unsupported Types value: {0}", new Integer(
1701:                                    targetSqlType)),
1702:                            PSQLState.INVALID_PARAMETER_TYPE);
1703:                }
1704:            }
1705:
1706:            public void setObject(int parameterIndex, Object x,
1707:                    int targetSqlType) throws SQLException {
1708:                setObject(parameterIndex, x, targetSqlType, 0);
1709:            }
1710:
1711:            /*
1712:             * This stores an Object into a parameter.
1713:             */
1714:            public void setObject(int parameterIndex, Object x)
1715:                    throws SQLException {
1716:                checkClosed();
1717:                if (x == null)
1718:                    setNull(parameterIndex, Types.OTHER);
1719:                else if (x instanceof  String)
1720:                    setString(parameterIndex, (String) x);
1721:                else if (x instanceof  BigDecimal)
1722:                    setBigDecimal(parameterIndex, (BigDecimal) x);
1723:                else if (x instanceof  Short)
1724:                    setShort(parameterIndex, ((Short) x).shortValue());
1725:                else if (x instanceof  Integer)
1726:                    setInt(parameterIndex, ((Integer) x).intValue());
1727:                else if (x instanceof  Long)
1728:                    setLong(parameterIndex, ((Long) x).longValue());
1729:                else if (x instanceof  Float)
1730:                    setFloat(parameterIndex, ((Float) x).floatValue());
1731:                else if (x instanceof  Double)
1732:                    setDouble(parameterIndex, ((Double) x).doubleValue());
1733:                else if (x instanceof  byte[])
1734:                    setBytes(parameterIndex, (byte[]) x);
1735:                else if (x instanceof  java.sql.Date)
1736:                    setDate(parameterIndex, (java.sql.Date) x);
1737:                else if (x instanceof  Time)
1738:                    setTime(parameterIndex, (Time) x);
1739:                else if (x instanceof  Timestamp)
1740:                    setTimestamp(parameterIndex, (Timestamp) x);
1741:                else if (x instanceof  Boolean)
1742:                    setBoolean(parameterIndex, ((Boolean) x).booleanValue());
1743:                else if (x instanceof  Byte)
1744:                    setByte(parameterIndex, ((Byte) x).byteValue());
1745:                else if (x instanceof  Blob)
1746:                    setBlob(parameterIndex, (Blob) x);
1747:                else if (x instanceof  Clob)
1748:                    setClob(parameterIndex, (Clob) x);
1749:                else if (x instanceof  Array)
1750:                    setArray(parameterIndex, (Array) x);
1751:                else if (x instanceof  PGobject)
1752:                    setPGobject(parameterIndex, (PGobject) x);
1753:                else {
1754:                    // Can't infer a type.
1755:                    throw new PSQLException(
1756:                            GT
1757:                                    .tr(
1758:                                            "Can''t infer the SQL type to use for an instance of {0}. Use setObject() with an explicit Types value to specify the type to use.",
1759:                                            x.getClass().getName()),
1760:                            PSQLState.INVALID_PARAMETER_TYPE);
1761:                }
1762:            }
1763:
1764:            /*
1765:             * Before executing a stored procedure call you must explicitly
1766:             * call registerOutParameter to register the java.sql.Type of each
1767:             * out parameter.
1768:             *
1769:             * <p>Note: When reading the value of an out parameter, you must use
1770:             * the getXXX method whose Java type XXX corresponds to the
1771:             * parameter's registered SQL type.
1772:             *
1773:             * ONLY 1 RETURN PARAMETER if {?= call ..} syntax is used
1774:             *
1775:             * @param parameterIndex the first parameter is 1, the second is 2,...
1776:             * @param sqlType SQL type code defined by java.sql.Types; for
1777:             * parameters of type Numeric or Decimal use the version of
1778:             * registerOutParameter that accepts a scale value
1779:             * @exception SQLException if a database-access error occurs.
1780:             */
1781:            public void registerOutParameter(int parameterIndex, int sqlType,
1782:                    boolean setPreparedParameters) throws SQLException {
1783:                checkClosed();
1784:                switch (sqlType) {
1785:                case Types.TINYINT:
1786:                    // we don't have a TINYINT type use SMALLINT
1787:                    sqlType = Types.SMALLINT;
1788:                    break;
1789:                case Types.LONGVARCHAR:
1790:                    sqlType = Types.VARCHAR;
1791:                    break;
1792:                case Types.DECIMAL:
1793:                    sqlType = Types.NUMERIC;
1794:                    break;
1795:                case Types.FLOAT:
1796:                    // float is the same as double
1797:                    sqlType = Types.DOUBLE;
1798:                    break;
1799:                case Types.VARBINARY:
1800:                case Types.LONGVARBINARY:
1801:                    sqlType = Types.BINARY;
1802:                    break;
1803:                default:
1804:                    break;
1805:                }
1806:                if (!isFunction)
1807:                    throw new PSQLException(
1808:                            GT
1809:                                    .tr("This statement does not declare an OUT parameter.  Use '{' ?= call ... '}' to declare one."),
1810:                            PSQLState.STATEMENT_NOT_ALLOWED_IN_FUNCTION_CALL);
1811:                checkIndex(parameterIndex, false);
1812:
1813:                if (setPreparedParameters)
1814:                    preparedParameters.registerOutParameter(parameterIndex,
1815:                            sqlType);
1816:                // functionReturnType contains the user supplied value to check
1817:                // testReturn contains a modified version to make it easier to
1818:                // check the getXXX methods..
1819:                functionReturnType[parameterIndex - 1] = sqlType;
1820:                testReturn[parameterIndex - 1] = sqlType;
1821:
1822:                if (functionReturnType[parameterIndex - 1] == Types.CHAR
1823:                        || functionReturnType[parameterIndex - 1] == Types.LONGVARCHAR)
1824:                    testReturn[parameterIndex - 1] = Types.VARCHAR;
1825:                else if (functionReturnType[parameterIndex - 1] == Types.FLOAT)
1826:                    testReturn[parameterIndex - 1] = Types.REAL; // changes to streamline later error checking
1827:                returnTypeSet = true;
1828:            }
1829:
1830:            /*
1831:             * You must also specify the scale for numeric/decimal types:
1832:             *
1833:             * <p>Note: When reading the value of an out parameter, you must use
1834:             * the getXXX method whose Java type XXX corresponds to the
1835:             * parameter's registered SQL type.
1836:             *
1837:             * @param parameterIndex the first parameter is 1, the second is 2,...
1838:             * @param sqlType use either java.sql.Type.NUMERIC or java.sql.Type.DECIMAL
1839:             * @param scale a value greater than or equal to zero representing the
1840:             * desired number of digits to the right of the decimal point
1841:             * @exception SQLException if a database-access error occurs.
1842:             */
1843:            public void registerOutParameter(int parameterIndex, int sqlType,
1844:                    int scale, boolean setPreparedParameters)
1845:                    throws SQLException {
1846:                registerOutParameter(parameterIndex, sqlType,
1847:                        setPreparedParameters); // ignore for now..
1848:            }
1849:
1850:            /*
1851:             * An OUT parameter may have the value of SQL NULL; wasNull
1852:             * reports whether the last value read has this special value.
1853:             *
1854:             * <p>Note: You must first call getXXX on a parameter to read its
1855:             * value and then call wasNull() to see if the value was SQL NULL.
1856:             * @return true if the last parameter read was SQL NULL
1857:             * @exception SQLException if a database-access error occurs.
1858:             */
1859:            public boolean wasNull() throws SQLException {
1860:                if (lastIndex == 0)
1861:                    throw new PSQLException(
1862:                            GT
1863:                                    .tr("wasNull cannot be call before fetching a result."),
1864:                            PSQLState.OBJECT_NOT_IN_STATE);
1865:
1866:                // check to see if the last access threw an exception
1867:                return (callResult[lastIndex - 1] == null);
1868:            }
1869:
1870:            /*
1871:             * Get the value of a CHAR, VARCHAR, or LONGVARCHAR parameter as a
1872:             * Java String.
1873:             *
1874:             * @param parameterIndex the first parameter is 1, the second is 2,...
1875:             * @return the parameter value; if the value is SQL NULL, the result is null
1876:             * @exception SQLException if a database-access error occurs.
1877:             */
1878:            public String getString(int parameterIndex) throws SQLException {
1879:                checkClosed();
1880:                checkIndex(parameterIndex, Types.VARCHAR, "String");
1881:                return (String) callResult[parameterIndex - 1];
1882:            }
1883:
1884:            /*
1885:             * Get the value of a BIT parameter as a Java boolean.
1886:             *
1887:             * @param parameterIndex the first parameter is 1, the second is 2,...
1888:             * @return the parameter value; if the value is SQL NULL, the result is false
1889:             * @exception SQLException if a database-access error occurs.
1890:             */
1891:            public boolean getBoolean(int parameterIndex) throws SQLException {
1892:                checkClosed();
1893:                checkIndex(parameterIndex, Types.BIT, "Boolean");
1894:                if (callResult[parameterIndex - 1] == null)
1895:                    return false;
1896:
1897:                return ((Boolean) callResult[parameterIndex - 1])
1898:                        .booleanValue();
1899:            }
1900:
1901:            /*
1902:             * Get the value of a TINYINT parameter as a Java byte.
1903:             *
1904:             * @param parameterIndex the first parameter is 1, the second is 2,...
1905:             * @return the parameter value; if the value is SQL NULL, the result is 0
1906:             * @exception SQLException if a database-access error occurs.
1907:             */
1908:            public byte getByte(int parameterIndex) throws SQLException {
1909:                checkClosed();
1910:                // fake tiny int with smallint
1911:                checkIndex(parameterIndex, Types.SMALLINT, "Byte");
1912:
1913:                if (callResult[parameterIndex - 1] == null)
1914:                    return 0;
1915:
1916:                return ((Integer) callResult[parameterIndex - 1]).byteValue();
1917:
1918:            }
1919:
1920:            /*
1921:             * Get the value of a SMALLINT parameter as a Java short.
1922:             *
1923:             * @param parameterIndex the first parameter is 1, the second is 2,...
1924:             * @return the parameter value; if the value is SQL NULL, the result is 0
1925:             * @exception SQLException if a database-access error occurs.
1926:             */
1927:            public short getShort(int parameterIndex) throws SQLException {
1928:                checkClosed();
1929:                checkIndex(parameterIndex, Types.SMALLINT, "Short");
1930:                if (callResult[parameterIndex - 1] == null)
1931:                    return 0;
1932:                return ((Integer) callResult[parameterIndex - 1]).shortValue();
1933:            }
1934:
1935:            /*
1936:             * Get the value of an INTEGER parameter as a Java int.
1937:             *
1938:             * @param parameterIndex the first parameter is 1, the second is 2,...
1939:             * @return the parameter value; if the value is SQL NULL, the result is 0
1940:             * @exception SQLException if a database-access error occurs.
1941:             */
1942:            public int getInt(int parameterIndex) throws SQLException {
1943:                checkClosed();
1944:                checkIndex(parameterIndex, Types.INTEGER, "Int");
1945:                if (callResult[parameterIndex - 1] == null)
1946:                    return 0;
1947:
1948:                return ((Integer) callResult[parameterIndex - 1]).intValue();
1949:            }
1950:
1951:            /*
1952:             * Get the value of a BIGINT parameter as a Java long.
1953:             *
1954:             * @param parameterIndex the first parameter is 1, the second is 2,...
1955:             * @return the parameter value; if the value is SQL NULL, the result is 0
1956:             * @exception SQLException if a database-access error occurs.
1957:             */
1958:            public long getLong(int parameterIndex) throws SQLException {
1959:                checkClosed();
1960:                checkIndex(parameterIndex, Types.BIGINT, "Long");
1961:                if (callResult[parameterIndex - 1] == null)
1962:                    return 0;
1963:
1964:                return ((Long) callResult[parameterIndex - 1]).longValue();
1965:            }
1966:
1967:            /*
1968:             * Get the value of a FLOAT parameter as a Java float.
1969:             *
1970:             * @param parameterIndex the first parameter is 1, the second is 2,...
1971:             * @return the parameter value; if the value is SQL NULL, the result is 0
1972:             * @exception SQLException if a database-access error occurs.
1973:             */
1974:            public float getFloat(int parameterIndex) throws SQLException {
1975:                checkClosed();
1976:                checkIndex(parameterIndex, Types.REAL, "Float");
1977:                if (callResult[parameterIndex - 1] == null)
1978:                    return 0;
1979:
1980:                return ((Float) callResult[parameterIndex - 1]).floatValue();
1981:            }
1982:
1983:            /*
1984:             * Get the value of a DOUBLE parameter as a Java double.
1985:             *
1986:             * @param parameterIndex the first parameter is 1, the second is 2,...
1987:             * @return the parameter value; if the value is SQL NULL, the result is 0
1988:             * @exception SQLException if a database-access error occurs.
1989:             */
1990:            public double getDouble(int parameterIndex) throws SQLException {
1991:                checkClosed();
1992:                checkIndex(parameterIndex, Types.DOUBLE, "Double");
1993:                if (callResult[parameterIndex - 1] == null)
1994:                    return 0;
1995:
1996:                return ((Double) callResult[parameterIndex - 1]).doubleValue();
1997:            }
1998:
1999:            /*
2000:             * Get the value of a NUMERIC parameter as a java.math.BigDecimal
2001:             * object.
2002:             *
2003:             * @param parameterIndex the first parameter is 1, the second is 2,...
2004:             * @param scale a value greater than or equal to zero representing the
2005:             * desired number of digits to the right of the decimal point
2006:             * @return the parameter value; if the value is SQL NULL, the result is null
2007:             * @exception SQLException if a database-access error occurs.
2008:             * @deprecated in Java2.0
2009:             */
2010:            public BigDecimal getBigDecimal(int parameterIndex, int scale)
2011:                    throws SQLException {
2012:                checkClosed();
2013:                checkIndex(parameterIndex, Types.NUMERIC, "BigDecimal");
2014:                return ((BigDecimal) callResult[parameterIndex - 1]);
2015:            }
2016:
2017:            /*
2018:             * Get the value of a SQL BINARY or VARBINARY parameter as a Java
2019:             * byte[]
2020:             *
2021:             * @param parameterIndex the first parameter is 1, the second is 2,...
2022:             * @return the parameter value; if the value is SQL NULL, the result is null
2023:             * @exception SQLException if a database-access error occurs.
2024:             */
2025:            public byte[] getBytes(int parameterIndex) throws SQLException {
2026:                checkClosed();
2027:                checkIndex(parameterIndex, Types.VARBINARY, Types.BINARY,
2028:                        "Bytes");
2029:                return ((byte[]) callResult[parameterIndex - 1]);
2030:            }
2031:
2032:            /*
2033:             * Get the value of a SQL DATE parameter as a java.sql.Date object
2034:             *
2035:             * @param parameterIndex the first parameter is 1, the second is 2,...
2036:             * @return the parameter value; if the value is SQL NULL, the result is null
2037:             * @exception SQLException if a database-access error occurs.
2038:             */
2039:            public java.sql.Date getDate(int parameterIndex)
2040:                    throws SQLException {
2041:                checkClosed();
2042:                checkIndex(parameterIndex, Types.DATE, "Date");
2043:                return (java.sql.Date) callResult[parameterIndex - 1];
2044:            }
2045:
2046:            /*
2047:             * Get the value of a SQL TIME parameter as a java.sql.Time object.
2048:             *
2049:             * @param parameterIndex the first parameter is 1, the second is 2,...
2050:             * @return the parameter value; if the value is SQL NULL, the result is null
2051:             * @exception SQLException if a database-access error occurs.
2052:             */
2053:            public java.sql.Time getTime(int parameterIndex)
2054:                    throws SQLException {
2055:                checkClosed();
2056:                checkIndex(parameterIndex, Types.TIME, "Time");
2057:                return (java.sql.Time) callResult[parameterIndex - 1];
2058:            }
2059:
2060:            /*
2061:             * Get the value of a SQL TIMESTAMP parameter as a java.sql.Timestamp object.
2062:             *
2063:             * @param parameterIndex the first parameter is 1, the second is 2,...
2064:             * @return the parameter value; if the value is SQL NULL, the result is null
2065:             * @exception SQLException if a database-access error occurs.
2066:             */
2067:            public java.sql.Timestamp getTimestamp(int parameterIndex)
2068:                    throws SQLException {
2069:                checkClosed();
2070:                checkIndex(parameterIndex, Types.TIMESTAMP, "Timestamp");
2071:                return (java.sql.Timestamp) callResult[parameterIndex - 1];
2072:            }
2073:
2074:            // getObject returns a Java object for the parameter.
2075:            // See the JDBC spec's "Dynamic Programming" chapter for details.
2076:            /*
2077:             * Get the value of a parameter as a Java object.
2078:             *
2079:             * <p>This method returns a Java object whose type coresponds to the
2080:             * SQL type that was registered for this parameter using
2081:             * registerOutParameter.
2082:             *
2083:             * <P>Note that this method may be used to read datatabase-specific,
2084:             * abstract data types. This is done by specifying a targetSqlType
2085:             * of java.sql.types.OTHER, which allows the driver to return a
2086:             * database-specific Java type.
2087:             *
2088:             * <p>See the JDBC spec's "Dynamic Programming" chapter for details.
2089:             *
2090:             * @param parameterIndex the first parameter is 1, the second is 2,...
2091:             * @return A java.lang.Object holding the OUT parameter value.
2092:             * @exception SQLException if a database-access error occurs.
2093:             */
2094:            public Object getObject(int parameterIndex) throws SQLException {
2095:                checkClosed();
2096:                checkIndex(parameterIndex);
2097:                return callResult[parameterIndex - 1];
2098:            }
2099:
2100:            /*
2101:             * Returns the SQL statement with the current template values
2102:             * substituted.
2103:             */
2104:            public String toString() {
2105:                if (preparedQuery == null)
2106:                    return super .toString();
2107:
2108:                return preparedQuery.toString(preparedParameters);
2109:            }
2110:
2111:            /*
2112:             * Note if s is a String it should be escaped by the caller to avoid SQL
2113:             * injection attacks.  It is not done here for efficency reasons as
2114:             * most calls to this method do not require escaping as the source
2115:             * of the string is known safe (i.e. Integer.toString())
2116:             */
2117:            private void bindLiteral(int paramIndex, String s, int oid)
2118:                    throws SQLException {
2119:                if (adjustIndex)
2120:                    paramIndex--;
2121:                preparedParameters.setLiteralParameter(paramIndex, s, oid);
2122:            }
2123:
2124:            /*
2125:             * This version is for values that should turn into strings
2126:             * e.g. setString directly calls bindString with no escaping;
2127:             * the per-protocol ParameterList does escaping as needed.
2128:             */
2129:            private void bindString(int paramIndex, String s, int oid)
2130:                    throws SQLException {
2131:                if (adjustIndex)
2132:                    paramIndex--;
2133:                preparedParameters.setStringParameter(paramIndex, s, oid);
2134:            }
2135:
2136:            /**
2137:             * this method will turn a string of the form
2138:             * { [? =] call <some_function> [(?, [?,..])] }
2139:             * into the PostgreSQL format which is
2140:             * select <some_function> (?, [?, ...]) as result
2141:             * or select * from <some_function> (?, [?, ...]) as result (7.3)
2142:             */
2143:            private String modifyJdbcCall(String p_sql) throws SQLException {
2144:                checkClosed();
2145:
2146:                // Mini-parser for JDBC function-call syntax (only)
2147:                // TODO: Merge with escape processing (and parameter parsing?)
2148:                // so we only parse each query once.
2149:
2150:                isFunction = false;
2151:
2152:                boolean stdStrings = connection.getStandardConformingStrings();
2153:
2154:                int len = p_sql.length();
2155:                int state = 1;
2156:                boolean inQuotes = false, inEscape = false;
2157:                outParmBeforeFunc = false;
2158:                int startIndex = -1, endIndex = -1;
2159:                boolean syntaxError = false;
2160:                int i = 0;
2161:
2162:                while (i < len && !syntaxError) {
2163:                    char ch = p_sql.charAt(i);
2164:
2165:                    switch (state) {
2166:                    case 1: // Looking for { at start of query
2167:                        if (ch == '{') {
2168:                            ++i;
2169:                            ++state;
2170:                        } else if (Character.isWhitespace(ch)) {
2171:                            ++i;
2172:                        } else {
2173:                            // Not function-call syntax. Skip the rest of the string.
2174:                            i = len;
2175:                        }
2176:                        break;
2177:
2178:                    case 2: // After {, looking for ? or =, skipping whitespace
2179:                        if (ch == '?') {
2180:                            outParmBeforeFunc = isFunction = true; // { ? = call ... }  -- function with one out parameter
2181:                            ++i;
2182:                            ++state;
2183:                        } else if (ch == 'c') { // { call ... }      -- proc with no out parameters
2184:                            state += 3; // Don't increase 'i'
2185:                        } else if (Character.isWhitespace(ch)) {
2186:                            ++i;
2187:                        } else {
2188:                            // "{ foo ...", doesn't make sense, complain.
2189:                            syntaxError = true;
2190:                        }
2191:                        break;
2192:
2193:                    case 3: // Looking for = after ?, skipping whitespace
2194:                        if (ch == '=') {
2195:                            ++i;
2196:                            ++state;
2197:                        } else if (Character.isWhitespace(ch)) {
2198:                            ++i;
2199:                        } else {
2200:                            syntaxError = true;
2201:                        }
2202:                        break;
2203:
2204:                    case 4: // Looking for 'call' after '? =' skipping whitespace
2205:                        if (ch == 'c' || ch == 'C') {
2206:                            ++state; // Don't increase 'i'.
2207:                        } else if (Character.isWhitespace(ch)) {
2208:                            ++i;
2209:                        } else {
2210:                            syntaxError = true;
2211:                        }
2212:                        break;
2213:
2214:                    case 5: // Should be at 'call ' either at start of string or after ?=
2215:                        if ((ch == 'c' || ch == 'C')
2216:                                && i + 4 <= len
2217:                                && p_sql.substring(i, i + 4).equalsIgnoreCase(
2218:                                        "call")) {
2219:                            isFunction = true;
2220:                            i += 4;
2221:                            ++state;
2222:                        } else if (Character.isWhitespace(ch)) {
2223:                            ++i;
2224:                        } else {
2225:                            syntaxError = true;
2226:                        }
2227:                        break;
2228:
2229:                    case 6: // Looking for whitespace char after 'call'
2230:                        if (Character.isWhitespace(ch)) {
2231:                            // Ok, we found the start of the real call.
2232:                            ++i;
2233:                            ++state;
2234:                            startIndex = i;
2235:                        } else {
2236:                            syntaxError = true;
2237:                        }
2238:                        break;
2239:
2240:                    case 7: // In "body" of the query (after "{ [? =] call ")
2241:                        if (ch == '\'') {
2242:                            inQuotes = !inQuotes;
2243:                            ++i;
2244:                        } else if (inQuotes && ch == '\\' && !stdStrings) {
2245:                            // Backslash in string constant, skip next character.
2246:                            i += 2;
2247:                        } else if (!inQuotes && ch == '{') {
2248:                            inEscape = !inEscape;
2249:                            ++i;
2250:                        } else if (!inQuotes && ch == '}') {
2251:                            if (!inEscape) {
2252:                                // Should be end of string.
2253:                                endIndex = i;
2254:                                ++i;
2255:                                ++state;
2256:                            } else {
2257:                                inEscape = false;
2258:                            }
2259:                        } else if (!inQuotes && ch == ';') {
2260:                            syntaxError = true;
2261:                        } else {
2262:                            // Everything else is ok.
2263:                            ++i;
2264:                        }
2265:                        break;
2266:
2267:                    case 8: // At trailing end of query, eating whitespace
2268:                        if (Character.isWhitespace(ch)) {
2269:                            ++i;
2270:                        } else {
2271:                            syntaxError = true;
2272:                        }
2273:                        break;
2274:
2275:                    default:
2276:                        throw new IllegalStateException(
2277:                                "somehow got into bad state " + state);
2278:                    }
2279:                }
2280:
2281:                // We can only legally end in a couple of states here.
2282:                if (i == len && !syntaxError) {
2283:                    if (state == 1)
2284:                        return p_sql; // Not an escaped syntax.
2285:                    if (state != 8)
2286:                        syntaxError = true; // Ran out of query while still parsing
2287:                }
2288:
2289:                if (syntaxError)
2290:                    throw new PSQLException(
2291:                            GT
2292:                                    .tr(
2293:                                            "Malformed function or procedure escape syntax at offset {0}.",
2294:                                            new Integer(i)),
2295:                            PSQLState.STATEMENT_NOT_ALLOWED_IN_FUNCTION_CALL);
2296:
2297:                if (connection.haveMinimumServerVersion("8.1")
2298:                        && ((AbstractJdbc2Connection) connection)
2299:                                .getProtocolVersion() == 3) {
2300:                    String s = p_sql.substring(startIndex, endIndex);
2301:                    StringBuffer sb = new StringBuffer(s);
2302:                    if (outParmBeforeFunc) {
2303:                        // move the single out parameter into the function call 
2304:                        // so that it can be treated like all other parameters
2305:                        boolean needComma = false;
2306:
2307:                        // have to use String.indexOf for java 2
2308:                        int opening = s.indexOf('(') + 1;
2309:                        int closing = s.indexOf(')');
2310:                        for (int j = opening; j < closing; j++) {
2311:                            if (!Character.isWhitespace(sb.charAt(j))) {
2312:                                needComma = true;
2313:                                break;
2314:                            }
2315:                        }
2316:                        if (needComma) {
2317:                            sb.insert(opening, "?,");
2318:                        } else {
2319:                            sb.insert(opening, "?");
2320:                        }
2321:
2322:                    }
2323:                    return "select * from " + sb.toString() + " as result";
2324:                } else {
2325:                    return "select " + p_sql.substring(startIndex, endIndex)
2326:                            + " as result";
2327:                }
2328:            }
2329:
2330:            /** helperfunction for the getXXX calls to check isFunction and index == 1
2331:             * Compare BOTH type fields against the return type.
2332:             */
2333:            protected void checkIndex(int parameterIndex, int type1, int type2,
2334:                    String getName) throws SQLException {
2335:                checkIndex(parameterIndex);
2336:                if (type1 != this .testReturn[parameterIndex - 1]
2337:                        && type2 != this .testReturn[parameterIndex - 1])
2338:                    throw new PSQLException(
2339:                            GT
2340:                                    .tr(
2341:                                            "Parameter of type {0} was registered, but call to get{1} (sqltype={2}) was made.",
2342:                                            new Object[] {
2343:                                                    "java.sql.Types="
2344:                                                            + testReturn[parameterIndex - 1],
2345:                                                    getName,
2346:                                                    "java.sql.Types=" + type1 }),
2347:                            PSQLState.MOST_SPECIFIC_TYPE_DOES_NOT_MATCH);
2348:            }
2349:
2350:            /** helperfunction for the getXXX calls to check isFunction and index == 1
2351:             */
2352:            protected void checkIndex(int parameterIndex, int type,
2353:                    String getName) throws SQLException {
2354:                checkIndex(parameterIndex);
2355:                if (type != this .testReturn[parameterIndex - 1])
2356:                    throw new PSQLException(
2357:                            GT
2358:                                    .tr(
2359:                                            "Parameter of type {0} was registered, but call to get{1} (sqltype={2}) was made.",
2360:                                            new Object[] {
2361:                                                    "java.sql.Types="
2362:                                                            + testReturn[parameterIndex - 1],
2363:                                                    getName,
2364:                                                    "java.sql.Types=" + type }),
2365:                            PSQLState.MOST_SPECIFIC_TYPE_DOES_NOT_MATCH);
2366:            }
2367:
2368:            private void checkIndex(int parameterIndex) throws SQLException {
2369:                checkIndex(parameterIndex, true);
2370:            }
2371:
2372:            /** helperfunction for the getXXX calls to check isFunction and index == 1
2373:             * @param parameterIndex index of getXXX (index)
2374:             * check to make sure is a function and index == 1
2375:             */
2376:            private void checkIndex(int parameterIndex, boolean fetchingData)
2377:                    throws SQLException {
2378:                if (!isFunction)
2379:                    throw new PSQLException(
2380:                            GT
2381:                                    .tr("A CallableStatement was declared, but no call to registerOutParameter(1, <some type>) was made."),
2382:                            PSQLState.STATEMENT_NOT_ALLOWED_IN_FUNCTION_CALL);
2383:
2384:                if (fetchingData) {
2385:                    if (!returnTypeSet)
2386:                        throw new PSQLException(GT
2387:                                .tr("No function outputs were registered."),
2388:                                PSQLState.OBJECT_NOT_IN_STATE);
2389:
2390:                    if (callResult == null)
2391:                        throw new PSQLException(
2392:                                GT
2393:                                        .tr("Results cannot be retrieved from a CallableStatement before it is executed."),
2394:                                PSQLState.NO_DATA);
2395:
2396:                    lastIndex = parameterIndex;
2397:                }
2398:            }
2399:
2400:            public void setPrepareThreshold(int newThreshold)
2401:                    throws SQLException {
2402:                checkClosed();
2403:
2404:                if (newThreshold < 0)
2405:                    newThreshold = 0;
2406:
2407:                this .m_prepareThreshold = newThreshold;
2408:            }
2409:
2410:            public int getPrepareThreshold() {
2411:                return m_prepareThreshold;
2412:            }
2413:
2414:            public void setUseServerPrepare(boolean flag) throws SQLException {
2415:                setPrepareThreshold(flag ? 1 : 0);
2416:            }
2417:
2418:            public boolean isUseServerPrepare() {
2419:                return (preparedQuery != null && m_prepareThreshold != 0 && m_useCount + 1 >= m_prepareThreshold);
2420:            }
2421:
2422:            protected void checkClosed() throws SQLException {
2423:                if (isClosed)
2424:                    throw new PSQLException(GT
2425:                            .tr("This statement has been closed."),
2426:                            PSQLState.OBJECT_NOT_IN_STATE);
2427:            }
2428:
2429:            // ** JDBC 2 Extensions **
2430:
2431:            public void addBatch(String p_sql) throws SQLException {
2432:                checkClosed();
2433:
2434:                if (preparedQuery != null)
2435:                    throw new PSQLException(
2436:                            GT
2437:                                    .tr("Can''t use query methods that take a query string on a PreparedStatement."),
2438:                            PSQLState.WRONG_OBJECT_TYPE);
2439:
2440:                if (batchStatements == null) {
2441:                    batchStatements = new ArrayList();
2442:                    batchParameters = new ArrayList();
2443:                }
2444:
2445:                p_sql = replaceProcessing(p_sql);
2446:
2447:                batchStatements.add(connection.getQueryExecutor()
2448:                        .createSimpleQuery(p_sql));
2449:                batchParameters.add(null);
2450:            }
2451:
2452:            public void clearBatch() throws SQLException {
2453:                if (batchStatements != null) {
2454:                    batchStatements.clear();
2455:                    batchParameters.clear();
2456:                }
2457:            }
2458:
2459:            //
2460:            // ResultHandler for batch queries.
2461:            //
2462:
2463:            private class BatchResultHandler implements  ResultHandler {
2464:                private BatchUpdateException batchException = null;
2465:                private int resultIndex = 0;
2466:
2467:                private final Query[] queries;
2468:                private final ParameterList[] parameterLists;
2469:                private final int[] updateCounts;
2470:
2471:                BatchResultHandler(Query[] queries,
2472:                        ParameterList[] parameterLists, int[] updateCounts) {
2473:                    this .queries = queries;
2474:                    this .parameterLists = parameterLists;
2475:                    this .updateCounts = updateCounts;
2476:                }
2477:
2478:                public void handleResultRows(Query fromQuery, Field[] fields,
2479:                        Vector tuples, ResultCursor cursor) {
2480:                    handleError(new PSQLException(
2481:                            GT
2482:                                    .tr("A result was returned when none was expected."),
2483:                            PSQLState.TOO_MANY_RESULTS));
2484:                }
2485:
2486:                public void handleCommandStatus(String status, int updateCount,
2487:                        long insertOID) {
2488:                    if (resultIndex >= updateCounts.length) {
2489:                        handleError(new PSQLException(GT
2490:                                .tr("Too many update results were returned."),
2491:                                PSQLState.TOO_MANY_RESULTS));
2492:                        return;
2493:                    }
2494:
2495:                    updateCounts[resultIndex++] = updateCount;
2496:                }
2497:
2498:                public void handleWarning(SQLWarning warning) {
2499:                    AbstractJdbc2Statement.this .addWarning(warning);
2500:                }
2501:
2502:                public void handleError(SQLException newError) {
2503:                    if (batchException == null) {
2504:                        int[] successCounts;
2505:
2506:                        if (resultIndex >= updateCounts.length)
2507:                            successCounts = updateCounts;
2508:                        else {
2509:                            successCounts = new int[resultIndex];
2510:                            System.arraycopy(updateCounts, 0, successCounts, 0,
2511:                                    resultIndex);
2512:                        }
2513:
2514:                        String queryString = "<unknown>";
2515:                        if (resultIndex < queries.length)
2516:                            queryString = queries[resultIndex]
2517:                                    .toString(parameterLists[resultIndex]);
2518:
2519:                        batchException = new BatchUpdateException(
2520:                                GT
2521:                                        .tr(
2522:                                                "Batch entry {0} {1} was aborted.  Call getNextException to see the cause.",
2523:                                                new Object[] {
2524:                                                        new Integer(resultIndex),
2525:                                                        queryString }),
2526:                                successCounts);
2527:                    }
2528:
2529:                    batchException.setNextException(newError);
2530:                }
2531:
2532:                public void handleCompletion() throws SQLException {
2533:                    if (batchException != null)
2534:                        throw batchException;
2535:                }
2536:            }
2537:
2538:            private class CallableBatchResultHandler implements  ResultHandler {
2539:                private BatchUpdateException batchException = null;
2540:                private int resultIndex = 0;
2541:
2542:                private final Query[] queries;
2543:                private final ParameterList[] parameterLists;
2544:                private final int[] updateCounts;
2545:
2546:                CallableBatchResultHandler(Query[] queries,
2547:                        ParameterList[] parameterLists, int[] updateCounts) {
2548:                    this .queries = queries;
2549:                    this .parameterLists = parameterLists;
2550:                    this .updateCounts = updateCounts;
2551:                }
2552:
2553:                public void handleResultRows(Query fromQuery, Field[] fields,
2554:                        Vector tuples, ResultCursor cursor) {
2555:
2556:                }
2557:
2558:                public void handleCommandStatus(String status, int updateCount,
2559:                        long insertOID) {
2560:                    if (resultIndex >= updateCounts.length) {
2561:                        handleError(new PSQLException(GT
2562:                                .tr("Too many update results were returned."),
2563:                                PSQLState.TOO_MANY_RESULTS));
2564:                        return;
2565:                    }
2566:
2567:                    updateCounts[resultIndex++] = updateCount;
2568:                }
2569:
2570:                public void handleWarning(SQLWarning warning) {
2571:                    AbstractJdbc2Statement.this .addWarning(warning);
2572:                }
2573:
2574:                public void handleError(SQLException newError) {
2575:                    if (batchException == null) {
2576:                        int[] successCounts;
2577:
2578:                        if (resultIndex >= updateCounts.length)
2579:                            successCounts = updateCounts;
2580:                        else {
2581:                            successCounts = new int[resultIndex];
2582:                            System.arraycopy(updateCounts, 0, successCounts, 0,
2583:                                    resultIndex);
2584:                        }
2585:
2586:                        String queryString = "<unknown>";
2587:                        if (resultIndex < queries.length)
2588:                            queryString = queries[resultIndex]
2589:                                    .toString(parameterLists[resultIndex]);
2590:
2591:                        batchException = new BatchUpdateException(
2592:                                GT
2593:                                        .tr(
2594:                                                "Batch entry {0} {1} was aborted.  Call getNextException to see the cause.",
2595:                                                new Object[] {
2596:                                                        new Integer(resultIndex),
2597:                                                        queryString }),
2598:                                successCounts);
2599:                    }
2600:
2601:                    batchException.setNextException(newError);
2602:                }
2603:
2604:                public void handleCompletion() throws SQLException {
2605:                    if (batchException != null)
2606:                        throw batchException;
2607:                }
2608:            }
2609:
2610:            public int[] executeBatch() throws SQLException {
2611:                checkClosed();
2612:
2613:                // Every statement execution clears any previous warnings.
2614:                clearWarnings();
2615:
2616:                if (batchStatements == null || batchStatements.isEmpty())
2617:                    return new int[0];
2618:
2619:                int size = batchStatements.size();
2620:                int[] updateCounts = new int[size];
2621:
2622:                // Construct query/parameter arrays.
2623:                Query[] queries = (Query[]) batchStatements
2624:                        .toArray(new Query[batchStatements.size()]);
2625:                ParameterList[] parameterLists = (ParameterList[]) batchParameters
2626:                        .toArray(new ParameterList[batchParameters.size()]);
2627:                batchStatements.clear();
2628:                batchParameters.clear();
2629:
2630:                // Close any existing resultsets associated with this statement.
2631:                while (firstUnclosedResult != null) {
2632:                    if (firstUnclosedResult.getResultSet() != null) {
2633:                        firstUnclosedResult.getResultSet().close();
2634:                    }
2635:                    firstUnclosedResult = firstUnclosedResult.getNext();
2636:                }
2637:
2638:                if (lastSimpleQuery != null) {
2639:                    lastSimpleQuery.close();
2640:                    lastSimpleQuery = null;
2641:                }
2642:
2643:                int flags = QueryExecutor.QUERY_NO_RESULTS;
2644:
2645:                // Only use named statements after we hit the threshold
2646:                if (preparedQuery != null) {
2647:                    m_useCount += queries.length;
2648:                }
2649:                if (m_prepareThreshold == 0 || m_useCount < m_prepareThreshold)
2650:                    flags |= QueryExecutor.QUERY_ONESHOT;
2651:
2652:                if (connection.getAutoCommit())
2653:                    flags |= QueryExecutor.QUERY_SUPPRESS_BEGIN;
2654:
2655:                result = null;
2656:
2657:                ResultHandler handler;
2658:                if (isFunction) {
2659:                    handler = new CallableBatchResultHandler(queries,
2660:                            parameterLists, updateCounts);
2661:                } else {
2662:                    handler = new BatchResultHandler(queries, parameterLists,
2663:                            updateCounts);
2664:                }
2665:
2666:                connection.getQueryExecutor().execute(queries, parameterLists,
2667:                        handler, maxrows, fetchSize, flags);
2668:
2669:                return updateCounts;
2670:            }
2671:
2672:            /*
2673:             * Cancel can be used by one thread to cancel a statement that
2674:             * is being executed by another thread.
2675:             * <p>
2676:             *
2677:             * @exception SQLException only because thats the spec.
2678:             */
2679:            public void cancel() throws SQLException {
2680:                connection.cancelQuery();
2681:            }
2682:
2683:            public Connection getConnection() throws SQLException {
2684:                return (Connection) connection;
2685:            }
2686:
2687:            public int getFetchDirection() {
2688:                return fetchdirection;
2689:            }
2690:
2691:            public int getResultSetConcurrency() {
2692:                return concurrency;
2693:            }
2694:
2695:            public int getResultSetType() {
2696:                return resultsettype;
2697:            }
2698:
2699:            public void setFetchDirection(int direction) throws SQLException {
2700:                switch (direction) {
2701:                case ResultSet.FETCH_FORWARD:
2702:                case ResultSet.FETCH_REVERSE:
2703:                case ResultSet.FETCH_UNKNOWN:
2704:                    fetchdirection = direction;
2705:                    break;
2706:                default:
2707:                    throw new PSQLException(GT.tr(
2708:                            "Invalid fetch direction constant: {0}.",
2709:                            new Integer(direction)),
2710:                            PSQLState.INVALID_PARAMETER_VALUE);
2711:                }
2712:            }
2713:
2714:            public void setFetchSize(int rows) throws SQLException {
2715:                checkClosed();
2716:                if (rows < 0)
2717:                    throw new PSQLException(
2718:                            GT
2719:                                    .tr("Fetch size must be a value greater to or equal to 0."),
2720:                            PSQLState.INVALID_PARAMETER_VALUE);
2721:                fetchSize = rows;
2722:            }
2723:
2724:            public void addBatch() throws SQLException {
2725:                checkClosed();
2726:
2727:                if (batchStatements == null) {
2728:                    batchStatements = new ArrayList();
2729:                    batchParameters = new ArrayList();
2730:                }
2731:
2732:                // we need to create copies of our parameters, otherwise the values can be changed
2733:                batchStatements.add(preparedQuery);
2734:                batchParameters.add(preparedParameters.copy());
2735:            }
2736:
2737:            public ResultSetMetaData getMetaData() throws SQLException {
2738:                checkClosed();
2739:                ResultSet rs = getResultSet();
2740:
2741:                if (rs == null) {
2742:                    // OK, we haven't executed it yet, we've got to go to the backend
2743:                    // for more info.  We send the full query, but just don't
2744:                    // execute it.
2745:
2746:                    int flags = QueryExecutor.QUERY_ONESHOT
2747:                            | QueryExecutor.QUERY_DESCRIBE_ONLY
2748:                            | QueryExecutor.QUERY_SUPPRESS_BEGIN;
2749:                    StatementResultHandler handler = new StatementResultHandler();
2750:                    connection.getQueryExecutor().execute(preparedQuery,
2751:                            preparedParameters, handler, 0, 0, flags);
2752:                    ResultWrapper wrapper = handler.getResults();
2753:                    if (wrapper != null) {
2754:                        rs = wrapper.getResultSet();
2755:                    }
2756:                }
2757:
2758:                if (rs != null)
2759:                    return rs.getMetaData();
2760:
2761:                return null;
2762:            }
2763:
2764:            public void setArray(int i, java.sql.Array x) throws SQLException {
2765:                checkClosed();
2766:
2767:                if (null == x) {
2768:                    setNull(i, Types.ARRAY);
2769:                    return;
2770:                }
2771:
2772:                // This only works for Array implementations that return a valid array
2773:                // literal from Array.toString(), such as the implementation we return
2774:                // from ResultSet.getArray(). Eventually we need a proper implementation
2775:                // here that works for any Array implementation.
2776:
2777:                // Use a typename that is "_" plus the base type; this matches how the
2778:                // backend looks for array types.
2779:                String typename = "_" + x.getBaseTypeName();
2780:                int oid = connection.getPGType(typename);
2781:                if (oid == Oid.UNSPECIFIED)
2782:                    throw new PSQLException(GT
2783:                            .tr("Unknown type {0}.", typename),
2784:                            PSQLState.INVALID_PARAMETER_TYPE);
2785:
2786:                setString(i, x.toString(), oid);
2787:            }
2788:
2789:            public void setBlob(int i, Blob x) throws SQLException {
2790:                checkClosed();
2791:
2792:                if (x == null) {
2793:                    setNull(i, Types.BLOB);
2794:                    return;
2795:                }
2796:
2797:                InputStream l_inStream = x.getBinaryStream();
2798:                LargeObjectManager lom = connection.getLargeObjectAPI();
2799:                long oid = lom.createLO();
2800:                LargeObject lob = lom.open(oid);
2801:                OutputStream los = lob.getOutputStream();
2802:                byte[] buf = new byte[4096];
2803:                try {
2804:                    // could be buffered, but then the OutputStream returned by LargeObject
2805:                    // is buffered internally anyhow, so there would be no performance
2806:                    // boost gained, if anything it would be worse!
2807:                    int bytesRemaining = (int) x.length();
2808:                    int numRead = l_inStream.read(buf, 0, Math.min(buf.length,
2809:                            bytesRemaining));
2810:                    while (numRead != -1 && bytesRemaining > 0) {
2811:                        bytesRemaining -= numRead;
2812:                        if (numRead == buf.length)
2813:                            los.write(buf); // saves a buffer creation and copy in LargeObject since it's full
2814:                        else
2815:                            los.write(buf, 0, numRead);
2816:                        numRead = l_inStream.read(buf, 0, Math.min(buf.length,
2817:                                bytesRemaining));
2818:                    }
2819:                } catch (IOException se) {
2820:                    throw new PSQLException(
2821:                            GT
2822:                                    .tr("Unexpected error writing large object to database."),
2823:                            PSQLState.UNEXPECTED_ERROR, se);
2824:                } finally {
2825:                    try {
2826:                        los.close();
2827:                        l_inStream.close();
2828:                    } catch (Exception e) {
2829:                    }
2830:                }
2831:                setLong(i, oid);
2832:            }
2833:
2834:            public void setCharacterStream(int i, java.io.Reader x, int length)
2835:                    throws SQLException {
2836:                checkClosed();
2837:
2838:                if (x == null) {
2839:                    if (connection.haveMinimumServerVersion("7.2")) {
2840:                        setNull(i, Types.VARCHAR);
2841:                    } else {
2842:                        setNull(i, Types.CLOB);
2843:                    }
2844:                    return;
2845:                }
2846:
2847:                if (length < 0)
2848:                    throw new PSQLException(GT.tr("Invalid stream length {0}.",
2849:                            new Integer(length)),
2850:                            PSQLState.INVALID_PARAMETER_VALUE);
2851:
2852:                if (connection.haveMinimumCompatibleVersion("7.2")) {
2853:                    //Version 7.2 supports CharacterStream for for the PG text types
2854:                    //As the spec/javadoc for this method indicate this is to be used for
2855:                    //large text values (i.e. LONGVARCHAR) PG doesn't have a separate
2856:                    //long varchar datatype, but with toast all the text datatypes are capable of
2857:                    //handling very large values.  Thus the implementation ends up calling
2858:                    //setString() since there is no current way to stream the value to the server
2859:                    char[] l_chars = new char[length];
2860:                    int l_charsRead = 0;
2861:                    try {
2862:                        while (true) {
2863:                            int n = x.read(l_chars, l_charsRead, length
2864:                                    - l_charsRead);
2865:                            if (n == -1)
2866:                                break;
2867:
2868:                            l_charsRead += n;
2869:
2870:                            if (l_charsRead == length)
2871:                                break;
2872:                        }
2873:                    } catch (IOException l_ioe) {
2874:                        throw new PSQLException(GT
2875:                                .tr("Provided Reader failed."),
2876:                                PSQLState.UNEXPECTED_ERROR, l_ioe);
2877:                    }
2878:                    setString(i, new String(l_chars, 0, l_charsRead));
2879:                } else {
2880:                    //Version 7.1 only supported streams for LargeObjects
2881:                    //but the jdbc spec indicates that streams should be
2882:                    //available for LONGVARCHAR instead
2883:                    LargeObjectManager lom = connection.getLargeObjectAPI();
2884:                    long oid = lom.createLO();
2885:                    LargeObject lob = lom.open(oid);
2886:                    OutputStream los = lob.getOutputStream();
2887:                    try {
2888:                        // could be buffered, but then the OutputStream returned by LargeObject
2889:                        // is buffered internally anyhow, so there would be no performance
2890:                        // boost gained, if anything it would be worse!
2891:                        int c = x.read();
2892:                        int p = 0;
2893:                        while (c > -1 && p < length) {
2894:                            los.write(c);
2895:                            c = x.read();
2896:                            p++;
2897:                        }
2898:                        los.close();
2899:                    } catch (IOException se) {
2900:                        throw new PSQLException(
2901:                                GT
2902:                                        .tr("Unexpected error writing large object to database."),
2903:                                PSQLState.UNEXPECTED_ERROR, se);
2904:                    }
2905:                    // lob is closed by the stream so don't call lob.close()
2906:                    setLong(i, oid);
2907:                }
2908:            }
2909:
2910:            public void setClob(int i, Clob x) throws SQLException {
2911:                checkClosed();
2912:
2913:                if (x == null) {
2914:                    setNull(i, Types.CLOB);
2915:                    return;
2916:                }
2917:
2918:                InputStream l_inStream = x.getAsciiStream();
2919:                int l_length = (int) x.length();
2920:                LargeObjectManager lom = connection.getLargeObjectAPI();
2921:                long oid = lom.createLO();
2922:                LargeObject lob = lom.open(oid);
2923:                OutputStream los = lob.getOutputStream();
2924:                try {
2925:                    // could be buffered, but then the OutputStream returned by LargeObject
2926:                    // is buffered internally anyhow, so there would be no performance
2927:                    // boost gained, if anything it would be worse!
2928:                    int c = l_inStream.read();
2929:                    int p = 0;
2930:                    while (c > -1 && p < l_length) {
2931:                        los.write(c);
2932:                        c = l_inStream.read();
2933:                        p++;
2934:                    }
2935:                    los.close();
2936:                } catch (IOException se) {
2937:                    throw new PSQLException(
2938:                            GT
2939:                                    .tr("Unexpected error writing large object to database."),
2940:                            PSQLState.UNEXPECTED_ERROR, se);
2941:                }
2942:                // lob is closed by the stream so don't call lob.close()
2943:                setLong(i, oid);
2944:            }
2945:
2946:            public void setNull(int i, int t, String s) throws SQLException {
2947:                checkClosed();
2948:                setNull(i, t);
2949:            }
2950:
2951:            public void setRef(int i, Ref x) throws SQLException {
2952:                throw Driver.notImplemented(this .getClass(), "setRef(int,Ref)");
2953:            }
2954:
2955:            public void setDate(int i, java.sql.Date d, java.util.Calendar cal)
2956:                    throws SQLException {
2957:                checkClosed();
2958:
2959:                if (d == null) {
2960:                    setNull(i, Types.DATE);
2961:                    return;
2962:                }
2963:
2964:                if (cal != null)
2965:                    cal = (Calendar) cal.clone();
2966:
2967:                // We must use UNSPECIFIED here, or inserting a Date-with-timezone into a
2968:                // timestamptz field does an unexpected rotation by the server's TimeZone:
2969:                //
2970:                // We want to interpret 2005/01/01 with calendar +0100 as
2971:                // "local midnight in +0100", but if we go via date it interprets it
2972:                // as local midnight in the server's timezone:
2973:
2974:                // template1=# select '2005-01-01+0100'::timestamptz;
2975:                //       timestamptz       
2976:                // ------------------------
2977:                //  2005-01-01 02:00:00+03
2978:                // (1 row)
2979:
2980:                // template1=# select '2005-01-01+0100'::date::timestamptz;
2981:                //       timestamptz       
2982:                // ------------------------
2983:                //  2005-01-01 00:00:00+03
2984:                // (1 row)
2985:
2986:                bindString(i, connection.getTimestampUtils().toString(cal, d),
2987:                        Oid.UNSPECIFIED);
2988:            }
2989:
2990:            public void setTime(int i, Time t, java.util.Calendar cal)
2991:                    throws SQLException {
2992:                checkClosed();
2993:
2994:                if (t == null) {
2995:                    setNull(i, Types.TIME);
2996:                    return;
2997:                }
2998:
2999:                if (cal != null)
3000:                    cal = (Calendar) cal.clone();
3001:
3002:                bindString(i, connection.getTimestampUtils().toString(cal, t),
3003:                        Oid.UNSPECIFIED);
3004:            }
3005:
3006:            public void setTimestamp(int i, Timestamp t, java.util.Calendar cal)
3007:                    throws SQLException {
3008:                checkClosed();
3009:
3010:                if (t == null) {
3011:                    setNull(i, Types.TIMESTAMP);
3012:                    return;
3013:                }
3014:
3015:                if (cal != null)
3016:                    cal = (Calendar) cal.clone();
3017:
3018:                // Use UNSPECIFIED as a compromise to get both TIMESTAMP and TIMESTAMPTZ working.
3019:                // This is because you get this in a +1300 timezone:
3020:                // 
3021:                // template1=# select '2005-01-01 15:00:00 +1000'::timestamptz;
3022:                //       timestamptz       
3023:                // ------------------------
3024:                //  2005-01-01 18:00:00+13
3025:                // (1 row)
3026:
3027:                // template1=# select '2005-01-01 15:00:00 +1000'::timestamp;
3028:                //       timestamp      
3029:                // ---------------------
3030:                //  2005-01-01 15:00:00
3031:                // (1 row)        
3032:
3033:                // template1=# select '2005-01-01 15:00:00 +1000'::timestamptz::timestamp;
3034:                //       timestamp      
3035:                // ---------------------
3036:                //  2005-01-01 18:00:00
3037:                // (1 row)
3038:
3039:                // So we want to avoid doing a timestamptz -> timestamp conversion, as that
3040:                // will first convert the timestamptz to an equivalent time in the server's
3041:                // timezone (+1300, above), then turn it into a timestamp with the "wrong"
3042:                // time compared to the string we originally provided. But going straight
3043:                // to timestamp is OK as the input parser for timestamp just throws away
3044:                // the timezone part entirely. Since we don't know ahead of time what type
3045:                // we're actually dealing with, UNSPECIFIED seems the lesser evil, even if it
3046:                // does give more scope for type-mismatch errors being silently hidden.
3047:
3048:                bindString(i, connection.getTimestampUtils().toString(cal, t),
3049:                        Oid.UNSPECIFIED); // Let the server infer the right type.
3050:            }
3051:
3052:            // ** JDBC 2 Extensions for CallableStatement**
3053:
3054:            public java.sql.Array getArray(int i) throws SQLException {
3055:                checkClosed();
3056:                checkIndex(i, Types.ARRAY, "Array");
3057:                return (Array) callResult[i - 1];
3058:            }
3059:
3060:            public java.math.BigDecimal getBigDecimal(int parameterIndex)
3061:                    throws SQLException {
3062:                checkClosed();
3063:                checkIndex(parameterIndex, Types.NUMERIC, "BigDecimal");
3064:                return ((BigDecimal) callResult[parameterIndex - 1]);
3065:            }
3066:
3067:            public Blob getBlob(int i) throws SQLException {
3068:                throw Driver.notImplemented(this .getClass(), "getBlob(int)");
3069:            }
3070:
3071:            public Clob getClob(int i) throws SQLException {
3072:                throw Driver.notImplemented(this .getClass(), "getClob(int)");
3073:            }
3074:
3075:            public Object getObjectImpl(int i, java.util.Map map)
3076:                    throws SQLException {
3077:                if (map == null || map.isEmpty()) {
3078:                    return getObject(i);
3079:                }
3080:                throw Driver.notImplemented(this .getClass(),
3081:                        "getObjectImpl(int,Map)");
3082:            }
3083:
3084:            public Ref getRef(int i) throws SQLException {
3085:                throw Driver.notImplemented(this .getClass(), "getRef(int)");
3086:            }
3087:
3088:            public java.sql.Date getDate(int i, java.util.Calendar cal)
3089:                    throws SQLException {
3090:                checkClosed();
3091:                checkIndex(i, Types.DATE, "Date");
3092:
3093:                if (callResult[i - 1] == null)
3094:                    return null;
3095:
3096:                if (cal != null)
3097:                    cal = (Calendar) cal.clone();
3098:
3099:                String value = callResult[i - 1].toString();
3100:                return connection.getTimestampUtils().toDate(cal, value);
3101:            }
3102:
3103:            public Time getTime(int i, java.util.Calendar cal)
3104:                    throws SQLException {
3105:                checkClosed();
3106:                checkIndex(i, Types.TIME, "Time");
3107:
3108:                if (callResult[i - 1] == null)
3109:                    return null;
3110:
3111:                if (cal != null)
3112:                    cal = (Calendar) cal.clone();
3113:
3114:                String value = callResult[i - 1].toString();
3115:                return connection.getTimestampUtils().toTime(cal, value);
3116:            }
3117:
3118:            public Timestamp getTimestamp(int i, java.util.Calendar cal)
3119:                    throws SQLException {
3120:                checkClosed();
3121:                checkIndex(i, Types.TIMESTAMP, "Timestamp");
3122:
3123:                if (callResult[i - 1] == null)
3124:                    return null;
3125:
3126:                if (cal != null)
3127:                    cal = (Calendar) cal.clone();
3128:
3129:                String value = callResult[i - 1].toString();
3130:                return connection.getTimestampUtils().toTimestamp(cal, value);
3131:            }
3132:
3133:            // no custom types allowed yet..
3134:            public void registerOutParameter(int parameterIndex, int sqlType,
3135:                    String typeName) throws SQLException {
3136:                throw Driver.notImplemented(this .getClass(),
3137:                        "registerOutParameter(int,int,String)");
3138:            }
3139:
3140:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.