📄 session.java
字号:
// DDL statements cs = new CompiledStatement(currentSchema); break; } } // In addition to requiring that the compilation was successful, // we also require that the submitted sql represents a _single_ // valid DML or DDL statement. We do not check the DDL yet. // fredt - now accepts semicolon and whitespace at the end of statement // fredt - investigate if it should or not for prepared statements if (cs.type != CompiledStatement.DDL) { while (tokenizer.getPosition() < tokenizer.getLength()) { token = tokenizer.getString(); if (token.length() != 0 &&!token.equals(Token.T_SEMICOLON)) { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } } } // - need to be able to key cs against its sql in statement pool // - also need to be able to revalidate its sql occasionally cs.sql = sql; return cs; } /** * Executes the command encapsulated by the cmd argument. * * @param cmd the command to execute * @return the result of executing the command */ public Result execute(Result cmd) { try { if (isClosed) { Trace.check(false, Trace.ACCESS_IS_DENIED, Trace.getMessage(Trace.Session_execute)); } } catch (Throwable t) { return new Result(t, null); } synchronized (database) { int type = cmd.mode; if (sessionMaxRows == 0) { currentMaxRows = cmd.updateCount; } // we simply get the next system change number - no matter what type of query sessionSCN = database.nextDMLSCN(); JavaSystem.gc(); switch (type) { case ResultConstants.SQLEXECUTE : { Result resultout = sqlExecute(cmd); resultout = performPostExecute(resultout); return resultout; } case ResultConstants.BATCHEXECUTE : { Result resultout = sqlExecuteBatch(cmd); resultout = performPostExecute(resultout); return resultout; } case ResultConstants.SQLEXECDIRECT : { Result resultout = sqlExecuteDirectNoPreChecks(cmd.getMainString()); resultout = performPostExecute(resultout); return resultout; } case ResultConstants.BATCHEXECDIRECT : { Result resultout = sqlExecuteBatchDirect(cmd); resultout = performPostExecute(resultout); return resultout; } case ResultConstants.SQLPREPARE : { return sqlPrepare(cmd.getMainString()); } case ResultConstants.SQLFREESTMT : { return sqlFreeStatement(cmd.getStatementID()); } case ResultConstants.GETSESSIONATTR : { return getAttributes(); } case ResultConstants.SETSESSIONATTR : { return setAttributes(cmd); } case ResultConstants.SQLENDTRAN : { switch (cmd.getEndTranType()) { case ResultConstants.COMMIT : commit(); break; case ResultConstants.ROLLBACK : rollback(); break; case ResultConstants.SAVEPOINT_NAME_RELEASE : try { String name = cmd.getMainString(); releaseSavepoint(name); } catch (Throwable t) { return new Result(t, null); } break; case ResultConstants.SAVEPOINT_NAME_ROLLBACK : try { rollbackToSavepoint(cmd.getMainString()); } catch (Throwable t) { return new Result(t, null); } break; // not yet // case ResultConstants.COMMIT_AND_CHAIN : // case ResultConstants.ROLLBACK_AND_CHAIN : } return emptyUpdateCount; } case ResultConstants.SQLSETCONNECTATTR : { switch (cmd.getConnectionAttrType()) { case ResultConstants.SQL_ATTR_SAVEPOINT_NAME : try { savepoint(cmd.getMainString()); } catch (Throwable t) { return new Result(t, null); } // case ResultConstants.SQL_ATTR_AUTO_IPD // - always true // default: throw - case never happens } return emptyUpdateCount; } case ResultConstants.SQLDISCONNECT : { close(); return emptyUpdateCount; } default : { return new Result( Trace.runtimeError( Trace.INTERNAL_session_operation_not_supported, null), null); } } } } private Result performPostExecute(Result r) { try { if (database != null) { database.schemaManager.logSequences(this, database.logger); if (isAutoCommit) { database.logger.synchLog(); } } return r; } catch (Exception e) { return new Result(e, null); } } public Result sqlExecuteDirectNoPreChecks(String sql) { synchronized (database) { return dbCommandInterpreter.execute(sql); } } Result sqlExecuteCompiledNoPreChecks(CompiledStatement cs) { return compiledStatementExecutor.execute(cs); } /** * Retrieves a MULTI Result describing three aspects of the * CompiledStatement prepared from the SQL argument for execution * in this session context. <p> * * <ol> * <li>A PREPARE_ACK mode Result describing id of the statement * prepared by this request. This is used by the JDBC implementation * to later identify to the engine which prepared statement to execute. * * <li>A DATA mode result describing the statement's result set metadata. * This is used to generate the JDBC ResultSetMetaData object returned * by PreparedStatement.getMetaData and CallableStatement.getMetaData. * * <li>A DATA mode result describing the statement's parameter metdata. * This is used to by the JDBC implementation to determine * how to send parameters back to the engine when executing the * statement. It is also used to construct the JDBC ParameterMetaData * object for PreparedStatements and CallableStatements. * * @param sql a string describing the desired statement object * @throws HsqlException is a database access error occurs * @return a MULTI Result describing the compiled statement. */ private Result sqlPrepare(String sql) { int csid = compiledStatementManager.getStatementID(currentSchema, sql); CompiledStatement cs = compiledStatementManager.getStatement(csid); Result rmd; Result pmd; if (cs == null) { // compile try { Session sys = database.sessionManager.getSysSession(currentSchema.name, false); cs = sys.sqlCompileStatement(sql); } catch (Throwable t) { return new Result(t, sql); } csid = compiledStatementManager.registerStatement(csid, cs); } else if (!cs.isValid) { // revalidate with the original contexts schema try { Session sys = database.sessionManager.getSysSession( cs.schemaHsqlName.name, false); cs = sys.sqlCompileStatement(sql); } catch (Throwable t) { compiledStatementManager.freeStatement(csid, sessionId); return new Result(t, sql); } csid = compiledStatementManager.registerStatement(csid, cs); } compiledStatementManager.linkSession(csid, sessionId); rmd = cs.describeResult(); pmd = cs.describeParameters(); return Result.newPrepareResponse(csid, rmd, pmd); } private Result sqlExecuteBatch(Result cmd) { int csid; Record record; Result out; CompiledStatement cs; Expression[] parameters; int[] updateCounts; int count; csid = cmd.getStatementID(); cs = compiledStatementManager.getStatement(csid); if (cs == null ||!cs.isValid) { cs = recompileStatement(cs, csid); if (cs == null) { // invalid sql has been removed already return new Result( Trace.runtimeError( Trace.INVALID_PREPARED_STATEMENT, null), null); } } parameters = cs.parameters; count = 0; updateCounts = new int[cmd.getSize()]; record = cmd.rRoot; while (record != null) { Result in; Object[] pvals = record.data; try { for (int i = 0; i < parameters.length; i++) { parameters[i].bind(pvals[i]); } in = compiledStatementExecutor.execute(cs); } catch (Throwable t) { in = new Result(ResultConstants.ERROR); // t.printStackTrace(); // Trace.printSystemOut(t.toString()); // if (t instanceof OutOfMemoryError) { // System.gc(); // } // "in" alread equals "err" // maybe test for OOME and do a gc() ? // t.printStackTrace(); } // On the client side, iterate over the vals and throw // a BatchUpdateException if a batch status value of // esultConstants.EXECUTE_FAILED is encountered in the result if (in.mode == ResultConstants.UPDATECOUNT) { updateCounts[count++] = in.updateCount; } else if (in.mode == ResultConstants.DATA) { // FIXME: we don't have what it takes yet // to differentiate between things like // stored procedure calls to methods with // void return type and select statements with // a single row/column containg null updateCounts[count++] = ResultConstants.SUCCESS_NO_INFO; } else { updateCounts = ArrayUtil.arraySlice(updateCounts, 0, count); break; } record = record.next; } out = new Result(ResultConstants.SQLEXECUTE, updateCounts, 0); return out; } private Result sqlExecuteBatchDirect(Result cmd) { Record record; Result out; int[] updateCounts; int count; count = 0; updateCounts = new int[cmd.getSize()]; record = cmd.rRoot; while (record != null) { Result in; String sql = (String) record.data[0]; try { in = dbCommandInterpreter.execute(sql); } catch (Throwable t) { in = new Result(ResultConstants.ERROR); // if (t instanceof OutOfMemoryError) { // System.gc(); // } // "in" alread equals "err" // maybe test for OOME and do a gc() ? // t.printStackTrace(); } // On the client side, iterate over the colType vals and throw // a BatchUpdateException if a batch status value of // ResultConstants.EXECUTE_FAILED is encountered if (in.mode == ResultConstants.UPDATECOUNT) { updateCounts[count++] = in.updateCount; } else if (in.mode == ResultConstants.DATA) { // FIXME: we don't have what it takes yet // to differentiate between things like // stored procedure calls to methods with // void return type and select statements with // a single row/column containg null updateCounts[count++] = ResultConstants.SUCCESS_NO_INFO; } else { updateCounts = ArrayUtil.arraySlice(updateCounts, 0, count);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -