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
2 changes: 1 addition & 1 deletion .agents/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ flowchart LR

VALUES and SET use the same scalar expression resolver as SELECT. UPDATE supplies the target relation; VALUES supplies only parameter/local bindings. Arithmetic lookup follows only grammar wrappers spanning the complete expression, rather than scanning operand subtrees. ANTLR operator contexts preserve precedence and scalar parentheses are unwrapped only after excluding tuples, lambdas and subqueries. DML values resolve supported comparisons with their nullability. Assignment validation is shared with SELECT-backed DML and permits exact types, optional destinations, contextual NULL and lossless integer widening; it does not insert casts or evaluate SQL. Direct parameter assignment inference remains separate from resolving operands in compound expressions.

`internal/model` is the boundary between analysis and generation: YQL type identity, parameters, result sets and source locations. Nullability is an `Optional` type, compound type metadata is retained, and Struct fields have name-based identity independent of declaration order. `Bytes` normalizes to binary `String`; `Text` normalizes to Unicode `Utf8`. A table catalog and a query projection are distinct: `SELECT name` does not generate the whole table. Projection columns retain their API name and, where different, the exact YDB result name in `WireName`. For example, an unaliased `b.title` in a join is returned as `b.title`. Name-based decoders use `Column.ResultName()`, which selects `WireName` when present and otherwise `Name`; positional decoders retain the analyzed projection order. Generated API fields continue to use `Name`. `AnalyzedQuery.SQL` contains executable YQL with supported wildcard projections expanded into explicit quoted columns; declarations and text outside wildcard spans are retained. The analyzer records explicitly declared parameter names in `DeclaredParameters`. Generators retain user-written declarations in executable SQL. SDK adapters use this metadata to avoid duplicate declarations while binding inferred parameters with their resolved types. Parameter names omit the leading `$`; their types and result column types must be resolved. TypeScript result properties use `Column.ResultName()` verbatim, including qualified names as quoted properties. No target-specific SQL alias rewriting or result-key conversion is needed for this target. `analyzer.Analyze` returns an error whenever its result contains diagnostics.
`internal/model` is the boundary between analysis and generation: YQL type identity, parameters, result sets and source locations. Nullability is an `Optional` type, compound type metadata is retained, and Struct fields have name-based identity independent of declaration order. `Bytes` normalizes to binary `String`; `Text` normalizes to Unicode `Utf8`. A table catalog and a query projection are distinct: `SELECT name` does not generate the whole table. Projection columns retain their API name and, where different, the exact YDB result name in `WireName`. For example, an unaliased `b.title` in a join is returned as `b.title`. Name-based decoders use `Column.ResultName()`, which selects `WireName` when present and otherwise `Name`; positional decoders retain the analyzed projection order. Generated API fields continue to use `Name`. `AnalyzedQuery.SQL` contains executable YQL with supported wildcard projections expanded into explicit quoted columns; unnamed computed expressions combined with a wildcard receive explicit aliases preserving their original YDB names, so expansion cannot change references such as ORDER BY column1. Declarations and text outside those wildcard replacements and alias insertions are retained. The analyzer records explicitly declared parameter names in `DeclaredParameters`. Generators retain user-written declarations in executable SQL. SDK adapters use this metadata to avoid duplicate declarations while binding inferred parameters with their resolved types. Parameter names omit the leading `$`; their types and result column types must be resolved. TypeScript result properties use `Column.ResultName()` verbatim, including qualified names as quoted properties. No target-specific SQL alias rewriting or result-key conversion is needed for this target. `analyzer.Analyze` returns an error whenever its result contains diagnostics.

The language packages in `internal/codegen` produce files from that resolved model. They handle naming, runtime-specific parameter binding, result decoding and resource lifetimes. They do not analyze SQL or load external code. jOOQ uses typed JDBC execution for structured batches and explicitly declared queries, with resolved table references rendered through jOOQ to preserve table mappings. For the jOOQ DSL target, `AnalyzedQuery.Syntax` retains ANTLR contexts and analyzer-resolved column/table bindings for the executable SQL, including the positions after wildcard expansion. The renderer walks these contexts directly; it does not reparse text or construct a second AST. Unsupported DSL constructs fail in the target without restricting other generators. Lexical adaptation of parameter placeholders for a driver is separate from semantic query analysis and must preserve strings, comments and identifiers. `internal/codegen/jdbc` implements shared SQL rendering for Java and Kotlin; their SDK binding and result decoding remain in each generator.

Expand Down
1 change: 1 addition & 0 deletions .agents/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Read [decisions](decisions.md) before changing the analysis/generation boundary

- [README](../README.md): build and first generation.
- [Compatibility](../docs/compatibility.md): supported config, queries, schema migrations, intentional exclusions and output ownership.
- [YQL built-ins](../docs/yql-builtins.md): complete upstream reference-section inventory and remaining semantic/type prerequisites, distinct from the implemented function subset.
- [Database-assisted analysis](../docs/database-analysis.md): live schema discovery, drift checks and connection settings.
- [Targets](../docs/targets.md), [C++](../docs/cpp.md), [C#](../docs/csharp.md), [Java](../docs/java.md), [Kotlin](../docs/kotlin.md), [TypeScript](../docs/typescript.md), [Rust](../docs/rust.md), [PHP](../docs/php.md): generated API and runtime contracts.
- [Installation](../docs/installation.md): release artifacts, checksum and version checks.
Expand Down
2 changes: 1 addition & 1 deletion .agents/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ These choices constrain maintenance; implementation details remain in the linked
| SQL-first framework adapters | Named SQL determines generated methods. The jOOQ prototype translates those statements to typed DSL using the analyzed ANTLR contexts. It does not invent entity CRUD operations. ORM contracts for Spring/Hibernate remain deferred in [issue #12](https://github.com/ydb-platform/sqlc-ydb/issues/12). See [Java](../docs/java.md). |
| Separate API field names from result-set keys | JOIN result keys can include table qualifiers. Name-based decoders use `Column.ResultName()`; positional decoders retain projection order. See [architecture](architecture.md). |
| TypeScript DTOs preserve result column names | Result properties use exact SDK keys, with quoted properties for qualified names. This avoids SQL alias changes and runtime name mapping. Method and parameter names retain their TypeScript naming conventions. |
| Preserve declarations and formatting outside wildcard expansions | Expand supported SELECT/RETURNING wildcards before generators; retain source `DECLARE` statements and all SQL text outside replaced wildcard spans. The analyzer records declared parameter names once; adapters avoid duplicate SDK declarations without deleting source text. See [architecture](architecture.md). |
| Preserve declarations and formatting during projection normalization | Expand supported SELECT/RETURNING wildcards before generators. If a SELECT combines a wildcard and unaliased computed expressions, pin their original YDB result names with explicit AS aliases before expansion; otherwise extra columns would change those names and could break ORDER BY references. Retain source `DECLARE` statements and all text outside the wildcard replacements and these alias insertions. The analyzer records declared parameter names once; adapters avoid duplicate SDK declarations without deleting source text. See [architecture](architecture.md). |
| Follow each target's documented SDK value contract | Typed bindings preserve YQL parameter types. The maintainer-approved TypeScript API uses SDK-native Date and parsed JSON results; other targets retain their documented precision guarantees. See [targets](../docs/targets.md) and its language references. |
| SQL at its execution site | Keep queries readable where they execute. The two-level indentation and batch expression rules are in [generated code layout](development.md#generated-code-layout). |
| Share example dependencies by language | Keep generated outputs inside each example's language/runtime directories and reuse dependency manifests and harnesses across example families. See [development](development.md#generated-runtime-checks). |
Expand Down
4 changes: 3 additions & 1 deletion .agents/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ go tool cover -html=coverage.out -o coverage.html

`make coverage` runs the root Go module's tests without caching and writes `coverage.out` in atomic mode. `-coverpkg=./...` includes calls across package boundaries, so CLI and golden tests contribute to analyzer and generator coverage. The final `total` from `go tool cover` is the combined statement coverage; the per-test-package percentages are not independent package coverage figures. The denominator contains only sqlc-ydb runtime code, including the CLI entry point even when untested. Unit and end-to-end tests run and contribute coverage of that code, but their own source is not measured. Examples, the `internal/endtoend` harness, `*_test.go` files, golden outputs, `.github` tooling and the external ANTLR parser dependency are outside this scope. Go already excludes test source and the separate examples module from the profile; `codecov.yml` also explicitly excludes the repository's non-runtime paths. This local profile excludes live YDB tests unless their environment variables are set, and excludes optional SDK checks unless explicitly enabled.

CI saves the offline profile together with `coverage-sdk.out` and `coverage-typescript.out` from compiler/SDK-backed generator tests as the `generator-coverage` artifact and uploads them to Codecov with the `unit` flag on pushes to `main` and pull requests. The `ydb-acceptance` job also instruments the semantic, integer pagination, table-path-prefix, callback, Go generator and Python generator live tests and uploads their six profiles with the `integration` flag, saving them as the `generator-integration-coverage` artifact. Codecov merges these profiles; generated application runtime coverage is not measured. SDK checks contribute coverage of the generator code they execute. The PR comment updates as reports arrive, so the first report can show only offline coverage. [codecov.yml](../codecov.yml) compares project coverage with the base commit (allowing a one percentage point drop) and requires 80% patch coverage. It enables one updated PR comment with the coverage difference and impacted files, including on the first PR without a base report. A successful `main` upload establishes the comparison baseline and populates the README badge.
CI saves the offline profile together with `coverage-sdk.out` and `coverage-typescript.out` from compiler/SDK-backed generator tests as the `generator-coverage` artifact and uploads them to Codecov with the `unit` flag on pushes to `main` and pull requests. The `ydb-acceptance` job also instruments the semantic, integer pagination, table-path-prefix, callback, shared-expression, Go generator and Python generator live tests and uploads their seven profiles with the `integration` flag, saving them as the `generator-integration-coverage` artifact. Codecov merges these profiles; generated application runtime coverage is not measured. SDK checks contribute coverage of the generator code they execute. The PR comment updates as reports arrive, so the first report can show only offline coverage. [codecov.yml](../codecov.yml) compares project coverage with the base commit (allowing a one percentage point drop) and requires 80% patch coverage. It enables one updated PR comment with the coverage difference and impacted files, including on the first PR without a base report. A successful `main` upload establishes the comparison baseline and populates the README badge.

Repository administrators must enable `ydb-platform/sqlc-ydb` in Codecov and grant the [Codecov GitHub App](https://github.com/apps/codecov) access so it can post PR comments. Set the repository Actions secret `CODECOV_TOKEN` to the Codecov upload token, as in ydb-go-sdk. Alternatively, the organization can allow tokenless public uploads with **Global Upload Token → Not required** in Codecov; the action accepts an empty secret in that mode. Public fork PR uploads do not need access to the secret. See [Codecov token authentication](https://docs.codecov.com/docs/codecov-tokens) and [PR comments](https://docs.codecov.com/docs/pull-request-comments). An upload failure fails the CI job rather than silently leaving stale coverage.

Expand Down Expand Up @@ -173,3 +173,5 @@ YDB_CONNECTION_STRING=grpc://localhost:2136/local composer --working-dir=tests/e
The [TypeScript](../docs/typescript.md), [Rust](../docs/rust.md) and [PHP](../docs/php.md) pages define their value representations, dependencies and runtime ownership.

`TestLiveYDBEach` generates the callback fixture and runs both Go profiles sequentially using unique disposable tables. It checks full and empty results, a 16 MiB streaming result, cancellation, early termination, no replay of retryable callback errors, connection reuse, sessions and transactions. Run `YDB_CONNECTION_STRING=grpc://localhost:2136/local go test -p 1 -count=1 -timeout=240s ./internal/endtoend -run '^TestLiveYDBEach$' -v`. Stable and nightly CI run this suite in a separate sequential step with its own 240-second test budget; stable CI includes `coverage-each-live.out` in integration coverage. `TestEachGeneratedGoCompiles` checks the same harness offline; `TestEachRuntime` in the Go generator package covers deterministic error/cleanup paths and retained-memory bounds.

`TestLiveYDBSharedExpressions` checks Boolean values, conditional aggregates, string concatenation, verified casts, literal-aware COALESCE and implicit result names against server metadata and generated Go native/database/sql execution. Wildcard collision checks compare original and normalized SQL metadata independently and verify positional decoding with distinct values and types. Run `YDB_CONNECTION_STRING=grpc://localhost:2136/local go test -p 1 -count=1 -timeout=240s ./internal/endtoend -run '^TestLiveYDBSharedExpressions$' -v` sequentially with the other live suites; set `SQLC_YDB_TEST_MAVEN=mvn` to include generated jOOQ execution for output-alias ordering and wildcard collisions. Stable and nightly CI run the suite in a separate step; stable CI enables jOOQ and uploads `coverage-shared-expressions-live.out` with the integration coverage. The authors examples additionally execute reporting, prefix search and export metadata through the generated clients.
Loading
Loading