diff --git a/pom.xml b/pom.xml
index b03e3370599..9640cd48d14 100644
--- a/pom.xml
+++ b/pom.xml
@@ -84,6 +84,7 @@
1.11.3
1.35.0
6.2.12
diff --git a/sql/src/main/codegen/includes/insert.ftl b/sql/src/main/codegen/includes/insert.ftl
index 0f1db5a4448..00133496d24 100644
--- a/sql/src/main/codegen/includes/insert.ftl
+++ b/sql/src/main/codegen/includes/insert.ftl
@@ -17,6 +17,63 @@
* under the License.
*/
+/**
+ * Parses an INSERT statement. This function is copied from SqlInsert in core/src/main/codegen/templates/Parser.jj,
+ * with some changes to allow a custom error message if an OVERWRITE clause is present.
+ */
+SqlNode DruidSqlInsert() :
+{
+ final List keywords = new ArrayList();
+ final SqlNodeList keywordList;
+ final SqlIdentifier tableName;
+ SqlNode tableRef;
+ SqlNode source;
+ final SqlNodeList columnList;
+ final Span s;
+ final Pair p;
+}
+{
+ (
+
+ |
+ { keywords.add(SqlInsertKeyword.UPSERT.symbol(getPos())); }
+ )
+ { s = span(); }
+ SqlInsertKeywords(keywords) {
+ keywordList = new SqlNodeList(keywords, s.addAll(keywords).pos());
+ }
+ tableName = CompoundTableIdentifier()
+ ( tableRef = TableHints(tableName) | { tableRef = tableName; } )
+ [ LOOKAHEAD(5) tableRef = ExtendTable(tableRef) ]
+ (
+ LOOKAHEAD(2)
+ p = ParenthesizedCompoundIdentifierList() {
+ if (p.right.size() > 0) {
+ tableRef = extend(tableRef, p.right);
+ }
+ if (p.left.size() > 0) {
+ columnList = p.left;
+ } else {
+ columnList = null;
+ }
+ }
+ | { columnList = null; }
+ )
+ (
+
+ {
+ throw org.apache.druid.sql.calcite.parser.DruidSqlParserUtils.problemParsing(
+ "An OVERWRITE clause is not allowed with INSERT statements. Use REPLACE statements if overwriting existing segments is required or remove the OVERWRITE clause."
+ );
+ }
+ |
+ source = OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY) {
+ return new SqlInsert(s.end(source), keywordList, tableRef, source,
+ columnList);
+ }
+ )
+}
+
// Using fully qualified name for Pair class, since Calcite also has a same class name being used in the Parser.jj
SqlNode DruidSqlInsertEof() :
{
@@ -25,7 +82,7 @@ SqlNode DruidSqlInsertEof() :
SqlNodeList clusteredBy = null;
}
{
- insertNode = SqlInsert()
+ insertNode = DruidSqlInsert()
// PARTITIONED BY is necessary, but is kept optional in the grammar. It is asserted that it is not missing in the
// DruidSqlInsert constructor so that we can return a custom error message.
[
diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteInsertDmlTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteInsertDmlTest.java
index 5752ed9e535..a34c93ce9c9 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteInsertDmlTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteInsertDmlTest.java
@@ -1418,6 +1418,15 @@ public class CalciteInsertDmlTest extends CalciteIngestionDmlTest
.verify();
}
+ @Test
+ public void testInsertWithOverwriteClause()
+ {
+ testIngestionQuery()
+ .sql("INSERT INTO dst OVERWRITE ALL SELECT * FROM foo PARTITIONED BY ALL TIME")
+ .expectValidationError(DruidException.class, "An OVERWRITE clause is not allowed with INSERT statements. Use REPLACE statements if overwriting existing segments is required or remove the OVERWRITE clause.")
+ .verify();
+ }
+
@Test
public void testInsertFromExternalProjectSort()
{