This is an automated email from the ASF dual-hosted git repository. jackietien pushed a commit to branch force_ci/object_type in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit ccf4346314ed05bfdccf5c264947e7e475b28c0e Author: Caideyipi <[email protected]> AuthorDate: Mon Nov 24 10:46:24 2025 +0800 Optimized the error message when the column is not tag/attribute in device related SQLs (#16750) * logic * may-fi * fix * fix * Update IoTDBDeviceIT.java * fixfix * fix * fix * h * coding (cherry picked from commit 36154e5030096afe31e985b17f53984b69d8ff27) --- .../iotdb/relational/it/schema/IoTDBDeviceIT.java | 44 +++++++++++++------ .../relational/analyzer/StatementAnalyzer.java | 51 +++++++++++++++++++--- 2 files changed, 77 insertions(+), 18 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 44ea1e66bf7..1923210b50d 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 @@ -38,6 +38,7 @@ import java.sql.Statement; import java.util.Collections; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @RunWith(IoTDBTestRunner.class) @@ -163,20 +164,11 @@ public class IoTDBDeviceIT { assertEquals("550: Table 'test.table2' does not exist.", e.getMessage()); } - try { - statement.executeQuery("show devices from table0 where temperature = 37.6"); - fail("Show devices shall fail for measurement predicate"); - } catch (final Exception e) { - assertEquals( - "701: The TIME/FIELD columns are currently not allowed in devices related operations", - e.getMessage()); - } - try { statement.executeQuery("count devices from table0 where a = 1"); fail("Count devices shall fail for non-exist column"); } catch (final Exception e) { - assertEquals("616: Column 'a' cannot be resolved", e.getMessage()); + assertEquals("701: Column 'a' is not an attribute or tag column", e.getMessage()); } // Test fully qualified name @@ -224,6 +216,34 @@ public class IoTDBDeviceIT { assertEquals("701: Update's attribute value must be STRING, TEXT or null.", e.getMessage()); } + try { + statement.execute("show devices from table0 where humidity = 1"); + fail("Update shall fail for non-tag/attribute columns"); + } catch (final Exception e) { + assertEquals("701: Column 'humidity' is not an attribute or tag column", e.getMessage()); + } + + try { + statement.execute("count devices from table0 where humidity = 1"); + fail("Update shall fail for non-tag/attribute columns"); + } catch (final Exception e) { + assertEquals("701: Column 'humidity' is not an attribute or tag column", e.getMessage()); + } + + try { + statement.execute("update table0 set model = '1' where humidity = 1"); + fail("Update shall fail for non-tag/attribute columns"); + } catch (final Exception e) { + assertEquals("701: Column 'humidity' is not an attribute or tag column", e.getMessage()); + } + + try { + statement.execute("update table0 set model = humidity"); + fail("Update shall fail for non-tag/attribute columns"); + } catch (final Exception e) { + assertTrue(e.getMessage().contains("Column 'humidity' is not an attribute or tag column")); + } + // Test filter with no effect statement.execute("update table0 set model = null where model = 'A' and model = 'B'"); @@ -270,9 +290,7 @@ public class IoTDBDeviceIT { statement.executeQuery("delete devices from table0 where time = 1"); fail("Delete devices shall fail when specifies non tag column"); } catch (final Exception e) { - assertEquals( - "701: The TIME/FIELD columns are currently not allowed in devices related operations", - e.getMessage()); + assertEquals("701: Column 'time' is not an attribute or tag column", e.getMessage()); } } } 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 01b216fe875..96f68194400 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 @@ -19,6 +19,7 @@ package org.apache.iotdb.db.queryengine.plan.relational.analyzer; +import org.apache.iotdb.commons.exception.IoTDBException; import org.apache.iotdb.commons.schema.table.TsTable; import org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory; import org.apache.iotdb.commons.schema.table.column.TsTableColumnSchema; @@ -551,9 +552,24 @@ public class StatementAnalyzer { } attributeNames.add((SymbolReference) parsedColumn); - final Pair<Type, Expression> expressionPair = - analyzeAndRewriteExpression( - translationMap, translationMap.getScope(), assignment.getValue()); + final Pair<Type, Expression> expressionPair; + try { + expressionPair = + analyzeAndRewriteExpression( + translationMap, translationMap.getScope(), assignment.getValue()); + } catch (final Exception e) { + if (e.getMessage().contains("cannot be resolved")) { + throw new SemanticException( + new IoTDBException( + e.getCause() + .getMessage() + .replace( + "cannot be resolved", + "is not an attribute or tag column"), + TSStatusCode.SEMANTIC_ERROR.getStatusCode())); + } + throw e; + } if (!expressionPair.getLeft().equals(StringType.STRING) && !expressionPair.getLeft().equals(BinaryType.TEXT) && !expressionPair.getLeft().equals(UnknownType.UNKNOWN)) { @@ -4546,11 +4562,24 @@ public class StatementAnalyzer { final TableSchema originalSchema = tableSchema.get(); final ImmutableList.Builder<Field> fields = ImmutableList.builder(); + // We only leave attribute & tag here because the others are not allowed in device related + // SQLs fields.addAll( analyzeTableOutputFields( node.getTable(), name, - new TableSchema(originalSchema.getTableName(), originalSchema.getColumns()))); + new TableSchema( + originalSchema.getTableName(), + originalSchema.getColumns().stream() + .filter( + columnSchema -> + columnSchema + .getColumnCategory() + .equals(TsTableColumnCategory.ATTRIBUTE) + || columnSchema + .getColumnCategory() + .equals(TsTableColumnCategory.TAG)) + .collect(Collectors.toList())))); final List<Field> fieldList = fields.build(); final Scope scope = createAndAssignScope(node, context, fieldList); translationMap = @@ -4564,7 +4593,19 @@ public class StatementAnalyzer { new PlannerContext(metadata, null)); if (node.getWhere().isPresent()) { - analyzeWhere(node, translationMap.getScope(), node.getWhere().get()); + try { + analyzeWhere(node, translationMap.getScope(), node.getWhere().get()); + } catch (final Throwable e) { + if (e instanceof SemanticException && e.getMessage().contains("cannot be resolved")) { + throw new SemanticException( + new IoTDBException( + e.getCause() + .getMessage() + .replace("cannot be resolved", "is not an attribute or tag column"), + TSStatusCode.SEMANTIC_ERROR.getStatusCode())); + } + throw e; + } node.setWhere(translationMap.rewrite(analysis.getWhere(node))); } }
