From c55dd26e9c9eee9e2e31fd53302d2c21d6f19356 Mon Sep 17 00:00:00 2001 From: Tian Jiang Date: Wed, 15 Jan 2025 09:36:46 +0800 Subject: [PATCH 1/5] Allow to write time column only --- .../it/db/it/IoTDBInsertTableIT.java | 11 +++--- .../it/session/IoTDBSessionRelationalIT.java | 34 +++++++++++++++++++ .../org/apache/iotdb/session/Session.java | 11 ++++-- .../thrift/impl/ClientRPCServiceImpl.java | 2 +- .../planner/plan/node/write/InsertNode.java | 2 ++ .../plan/node/write/InsertRowNode.java | 3 ++ .../node/write/RelationalInsertRowNode.java | 8 +++++ .../write/RelationalInsertTabletNode.java | 8 +++++ .../fetcher/TableHeaderSchemaValidator.java | 4 --- .../plan/relational/sql/ast/InsertRows.java | 3 ++ .../statement/crud/InsertBaseStatement.java | 28 ++++++++++----- .../statement/crud/InsertRowStatement.java | 3 ++ .../dataregion/memtable/AbstractMemTable.java | 24 ++++++------- 13 files changed, 104 insertions(+), 37 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java index e751ab6423f24..4cd25e67a26f0 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java @@ -875,13 +875,7 @@ public void testInsertSingleColumn() throws SQLException { // only tag st1.execute("insert into sg21(tag1) values('1')"); // only time - try { - st1.execute("insert into sg21(time) values(1)"); - } catch (SQLException e) { - assertEquals( - "305: [INTERNAL_SERVER_ERROR(305)] Exception occurred: \"insert into sg21(time) values(1)\". executeStatement failed. No column other than Time present, please check the request", - e.getMessage()); - } + st1.execute("insert into sg21(time) values(1)"); // only attribute st1.execute("insert into sg21(ss1) values('1')"); // only field @@ -897,6 +891,9 @@ public void testInsertSingleColumn() throws SQLException { assertFalse(rs1.next()); rs1 = st1.executeQuery("select time, ss1, ss2 from sg21 order by time"); + assertTrue(rs1.next()); + assertEquals(1, rs1.getLong("time")); + assertTrue(rs1.next()); rs1.getString("ss1"); assertTrue(rs1.wasNull()); diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/session/IoTDBSessionRelationalIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/session/IoTDBSessionRelationalIT.java index 1f70341892b3d..4a0984fef4ba8 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/session/IoTDBSessionRelationalIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/session/IoTDBSessionRelationalIT.java @@ -580,6 +580,40 @@ public void insertRelationalTabletTest() } } + @Test + public void insertTimeOnlyTest() throws IoTDBConnectionException, StatementExecutionException { + try (ITableSession session = EnvFactory.getEnv().getTableSessionConnection()) { + session.executeNonQueryStatement("USE \"db1\""); + session.executeNonQueryStatement("CREATE TABLE IF NOT EXISTS time_only (time time)"); + + List schemaList = Collections.emptyList(); + final List columnTypes = Collections.emptyList(); + + Tablet tablet = + new Tablet( + "time_only", + IMeasurementSchema.getMeasurementNameList(schemaList), + IMeasurementSchema.getDataTypeList(schemaList), + columnTypes); + + long timestamp = 0; + for (int row = 0; row < 10; row++) { + tablet.addTimestamp(row, timestamp++); + } + session.insert(tablet); + tablet.reset(); + + for (int i = 0; i < 10; i++) { + session.executeNonQueryStatement( + String.format("INSERT INTO time_only (time) VALUES (%d)", timestamp++)); + } + + SessionDataSet dataSet = session.executeQueryStatement("select count(time) from time_only"); + RowRecord rec = dataSet.next(); + assertEquals(20, rec.getFields().get(0).getLongV()); + } + } + @Test public void insertRelationalTabletWithCacheLeaderTest() throws IoTDBConnectionException, StatementExecutionException { diff --git a/iotdb-client/session/src/main/java/org/apache/iotdb/session/Session.java b/iotdb-client/session/src/main/java/org/apache/iotdb/session/Session.java index 1e65be39082f6..c775e7d89a214 100644 --- a/iotdb-client/session/src/main/java/org/apache/iotdb/session/Session.java +++ b/iotdb-client/session/src/main/java/org/apache/iotdb/session/Session.java @@ -2959,9 +2959,14 @@ private TSInsertTabletReq genTSInsertTabletReq(Tablet tablet, boolean sorted, bo TSInsertTabletReq request = new TSInsertTabletReq(); - for (IMeasurementSchema measurementSchema : tablet.getSchemas()) { - request.addToMeasurements(measurementSchema.getMeasurementName()); - request.addToTypes(measurementSchema.getType().ordinal()); + if (tablet.getSchemas().isEmpty()) { + request.measurements = Collections.emptyList(); + request.types = Collections.emptyList(); + } else { + for (IMeasurementSchema measurementSchema : tablet.getSchemas()) { + request.addToMeasurements(measurementSchema.getMeasurementName()); + request.addToTypes(measurementSchema.getType().ordinal()); + } } request.setPrefixPath(tablet.getDeviceId()); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java index 506b962daf54f..97aaaef68018c 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java @@ -2212,7 +2212,7 @@ public TSStatus insertTablet(TSInsertTabletReq req) { // Step 1: transfer from TSInsertTabletReq to Statement InsertTabletStatement statement = StatementGenerator.createStatement(req); // return success when this statement is empty because server doesn't need to execute it - if (statement.isEmpty()) { + if (statement.isEmpty() && !req.isWriteToTable()) { return RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/InsertNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/InsertNode.java index 06ba52e78b3f8..cb10be48465ea 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/InsertNode.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/InsertNode.java @@ -382,6 +382,8 @@ public void setColumnCategories(TsTableColumnCategory[] columnCategories) { idColumnIndices.add(i); } } + } else { + idColumnIndices = Collections.emptyList(); } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/InsertRowNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/InsertRowNode.java index ffd51f2238411..a5d35b7fffc9e 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/InsertRowNode.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/InsertRowNode.java @@ -155,6 +155,9 @@ public List getOutputColumnNames() { @Override public TSDataType[] getDataTypes() { if (isNeedInferType) { + if (dataTypes == null) { + return new TSDataType[0]; + } TSDataType[] predictedDataTypes = new TSDataType[dataTypes.length]; for (int i = 0; i < dataTypes.length; i++) { predictedDataTypes[i] = TypeInferenceUtils.getPredictedDataType(values[i], true); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/RelationalInsertRowNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/RelationalInsertRowNode.java index d4240970386e3..d3bdea90fcc62 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/RelationalInsertRowNode.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/RelationalInsertRowNode.java @@ -246,4 +246,12 @@ public void updateLastCache(String databaseName) { TableDeviceSchemaCache.getInstance() .updateLastCacheIfExists(databaseName, getDeviceID(), rawMeasurements, timeValuePairs); } + + @Override + public boolean allMeasurementFailed() { + if (measurements != null && measurements.length > 0) { + return failedMeasurementNumber >= measurements.length; + } + return false; + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/RelationalInsertTabletNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/RelationalInsertTabletNode.java index 703217434535b..741bf29b83c86 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/RelationalInsertTabletNode.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/RelationalInsertTabletNode.java @@ -372,4 +372,12 @@ public void updateLastCache(String databaseName) { startOffset = endOffset; } } + + @Override + public boolean allMeasurementFailed() { + if (measurements != null && measurements.length > 0) { + return failedMeasurementNumber >= measurements.length; + } + return false; + } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableHeaderSchemaValidator.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableHeaderSchemaValidator.java index 41932c8944d20..0bcd0d800217d 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableHeaderSchemaValidator.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableHeaderSchemaValidator.java @@ -98,10 +98,6 @@ public Optional validateTableHeaderSchema( .takeReadLock(context, SchemaLockType.VALIDATE_VS_DELETION); final List inputColumnList = tableSchema.getColumns(); - if (inputColumnList == null || inputColumnList.isEmpty()) { - throw new IllegalArgumentException( - "No column other than Time present, please check the request"); - } // Get directly if there is a table because we do not want "addColumn" to affect // original writings TsTable table = 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 cdfb4c3c39f3e..73b0448f66272 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 @@ -143,6 +143,9 @@ public List getAttributeColumnNameList() { @Override public List getAttributeValueList() { + if (insertRowStatement.getColumnCategories() == null) { + return Collections.singletonList(new Object[0]); + } List attributeValueList = new ArrayList<>(); for (int i = 0; i < insertRowStatement.getColumnCategories().length; i++) { if (insertRowStatement.getColumnCategories()[i] == TsTableColumnCategory.ATTRIBUTE) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/InsertBaseStatement.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/InsertBaseStatement.java index 34b73b678fccd..1e65a3adfef58 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/InsertBaseStatement.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/InsertBaseStatement.java @@ -309,6 +309,8 @@ public List getIdColumnIndices() { idColumnIndices.add(i); } } + } else if (columnCategories == null) { + return Collections.emptyList(); } return idColumnIndices; } @@ -492,7 +494,18 @@ public void insertColumn(final int pos, final ColumnSchema columnSchema) { throw new ArrayIndexOutOfBoundsException(pos); } - if (measurementSchemas != null) { + String[] tmpMeasurements = new String[measurements.length + 1]; + System.arraycopy(measurements, 0, tmpMeasurements, 0, pos); + tmpMeasurements[pos] = columnSchema.getName(); + System.arraycopy(measurements, pos, tmpMeasurements, pos + 1, measurements.length - pos); + measurements = tmpMeasurements; + + if (measurementSchemas == null) { + measurementSchemas = new MeasurementSchema[measurements.length]; + measurementSchemas[pos] = + new MeasurementSchema( + columnSchema.getName(), InternalTypeManager.getTSDataType(columnSchema.getType())); + } else { final MeasurementSchema[] tmp = new MeasurementSchema[measurementSchemas.length + 1]; System.arraycopy(measurementSchemas, 0, tmp, 0, pos); tmp[pos] = @@ -502,15 +515,9 @@ public void insertColumn(final int pos, final ColumnSchema columnSchema) { measurementSchemas = tmp; } - String[] tmpMeasurements = new String[measurements.length + 1]; - System.arraycopy(measurements, 0, tmpMeasurements, 0, pos); - tmpMeasurements[pos] = columnSchema.getName(); - System.arraycopy(measurements, pos, tmpMeasurements, pos + 1, measurements.length - pos); - measurements = tmpMeasurements; - if (dataTypes == null) { // sql insertion - dataTypes = new TSDataType[measurements.length + 1]; + dataTypes = new TSDataType[measurements.length]; dataTypes[pos] = InternalTypeManager.getTSDataType(columnSchema.getType()); } else { final TSDataType[] tmpTypes = new TSDataType[dataTypes.length + 1]; @@ -521,7 +528,7 @@ public void insertColumn(final int pos, final ColumnSchema columnSchema) { } if (columnCategories == null) { - columnCategories = new TsTableColumnCategory[measurements.length + 1]; + columnCategories = new TsTableColumnCategory[measurements.length]; columnCategories[pos] = columnSchema.getColumnCategory(); } else { final TsTableColumnCategory[] tmpCategories = @@ -599,6 +606,9 @@ public void toLowerCase() { @TableModel public List getAttributeColumnNameList() { + if (getColumnCategories() == null) { + return Collections.emptyList(); + } final List attributeColumnNameList = new ArrayList<>(); for (int i = 0; i < getColumnCategories().length; i++) { if (getColumnCategories()[i] == TsTableColumnCategory.ATTRIBUTE) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/InsertRowStatement.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/InsertRowStatement.java index d33a83b0c326a..3fad4a1510b3b 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/InsertRowStatement.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/InsertRowStatement.java @@ -205,6 +205,9 @@ protected boolean checkAndCastDataType(int columnIndex, TSDataType dataType) { */ @SuppressWarnings("squid:S3776") // Suppress high Cognitive Complexity warning public void transferType(ZoneId zoneId) throws QueryProcessException { + if (measurementSchemas == null) { + return; + } for (int i = 0; i < measurementSchemas.length; i++) { // null when time series doesn't exist diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AbstractMemTable.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AbstractMemTable.java index 027de99166ba6..a52e81cb5394c 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AbstractMemTable.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/AbstractMemTable.java @@ -256,9 +256,7 @@ public int insertAlignedRow(InsertRowNode insertRowNode) { schemaList.add(schema); dataTypes.add(schema.getType()); } - if (schemaList.isEmpty()) { - return 0; - } + memSize += MemUtils.getAlignedRowRecordSize(dataTypes, values, insertRowNode.getColumnCategories()); writeAlignedRow(insertRowNode.getDeviceID(), schemaList, insertRowNode.getTime(), values); @@ -356,18 +354,18 @@ public void writeAlignedTablet( InsertTabletNode insertTabletNode, int start, int end, TSStatus[] results) { List schemaList = new ArrayList<>(); - for (int i = 0; i < insertTabletNode.getMeasurementSchemas().length; i++) { - if (insertTabletNode.getColumns()[i] == null - || (insertTabletNode.getColumnCategories() != null - && insertTabletNode.getColumnCategories()[i] != TsTableColumnCategory.FIELD)) { - schemaList.add(null); - } else { - schemaList.add(insertTabletNode.getMeasurementSchemas()[i]); + if (insertTabletNode.getMeasurementSchemas() != null) { + for (int i = 0; i < insertTabletNode.getMeasurementSchemas().length; i++) { + if (insertTabletNode.getColumns()[i] == null + || (insertTabletNode.getColumnCategories() != null + && insertTabletNode.getColumnCategories()[i] != TsTableColumnCategory.FIELD)) { + schemaList.add(null); + } else { + schemaList.add(insertTabletNode.getMeasurementSchemas()[i]); + } } } - if (schemaList.isEmpty()) { - return; - } + final List> deviceEndOffsetPair = insertTabletNode.splitByDevice(start, end); int splitStart = start; From 79348263936b7314f016b387cdbcdd188fa6f370 Mon Sep 17 00:00:00 2001 From: Tian Jiang Date: Wed, 15 Jan 2025 14:15:02 +0800 Subject: [PATCH 2/5] add it --- .../it/db/it/IoTDBInsertTableIT.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java index 4cd25e67a26f0..b16c10843a138 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java @@ -19,6 +19,7 @@ package org.apache.iotdb.relational.it.db.it; +import org.apache.iotdb.isession.ISession; import org.apache.iotdb.isession.ITableSession; import org.apache.iotdb.isession.SessionDataSet; import org.apache.iotdb.it.env.EnvFactory; @@ -55,6 +56,7 @@ import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -1137,4 +1139,49 @@ private List checkHeader( } return actualIndexToExpectedIndexList; } + + @Test + public void insertTimeOnlyTest() throws IoTDBConnectionException, StatementExecutionException { + try (ISession session = EnvFactory.getEnv().getSessionConnection()) { + + List schemaList = Collections.emptyList(); + final List columnTypes = Collections.emptyList(); + + Tablet tablet = + new Tablet( + "root.sg1.d1", + IMeasurementSchema.getMeasurementNameList(schemaList), + IMeasurementSchema.getDataTypeList(schemaList), + columnTypes); + + long timestamp = 0; + for (int row = 0; row < 10; row++) { + tablet.addTimestamp(row, timestamp++); + } + session.insertTablet(tablet); + tablet.setDeviceId("root.sg1.d2"); + session.insertAlignedTablet(tablet); + tablet.reset(); + + try { + session.executeNonQueryStatement( + String.format("INSERT INTO root.sg1.d3 (time) VALUES (%d)", timestamp++)); + fail("Exception expected"); + } catch (StatementExecutionException e) { + assertEquals( + "701: InsertStatement should contain at least one measurement", e.getMessage()); + } + + try { + session.executeNonQueryStatement( + String.format("INSERT INTO root.sg1.d4 (time) ALIGNED VALUES (%d)", timestamp++)); + } catch (StatementExecutionException e) { + assertEquals( + "701: InsertStatement should contain at least one measurement", e.getMessage()); + } + + SessionDataSet dataSet = session.executeQueryStatement("select count(*) from root.sg1.**"); + assertFalse(dataSet.hasNext()); + } + } } From 6a92c6019a4a518dcf35e95e6cb3746ee5d9ac0a Mon Sep 17 00:00:00 2001 From: Tian Jiang Date: Thu, 16 Jan 2025 18:14:23 +0800 Subject: [PATCH 3/5] move test --- .../it/db/it/IoTDBInsertTableIT.java | 47 ------------------- .../session/it/IoTDBSessionSimpleIT.java | 46 ++++++++++++++++++ 2 files changed, 46 insertions(+), 47 deletions(-) diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java index b16c10843a138..4cd25e67a26f0 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/db/it/IoTDBInsertTableIT.java @@ -19,7 +19,6 @@ package org.apache.iotdb.relational.it.db.it; -import org.apache.iotdb.isession.ISession; import org.apache.iotdb.isession.ITableSession; import org.apache.iotdb.isession.SessionDataSet; import org.apache.iotdb.it.env.EnvFactory; @@ -56,7 +55,6 @@ import java.time.LocalDate; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -1139,49 +1137,4 @@ private List checkHeader( } return actualIndexToExpectedIndexList; } - - @Test - public void insertTimeOnlyTest() throws IoTDBConnectionException, StatementExecutionException { - try (ISession session = EnvFactory.getEnv().getSessionConnection()) { - - List schemaList = Collections.emptyList(); - final List columnTypes = Collections.emptyList(); - - Tablet tablet = - new Tablet( - "root.sg1.d1", - IMeasurementSchema.getMeasurementNameList(schemaList), - IMeasurementSchema.getDataTypeList(schemaList), - columnTypes); - - long timestamp = 0; - for (int row = 0; row < 10; row++) { - tablet.addTimestamp(row, timestamp++); - } - session.insertTablet(tablet); - tablet.setDeviceId("root.sg1.d2"); - session.insertAlignedTablet(tablet); - tablet.reset(); - - try { - session.executeNonQueryStatement( - String.format("INSERT INTO root.sg1.d3 (time) VALUES (%d)", timestamp++)); - fail("Exception expected"); - } catch (StatementExecutionException e) { - assertEquals( - "701: InsertStatement should contain at least one measurement", e.getMessage()); - } - - try { - session.executeNonQueryStatement( - String.format("INSERT INTO root.sg1.d4 (time) ALIGNED VALUES (%d)", timestamp++)); - } catch (StatementExecutionException e) { - assertEquals( - "701: InsertStatement should contain at least one measurement", e.getMessage()); - } - - SessionDataSet dataSet = session.executeQueryStatement("select count(*) from root.sg1.**"); - assertFalse(dataSet.hasNext()); - } - } } diff --git a/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionSimpleIT.java b/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionSimpleIT.java index 4ca5c1fd2e2e1..be4b0c85c7bd0 100644 --- a/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionSimpleIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionSimpleIT.java @@ -43,6 +43,7 @@ import org.apache.tsfile.read.common.RowRecord; import org.apache.tsfile.utils.Binary; import org.apache.tsfile.write.record.Tablet; +import org.apache.tsfile.write.record.Tablet.ColumnCategory; import org.apache.tsfile.write.schema.IMeasurementSchema; import org.apache.tsfile.write.schema.MeasurementSchema; import org.junit.After; @@ -1898,4 +1899,49 @@ public void convertRecordsToTabletsTest() { e.printStackTrace(); } } + + @Test + public void insertTimeOnlyTest() throws IoTDBConnectionException, StatementExecutionException { + try (ISession session = EnvFactory.getEnv().getSessionConnection()) { + + List schemaList = Collections.emptyList(); + final List columnTypes = Collections.emptyList(); + + Tablet tablet = + new Tablet( + "root.sg1.d1", + IMeasurementSchema.getMeasurementNameList(schemaList), + IMeasurementSchema.getDataTypeList(schemaList), + columnTypes); + + long timestamp = 0; + for (int row = 0; row < 10; row++) { + tablet.addTimestamp(row, timestamp++); + } + session.insertTablet(tablet); + tablet.setDeviceId("root.sg1.d2"); + session.insertAlignedTablet(tablet); + tablet.reset(); + + try { + session.executeNonQueryStatement( + String.format("INSERT INTO root.sg1.d3 (time) VALUES (%d)", timestamp++)); + fail("Exception expected"); + } catch (StatementExecutionException e) { + assertEquals( + "701: InsertStatement should contain at least one measurement", e.getMessage()); + } + + try { + session.executeNonQueryStatement( + String.format("INSERT INTO root.sg1.d4 (time) ALIGNED VALUES (%d)", timestamp++)); + } catch (StatementExecutionException e) { + assertEquals( + "701: InsertStatement should contain at least one measurement", e.getMessage()); + } + + SessionDataSet dataSet = session.executeQueryStatement("select count(*) from root.sg1.**"); + assertFalse(dataSet.hasNext()); + } + } } From 7bc6e412512fdd7b4d7b87112ca2c99a644847d1 Mon Sep 17 00:00:00 2001 From: Tian Jiang Date: Thu, 16 Jan 2025 18:33:25 +0800 Subject: [PATCH 4/5] Fix getDataTypes --- .../plan/planner/plan/node/write/InsertRowNode.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/InsertRowNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/InsertRowNode.java index a5d35b7fffc9e..68fa60b103690 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/InsertRowNode.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/write/InsertRowNode.java @@ -154,10 +154,10 @@ public List getOutputColumnNames() { @Override public TSDataType[] getDataTypes() { + if (dataTypes == null) { + dataTypes = new TSDataType[0]; + } if (isNeedInferType) { - if (dataTypes == null) { - return new TSDataType[0]; - } TSDataType[] predictedDataTypes = new TSDataType[dataTypes.length]; for (int i = 0; i < dataTypes.length; i++) { predictedDataTypes[i] = TypeInferenceUtils.getPredictedDataType(values[i], true); From ea9f72676331fa196312b2a243baa73a20e0a9a2 Mon Sep 17 00:00:00 2001 From: Tian Jiang Date: Mon, 10 Feb 2025 11:49:53 +0800 Subject: [PATCH 5/5] move update mod file existence inside --- .../modification/ModificationFile.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/ModificationFile.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/ModificationFile.java index 435f1fe8d3aec..fe2cd16841af1 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/ModificationFile.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/modification/ModificationFile.java @@ -119,13 +119,15 @@ public void write(ModEntry entry) throws IOException { cascadeFile.write(entry); } } + + if (!fileExists) { + fileExists = true; + updateFileNum = 1; + } } finally { lock.writeLock().unlock(); } - if (!fileExists) { - fileExists = true; - updateFileNum = 1; - } + updateModFileMetric(updateFileNum, size); } @@ -152,13 +154,15 @@ public void write(Collection entries) throws IOException { cascadeFile.write(entries); } } + + if (!fileExists) { + updateFileNum = 1; + fileExists = true; + } } finally { lock.writeLock().unlock(); } - if (!fileExists) { - updateFileNum = 1; - fileExists = true; - } + updateModFileMetric(updateFileNum, size); }