Skip to content

Commit 81be9ce

Browse files
authored
Load: Optimized the partial path split logic in modifications coverage judgment (apache#16212) && Refactored tsFile load IT && Fixed the bug that loading non-exist table which is deleted in file may cause NPE (apache#16217)
* fix * fix * 1-l * ci-fix * refactor * may-final
1 parent 13f84fd commit 81be9ce

File tree

10 files changed

+429
-200
lines changed

10 files changed

+429
-200
lines changed

integration-test/src/main/java/org/apache/iotdb/it/utils/TsFileGenerator.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.apache.iotdb.it.utils;
2121

22+
import org.apache.iotdb.commons.conf.IoTDBConstant;
2223
import org.apache.iotdb.commons.exception.IllegalPathException;
2324
import org.apache.iotdb.commons.path.MeasurementPath;
2425
import org.apache.iotdb.db.storageengine.dataregion.modification.ModEntry;
@@ -30,6 +31,7 @@
3031
import org.apache.tsfile.write.TsFileWriter;
3132
import org.apache.tsfile.write.record.Tablet;
3233
import org.apache.tsfile.write.schema.IMeasurementSchema;
34+
import org.apache.tsfile.write.schema.MeasurementSchema;
3335
import org.slf4j.Logger;
3436
import org.slf4j.LoggerFactory;
3537

@@ -225,6 +227,32 @@ private void generateTEXT(final Tablet tablet, final int column, final int row)
225227
tablet.addValue(row, column, String.format("test point %d", random.nextInt()));
226228
}
227229

230+
public void generateDeletion(final String device) throws IOException, IllegalPathException {
231+
try (final ModificationFile modificationFile =
232+
new ModificationFile(ModificationFile.getExclusiveMods(tsFile), false)) {
233+
modificationFile.write(
234+
new TreeDeletionEntry(
235+
new MeasurementPath(device, IoTDBConstant.ONE_LEVEL_PATH_WILDCARD),
236+
Long.MIN_VALUE,
237+
Long.MAX_VALUE));
238+
device2TimeSet.remove(device);
239+
device2MeasurementSchema.remove(device);
240+
}
241+
}
242+
243+
public void generateDeletion(final String device, final MeasurementSchema measurement)
244+
throws IOException, IllegalPathException {
245+
try (final ModificationFile modificationFile =
246+
new ModificationFile(ModificationFile.getExclusiveMods(tsFile), false)) {
247+
modificationFile.write(
248+
new TreeDeletionEntry(
249+
new MeasurementPath(device, measurement.getMeasurementName()),
250+
Long.MIN_VALUE,
251+
Long.MAX_VALUE));
252+
device2MeasurementSchema.get(device).remove(measurement);
253+
}
254+
}
255+
228256
public void generateDeletion(final String device, final int number)
229257
throws IOException, IllegalPathException {
230258
try (final ModificationFile modificationFile =

integration-test/src/main/java/org/apache/iotdb/it/utils/TsFileTableGenerator.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,15 @@
1919

2020
package org.apache.iotdb.it.utils;
2121

22+
import org.apache.iotdb.db.storageengine.dataregion.modification.DeletionPredicate;
23+
import org.apache.iotdb.db.storageengine.dataregion.modification.ModificationFile;
24+
import org.apache.iotdb.db.storageengine.dataregion.modification.TableDeletionEntry;
25+
2226
import org.apache.tsfile.enums.ColumnCategory;
2327
import org.apache.tsfile.enums.TSDataType;
2428
import org.apache.tsfile.exception.write.WriteProcessException;
2529
import org.apache.tsfile.file.metadata.TableSchema;
30+
import org.apache.tsfile.read.common.TimeRange;
2631
import org.apache.tsfile.write.TsFileWriter;
2732
import org.apache.tsfile.write.record.Tablet;
2833
import org.apache.tsfile.write.schema.IMeasurementSchema;
@@ -173,11 +178,13 @@ private void generateTEXT(final Tablet tablet, final int column, final int row)
173178
tablet.addValue(row, column, String.format("test point %d", random.nextInt()));
174179
}
175180

176-
public long getTotalNumber() {
177-
return table2TimeSet.entrySet().stream()
178-
.mapToInt(
179-
entry -> entry.getValue().size() * table2MeasurementSchema.get(entry.getKey()).size())
180-
.sum();
181+
public void generateDeletion(final String table) throws IOException {
182+
try (final ModificationFile modificationFile =
183+
new ModificationFile(ModificationFile.getExclusiveMods(tsFile), false)) {
184+
modificationFile.write(
185+
new TableDeletionEntry(
186+
new DeletionPredicate(table), new TimeRange(Long.MIN_VALUE, Long.MAX_VALUE)));
187+
}
181188
}
182189

183190
@Override

integration-test/src/test/java/org/apache/iotdb/db/it/IoTDBLoadTsFileIT.java

Lines changed: 15 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,14 @@
2121

2222
import org.apache.iotdb.commons.auth.entity.PrivilegeType;
2323
import org.apache.iotdb.commons.schema.column.ColumnHeaderConstant;
24+
import org.apache.iotdb.db.it.utils.TestUtils;
2425
import org.apache.iotdb.it.env.EnvFactory;
2526
import org.apache.iotdb.it.framework.IoTDBTestRunner;
2627
import org.apache.iotdb.it.utils.TsFileGenerator;
27-
import org.apache.iotdb.it.utils.TsFileTableGenerator;
2828
import org.apache.iotdb.itbase.category.ClusterIT;
2929
import org.apache.iotdb.itbase.category.LocalStandaloneIT;
30-
import org.apache.iotdb.itbase.env.BaseEnv;
3130
import org.apache.iotdb.jdbc.IoTDBSQLException;
3231

33-
import org.apache.tsfile.enums.ColumnCategory;
3432
import org.apache.tsfile.enums.TSDataType;
3533
import org.apache.tsfile.file.metadata.enums.TSEncoding;
3634
import org.apache.tsfile.read.common.Path;
@@ -107,8 +105,8 @@ private void registerSchema() throws SQLException {
107105
try (final Connection connection = EnvFactory.getEnv().getConnection();
108106
final Statement statement = connection.createStatement()) {
109107

110-
statement.execute("CREATE DATABASE " + SchemaConfig.STORAGE_GROUP_0);
111-
statement.execute("CREATE DATABASE " + SchemaConfig.STORAGE_GROUP_1);
108+
statement.execute("CREATE DATABASE " + SchemaConfig.DATABASE_0);
109+
statement.execute("CREATE DATABASE " + SchemaConfig.DATABASE_1);
112110

113111
statement.execute(convert2SQL(SchemaConfig.DEVICE_0, SchemaConfig.MEASUREMENT_00));
114112
statement.execute(convert2SQL(SchemaConfig.DEVICE_0, SchemaConfig.MEASUREMENT_01));
@@ -163,8 +161,8 @@ private void deleteSG() throws SQLException {
163161
try (final Connection connection = EnvFactory.getEnv().getConnection();
164162
final Statement statement = connection.createStatement()) {
165163

166-
statement.execute(String.format("delete database %s", SchemaConfig.STORAGE_GROUP_0));
167-
statement.execute(String.format("delete database %s", SchemaConfig.STORAGE_GROUP_1));
164+
statement.execute(String.format("delete database %s", SchemaConfig.DATABASE_0));
165+
statement.execute(String.format("delete database %s", SchemaConfig.DATABASE_1));
168166
} catch (final IoTDBSQLException ignored) {
169167
}
170168
}
@@ -702,16 +700,19 @@ public void testLoadWithMods() throws Exception {
702700
generator.registerTimeseries(
703701
SchemaConfig.DEVICE_3, Collections.singletonList(SchemaConfig.MEASUREMENT_30));
704702
generator.registerAlignedTimeseries(
705-
SchemaConfig.DEVICE_4, Collections.singletonList(SchemaConfig.MEASUREMENT_40));
703+
SchemaConfig.DEVICE_4,
704+
new ArrayList<>(Arrays.asList(SchemaConfig.MEASUREMENT_30, SchemaConfig.MEASUREMENT_40)));
706705
generator.generateData(SchemaConfig.DEVICE_2, 100, PARTITION_INTERVAL / 10_000, false);
707706
generator.generateData(SchemaConfig.DEVICE_3, 100, PARTITION_INTERVAL / 10_000, false);
707+
generator.generateDeletion(SchemaConfig.DEVICE_3);
708708
generator.generateData(SchemaConfig.DEVICE_4, 100, PARTITION_INTERVAL / 10_000, true);
709709
generator.generateDeletion(SchemaConfig.DEVICE_2, 2);
710710
generator.generateDeletion(SchemaConfig.DEVICE_4, 2);
711711
generator.generateData(SchemaConfig.DEVICE_2, 100, PARTITION_INTERVAL / 10_000, false);
712712
generator.generateData(SchemaConfig.DEVICE_4, 100, PARTITION_INTERVAL / 10_000, true);
713713
generator.generateDeletion(SchemaConfig.DEVICE_2, 2);
714714
generator.generateDeletion(SchemaConfig.DEVICE_4, 2);
715+
generator.generateDeletion(SchemaConfig.DEVICE_4, SchemaConfig.MEASUREMENT_30);
715716
writtenPoint2 = generator.getTotalNumber();
716717
}
717718

@@ -731,6 +732,10 @@ public void testLoadWithMods() throws Exception {
731732
Assert.fail("This ResultSet is empty.");
732733
}
733734
}
735+
736+
TestUtils.assertSingleResultSetEqual(
737+
TestUtils.executeQueryWithRetry(statement, "count timeSeries root.sg.**"),
738+
Collections.singletonMap("count(timeseries)", "18"));
734739
}
735740
}
736741

@@ -891,139 +896,9 @@ public void testLoadWithConvertOnTypeMismatchForTreeModel() throws Exception {
891896
return pairs;
892897
}
893898

894-
@Test
895-
public void testLoadWithEmptyDatabaseForTableModel() throws Exception {
896-
final int lineCount = 10000;
897-
898-
final List<Pair<MeasurementSchema, MeasurementSchema>> measurementSchemas =
899-
generateMeasurementSchemasForDataTypeConvertion();
900-
final List<ColumnCategory> columnCategories =
901-
generateTabletColumnCategory(0, measurementSchemas.size());
902-
903-
final File file = new File(tmpDir, "1-0-0-0.tsfile");
904-
905-
final List<IMeasurementSchema> schemaList =
906-
measurementSchemas.stream().map(pair -> pair.right).collect(Collectors.toList());
907-
908-
try (final TsFileTableGenerator generator = new TsFileTableGenerator(file)) {
909-
generator.registerTable(SchemaConfig.TABLE_0, schemaList, columnCategories);
910-
911-
generator.generateData(SchemaConfig.TABLE_0, lineCount, PARTITION_INTERVAL / 10_000);
912-
}
913-
914-
// Prepare normal user
915-
try (final Connection adminCon = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
916-
final Statement adminStmt = adminCon.createStatement()) {
917-
adminStmt.execute("create user test 'password123456'");
918-
adminStmt.execute(
919-
String.format(
920-
"grant create, insert on %s.%s to user test",
921-
SchemaConfig.DATABASE_0, SchemaConfig.TABLE_0));
922-
923-
// auto-create table
924-
adminStmt.execute(String.format("create database if not exists %s", SchemaConfig.DATABASE_0));
925-
}
926-
927-
try (final Connection connection =
928-
EnvFactory.getEnv().getConnection("test", "password123456", BaseEnv.TABLE_SQL_DIALECT);
929-
final Statement statement = connection.createStatement()) {
930-
statement.execute(String.format("use %s", SchemaConfig.DATABASE_0));
931-
statement.execute(String.format("load '%s'", file.getAbsolutePath()));
932-
}
933-
934-
try (final Connection adminCon = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
935-
final Statement adminStmt = adminCon.createStatement()) {
936-
adminStmt.execute(String.format("use %s", SchemaConfig.DATABASE_0));
937-
try (final ResultSet resultSet =
938-
adminStmt.executeQuery(String.format("select count(*) from %s", SchemaConfig.TABLE_0))) {
939-
if (resultSet.next()) {
940-
Assert.assertEquals(lineCount, resultSet.getLong(1));
941-
} else {
942-
Assert.fail("This ResultSet is empty.");
943-
}
944-
}
945-
}
946-
}
947-
948-
@Test
949-
@Ignore("Load with conversion is currently banned")
950-
public void testLoadWithConvertOnTypeMismatchForTableModel() throws Exception {
951-
final int lineCount = 10000;
952-
953-
List<Pair<MeasurementSchema, MeasurementSchema>> measurementSchemas =
954-
generateMeasurementSchemasForDataTypeConvertion();
955-
List<ColumnCategory> columnCategories =
956-
generateTabletColumnCategory(0, measurementSchemas.size());
957-
958-
final File file = new File(tmpDir, "1-0-0-0.tsfile");
959-
960-
List<MeasurementSchema> schemaList1 =
961-
measurementSchemas.stream().map(pair -> pair.left).collect(Collectors.toList());
962-
List<IMeasurementSchema> schemaList2 =
963-
measurementSchemas.stream().map(pair -> pair.right).collect(Collectors.toList());
964-
965-
try (final TsFileTableGenerator generator = new TsFileTableGenerator(file)) {
966-
generator.registerTable(SchemaConfig.TABLE_0, schemaList2, columnCategories);
967-
968-
generator.generateData(SchemaConfig.TABLE_0, lineCount, PARTITION_INTERVAL / 10_000);
969-
}
970-
971-
try (final Connection connection =
972-
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
973-
final Statement statement = connection.createStatement()) {
974-
statement.execute(String.format("create database if not exists %s", SchemaConfig.DATABASE_0));
975-
statement.execute(String.format("use %s", SchemaConfig.DATABASE_0));
976-
statement.execute(convert2TableSQL(SchemaConfig.TABLE_0, schemaList1, columnCategories));
977-
statement.execute(
978-
String.format(
979-
"load '%s' with ('database'='%s')", file.getAbsolutePath(), SchemaConfig.DATABASE_0));
980-
try (final ResultSet resultSet =
981-
statement.executeQuery(String.format("select count(*) from %s", SchemaConfig.TABLE_0))) {
982-
if (resultSet.next()) {
983-
Assert.assertEquals(lineCount, resultSet.getLong(1));
984-
} else {
985-
Assert.fail("This ResultSet is empty.");
986-
}
987-
}
988-
}
989-
}
990-
991-
private List<ColumnCategory> generateTabletColumnCategory(int tagNum, int filedNum) {
992-
List<ColumnCategory> columnTypes = new ArrayList<>(tagNum + filedNum);
993-
for (int i = 0; i < tagNum; i++) {
994-
columnTypes.add(ColumnCategory.TAG);
995-
}
996-
for (int i = 0; i < filedNum; i++) {
997-
columnTypes.add(ColumnCategory.FIELD);
998-
}
999-
return columnTypes;
1000-
}
1001-
1002-
private String convert2TableSQL(
1003-
final String tableName,
1004-
final List<MeasurementSchema> schemaList,
1005-
final List<ColumnCategory> columnCategoryList) {
1006-
List<String> columns = new ArrayList<>();
1007-
for (int i = 0; i < schemaList.size(); i++) {
1008-
final MeasurementSchema measurement = schemaList.get(i);
1009-
columns.add(
1010-
String.format(
1011-
"%s %s %s",
1012-
measurement.getMeasurementName(),
1013-
measurement.getType(),
1014-
columnCategoryList.get(i).name()));
1015-
}
1016-
String tableCreation =
1017-
String.format("create table %s(%s)", tableName, String.join(", ", columns));
1018-
LOGGER.info("schema execute: {}", tableCreation);
1019-
return tableCreation;
1020-
}
1021-
1022899
private static class SchemaConfig {
1023-
private static final String DATABASE_0 = "root";
1024-
private static final String TABLE_0 = "test";
1025-
private static final String STORAGE_GROUP_0 = "root.sg.test_0";
1026-
private static final String STORAGE_GROUP_1 = "root.sg.test_1";
900+
private static final String DATABASE_0 = "root.sg.test_0";
901+
private static final String DATABASE_1 = "root.sg.test_1";
1027902

1028903
// device 0, nonaligned, sg 0
1029904
private static final String DEVICE_0 = "root.sg.test_0.d_0";

0 commit comments

Comments
 (0)