Commit ec82c41f authored by terrymanu's avatar terrymanu
Browse files

refactor ExpressionExtractor

parent e5a0eecc
Loading
Loading
Loading
Loading
+59 −36
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
package io.shardingsphere.core.parsing.antlr.extractor.impl;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import io.shardingsphere.core.parsing.antlr.extractor.OptionalSQLSegmentExtractor;
import io.shardingsphere.core.parsing.antlr.extractor.util.ExtractorUtils;
import io.shardingsphere.core.parsing.antlr.extractor.util.RuleName;
@@ -27,7 +28,6 @@ import io.shardingsphere.core.parsing.antlr.sql.segment.expr.ExpressionSegment;
import io.shardingsphere.core.parsing.antlr.sql.segment.expr.FunctionExpressionSegment;
import io.shardingsphere.core.parsing.antlr.sql.segment.expr.PropertyExpressionSegment;
import io.shardingsphere.core.parsing.antlr.sql.segment.expr.StarExpressionSegment;
import io.shardingsphere.core.parsing.antlr.sql.segment.expr.SubquerySegment;
import io.shardingsphere.core.parsing.lexer.token.Symbol;
import io.shardingsphere.core.util.SQLUtil;
import org.antlr.v4.runtime.ParserRuleContext;
@@ -43,53 +43,58 @@ import java.util.HashMap;
 */
public final class ExpressionExtractor implements OptionalSQLSegmentExtractor {
    
    private final SubqueryExtractor subqueryExtractor = new SubqueryExtractor();
    
    @Override
    public Optional<ExpressionSegment> extract(final ParserRuleContext expressionNode) {
    public Optional<? extends ExpressionSegment> extract(final ParserRuleContext expressionNode) {
        String firstChildText = expressionNode.getText();
        if (firstChildText.endsWith(Symbol.STAR.getLiterals())) {
            int position = firstChildText.indexOf(Symbol.DOT.getLiterals());
            Optional<String> owner = Optional.absent();
            if (0 < position) {
                owner = Optional.of(SQLUtil.getExactlyValue(firstChildText.substring(0, position)));
            }
            return Optional.<ExpressionSegment>of(new StarExpressionSegment(expressionNode.getStart().getStartIndex(), owner));
            return Optional.of(getStarExpressionSegment(expressionNode, firstChildText));
        }
        Optional<ParserRuleContext> subqueryNode = ExtractorUtils.findFirstChildNode(expressionNode, RuleName.SUBQUERY);
        if (subqueryNode.isPresent()) {
            Optional<SubquerySegment> subquerySegment = new SubqueryExtractor().extract(subqueryNode.get());
            if (subquerySegment.isPresent()) {
                return Optional.<ExpressionSegment>of(subquerySegment.get());
        return subqueryNode.isPresent() ? subqueryExtractor.extract(subqueryNode.get()) : Optional.of(fillForPropertyOrFunction(expressionNode));
    }
            return Optional.absent();
    
    private ExpressionSegment getStarExpressionSegment(final ParserRuleContext expressionNode, final String text) {
        StarExpressionSegment result = new StarExpressionSegment(expressionNode.getStart().getStartIndex());
        if (text.contains(Symbol.DOT.getLiterals())) {
            result.setOwner(SQLUtil.getExactlyValue(text.substring(0, text.indexOf(Symbol.DOT.getLiterals()))));
        }
        return fillForPropertyOrFunction(expressionNode);
        return result;
    }
    
    private Optional<ExpressionSegment> fillForPropertyOrFunction(final ParserRuleContext node) {
        Optional<ParserRuleContext> aliasNode = ExtractorUtils.findFirstChildNode(node, RuleName.ALIAS);
        Optional<String> alias = aliasNode.isPresent() ? Optional.of(SQLUtil.getExactlyValue(aliasNode.get().getText())) : Optional.<String>absent();
        Optional<ParserRuleContext> functionCall = ExtractorUtils.findFirstChildNode(node, RuleName.FUNCTION_CALL);
        if (functionCall.isPresent()) {
            String name = functionCall.get().getChild(0).getText();
            int startIndex = ((TerminalNode) functionCall.get().getChild(1)).getSymbol().getStartIndex();
            boolean hasDistinct = hasDistinct(node);
            int distinctColumnNameStartPosition = hasDistinct ? calculateDistinctColumnNamePosition(functionCall.get()) : -1;
            FunctionExpressionSegment functionExpressionSegment = new FunctionExpressionSegment(name, functionCall.get().getStart().getStartIndex(),
                    startIndex, functionCall.get().getStop().getStopIndex(), hasDistinct, distinctColumnNameStartPosition);
            functionExpressionSegment.setAlias(alias);
            return Optional.<ExpressionSegment>of(functionExpressionSegment);
        }
        if (RuleName.COLUMN_NAME.getName().equals(node.getChild(0).getClass().getSimpleName())) {
            ParserRuleContext columnNode = (ParserRuleContext) node.getChild(0);
            Optional<ColumnSegment> columnSegment = new ColumnSegmentExtractor(new HashMap<String, String>()).extract(columnNode);
            return Optional.<ExpressionSegment>of(new PropertyExpressionSegment(columnSegment.get().getOwner(), columnSegment.get().getName(),
                    columnNode.getStart().getStartIndex(), columnNode.getStop().getStopIndex(), alias));
    private ExpressionSegment fillForPropertyOrFunction(final ParserRuleContext expressionNode) {
        Optional<ParserRuleContext> functionNode = ExtractorUtils.findFirstChildNode(expressionNode, RuleName.FUNCTION_CALL);
        if (functionNode.isPresent()) {
            return getFunctionExpressionSegment(expressionNode, functionNode.get());
        }
        return Optional.<ExpressionSegment>of(new CommonExpressionSegment(node.getStart().getStartIndex(), node.getStop().getStopIndex(), alias));
        if (RuleName.COLUMN_NAME.getName().equals(expressionNode.getChild(0).getClass().getSimpleName())) {
            return getPropertyExpressionSegment(expressionNode);
        }
        CommonExpressionSegment result = new CommonExpressionSegment(expressionNode.getStart().getStartIndex(), expressionNode.getStop().getStopIndex());
        Optional<String> alias = getAlias(expressionNode);
        if (alias.isPresent()) {
            result.setAlias(alias.get());
        }
        return result;
    }
    
    private boolean hasDistinct(final ParserRuleContext node) {
        return ExtractorUtils.findFirstChildNode(node, RuleName.DISTINCT).isPresent();
    private ExpressionSegment getFunctionExpressionSegment(final ParserRuleContext expressionNode, final ParserRuleContext functionNode) {
        String functionName = functionNode.getChild(0).getText();
        int startIndex = ((TerminalNode) functionNode.getChild(1)).getSymbol().getStartIndex();
        boolean hasDistinct = hasDistinct(expressionNode);
        int distinctColumnNameStartPosition = hasDistinct ? calculateDistinctColumnNamePosition(functionNode) : -1;
        FunctionExpressionSegment result = new FunctionExpressionSegment(functionName, 
                functionNode.getStart().getStartIndex(), startIndex, functionNode.getStop().getStopIndex(), hasDistinct, distinctColumnNameStartPosition);
        Optional<String> alias = getAlias(expressionNode);
        if (alias.isPresent()) {
            result.setAlias(alias.get());
        }
        return result;
    }
    
    private boolean hasDistinct(final ParserRuleContext expressionNode) {
        return ExtractorUtils.findFirstChildNode(expressionNode, RuleName.DISTINCT).isPresent();
    }
    
    private int calculateDistinctColumnNamePosition(final ParserRuleContext functionNode) {
@@ -102,4 +107,22 @@ public final class ExpressionExtractor implements OptionalSQLSegmentExtractor {
        }
        return -1;
    }
    
    private ExpressionSegment getPropertyExpressionSegment(final ParserRuleContext expressionNode) {
        ParserRuleContext columnNode = (ParserRuleContext) expressionNode.getChild(0);
        Optional<ColumnSegment> columnSegment = new ColumnSegmentExtractor(new HashMap<String, String>()).extract(columnNode);
        Preconditions.checkState(columnSegment.isPresent());
        PropertyExpressionSegment result = new PropertyExpressionSegment(
                columnSegment.get().getOwner(), columnSegment.get().getName(), columnNode.getStart().getStartIndex(), columnNode.getStop().getStopIndex());
        Optional<String> alias = getAlias(expressionNode);
        if (alias.isPresent()) {
            result.setAlias(alias.get());
        }
        return result;
    }
    
    private Optional<String> getAlias(final ParserRuleContext expressionNode) {
        Optional<ParserRuleContext> aliasNode = ExtractorUtils.findFirstChildNode(expressionNode, RuleName.ALIAS);
        return aliasNode.isPresent() ? Optional.of(SQLUtil.getExactlyValue(aliasNode.get().getText())) : Optional.<String>absent();
    }
}
+6 −6
Original line number Diff line number Diff line
@@ -156,7 +156,7 @@ public final class PredicateExtractor implements OptionalSQLSegmentExtractor {
        Optional<ColumnSegment> column = buildColumn(exprNode);
        Preconditions.checkState(column.isPresent());
        ParserRuleContext valueNode = leftNode.isPresent() ? (ParserRuleContext) comparisionNode.get().parent.getChild(2) : (ParserRuleContext) comparisionNode.get().parent.getChild(0);
        Optional<ExpressionSegment> sqlExpression = buildExpression(questionNodeIndexMap, valueNode);
        Optional<? extends ExpressionSegment> sqlExpression = buildExpression(questionNodeIndexMap, valueNode);
        return sqlExpression.isPresent()
                ? Optional.of(new ConditionSegment(column.get(), ShardingOperator.EQUAL, new EqualsValueExpressionSegment(sqlExpression.get()))) : Optional.<ConditionSegment>absent();
    }
@@ -165,8 +165,8 @@ public final class PredicateExtractor implements OptionalSQLSegmentExtractor {
        return Symbol.EQ.getLiterals().equalsIgnoreCase(comparisionNode.getText()) && 3 == comparisionNode.getParent().getChildCount();
    }
    
    private Optional<ExpressionSegment> buildExpression(final Map<ParserRuleContext, Integer> questionNodeIndexMap, final ParserRuleContext valueNode) {
        Optional<ExpressionSegment> sqlExpression = new ExpressionExtractor().extract(valueNode);
    private Optional<? extends ExpressionSegment> buildExpression(final Map<ParserRuleContext, Integer> questionNodeIndexMap, final ParserRuleContext valueNode) {
        Optional<? extends ExpressionSegment> sqlExpression = new ExpressionExtractor().extract(valueNode);
        if (!sqlExpression.isPresent() || !(sqlExpression.get() instanceof CommonExpressionSegment)) {
            return sqlExpression;
        }
@@ -213,8 +213,8 @@ public final class PredicateExtractor implements OptionalSQLSegmentExtractor {
        if (!column.isPresent()) {
            return Optional.absent();
        }
        Optional<ExpressionSegment> beginSQLExpression = buildExpression(questionNodeIndexMap, (ParserRuleContext) predicateNode.getChild(2));
        Optional<ExpressionSegment> endSQLExpression = buildExpression(questionNodeIndexMap, (ParserRuleContext) predicateNode.getChild(4));
        Optional<? extends ExpressionSegment> beginSQLExpression = buildExpression(questionNodeIndexMap, (ParserRuleContext) predicateNode.getChild(2));
        Optional<? extends ExpressionSegment> endSQLExpression = buildExpression(questionNodeIndexMap, (ParserRuleContext) predicateNode.getChild(4));
        if (beginSQLExpression.isPresent() && endSQLExpression.isPresent()) {
            return Optional.of(new ConditionSegment(column.get(), ShardingOperator.BETWEEN, new BetweenValueExpressionSegment(beginSQLExpression.get(), endSQLExpression.get())));
        }
@@ -229,7 +229,7 @@ public final class PredicateExtractor implements OptionalSQLSegmentExtractor {
        List<ExpressionSegment> sqlExpressions = new LinkedList<>();
        for (int i = 3; i < predicateNode.getChildCount(); i++) {
            if (RuleName.SIMPLE_EXPR.getName().equals(predicateNode.getChild(i).getClass().getSimpleName())) {
                Optional<ExpressionSegment> expression = buildExpression(questionNodeIndexMap, (ParserRuleContext) predicateNode.getChild(i));
                Optional<? extends ExpressionSegment> expression = buildExpression(questionNodeIndexMap, (ParserRuleContext) predicateNode.getChild(i));
                if (!expression.isPresent()) {
                    sqlExpressions.clear();
                    break;
+2 −2
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ import org.antlr.v4.runtime.tree.TerminalNodeImpl;
 */
public final class SelectClauseExtractor implements OptionalSQLSegmentExtractor {
    
    private ExpressionExtractor expressionExtractor = new ExpressionExtractor();
    private final ExpressionExtractor expressionExtractor = new ExpressionExtractor();
    
    @Override
    public Optional<SelectClauseSegment> extract(final ParserRuleContext ancestorNode) {
@@ -55,7 +55,7 @@ public final class SelectClauseExtractor implements OptionalSQLSegmentExtractor
            if (childNode instanceof TerminalNodeImpl) {
                continue;
            }
            Optional<ExpressionSegment> expressionSegment = expressionExtractor.extract((ParserRuleContext) childNode);
            Optional<? extends ExpressionSegment> expressionSegment = expressionExtractor.extract((ParserRuleContext) childNode);
            if (expressionSegment.isPresent()) {
                result.getExpressions().add(expressionSegment.get());
            }
+1 −2
Original line number Diff line number Diff line
@@ -103,8 +103,7 @@ public final class SelectClauseFiller implements SQLStatementFiller<SelectClause
            FunctionExpressionSegment functionExpressionSegment = (FunctionExpressionSegment) expressionSegment;
            Optional<String> alias = functionExpressionSegment.getAlias();
            if (functionExpressionSegment.isHasDistinct() && !alias.isPresent()) {
                alias = Optional.of(DerivedAlias.AGGREGATION_DISTINCT_DERIVED.getDerivedAlias(offset));
                ((FunctionExpressionSegment) expressionSegment).setAlias(alias);
                ((FunctionExpressionSegment) expressionSegment).setAlias(DerivedAlias.AGGREGATION_DISTINCT_DERIVED.getDerivedAlias(offset));
                return offset + 1;
            }
        }
+11 −4
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@
package io.shardingsphere.core.parsing.antlr.sql.segment.expr;

import com.google.common.base.Optional;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
@@ -30,17 +29,25 @@ import lombok.Setter;
 */
@RequiredArgsConstructor
@Getter
@Setter
public final class CommonExpressionSegment implements ExpressionSegment {
    
    private final int startPosition;
    
    private final int endPosition;
    
    private final Optional<String> alias;
    private String alias;
    
    @Setter
    private int index = -1;
    
    @Setter
    private Number value = -1;
    
    /**
     * Get alias.
     *
     * @return alias
     */
    public Optional<String> getAlias() {
        return Optional.fromNullable(alias);
    }
}
Loading