@@ -200,6 +200,42 @@ WHERE age NOT IN (SELECT age FROM catalog.departments WHERE dept_name = 'Enginee
200200 """ );
201201 }
202202
203+ @ Test
204+ public void testUnionAll () {
205+ givenQuery (
206+ """
207+ SELECT name FROM catalog.employees UNION ALL SELECT dept_name FROM catalog.departments
208+ """ )
209+ .assertPlan (
210+ """
211+ LogicalUnion(all=[true])
212+ LogicalProject(name=[$1])
213+ LogicalTableScan(table=[[catalog, employees]])
214+ LogicalProject(dept_name=[$1])
215+ LogicalTableScan(table=[[catalog, departments]])
216+ """ );
217+ }
218+
219+ @ Test
220+ public void testMultiWayUnion () {
221+ givenQuery (
222+ """
223+ SELECT name FROM catalog.employees
224+ UNION ALL SELECT dept_name FROM catalog.departments
225+ UNION ALL SELECT name FROM catalog.employees
226+ """ )
227+ .assertPlan (
228+ """
229+ LogicalUnion(all=[true])
230+ LogicalProject(name=[$1])
231+ LogicalTableScan(table=[[catalog, employees]])
232+ LogicalProject(dept_name=[$1])
233+ LogicalTableScan(table=[[catalog, departments]])
234+ LogicalProject(name=[$1])
235+ LogicalTableScan(table=[[catalog, employees]])
236+ """ );
237+ }
238+
203239 @ Test
204240 public void testNotExistsSubquery () {
205241 givenQuery (
@@ -241,6 +277,57 @@ public void selectExpressionWithoutFrom() {
241277 """ );
242278 }
243279
280+ @ Test
281+ public void testGroupByAggregateAlias () {
282+ givenQuery (
283+ """
284+ SELECT department, SUM(age) AS total FROM catalog.employees GROUP BY department
285+ """ )
286+ .assertPlan (
287+ """
288+ LogicalProject(department=[$0], total=[$1])
289+ LogicalAggregate(group=[{0}], SUM(age)=[SUM($1)])
290+ LogicalProject(department=[$3], age=[$2])
291+ LogicalTableScan(table=[[catalog, employees]])
292+ """ );
293+ }
294+
295+ @ Test
296+ public void testOrderByAggregateAlias () {
297+ givenQuery (
298+ """
299+ SELECT department, COUNT(*) AS cnt FROM catalog.employees
300+ GROUP BY department ORDER BY cnt DESC LIMIT 3
301+ """ )
302+ .assertPlan (
303+ """
304+ LogicalSort(sort0=[$1], dir0=[DESC-nulls-last])
305+ LogicalProject(department=[$1], cnt=[$0])
306+ LogicalSort(sort0=[$0], dir0=[DESC-nulls-last], fetch=[3])
307+ LogicalProject(COUNT(*)=[$1], department=[$0])
308+ LogicalAggregate(group=[{0}], COUNT(*)=[COUNT()])
309+ LogicalProject(department=[$3])
310+ LogicalTableScan(table=[[catalog, employees]])
311+ """ );
312+ }
313+
314+ @ Test
315+ public void testAliasPreservedInOutputSchema () {
316+ givenQuery ("SELECT COUNT(*) AS cnt FROM catalog.employees" ).assertFields ("cnt" );
317+
318+ givenQuery ("SELECT department, COUNT(*) AS cnt FROM catalog.employees GROUP BY department" )
319+ .assertFields ("department" , "cnt" );
320+
321+ givenQuery ("SELECT department, COUNT(*) FROM catalog.employees GROUP BY department" )
322+ .assertFields ("department" , "COUNT(*)" );
323+
324+ givenQuery ("SELECT MAX(age) + MIN(age) AS range_sum FROM catalog.employees" )
325+ .assertFields ("range_sum" );
326+
327+ givenQuery ("SELECT id, name, age AS years, department FROM catalog.employees" )
328+ .assertFields ("id" , "name" , "years" , "department" );
329+ }
330+
244331 @ Test
245332 public void testHavingMaxCol () {
246333 givenQuery (
@@ -259,6 +346,47 @@ GROUP BY department HAVING MAX(age) > 30
259346 """ );
260347 }
261348
349+ @ Test
350+ public void testCountStarWithFilter () {
351+ givenQuery ("SELECT COUNT(*) FILTER(WHERE age > 30) FROM catalog.employees" )
352+ .assertPlan (
353+ """
354+ LogicalAggregate(group=[{}], COUNT(*) FILTER(WHERE age > 30)=[COUNT() FILTER $0])
355+ LogicalProject($f1=[>($2, 30)])
356+ LogicalTableScan(table=[[catalog, employees]])
357+ """ );
358+ }
359+
360+ @ Test
361+ public void testFilteredAggregateWithGroupBy () {
362+ givenQuery (
363+ """
364+ SELECT department, SUM(age) FILTER(WHERE age > 30) FROM catalog.employees
365+ GROUP BY department
366+ """ )
367+ .assertPlan (
368+ """
369+ LogicalAggregate(group=[{0}], SUM(age) FILTER(WHERE age > 30)=[SUM($1) FILTER $2])
370+ LogicalProject(department=[$3], age=[$2], $f3=[>($2, 30)])
371+ LogicalTableScan(table=[[catalog, employees]])
372+ """ );
373+ }
374+
375+ @ Test
376+ public void testMultipleFilteredAggregates () {
377+ givenQuery (
378+ """
379+ SELECT MAX(age) FILTER(WHERE age > 30), MIN(age) FILTER(WHERE age < 50)
380+ FROM catalog.employees
381+ """ )
382+ .assertPlan (
383+ """
384+ LogicalAggregate(group=[{}], MAX(age) FILTER(WHERE age > 30)=[MAX($0) FILTER $1], MIN(age) FILTER(WHERE age < 50)=[MIN($0) FILTER $2])
385+ LogicalProject(age=[$2], $f4=[>($2, 30)], $f5=[<($2, 50)])
386+ LogicalTableScan(table=[[catalog, employees]])
387+ """ );
388+ }
389+
262390 @ Test
263391 public void testScalarFnOverAggregate () {
264392 givenQuery ("SELECT ABS(MAX(age)) FROM catalog.employees" )
@@ -337,6 +465,33 @@ GROUP BY department HAVING MAX(age) > 30 AND MIN(age) < 50
337465 """ );
338466 }
339467
468+ @ Test
469+ public void testCountDistinctWindowWithOrderBy () {
470+ // No frame printed: RANGE .. CURRENT ROW is Calcite's default for ORDER BY.
471+ givenQuery (
472+ """
473+ SELECT department, COUNT(DISTINCT name) OVER(ORDER BY department) FROM catalog.employees
474+ """ )
475+ .assertPlan (
476+ """
477+ LogicalProject(department=[$3], COUNT(DISTINCT name) OVER(ORDER BY department)=[COUNT(DISTINCT $1) OVER (ORDER BY $3 NULLS FIRST)])
478+ LogicalTableScan(table=[[catalog, employees]])
479+ """ );
480+ }
481+
482+ @ Test
483+ public void testSumWindowWithPartitionAndOrderBy () {
484+ givenQuery (
485+ """
486+ SELECT name, SUM(age) OVER(PARTITION BY department ORDER BY age) FROM catalog.employees
487+ """ )
488+ .assertPlan (
489+ """
490+ LogicalProject(name=[$1], SUM(age) OVER(PARTITION BY department ORDER BY age)=[SUM($2) OVER (PARTITION BY $3 ORDER BY $2 NULLS FIRST)])
491+ LogicalTableScan(table=[[catalog, employees]])
492+ """ );
493+ }
494+
340495 @ Test
341496 public void testWindowOrderByDefaultsNullsFirst () {
342497 // Window function ORDER BY without explicit NULLS FIRST/LAST defaults to NULLS FIRST,
0 commit comments