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