This is an automated email from the ASF dual-hosted git repository.

justinchen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new d583362ab98 Optimized the value type check for update device (#16448)
d583362ab98 is described below

commit d583362ab9842bd65abb2c168b5683647e6ac563
Author: Caideyipi <[email protected]>
AuthorDate: Tue Sep 30 18:12:04 2025 +0800

    Optimized the value type check for update device (#16448)
---
 .../iotdb/relational/it/schema/IoTDBDeviceIT.java  |  4 +--
 .../relational/analyzer/StatementAnalyzer.java     | 31 +++++++++++++++-------
 .../metadata/fetcher/SchemaPredicateUtil.java      | 28 +++++++++----------
 .../plan/relational/planner/TranslationMap.java    |  2 +-
 .../sql/ast/AbstractQueryDeviceWithCache.java      |  3 +--
 .../relational/sql/ast/AbstractTraverseDevice.java |  2 +-
 .../plan/relational/sql/ast/DeleteDevice.java      |  5 ++--
 7 files changed, 41 insertions(+), 34 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDeviceIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDeviceIT.java
index 7b023b4e9f6..44ea1e66bf7 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDeviceIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDeviceIT.java
@@ -221,9 +221,7 @@ public class IoTDBDeviceIT {
         statement.execute("update table0 set model = cast(device_id as 
int32)");
         fail("Update shall fail when result type mismatch");
       } catch (final Exception e) {
-        assertEquals(
-            "507: Result type mismatch for attribute 'model', expected class 
org.apache.tsfile.utils.Binary, actual class java.lang.Integer",
-            e.getMessage());
+        assertEquals("701: Update's attribute value must be STRING, TEXT or 
null.", e.getMessage());
       }
 
       // Test filter with no effect
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
index 408c52909e7..6a2b7eb34c1 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java
@@ -220,10 +220,14 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Streams;
 import org.apache.tsfile.common.conf.TSFileConfig;
+import org.apache.tsfile.read.common.type.BinaryType;
 import org.apache.tsfile.read.common.type.RowType;
+import org.apache.tsfile.read.common.type.StringType;
 import org.apache.tsfile.read.common.type.TimestampType;
 import org.apache.tsfile.read.common.type.Type;
+import org.apache.tsfile.read.common.type.UnknownType;
 import org.apache.tsfile.utils.Binary;
+import org.apache.tsfile.utils.Pair;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -507,7 +511,7 @@ public class StatementAnalyzer {
       final TsTable table =
           DataNodeTableCache.getInstance().getTable(node.getDatabase(), 
node.getTableName());
       DataNodeTreeViewSchemaUtils.checkTableInWrite(node.getDatabase(), table);
-      if (!node.parseRawExpression(
+      if (!node.parseWhere(
           null,
           table,
           table.getColumnList().stream()
@@ -531,7 +535,8 @@ public class StatementAnalyzer {
                     assignment -> {
                       final Expression parsedColumn =
                           analyzeAndRewriteExpression(
-                              translationMap, translationMap.getScope(), 
assignment.getName());
+                                  translationMap, translationMap.getScope(), 
assignment.getName())
+                              .getRight();
                       if (!(parsedColumn instanceof SymbolReference)
                           || table
                                   .getColumnSchema(((SymbolReference) 
parsedColumn).getName())
@@ -545,10 +550,16 @@ public class StatementAnalyzer {
                       }
                       attributeNames.add((SymbolReference) parsedColumn);
 
-                      return new UpdateAssignment(
-                          parsedColumn,
+                      final Pair<Type, Expression> expressionPair =
                           analyzeAndRewriteExpression(
-                              translationMap, translationMap.getScope(), 
assignment.getValue()));
+                              translationMap, translationMap.getScope(), 
assignment.getValue());
+                      if (!expressionPair.getLeft().equals(StringType.STRING)
+                          && !expressionPair.getLeft().equals(BinaryType.TEXT)
+                          && 
!expressionPair.getLeft().equals(UnknownType.UNKNOWN)) {
+                        throw new SemanticException(
+                            "Update's attribute value must be STRING, TEXT or 
null.");
+                      }
+                      return new UpdateAssignment(parsedColumn, 
expressionPair.getRight());
                     })
                 .collect(Collectors.toList()));
       }
@@ -569,7 +580,7 @@ public class StatementAnalyzer {
       DataNodeTreeViewSchemaUtils.checkTableInWrite(node.getDatabase(), table);
       node.parseModEntries(table);
       analyzeTraverseDevice(node, context, node.getWhere().isPresent());
-      node.parseRawExpression(
+      node.parseWhere(
           null,
           table,
           table.getColumnList().stream()
@@ -4515,7 +4526,7 @@ public class StatementAnalyzer {
       final String tableName = node.getTableName();
 
       if (Objects.isNull(database)) {
-        throw new SemanticException("The database must be set before show 
devices.");
+        throw new SemanticException("The database must be set.");
       }
 
       if (!metadata.tableExists(new QualifiedObjectName(database, tableName))) 
{
@@ -4560,11 +4571,11 @@ public class StatementAnalyzer {
       return translationMap;
     }
 
-    private Expression analyzeAndRewriteExpression(
+    private Pair<Type, Expression> analyzeAndRewriteExpression(
         final TranslationMap translationMap, final Scope scope, final 
Expression expression) {
-      analyzeExpression(expression, scope);
+      final Type type = analyzeExpression(expression, 
scope).getType(expression);
       scope.getRelationType().getAllFields();
-      return translationMap.rewrite(expression);
+      return new Pair<>(type, translationMap.rewrite(expression));
     }
 
     @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/SchemaPredicateUtil.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/SchemaPredicateUtil.java
index 0620f3b5383..c794ab3fba7 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/SchemaPredicateUtil.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/SchemaPredicateUtil.java
@@ -58,8 +58,8 @@ public class SchemaPredicateUtil {
       final TsTable table,
       final MPPQueryContext queryContext,
       final boolean isDirectDeviceQuery) {
-    final List<Expression> idDeterminedList = new ArrayList<>();
-    final List<Expression> idFuzzyList = new ArrayList<>();
+    final List<Expression> tagDeterminedList = new ArrayList<>();
+    final List<Expression> tagFuzzyList = new ArrayList<>();
     final CheckSchemaPredicateVisitor visitor = new 
CheckSchemaPredicateVisitor();
     final CheckSchemaPredicateVisitor.Context context =
         new CheckSchemaPredicateVisitor.Context(table, queryContext, 
isDirectDeviceQuery);
@@ -70,15 +70,15 @@ public class SchemaPredicateUtil {
       if (expression instanceof BetweenPredicate) {
         final BetweenPredicate predicate = (BetweenPredicate) expression;
 
-        // Separate the between predicate to simply the logic and to handle 
cases like
-        // '2' between id1 and attr2 / id1 between '2' and attr1
+        // Separate the between predicate to simplify the logic and to handle 
cases like '2' between
+        // id1 and attr2 / id1 between '2' and attr1
         separateExpression(
             new ComparisonExpression(
                 ComparisonExpression.Operator.LESS_THAN_OR_EQUAL,
                 predicate.getMin(),
                 predicate.getValue()),
-            idDeterminedList,
-            idFuzzyList,
+            tagDeterminedList,
+            tagFuzzyList,
             visitor,
             context);
         separateExpression(
@@ -86,27 +86,27 @@ public class SchemaPredicateUtil {
                 ComparisonExpression.Operator.LESS_THAN_OR_EQUAL,
                 predicate.getValue(),
                 predicate.getMax()),
-            idDeterminedList,
-            idFuzzyList,
+            tagDeterminedList,
+            tagFuzzyList,
             visitor,
             context);
         continue;
       }
-      separateExpression(expression, idDeterminedList, idFuzzyList, visitor, 
context);
+      separateExpression(expression, tagDeterminedList, tagFuzzyList, visitor, 
context);
     }
-    return new Pair<>(idDeterminedList, idFuzzyList);
+    return new Pair<>(tagDeterminedList, tagFuzzyList);
   }
 
   private static void separateExpression(
       final Expression expression,
-      final List<Expression> idDeterminedList,
-      final List<Expression> idFuzzyList,
+      final List<Expression> tagDeterminedList,
+      final List<Expression> tagFuzzyList,
       final CheckSchemaPredicateVisitor visitor,
       final CheckSchemaPredicateVisitor.Context context) {
     if (Boolean.TRUE.equals(expression.accept(visitor, context))) {
-      idFuzzyList.add(expression);
+      tagFuzzyList.add(expression);
     } else {
-      idDeterminedList.add(expression);
+      tagDeterminedList.add(expression);
     }
   }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TranslationMap.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TranslationMap.java
index 0edd20bc36d..0f831b8168b 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TranslationMap.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TranslationMap.java
@@ -260,7 +260,7 @@ public class TranslationMap {
 
             return getSymbolForColumn(node)
                 .map(symbol -> (Expression) symbol.toSymbolReference())
-                .orElseGet(() -> node);
+                .orElse(node);
           }
 
           @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractQueryDeviceWithCache.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractQueryDeviceWithCache.java
index 327b5703b4e..ab2a1afe76a 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractQueryDeviceWithCache.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractQueryDeviceWithCache.java
@@ -64,8 +64,7 @@ public abstract class AbstractQueryDeviceWithCache extends 
AbstractTraverseDevic
     final Map<String, List<DeviceEntry>> entries = new HashMap<>();
     entries.put(database, new ArrayList<>());
 
-    final boolean needFetch =
-        super.parseRawExpression(entries, tableInstance, attributeColumns, 
context);
+    final boolean needFetch = super.parseWhere(entries, tableInstance, 
attributeColumns, context);
     if (!needFetch) {
       context.reserveMemoryForFrontEnd(
           
entries.get(database).stream().map(DeviceEntry::ramBytesUsed).reduce(0L, 
Long::sum));
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractTraverseDevice.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractTraverseDevice.java
index 2493418b671..c61945b1b91 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractTraverseDevice.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AbstractTraverseDevice.java
@@ -128,7 +128,7 @@ public abstract class AbstractTraverseDevice extends 
Statement {
     this.where = where;
   }
 
-  public boolean parseRawExpression(
+  public boolean parseWhere(
       final Map<String, List<DeviceEntry>> entries,
       final TsTable tableInstance,
       final List<String> attributeColumns,
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DeleteDevice.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DeleteDevice.java
index 10935e97d4e..9b1487b0a48 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DeleteDevice.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DeleteDevice.java
@@ -75,13 +75,12 @@ public class DeleteDevice extends AbstractTraverseDevice {
   }
 
   @Override
-  public boolean parseRawExpression(
+  public boolean parseWhere(
       final Map<String, List<DeviceEntry>> entries,
       final TsTable tableInstance,
       final List<String> attributeColumns,
       final MPPQueryContext context) {
-    return mayDeleteDevice =
-        super.parseRawExpression(entries, tableInstance, attributeColumns, 
context);
+    return mayDeleteDevice = super.parseWhere(entries, tableInstance, 
attributeColumns, context);
   }
 
   public boolean isMayDeleteDevice() {

Reply via email to