You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by dm...@apache.org on 2023/03/23 07:56:00 UTC
[calcite] branch main updated: [CALCITE-5403] Babel parser should parse PostgreSQL's SET, RESET, BEGIN, SHOW, ROLLBACK, COMMIT commands
This is an automated email from the ASF dual-hosted git repository.
dmsysolyatin 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 62024984f0 [CALCITE-5403] Babel parser should parse PostgreSQL's SET, RESET, BEGIN, SHOW, ROLLBACK, COMMIT commands
62024984f0 is described below
commit 62024984f0d4058c57899ac3d0cac674fac6fb18
Author: dssysolyatin <dm...@gmail.com>
AuthorDate: Mon Nov 28 20:06:59 2022 +0200
[CALCITE-5403] Babel parser should parse PostgreSQL's SET, RESET, BEGIN, SHOW, ROLLBACK, COMMIT commands
---
babel/src/main/codegen/config.fmpp | 26 ++
.../codegen/includes/parserPostgresqlImpls.ftl | 264 +++++++++++++++++++++
.../calcite/sql/babel/postgresql/AndChain.java | 36 +++
.../calcite/sql/babel/postgresql/SqlBegin.java | 89 +++++++
.../calcite/sql/babel/postgresql/SqlCommit.java | 71 ++++++
.../calcite/sql/babel/postgresql/SqlDiscard.java | 70 ++++++
.../calcite/sql/babel/postgresql/SqlRollback.java | 71 ++++++
.../calcite/sql/babel/postgresql/SqlShow.java | 74 ++++++
.../calcite/sql/babel/postgresql/package-info.java | 21 ++
.../org/apache/calcite/test/BabelParserTest.java | 80 +++++++
10 files changed, 802 insertions(+)
diff --git a/babel/src/main/codegen/config.fmpp b/babel/src/main/codegen/config.fmpp
index eb0d5f1ef6..a61dee55e2 100644
--- a/babel/src/main/codegen/config.fmpp
+++ b/babel/src/main/codegen/config.fmpp
@@ -30,14 +30,25 @@ data: {
"org.apache.calcite.sql.SqlCreate",
"org.apache.calcite.sql.babel.SqlBabelCreateTable",
"org.apache.calcite.sql.babel.TableCollectionType",
+ "org.apache.calcite.sql.babel.postgresql.AndChain",
+ "org.apache.calcite.sql.babel.postgresql.SqlBegin",
+ "org.apache.calcite.sql.babel.postgresql.SqlCommit",
+ "org.apache.calcite.sql.babel.postgresql.SqlDiscard",
+ "org.apache.calcite.sql.babel.postgresql.SqlRollback",
+ "org.apache.calcite.sql.babel.postgresql.SqlShow",
"org.apache.calcite.sql.ddl.SqlDdlNodes",
]
# List of new keywords. Example: "DATABASES", "TABLES". If the keyword is
# not a reserved keyword, add it to the 'nonReservedKeywords' section.
keywords: [
+ "DISCARD"
"IF"
+ "PLANS"
+ "SEED"
"SEMI"
+ "SEQUENCES"
+ "TEMP"
"VOLATILE"
]
@@ -45,8 +56,13 @@ data: {
# items in this list become non-reserved
nonReservedKeywordsToAdd: [
# not in core, added in babel
+ "DISCARD"
"IF"
+ "PLANS"
+ "SEED"
"SEMI"
+ "SEQUENCES"
+ "TEMP"
# The following keywords are reserved in core Calcite,
# are reserved in some version of SQL,
@@ -544,6 +560,15 @@ data: {
createStatementParserMethods: [
"SqlCreateTable"
]
+
+ statementParserMethods: [
+ "PostgresqlSqlShow()",
+ "PostgresqlSqlSetOption()",
+ "PostgresqlSqlBegin()",
+ "PostgresqlSqlDiscard()",
+ "PostgresqlSqlCommit()",
+ "PostgresqlSqlRollback()"
+ ]
# Binary operators tokens.
# Example: "< INFIX_CAST: \"::\" >".
@@ -566,6 +591,7 @@ data: {
# Example: "parserImpls.ftl".
implementationFiles: [
"parserImpls.ftl"
+ "parserPostgresqlImpls.ftl"
]
includePosixOperators: true
diff --git a/babel/src/main/codegen/includes/parserPostgresqlImpls.ftl b/babel/src/main/codegen/includes/parserPostgresqlImpls.ftl
new file mode 100644
index 0000000000..fee70a58d7
--- /dev/null
+++ b/babel/src/main/codegen/includes/parserPostgresqlImpls.ftl
@@ -0,0 +1,264 @@
+<#--
+// 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.
+-->
+
+/** SHOW (<TRANSACTION ISOLATION LEVEL> | name) */
+SqlNode PostgresqlSqlShow() :
+{
+ final SqlIdentifier parameter;
+ final Span s;
+}
+{
+ <SHOW> { s = span(); }
+ (
+ parameter = PostgresqlTransactionIsolationLevel()
+|
+ <IDENTIFIER> {
+ parameter = new SqlIdentifier(token.image.toLowerCase(Locale.ROOT), getPos());
+ }
+ ) { return SqlShow.OPERATOR.createCall(null, s.end(this), parameter); }
+}
+
+SqlIdentifier PostgresqlTransactionIsolationLevel() :
+{
+ final Span s;
+}
+{
+ { s = span(); } <TRANSACTION> <ISOLATION> <LEVEL> {
+ return new SqlIdentifier("transaction_isolation", s.end(this));
+ }
+}
+
+/**
+ * SET [ SESSION | LOCAL ] configuration_parameter { TO | = } { value | 'value' | DEFAULT }
+ * SET [ SESSION | LOCAL ] TIME ZONE { value | 'value' | LOCAL | DEFAULT }
+ * SET [ SESSION | LOCAL ] (SCHEMA | NAMES | SEED) value
+ * value - Values can be specified as string constants, identifiers, numbers, or comma-separated lists of these
+ */
+SqlNode PostgresqlSqlSetOption() :
+{
+ SqlIdentifier name;
+ final SqlNode val;
+ String scope = null;
+ Span s;
+}
+{
+ { s = span(); }
+ (
+ <SET> {
+ s.add(this);
+ }
+ [ scope = PostgresqlOptionScope() ]
+ (
+ <TIME> <ZONE> { name = new SqlIdentifier("timezone", getPos()); }
+ (
+ val = Default()
+ |
+ <LOCAL> { val = SqlLiteral.createCharString("LOCAL", getPos()); }
+ |
+ val = Literal()
+ )
+ |
+ (
+ <SCHEMA> { name = new SqlIdentifier("search_path", getPos()); }
+ |
+ <NAMES> { name = new SqlIdentifier("client_encoding", getPos()); }
+ |
+ <SEED> { name = new SqlIdentifier("seed", getPos()); }
+ |
+ name = CompoundIdentifier()
+ ( <EQ> | <TO> )
+ )
+ val = PostgresqlSqlOptionValues()
+ ){
+ return new SqlSetOption(s.end(val), scope, name, val);
+ }
+
+ |
+ <RESET> {
+ s.add(this);
+ }
+ (
+ name = CompoundIdentifier()
+ |
+ <ALL> {
+ name = new SqlIdentifier(token.image.toUpperCase(Locale.ROOT),
+ getPos());
+ }
+ )
+ {
+ return new SqlSetOption(s.end(name), scope, name, null);
+ }
+ )
+}
+
+String PostgresqlOptionScope() :
+{
+}
+{
+ ( <LOCAL> | <SESSION> ) { return token.image.toUpperCase(Locale.ROOT); }
+}
+
+SqlNode PostgresqlSqlOptionValues():
+{
+ final List<SqlNode> list;
+ Span s;
+ SqlNode e;
+}
+{
+ e = PostgresqlSqlOptionValue() { s = span(); list = startList(e); }
+ ( <COMMA> e = PostgresqlSqlOptionValue() { list.add(e); } )*
+ {
+ return list.size() > 1 ? new SqlNodeList(list, s.end(this)) : e;
+ }
+}
+
+SqlNode PostgresqlSqlOptionValue():
+{
+ final SqlNode val;
+}
+{
+ (
+ val = Default()
+ |
+ val = Literal()
+ |
+ val = SimpleIdentifier()
+ ) {
+ return val;
+ }
+}
+
+/** DISCARD { ALL | PLANS | SEQUENCES | TEMPORARY | TEMP } */
+SqlNode PostgresqlSqlDiscard() :
+{
+ final Span s;
+}
+{
+ { s = span(); }
+ <DISCARD> ( <ALL> | <PLANS> | <SEQUENCES> | <TEMPORARY> | <TEMP> ) {
+ return SqlDiscard.OPERATOR.createCall(s.end(this), new SqlIdentifier(
+ token.image.toUpperCase(Locale.ROOT), getPos()));
+ }
+}
+
+/**
+ * BEGIN [ WORK | TRANSACTION ] [ transaction_mode [, ...] ]
+ * where transaction_mode is one of:
+ * ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
+ * READ WRITE | READ ONLY
+ * [ NOT ] DEFERRABLE
+ */
+SqlNode PostgresqlSqlBegin() :
+{
+ final Span s;
+ SqlNodeList transactionModeList = SqlNodeList.EMPTY;
+}
+{
+ { s = span(); }
+ <BEGIN> [ ( <WORK> | <TRANSACTION> ) ] [transactionModeList = PostgresqlSqlBeginTransactionModeList()] {
+ return SqlBegin.OPERATOR.createCall(s.end(this), (SqlNode) transactionModeList);
+ }
+}
+
+SqlNodeList PostgresqlSqlBeginTransactionModeList():
+{
+ final List<SqlNode> list;
+ Span s;
+ SqlNode e;
+}
+{
+ { s = span(); }
+ e = PostgresqlSqlBeginTransactionMode() { s = span(); list = startList(e); }
+ ( <COMMA> e = PostgresqlSqlBeginTransactionMode() { list.add(e); } )*
+ { return new SqlNodeList(list, s.end(this)); }
+}
+
+SqlNode PostgresqlSqlBeginTransactionMode():
+{
+ final Span s;
+ SqlBegin.TransactionMode m;
+}
+{
+ { s = span(); }
+(
+ LOOKAHEAD(2)
+ <READ>
+ (
+ <WRITE> { m = SqlBegin.TransactionMode.READ_WRITE; }
+ |
+ <ONLY> { m = SqlBegin.TransactionMode.READ_ONLY; }
+ )
+|
+ <DEFERRABLE> { m = SqlBegin.TransactionMode.DEFERRABLE; }
+|
+ <NOT> <DEFERRABLE> { m = SqlBegin.TransactionMode.NOT_DEFERRABLE; }
+|
+ <ISOLATION> <LEVEL>
+ (
+ <SERIALIZABLE> { m = SqlBegin.TransactionMode.ISOLATION_LEVEL_SERIALIZABLE; }
+ |
+ <REPEATABLE> <READ> { m = SqlBegin.TransactionMode.ISOLATION_LEVEL_REPEATABLE_READ; }
+ |
+ <READ>
+ (
+ <COMMITTED> { m = SqlBegin.TransactionMode.ISOLATION_LEVEL_READ_COMMITTED; }
+ |
+ <UNCOMMITTED> { m = SqlBegin.TransactionMode.ISOLATION_LEVEL_READ_UNCOMMITTED; }
+ )
+ )
+) {
+ return m.symbol(s.end(this));
+ }
+}
+
+/** COMMIT [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ] */
+SqlNode PostgresqlSqlCommit():
+{
+ final Span s;
+ AndChain chain = AndChain.AND_NO_CHAIN;
+}
+{
+ { s = span(); }
+ <COMMIT> [ <WORK> | <TRANSACTION> ] [
+ (
+ <AND> <CHAIN> { chain = AndChain.AND_CHAIN; }
+ |
+ <AND> <NO> <CHAIN>
+ )] {
+ final SqlParserPos pos = s.end(this);
+ return SqlCommit.OPERATOR.createCall(pos, chain.symbol(pos));
+ }
+}
+
+/** ROLLBACK [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ] */
+SqlNode PostgresqlSqlRollback():
+{
+ final Span s;
+ AndChain chain = AndChain.AND_NO_CHAIN;
+}
+{
+ { s = span(); }
+ <ROLLBACK> [ <WORK> | <TRANSACTION> ] [
+ (
+ <AND> <CHAIN> { chain = AndChain.AND_CHAIN; }
+ |
+ <AND> <NO> <CHAIN>
+ )] {
+ final SqlParserPos pos = s.end(this);
+ return SqlRollback.OPERATOR.createCall(pos, chain.symbol(pos));
+ }
+}
diff --git a/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/AndChain.java b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/AndChain.java
new file mode 100644
index 0000000000..f9129b5a04
--- /dev/null
+++ b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/AndChain.java
@@ -0,0 +1,36 @@
+/*
+ * 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.babel.postgresql;
+
+import org.apache.calcite.sql.Symbolizable;
+
+/**
+ * Defines the keywords that can occur immediately after the "ROLLBACK" or "COMMIT" keywords.
+ *
+ * @see SqlCommit
+ * @see SqlRollback
+ * @see <a href="https://www.postgresql.org/docs/current/sql-commit.html">COMMIT specification</a>
+ * @see <a href="https://www.postgresql.org/docs/current/sql-rollback.html">ROLLBACK specification</a>
+ */
+public enum AndChain implements Symbolizable {
+ AND_CHAIN,
+ AND_NO_CHAIN;
+
+ @Override public String toString() {
+ return super.toString().replace("_", " ");
+ }
+}
diff --git a/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlBegin.java b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlBegin.java
new file mode 100644
index 0000000000..bfd275c3ef
--- /dev/null
+++ b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlBegin.java
@@ -0,0 +1,89 @@
+/*
+ * 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.babel.postgresql;
+
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSpecialOperator;
+import org.apache.calcite.sql.SqlWriter;
+import org.apache.calcite.sql.Symbolizable;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.ReturnTypes;
+
+import com.google.common.collect.ImmutableList;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
+
+/**
+ * Parse tree node representing a {@code BEGIN} clause.
+ * @see <a href="https://www.postgresql.org/docs/current/sql-begin.html">BEGIN specification</a>
+ */
+public class SqlBegin extends SqlCall {
+ public static final SqlSpecialOperator OPERATOR =
+ new SqlSpecialOperator("BEGIN", SqlKind.OTHER_FUNCTION, 32, false, ReturnTypes.BOOLEAN, null,
+ null) {
+ @Override public SqlCall createCall(@Nullable final SqlLiteral functionQualifier,
+ final SqlParserPos pos,
+ final @Nullable SqlNode... operands) {
+ return new SqlBegin(pos, (SqlNodeList) operands[0]);
+ }
+ };
+
+ private final SqlNodeList transactionModeList;
+
+ protected SqlBegin(final SqlParserPos pos, final SqlNodeList transactionModeList) {
+ super(pos);
+ this.transactionModeList = transactionModeList;
+ }
+
+ @Override public SqlOperator getOperator() {
+ return OPERATOR;
+ }
+
+ @Override public List<SqlNode> getOperandList() {
+ return ImmutableList.of(transactionModeList);
+ }
+
+ @Override public void unparse(final SqlWriter writer, final int leftPrec, final int rightPrec) {
+ writer.keyword("BEGIN");
+ transactionModeList.unparse(writer, -1, -1);
+ }
+
+ /**
+ * Transaction mode.
+ */
+ public enum TransactionMode implements Symbolizable {
+ READ_WRITE,
+ READ_ONLY,
+ DEFERRABLE,
+ NOT_DEFERRABLE,
+ ISOLATION_LEVEL_SERIALIZABLE,
+ ISOLATION_LEVEL_REPEATABLE_READ,
+ ISOLATION_LEVEL_READ_COMMITTED,
+ ISOLATION_LEVEL_READ_UNCOMMITTED;
+
+ @Override public String toString() {
+ return super.toString().replace("_", " ");
+ }
+ }
+}
diff --git a/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlCommit.java b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlCommit.java
new file mode 100644
index 0000000000..8b9491803f
--- /dev/null
+++ b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlCommit.java
@@ -0,0 +1,71 @@
+/*
+ * 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.babel.postgresql;
+
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSpecialOperator;
+import org.apache.calcite.sql.SqlWriter;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.ReturnTypes;
+
+import com.google.common.collect.ImmutableList;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
+
+/**
+ * Parse tree node representing a {@code COMMIT} clause.
+ * @see <a href="https://www.postgresql.org/docs/current/sql-commit.html">COMMIT specification</a>
+ */
+public class SqlCommit extends SqlCall {
+
+ public static final SqlSpecialOperator OPERATOR =
+ new SqlSpecialOperator("COMMIT", SqlKind.OTHER_FUNCTION, 32, false, ReturnTypes.BOOLEAN, null,
+ null) {
+ @Override public SqlCall createCall(@Nullable final SqlLiteral functionQualifier,
+ final SqlParserPos pos,
+ final @Nullable SqlNode... operands) {
+ return new SqlCommit(pos, (SqlLiteral) operands[0]);
+ }
+ };
+ private final SqlLiteral chain;
+
+ protected SqlCommit(final SqlParserPos pos, final SqlLiteral chain) {
+ super(pos);
+ this.chain = chain;
+ }
+
+ @Override public SqlOperator getOperator() {
+ return OPERATOR;
+ }
+
+ @Override public List<SqlNode> getOperandList() {
+ return ImmutableList.of(this.chain);
+ }
+
+ @Override public void unparse(final SqlWriter writer, final int leftPrec, final int rightPrec) {
+ writer.keyword("COMMIT");
+ if (this.chain.symbolValue(AndChain.class) == AndChain.AND_CHAIN) {
+ writer.literal("AND CHAIN");
+ }
+ }
+}
diff --git a/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlDiscard.java b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlDiscard.java
new file mode 100644
index 0000000000..78adbd8574
--- /dev/null
+++ b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlDiscard.java
@@ -0,0 +1,70 @@
+/*
+ * 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.babel.postgresql;
+
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSpecialOperator;
+import org.apache.calcite.sql.SqlWriter;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.ReturnTypes;
+
+import com.google.common.collect.ImmutableList;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
+
+/**
+ * Parse tree node representing a {@code DISCARD} clause.
+ * @see <a href="https://www.postgresql.org/docs/current/sql-discard.html">DISCARD specification</a>
+ */
+public class SqlDiscard extends SqlCall {
+ public static final SqlSpecialOperator OPERATOR =
+ new SqlSpecialOperator("DISCARD", SqlKind.OTHER_FUNCTION, 32, false, ReturnTypes.BOOLEAN,
+ null, null) {
+ @Override public SqlCall createCall(@Nullable final SqlLiteral functionQualifier,
+ final SqlParserPos pos,
+ final @Nullable SqlNode... operands) {
+ return new SqlDiscard(pos, (SqlIdentifier) operands[0]);
+ }
+ };
+
+ private final SqlIdentifier subcommand;
+
+ public SqlDiscard(final SqlParserPos pos, final SqlIdentifier subcommand) {
+ super(pos);
+ this.subcommand = subcommand;
+ }
+
+ @Override public SqlOperator getOperator() {
+ return OPERATOR;
+ }
+
+ @Override public List<SqlNode> getOperandList() {
+ return ImmutableList.of(subcommand);
+ }
+
+ @Override public void unparse(final SqlWriter writer, final int leftPrec, final int rightPrec) {
+ writer.keyword("DISCARD");
+ writer.literal(subcommand.toString());
+ }
+}
diff --git a/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlRollback.java b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlRollback.java
new file mode 100644
index 0000000000..c400f0c843
--- /dev/null
+++ b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlRollback.java
@@ -0,0 +1,71 @@
+/*
+ * 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.babel.postgresql;
+
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSpecialOperator;
+import org.apache.calcite.sql.SqlWriter;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.ReturnTypes;
+
+import com.google.common.collect.ImmutableList;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
+
+/**
+ * Parse tree node representing a {@code ROLLBACK} clause.
+ * @see <a href="https://www.postgresql.org/docs/current/sql-rollback.html">ROLLBACK specification</a>
+ */
+public class SqlRollback extends SqlCall {
+
+ public static final SqlSpecialOperator OPERATOR =
+ new SqlSpecialOperator("ROLLBACK", SqlKind.OTHER_FUNCTION, 32, false, ReturnTypes.BOOLEAN,
+ null, null) {
+ @Override public SqlCall createCall(@Nullable final SqlLiteral functionQualifier,
+ final SqlParserPos pos,
+ final @Nullable SqlNode... operands) {
+ return new SqlRollback(pos, (SqlLiteral) operands[0]);
+ }
+ };
+ private final SqlLiteral chain;
+
+ protected SqlRollback(final SqlParserPos pos, final SqlLiteral chain) {
+ super(pos);
+ this.chain = chain;
+ }
+
+ @Override public SqlOperator getOperator() {
+ return OPERATOR;
+ }
+
+ @Override public List<SqlNode> getOperandList() {
+ return ImmutableList.of(this.chain);
+ }
+
+ @Override public void unparse(final SqlWriter writer, final int leftPrec, final int rightPrec) {
+ writer.keyword("ROLLBACK");
+ if (this.chain.symbolValue(AndChain.class) == AndChain.AND_CHAIN) {
+ writer.literal("AND CHAIN");
+ }
+ }
+}
diff --git a/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlShow.java b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlShow.java
new file mode 100644
index 0000000000..6e81b01cb2
--- /dev/null
+++ b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/SqlShow.java
@@ -0,0 +1,74 @@
+/*
+ * 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.babel.postgresql;
+
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSpecialOperator;
+import org.apache.calcite.sql.SqlWriter;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.ReturnTypes;
+
+import com.google.common.collect.ImmutableList;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
+
+/**
+ * Parse tree node representing a {@code SHOW} clause.
+ * @see <a href="https://www.postgresql.org/docs/current/sql-show.html">SHOW specification</a>
+ */
+public class SqlShow extends SqlCall {
+ public static final SqlSpecialOperator OPERATOR =
+ new SqlSpecialOperator("SHOW", SqlKind.OTHER_FUNCTION, 32, false, ReturnTypes.VARCHAR_2000,
+ null, null) {
+ @Override public SqlCall createCall(@Nullable final SqlLiteral functionQualifier,
+ final SqlParserPos pos,
+ final @Nullable SqlNode... operands) {
+ return new SqlShow(pos, (SqlIdentifier) operands[0]);
+ }
+ };
+
+ private final SqlIdentifier name;
+
+ protected SqlShow(final SqlParserPos pos, SqlIdentifier name) {
+ super(pos);
+ this.name = name;
+ }
+
+ @Override public SqlOperator getOperator() {
+ return OPERATOR;
+ }
+
+ @Override public List<SqlNode> getOperandList() {
+ return ImmutableList.of(name);
+ }
+
+ @Override public void unparse(final SqlWriter writer, final int leftPrec, final int rightPrec) {
+ writer.keyword("SHOW");
+ writer.identifier(name.getSimple(), false);
+ }
+
+ public SqlIdentifier getName() {
+ return name;
+ }
+}
diff --git a/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/package-info.java b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/package-info.java
new file mode 100644
index 0000000000..2362f6f463
--- /dev/null
+++ b/babel/src/main/java/org/apache/calcite/sql/babel/postgresql/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Parse tree for PostgreSQL extensions used by the Babel parser.
+ */
+package org.apache.calcite.sql.babel.postgresql;
diff --git a/babel/src/test/java/org/apache/calcite/test/BabelParserTest.java b/babel/src/test/java/org/apache/calcite/test/BabelParserTest.java
index 9cccc5e448..310929592a 100644
--- a/babel/src/test/java/org/apache/calcite/test/BabelParserTest.java
+++ b/babel/src/test/java/org/apache/calcite/test/BabelParserTest.java
@@ -18,6 +18,7 @@ package org.apache.calcite.test;
import org.apache.calcite.sql.SqlDialect;
import org.apache.calcite.sql.dialect.MysqlSqlDialect;
+import org.apache.calcite.sql.dialect.PostgresqlSqlDialect;
import org.apache.calcite.sql.parser.SqlAbstractParserImpl;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.parser.SqlParserFixture;
@@ -333,6 +334,85 @@ class BabelParserTest extends SqlParserTest {
.ok("SELECT (ARRAY['a', 'b'])");
}
+ @Test void testPostgresqlShow() {
+ SqlParserFixture f = fixture().withDialect(PostgresqlSqlDialect.DEFAULT);
+ f.sql("SHOW autovacuum")
+ .ok("SHOW \"autovacuum\"");
+ f.sql("SHOW TRANSACTION ISOLATION LEVEL")
+ .ok("SHOW \"transaction_isolation\"");
+ }
+
+ @Test void testPostgresqlSetOption() {
+ SqlParserFixture f = fixture().withDialect(PostgresqlSqlDialect.DEFAULT);
+ f.sql("SET SESSION autovacuum = true")
+ .ok("ALTER SESSION SET \"autovacuum\" = TRUE");
+ f.sql("SET SESSION autovacuum = DEFAULT")
+ .ok("ALTER SESSION SET \"autovacuum\" = DEFAULT");
+ f.sql("SET LOCAL autovacuum TO 'DEFAULT'")
+ .ok("ALTER LOCAL SET \"autovacuum\" = 'DEFAULT'");
+
+ f.sql("SET SESSION TIME ZONE DEFAULT")
+ .ok("ALTER SESSION SET \"timezone\" = DEFAULT");
+ f.sql("SET SESSION TIME ZONE LOCAL")
+ .ok("ALTER SESSION SET \"timezone\" = 'LOCAL'");
+ f.sql("SET TIME ZONE 'PST8PDT'")
+ .ok("SET \"timezone\" = 'PST8PDT'");
+ f.sql("SET TIME ZONE INTERVAL '-08:00' HOUR TO MINUTE")
+ .ok("SET \"timezone\" = INTERVAL '-08:00' HOUR TO MINUTE");
+
+ f.sql("SET search_path = public,public,\"$user\"")
+ .ok("SET \"search_path\" = \"public\", \"public\", \"$user\"");
+ f.sql("SET SCHEMA public,public,\"$user\"")
+ .ok("SET \"search_path\" = \"public\", \"public\", \"$user\"");
+ f.sql("SET NAMES iso_8859_15_to_utf8")
+ .ok("SET \"client_encoding\" = \"iso_8859_15_to_utf8\"");
+ }
+
+ @Test void testPostgresqlBegin() {
+ SqlParserFixture f = fixture().withDialect(PostgresqlSqlDialect.DEFAULT);
+ f.sql("BEGIN").same();
+ f.sql("BEGIN READ ONLY").same();
+ f.sql("BEGIN TRANSACTION READ WRITE")
+ .ok("BEGIN READ WRITE");
+ f.sql("BEGIN WORK ISOLATION LEVEL SERIALIZABLE")
+ .ok("BEGIN ISOLATION LEVEL SERIALIZABLE");
+ f.sql("BEGIN ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE").same();
+ f.sql("BEGIN ISOLATION LEVEL SERIALIZABLE, READ WRITE, NOT DEFERRABLE").same();
+ }
+
+ @Test void testPostgresqlCommit() {
+ SqlParserFixture f = fixture().withDialect(PostgresqlSqlDialect.DEFAULT);
+ f.sql("COMMIT").same();
+ f.sql("COMMIT WORK")
+ .ok("COMMIT");
+ f.sql("COMMIT TRANSACTION")
+ .ok("COMMIT");
+ f.sql("COMMIT AND NO CHAIN")
+ .ok("COMMIT");
+ f.sql("COMMIT AND CHAIN").same();
+ }
+
+ @Test void testPostgresqlRollback() {
+ SqlParserFixture f = fixture().withDialect(PostgresqlSqlDialect.DEFAULT);
+ f.sql("ROLLBACK").same();
+ f.sql("ROLLBACK WORK")
+ .ok("ROLLBACK");
+ f.sql("ROLLBACK TRANSACTION")
+ .ok("ROLLBACK");
+ f.sql("ROLLBACK AND NO CHAIN")
+ .ok("ROLLBACK");
+ f.sql("ROLLBACK AND CHAIN").same();
+ }
+
+ @Test void testPostgresqlDiscard() {
+ SqlParserFixture f = fixture().withDialect(PostgresqlSqlDialect.DEFAULT);
+ f.sql("DISCARD ALL").same();
+ f.sql("DISCARD PLANS").same();
+ f.sql("DISCARD SEQUENCES").same();
+ f.sql("DISCARD TEMPORARY").same();
+ f.sql("DISCARD TEMP").same();
+ }
+
/** Similar to {@link #testHoist()} but using custom parser. */
@Test void testHoistMySql() {
// SQL contains back-ticks, which require MySQL's quoting,