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
36 changes: 33 additions & 3 deletions babel/src/test/java/org/apache/calcite/test/BabelTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,21 @@ names, is(
});

fixture.withSql("select * exclude (empno, ^foo^) from emp")
.fails("SELECT \\* EXCLUDE list contains unknown column\\(s\\): FOO");
.fails("SELECT \\* EXCLUDE/EXCEPT list contains unknown column\\(s\\): FOO");

// Alias form: EXCEPT behaves the same as EXCLUDE
fixture.withSql("select * except(empno, deptno) from emp")
.type(type -> {
final List<String> names = type.getFieldList().stream()
.map(RelDataTypeField::getName)
.collect(Collectors.toList());
assertThat(
names, is(
ImmutableList.of("ENAME", "JOB", "MGR", "HIREDATE", "SAL", "COMM", "SLACKER")));
});

fixture.withSql("select * except (empno, ^foo^) from emp")
.fails("SELECT \\* EXCLUDE/EXCEPT list contains unknown column\\(s\\): FOO");

fixture.withSql("select e.* exclude(e.empno, e.ename, e.job, e.mgr)"
+ " from emp e join dept d on e.deptno = d.deptno")
Expand All @@ -210,7 +224,23 @@ names, is(

fixture.withSql("select e.* exclude(e.empno, e.ename, e.job, e.mgr, ^d.deptno^)"
+ " from emp e join dept d on e.deptno = d.deptno")
.fails("SELECT \\* EXCLUDE list contains unknown column\\(s\\): D.DEPTNO");
.fails("SELECT \\* EXCLUDE/EXCEPT list contains unknown column\\(s\\): D.DEPTNO");

// Alias form: EXCEPT for table-qualified star
fixture.withSql("select e.* except(e.empno, e.ename, e.job, e.mgr)"
+ " from emp e join dept d on e.deptno = d.deptno")
.type(type -> {
final List<String> names = type.getFieldList().stream()
.map(RelDataTypeField::getName)
.collect(Collectors.toList());
assertThat(
names, is(
ImmutableList.of("HIREDATE", "SAL", "COMM", "DEPTNO", "SLACKER")));
});

fixture.withSql("select e.* except(e.empno, e.ename, e.job, e.mgr, ^d.deptno^)"
+ " from emp e join dept d on e.deptno = d.deptno")
.fails("SELECT \\* EXCLUDE/EXCEPT list contains unknown column\\(s\\): D.DEPTNO");

fixture.withSql("select e.* exclude(e.empno, e.ename, e.job, e.mgr), d.* exclude(d.name)"
+ " from emp e join dept d on e.deptno = d.deptno")
Expand Down Expand Up @@ -242,7 +272,7 @@ names, is(

// To verify that the exclude list contains all columns in the table
fixture.withSql("select ^*^ exclude(deptno, name) from dept")
.fails("SELECT \\* EXCLUDE list cannot exclude all columns");
.fails("SELECT \\* EXCLUDE/EXCEPT list cannot exclude all columns");
}

/** Tests that DATEADD, DATEDIFF, DATEPART, DATE_PART allow custom time
Expand Down
52 changes: 52 additions & 0 deletions babel/src/test/resources/sql/select.iq
Original file line number Diff line number Diff line change
Expand Up @@ -234,4 +234,56 @@ WHERE d.loc = 'CHICAGO';

!ok

# [CALCITE-7331] Support the alias form SELECT * EXCEPT() for SELECT * EXCLUDE()
select 1 as x, 2 as y except (select 3 as a, 4 as b);
+---+---+
| X | Y |
+---+---+
| 1 | 2 |
+---+---+
(1 row)

!ok

with t(x, y) as (values(1, 2))
select 1 as x, 2 as y except (y) from t;
Non-query expression encountered in illegal context
!error

with t(x, y) as (values(1, 2))
select x except (x) from t;
EXCLUDE/EXCEPT clause must follow a STAR expression
!error

with t(x, y) as (values(1, 2))
select * except (x) from t;
+---+
| Y |
+---+
| 2 |
+---+
(1 row)

!ok

select 1 as x, e.* except(e.empno, e.ename, e.job, e.mgr), d.* except(d.dname), 2 as y
from emp e join dept d on e.deptno = d.deptno limit 1;
+---+------------+---------+------+--------+---------+----------+---+
| X | HIREDATE | SAL | COMM | DEPTNO | DEPTNO0 | LOC | Y |
+---+------------+---------+------+--------+---------+----------+---+
| 1 | 1981-06-09 | 2450.00 | | 10 | 10 | NEW YORK | 2 |
+---+------------+---------+------+--------+---------+----------+---+
(1 row)

!ok

select d1.* except(d1.dname) from dept d1 except(select d2.* except(d2.dname) from dept d2);
+--------+-----+
| DEPTNO | LOC |
+--------+-----+
+--------+-----+
(0 rows)

!ok

# End select.iq
2 changes: 1 addition & 1 deletion core/src/main/codegen/templates/Parser.jj
Original file line number Diff line number Diff line change
Expand Up @@ -2049,7 +2049,7 @@ SqlNodeList StarExcludeList() :
SqlIdentifier id;
}
{
<EXCLUDE> <LPAREN> { s = span(); }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this could potentially be configurable, but I guess that people can adapt the parser and choose what they want.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we'll keep it simple for now, supporting both, and keeping the configuration parameters as minimal as possible.

( <EXCLUDE> | <EXCEPT> ) <LPAREN> { s = span(); }
id = CompoundIdentifier() {
list.add(id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -807,13 +807,13 @@ ExInst<CalciteException> illegalArgumentForTableFunctionCall(String a0,
@BaseMessage("SELECT * requires a FROM clause")
ExInst<SqlValidatorException> selectStarRequiresFrom();

@BaseMessage("EXCLUDE clause must follow a STAR expression")
@BaseMessage("EXCLUDE/EXCEPT clause must follow a STAR expression")
ExInst<CalciteException> selectExcludeRequiresStar();

@BaseMessage("SELECT * EXCLUDE list contains unknown column(s): {0}")
@BaseMessage("SELECT * EXCLUDE/EXCEPT list contains unknown column(s): {0}")
ExInst<SqlValidatorException> selectStarExcludeListContainsUnknownColumns(String columns);

@BaseMessage("SELECT * EXCLUDE list cannot exclude all columns")
@BaseMessage("SELECT * EXCLUDE/EXCEPT list cannot exclude all columns")
ExInst<SqlValidatorException> selectStarExcludeCannotExcludeAllColumns();

@BaseMessage("Group function ''{0}'' can only appear in GROUP BY clause")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,9 @@ CannotStreamResultsForNonStreamingInputs=Cannot stream results of a query with n
MinusNotAllowed=MINUS is not allowed under the current SQL conformance level
SelectMissingFrom=SELECT must have a FROM clause
SelectStarRequiresFrom=SELECT * requires a FROM clause
SelectExcludeRequiresStar=EXCLUDE clause must follow a STAR expression
SelectStarExcludeListContainsUnknownColumns=SELECT * EXCLUDE list contains unknown column(s): {0}
SelectStarExcludeCannotExcludeAllColumns=SELECT * EXCLUDE list cannot exclude all columns
SelectExcludeRequiresStar=EXCLUDE/EXCEPT clause must follow a STAR expression
SelectStarExcludeListContainsUnknownColumns=SELECT * EXCLUDE/EXCEPT list contains unknown column(s): {0}
SelectStarExcludeCannotExcludeAllColumns=SELECT * EXCLUDE/EXCEPT list cannot exclude all columns
GroupFunctionMustAppearInGroupByClause=Group function ''{0}'' can only appear in GROUP BY clause
AuxiliaryWithoutMatchingGroupCall=Call to auxiliary group function ''{0}'' must have matching call to group function ''{1}'' in GROUP BY clause
PivotAggMalformed=Measure expression in PIVOT must use aggregate function
Expand Down
2 changes: 1 addition & 1 deletion site/_docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ starWithExclude:

Note:

* `SELECT * EXCLUDE (...)` is recognized only when the Babel parser is enabled. It sets the generated parser configuration flag `includeStarExclude` to `true` (the standard parser leaves that flag `false`), which allows a `STAR` token followed by `EXCLUDE` and a parenthesized identifier list to be parsed into a `SqlStarExclude` node and ensures validators respect the exclusion list when expanding the projection. Reusing the same parser configuration elsewhere enables the same syntax for other components that need it.
* `SELECT * EXCLUDE (...)` is recognized only when the Babel parser is enabled. It sets the generated parser configuration flag `includeStarExclude` to `true` (the standard parser leaves that flag `false`), which allows a `STAR` token followed by `EXCLUDE` (or the alias `EXCEPT`) and a parenthesized identifier list to be parsed into a `SqlStarExclude` node and ensures validators respect the exclusion list when expanding the projection. Reusing the same parser configuration elsewhere enables the same syntax for other components that need it.

projectItem:
expression [ [ AS ] columnAlias ]
Expand Down
Loading