Skip to content

Instantly share code, notes, and snippets.

@junwen12221
Created March 29, 2021 08:40
Show Gist options
  • Save junwen12221/61b0b18dfff1024e9ae3d68e465bc8c2 to your computer and use it in GitHub Desktop.
Save junwen12221/61b0b18dfff1024e9ae3d68e465bc8c2 to your computer and use it in GitHub Desktop.
package io.mycat.drdsrunner;
import io.mycat.DataNode;
import io.mycat.calcite.table.ShardingTable;
import io.mycat.router.CustomRuleFunction;
import org.apache.calcite.rex.RexDynamicParam;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexNode;
import java.util.Collections;
import java.util.List;
public interface ConditionHandler {
List<DataNode> handle(ShardingTable shardingTable, Object[] params);
}
package io.mycat.drdsrunner;
public class DataNodeMapping {
}
package io.mycat.drdsrunner;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
import io.mycat.*;
import io.mycat.assemble.MycatTest;
import io.mycat.calcite.resultset.CalciteRowMetaData;
import io.mycat.calcite.spm.Plan;
import io.mycat.calcite.spm.PlanCache;
import io.mycat.calcite.table.SchemaHandler;
import io.mycat.config.*;
import io.mycat.datasource.jdbc.datasource.JdbcConnectionManager;
import io.mycat.hint.CreateClusterHint;
import io.mycat.hint.CreateDataSourceHint;
import io.mycat.hint.CreateSchemaHint;
import io.mycat.plug.loadBalance.LoadBalanceManager;
import io.mycat.plug.sequence.SequenceGenerator;
import io.mycat.replica.ReplicaSelectorRuntime;
import io.mycat.runtime.MycatDataContextImpl;
import io.mycat.sqlhandler.ConfigUpdater;
import io.mycat.util.JsonUtil;
import io.mycat.util.NameMap;
import jdk.nashorn.internal.objects.annotations.Getter;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.sql.SqlExplainFormat;
import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.util.Util;
import org.junit.Before;
import javax.annotation.concurrent.NotThreadSafe;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public abstract class DrdsTest implements MycatTest {
static DrdsRunner drdsRunner = null;
@SneakyThrows
public static DrdsRunner getDrds() {
if (drdsRunner != null) {
return drdsRunner;
}
synchronized (DrdsTest.class) {
if (drdsRunner == null) {
MycatCore mycatCore = new MycatCore();
FileMetadataStorageManager fileMetadataStorageManager = MetaClusterCurrent.wrapper(FileMetadataStorageManager.class);
MycatRouterConfig mycatRouterConfig = new MycatRouterConfig();
LogicSchemaConfig logicSchemaConfig = new LogicSchemaConfig();
mycatRouterConfig.getSchemas().add(logicSchemaConfig);
logicSchemaConfig.setSchemaName("db1");
NormalTableConfig mainNormalTableConfig = new NormalTableConfig();
mainNormalTableConfig.setCreateTableSQL("CREATE TABLE `normal` (\n" +
" `id` int(11) NOT NULL,\n" +
" `addressname` varchar(20) DEFAULT NULL,\n" +
" PRIMARY KEY (`id`)\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n");
NormalBackEndTableInfoConfig normalBackEndTableInfoConfig = new NormalBackEndTableInfoConfig();
normalBackEndTableInfoConfig.setTargetName("prototype");
normalBackEndTableInfoConfig.setSchemaName("db1");
normalBackEndTableInfoConfig.setTableName("normal");
mainNormalTableConfig.setDataNode(normalBackEndTableInfoConfig);
logicSchemaConfig.getNormalTables().put("normal", mainNormalTableConfig);
NormalTableConfig orherNormalTableConfig = new NormalTableConfig();
orherNormalTableConfig.setCreateTableSQL("CREATE TABLE `normal2` (\n" +
" `id` int(11) NOT NULL,\n" +
" `addressname` varchar(20) DEFAULT NULL,\n" +
" PRIMARY KEY (`id`)\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n");
NormalBackEndTableInfoConfig otherNormalBackEndTableInfoConfig = new NormalBackEndTableInfoConfig();
otherNormalBackEndTableInfoConfig.setTargetName("prototype");
otherNormalBackEndTableInfoConfig.setSchemaName("db1");
otherNormalBackEndTableInfoConfig.setTableName("normal2");
orherNormalTableConfig.setDataNode(otherNormalBackEndTableInfoConfig);
logicSchemaConfig.getNormalTables().put("normal2", orherNormalTableConfig);
GlobalTableConfig globalTableConfig = new GlobalTableConfig();
globalTableConfig.getDataNodes().add(
GlobalBackEndTableInfoConfig.builder().targetName("c0").build()
);
globalTableConfig.getDataNodes().add(
GlobalBackEndTableInfoConfig.builder().targetName("c1").build()
);
globalTableConfig.setCreateTableSQL("CREATE TABLE `global` (\n" +
" `id` int(11) NOT NULL AUTO_INCREMENT,\n" +
" `companyname` varchar(20) DEFAULT NULL,\n" +
" `addressid` int(11) DEFAULT NULL,\n" +
" PRIMARY KEY (`id`)\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 broadcast; ");
logicSchemaConfig.getGlobalTables().put("global", globalTableConfig);
ShardingTableConfig mainSharding = new ShardingTableConfig();
mainSharding.setCreateTableSQL("CREATE TABLE db1.`sharding` (\n" +
" `id` bigint NOT NULL AUTO_INCREMENT,\n" +
" `user_id` varchar(100) DEFAULT NULL,\n" +
" `traveldate` date DEFAULT NULL,\n" +
" `fee` decimal(10,0) DEFAULT NULL,\n" +
" `days` int DEFAULT NULL,\n" +
" `blob` longblob,\n" +
" PRIMARY KEY (`id`),\n" +
" KEY `id` (`id`)\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8"
+ " dbpartition by hash(id) tbpartition by hash(id) tbpartitions 2 dbpartitions 2;");
mainSharding.setFunction(ShardingFuntion.builder().properties(JsonUtil.from("{\n" +
"\t\t\t\t\t\"dbNum\":\"2\",\n" +
"\t\t\t\t\t\"mappingFormat\":\"c${targetIndex}/db1_${dbIndex}/sharding_${tableIndex}\",\n" +
"\t\t\t\t\t\"tableNum\":\"2\",\n" +
"\t\t\t\t\t\"tableMethod\":\"hash(id)\",\n" +
"\t\t\t\t\t\"storeNum\":2,\n" +
"\t\t\t\t\t\"dbMethod\":\"hash(id)\"\n" +
"\t\t\t\t}", Map.class)).build());
logicSchemaConfig.getShadingTables().put("sharding", mainSharding);
ShardingTableConfig er = new ShardingTableConfig();
er.setCreateTableSQL("CREATE TABLE db1.`er` (\n" +
" `id` bigint NOT NULL AUTO_INCREMENT,\n" +
" `user_id` varchar(100) DEFAULT NULL,\n" +
" `traveldate` date DEFAULT NULL,\n" +
" `fee` decimal(10,0) DEFAULT NULL,\n" +
" `days` int DEFAULT NULL,\n" +
" `blob` longblob,\n" +
" PRIMARY KEY (`id`),\n" +
" KEY `id` (`id`)\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8"
+ " dbpartition by hash(id) tbpartition by hash(id) tbpartitions 2 dbpartitions 2;");
er.setFunction(ShardingFuntion.builder().properties(JsonUtil.from("{\n" +
"\t\t\t\t\t\"dbNum\":\"2\",\n" +
"\t\t\t\t\t\"mappingFormat\":\"c${targetIndex}/db1_${dbIndex}/er_${tableIndex}\",\n" +
"\t\t\t\t\t\"tableNum\":\"2\",\n" +
"\t\t\t\t\t\"tableMethod\":\"hash(id)\",\n" +
"\t\t\t\t\t\"storeNum\":2,\n" +
"\t\t\t\t\t\"dbMethod\":\"hash(id)\"\n" +
"\t\t\t\t}", Map.class)).build());
logicSchemaConfig.getShadingTables().put("er", er);
ShardingTableConfig other_sharding = new ShardingTableConfig();
other_sharding.setCreateTableSQL("CREATE TABLE db1.`other_sharding` (\n" +
" `id` bigint NOT NULL AUTO_INCREMENT,\n" +
" `user_id` varchar(100) DEFAULT NULL,\n" +
" `traveldate` date DEFAULT NULL,\n" +
" `fee` decimal(10,0) DEFAULT NULL,\n" +
" `days` int DEFAULT NULL,\n" +
" `blob` longblob,\n" +
" PRIMARY KEY (`id`),\n" +
" KEY `id` (`id`)\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8"
+ " dbpartition by mod_hash(id) tbpartition by hash(id) tbpartitions 2 dbpartitions 2;");
other_sharding.setFunction(ShardingFuntion.builder().properties(JsonUtil.from("{\n" +
"\t\t\t\t\t\"dbNum\":\"2\",\n" +
"\t\t\t\t\t\"mappingFormat\":\"c${targetIndex}/db1_${dbIndex}/other_sharding_${tableIndex}\",\n" +
"\t\t\t\t\t\"tableNum\":\"2\",\n" +
"\t\t\t\t\t\"tableMethod\":\"UNI_HASH(id)\",\n" +
"\t\t\t\t\t\"storeNum\":2,\n" +
"\t\t\t\t\t\"dbMethod\":\"hash(id)\"\n" +
"\t\t\t\t}", Map.class)).build());
logicSchemaConfig.getShadingTables().put("other_sharding", other_sharding);
mycatRouterConfig.getClusters().add(CreateClusterHint.createConfig("c0", Arrays.asList("ds0"), Collections.emptyList()));
mycatRouterConfig.getClusters().add(CreateClusterHint.createConfig("c1", Arrays.asList("ds1"), Collections.emptyList()));
{
NormalTableConfig orherTargetNormalTableConfig = new NormalTableConfig();
orherTargetNormalTableConfig.setCreateTableSQL("CREATE TABLE `normal3` (\n" +
" `id` int(11) NOT NULL,\n" +
" `addressname` varchar(20) DEFAULT NULL,\n" +
" PRIMARY KEY (`id`)\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;\n");
NormalBackEndTableInfoConfig otherTargetNormalBackEndTableInfoConfig = new NormalBackEndTableInfoConfig();
otherTargetNormalBackEndTableInfoConfig.setTargetName("ds1");
otherTargetNormalBackEndTableInfoConfig.setSchemaName("db1");
otherTargetNormalBackEndTableInfoConfig.setTableName("normal3");
orherTargetNormalTableConfig.setDataNode(otherTargetNormalBackEndTableInfoConfig);
logicSchemaConfig.getNormalTables().put("normal3", orherTargetNormalTableConfig);
}
mycatRouterConfig.getDatasources().add(CreateDataSourceHint.createConfig("ds0", DB1));
mycatRouterConfig.getDatasources().add(CreateDataSourceHint.createConfig("ds1", DB2));
mycatRouterConfig.getDatasources().add(CreateDataSourceHint.createConfig("prototype", DB1));
fileMetadataStorageManager.start(mycatRouterConfig);
drdsRunner = MetaClusterCurrent.wrapper(DrdsRunner.class);
}
}
return drdsRunner;
}
public static Explain parse(String sql) {
DrdsRunner drds = getDrds();
DrdsSql drdsSql = drds.preParse(sql);
MycatDataContextImpl mycatDataContext = new MycatDataContextImpl();
Plan plan = drds.getPlan(mycatDataContext, drdsSql);
return new Explain(plan,drdsSql);
}
public static String dumpPlan(RelNode relNode) {
String dumpPlan = Util.toLinux(RelOptUtil.dumpPlan("", relNode, SqlExplainFormat.TEXT,
SqlExplainLevel.EXPPLAN_ATTRIBUTES));
System.out.println(dumpPlan);
return dumpPlan;
}
}
package io.mycat.drdsrunner;
import io.mycat.DrdsSql;
import io.mycat.calcite.spm.Plan;
import io.mycat.calcite.spm.SpecificSql;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.sql.SqlExplainFormat;
import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.util.Util;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.stream.Collectors;
@Getter
public class Explain {
private Plan plan;
private DrdsSql drdsSql;
public Explain(Plan plan, DrdsSql drdsSql) {
this.plan = plan;
this.drdsSql = drdsSql;
}
public String getColumnInfo() {
return plan.getMetaData().toSimpleText();
}
// public String dumpPlan2() {
// String dumpPlan = Util.toLinux(RelOptUtil.dumpPlan("", plan.getPhysical(), SqlExplainFormat.TEXT,
// SqlExplainLevel.EXPPLAN_ATTRIBUTES));
// System.out.println(dumpPlan);
// return dumpPlan;
// }
public String dumpPlan() {
return plan.dumpPlan().replaceAll("\r"," ").replaceAll("\n"," ");
}
public List<SpecificSql> specificSql() {
return plan.specificSql(drdsSql);
}
}
package io.mycat.drdsrunner;
import io.mycat.DataNode;
import io.mycat.calcite.table.ShardingTable;
import io.mycat.router.CustomRuleFunction;
import lombok.ToString;
import java.util.Collections;
import java.util.List;
@ToString
public class GetQueryAllIterator implements ConditionHandler{
public GetQueryAllIterator() {
}
public static GetQueryAllIterator of() {
return new GetQueryAllIterator();
}
public List<DataNode> handle(ShardingTable table, Object[] params) {
CustomRuleFunction shardingFuntion = table.getShardingFuntion();
return shardingFuntion.calculate(Collections.emptyMap());
}
}
package io.mycat.drdsrunner;
import io.mycat.DataNode;
import io.mycat.RangeVariable;
import io.mycat.RangeVariableType;
import io.mycat.calcite.table.ShardingTable;
import io.mycat.querycondition.ComparisonOperator;
import io.mycat.querycondition.KeyMeta;
import io.mycat.router.CustomRuleFunction;
import lombok.ToString;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rex.RexNode;
import java.util.*;
import static io.mycat.drdsrunner.MycatRexUtil.resolveParam;
@ToString
public class GetRangeQueryIterator implements ConditionHandler {
private final List<Object> rangeQueryLowerKey;
private final ComparisonOperator rangeQueryLowerOp;
private final List<Object> rangeQueryUpperKey;
private final ComparisonOperator rangeQueryUpperOp;
private final List<String> selectedColumnNames;
public GetRangeQueryIterator(List<Object> rangeQueryLowerKey,
ComparisonOperator rangeQueryLowerOp,
List<Object> rangeQueryUpperKey,
ComparisonOperator rangeQueryUpperOp,
List<String> selectedColumnNames) {
this.rangeQueryLowerKey = rangeQueryLowerKey;
this.rangeQueryLowerOp = rangeQueryLowerOp;
this.rangeQueryUpperKey = rangeQueryUpperKey;
this.rangeQueryUpperOp = rangeQueryUpperOp;
this.selectedColumnNames = selectedColumnNames;
}
public static GetRangeQueryIterator of(List<Object> rangeQueryLowerKey,
ComparisonOperator rangeQueryLowerOp,
List<Object> rangeQueryUpperKey,
ComparisonOperator rangeQueryUpperOp,
List<String> selectedColumnNames) {
return new GetRangeQueryIterator(rangeQueryLowerKey, rangeQueryLowerOp, rangeQueryUpperKey, rangeQueryUpperOp, selectedColumnNames);
}
public List<DataNode> handle(ShardingTable table, Object[] paramsArgs) {
List<Object> rangeQueryLowerKey = this.rangeQueryLowerKey;
ComparisonOperator rangeQueryLowerOp = this.rangeQueryLowerOp;
List<Object> rangeQueryUpperKey = this.rangeQueryUpperKey;
ComparisonOperator rangeQueryUpperOp = this.rangeQueryUpperOp;
List<String> selectedColumnNames = this.selectedColumnNames;
return getDataNodes(table, paramsArgs, rangeQueryLowerKey, rangeQueryLowerOp, rangeQueryUpperKey, rangeQueryUpperOp, selectedColumnNames);
}
public static List<DataNode> getDataNodes(ShardingTable table, Object[] paramsArgs, List<Object> rangeQueryLowerKey, ComparisonOperator rangeQueryLowerOp, List<Object> rangeQueryUpperKey, ComparisonOperator rangeQueryUpperOp, List<String> selectedColumnNames) {
Object[] leftValues = new Object[rangeQueryLowerKey.size()];
Object[] rightValues = new Object[rangeQueryUpperKey.size()];
for (int i = 0; i < leftValues.length; i++) {
Object o = rangeQueryLowerKey.get(i);
if (o instanceof RexNode) {
leftValues[i] = resolveParam((RexNode) o, paramsArgs);
} else {
leftValues[i] = o;
}
}
for (int i = 0; i < rightValues.length; i++) {
Object o = rangeQueryUpperKey.get(i);
if (o instanceof RexNode) {
rightValues[i] = resolveParam((RexNode) o, paramsArgs);
} else {
rightValues[i] = o;
}
}
Arrays.sort(leftValues);
Arrays.sort(rightValues);
Object leftSmallOne = leftValues[0];
Object rightBigOne = rightValues[rightValues.length - 1];
if (rangeQueryLowerOp == ComparisonOperator.LT) {
rangeQueryLowerOp = ComparisonOperator.LTE;
}
if (rangeQueryUpperOp == ComparisonOperator.GT) {
rangeQueryUpperOp = ComparisonOperator.GTE;
}
if (rangeQueryLowerOp == ComparisonOperator.LTE && rangeQueryUpperOp == ComparisonOperator.GTE){
String columnName = selectedColumnNames.get(0);
HashMap<String, Collection<RangeVariable>> map = new HashMap<>();
map.put(columnName,Collections.singleton(new RangeVariable(columnName, RangeVariableType.RANGE,leftSmallOne,rightBigOne)));
return table.getShardingFuntion().calculate(map);
}else {
return table.getShardingFuntion().calculate(Collections.emptyMap());
}
}
}
package io.mycat.drdsrunner;
import io.mycat.DataNode;
import io.mycat.calcite.table.ShardingTable;
import io.mycat.querycondition.ComparisonOperator;
import io.mycat.router.CustomRuleFunction;
import lombok.ToString;
import org.apache.calcite.rex.RexNode;
import java.util.Collections;
import java.util.List;
@ToString
public class GetRecordIteratorBySk implements ConditionHandler{
private final String indexName;
private final List<Object> pointQueryKey;
private final ComparisonOperator gte;
private final List<Object> pointQueryKey1;
private final ComparisonOperator lte;
private final List<String> selectedColumnNames;
public GetRecordIteratorBySk(String indexName, List<Object> pointQueryKey, ComparisonOperator gte, List<Object> pointQueryKey1, ComparisonOperator lte, List<String> selectedColumnNames) {
this.indexName = indexName;
this.pointQueryKey = pointQueryKey;
this.gte = gte;
this.pointQueryKey1 = pointQueryKey1;
this.lte = lte;
this.selectedColumnNames = selectedColumnNames;
}
public static GetRecordIteratorBySk of(String indexName, List<Object> pointQueryKey, ComparisonOperator gte, List<Object> pointQueryKey1, ComparisonOperator lte, List<String> selectedColumnNames, List<RexNode> pushDownConditions){
return new GetRecordIteratorBySk(indexName,pointQueryKey,gte,pointQueryKey1,lte,selectedColumnNames);
}
public List<DataNode> handle(ShardingTable table, Object[] params) {
GetRangeQueryIterator.getDataNodes(table,params,pointQueryKey,)
}
}
package io.mycat.drdsrunner;
import io.mycat.querycondition.QueryType;
import org.testng.annotations.Test;
public class IndexCondition2 {
public static final IndexCondition2 EMPTY_CONDITION = ;
public QueryType getQueryType() {
}
}
package io.mycat.drdsrunner;
import org.apache.calcite.rex.RexDynamicParam;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexNode;
public class MycatRexUtil {
public static Object resolveParam(RexNode rexNode, Object[] params) {
if (rexNode instanceof RexDynamicParam) {
int index = ((RexDynamicParam) rexNode).getIndex();
return params[index];
}
if (rexNode instanceof RexLiteral) {
return ((RexLiteral) rexNode).getValue();
}
return rexNode;
}
}
package io.mycat.drdsrunner;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
import io.mycat.DrdsRunner;
import io.mycat.MetaClusterCurrent;
import io.mycat.MetadataManager;
import io.mycat.MycatCore;
import io.mycat.calcite.MycatCalciteSupport;
import io.mycat.calcite.physical.MycatInsertRel;
import io.mycat.calcite.physical.MycatUpdateRel;
import io.mycat.config.*;
import io.mycat.hint.CreateClusterHint;
import io.mycat.hint.CreateDataSourceHint;
import io.mycat.router.ShardingTableHandler;
import io.mycat.util.JsonUtil;
import org.apache.calcite.persistor.MycatInsertRelPersistor;
import org.apache.calcite.persistor.MycatUpdateRelPersistor;
import org.apache.calcite.persistor.RelOptCostPersistor;
import org.apache.calcite.plan.RelOptCost;
import org.junit.Assert;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import static io.mycat.assemble.MycatTest.DB1;
import static io.mycat.assemble.MycatTest.DB2;
import static org.apache.calcite.persistor.RelOptCostPersistor.toRelOptCost;
public class PersistTest {
@Test
public void testMycaUpdateRel() {
initRuntime();
MetadataManager metadataManager = MetaClusterCurrent.wrapper(MetadataManager.class);
MycatUpdateRel mycatUpdateRel = MycatUpdateRel.create(Arrays.asList(MycatCalciteSupport.RexBuilder.makeLiteral(true)),
(SQLStatement) SQLUtils.parseSingleMysqlStatement(
"INSERT INTO db1.sharding (id) VALUES (?)"),"db1","sharding");
String persist = MycatUpdateRelPersistor.persist(mycatUpdateRel);
Assert.assertEquals(persist, MycatUpdateRelPersistor.persist(MycatUpdateRelPersistor.unPersist(persist)));
}
@Test
public void testMycatInsertRel() {
initRuntime();
MetadataManager metadataManager = MetaClusterCurrent.wrapper(MetadataManager.class);
MycatInsertRel mycatInsertRel = MycatInsertRel.create(-1, Arrays.asList(1),
(MySqlInsertStatement) SQLUtils.parseSingleMysqlStatement(
"INSERT INTO db1.sharding (id) VALUES (?)"), (ShardingTableHandler) metadataManager.getTable("db1", "sharding"));
String persist = MycatInsertRelPersistor.persist(mycatInsertRel);
Assert.assertEquals(persist, MycatInsertRelPersistor.persist(MycatInsertRelPersistor.unPersist(persist)));
}
public static void main(String[] args) {
initRuntime();
MetadataManager wrapper = MetaClusterCurrent.wrapper(MetadataManager.class);
System.out.println();
}
public static void initRuntime() {
MycatCore mycatCore = new MycatCore();
FileMetadataStorageManager fileMetadataStorageManager = MetaClusterCurrent.wrapper(FileMetadataStorageManager.class);
MycatRouterConfig mycatRouterConfig = new MycatRouterConfig();
LogicSchemaConfig logicSchemaConfig = new LogicSchemaConfig();
mycatRouterConfig.getSchemas().add(logicSchemaConfig);
logicSchemaConfig.setSchemaName("db1");
ShardingTableConfig mainSharding = new ShardingTableConfig();
mainSharding.setCreateTableSQL("CREATE TABLE db1.`sharding` (\n" +
" `id` bigint NOT NULL AUTO_INCREMENT,\n" +
" `user_id` varchar(100) DEFAULT NULL,\n" +
" `traveldate` date DEFAULT NULL,\n" +
" `fee` decimal(10,0) DEFAULT NULL,\n" +
" `days` int DEFAULT NULL,\n" +
" `blob` longblob,\n" +
" PRIMARY KEY (`id`),\n" +
" KEY `id` (`id`)\n" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8"
+ " dbpartition by hash(id) tbpartition by hash(id) tbpartitions 2 dbpartitions 2;");
mainSharding.setFunction(ShardingFuntion.builder().properties(JsonUtil.from("{\n" +
"\t\t\t\t\t\"dbNum\":\"2\",\n" +
"\t\t\t\t\t\"mappingFormat\":\"c${targetIndex}/db1_${dbIndex}/sharding_${tableIndex}\",\n" +
"\t\t\t\t\t\"tableNum\":\"2\",\n" +
"\t\t\t\t\t\"tableMethod\":\"hash(id)\",\n" +
"\t\t\t\t\t\"storeNum\":2,\n" +
"\t\t\t\t\t\"dbMethod\":\"hash(id)\"\n" +
"\t\t\t\t}", Map.class)).build());
logicSchemaConfig.getShadingTables().put("sharding", mainSharding);
mycatRouterConfig.getClusters().add(CreateClusterHint.createConfig("c0", Arrays.asList("ds0"), Collections.emptyList()));
mycatRouterConfig.getDatasources().add(CreateDataSourceHint.createConfig("ds0", DB1));
mycatRouterConfig.getDatasources().add(CreateDataSourceHint.createConfig("prototype", DB1));
fileMetadataStorageManager.start(mycatRouterConfig);
}
@Test
public void testVolcanoCostPersist() {
String text = "{\n" +
"\t\"cpu\":2.0,\n" +
"\t\"io\":3.0,\n" +
"\t\"rowCount\":1.0,\n" +
"\t\"className\":\"org.apache.calcite.plan.volcano.VolcanoCost\"\n" +
"}";
RelOptCost relOptCost = toRelOptCost(text);
Assert.assertEquals(text, RelOptCostPersistor. persist(relOptCost));
}
}
package io.mycat.drdsrunner;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import io.mycat.calcite.MycatCalciteSupport;
import io.mycat.querycondition.*;
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.rex.*;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.commons.collections4.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class PredicateAnalyzer3 {
private static final RexBuilder REX_BUILDER = MycatCalciteSupport.RexBuilder;
private final List<KeyMeta> keyMetaList;
private final String forceIndexName;
public PredicateAnalyzer3(List<KeyMeta> keyMetaList, String forceIndexName) {
this.keyMetaList = keyMetaList;
this.forceIndexName = forceIndexName;
}
public static class KeyMeta {
String columnName;
}
public static class IndexCondition {
public static final IndexCondition EMPTY_CONDITION = ;
String indexName;
boolean canPushDown() {
}
public boolean nameMatch(String name) {
return name != null && name.equalsIgnoreCase(indexName);
}
public QueryType getQueryType() {
return null;
}
}
public IndexCondition translateMatch(RexNode condition) {
List<RexNode> disjunctions = RelOptUtil.disjunctions(condition);
if (disjunctions.size() == 1) {
return translateAnd(disjunctions.get(0));
} else {
return IndexCondition.EMPTY_CONDITION;
}
}
private IndexCondition translateAnd(RexNode condition) {
// expand calls to SEARCH(..., Sarg()) to >, =, etc.
final RexNode condition2 =
RexUtil.expandSearch(REX_BUILDER, null, condition);
// decompose condition by AND, flatten row expression
List<RexNode> rexNodeList = RelOptUtil.conjunctions(condition2);
List<IndexCondition> indexConditions = new ArrayList<>();
// try to push down filter by secondary keys
for (KeyMeta skMeta : keyMetaList) {
indexConditions.add(findPushDownCondition(rexNodeList, skMeta));
}
// a collection of all possible push down conditions, see if it can
// be pushed down, filter by forcing index name, then sort by comparator
Stream<IndexCondition> pushDownConditions = indexConditions.stream()
.filter(IndexCondition::canPushDown)
.filter(this::nonForceIndexOrMatchForceIndexName)
.sorted(new IndexConditionComparator());
return pushDownConditions.findFirst().orElse(IndexCondition.EMPTY_CONDITION);
}
private List<InternalRexNode> analyzePrefixMatches(List<RexNode> rexNodeList, io.mycat.querycondition.KeyMeta keyMeta) {
return rexNodeList.stream()
.map(rexNode -> translateMatch2(rexNode, keyMeta))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
}
/**
* Translates a call to a binary operator. Returns null on failure.
*/
private Optional<InternalRexNode> translateBinary2(String op, RexNode left,
RexNode right, RexNode originNode, io.mycat.querycondition.KeyMeta keyMeta) {
RexNode rightLiteral;
if (right.isA(SqlKind.LITERAL) || right.isA(SqlKind.DYNAMIC_PARAM)) {
rightLiteral = right;
} else {
// because MySQL's TIMESTAMP is mapped to TIMESTAMP_WITH_TIME_ZONE sql type,
// we should cast the value to literal.
if (right.isA(SqlKind.CAST)
&& isSqlTypeMatch((RexCall) right, SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE)) {
rightLiteral = ((RexCall) right).operands.get(0);
} else {
return Optional.empty();
}
}
switch (left.getKind()) {
case INPUT_REF:
final RexInputRef left1 = (RexInputRef) left;
String name = fieldNames.get(left1.getIndex());
// filter out field does not show in index column
if (!keyMeta.getKeyColumnNames().contains(name)) {
return Optional.empty();
}
return translateOp2(op, name, rightLiteral, originNode, keyMeta);
case CAST:
return translateBinary2(op, ((RexCall) left).operands.get(0), right,
originNode, keyMeta);
default:
return Optional.empty();
}
}
/**
* Combines a field name, operator, and literal to produce a predicate string.
*/
private static Optional<InternalRexNode> translateOp2(String op, String name,
RexNode right, RexNode originNode, io.mycat.querycondition.KeyMeta keyMeta) {
;
InternalRexNode node = new InternalRexNode();
node.node = originNode;
node.ordinalInKey = keyMeta.getKeyColumnNames().indexOf(name);
// For variable length column, Innodb-java-reader have a limitation,
// left-prefix index length should be less than search value literal.
// For example, we cannot leverage index of EMAIL(3) upon search value
// `[email protected]`, because the value length is longer than 3.
node.fieldName = name;
node.op = op;
node.right = right;
return Optional.of(node);
}
private IndexCondition findPushDownCondition(List<RexNode> rexNodeList, KeyMeta skMeta) {
// find field expressions matching index columns and specific operators
List<InternalRexNode> matchedRexNodeList = analyzePrefixMatches(rexNodeList, keyMeta);
// none of the conditions can be pushed down
if (CollectionUtils.isEmpty(matchedRexNodeList)) {
return IndexCondition.EMPTY_CONDITION;
}
// a collection that maps ordinal in index column list
// to multiple field expressions
Multimap<Integer,InternalRexNode> keyOrdToNodesMap = HashMultimap.create();
for (InternalRexNode node : matchedRexNodeList) {
keyOrdToNodesMap.put(node.ordinalInKey, node);
}
// left-prefix index rule not match
Collection<InternalRexNode> leftMostKeyNodes = keyOrdToNodesMap.get(0);
if (CollectionUtils.isEmpty(leftMostKeyNodes)) {
return IndexCondition.EMPTY_CONDITION;
}
// create result which might have conditions to push down
List<String> indexColumnNames = keyMeta.getKeyColumnNames();
List<RexNode> pushDownRexNodeList = new ArrayList<>();
List<RexNode> remainderRexNodeList = new ArrayList<>(rexNodeList);
io.mycat.querycondition.IndexCondition condition =
io.mycat.querycondition.IndexCondition.create(fieldNames, keyMeta.getName(), indexColumnNames);
// handle point query if possible
condition = handlePointQuery(condition, keyMeta, leftMostKeyNodes,
keyOrdToNodesMap, pushDownRexNodeList, remainderRexNodeList);
if (condition.canPushDown()) {
return condition;
}
// handle range query
condition = handleRangeQuery(condition, keyMeta, leftMostKeyNodes,
pushDownRexNodeList, remainderRexNodeList, ">=", ">");
condition = handleRangeQuery(condition, keyMeta, leftMostKeyNodes,
pushDownRexNodeList, remainderRexNodeList, "<=", "<");
return condition;
}
private boolean nonForceIndexOrMatchForceIndexName(IndexCondition indexCondition) {
return Optional.ofNullable(forceIndexName)
.map(indexCondition::nameMatch).orElse(true);
}
static class IndexConditionComparator implements Comparator<IndexCondition> {
@Override
public int compare(IndexCondition o1,IndexCondition o2) {
return Integer.compare(o1.getQueryType().priority(), o2.getQueryType().priority());
}
}
/**
* Internal representation of a row expression.
*/
private static class InternalRexNode {
/**
* Relation expression node.
*/
RexNode node;
/**
* Field ordinal in indexes.
*/
int ordinalInKey;
/**
* Field name.
*/
String fieldName;
/**
* Binary operation like =, >=, <=, > or <.
*/
String op;
/**
* Binary operation right literal value.
*/
Object right;
}
private static io.mycat.querycondition.IndexCondition handleRangeQuery(io.mycat.querycondition.IndexCondition condition,
io.mycat.querycondition.KeyMeta keyMeta, Collection<InternalRexNode> leftMostKeyNodes,
List<RexNode> pushDownRexNodeList,
List<RexNode> remainderRexNodeList,
String... opList) {
Optional<InternalRexNode> node = findFirstOp(leftMostKeyNodes, opList);
if (node.isPresent()) {
pushDownRexNodeList.add(node.get().node);
remainderRexNodeList.remove(node.get().node);
List<Object> key = createKey(Lists.newArrayList(node.get()));
ComparisonOperator op = ComparisonOperator.parse(node.get().op);
if (ComparisonOperator.isLowerBoundOp(opList)) {
return condition
.withQueryType(QueryType.getRangeQuery(keyMeta.isSecondaryKey()))
.withRangeQueryLowerOp(op)
.withRangeQueryLowerKey(key)
.withPushDownConditions(pushDownRexNodeList)
.withRemainderConditions(remainderRexNodeList);
} else if (ComparisonOperator.isUpperBoundOp(opList)) {
return condition
.withQueryType(QueryType.getRangeQuery(keyMeta.isSecondaryKey()))
.withRangeQueryUpperOp(op)
.withRangeQueryUpperKey(key)
.withPushDownConditions(pushDownRexNodeList)
.withRemainderConditions(remainderRexNodeList);
} else {
throw new AssertionError("comparison operation is invalid " + op);
}
}
return condition;
}
private static boolean isSqlTypeMatch(RexCall rexCall, SqlTypeName sqlTypeName) {
assert rexCall != null;
return rexCall.type.getSqlTypeName() == sqlTypeName;
}
/**
* Translates a binary relation.
*/
private Optional<InternalRexNode> translateMatch2(RexNode node, io.mycat.querycondition.KeyMeta keyMeta) {
switch (node.getKind()) {
case EQUALS:
return translateBinary("=", "=", (RexCall) node, keyMeta);
case LESS_THAN:
return translateBinary("<", ">", (RexCall) node, keyMeta);
case LESS_THAN_OR_EQUAL:
return translateBinary("<=", ">=", (RexCall) node, keyMeta);
case GREATER_THAN:
return translateBinary(">", "<", (RexCall) node, keyMeta);
case GREATER_THAN_OR_EQUAL:
return translateBinary(">=", "<=", (RexCall) node, keyMeta);
default:
return Optional.empty();
}
}
private Optional<InternalRexNode> translateBinary(String op, String rop,
RexCall call, io.mycat.querycondition.KeyMeta keyMeta) {
final RexNode left = call.operands.get(0);
final RexNode right = call.operands.get(1);
Optional<InternalRexNode> expression =
translateBinary2(op, left, right, call, keyMeta);
if (expression.isPresent()) {
return expression;
}
expression = translateBinary2(rop, right, left, call, keyMeta);
return expression;
}
}
//package io.mycat.drdsrunner;
//
//import io.mycat.calcite.MycatCalciteSupport;
//import io.mycat.querycondition.*;
//import org.apache.calcite.rex.*;
//import org.apache.calcite.sql.fun.SqlStdOperatorTable;
//import org.apache.calcite.sql.type.SqlTypeName;
//import org.jetbrains.annotations.NotNull;
//import org.junit.Assert;
//import org.junit.Test;
//
//import java.util.*;
//
//public class PredicateAnalyzerTest {
// private static final RexBuilder rexBuilder = MycatCalciteSupport.RexBuilder;
//
//
// @Test
// public void testTrue() {
// RexLiteral rexLiteral = rexBuilder.makeLiteral(true);
// List<String> columnList = Arrays.asList("id");
// PredicateAnalyzer2 predicateAnalyzer2 = new PredicateAnalyzer2(
// columnList,
// KeyMeta.builder().name("default").type(KeyMeta.Type.PRIMARY_KEY).keyColumnNames(columnList).build(), Collections.emptyList(), null);
// IndexCondition indexCondition = predicateAnalyzer2.translateMatch(rexLiteral);
// Assert.assertEquals(null, indexCondition.getQueryType());
// }
//
// @Test
// public void testEqual() {
// RexNode rexNode = rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexBuilder.makeInputRef(
// MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER),
// 0
// ), rexBuilder.makeLiteral(1, MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER), false));
// List<String> columnList = Arrays.asList("id");
// PredicateAnalyzer2 predicateAnalyzer2 = new PredicateAnalyzer2(
// columnList,
// KeyMeta.builder().name("default").type(KeyMeta.Type.PRIMARY_KEY).keyColumnNames(columnList).build(), Collections.emptyList(), null);
// Object o = getObject(predicateAnalyzer2, (rexNode));
// Assert.assertEquals("QueryByPrimaryKey(pointQueryKey=[1], selectedColumnNames=[id])", Objects.toString(o));
// }
//
// @Test
// public void testEqualParam() {
// RexNode rexNode = rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexBuilder.makeInputRef(
// MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER),
// 0
// ), rexBuilder.makeDynamicParam(MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER), 0));
// List<String> columnList = Arrays.asList("id");
// PredicateAnalyzer2 predicateAnalyzer2 = new PredicateAnalyzer2(
// columnList,
// KeyMeta.builder().name("default").type(KeyMeta.Type.PRIMARY_KEY).keyColumnNames(columnList).build(), Collections.emptyList(), null);
// Object o = getObject(predicateAnalyzer2.translateMatch(rexNode), columnList);
// Assert.assertEquals("QueryByPrimaryKey(pointQueryKey=[?0], selectedColumnNames=[id])", Objects.toString(o));
// }
//
// @Test
// public void testRange() {
// RexNode leftRexNode = rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN, rexBuilder.makeInputRef(
// MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER),
// 0
// ), rexBuilder.makeDynamicParam(MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER), 0));
//
// RexNode rightRexNode = rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, rexBuilder.makeInputRef(
// MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER),
// 0
// ), rexBuilder.makeDynamicParam(MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER), 1));
//
// RexNode rexNode = rexBuilder.makeCall(SqlStdOperatorTable.AND, leftRexNode, rightRexNode);
// List<String> columnList = Arrays.asList("id");
// PredicateAnalyzer2 predicateAnalyzer2 = new PredicateAnalyzer2(
// columnList,
// KeyMeta.builder().name("default").type(KeyMeta.Type.PRIMARY_KEY).keyColumnNames(columnList).build(), Collections.emptyList(), null);
// Object o = getObject(predicateAnalyzer2.translateMatch(rexNode), columnList);
// Assert.assertEquals("GetRangeQueryIterator(rangeQueryLowerKey=[?0], rangeQueryLowerOp=GT, rangeQueryUpperKey=[?1], rangeQueryUpperOp=LT, selectedColumnNames=[id])", Objects.toString(o));
// }
//
// @Test
// public void testOr() {
// RexNode leftRexNode = rexBuilder.makeCall(SqlStdOperatorTable.GREATER_THAN, rexBuilder.makeInputRef(
// MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER),
// 0
// ), rexBuilder.makeDynamicParam(MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER), 0));
//
// RexNode rightRexNode = rexBuilder.makeCall(SqlStdOperatorTable.LESS_THAN, rexBuilder.makeInputRef(
// MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER),
// 0
// ), rexBuilder.makeDynamicParam(MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER), 1));
//
// RexNode rexNode = rexBuilder.makeCall(SqlStdOperatorTable.OR, leftRexNode, rightRexNode);
// List<String> columnList = Arrays.asList("id");
// PredicateAnalyzer2 predicateAnalyzer2 = new PredicateAnalyzer2(
// columnList,
// KeyMeta.builder().name("default").type(KeyMeta.Type.PRIMARY_KEY).keyColumnNames(columnList).build(), Collections.emptyList(), null);
// Assert.assertEquals("(null, index=null)", Objects.toString(predicateAnalyzer2.translateMatch(rexNode)));
// }
//
// @Test
// public void testNot() {
// RexNode leftRexNode = rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexBuilder.makeInputRef(
// MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER),
// 0
// ), rexBuilder.makeDynamicParam(MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER), 0));
// RexNode rexNode = rexBuilder.makeCall(SqlStdOperatorTable.NOT, leftRexNode);
// List<String> columnList = Arrays.asList("id");
// PredicateAnalyzer2 predicateAnalyzer2 = new PredicateAnalyzer2(
// columnList,
// KeyMeta.builder().name("default").type(KeyMeta.Type.PRIMARY_KEY).keyColumnNames(columnList).build(), Collections.emptyList(), null);
// Assert.assertEquals("(null, index=null)", Objects.toString(predicateAnalyzer2.translateMatch(rexNode)));
// }
//
// @Test
// public void testDoubleColumns() {
// RexNode leftRexNode = rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexBuilder.makeInputRef(
// MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER),
// 0
// ), rexBuilder.makeDynamicParam(MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER), 0));
// RexNode rightRexNode = rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, rexBuilder.makeInputRef(
// MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER),
// 1
// ), rexBuilder.makeDynamicParam(MycatCalciteSupport.TypeFactory.createSqlType(SqlTypeName.INTEGER), 0));
// List<String> columnList = Arrays.asList("id", "id2");
// PredicateAnalyzer2 predicateAnalyzer2 = new PredicateAnalyzer2(
// columnList,
// KeyMeta.builder().name("default").type(KeyMeta.Type.PRIMARY_KEY).keyColumnNames(columnList).build(), Collections.emptyList(), null);
// Assert.assertEquals("(PK_POINT_QUERY, index=default, id=?0,id2=?0)", Objects.toString(predicateAnalyzer2.translateMatch(RexUtil.composeConjunction(rexBuilder, Arrays.asList(leftRexNode, rightRexNode)))));
// }
//
// @NotNull
// private Object getObject(PredicateAnalyzer2 predicateAnalyzer2, RexNode rexNode, List<String> columnList) {
// IndexCondition condition = predicateAnalyzer2.translateMatch(rexNode);
// final List<Object> pointQueryKey = condition.getPointQueryKey();
// final ComparisonOperator rangeQueryLowerOp = condition.getRangeQueryLowerOp();
// final List<Object> rangeQueryLowerKey = condition.getRangeQueryLowerKey();
// final ComparisonOperator rangeQueryUpperOp = condition.getRangeQueryUpperOp();
// final List<Object> rangeQueryUpperKey = condition.getRangeQueryUpperKey();
// final String indexName = condition.getIndexName();
//
// final List<String> selectedColumnNames = columnList;
//
//
// Object o;
// switch (condition.getQueryType()) {
// case PK_POINT_QUERY:
// //queryByPrimaryKey
// o = QueryByPrimaryKey.of(pointQueryKey,condition.getIndexColumnNames());
// break;
// case PK_RANGE_QUERY:
// o = GetRangeQueryIterator.of(
// rangeQueryLowerKey, rangeQueryLowerOp, rangeQueryUpperKey, rangeQueryUpperOp, condition.getIndexColumnNames());
// break;
// case SK_POINT_QUERY:
// o = GetRecordIteratorBySk.of(indexName,
// pointQueryKey, ComparisonOperator.GTE, pointQueryKey, ComparisonOperator.LTE,
// selectedColumnNames, pushDownConditions);
// break;
// case SK_RANGE_QUERY:
// case SK_FULL_SCAN:
// o = GetRecordIteratorBySk.of(indexName,
// rangeQueryLowerKey, rangeQueryLowerOp, rangeQueryUpperKey, rangeQueryUpperOp,
// selectedColumnNames, pushDownConditions);
// break;
// case PK_FULL_SCAN:
// default:
// o = GetQueryAllIterator.of();
// break;
//
// }
// return o;
// }
//
//
//}
package io.mycat.drdsrunner;
import io.mycat.DataNode;
import io.mycat.RangeVariable;
import io.mycat.RangeVariableType;
import io.mycat.calcite.table.ShardingTable;
import io.mycat.querycondition.KeyMeta;
import io.mycat.router.CustomRuleFunction;
import lombok.ToString;
import org.apache.calcite.rex.RexDynamicParam;
import org.apache.calcite.rex.RexNode;
import java.util.*;
import static io.mycat.drdsrunner.MycatRexUtil.resolveParam;
@ToString
public class QueryByPrimaryKey implements ConditionHandler {
private final List<Object> pointQueryKey;
private final List<String> fieldList;
public QueryByPrimaryKey(List<Object> pointQueryKey, List<String> fieldList) {
this.pointQueryKey = pointQueryKey;
this.fieldList = fieldList;
}
public static QueryByPrimaryKey of(List<Object> pointQueryKey, List<String> fieldList) {
return new QueryByPrimaryKey(pointQueryKey, fieldList);
}
public List<DataNode> handle(ShardingTable table, Object[] params) {
CustomRuleFunction shardingFuntion = table.getShardingFuntion();
if (pointQueryKey.isEmpty()) {
return shardingFuntion.calculate(Collections.emptyMap());
}
List<String> keyColumnNames = fieldList;
String columnName = keyColumnNames.get(0);
Map<String, Collection<RangeVariable>> map = new HashMap<>();
Object[] values = new Object[pointQueryKey.size()];
int index = 0;
for (Object o : pointQueryKey) {
if (o instanceof RexNode) {
values[index] = resolveParam((RexNode) o, params);
}else {
values[index] = o;
}
index++;
}
Collection<RangeVariable> rangeVariables = map.computeIfAbsent(columnName, (k) -> new ArrayList<>());
for (Object value : values) {
rangeVariables.add(new RangeVariable(columnName, RangeVariableType.EQUAL, value));
}
if (pointQueryKey.isEmpty()) {
return shardingFuntion.calculate(Collections.emptyMap());
}
return shardingFuntion.calculate(map);
}
}
package io.mycat.drdsrunner;
import io.mycat.calcite.physical.MycatProject;
import io.mycat.calcite.spm.SpecificSql;
import org.apache.calcite.rel.RelNode;
import org.junit.Assert;
import org.junit.Test;
import java.io.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public class ShardingJoinTest extends DrdsTest {
// @Test
// public void testSelectTest() throws Exception {
// Explain explain = parse("select 1");
// RelNode physical = explain.getPlan().getPhysical();
// ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
// objectOutputStream.writeObject(physical);
//
// physical instanceof MycatProject
// ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(outputStream.toByteArray()));
// Object o = inputStream.readObject();
// Assert.assertEquals("[{columnType=INTEGER, nullable=false, columnName=1}]", explain.getColumnInfo());
// Assert.assertEquals("MycatProject(1=[1]) MycatValues(tuples=[[{ 0 }]]) ", explain.dumpPlan());
// }
@Test
public void testSelect1() throws Exception {
Explain explain = parse("select 1");
Assert.assertEquals("[{columnType=INTEGER, nullable=false, columnName=1}]", explain.getColumnInfo());
Assert.assertEquals("MycatProject(1=[1]) MycatValues(tuples=[[{ 0 }]]) ", explain.dumpPlan());
}
@Test
public void testSelectNormal() throws Exception {
Explain explain = parse("select * from db1.normal");
Assert.assertEquals("[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=addressname}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[normalTables=db1.normal]) ", explain.dumpPlan());
// Assert.assertEquals(
// "[SpecificSql(relNode=MycatView(distribution=[normalTables=db1.normal]) , parameterizedSql=SELECT * FROM db1.normal, sqls=[Each(targetName=prototype, sql=SELECT * FROM db1.normal)])]",
// explain.specificSql().toString());
}
@Test
public void testSelectNormalNormal() throws Exception {
Explain explain = parse("select * from db1.normal s join db1.normal2 e on s.id = e.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=addressname}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=addressname0}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[normalTables=db1.normal,db1.normal2]) ", explain.dumpPlan());
// Assert.assertEquals("[SpecificSql(relNode=MycatView(distribution=[normalTables=db1.normal,db1.normal2]) , parameterizedSql=SELECT * FROM db1.normal INNER JOIN db1.normal2 ON (`normal`.`id` = `normal2`.`id`), sqls=[Each(targetName=prototype, sql=SELECT * FROM db1.normal INNER JOIN db1.normal2 ON (`normal`.`id` = `normal2`.`id`))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectNormalOtherNormal() throws Exception {
Explain explain = parse("select * from db1.normal s join db1.normal3 e on s.id = e.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=addressname}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=addressname0}]",
explain.getColumnInfo());
Assert.assertEquals("MycatHashJoin(condition=[=($0, $2)], joinType=[inner]) MycatView(distribution=[normalTables=db1.normal]) MycatView(distribution=[normalTables=db1.normal3]) ", explain.dumpPlan());
// Assert.assertEquals("[SpecificSql(relNode=MycatView(distribution=[normalTables=db1.normal,db1.normal2]) , parameterizedSql=SELECT * FROM db1.normal INNER JOIN db1.normal2 ON (`normal`.`id` = `normal2`.`id`), sqls=[Each(targetName=prototype, sql=SELECT * FROM db1.normal INNER JOIN db1.normal2 ON (`normal`.`id` = `normal2`.`id`))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectNormalGlobal() throws Exception {
Explain explain = parse("select * from db1.normal s join db1.global e on s.id = e.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=addressname}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=companyname}, {columnType=BIGINT, nullable=true, columnName=addressid}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[normalTables=db1.normal,globalTables=db1.global]) ", explain.dumpPlan());
// Assert.assertEquals("[SpecificSql(relNode=MycatView(distribution=[normalTables=db1.normal,globalTables=db1.global]) , parameterizedSql=SELECT * FROM db1.normal INNER JOIN db1.global ON (`normal`.`id` = `global`.`id`), sqls=[Each(targetName=prototype, sql=SELECT * FROM db1.normal INNER JOIN db1.global ON (`normal`.`id` = `global`.`id`))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectNormalSharding() throws Exception {
Explain explain = parse("select * from db1.normal s join db1.sharding e on s.id = e.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=addressname}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}]",
explain.getColumnInfo());
Assert.assertEquals("MycatHashJoin(condition=[=($0, $2)], joinType=[inner]) MycatView(distribution=[normalTables=db1.normal]) MycatView(distribution=[shardingTables=db1.sharding]) ", explain.dumpPlan());
// Assert.assertEquals(
// "[SpecificSql(relNode=MycatView(distribution=[normalTables=db1.normal]) , parameterizedSql=SELECT * FROM db1.normal, sqls=[Each(targetName=prototype, sql=SELECT * FROM db1.normal)]), SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding]) , parameterizedSql=SELECT * FROM db1.sharding, sqls=[Each(targetName=c0, sql=(SELECT * FROM db1_0.sharding_0 UNION ALL SELECT * FROM db1_0.sharding_1)), Each(targetName=c1, sql=(SELECT * FROM db1_1.sharding_0 UNION ALL SELECT * FROM db1_1.sharding_1))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectSharding() throws Exception {
Explain explain = parse("select * from db1.sharding");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[shardingTables=db1.sharding]) ", explain.dumpPlan());
// Assert.assertEquals(
// "[SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding]) , parameterizedSql=SELECT * FROM db1.sharding, sqls=[Each(targetName=c0, sql=(SELECT * FROM db1_0.sharding_0 UNION ALL SELECT * FROM db1_0.sharding_1)), Each(targetName=c1, sql=(SELECT * FROM db1_1.sharding_0 UNION ALL SELECT * FROM db1_1.sharding_1))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectShardingWhere() throws Exception {
Explain explain = parse("select * from db1.sharding where id = 1");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[shardingTables=db1.sharding], conditions=[=(CAST($0):DECIMAL(19, 0), ?0)]) ", explain.dumpPlan());
// Assert.assertEquals(
// "[SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding], conditions=[=(CAST($0):DECIMAL(19, 0), ?0)]) , parameterizedSql=SELECT * FROM db1.sharding WHERE (CAST(`id` AS decimal) = ?), sqls=[Each(targetName=c0, sql=SELECT * FROM db1_0.sharding_1 WHERE (CAST(`id` AS decimal) = ?))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectShardingSelf() throws Exception {
Explain explain = parse("select * from db1.sharding s join db1.sharding e on s.id = e.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=user_id0}, {columnType=DATE, nullable=true, columnName=traveldate0}, {columnType=DECIMAL, nullable=true, columnName=fee0}, {columnType=BIGINT, nullable=true, columnName=days0}, {columnType=VARBINARY, nullable=true, columnName=blob0}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[shardingTables=db1.sharding,db1.sharding]) ", explain.dumpPlan());
// Assert.assertEquals("[SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding,db1.sharding]) , parameterizedSql=SELECT * FROM db1.sharding INNER JOIN db1.sharding AS `sharding0` ON (`sharding`.`id` = `sharding0`.`id`), sqls=[Each(targetName=c0, sql=(SELECT * FROM db1_0.sharding_0 INNER JOIN db1_0.sharding_0 AS `sharding_00` ON (`sharding_0`.`id` = `sharding_00`.`id`) UNION ALL SELECT * FROM db1_0.sharding_1 INNER JOIN db1_0.sharding_1 AS `sharding_10` ON (`sharding_1`.`id` = `sharding_10`.`id`))), Each(targetName=c1, sql=(SELECT * FROM db1_1.sharding_0 INNER JOIN db1_1.sharding_0 AS `sharding_00` ON (`sharding_0`.`id` = `sharding_00`.`id`) UNION ALL SELECT * FROM db1_1.sharding_1 INNER JOIN db1_1.sharding_1 AS `sharding_10` ON (`sharding_1`.`id` = `sharding_10`.`id`)))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectShardingSharding() throws Exception {
Explain explain = parse("select * from db1.sharding s join db1.other_sharding e on s.id = e.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=user_id0}, {columnType=DATE, nullable=true, columnName=traveldate0}, {columnType=DECIMAL, nullable=true, columnName=fee0}, {columnType=BIGINT, nullable=true, columnName=days0}, {columnType=VARBINARY, nullable=true, columnName=blob0}]",
explain.getColumnInfo());
Assert.assertEquals("MycatHashJoin(condition=[=($0, $6)], joinType=[inner]) MycatView(distribution=[shardingTables=db1.sharding]) MycatView(distribution=[shardingTables=db1.other_sharding]) ", explain.dumpPlan());
// Assert.assertEquals("[SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding]) , parameterizedSql=SELECT * FROM db1.sharding, sqls=[Each(targetName=c0, sql=(SELECT * FROM db1_0.sharding_0 UNION ALL SELECT * FROM db1_0.sharding_1)), Each(targetName=c1, sql=(SELECT * FROM db1_1.sharding_0 UNION ALL SELECT * FROM db1_1.sharding_1))]), SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.other_sharding]) , parameterizedSql=SELECT * FROM db1.other_sharding, sqls=[Each(targetName=c0, sql=(SELECT * FROM db1_0.other_sharding_0 UNION ALL SELECT * FROM db1_0.other_sharding_1)), Each(targetName=c1, sql=(SELECT * FROM db1_1.other_sharding_0 UNION ALL SELECT * FROM db1_1.other_sharding_1))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectShardingNormal() throws Exception {
Explain explain = parse("select * from db1.sharding s join db1.normal e on s.id = e.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=addressname}]",
explain.getColumnInfo());
Assert.assertEquals("MycatHashJoin(condition=[=($0, $6)], joinType=[inner]) MycatView(distribution=[shardingTables=db1.sharding]) MycatView(distribution=[normalTables=db1.normal]) ", explain.dumpPlan());
// Assert.assertEquals("[SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding]) , parameterizedSql=SELECT * FROM db1.sharding, sqls=[Each(targetName=c0, sql=(SELECT * FROM db1_0.sharding_0 UNION ALL SELECT * FROM db1_0.sharding_1)), Each(targetName=c1, sql=(SELECT * FROM db1_1.sharding_0 UNION ALL SELECT * FROM db1_1.sharding_1))]), SpecificSql(relNode=MycatView(distribution=[normalTables=db1.normal]) , parameterizedSql=SELECT * FROM db1.normal, sqls=[Each(targetName=prototype, sql=SELECT * FROM db1.normal)])]",
// explain.specificSql().toString());
}
@Test
public void testSelectShardingGlobal() throws Exception {
Explain explain = parse("select * from db1.sharding s join db1.global e on s.id = e.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=companyname}, {columnType=BIGINT, nullable=true, columnName=addressid}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[shardingTables=db1.sharding,globalTables=db1.global]) ", explain.dumpPlan());
// Assert.assertEquals(
// "[SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding,globalTables=db1.global]) , parameterizedSql=SELECT * FROM db1.sharding INNER JOIN db1.global ON (`sharding`.`id` = `global`.`id`), sqls=[Each(targetName=c0, sql=(SELECT * FROM db1_0.sharding_0 INNER JOIN db1.global ON (`sharding_0`.`id` = `global`.`id`) UNION ALL SELECT * FROM db1_0.sharding_1 INNER JOIN db1.global AS `global0` ON (`sharding_1`.`id` = `global0`.`id`))), Each(targetName=c1, sql=(SELECT * FROM db1_1.sharding_0 INNER JOIN db1.global ON (`sharding_0`.`id` = `global`.`id`) UNION ALL SELECT * FROM db1_1.sharding_1 INNER JOIN db1.global AS `global0` ON (`sharding_1`.`id` = `global0`.`id`)))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectShardingERWhere() throws Exception {
Explain explain = parse("select * from db1.sharding s join db1.er e on s.id = e.id where s.id = 1");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=user_id0}, {columnType=DATE, nullable=true, columnName=traveldate0}, {columnType=DECIMAL, nullable=true, columnName=fee0}, {columnType=BIGINT, nullable=true, columnName=days0}, {columnType=VARBINARY, nullable=true, columnName=blob0}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[shardingTables=db1.sharding,db1.er], conditions=[=(CAST($0):DECIMAL(19, 0), ?0)]) ", explain.dumpPlan());
System.out.println(explain.specificSql());
// Assert.assertEquals(
// "[SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding], conditions=[=(CAST($0):DECIMAL(19, 0), ?0)]) , parameterizedSql=SELECT * FROM db1.sharding WHERE (CAST(`id` AS decimal) = ?), sqls=[Each(targetName=c0, sql=SELECT * FROM db1_0.sharding_1 WHERE (CAST(`id` AS decimal) = ?))]), SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.er], conditions=[=(CAST($0):DECIMAL(19, 0), ?0)]) , parameterizedSql=SELECT * FROM db1.er WHERE (CAST(`id` AS decimal) = ?), sqls=[Each(targetName=c0, sql=SELECT * FROM db1_0.er_1 WHERE (CAST(`id` AS decimal) = ?))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectShardingER() throws Exception {
Explain explain = parse("select * from db1.sharding s join db1.er e on s.id = e.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=user_id0}, {columnType=DATE, nullable=true, columnName=traveldate0}, {columnType=DECIMAL, nullable=true, columnName=fee0}, {columnType=BIGINT, nullable=true, columnName=days0}, {columnType=VARBINARY, nullable=true, columnName=blob0}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[shardingTables=db1.sharding,db1.er]) ", explain.dumpPlan());
System.out.println(explain.specificSql());
// Assert.assertEquals(
// "[SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding,db1.er]) , parameterizedSql=SELECT * FROM db1.sharding INNER JOIN db1.er ON (`sharding`.`id` = `er`.`id`), sqls=[Each(targetName=c0, sql=(SELECT * FROM db1_0.sharding_0 INNER JOIN db1_0.er_0 ON (`sharding_0`.`id` = `er_0`.`id`) UNION ALL SELECT * FROM db1_0.sharding_1 INNER JOIN db1_0.er_1 ON (`sharding_1`.`id` = `er_1`.`id`))), Each(targetName=c1, sql=(SELECT * FROM db1_1.sharding_0 INNER JOIN db1_1.er_0 ON (`sharding_0`.`id` = `er_0`.`id`) UNION ALL SELECT * FROM db1_1.sharding_1 INNER JOIN db1_1.er_1 ON (`sharding_1`.`id` = `er_1`.`id`)))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectShardingERGlobal() throws Exception {
Explain explain = parse("select * from db1.sharding s join db1.er e on s.id = e.id join db1.global g on e.id = g.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=user_id0}, {columnType=DATE, nullable=true, columnName=traveldate0}, {columnType=DECIMAL, nullable=true, columnName=fee0}, {columnType=BIGINT, nullable=true, columnName=days0}, {columnType=VARBINARY, nullable=true, columnName=blob0}, {columnType=BIGINT, nullable=true, columnName=id1}, {columnType=VARCHAR, nullable=true, columnName=companyname}, {columnType=BIGINT, nullable=true, columnName=addressid}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[shardingTables=db1.sharding,db1.er,globalTables=db1.global]) ", explain.dumpPlan());
System.out.println(explain.specificSql());
// Assert.assertEquals(
// "[SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding,db1.er,globalTables=db1.global]) , parameterizedSql=SELECT * FROM db1.sharding INNER JOIN db1.er ON (`sharding`.`id` = `er`.`id`) INNER JOIN db1.global ON (`er`.`id` = `global`.`id`), sqls=[Each(targetName=c0, sql=(SELECT * FROM db1_0.sharding_0 INNER JOIN db1_0.er_0 ON (`sharding_0`.`id` = `er_0`.`id`) INNER JOIN db1.global ON (`er_0`.`id` = `global`.`id`) UNION ALL SELECT * FROM db1_0.sharding_1 INNER JOIN db1_0.er_1 ON (`sharding_1`.`id` = `er_1`.`id`) INNER JOIN db1.global AS `global0` ON (`er_1`.`id` = `global0`.`id`))), Each(targetName=c1, sql=(SELECT * FROM db1_1.sharding_0 INNER JOIN db1_1.er_0 ON (`sharding_0`.`id` = `er_0`.`id`) INNER JOIN db1.global ON (`er_0`.`id` = `global`.`id`) UNION ALL SELECT * FROM db1_1.sharding_1 INNER JOIN db1_1.er_1 ON (`sharding_1`.`id` = `er_1`.`id`) INNER JOIN db1.global AS `global0` ON (`er_1`.`id` = `global0`.`id`)))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectShardingGlobalER() throws Exception {
Explain explain = parse("select * from db1.sharding s join db1.global g on s.id = g.id join db1.er e on e.id = s.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=companyname}, {columnType=BIGINT, nullable=true, columnName=addressid}, {columnType=BIGINT, nullable=true, columnName=id1}, {columnType=VARCHAR, nullable=true, columnName=user_id0}, {columnType=DATE, nullable=true, columnName=traveldate0}, {columnType=DECIMAL, nullable=true, columnName=fee0}, {columnType=BIGINT, nullable=true, columnName=days0}, {columnType=VARBINARY, nullable=true, columnName=blob0}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[shardingTables=db1.sharding,db1.er,globalTables=db1.global]) ", explain.dumpPlan());
System.out.println(explain.specificSql());
// Assert.assertEquals(
// "[SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding,globalTables=db1.global]) , parameterizedSql=SELECT * FROM db1.sharding INNER JOIN db1.global ON (`sharding`.`id` = `global`.`id`), sqls=[Each(targetName=c0, sql=(SELECT * FROM db1_0.sharding_0 INNER JOIN db1.global ON (`sharding_0`.`id` = `global`.`id`) UNION ALL SELECT * FROM db1_0.sharding_1 INNER JOIN db1.global AS `global0` ON (`sharding_1`.`id` = `global0`.`id`))), Each(targetName=c1, sql=(SELECT * FROM db1_1.sharding_0 INNER JOIN db1.global ON (`sharding_0`.`id` = `global`.`id`) UNION ALL SELECT * FROM db1_1.sharding_1 INNER JOIN db1.global AS `global0` ON (`sharding_1`.`id` = `global0`.`id`)))]), SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.er]) , parameterizedSql=SELECT * FROM db1.er, sqls=[Each(targetName=c0, sql=(SELECT * FROM db1_0.er_0 UNION ALL SELECT * FROM db1_0.er_1)), Each(targetName=c1, sql=(SELECT * FROM db1_1.er_0 UNION ALL SELECT * FROM db1_1.er_1))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectShardingGlobalER2() throws Exception {
Explain explain = parse("select * from db1.sharding s join db1.global g on s.id = g.id join db1.er e on e.id = g.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=companyname}, {columnType=BIGINT, nullable=true, columnName=addressid}, {columnType=BIGINT, nullable=true, columnName=id1}, {columnType=VARCHAR, nullable=true, columnName=user_id0}, {columnType=DATE, nullable=true, columnName=traveldate0}, {columnType=DECIMAL, nullable=true, columnName=fee0}, {columnType=BIGINT, nullable=true, columnName=days0}, {columnType=VARBINARY, nullable=true, columnName=blob0}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[shardingTables=db1.sharding,db1.er,globalTables=db1.global]) ", explain.dumpPlan());
System.out.println(explain.specificSql());
}
@Test
public void testSelectShardingGlobalBadColumn() throws Exception {
Explain explain = parse("select t2.id from db1.sharding t2 join db1.normal t1 on t2.id = t1.id join db1.er l2 on t2.id = l2.id;");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}]",
explain.getColumnInfo());
System.out.println(explain.dumpPlan());
System.out.println(explain.specificSql());
}
@Test
public void testSelectGlobalShardingBadColumn() throws Exception {
Explain explain = parse("select * from db1.global g join db1.sharding s on s.id = g.id join db1.er e on e.id = g.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=companyname}, {columnType=BIGINT, nullable=true, columnName=addressid}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}, {columnType=BIGINT, nullable=true, columnName=id1}, {columnType=VARCHAR, nullable=true, columnName=user_id0}, {columnType=DATE, nullable=true, columnName=traveldate0}, {columnType=DECIMAL, nullable=true, columnName=fee0}, {columnType=BIGINT, nullable=true, columnName=days0}, {columnType=VARBINARY, nullable=true, columnName=blob0}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[shardingTables=db1.sharding,db1.er,globalTables=db1.global]) ", explain.dumpPlan());
System.out.println(explain.specificSql());
// Assert.assertEquals(
// "[SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding,globalTables=db1.global]) , parameterizedSql=SELECT * FROM db1.global INNER JOIN db1.sharding ON (`global`.`id` = `sharding`.`id`), sqls=[Each(targetName=c0, sql=(SELECT * FROM db1.global INNER JOIN db1_0.sharding_0 ON (`global`.`id` = `sharding_0`.`id`) UNION ALL SELECT * FROM db1.global AS `global0` INNER JOIN db1_0.sharding_1 ON (`global0`.`id` = `sharding_1`.`id`))), Each(targetName=c1, sql=(SELECT * FROM db1.global INNER JOIN db1_1.sharding_0 ON (`global`.`id` = `sharding_0`.`id`) UNION ALL SELECT * FROM db1.global AS `global0` INNER JOIN db1_1.sharding_1 ON (`global0`.`id` = `sharding_1`.`id`)))]), SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.er]) , parameterizedSql=SELECT * FROM db1.er, sqls=[Each(targetName=c0, sql=(SELECT * FROM db1_0.er_0 UNION ALL SELECT * FROM db1_0.er_1)), Each(targetName=c1, sql=(SELECT * FROM db1_1.er_0 UNION ALL SELECT * FROM db1_1.er_1))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectGlobal() throws Exception {
Set<String> explainColumnSet = new HashSet<>();
Set<String> explainSet = new HashSet<>();
Set<List<SpecificSql>> sqlSet = new HashSet<>();
long end = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(5);
Explain explain;
while (true) {
explain = parse("select * from db1.global");
explainColumnSet.add(explain.getColumnInfo());
explainSet.add(explain.dumpPlan());
sqlSet.add(explain.specificSql());
if (sqlSet.size() > 1 || (System.currentTimeMillis() > end)) {
break;
}
}
Assert.assertTrue(
explainColumnSet.contains(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=companyname}, {columnType=BIGINT, nullable=true, columnName=addressid}]")
);
Assert.assertEquals("MycatView(distribution=[globalTables=db1.global]) ",explain.dumpPlan());
// Assert.assertEquals("[[SpecificSql(relNode=MycatView(distribution=[globalTables=db1.global]) , parameterizedSql=SELECT * FROM db1.global, sqls=[Each(targetName=c0, sql=SELECT * FROM db1.global)])], [SpecificSql(relNode=MycatView(distribution=[globalTables=db1.global]) , parameterizedSql=SELECT * FROM db1.global, sqls=[Each(targetName=c1, sql=SELECT * FROM db1.global)])]]",
// sqlSet.toString());
}
@Test
public void testSelectGlobalNormal() throws Exception {
Explain explain = parse("select * from db1.global s join db1.normal e on s.id = e.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=companyname}, {columnType=BIGINT, nullable=true, columnName=addressid}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=addressname}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[normalTables=db1.normal,globalTables=db1.global]) ", explain.dumpPlan());
// Assert.assertEquals(
// "[SpecificSql(relNode=MycatView(distribution=[normalTables=db1.normal,globalTables=db1.global]) , parameterizedSql=SELECT * FROM db1.global INNER JOIN db1.normal ON (`global`.`id` = `normal`.`id`), sqls=[Each(targetName=prototype, sql=SELECT * FROM db1.global INNER JOIN db1.normal ON (`global`.`id` = `normal`.`id`))])]",
// explain.specificSql().toString());
}
@Test
public void testSelectGlobalSharding() throws Exception {
Explain explain = parse("select * from db1.global s join db1.sharding e on s.id = e.id");
Assert.assertEquals(
"[{columnType=BIGINT, nullable=true, columnName=id}, {columnType=VARCHAR, nullable=true, columnName=companyname}, {columnType=BIGINT, nullable=true, columnName=addressid}, {columnType=BIGINT, nullable=true, columnName=id0}, {columnType=VARCHAR, nullable=true, columnName=user_id}, {columnType=DATE, nullable=true, columnName=traveldate}, {columnType=DECIMAL, nullable=true, columnName=fee}, {columnType=BIGINT, nullable=true, columnName=days}, {columnType=VARBINARY, nullable=true, columnName=blob}]",
explain.getColumnInfo());
Assert.assertEquals("MycatView(distribution=[shardingTables=db1.sharding,globalTables=db1.global]) ", explain.dumpPlan());
// Assert.assertEquals(
// "[SpecificSql(relNode=MycatView(distribution=[shardingTables=db1.sharding,globalTables=db1.global]) , parameterizedSql=SELECT * FROM db1.global INNER JOIN db1.sharding ON (`global`.`id` = `sharding`.`id`), sqls=[Each(targetName=c0, sql=(SELECT * FROM db1.global INNER JOIN db1_0.sharding_0 ON (`global`.`id` = `sharding_0`.`id`) UNION ALL SELECT * FROM db1.global AS `global0` INNER JOIN db1_0.sharding_1 ON (`global0`.`id` = `sharding_1`.`id`))), Each(targetName=c1, sql=(SELECT * FROM db1.global INNER JOIN db1_1.sharding_0 ON (`global`.`id` = `sharding_0`.`id`) UNION ALL SELECT * FROM db1.global AS `global0` INNER JOIN db1_1.sharding_1 ON (`global0`.`id` = `sharding_1`.`id`)))])]",
// explain.specificSql().toString());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment