Skip to content

feat: SQL UNION over project and filter. - #20593

Merged
gianm merged 3 commits into
apache:masterfrom
gianm:union-smf
Oct 15, 2026
Merged

gianm merged 3 commits into
apache:masterfrom
gianm:union-smf

Conversation

@gianm

@gianm gianm commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

This patch adds the ability for SQL UNION to run over relations that involve projections and filters of base tables, such as:

  SELECT dim1, SUM(m1), COUNT(*)
  FROM (SELECT dim1, m1 FROM foo2 WHERE dim1 = '1'
        UNION ALL
        SELECT dim1, m1 FROM foo)
  GROUP BY 1;

Such queries are planned into stacks of the existing "filter" datasource and the new "project" datasource.

Other changes, outside the SQL planner:

  1. DataSource method "createSegmentPruner" has DimFilter and
    VirtualColumns added as parameters. This enables DataSource
    implementations, such as FilteredDataSource and ProjectDataSource,
    to rewrite the filter and contribute additional virtual columns to
    the pruning logic. ExecutionVertex#isBaseColumn is removed and more
    scenarios are now pruneable.

  2. DataSource gets "getReservedColumns" with a set of column names to
    avoid when generating higher-level virtual columns. This is used
    by the SQL planner to avoid name collisions.

  3. DataSource gets "mayFilterRows", which allows time-boundary queries
    to properly recognize that filtering DataSources should go down the
    "query has filter" path.

  4. Fix an issue where various CursorHolder implementations return
    lists from "getOrdering" that erroneously include base columns
    which were shadowed by virtual columns.

  5. Updates to MSQ to call the new ExecutionVertex#splitUnion and
    splitUnionSegmentMapFunctions methods to provide each arm with its
    own SegmentPruner and SegmentMapFunction.

This patch adds the ability for SQL UNION to run over relations that
involve projections and filters of base tables, such as:

  SELECT dim1, SUM(m1), COUNT(*)
  FROM (SELECT dim1, m1 FROM foo2 WHERE dim1 = '1'
        UNION ALL
        SELECT dim1, m1 FROM foo)
  GROUP BY 1;

Such queries are planned into stacks of the existing "filter" datasource
and the new "project" datasource.

Other changes, outside the SQL planner:

1) DataSource method "createSegmentPruner" has DimFilter and
   VirtualColumns added as parameters. This enables DataSource
   implementations, such as FilteredDataSource and ProjectDataSource,
   to rewrite the filter and contribute additional virtual columns to
   the pruning logic. ExecutionVertex#isBaseColumn is removed and more
   scenarios are now pruneable.

2) DataSource gets "getReservedColumns" with a set of column names to
   avoid when generating higher-level virtual columns. This is used
   by the SQL planner to avoid name collisions.

3) DataSource gets "mayFilterRows", which allows time-boundary queries
   to properly recognize that filtering DataSources should go down the
   "query has filter" path.

4) Fix an issue where various CursorHolder implementations return
   lists from "getOrdering" that erroneously include base columns
   which were shadowed by virtual columns.

5) Updates to MSQ to call the new ExecutionVertex#splitUnion and
   splitUnionSegmentMapFunctions methods to provide each arm with its
   own SegmentPruner and  SegmentMapFunction.
@github-actions github-actions Bot added Area - Documentation Area - Batch Ingestion Area - Querying Area - Segment Format and Ser/De Area - MSQ For multi stage queries - https://github.com/apache/druid/issues/12262 labels Oct 14, 2026
new LookupDataSource("lookyloo"),
"j0.",
equalsCondition(
makeColumnExpression("x0"),
"j0.",
equalsCondition(
makeColumnExpression("x0"),
makeColumnExpression("j0.k")
),
new LookupDataSource("lookyloo"),
"j0.",
equalsCondition(makeColumnExpression("dim1"), makeColumnExpression("j0.k")),
),
new LookupDataSource("lookyloo"),
"j0.",
equalsCondition(makeColumnExpression("dim1"), makeColumnExpression("j0.k")),
Comment on lines +149 to +150
plannerContext.setPlanningError("SQL requires union between inputs that are not simple table scans "
+ "and involve more than a filter or a projection.");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: this error message reads a bit off

@gianm
gianm merged commit d5d0f11 into apache:master Oct 15, 2026
42 of 43 checks passed
@gianm
gianm deleted the union-smf branch October 15, 2026 06:22
@github-actions github-actions Bot added this to the 39.0.0 milestone Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area - Batch Ingestion Area - Documentation Area - MSQ For multi stage queries - https://github.com/apache/druid/issues/12262 Area - Querying Area - Segment Format and Ser/De

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants