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

yongzao pushed a commit to branch fix-model-management-bug-in-iotdb-table-sql
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to 
refs/heads/fix-model-management-bug-in-iotdb-table-sql by this push:
     new 556fea54acd submit for CI test
556fea54acd is described below

commit 556fea54acdecd81234c0e0e25ced50c91978314
Author: Yongzao <[email protected]>
AuthorDate: Sat Jul 12 11:17:34 2025 +0800

    submit for CI test
---
 .../org/apache/iotdb/ainode/it/AINodeBasicIT.java  | 268 ---------------------
 .../iotdb/ainode/it/AINodeClusterConfigIT.java     |  76 ++++++
 .../iotdb/ainode/it/AINodeInferenceSQLIT.java      | 200 +++++++++++++++
 .../iotdb/ainode/it/AINodeModelManageIT.java       | 211 ++++++++++++++++
 .../apache/iotdb/ainode/utils/AINodeTestUtils.java |  89 +++++++
 .../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4   |   2 +-
 .../iotdb/confignode/manager/ModelManager.java     |   2 +-
 .../queryengine/plan/analyze/AnalyzeVisitor.java   |   2 +-
 .../execution/config/TableConfigTaskVisitor.java   |  23 ++
 .../execution/config/TreeConfigTaskVisitor.java    |  14 +-
 .../config/executor/ClusterConfigTaskExecutor.java |  17 +-
 .../config/executor/IConfigTaskExecutor.java       |   8 +-
 .../config/metadata/ai/CreateModelTask.java        |  14 +-
 .../db/queryengine/plan/parser/ASTVisitor.java     |  26 +-
 .../plan/relational/sql/ast/AstVisitor.java        |   8 +
 .../plan/relational/sql/ast/CreateModel.java       |  72 ++++++
 .../plan/relational/sql/ast/DropModel.java         |  64 +++++
 .../plan/relational/sql/parser/AstBuilder.java     |  66 +++--
 .../plan/statement/crud/QueryStatement.java        |  10 +-
 .../metadata/model/CreateModelStatement.java       |  10 +-
 .../metadata/model/DropModelStatement.java         |  10 +-
 .../metadata/model/ShowModelsStatement.java        |  12 +-
 .../db/relational/grammar/sql/RelationalSql.g4     |   8 +-
 23 files changed, 850 insertions(+), 362 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeBasicIT.java 
b/integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeBasicIT.java
deleted file mode 100644
index 84cb3576cee..00000000000
--- 
a/integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeBasicIT.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * 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.ainode.it;
-
-import org.apache.iotdb.it.env.EnvFactory;
-
-import org.junit.Test;
-
-import java.io.File;
-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.it.utils.TestUtils.prepareData;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-// @RunWith(IoTDBTestRunner.class)
-// @Category({AIClusterIT.class})
-public class AINodeBasicIT {
-  static final String MODEL_PATH =
-      System.getProperty("user.dir")
-          + File.separator
-          + "src"
-          + File.separator
-          + "test"
-          + File.separator
-          + "resources"
-          + File.separator
-          + "ainode-example";
-
-  static String[] sqls =
-      new String[] {
-        "set configuration \"trusted_uri_pattern\"='.*'",
-        "create model identity using uri \"" + MODEL_PATH + "\"",
-        "CREATE DATABASE root.AI.data",
-        "CREATE TIMESERIES root.AI.data.s0 WITH DATATYPE=FLOAT, ENCODING=RLE",
-        "CREATE TIMESERIES root.AI.data.s1 WITH DATATYPE=FLOAT, ENCODING=RLE",
-        "CREATE TIMESERIES root.AI.data.s2 WITH DATATYPE=FLOAT, ENCODING=RLE",
-        "CREATE TIMESERIES root.AI.data.s3 WITH DATATYPE=DOUBLE, ENCODING=RLE",
-        "insert into root.AI.data(timestamp,s0,s1,s2,s3) 
values(1,1.0,2.0,3.0,4.0)",
-        "insert into root.AI.data(timestamp,s0,s1,s2,s3) 
values(2,2.0,3.0,4.0,5.0)",
-        "insert into root.AI.data(timestamp,s0,s1,s2,s3) 
values(3,3.0,4.0,5.0,6.0)",
-        "insert into root.AI.data(timestamp,s0,s1,s2,s3) 
values(4,4.0,5.0,6.0,7.0)",
-        "insert into root.AI.data(timestamp,s0,s1,s2,s3) 
values(5,5.0,6.0,7.0,8.0)",
-        "insert into root.AI.data(timestamp,s0,s1,s2,s3) 
values(6,6.0,7.0,8.0,9.0)",
-        "insert into root.AI.data(timestamp,s0,s1,s2,s3) 
values(7,7.0,8.0,9.0,10.0)",
-      };
-
-  //  @BeforeClass
-  public static void setUp() throws Exception {
-    // Init 1C1D1M cluster environment
-    EnvFactory.getEnv().initClusterEnvironment(1, 1);
-    prepareData(sqls);
-  }
-
-  //  @AfterClass
-  public static void tearDown() throws Exception {
-    EnvFactory.getEnv().cleanClusterEnvironment();
-  }
-
-  private static void checkHeader(ResultSetMetaData resultSetMetaData, String 
title)
-      throws SQLException {
-    String[] headers = title.split(",");
-    for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
-      assertEquals(headers[i - 1], resultSetMetaData.getColumnName(i));
-    }
-  }
-
-  private void errorTest(String sql, String errorMessage) {
-    try (Connection connection = EnvFactory.getEnv().getConnection();
-        Statement statement = connection.createStatement()) {
-
-      try (ResultSet ignored = statement.executeQuery(sql)) {
-        fail("There should be an exception");
-      }
-    } catch (SQLException e) {
-      assertEquals(errorMessage, e.getMessage());
-    }
-  }
-
-  @Test
-  public void aiNodeConnectionTest() {
-    String sql = "SHOW AINODES";
-    String title = "NodeID,Status,InternalAddress,InternalPort";
-    try (Connection connection = EnvFactory.getEnv().getConnection();
-        Statement statement = connection.createStatement()) {
-
-      try (ResultSet resultSet = statement.executeQuery(sql)) {
-        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
-        checkHeader(resultSetMetaData, title);
-        int count = 0;
-        while (resultSet.next()) {
-          assertEquals("2", resultSet.getString(1));
-          assertEquals("Running", resultSet.getString(2));
-          count++;
-        }
-        assertEquals(1, count);
-      }
-    } catch (SQLException e) {
-      e.printStackTrace();
-      fail(e.getMessage());
-    }
-  }
-
-  @Test
-  public void ModelOperationTest() {
-    String registerSql = "create model operationTest using uri \"" + 
MODEL_PATH + "\"";
-    String showSql = "SHOW MODELS operationTest";
-    String dropSql = "DROP MODEL operationTest";
-    try (Connection connection = EnvFactory.getEnv().getConnection();
-        Statement statement = connection.createStatement()) {
-      statement.execute(registerSql);
-      boolean loading = true;
-      int count = 0;
-      while (loading) {
-        try (ResultSet resultSet = statement.executeQuery(showSql)) {
-          ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
-          checkHeader(resultSetMetaData, 
"ModelId,ModelType,State,Configs,Notes");
-          while (resultSet.next()) {
-            String modelName = resultSet.getString(1);
-            String modelType = resultSet.getString(2);
-            String status = resultSet.getString(3);
-
-            assertEquals("operationTest", modelName);
-            assertEquals("USER_DEFINED", modelType);
-            if (status.equals("ACTIVE")) {
-              loading = false;
-              count++;
-            } else if (status.equals("LOADING")) {
-              break;
-            } else {
-              fail("Unexpected status of model: " + status);
-            }
-          }
-        }
-      }
-      assertEquals(1, count);
-      statement.execute(dropSql);
-      try (ResultSet resultSet = statement.executeQuery(showSql)) {
-        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
-        checkHeader(resultSetMetaData, 
"ModelId,ModelType,State,Configs,Notes");
-        count = 0;
-        while (resultSet.next()) {
-          count++;
-        }
-        assertEquals(0, count);
-      }
-    } catch (SQLException e) {
-      fail(e.getMessage());
-    }
-  }
-
-  @Test
-  public void callInferenceTest2() {
-    String sql =
-        "CALL INFERENCE(_holtwinters, \"select s0 from root.AI.data\", 
predict_length=6, generateTime=true)";
-    try (Connection connection = EnvFactory.getEnv().getConnection();
-        Statement statement = connection.createStatement()) {
-      try (ResultSet resultSet = statement.executeQuery(sql)) {
-        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
-        checkHeader(resultSetMetaData, "Time,output0");
-        int count = 0;
-        while (resultSet.next()) {
-          count++;
-        }
-        assertEquals(6, count);
-      }
-    } catch (SQLException e) {
-      fail(e.getMessage());
-    }
-  }
-
-  @Test
-  public void callInferenceTest() {
-    String sql =
-        "CALL INFERENCE(identity, \"select s0,s1,s2 from root.AI.data\", 
generateTime=true)";
-    String sql2 = "CALL INFERENCE(identity, \"select s2,s0,s1 from 
root.AI.data\")";
-    String sql3 =
-        "CALL INFERENCE(_NaiveForecaster, \"select s0 from root.AI.data\", 
predict_length=3, generateTime=true)";
-    try (Connection connection = EnvFactory.getEnv().getConnection();
-        Statement statement = connection.createStatement()) {
-
-      try (ResultSet resultSet = statement.executeQuery(sql)) {
-        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
-        checkHeader(resultSetMetaData, "Time,output0,output1,output2");
-        int count = 0;
-        while (resultSet.next()) {
-          float s0 = resultSet.getFloat(2);
-          float s1 = resultSet.getFloat(3);
-          float s2 = resultSet.getFloat(4);
-
-          assertEquals(s0, count + 1.0, 0.0001);
-          assertEquals(s1, count + 2.0, 0.0001);
-          assertEquals(s2, count + 3.0, 0.0001);
-          count++;
-        }
-        assertEquals(7, count);
-      }
-
-      try (ResultSet resultSet = statement.executeQuery(sql2)) {
-        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
-        checkHeader(resultSetMetaData, "output0,output1,output2");
-        int count = 0;
-        while (resultSet.next()) {
-          float s2 = resultSet.getFloat(1);
-          float s0 = resultSet.getFloat(2);
-          float s1 = resultSet.getFloat(3);
-
-          assertEquals(s0, count + 1.0, 0.0001);
-          assertEquals(s1, count + 2.0, 0.0001);
-          assertEquals(s2, count + 3.0, 0.0001);
-          count++;
-        }
-        assertEquals(7, count);
-      }
-
-      try (ResultSet resultSet = statement.executeQuery(sql3)) {
-        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
-        checkHeader(resultSetMetaData, "Time,output0,output1,output2");
-        int count = 0;
-        while (resultSet.next()) {
-          count++;
-        }
-        assertEquals(3, count);
-      }
-
-    } catch (SQLException e) {
-      fail(e.getMessage());
-    }
-  }
-
-  @Test
-  public void errorTest() {
-    String sql =
-        "CALL INFERENCE(notFound404, \"select s0,s1,s2 from root.AI.data\", 
window=head(5))";
-    errorTest(sql, "1505: model [notFound404] has not been created.");
-    sql = "CALL INFERENCE(identity, \"select s0,s1,s2 from root.AI.data\", 
window=head(2))";
-    errorTest(sql, "701: Window output 2 is not equal to input size of model 
7");
-    sql = "CALL INFERENCE(identity, \"select s0,s1,s2 from root.AI.data limit 
5\")";
-    errorTest(
-        sql,
-        "301: The number of rows 5 in the input data does not match the model 
input 7. Try to use LIMIT in SQL or WINDOW in CALL INFERENCE");
-    sql = "CREATE MODEL 中文 USING URI \"" + MODEL_PATH + "\"";
-    errorTest(sql, "701: ModelName can only contain letters, numbers, and 
underscores");
-    sql = "DROP MODEL _GaussianHMM";
-    errorTest(sql, "1502: Built-in model _GaussianHMM can't be removed");
-  }
-}
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeClusterConfigIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeClusterConfigIT.java
new file mode 100644
index 00000000000..89bd887b739
--- /dev/null
+++ 
b/integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeClusterConfigIT.java
@@ -0,0 +1,76 @@
+/*
+ * 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.ainode.it;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.AIClusterIT;
+
+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.ainode.utils.AINodeTestUtils.checkHeader;
+import static org.junit.Assert.assertEquals;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({AIClusterIT.class})
+public class AINodeClusterConfigIT {
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    // Init 1C1D1A cluster environment
+    EnvFactory.getEnv().initClusterEnvironment(1, 1);
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    EnvFactory.getEnv().cleanClusterEnvironment();
+  }
+
+  @Test
+  public void aiNodeRegisterTest() throws SQLException {
+    String sql = "SHOW AINODES";
+    String title = "NodeID,Status,InternalAddress,InternalPort";
+    try (Connection connection = EnvFactory.getEnv().getConnection();
+        Statement statement = connection.createStatement()) {
+
+      try (ResultSet resultSet = statement.executeQuery(sql)) {
+        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+        checkHeader(resultSetMetaData, title);
+        int count = 0;
+        while (resultSet.next()) {
+          assertEquals("2", resultSet.getString(1));
+          assertEquals("Running", resultSet.getString(2));
+          count++;
+        }
+        assertEquals(1, count);
+      }
+    }
+  }
+}
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeInferenceSQLIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeInferenceSQLIT.java
new file mode 100644
index 00000000000..2b175511c6b
--- /dev/null
+++ 
b/integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeInferenceSQLIT.java
@@ -0,0 +1,200 @@
+/*
+ * 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.ainode.it;
+
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.AIClusterIT;
+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.ainode.utils.AINodeTestUtils.EXAMPLE_MODEL_PATH;
+import static org.apache.iotdb.ainode.utils.AINodeTestUtils.checkHeader;
+import static org.apache.iotdb.ainode.utils.AINodeTestUtils.errorTest;
+import static org.apache.iotdb.db.it.utils.TestUtils.prepareData;
+import static org.apache.iotdb.db.it.utils.TestUtils.prepareTableData;
+import static org.junit.Assert.assertEquals;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({AIClusterIT.class})
+public class AINodeInferenceSQLIT {
+
+  static String[] WRITE_SQL_IN_TREE =
+      new String[] {
+        "set configuration \"trusted_uri_pattern\"='.*'",
+        "create model identity using uri \"" + EXAMPLE_MODEL_PATH + "\"",
+        "CREATE DATABASE root.AI",
+        "CREATE TIMESERIES root.AI.s0 WITH DATATYPE=FLOAT, ENCODING=RLE",
+        "CREATE TIMESERIES root.AI.s1 WITH DATATYPE=DOUBLE, ENCODING=RLE",
+        "CREATE TIMESERIES root.AI.s2 WITH DATATYPE=INT32, ENCODING=RLE",
+        "CREATE TIMESERIES root.AI.s3 WITH DATATYPE=INT64, ENCODING=RLE",
+        "insert into root.AI(timestamp,s0,s1,s2,s3) values(1,1.0,2.0,3,4)",
+        "insert into root.AI(timestamp,s0,s1,s2,s3) values(2,2.0,3.0,4,5)",
+        "insert into root.AI(timestamp,s0,s1,s2,s3) values(3,3.0,4.0,5,6)",
+        "insert into root.AI(timestamp,s0,s1,s2,s3) values(4,4.0,5.0,6,7)",
+        "insert into root.AI(timestamp,s0,s1,s2,s3) values(5,5.0,6.0,7,8)",
+        "insert into root.AI(timestamp,s0,s1,s2,s3) values(6,6.0,7.0,8,9)",
+        "insert into root.AI(timestamp,s0,s1,s2,s3) values(7,7.0,8.0,9,10)",
+      };
+
+  static String[] WRITE_SQL_IN_TABLE =
+          new String[] {
+                  "set configuration \"trusted_uri_pattern\"='.*'",
+                  "create model identity using uri \"" + EXAMPLE_MODEL_PATH + 
"\"",
+                  "CREATE DATABASE root",
+                  "CREATE TABLE root.AI (s0 FLOAT FIELD, s1 DOUBLE FIELD, s2 
INT32 FIELD, s3 INT64 FIELD)",
+                  "insert into root.AI(time,s0,s1,s2,s3) 
values(1,1.0,2.0,3,4)",
+                  "insert into root.AI(time,s0,s1,s2,s3) 
values(2,2.0,3.0,4,5)",
+                  "insert into root.AI(time,s0,s1,s2,s3) 
values(3,3.0,4.0,5,6)",
+                  "insert into root.AI(time,s0,s1,s2,s3) 
values(4,4.0,5.0,6,7)",
+                  "insert into root.AI(time,s0,s1,s2,s3) 
values(5,5.0,6.0,7,8)",
+                  "insert into root.AI(time,s0,s1,s2,s3) 
values(6,6.0,7.0,8,9)",
+                  "insert into root.AI(time,s0,s1,s2,s3) 
values(7,7.0,8.0,9,10)",
+          };
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    // Init 1C1D1M cluster environment
+    EnvFactory.getEnv().initClusterEnvironment(1, 1);
+    prepareData(WRITE_SQL_IN_TREE);
+    prepareTableData(WRITE_SQL_IN_TABLE);
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    EnvFactory.getEnv().cleanClusterEnvironment();
+  }
+
+  @Test
+  public void callInferenceTestInTree() throws SQLException {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TREE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      callInferenceTest(statement);
+    }
+  }
+
+  @Test
+  public void callInferenceTestInTable() throws SQLException {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      callInferenceTest(statement);
+    }
+  }
+
+  public void callInferenceTest(Statement statement) throws SQLException {
+    // SQL1: user-defined model inferences multi-columns with generateTime=true
+    String sql1 =
+        "CALL INFERENCE(identity, \"select s0,s1,s2,s3 from root.AI\", 
generateTime=true)";
+    // SQL2: user-defined model inferences multi-columns with 
generateTime=false
+    String sql2 =
+        "CALL INFERENCE(identity, \"select s2,s0,s3,s1 from root.AI\", 
generateTime=false)";
+    // SQL3: built-in model inferences single column with given predict_length 
and multi-outputs
+    String sql3 =
+        "CALL INFERENCE(naive_forecaster, \"select s0 from root.AI\", 
predict_length=3, generateTime=true)";
+    // SQL4: built-in model inferences single column with given predict_length
+    String sql4 =
+        "CALL INFERENCE(holtwinters, \"select s0 from root.AI\", 
predict_length=6, generateTime=true)";
+
+    try (ResultSet resultSet = statement.executeQuery(sql1)) {
+      ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+      checkHeader(resultSetMetaData, "Time,output0,output1,output2,output3");
+      int count = 0;
+      while (resultSet.next()) {
+        float s0 = resultSet.getFloat(2);
+        float s1 = resultSet.getFloat(3);
+        float s2 = resultSet.getFloat(4);
+        float s3 = resultSet.getFloat(5);
+
+        assertEquals(s0, count + 1.0, 0.0001);
+        assertEquals(s1, count + 2.0, 0.0001);
+        assertEquals(s2, count + 3.0, 0.0001);
+        assertEquals(s3, count + 4.0, 0.0001);
+        count++;
+      }
+      assertEquals(7, count);
+    }
+
+    try (ResultSet resultSet = statement.executeQuery(sql2)) {
+      ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+      checkHeader(resultSetMetaData, "output0,output1,output2");
+      int count = 0;
+      while (resultSet.next()) {
+        float s2 = resultSet.getFloat(1);
+        float s0 = resultSet.getFloat(2);
+        float s3 = resultSet.getFloat(3);
+        float s1 = resultSet.getFloat(4);
+
+        assertEquals(s0, count + 1.0, 0.0001);
+        assertEquals(s1, count + 2.0, 0.0001);
+        assertEquals(s2, count + 3.0, 0.0001);
+        assertEquals(s3, count + 4.0, 0.0001);
+        count++;
+      }
+      assertEquals(7, count);
+    }
+
+    try (ResultSet resultSet = statement.executeQuery(sql3)) {
+      ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+      checkHeader(resultSetMetaData, "Time,output0,output1,output2");
+      int count = 0;
+      while (resultSet.next()) {
+        count++;
+      }
+      assertEquals(3, count);
+    }
+
+    try (ResultSet resultSet = statement.executeQuery(sql4)) {
+      ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+      checkHeader(resultSetMetaData, "Time,output0");
+      int count = 0;
+      while (resultSet.next()) {
+        count++;
+      }
+      assertEquals(6, count);
+    }
+  }
+
+  @Test
+  public void errorInferenceTest(Statement statement) {
+    String sql =
+        "CALL INFERENCE(notFound404, \"select s0,s1,s2 from root.AI.data\", 
window=head(5))";
+    errorTest(statement, sql, "1505: model [notFound404] has not been 
created.");
+    sql = "CALL INFERENCE(identity, \"select s0,s1,s2 from root.AI.data\", 
window=head(2))";
+    errorTest(statement, sql, "701: Window output 2 is not equal to input size 
of model 7");
+    sql = "CALL INFERENCE(identity, \"select s0,s1,s2 from root.AI.data limit 
5\")";
+    errorTest(
+        statement,
+        sql,
+        "301: The number of rows 5 in the input data does not match the model 
input 7. Try to use LIMIT in SQL or WINDOW in CALL INFERENCE");
+    sql = "CREATE MODEL 中文 USING URI \"" + EXAMPLE_MODEL_PATH + "\"";
+    errorTest(statement, sql, "701: ModelId can only contain letters, numbers, 
and underscores");
+  }
+}
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeModelManageIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeModelManageIT.java
new file mode 100644
index 00000000000..c86f3204328
--- /dev/null
+++ 
b/integration-test/src/test/java/org/apache/iotdb/ainode/it/AINodeModelManageIT.java
@@ -0,0 +1,211 @@
+/*
+ * 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.ainode.it;
+
+import org.apache.iotdb.ainode.utils.AINodeTestUtils.FakeModelInfo;
+import org.apache.iotdb.it.env.EnvFactory;
+import org.apache.iotdb.it.framework.IoTDBTestRunner;
+import org.apache.iotdb.itbase.category.AIClusterIT;
+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 java.util.AbstractMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.apache.iotdb.ainode.utils.AINodeTestUtils.EXAMPLE_MODEL_PATH;
+import static org.apache.iotdb.ainode.utils.AINodeTestUtils.checkHeader;
+import static org.apache.iotdb.ainode.utils.AINodeTestUtils.errorTest;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+@RunWith(IoTDBTestRunner.class)
+@Category({AIClusterIT.class})
+public class AINodeModelManageIT {
+
+  private static final Map<String, FakeModelInfo> BUILT_IN_MODEL_MAP =
+      Stream.of(
+              new AbstractMap.SimpleEntry<>(
+                  "arima", new FakeModelInfo("arima", "Arima", "BUILT_IN", 
"ACTIVE")),
+              new AbstractMap.SimpleEntry<>(
+                  "holtwinters",
+                  new FakeModelInfo("holtwinters", "HoltWinters", "BUILT_IN", 
"ACTIVE")),
+              new AbstractMap.SimpleEntry<>(
+                  "exponential_smoothing",
+                  new FakeModelInfo(
+                      "exponential_smoothing", "ExponentialSmoothing", 
"BUILT_IN", "ACTIVE")),
+              new AbstractMap.SimpleEntry<>(
+                  "naive_forecaster",
+                  new FakeModelInfo("naive_forecaster", "NaiveForecaster", 
"BUILT_IN", "ACTIVE")),
+              new AbstractMap.SimpleEntry<>(
+                  "stl_forecaster",
+                  new FakeModelInfo("stl_forecaster", "StlForecaster", 
"BUILT_IN", "ACTIVE")),
+              new AbstractMap.SimpleEntry<>(
+                  "gaussian_hmm",
+                  new FakeModelInfo("gaussian_hmm", "GaussianHmm", "BUILT_IN", 
"ACTIVE")),
+              new AbstractMap.SimpleEntry<>(
+                  "gmm_hmm", new FakeModelInfo("gmm_hmm", "GmmHmm", 
"BUILT_IN", "ACTIVE")),
+              new AbstractMap.SimpleEntry<>(
+                  "stray", new FakeModelInfo("stray", "Stray", "BUILT_IN", 
"ACTIVE")),
+              new AbstractMap.SimpleEntry<>(
+                  "sundial", new FakeModelInfo("sundial", "Timer-Sundial", 
"BUILT_IN", "ACTIVE")),
+              new AbstractMap.SimpleEntry<>(
+                  "timer_xl", new FakeModelInfo("timer_xl", "Timer-XL", 
"BUILT_IN", "ACTIVE")))
+          .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    // Init 1C1D1A cluster environment
+    EnvFactory.getEnv().initClusterEnvironment(1, 1);
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    EnvFactory.getEnv().cleanClusterEnvironment();
+  }
+
+  @Test
+  public void userDefinedModelManagementTestInTree() throws SQLException {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TREE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      userDefinedModelManagementTest(statement);
+    }
+  }
+
+  @Test
+  public void userDefinedModelManagementTestInTable() throws SQLException {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      userDefinedModelManagementTest(statement);
+    }
+  }
+
+  private void userDefinedModelManagementTest(Statement statement) throws 
SQLException {
+    final String registerSql =
+        "create model operationTest using uri \"" + EXAMPLE_MODEL_PATH + "\"";
+    final String showSql = "SHOW MODELS operationTest";
+    final String dropSql = "DROP MODEL operationTest";
+
+    statement.execute(registerSql);
+    boolean loading = true;
+    int count = 0;
+    while (loading) {
+      try (ResultSet resultSet = statement.executeQuery(showSql)) {
+        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+        checkHeader(resultSetMetaData, "ModelId,ModelType,Category,State");
+        while (resultSet.next()) {
+          String modelId = resultSet.getString(1);
+          String modelType = resultSet.getString(2);
+          String category = resultSet.getString(3);
+          String state = resultSet.getString(4);
+
+          assertEquals("operationTest", modelId);
+          assertNull(category);
+          assertEquals("USER_DEFINED", modelType);
+          if (state.equals("ACTIVE")) {
+            loading = false;
+            count++;
+          } else if (state.equals("LOADING")) {
+            break;
+          } else {
+            fail("Unexpected status of model: " + state);
+          }
+        }
+      }
+    }
+    assertEquals(1, count);
+    statement.execute(dropSql);
+    try (ResultSet resultSet = statement.executeQuery(showSql)) {
+      ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+      checkHeader(resultSetMetaData, "ModelId,ModelType,Category,State");
+      count = 0;
+      while (resultSet.next()) {
+        count++;
+      }
+      assertEquals(0, count);
+    }
+  }
+
+  @Test
+  public void dropBuiltInModelErrorTestInTree() throws SQLException {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TREE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      errorTest(statement, "drop model sundial", "1501: Built-in model sundial 
can't be removed");
+    }
+  }
+
+  @Test
+  public void dropBuiltInModelErrorTestInTable() throws SQLException {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      errorTest(statement, "drop model sundial", "1501: Built-in model sundial 
can't be removed");
+    }
+  }
+
+  @Test
+  public void showBuiltInModelTestInTree() throws SQLException {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TREE_SQL_DIALECT);
+        Statement statement = connection.createStatement()) {
+      showBuiltInModelTest(statement);
+    }
+  }
+
+  @Test
+  public void showBuiltInModelTestInTable() throws SQLException {
+    try (Connection connection = 
EnvFactory.getEnv().getConnection(BaseEnv.TABLE_SQL_DIALECT);
+        Statement statement = connection.createStatement(); ) {
+      showBuiltInModelTest(statement);
+    }
+  }
+
+  private void showBuiltInModelTest(Statement statement) throws SQLException {
+    int built_in_model_count = 0;
+    final String showSql = "SHOW MODELS";
+    try (ResultSet resultSet = statement.executeQuery(showSql)) {
+      ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
+      checkHeader(resultSetMetaData, "ModelId,ModelType,Category,State");
+      while (resultSet.next()) {
+        built_in_model_count++;
+        FakeModelInfo modelInfo =
+            new FakeModelInfo(
+                resultSet.getString(1),
+                resultSet.getString(2),
+                resultSet.getString(3),
+                resultSet.getString(4));
+        assertTrue(BUILT_IN_MODEL_MAP.containsKey(modelInfo.getModelId()));
+        assertEquals(BUILT_IN_MODEL_MAP.get(modelInfo.getModelId()), 
modelInfo);
+      }
+    }
+    assertEquals(BUILT_IN_MODEL_MAP.size(), built_in_model_count);
+  }
+}
diff --git 
a/integration-test/src/test/java/org/apache/iotdb/ainode/utils/AINodeTestUtils.java
 
b/integration-test/src/test/java/org/apache/iotdb/ainode/utils/AINodeTestUtils.java
new file mode 100644
index 00000000000..ba79e2b52b7
--- /dev/null
+++ 
b/integration-test/src/test/java/org/apache/iotdb/ainode/utils/AINodeTestUtils.java
@@ -0,0 +1,89 @@
+package org.apache.iotdb.ainode.utils;
+
+import java.io.File;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Objects;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class AINodeTestUtils {
+
+  public static final String EXAMPLE_MODEL_PATH =
+      System.getProperty("user.dir")
+          + File.separator
+          + "src"
+          + File.separator
+          + "test"
+          + File.separator
+          + "resources"
+          + File.separator
+          + "ainode-example";
+
+  public static void checkHeader(ResultSetMetaData resultSetMetaData, String 
title)
+      throws SQLException {
+    String[] headers = title.split(",");
+    for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
+      assertEquals(headers[i - 1], resultSetMetaData.getColumnName(i));
+    }
+  }
+
+  public static void errorTest(Statement statement, String sql, String 
errorMessage) {
+    try (ResultSet ignored = statement.executeQuery(sql)) {
+      fail("There should be an exception");
+    } catch (SQLException e) {
+      assertEquals(errorMessage, e.getMessage());
+    }
+  }
+
+  public static class FakeModelInfo {
+
+    private final String modelId;
+    private final String modelType;
+    private final String category;
+    private final String state;
+
+    public FakeModelInfo(String modelId, String modelType, String category, 
String state) {
+      this.modelId = modelId;
+      this.modelType = modelType;
+      this.category = category;
+      this.state = state;
+    }
+
+    public String getModelId() {
+      return modelId;
+    }
+
+    public String getModelType() {
+      return modelType;
+    }
+
+    public String getCategory() {
+      return category;
+    }
+
+    public String getState() {
+      return state;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (o == null || getClass() != o.getClass()) {
+        return false;
+      }
+      FakeModelInfo modelInfo = (FakeModelInfo) o;
+      return Objects.equals(modelId, modelInfo.modelId)
+          && Objects.equals(modelType, modelInfo.modelType)
+          && Objects.equals(category, modelInfo.category)
+          && Objects.equals(state, modelInfo.state);
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(modelId, modelType, category, state);
+    }
+  }
+}
diff --git 
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index 01c7de75ede..a30619f6762 100644
--- 
a/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++ 
b/iotdb-core/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -698,7 +698,7 @@ dropSubscription
 // AI Model 
=========================================================================================
 // ---- Create Model
 createModel
-    : CREATE MODEL modelName=identifier uriClause
+    : CREATE MODEL modelId=identifier uriClause
     | CREATE MODEL modelId=identifier (WITH HYPERPARAMETERS LR_BRACKET 
hparamPair (COMMA hparamPair)* RR_BRACKET)? FROM MODEL 
existingModelId=identifier ON DATASET LR_BRACKET trainingData RR_BRACKET
     ;
 
diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ModelManager.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ModelManager.java
index ad1a6bed4ed..e9d9ff97510 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ModelManager.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/ModelManager.java
@@ -82,7 +82,7 @@ public class ModelManager {
 
   public TSStatus dropModel(TDropModelReq req) {
     if (modelInfo.checkModelType(req.getModelId()) != ModelType.USER_DEFINED) {
-      return new TSStatus(TSStatusCode.MODEL_EXIST_ERROR.getStatusCode())
+      return new TSStatus(TSStatusCode.DROP_MODEL_ERROR.getStatusCode())
           .setMessage(String.format("Built-in model %s can't be removed", 
req.modelId));
     }
     if (!modelInfo.contain(req.modelId)) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
index 434419bf596..7cee0de1fb4 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
@@ -428,7 +428,7 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
     }
 
     // Get model metadata from configNode and do some check
-    String modelId = queryStatement.getModelName();
+    String modelId = queryStatement.getModelId();
     TSStatus status = modelFetcher.fetchModel(modelId, analysis);
     if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
       throw new GetModelInfoException(status.getMessage());
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 b3b10606d3e..a9282a88b43 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
@@ -52,7 +52,9 @@ import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.ShowFuncti
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.ShowPipePluginsTask;
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.ShowRegionTask;
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.ShowVariablesTask;
+import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.ai.CreateModelTask;
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.ai.CreateTrainingTask;
+import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.ai.DropModelTask;
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.ai.ShowModelsTask;
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.region.ExtendRegionTask;
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.region.MigrateRegionTask;
@@ -123,6 +125,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ClearCache;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ColumnDefinition;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateFunction;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateModel;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreatePipe;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreatePipePlugin;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateTable;
@@ -136,6 +139,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DescribeTable;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropColumn;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropDB;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropFunction;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropModel;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropPipe;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropPipePlugin;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropSubscription;
@@ -1362,8 +1366,27 @@ public class TableConfigTaskVisitor extends 
AstVisitor<IConfigTask, MPPQueryCont
         node.getModelId(), node.getParameters(), node.getExistingModelId(), 
node.getTargetSql());
   }
 
+  @Override
+  protected IConfigTask visitCreateModel(CreateModel node, MPPQueryContext 
context) {
+    context.setQueryType(QueryType.WRITE);
+    String uri = node.getUri();
+    if (uri != null && ExecutableManager.isUriTrusted(uri)) {
+      // user specified uri and that uri is trusted
+      return new CreateModelTask(node.getModelId(), uri);
+    }
+    // user specified uri and that uri is not trusted
+    throw new SemanticException(getUnTrustedUriErrorMsg(uri));
+  }
+
   @Override
   protected IConfigTask visitShowModels(ShowModels node, MPPQueryContext 
context) {
+    context.setQueryType(QueryType.READ);
     return new ShowModelsTask(node.getModelId());
   }
+
+  @Override
+  protected IConfigTask visitDropModel(DropModel node, MPPQueryContext 
context) {
+    context.setQueryType(QueryType.WRITE);
+    return new DropModelTask(node.getModelId());
+  }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TreeConfigTaskVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TreeConfigTaskVisitor.java
index 6bd1d0392d5..3aa4217cd8e 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TreeConfigTaskVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TreeConfigTaskVisitor.java
@@ -765,26 +765,26 @@ public class TreeConfigTaskVisitor extends 
StatementVisitor<IConfigTask, MPPQuer
   @Override
   public IConfigTask visitCreateModel(
       CreateModelStatement createModelStatement, MPPQueryContext context) {
-    if (createModelStatement.getUri() != null && 
isUriTrusted(createModelStatement.getUri())) {
-      // 1. user specified uri and that uri is trusted
-      // 2. user doesn't specify uri
-      return new CreateModelTask(createModelStatement, context);
+    String uri = createModelStatement.getUri();
+    if (uri != null && isUriTrusted(uri)) {
+      // user specified uri and that uri is trusted
+      return new CreateModelTask(createModelStatement.getModelId(), uri);
     } else {
       // user specified uri and that uri is not trusted
-      throw new 
SemanticException(getUnTrustedUriErrorMsg(createModelStatement.getUri()));
+      throw new SemanticException(getUnTrustedUriErrorMsg(uri));
     }
   }
 
   @Override
   public IConfigTask visitDropModel(
       DropModelStatement dropModelStatement, MPPQueryContext context) {
-    return new DropModelTask(dropModelStatement.getModelName());
+    return new DropModelTask(dropModelStatement.getModelId());
   }
 
   @Override
   public IConfigTask visitShowModels(
       ShowModelsStatement showModelsStatement, MPPQueryContext context) {
-    return new ShowModelsTask(showModelsStatement.getModelName());
+    return new ShowModelsTask(showModelsStatement.getModelId());
   }
 
   @Override
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 86e42530e11..e3c82de71ea 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
@@ -250,7 +250,6 @@ import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowClusterStatem
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowDatabaseStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowRegionStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTTLStatement;
-import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.model.CreateModelStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.AlterPipeStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.CreatePipePluginStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.CreatePipeStatement;
@@ -3300,13 +3299,11 @@ public class ClusterConfigTaskExecutor implements 
IConfigTaskExecutor {
   }
 
   @Override
-  public SettableFuture<ConfigTaskResult> createModel(
-      final CreateModelStatement createModelStatement, final MPPQueryContext 
context) {
+  public SettableFuture<ConfigTaskResult> createModel(String modelId, String 
uri) {
     final SettableFuture<ConfigTaskResult> future = SettableFuture.create();
     try (final ConfigNodeClient client =
         
CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)) {
-      final TCreateModelReq req =
-          new TCreateModelReq(createModelStatement.getModelName(), 
createModelStatement.getUri());
+      final TCreateModelReq req = new TCreateModelReq(modelId, uri);
       final TSStatus status = client.createModel(req);
       if (TSStatusCode.SUCCESS_STATUS.getStatusCode() != status.getCode()) {
         future.setException(new IoTDBException(status.message, status.code));
@@ -3320,11 +3317,11 @@ public class ClusterConfigTaskExecutor implements 
IConfigTaskExecutor {
   }
 
   @Override
-  public SettableFuture<ConfigTaskResult> dropModel(final String modelName) {
+  public SettableFuture<ConfigTaskResult> dropModel(final String modelId) {
     final SettableFuture<ConfigTaskResult> future = SettableFuture.create();
     try (final ConfigNodeClient client =
         
CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)) {
-      final TSStatus executionStatus = client.dropModel(new 
TDropModelReq(modelName));
+      final TSStatus executionStatus = client.dropModel(new 
TDropModelReq(modelId));
       if (TSStatusCode.SUCCESS_STATUS.getStatusCode() != 
executionStatus.getCode()) {
         future.setException(new IoTDBException(executionStatus.message, 
executionStatus.code));
       } else {
@@ -3337,13 +3334,13 @@ public class ClusterConfigTaskExecutor implements 
IConfigTaskExecutor {
   }
 
   @Override
-  public SettableFuture<ConfigTaskResult> showModels(final String modelName) {
+  public SettableFuture<ConfigTaskResult> showModels(final String modelId) {
     final SettableFuture<ConfigTaskResult> future = SettableFuture.create();
     try (final ConfigNodeClient client =
         
CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)) {
       final TShowModelReq req = new TShowModelReq();
-      if (modelName != null) {
-        req.setModelId(modelName);
+      if (modelId != null) {
+        req.setModelId(modelId);
       }
       final TShowModelResp showModelResp = client.showModel(req);
       if (showModelResp.getStatus().getCode() != 
TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
index 11df7b6f689..fe1f36b1b5d 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java
@@ -62,7 +62,6 @@ import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowClusterStatem
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowDatabaseStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowRegionStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.ShowTTLStatement;
-import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.model.CreateModelStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.AlterPipeStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.CreatePipePluginStatement;
 import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.pipe.CreatePipeStatement;
@@ -415,12 +414,11 @@ public interface IConfigTaskExecutor {
   SettableFuture<ConfigTaskResult> showCurrentTimestamp();
 
   // =============================== AI 
=========================================
-  SettableFuture<ConfigTaskResult> createModel(
-      CreateModelStatement createModelStatement, MPPQueryContext context);
+  SettableFuture<ConfigTaskResult> createModel(String modelId, String uri);
 
-  SettableFuture<ConfigTaskResult> dropModel(String modelName);
+  SettableFuture<ConfigTaskResult> dropModel(String modelId);
 
-  SettableFuture<ConfigTaskResult> showModels(String modelName);
+  SettableFuture<ConfigTaskResult> showModels(String modelId);
 
   SettableFuture<ConfigTaskResult> createTraining(
       String modelId,
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/ai/CreateModelTask.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/ai/CreateModelTask.java
index 875455529b5..6f488a0e7bf 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/ai/CreateModelTask.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/ai/CreateModelTask.java
@@ -19,27 +19,25 @@
 
 package org.apache.iotdb.db.queryengine.plan.execution.config.metadata.ai;
 
-import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import org.apache.iotdb.db.queryengine.plan.execution.config.ConfigTaskResult;
 import org.apache.iotdb.db.queryengine.plan.execution.config.IConfigTask;
 import 
org.apache.iotdb.db.queryengine.plan.execution.config.executor.IConfigTaskExecutor;
-import 
org.apache.iotdb.db.queryengine.plan.statement.metadata.model.CreateModelStatement;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
 public class CreateModelTask implements IConfigTask {
 
-  private final CreateModelStatement createModelStatement;
-  private final MPPQueryContext context;
+  private final String modelId;
+  private final String uri;
 
-  public CreateModelTask(CreateModelStatement createModelStatement, 
MPPQueryContext context) {
-    this.createModelStatement = createModelStatement;
-    this.context = context;
+  public CreateModelTask(String modelId, String uri) {
+    this.modelId = modelId;
+    this.uri = uri;
   }
 
   @Override
   public ListenableFuture<ConfigTaskResult> execute(IConfigTaskExecutor 
configTaskExecutor)
       throws InterruptedException {
-    return configTaskExecutor.createModel(createModelStatement, context);
+    return configTaskExecutor.createModel(modelId, uri);
   }
 }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
index ad84c41b262..b30dd297153 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/parser/ASTVisitor.java
@@ -1354,19 +1354,19 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
   }
 
   // Create Model 
=====================================================================
-  public static void validateModelName(String modelName) {
-    if (modelName.length() < 2 || modelName.length() > 64) {
-      throw new SemanticException("Model name should be 2-64 characters");
-    } else if (modelName.startsWith("_")) {
-      throw new SemanticException("Model name should not start with '_'");
-    } else if (!modelName.matches("^[-\\w]*$")) {
-      throw new SemanticException("ModelName can only contain letters, 
numbers, and underscores");
+  public static void validateModelId(String modelId) {
+    if (modelId.length() < 2 || modelId.length() > 64) {
+      throw new SemanticException("ModelId should be 2-64 characters");
+    } else if (modelId.startsWith("_")) {
+      throw new SemanticException("ModelId should not start with '_'");
+    } else if (!modelId.matches("^[-\\w]*$")) {
+      throw new SemanticException("ModelId can only contain letters, numbers, 
and underscores");
     }
   }
 
   @Override
   public Statement visitCreateModel(IoTDBSqlParser.CreateModelContext ctx) {
-    if (ctx.modelName == null) {
+    if (ctx.uriClause() == null) {
       String modelId = ctx.modelId.getText();
       CreateTrainingStatement createTrainingStatement = new 
CreateTrainingStatement(modelId);
       if (ctx.hparamPair() != null) {
@@ -1404,10 +1404,10 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
       createTrainingStatement.setTargetPathPatterns(targetPath);
       return createTrainingStatement;
     }
-    String modelName = ctx.modelName.getText();
-    validateModelName(modelName);
+    String modelId = ctx.modelId.getText();
+    validateModelId(modelId);
     CreateModelStatement createModelStatement = new CreateModelStatement();
-    createModelStatement.setModelName(parseIdentifier(modelName));
+    createModelStatement.setModelId(parseIdentifier(modelId));
     createModelStatement.setUri(parseAndValidateURI(ctx.uriClause()));
     return createModelStatement;
   }
@@ -1423,7 +1423,7 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
   public Statement visitShowModels(IoTDBSqlParser.ShowModelsContext ctx) {
     ShowModelsStatement statement = new ShowModelsStatement();
     if (ctx.modelId != null) {
-      statement.setModelName(parseIdentifier(ctx.modelId.getText()));
+      statement.setModelId(parseIdentifier(ctx.modelId.getText()));
     }
     return statement;
   }
@@ -4571,7 +4571,7 @@ public class ASTVisitor extends 
IoTDBSqlParserBaseVisitor<Statement> {
         (QueryStatement)
             StatementGenerator.createStatement(sql.substring(1, sql.length() - 
1), zoneId);
 
-    statement.setModelName(parseIdentifier(ctx.modelId.getText()));
+    statement.setModelId(parseIdentifier(ctx.modelId.getText()));
     statement.setHasModelInference(true);
 
     if (ctx.hparamPair() != null) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
index fd3eda8e6f0..a7a4fdbc305 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java
@@ -725,10 +725,18 @@ public abstract class AstVisitor<R, C> {
     return visitStatement(node, context);
   }
 
+  protected R visitCreateModel(CreateModel node, C context) {
+    return visitStatement(node, context);
+  }
+
   protected R visitShowModels(ShowModels node, C context) {
     return visitStatement(node, context);
   }
 
+  protected R visitDropModel(DropModel node, C context) {
+    return visitStatement(node, context);
+  }
+
   public R visitTableArgument(TableFunctionTableArgument 
tableFunctionTableArgument, C context) {
     return visitNode(tableFunctionTableArgument, context);
   }
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CreateModel.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CreateModel.java
new file mode 100644
index 00000000000..f2132aab440
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CreateModel.java
@@ -0,0 +1,72 @@
+/*
+ * 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.sql.ast;
+
+import java.util.List;
+import java.util.Objects;
+
+public class CreateModel extends Statement {
+
+  private final String modelId;
+  private final String uri;
+
+  public CreateModel(String modelId, String uri) {
+    super(null);
+    this.modelId = modelId;
+    this.uri = uri;
+  }
+
+  public String getModelId() {
+    return modelId;
+  }
+
+  public String getUri() {
+    return uri;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitCreateModel(this, context);
+  }
+
+  @Override
+  public List<? extends Node> getChildren() {
+    return null;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    CreateModel that = (CreateModel) o;
+    return Objects.equals(modelId, that.modelId) && Objects.equals(uri, 
that.uri);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(modelId, uri);
+  }
+
+  @Override
+  public String toString() {
+    return "CreateModel{" + "modelId='" + modelId + '\'' + ", uri='" + uri + 
'\'' + '}';
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DropModel.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DropModel.java
new file mode 100644
index 00000000000..780b7c38f9a
--- /dev/null
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/DropModel.java
@@ -0,0 +1,64 @@
+/*
+ * 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.sql.ast;
+
+import java.util.List;
+import java.util.Objects;
+
+public class DropModel extends Statement {
+
+  private final String modelId;
+
+  public DropModel(String modelId) {
+    super(null);
+    this.modelId = modelId;
+  }
+
+  public String getModelId() {
+    return modelId;
+  }
+
+  @Override
+  public <R, C> R accept(AstVisitor<R, C> visitor, C context) {
+    return visitor.visitDropModel(this, context);
+  }
+
+  @Override
+  public List<? extends Node> getChildren() {
+    return null;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (o == null || getClass() != o.getClass()) return false;
+    DropModel dropModel = (DropModel) o;
+    return Objects.equals(modelId, dropModel.modelId);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(modelId);
+  }
+
+  @Override
+  public String toString() {
+    return "DropModel{" + "modelId='" + modelId + '\'' + '}';
+  }
+}
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
index 26fd39070fd..76c22001c40 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java
@@ -58,6 +58,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountStatement;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateFunction;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateIndex;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateModel;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreatePipe;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreatePipePlugin;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateTable;
@@ -78,6 +79,7 @@ import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropColumn;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropDB;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropFunction;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropIndex;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropModel;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropPipe;
 import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropPipePlugin;
 import 
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.DropSubscription;
@@ -3544,51 +3546,63 @@ public class AstBuilder extends 
RelationalSqlBaseVisitor<Node> {
   }
 
   // ***************** AI *****************
-  public static void validateModelName(String modelName) {
-    if (modelName.length() < 2 || modelName.length() > 64) {
-      throw new SemanticException("Model name should be 2-64 characters");
-    } else if (modelName.startsWith("_")) {
-      throw new SemanticException("Model name should not start with '_'");
-    } else if (!modelName.matches("^[-\\w]*$")) {
-      throw new SemanticException("ModelName can only contain letters, 
numbers, and underscores");
+  public static void validateModelId(String modelId) {
+    if (modelId.length() < 2 || modelId.length() > 64) {
+      throw new SemanticException("ModelId should be 2-64 characters");
+    } else if (modelId.startsWith("_")) {
+      throw new SemanticException("ModelId should not start with '_'");
+    } else if (!modelId.matches("^[-\\w]*$")) {
+      throw new SemanticException("ModelId can only contain letters, numbers, 
and underscores");
     }
   }
 
   @Override
   public Node 
visitCreateModelStatement(RelationalSqlParser.CreateModelStatementContext ctx) {
     String modelId = ctx.modelId.getText();
-    validateModelName(modelId);
-
-    if (ctx.targetData == null) {
-      throw new SemanticException("Target data in sql should be set in CREATE 
MODEL");
-    }
-    String targetData = ((StringLiteral) visit(ctx.targetData)).getValue();
-    CreateTraining createTraining = new CreateTraining(modelId, targetData);
-    if (ctx.HYPERPARAMETERS() != null) {
-      Map<String, String> parameters = new HashMap<>();
-      for (RelationalSqlParser.HparamPairContext hparamPairContext : 
ctx.hparamPair()) {
-        parameters.put(
-            hparamPairContext.hparamKey.getText(), 
hparamPairContext.hyparamValue.getText());
+    validateModelId(modelId);
+    if (ctx.uriClause() == null) {
+      if (ctx.targetData == null) {
+        throw new SemanticException("Target data in sql should be set in 
CREATE MODEL");
+      }
+      String targetData = ((StringLiteral) visit(ctx.targetData)).getValue();
+      CreateTraining createTraining = new CreateTraining(modelId, targetData);
+      if (ctx.HYPERPARAMETERS() != null) {
+        Map<String, String> parameters = new HashMap<>();
+        for (RelationalSqlParser.HparamPairContext hparamPairContext : 
ctx.hparamPair()) {
+          parameters.put(
+              hparamPairContext.hparamKey.getText(), 
hparamPairContext.hyparamValue.getText());
+        }
+        createTraining.setParameters(parameters);
       }
-      createTraining.setParameters(parameters);
-    }
 
-    if (ctx.existingModelId != null) {
-      createTraining.setExistingModelId(ctx.existingModelId.getText());
-    }
+      if (ctx.existingModelId != null) {
+        createTraining.setExistingModelId(ctx.existingModelId.getText());
+      }
 
-    return createTraining;
+      return createTraining;
+    }
+    String uri = ((Identifier) visit(ctx.uriClause().uri)).getValue();
+    return new CreateModel(modelId, uri);
   }
 
   @Override
   public Node 
visitShowModelsStatement(RelationalSqlParser.ShowModelsStatementContext ctx) {
     ShowModels showModels = new ShowModels();
     if (ctx.modelId != null) {
-      showModels.setModelId(ctx.modelId.getText());
+      String modelId = ctx.modelId.getText();
+      validateModelId(modelId);
+      showModels.setModelId(modelId);
     }
     return showModels;
   }
 
+  @Override
+  public Node 
visitDropModelStatement(RelationalSqlParser.DropModelStatementContext ctx) {
+    String modelId = ctx.modelId.getText();
+    validateModelId(modelId);
+    return new DropModel(modelId);
+  }
+
   // ***************** arguments *****************
   @Override
   public Node visitGenericType(RelationalSqlParser.GenericTypeContext ctx) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/QueryStatement.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/QueryStatement.java
index 1993def2326..ba4ac07ae87 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/QueryStatement.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/QueryStatement.java
@@ -137,7 +137,7 @@ public class QueryStatement extends 
AuthorityInformationStatement {
   private boolean isResultSetEmpty = false;
 
   // [IoTDB-AI] used for model inference, which will be removed in the future
-  private String modelName;
+  private String modelId;
   private boolean hasModelInference = false;
   private boolean generateTime = false;
   private InferenceWindow inferenceWindow = null;
@@ -151,12 +151,12 @@ public class QueryStatement extends 
AuthorityInformationStatement {
     return generateTime;
   }
 
-  public void setModelName(String modelName) {
-    this.modelName = modelName;
+  public void setModelId(String modelId) {
+    this.modelId = modelId;
   }
 
-  public String getModelName() {
-    return modelName;
+  public String getModelId() {
+    return modelId;
   }
 
   public void setHasModelInference(boolean hasModelInference) {
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/model/CreateModelStatement.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/model/CreateModelStatement.java
index e54792ac831..c99462bc3d1 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/model/CreateModelStatement.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/model/CreateModelStatement.java
@@ -34,7 +34,7 @@ import java.util.List;
 
 public class CreateModelStatement extends Statement implements 
IConfigStatement {
 
-  private String modelName;
+  private String modelId;
 
   private String uri;
 
@@ -46,16 +46,16 @@ public class CreateModelStatement extends Statement 
implements IConfigStatement
     return uri;
   }
 
-  public String getModelName() {
-    return modelName;
+  public String getModelId() {
+    return modelId;
   }
 
   public void setUri(String uri) {
     this.uri = uri;
   }
 
-  public void setModelName(String modelName) {
-    this.modelName = modelName;
+  public void setModelId(String modelId) {
+    this.modelId = modelId;
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/model/DropModelStatement.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/model/DropModelStatement.java
index 21871b58751..1273cde4fac 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/model/DropModelStatement.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/model/DropModelStatement.java
@@ -34,14 +34,14 @@ import java.util.List;
 
 public class DropModelStatement extends Statement implements IConfigStatement {
 
-  private final String modelName;
+  private final String modelId;
 
-  public DropModelStatement(String modelName) {
-    this.modelName = modelName;
+  public DropModelStatement(String modelId) {
+    this.modelId = modelId;
   }
 
-  public String getModelName() {
-    return modelName;
+  public String getModelId() {
+    return modelId;
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/model/ShowModelsStatement.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/model/ShowModelsStatement.java
index 50241dad114..4675ed8980c 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/model/ShowModelsStatement.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/metadata/model/ShowModelsStatement.java
@@ -34,22 +34,22 @@ import java.util.List;
 
 public class ShowModelsStatement extends Statement implements IConfigStatement 
{
 
-  private String modelName;
+  private String modelId;
 
   public ShowModelsStatement() {
     // do nothing
   }
 
-  public void setModelName(String modelName) {
-    this.modelName = modelName;
+  public void setModelId(String modelId) {
+    this.modelId = modelId;
   }
 
   public boolean isSetModelName() {
-    return modelName != null;
+    return modelId != null;
   }
 
-  public String getModelName() {
-    return modelName;
+  public String getModelId() {
+    return modelId;
   }
 
   @Override
diff --git 
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
 
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
index 91bb547c27f..de9d62dcd21 100644
--- 
a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
+++ 
b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4
@@ -162,6 +162,7 @@ statement
 
     // AI
     | createModelStatement
+    | dropModelStatement
     | showModelsStatement
 
     // View, Trigger, CQ, Quota are not supported yet
@@ -782,13 +783,18 @@ revokeGrantOpt
 // ------------------------------------------- AI 
---------------------------------------------------------
 
 createModelStatement
-    : CREATE MODEL modelId=identifier (WITH HYPERPARAMETERS '(' hparamPair 
(',' hparamPair)* ')')? FROM MODEL existingModelId=identifier ON DATASET '(' 
targetData=string ')'
+    : CREATE MODEL modelId=identifier uriClause
+    | CREATE MODEL modelId=identifier (WITH HYPERPARAMETERS '(' hparamPair 
(',' hparamPair)* ')')? FROM MODEL existingModelId=identifier ON DATASET '(' 
targetData=string ')'
     ;
 
 hparamPair
     : hparamKey=identifier '=' hyparamValue=primaryExpression
     ;
 
+dropModelStatement
+    : DROP MODEL modelId=identifier
+    ;
+
 showModelsStatement
     : SHOW MODELS
     | SHOW MODELS modelId=identifier

Reply via email to