This is an automated email from the ASF dual-hosted git repository.
kxiao pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.0 by this push:
new 17a92ef056e [Bug](insert)fix insert wrong data on mv when stmt have
multiple values (#27297) (#27382)
17a92ef056e is described below
commit 17a92ef056e96629dd7bf38c780cbddf73e97c68
Author: Pxl <[email protected]>
AuthorDate: Thu Nov 23 01:48:03 2023 +0800
[Bug](insert)fix insert wrong data on mv when stmt have multiple values
(#27297) (#27382)
fix insert wrong data on mv when stmt have multiple values
---
.../apache/doris/analysis/NativeInsertStmt.java | 59 +++++++++++++---------
.../mv_p0/test_insert_multi/test_insert_multi.out | 9 ++++
.../test_insert_multi/test_insert_multi.groovy | 39 ++++++++++++++
3 files changed, 84 insertions(+), 23 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/NativeInsertStmt.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/NativeInsertStmt.java
index cc2d1341377..391d8c6820f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/NativeInsertStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/NativeInsertStmt.java
@@ -595,25 +595,6 @@ public class NativeInsertStmt extends InsertStmt {
checkColumnCoverage(mentionedColumns, targetTable.getBaseSchema());
realTargetColumnNames =
targetColumns.stream().map(Column::getName).collect(Collectors.toList());
- Map<String, Expr> slotToIndex =
Maps.newTreeMap(String.CASE_INSENSITIVE_ORDER);
- for (int i = 0; i < queryStmt.getResultExprs().size(); i++) {
- Expr expr = queryStmt.getResultExprs().get(i);
- if (!(expr instanceof StringLiteral && ((StringLiteral)
expr).getValue()
- .equals(SelectStmt.DEFAULT_VALUE))) {
- slotToIndex.put(realTargetColumnNames.get(i),
queryStmt.getResultExprs().get(i)
-
.checkTypeCompatibility(targetTable.getColumn(realTargetColumnNames.get(i)).getType()));
- }
- }
-
- for (Column column : targetTable.getBaseSchema()) {
- if (!slotToIndex.containsKey(column.getName())) {
- if (column.getDefaultValue() == null) {
- slotToIndex.put(column.getName(), new NullLiteral());
- } else {
- slotToIndex.put(column.getName(), new
StringLiteral(column.getDefaultValue()));
- }
- }
- }
// handle VALUES() or SELECT constant list
if (isValuesOrConstantSelect) {
@@ -622,7 +603,7 @@ public class NativeInsertStmt extends InsertStmt {
// INSERT INTO VALUES(...)
List<ArrayList<Expr>> rows =
selectStmt.getValueList().getRows();
for (int rowIdx = 0; rowIdx < rows.size(); ++rowIdx) {
- analyzeRow(analyzer, targetColumns, rows, rowIdx,
origColIdxsForExtendCols, slotToIndex);
+ analyzeRow(analyzer, targetColumns, rows, rowIdx,
origColIdxsForExtendCols, realTargetColumnNames);
}
// clear these 2 structures, rebuild them using VALUES exprs
@@ -640,7 +621,7 @@ public class NativeInsertStmt extends InsertStmt {
// `selectStmt.getResultExprs().clear();` will clear the
`rows` too, causing
// error.
rows.add(Lists.newArrayList(selectStmt.getResultExprs()));
- analyzeRow(analyzer, targetColumns, rows, 0,
origColIdxsForExtendCols, slotToIndex);
+ analyzeRow(analyzer, targetColumns, rows, 0,
origColIdxsForExtendCols, realTargetColumnNames);
// rows may be changed in analyzeRow(), so rebuild the result
exprs
selectStmt.getResultExprs().clear();
for (Expr expr : rows.get(0)) {
@@ -651,6 +632,8 @@ public class NativeInsertStmt extends InsertStmt {
// INSERT INTO SELECT ... FROM tbl
if (!origColIdxsForExtendCols.isEmpty()) {
// extend the result expr by duplicating the related exprs
+ Map<String, Expr> slotToIndex =
buildSlotToIndex(queryStmt.getResultExprs(), realTargetColumnNames,
+ analyzer);
for (Pair<Integer, Column> entry : origColIdxsForExtendCols) {
if (entry.second == null) {
queryStmt.getResultExprs().add(queryStmt.getResultExprs().get(entry.first));
@@ -680,6 +663,8 @@ public class NativeInsertStmt extends InsertStmt {
// expand colLabels in QueryStmt
if (!origColIdxsForExtendCols.isEmpty()) {
if (queryStmt.getResultExprs().size() !=
queryStmt.getBaseTblResultExprs().size()) {
+ Map<String, Expr> slotToIndex =
buildSlotToIndex(queryStmt.getBaseTblResultExprs(),
+ realTargetColumnNames, analyzer);
for (Pair<Integer, Column> entry : origColIdxsForExtendCols) {
if (entry.second == null) {
queryStmt.getBaseTblResultExprs().add(queryStmt.getBaseTblResultExprs().get(entry.first));
@@ -718,8 +703,34 @@ public class NativeInsertStmt extends InsertStmt {
}
}
- private void analyzeRow(Analyzer analyzer, List<Column> targetColumns,
List<ArrayList<Expr>> rows,
- int rowIdx, List<Pair<Integer, Column>> origColIdxsForExtendCols,
Map<String, Expr> slotToIndex)
+ private Map<String, Expr> buildSlotToIndex(ArrayList<Expr> row,
List<String> realTargetColumnNames,
+ Analyzer analyzer) throws AnalysisException {
+ Map<String, Expr> slotToIndex =
Maps.newTreeMap(String.CASE_INSENSITIVE_ORDER);
+ for (int i = 0; i < row.size(); i++) {
+ Expr expr = row.get(i);
+ expr.analyze(analyzer);
+ if (expr instanceof DefaultValueExpr || expr instanceof
StringLiteral
+ && ((StringLiteral)
expr).getValue().equals(SelectStmt.DEFAULT_VALUE)) {
+ continue;
+ }
+ expr.analyze(analyzer);
+ slotToIndex.put(realTargetColumnNames.get(i),
+
expr.checkTypeCompatibility(targetTable.getColumn(realTargetColumnNames.get(i)).getType()));
+ }
+ for (Column column : targetTable.getBaseSchema()) {
+ if (!slotToIndex.containsKey(column.getName())) {
+ if (column.getDefaultValue() == null) {
+ slotToIndex.put(column.getName(), new NullLiteral());
+ } else {
+ slotToIndex.put(column.getName(), new
StringLiteral(column.getDefaultValue()));
+ }
+ }
+ }
+ return slotToIndex;
+ }
+
+ private void analyzeRow(Analyzer analyzer, List<Column> targetColumns,
List<ArrayList<Expr>> rows, int rowIdx,
+ List<Pair<Integer, Column>> origColIdxsForExtendCols, List<String>
realTargetColumnNames)
throws AnalysisException {
// 1. check number of fields if equal with first row
// targetColumns contains some shadow columns, which is added by
system,
@@ -729,6 +740,8 @@ public class NativeInsertStmt extends InsertStmt {
}
ArrayList<Expr> row = rows.get(rowIdx);
+ Map<String, Expr> slotToIndex = buildSlotToIndex(row,
realTargetColumnNames, analyzer);
+
if (!origColIdxsForExtendCols.isEmpty()) {
/**
* we should extend the row for shadow columns.
diff --git a/regression-test/data/mv_p0/test_insert_multi/test_insert_multi.out
b/regression-test/data/mv_p0/test_insert_multi/test_insert_multi.out
new file mode 100644
index 00000000000..46af1505087
--- /dev/null
+++ b/regression-test/data/mv_p0/test_insert_multi/test_insert_multi.out
@@ -0,0 +1,9 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !select_star --
+1 1 1 2020-02-02 1
+1 2 2 2020-02-02 1
+
+-- !select_mv --
+1 1
+2 1
+
diff --git
a/regression-test/suites/mv_p0/test_insert_multi/test_insert_multi.groovy
b/regression-test/suites/mv_p0/test_insert_multi/test_insert_multi.groovy
new file mode 100644
index 00000000000..3f0d648f7c4
--- /dev/null
+++ b/regression-test/suites/mv_p0/test_insert_multi/test_insert_multi.groovy
@@ -0,0 +1,39 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import org.codehaus.groovy.runtime.IOGroovyMethods
+
+suite ("test_insert_multi") {
+
+ sql """ DROP TABLE IF EXISTS sales_records; """
+
+ sql """
+ create table sales_records(record_id int, seller_id int, store_id
int, sale_date date, sale_amt bigint) distributed by hash(record_id)
properties("replication_num" = "1");
+ """
+
+ createMV ("create materialized view store_amt as select store_id,
sum(sale_amt) from sales_records group by store_id;")
+
+ sql """insert into sales_records
values(1,1,1,"2020-02-02",1),(1,2,2,"2020-02-02",1);"""
+
+ qt_select_star "select * from sales_records order by 1,2;"
+
+ explain {
+ sql(" SELECT store_id, sum(sale_amt) FROM sales_records GROUP BY
store_id order by 1;")
+ contains "(store_amt)"
+ }
+ qt_select_mv " SELECT store_id, sum(sale_amt) FROM sales_records GROUP BY
store_id order by 1;"
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]