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 <[email protected]>
AuthorDate: Sun Jun 18 10:10:51 2023 +0800
[CALCITE-5688] Support TRUNCATE TABLE DDL statement in server parser
Co-authored-by: sumeetgajjar <[email protected]>
---
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