Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -2126,6 +2126,9 @@ protected void inferUnknownTypes(
setValidatedNodeType(node, newInferredType);
} else if (node instanceof SqlNodeList) {
SqlNodeList nodeList = (SqlNodeList) node;
if (inferRowSqlNodeList(inferredType, scope, nodeList)) {
return;
}
if (inferredType.isStruct()) {
if (inferredType.getFieldCount() != nodeList.size()) {
// this can happen when we're validating an INSERT
Expand Down Expand Up @@ -2204,6 +2207,25 @@ protected void inferUnknownTypes(
}
}

private boolean inferRowSqlNodeList(final RelDataType inferredType,
final SqlValidatorScope scope, final SqlNodeList nodeList) {
if (!inferredType.isStruct()) {
return false;
}
boolean inferred = false;
for (SqlNode child : nodeList) {
if (child instanceof SqlBasicCall && SqlKind.ROW == child.getKind()) {
List<SqlNode> operands = ((SqlBasicCall) child).getOperandList();
for (int index = 0; index < operands.size(); index++) {
RelDataType type = inferredType.getFieldList().get(index).getType();
inferUnknownTypes(type, scope, operands.get(index));
}
inferred = true;
}
}
return inferred;
}

/**
* Adds an expression to a select list, ensuring that its alias does not
* clash with any existing expressions on the list.
Expand Down
25 changes: 25 additions & 0 deletions core/src/test/java/org/apache/calcite/test/JdbcTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9012,6 +9012,31 @@ void checkCalciteSchemaGetSubSchemaMap(boolean cache) {
});
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-7197">[CALCITE-7197]</a>
* UnsupportedOperationException when using dynamic parameters inside ROW expression. */
@Test void testSelectWithPlaceholdersInRowExpression() {
CalciteAssert.that()
.with(Lex.MYSQL)
.with(CalciteAssert.Config.SCOTT)
.query("select empno, ename from emp\n"
+ "where row(empno, ename) in ((?, ?))")
.consumesPreparedStatement(p -> {
p.setInt(1, 7782);
p.setString(2, "CLARK");
})
.returns(resultSet -> {
try {
assertTrue(resultSet.next());
assertThat(resultSet.getInt(1), is(7782));
assertThat(resultSet.getString(2), is("CLARK"));
assertFalse(resultSet.next());
} catch (SQLException e) {
throw new RuntimeException(e);
}
});
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-5414">[CALCITE-5414]</a>
* Convert between standard Gregorian and proleptic Gregorian calendars for
Expand Down
20 changes: 20 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 @@ -12405,6 +12405,26 @@ private void checkCustomColumnResolving(String table) {
.fails(maxError);
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-7197">[CALCITE-7197]</a>
* UnsupportedOperationException when using dynamic parameters inside ROW expression. */
@Test void testSelectWithRowExpressionPredicate() {
// test single row expression values
sql("select empno, ename from emp where row(empno, ename) in ((?, ?))")
.ok()
.assertBindType(is("RecordType(INTEGER ?0, VARCHAR(20) ?1)"));

// test multiple row expression values
sql("select empno, ename from emp where row(empno, ename) in ((?, ?), (7782, ?), (?, 'CLARK'))")
.ok()
.assertBindType(is("RecordType(INTEGER ?0, VARCHAR(20) ?1, VARCHAR(20) ?2, INTEGER ?3)"));

// test single row expression values with expression
sql("select empno, ename from emp where row(empno, ename) in ((? + 1, ?))")
.ok()
.assertBindType(is("RecordType(INTEGER ?0, VARCHAR(20) ?1)"));
}

@Test void testRolledUpColumnInWhere() {
final String error = "Rolled up column 'SLACKINGMIN' is not allowed in GREATER_THAN";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19698,16 +19698,7 @@ LogicalProject(A=[$0], Y=[$1])
LogicalProject(EXPR$0=[$0], EXPR$1=[$1])
LogicalValues(tuples=[[{ 1, 2 }, { 3, null }, { 7369, null }, { 7499, 30 }, { null, 20 }, { null, 5 }]])
LogicalAggregate(group=[{0, 1}])
LogicalUnion(all=[true])
LogicalProject(EXPR$0=[3], EXPR$1=[null:INTEGER])
LogicalValues(tuples=[[{ 0 }]])
LogicalProject(EXPR$0=[7369], EXPR$1=[null:INTEGER])
LogicalValues(tuples=[[{ 0 }]])
LogicalProject(EXPR$0=[null:INTEGER], EXPR$1=[20])
LogicalValues(tuples=[[{ 0 }]])
LogicalProject(EXPR$0=[null:INTEGER], EXPR$1=[5])
LogicalValues(tuples=[[{ 0 }]])
LogicalValues(tuples=[[{ 1, 2 }, { 7499, 30 }]])
LogicalValues(tuples=[[{ 1, 2 }, { 3, null }, { 7369, null }, { 7499, 30 }, { null, 20 }, { null, 5 }]])
]]>
</Resource>
<Resource name="planAfter">
Expand All @@ -19716,7 +19707,7 @@ LogicalProject(A=[$0], Y=[$1])
LogicalJoin(condition=[AND(=($0, $2), =($1, $3))], joinType=[inner])
LogicalValues(tuples=[[{ 1, 2 }, { 3, null }, { 7369, null }, { 7499, 30 }, { null, 20 }, { null, 5 }]])
LogicalAggregate(group=[{0, 1}])
LogicalValues(tuples=[[{ 3, null }, { 7369, null }, { null, 20 }, { null, 5 }, { 1, 2 }, { 7499, 30 }]])
LogicalValues(tuples=[[{ 1, 2 }, { 3, null }, { 7369, null }, { 7499, 30 }, { null, 20 }, { null, 5 }]])
]]>
</Resource>
</TestCase>
Expand All @@ -19738,15 +19729,9 @@ LogicalProject(A=[$0], Y=[$1])
LogicalUnion(all=[true])
LogicalProject(EXPR$0=[1], EXPR$1=[2])
LogicalValues(tuples=[[{ 0 }]])
LogicalProject(EXPR$0=[3], EXPR$1=[null:INTEGER])
LogicalValues(tuples=[[{ 0 }]])
LogicalProject(EXPR$0=[7369], EXPR$1=[null:INTEGER])
LogicalValues(tuples=[[{ 0 }]])
LogicalProject(EXPR$0=[null:INTEGER], EXPR$1=[20])
LogicalValues(tuples=[[{ 0 }]])
LogicalProject(EXPR$0=[null:INTEGER], EXPR$1=[5])
LogicalValues(tuples=[[{ 0 }]])
LogicalValues(tuples=[[{ 7499, 30 }]])
LogicalValues(tuples=[[{ 3, null }, { 7369, null }, { 7499, 30 }, { null, 5 }]])
]]>
</Resource>
<Resource name="planAfter">
Expand All @@ -19755,7 +19740,7 @@ LogicalProject(A=[$0], Y=[$1])
LogicalJoin(condition=[AND(=($0, $2), =($1, $3))], joinType=[inner])
LogicalValues(tuples=[[{ 1, 2 }, { 3, null }, { 7369, null }, { 7499, 30 }, { null, 20 }, { null, 5 }]])
LogicalAggregate(group=[{0, 1}])
LogicalValues(tuples=[[{ 1, 2 }, { 3, null }, { 7369, null }, { null, 20 }, { null, 5 }, { 7499, 30 }]])
LogicalValues(tuples=[[{ 1, 2 }, { null, 20 }, { 3, null }, { 7369, null }, { 7499, 30 }, { null, 5 }]])
]]>
</Resource>
</TestCase>
Expand Down
17 changes: 17 additions & 0 deletions core/src/test/resources/sql/conditions.iq
Original file line number Diff line number Diff line change
Expand Up @@ -547,4 +547,21 @@ where 5 < cast(deptno as integer) OR 5 >= cast(deptno as integer) OR deptno IS N
EnumerableTableScan(table=[[scott, EMP]])
!plan

!use scott

# Test case for [CALCITE-7197] UnsupportedOperationException when using dynamic parameters inside ROW expression
select *
from "scott".emp
where row(empno, ename) in ((7782, 'CLARK'), (7902, 'FORD'), (7839, 'KING'));
+-------+-------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+-----------+------+------------+---------+------+--------+
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | | 10 |
| 7839 | KING | PRESIDENT | | 1981-11-17 | 5000.00 | | 10 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | | 20 |
+-------+-------+-----------+------+------------+---------+------+--------+
(3 rows)

!ok

# End conditions.iq
Loading