public SQLExpr primary()

in core/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java [461:1272]


    public SQLExpr primary() {
        List<String> beforeComments = null;
        if (lexer.isKeepComments() && lexer.hasComment()) {
            beforeComments = lexer.readAndResetComments();
        }

        SQLExpr sqlExpr = null;

        final Token tok = lexer.token;

        switch (tok) {
            case LPAREN:
                lexer.nextToken();
                if (lexer.token == Token.RPAREN) {
                    lexer.nextToken();
                    sqlExpr = new SQLMethodInvokeExpr();
                    break;
                }
                sqlExpr = expr();

                if (lexer.token == Token.COMMA) {
                    SQLListExpr listExpr = new SQLListExpr();
                    listExpr.addItem(sqlExpr);
                    do {
                        lexer.nextToken();
                        listExpr.addItem(expr());
                    } while (lexer.token == Token.COMMA);

                    sqlExpr = listExpr;
                }
                if (sqlExpr instanceof SQLExprImpl) {
                    ((SQLExprImpl) sqlExpr).setParenthesized(true);
                }

                if ((lexer.token == Token.UNION || lexer.token == Token.MINUS || lexer.token == Token.EXCEPT)
                        && sqlExpr instanceof SQLQueryExpr) {
                    SQLQueryExpr queryExpr = (SQLQueryExpr) sqlExpr;

                    SQLSelectQuery query = this.createSelectParser().queryRest(queryExpr.getSubQuery().getQuery(), true);
                    queryExpr.getSubQuery().setQuery(query);
                }

                accept(Token.RPAREN);
                break;
            case INSERT:
                lexer.nextToken();
                if (lexer.token != Token.LPAREN) {
                    throw new ParserException("syntax error. " + lexer.info());
                }
                sqlExpr = new SQLIdentifierExpr("INSERT");
                break;
            case IDENTIFIER:
                String ident = lexer.stringVal();
                long hash_lower = lexer.hashLCase();

                int sourceLine = -1, sourceColumn = -1;
                if (lexer.keepSourceLocation) {
                    lexer.computeRowAndColumn();
                    sourceLine = lexer.posLine;
                    sourceColumn = lexer.posColumn;
                }

                lexer.nextToken();
                if (lexer.identifierEquals("COLLATE")) {
                    acceptIdentifier("COLLATE");
                    String collateValue = lexer.stringVal();
                    if (lexer.token == Token.IDENTIFIER || lexer.token == Token.LITERAL_ALIAS || lexer.token == Token.LITERAL_CHARS) {
                        SQLIdentifierExpr identifierExpr = new SQLIdentifierExpr(ident);
                        identifierExpr.setCollate(collateValue);
                        lexer.nextToken();
                        sqlExpr = identifierExpr;
                    } else {
                        throw new ParserException("syntax error. " + lexer.info());
                    }
                } else if (hash_lower == FnvHash.Constants.TRY_CAST) {
                    accept(Token.LPAREN);
                    SQLCastExpr cast = new SQLCastExpr();
                    cast.setTry(true);
                    cast.setExpr(expr());
                    accept(Token.AS);
                    cast.setDataType(parseDataType(false));
                    accept(Token.RPAREN);

                    sqlExpr = cast;
                } else if (hash_lower == FnvHash.Constants.DATE
                        && (lexer.token == Token.LITERAL_CHARS || lexer.token == Token.VARIANT)
                        && (dialectFeatureEnabled(SQLDateExpr))) {
                    String literal = lexer.token == Token.LITERAL_CHARS ? lexer.stringVal() : "?";
                    lexer.nextToken();
                    SQLDateExpr dateExpr = new SQLDateExpr();
                    dateExpr.setValue(literal);
                    sqlExpr = dateExpr;
                } else if (hash_lower == FnvHash.Constants.TIMESTAMP
                        && (lexer.token == Token.LITERAL_CHARS || lexer.token == Token.VARIANT)
                        && dialectFeatureEnabled(SQLTimestampExpr)) {
                    SQLTimestampExpr dateExpr = new SQLTimestampExpr(lexer.stringVal());
                    lexer.nextToken();
                    sqlExpr = dateExpr;
                } else if (hash_lower == FnvHash.Constants.TIME
                        && (lexer.token == Token.LITERAL_CHARS || lexer.token == Token.VARIANT)) {
                    SQLTimeExpr dateExpr = new SQLTimeExpr(lexer.stringVal());
                    lexer.nextToken();
                    sqlExpr = dateExpr;
                } else if (hash_lower == FnvHash.Constants.TIME && lexer.token == Token.LITERAL_ALIAS) {
                    SQLTimeExpr dateExpr = new SQLTimeExpr(SQLUtils.normalize(lexer.stringVal()));
                    lexer.nextToken();
                    sqlExpr = dateExpr;
                } else if (hash_lower == FnvHash.Constants.DATETIME
                        && (lexer.token == Token.LITERAL_CHARS || lexer.token == Token.VARIANT)) {
                    SQLDateTimeExpr dateExpr = new SQLDateTimeExpr(lexer.stringVal());
                    lexer.nextToken();
                    sqlExpr = dateExpr;
                } else if (hash_lower == FnvHash.Constants.DATETIME && lexer.token == Token.LITERAL_ALIAS) {
                    SQLDateTimeExpr dateExpr = new SQLDateTimeExpr(SQLUtils.normalize(lexer.stringVal()));
                    lexer.nextToken();
                    sqlExpr = dateExpr;
                } else if (hash_lower == FnvHash.Constants.BOOLEAN && lexer.token == Token.LITERAL_CHARS) {
                    sqlExpr = new SQLBooleanExpr(Boolean.valueOf(lexer.stringVal()));
                    lexer.nextToken();
                } else if (hash_lower == FnvHash.Constants.DATE && lexer.token == Token.LITERAL_ALIAS) {
                    sqlExpr = new SQLDateExpr(lexer.stringVal());
                    lexer.nextToken();
                } else if (hash_lower == FnvHash.Constants.DATETIME && lexer.token == Token.LITERAL_ALIAS) {
                    sqlExpr = new SQLDateTimeExpr(lexer.stringVal());
                    lexer.nextToken();
                } else if (hash_lower == FnvHash.Constants.TIMESTAMP && lexer.token == Token.LITERAL_ALIAS) {
                    sqlExpr = new SQLTimestampExpr(lexer.stringVal());
                    lexer.nextToken();
                } else if (hash_lower == FnvHash.Constants.ARRAY && (lexer.token == Token.LBRACKET || lexer.token == Token.LT)) {
                    sqlExpr = parseArrayExpr(ident);
                } else {
                    sqlExpr = primaryIdentifierRest(hash_lower, ident);
                    if (sqlExpr == null) {
                        char c0 = ident.charAt(0);
                        if (c0 == '`' || c0 == '[' || c0 == '"') {
                            if (lexer.isEnabled(SQLParserFeature.IgnoreNameQuotes)) {
                                ident = ident.substring(1, ident.length() - 1);
                            }
                            hash_lower = FnvHash.hashCode64(ident);
                        }
                        SQLIdentifierExpr identifierExpr = new SQLIdentifierExpr(ident, hash_lower);
                        if (sourceLine != -1) {
                            identifierExpr.setSource(sourceLine, sourceColumn);
                        }
                        sqlExpr = identifierExpr;
                    }
                }
                break;
            case NEW:
                throw new ParserException("TODO " + lexer.info());
            case LITERAL_INT:
                Number number = lexer.integerValue();
                lexer.nextToken();

                if (lexer.identifierEquals(FnvHash.Constants.BD)) {
                    SQLDecimalExpr decimalExpr = new SQLDecimalExpr();
                    decimalExpr.setValue(new BigDecimal(number.intValue()));
                    lexer.nextToken();
                    sqlExpr = decimalExpr;
                } else {
                    sqlExpr = new SQLIntegerExpr(number);
                }
                break;
            case LITERAL_FLOAT:
                sqlExpr = lexer.numberExpr();
                lexer.nextToken();

                if (lexer.identifierEquals(FnvHash.Constants.BD)) {
                    SQLDecimalExpr decimalExpr = new SQLDecimalExpr();
                    decimalExpr.setValue(new BigDecimal(sqlExpr.toString()));
                    lexer.nextToken();
                    sqlExpr = decimalExpr;
                }

                break;
            case LITERAL_CHARS: {
                sqlExpr = new SQLCharExpr(lexer.stringVal());
                sqlExpr = primaryLiteralCharsRest(sqlExpr);
                break;
            }
            case LITERAL_NCHARS:
                sqlExpr = new SQLNCharExpr(lexer.stringVal());
                lexer.nextToken();
                sqlExpr = primaryLiteralNCharsRest(sqlExpr);
                break;
            case VARIANT: {
                if (lexer.keepSourceLocation) {
                    lexer.computeRowAndColumn();
                }
                int line = lexer.getPosLine(), column = lexer.getPosColumn();
                String varName = lexer.stringVal();
                lexer.nextToken();

                if (varName.equals(":") && lexer.token == Token.IDENTIFIER && dialectFeatureEnabled(PrimaryVariantColon)) {
                    String part2 = lexer.stringVal();
                    lexer.nextToken();
                    varName += part2;
                }

                SQLVariantRefExpr varRefExpr = new SQLVariantRefExpr(varName);
                varRefExpr.setSource(line, column);
                if (varName.startsWith(":")) {
                    varRefExpr.setIndex(lexer.nextVarIndex());
                }
                if (varRefExpr.getName().equals("@")
                        && (lexer.token == Token.LITERAL_CHARS || (lexer.token == Token.VARIANT && lexer.stringVal().startsWith("@")))) {
                    varRefExpr.setName("@'" + lexer.stringVal() + "'");
                    lexer.nextToken();
                } else if (varRefExpr.getName().equals("@@") && lexer.token == Token.LITERAL_CHARS) {
                    varRefExpr.setName("@@'" + lexer.stringVal() + "'");
                    lexer.nextToken();
                }
                sqlExpr = varRefExpr;
            }
            break;
            case DEFAULT:
                sqlExpr = primaryDefaultRest();
                lexer.nextToken();
                break;
            case DUAL:
            case KEY:
//            case DISTINCT:
            case LIMIT:
            case SCHEMA:
            case COLUMN:
            case IF:
            case END:
            case COMMENT:
            case COMPUTE:
            case ENABLE:
            case DISABLE:
            case INITIALLY:
            case SEQUENCE:
            case USER:
            case EXPLAIN:
            case WITH:
            case GRANT:
            case REPLACE:
            case INDEX:
//            case MODEL:
            case PCTFREE:
            case INITRANS:
            case MAXTRANS:
            case SEGMENT:
            case CREATION:
            case IMMEDIATE:
            case DEFERRED:
            case STORAGE:
            case NEXT:
            case MINEXTENTS:
            case MAXEXTENTS:
            case MAXSIZE:
            case PCTINCREASE:
            case FLASH_CACHE:
            case CELL_FLASH_CACHE:
            case NONE:
            case LOB:
            case STORE:
            case ROW:
            case CHUNK:
            case CACHE:
            case NOCACHE:
            case LOGGING:
            case NOCOMPRESS:
            case KEEP_DUPLICATES:
            case EXCEPTIONS:
            case PURGE:
            case FULL:
            case TO:
            case IDENTIFIED:
            case PASSWORD:
            case BINARY:
            case WINDOW:
            case OFFSET:
            case SHARE:
            case START:
            case CONNECT:
            case MATCHED:
            case ERRORS:
            case REJECT:
            case UNLIMITED:
            case BEGIN:
            case EXCLUSIVE:
            case MODE:
            case ADVISE:
            case VIEW:
            case ESCAPE:
            case OVER:
            case ORDER:
            case CONSTRAINT:
            case TYPE:
            case OPEN:
            case REPEAT:
            case TABLE:
            case TRUNCATE:
            case EXCEPTION:
            case FUNCTION:
            case IDENTITY:
            case EXTRACT:
            case DESC:
            case DO:
            case GROUP:
            case MOD:
            case CONCAT:
            case PRIMARY:
            case PARTITION:
            case LEAVE:
            case CLOSE:
            case CONDITION:
            case OUT:
            case USE:
            case EXCEPT:
            case INTERSECT:
            case MERGE:
            case MINUS:
            case UNTIL:
            case TOP:
            case SHOW:
            case INOUT:
            case OUTER:
            case QUALIFY:
            case GET:
                sqlExpr = new SQLIdentifierExpr(lexer.stringVal());
                lexer.nextToken();
                break;
            case CASE:
                SQLCaseExpr caseExpr = new SQLCaseExpr();
                lexer.nextToken();
                if (lexer.token != Token.WHEN) {
                    caseExpr.setValueExpr(expr());
                }

                accept(Token.WHEN);
                SQLExpr testExpr = expr();
                accept(Token.THEN);
                SQLExpr valueExpr = expr();
                SQLCaseExpr.Item caseItem = new SQLCaseExpr.Item(testExpr, valueExpr);
                caseExpr.addItem(caseItem);

                while (lexer.token == Token.WHEN) {
                    lexer.nextToken();
                    testExpr = expr();
                    accept(Token.THEN);
                    valueExpr = expr();
                    caseItem = new SQLCaseExpr.Item(testExpr, valueExpr);
                    caseExpr.addItem(caseItem);
                }

                if (lexer.token == Token.ELSE) {
                    lexer.nextToken();
                    caseExpr.setElseExpr(expr());
                }

                accept(Token.END);

                sqlExpr = caseExpr;
                break;
            case EXISTS: {
                String strVal = lexer.stringVal();
                lexer.nextToken();
                switch (lexer.token) {
                    case COMMA:
                    case DOT:
                        sqlExpr = new SQLIdentifierExpr(strVal);
                        break;
                    default:
                        accept(Token.LPAREN);
                        sqlExpr = new SQLExistsExpr(createSelectParser().select());
                        accept(Token.RPAREN);
                        parseQueryPlanHint(sqlExpr);
                        break;
                }

                break;
            }
            case NOT:
                lexer.nextToken();
                if (lexer.token == Token.EXISTS) {
                    lexer.nextToken();
                    accept(Token.LPAREN);
                    SQLExistsExpr exists = new SQLExistsExpr(createSelectParser().select(), true);
                    accept(Token.RPAREN);

                    parseQueryPlanHint(exists);
                    if (lexer.token == Token.EQ) {
                        exists.setNot(false);
                        SQLExpr relational = this.relationalRest(exists);
                        sqlExpr = new SQLNotExpr(relational);
                    } else {
                        sqlExpr = exists;
                    }
                } else if (lexer.token == Token.LPAREN) {
                    lexer.nextToken();

                    SQLExpr notTarget = expr();
                    if (notTarget instanceof SQLBinaryOpExpr) {
                        ((SQLBinaryOpExpr) notTarget).setParenthesized(true);
                    }
                    if (notTarget instanceof SQLUnaryExpr) {
                        ((SQLUnaryExpr) notTarget).setParenthesized(true);
                    }
                    accept(Token.RPAREN);
                    notTarget = bitXorRest(notTarget);
                    notTarget = multiplicativeRest(notTarget);
                    notTarget = additiveRest(notTarget);
                    notTarget = shiftRest(notTarget);
                    notTarget = bitAndRest(notTarget);
                    notTarget = bitOrRest(notTarget);
                    notTarget = inRest(notTarget);
                    notTarget = relationalRest(notTarget);
                    sqlExpr = new SQLNotExpr(notTarget);

                    parseQueryPlanHint(sqlExpr);
                    return primaryRest(sqlExpr);
                } else {
                    SQLExpr restExpr = relational();
                    sqlExpr = new SQLNotExpr(restExpr);
                    parseQueryPlanHint(sqlExpr);
                }
                break;
            case FROM:
            case SELECT:
                sqlExpr = parseQueryExpr();
                break;
            case CAST:
                sqlExpr = parseCast();
                break;
            case SUB:
                lexer.nextToken();
                switch (lexer.token) {
                    case LITERAL_INT:
                        Number integerValue = lexer.integerValue();
                        if (integerValue instanceof Integer) {
                            int intVal = integerValue.intValue();
                            if (intVal == Integer.MIN_VALUE) {
                                integerValue = Long.valueOf(((long) intVal) * -1);
                            } else {
                                integerValue = Integer.valueOf(intVal * -1);
                            }
                        } else if (integerValue instanceof Long) {
                            long longVal = ((Long) integerValue).longValue();
                            if (longVal == 2147483648L) {
                                integerValue = Integer.valueOf((int) (((long) longVal) * -1));
                            } else {
                                integerValue = Long.valueOf(longVal * -1);
                            }
                        } else {
                            integerValue = ((BigInteger) integerValue).negate();
                        }
                        sqlExpr = new SQLIntegerExpr(integerValue);
                        lexer.nextToken();
                        break;
                    case LITERAL_FLOAT:
                        sqlExpr = lexer.numberExpr(true);
                        lexer.nextToken();
                        break;
                    case LITERAL_CHARS:
                    case LITERAL_ALIAS:
                        sqlExpr = primarySubLiteralAliasRest();
                        lexer.nextToken();

                        if (lexer.token == Token.LPAREN
                                || lexer.token == Token.LBRACKET
                                || lexer.token == Token.DOT) {
                            sqlExpr = primaryRest(sqlExpr);
                        }
                        sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr);

                        break;
                    case QUES: {
                        SQLVariantRefExpr variantRefExpr = new SQLVariantRefExpr("?");
                        variantRefExpr.setIndex(lexer.nextVarIndex());
                        sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, variantRefExpr);
                        lexer.nextToken();
                        break;
                    }
                    case PLUS:
                    case SUB:
                    case LPAREN:
                    case IDENTIFIER:
                    case BANG:
                    case CASE:
                    case CAST:
                    case NULL:
                    case INTERVAL:
                    case LBRACE:
                    case IF:
                    case CHECK:
                    case INDEX:
                    case PRIMARY:
                    case KEY:
                    case REPLACE:
                        sqlExpr = primary();

                        while (lexer.token == Token.HINT) {
                            lexer.nextToken();
                        }

                        sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr);
                        break;
                    case VARIANT:
                        sqlExpr = primary();
                        sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Negative, sqlExpr);
                        break;
                    default:
                        throw new ParserException("TODO : " + lexer.info());
                }
                break;
            case PLUS:
                lexer.nextToken();
                switch (lexer.token) {
                    case LITERAL_CHARS:
                    case LITERAL_ALIAS:
                        sqlExpr = new SQLIdentifierExpr(lexer.stringVal());
                        sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Plus, sqlExpr);
                        lexer.nextToken();
                        break;
                    case QUES: {
                        SQLVariantRefExpr variantRefExpr = new SQLVariantRefExpr("?");
                        variantRefExpr.setIndex(lexer.nextVarIndex());
                        sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Plus, variantRefExpr);
                        lexer.nextToken();
                        break;
                    }
                    case PLUS:
                    case SUB:
                    case LITERAL_FLOAT:
                    case LITERAL_INT:
                    case LPAREN:
                    case IDENTIFIER:
                    case BANG:
                    case CASE:
                    case CAST:
                    case NULL:
                    case INTERVAL:
                    case LBRACE:
                    case IF:
                    case CHECK:
                    case REPLACE:
                        sqlExpr = primary();

                        while (lexer.token == Token.HINT) {
                            lexer.nextToken();
                        }

                        sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Plus, sqlExpr);
                        break;
                    default:
                        throw new ParserException("TODO " + lexer.info());
                }
                break;
            case TILDE:
                lexer.nextToken();
                SQLExpr unaryValueExpr = primary();
                SQLUnaryExpr unary = new SQLUnaryExpr(SQLUnaryOperator.Compl, unaryValueExpr);
                sqlExpr = unary;
                break;
            case QUES:
                primaryQues();
                SQLVariantRefExpr quesVarRefExpr = new SQLVariantRefExpr("?");
                quesVarRefExpr.setIndex(lexer.nextVarIndex());
                sqlExpr = quesVarRefExpr;
                break;
            case LEFT:
                sqlExpr = new SQLIdentifierExpr("LEFT");
                lexer.nextToken();
                break;
            case RIGHT:
                sqlExpr = new SQLIdentifierExpr("RIGHT");
                lexer.nextToken();
                break;
            case INNER:
                sqlExpr = new SQLIdentifierExpr("INNER");
                lexer.nextToken();
                break;
            case DATABASE:
                sqlExpr = new SQLIdentifierExpr("DATABASE");
                lexer.nextToken();
                break;
            case CASCADE:
                sqlExpr = new SQLIdentifierExpr("CASCADE");
                lexer.nextToken();
                break;
            case LOCK:
                sqlExpr = new SQLIdentifierExpr("LOCK");
                lexer.nextToken();
                break;
            case NULL:
                sqlExpr = new SQLNullExpr();
                lexer.nextToken();
                break;
            case BANG:
                lexer.nextToken();
                sqlExpr = new SQLUnaryExpr(
                        SQLUnaryOperator.Not,
                        primary()
                );
                break;
            case BANGBANG: {
                if (!dialectFeatureEnabled(PrimaryBangBangSupport)) {
                    throw new ParserException(lexer.info());
                }
                lexer.nextToken();
                sqlExpr = new SQLUnaryExpr(
                        SQLUnaryOperator.Not,
                        primary()
                );
                break;
            }
            case BANG_TILDE: {
                lexer.nextToken();
                SQLExpr bangExpr = primary();
                sqlExpr = new SQLUnaryExpr(SQLUnaryOperator.Not, new SQLUnaryExpr(SQLUnaryOperator.Compl, bangExpr));
                break;
            }
            case LITERAL_HEX:
                String hex = lexer.hexString();
                sqlExpr = new SQLHexExpr(hex);
                lexer.nextToken();
                break;
            case INTERVAL:
                sqlExpr = parseInterval();
                break;
            case COLON:
                lexer.nextToken();
                if (lexer.token == Token.LITERAL_ALIAS) {
                    sqlExpr = new SQLVariantRefExpr(":\"" + lexer.stringVal() + "\"");
                    lexer.nextToken();
                }
                break;
            case ANY:
                sqlExpr = parseAny();
                break;
            case SOME:
                sqlExpr = parseSome();
                break;
            case ALL:
                sqlExpr = parseAll();
                break;
            case LITERAL_ALIAS:
                sqlExpr = parseAliasExpr(lexer.stringVal());
                lexer.nextToken();
                break;
            case EOF:
                throw new EOFParserException();
            case TRUE:
                lexer.nextToken();
                sqlExpr = new SQLBooleanExpr(true);
                break;
            case FALSE:
                lexer.nextToken();
                sqlExpr = new SQLBooleanExpr(false);
                break;
            case BITS: {
                String strVal = lexer.stringVal();
                lexer.nextToken();
                sqlExpr = new SQLBinaryExpr(strVal);
                break;
            }
            case GLOBAL:
            case CONTAINS:
                sqlExpr = inRest(null);
                break;
            case SET: {
                Lexer.SavePoint savePoint = lexer.mark();
                lexer.nextToken();
                if (lexer.token == Token.SET && dialectFeatureEnabled(PrimaryTwoConsecutiveSet)) {
                    lexer.nextToken();
                }
                if (lexer.token() == Token.LPAREN) {
                    sqlExpr = new SQLIdentifierExpr("SET");
                } else if (lexer.token == Token.DOT) {
                    sqlExpr = new SQLIdentifierExpr("SET");
                    sqlExpr = this.primaryRest(sqlExpr);
                } else {
                    lexer.reset(savePoint);
                    throw new ParserException("ERROR. " + lexer.info());
                }
                break;
            }
            case LBRACE: {
                lexer.nextToken();
                if (lexer.identifierEquals(FnvHash.Constants.TS)) {
                    lexer.nextToken();
                    String literal = lexer.stringVal();
                    lexer.nextToken();
                    sqlExpr = new SQLTimestampExpr(literal);
                } else if (lexer.identifierEquals(FnvHash.Constants.D)
                        || lexer.identifierEquals(FnvHash.Constants.DATE)
                ) {
                    lexer.nextToken();
                    String literal = lexer.stringVal();
                    if (literal.length() > 2
                            && literal.charAt(0) == '"'
                            && literal.charAt(literal.length() - 1) == '"') {
                        literal = literal.substring(1, literal.length() - 1);
                    }
                    lexer.nextToken();
                    sqlExpr = new SQLDateExpr(literal);
                } else if (lexer.identifierEquals(FnvHash.Constants.T)) {
                    lexer.nextToken();
                    String literal = lexer.stringVal();
                    lexer.nextToken();
                    sqlExpr = new SQLTimeExpr(literal);
                } else if (lexer.identifierEquals(FnvHash.Constants.FN)) {
                    lexer.nextToken();
                    sqlExpr = this.expr();
                } else if (dialectFeatureEnabled(PrimaryLbraceOdbcEscape)) {
                    sqlExpr = this.expr(); // {identifier expr} is ODBC escape syntax and is accepted for ODBC compatibility.
                } else if (lexer.nextIf(LBRACE)) {
                    // support dbt style: {{ source(a,b) }} as identifier
                    sqlExpr = new SQLPatternExpr(this.expr());
                    // skip }
                    accept(RBRACE);
                } else {
                    throw new ParserException("ERROR. " + lexer.info());
                }
                accept(Token.RBRACE);
                break;
            }
            case VALUES:
            case TRIGGER:
            case FOR:
            case CHECK:
            case DELETE:
            case BY:
            case UPDATE:
            case LOOP:
            case LIKE:
            case UNION:
            case CREATE:
            case COMMA:
            case STAR:
            case DIV:
            case DISTRIBUTE:
            case UNIQUE:
            case PROCEDURE:
            case REFERENCES:
            case IS:
            case REVOKE:
            case DECLARE:
            case DROP:
            case RLIKE:
            case FOREIGN:
            case FETCH:
            case ASC:
            case CURSOR:
            case ALTER:
                sqlExpr = primaryCommon(sqlExpr);
                break;
            case AS: {
                sqlExpr = primaryAs(sqlExpr);
                break;
            }
            case DISTINCT:
                sqlExpr = primaryDistinct(sqlExpr);
                break;
            case BETWEEN:
            case IN:
                sqlExpr = primaryIn(sqlExpr);
                break;
            case LBRACKET:
                SQLArrayExpr arrayTmp = new SQLArrayExpr();
                lexer.nextToken();
                this.exprList(arrayTmp.getValues(), arrayTmp);
                accept(Token.RBRACKET);
                sqlExpr = arrayTmp;
                break;
            case ON:
                sqlExpr = primaryOn(sqlExpr);
                break;
            case COLONCOLON:
                sqlExpr = primaryColonColon(sqlExpr);
                break;
            case ARRAY: {
                SQLArrayExpr array = new SQLArrayExpr();
                array.setExpr(new SQLIdentifierExpr("ARRAY"));
                lexer.nextToken();
                if (lexer.nextIf(Token.LT)) {
                    SQLDataType sqlDataType = this.parseDataType();
                    array.setDataType(sqlDataType);
                    accept(Token.GT);
                }
                if (lexer.nextIf(Token.LBRACKET)) {
                    this.exprList(array.getValues(), array);
                    accept(Token.RBRACKET);
                } else {
                    throw new ParserException("Syntax error. " + lexer.info());
                }

                sqlExpr = array;
                break;
            }
            case LITERAL_TEXT_BLOCK:
                sqlExpr = new SQLCharExpr(lexer.stringVal());
                lexer.nextToken();
                break;
            default:
                throw new ParserException("ERROR. " + lexer.info());
        }

        SQLExpr expr = primaryRest(sqlExpr);

        if (beforeComments != null) {
            expr.addBeforeComment(beforeComments);
        }
        if (lexer.hasComment() && lexer.isKeepComments()) {
            // @todo 是否保留注释,暂时待定,因为保留的话,有20来个测试用例会失败 by lizongbo
            // expr.addAfterComment(lexer.readAndResetComments());
        }
        return expr;
    }