📄 jdbcconnection.java
字号:
* to arbitrary depth, but enforces a very strict interpretation of the * syntax and does not detect or process SQL comments. <p> * * In essence, the HSQLDB engine directly handles the prescribed syntax * and date / time formats specified internal to the JDBC escapes. * It also directly offers the XOpen / ODBC extended scalar * functions specified available internal to the {fn ...} JDBC escape. * As such, the driver simply removes the curly braces and JDBC escape * codes in the simplest and fastest fashion possible, by replacing them * with whitespace. * * But to avoid a great deal of complexity, certain forms of input * whitespace are currently not recognised. For instance, * the driver handles "{?= call ...}" but not "{ ?= call ...} or * "{? = call ...}" <p> * * Also, comments embedded in SQL are currently not detected or * processed and thus may have unexpected effects on the output * of this method, for instance causing otherwise valid SQL to become * invalid. It is especially important to be aware of this because escape * processing is set true by default for Statement objects and is always * set true when producing a PreparedStatement from prepareStatement() * or CallableStatement from prepareCall(). Currently, it is simply * recommended to avoid submitting SQL having comments containing JDBC * escape sequence patterns and/or single or double quotation marks, * as this will avoid any potential problems. * * It is intended to implement a less strict handling of whitespace and * proper processing of SQL comments at some point in the near future, * perhaps before the final 1.7.2 release. * * In any event, 1.7.2 now correctly processes the following JDBC escape * forms to arbitrary nesting depth, but only if the exact whitespace * layout described below is used: <p> * * <ol> * <li>{call ...} * <li>{?= call ...} * <li>{fn ...} * <li>{oj ...} * <li>{d ...} * <li>{t ...} * <li>{ts ...} * </ol> <p> * * </div> <!-- end release-specific documentation --> * * @param sql a SQL statement that may contain one or more '?' * parameter placeholders * @return the native form of this statement * @throws SQLException if a database access error occurs <p> */ public synchronized String nativeSQL(final String sql) throws SQLException { // boucherb@users 20030405 // FIXME: does not work properly for nested escapes // e.g. {call ...(...,{ts '...'},....)} does not work // boucherb@users 20030817 // TESTME: First kick at the FIXME cat done. Now lots of testing // and refinment checkClosed(); // CHECKME: Thow or return null if input is null? if (sql == null || sql.length() == 0 || sql.indexOf('{') == -1) { return sql; } // boolean changed = false; int state = 0; int len = sql.length(); int nest = 0; StringBuffer sb = new StringBuffer(sql.length()); //avoid 16 extra String msg; //-- final int outside_all = 0; final int outside_escape_inside_single_quotes = 1; final int outside_escape_inside_double_quotes = 2; //-- final int inside_escape = 3; final int inside_escape_inside_single_quotes = 4; final int inside_escape_inside_double_quotes = 5; // TODO: // final int inside_single_line_comment = 6; // final int inside_multi_line_comment = 7; // Better than old way for large inputs and for avoiding GC overhead; // toString() reuses internal char[], reducing memory requirment // and garbage items 3:2 sb.append(sql); for (int i = 0; i < len; i++) { char c = sb.charAt(i); switch (state) { case outside_all : // Not inside an escape or quotes if (c == '\'') { state = outside_escape_inside_single_quotes; } else if (c == '"') { state = outside_escape_inside_double_quotes; } else if (c == '{') { i = onStartEscapeSequence(sql, sb, i); // changed = true; nest++; state = inside_escape; } break; case outside_escape_inside_single_quotes : // inside ' ' only case inside_escape_inside_single_quotes : // inside { } and ' ' if (c == '\'') { state -= 1; } break; case outside_escape_inside_double_quotes : // inside " " only case inside_escape_inside_double_quotes : // inside { } and " " if (c == '"') { state -= 2; } break; case inside_escape : // inside { } if (c == '\'') { state = inside_escape_inside_single_quotes; } else if (c == '"') { state = inside_escape_inside_double_quotes; } else if (c == '}') { sb.setCharAt(i, ' '); // changed = true; nest--; state = (nest == 0) ? outside_all : inside_escape; } else if (c == '{') { i = onStartEscapeSequence(sql, sb, i); // changed = true; nest++; state = inside_escape; } } } return sb.toString(); } /** * <!-- start generic documentation --> * Sets this connection's auto-commit mode to the given state. * If a connection is in auto-commit mode, then all its SQL * statements will be executed and committed as individual transactions. * Otherwise, its SQL statements are grouped into transactions that * are terminated by a call to either the method <code>commit</code> or * the method <code>rollback</code>. By default, new connections are * in auto-commit mode. <p> * * The commit occurs when the statement completes or the next * execute occurs, whichever comes first. In the case of * statements returning a <code>ResultSet</code> object, the * statement completes when the last row of the <code>ResultSet</code> * object has been retrieved or the <code>ResultSet</code> object * has been closed. In advanced cases, a single statement may * return multiple results as well as output parameter values. In * these cases, the commit occurs when all results and output * parameter values have been retrieved. <p> * * <B>NOTE:</B> If this method is called during a transaction, * the transaction is committed. <p> * * <!-- end generic documentation --> * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Up to and including HSQLDB 1.7.2, <p> * * <ol> * <li> All rows of a result set are retrieved internally <em> * before</em> the first row can actually be fetched.<br> * Therefore, a statement can be considered complete as soon as * any XXXStatement.executeXXX method returns. </li> * * <li> Multiple result sets and output parameters are not yet * supported. </li> * </ol> * <p> * * (boucherb@users) </div> <!-- end release-specific * documentation --> * * @param autoCommit <code>true</code> to enable auto-commit * mode; <code>false</code> to disable it * @exception SQLException if a database access error occurs * @see #getAutoCommit */ public synchronized void setAutoCommit(boolean autoCommit) throws SQLException { checkClosed(); try { sessionProxy.setAutoCommit(autoCommit); } catch (HsqlException e) { throw Util.sqlException(e); } } /** * Gets the current auto-commit state. * * @return the current state of auto-commit mode * @exception SQLException Description of the Exception * @see #setAutoCommit */ public synchronized boolean getAutoCommit() throws SQLException { checkClosed(); try { return sessionProxy.isAutoCommit(); } catch (HsqlException e) { throw Util.sqlException(e); } } /** * <!-- start generic documentation --> * Makes all changes made since the * previous commit/rollback permanent and releases any database * locks currently held by the Connection. This method should be * used only when auto-commit mode has been disabled. <p> * * <!-- end generic documentation --> * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with HSQLDB 1.7.2, savepoints are supported both * in SQL and via the JDBC interface. <p> * * Using SQL, savepoints may be set, released and used in rollback * as follows: * * <pre> * SAVEPOINT <savepoint-name> * RELEASE SAVEPOINT <savepoint-name> * ROLLBACK TO SAVEPOINT <savepoint-name> * </pre> * * </div><!-- end release-specific documentation --> * * @exception SQLException if a database access error occurs * @see #setAutoCommit */ public synchronized void commit() throws SQLException { checkClosed(); try { sessionProxy.commit(); } catch (HsqlException e) { throw Util.sqlException(e); } } /** * <!-- start generic documentation --> * Drops all changes made since the * previous commit/rollback and releases any database locks * currently held by this Connection. This method should be used * only when auto- commit has been disabled. <p> * * <!-- end generic documentation --> * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * Starting with HSQLDB 1.7.2, savepoints are fully supported both * in SQL and via the JDBC interface. <p> * * Using SQL, savepoints may be set, released and used in rollback * as follows: * * <pre> * SAVEPOINT <savepoint-name> * RELEASE SAVEPOINT <savepoint-name> * ROLLBACK TO SAVEPOINT <savepoint-name> * </pre> * * </div> <!-- end release-specific documentation --> * * @exception SQLException if a database access error occurs * @see #setAutoCommit */ public synchronized void rollback() throws SQLException { checkClosed(); try { sessionProxy.rollback(); } catch (HsqlException e) { throw Util.sqlException(e); } } /** * <!-- start generic documentation --> * Releases this <code>Connection</code> * object's database and JDBC resources immediately instead of * waiting for them to be automatically released.<p> * * Calling the method <code>close</code> on a <code>Connection</code> * object that is already closed is a no-op. <p> * * <B>Note:</B> A <code>Connection</code> object is automatically * closed when it is garbage collected. Certain fatal errors also * close a <code>Connection</code> object. <p> * * <!-- end generic documentation --> * <!-- start release-specific documentation --> * <div class="ReleaseSpecificDocumentation"> * <h3>HSQLDB-Specific Information:</h3> <p> * * In 1.7.2, <code>INTERNAL</code> <code>Connection</code> * objects are not closable from JDBC client code. <p> * * </div> <!-- end release-specific documentation -->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -