Repository navigation
Conversation
Preload took the number in the alias of a joined table from the process-wide bob.NextUniqueInt(), so the same query had different SQL every time it was built. Drivers that cache prepared statements by their SQL, such as pgx, could never reuse the statement of a query that preloads, and on PostgreSQL 18 every execution added an entry to pg_stat_statements. The aliases also got longer the longer the process ran, until the "alias.column" name of a preloaded column passed PostgreSQL's limit of 63 bytes and the query failed. The number now comes from the query, through the new (*bob.Load).NextUniqueInt. Since the alias depends on the query, a preloader is only built when its mod is applied to the query. Fixes stephenafamo#741 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Generated joins through another table, such as SelectJoins.Videos.InnerJoin.Tags, took the number in the alias of the table in between from the process-wide bob.NextUniqueInt(), so the same query had different SQL every time it was built, the same problem as Preload had. They now take it from the query, like Preload. The join types now require the query to have NextUniqueInt(). They are internal to the generated package, and every query type they are used with has it through bob.Load. Refs stephenafamo#741 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
|
@stephenafamo sorry for bothering you again - but I would appreciate your review one more time |
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.
Description
Preloadand the generated joins through another table (such asSelectJoins.Videos.InnerJoin.Tags) took the number in their table aliases from the process-widebob.NextUniqueInt(). The same query was... AS "users_10001"on one build and"users_10002"on the next, so drivers that cache prepared statements by their SQL, such as pgx, could never reuse the statement (#741).The number now comes from the query, through a new
(*bob.Load).NextUniqueInt(). Every query starts at 10001, so the aliases look exactly as they do today in a freshly started process, and the same query always gives the same SQL.No breaking change. The
Preloadertype keeps its signature: a preloader works out its aliases when its mod is applied to the query, which is when the query's counter is available. Hand-written preloaders and code generated by the current version keep compiling. The only behaviour change is for code that calls aPreloaderfunction directly and uses the returned mapper mod before applying the returned mod; nothing in bob does that.For the generated joins, the join types now require the query to have
NextUniqueInt(). Those types are internal to the generated package, and every query type they are used with already has it.Measured with pgx v5.7.5
Same Preload query, 5000 executions on one connection, median of 3 runs:
database/sql+pgx/stdlib, PostgreSQL 16, µs/querypg_stat_statementsentries on PostgreSQL 18 (1000 runs)It also fixes a failure that showed up while measuring: because the global counter only grows, a long-running process eventually gives aliases with 6+ digits, and with long table and column names the
"alias.column"name of a preloaded column passes PostgreSQL's 63-byte limit. The query then fails withno destination for column ...although the same query worked when the process started.Relation to #783
#783 fixes the same issue by passing an alias allocator through a new variadic parameter on
Preloader, which is a breaking change. This PR gets the same result without it. I ran the #741-related scenarios from #783's tests, both itsormtests and its generated join tests, against this branch (adapted to the alias format): all pass. This PR is +178 / −16.#783 also fixes two unrelated
Preloadbugs, both present onmain:PreloadAson a relationship through another table gives every side the same alias, andto_wherecolumns are qualified with the parent table instead of the joined one. They are left out here to keep this PR to one problem; they would fit well in their own PR.Related issue
Fixes #741
Checklist
go test -race ./...including the generated-code suites against PostgreSQL, MySQL and SQLite. The new tests fail without the change.CHANGELOG.mdis updated.Prepared with Claude Code; the measurements above were run locally.