Open
Description
I have found these related issues/pull requests
#3181 introduced a --no-transaction
directive specifically so that things like CREATE INDEX CONCURRENTLY
or CREATE DATABASE
could be run on Postgres.
Description
But if you include more than one statement in a query Postgres starts an implicit transaction, which means that you can only run a single statement per migration file. This quickly becomes frustrating.
Prefered solution
I propose the addition of a -- sqlx: split migration
directive that allows doing something like this:
-- no-transaction
CREATE INDEX CONCURRENTLY ...
-- sqlx: split migration
CREATE INDEX CONCURRENTLY ...
Then sqlx literally calls split()
on the migration string and runs multiple queries instead of a single one.
Is this a breaking change? Why or why not?
I don't think it has to be.
Activity
titaniumtraveler commentedon Jan 19, 2025
Here is a link to the docs this is talking about: https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-MULTI-STATEMENT
I have been reading up on the internals chapter of the manual lately and had been a bit confused, because I remembered a sentence that suggested differently (and I accidentally had skipped over the section just below that, that explains the thing with the transactions).
I would prefer using
sqlx:split-migration
instead to avoid whitespace, which might lead to more user errors and the migration not actually being split.(This is me speaking as someone who literally only contributed one patch to the project to add completions to
sqlx-cli
viaclap_complete
)On that topic, it might be a good idea to rename
no-transaction
tosqlx:no-transaction
?(And deprecate, but not remove the old one of cause)
If it is expected, or at least possible that more directives are added in the future it would be nice for them to have a consistent format and be clearly attributable to
sqlx
.Also it would make it easier to add snippets for them into code editors ...
adriangb commentedon Jan 19, 2025
I'm fine with any name 😄
adriangb commentedon Jan 19, 2025
Another question is: do we want to support
sqlx:no-transaction
for eachsqlx:split-migration
? Technically we could, but that would require more extensive refactors that might be breaking changes.titaniumtraveler commentedon Jan 19, 2025
I don't think it would be very hard. The way your PR works just isn't good for
that. As far as I could see, your PR currently processes at execution time,
which in my opinion is the wrong way to processes the migration.
Wouldn't it be better to split the migrations as they are read from the
filesystem? (That would also avoid some runtime work when people are executing
the migrator returned by
migrate!()
)Implementing it on the level of
resolve_blocking()
(where the migrations are read from the directory) would also have to advantage that all the directives that influence how a migration is executed are implemented in one place!sqlx/sqlx-core/src/migrate/source.rs
Lines 57 to 145 in f6d2fa3
adriangb commentedon Jan 19, 2025
I thought of that but we'd have to add a suffix to the version or something
titaniumtraveler commentedon Jan 19, 2025
Yeah you are right. And adding it would sadly break SemVer, because
Migration
is not marked as#[non_exhaustive]
.I guess in this case it might genuinely better to wait for
0.9.0
.As I understand it, there is a bunch of work happening in #3383 for that, which also refactors this section of the code anyway.