abstractjdbc1statement.java

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

JAVA
2,147
字号
		/*	 * Return the current query transformed into a cursor-based statement.	 * This uses a new cursor on each query.	 */	private String[] transformToCursorFetch() 	{				// Pinch the prepared count for our own nefarious purposes.		m_cursorName = "JDBC_CURS_" + next_preparedCount();				// Create a cursor declaration and initial fetch statement from the original query.		int len = m_sqlFragments.length;		String[] cursorBasedSql = new String[len];		System.arraycopy(m_sqlFragments, 0, cursorBasedSql, 0, len);		cursorBasedSql[0] = "DECLARE " + m_cursorName + " CURSOR FOR " + cursorBasedSql[0];		cursorBasedSql[len-1] += "; FETCH FORWARD " + fetchSize + " FROM " + m_cursorName;				// Make the cursor based query the one that will be used.		if (org.postgresql.Driver.logDebug)			org.postgresql.Driver.debug("using cursor based sql with cursor name " + m_cursorName);				return cursorBasedSql;	}	/**	 * Do transformations to a query for server-side prepare or setFetchSize() cursor	 * work.	 * @return the query fragments to execute	 */	private String[] getQueryFragments()	{		// nb: isSingleXXX() are relatively expensive, avoid calling them unless we must.				// We check the "mutable" bits of these conditions (which may change without		// a new query being created) here; isSingleXXX() only concern themselves with		// the query structure itself.		// We prefer cursor-based-fetch over server-side-prepare here.				// Eventually a v3 implementation should let us do both at once.		if (fetchSize > 0 && !connection.getAutoCommit() && isSingleSelect())			return transformToCursorFetch();		if (isUseServerPrepare() && isSingleDML())			return transformToServerPrepare();				// Not server-prepare or cursor-fetch, just return a plain query.		return m_sqlFragments;	}                                       		/*	 * Some prepared statements return multiple results; the execute method	 * handles these complex statements as well as the simpler form of	 * statements handled by executeQuery and executeUpdate	 *	 * @return true if the next result is a ResultSet; false if it is an	 *		 update count or there are no more results	 * @exception SQLException if a database access error occurs	 */	public boolean execute() throws SQLException	{		if (isFunction && !returnTypeSet)			throw new PSQLException("postgresql.call.noreturntype", PSQLState.STATEMENT_NOT_ALLOWED_IN_FUNCTION_CALL);		if (isFunction)		{ // set entry 1 to dummy entry..			m_binds[0] = ""; // dummy entry which ensured that no one overrode			m_bindTypes[0] = PG_TEXT;			// and calls to setXXX (2,..) really went to first arg in a function call..		}		// New in 7.1, if we have a previous resultset then force it to close		// This brings us nearer to compliance, and helps memory management.		// Internal stuff will call ExecSQL directly, bypassing this.		if (result != null)		{			java.sql.ResultSet rs = getResultSet();			if (rs != null)				rs.close();		}		// Get the actual query fragments to run (might be a transformed version of		// the original fragments)		String[] fragments = getQueryFragments();		// New in 7.1, pass Statement so that ExecSQL can customise to it                		result = QueryExecutor.execute(fragments,									   m_binds,									   this);		//If we are executing a callable statement function set the return data		if (isFunction)		{			if (!result.reallyResultSet())				throw new PSQLException("postgresql.call.noreturnval", PSQLState.NO_DATA);			if (!result.next ())				throw new PSQLException ("postgresql.call.noreturnval", PSQLState.NO_DATA);			callResult = result.getObject(1);			int columnType = result.getMetaData().getColumnType(1);			if (columnType != functionReturnType)				throw new PSQLException ("postgresql.call.wrongrtntype", PSQLState.DATA_TYPE_MISMATCH,										 new Object[]{											 "java.sql.Types=" + columnType, "java.sql.Types=" + functionReturnType });			result.close ();			return true;		}		else		{			return (result != null && result.reallyResultSet());		}	}		/*	 * setCursorName defines the SQL cursor name that will be used by	 * subsequent execute methods.	This name can then be used in SQL	 * positioned update/delete statements to identify the current row	 * in the ResultSet generated by this statement.  If a database	 * doesn't support positioned update/delete, this method is a	 * no-op.	 *	 * <p><B>Note:</B> By definition, positioned update/delete execution	 * must be done by a different Statement than the one which	 * generated the ResultSet being used for positioning.	Also, cursor	 * names must be unique within a Connection.	 *	 * <p>We throw an additional constriction.	There can only be one	 * cursor active at any one time.	 *	 * @param name the new cursor name	 * @exception SQLException if a database access error occurs	 */	public void setCursorName(String name) throws SQLException	{		connection.setCursorName(name);	}	/*	 * getUpdateCount returns the current result as an update count,	 * if the result is a ResultSet or there are no more results, -1	 * is returned.  It should only be called once per result.	 *	 * @return the current result as an update count.	 * @exception SQLException if a database access error occurs	 */	public int getUpdateCount() throws SQLException	{		if (result == null)			return -1;		if (isFunction)			return 1;		if (result.reallyResultSet())			return -1;		return result.getResultCount();	}	/*	 * getMoreResults moves to a Statement's next result.  If it returns	 * true, this result is a ResulSet.	 *	 * @return true if the next ResultSet is valid	 * @exception SQLException if a database access error occurs	 */	public boolean getMoreResults() throws SQLException	{		result = (BaseResultSet) result.getNext();		return (result != null && result.reallyResultSet());	}	/*	 * Returns the status message from the current Result.<p>	 * This is used internally by the driver.	 *	 * @return status message from backend	 */	public String getResultStatusString()	{		if (result == null)			return null;		return result.getStatusString();	}	/*	 * The maxRows limit is set to limit the number of rows that	 * any ResultSet can contain.  If the limit is exceeded, the	 * excess rows are silently dropped.	 *	 * @return the current maximum row limit; zero means unlimited	 * @exception SQLException if a database access error occurs	 */	public int getMaxRows() throws SQLException	{		return maxrows;	}	/*	 * Set the maximum number of rows	 *	 * @param max the new max rows limit; zero means unlimited	 * @exception SQLException if a database access error occurs	 * @see getMaxRows	 */	public void setMaxRows(int max) throws SQLException	{		if (max<0) throw new PSQLException("postgresql.input.rows.gt0");		maxrows = max;	}	/*	 * If escape scanning is on (the default), the driver will do escape	 * substitution before sending the SQL to the database.	 *	 * @param enable true to enable; false to disable	 * @exception SQLException if a database access error occurs	 */	public void setEscapeProcessing(boolean enable) throws SQLException	{		replaceProcessingEnabled = enable;	}	/*	 * The queryTimeout limit is the number of seconds the driver	 * will wait for a Statement to execute.  If the limit is	 * exceeded, a SQLException is thrown.	 *	 * @return the current query timeout limit in seconds; 0 = unlimited	 * @exception SQLException if a database access error occurs	 */	public int getQueryTimeout() throws SQLException	{		return timeout;	}	/*	 * Sets the queryTimeout limit	 *	 * @param seconds - the new query timeout limit in seconds	 * @exception SQLException if a database access error occurs	 */	public void setQueryTimeout(int seconds) throws SQLException	{		if (seconds<0) throw new PSQLException("postgresql.input.query.gt0");		timeout = seconds;	}	/**	 * This adds a warning to the warning chain.	 * @param msg message to add	 */	public void addWarning(String msg)	{		if (warnings != null)			warnings.setNextWarning(new SQLWarning(msg));		else			warnings = new SQLWarning(msg);	}	/*	 * The first warning reported by calls on this Statement is	 * returned.  A Statement's execute methods clear its SQLWarning	 * chain.  Subsequent Statement warnings will be chained to this	 * SQLWarning.	 *	 * <p>The Warning chain is automatically cleared each time a statement	 * is (re)executed.	 *	 * <p><B>Note:</B>	If you are processing a ResultSet then any warnings	 * associated with ResultSet reads will be chained on the ResultSet	 * object.	 *	 * @return the first SQLWarning on null	 * @exception SQLException if a database access error occurs	 */	public SQLWarning getWarnings() throws SQLException	{		return warnings;	}	/*	 * The maxFieldSize limit (in bytes) is the maximum amount of	 * data returned for any column value; it only applies to	 * BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR and LONGVARCHAR	 * columns.  If the limit is exceeded, the excess data is silently	 * discarded.	 *	 * @return the current max column size limit; zero means unlimited	 * @exception SQLException if a database access error occurs	 */	public int getMaxFieldSize() throws SQLException	{		return maxfieldSize;	}	/*	 * Sets the maxFieldSize 	 *	 * @param max the new max column size limit; zero means unlimited	 * @exception SQLException if a database access error occurs	 */	public void setMaxFieldSize(int max) throws SQLException	{		if (max < 0) throw new PSQLException("postgresql.input.field.gt0");		maxfieldSize = max;	}	/*	 * After this call, getWarnings returns null until a new warning	 * is reported for this Statement.	 *	 * @exception SQLException if a database access error occurs	 */	public void clearWarnings() throws SQLException	{		warnings = null;	}	/*	 * Cancel can be used by one thread to cancel a statement that	 * is being executed by another thread.	 * <p>	 * Not implemented, this method is a no-op.	 *	 * @exception SQLException only because thats the spec.	 */	public void cancel() throws SQLException	{		throw new PSQLException("postgresql.unimplemented", PSQLState.NOT_IMPLEMENTED);	}	/*	 * getResultSet returns the current result as a ResultSet.	It	 * should only be called once per result.	 *	 * @return the current result set; null if there are no more	 * @exception SQLException if a database access error occurs (why?)	 */	public java.sql.ResultSet getResultSet() throws SQLException	{		if (result != null && result.reallyResultSet())			return (ResultSet) result;		return null;	}	/*	 * In many cases, it is desirable to immediately release a	 * Statement's database and JDBC resources instead of waiting	 * for this to happen when it is automatically closed.	The	 * close method provides this immediate release.	 *	 * <p><B>Note:</B> A Statement is automatically closed when it is	 * garbage collected.  When a Statement is closed, its current	 * ResultSet, if one exists, is also closed.	 *	 * @exception SQLException if a database access error occurs (why?)	 */	public void close() throws SQLException	{		// closing an already closed Statement is a no-op.		if (isClosed)			return;		// Force the ResultSet to close		java.sql.ResultSet rs = getResultSet();		if (rs != null)			rs.close();		deallocateQuery();		// Disasociate it from us (For Garbage Collection)		result = null;		isClosed = true;	} 	/** 	 * This finalizer ensures that statements that have allocated server-side 	 * resources free them when they become unreferenced. 	 */ 	protected void finalize() { 		try { close(); } 		catch (SQLException e) {} 	} 	/*	 * Filter the SQL string of Java SQL Escape clauses.	 *	 * Currently implemented Escape clauses are those mentioned in 11.3	 * in the specification. Basically we look through the sql string for	 * {d xxx}, {t xxx} or {ts xxx} in non-string sql code. When we find	 * them, we just strip the escape part leaving only the xxx part.	 * So, something like "select * from x where d={d '2001-10-09'}" would	 * return "select * from x where d= '2001-10-09'".	 */	protected String replaceProcessing(String p_sql)	{		if (replaceProcessingEnabled)		{			// Since escape codes can only appear in SQL CODE, we keep track			// of if we enter a string or not.			StringBuffer newsql = new StringBuffer(p_sql.length());			short state = IN_SQLCODE;			int i = -1;			int len = p_sql.length();			while (++i < len)			{				char c = p_sql.charAt(i);				switch (state)				{					case IN_SQLCODE:						if (c == '\'')				  // start of a string?							state = IN_STRING;						else if (c == '{')			  // start of an escape code?							if (i + 1 < len)							{								char next = p_sql.charAt(i + 1);								if (next == 'd')								{									state = ESC_TIMEDATE;									i++;									break;								}								else if (next == 't')								{									state = ESC_TIMEDATE;									i += (i + 2 < len && p_sql.charAt(i + 2) == 's') ? 2 : 1;									break;								}							}

⌨️ 快捷键说明

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