private CompiledStatement sqlCompileStatement(String sql, int type) throws HsqlException { Tokenizer tokenizer; String token; Parser parser; int cmd; CompiledStatement cs; boolean isCmdOk; tokenizer = new Tokenizer(sql); parser = new Parser(dDatabase, tokenizer, this); token = tokenizer.getString(); cmd = Token.get(token); isCmdOk = true; switch (cmd) { case Token.SELECT: { cs = parser.compileSelectStatement(null); break; } case Token.INSERT: { cs = parser.compileInsertStatement(null); break; } case Token.UPDATE: { cs = parser.compileUpdateStatement(null); break; } case Token.DELETE: { cs = parser.compileDeleteStatement(null); break; } case Token.CALL: { if (type != CompiledStatement.CALL) { throw Trace.error(Trace.ASSERT_FAILED, "not a CALL statement"); } cs = parser.compileCallStatement(null); break; } default: { isCmdOk = false; cs = null; break; } } // In addition to requiring that the compilation was successful, // we also require that the submitted sql represents a _single_ // valid DML statement. if (!isCmdOk) { throw Trace.error(Trace.UNEXPECTED_TOKEN, token); } // fredt - now accepts semicolon and whitespace at the end of statement // fredt - investigate if it should or not while (tokenizer.getPosition() < tokenizer.getLength()) { token = tokenizer.getString(); Trace.check( token.length() == 0 || token.equals(Token.T_SEMICOLON), 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; }