Skip to content

Conversation

copito
Copy link

@copito copito commented Jun 29, 2025

This commit introduces the sqlc.optional feature, allowing conditional inclusion of SQL query fragments at runtime.

Key changes:

  1. Parser Enhancement: The SQL parser now recognizes sqlc.optional('ConditionKey', 'SQLFragment') syntax within query files. This information is stored in the query's metadata.

  2. Code Generation:

    • Go code generation logic has been updated to process these OptionalBlocks.
    • Generated Go functions now include new parameters (typed as interface{}) corresponding to each ConditionKey.
    • Templates (stdlib/queryCode.tmpl, pgx/queryCode.tmpl) were modified to dynamically build the SQL query string and its arguments at runtime. If an optional Go parameter is non-nil, its associated SQL fragment is included in the final query, and its value is added to the list of database arguments.
  3. Parameter Handling: $N placeholders in all SQL fragments (base or optional) consistently refer to the Nth parameter in the generated Go function's signature.

  4. Documentation: Added comprehensive documentation for sqlc.optional in docs/reference/query-annotations.md, covering syntax, behavior, parameter numbering, and examples.

  5. Examples: A new runnable example has been added to examples/dynamic_query/postgresql/ to demonstrate practical usage.

  6. Tests: New end-to-end tests were added in internal/endtoend/testdata/dynamic_query/ for both stdlib and pgx drivers, ensuring the correctness of the generated code.

This commit introduces the `sqlc.optional` feature, allowing conditional inclusion of SQL query fragments at runtime.

Key changes:

1.  **Parser Enhancement**: The SQL parser now recognizes `sqlc.optional('ConditionKey', 'SQLFragment')` syntax within query files. This information is stored in the query's metadata.

2.  **Code Generation**:
    - Go code generation logic has been updated to process these `OptionalBlocks`.
    - Generated Go functions now include new parameters (typed as `interface{}`) corresponding to each `ConditionKey`.
    - Templates (`stdlib/queryCode.tmpl`, `pgx/queryCode.tmpl`) were modified to dynamically build the SQL query string and its arguments at runtime. If an optional Go parameter is non-nil, its associated SQL fragment is included in the final query, and its value is added to the list of database arguments.

3.  **Parameter Handling**: `$N` placeholders in all SQL fragments (base or optional) consistently refer to the Nth parameter in the generated Go function's signature.

4.  **Documentation**: Added comprehensive documentation for `sqlc.optional` in `docs/reference/query-annotations.md`, covering syntax, behavior, parameter numbering, and examples.

5.  **Examples**: A new runnable example has been added to `examples/dynamic_query/postgresql/` to demonstrate practical usage.

6.  **Tests**: New end-to-end tests were added in `internal/endtoend/testdata/dynamic_query/` for both `stdlib` and `pgx` drivers, ensuring the correctness of the generated code.
@dosubot dosubot bot added size:XXL This PR changes 1000+ lines, ignoring generated files. 🔧 golang labels Jun 29, 2025
@ororsatti
Copy link

ororsatti commented Jun 29, 2025

Just a comment, but maybe the optional types can be something like NullString ?

type xxxOptional struct {
Xxx *<type>
Valid bool
}

This way it won't have to be interface{} when ever you wanna use a optional value.

@kyleconroy
Copy link
Collaborator

Really appreciate you taking a crack at this! You're heading in the right direction, but I don't think this exact syntax is what we're going to adopt. Sorry I don't have more specific feedback, but hoping to get more time in the next few months to get to a design that I'm happy with.

In the future, please start a discussion first so that you don't implement a full feature I end up not merging.

@kyleconroy kyleconroy closed this Aug 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size:XXL This PR changes 1000+ lines, ignoring generated files. 🔧 golang
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants