This is an automated email from the ASF dual-hosted git repository.
panxiaolei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new f4ed52906a [Feature](Materialized-View) change mv rewrite from bottom
up to up bottom && Compatible with old … (#16750)
f4ed52906a is described below
commit f4ed52906ac5783858f22a5e10e318b4bea986f2
Author: Pxl <[email protected]>
AuthorDate: Wed Feb 15 17:24:46 2023 +0800
[Feature](Materialized-View) change mv rewrite from bottom up to up bottom
&& Compatible with old … (#16750)
1.change mv rewrite from bottom up to up bottom
2.compatible with old version mv
3.restore some ut codes (but disable)
4. fix some ut introduced by [fix](planner)fix bug for missing slot #16601
and [Feature](Materialized-View) support multiple slot on one column in
materialized view #16378
---
.../doris/analysis/CreateMaterializedViewStmt.java | 17 ++
.../java/org/apache/doris/analysis/QueryStmt.java | 1 +
.../main/java/org/apache/doris/catalog/Column.java | 12 ++
.../doris/catalog/MaterializedIndexMeta.java | 52 +++++-
.../java/org/apache/doris/catalog/OlapTable.java | 6 +-
.../main/java/org/apache/doris/catalog/Table.java | 2 +-
.../apache/doris/planner/SingleNodePlanner.java | 4 +-
.../org/apache/doris/rewrite/ExprRewriter.java | 72 +++++++--
.../doris/rewrite/mvrewrite/ExprToSlotRefRule.java | 2 +-
.../planner/MaterializedViewFunctionTest.java | 3 +-
.../planner/MaterializedViewSelectorTest.java | 177 +++++++++++++++++++++
11 files changed, 322 insertions(+), 26 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateMaterializedViewStmt.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateMaterializedViewStmt.java
index 5fe8244019..76c86c62b3 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateMaterializedViewStmt.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/analysis/CreateMaterializedViewStmt.java
@@ -496,6 +496,23 @@ public class CreateMaterializedViewStmt extends DdlStmt {
return name;
}
+ public static String oldmvColumnBreaker(String name) {
+ if (name.startsWith(MATERIALIZED_VIEW_NAME_PREFIX)) {
+ // mv_count_k2 -> k2
+ name = name.substring(MATERIALIZED_VIEW_NAME_PREFIX.length());
+ for (String prefix : FN_NAME_TO_PATTERN.keySet()) {
+ if (name.startsWith(prefix)) {
+ return name.substring(prefix.length() + 1);
+ }
+ }
+ }
+ if (name.startsWith(MATERIALIZED_VIEW_NAME_PREFIX)) {
+ // mv_k2 -> k2
+ return
mvColumnBreaker(name.substring(MATERIALIZED_VIEW_NAME_PREFIX.length()));
+ }
+ return name;
+ }
+
public static boolean isMVColumn(String name) {
return isMVColumnAggregate(name) || isMVColumnNormal(name);
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/QueryStmt.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/QueryStmt.java
index 2181d30fd3..3564cb2927 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/QueryStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/QueryStmt.java
@@ -281,6 +281,7 @@ public abstract class QueryStmt extends StatementBase
implements Queriable {
ExprRewriter rewriter = analyzer.getMVExprRewriter();
rewriter.reset();
rewriter.setDisableTuplesMVRewriter(disableTuplesMVRewriter);
+ rewriter.setUpBottom();
Expr result = rewriter.rewrite(expr, analyzer);
if (result != expr) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
index 3c0da6dab2..2a1f5de023 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
@@ -111,6 +111,7 @@ public class Column implements Writable,
GsonPostProcessable {
// so the define expr in RollupJob must be analyzed.
// In other cases, such as define expr in `MaterializedIndexMeta`, it may
not be analyzed after being replayed.
private Expr defineExpr; // use to define column in materialize view
+ private String defineName = null;
@SerializedName(value = "visible")
private boolean visible;
@SerializedName(value = "defaultValueExprDef")
@@ -236,6 +237,17 @@ public class Column implements Writable,
GsonPostProcessable {
this.children.add(column);
}
+ public void setDefineName(String defineName) {
+ this.defineName = defineName;
+ }
+
+ public String getDefineName() {
+ if (defineName != null) {
+ return defineName;
+ }
+ return name;
+ }
+
public void setName(String newName) {
this.name = newName;
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/catalog/MaterializedIndexMeta.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/MaterializedIndexMeta.java
index a45ebdbfca..455a86b88e 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/catalog/MaterializedIndexMeta.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/catalog/MaterializedIndexMeta.java
@@ -19,6 +19,7 @@ package org.apache.doris.catalog;
import org.apache.doris.analysis.CreateMaterializedViewStmt;
import org.apache.doris.analysis.Expr;
+import org.apache.doris.analysis.SlotRef;
import org.apache.doris.analysis.SqlParser;
import org.apache.doris.analysis.SqlScanner;
import org.apache.doris.common.io.Text;
@@ -40,6 +41,7 @@ import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.StringReader;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -136,14 +138,62 @@ public class MaterializedIndexMeta implements Writable,
GsonPostProcessable {
return schemaVersion;
}
- private void setColumnsDefineExpr(Map<String, Expr>
columnNameToDefineExpr) {
+ private void setColumnsDefineExpr(Map<String, Expr>
columnNameToDefineExpr) throws IOException {
for (Map.Entry<String, Expr> entry :
columnNameToDefineExpr.entrySet()) {
+ boolean match = false;
for (Column column : schema) {
if (column.getName().equals(entry.getKey())) {
column.setDefineExpr(entry.getValue());
+ match = true;
break;
}
}
+
+ if (!match) {
+ // Compatibility code for older versions of mv
+ // store_id -> mv_store_id
+ // sale_amt -> mva_SUM__`sale_amt`
+ // mv_count_sale_amt -> mva_SUM__CASE WHEN `sale_amt` IS NULL
THEN 0 ELSE 1 END
+ List<SlotRef> slots = new ArrayList<>();
+ entry.getValue().collect(SlotRef.class, slots);
+ if (slots.size() > 1) {
+ throw new IOException("DefineExpr have multiple slot in
MaterializedIndex, Expr=" + entry.getKey());
+ }
+
+ String name =
MaterializedIndexMeta.normalizeName(slots.get(0).toSqlWithoutTbl());
+ Column matchedColumn = null;
+
+ String columnList = "[";
+ for (Column column : schema) {
+ if (columnList.length() != 1) {
+ columnList += ", ";
+ }
+ columnList += column.getName();
+ }
+ columnList += "]";
+
+ for (Column column : schema) {
+ if
(CreateMaterializedViewStmt.oldmvColumnBreaker(column.getName()).equals(name)) {
+ if (matchedColumn == null) {
+ matchedColumn = column;
+ } else {
+ LOG.warn("DefineExpr match multiple column in
MaterializedIndex, ExprName=" + entry.getKey()
+ + ", Expr=" +
entry.getValue().toSqlWithoutTbl() + ", Slot=" + name
+ + ", Columns=" + columnList);
+ }
+ }
+ }
+ if (matchedColumn != null) {
+ LOG.debug("trans old MV, MV: {}, DefineExpr:{},
DefineName:{}",
+ matchedColumn.getName(),
entry.getValue().toSqlWithoutTbl(), entry.getKey());
+ matchedColumn.setDefineExpr(entry.getValue());
+ matchedColumn.setDefineName(entry.getKey());
+ } else {
+ LOG.warn("DefineExpr does not match any column in
MaterializedIndex, ExprName=" + entry.getKey()
+ + ", Expr=" + entry.getValue().toSqlWithoutTbl() +
", Slot=" + name
+ + ", Columns=" + columnList);
+ }
+ }
}
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
index b6bfa3edb8..e570274625 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/OlapTable.java
@@ -333,9 +333,9 @@ public class OlapTable extends Table {
}
for (MaterializedIndexMeta indexMeta : indexIdToMeta.values()) {
for (Column column : indexMeta.getSchema()) {
- if (!nameToColumn.containsKey(column.getName())) {
+ if (!nameToColumn.containsKey(column.getDefineName())) {
fullSchema.add(column);
- nameToColumn.put(column.getName(), column);
+ nameToColumn.put(column.getDefineName(), column);
}
}
}
@@ -403,7 +403,7 @@ public class OlapTable extends Table {
public Column getVisibleColumn(String columnName) {
for (MaterializedIndexMeta meta : getVisibleIndexIdToMeta().values()) {
for (Column column : meta.getSchema()) {
- if (MaterializedIndexMeta.matchColumnName(column.getName(),
columnName)) {
+ if
(MaterializedIndexMeta.matchColumnName(column.getDefineName(), columnName)) {
return column;
}
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Table.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Table.java
index 9ba5253883..3f8597f1e0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Table.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Table.java
@@ -124,7 +124,7 @@ public abstract class Table extends MetaObject implements
Writable, TableIf {
this.nameToColumn = Maps.newTreeMap(String.CASE_INSENSITIVE_ORDER);
if (this.fullSchema != null) {
for (Column col : this.fullSchema) {
- nameToColumn.put(col.getName(), col);
+ nameToColumn.put(col.getDefineName(), col);
}
} else {
// Only view in with-clause have null base
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
b/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
index 318ebb270c..619ee2efe5 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/SingleNodePlanner.java
@@ -1193,10 +1193,10 @@ public class SingleNodePlanner {
// create left-deep sequence of binary hash joins; assign node ids
as we go along
TableRef tblRef = selectStmt.getTableRefs().get(0);
materializeTableResultForCrossJoinOrCountStar(tblRef, analyzer);
- if (selectStmt.getSelectList().getItems().size() == 1) {
+ if (selectStmt.getResultExprs().size() == 1) {
final List<SlotId> slotIds = Lists.newArrayList();
final List<TupleId> tupleIds = Lists.newArrayList();
- Expr resultExprSelected =
selectStmt.getSelectList().getItems().get(0).getExpr();
+ Expr resultExprSelected = selectStmt.getResultExprs().get(0);
if (resultExprSelected != null && resultExprSelected
instanceof SlotRef) {
resultExprSelected.getIds(tupleIds, slotIds);
for (SlotId id : slotIds) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/rewrite/ExprRewriter.java
b/fe/fe-core/src/main/java/org/apache/doris/rewrite/ExprRewriter.java
index 7ffb42c0e7..43e9994a1e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/rewrite/ExprRewriter.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/rewrite/ExprRewriter.java
@@ -34,10 +34,12 @@ import java.util.Map;
import java.util.Set;
/**
- * Helper class that drives the transformation of Exprs according to a given
list of
+ * Helper class that drives the transformation of Exprs according to a given
+ * list of
* ExprRewriteRules. The rules are applied as follows:
- * - a single rule is applied repeatedly to the Expr and all its children in a
bottom-up
- * fashion until there are no more changes
+ * - a single rule is applied repeatedly to the Expr and all its children in a
+ * bottom-up
+ * fashion until there are no more changes
* - the rule list is applied repeatedly until no rule has made any changes
* - the rules are applied in the order they appear in the rule list
* Keeps track of how many transformations were applied.
@@ -51,11 +53,13 @@ import java.util.Set;
* Doris match different Rewriter framework execution.
*/
public class ExprRewriter {
+ private boolean useUpBottom = false;
private int numChanges = 0;
private final List<ExprRewriteRule> rules;
// The type of clause that executes the rule.
- // This type is only used in InferFiltersRule, RewriteDateLiteralRule,
other rules are not used
+ // This type is only used in InferFiltersRule, RewriteDateLiteralRule,
other
+ // rules are not used
public enum ClauseType {
INNER_JOIN_CLAUSE,
LEFT_OUTER_JOIN_CLAUSE,
@@ -71,18 +75,27 @@ public class ExprRewriter {
public static ClauseType fromJoinType(JoinOperator joinOp) {
switch (joinOp) {
- case INNER_JOIN: return INNER_JOIN_CLAUSE;
- case LEFT_OUTER_JOIN: return LEFT_OUTER_JOIN_CLAUSE;
- case RIGHT_OUTER_JOIN: return RIGHT_OUTER_JOIN_CLAUSE;
- case FULL_OUTER_JOIN: return FULL_OUTER_JOIN_CLAUSE;
- case LEFT_SEMI_JOIN: return LEFT_SEMI_JOIN_CLAUSE;
- case RIGHT_SEMI_JOIN: return RIGHT_SEMI_JOIN_CLAUSE;
+ case INNER_JOIN:
+ return INNER_JOIN_CLAUSE;
+ case LEFT_OUTER_JOIN:
+ return LEFT_OUTER_JOIN_CLAUSE;
+ case RIGHT_OUTER_JOIN:
+ return RIGHT_OUTER_JOIN_CLAUSE;
+ case FULL_OUTER_JOIN:
+ return FULL_OUTER_JOIN_CLAUSE;
+ case LEFT_SEMI_JOIN:
+ return LEFT_SEMI_JOIN_CLAUSE;
+ case RIGHT_SEMI_JOIN:
+ return RIGHT_SEMI_JOIN_CLAUSE;
case NULL_AWARE_LEFT_ANTI_JOIN:
case LEFT_ANTI_JOIN:
return LEFT_ANTI_JOIN_CLAUSE;
- case RIGHT_ANTI_JOIN: return RIGHT_ANTI_JOIN_CLAUSE;
- case CROSS_JOIN: return CROSS_JOIN_CLAUSE;
- default: return OTHER_CLAUSE;
+ case RIGHT_ANTI_JOIN:
+ return RIGHT_ANTI_JOIN_CLAUSE;
+ case CROSS_JOIN:
+ return CROSS_JOIN_CLAUSE;
+ default:
+ return OTHER_CLAUSE;
}
}
@@ -126,6 +139,10 @@ public class ExprRewriter {
}
}
+ public void setUpBottom() {
+ useUpBottom = true;
+ }
+
public Expr rewrite(Expr expr, Analyzer analyzer) throws AnalysisException
{
ClauseType clauseType = ClauseType.OTHER_CLAUSE;
return rewrite(expr, analyzer, clauseType);
@@ -138,7 +155,8 @@ public class ExprRewriter {
do {
oldNumChanges = numChanges;
for (ExprRewriteRule rule : rules) {
- // when foldConstantByBe is on, fold all constant expr by BE
instead of applying FoldConstantsRule in FE
+ // when foldConstantByBe is on, fold all constant expr by BE
instead of applying
+ // FoldConstantsRule in FE
if (rule instanceof FoldConstantsRule &&
analyzer.safeIsEnableFoldConstantByBe()) {
continue;
}
@@ -181,7 +199,8 @@ public class ExprRewriter {
}
/**
- * Applies 'rule' on the Expr tree rooted at 'expr' until there are no
more changes.
+ * Applies 'rule' on the Expr tree rooted at 'expr' until there are no more
+ * changes.
* Returns the transformed Expr or 'expr' if there were no changes.
*/
private Expr applyRuleRepeatedly(Expr expr, ExprRewriteRule rule, Analyzer
analyzer, ClauseType clauseType)
@@ -190,11 +209,20 @@ public class ExprRewriter {
Expr rewrittenExpr = expr;
do {
oldNumChanges = numChanges;
- rewrittenExpr = applyRuleBottomUp(rewrittenExpr, rule, analyzer,
clauseType);
+ rewrittenExpr = applyRule(rewrittenExpr, rule, analyzer,
clauseType);
} while (oldNumChanges != numChanges);
return rewrittenExpr;
}
+ private Expr applyRule(Expr expr, ExprRewriteRule rule, Analyzer analyzer,
ClauseType clauseType)
+ throws AnalysisException {
+ if (useUpBottom) {
+ return applyRuleUpBottom(expr, rule, analyzer, clauseType);
+ } else {
+ return applyRuleBottomUp(expr, rule, analyzer, clauseType);
+ }
+ }
+
/**
* Applies 'rule' on 'expr' and all its children in a bottom-up fashion.
* Returns the transformed Expr or 'expr' if there were no changes.
@@ -211,6 +239,18 @@ public class ExprRewriter {
return rewrittenExpr;
}
+ private Expr applyRuleUpBottom(Expr expr, ExprRewriteRule rule, Analyzer
analyzer, ClauseType clauseType)
+ throws AnalysisException {
+ Expr rewrittenExpr = rule.apply(expr, analyzer, clauseType);
+ if (rewrittenExpr != expr) {
+ ++numChanges;
+ }
+ for (int i = 0; i < expr.getChildren().size(); ++i) {
+ expr.setChild(i, applyRuleUpBottom(expr.getChild(i), rule,
analyzer, clauseType));
+ }
+ return rewrittenExpr;
+ }
+
public void rewriteList(List<Expr> exprs, Analyzer analyzer) throws
AnalysisException {
for (int i = 0; i < exprs.size(); ++i) {
exprs.set(i, rewrite(exprs.get(i), analyzer));
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/ExprToSlotRefRule.java
b/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/ExprToSlotRefRule.java
index 3d58c68fd5..ea03d0af62 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/ExprToSlotRefRule.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/rewrite/mvrewrite/ExprToSlotRefRule.java
@@ -267,7 +267,7 @@ public class ExprToSlotRefRule implements ExprRewriteRule {
private Expr rewriteExpr(TableName tableName, Column mvColumn, Analyzer
analyzer) {
Preconditions.checkNotNull(mvColumn);
Preconditions.checkNotNull(tableName);
- SlotRef mvSlotRef = new SlotRef(tableName, mvColumn.getName());
+ SlotRef mvSlotRef = new SlotRef(tableName, mvColumn.getDefineName());
mvSlotRef.analyzeNoThrow(analyzer);
return mvSlotRef;
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/planner/MaterializedViewFunctionTest.java
b/fe/fe-core/src/test/java/org/apache/doris/planner/MaterializedViewFunctionTest.java
index 60a813b2cf..501e203ae3 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/planner/MaterializedViewFunctionTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/planner/MaterializedViewFunctionTest.java
@@ -550,8 +550,7 @@ public class MaterializedViewFunctionTest {
dorisAssert.withMaterializedView(createEmpsMVsql).query(query).explainContains(QUERY_USE_EMPS_MV,
2);
}
- // Can not support match multiple mv now
- //@Test
+ @Test
public void testMultiMVMultiUsage() throws Exception {
String createEmpsMVSql01 = "create materialized view emp_mv_01 as
select deptno, empid, salary "
+ "from " + EMPS_TABLE_NAME + " order by deptno;";
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/planner/MaterializedViewSelectorTest.java
b/fe/fe-core/src/test/java/org/apache/doris/planner/MaterializedViewSelectorTest.java
index 2e8e2ebc2e..7767fc71ab 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/planner/MaterializedViewSelectorTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/planner/MaterializedViewSelectorTest.java
@@ -156,6 +156,137 @@ public class MaterializedViewSelectorTest {
Assert.assertTrue("MAX".equalsIgnoreCase(aggregatedColumn2.getFnName().getFunction()));
}
+ @Disabled
+ public void testCheckCompensatingPredicates(@Injectable SelectStmt
selectStmt, @Injectable Analyzer analyzer,
+ @Injectable MaterializedIndexMeta indexMeta1,
+ @Injectable MaterializedIndexMeta indexMeta2,
+ @Injectable MaterializedIndexMeta indexMeta3,
+ @Injectable MaterializedIndexMeta indexMeta4, @Injectable SlotRef
slotRef1, @Injectable SlotRef slotRef2) {
+ Set<String> tableAColumnNames = Sets.newHashSet();
+ tableAColumnNames.add("C1");
+ Map<Long, MaterializedIndexMeta> candidateIndexIdToSchema =
Maps.newHashMap();
+ List<Column> index1Columns = Lists.newArrayList();
+ Column index1Column1 = new Column("c1", Type.INT, true, null, true,
"", "");
+ index1Columns.add(index1Column1);
+ index1Column1.setDefineExpr(slotRef1);
+ candidateIndexIdToSchema.put(new Long(1), indexMeta1);
+ List<Column> index2Columns = Lists.newArrayList();
+ Column index2Column1 = new Column("c1", Type.INT, false,
AggregateType.NONE, true, "", "");
+ index2Columns.add(index2Column1);
+ index2Column1.setDefineExpr(slotRef1);
+ candidateIndexIdToSchema.put(new Long(2), indexMeta2);
+ List<Column> index3Columns = Lists.newArrayList();
+ Column index3Column1 = new Column("c1", Type.INT, false,
AggregateType.SUM, true, "", "");
+ index3Column1.setDefineExpr(slotRef1);
+ index3Columns.add(index3Column1);
+ candidateIndexIdToSchema.put(new Long(3), indexMeta3);
+ List<Column> index4Columns = Lists.newArrayList();
+ Column index4Column2 = new Column("c2", Type.INT, true, null, true,
"", "");
+ index4Column2.setDefineExpr(slotRef2);
+ index4Columns.add(index4Column2);
+ candidateIndexIdToSchema.put(new Long(4), indexMeta4);
+
+ List<Expr> whereList = Lists.newArrayList();
+ whereList.add(slotRef1);
+ new Expectations() {
+ {
+ selectStmt.getAggInfo();
+ result = null;
+ selectStmt.getWhereClause();
+ result = whereList;
+ indexMeta1.getSchema();
+ result = index1Columns;
+ indexMeta2.getSchema();
+ result = index2Columns;
+ indexMeta3.getSchema();
+ result = index3Columns;
+ indexMeta4.getSchema();
+ result = index4Columns;
+ slotRef1.toSqlWithoutTbl();
+ result = "c1";
+ }
+ };
+
+ MaterializedViewSelector selector = new
MaterializedViewSelector(selectStmt, analyzer);
+ try {
+ Deencapsulation.invoke(selector, "checkCompensatingPredicates",
tableAColumnNames,
+ candidateIndexIdToSchema);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Assert.fail(e.getMessage());
+ }
+
+ Assert.assertEquals(2, candidateIndexIdToSchema.size());
+ Assert.assertTrue(candidateIndexIdToSchema.keySet().contains(new
Long(1)));
+ Assert.assertTrue(candidateIndexIdToSchema.keySet().contains(new
Long(2)));
+ }
+
+ @Disabled
+ public void testCheckGrouping(@Injectable SelectStmt selectStmt,
@Injectable Analyzer analyzer,
+ @Injectable OlapTable table,
+ @Injectable MaterializedIndexMeta indexMeta1,
+ @Injectable MaterializedIndexMeta indexMeta2,
+ @Injectable MaterializedIndexMeta indexMeta3, @Injectable SlotRef
slotRef1, @Injectable SlotRef slotRef2) {
+ Set<String> tableAColumnNames = Sets.newHashSet();
+ tableAColumnNames.add("C1");
+ Map<Long, MaterializedIndexMeta> candidateIndexIdToSchema =
Maps.newHashMap();
+ List<Column> index1Columns = Lists.newArrayList();
+ Column index1Column1 = new Column("c2", Type.INT, true, null, true,
"", "");
+ index1Column1.setDefineExpr(slotRef2);
+ index1Columns.add(index1Column1);
+ candidateIndexIdToSchema.put(new Long(1), indexMeta1);
+ List<Column> index2Columns = Lists.newArrayList();
+ Column index2Column1 = new Column("c1", Type.INT, true, null, true,
"", "");
+ index2Column1.setDefineExpr(slotRef1);
+ index2Columns.add(index2Column1);
+ Column index2Column2 = new Column("c2", Type.INT, false,
AggregateType.SUM, true, "", "");
+ index2Column2.setDefineExpr(slotRef2);
+ index2Columns.add(index2Column2);
+ candidateIndexIdToSchema.put(new Long(2), indexMeta2);
+ List<Column> index3Columns = Lists.newArrayList();
+ Column index3Column1 = new Column("c2", Type.INT, true, null, true,
"", "");
+ index3Column1.setDefineExpr(slotRef2);
+ index3Columns.add(index3Column1);
+ Column index3Column2 = new Column("c1", Type.INT, false,
AggregateType.SUM, true, "", "");
+ index3Column1.setDefineExpr(slotRef1);
+ index3Columns.add(index3Column2);
+ candidateIndexIdToSchema.put(new Long(3), indexMeta3);
+ List<Expr> groupingList = Lists.newArrayList();
+ groupingList.add(slotRef1);
+ List<Expr> aggList = Lists.newArrayList();
+ new Expectations() {
+ {
+ selectStmt.getAggInfo().getGroupingExprs();
+ result = groupingList;
+ selectStmt.getAggInfo().getAggregateExprs();
+ result = aggList;
+ indexMeta1.getSchema();
+ result = index1Columns;
+ indexMeta1.getKeysType();
+ result = KeysType.DUP_KEYS;
+ indexMeta2.getSchema();
+ result = index2Columns;
+ indexMeta3.getSchema();
+ result = index3Columns;
+ slotRef1.toSqlWithoutTbl();
+ result = "c1";
+ }
+ };
+
+ try {
+ MaterializedViewSelector selector = new
MaterializedViewSelector(selectStmt, analyzer);
+ Deencapsulation.setField(selector, "isSPJQuery", false);
+ Deencapsulation.invoke(selector, "checkGrouping", table,
tableAColumnNames, candidateIndexIdToSchema);
+ } catch (Exception e) {
+ e.printStackTrace();
+ Assert.fail(e.getMessage());
+ }
+
+ Assert.assertEquals(2, candidateIndexIdToSchema.size());
+ Assert.assertTrue(candidateIndexIdToSchema.keySet().contains(new
Long(1)));
+ Assert.assertTrue(candidateIndexIdToSchema.keySet().contains(new
Long(2)));
+ }
+
@Disabled
public void testCheckAggregationFunction(@Injectable SelectStmt
selectStmt, @Injectable Analyzer analyzer,
@Injectable OlapTable table,
@@ -213,6 +344,52 @@ public class MaterializedViewSelectorTest {
Assert.assertTrue(candidateIndexIdToSchema.keySet().contains(new
Long(3)));
}
+ @Disabled
+ public void testCheckOutputColumns(@Injectable SelectStmt selectStmt,
@Injectable Analyzer analyzer,
+ @Injectable MaterializedIndexMeta indexMeta1,
+ @Injectable MaterializedIndexMeta indexMeta2,
+ @Injectable MaterializedIndexMeta indexMeta3) {
+ Map<Long, MaterializedIndexMeta> candidateIndexIdToSchema =
Maps.newHashMap();
+ List<Column> index1Columns = Lists.newArrayList();
+ Column index1Column1 = new Column("c2", Type.INT, true, null, true,
"", "");
+ index1Columns.add(index1Column1);
+ candidateIndexIdToSchema.put(new Long(1), indexMeta1);
+ List<Column> index2Columns = Lists.newArrayList();
+ Column index2Column1 = new Column("c1", Type.INT, true, null, true,
"", "");
+ index2Columns.add(index2Column1);
+ Column index2Column2 = new Column("c2", Type.INT, false,
AggregateType.NONE, true, "", "");
+ index2Columns.add(index2Column2);
+ candidateIndexIdToSchema.put(new Long(2), indexMeta2);
+ List<Column> index3Columns = Lists.newArrayList();
+ Column index3Column1 = new Column("C2", Type.INT, true, null, true,
"", "");
+ index3Columns.add(index3Column1);
+ Column index3Column2 = new Column("c1", Type.INT, false,
AggregateType.SUM, true, "", "");
+ index3Columns.add(index3Column2);
+ candidateIndexIdToSchema.put(new Long(3), indexMeta3);
+ new Expectations() {
+ {
+ selectStmt.getAggInfo();
+ result = null;
+ indexMeta1.getSchema();
+ result = index1Columns;
+ indexMeta2.getSchema();
+ result = index2Columns;
+ indexMeta3.getSchema();
+ result = index3Columns;
+ }
+ };
+
+ MaterializedViewSelector selector = new
MaterializedViewSelector(selectStmt, analyzer);
+ Set<String> columnNamesInQueryOutput = Sets.newHashSet();
+ columnNamesInQueryOutput.add("c1");
+ columnNamesInQueryOutput.add("c2");
+ Deencapsulation.invoke(selector, "checkOutputColumns",
columnNamesInQueryOutput,
+ candidateIndexIdToSchema);
+ Assert.assertEquals(2, candidateIndexIdToSchema.size());
+ Assert.assertTrue(candidateIndexIdToSchema.keySet().contains(new
Long(2)));
+ Assert.assertTrue(candidateIndexIdToSchema.keySet().contains(new
Long(3)));
+ }
+
@Test
public void testCompensateIndex(@Injectable SelectStmt selectStmt,
@Injectable Analyzer analyzer,
@Injectable OlapTable table) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]