You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ja...@apache.org on 2024/06/28 12:37:50 UTC

(iotdb) branch ty/TEXT2STRING created (now 72ba229b592)

This is an automated email from the ASF dual-hosted git repository.

jackietien pushed a change to branch ty/TEXT2STRING
in repository https://gitbox.apache.org/repos/asf/iotdb.git


      at 72ba229b592 Add IT for table management and change type of ID and ATTRIBUTE column from TEXT to STRING

This branch includes the following new commits:

     new 72ba229b592 Add IT for table management and change type of ID and ATTRIBUTE column from TEXT to STRING

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(iotdb) 01/01: Add IT for table management and change type of ID and ATTRIBUTE column from TEXT to STRING

Posted by ja...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jackietien pushed a commit to branch ty/TEXT2STRING
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 72ba229b592bcfa68a979311dac7fc8a0e981f1f
Author: JackieTien97 <ja...@gmail.com>
AuthorDate: Fri Jun 28 20:37:20 2024 +0800

    Add IT for table management and change type of ID and ATTRIBUTE column from TEXT to STRING
---
 .../iotdb/itbase/runtime/ClusterTestStatement.java |  11 +-
 .../relational/it/schema/IoTDBDatabaseIT.java      |   4 +-
 .../iotdb/relational/it/schema/IoTDBTableIT.java   | 203 +++++++++++++++++++++
 .../CnToDnInternalServiceAsyncRequestManager.java  |   5 +
 .../impl/schema/table/CreateTableProcedure.java    |   8 +-
 .../execution/config/TableConfigTaskVisitor.java   |  46 ++++-
 .../config/executor/ClusterConfigTaskExecutor.java |  13 +-
 .../relational/AlterTableAddColumnTask.java        |  14 +-
 .../config/metadata/relational/ShowTablesTask.java |   7 +-
 .../relational/metadata/TableMetadataImpl.java     |   4 +-
 .../db/schemaengine/table/DataNodeTableCache.java  |  10 +-
 .../apache/iotdb/db/utils/ErrorHandlingUtils.java  |   6 +-
 .../plan/relational/analyzer/TestMatadata.java     |  12 +-
 .../apache/iotdb/commons/schema/table/TsTable.java |   4 +
 14 files changed, 310 insertions(+), 37 deletions(-)

diff --git a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestStatement.java b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestStatement.java
index c6b139a3eeb..f8c3e38ea57 100644
--- a/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestStatement.java
+++ b/integration-test/src/main/java/org/apache/iotdb/itbase/runtime/ClusterTestStatement.java
@@ -187,7 +187,16 @@ public class ClusterTestStatement implements Statement {
 
   @Override
   public boolean execute(String sql) throws SQLException {
-    return writeStatement.execute(sql);
+    sql = sql.trim();
+    boolean result = writeStatement.execute(sql);
+    // if use XXXX, sendRequest to all statements
+    if (sql.length() > 4 && "use ".equalsIgnoreCase(sql.substring(0, 4))) {
+      for (Statement readStatement : readStatements) {
+        boolean tmp = readStatement.execute(sql);
+        result = result && tmp;
+      }
+    }
+    return result;
   }
 
   @Override
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java
index d2450039a70..3260d4b27f6 100644
--- a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java
@@ -147,9 +147,9 @@ public class IoTDBDatabaseIT {
       }
       //
       //      // TODO fix it, should succeed
-      statement.execute("create database \"a.b\"");
+      //      statement.execute("create database \"a.b\"");
       //      statement.execute("use \"a.b\"");
-      statement.execute("drop database \"a.b\"");
+      //      statement.execute("drop database \"a.b\"");
 
     } catch (SQLException e) {
       e.printStackTrace();
diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java
index a01741d2cda..d55fc3300fe 100644
--- a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBTableIT.java
@@ -23,12 +23,25 @@ import org.apache.iotdb.it.env.EnvFactory;
 import org.apache.iotdb.it.framework.IoTDBTestRunner;
 import org.apache.iotdb.itbase.category.ClusterIT;
 import org.apache.iotdb.itbase.category.LocalStandaloneIT;
+import org.apache.iotdb.itbase.env.BaseEnv;
 
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
+import org.junit.Test;
 import org.junit.experimental.categories.Category;
 import org.junit.runner.RunWith;
 
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import static org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant.describeTableColumnHeaders;
+import static org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant.showTablesColumnHeaders;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
 @RunWith(IoTDBTestRunner.class)
 @Category({LocalStandaloneIT.class, ClusterIT.class})
 public class IoTDBTableIT {
@@ -42,4 +55,194 @@ public class IoTDBTableIT {
   public static void tearDown() throws Exception {
     EnvFactory.getEnv().cleanClusterEnvironment();
   }
+
+  @Test
+  public void testManageDatabase() {
+    try (Connection connection = EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+
+      statement.execute("create database test1");
+      statement.execute("create database test2");
+
+      // should specify database before create table
+      try {
+        statement.execute(
+            "create table table1(region_id STRING ID, plant_id STRING ID, device_id STRING ID, model STRING ATTRIBUTE, temperature FLOAT MEASUREMENT, humidity DOUBLE MEASUREMENT) with (TTL=3600000)");
+      } catch (SQLException e) {
+        assertEquals("701: database is not specified", e.getMessage());
+      }
+
+      // or use full qualified table name
+      statement.execute(
+          "create table test1.table1(region_id STRING ID, plant_id STRING ID, device_id STRING ID, model STRING ATTRIBUTE, temperature FLOAT MEASUREMENT, humidity DOUBLE MEASUREMENT) with (TTL=3600000)");
+
+      statement.execute("use test2");
+
+      try {
+        statement.execute(
+            "create table table2(region_id TEXT ID, plant_id STRING ID, device_id STRING ID, model STRING ATTRIBUTE, temperature FLOAT MEASUREMENT, humidity DOUBLE MEASUREMENT) with (TTL=3600000)");
+      } catch (SQLException e) {
+        assertEquals(
+            "701: DataType of ID Column should only be STRING, current is TEXT", e.getMessage());
+      }
+
+      try {
+        statement.execute(
+            "create table table2(region_id INT32 ID, plant_id STRING ID, device_id STRING ID, model STRING ATTRIBUTE, temperature FLOAT MEASUREMENT, humidity DOUBLE MEASUREMENT) with (TTL=3600000)");
+      } catch (SQLException e) {
+        assertEquals(
+            "701: DataType of ID Column should only be STRING, current is INT32", e.getMessage());
+      }
+
+      try {
+        statement.execute(
+            "create table table2(region_id STRING ID, plant_id STRING ID, device_id STRING ID, model TEXT ATTRIBUTE, temperature FLOAT MEASUREMENT, humidity DOUBLE MEASUREMENT) with (TTL=3600000)");
+      } catch (SQLException e) {
+        assertEquals(
+            "701: DataType of ATTRIBUTE Column should only be STRING, current is TEXT",
+            e.getMessage());
+      }
+
+      try {
+        statement.execute(
+            "create table table2(region_id STRING ID, plant_id STRING ID, device_id STRING ID, model DOUBLE ATTRIBUTE, temperature FLOAT MEASUREMENT, humidity DOUBLE MEASUREMENT) with (TTL=3600000)");
+      } catch (SQLException e) {
+        assertEquals(
+            "701: DataType of ATTRIBUTE Column should only be STRING, current is DOUBLE",
+            e.getMessage());
+      }
+
+      statement.execute(
+          "create table table2(region_id STRING ID, plant_id STRING ID, color STRING ATTRIBUTE, temperature FLOAT MEASUREMENT, speed DOUBLE MEASUREMENT) with (TTL=6600000)");
+
+      String[] tableNames = new String[] {"table2"};
+      long[] ttls = new long[] {6600000L};
+
+      // show tables from current database
+      try (ResultSet resultSet = statement.executeQuery("SHOW tables")) {
+        int cnt = 0;
+        ResultSetMetaData metaData = resultSet.getMetaData();
+        assertEquals(showTablesColumnHeaders.size(), metaData.getColumnCount());
+        for (int i = 0; i < showTablesColumnHeaders.size(); i++) {
+          assertEquals(
+              showTablesColumnHeaders.get(i).getColumnName(), metaData.getColumnName(i + 1));
+        }
+        while (resultSet.next()) {
+          assertEquals(tableNames[cnt], resultSet.getString(1));
+          assertEquals(ttls[cnt], resultSet.getInt(2));
+          cnt++;
+        }
+        assertEquals(tableNames.length, cnt);
+      }
+
+      // show tables by specifying another database
+      tableNames = new String[] {"table1"};
+      ttls = new long[] {3600000L};
+
+      // using SHOW tables in
+      try (ResultSet resultSet = statement.executeQuery("SHOW tables in test1")) {
+        int cnt = 0;
+        ResultSetMetaData metaData = resultSet.getMetaData();
+        assertEquals(showTablesColumnHeaders.size(), metaData.getColumnCount());
+        for (int i = 0; i < showTablesColumnHeaders.size(); i++) {
+          assertEquals(
+              showTablesColumnHeaders.get(i).getColumnName(), metaData.getColumnName(i + 1));
+        }
+        while (resultSet.next()) {
+          assertEquals(tableNames[cnt], resultSet.getString(1));
+          assertEquals(ttls[cnt], resultSet.getInt(2));
+          cnt++;
+        }
+        assertEquals(tableNames.length, cnt);
+      }
+
+      // using SHOW tables from
+      try (ResultSet resultSet = statement.executeQuery("SHOW tables from test1")) {
+        int cnt = 0;
+        ResultSetMetaData metaData = resultSet.getMetaData();
+        assertEquals(showTablesColumnHeaders.size(), metaData.getColumnCount());
+        for (int i = 0; i < showTablesColumnHeaders.size(); i++) {
+          assertEquals(
+              showTablesColumnHeaders.get(i).getColumnName(), metaData.getColumnName(i + 1));
+        }
+        while (resultSet.next()) {
+          assertEquals(tableNames[cnt], resultSet.getString(1));
+          assertEquals(ttls[cnt], resultSet.getInt(2));
+          cnt++;
+        }
+        assertEquals(tableNames.length, cnt);
+      }
+
+      // show tables from a non-exist database
+      try {
+        statement.executeQuery("SHOW tables from test3");
+      } catch (SQLException e) {
+        assertEquals("500: Database test3 doesn't exists.", e.getMessage());
+      }
+
+      // describe
+      try {
+        statement.executeQuery("describe table1");
+      } catch (SQLException e) {
+        assertEquals("550: Table test2.table1 not exists.", e.getMessage());
+      }
+
+      String[] columnNames =
+          new String[] {
+            "Time", "region_id", "plant_id", "device_id", "model", "temperature", "humidity"
+          };
+      String[] dataTypes =
+          new String[] {"INT64", "STRING", "STRING", "STRING", "STRING", "FLOAT", "DOUBLE"};
+      String[] categories =
+          new String[] {"TIME", "ID", "ID", "ID", "ATTRIBUTE", "MEASUREMENT", "MEASUREMENT"};
+
+      try (ResultSet resultSet = statement.executeQuery("describe test1.table1")) {
+        int cnt = 0;
+        ResultSetMetaData metaData = resultSet.getMetaData();
+        assertEquals(describeTableColumnHeaders.size(), metaData.getColumnCount());
+        for (int i = 0; i < describeTableColumnHeaders.size(); i++) {
+          assertEquals(
+              describeTableColumnHeaders.get(i).getColumnName(), metaData.getColumnName(i + 1));
+        }
+        while (resultSet.next()) {
+          assertEquals(columnNames[cnt], resultSet.getString(1));
+          assertEquals(dataTypes[cnt], resultSet.getString(2));
+          assertEquals(categories[cnt], resultSet.getString(3));
+          cnt++;
+        }
+        assertEquals(columnNames.length, cnt);
+      }
+
+      columnNames = new String[] {"Time", "region_id", "plant_id", "color", "temperature", "speed"};
+      dataTypes = new String[] {"INT64", "STRING", "STRING", "STRING", "FLOAT", "DOUBLE"};
+      categories = new String[] {"TIME", "ID", "ID", "ATTRIBUTE", "MEASUREMENT", "MEASUREMENT"};
+
+      try (ResultSet resultSet = statement.executeQuery("desc table2")) {
+        int cnt = 0;
+        ResultSetMetaData metaData = resultSet.getMetaData();
+        assertEquals(describeTableColumnHeaders.size(), metaData.getColumnCount());
+        for (int i = 0; i < describeTableColumnHeaders.size(); i++) {
+          assertEquals(
+              describeTableColumnHeaders.get(i).getColumnName(), metaData.getColumnName(i + 1));
+        }
+        while (resultSet.next()) {
+          assertEquals(columnNames[cnt], resultSet.getString(1));
+          assertEquals(dataTypes[cnt], resultSet.getString(2));
+          assertEquals(categories[cnt], resultSet.getString(3));
+          cnt++;
+        }
+        assertEquals(columnNames.length, cnt);
+      }
+
+      try {
+        statement.executeQuery("describe test3.table3");
+      } catch (SQLException e) {
+        assertEquals("550: Table test3.table3 not exists.", e.getMessage());
+      }
+
+    } catch (SQLException e) {
+      e.printStackTrace();
+      fail(e.getMessage());
+    }
+  }
 }
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/CnToDnInternalServiceAsyncRequestManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/CnToDnInternalServiceAsyncRequestManager.java
index 8f3e7c720fc..020cb503cce 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/CnToDnInternalServiceAsyncRequestManager.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/client/async/CnToDnInternalServiceAsyncRequestManager.java
@@ -82,6 +82,7 @@ import org.apache.iotdb.mpp.rpc.thrift.TResetPeerListReq;
 import org.apache.iotdb.mpp.rpc.thrift.TRollbackSchemaBlackListReq;
 import org.apache.iotdb.mpp.rpc.thrift.TRollbackSchemaBlackListWithTemplateReq;
 import org.apache.iotdb.mpp.rpc.thrift.TRollbackViewSchemaBlackListReq;
+import org.apache.iotdb.mpp.rpc.thrift.TUpdateTableReq;
 import org.apache.iotdb.mpp.rpc.thrift.TUpdateTemplateReq;
 import org.apache.iotdb.mpp.rpc.thrift.TUpdateTriggerLocationReq;
 
@@ -350,6 +351,10 @@ public class CnToDnInternalServiceAsyncRequestManager
         CnToDnRequestType.TEST_CONNECTION,
         (req, client, handler) ->
             client.testConnectionEmptyRPC((DataNodeTSStatusRPCHandler) handler));
+    actionMapBuilder.put(
+        CnToDnRequestType.UPDATE_TABLE,
+        (req, client, handler) ->
+            client.updateTable((TUpdateTableReq) req, (DataNodeTSStatusRPCHandler) handler));
   }
 
   @Override
diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/CreateTableProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/CreateTableProcedure.java
index 29dade50ca4..f3b48bb544e 100644
--- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/CreateTableProcedure.java
+++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/table/CreateTableProcedure.java
@@ -23,7 +23,6 @@ import org.apache.iotdb.common.rpc.thrift.TConsensusGroupId;
 import org.apache.iotdb.common.rpc.thrift.TDataNodeLocation;
 import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet;
 import org.apache.iotdb.common.rpc.thrift.TSStatus;
-import org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.exception.IoTDBException;
 import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.commons.path.PartialPath;
@@ -66,7 +65,6 @@ import java.util.Objects;
 import java.util.Set;
 
 import static org.apache.iotdb.commons.conf.IoTDBConstant.MULTI_LEVEL_PATH_WILDCARD;
-import static org.apache.iotdb.commons.conf.IoTDBConstant.PATH_SEPARATOR;
 import static org.apache.iotdb.commons.schema.SchemaConstant.ROOT;
 
 public class CreateTableProcedure
@@ -177,12 +175,12 @@ public class CreateTableProcedure
     DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream);
     PartialPath path = null;
     try {
-      path =
-          new PartialPath(ROOT + PATH_SEPARATOR + database + PATH_SEPARATOR + table.getTableName());
+      path = new PartialPath(new String[] {ROOT, database, table.getTableName()});
       patternTree.appendPathPattern(path);
       patternTree.appendPathPattern(path.concatNode(MULTI_LEVEL_PATH_WILDCARD));
       patternTree.serialize(dataOutputStream);
-    } catch (IllegalPathException | IOException ignored) {
+    } catch (IOException e) {
+      LOGGER.warn("failed to serialize request for table {}.{}", database, table.getTableName(), e);
     }
     ByteBuffer patternTreeBytes = ByteBuffer.wrap(byteArrayOutputStream.toByteArray());
 
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
index 657512ef824..f1dc7ba7403 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java
@@ -45,7 +45,10 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DataType;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DescribeTable;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropDB;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropTable;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LongLiteral;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Node;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Property;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowDB;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ShowTables;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Use;
@@ -54,12 +57,27 @@ import org.apache.iotdb.db.queryengine.plan.relational.type.TypeNotFoundExceptio
 import org.apache.tsfile.common.conf.TSFileDescriptor;
 import org.apache.tsfile.enums.TSDataType;
 
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant.COLUMN_TTL;
 import static org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager.getTSDataType;
 import static org.apache.iotdb.db.queryengine.plan.relational.type.TypeSignatureTranslator.toTypeSignature;
 import static org.apache.iotdb.db.utils.EncodingInferenceUtils.getDefaultEncoding;
 
 public class TableConfigTaskVisitor extends AstVisitor<IConfigTask, MPPQueryContext> {
 
+  private static final String DATABASE_NOT_SPECIFIED = "database is not specified";
+
+  private static final Set<String> TABLE_ALLOWED_PROPERTIES = new HashSet<>();
+
+  static {
+    TABLE_ALLOWED_PROPERTIES.add(COLUMN_TTL.toLowerCase(Locale.ENGLISH));
+  }
+
   private final IClientSession clientSession;
 
   private final Metadata metadata;
@@ -107,9 +125,23 @@ public class TableConfigTaskVisitor extends AstVisitor<IConfigTask, MPPQueryCont
       database = node.getName().getPrefix().get().toString();
     }
     if (database == null) {
-      throw new SemanticException("unknown database");
+      throw new SemanticException(DATABASE_NOT_SPECIFIED);
     }
     TsTable table = new TsTable(node.getName().getSuffix());
+    Map<String, String> map = new HashMap<>();
+    for (Property property : node.getProperties()) {
+      String key = property.getName().getValue().toLowerCase(Locale.ENGLISH);
+      if (TABLE_ALLOWED_PROPERTIES.contains(key) && !property.isSetToDefault()) {
+        Expression value = property.getNonDefaultValue();
+        if (!(value instanceof LongLiteral)) {
+          throw new SemanticException(
+              "TTL' value must be a LongLiteral, but now is: " + value.toString());
+        }
+        map.put(key, String.valueOf(((LongLiteral) value).getParsedValue()));
+      }
+    }
+    table.setProps(map);
+
     for (ColumnDefinition columnDefinition : node.getElements()) {
       TsTableColumnCategory category = columnDefinition.getColumnCategory();
       String columnName = columnDefinition.getName().getValue();
@@ -120,9 +152,17 @@ public class TableConfigTaskVisitor extends AstVisitor<IConfigTask, MPPQueryCont
       TSDataType dataType = getDataType(columnDefinition.getType());
       switch (category) {
         case ID:
+          if (!TSDataType.STRING.equals(dataType)) {
+            throw new SemanticException(
+                "DataType of ID Column should only be STRING, current is " + dataType);
+          }
           table.addColumnSchema(new IdColumnSchema(columnName, dataType));
           break;
         case ATTRIBUTE:
+          if (!TSDataType.STRING.equals(dataType)) {
+            throw new SemanticException(
+                "DataType of ATTRIBUTE Column should only be STRING, current is " + dataType);
+          }
           table.addColumnSchema(new AttributeColumnSchema(columnName, dataType));
           break;
         case TIME:
@@ -163,7 +203,7 @@ public class TableConfigTaskVisitor extends AstVisitor<IConfigTask, MPPQueryCont
       database = node.getDbName().get().toString();
     }
     if (database == null) {
-      throw new SemanticException("unknown database");
+      throw new SemanticException(DATABASE_NOT_SPECIFIED);
     }
     return new ShowTablesTask(database);
   }
@@ -176,7 +216,7 @@ public class TableConfigTaskVisitor extends AstVisitor<IConfigTask, MPPQueryCont
       database = node.getTable().getPrefix().get().toString();
     }
     if (database == null) {
-      throw new SemanticException("unknown database");
+      throw new SemanticException(DATABASE_NOT_SPECIFIED);
     }
     return new DescribeTableTask(database, node.getTable().getSuffix());
   }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
index ef900fddafe..aea0ab14e5e 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java
@@ -268,6 +268,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.TreeMap;
 import java.util.stream.Collectors;
 
@@ -2933,8 +2934,16 @@ public class ClusterConfigTaskExecutor implements IConfigTaskExecutor {
   @Override
   public SettableFuture<ConfigTaskResult> showTables(String database) {
     SettableFuture<ConfigTaskResult> future = SettableFuture.create();
-    List<TsTable> tableList = DataNodeTableCache.getInstance().getTables(database);
-    ShowTablesTask.buildTsBlock(tableList, future);
+
+    Optional<List<TsTable>> tableList = DataNodeTableCache.getInstance().getTables(database);
+    if (tableList.isPresent()) {
+      ShowTablesTask.buildTsBlock(tableList.get(), future);
+    } else {
+      future.setException(
+          new IoTDBException(
+              String.format("Database %s doesn't exists.", database),
+              TSStatusCode.DATABASE_NOT_EXIST.getStatusCode()));
+    }
     return future;
   }
 
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/AlterTableAddColumnTask.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/AlterTableAddColumnTask.java
index febd54cc8a7..17058e6f6c0 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/AlterTableAddColumnTask.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/AlterTableAddColumnTask.java
@@ -33,7 +33,7 @@ import org.apache.iotdb.db.queryengine.plan.relational.type.InternalTypeManager;
 import com.google.common.util.concurrent.ListenableFuture;
 import org.apache.tsfile.common.conf.TSFileDescriptor;
 import org.apache.tsfile.enums.TSDataType;
-import org.apache.tsfile.read.common.type.BinaryType;
+import org.apache.tsfile.read.common.type.StringType;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -69,16 +69,16 @@ public class AlterTableAddColumnTask implements IConfigTask {
     for (ColumnSchema inputColumn : inputColumnList) {
       switch (inputColumn.getColumnCategory()) {
         case ID:
-          if (!inputColumn.getType().equals(BinaryType.TEXT)) {
-            throw new SemanticException("Id column only support data type TEXT.");
+          if (!inputColumn.getType().equals(StringType.STRING)) {
+            throw new SemanticException("Id column only support data type STRING.");
           }
-          columnSchemaList.add(new IdColumnSchema(inputColumn.getName(), TSDataType.TEXT));
+          columnSchemaList.add(new IdColumnSchema(inputColumn.getName(), TSDataType.STRING));
           break;
         case ATTRIBUTE:
-          if (!inputColumn.getType().equals(BinaryType.TEXT)) {
-            throw new SemanticException("Attribute column only support data type TEXT.");
+          if (!inputColumn.getType().equals(StringType.STRING)) {
+            throw new SemanticException("Attribute column only support data type STRING.");
           }
-          columnSchemaList.add(new AttributeColumnSchema(inputColumn.getName(), TSDataType.TEXT));
+          columnSchemaList.add(new AttributeColumnSchema(inputColumn.getName(), TSDataType.STRING));
           break;
         case MEASUREMENT:
           TSDataType dataType = InternalTypeManager.getTSDataType(inputColumn.getType());
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowTablesTask.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowTablesTask.java
index 65dbe9adfd0..fc7c1e491de 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowTablesTask.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/relational/ShowTablesTask.java
@@ -37,8 +37,11 @@ import org.apache.tsfile.read.common.block.TsBlockBuilder;
 import org.apache.tsfile.utils.Binary;
 
 import java.util.List;
+import java.util.Locale;
 import java.util.stream.Collectors;
 
+import static org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant.COLUMN_TTL;
+
 public class ShowTablesTask implements IConfigTask {
 
   private final String database;
@@ -67,7 +70,9 @@ public class ShowTablesTask implements IConfigTask {
       builder
           .getColumnBuilder(0)
           .writeBinary(new Binary(table.getTableName(), TSFileConfig.STRING_CHARSET));
-      builder.getColumnBuilder(1).appendNull();
+      builder
+          .getColumnBuilder(1)
+          .writeLong(Long.parseLong(table.getPropValue(COLUMN_TTL.toLowerCase(Locale.ENGLISH))));
       builder.declarePosition();
     }
 
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 dcc5f671687..b017f8d3d72 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
@@ -169,7 +169,7 @@ public class TableMetadataImpl implements Metadata {
         throw new SemanticException(
             "Scalar function: "
                 + functionName.toLowerCase(Locale.ENGLISH)
-                + " only supports text data type.");
+                + " only supports text or string data type.");
       }
       return argumentTypes.get(0);
     } else if (BuiltinScalarFunction.SUBSTRING.getFunctionName().equalsIgnoreCase(functionName)) {
@@ -183,7 +183,7 @@ public class TableMetadataImpl implements Metadata {
         throw new SemanticException(
             "Scalar function"
                 + functionName.toLowerCase(Locale.ENGLISH)
-                + " only supports text data type.");
+                + " only supports text or string data type.");
       }
       return argumentTypes.get(0);
     }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/table/DataNodeTableCache.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/table/DataNodeTableCache.java
index d1f4d75ba31..ffe32fd0870 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/table/DataNodeTableCache.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/table/DataNodeTableCache.java
@@ -29,9 +29,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -222,13 +222,11 @@ public class DataNodeTableCache implements ITableCache {
     }
   }
 
-  public List<TsTable> getTables(String database) {
+  public Optional<List<TsTable>> getTables(String database) {
     readWriteLock.readLock().lock();
     try {
-      if (databaseTableMap.containsKey(database)) {
-        return new ArrayList<>(databaseTableMap.get(database).values());
-      }
-      return Collections.emptyList();
+      Map<String, TsTable> tableMap = databaseTableMap.get(database);
+      return tableMap != null ? Optional.of(new ArrayList<>(tableMap.values())) : Optional.empty();
     } finally {
       readWriteLock.readLock().unlock();
     }
diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/ErrorHandlingUtils.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/ErrorHandlingUtils.java
index e698ba8487e..34fd8b96bb0 100644
--- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/ErrorHandlingUtils.java
+++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/ErrorHandlingUtils.java
@@ -97,8 +97,10 @@ public class ErrorHandlingUtils {
       if (status.getCode() != TSStatusCode.STORAGE_ENGINE_NOT_READY.getStatusCode()) {
         String message =
             String.format(
-                "Status code: %s, Query Statement: %s failed", status.getCode(), operation);
-        if (status.getCode() == TSStatusCode.SQL_PARSE_ERROR.getStatusCode()) {
+                "Status code: %s, Query Statement: %s failed because %s",
+                status.getCode(), operation, status.getMessage());
+        if (status.getCode() == TSStatusCode.SQL_PARSE_ERROR.getStatusCode()
+            || status.getCode() == TSStatusCode.SEMANTIC_ERROR.getStatusCode()) {
           LOGGER.warn(message);
         } else {
           LOGGER.warn(message, e);
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 faa5509c9c2..0584cf62dfb 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
@@ -43,7 +43,7 @@ import org.apache.iotdb.mpp.rpc.thrift.TRegionRouteReq;
 
 import org.apache.tsfile.file.metadata.IDeviceID;
 import org.apache.tsfile.file.metadata.StringArrayDeviceID;
-import org.apache.tsfile.read.common.type.BinaryType;
+import org.apache.tsfile.read.common.type.StringType;
 import org.apache.tsfile.read.common.type.Type;
 
 import java.util.Arrays;
@@ -77,11 +77,11 @@ public class TestMatadata implements Metadata {
   private static final String S2 = "s2";
   private static final String S3 = "s3";
   private static final ColumnMetadata TIME_CM = new ColumnMetadata(TIME, INT64);
-  private static final ColumnMetadata TAG1_CM = new ColumnMetadata(TAG1, BinaryType.TEXT);
-  private static final ColumnMetadata TAG2_CM = new ColumnMetadata(TAG2, BinaryType.TEXT);
-  private static final ColumnMetadata TAG3_CM = new ColumnMetadata(TAG3, BinaryType.TEXT);
-  private static final ColumnMetadata ATTR1_CM = new ColumnMetadata(ATTR1, BinaryType.TEXT);
-  private static final ColumnMetadata ATTR2_CM = new ColumnMetadata(ATTR2, BinaryType.TEXT);
+  private static final ColumnMetadata TAG1_CM = new ColumnMetadata(TAG1, StringType.STRING);
+  private static final ColumnMetadata TAG2_CM = new ColumnMetadata(TAG2, StringType.STRING);
+  private static final ColumnMetadata TAG3_CM = new ColumnMetadata(TAG3, StringType.STRING);
+  private static final ColumnMetadata ATTR1_CM = new ColumnMetadata(ATTR1, StringType.STRING);
+  private static final ColumnMetadata ATTR2_CM = new ColumnMetadata(ATTR2, StringType.STRING);
   private static final ColumnMetadata S1_CM = new ColumnMetadata(S1, INT64);
   private static final ColumnMetadata S2_CM = new ColumnMetadata(S2, INT64);
   private static final ColumnMetadata S3_CM = new ColumnMetadata(S3, DOUBLE);
diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
index dd0d4662cc7..919f96e1708 100644
--- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
+++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/table/TsTable.java
@@ -147,6 +147,10 @@ public class TsTable {
     return table;
   }
 
+  public void setProps(Map<String, String> props) {
+    this.props = props;
+  }
+
   @Override
   public boolean equals(Object o) {
     return super.equals(o);