Repository navigation
Conversation
A column typed with a domain reports the domain's name, as the analysis core and the databases themselves do, but nothing told a plugin what the domain stands on, so generators fell back to an untyped value. The plugin catalog's Schema gains domains: each domain's name, its base as a type expression, and whether it forbids NULL. The field is additive; plugins that do not read it are unaffected. The core path fills it from its catalog, which already records every domain and SQL Server alias type with its base, so SQL Server's CREATE TYPE ... FROM, and PostgreSQL's CREATE DOMAIN under the core analyzer, reach plugins. A domain outside the default schema is named qualified, as columns of it are. Refs sqlc-dev#4483 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The catalog PostgreSQL is analyzed with by default ignored CREATE DOMAIN, so a plugin generating for PostgreSQL was told nothing about a domain even with the protocol able to carry it. The catalog now records each domain with its base type and whether it is declared NOT NULL, in the schema it was created in, and DROP DOMAIN removes it as DROP TYPE does. Refs sqlc-dev#4483 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A column typed with a PostgreSQL domain or a SQL Server alias type was
generated as interface{} or any, since no mapper knew the domain's name.
The Go generator now looks the domain up in the plugin catalog and maps
the column as the domain's base, wherever the domain appears in the type,
so an array of a domain is a slice of its base. A db_type override that
names the domain still applies first, so one override covers every
column of it, as sqlc-dev#434 describes.
Refs sqlc-dev#3324
Refs sqlc-dev#434
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A column typed with a domain declared NOT NULL was still nullable, so its Go field was a nullable wrapper for a value that can never be NULL. A column of such a domain is now NOT NULL, as PostgreSQL enforces it; an array of one may still be NULL, and the optional side of an outer join is still nullable. Fixes sqlc-dev#3265 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A type outside the default namespaces is reported qualified, so a bare name falling back to any schema made billing.text stand in for every ordinary text column, and recursed forever when its base was text. A domain whose base reports its own bare name stops there too. Addresses review comment r4556992324 on #2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The PostgreSQL mappers read the flat type, so naming it after the resolved expression made an array of a domain the type array, and generated []any. Describe the expression the way coreResultCatalog does: the innermost element's name and one dimension per array. Addresses review comment r4556992392 on #2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The flat type kept only the base's name, so a domain over text[] lost its element and dimensions and generated any. Add the base's dimensions to the column's own, and let the domain's base decide how many slices the Go type has, since the column alone does not say. Addresses review comment r4556992433 on #2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A column took its domain's NOT NULL as its own, so changing its type kept it, and dropping the column's NOT NULL dropped the domain's too. Remember which one the column has, and work it out again when the column's type or constraint changes. Addresses review comment r4556992493 on #2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The catalog ignored ALTER DOMAIN, so a domain kept the NOT NULL it was created with, and so did its columns. Apply the change to the domain and work out each column's again, leaving a column's own NOT NULL be. Addresses review comment r4556992586 on #2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A domain over a NOT NULL domain forbids NULL too, but only the domain's own constraint made its columns NOT NULL. Follow the domain's base while it is a domain, stopping at an array, whose elements' constraint does not apply to the array itself. Addresses review comment r4556992619 on #2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The base was read the way the analysis core reads a type, lowercased and without pg_catalog, so a domain over a quoted enum named no enum and one over numeric missed a pg_catalog.numeric override. Keep the parser's name, as a column of the base type has it. Addresses review comment r4556992547 on #2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ain's A child that redeclared an inherited domain column NOT NULL kept the mark that the NOT NULL came from the domain alone, so ALTER DOMAIN ... DROP NOT NULL cleared the child's own constraint. The child also shared the parent's column, so merging a NOT NULL into it changed the parent. Copy inherited columns and drop the domain mark when any merged declaration is NOT NULL by its own constraint. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
An override on a domain's base type supplied the column's Go type, but its go_struct_tag was matched only against the domain's own name and so was dropped. Walk the domain to its base for tags the way goInnerType does for the type, stopping where an override names the type, and apply the domain's and column's own tags over the base's. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
COMMENT ON DOMAIN was skipped, so a plugin saw an empty comment on a domain the schema commented. Translate it as COMMENT ON TYPE, which already finds the domain by its type name. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
resolveDomains replaced a whole chain of domains with the last base, so goInnerType never checked an override on a domain in the middle of the chain: with validated_id AS id AS text, a db_type override on id generated string. Replace one domain per step, as the legacy path does, and let goInnerType check overrides between steps. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This was referenced Nov 13, 2026
Author
|
I have been using sqlc with mssql as a trial and ran in to feature gaps so I figured I would spend the time and tokens to suggest some changes. Adds the type alias support. Structs no longer resolve to any, instead resolve based on the underlying type of the alias. This is the PR I am most unsure about since it isn't a huge gap in my opinion, but is a nice to have. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Expose domain and alias-type definitions to code-generation plugins, and use that metadata to generate Go fields as their base types instead of
any.A column still reports its domain's own type name. The plugin catalog gains an additive
Schema.domainsfield describing each domain's name, base type expression, nullability constraint, and comment. This preserves the analysis core's distinction between a domain and its base while giving generators enough information to choose a representation.Related requests and design context: #4483, #434, #3324, #3265, #4618, and #4621.
Compatibility and generated changes
The protocol change is additive. Existing plugins that do not read
domainsretain their current behavior; external generators need regenerated protocol bindings to use the new metadata. Column type names are not replaced with base names in the plugin request. The protobuf bindings and catalog query output are included.Existing JSON request goldens gain
domains; SQL Server alias columns previously represented asanybecome their base representations. The new PostgreSQL request fixture is large because it records the complete catalog, following the existing request-dump tests.This branch targets
maindirectly and is independent of the SQL Server query and expression-typing proposals.Related independent drafts: #4687 (core query support) and #4689 (expression typing). Adjacent compiler edits may need conflict resolution when these are integrated; none requires another to land first.
Tests and validation
New CLI golden cases cover PostgreSQL and SQL Server plugin requests, Go domain representations, nullability changes, inherited constraints, arrays, override precedence, intermediate domains, and domain comments. Override documentation is updated.
The complete
TestReplay/base/corpus passed during preparation on this branch's unchanged code tree. Existing golden differences are limited to the intended metadata, alias-type representations, and corrected inherited-column nullability.This draft submission did not rerun the full live-database/examples suite. Upstream CI has not yet been evaluated.
Known limitations
Fork review and detailed history: EliSauder#2.
AI assistance
Prepared with GitHub Copilot assistance. Opened as a draft for author and maintainer review.