abstractjdbc1statement.java

来自「PostgreSQL7.4.6 for Linux」· Java 代码 · 共 2,147 行 · 第 1/5 页

JAVA
2,147
字号
package org.postgresql.jdbc1;import org.postgresql.core.BaseConnection;import org.postgresql.core.BaseResultSet;import org.postgresql.core.BaseStatement;import org.postgresql.core.Field;import org.postgresql.core.QueryExecutor;import org.postgresql.largeobject.LargeObject;import org.postgresql.largeobject.LargeObjectManager;import org.postgresql.util.PGbytea;import org.postgresql.util.PGobject;import org.postgresql.util.PSQLException;import org.postgresql.util.PSQLState;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.math.BigDecimal;import java.sql.CallableStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.SQLWarning;import java.sql.Time;import java.sql.Timestamp;import java.sql.Types;import java.util.Vector;/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1Statement.java,v 1.41.2.8 2004/10/21 19:13:55 jurka Exp $ * This class defines methods of the jdbc1 specification.  This class is * extended by org.postgresql.jdbc2.AbstractJdbc2Statement which adds the jdbc2 * methods.  The real Statement class (for jdbc1) is org.postgresql.jdbc1.Jdbc1Statement */public abstract class AbstractJdbc1Statement implements BaseStatement{        // The connection who created us	protected BaseConnection connection;	/** The warnings chain. */	protected SQLWarning warnings = null;	/** Maximum number of rows to return, 0 = unlimited */	protected int maxrows = 0;	/** Number of rows to get in a batch. */	protected int fetchSize = 0;	/** Timeout (in seconds) for a query (not used) */	protected int timeout = 0;	protected boolean replaceProcessingEnabled = true;	/** The current results */	protected BaseResultSet result = null;	// Static variables for parsing SQL when replaceProcessing is true.	private static final short IN_SQLCODE = 0;	private static final short IN_STRING = 1;	private static final short BACKSLASH = 2;	private static final short ESC_TIMEDATE = 3;	// Some performance caches	private StringBuffer sbuf = new StringBuffer(32);	protected String[] m_sqlFragments;              // Query fragments.	private String[] m_executeSqlFragments;         // EXECUTE(...) if useServerPrepare	protected Object[] m_binds = new Object[0];     // Parameter values		protected String[] m_bindTypes = new String[0]; // Parameter types, for PREPARE(...)	protected String m_statementName = null;        // Allocated PREPARE statement name for server-prepared statements	protected String m_cursorName = null;           // Allocated DECLARE cursor name for cursor-based fetch 	// Constants for allowXXX and m_isSingleStatement vars, below.	// The idea is to defer the cost of examining the query until we really need to know,	// but don't reexamine it every time thereafter. 	private static final short UNKNOWN = 0;      // Don't know yet, examine the query.	private static final short NO = 1;           // Don't use feature	private static final short YES = 2;          // Do use feature		private short m_isSingleDML = UNKNOWN;         // Is the query a single SELECT/UPDATE/INSERT/DELETE?	private short m_isSingleSelect = UNKNOWN;      // Is the query a single SELECT?	private short m_isSingleStatement = UNKNOWN;   // Is the query a single statement?	private boolean m_useServerPrepare = false;	private boolean isClosed = false;    // m_preparedCount is used for naming of auto-cursors and must    // be synchronized so that multiple threads using the same    // connection don't stomp over each others cursors.	private static int m_preparedCount = 1;    private synchronized static int next_preparedCount()    {        return m_preparedCount++;    }	//Used by the callablestatement style methods	private static final String JDBC_SYNTAX = "{[? =] call <some_function> ([? [,?]*]) }";	private static final String RESULT_ALIAS = "result";	private String originalSql = "";	private boolean isFunction;	// functionReturnType contains the user supplied value to check	// testReturn contains a modified version to make it easier to	// check the getXXX methods..	private int functionReturnType;	private int testReturn;	// returnTypeSet is true when a proper call to registerOutParameter has been made	private boolean returnTypeSet;	protected Object callResult;	protected int maxfieldSize = 0;	public abstract BaseResultSet createResultSet(Field[] fields, Vector tuples, String status, int updateCount, long insertOID) throws SQLException;	public AbstractJdbc1Statement (BaseConnection connection)	{		this.connection = connection;	}	public AbstractJdbc1Statement (BaseConnection connection, String p_sql) throws SQLException	{		this.connection = connection;		parseSqlStmt(p_sql);  // this allows Callable stmt to override	}	public BaseConnection getPGConnection() {		return connection;	}	public String getFetchingCursorName() {		return m_cursorName;	}	public int getFetchSize() {		return fetchSize;	}	protected void parseSqlStmt (String p_sql) throws SQLException	{		String l_sql = p_sql;		l_sql = replaceProcessing(l_sql);		if (this instanceof CallableStatement)		{			l_sql = modifyJdbcCall(l_sql);		}		Vector v = new Vector();		boolean inQuotes = false;		int lastParmEnd = 0, i;		m_isSingleSelect = m_isSingleDML = UNKNOWN;		m_isSingleStatement = YES;		for (i = 0; i < l_sql.length(); ++i)		{			int c = l_sql.charAt(i);			if (c == '\'')				inQuotes = !inQuotes;			if (c == '?' && !inQuotes)			{				v.addElement(l_sql.substring (lastParmEnd, i));				lastParmEnd = i + 1;			}			if (c == ';' && !inQuotes)				m_isSingleStatement = m_isSingleSelect = m_isSingleDML = NO;		}		v.addElement(l_sql.substring (lastParmEnd, l_sql.length()));		m_sqlFragments = new String[v.size()];		m_binds = new Object[v.size() - 1];		m_bindTypes = new String[v.size() - 1];		for (i = 0 ; i < m_sqlFragments.length; ++i)			m_sqlFragments[i] = (String)v.elementAt(i);	}	/*	 * Deallocate resources allocated for the current query	 * in preparation for replacing it with a new query.	 */	private void deallocateQuery()	{				//If we have already created a server prepared statement, we need		//to deallocate the existing one		if (m_statementName != null)		{			try			{				connection.execSQL("DEALLOCATE " + m_statementName);			}			catch (Exception e)			{			}		}		m_statementName = null;		m_cursorName = null; // automatically closed at end of txn anyway		m_executeSqlFragments = null;		m_isSingleStatement = m_isSingleSelect = m_isSingleDML = UNKNOWN;	}  	/*	 * Execute a SQL statement that retruns a single ResultSet	 *	 * @param sql typically a static SQL SELECT statement	 * @return a ResulSet that contains the data produced by the query	 * @exception SQLException if a database access error occurs	 */	public java.sql.ResultSet executeQuery(String p_sql) throws SQLException	{		deallocateQuery();		String l_sql = replaceProcessing(p_sql);		m_sqlFragments = new String[] {l_sql};		m_binds = new Object[0];		return executeQuery();	}	/*	 * A Prepared SQL query is executed and its ResultSet is returned	 *	 * @return a ResultSet that contains the data produced by the	 *		 *	query - never null	 * @exception SQLException if a database access error occurs	 */	public java.sql.ResultSet executeQuery() throws SQLException	{                this.execute();		while (result != null && !result.reallyResultSet())			result = (BaseResultSet) result.getNext();		if (result == null)			throw new PSQLException("postgresql.stat.noresult", PSQLState.NO_DATA);		return (ResultSet) result;	}	/*	 * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition	 * SQL statements that return nothing such as SQL DDL statements	 * can be executed	 *	 * @param sql a SQL statement	 * @return either a row count, or 0 for SQL commands	 * @exception SQLException if a database access error occurs	 */	public int executeUpdate(String p_sql) throws SQLException	{		deallocateQuery();		String l_sql = replaceProcessing(p_sql);		m_sqlFragments = new String[] {l_sql};		m_binds = new Object[0];		return executeUpdate();	}	/*	 * Execute a SQL INSERT, UPDATE or DELETE statement.  In addition,	 * SQL statements that return nothing such as SQL DDL statements can	 * be executed.	 *	 * @return either the row count for INSERT, UPDATE or DELETE; or	 *		 *	0 for SQL statements that return nothing.	 * @exception SQLException if a database access error occurs	 */	public int executeUpdate() throws SQLException	{		this.execute();		if (result.reallyResultSet())			throw new PSQLException("postgresql.stat.result");		return this.getUpdateCount();	}	/*	 * Execute a SQL statement that may return multiple results. We	 * don't have to worry about this since we do not support multiple	 * ResultSets.	 You can use getResultSet or getUpdateCount to	 * retrieve the result.	 *	 * @param sql any SQL statement	 * @return true if the next result is a ResulSet, false if it is	 *	an update count or there are no more results	 * @exception SQLException if a database access error occurs	 */	public boolean execute(String p_sql) throws SQLException	{		deallocateQuery();		String l_sql = replaceProcessing(p_sql);		m_sqlFragments = new String[] {l_sql};		m_binds = new Object[0];		return execute();	}	/*	 * Check if the current query is a single statement.	 */	private boolean isSingleStatement()	{		if (m_isSingleStatement != UNKNOWN)			return m_isSingleStatement == YES;				// Crude detection of multiple statements. This could be		// improved by parsing the whole query for quotes, but is		// it worth it given that the only queries that get here are		// unparameterized queries?				for (int i = 0; i < m_sqlFragments.length; ++i) { // a bit redundant, but ..			if (m_sqlFragments[i].indexOf(';') != -1) {				m_isSingleStatement = NO;				return false;			}		}				m_isSingleStatement = YES;		return true;	}	/*	 * Helper for isSingleSelect() and isSingleDML(): computes values	 * of m_isSingleDML and m_isSingleSelect.	 */	private void analyzeStatementType()	{		if (!isSingleStatement()) {			m_isSingleSelect = m_isSingleDML = NO;			return;		}				String compare = m_sqlFragments[0].trim().toLowerCase();		if (compare.startsWith("select")) {			m_isSingleSelect = m_isSingleDML = YES;			return;		}		m_isSingleSelect = NO;		if (!compare.startsWith("update") &&			!compare.startsWith("delete") &&			!compare.startsWith("insert")) {			m_isSingleDML = NO;			return;		}				m_isSingleDML = YES;	}	/*	 * Check if the current query is a single SELECT.	 */	private boolean isSingleSelect()	{		if (m_isSingleSelect == UNKNOWN)			analyzeStatementType();		return m_isSingleSelect == YES;	}	/*	 * Check if the current query is a single SELECT/UPDATE/INSERT/DELETE.	 */	private boolean isSingleDML()	{		if (m_isSingleDML == UNKNOWN)			analyzeStatementType();		return m_isSingleDML == YES;	}	/*	 * Return the query fragments to use for a server-prepared statement.	 * The first query executed will include a PREPARE and EXECUTE;	 * subsequent queries will just be an EXECUTE.	 */	private String[] transformToServerPrepare() {		if (m_statementName != null)			return m_executeSqlFragments;               		// First time through.		m_statementName = "JDBC_STATEMENT_" + next_preparedCount();               		// Set up m_executeSqlFragments		m_executeSqlFragments = new String[m_sqlFragments.length];		m_executeSqlFragments[0] = "EXECUTE " + m_statementName;                                		if (m_sqlFragments.length > 1) {			m_executeSqlFragments[0] += "(";			for (int i = 1; i < m_bindTypes.length; i++)				m_executeSqlFragments[i] = ", ";			m_executeSqlFragments[m_bindTypes.length] = ")";		}               		// Set up the PREPARE.		String[] prepareSqlFragments = new String[m_sqlFragments.length];		System.arraycopy(m_sqlFragments, 0, prepareSqlFragments, 0, m_sqlFragments.length);               		synchronized (sbuf) {			sbuf.setLength(0);			sbuf.append("PREPARE ");			sbuf.append(m_statementName);			if (m_sqlFragments.length > 1) {				sbuf.append("(");				for (int i = 0; i < m_bindTypes.length; i++) {					if (i != 0) sbuf.append(", ");					sbuf.append(m_bindTypes[i]);                                                    				}				sbuf.append(")");			}			sbuf.append(" AS ");			sbuf.append(m_sqlFragments[0]);			for (int i = 1; i < m_sqlFragments.length; i++) {				sbuf.append(" $");				sbuf.append(i);				sbuf.append(" ");				sbuf.append(m_sqlFragments[i]);			}			sbuf.append("; ");			sbuf.append(m_executeSqlFragments[0]);                       			prepareSqlFragments[0] = sbuf.toString();		}               		System.arraycopy(m_executeSqlFragments, 1, prepareSqlFragments, 1, prepareSqlFragments.length - 1);		return prepareSqlFragments;	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?