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