All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.pingcap.tikv.parser.AstBuilder Maven / Gradle / Ivy

There is a newer version: 3.2.3
Show newest version
/*
 * Copyright 2020 PingCAP, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.pingcap.tikv.parser;

import static com.pingcap.tikv.types.IntegerType.BOOLEAN;

import com.google.common.primitives.Doubles;
import com.pingcap.tikv.exception.UnsupportedSyntaxException;
import com.pingcap.tikv.expression.ArithmeticBinaryExpression;
import com.pingcap.tikv.expression.ColumnRef;
import com.pingcap.tikv.expression.ComparisonBinaryExpression;
import com.pingcap.tikv.expression.Constant;
import com.pingcap.tikv.expression.Expression;
import com.pingcap.tikv.expression.FuncCallExpr;
import com.pingcap.tikv.expression.FuncCallExpr.Type;
import com.pingcap.tikv.expression.LogicalBinaryExpression;
import com.pingcap.tikv.meta.TiTableInfo;
import com.pingcap.tikv.parser.MySqlParser.ExpressionContext;
import com.pingcap.tikv.parser.MySqlParser.FunctionNameBaseContext;
import com.pingcap.tikv.types.IntegerType;
import com.pingcap.tikv.types.RealType;
import org.antlr.v4.runtime.tree.TerminalNode;

// AstBuilder will convert ParseTree into Ast Node.
// In tikv java client, we only need to parser expression
// which is used by partition pruning.
public class AstBuilder extends MySqlParserBaseVisitor {
  private TiTableInfo tableInfo;

  public AstBuilder() {}

  public AstBuilder(TiTableInfo tableInfo) {
    this.tableInfo = tableInfo;
  }

  public Expression visitSimpleId(MySqlParser.SimpleIdContext ctx) {
    if (ctx.ID() != null) {
      return createColRef(ctx.ID().getSymbol().getText());
    }

    if (ctx.functionNameBase() != null) {
      return createColRef(ctx.functionNameBase().getText());
    }

    throw new UnsupportedSyntaxException(ctx.getParent().toString() + ": it is not supported");
  }

  private Expression createColRef(String id) {
    if (tableInfo != null) {
      return ColumnRef.create(id, tableInfo);
    } else {
      return ColumnRef.create(id);
    }
  }

  @Override
  public Expression visitUid(MySqlParser.UidContext ctx) {
    if (ctx.REVERSE_QUOTE_ID() != null) {
      return createColRef(ctx.REVERSE_QUOTE_ID().getSymbol().getText());
    }
    return visitSimpleId(ctx.simpleId());
  }

  @Override
  public Expression visitScalarFunctionCall(MySqlParser.ScalarFunctionCallContext ctx) {
    FunctionNameBaseContext fnNameCtx = ctx.scalarFunctionName().functionNameBase();
    if (fnNameCtx != null) {
      if (fnNameCtx.YEAR() != null) {
        Expression args = visitFunctionArgs(ctx.functionArgs());
        return new FuncCallExpr(args, Type.YEAR);
      }
    }
    return visitChildren(ctx);
  }

  @Override
  public Expression visitFullColumnName(MySqlParser.FullColumnNameContext ctx) {
    return visitUid(ctx.uid());
  }

  private Expression parseIntOrLongOrDec(String val) {
    try {
      return Constant.create(Integer.parseInt(val), IntegerType.INT);
    } catch (Exception e) {
      try {
        return Constant.create(Long.parseLong(val), IntegerType.BIGINT);
      } catch (Exception e2) {
        return Constant.create(Double.parseDouble(val), RealType.DOUBLE);
      }
    }
  }

  @Override
  public Expression visitDecimalLiteral(MySqlParser.DecimalLiteralContext ctx) {
    if (ctx.ONE_DECIMAL() != null) {
      String val = ctx.ONE_DECIMAL().getSymbol().getText();
      return parseIntOrLongOrDec(val);
    }
    if (ctx.TWO_DECIMAL() != null) {
      String val = ctx.TWO_DECIMAL().getSymbol().getText();
      return parseIntOrLongOrDec(val);
    }
    if (ctx.DECIMAL_LITERAL() != null) {
      String val = ctx.DECIMAL_LITERAL().getSymbol().getText();
      return parseIntOrLongOrDec(val);
    }

    if (ctx.ZERO_DECIMAL() != null) {
      String val = ctx.ZERO_DECIMAL().getSymbol().getText();
      return parseIntOrLongOrDec(val);
    }

    throw new UnsupportedSyntaxException(ctx.toString() + ": it is not supported.");
  }

  @Override
  public Expression visitBooleanLiteral(MySqlParser.BooleanLiteralContext ctx) {
    if (ctx.FALSE() != null) return Constant.create(0);
    return Constant.create(1, BOOLEAN);
  }

  @Override
  public Expression visitStringLiteral(MySqlParser.StringLiteralContext ctx) {
    if (ctx.STRING_LITERAL() != null) {
      StringBuilder sb = new StringBuilder();
      for (TerminalNode str : ctx.STRING_LITERAL()) {
        sb.append(str.getSymbol().getText());
      }
      return Constant.create(sb.toString().replace("\"", ""));
    }
    throw new UnsupportedSyntaxException(ctx.toString() + " is not supported yet");
  }

  @Override
  public Expression visitConstant(MySqlParser.ConstantContext ctx) {
    if (ctx.nullLiteral != null) {
      return Constant.create(null);
    }

    if (ctx.booleanLiteral() != null) {
      return visitBooleanLiteral(ctx.booleanLiteral());
    }

    if (ctx.decimalLiteral() != null) {
      return visitDecimalLiteral(ctx.decimalLiteral());
    }

    if (ctx.stringLiteral() != null) {
      return visitStringLiteral(ctx.stringLiteral());
    }

    if (ctx.REAL_LITERAL() != null) {
      return Constant.create(
          Doubles.tryParse(ctx.REAL_LITERAL().getSymbol().getText()), RealType.REAL);
    }

    throw new UnsupportedSyntaxException(ctx.toString() + "not supported constant");
  }

  @Override
  public Expression visitConstantExpressionAtom(MySqlParser.ConstantExpressionAtomContext ctx) {
    return visitChildren(ctx);
  }

  @Override
  public Expression visitBinaryComparisonPredicate(
      MySqlParser.BinaryComparisonPredicateContext ctx) {
    Expression left = visitChildren(ctx.left);
    Expression right = visitChildren(ctx.right);
    switch (ctx.comparisonOperator().getText()) {
      case "<":
        return ComparisonBinaryExpression.lessThan(left, right);
      case "<=":
        return ComparisonBinaryExpression.lessEqual(left, right);
      case "=":
        return ComparisonBinaryExpression.equal(left, right);
      case ">":
        return ComparisonBinaryExpression.greaterThan(left, right);
      case ">=":
        return ComparisonBinaryExpression.greaterEqual(left, right);
    }

    throw new UnsupportedSyntaxException(
        ctx.toString() + ": it is not possible reach to this line of code");
  }

  public Expression visitLogicalExpression(MySqlParser.LogicalExpressionContext ctx) {
    ExpressionContext left = ctx.expression(0);
    ExpressionContext right = ctx.expression(1);
    switch (ctx.logicalOperator().getText()) {
      case "and":
        return LogicalBinaryExpression.and(visitChildren(left), visitChildren(right));
      case "or":
        return LogicalBinaryExpression.or(visitChildren(left), visitChildren(right));
      case "xor":
        return LogicalBinaryExpression.xor(visitChildren(left), visitChildren(right));
    }

    throw new UnsupportedSyntaxException(
        ctx.toString() + ": it is not possible reach to this line of code");
  }

  @Override
  public Expression visitMathExpressionAtom(MySqlParser.MathExpressionAtomContext ctx) {
    Expression left = visitChildren(ctx.left);
    Expression right = visitChildren(ctx.right);
    switch (ctx.mathOperator().getText()) {
      case "+":
        return ArithmeticBinaryExpression.plus(left, right);
      case "-":
        return ArithmeticBinaryExpression.minus(left, right);
      case "*":
        return ArithmeticBinaryExpression.multiply(left, right);
      case "/":
      case "div":
        return ArithmeticBinaryExpression.divide(left, right);
    }
    throw new UnsupportedSyntaxException(ctx.toString() + ": it is not supported right now");
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy