Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,24 @@ public void testDeleteDataByAttributeFilterWithoutTagColumns() throws SQLExcepti
+ "(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'");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,15 @@
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 {
Expand Down Expand Up @@ -100,10 +104,26 @@

@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(
Expand Down Expand Up @@ -157,4 +177,97 @@
}
};
}

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();

Check warning on line 258 in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRows.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this unnecessary cast to "Object[]".

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ9GoUku9pQIW-QdRLol&open=AZ9GoUku9pQIW-QdRLol&pullRequest=18176
}

@Override
public boolean equals(final Object object) {
return this == object
|| object instanceof DeviceIdKey

Check warning on line 264 in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/InsertRows.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this instanceof check and cast with 'instanceof DeviceIdKey deviceidkey'

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ9GoUku9pQIW-QdRLom&open=AZ9GoUku9pQIW-QdRLom&pullRequest=18176
&& Arrays.equals(deviceId, ((DeviceIdKey) object).deviceId);
}

@Override
public int hashCode() {
return Arrays.hashCode(deviceId);
}
}
}
Loading