diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/ITableDeviceSchemaValidation.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/ITableDeviceSchemaValidation.java new file mode 100644 index 0000000000000..60ca965e632d6 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/ITableDeviceSchemaValidation.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.iotdb.db.queryengine.plan.relational.metadata; + +import java.util.List; + +/** + * This class acts as a request for device schema validation and defines the necessary information + * interfaces. + * + *

e.g. {database"db", "t1", [["hebei", "p_1", "t_1"], ["shandong", null, "t_1"]], ["attr_1", + * "attr_2"], [["attr_value1", "attr_value2"], ["v_1", null]]} + * + *

    + *
  1. database = "db" + *
  2. tableName = "t1" + *
  3. deviceIdList = [["hebei", "p_1", "t_1"], ["shandong", null, "t_1"]] + *
  4. attributeColumnNameList = ["attr_1", "attr_2"] + *
  5. attributeValueList = [["attr_value1", "attr_value2"], ["v_1", null]] + *
+ */ +public interface ITableDeviceSchemaValidation { + + /** + * @return database name + */ + String getDatabase(); + + /** + * @return table name without database name as prefix + */ + String getTableName(); + + /** + * @return ids, without db or table name, of all involved devices + */ + List getDeviceIdList(); + + /** + * @return attribute column names + */ + List getAttributeColumnNameList(); + + /** + * @return attribute values, the order of which shall be consistent with that of the provided + * device ids and attribute column names. + */ + List getAttributeValueList(); +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java index f37aabbce8bb8..dc66581b74c2c 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/Metadata.java @@ -19,6 +19,7 @@ package org.apache.iotdb.db.queryengine.plan.relational.metadata; +import org.apache.iotdb.db.queryengine.common.MPPQueryContext; import org.apache.iotdb.db.queryengine.common.SessionInfo; import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType; import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl; @@ -67,4 +68,33 @@ List indexScan( QualifiedObjectName tableName, List expressionList, List attributeColumns); + + /** + * This method is used for table column validation and should be invoked before device validation. + * + *

This method return all the existing column schemas in the target table. + * + *

When table or column is missing, this method will execute auto creation. + * + *

When using SQL, the columnSchemaList could be null and there won't be any validation. + * + *

When the input dataType or category of one column is null, the column cannot be auto + * created. + * + *

If validation failed, a SemanticException will be thrown. + */ + TableSchema validateTableHeaderSchema( + String database, TableSchema tableSchema, MPPQueryContext context); + + /** + * This method is used for table device validation and should be invoked after column validation. + * + *

When device id is missing, this method will execute auto creation. + * + *

When device attribute is missing or different from that stored in IoTDB, the attribute will + * be auto upsert. + * + *

If validation failed, a SemanticException will be thrown. + */ + void validateDeviceSchema(ITableDeviceSchemaValidation schemaValidation, MPPQueryContext context); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java index 1c897c9646ef1..67f030ede35f6 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/TableMetadataImpl.java @@ -22,6 +22,7 @@ import org.apache.iotdb.commons.udf.builtin.BuiltinAggregationFunction; import org.apache.iotdb.commons.udf.builtin.BuiltinScalarFunction; import org.apache.iotdb.db.exception.sql.SemanticException; +import org.apache.iotdb.db.queryengine.common.MPPQueryContext; import org.apache.iotdb.db.queryengine.common.SessionInfo; import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType; import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl; @@ -275,6 +276,18 @@ public List indexScan( return result; } + @Override + public TableSchema validateTableHeaderSchema( + String database, TableSchema tableSchema, MPPQueryContext context) { + throw new UnsupportedOperationException(); + } + + @Override + public void validateDeviceSchema( + ITableDeviceSchemaValidation schemaValidation, MPPQueryContext context) { + throw new UnsupportedOperationException(); + } + public static boolean isTwoNumericType(List argumentTypes) { return argumentTypes.size() == 2 && isNumericType(argumentTypes.get(0)) diff --git a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java index c8eec5486c045..585898e2b089e 100644 --- a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java +++ b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/TestMatadata.java @@ -16,11 +16,13 @@ import org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory; import org.apache.iotdb.commons.udf.builtin.BuiltinAggregationFunction; +import org.apache.iotdb.db.queryengine.common.MPPQueryContext; import org.apache.iotdb.db.queryengine.common.SessionInfo; import org.apache.iotdb.db.queryengine.plan.relational.function.OperatorType; import org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnMetadata; import org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnSchema; import org.apache.iotdb.db.queryengine.plan.relational.metadata.DeviceEntry; +import org.apache.iotdb.db.queryengine.plan.relational.metadata.ITableDeviceSchemaValidation; import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata; import org.apache.iotdb.db.queryengine.plan.relational.metadata.OperatorNotFoundException; import org.apache.iotdb.db.queryengine.plan.relational.metadata.QualifiedObjectName; @@ -184,6 +186,18 @@ public List indexScan( Arrays.asList("a1", "a2"))); } + @Override + public TableSchema validateTableHeaderSchema( + String database, TableSchema tableSchema, MPPQueryContext context) { + throw new UnsupportedOperationException(); + } + + @Override + public void validateDeviceSchema( + ITableDeviceSchemaValidation schemaValidation, MPPQueryContext context) { + throw new UnsupportedOperationException(); + } + public static boolean isTwoNumericType(List argumentTypes) { return argumentTypes.size() == 2 && isNumericType(argumentTypes.get(0))