From 911fabd7db28e8174a2b46eed6db4313ffe85b8a Mon Sep 17 00:00:00 2001 From: emmymiao87 <522274284@qq.com> Date: Mon, 24 Aug 2020 16:14:39 +0800 Subject: [PATCH] Keep the scale and precision of type when creating mv The DECIMAL, CHAR, VARCHAR have their own scale and precision in column. The mv column should keep those scale and precision. Fixed #4433 Change-Id: Ie288738a4356e60d11ea472dd274e54bc7ae6990 --- .../analysis/CreateMaterializedViewStmt.java | 8 +- .../CreateMaterializedViewStmtTest.java | 155 ++++++++++++++++-- 2 files changed, 151 insertions(+), 12 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 49fffa9fcf3769..c5607bd399d26f 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 @@ -18,6 +18,7 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.AggregateType; +import org.apache.doris.catalog.Column; import org.apache.doris.catalog.FunctionSet; import org.apache.doris.catalog.KeysType; import org.apache.doris.catalog.PrimitiveType; @@ -346,6 +347,9 @@ private MVColumnItem buildMVColumnItem(FunctionCallExpr functionCallExpr) throws Preconditions.checkArgument(slots.size() == 1); SlotRef baseColumnRef = slots.get(0); String baseColumnName = baseColumnRef.getColumnName().toLowerCase(); + Column baseColumn = baseColumnRef.getColumn(); + Preconditions.checkNotNull(baseColumn); + Type baseType = baseColumn.getOriginType(); Expr functionChild0 = functionCallExpr.getChild(0); String mvColumnName; AggregateType mvAggregateType; @@ -362,14 +366,14 @@ private MVColumnItem buildMVColumnItem(FunctionCallExpr functionCallExpr) throws } else if (baseColumnType == PrimitiveType.FLOAT) { type = Type.DOUBLE; } else { - type = Type.fromPrimitiveType(baseColumnRef.getType().getPrimitiveType()); + type = baseType; } break; case "min": case "max": mvColumnName = baseColumnName; mvAggregateType = AggregateType.valueOf(functionName.toUpperCase()); - type = Type.fromPrimitiveType(baseColumnRef.getType().getPrimitiveType()); + type = baseType; break; case FunctionSet.BITMAP_UNION: // Compatible aggregation models diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateMaterializedViewStmtTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateMaterializedViewStmtTest.java index fdfcec542fab81..7127aee7009592 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateMaterializedViewStmtTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/CreateMaterializedViewStmtTest.java @@ -18,8 +18,10 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.AggregateType; +import org.apache.doris.catalog.Column; import org.apache.doris.catalog.KeysType; import org.apache.doris.catalog.PrimitiveType; +import org.apache.doris.catalog.ScalarType; import org.apache.doris.catalog.Type; import org.apache.doris.common.Config; import org.apache.doris.common.UserException; @@ -252,12 +254,15 @@ public void testOrderOfColumn(@Injectable SlotRef slotRef1, @Test public void testOrderByAggregateColumn(@Injectable SlotRef slotRef1, @Injectable TableRef tableRef, - @Injectable SelectStmt selectStmt) throws UserException { + @Injectable SelectStmt selectStmt, + @Injectable Column column2, + @Injectable SlotDescriptor slotDescriptor) throws UserException { SelectList selectList = new SelectList(); SelectListItem selectListItem1 = new SelectListItem(slotRef1, null); selectList.addItem(selectListItem1); TableName tableName = new TableName("db", "table"); SlotRef slotRef2 = new SlotRef(tableName, "v1"); + Deencapsulation.setField(slotRef2, "desc", slotDescriptor); List fnChildren = Lists.newArrayList(slotRef2); FunctionCallExpr functionCallExpr = new FunctionCallExpr("sum", fnChildren); SelectListItem selectListItem2 = new SelectListItem(functionCallExpr, null); @@ -283,6 +288,10 @@ public void testOrderByAggregateColumn(@Injectable SlotRef slotRef1, result = orderByElementList; slotRef1.getColumnName(); result = "k1"; + slotDescriptor.getColumn(); + result = column2; + column2.getOriginType(); + result = Type.INT; } }; CreateMaterializedViewStmt createMaterializedViewStmt = new CreateMaterializedViewStmt("test", selectStmt, null); @@ -326,12 +335,15 @@ public void testDuplicateColumn(@Injectable SelectStmt selectStmt) throws UserEx @Test public void testDuplicateColumn1(@Injectable SlotRef slotRef1, - @Injectable SelectStmt selectStmt) throws UserException { + @Injectable SelectStmt selectStmt, + @Injectable Column column2, + @Injectable SlotDescriptor slotDescriptor) throws UserException { SelectList selectList = new SelectList(); SelectListItem selectListItem1 = new SelectListItem(slotRef1, null); selectList.addItem(selectListItem1); TableName tableName = new TableName("db", "table"); SlotRef slotRef2 = new SlotRef(tableName, "k2"); + Deencapsulation.setField(slotRef2, "desc", slotDescriptor); List fn1Children = Lists.newArrayList(slotRef2); FunctionCallExpr functionCallExpr1 = new FunctionCallExpr("sum", fn1Children); SelectListItem selectListItem2 = new SelectListItem(functionCallExpr1, null); @@ -349,6 +361,10 @@ public void testDuplicateColumn1(@Injectable SlotRef slotRef1, result = selectList; slotRef1.getColumnName(); result = "k1"; + slotDescriptor.getColumn(); + result = column2; + column2.getOriginType(); + result = Type.INT; } }; CreateMaterializedViewStmt createMaterializedViewStmt = new CreateMaterializedViewStmt("test", selectStmt, null); @@ -364,7 +380,9 @@ public void testDuplicateColumn1(@Injectable SlotRef slotRef1, public void testOrderByColumnsLessThenGroupByColumns(@Injectable SlotRef slotRef1, @Injectable SlotRef slotRef2, @Injectable TableRef tableRef, - @Injectable SelectStmt selectStmt) throws UserException { + @Injectable SelectStmt selectStmt, + @Injectable Column column3, + @Injectable SlotDescriptor slotDescriptor) throws UserException { SelectList selectList = new SelectList(); SelectListItem selectListItem1 = new SelectListItem(slotRef1, null); selectList.addItem(selectListItem1); @@ -372,6 +390,7 @@ public void testOrderByColumnsLessThenGroupByColumns(@Injectable SlotRef slotRef selectList.addItem(selectListItem2); TableName tableName = new TableName("db", "table"); SlotRef functionChild0 = new SlotRef(tableName, "v1"); + Deencapsulation.setField(functionChild0, "desc", slotDescriptor); List fn1Children = Lists.newArrayList(functionChild0); FunctionCallExpr functionCallExpr = new FunctionCallExpr("sum", fn1Children); SelectListItem selectListItem3 = new SelectListItem(functionCallExpr, null); @@ -398,6 +417,10 @@ public void testOrderByColumnsLessThenGroupByColumns(@Injectable SlotRef slotRef result = "k1"; slotRef2.getColumnName(); result = "non-k2"; + slotDescriptor.getColumn(); + result = column3; + column3.getOriginType(); + result = Type.INT; } }; CreateMaterializedViewStmt createMaterializedViewStmt = new CreateMaterializedViewStmt("test", selectStmt, null); @@ -416,7 +439,9 @@ public void testMVColumnsWithoutOrderby(@Injectable SlotRef slotRef1, @Injectable SlotRef slotRef4, @Injectable TableRef tableRef, @Injectable SelectStmt selectStmt, - @Injectable AggregateInfo aggregateInfo) throws UserException { + @Injectable AggregateInfo aggregateInfo, + @Injectable Column column5, + @Injectable SlotDescriptor slotDescriptor) throws UserException { SelectList selectList = new SelectList(); SelectListItem selectListItem1 = new SelectListItem(slotRef1, null); selectList.addItem(selectListItem1); @@ -429,6 +454,7 @@ public void testMVColumnsWithoutOrderby(@Injectable SlotRef slotRef1, TableName tableName = new TableName("db", "table"); final String columnName5 = "sum_v2"; SlotRef functionChild0 = new SlotRef(tableName, columnName5); + Deencapsulation.setField(functionChild0, "desc", slotDescriptor); List fn1Children = Lists.newArrayList(functionChild0); FunctionCallExpr functionCallExpr = new FunctionCallExpr("sum", fn1Children); SelectListItem selectListItem5 = new SelectListItem(functionCallExpr, null); @@ -465,6 +491,10 @@ public void testMVColumnsWithoutOrderby(@Injectable SlotRef slotRef1, result = columnName3; slotRef4.getColumnName(); result = columnName4; + functionChild0.getColumn(); + result = column5; + column5.getOriginType(); + result = Type.INT; } }; @@ -907,7 +937,9 @@ public void testMVColumns(@Injectable SlotRef slotRef1, @Injectable SlotRef slotRef2, @Injectable TableRef tableRef, @Injectable SelectStmt selectStmt, - @Injectable AggregateInfo aggregateInfo) throws UserException { + @Injectable AggregateInfo aggregateInfo, + @Injectable Column column1, + @Injectable SlotDescriptor slotDescriptor) throws UserException { SelectList selectList = new SelectList(); SelectListItem selectListItem1 = new SelectListItem(slotRef1, null); selectList.addItem(selectListItem1); @@ -916,6 +948,7 @@ public void testMVColumns(@Injectable SlotRef slotRef1, TableName tableName = new TableName("db", "table"); final String columnName3 = "sum_v2"; SlotRef slotRef = new SlotRef(tableName, columnName3); + Deencapsulation.setField(slotRef, "desc", slotDescriptor); List children = Lists.newArrayList(slotRef); FunctionCallExpr functionCallExpr = new FunctionCallExpr("sum", children); SelectListItem selectListItem3 = new SelectListItem(functionCallExpr, null); @@ -949,6 +982,10 @@ public void testMVColumns(@Injectable SlotRef slotRef1, result = columnName1; slotRef2.getColumnName(); result = columnName2; + slotDescriptor.getColumn(); + result = column1; + column1.getOriginType(); + result = Type.INT; } }; @@ -1025,13 +1062,29 @@ public void testDeduplicateMV(@Injectable SlotRef slotRef1, } @Test - public void testBuildMVColumnItem(@Injectable SelectStmt selectStmt) { + public void testBuildMVColumnItem(@Injectable SelectStmt selectStmt, + @Injectable Column column1, + @Injectable Column column2, + @Injectable Column column3, + @Injectable Column column4, + @Injectable SlotDescriptor slotDescriptor1, + @Injectable SlotDescriptor slotDescriptor2, + @Injectable SlotDescriptor slotDescriptor3, + @Injectable SlotDescriptor slotDescriptor4) { CreateMaterializedViewStmt createMaterializedViewStmt = new CreateMaterializedViewStmt("test", selectStmt, null); SlotRef slotRef = new SlotRef(new TableName("db", "table"), "a"); List params = Lists.newArrayList(); params.add(slotRef); FunctionCallExpr functionCallExpr = new FunctionCallExpr("sum", params); - slotRef.setType(Type.LARGEINT); + Deencapsulation.setField(slotRef, "desc", slotDescriptor1); + new Expectations() { + { + slotDescriptor1.getColumn(); + result = column1; + column1.getOriginType(); + result = Type.LARGEINT; + } + }; MVColumnItem mvColumnItem = Deencapsulation.invoke(createMaterializedViewStmt, "buildMVColumnItem", functionCallExpr); Assert.assertEquals(Type.LARGEINT, mvColumnItem.getType()); @@ -1039,7 +1092,15 @@ public void testBuildMVColumnItem(@Injectable SelectStmt selectStmt) { List params2 = Lists.newArrayList(); params2.add(slotRef2); FunctionCallExpr functionCallExpr2 = new FunctionCallExpr("sum", params2); - slotRef2.setType(Type.SMALLINT); + Deencapsulation.setField(slotRef2, "desc", slotDescriptor2); + new Expectations() { + { + slotDescriptor2.getColumn(); + result = column2; + column2.getOriginType(); + result = Type.BIGINT; + } + }; MVColumnItem mvColumnItem2 = Deencapsulation.invoke(createMaterializedViewStmt, "buildMVColumnItem", functionCallExpr2); Assert.assertEquals(Type.BIGINT, mvColumnItem2.getType()); @@ -1047,7 +1108,15 @@ public void testBuildMVColumnItem(@Injectable SelectStmt selectStmt) { List params3 = Lists.newArrayList(); params3.add(slotRef3); FunctionCallExpr functionCallExpr3 = new FunctionCallExpr("min", params3); - slotRef3.setType(Type.VARCHAR); + Deencapsulation.setField(slotRef3, "desc", slotDescriptor3); + new Expectations() { + { + slotDescriptor3.getColumn(); + result = column3; + column3.getOriginType(); + result = Type.VARCHAR; + } + }; MVColumnItem mvColumnItem3 = Deencapsulation.invoke(createMaterializedViewStmt, "buildMVColumnItem", functionCallExpr3); Assert.assertEquals(Type.VARCHAR, mvColumnItem3.getType()); @@ -1055,11 +1124,77 @@ public void testBuildMVColumnItem(@Injectable SelectStmt selectStmt) { List params4 = Lists.newArrayList(); params4.add(slotRef4); FunctionCallExpr functionCallExpr4 = new FunctionCallExpr("sum", params4); - slotRef4.setType(Type.DOUBLE); + Deencapsulation.setField(slotRef4, "desc", slotDescriptor4); + new Expectations() { + { + slotDescriptor4.getColumn(); + result = column4; + column4.getOriginType(); + result = Type.DOUBLE; + } + }; MVColumnItem mvColumnItem4 = Deencapsulation.invoke(createMaterializedViewStmt, "buildMVColumnItem", functionCallExpr4); Assert.assertEquals(Type.DOUBLE, mvColumnItem4.getType()); + } + @Test + public void testKeepScaleAndPrecisionOfType(@Injectable SelectStmt selectStmt, + @Injectable SlotDescriptor slotDescriptor1, + @Injectable Column column1, + @Injectable SlotDescriptor slotDescriptor2, + @Injectable Column column2, + @Injectable SlotDescriptor slotDescriptor3, + @Injectable Column column3) { + CreateMaterializedViewStmt createMaterializedViewStmt = new CreateMaterializedViewStmt("test", selectStmt, null); + SlotRef slotRef = new SlotRef(new TableName("db", "table"), "a"); + List params = Lists.newArrayList(); + params.add(slotRef); + FunctionCallExpr functionCallExpr = new FunctionCallExpr("min", params); + Deencapsulation.setField(slotRef, "desc", slotDescriptor1); + new Expectations() { + { + slotDescriptor1.getColumn(); + result = column1; + column1.getOriginType(); + result = ScalarType.createVarchar(50); + } + }; + MVColumnItem mvColumnItem = Deencapsulation.invoke(createMaterializedViewStmt, "buildMVColumnItem", functionCallExpr); + Assert.assertEquals(50, ((ScalarType)mvColumnItem.getType()).getLength()); + + SlotRef slotRef2 = new SlotRef(new TableName("db", "table"), "a"); + List params2 = Lists.newArrayList(); + params2.add(slotRef2); + FunctionCallExpr functionCallExpr2 = new FunctionCallExpr("min", params2); + Deencapsulation.setField(slotRef2, "desc", slotDescriptor2); + new Expectations() { + { + slotDescriptor2.getColumn(); + result = column2; + column2.getOriginType(); + result = ScalarType.createDecimalV2Type(10,1); + } + }; + MVColumnItem mvColumnItem2 = Deencapsulation.invoke(createMaterializedViewStmt, "buildMVColumnItem", functionCallExpr2); + Assert.assertEquals(new Integer(10), ((ScalarType)mvColumnItem2.getType()).getPrecision()); + Assert.assertEquals(1, ((ScalarType)mvColumnItem2.getType()).getScalarScale()); + + SlotRef slotRef3 = new SlotRef(new TableName("db", "table"), "a"); + List params3 = Lists.newArrayList(); + params3.add(slotRef3); + FunctionCallExpr functionCallExpr3 = new FunctionCallExpr("min", params3); + Deencapsulation.setField(slotRef3, "desc", slotDescriptor3); + new Expectations() { + { + slotDescriptor3.getColumn(); + result = column3; + column3.getOriginType(); + result = ScalarType.createChar(5); + } + }; + MVColumnItem mvColumnItem3 = Deencapsulation.invoke(createMaterializedViewStmt, "buildMVColumnItem", functionCallExpr3); + Assert.assertEquals(5, ((ScalarType)mvColumnItem3.getType()).getLength()); } }