abstractjdbc1connection.java
来自「PostgreSQL7.4.6 for Linux」· Java 代码 · 共 1,864 行 · 第 1/4 页
JAVA
1,864 行
* * @param level one of the TRANSACTION_* isolation values with * the exception of TRANSACTION_NONE; some databases may * not support other values * @exception SQLException if a database access error occurs * @see java.sql.DatabaseMetaData#supportsTransactionIsolationLevel */ public void setTransactionIsolation(int level) throws SQLException { //In 7.1 and later versions of the server it is possible using //the "set session" command to set this once for all future txns //however in 7.0 and prior versions it is necessary to set it in //each transaction, thus adding complexity below. //When we decide to drop support for servers older than 7.1 //this can be simplified isolationLevel = level; String isolationLevelSQL; if (!haveMinimumServerVersion("7.1")) { isolationLevelSQL = getIsolationLevelSQL(); } else { isolationLevelSQL = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL "; switch (isolationLevel) { case Connection.TRANSACTION_READ_COMMITTED: isolationLevelSQL += "READ COMMITTED"; break; case Connection.TRANSACTION_SERIALIZABLE: isolationLevelSQL += "SERIALIZABLE"; break; default: throw new PSQLException("postgresql.con.isolevel", PSQLState.TRANSACTION_STATE_INVALID, new Integer(isolationLevel)); } } execSQL(isolationLevelSQL); } /* * Helper method used by setTransactionIsolation(), commit(), rollback() * and setAutoCommit(). This returns the SQL string needed to * set the isolation level for a transaction. In 7.1 and later it * is possible to set a default isolation level that applies to all * future transactions, this method is only necesary for 7.0 and older * servers, and should be removed when support for these older * servers are dropped */ protected String getIsolationLevelSQL() throws SQLException { //7.1 and higher servers have a default specified so //no additional SQL is required to set the isolation level if (haveMinimumServerVersion("7.1")) { return ""; } StringBuffer sb = new StringBuffer("SET TRANSACTION ISOLATION LEVEL"); switch (isolationLevel) { case Connection.TRANSACTION_READ_COMMITTED: sb.append(" READ COMMITTED"); break; case Connection.TRANSACTION_SERIALIZABLE: sb.append(" SERIALIZABLE"); break; default: throw new PSQLException("postgresql.con.isolevel", PSQLState.TRANSACTION_STATE_INVALID, new Integer(isolationLevel)); } return sb.toString(); } /* * A sub-space of this Connection's database may be selected by * setting a catalog name. If the driver does not support catalogs, * it will silently ignore this request * * @exception SQLException if a database access error occurs */ public void setCatalog(String catalog) throws SQLException { //no-op } /* * Return the connections current catalog name, or null if no * catalog name is set, or we dont support catalogs. * * @return the current catalog name or null * @exception SQLException if a database access error occurs */ public String getCatalog() throws SQLException { return PG_DATABASE; } /* * Overides finalize(). If called, it closes the connection. * * This was done at the request of Rachel Greenham * <rachel@enlarion.demon.co.uk> who hit a problem where multiple * clients didn't close the connection, and once a fortnight enough * clients were open to kill the org.postgres server. */ public void finalize() throws Throwable { close(); } private static String extractVersionNumber(String fullVersionString) { StringTokenizer versionParts = new StringTokenizer(fullVersionString); versionParts.nextToken(); /* "PostgreSQL" */ return versionParts.nextToken(); /* "X.Y.Z" */ } /* * Get server version number */ public String getDBVersionNumber() { return dbVersionNumber; } // Parse a "dirty" integer surrounded by non-numeric characters private static int integerPart(String dirtyString) { int start, end; for (start = 0; start < dirtyString.length() && !Character.isDigit(dirtyString.charAt(start)); ++start) ; for (end = start; end < dirtyString.length() && Character.isDigit(dirtyString.charAt(end)); ++end) ; if (start == end) return 0; return Integer.parseInt(dirtyString.substring(start, end)); } /* * Get server major version */ public int getServerMajorVersion() { try { StringTokenizer versionTokens = new StringTokenizer(dbVersionNumber, "."); // aaXbb.ccYdd return integerPart(versionTokens.nextToken()); // return X } catch (NoSuchElementException e) { return 0; } } /* * Get server minor version */ public int getServerMinorVersion() { try { StringTokenizer versionTokens = new StringTokenizer(dbVersionNumber, "."); // aaXbb.ccYdd versionTokens.nextToken(); // Skip aaXbb return integerPart(versionTokens.nextToken()); // return Y } catch (NoSuchElementException e) { return 0; } } /** * Is the server we are connected to running at least this version? * This comparison method will fail whenever a major or minor version * goes to two digits (10.3.0) or (7.10.1). */ public boolean haveMinimumServerVersion(String ver) throws SQLException { return (getDBVersionNumber().compareTo(ver) >= 0); } /* * This method returns true if the compatible level set in the connection * (which can be passed into the connection or specified in the URL) * is at least the value passed to this method. This is used to toggle * between different functionality as it changes across different releases * of the jdbc driver code. The values here are versions of the jdbc client * and not server versions. For example in 7.1 get/setBytes worked on * LargeObject values, in 7.2 these methods were changed to work on bytea * values. This change in functionality could be disabled by setting the * "compatible" level to be 7.1, in which case the driver will revert to * the 7.1 functionality. */ public boolean haveMinimumCompatibleVersion(String ver) throws SQLException { return (compatible.compareTo(ver) >= 0); } /* * This returns the java.sql.Types type for a PG type oid * * @param oid PostgreSQL type oid * @return the java.sql.Types type * @exception SQLException if a database access error occurs */ public int getSQLType(int oid) throws SQLException { Integer sqlType = (Integer)sqlTypeCache.get(new Integer(oid)); // it's not in the cache, so perform a query, and add the result to the cache if (sqlType == null) { String pgType; // The opaque type does not exist in the system catalogs. if (oid == 0) { pgType = "opaque"; } else { String sql; if (haveMinimumServerVersion("7.3")) { sql = "SELECT typname FROM pg_catalog.pg_type WHERE oid = " +oid; } else { sql = "SELECT typname FROM pg_type WHERE oid = " +oid; } BaseResultSet result = execSQL(sql); if (result.getColumnCount() != 1 || result.getTupleCount() != 1) { throw new PSQLException("postgresql.unexpected", PSQLState.UNEXPECTED_ERROR); } result.next(); pgType = result.getString(1); result.close(); } Integer iOid = new Integer(oid); sqlType = new Integer(getSQLType(pgType)); sqlTypeCache.put(iOid, sqlType); pgTypeCache.put(iOid, pgType); } return sqlType.intValue(); } /* * This returns the oid for a given PG data type * @param typeName PostgreSQL type name * @return PostgreSQL oid value for a field of this type */ public int getPGType(String typeName) throws SQLException { int oid = -1; if (typeName != null) { Integer oidValue = (Integer) typeOidCache.get(typeName); if (oidValue != null) { oid = oidValue.intValue(); } else { // it's not in the cache, so perform a query, and add the result to the cache String sql; if (haveMinimumServerVersion("7.3")) { sql = "SELECT oid FROM pg_catalog.pg_type WHERE typname='" + typeName + "'"; } else { sql = "SELECT oid FROM pg_type WHERE typname='" + typeName + "'"; } BaseResultSet result = execSQL(sql); if (result.getColumnCount() != 1 || result.getTupleCount() != 1) throw new PSQLException("postgresql.unexpected", PSQLState.UNEXPECTED_ERROR); result.next(); oid = Integer.parseInt(result.getString(1)); typeOidCache.put(typeName, new Integer(oid)); result.close(); } } return oid; } /* * We also need to get the PG type name as returned by the back end. * * @return the String representation of the type of this field * @exception SQLException if a database access error occurs */ public String getPGType(int oid) throws SQLException { String pgType = (String) pgTypeCache.get(new Integer(oid)); if (pgType == null) { getSQLType(oid); pgType = (String) pgTypeCache.get(new Integer(oid)); } return pgType; } //Because the get/setLogStream methods are deprecated in JDBC2 //we use them for JDBC1 here and override this method in the jdbc2 //version of this class protected void enableDriverManagerLogging() { if (DriverManager.getLogStream() == null) { DriverManager.setLogStream(System.out); } } // This is a cache of the DatabaseMetaData instance for this connection protected java.sql.DatabaseMetaData metadata; /* * Tests to see if a Connection is closed * * @return the status of the connection * @exception SQLException (why?) */ public boolean isClosed() throws SQLException { return (pgStream == null); } /* * This implemetation uses the jdbc1Types array to support the jdbc1 * datatypes. Basically jdbc1 and jdbc2 are the same, except that * jdbc2 adds the Array types. */ public int getSQLType(String pgTypeName) { int sqlType = Types.OTHER; // default value for (int i = 0;i < jdbc1Types.length;i++) { if (pgTypeName.equals(jdbc1Types[i])) { sqlType = jdbc1Typei[i]; break; } } return sqlType; } /* * This table holds the org.postgresql names for the types supported. * Any types that map to Types.OTHER (eg POINT) don't go into this table. * They default automatically to Types.OTHER * * Note: This must be in the same order as below. * * Tip: keep these grouped together by the Types. value */ private static final String jdbc1Types[] = { "int2", "int4", "oid", "int8", "cash", "money", "numeric", "float4", "float8", "bpchar", "char", "char2", "char4", "char8", "char16", "varchar", "text", "name", "filename", "bytea", "bool", "bit", "date", "time", "abstime", "timestamp", "timestamptz" }; /* * This table holds the JDBC type for each entry above. * * Note: This must be in the same order as above * * Tip: keep these grouped together by the Types. value */ private static final int jdbc1Typei[] = { Types.SMALLINT, Types.INTEGER, Types.INTEGER, Types.BIGINT, Types.DOUBLE, Types.DOUBLE, Types.NUMERIC, Types.REAL, Types.DOUBLE, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.BINARY, Types.BIT, Types.BIT, Types.DATE, Types.TIME, Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP }; public void cancelQuery() throws SQLException { org.postgresql.core.PGStream cancelStream = null; try { cancelStream = new org.postgresql.core.PGStream(PG_HOST, PG_PORT); } catch (ConnectException cex) { // Added by Peter Mount <peter@retep.org.uk> // ConnectException is thrown when the connection cannot be made. // we trap this an return a more meaningful message for the end user throw new PSQLException ("postgresql.con.refused", PSQLState.CONNECTION_REJECTED); } catch (IOException e) { throw new PSQLException ("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } // Now we need to construct and send a cancel packet try { cancelStream.SendInteger(16, 4); cancelStream.SendInteger(80877102, 4); cancelStream.SendInteger(pid, 4); cancelStream.SendInteger(ckey, 4); cancelStream.flush(); } catch (IOException e) { throw new PSQLException("postgresql.con.failed", PSQLState.CONNECTION_UNABLE_TO_CONNECT, e); } finally { try { if (cancelStream != null) cancelStream.close(); } catch (IOException e) {} // Ignore } } //Methods to support postgres notifications public void addNotification(org.postgresql.PGNotification p_notification) { if (m_notifications == null) m_notifications = new Vector(); m_notifications.addElement(p_notification); } public PGNotification[] getNotifications() { PGNotification[] l_return = null; if (m_notifications != null) { l_return = new PGNotification[m_notifications.size()]; m_notifications.copyInto(l_return); } m_notifications = null; return l_return; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?