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 + -
显示快捷键?