Skip to content

Support :execresult, :batch*, more PostgreSQL types, composites, SQLite affinity - #43

Merged
doron050 merged 6 commits into
mainfrom
devin/1793571509-unsupported-features
Nov 3, 2026
Merged

doron050 merged 6 commits into
mainfrom
devin/1793571509-unsupported-features

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds the sqlc features from the feature-gap analysis (section 1b) that used to make generation fail with an error. It also contains the section 1c options work from #44, which was merged into this branch.

  • :execresult: returns ExecResult (rows_affected, last_insert_id). This is a Data class (a Struct below Ruby 3.2) nested in the query class. pg: result.cmd_tuples with nil last id (use RETURNING). mysql2: stmt.affected_rows / client.last_id. sqlite3: client.changes / client.last_insert_row_id.
  • :batchexec / :batchone / :batchmany: take an Array of <Query>Args (the same kind of Data class :copyfrom uses) and run the prepared statement once per element on one connection. They return nil / Array[Row?] / Array[Array[Row]]. Available on all three drivers. This is sequential execution, not libpq pipeline mode.
  • Unknown types no longer abort generation: a query column or parameter whose type the plugin doesn't map (e.g. now(), unnest, any, domains) is typed untyped. Models already did this.
  • More PostgreSQL types: timetz, tsvector / tsquery, hstore, ltree / lquery / ltxtquery, geometric types, ranges and multiranges, reg*, pg_lsn, ... map to String, and oid maps to Integer. These are the classes the pg gem returns; I checked each one against postgres:16. Pseudo-types (any, anyelement, record, void, ...) map to untyped.
  • Composite types: Schema.composite_types (protobuf field 5) is now decoded. Composite columns are String (the record text, e.g. "(3,4)").
  • SQLite declared types: VARCHAR(255), DECIMAL(10, 5), UNSIGNED BIG INT, NATIVE CHARACTER(70) are normalized. Types that no mapping matches follow SQLite's type-affinity rules, through a new driver hook affinity_type.
  • Options (from Options: model/table/db_type overrides, rename, global options, unknown-option errors, engine check, comments #44): model/table/db_type overrides, rename, exactTableNames, global options, errors for unknown options, engine/driver check, schema/table/column/enum comments as doc comments. Breaking: configs with misspelled option names now fail.

Domains stay untyped: sqlc sends only the domain name, not its base type.

The examples gain postgres_special_types (incl. a composite type and a domain), SQLite declared_types, and :execresult / :batch* queries for all three engines. The fixtures are recaptured, and steep_expectations.yml is refreshed (line shifts only).

Checklist

  • examples/ is regenerated (rake sqlc_generate_process) and committed
  • Tests added or updated (rake test, and rake end2end_* when the generated code changes)
  • The generated code stays RuboCop-clean (rake rubocop) and Steep-clean (rake steep)
  • Labelled (feature, bug, breaking, documentation) so the release notes are grouped correctly

Tested locally: rake test, rake rubocop steep, rake end2end_pg (postgres:16), rake end2end_mysql2 (mysql:8.3), rake end2end_sqlite3.

devin-ai-integration Bot and others added 2 commits November 1, 2026 22:17
…le/attribute names, outer-join embeds, nested and undecoded PG arrays

Co-Authored-By: Doron Eli Rachman <doron050@gmail.com>
…osite types, SQLite type affinity; unknown types fall back to untyped

Co-Authored-By: Doron Eli Rachman <doron050@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

devin-ai-integration Bot and others added 4 commits November 3, 2026 14:49
…wn-option errors, engine check, comments (#44)

## Summary
Fixes the configuration and option gaps from the feature-gap analysis
(section 1c). **Stacked on #43**, which is stacked on #42; retarget to
`main` once those are merged.

- **Overrides now apply to models.** Before, `overrides:` only affected
query rows and parameters, so `Author#bio` kept the database type while
`GetAuthorRow#bio` used the override. `*:<column>` now also applies to
models. Two new forms work like sqlc's Go overrides:
- `column: "<table>.<column>"` (or `"<schema>.<table>.<column>"`): the
table's model plus every query column that sqlc reports as coming from
that table.
  - `db_type: "uuid"`: every column or parameter of that database type.
- Order of precedence: `Query:col` > `table.col` > `*:col` > `db_type`.
- **`rename`**: `{authors: Writer, bio: biography}`. A table name (or
`schema.table`) sets the model class name. A column name sets the
attribute name in rows and models; the value is still read by the
original column name. Class names are validated.
- **`exactTableNames`** (the equivalent of `emit_exact_table_names`):
`authors` gives `Authors` instead of `Author`.
- **Global options**: `GenerateRequest.global_options` (field 6, the
plugin's entry in the top-level `options:` of `sqlc.yaml`) used to be
ignored. It is now merged under the codegen options: the codegen options
win, and the `overrides` of both apply.
- **Unknown options are rejected** instead of silently ignored, with a
hint for near misses: `unknown plugin options: generate_types (did you
mean generateTypes?)`.
- **Engine check**: `GenerateRequest.settings` (`version`, `engine`) is
now decoded. A driver used with another engine (e.g. `driver: pg` with
`engine: mysql`) is an error.
- **Comments**: table and enum comments become doc comments of the
models (`.rb` + `.rbs`), and column comments become comments in the RBS.
The PG example gains `COMMENT ON` statements to show this.

**Breaking:** configs with misspelled or unsupported option keys now
fail. Models change type when an existing `*:<column>` override matches
one of their columns.

The fixtures are recaptured; they now include `settings`.

## Checklist
- [x] `examples/` is regenerated (`rake sqlc_generate_process`) and
committed
- [x] Tests added or updated (`rake test`, and `rake end2end_*` when the
generated code changes)
- [x] The generated code stays RuboCop-clean (`rake rubocop`) and
Steep-clean (`rake steep`)
- [x] Labelled (`feature`, `bug`, `breaking`, `documentation`) so the
release notes are grouped correctly

Tested locally: `rake test`, `rake rubocop steep`, `rake end2end_pg`
(postgres:16).

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Doron Eli Rachman <doron050@gmail.com>
…wrong-output

Co-Authored-By: Doron Eli Rachman <doron050@gmail.com>

# Conflicts:
#	examples/authors/postgresql/query.sql
#	examples/authors/postgresql/schema.sql
#	examples/pg/models.rb
#	examples/pg/models.rbs
#	examples/pg/query_sql.rb
#	examples/pg/query_sql.rbs
#	lib/sqlc_gen_ruby/code.rb
#	lib/sqlc_gen_ruby/drivers/pg.rb
#	lib/sqlc_gen_ruby/generator.rb
#	lib/sqlc_gen_ruby/method_gen.rb
#	lib/sqlc_gen_ruby/row_layout.rb
#	lib/sqlc_gen_ruby/type_resolver.rb
#	steep_expectations.yml
#	test/features_test.rb
#	test/fixtures/pg.bin
#	test/golden/pg/default/models.rb
#	test/golden/pg/default/models.rbs
#	test/golden/pg/default/my_queries_sql.rb
#	test/golden/pg/default/other_sql.rb
#	test/golden/pg/default/query_sql.rb
#	test/golden/pg/default/query_sql.rbs
#	test/golden/pg/ruby31_gemfile/models.rb
#	test/golden/pg/ruby31_gemfile/models.rbs
#	test/golden/pg/ruby31_gemfile/my_queries_sql.rb
#	test/golden/pg/ruby31_gemfile/other_sql.rb
#	test/golden/pg/ruby31_gemfile/query_sql.rb
#	test/golden/pg/ruby31_gemfile/query_sql.rbs
#	test/golden/pg/ruby32_notypes/models.rb
#	test/golden/pg/ruby32_notypes/my_queries_sql.rb
#	test/golden/pg/ruby32_notypes/other_sql.rb
#	test/golden/pg/ruby32_notypes/query_sql.rb
#	tests/end2end_pg.rb
…9-unsupported-features

Co-Authored-By: Doron Eli Rachman <doron050@gmail.com>
@devin-ai-integration
devin-ai-integration Bot changed the base branch from devin/1793571093-fix-wrong-output to main November 3, 2026 13:03
@devin-ai-integration devin-ai-integration Bot reopened this Nov 3, 2026
@doron050
doron050 merged commit 6102eb9 into main Nov 3, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant