This is an automated email from the ASF dual-hosted git repository.
jt2594838 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 8235112d353 Fix no-tag table attribute deletion (#18176)
8235112d353 is described below
commit 8235112d353c7f800ab8009ab134a302968c3ab7
Author: Caideyipi <[email protected]>
AuthorDate: Mon Jul 13 10:41:47 2026 +0800
Fix no-tag table attribute deletion (#18176)
---
.../relational/it/db/it/IoTDBDeletionTableIT.java | 18 ++++
.../plan/relational/sql/ast/InsertRows.java | 115 ++++++++++++++++++++-
2 files changed, 132 insertions(+), 1 deletion(-)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBDeletionTableIT.java
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBDeletionTableIT.java
index 3ac335df1ad..82b6c1a8ff6 100644
---
a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBDeletionTableIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBDeletionTableIT.java
@@ -653,6 +653,24 @@ public class IoTDBDeletionTableIT {
+ "(3, 'blue', 'large', 13),"
+ "(4, 'red', 'small', 14)");
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery("show devices from delete_by_attr_no_tag"),
+ "attr1,attr2,",
+ Collections.singleton("red,small,"));
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery(
+ "show devices from delete_by_attr_no_tag "
+ + "where attr1 = 'red' AND attr2 = 'small'"),
+ "attr1,attr2,",
+ Collections.singleton("red,small,"));
+ statement.execute(
+ "INSERT INTO delete_by_attr_no_tag(time, attr1, attr2, s1) VALUES "
+ + "(2, 'blue', 'large', 12),"
+ + "(4, 'red', 'small', 14)");
+ TestUtils.assertResultSetEqual(
+ statement.executeQuery("show devices from delete_by_attr_no_tag"),
+ "attr1,attr2,",
+ Collections.singleton("red,small,"));
statement.execute(
"DELETE FROM delete_by_attr_no_tag "
+ "WHERE time >= 2 AND time <= 4 AND attr1 = 'red' AND attr2 =
'small'");
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRows.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRows.java
index 4eb49df7183..6b5804ba4eb 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRows.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRows.java
@@ -31,11 +31,15 @@ import
org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowStatement;
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertRowsStatement;
import org.apache.tsfile.enums.TSDataType;
+import org.apache.tsfile.utils.Constants;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
public class InsertRows extends WrappedInsertStatement {
@@ -100,10 +104,26 @@ public class InsertRows extends WrappedInsertStatement {
@Override
public void validateDeviceSchema(Metadata metadata, MPPQueryContext context)
{
+ final Map<String, Map<String, CoalescedDeviceSchemaValidation>>
validationMap =
+ new LinkedHashMap<>();
for (InsertRowStatement insertRowStatement :
getInnerTreeStatement().getInsertRowStatementList()) {
-
metadata.validateDeviceSchema(createTableSchemaValidation(insertRowStatement),
context);
+ final ITableDeviceSchemaValidation rowValidation =
+ createTableSchemaValidation(insertRowStatement);
+ validationMap
+ .computeIfAbsent(rowValidation.getDatabase(), key -> new
LinkedHashMap<>())
+ .computeIfAbsent(
+ rowValidation.getTableName(),
+ tableName ->
+ new
CoalescedDeviceSchemaValidation(rowValidation.getDatabase(), tableName))
+ .add(
+ rowValidation.getDeviceIdList().get(0),
+ rowValidation.getAttributeColumnNameList(),
+ rowValidation.getAttributeValueList().get(0));
}
+ validationMap.values().stream()
+ .flatMap(tableValidationMap -> tableValidationMap.values().stream())
+ .forEach(validation -> metadata.validateDeviceSchema(validation,
context));
}
protected ITableDeviceSchemaValidation createTableSchemaValidation(
@@ -157,4 +177,97 @@ public class InsertRows extends WrappedInsertStatement {
}
};
}
+
+ private static class CoalescedDeviceSchemaValidation implements
ITableDeviceSchemaValidation {
+
+ private final String database;
+ private final String tableName;
+ private final Map<DeviceIdKey, Map<Integer, Object>>
deviceAttributeValueMap =
+ new LinkedHashMap<>();
+ private final List<String> attributeColumnNameList = new ArrayList<>();
+ private final Map<String, Integer> attributeColumnIndexMap = new
LinkedHashMap<>();
+
+ private CoalescedDeviceSchemaValidation(final String database, final
String tableName) {
+ this.database = database;
+ this.tableName = tableName;
+ }
+
+ private void add(
+ final Object[] deviceId,
+ final List<String> attributeColumnNames,
+ final Object[] attributeValues) {
+ final Map<Integer, Object> attributeValueMap =
+ deviceAttributeValueMap.computeIfAbsent(
+ new DeviceIdKey(deviceId), key -> new HashMap<>());
+ for (int i = 0; i < attributeColumnNames.size(); i++) {
+ final int attributeColumnIndex =
+ attributeColumnIndexMap.computeIfAbsent(
+ attributeColumnNames.get(i),
+ attributeColumnName -> {
+ attributeColumnNameList.add(attributeColumnName);
+ return attributeColumnNameList.size() - 1;
+ });
+ if (i < attributeValues.length
+ && attributeValues[i] != null
+ && attributeValues[i] != Constants.NONE) {
+ attributeValueMap.put(attributeColumnIndex, attributeValues[i]);
+ }
+ }
+ }
+
+ @Override
+ public String getDatabase() {
+ return database;
+ }
+
+ @Override
+ public String getTableName() {
+ return tableName;
+ }
+
+ @Override
+ public List<Object[]> getDeviceIdList() {
+ final List<Object[]> deviceIdList = new
ArrayList<>(deviceAttributeValueMap.size());
+ deviceAttributeValueMap.keySet().forEach(key ->
deviceIdList.add(key.deviceId));
+ return deviceIdList;
+ }
+
+ @Override
+ public List<String> getAttributeColumnNameList() {
+ return attributeColumnNameList;
+ }
+
+ @Override
+ public List<Object[]> getAttributeValueList() {
+ final List<Object[]> attributeValueList = new
ArrayList<>(deviceAttributeValueMap.size());
+ for (final Map<Integer, Object> attributeValueMap :
deviceAttributeValueMap.values()) {
+ final Object[] attributeValues = new
Object[attributeColumnNameList.size()];
+ Arrays.fill(attributeValues, Constants.NONE);
+ attributeValueMap.forEach((index, value) -> attributeValues[index] =
value);
+ attributeValueList.add(attributeValues);
+ }
+ return attributeValueList;
+ }
+ }
+
+ private static class DeviceIdKey {
+
+ private final Object[] deviceId;
+
+ private DeviceIdKey(final Object[] deviceId) {
+ this.deviceId = (Object[]) deviceId.clone();
+ }
+
+ @Override
+ public boolean equals(final Object object) {
+ return this == object
+ || object instanceof DeviceIdKey
+ && Arrays.equals(deviceId, ((DeviceIdKey) object).deviceId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(deviceId);
+ }
+ }
}