Commit 75cdafcc authored by gaohongtao's avatar gaohongtao
Browse files

fix #25 OR表达式下会出现重复结果问题

parent b005981e
Loading
Loading
Loading
Loading
+24 −24
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import com.dangdang.ddframe.rdb.sharding.api.DatabaseType;
import com.dangdang.ddframe.rdb.sharding.api.rule.DataNode;
import com.dangdang.ddframe.rdb.sharding.api.rule.TableRule;
import com.dangdang.ddframe.rdb.sharding.exception.SQLParserException;
import com.dangdang.ddframe.rdb.sharding.router.SQLExecutionUnit;
import com.dangdang.ddframe.rdb.sharding.router.SQLRouteEngine;
import com.dangdang.ddframe.rdb.sharding.router.SQLRouteResult;
import com.google.common.collect.Lists;
@@ -61,17 +62,17 @@ public class TableRuleTest extends AbstractConfigTest {
        SQLRouteEngine engine = new SQLRouteEngine(getShardingRuleBuilder("algorithm").build(), DatabaseType.MySQL);
        
        SQLRouteResult result = engine.route("select * from order1 where order_id = 1", null);
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_1 WHERE order_id = 1"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_1 WHERE order_id = 1"));
        result = engine.route("select * from order1 where order_id = ?", Lists.newArrayList((Object) 1));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_1 WHERE order_id = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_1 WHERE order_id = ?"));
        
        result = engine.route("select * from order1 where order_id = '1'", null);
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_1 WHERE order_id = '1'"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_1 WHERE order_id = '1'"));
        result = engine.route("select * from order1 where order_id = ?", Lists.newArrayList((Object) "1"));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_1 WHERE order_id = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_1 WHERE order_id = ?"));
        
        result = engine.route("select * from order1 where order_id = ?", Lists.newArrayList((Object) new java.sql.Date(12000111L)));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_1 WHERE order_id = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_1 WHERE order_id = ?"));
    }
    
    @Test
@@ -79,17 +80,17 @@ public class TableRuleTest extends AbstractConfigTest {
        SQLRouteEngine engine = new SQLRouteEngine(getShardingRuleBuilder("algorithm").build(), DatabaseType.MySQL);
        
        SQLRouteResult result = engine.route("select * from order2 where order_id = 1.11", null);
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_1 WHERE order_id = 1.11"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_1 WHERE order_id = 1.11"));
        result = engine.route("select * from order2 where order_id = ?", Lists.newArrayList((Object) 1.11));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_1 WHERE order_id = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_1 WHERE order_id = ?"));
        
        result = engine.route("select * from order2 where order_id = '1.11'", null);
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_1 WHERE order_id = '1.11'"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_1 WHERE order_id = '1.11'"));
        result = engine.route("select * from order2 where order_id = ?", Lists.newArrayList((Object) "1.11"));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_1 WHERE order_id = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_1 WHERE order_id = ?"));
        
        result = engine.route("select * from order2 where order_id = ?", Lists.newArrayList((Object) new java.sql.Date(12000111L)));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_0 WHERE order_id = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_0 WHERE order_id = ?"));
    }
    
    @Test(expected = UnsupportedOperationException.class)
@@ -103,13 +104,13 @@ public class TableRuleTest extends AbstractConfigTest {
        SQLRouteEngine engine = new SQLRouteEngine(getShardingRuleBuilder("algorithm").build(), DatabaseType.MySQL);
        
        SQLRouteResult result = engine.route("select * from order3 where date = ?", Lists.newArrayList((Object) new SimpleDateFormat("yyyyMMdd").parse("20151015")));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_0 WHERE date = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_0 WHERE date = ?"));
        
        result = engine.route("select * from order3 where date = ?", Lists.newArrayList((Object) "20151115"));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_1 WHERE date = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_1 WHERE date = ?"));
        
        result = engine.route("select * from order3 where date = ?", Lists.newArrayList((Object) new SimpleDateFormat("yyyyMMdd").parse("20151015").getTime()));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_0 WHERE date = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_0 WHERE date = ?"));
        
    }
    
@@ -118,13 +119,13 @@ public class TableRuleTest extends AbstractConfigTest {
        SQLRouteEngine engine = new SQLRouteEngine(getShardingRuleBuilder("algorithm").build(), DatabaseType.MySQL);
        
        SQLRouteResult result = engine.route("select * from order4 where date = ?", Lists.newArrayList((Object) new SimpleDateFormat("yyyyMMdd").parse("20151015")));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_201510 WHERE date = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_201510 WHERE date = ?"));
        
        result = engine.route("select * from order4 where date = ?", Lists.newArrayList((Object) new SimpleDateFormat("yyyyMMdd").parse("20151015").getTime()));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_201510 WHERE date = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_201510 WHERE date = ?"));
        
        result = engine.route("select * from order4 where date = ?", Lists.newArrayList((Object) "201511"));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_201511 WHERE date = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_201511 WHERE date = ?"));
    }
    
    @Test
@@ -132,10 +133,10 @@ public class TableRuleTest extends AbstractConfigTest {
        SQLRouteEngine engine = new SQLRouteEngine(getShardingRuleBuilder("algorithm").build(), DatabaseType.MySQL);
        
        SQLRouteResult result = engine.route("select * from order5 where date = ?", Lists.newArrayList((Object) new SimpleDateFormat("yyyyMMdd").parse("20151015")));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_0 WHERE date = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_0 WHERE date = ?"));
        
        result = engine.route("select * from order5 where date = ?", Lists.newArrayList((Object) new SimpleDateFormat("yyyyMMdd").parse("20151015").getTime()));
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_0 WHERE date = ?"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_0 WHERE date = ?"));
        
    }
    
@@ -144,7 +145,7 @@ public class TableRuleTest extends AbstractConfigTest {
        SQLRouteEngine engine = new SQLRouteEngine(getShardingRuleBuilder("algorithm").build(), DatabaseType.MySQL);
        
        SQLRouteResult result = engine.route("select * from order1 where order_id in (1,3)", null);
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_1 WHERE order_id IN (1, 3)"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_1 WHERE order_id IN (1, 3)"));
    }
    
    @Test(expected = UnsupportedOperationException.class)
@@ -169,29 +170,28 @@ public class TableRuleTest extends AbstractConfigTest {
    public void testNullRouteResult() throws FileNotFoundException, SQLParserException, ParseException {
        SQLRouteEngine engine = new SQLRouteEngine(getShardingRuleBuilder("algorithm").build(), DatabaseType.MySQL);
        SQLRouteResult result = engine.route("select * from order6 where order_id = 1", null);
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_0 WHERE order_id = 1"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_0 WHERE order_id = 1"));
    }
    
    @Test
    public void testDefaultStrategy() throws SQLParserException, FileNotFoundException {
        SQLRouteEngine engine = new SQLRouteEngine(getShardingRuleBuilder("defaultStrategy").build(), DatabaseType.MySQL);
        SQLRouteResult result = engine.route("select * from order1 where order_id = 1", null);
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_0 WHERE order_id = 1"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_0 WHERE order_id = 1"));
    }
    
    @Test
    public void testBindingTable() {
        SQLRouteEngine engine = new SQLRouteEngine(getShardingRuleBuilder("binding_table").build(), DatabaseType.MySQL);
        SQLRouteResult result = engine.route("select * from t_order o ,t_order_item i where o.order_id = i.order_id and o.order_id = 11", null);
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_1 o, t_order_item_1 i WHERE o.order_id = i.order_id AND o.order_id = 11"));
        assertThat(result.getExecutionUnits().iterator().next().getSql(), is("SELECT * FROM t_order_1 o, t_order_item_1 i WHERE o.order_id = i.order_id AND o.order_id = 11"));
    }
    
    @Test
    public void testReturnMultiResult() {
        SQLRouteEngine engine = new SQLRouteEngine(getShardingRuleBuilder("algorithm").build(), DatabaseType.MySQL);
        SQLRouteResult result = engine.route("select * from order7 o where o.order_id = 1", null);
        assertThat(result.getExecutionUnits().get(0).getSql(), is("SELECT * FROM t_order_0 o WHERE o.order_id = 1"));
        assertThat(result.getExecutionUnits().get(1).getSql(), is("SELECT * FROM t_order_1 o WHERE o.order_id = 1"));
        assertThat(result.getExecutionUnits(), hasItems(new SQLExecutionUnit("db0", "SELECT * FROM t_order_0 o WHERE o.order_id = 1"), new SQLExecutionUnit("db0", "SELECT * FROM t_order_1 o WHERE o.order_id = 1")));
    }
    
    @Override
+3 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@

package com.dangdang.ddframe.rdb.sharding.router;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
@@ -29,6 +30,7 @@ import lombok.extern.slf4j.Slf4j;
@Getter
@Slf4j
@ToString
@EqualsAndHashCode
public class SQLExecutionUnit {
    
    private final String dataSource;
@@ -38,6 +40,6 @@ public class SQLExecutionUnit {
    public SQLExecutionUnit(final String dataSource, final String sql) {
        this.dataSource = dataSource;
        this.sql = sql;
        log.debug("route sql to db: [{}] sql: [{}]", dataSource, sql);
        log.trace("route sql to db: [{}] sql: [{}]", dataSource, sql);
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import com.dangdang.ddframe.rdb.sharding.router.single.SingleTableRouter;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * SQL路由引擎.
@@ -45,6 +46,7 @@ import lombok.RequiredArgsConstructor;
 * @author gaohongtao, zhangiang
 */
@RequiredArgsConstructor
@Slf4j
public final class SQLRouteEngine {
    
    private final ShardingRule shardingRule;
@@ -82,6 +84,8 @@ public final class SQLRouteEngine {
            }), parsedResult.getRouteContext().getSqlBuilder(), parsedResult.getRouteContext().getSqlStatementType()));
        }
        MetricsContext.stop(context);
        log.debug("final route result:{}", result.getExecutionUnits());
        log.debug("merge context:{}", result.getMergeContext());
        return result;
    }
    
+3 −4
Original line number Diff line number Diff line
@@ -17,11 +17,10 @@

package com.dangdang.ddframe.rdb.sharding.router;

import java.util.ArrayList;
import java.util.List;
import java.util.HashSet;
import java.util.Set;

import com.dangdang.ddframe.rdb.sharding.parser.result.merger.MergeContext;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@@ -36,5 +35,5 @@ public final class SQLRouteResult {
    
    private final MergeContext mergeContext;
    
    private final List<SQLExecutionUnit> executionUnits = new ArrayList<>();
    private final Set<SQLExecutionUnit> executionUnits = new HashSet<>();
}
+8 −10
Original line number Diff line number Diff line
@@ -17,10 +17,6 @@

package com.dangdang.ddframe.rdb.sharding.router;

import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -29,11 +25,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.sql.DataSource;

import org.junit.Before;

import com.dangdang.ddframe.rdb.sharding.api.DatabaseType;
import com.dangdang.ddframe.rdb.sharding.api.rule.BindingTableRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRule;
@@ -45,10 +38,15 @@ import com.dangdang.ddframe.rdb.sharding.exception.SQLParserException;
import com.dangdang.ddframe.rdb.sharding.router.fixture.OrderAttrShardingAlgorithm;
import com.dangdang.ddframe.rdb.sharding.router.fixture.OrderShardingAlgorithm;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;

import lombok.AccessLevel;
import lombok.Getter;
import org.junit.Before;

import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

public abstract class AbstractBaseRouteSqlTest {
    
@@ -87,7 +85,7 @@ public abstract class AbstractBaseRouteSqlTest {
            final Collection<String> targetDataSources, final Collection<String> targetSQLs) throws SQLParserException {
        SQLRouteResult actual = new SQLRouteEngine(getShardingRule(), DatabaseType.MySQL).route(originSql, parameters);
        assertThat(actual.getExecutionUnits().size(), is(expectedSize));
        Set<String> actualDdataSources = new HashSet<String>(Lists.transform(actual.getExecutionUnits(), new Function<SQLExecutionUnit, String>() {
        Set<String> actualDdataSources = new HashSet<>(Collections2.transform(actual.getExecutionUnits(), new Function<SQLExecutionUnit, String>() {
            
            @Override
            public String apply(final SQLExecutionUnit input) {
@@ -95,7 +93,7 @@ public abstract class AbstractBaseRouteSqlTest {
            }
        }));
        assertThat(actualDdataSources, hasItems(targetDataSources.toArray(new String[0])));
        List<String> actualSQLs = Lists.transform(actual.getExecutionUnits(), new Function<SQLExecutionUnit, String>() {
        Collection<String> actualSQLs = Collections2.transform(actual.getExecutionUnits(), new Function<SQLExecutionUnit, String>() {
            
            @Override
            public String apply(final SQLExecutionUnit input) {
Loading