Skip to content

Reference impl gep26#2658

Draft
paulk-asert wants to merge 3 commits into
apache:masterfrom
paulk-asert:referenceImpl_gep26
Draft

Reference impl gep26#2658
paulk-asert wants to merge 3 commits into
apache:masterfrom
paulk-asert:referenceImpl_gep26

Conversation

@paulk-asert

@paulk-asert paulk-asert commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

NOT for MERGING just yet! This is a reference implementation for GEP-26. I think we still want to target Groovy 7 and we're not quite ready to branch for that yet, but this gives us something to discuss about the feature boundary for what we deliver and for performance testing.

GEP-26: GINQ SQL backend — reference implementation (native-sql provider)

Implements the core of GEP-26: the same GINQ syntax, executed against a relational database instead of in-memory collections. See the GEP for the full design rationale, architecture, and phasing; this PR is a working subset.

def threshold = 50000
GQL(provider: 'native-sql', dataSource: db) {
    from e in 'employees'
    join d in 'departments' on e.deptId == d.id
    where e.salary > threshold
    select e.name, d.name as deptName
}
// SELECT e.name, d.name AS deptName FROM employees e
//   INNER JOIN departments d ON e.deptId = d.id WHERE e.salary > ?

What's included

  • New optional module groovy-ginq-sql (excluded from groovy-all, like groovy-ginq):
    GINQ AST → SQL IR translator, ANSI renderer with a minimal Dialect SPI, and a thin
    runtime wrapper over groovy.sql.Sql returning Queryable<GroovyRowResult>.
  • Coverage: GEP phases 1–2 (single-table queries, all join types, classic and
    groupby ... into aggregation, having, set operations, distinct, orderby/limit) plus
    phase 4 subqueries (derived tables, exists, in (subquery), scalar subqueries,
    including correlated references) and a first tranche of function mapping
    (UPPER/LOWER/TRIM/CHAR_LENGTH/LIKE with escaping/SUBSTRING/REPLACE/||/CASE WHEN).
  • Parameter safety: the SQL text is a compile-time constant; every literal and captured
    variable becomes a positional bound parameter (see the GEP's security section).
  • Strict mode: untranslatable constructs are compile-time errors with source positions.
  • Small additive changes to groovy-ginq core: provider/dataSource options, a
    ServiceLoader-based GinqProvider registry, raw option-expression plumbing on the
    (incubating) GinqAstVisitor SPI, optimizer gating for non-collection providers, and a
    @GQ(provider=...) member.

Not in this PR (per GEP phasing)

jOOQ provider (phase 3), mixed-mode fallback (phase 5), window functions, and dialect breadth.

Notes for reviewers

  • Trailing orderby/limit on a set operation applies to the combined result (SQL
    semantics), unlike the collection provider which sorts the final operand before combining.
    Flagged in the userguide; happy to adjust if the divergence is unwanted.
  • Tests: renderer unit tests, generated-SQL shape tests, and end-to-end tests against
    in-memory HSQLDB (already in the dependency-verification metadata — no new artifacts).
  • Because GINQ macros expand at test-compile time, groovy-ginq-sql/build.gradle declares
    the provider classes as an input to compileTestGroovy so macro-using tests aren't served
    stale from the build cache.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a new “provider” SPI for GINQ, and adds a reference SQL backend (GEP-26) as an optional module (groovy-ginq-sql) that translates GINQ queries into ANSI SQL with bound parameters and executes them against JDBC data sources.

Changes:

  • Add provider (and runtime dataSource) configuration plumbing to GINQ macros/annotation processing, plus provider discovery via ServiceLoader.
  • Add a new optional groovy-ginq-sql subproject implementing a native-sql provider with a SQL IR, renderer, strict-mode translator, and runtime execution support.
  • Extend documentation/specs/tests to cover provider selection and SQL execution semantics.

Reviewed changes

Copilot reviewed 55 out of 55 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
subprojects/groovy-ginq/src/test/groovy/org/apache/groovy/ginq/GinqErrorTest.groovy Updates option validation expectations; adds provider-related error tests.
subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy Adds spec coverage for selecting the collection provider via provider.
subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc Documents provider selection and the new SQL backend usage/semantics.
subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/transform/GinqASTTransformation.java Filters default @GQ options to those actually present on the annotation (excludes runtime-only options).
subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/package-info.java Adds package documentation for provider SPI.
subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/GinqProvider.java Introduces provider SPI (name → AST walker class).
subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/GinqGroovyMethods.groovy Adds provider/dataSource options, resolves provider via ServiceLoader, and passes raw option expressions to visitors.
subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/dsl/GinqAstVisitor.java Adds configuration-expression hooks for passing raw option expressions (runtime values) to providers.
subprojects/groovy-ginq/src/main/groovy/groovy/ginq/transform/GQ.java Adds provider() option to @GQ annotation (incubating).
subprojects/groovy-ginq-sql/src/test/groovy/org/apache/groovy/ginq/provider/sql/SqlRendererTest.groovy Unit tests for SQL rendering and parameter ordering.
subprojects/groovy-ginq-sql/src/test/groovy/org/apache/groovy/ginq/provider/sql/GinqSqlTranslationTest.groovy Validates generated SQL and parameters via a capturing Sql wrapper.
subprojects/groovy-ginq-sql/src/test/groovy/org/apache/groovy/ginq/provider/sql/GinqSqlTestSupport.groovy Test fixture for creating/populating in-memory HSQLDB databases.
subprojects/groovy-ginq-sql/src/test/groovy/org/apache/groovy/ginq/provider/sql/GinqSqlIntegrationTest.groovy End-to-end execution tests against HSQLDB for the native-sql provider.
subprojects/groovy-ginq-sql/src/test/groovy/org/apache/groovy/ginq/provider/sql/GinqSqlErrorTest.groovy Strict-mode error tests for SQL translation/provider constraints.
subprojects/groovy-ginq-sql/src/main/resources/META-INF/services/org.apache.groovy.ginq.provider.GinqProvider Registers the SQL provider via ServiceLoader.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/runtime/SqlGinqRuntime.java Runtime execution support for rendered SQL and LIKE pattern escaping.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/runtime/package-info.java Package docs for SQL runtime support.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/render/SqlRenderer.groovy Renders SQL IR to SQL text + positional parameter expressions.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/render/RenderedSql.groovy Holds rendered SQL and collected parameter expressions.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/render/package-info.java Package docs for SQL rendering.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/render/Dialect.java Dialect SPI for identifier/function/operator differences.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/render/AnsiDialect.java Default ANSI SQL dialect implementation.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/package-info.java Package docs for the SQL provider module.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/NativeSqlGinqProvider.java Provider SPI implementation for native-sql.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlExpr.groovy Base type for SQL expression IR.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlBinary.groovy IR node for binary operators.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlUnary.groovy IR node for prefix unary operators.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlColumn.groovy IR node for column references.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlParam.groovy IR node for bound parameters (captures Groovy expressions).
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlLiteral.groovy IR node for inline SQL literals (compile-time constants).
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlIsNull.groovy IR node for IS NULL / IS NOT NULL.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlIn.groovy IR node for IN/NOT IN value lists.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlInQuery.groovy IR node for IN/NOT IN subqueries.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlExists.groovy IR node for EXISTS(subquery).
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlScalarQuery.groovy IR node for scalar subqueries.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlFunction.groovy IR node for functions/aggregates.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlCaseWhen.groovy IR node for searched CASE WHEN expressions.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlCountStar.groovy IR node for COUNT(*).
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlStar.groovy IR node for * / alias.* projections.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlProjection.groovy IR node for select-list projections (+ optional alias).
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlOrderSpec.groovy IR node for ORDER BY items (including null ordering).
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlOrdinal.groovy IR node for select-list ordinals (set-op ORDER BY).
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlTableSource.java Marker interface for aliased table sources.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlTableRef.groovy IR node for table references.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlDerivedTable.groovy IR node for derived tables (subquery in FROM/JOIN).
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlJoin.groovy IR node for joins.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlQueryNode.java Marker interface for top-level renderable queries.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlQuery.groovy IR node for SELECT queries.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/SqlSetQuery.groovy IR node for set operations (UNION/INTERSECT/MINUS).
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/ir/package-info.java Package docs for SQL IR.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/GinqToSqlTranslator.groovy Strict-mode translator from GINQ AST to SQL IR.
subprojects/groovy-ginq-sql/src/main/groovy/org/apache/groovy/ginq/provider/sql/GinqSqlWalker.groovy Provider AST walker that renders and rewrites queries into runtime execution calls.
subprojects/groovy-ginq-sql/build.gradle Adds the optional SQL provider module build + test dependencies and macro-cache invalidation wiring.
settings.gradle Registers the new groovy-ginq-sql subproject.

Comment thread subprojects/groovy-ginq-sql/build.gradle
@paulk-asert paulk-asert force-pushed the referenceImpl_gep26 branch from 30f1d7b to 8a0d584 Compare July 3, 2026 04:22
@paulk-asert paulk-asert marked this pull request as draft July 3, 2026 04:22
@testlens-app

testlens-app Bot commented Jul 4, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: 7a1c966
▶️ Tests: 75718 executed
⚪️ Checks: 23/23 completed


Learn more about TestLens at testlens.app.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants