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

jiajunxie pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new fb6f43192c [CALCITE-5688] Support TRUNCATE TABLE DDL statement in 
server parser
fb6f43192c is described below

commit fb6f43192c4253caea63c0705067a9aa12a3fa74
Author: xiejiajun <jiajunbernou...@foxmail.com>
AuthorDate: Sun Jun 18 10:10:51 2023 +0800

    [CALCITE-5688] Support TRUNCATE TABLE DDL statement in server parser
    
    Co-authored-by: sumeetgajjar <sumeetgajja...@gmail.com>
---
 core/src/main/codegen/default_config.fmpp          |  6 ++
 core/src/main/codegen/templates/Parser.jj          | 28 +++++++++
 .../main/java/org/apache/calcite/sql/SqlKind.java  |  5 +-
 .../java/org/apache/calcite/sql/SqlTruncate.java   | 33 +++++++++++
 .../org/apache/calcite/sql/ddl/SqlDdlNodes.java    |  6 ++
 .../apache/calcite/sql/ddl/SqlTruncateTable.java   | 66 ++++++++++++++++++++++
 server/src/main/codegen/config.fmpp                |  8 +++
 server/src/main/codegen/includes/parserImpls.ftl   | 19 +++++++
 .../apache/calcite/server/ServerDdlExecutor.java   | 38 +++++++++++++
 .../org/apache/calcite/test/ServerParserTest.java  | 11 ++++
 .../java/org/apache/calcite/test/ServerTest.java   | 15 +++++
 server/src/test/resources/sql/table.iq             | 19 +++++++
 12 files changed, 253 insertions(+), 1 deletion(-)

diff --git a/core/src/main/codegen/default_config.fmpp 
b/core/src/main/codegen/default_config.fmpp
index 8c6fa48470..6a172a6ef7 100644
--- a/core/src/main/codegen/default_config.fmpp
+++ b/core/src/main/codegen/default_config.fmpp
@@ -424,6 +424,12 @@ parser: {
   dropStatementParserMethods: [
   ]
 
+  # List of methods for parsing extensions to "TRUNCATE" calls.
+  # Each must accept arguments "(SqlParserPos pos)".
+  # Example: "SqlTruncate".
+  truncateStatementParserMethods: [
+  ]
+
   # Binary operators tokens.
   # Example: "< INFIX_CAST: \"::\" >".
   binaryOperatorsTokens: [
diff --git a/core/src/main/codegen/templates/Parser.jj 
b/core/src/main/codegen/templates/Parser.jj
index 56e44c06e8..822f6a407b 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -1136,6 +1136,10 @@ SqlNode SqlStmt() :
 <#if 
(parser.dropStatementParserMethods!default.parser.dropStatementParserMethods)?size
 != 0>
         stmt = SqlDrop()
     |
+</#if>
+<#if 
(parser.truncateStatementParserMethods!default.parser.truncateStatementParserMethods)?size
 != 0>
+        stmt = SqlTruncate()
+    |
 </#if>
         stmt = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY)
     |
@@ -4354,6 +4358,30 @@ SqlDrop SqlDrop() :
 }
 </#if>
 
+<#if 
(parser.truncateStatementParserMethods!default.parser.truncateStatementParserMethods)?size
 != 0>
+/**
+ * Parses a TRUNCATE statement.
+ */
+SqlTruncate SqlTruncate() :
+{
+    final Span s;
+    final SqlTruncate truncate;
+}
+{
+    <TRUNCATE> { s = span(); }
+    (
+<#-- additional literal parser methods are included here -->
+<#list 
(parser.truncateStatementParserMethods!default.parser.truncateStatementParserMethods)
 as method>
+        truncate = ${method}(s)
+        <#sep>|</#sep>
+</#list>
+    )
+    {
+        return truncate;
+    }
+}
+</#if>
+
 /**
  * Parses a literal expression, allowing continued string literals.
  * Usually returns an SqlLiteral, but a continued string literal
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlKind.java 
b/core/src/main/java/org/apache/calcite/sql/SqlKind.java
index b7cbd3f65f..c98a0ccf49 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlKind.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlKind.java
@@ -1158,6 +1158,9 @@ public enum SqlKind {
   /** {@code DROP TABLE} DDL statement. */
   DROP_TABLE,
 
+  /** {@code TRUNCATE TABLE} DDL statement. */
+  TRUNCATE_TABLE,
+
   /** {@code CREATE VIEW} DDL statement. */
   CREATE_VIEW,
 
@@ -1269,7 +1272,7 @@ public enum SqlKind {
   public static final EnumSet<SqlKind> DDL =
       EnumSet.of(COMMIT, ROLLBACK, ALTER_SESSION,
           CREATE_SCHEMA, CREATE_FOREIGN_SCHEMA, DROP_SCHEMA,
-          CREATE_TABLE, ALTER_TABLE, DROP_TABLE,
+          CREATE_TABLE, ALTER_TABLE, DROP_TABLE, TRUNCATE_TABLE,
           CREATE_FUNCTION, DROP_FUNCTION,
           CREATE_VIEW, ALTER_VIEW, DROP_VIEW,
           CREATE_MATERIALIZED_VIEW, ALTER_MATERIALIZED_VIEW,
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlTruncate.java 
b/core/src/main/java/org/apache/calcite/sql/SqlTruncate.java
new file mode 100644
index 0000000000..d8e75bb312
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/sql/SqlTruncate.java
@@ -0,0 +1,33 @@
+/*
+ * 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.calcite.sql;
+
+import org.apache.calcite.sql.parser.SqlParserPos;
+
+/**
+ * Base class for an TRUNCATE statements parse tree nodes. The portion of the 
statement covered by
+ * this class is "TRUNCATE". Subclasses handle whatever comes afterwards.
+ */
+public abstract class SqlTruncate extends SqlDdl {
+
+  /**
+   * Creates a SqlTruncate.
+   */
+  protected SqlTruncate(SqlOperator operator, SqlParserPos pos) {
+    super(operator, pos);
+  }
+}
diff --git a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDdlNodes.java 
b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDdlNodes.java
index 8454809418..acc2fd6d3b 100644
--- a/core/src/main/java/org/apache/calcite/sql/ddl/SqlDdlNodes.java
+++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlDdlNodes.java
@@ -101,6 +101,12 @@ public class SqlDdlNodes {
     return new SqlDropTable(pos, ifExists, name);
   }
 
+  /** Creates a TRUNCATE TABLE. */
+  public static SqlTruncateTable truncateTable(SqlParserPos pos,
+      SqlIdentifier name, boolean continueIdentity) {
+    return new SqlTruncateTable(pos, name, continueIdentity);
+  }
+
   /** Creates a DROP VIEW. */
   public static SqlDrop dropView(SqlParserPos pos, boolean ifExists,
       SqlIdentifier name) {
diff --git 
a/core/src/main/java/org/apache/calcite/sql/ddl/SqlTruncateTable.java 
b/core/src/main/java/org/apache/calcite/sql/ddl/SqlTruncateTable.java
new file mode 100644
index 0000000000..2d82107efc
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/sql/ddl/SqlTruncateTable.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.sql.ddl;
+
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSpecialOperator;
+import org.apache.calcite.sql.SqlTruncate;
+import org.apache.calcite.sql.SqlWriter;
+import org.apache.calcite.sql.parser.SqlParserPos;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * Parse tree for {@code TRUNCATE TABLE} statement.
+ */
+public class SqlTruncateTable extends SqlTruncate {
+
+  private static final SqlOperator OPERATOR =
+      new SqlSpecialOperator("TRUNCATE TABLE", SqlKind.TRUNCATE_TABLE);
+  public final SqlIdentifier name;
+  public final boolean continueIdentify;
+
+  /**
+   * Creates a SqlTruncateTable.
+   */
+  public SqlTruncateTable(SqlParserPos pos, SqlIdentifier name, boolean 
continueIdentify) {
+    super(OPERATOR, pos);
+    this.name = name;
+    this.continueIdentify = continueIdentify;
+  }
+
+  @Override public List<SqlNode> getOperandList() {
+    return ImmutableList.of(name);
+  }
+
+  @Override public void unparse(SqlWriter writer, int leftPrec, int rightPrec) 
{
+    writer.keyword("TRUNCATE");
+    writer.keyword("TABLE");
+    name.unparse(writer, leftPrec, rightPrec);
+    if (continueIdentify) {
+      writer.keyword("CONTINUE IDENTITY");
+    } else {
+      writer.keyword("RESTART IDENTITY");
+
+    }
+  }
+}
diff --git a/server/src/main/codegen/config.fmpp 
b/server/src/main/codegen/config.fmpp
index 448357e9ec..731d569cb2 100644
--- a/server/src/main/codegen/config.fmpp
+++ b/server/src/main/codegen/config.fmpp
@@ -29,6 +29,7 @@ data: {
       "org.apache.calcite.schema.ColumnStrategy"
       "org.apache.calcite.sql.SqlCreate"
       "org.apache.calcite.sql.SqlDrop"
+      "org.apache.calcite.sql.SqlTruncate"
       "org.apache.calcite.sql.ddl.SqlDdlNodes"
     ]
 
@@ -82,6 +83,13 @@ data: {
       "SqlDropFunction"
     ]
 
+  # List of methods for parsing extensions to "TRUNCATE" calls.
+  # Each must accept arguments "(SqlParserPos pos)".
+  # Example: "SqlTruncateTable".
+  truncateStatementParserMethods: [
+    "SqlTruncateTable"
+  ]
+
     # List of files in @includes directory that have parser method
     # implementations for parsing custom SQL statements, literals or types
     # given as part of "statementParserMethods", "literalParserMethods" or
diff --git a/server/src/main/codegen/includes/parserImpls.ftl 
b/server/src/main/codegen/includes/parserImpls.ftl
index 5802a728f0..00e1f386e9 100644
--- a/server/src/main/codegen/includes/parserImpls.ftl
+++ b/server/src/main/codegen/includes/parserImpls.ftl
@@ -376,6 +376,25 @@ SqlDrop SqlDropTable(Span s, boolean replace) :
     }
 }
 
+SqlTruncate SqlTruncateTable(Span s) :
+{
+    final SqlIdentifier id;
+    final boolean continueIdentity;
+}
+{
+      <TABLE> id = CompoundIdentifier()
+    (
+      <CONTINUE> <IDENTITY> { continueIdentity = true; }
+      |
+      <RESTART> <IDENTITY> { continueIdentity = false; }
+      |
+      { continueIdentity = true; }
+    )
+    {
+        return SqlDdlNodes.truncateTable(s.end(this), id, continueIdentity);
+    }
+}
+
 SqlDrop SqlDropView(Span s, boolean replace) :
 {
     final boolean ifExists;
diff --git 
a/server/src/main/java/org/apache/calcite/server/ServerDdlExecutor.java 
b/server/src/main/java/org/apache/calcite/server/ServerDdlExecutor.java
index c028ae386e..467fc8ce27 100644
--- a/server/src/main/java/org/apache/calcite/server/ServerDdlExecutor.java
+++ b/server/src/main/java/org/apache/calcite/server/ServerDdlExecutor.java
@@ -65,6 +65,7 @@ import org.apache.calcite.sql.ddl.SqlCreateType;
 import org.apache.calcite.sql.ddl.SqlCreateView;
 import org.apache.calcite.sql.ddl.SqlDropObject;
 import org.apache.calcite.sql.ddl.SqlDropSchema;
+import org.apache.calcite.sql.ddl.SqlTruncateTable;
 import org.apache.calcite.sql.dialect.CalciteSqlDialect;
 import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlAbstractParserImpl;
@@ -182,6 +183,24 @@ public class ServerDdlExecutor extends DdlExecutorImpl {
         null, null, null, null, null);
   }
 
+  /** Erase the table date that calcite-sever created. */
+  static void erase(SqlIdentifier name, CalcitePrepare.Context context) {
+    // Directly clearing data is more efficient than executing SQL
+    final Pair<CalciteSchema, String> pair = schema(context, true, name);
+    final CalciteSchema calciteSchema = pair.left;
+    final String tblName = pair.right;
+    final Table table = calciteSchema
+        .getTable(tblName, context.config().caseSensitive())
+        .getTable();
+    if (table instanceof MutableArrayTable) {
+      MutableArrayTable mutableArrayTable = (MutableArrayTable) table;
+      mutableArrayTable.rows.clear();
+    } else {
+      // Not calcite-server created, so not support truncate.
+      throw new UnsupportedOperationException("Only MutableArrayTable support 
truncate");
+    }
+  }
+
   /** Populates the table called {@code name} by executing {@code query}. */
   static void populate(SqlIdentifier name, SqlNode query,
       CalcitePrepare.Context context) {
@@ -341,6 +360,25 @@ public class ServerDdlExecutor extends DdlExecutorImpl {
     }
   }
 
+  /**
+   * Executes a {@code TRUNCATE TABLE} command.
+   */
+  public void execute(SqlTruncateTable truncate,
+      CalcitePrepare.Context context) {
+    final Pair<CalciteSchema, String> pair = schema(context, true, 
truncate.name);
+    if (pair.left.plus().getTable(pair.right) == null) {
+      throw SqlUtil.newContextException(truncate.name.getParserPosition(),
+          RESOURCE.tableNotFound(pair.right));
+    }
+
+    if (!truncate.continueIdentify) {
+      // Calcite not support RESTART IDENTIFY
+      throw new UnsupportedOperationException("RESTART IDENTIFY is not 
supported");
+    }
+
+    erase(truncate.name, context);
+  }
+
   /** Executes a {@code CREATE MATERIALIZED VIEW} command. */
   public void execute(SqlCreateMaterializedView create,
       CalcitePrepare.Context context) {
diff --git a/server/src/test/java/org/apache/calcite/test/ServerParserTest.java 
b/server/src/test/java/org/apache/calcite/test/ServerParserTest.java
index 64ab59ef9c..bcbd8f5656 100644
--- a/server/src/test/java/org/apache/calcite/test/ServerParserTest.java
+++ b/server/src/test/java/org/apache/calcite/test/ServerParserTest.java
@@ -287,6 +287,17 @@ class ServerParserTest extends SqlParserTest {
         .ok("DROP TABLE IF EXISTS `X`");
   }
 
+  @Test void testTruncateTable() {
+    sql("truncate table x")
+        .ok("TRUNCATE TABLE `X` CONTINUE IDENTITY");
+
+    sql("truncate table x continue identity")
+        .ok("TRUNCATE TABLE `X` CONTINUE IDENTITY");
+
+    sql("truncate table x restart identity")
+        .ok("TRUNCATE TABLE `X` RESTART IDENTITY");
+  }
+
   @Test void testDropView() {
     sql("drop view x")
         .ok("DROP VIEW `X`");
diff --git a/server/src/test/java/org/apache/calcite/test/ServerTest.java 
b/server/src/test/java/org/apache/calcite/test/ServerTest.java
index bec633d68e..cc5fb2a4f7 100644
--- a/server/src/test/java/org/apache/calcite/test/ServerTest.java
+++ b/server/src/test/java/org/apache/calcite/test/ServerTest.java
@@ -34,6 +34,7 @@ import org.apache.calcite.sql.ddl.SqlCreateView;
 import org.apache.calcite.sql.ddl.SqlDropFunction;
 import org.apache.calcite.sql.ddl.SqlDropMaterializedView;
 import org.apache.calcite.sql.ddl.SqlDropSchema;
+import org.apache.calcite.sql.ddl.SqlTruncateTable;
 
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
@@ -102,6 +103,7 @@ class ServerTest {
     executor.execute((SqlDropMaterializedView) o, context);
     executor.execute((SqlDropFunction) o, context);
     executor.execute((SqlDropSchema) o, context);
+    executor.execute((SqlTruncateTable) o, context);
   }
 
   @Test void testStatement() throws Exception {
@@ -223,6 +225,19 @@ class ServerTest {
     }
   }
 
+  @Test void testTruncateTable() throws Exception {
+    try (Connection c = connect();
+        Statement s = c.createStatement()) {
+      final boolean b = s.execute("create table t (i int not null)");
+      assertThat(b, is(false));
+
+      final String errMsg =
+          assertThrows(SQLException.class,
+              () -> s.execute("truncate table t restart 
identity")).getMessage();
+      assertThat(errMsg, containsString("RESTART IDENTIFY is not supported"));
+    }
+  }
+
   @Test void testCreateFunction() throws Exception {
     try (Connection c = connect();
          Statement s = c.createStatement()) {
diff --git a/server/src/test/resources/sql/table.iq 
b/server/src/test/resources/sql/table.iq
index 54f814a0ae..5f916c7254 100755
--- a/server/src/test/resources/sql/table.iq
+++ b/server/src/test/resources/sql/table.iq
@@ -50,6 +50,21 @@ select * from t;
 
 !ok
 
+
+truncate table t;
+(0 rows modified)
+
+!update
+
+select * from t;
++---+---+
+| I | J |
++---+---+
++---+---+
+(0 rows)
+
+!ok
+
 drop table t;
 (0 rows modified)
 
@@ -215,4 +230,8 @@ drop table if exists t;
 
 !update
 
+truncate table t;
+Table 'T' not found
+!error
+
 # End table.iq

Reply via email to