This is an automated email from the ASF dual-hosted git repository.
jackietien 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 3e11b7bd7ab Fix status code of category or data type mismatch
3e11b7bd7ab is described below
commit 3e11b7bd7abc077cdcd003dc32db4772d7d22e64
Author: Jiang Tian <[email protected]>
AuthorDate: Thu Aug 22 16:32:42 2024 +0800
Fix status code of category or data type mismatch
---
.../relational/it/db/it/IoTDBInsertTableIT.java | 63 +---------------
.../iotdb/session/it/IoTDBSessionRelationalIT.java | 84 ++++++++++++++++++++++
.../java/org/apache/iotdb/rpc/TSStatusCode.java | 3 +-
.../iotdb/db/exception/sql/SemanticException.java | 8 +++
.../db/queryengine/plan/analyze/AnalyzeUtils.java | 9 ++-
.../fetcher/TableHeaderSchemaValidator.java | 17 ++++-
.../relational/sql/ast/WrappedInsertStatement.java | 21 ++++--
.../plan/statement/crud/InsertRowStatement.java | 4 +-
.../schema/table/column/TsTableColumnSchema.java | 4 ++
9 files changed, 139 insertions(+), 74 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 44924251a36..53dfe7700fe 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
@@ -173,66 +173,6 @@ public class IoTDBInsertTableIT {
}
}
- @Test
- public void testPartialInsertionRestart() throws SQLException {
- try (Connection connection =
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
- Statement statement = connection.createStatement()) {
- statement.execute("USE \"test\"");
- statement.execute("SET CONFIGURATION enable_auto_create_schema='false'");
- statement.execute(
- "create table sg5 (id1 string id, s1 text measurement, s2 double
measurement)");
-
- try {
- statement.execute("INSERT INTO sg5(id1,time,s1,s2) VALUES('d1',
100,'test','test')");
- } catch (SQLException e) {
- // ignore
- }
- } finally {
- try (Connection connection =
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
- Statement statement = connection.createStatement()) {
- statement.execute("SET CONFIGURATION
enable_auto_create_schema='true'");
- }
- }
-
- // TODO: replace restartDaemon() with new methods in Env.
- /*
- long time = 0;
- try {
- EnvironmentUtils.restartDaemon();
- StorageEngine.getInstance().recover();
- // wait for recover
- while (!StorageEngine.getInstance().isAllSgReady()) {
- Thread.sleep(500);
- time += 500;
- if (time > 10000) {
- logger.warn("wait too long in restart, wait for: " + time / 1000 +
"s");
- }
- }
- } catch (Exception e) {
- fail(e.getMessage());
- }
- */
-
- try (Connection connection =
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
- Statement statement = connection.createStatement()) {
- statement.execute("use \"test\"");
-
- try (ResultSet resultSet = statement.executeQuery("SELECT s1 FROM sg5"))
{
- assertNotNull(resultSet);
- int cnt = 0;
- while (resultSet.next()) {
- cnt++;
- assertEquals("test", resultSet.getString("s1"));
- }
- assertEquals(1, cnt);
- }
- try (ResultSet resultSet = statement.executeQuery("SELECT s2 FROM sg5"))
{
- assertNotNull(resultSet);
- assertFalse(resultSet.next());
- }
- }
- }
-
@Test
public void testPartialInsertTablet() {
try (ISession session =
EnvFactory.getEnv().getSessionConnection(BaseEnv.TABLE_SQL_DIALECT)) {
@@ -522,8 +462,7 @@ public class IoTDBInsertTableIT {
st1.execute("insert into wt14(time, s1, s2) values(100, null, 1), (101,
null, 2)");
fail();
} catch (SQLException e) {
- assertTrue(
-
e.getMessage().contains(Integer.toString(TSStatusCode.METADATA_ERROR.getStatusCode())));
+ assertEquals("507: Table wt14 does not exist", e.getMessage());
}
try (Connection connection =
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT)) {
try (Statement st2 = connection.createStatement()) {
diff --git
a/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionRelationalIT.java
b/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionRelationalIT.java
index 8d01cdb15ab..fc7c96daeff 100644
---
a/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionRelationalIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/session/it/IoTDBSessionRelationalIT.java
@@ -344,6 +344,90 @@ public class IoTDBSessionRelationalIT {
}
}
+ @Test
+ @Category({LocalStandaloneIT.class, ClusterIT.class})
+ public void partialInsertSQLTest() throws IoTDBConnectionException,
StatementExecutionException {
+ try (ISession session =
EnvFactory.getEnv().getSessionConnection(TREE_SQL_DIALECT)) {
+ // disable auto-creation only for this test
+ session.executeNonQueryStatement("SET CONFIGURATION
\"enable_auto_create_schema\"=\"false\"");
+ }
+ try (ISession session =
EnvFactory.getEnv().getSessionConnection(TABLE_SQL_DIALECT)) {
+ session.executeNonQueryStatement("USE \"db1\"");
+ // the table is missing column "m2"
+ session.executeNonQueryStatement(
+ "CREATE TABLE table2_2 (id1 string id, attr1 string attribute, "
+ + "m1 double "
+ + "measurement)");
+ try {
+ session.executeNonQueryStatement(
+ "INSERT INTO table2_2 (time, id1, attr1, m1, m2) values (1, '1',
'1', 1.0, 2.0)");
+ fail("Exception expected");
+ } catch (StatementExecutionException e) {
+ assertEquals(
+ "616: Unknown column category for m2. Cannot auto create column.",
e.getMessage());
+ }
+
+ } finally {
+ try (ISession session =
EnvFactory.getEnv().getSessionConnection(TREE_SQL_DIALECT)) {
+ session.executeNonQueryStatement(
+ "SET CONFIGURATION \"enable_auto_create_schema\"=\"true\"");
+ }
+ }
+ }
+
+ @Test
+ @Category({LocalStandaloneIT.class, ClusterIT.class})
+ public void partialInsertRelationalRowFailTest()
+ throws IoTDBConnectionException, StatementExecutionException {
+ try (ISession session =
EnvFactory.getEnv().getSessionConnection(TREE_SQL_DIALECT)) {
+ // disable auto-creation only for this test
+ session.executeNonQueryStatement("SET CONFIGURATION
\"enable_auto_create_schema\"=\"false\"");
+ session.executeNonQueryStatement("SET CONFIGURATION
\"enable_partial_insert\"=\"false\"");
+ }
+ try (ISession session =
EnvFactory.getEnv().getSessionConnection(TABLE_SQL_DIALECT)) {
+ session.executeNonQueryStatement("USE \"db1\"");
+ // the table is missing column "m2"
+ session.executeNonQueryStatement(
+ "CREATE TABLE table2_3 (id1 string id, attr1 string attribute, "
+ + "m1 double "
+ + "measurement)");
+
+ // the insertion contains "m2"
+ List<IMeasurementSchema> schemaList = new ArrayList<>();
+ schemaList.add(new MeasurementSchema("id1", TSDataType.STRING));
+ schemaList.add(new MeasurementSchema("attr1", TSDataType.STRING));
+ schemaList.add(new MeasurementSchema("m1", TSDataType.DOUBLE));
+ schemaList.add(new MeasurementSchema("m2", TSDataType.DOUBLE));
+ final List<ColumnType> columnTypes =
+ Arrays.asList(
+ ColumnType.ID, ColumnType.ATTRIBUTE, ColumnType.MEASUREMENT,
ColumnType.MEASUREMENT);
+ List<String> measurementIds =
+ schemaList.stream()
+ .map(IMeasurementSchema::getMeasurementId)
+ .collect(Collectors.toList());
+ List<TSDataType> dataTypes =
+
schemaList.stream().map(IMeasurementSchema::getType).collect(Collectors.toList());
+
+ Object[] values = new Object[] {"id:" + 1, "attr:" + 1, 1 * 1.0, 1 *
1.0};
+ try {
+ session.insertRelationalRecord(
+ "table2_3", 1, measurementIds, dataTypes, columnTypes, values);
+ fail("Exception expected");
+ } catch (StatementExecutionException e) {
+ assertEquals(
+ "507: Fail to insert measurements [m2] caused by [Column m2 does
not exists or fails to be created]",
+ e.getMessage());
+ }
+
+ } finally {
+ try (ISession session =
EnvFactory.getEnv().getSessionConnection(TREE_SQL_DIALECT)) {
+ session.executeNonQueryStatement(
+ "SET CONFIGURATION \"enable_auto_create_schema\"=\"true\"");
+ session.executeNonQueryStatement("SET CONFIGURATION
\"enable_partial_insert\"=\"true\"");
+ }
+ }
+ }
+
@Test
@Category({LocalStandaloneIT.class, ClusterIT.class})
public void insertRelationalRowTest()
diff --git
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
index cb2e8220e90..53aa7125775 100644
---
a/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
+++
b/iotdb-client/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
@@ -107,8 +107,9 @@ public enum TSStatusCode {
DISK_SPACE_INSUFFICIENT(611),
OVERSIZE_TTL(612),
TTL_CONFIG_ERROR(613),
- COLUMN_TYPE_MISMATCH(614),
+ DATA_TYPE_MISMATCH(614),
COLUMN_CATEGORY_MISMATCH(615),
+ COLUMN_NOT_EXISTS(616),
// Query Engine
SQL_PARSE_ERROR(700),
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/sql/SemanticException.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/sql/SemanticException.java
index 66f3af08e91..630929318c2 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/sql/SemanticException.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/exception/sql/SemanticException.java
@@ -24,6 +24,14 @@ import org.apache.iotdb.rpc.TSStatusCode;
public class SemanticException extends IoTDBRuntimeException {
+ public SemanticException(String message, int statusCode) {
+ super(message, statusCode);
+ }
+
+ public SemanticException(Throwable cause, int statusCode) {
+ super(cause, statusCode);
+ }
+
public SemanticException(String message) {
super(message, TSStatusCode.SEMANTIC_ERROR.getStatusCode());
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeUtils.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeUtils.java
index 8c7d245f113..9d6556b501f 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeUtils.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeUtils.java
@@ -210,7 +210,14 @@ public class AnalyzeUtils {
analysis.setFailStatus(
RpcUtils.getStatus(exception.getErrorCode(),
exception.getMessage()));
} else {
- analysis.setFailStatus(RpcUtils.getStatus(TSStatusCode.METADATA_ERROR,
e.getMessage()));
+ if (e.getErrorCode() != TSStatusCode.SEMANTIC_ERROR.getStatusCode()) {
+ // a specific code has been set, use it
+ analysis.setFailStatus(RpcUtils.getStatus(e.getErrorCode(),
e.getMessage()));
+ } else {
+ // use METADATA_ERROR by default
+ analysis.setFailStatus(
+ RpcUtils.getStatus(TSStatusCode.METADATA_ERROR.getStatusCode(),
e.getMessage()));
+ }
}
} finally {
PERFORMANCE_OVERVIEW_METRICS.recordScheduleSchemaValidateCost(System.nanoTime()
- startTime);
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 3bd069e2a0a..48c95f8c469 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
@@ -54,6 +54,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
import static
org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager.getTSDataType;
import static
org.apache.iotdb.db.utils.EncodingInferenceUtils.getDefaultEncoding;
@@ -119,13 +120,15 @@ public class TableHeaderSchemaValidator {
throw new SemanticException(
String.format(
"Unknown column category for %s. Cannot auto create column.",
- columnSchema.getName()));
+ columnSchema.getName()),
+ TSStatusCode.COLUMN_NOT_EXISTS.getStatusCode());
}
if (columnSchema.getType() == null) {
throw new SemanticException(
String.format(
"Unknown column data type for %s. Cannot auto create
column.",
- columnSchema.getName()));
+ columnSchema.getName()),
+ TSStatusCode.COLUMN_NOT_EXISTS.getStatusCode());
}
missingColumnList.add(columnSchema);
} else {
@@ -136,7 +139,8 @@ public class TableHeaderSchemaValidator {
if (columnSchema.getColumnCategory() != null
&&
!existingColumn.getColumnCategory().equals(columnSchema.getColumnCategory())) {
throw new SemanticException(
- String.format("Wrong category at column %s.",
columnSchema.getName()));
+ String.format("Wrong category at column %s.",
columnSchema.getName()),
+ TSStatusCode.COLUMN_CATEGORY_MISMATCH.getStatusCode());
}
}
}
@@ -148,6 +152,13 @@ public class TableHeaderSchemaValidator {
// check id or attribute column data type in this method
autoCreateColumn(database, tableSchema.getTableName(),
missingColumnList, context);
table = DataNodeTableCache.getInstance().getTable(database,
tableSchema.getTableName());
+ } else if (!missingColumnList.isEmpty()
+ && !IoTDBDescriptor.getInstance().getConfig().isEnablePartialInsert())
{
+ throw new SemanticException(
+ String.format(
+ "Missing columns %s.",
+
missingColumnList.stream().map(ColumnSchema::getName).collect(Collectors.toList())),
+ TSStatusCode.COLUMN_NOT_EXISTS.getStatusCode());
}
table
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/WrappedInsertStatement.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/WrappedInsertStatement.java
index 801ec407b90..b951c02cc49 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/WrappedInsertStatement.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/WrappedInsertStatement.java
@@ -30,6 +30,8 @@ import
org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
import org.apache.iotdb.db.queryengine.plan.relational.metadata.TableSchema;
import
org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager;
import org.apache.iotdb.db.queryengine.plan.statement.crud.InsertBaseStatement;
+import org.apache.iotdb.db.utils.TypeInferenceUtils;
+import org.apache.iotdb.rpc.TSStatusCode;
import org.apache.tsfile.common.conf.TSFileDescriptor;
import org.apache.tsfile.enums.TSDataType;
@@ -77,12 +79,16 @@ public abstract class WrappedInsertStatement extends
WrappedStatement
new ArrayList<>(insertBaseStatement.getMeasurements().length);
for (int i = 0; i < insertBaseStatement.getMeasurements().length; i++) {
if (insertBaseStatement.getMeasurements()[i] != null) {
+ TSDataType dataType = insertBaseStatement.getDataType(i);
+ if (dataType == null) {
+ dataType =
+ TypeInferenceUtils.getPredictedDataType(
+ insertBaseStatement.getFirstValueOfIndex(i), true);
+ }
columnSchemas.add(
new ColumnSchema(
insertBaseStatement.getMeasurements()[i],
- insertBaseStatement.getDataType(i) != null
- ? TypeFactory.getType(insertBaseStatement.getDataType(i))
- : null,
+ dataType != null ? TypeFactory.getType(dataType) : null,
false,
insertBaseStatement.getColumnCategory(i)));
} else {
@@ -159,7 +165,8 @@ public abstract class WrappedInsertStatement extends
WrappedStatement
// the column does not exist and auto-creation is disabled
SemanticException semanticException =
new SemanticException(
- "Column " + incoming.getName() + " does not exists or fails to
be " + "created");
+ "Column " + incoming.getName() + " does not exists or fails to
be " + "created",
+ TSStatusCode.COLUMN_NOT_EXISTS.getStatusCode());
if (incoming.getColumnCategory() != TsTableColumnCategory.MEASUREMENT) {
// non-measurement columns cannot be partially inserted
throw semanticException;
@@ -179,7 +186,8 @@ public abstract class WrappedInsertStatement extends
WrappedStatement
new SemanticException(
String.format(
"Inconsistent data type of column %s: %s/%s",
- incoming.getName(), incoming.getType(), real.getType()));
+ incoming.getName(), incoming.getType(), real.getType()),
+ TSStatusCode.DATA_TYPE_MISMATCH.getStatusCode());
if (incoming.getColumnCategory() != TsTableColumnCategory.MEASUREMENT) {
// non-measurement columns cannot be partially inserted
throw semanticException;
@@ -195,7 +203,8 @@ public abstract class WrappedInsertStatement extends
WrappedStatement
throw new SemanticException(
String.format(
"Inconsistent column category of column %s: %s/%s",
- incoming.getName(), incoming.getColumnCategory(),
real.getColumnCategory()));
+ incoming.getName(), incoming.getColumnCategory(),
real.getColumnCategory()),
+ TSStatusCode.COLUMN_CATEGORY_MISMATCH.getStatusCode());
}
TSDataType tsDataType = InternalTypeManager.getTSDataType(real.getType());
MeasurementSchema measurementSchema =
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 f2fa614fc58..a0b67ba997d 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
@@ -40,6 +40,7 @@ import
org.apache.iotdb.db.queryengine.plan.statement.StatementVisitor;
import org.apache.iotdb.db.utils.CommonUtils;
import org.apache.iotdb.db.utils.TypeInferenceUtils;
import org.apache.iotdb.db.utils.annotations.TableModel;
+import org.apache.iotdb.rpc.TSStatusCode;
import org.apache.tsfile.enums.TSDataType;
import org.apache.tsfile.file.metadata.IDeviceID;
@@ -247,7 +248,8 @@ public class InsertRowStatement extends InsertBaseStatement
implements ISchemaVa
if
(!IoTDBDescriptor.getInstance().getConfig().isEnablePartialInsert()) {
throw e;
} else {
- markFailedMeasurement(i, e);
+ markFailedMeasurement(
+ i, new SemanticException(e,
TSStatusCode.DATA_TYPE_MISMATCH.getStatusCode()));
}
}
}
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/column/TsTableColumnSchema.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/column/TsTableColumnSchema.java
index f1bf80b5a52..af6baf7c043 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/column/TsTableColumnSchema.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/column/TsTableColumnSchema.java
@@ -71,4 +71,8 @@ public abstract class TsTableColumnSchema {
public int hashCode() {
return Objects.hash(columnName);
}
+
+ public void setDataType(TSDataType dataType) {
+ this.dataType = dataType;
+ }
}