Skip to content

feat!: sqlc v1.31.1 feature parity - #2

Merged
kvdomingo merged 2 commits into
mainfrom
development
Oct 4, 2026
Merged

kvdomingo merged 2 commits into
mainfrom
development

Conversation

@kvdomingo

Copy link
Copy Markdown
Owner

No description provided.

kvdomingo and others added 2 commits September 9, 2026 00:53
* docs(openspec): propose sqlc-feature-parity change

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(tooling): move CI to sqlc 1.31.1 and examples to SQLAlchemy 2

Example deps move to SQLAlchemy 2, psycopg 3, pydantic 2 and mypy for
the upcoming fixture checks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(testdata): regenerate fixtures and examples with sqlc 1.31.1

Examples now build against the local plugin (file://../bin) so that
sqlc diff checks this tree rather than the released 1.2.0 WASM.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(ast): add ListComp, With, BinOp, Tuple, ellipsis and class type params

Needed for executemany param lists, error wrapping, X | None
annotations, Union[...] slices, protocol stubs and PEP 695 queriers.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(printer): escape string literals, print docstrings, pass and else

String constants escape backslashes and quotes, so SQL text is now
emitted as runtime text and the printer doubles its backslashes. Class
and function docstrings share one triple-quoted helper (multi-line
docstrings used to print five quotes), empty class bodies print pass,
multi-line field comments stay inside comments, and If prints else.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(codegen): escape Python keywords and sanitize enum member names

Field, parameter, method and class names go through one pyIdent helper
(rename, then a trailing underscore for hard keywords). Enum members
that sanitize to an empty, digit-leading or duplicate name get
VALUE_<n>, a VALUE_ prefix, or a _<k> suffix.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(codegen): record imports while building, share one querier builder

Each generated file now records the imports its nodes use (typing and
collections.abc names, dotted type modules, py_import names), replacing
the importer's parallel prediction. Sync and async querier methods come
from one builder with an async flag. pyType carries ArrayDims for nested
List wrappers, and the PostgreSQL map gains the varchar/bpchar/name/time/
timestamp spellings sqlc's Go codegen knows. Existing fixtures are
unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(testdata): cover emit_modern_types and emit_aware_datetime

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(config): add overrides, rename, omit_unused_structs, omit_sqlc_version

overrides map a db_type or column (with * globs) to a py_type, given as
a dotted path or as py_type plus py_import. Overrides and rename are
also read from sqlc's global options for the plugin; codegen entries
are checked first, while global rename values win. Invalid entries fail
generation and name the entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(querier): accept sessions and cast row values

Querier and AsyncQuerier take Connection | Session and AsyncConnection |
AsyncSession and declare a typed _conn. Row values are wrapped in
typing.cast so mypy --strict accepts the generated code. rowcount reads
and the :execresult return use string annotations, so no subscripted
SQLAlchemy type is evaluated at runtime. Annotation-only: behaviour is
unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(querier): generic queriers, query docstrings and sqlc.embed()

emit_generic_querier makes Querier/AsyncQuerier PEP 695 generics bounded
by the connection-or-session union, so Querier(session)._conn is typed
Session. Query comments become method docstrings. sqlc.embed() fields
are built as nested models from their run of row columns.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(querier): support :copyfrom, :batchexec, :batchone and :batchmany

All four take one positional Sequence of params objects. :copyfrom and
:batchexec run a single executemany (returning rowcount and None);
:batchone and :batchmany are generators that run the statement per item
and yield lazily. Generation used to fail on :copyfrom and panic on the
batch commands.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(querier): emit QuerierProtocol and AsyncQuerierProtocol

Behind emit_querier_protocol. Protocols come from the same method list
as the queriers; async generator methods are declared with plain def so
the implementation matches structurally.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(querier): typed query errors behind emit_query_errors

Generates errors.py with alt-sqlc-gen-python's QueryError hierarchy plus
constraint_name, and wraps each querier method body in
errors._wrap_errors(), which re-raises IntegrityError/OperationalError
as the class for the SQLSTATE. The with block encloses generator loops,
so errors while iterating are wrapped too. A query file mapping to
errors.py fails generation.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(ci): feature matrix fixtures, compile and mypy --strict in CI

Two kitchen-sink fixtures combine every new feature with the classic and
the modern option sets. The db job moves to Python 3.12 (PEP 695
fixtures), compiles every fixture, and type-checks both matrices.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(examples): exercise new features against Postgres

A library example is generated with the classic and the modern option
sets. pytest covers lazy batch results, single executemany calls, typed
errors (also while iterating) through psycopg and asyncpg, Session and
generic queriers, a protocol fake, and aware datetimes. The harness
moves to SQLAlchemy 2, psycopg 3 and pytest-asyncio 1.x.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* docs: document new options, commands and fork migration

README gains sections for every new option and command plus a note for
alt-sqlc-gen-python users; design.md records where the implementation
differs from the original plan.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* ci: update postgres

* ci: install sqlalchemy asyncio extras

* chore(go): bump to Go 1.27

go.mod moves from go 1.19 to 1.27 and mise pins 1.27.1; CI reads the
version from go.mod so the two cannot drift. Fixture sha256s follow the
rebuilt WASM.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* ci: add zizmor, pre-commit hooks

* ci: autogenerate release version

* docs(readme): match the implementation and the automated release

The README described the original fork's always-on modern output,
try/except error wrapping and a keyword-only :batchexec. Document the
opt-in options as implemented, the batch commands, the published
alt-sqlc-gen-python.wasm asset and the PR-title-driven release workflow.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* ci(release): start versioning at v1.0.0

The fork drops upstream's tags. With none present, the first releasable
merge is tagged v1.0.0 instead of counting up from v0.0.0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* docs: update readme

* docs(readme): document override aliases, generic py_type, rename precedence and embed nulls

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(codegen): escape shadowing params, dedupe param names, import every py_type module, accept db_type aliases

A keyword parameter named errors, models, cast or an imported module
shadowed the module-level name the method body reads. Repeated parameter
names produced a SyntaxError. A generic py_type such as
dict[str, decimal.Decimal] was cut at its last dot into an invalid import.
db_type: bigint never matched because sqlc reports pg_catalog.int8.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(codegen): escape builtin-named params, keep deduped names unique

Params named after a builtin or py_type name used inside cast() (list,
int, str, dict, ...) shadowed it in the method body; escape them like
errors/cast. Dedup suffixes for params and struct fields now skip names
already taken, so id, id, id_2 no longer yields two id_2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(codegen): escape builtin-named methods, reject models.sql query files

Method names are now escaped against the same shadowed-name set as params,
so a query named List/Int/Models no longer hides those types in later
annotations of the class body. A query file named models.sql now errors
instead of silently overwriting models.py.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(codegen): reject duplicate method names, rename generic type parameter

Two queries that map to the same Python method (e.g. List and List_) now
fail generation instead of emitting duplicate defs and constants.

The generic querier type parameter is now _ConnT, so it no longer shadows
the SQL constant of a query named T.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(codegen): scope duplicate-name checks per query file, catch constant and NFKC collisions

Each query file is its own module, so same-named methods across files are
valid again. Also reject duplicate constants and methods that collide after
Python's NFKC identifier normalisation. Update docs to the _ConnT type
parameter name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@kvdomingo kvdomingo self-assigned this Oct 4, 2026
@kvdomingo kvdomingo changed the title feat: sqlc v1.31.1 feature parity feat!: sqlc v1.31.1 feature parity Oct 4, 2026
@kvdomingo
kvdomingo merged commit d3b9c8b into main Oct 4, 2026
2 checks passed
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.

1 participant