This is an automated email from the ASF dual-hosted git repository.
morrysnow 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 d34ef4dcddf [fix](Nereids) update assignment column name should case
insensitive (#30072)
d34ef4dcddf is described below
commit d34ef4dcddf1d88e9ba4b34e67265176cda37b26
Author: morrySnow <[email protected]>
AuthorDate: Thu Jan 25 14:55:03 2024 +0800
[fix](Nereids) update assignment column name should case insensitive
(#30072)
pick from master PR #30071
---
.../doris/nereids/rules/analysis/SlotBinder.java | 34 ++++++++++--------
.../trees/plans/commands/UpdateCommand.java | 41 +++++++++++++++++++---
.../nereids_p0/update/update_unique_table.groovy | 12 ++++++-
3 files changed, 67 insertions(+), 20 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SlotBinder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SlotBinder.java
index 57d84610cfd..39bc3074cb9 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SlotBinder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/SlotBinder.java
@@ -53,7 +53,10 @@ import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
-class SlotBinder extends SubExprAnalyzer {
+/**
+ * SlotBinder is used to bind slot
+ */
+public class SlotBinder extends SubExprAnalyzer {
/*
bounded={table.a, a}
unbound=a
@@ -260,18 +263,6 @@ class SlotBinder extends SubExprAnalyzer {
return new BoundStar(slots);
}
- private boolean compareDbNameIgnoreClusterName(String unBoundDbName,
String boundedDbName) {
- if (unBoundDbName.equalsIgnoreCase(boundedDbName)) {
- return true;
- }
- // boundedDbName example
- int idx = boundedDbName.indexOf(ClusterNamespace.CLUSTER_DELIMITER);
- if (idx > -1) {
- return unBoundDbName.equalsIgnoreCase(boundedDbName.substring(idx
+ 1));
- }
- return false;
- }
-
private List<Slot> bindSlot(UnboundSlot unboundSlot, List<Slot>
boundSlots) {
return boundSlots.stream().distinct().filter(boundSlot -> {
List<String> nameParts = unboundSlot.getNameParts();
@@ -311,7 +302,22 @@ class SlotBinder extends SubExprAnalyzer {
}).collect(Collectors.toList());
}
- private boolean sameTableName(String boundSlot, String unboundSlot) {
+ /**
+ * compareDbNameIgnoreClusterName.
+ */
+ public static boolean compareDbNameIgnoreClusterName(String unBoundDbName,
String boundedDbName) {
+ if (unBoundDbName.equalsIgnoreCase(boundedDbName)) {
+ return true;
+ }
+ // boundedDbName example
+ int idx = boundedDbName.indexOf(ClusterNamespace.CLUSTER_DELIMITER);
+ if (idx > -1) {
+ return unBoundDbName.equalsIgnoreCase(boundedDbName.substring(idx
+ 1));
+ }
+ return false;
+ }
+
+ public static boolean sameTableName(String boundSlot, String unboundSlot) {
if (Config.lower_case_table_names != 1) {
return boundSlot.equals(unboundSlot);
} else {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UpdateCommand.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UpdateCommand.java
index 92f3fb21ee5..79ed4055ce9 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UpdateCommand.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/UpdateCommand.java
@@ -22,10 +22,11 @@ import org.apache.doris.catalog.KeysType;
import org.apache.doris.catalog.OlapTable;
import org.apache.doris.catalog.Table;
import org.apache.doris.catalog.TableIf;
-import org.apache.doris.common.AnalysisException;
+import org.apache.doris.nereids.analyzer.UnboundAlias;
import org.apache.doris.nereids.analyzer.UnboundOlapTableSink;
import org.apache.doris.nereids.analyzer.UnboundSlot;
-import org.apache.doris.nereids.trees.expressions.Alias;
+import org.apache.doris.nereids.exceptions.AnalysisException;
+import org.apache.doris.nereids.rules.analysis.SlotBinder;
import org.apache.doris.nereids.trees.expressions.EqualTo;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.NamedExpression;
@@ -94,12 +95,13 @@ public class UpdateCommand extends Command implements
ForwardWithSync, Explainab
/**
* add LogicalOlapTableSink node, public for test.
*/
- public LogicalPlan completeQueryPlan(ConnectContext ctx, LogicalPlan
logicalQuery) throws AnalysisException {
+ public LogicalPlan completeQueryPlan(ConnectContext ctx, LogicalPlan
logicalQuery) {
checkTable(ctx);
- Map<String, Expression> colNameToExpression = Maps.newHashMap();
+ Map<String, Expression> colNameToExpression =
Maps.newTreeMap(String.CASE_INSENSITIVE_ORDER);
for (EqualTo equalTo : assignments) {
List<String> nameParts = ((UnboundSlot)
equalTo.left()).getNameParts();
+ checkAssignmentColumn(ctx, nameParts);
colNameToExpression.put(nameParts.get(nameParts.size() - 1),
equalTo.right());
}
List<NamedExpression> selectItems = Lists.newArrayList();
@@ -112,11 +114,16 @@ public class UpdateCommand extends Command implements
ForwardWithSync, Explainab
Expression expr = colNameToExpression.get(column.getName());
selectItems.add(expr instanceof UnboundSlot
? ((NamedExpression) expr)
- : new Alias(expr));
+ : new UnboundAlias(expr));
+ colNameToExpression.remove(column.getName());
} else {
selectItems.add(new UnboundSlot(tableName, column.getName()));
}
}
+ if (!colNameToExpression.isEmpty()) {
+ throw new AnalysisException("unknown column in assignment list: "
+ + String.join(", ", colNameToExpression.keySet()));
+ }
logicalQuery = new LogicalProject<>(selectItems, logicalQuery);
if (cte.isPresent()) {
@@ -128,6 +135,30 @@ public class UpdateCommand extends Command implements
ForwardWithSync, Explainab
ImmutableList.of(), logicalQuery);
}
+ private void checkAssignmentColumn(ConnectContext ctx, List<String>
columnNameParts) {
+ if (columnNameParts.size() <= 1) {
+ return;
+ }
+ String dbName = null;
+ String tableName = null;
+ if (columnNameParts.size() == 3) {
+ dbName = columnNameParts.get(0);
+ tableName = columnNameParts.get(1);
+ } else if (columnNameParts.size() == 2) {
+ tableName = columnNameParts.get(0);
+ } else {
+ throw new AnalysisException("column in assignment list is invalid,
" + String.join(".", columnNameParts));
+ }
+ if (dbName != null && this.tableAlias != null) {
+ throw new AnalysisException("column in assignment list is invalid,
" + String.join(".", columnNameParts));
+ }
+ List<String> tableQualifier = RelationUtil.getQualifierName(ctx,
nameParts);
+ if (!SlotBinder.sameTableName(tableAlias == null ?
tableQualifier.get(2) : tableAlias, tableName)
+ || (dbName != null &&
SlotBinder.compareDbNameIgnoreClusterName(tableQualifier.get(1), dbName))) {
+ throw new AnalysisException("column in assignment list is invalid,
" + String.join(".", columnNameParts));
+ }
+ }
+
private void checkTable(ConnectContext ctx) throws AnalysisException {
if (ctx.getSessionVariable().isInDebugMode()) {
throw new AnalysisException("Update is forbidden since current
session is in debug mode."
diff --git
a/regression-test/suites/nereids_p0/update/update_unique_table.groovy
b/regression-test/suites/nereids_p0/update/update_unique_table.groovy
index 59ea06b10b8..e84b3033c6b 100644
--- a/regression-test/suites/nereids_p0/update/update_unique_table.groovy
+++ b/regression-test/suites/nereids_p0/update/update_unique_table.groovy
@@ -95,10 +95,20 @@ suite('update_unique_table') {
sql '''
update t1
- set t1.c1 = t2.c1, t1.c3 = t2.c3 * 100
+ set t1.C1 = t2.c1, t1.c3 = t2.c3 * 100
from t2 inner join t3 on t2.id = t3.id
where t1.id = t2.id;
'''
qt_sql 'select * from t1 order by id'
+
+ test {
+ sql '''update t1 set t.c1 = 1 where t1.c1 = 1;'''
+ exception ""
+ }
+
+ test {
+ sql '''update t1 t set t1.c1 = 1 where t1.c1 = 1;'''
+ exception ""
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]