Add better error messages for using OVERWRITE with INSERT statments (#15517)

* Add better error messages for using OVERWRITE with INSERT statments
This commit is contained in:
Adarsh Sanjeev 2023-12-08 15:33:46 +05:30 committed by GitHub
parent c353ccfdef
commit 2e45eadc08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 68 additions and 1 deletions

View File

@ -84,6 +84,7 @@
<avro.version>1.11.3</avro.version>
<!-- When updating Calcite, also propagate updates to these files which we've copied and modified:
default_config.fmpp
sql/src/main/codegen/includes/*
-->
<calcite.version>1.35.0</calcite.version>
<confluent.version>6.2.12</confluent.version>

View File

@ -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<SqlLiteral> keywords = new ArrayList<SqlLiteral>();
final SqlNodeList keywordList;
final SqlIdentifier tableName;
SqlNode tableRef;
SqlNode source;
final SqlNodeList columnList;
final Span s;
final Pair<SqlNodeList, SqlNodeList> p;
}
{
(
<INSERT>
|
<UPSERT> { keywords.add(SqlInsertKeyword.UPSERT.symbol(getPos())); }
)
{ s = span(); }
SqlInsertKeywords(keywords) {
keywordList = new SqlNodeList(keywords, s.addAll(keywords).pos());
}
<INTO> 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; }
)
(
<OVERWRITE>
{
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.
[

View File

@ -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()
{