📄 parser.java
字号:
Expression condition = null; // parse table list HsqlArrayList vfilter = new HsqlArrayList(); vfilter.add(parseTableFilter(false)); while (true) { token = tokenizer.getString(); if (tokenizer.wasThis(Token.T_INNER)) { tokenizer.getThis(Token.T_JOIN); token = Token.T_JOIN; } if (token.equals(Token.T_LEFT) &&!tokenizer.wasQuotedIdentifier()) { tokenizer.isGetThis(Token.T_OUTER); tokenizer.getThis(Token.T_JOIN); TableFilter tf = parseTableFilter(true); vfilter.add(tf); tokenizer.getThis(Token.T_ON); Expression newcondition = parseExpression(); newcondition.checkTables(vfilter); condition = addJoinCondition(condition, newcondition, tf, true); } else if (tokenizer.wasThis(Token.T_JOIN)) { vfilter.add(parseTableFilter(false)); tokenizer.getThis(Token.T_ON); Expression newcondition = parseExpression(); newcondition.checkTables(vfilter); condition = addJoinCondition(condition, newcondition, null, false); } else if (tokenizer.wasThis(Token.T_COMMA)) { vfilter.add(parseTableFilter(false)); } else { tokenizer.back(); break; } } resolveSelectTableFilter(select, vcolumn, vfilter); // where token = tokenizer.getString(); if (tokenizer.wasThis(Token.T_WHERE)) { Expression newcondition = parseExpression(); condition = addCondition(condition, newcondition); token = tokenizer.getString(); } select.queryCondition = condition; // group by if (tokenizer.wasThis(Token.T_GROUP)) { tokenizer.getThis(Token.T_BY); int len = 0; do { Expression e = parseExpression(); vcolumn.add(e); token = tokenizer.getString(); len++; } while (tokenizer.wasThis(Token.T_COMMA)); select.iGroupLen = len; } // having if (tokenizer.wasThis(Token.T_HAVING)) { select.iHavingLen = 1; select.havingCondition = parseExpression(); token = tokenizer.getString(); vcolumn.add(select.havingCondition); } if (isMain || limitWithOrder) { if (tokenizer.wasThis(Token.T_ORDER)) { tokenizer.getThis(Token.T_BY); parseOrderBy(select, vcolumn); token = tokenizer.getString(); } if (tokenizer.wasThis(Token.T_LIMIT)) { parseLimit(token, select, true); token = tokenizer.getString(); } } boolean closebrackets = false; if (brackets > 0 && token.equals(Token.T_CLOSEBRACKET)) { closebrackets = true; brackets -= Parser.parseCloseBrackets(tokenizer, brackets - 1) + 1; token = tokenizer.getString(); } select.unionDepth = brackets; // checks for ORDER and LIMIT if (!(isMain || closebrackets)) { limitWithOrder = false; } boolean hasOrder = select.iOrderLen != 0; boolean hasLimit = select.limitCondition != null; if (limitWithOrder) { if (hasLimit &&!hasOrder) { throw Trace.error(Trace.ORDER_LIMIT_REQUIRED); } } else { if (hasOrder &&!canHaveOrder) { throw Trace.error(Trace.INVALID_ORDER_BY); } if (hasLimit &&!canHaveLimit) { throw Trace.error(Trace.INVALID_LIMIT); } } int unionType = parseUnion(token); if (unionType != Select.NOUNION) { boolean openbracket = false; select.unionType = unionType; if (tokenizer.isGetThis(Token.T_OPENBRACKET)) { openbracket = true; brackets += Parser.parseOpenBrackets(tokenizer) + 1; } tokenizer.getThis(Token.T_SELECT); // accept ORDRY BY with LIMIT when in brackets select.unionSelect = parseSelect(brackets, false, false, openbracket, false); token = tokenizer.getString(); } if (isMain && (canHaveOrder || limitWithOrder) && select.iOrderLen == 0) { if (tokenizer.wasThis(Token.T_ORDER)) { tokenizer.getThis(Token.T_BY); parseOrderBy(select, vcolumn); token = tokenizer.getString(); select.sortUnion = true; } if (tokenizer.wasThis(Token.T_LIMIT)) { parseLimit(token, select, true); token = tokenizer.getString(); } } tokenizer.back(); if (isMain) { select.prepareUnions(); } int len = vcolumn.size(); select.exprColumns = new Expression[len]; vcolumn.toArray(select.exprColumns); return select; } /** * Parses the given token and any further tokens in tokenizer to return * any UNION or other set operation ID. */ int parseUnion(String token) throws HsqlException { int unionType = Select.NOUNION; if (tokenizer.wasSimpleToken()) { switch (Token.get(token)) { case Token.UNION : token = tokenizer.getSimpleToken(); if (token.equals(Token.T_ALL)) { unionType = Select.UNIONALL; } else if (token.equals(Token.T_DISTINCT)) { unionType = Select.UNION; } else { unionType = Select.UNION; tokenizer.back(); } break; case Token.INTERSECT : tokenizer.isGetThis(Token.T_DISTINCT); unionType = Select.INTERSECT; break; case Token.EXCEPT : case Token.MINUS : tokenizer.isGetThis(Token.T_DISTINCT); unionType = Select.EXCEPT; break; default : break; } } return unionType; }// fredt@users 20011010 - patch 471710 by fredt - LIMIT rewritten// SELECT LIMIT n m DISTINCT ... queries and error message// "SELECT LIMIT n m ..." creates the result set for the SELECT statement then// discards the first n rows and returns m rows of the remaining result set// "SELECT LIMIT 0 m" is equivalent to "SELECT TOP m" or "SELECT FIRST m"// in other RDBMS's// "SELECT LIMIT n 0" discards the first n rows and returns the remaining rows// fredt@users 20020225 - patch 456679 by hiep256 - TOP keyword private void parseLimit(String token, Select select, boolean isEnd) throws HsqlException { if (select.limitCondition != null) { return; } Expression e1 = null; Expression e2; boolean islimit = false; if (isEnd) { if (token.equals(Token.T_LIMIT)) { islimit = true; read(); e2 = readTerm(); if (sToken.equals(Token.T_OFFSET)) { read(); e1 = readTerm(); } tokenizer.back(); } else { return; } } else if (token.equals(Token.T_LIMIT)) { read(); e1 = readTerm(); e2 = readTerm(); islimit = true; tokenizer.back(); } else if (token.equals(Token.T_TOP)) { read(); e2 = readTerm(); tokenizer.back(); } else { return; } if (e1 == null) { e1 = new Expression(Types.INTEGER, ValuePool.getInt(0)); } if (e1.isParam() || (e1.getType() == Expression.VALUE && e1.getDataType() == Types.INTEGER && e1.getValue(null) != null && ((Integer) e1.getValue(null)).intValue() >= 0)) { if (e2.isParam() || (e2.getType() == Expression.VALUE && e2.getDataType() == Types.INTEGER && e2.getValue(null) != null && ((Integer) e2.getValue(null)).intValue() >= 0)) { // necessary for params e1.setDataType(Types.INTEGER); e2.setDataType(Types.INTEGER); select.limitCondition = new Expression(Expression.LIMIT, e1, e2); return; } } int messageid = islimit ? Trace.INVALID_LIMIT_EXPRESSION : Trace.INVALID_TOP_EXPRESSION; throw Trace.error(Trace.WRONG_DATA_TYPE, messageid); } private void parseOrderBy(Select select, HsqlArrayList vcolumn) throws HsqlException { String token; int len = 0; do { Expression e = parseExpression(); e = resolveOrderByExpression(e, select, vcolumn); token = tokenizer.getString(); if (token.equals(Token.T_DESC)) { e.setDescending(); token = tokenizer.getString(); } else if (token.equals(Token.T_ASC)) { token = tokenizer.getString(); } vcolumn.add(e); len++; } while (token.equals(Token.T_COMMA)); tokenizer.back(); select.iOrderLen = len; } private void resolveSelectTableFilter(Select select, HsqlArrayList vcolumn, HsqlArrayList vfilter) throws HsqlException { int len = vfilter.size(); TableFilter[] filters = new TableFilter[len]; vfilter.toArray(filters); select.tFilter = filters; // expand [table.]* columns len = vcolumn.size(); for (int i = 0; i < len; i++) { Expression e = (Expression) (vcolumn.get(i)); if (e.getType() == Expression.ASTERIX) { int current = i; Table table = null; String n = e.getTableName(); for (int t = 0; t < filters.length; t++) { TableFilter f = filters[t];// e.resolve(f); e.resolveTables(f); if (n != null &&!n.equals(f.getName())) { continue; } table = f.getTable(); int col = table.getColumnCount(); for (int c = 0; c < col; c++) { Expression ins = new Expression(f.getName(), table.getColumn(c)); vcolumn.add(current++, ins); // now there is one element more to parse len++; } } Trace.check(table != null, Trace.TABLE_NOT_FOUND, n); // minus the asterix element len--; vcolumn.remove(current); } else /* if (e.getType() == Expression.COLUMN) */ { if (e.getFilter() == null) { for (int f = 0; f < filters.length; f++) { e.resolveTables(filters[f]); } } } } for (int i = 0; i < len; i++) { Expression e = (Expression) (vcolumn.get(i)); e.resolveTypes(session); } select.iResultLen = len; } /** * Resolves an ORDER BY Expression, returning the column Expression object * to which it refers if it is an alias or column index. <p> * * If select is a SET QUERY, then only column indexes or names in the first * query are allowed. * * @param e search column expression * @param vcolumn list of columns * @param union is select a union * @return new or the same expression * @throws HsqlException if an ambiguous reference to an alias or * non-integer column index is encountered */ private static Expression resolveOrderByExpression(Expression e, Select select, HsqlArrayList vcolumn) throws HsqlException { int visiblecols = select.iResultLen; boolean union = select.unionSelect != null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -