Skip to content

Commit

Permalink
1、Fix bug when parse or condition contains no sharding column(修复非分片键在…
Browse files Browse the repository at this point in the history
…or语句中解析不正确bug)

2、Add test case for or(增加or的测试用例)
  • Loading branch information
maxiaoguang64 committed Apr 17, 2018
1 parent 96009b4 commit 90f4721
Show file tree
Hide file tree
Showing 9 changed files with 290 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import io.shardingjdbc.core.parsing.lexer.token.DefaultKeyword;
import io.shardingjdbc.core.parsing.lexer.token.Keyword;
import io.shardingjdbc.core.parsing.lexer.token.Symbol;
import io.shardingjdbc.core.parsing.parser.clause.condition.NoShardingCondition;
import io.shardingjdbc.core.parsing.parser.clause.expression.AliasExpressionParser;
import io.shardingjdbc.core.parsing.parser.clause.expression.BasicExpressionParser;
import io.shardingjdbc.core.parsing.parser.context.condition.AndCondition;
Expand Down Expand Up @@ -92,7 +93,16 @@ public void parse(final ShardingRule shardingRule, final SQLStatement sqlStateme
private void parseWhere(final ShardingRule shardingRule, final SQLStatement sqlStatement, final List<SelectItem> items) {
do {
OrCondition orCondition = parseOr(shardingRule, sqlStatement, items);
sqlStatement.getConditions().getOrCondition().getAndConditions().addAll(orCondition.getAndConditions());
boolean isAllrouter = false;
for (AndCondition each : orCondition.getAndConditions()) {
if (each.getConditions().get(0) instanceof NoShardingCondition) {
isAllrouter = true;
break;
}
}
if (!isAllrouter) {
sqlStatement.getConditions().getOrCondition().getAndConditions().addAll(orCondition.getAndConditions());
}
} while (lexerEngine.skipIfEqual(DefaultKeyword.AND));
lexerEngine.unsupportedIfEqual(DefaultKeyword.OR);
}
Expand All @@ -110,11 +120,7 @@ private OrCondition parseOr(final ShardingRule shardingRule, final SQLStatement
result.getAndConditions().addAll(merge(subOrCondition, orCondition).getAndConditions());
} else {
OrCondition orCondition = parseAnd(shardingRule, sqlStatement, items);
try {
result.getAndConditions().addAll(orCondition.getAndConditions());
} catch (Exception e) {
e.printStackTrace();
}
result.getAndConditions().addAll(orCondition.getAndConditions());
}
} while (lexerEngine.skipIfEqual(DefaultKeyword.OR));
return result;
Expand All @@ -128,13 +134,9 @@ private OrCondition parseAnd(final ShardingRule shardingRule, final SQLStatement
lexerEngine.skipIfEqual(Symbol.RIGHT_PAREN);
result = merge(result, subOrCondition);
} else {
Optional<Condition> condition = parseComparisonCondition(shardingRule, sqlStatement, items);
Condition condition = parseComparisonCondition(shardingRule, sqlStatement, items);
skipsDoubleColon();
if (condition.isPresent() && shardingRule.isShardingColumn(condition.get().getColumn())) {
OrCondition orCondition = new OrCondition();
orCondition.add(condition.get());
result = merge(result, orCondition);
}
result = merge(result, new OrCondition(condition));
}
} while (lexerEngine.skipIfEqual(DefaultKeyword.AND));
return result;
Expand Down Expand Up @@ -164,11 +166,11 @@ private AndCondition merge(final AndCondition andCondition1, final AndCondition
for (Condition each : andCondition2.getConditions()) {
result.getConditions().add(each);
}
return result;
return result.trim();
}

private Optional<Condition> parseComparisonCondition(final ShardingRule shardingRule, final SQLStatement sqlStatement, final List<SelectItem> items) {
Optional<Condition> result = Optional.absent();
private Condition parseComparisonCondition(final ShardingRule shardingRule, final SQLStatement sqlStatement, final List<SelectItem> items) {
Condition result;
SQLExpression left = basicExpressionParser.parse(sqlStatement);
if (lexerEngine.skipIfEqual(Symbol.EQ)) {
result = parseEqualCondition(shardingRule, sqlStatement, left);
Expand All @@ -182,6 +184,7 @@ private Optional<Condition> parseComparisonCondition(final ShardingRule sharding
result = parseBetweenCondition(shardingRule, sqlStatement, left);
return result;
}
result = new NoShardingCondition();
if (sqlStatement instanceof SelectStatement && isRowNumberCondition(items, left)) {
if (lexerEngine.skipIfEqual(Symbol.LT)) {
parseRowCountCondition((SelectStatement) sqlStatement, false);
Expand Down Expand Up @@ -216,20 +219,20 @@ private Optional<Condition> parseComparisonCondition(final ShardingRule sharding
return result;
}

private Optional<Condition> parseEqualCondition(final ShardingRule shardingRule, final SQLStatement sqlStatement, final SQLExpression left) {
private Condition parseEqualCondition(final ShardingRule shardingRule, final SQLStatement sqlStatement, final SQLExpression left) {
SQLExpression right = basicExpressionParser.parse(sqlStatement);
// TODO if have more tables, and cannot find column belong to, should not add to condition, should parse binding table rule.
if ((sqlStatement.getTables().isSingleTable() || left instanceof SQLPropertyExpression)
&& (right instanceof SQLNumberExpression || right instanceof SQLTextExpression || right instanceof SQLPlaceholderExpression)) {
Optional<Column> column = find(sqlStatement.getTables(), left);
if (column.isPresent()) {
return Optional.of(new Condition(column.get(), right));
if (column.isPresent() && shardingRule.isShardingColumn(column.get())) {
return new Condition(column.get(), right);
}
}
return Optional.absent();
return new NoShardingCondition();
}

private Optional<Condition> parseInCondition(final ShardingRule shardingRule, final SQLStatement sqlStatement, final SQLExpression left) {
private Condition parseInCondition(final ShardingRule shardingRule, final SQLStatement sqlStatement, final SQLExpression left) {
lexerEngine.accept(Symbol.LEFT_PAREN);
List<SQLExpression> rights = new LinkedList<>();
do {
Expand All @@ -238,23 +241,23 @@ private Optional<Condition> parseInCondition(final ShardingRule shardingRule, fi
} while (!lexerEngine.equalAny(Symbol.RIGHT_PAREN));
lexerEngine.nextToken();
Optional<Column> column = find(sqlStatement.getTables(), left);
if (column.isPresent()) {
return Optional.of(new Condition(column.get(), rights));
if (column.isPresent() && shardingRule.isShardingColumn(column.get())) {
return new Condition(column.get(), rights);
}
return Optional.absent();
return new NoShardingCondition();
}

private Optional<Condition> parseBetweenCondition(final ShardingRule shardingRule, final SQLStatement sqlStatement, final SQLExpression left) {
private Condition parseBetweenCondition(final ShardingRule shardingRule, final SQLStatement sqlStatement, final SQLExpression left) {
List<SQLExpression> rights = new LinkedList<>();
rights.add(basicExpressionParser.parse(sqlStatement));
skipsDoubleColon();
lexerEngine.accept(DefaultKeyword.AND);
rights.add(basicExpressionParser.parse(sqlStatement));
Optional<Column> column = find(sqlStatement.getTables(), left);
if (column.isPresent()) {
return Optional.of(new Condition(column.get(), rights.get(0), rights.get(1)));
if (column.isPresent() && shardingRule.isShardingColumn(column.get())) {
return new Condition(column.get(), rights.get(0), rights.get(1));
}
return Optional.absent();
return new NoShardingCondition();
}

private boolean isRowNumberCondition(final List<SelectItem> items, final SQLExpression sqlExpression) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 1999-2015 dangdang.com.
* <p>
* 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,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* </p>
*/

package io.shardingjdbc.core.parsing.parser.clause.condition;

import io.shardingjdbc.core.parsing.parser.context.condition.Condition;

/**
* No sharding condition.
*
* @author maxiaoguang
*/
public final class NoShardingCondition extends Condition {
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@

import com.google.common.base.Objects;
import com.google.common.base.Optional;
import io.shardingjdbc.core.parsing.parser.clause.condition.NoShardingCondition;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.LinkedHashMap;
Expand All @@ -33,7 +34,7 @@
*
* @author maxiaoguang
*/
@RequiredArgsConstructor
@NoArgsConstructor
@Getter
@ToString
public final class AndCondition {
Expand All @@ -56,6 +57,27 @@ public Map<Column, List<Condition>> getConditionsMap() {
return result;
}

/**
* Trim conditions.
*
* @return trimed and condition
*/
public AndCondition trim() {
List<Condition> shardingConditions = new LinkedList<>();
for (Condition each : conditions) {
if (Condition.class.equals(each.getClass())) {
shardingConditions.add(each);
}
}
conditions.clear();
if (shardingConditions.isEmpty()) {
conditions.add(new NoShardingCondition());
} else {
conditions.addAll(shardingConditions);
}
return this;
}

/**
* Find condition via column.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ public class Condition {

private final Map<Integer, Integer> positionIndexMap = new LinkedHashMap<>();

protected Condition() {
column = null;
operator = null;
}

public Condition(final Column column, final SQLExpression sqlExpression) {
this(column, ShardingOperator.EQUAL);
init(sqlExpression, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import com.google.common.base.Optional;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.ArrayList;
Expand All @@ -30,13 +30,17 @@
*
* @author maxiaoguang
*/
@RequiredArgsConstructor
@NoArgsConstructor
@Getter
@ToString
public final class OrCondition {

private final List<AndCondition> andConditions = new ArrayList<>();

public OrCondition(final Condition condition) {
add(condition);
}

/**
* Add condition.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import io.shardingjdbc.core.parsing.SQLParsingEngine;
import io.shardingjdbc.core.parsing.parser.context.condition.Column;
import io.shardingjdbc.core.parsing.parser.context.condition.Condition;
import io.shardingjdbc.core.parsing.parser.exception.SQLParsingUnsupportedException;
import io.shardingjdbc.core.parsing.parser.sql.dml.DMLStatement;
import io.shardingjdbc.core.rule.ShardingRule;
import org.junit.Test;
Expand All @@ -38,6 +37,7 @@
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

public final class UpdateStatementParserTest extends AbstractStatementParserTest {

Expand Down Expand Up @@ -109,7 +109,14 @@ private void assertUpdateStatementWitParameter(final DMLStatement updateStatemen
@Test
public void parseWithOr() {
ShardingRule shardingRule = createShardingRule();
new SQLParsingEngine(DatabaseType.Oracle, "UPDATE TABLE_XXX SET field1=1 WHERE field1<1 AND (field1 >2 OR field2 =1)", shardingRule).parse(false);
DMLStatement updateStatement = (DMLStatement) new SQLParsingEngine(DatabaseType.Oracle, "UPDATE TABLE_XXX AS xxx SET field1=1 WHERE field1<1 AND (field1 >2 OR xxx.field2 =1)", shardingRule).parse(false);
assertUpdateStatementWitOr(updateStatement);
}

private void assertUpdateStatementWitOr(final DMLStatement updateStatement) {
assertThat(updateStatement.getTables().find("TABLE_XXX").get().getName(), is("TABLE_XXX"));
assertThat(updateStatement.getTables().find("TABLE_XXX").get().getAlias().get(), is("xxx"));
assertTrue(updateStatement.getConditions().getOrCondition().getAndConditions().isEmpty());
}

@Test
Expand Down
Loading

0 comments on commit 90f4721

Please sign in to comment.