From 39b3487aa9829d1d5b19733ef76319d8133dcb38 Mon Sep 17 00:00:00 2001 From: Adarsh Sanjeev Date: Fri, 13 May 2022 10:56:40 +0530 Subject: [PATCH] Add replace statement to sql parser (#12386) Relevant Issue: #11929 - Add custom replace statement to Druid SQL parser. - Edit DruidPlanner to convert relevant fields to Query Context. - Refactor common code with INSERT statements to reuse them for REPLACE where possible. --- sql/src/main/codegen/config.fmpp | 6 + sql/src/main/codegen/includes/common.ftl | 74 ++ sql/src/main/codegen/includes/explain.ftl | 2 + sql/src/main/codegen/includes/insert.ftl | 55 -- sql/src/main/codegen/includes/replace.ftl | 78 +++ .../sql/calcite/parser/DruidSqlInsert.java | 2 + .../calcite/parser/DruidSqlParserUtils.java | 212 ++++++ .../sql/calcite/parser/DruidSqlReplace.java | 129 ++++ .../sql/calcite/planner/DruidPlanner.java | 205 ++++-- .../sql/calcite/CalciteIngestionDmlTest.java | 339 +++++++++ .../sql/calcite/CalciteInsertDmlTest.java | 372 +--------- .../sql/calcite/CalciteReplaceDmlTest.java | 656 ++++++++++++++++++ .../calcite/parser/DruidSqlUnparseTest.java | 97 +++ 13 files changed, 1764 insertions(+), 463 deletions(-) create mode 100644 sql/src/main/codegen/includes/common.ftl create mode 100644 sql/src/main/codegen/includes/replace.ftl create mode 100644 sql/src/main/java/org/apache/druid/sql/calcite/parser/DruidSqlReplace.java create mode 100644 sql/src/test/java/org/apache/druid/sql/calcite/CalciteIngestionDmlTest.java create mode 100644 sql/src/test/java/org/apache/druid/sql/calcite/CalciteReplaceDmlTest.java create mode 100644 sql/src/test/java/org/apache/druid/sql/calcite/parser/DruidSqlUnparseTest.java diff --git a/sql/src/main/codegen/config.fmpp b/sql/src/main/codegen/config.fmpp index 817bd4e79e5..31fe812bbec 100644 --- a/sql/src/main/codegen/config.fmpp +++ b/sql/src/main/codegen/config.fmpp @@ -51,6 +51,7 @@ data: { # List of additional classes and packages to import. # Example. "org.apache.calcite.sql.*", "java.util.List". imports: [ + "java.util.List" "org.apache.calcite.sql.SqlNode" "org.apache.calcite.sql.SqlInsert" "org.apache.druid.java.util.common.granularity.Granularity" @@ -63,6 +64,7 @@ data: { # keyword add it to 'nonReservedKeywords' section. keywords: [ "CLUSTERED" + "OVERWRITE" "PARTITIONED" ] @@ -218,6 +220,7 @@ data: { "OTHERS" "OUTPUT" "OVERRIDING" + "OVERWRITE" "PAD" "PARAMETER_MODE" "PARAMETER_NAME" @@ -384,6 +387,7 @@ data: { statementParserMethods: [ "DruidSqlInsertEof()" "DruidSqlExplain()" + "DruidSqlReplaceEof()" ] # List of methods for parsing custom literals. @@ -433,8 +437,10 @@ data: { # given as part of "statementParserMethods", "literalParserMethods" or # "dataTypeParserMethods". implementationFiles: [ + "common.ftl" "insert.ftl" "explain.ftl" + "replace.ftl" ] includePosixOperators: false diff --git a/sql/src/main/codegen/includes/common.ftl b/sql/src/main/codegen/includes/common.ftl new file mode 100644 index 00000000000..136492482c6 --- /dev/null +++ b/sql/src/main/codegen/includes/common.ftl @@ -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. + */ + +// Using fully qualified name for Pair class, since Calcite also has a same class name being used in the Parser.jj +org.apache.druid.java.util.common.Pair PartitionGranularity() : +{ + SqlNode e; + Granularity granularity; + String unparseString; +} +{ + ( + + { + granularity = Granularities.HOUR; + unparseString = "HOUR"; + } + | + + { + granularity = Granularities.DAY; + unparseString = "DAY"; + } + | + + { + granularity = Granularities.MONTH; + unparseString = "MONTH"; + } + | + + { + granularity = Granularities.YEAR; + unparseString = "YEAR"; + } + | + + { + granularity = Granularities.ALL; + unparseString = "ALL"; + } + [ +