public boolean visit(SQLIdentifierExpr x) {
    String currentTable = getCurrentTable();

    if (subQueryMap.containsKey(currentTable)) {
      return false;
    }

    String ident = x.toString();

    if (variants.containsKey(ident)) {
      return false;
    }

    Column column;
    if (currentTable != null) {
      column = addColumn(currentTable, ident);
      x.putAttribute(ATTR_COLUMN, column);
    } else {
      column = handleUnkownColumn(ident);
      if (column != null) {
        x.putAttribute(ATTR_COLUMN, column);
      }
    }
    if (column != null) {
      setColumn(x, column);
    }
    return false;
  }
  @Override
  public boolean visit(SQLCreateIndexStatement x) {
    setMode(x, Mode.CreateIndex);

    SQLName name = (SQLName) ((SQLExprTableSource) x.getTable()).getExpr();

    String table = name.toString();
    setCurrentTable(table);

    TableStat stat = getTableStat(table);
    stat.incrementDropIndexCount();

    Map<String, String> aliasMap = getAliasMap();
    if (aliasMap != null) {
      aliasMap.put(table, table);
    }

    for (SQLSelectOrderByItem item : x.getItems()) {
      SQLExpr expr = item.getExpr();
      if (expr instanceof SQLIdentifierExpr) {
        SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;
        String columnName = identExpr.getName();
        addColumn(table, columnName);
      }
    }

    return false;
  }
  public static boolean visit(MappingVisitor visitor, SQLIdentifierExpr x) {
    String propertyName = x.getName();

    Property property = null;
    for (Entity entity : visitor.getEntities().values()) {
      property = entity.getProperty(propertyName);
      if (property != null) {
        break;
      }
    }

    if (property == null) {
      throw new DruidMappingException("property not found : " + propertyName);
    }

    String dbColumName = property.getDbColumnName();
    x.setName(dbColumName);

    if (x.getParent() instanceof SQLSelectItem) {
      SQLSelectItem selectItem = (SQLSelectItem) x.getParent();
      if (selectItem.getAlias() == null) {
        selectItem.setAlias('"' + property.getName() + '"');
      }
    }

    return false;
  }
  public void test_binary() throws Exception {
    SQLExprParser exprParser = new SQLExprParser("AGE > 5");
    SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) exprParser.expr();

    Assert.assertEquals(SQLBinaryOperator.GreaterThan, binaryOpExpr.getOperator());

    SQLIdentifierExpr left = (SQLIdentifierExpr) binaryOpExpr.getLeft();
    SQLIntegerExpr right = (SQLIntegerExpr) binaryOpExpr.getRight();

    Assert.assertEquals("AGE", left.getName());
    Assert.assertEquals(5, right.getNumber().intValue());
  }
    public boolean visit(SQLIdentifierExpr x) {
      if (subQueryMap.containsKey(currentTable)) {
        return false;
      }

      if (currentTable != null) {
        addOrderByColumn(currentTable, x.getName(), x);
      } else {
        addOrderByColumn("UNKOWN", x.getName(), x);
      }
      return false;
    }
 public boolean visit(SQLIdentifierExpr x) {
   String name = x.getName();
   name = WallVisitorUtils.form(name);
   if (config.isVariantCheck() && config.getDenyVariants().contains(name)) {
     getViolations()
         .add(
             new IllegalSQLObjectViolation(
                 ErrorCode.VARIANT_DENY, "variable not allow : " + name, toSQL(x)));
   }
   return true;
 }
  public static boolean visit(MappingVisitor visitor, SQLExprTableSource x) {
    SQLExpr expr = x.getExpr();

    if (expr instanceof SQLIdentifierExpr) {
      SQLIdentifierExpr tableExpr = (SQLIdentifierExpr) expr;
      String entityName = tableExpr.getName();

      Entity entity = visitor.getEntity(entityName);

      if (entity == null) {
        throw new DruidMappingException("entity not foudn : " + entityName);
      }

      tableExpr.setName(entity.getTableName());
    }

    if (x.getAlias() != null) {
      visitor.getTableSources().put(x.getAlias(), x);
    }

    return false;
  }
  public final SQLExpr primaryRest(SQLExpr expr) {
    if (expr == null) {
      throw new IllegalArgumentException("expr");
    }

    if (lexer.token() == Token.LITERAL_CHARS) {
      if (expr instanceof SQLIdentifierExpr) {
        SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;
        String ident = identExpr.getName();

        if (ident.equalsIgnoreCase("x")) {
          String charValue = lexer.stringVal();
          lexer.nextToken();
          expr = new SQLHexExpr(charValue);

          return primaryRest(expr);
        } else if (ident.equalsIgnoreCase("b")) {
          String charValue = lexer.stringVal();
          lexer.nextToken();
          expr = new SQLBinaryExpr(charValue);

          return primaryRest(expr);
        } else if (ident.startsWith("_")) {
          String charValue = lexer.stringVal();
          lexer.nextToken();

          MySqlCharExpr mysqlCharExpr = new MySqlCharExpr(charValue);
          mysqlCharExpr.setCharset(identExpr.getName());
          if (identifierEquals("COLLATE")) {
            lexer.nextToken();

            String collate = lexer.stringVal();
            mysqlCharExpr.setCollate(collate);
            accept(Token.IDENTIFIER);
          }

          expr = mysqlCharExpr;

          return primaryRest(expr);
        }
      } else if (expr instanceof SQLCharExpr) {
        SQLMethodInvokeExpr concat = new SQLMethodInvokeExpr("CONCAT");
        concat.addParameter(expr);
        do {
          String chars = lexer.stringVal();
          concat.addParameter(new SQLCharExpr(chars));
          lexer.nextToken();
        } while (lexer.token() == Token.LITERAL_CHARS || lexer.token() == Token.LITERAL_ALIAS);
        expr = concat;
      }
    } else if (lexer.token() == Token.IDENTIFIER) {
      if (expr instanceof SQLHexExpr) {
        if ("USING".equalsIgnoreCase(lexer.stringVal())) {
          lexer.nextToken();
          if (lexer.token() != Token.IDENTIFIER) {
            throw new ParserException("syntax error, illegal hex");
          }
          String charSet = lexer.stringVal();
          lexer.nextToken();
          expr.getAttributes().put("USING", charSet);

          return primaryRest(expr);
        }
      } else if ("COLLATE".equalsIgnoreCase(lexer.stringVal())) {
        lexer.nextToken();

        if (lexer.token() == Token.EQ) {
          lexer.nextToken();
        }

        if (lexer.token() != Token.IDENTIFIER) {
          throw new ParserException("syntax error");
        }

        String collate = lexer.stringVal();
        lexer.nextToken();

        SQLBinaryOpExpr binaryExpr =
            new SQLBinaryOpExpr(
                expr,
                SQLBinaryOperator.COLLATE,
                new SQLIdentifierExpr(collate),
                JdbcConstants.MYSQL);

        expr = binaryExpr;

        return primaryRest(expr);
      } else if (expr instanceof SQLVariantRefExpr) {
        if ("COLLATE".equalsIgnoreCase(lexer.stringVal())) {
          lexer.nextToken();

          if (lexer.token() != Token.IDENTIFIER) {
            throw new ParserException("syntax error");
          }

          String collate = lexer.stringVal();
          lexer.nextToken();

          expr.putAttribute("COLLATE", collate);

          return primaryRest(expr);
        }
      } else if (expr instanceof SQLIntegerExpr) {
        SQLIntegerExpr intExpr = (SQLIntegerExpr) expr;
        String binaryString = lexer.stringVal();
        if (intExpr.getNumber().intValue() == 0 && binaryString.startsWith("b")) {
          lexer.nextToken();
          expr = new SQLBinaryExpr(binaryString.substring(1));

          return primaryRest(expr);
        }
      }
    }

    if (lexer.token() == Token.LPAREN && expr instanceof SQLIdentifierExpr) {
      SQLIdentifierExpr identExpr = (SQLIdentifierExpr) expr;
      String ident = identExpr.getName();

      if ("EXTRACT".equalsIgnoreCase(ident)) {
        lexer.nextToken();

        if (lexer.token() != Token.IDENTIFIER) {
          throw new ParserException("syntax error");
        }

        String unitVal = lexer.stringVal();
        MySqlIntervalUnit unit = MySqlIntervalUnit.valueOf(unitVal.toUpperCase());
        lexer.nextToken();

        accept(Token.FROM);

        SQLExpr value = expr();

        MySqlExtractExpr extract = new MySqlExtractExpr();
        extract.setValue(value);
        extract.setUnit(unit);
        accept(Token.RPAREN);

        expr = extract;

        return primaryRest(expr);
      } else if ("SUBSTRING".equalsIgnoreCase(ident)) {
        lexer.nextToken();
        SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(ident);
        for (; ; ) {
          SQLExpr param = expr();
          methodInvokeExpr.addParameter(param);

          if (lexer.token() == Token.COMMA) {
            lexer.nextToken();
            continue;
          } else if (lexer.token() == Token.FROM) {
            lexer.nextToken();
            SQLExpr from = expr();
            methodInvokeExpr.addParameter(from);

            if (lexer.token() == Token.FOR) {
              lexer.nextToken();
              SQLExpr forExpr = expr();
              methodInvokeExpr.addParameter(forExpr);
            }
            break;
          } else if (lexer.token() == Token.RPAREN) {
            break;
          } else {
            throw new ParserException("syntax error");
          }
        }

        accept(Token.RPAREN);
        expr = methodInvokeExpr;

        return primaryRest(expr);
      } else if ("TRIM".equalsIgnoreCase(ident)) {
        lexer.nextToken();
        SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(ident);

        if (lexer.token() == Token.IDENTIFIER) {
          String flagVal = lexer.stringVal();
          if ("LEADING".equalsIgnoreCase(flagVal)) {
            lexer.nextToken();
            methodInvokeExpr.getAttributes().put("TRIM_TYPE", "LEADING");
          } else if ("BOTH".equalsIgnoreCase(flagVal)) {
            lexer.nextToken();
            methodInvokeExpr.getAttributes().put("TRIM_TYPE", "BOTH");
          } else if ("TRAILING".equalsIgnoreCase(flagVal)) {
            lexer.nextToken();
            methodInvokeExpr.putAttribute("TRIM_TYPE", "TRAILING");
          }
        }

        SQLExpr param = expr();
        methodInvokeExpr.addParameter(param);

        if (lexer.token() == Token.FROM) {
          lexer.nextToken();
          SQLExpr from = expr();
          methodInvokeExpr.putAttribute("FROM", from);
        }

        accept(Token.RPAREN);
        expr = methodInvokeExpr;

        return primaryRest(expr);
      } else if ("MATCH".equalsIgnoreCase(ident)) {
        lexer.nextToken();
        MySqlMatchAgainstExpr matchAgainstExpr = new MySqlMatchAgainstExpr();

        if (lexer.token() == Token.RPAREN) {
          lexer.nextToken();
        } else {
          exprList(matchAgainstExpr.getColumns(), matchAgainstExpr);
          accept(Token.RPAREN);
        }

        acceptIdentifier("AGAINST");

        accept(Token.LPAREN);
        SQLExpr against = primary();
        matchAgainstExpr.setAgainst(against);

        if (lexer.token() == Token.IN) {
          lexer.nextToken();
          if (identifierEquals("NATURAL")) {
            lexer.nextToken();
            acceptIdentifier("LANGUAGE");
            acceptIdentifier("MODE");
            if (lexer.token() == Token.WITH) {
              lexer.nextToken();
              acceptIdentifier("QUERY");
              acceptIdentifier("EXPANSION");
              matchAgainstExpr.setSearchModifier(
                  SearchModifier.IN_NATURAL_LANGUAGE_MODE_WITH_QUERY_EXPANSION);
            } else {
              matchAgainstExpr.setSearchModifier(SearchModifier.IN_NATURAL_LANGUAGE_MODE);
            }
          } else if (identifierEquals("BOOLEAN")) {
            lexer.nextToken();
            acceptIdentifier("MODE");
            matchAgainstExpr.setSearchModifier(SearchModifier.IN_BOOLEAN_MODE);
          } else {
            throw new ParserException("TODO");
          }
        } else if (lexer.token() == Token.WITH) {
          throw new ParserException("TODO");
        }

        accept(Token.RPAREN);

        expr = matchAgainstExpr;

        return primaryRest(expr);
      } else if (("CONVERT".equalsIgnoreCase(ident)) || ("CHAR".equalsIgnoreCase(ident))) {
        lexer.nextToken();
        SQLMethodInvokeExpr methodInvokeExpr = new SQLMethodInvokeExpr(ident);

        if (lexer.token() != Token.RPAREN) {
          exprList(methodInvokeExpr.getParameters(), methodInvokeExpr);
        }

        if (identifierEquals("USING")) {
          lexer.nextToken();
          if (lexer.token() != Token.IDENTIFIER) {
            throw new ParserException("syntax error");
          }
          String charset = lexer.stringVal();
          lexer.nextToken();
          methodInvokeExpr.putAttribute("USING", charset);
        }

        accept(Token.RPAREN);

        expr = methodInvokeExpr;

        return primaryRest(expr);
      } else if ("POSITION".equalsIgnoreCase(ident)) {
        accept(Token.LPAREN);
        SQLExpr subStr = this.primary();
        accept(Token.IN);
        SQLExpr str = this.expr();
        accept(Token.RPAREN);

        SQLMethodInvokeExpr locate = new SQLMethodInvokeExpr("LOCATE");
        locate.addParameter(subStr);
        locate.addParameter(str);

        expr = locate;
        return primaryRest(expr);
      }
    }

    if (lexer.token() == Token.VARIANT && "@".equals(lexer.stringVal())) {
      lexer.nextToken();
      MySqlUserName userName = new MySqlUserName();
      if (expr instanceof SQLCharExpr) {
        userName.setUserName(((SQLCharExpr) expr).toString());
      } else {
        userName.setUserName(((SQLIdentifierExpr) expr).getName());
      }

      if (lexer.token() == Token.LITERAL_CHARS) {
        userName.setHost("'" + lexer.stringVal() + "'");
      } else {
        userName.setHost(lexer.stringVal());
      }
      lexer.nextToken();
      return userName;
    }

    if (lexer.token() == Token.ERROR) {
      throw new ParserException(
          "syntax error, token: "
              + lexer.token()
              + " "
              + lexer.stringVal()
              + ", pos : "
              + lexer.pos());
    }

    return super.primaryRest(expr);
  }