Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions core/src/main/codegen/templates/Parser.jj
Original file line number Diff line number Diff line change
Expand Up @@ -7505,7 +7505,7 @@ SqlCall MatchRecognizeCallWithModifier() :
{
final Span s;
final SqlOperator runningOp;
final SqlNode func;
final SqlNode e;
}
{
(
Expand All @@ -7514,8 +7514,8 @@ SqlCall MatchRecognizeCallWithModifier() :
<FINAL> { runningOp = SqlStdOperatorTable.FINAL; }
)
{ s = span(); }
func = NamedFunctionCall() {
return runningOp.createCall(s.end(func), func);
e = Expression3(ExprContext.ACCEPT_NON_QUERY) {
return runningOp.createCall(s.end(e), e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8225,17 +8225,21 @@ private class PatternValidator extends SqlBasicVisitor<@Nullable Set<String>> {
int firstLastCount;
int prevNextCount;
int aggregateCount;
int argIndex;
int argCount;

PatternValidator(boolean isMeasure) {
this(isMeasure, 0, 0, 0);
this(isMeasure, 0, 0, 0, 0, 0);
}

PatternValidator(boolean isMeasure, int firstLastCount, int prevNextCount,
int aggregateCount) {
int aggregateCount, int index, int argCount) {
this.isMeasure = isMeasure;
this.firstLastCount = firstLastCount;
this.prevNextCount = prevNextCount;
this.aggregateCount = aggregateCount;
this.argIndex = index;
this.argCount = argCount;
}

@Override public Set<String> visit(SqlCall call) {
Expand Down Expand Up @@ -8281,13 +8285,14 @@ private class PatternValidator extends SqlBasicVisitor<@Nullable Set<String>> {
Static.RESOURCE.patternRunningFunctionInDefine(call.toString()));
}

for (SqlNode node : operands) {
for (int i = 0; i < operands.size(); i++) {
SqlNode node = operands.get(i);
if (node != null) {
vars.addAll(
requireNonNull(
node.accept(
new PatternValidator(isMeasure, firstLastCount, prevNextCount,
aggregateCount)),
aggregateCount, i, operands.size())),
() -> "node.accept(PatternValidator) for node " + node));
}
}
Expand Down Expand Up @@ -8329,7 +8334,13 @@ private class PatternValidator extends SqlBasicVisitor<@Nullable Set<String>> {
}

@Override public Set<String> visit(SqlLiteral literal) {
return ImmutableSet.of();
if ((this.argCount == 1 || this.argIndex < this.argCount - 1)
&& (this.firstLastCount > 0 || this.prevNextCount > 0)
&& !SqlUtil.isNull(literal)) {
return ImmutableSet.of(requireNonNull(literal.toValue()));
} else {
return ImmutableSet.of();
}
}

@Override public Set<String> visit(SqlIntervalQualifier qualifier) {
Expand Down
72 changes: 72 additions & 0 deletions core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2655,6 +2655,78 @@ void testLikeAndSimilarFails() {
.rewritesTo(expected8);
sql(expected8)
.withParserConfig(c -> c.withQuoting(Quoting.BACK_TICK)).ok();

// Test cases for [CALCITE-7465] https://issues.apache.org/jira/browse/CALCITE-7465
// Unparse of MATCH_RECOGNIZE MEASURES might produce unparsable sql
// Accepted by Snowflake (it doesn't accept FINAL or RUNNING before non function measure)
final String sql9 = "SELECT *\n"
+ "FROM emp\n"
+ "MATCH_RECOGNIZE (\n"
+ " MEASURES\n"
+ " A.deptno AS deptno\n"
+ " PATTERN (A B)\n"
+ " DEFINE\n"
+ " A AS A.empno = 123\n"
+ ")";
final String expected9 = "SELECT `EXPR$0`.`DEPTNO`\n"
+ "FROM `CATALOG`.`SALES`.`EMP` AS `EMP` MATCH_RECOGNIZE(\n"
+ "MEASURES FINAL `A`.`DEPTNO` AS `DEPTNO`\n"
+ "PATTERN (`A` `B`)\n"
+ "DEFINE `A` AS PREV(`A`.`EMPNO`, 0) = 123) AS `EXPR$0`";

sql(sql9)
.withValidatorConfig(c -> c.withIdentifierExpansion(true))
.rewritesTo(expected9);
sql(expected9)
.withParserConfig(c -> c.withQuoting(Quoting.BACK_TICK)).ok();

final String sql10 = "SELECT deptno\n"
+ "FROM emp\n"
+ "MATCH_RECOGNIZE (\n"
+ " MEASURES\n"
+ " A.deptno AS deptno\n"
+ "ALL ROWS PER MATCH\n"
+ " PATTERN (A B)\n"
+ " DEFINE\n"
+ " A AS A.empno = 123\n"
+ ")";
final String expected10 = "SELECT `EXPR$0`.`DEPTNO`\n"
+ "FROM `CATALOG`.`SALES`.`EMP` AS `EMP` MATCH_RECOGNIZE(\n"
+ "MEASURES RUNNING `A`.`DEPTNO` AS `DEPTNO`\n"
+ "ALL ROWS PER MATCH\n"
+ "PATTERN (`A` `B`)\n"
+ "DEFINE `A` AS PREV(`A`.`EMPNO`, 0) = 123) AS `EXPR$0`";

sql(sql10)
.withValidatorConfig(c -> c.withIdentifierExpansion(true))
.rewritesTo(expected10);
sql(expected10)
.withParserConfig(c -> c.withQuoting(Quoting.BACK_TICK)).ok();

// Test cases for [CALCITE-7486] https://issues.apache.org/jira/browse/CALCITE-7486
// Operators in MATCH_RECOGNIZE don't support SqlLiterals
// Accepted by Snowflake
final String sql11 = "SELECT *\n"
+ "FROM emp\n"
+ "MATCH_RECOGNIZE (\n"
+ " MEASURES\n"
+ " FIRST(DOWN.empno + DOWN.deptno + 1) AS bottom_total"
+ " PATTERN (DOWN{2,})\n"
+ " DEFINE\n"
+ " DOWN AS PREV(EMP.EMPNO + 2, 0) < 1"
+ ")";

final String expected11 = "SELECT `EXPR$0`.`BOTTOM_TOTAL`\n"
+ "FROM `CATALOG`.`SALES`.`EMP` AS `EMP` MATCH_RECOGNIZE(\n"
+ "MEASURES FINAL (FIRST(`DOWN`.`EMPNO` + `DOWN`.`DEPTNO`, 0) + FIRST(1, 0)) AS `BOTTOM_TOTAL`\n"
+ "PATTERN (`DOWN` { 2, })\n"
+ "DEFINE `DOWN` AS LAST(`EMP`.`EMPNO`, 0) + PREV(2, 0) < 1) AS `EXPR$0`";

sql(sql11)
.withValidatorConfig(c -> c.withIdentifierExpansion(true))
.rewritesTo(expected11);
sql(expected11)
.withParserConfig(c -> c.withQuoting(Quoting.BACK_TICK)).ok();
}

@Test void testIntervalTimeUnitEnumeration() {
Expand Down
Loading