Source Code Cross Referenced for AbstractJdbc2Connection.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/AbstractJdbc2Connection.java,v 1.43 2007/07/27 10:15:32 jurka Exp $
0007:         *
0008:         *-------------------------------------------------------------------------
0009:         */
0010:        package org.postgresql.jdbc2;
0011:
0012:        import java.io.IOException;
0013:        import java.io.PrintWriter;
0014:        import java.sql.*;
0015:        import java.util.*;
0016:        import org.postgresql.core.*;
0017:        import org.postgresql.Driver;
0018:        import org.postgresql.PGNotification;
0019:        import org.postgresql.fastpath.Fastpath;
0020:        import org.postgresql.largeobject.LargeObjectManager;
0021:        import org.postgresql.util.PSQLState;
0022:        import org.postgresql.util.PGobject;
0023:        import org.postgresql.util.PSQLException;
0024:        import org.postgresql.util.GT;
0025:
0026:        /**
0027:         * This class defines methods of the jdbc2 specification.
0028:         * The real Connection class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Connection
0029:         */
0030:        public abstract class AbstractJdbc2Connection implements  BaseConnection {
0031:            //
0032:            // Driver-wide connection ID counter, used for logging
0033:            //
0034:            private static int nextConnectionID = 1;
0035:
0036:            //
0037:            // Data initialized on construction:
0038:            //
0039:
0040:            // Per-connection logger
0041:            private final Logger logger;
0042:
0043:            /* URL we were created via */
0044:            private final String creatingURL;
0045:
0046:            private Throwable openStackTrace;
0047:
0048:            /* Actual network handler */
0049:            private final ProtocolConnection protoConnection;
0050:            /* Compatibility version */
0051:            private final String compatible;
0052:            /* Actual server version */
0053:            private final String dbVersionNumber;
0054:
0055:            /* Query that runs COMMIT */
0056:            private final Query commitQuery;
0057:            /* Query that runs ROLLBACK */
0058:            private final Query rollbackQuery;
0059:
0060:            private TypeInfoCache _typeCache;
0061:
0062:            // Default statement prepare threshold.
0063:            protected int prepareThreshold;
0064:            // Connection's autocommit state.
0065:            public boolean autoCommit = true;
0066:            // Connection's readonly state.
0067:            public boolean readOnly = false;
0068:
0069:            // Bind String to UNSPECIFIED or VARCHAR?
0070:            public final boolean bindStringAsVarchar;
0071:
0072:            // Current warnings; there might be more on protoConnection too.
0073:            public SQLWarning firstWarning = null;
0074:
0075:            public abstract DatabaseMetaData getMetaData() throws SQLException;
0076:
0077:            //
0078:            // Ctor.
0079:            //
0080:            protected AbstractJdbc2Connection(String host, int port,
0081:                    String user, String database, Properties info, String url)
0082:                    throws SQLException {
0083:                this .creatingURL = url;
0084:
0085:                // Read loglevel arg and set the loglevel based on this value;
0086:                // In addition to setting the log level, enable output to
0087:                // standard out if no other printwriter is set
0088:
0089:                int logLevel = Driver.getLogLevel();
0090:                String connectionLogLevel = info.getProperty("loglevel");
0091:                if (connectionLogLevel != null) {
0092:                    try {
0093:                        logLevel = Integer.parseInt(connectionLogLevel);
0094:                    } catch (Exception l_e) {
0095:                        // XXX revisit
0096:                        // invalid value for loglevel; ignore it
0097:                    }
0098:                }
0099:
0100:                synchronized (AbstractJdbc2Connection.class) {
0101:                    logger = new Logger(nextConnectionID++);
0102:                    logger.setLogLevel(logLevel);
0103:                }
0104:
0105:                if (logLevel > 0)
0106:                    enableDriverManagerLogging();
0107:
0108:                prepareThreshold = 5;
0109:                try {
0110:                    prepareThreshold = Integer.parseInt(info.getProperty(
0111:                            "prepareThreshold", "5"));
0112:                    if (prepareThreshold < 0)
0113:                        prepareThreshold = 0;
0114:                } catch (Exception e) {
0115:                }
0116:
0117:                //Print out the driver version number
0118:                if (logger.logInfo())
0119:                    logger.info(Driver.getVersion());
0120:
0121:                // Now make the initial connection and set up local state
0122:                this .protoConnection = ConnectionFactory.openConnection(host,
0123:                        port, user, database, info, logger);
0124:                this .dbVersionNumber = protoConnection.getServerVersion();
0125:                this .compatible = info.getProperty("compatible",
0126:                        Driver.MAJORVERSION + "." + Driver.MINORVERSION);
0127:
0128:                if (logger.logDebug()) {
0129:                    logger.debug("    compatible = " + compatible);
0130:                    logger.debug("    loglevel = " + logLevel);
0131:                    logger.debug("    prepare threshold = " + prepareThreshold);
0132:                }
0133:
0134:                //
0135:                // String -> text or unknown?
0136:                //
0137:
0138:                String stringType = info.getProperty("stringtype");
0139:                if (stringType != null) {
0140:                    if (stringType.equalsIgnoreCase("unspecified"))
0141:                        bindStringAsVarchar = false;
0142:                    else if (stringType.equalsIgnoreCase("varchar"))
0143:                        bindStringAsVarchar = true;
0144:                    else
0145:                        throw new PSQLException(
0146:                                GT
0147:                                        .tr(
0148:                                                "Unsupported value for stringtype parameter: {0}",
0149:                                                stringType),
0150:                                PSQLState.INVALID_PARAMETER_VALUE);
0151:                } else {
0152:                    bindStringAsVarchar = haveMinimumCompatibleVersion("8.0");
0153:                }
0154:
0155:                // Initialize timestamp stuff
0156:                timestampUtils = new TimestampUtils(
0157:                        haveMinimumServerVersion("7.4"),
0158:                        haveMinimumServerVersion("8.2"));
0159:
0160:                // Initialize common queries.
0161:                commitQuery = getQueryExecutor().createSimpleQuery("COMMIT");
0162:                rollbackQuery = getQueryExecutor()
0163:                        .createSimpleQuery("ROLLBACK");
0164:
0165:                // Initialize object handling
0166:                _typeCache = new TypeInfoCache(this );
0167:                initObjectTypes(info);
0168:
0169:                if (Boolean.valueOf(info.getProperty("logUnclosedConnections"))
0170:                        .booleanValue()) {
0171:                    openStackTrace = new Throwable(
0172:                            "Connection was created at this point:");
0173:                    enableDriverManagerLogging();
0174:                }
0175:            }
0176:
0177:            private final TimestampUtils timestampUtils;
0178:
0179:            public TimestampUtils getTimestampUtils() {
0180:                return timestampUtils;
0181:            }
0182:
0183:            /*
0184:             * The current type mappings
0185:             */
0186:            protected java.util.Map typemap;
0187:
0188:            public java.sql.Statement createStatement() throws SQLException {
0189:                // We now follow the spec and default to TYPE_FORWARD_ONLY.
0190:                return createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
0191:                        java.sql.ResultSet.CONCUR_READ_ONLY);
0192:            }
0193:
0194:            public abstract java.sql.Statement createStatement(
0195:                    int resultSetType, int resultSetConcurrency)
0196:                    throws SQLException;
0197:
0198:            public java.sql.PreparedStatement prepareStatement(String sql)
0199:                    throws SQLException {
0200:                return prepareStatement(sql,
0201:                        java.sql.ResultSet.TYPE_FORWARD_ONLY,
0202:                        java.sql.ResultSet.CONCUR_READ_ONLY);
0203:            }
0204:
0205:            public abstract java.sql.PreparedStatement prepareStatement(
0206:                    String sql, int resultSetType, int resultSetConcurrency)
0207:                    throws SQLException;
0208:
0209:            public java.sql.CallableStatement prepareCall(String sql)
0210:                    throws SQLException {
0211:                return prepareCall(sql, java.sql.ResultSet.TYPE_FORWARD_ONLY,
0212:                        java.sql.ResultSet.CONCUR_READ_ONLY);
0213:            }
0214:
0215:            public abstract java.sql.CallableStatement prepareCall(String sql,
0216:                    int resultSetType, int resultSetConcurrency)
0217:                    throws SQLException;
0218:
0219:            public java.util.Map getTypeMap() throws SQLException {
0220:                return typemap;
0221:            }
0222:
0223:            // Query executor associated with this connection.
0224:            public QueryExecutor getQueryExecutor() {
0225:                return protoConnection.getQueryExecutor();
0226:            }
0227:
0228:            /*
0229:             * This adds a warning to the warning chain.
0230:             * @param warn warning to add
0231:             */
0232:            public void addWarning(SQLWarning warn) {
0233:                // Add the warning to the chain
0234:                if (firstWarning != null)
0235:                    firstWarning.setNextWarning(warn);
0236:                else
0237:                    firstWarning = warn;
0238:
0239:            }
0240:
0241:            public ResultSet execSQLQuery(String s) throws SQLException {
0242:                return execSQLQuery(s, ResultSet.TYPE_FORWARD_ONLY,
0243:                        ResultSet.CONCUR_READ_ONLY);
0244:            }
0245:
0246:            /**
0247:             * Simple query execution.
0248:             */
0249:            public ResultSet execSQLQuery(String s, int resultSetType,
0250:                    int resultSetConcurrency) throws SQLException {
0251:                BaseStatement stat = (BaseStatement) createStatement(
0252:                        resultSetType, resultSetConcurrency);
0253:                boolean hasResultSet = stat.executeWithFlags(s,
0254:                        QueryExecutor.QUERY_SUPPRESS_BEGIN);
0255:
0256:                while (!hasResultSet && stat.getUpdateCount() != -1)
0257:                    hasResultSet = stat.getMoreResults();
0258:
0259:                if (!hasResultSet)
0260:                    throw new PSQLException(GT
0261:                            .tr("No results were returned by the query."),
0262:                            PSQLState.NO_DATA);
0263:
0264:                // Transfer warnings to the connection, since the user never
0265:                // has a chance to see the statement itself.
0266:                SQLWarning warnings = stat.getWarnings();
0267:                if (warnings != null)
0268:                    addWarning(warnings);
0269:
0270:                return stat.getResultSet();
0271:            }
0272:
0273:            public void execSQLUpdate(String s) throws SQLException {
0274:                BaseStatement stmt = (BaseStatement) createStatement();
0275:                if (stmt.executeWithFlags(s, QueryExecutor.QUERY_NO_METADATA
0276:                        | QueryExecutor.QUERY_NO_RESULTS
0277:                        | QueryExecutor.QUERY_SUPPRESS_BEGIN))
0278:                    throw new PSQLException(
0279:                            GT
0280:                                    .tr("A result was returned when none was expected."),
0281:                            PSQLState.TOO_MANY_RESULTS);
0282:
0283:                // Transfer warnings to the connection, since the user never
0284:                // has a chance to see the statement itself.
0285:                SQLWarning warnings = stmt.getWarnings();
0286:                if (warnings != null)
0287:                    addWarning(warnings);
0288:
0289:                stmt.close();
0290:            }
0291:
0292:            /*
0293:             * In SQL, a result table can be retrieved through a cursor that
0294:             * is named.  The current row of a result can be updated or deleted
0295:             * using a positioned update/delete statement that references the
0296:             * cursor name.
0297:             *
0298:             * We do not support positioned update/delete, so this is a no-op.
0299:             *
0300:             * @param cursor the cursor name
0301:             * @exception SQLException if a database access error occurs
0302:             */
0303:            public void setCursorName(String cursor) throws SQLException {
0304:                // No-op.
0305:            }
0306:
0307:            /*
0308:             * getCursorName gets the cursor name.
0309:             *
0310:             * @return the current cursor name
0311:             * @exception SQLException if a database access error occurs
0312:             */
0313:            public String getCursorName() throws SQLException {
0314:                return null;
0315:            }
0316:
0317:            /*
0318:             * We are required to bring back certain information by
0319:             * the DatabaseMetaData class. These functions do that.
0320:             *
0321:             * Method getURL() brings back the URL (good job we saved it)
0322:             *
0323:             * @return the url
0324:             * @exception SQLException just in case...
0325:             */
0326:            public String getURL() throws SQLException {
0327:                return creatingURL;
0328:            }
0329:
0330:            /*
0331:             * Method getUserName() brings back the User Name (again, we
0332:             * saved it)
0333:             *
0334:             * @return the user name
0335:             * @exception SQLException just in case...
0336:             */
0337:            public String getUserName() throws SQLException {
0338:                return protoConnection.getUser();
0339:            }
0340:
0341:            /*
0342:             * This returns the Fastpath API for the current connection.
0343:             *
0344:             * <p><b>NOTE:</b> This is not part of JDBC, but allows access to
0345:             * functions on the org.postgresql backend itself.
0346:             *
0347:             * <p>It is primarily used by the LargeObject API
0348:             *
0349:             * <p>The best way to use this is as follows:
0350:             *
0351:             * <p><pre>
0352:             * import org.postgresql.fastpath.*;
0353:             * ...
0354:             * Fastpath fp = ((org.postgresql.Connection)myconn).getFastpathAPI();
0355:             * </pre>
0356:             *
0357:             * <p>where myconn is an open Connection to org.postgresql.
0358:             *
0359:             * @return Fastpath object allowing access to functions on the org.postgresql
0360:             * backend.
0361:             * @exception SQLException by Fastpath when initialising for first time
0362:             */
0363:            public Fastpath getFastpathAPI() throws SQLException {
0364:                if (fastpath == null)
0365:                    fastpath = new Fastpath(this );
0366:                return fastpath;
0367:            }
0368:
0369:            // This holds a reference to the Fastpath API if already open
0370:            private Fastpath fastpath = null;
0371:
0372:            /*
0373:             * This returns the LargeObject API for the current connection.
0374:             *
0375:             * <p><b>NOTE:</b> This is not part of JDBC, but allows access to
0376:             * functions on the org.postgresql backend itself.
0377:             *
0378:             * <p>The best way to use this is as follows:
0379:             *
0380:             * <p><pre>
0381:             * import org.postgresql.largeobject.*;
0382:             * ...
0383:             * LargeObjectManager lo = ((org.postgresql.Connection)myconn).getLargeObjectAPI();
0384:             * </pre>
0385:             *
0386:             * <p>where myconn is an open Connection to org.postgresql.
0387:             *
0388:             * @return LargeObject object that implements the API
0389:             * @exception SQLException by LargeObject when initialising for first time
0390:             */
0391:            public LargeObjectManager getLargeObjectAPI() throws SQLException {
0392:                if (largeobject == null)
0393:                    largeobject = new LargeObjectManager(this );
0394:                return largeobject;
0395:            }
0396:
0397:            // This holds a reference to the LargeObject API if already open
0398:            private LargeObjectManager largeobject = null;
0399:
0400:            /*
0401:             * This method is used internally to return an object based around
0402:             * org.postgresql's more unique data types.
0403:             *
0404:             * <p>It uses an internal Hashtable to get the handling class. If the
0405:             * type is not supported, then an instance of org.postgresql.util.PGobject
0406:             * is returned.
0407:             *
0408:             * You can use the getValue() or setValue() methods to handle the returned
0409:             * object. Custom objects can have their own methods.
0410:             *
0411:             * @return PGobject for this type, and set to value
0412:             * @exception SQLException if value is not correct for this type
0413:             */
0414:            public Object getObject(String type, String value)
0415:                    throws SQLException {
0416:                if (typemap != null) {
0417:                    SQLData d = (SQLData) typemap.get(type);
0418:                    if (d != null) {
0419:                        // Handle the type (requires SQLInput & SQLOutput classes to be implemented)
0420:                        if (logger.logDebug())
0421:                            logger
0422:                                    .debug("getObject(String,String) with custom typemap");
0423:                        throw org.postgresql.Driver.notImplemented(this 
0424:                                .getClass(), "getObject(String,String)");
0425:                    }
0426:                }
0427:
0428:                PGobject obj = null;
0429:
0430:                if (logger.logDebug())
0431:                    logger.debug("Constructing object from type=" + type
0432:                            + " value=<" + value + ">");
0433:
0434:                try {
0435:                    Class klass = _typeCache.getPGobject(type);
0436:
0437:                    // If className is not null, then try to instantiate it,
0438:                    // It must be basetype PGobject
0439:
0440:                    // This is used to implement the org.postgresql unique types (like lseg,
0441:                    // point, etc).
0442:
0443:                    if (klass != null) {
0444:                        obj = (PGobject) (klass.newInstance());
0445:                        obj.setType(type);
0446:                        obj.setValue(value);
0447:                    } else {
0448:                        // If className is null, then the type is unknown.
0449:                        // so return a PGobject with the type set, and the value set
0450:                        obj = new PGobject();
0451:                        obj.setType(type);
0452:                        obj.setValue(value);
0453:                    }
0454:
0455:                    return obj;
0456:                } catch (SQLException sx) {
0457:                    // rethrow the exception. Done because we capture any others next
0458:                    throw sx;
0459:                } catch (Exception ex) {
0460:                    throw new PSQLException(GT.tr(
0461:                            "Failed to create object for: {0}.", type),
0462:                            PSQLState.CONNECTION_FAILURE, ex);
0463:                }
0464:            }
0465:
0466:            public void addDataType(String type, String name) {
0467:                try {
0468:                    addDataType(type, Class.forName(name));
0469:                } catch (Exception e) {
0470:                    throw new RuntimeException("Cannot register new type: " + e);
0471:                }
0472:            }
0473:
0474:            public void addDataType(String type, Class klass)
0475:                    throws SQLException {
0476:                _typeCache.addDataType(type, klass);
0477:            }
0478:
0479:            // This initialises the objectTypes hashtable
0480:            private void initObjectTypes(Properties info) throws SQLException {
0481:                // Add in the types that come packaged with the driver.
0482:                // These can be overridden later if desired.
0483:                addDataType("box", org.postgresql.geometric.PGbox.class);
0484:                addDataType("circle", org.postgresql.geometric.PGcircle.class);
0485:                addDataType("line", org.postgresql.geometric.PGline.class);
0486:                addDataType("lseg", org.postgresql.geometric.PGlseg.class);
0487:                addDataType("path", org.postgresql.geometric.PGpath.class);
0488:                addDataType("point", org.postgresql.geometric.PGpoint.class);
0489:                addDataType("polygon", org.postgresql.geometric.PGpolygon.class);
0490:                addDataType("money", org.postgresql.util.PGmoney.class);
0491:                addDataType("interval", org.postgresql.util.PGInterval.class);
0492:
0493:                for (Enumeration e = info.propertyNames(); e.hasMoreElements();) {
0494:                    String propertyName = (String) e.nextElement();
0495:                    if (propertyName.startsWith("datatype.")) {
0496:                        String typeName = propertyName.substring(9);
0497:                        String className = info.getProperty(propertyName);
0498:                        Class klass;
0499:
0500:                        try {
0501:                            klass = Class.forName(className);
0502:                        } catch (ClassNotFoundException cnfe) {
0503:                            throw new PSQLException(
0504:                                    GT
0505:                                            .tr(
0506:                                                    "Unable to load the class {0} responsible for the datatype {1}",
0507:                                                    new Object[] { className,
0508:                                                            typeName }),
0509:                                    PSQLState.SYSTEM_ERROR, cnfe);
0510:                        }
0511:
0512:                        addDataType(typeName, klass);
0513:                    }
0514:                }
0515:            }
0516:
0517:            /**
0518:             * In some cases, it is desirable to immediately release a Connection's
0519:             * database and JDBC resources instead of waiting for them to be
0520:             * automatically released.
0521:             *
0522:             * <B>Note:</B> A Connection is automatically closed when it is
0523:             * garbage collected.  Certain fatal errors also result in a closed
0524:             * connection.
0525:             *
0526:             * @exception SQLException if a database access error occurs
0527:             */
0528:            public void close() {
0529:                protoConnection.close();
0530:                openStackTrace = null;
0531:            }
0532:
0533:            /*
0534:             * A driver may convert the JDBC sql grammar into its system's
0535:             * native SQL grammar prior to sending it; nativeSQL returns the
0536:             * native form of the statement that the driver would have sent.
0537:             *
0538:             * @param sql a SQL statement that may contain one or more '?'
0539:             * parameter placeholders
0540:             * @return the native form of this statement
0541:             * @exception SQLException if a database access error occurs
0542:             */
0543:            public String nativeSQL(String sql) throws SQLException {
0544:                StringBuffer buf = new StringBuffer(sql.length());
0545:                AbstractJdbc2Statement.parseSql(sql, 0, buf, false,
0546:                        getStandardConformingStrings());
0547:                return buf.toString();
0548:            }
0549:
0550:            /*
0551:             * The first warning reported by calls on this Connection is
0552:             * returned.
0553:             *
0554:             * <B>Note:</B> Sebsequent warnings will be changed to this
0555:             * SQLWarning
0556:             *
0557:             * @return the first SQLWarning or null
0558:             * @exception SQLException if a database access error occurs
0559:             */
0560:            public synchronized SQLWarning getWarnings() throws SQLException {
0561:                SQLWarning newWarnings = protoConnection.getWarnings(); // NB: also clears them.
0562:                if (firstWarning == null)
0563:                    firstWarning = newWarnings;
0564:                else
0565:                    firstWarning.setNextWarning(newWarnings); // Chain them on.
0566:
0567:                return firstWarning;
0568:            }
0569:
0570:            /*
0571:             * After this call, getWarnings returns null until a new warning
0572:             * is reported for this connection.
0573:             *
0574:             * @exception SQLException if a database access error occurs
0575:             */
0576:            public synchronized void clearWarnings() throws SQLException {
0577:                protoConnection.getWarnings(); // Clear and discard.
0578:                firstWarning = null;
0579:            }
0580:
0581:            /*
0582:             * You can put a connection in read-only mode as a hunt to enable
0583:             * database optimizations
0584:             *
0585:             * <B>Note:</B> setReadOnly cannot be called while in the middle
0586:             * of a transaction
0587:             *
0588:             * @param readOnly - true enables read-only mode; false disables it
0589:             * @exception SQLException if a database access error occurs
0590:             */
0591:            public void setReadOnly(boolean readOnly) throws SQLException {
0592:                if (protoConnection.getTransactionState() != ProtocolConnection.TRANSACTION_IDLE)
0593:                    throw new PSQLException(
0594:                            GT
0595:                                    .tr("Cannot change transaction read-only property in the middle of a transaction."),
0596:                            PSQLState.ACTIVE_SQL_TRANSACTION);
0597:
0598:                if (haveMinimumServerVersion("7.4")
0599:                        && readOnly != this .readOnly) {
0600:                    String readOnlySql = "SET SESSION CHARACTERISTICS AS TRANSACTION "
0601:                            + (readOnly ? "READ ONLY" : "READ WRITE");
0602:                    execSQLUpdate(readOnlySql); // nb: no BEGIN triggered.
0603:                }
0604:
0605:                this .readOnly = readOnly;
0606:            }
0607:
0608:            /*
0609:             * Tests to see if the connection is in Read Only Mode.
0610:             *
0611:             * @return true if the connection is read only
0612:             * @exception SQLException if a database access error occurs
0613:             */
0614:            public boolean isReadOnly() throws SQLException {
0615:                return readOnly;
0616:            }
0617:
0618:            /*
0619:             * If a connection is in auto-commit mode, than all its SQL
0620:             * statements will be executed and committed as individual
0621:             * transactions.  Otherwise, its SQL statements are grouped
0622:             * into transactions that are terminated by either commit()
0623:             * or rollback().  By default, new connections are in auto-
0624:             * commit mode.  The commit occurs when the statement completes
0625:             * or the next execute occurs, whichever comes first.  In the
0626:             * case of statements returning a ResultSet, the statement
0627:             * completes when the last row of the ResultSet has been retrieved
0628:             * or the ResultSet has been closed.  In advanced cases, a single
0629:             * statement may return multiple results as well as output parameter
0630:             * values. Here the commit occurs when all results and output param
0631:             * values have been retrieved.
0632:             *
0633:             * @param autoCommit - true enables auto-commit; false disables it
0634:             * @exception SQLException if a database access error occurs
0635:             */
0636:            public void setAutoCommit(boolean autoCommit) throws SQLException {
0637:                if (this .autoCommit == autoCommit)
0638:                    return;
0639:
0640:                if (!this .autoCommit)
0641:                    commit();
0642:
0643:                this .autoCommit = autoCommit;
0644:            }
0645:
0646:            /*
0647:             * gets the current auto-commit state
0648:             *
0649:             * @return Current state of the auto-commit mode
0650:             * @see setAutoCommit
0651:             */
0652:            public boolean getAutoCommit() {
0653:                return this .autoCommit;
0654:            }
0655:
0656:            private void executeTransactionCommand(Query query)
0657:                    throws SQLException {
0658:                getQueryExecutor().execute(
0659:                        query,
0660:                        null,
0661:                        new TransactionCommandHandler(),
0662:                        0,
0663:                        0,
0664:                        QueryExecutor.QUERY_NO_METADATA
0665:                                | QueryExecutor.QUERY_NO_RESULTS
0666:                                | QueryExecutor.QUERY_SUPPRESS_BEGIN);
0667:            }
0668:
0669:            /*
0670:             * The method commit() makes all changes made since the previous
0671:             * commit/rollback permanent and releases any database locks currently
0672:             * held by the Connection. This method should only be used when
0673:             * auto-commit has been disabled.  (If autoCommit == true, then we
0674:             * just return anyhow)
0675:             *
0676:             * @exception SQLException if a database access error occurs
0677:             * @see setAutoCommit
0678:             */
0679:            public void commit() throws SQLException {
0680:                if (autoCommit)
0681:                    return;
0682:
0683:                if (protoConnection.getTransactionState() != ProtocolConnection.TRANSACTION_IDLE)
0684:                    executeTransactionCommand(commitQuery);
0685:            }
0686:
0687:            /*
0688:             * The method rollback() drops all changes made since the previous
0689:             * commit/rollback and releases any database locks currently held by
0690:             * the Connection.
0691:             *
0692:             * @exception SQLException if a database access error occurs
0693:             * @see commit
0694:             */
0695:            public void rollback() throws SQLException {
0696:                if (autoCommit)
0697:                    return;
0698:
0699:                if (protoConnection.getTransactionState() != ProtocolConnection.TRANSACTION_IDLE)
0700:                    executeTransactionCommand(rollbackQuery);
0701:            }
0702:
0703:            /*
0704:             * Get this Connection's current transaction isolation mode.
0705:             *
0706:             * @return the current TRANSACTION_* mode value
0707:             * @exception SQLException if a database access error occurs
0708:             */
0709:            public int getTransactionIsolation() throws SQLException {
0710:                String level = null;
0711:
0712:                if (haveMinimumServerVersion("7.3")) {
0713:                    // 7.3+ returns the level as a query result.
0714:                    ResultSet rs = execSQLQuery("SHOW TRANSACTION ISOLATION LEVEL"); // nb: no BEGIN triggered
0715:                    if (rs.next())
0716:                        level = rs.getString(1);
0717:                    rs.close();
0718:                } else {
0719:                    // 7.2 returns the level as an INFO message. Ew.
0720:                    // We juggle the warning chains a bit here.
0721:
0722:                    // Swap out current warnings.
0723:                    SQLWarning saveWarnings = getWarnings();
0724:                    clearWarnings();
0725:
0726:                    // Run the query any examine any resulting warnings.
0727:                    execSQLUpdate("SHOW TRANSACTION ISOLATION LEVEL"); // nb: no BEGIN triggered
0728:                    SQLWarning warning = getWarnings();
0729:                    if (warning != null)
0730:                        level = warning.getMessage();
0731:
0732:                    // Swap original warnings back.
0733:                    clearWarnings();
0734:                    if (saveWarnings != null)
0735:                        addWarning(saveWarnings);
0736:                }
0737:
0738:                // XXX revisit: throw exception instead of silently eating the error in unkwon cases?
0739:                if (level == null)
0740:                    return Connection.TRANSACTION_READ_COMMITTED; // Best guess.
0741:
0742:                level = level.toUpperCase();
0743:                if (level.indexOf("READ COMMITTED") != -1)
0744:                    return Connection.TRANSACTION_READ_COMMITTED;
0745:                if (level.indexOf("READ UNCOMMITTED") != -1)
0746:                    return Connection.TRANSACTION_READ_UNCOMMITTED;
0747:                if (level.indexOf("REPEATABLE READ") != -1)
0748:                    return Connection.TRANSACTION_REPEATABLE_READ;
0749:                if (level.indexOf("SERIALIZABLE") != -1)
0750:                    return Connection.TRANSACTION_SERIALIZABLE;
0751:
0752:                return Connection.TRANSACTION_READ_COMMITTED; // Best guess.
0753:            }
0754:
0755:            /*
0756:             * You can call this method to try to change the transaction
0757:             * isolation level using one of the TRANSACTION_* values.
0758:             *
0759:             * <B>Note:</B> setTransactionIsolation cannot be called while
0760:             * in the middle of a transaction
0761:             *
0762:             * @param level one of the TRANSACTION_* isolation values with
0763:             * the exception of TRANSACTION_NONE; some databases may
0764:             * not support other values
0765:             * @exception SQLException if a database access error occurs
0766:             * @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel
0767:             */
0768:            public void setTransactionIsolation(int level) throws SQLException {
0769:                if (protoConnection.getTransactionState() != ProtocolConnection.TRANSACTION_IDLE)
0770:                    throw new PSQLException(
0771:                            GT
0772:                                    .tr("Cannot change transaction isolation level in the middle of a transaction."),
0773:                            PSQLState.ACTIVE_SQL_TRANSACTION);
0774:
0775:                String isolationLevelName = getIsolationLevelName(level);
0776:                if (isolationLevelName == null)
0777:                    throw new PSQLException(GT.tr(
0778:                            "Transaction isolation level {0} not supported.",
0779:                            new Integer(level)), PSQLState.NOT_IMPLEMENTED);
0780:
0781:                String isolationLevelSQL = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL "
0782:                        + isolationLevelName;
0783:                execSQLUpdate(isolationLevelSQL); // nb: no BEGIN triggered
0784:            }
0785:
0786:            protected String getIsolationLevelName(int level) {
0787:                boolean pg80 = haveMinimumServerVersion("8.0");
0788:
0789:                if (level == Connection.TRANSACTION_READ_COMMITTED) {
0790:                    return "READ COMMITTED";
0791:                } else if (level == Connection.TRANSACTION_SERIALIZABLE) {
0792:                    return "SERIALIZABLE";
0793:                } else if (pg80
0794:                        && level == Connection.TRANSACTION_READ_UNCOMMITTED) {
0795:                    return "READ UNCOMMITTED";
0796:                } else if (pg80
0797:                        && level == Connection.TRANSACTION_REPEATABLE_READ) {
0798:                    return "REPEATABLE READ";
0799:                }
0800:
0801:                return null;
0802:            }
0803:
0804:            /*
0805:             * A sub-space of this Connection's database may be selected by
0806:             * setting a catalog name. If the driver does not support catalogs,
0807:             * it will silently ignore this request
0808:             *
0809:             * @exception SQLException if a database access error occurs
0810:             */
0811:            public void setCatalog(String catalog) throws SQLException {
0812:                //no-op
0813:            }
0814:
0815:            /*
0816:             * Return the connections current catalog name, or null if no
0817:             * catalog name is set, or we dont support catalogs.
0818:             *
0819:             * @return the current catalog name or null
0820:             * @exception SQLException if a database access error occurs
0821:             */
0822:            public String getCatalog() throws SQLException {
0823:                return protoConnection.getDatabase();
0824:            }
0825:
0826:            /*
0827:             * Overides finalize(). If called, it closes the connection.
0828:             *
0829:             * This was done at the request of Rachel Greenham
0830:             * <rachel@enlarion.demon.co.uk> who hit a problem where multiple
0831:             * clients didn't close the connection, and once a fortnight enough
0832:             * clients were open to kill the postgres server.
0833:             */
0834:            protected void finalize() throws Throwable {
0835:                if (openStackTrace != null)
0836:                    logger
0837:                            .log(
0838:                                    GT
0839:                                            .tr("Finalizing a Connection that was never closed:"),
0840:                                    openStackTrace);
0841:
0842:                close();
0843:            }
0844:
0845:            /*
0846:             * Get server version number
0847:             */
0848:            public String getDBVersionNumber() {
0849:                return dbVersionNumber;
0850:            }
0851:
0852:            // Parse a "dirty" integer surrounded by non-numeric characters
0853:            private static int integerPart(String dirtyString) {
0854:                int start, end;
0855:
0856:                for (start = 0; start < dirtyString.length()
0857:                        && !Character.isDigit(dirtyString.charAt(start)); ++start)
0858:                    ;
0859:
0860:                for (end = start; end < dirtyString.length()
0861:                        && Character.isDigit(dirtyString.charAt(end)); ++end)
0862:                    ;
0863:
0864:                if (start == end)
0865:                    return 0;
0866:
0867:                return Integer.parseInt(dirtyString.substring(start, end));
0868:            }
0869:
0870:            /*
0871:             * Get server major version
0872:             */
0873:            public int getServerMajorVersion() {
0874:                try {
0875:                    StringTokenizer versionTokens = new StringTokenizer(
0876:                            dbVersionNumber, "."); // aaXbb.ccYdd
0877:                    return integerPart(versionTokens.nextToken()); // return X
0878:                } catch (NoSuchElementException e) {
0879:                    return 0;
0880:                }
0881:            }
0882:
0883:            /*
0884:             * Get server minor version
0885:             */
0886:            public int getServerMinorVersion() {
0887:                try {
0888:                    StringTokenizer versionTokens = new StringTokenizer(
0889:                            dbVersionNumber, "."); // aaXbb.ccYdd
0890:                    versionTokens.nextToken(); // Skip aaXbb
0891:                    return integerPart(versionTokens.nextToken()); // return Y
0892:                } catch (NoSuchElementException e) {
0893:                    return 0;
0894:                }
0895:            }
0896:
0897:            /**
0898:             * Is the server we are connected to running at least this version?
0899:             * This comparison method will fail whenever a major or minor version
0900:             * goes to two digits (10.3.0) or (7.10.1).
0901:             */
0902:            public boolean haveMinimumServerVersion(String ver) {
0903:                return (dbVersionNumber.compareTo(ver) >= 0);
0904:            }
0905:
0906:            /*
0907:             * This method returns true if the compatible level set in the connection
0908:             * (which can be passed into the connection or specified in the URL)
0909:             * is at least the value passed to this method.  This is used to toggle
0910:             * between different functionality as it changes across different releases
0911:             * of the jdbc driver code.  The values here are versions of the jdbc client
0912:             * and not server versions.  For example in 7.1 get/setBytes worked on
0913:             * LargeObject values, in 7.2 these methods were changed to work on bytea
0914:             * values. This change in functionality could be disabled by setting the
0915:             * "compatible" level to be 7.1, in which case the driver will revert to
0916:             * the 7.1 functionality.
0917:             */
0918:            public boolean haveMinimumCompatibleVersion(String ver) {
0919:                return (compatible.compareTo(ver) >= 0);
0920:            }
0921:
0922:            public Encoding getEncoding() {
0923:                return protoConnection.getEncoding();
0924:            }
0925:
0926:            public byte[] encodeString(String str) throws SQLException {
0927:                try {
0928:                    return getEncoding().encode(str);
0929:                } catch (IOException ioe) {
0930:                    throw new PSQLException(
0931:                            GT
0932:                                    .tr("Unable to translate data into the desired encoding."),
0933:                            PSQLState.DATA_ERROR, ioe);
0934:                }
0935:            }
0936:
0937:            public String escapeString(String str) throws SQLException {
0938:                return Utils.appendEscapedLiteral(null, str,
0939:                        protoConnection.getStandardConformingStrings())
0940:                        .toString();
0941:            }
0942:
0943:            public boolean getStandardConformingStrings() {
0944:                return protoConnection.getStandardConformingStrings();
0945:            }
0946:
0947:            /*
0948:             * This returns the java.sql.Types type for a PG type oid
0949:             *
0950:             * @param oid PostgreSQL type oid
0951:             * @return the java.sql.Types type
0952:             * @exception SQLException if a database access error occurs
0953:             */
0954:            public int getSQLType(int oid) throws SQLException {
0955:                return _typeCache.getSQLType(oid);
0956:            }
0957:
0958:            public Iterator getPGTypeNamesWithSQLTypes() {
0959:                return _typeCache.getPGTypeNamesWithSQLTypes();
0960:            }
0961:
0962:            /*
0963:             * This returns the oid for a given PG data type
0964:             * @param typeName PostgreSQL type name
0965:             * @return PostgreSQL oid value for a field of this type, or 0 if not found
0966:             */
0967:            public int getPGType(String typeName) throws SQLException {
0968:                return _typeCache.getPGType(typeName);
0969:            }
0970:
0971:            public String getJavaClass(int oid) throws SQLException {
0972:                return _typeCache.getJavaClass(oid);
0973:            }
0974:
0975:            /*
0976:             * We also need to get the PG type name as returned by the back end.
0977:             *
0978:             * @return the String representation of the type, or null if not fould
0979:             * @exception SQLException if a database access error occurs
0980:             */
0981:            public String getPGType(int oid) throws SQLException {
0982:                return _typeCache.getPGType(oid);
0983:            }
0984:
0985:            // This is a cache of the DatabaseMetaData instance for this connection
0986:            protected java.sql.DatabaseMetaData metadata;
0987:
0988:            /*
0989:             * Tests to see if a Connection is closed
0990:             *
0991:             * @return the status of the connection
0992:             * @exception SQLException (why?)
0993:             */
0994:            public boolean isClosed() throws SQLException {
0995:                return protoConnection.isClosed();
0996:            }
0997:
0998:            public void cancelQuery() throws SQLException {
0999:                protoConnection.sendQueryCancel();
1000:            }
1001:
1002:            public PGNotification[] getNotifications() throws SQLException {
1003:                // Backwards-compatibility hand-holding.
1004:                PGNotification[] notifications = protoConnection
1005:                        .getNotifications();
1006:                return (notifications.length == 0 ? null : notifications);
1007:            }
1008:
1009:            //
1010:            // Handler for transaction queries
1011:            //
1012:            private class TransactionCommandHandler implements  ResultHandler {
1013:                private SQLException error;
1014:
1015:                public void handleResultRows(Query fromQuery, Field[] fields,
1016:                        Vector tuples, ResultCursor cursor) {
1017:                }
1018:
1019:                public void handleCommandStatus(String status, int updateCount,
1020:                        long insertOID) {
1021:                }
1022:
1023:                public void handleWarning(SQLWarning warning) {
1024:                    AbstractJdbc2Connection.this .addWarning(warning);
1025:                }
1026:
1027:                public void handleError(SQLException newError) {
1028:                    if (error == null)
1029:                        error = newError;
1030:                    else
1031:                        error.setNextException(newError);
1032:                }
1033:
1034:                public void handleCompletion() throws SQLException {
1035:                    if (error != null)
1036:                        throw error;
1037:                }
1038:            }
1039:
1040:            public int getPrepareThreshold() {
1041:                return prepareThreshold;
1042:            }
1043:
1044:            public void setPrepareThreshold(int newThreshold) {
1045:                this .prepareThreshold = (newThreshold <= 0 ? 0 : newThreshold);
1046:            }
1047:
1048:            public void setTypeMapImpl(java.util.Map map) throws SQLException {
1049:                typemap = map;
1050:            }
1051:
1052:            public Logger getLogger() {
1053:                return logger;
1054:            }
1055:
1056:            //Because the get/setLogStream methods are deprecated in JDBC2
1057:            //we use the get/setLogWriter methods here for JDBC2 by overriding
1058:            //the base version of this method
1059:            protected void enableDriverManagerLogging() {
1060:                if (DriverManager.getLogWriter() == null) {
1061:                    DriverManager
1062:                            .setLogWriter(new PrintWriter(System.out, true));
1063:                }
1064:            }
1065:
1066:            public int getSQLType(String pgTypeName) {
1067:                return _typeCache.getSQLType(pgTypeName);
1068:            }
1069:
1070:            public int getProtocolVersion() {
1071:                return protoConnection.getProtocolVersion();
1072:            }
1073:
1074:            public boolean getStringVarcharFlag() {
1075:                return bindStringAsVarchar;
1076:            }
1077:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.