From 65fe6b3b7817972645a7468be8f3b4a93b18df2d Mon Sep 17 00:00:00 2001
From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com>
Date: Sun, 19 Jan 2025 04:51:04 +0000
Subject: [PATCH 1/4] feat(postgres): allow running multiple statements in no
 tx migrations

---
 sqlx-postgres/src/migrate.rs | 15 +++++++++++----
 tests/postgres/migrate.rs    | 20 ++++++++++++++++++++
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/sqlx-postgres/src/migrate.rs b/sqlx-postgres/src/migrate.rs
index c37e92f4d6..054bcb1815 100644
--- a/sqlx-postgres/src/migrate.rs
+++ b/sqlx-postgres/src/migrate.rs
@@ -276,10 +276,17 @@ async fn execute_migration(
     conn: &mut PgConnection,
     migration: &Migration,
 ) -> Result<(), MigrateError> {
-    let _ = conn
-        .execute(&*migration.sql)
-        .await
-        .map_err(|e| MigrateError::ExecuteMigration(e, migration.version))?;
+    let sql = migration.sql.trim();
+    let split_migrations = sql.split("/* sqlx: split */");
+    for part in split_migrations {
+        if part.trim().is_empty() {
+            continue;
+        }
+        let _ = conn
+            .execute(&*part.trim())
+            .await
+            .map_err(|e| MigrateError::ExecuteMigration(e, migration.version))?;
+    }
 
     // language=SQL
     let _ = query(
diff --git a/tests/postgres/migrate.rs b/tests/postgres/migrate.rs
index 636dffe860..3ca5f3fb06 100644
--- a/tests/postgres/migrate.rs
+++ b/tests/postgres/migrate.rs
@@ -85,6 +85,26 @@ async fn no_tx(mut conn: PoolConnection<Postgres>) -> anyhow::Result<()> {
     Ok(())
 }
 
+
+#[sqlx::test(migrations = false)]
+async fn split(mut conn: PoolConnection<Postgres>) -> anyhow::Result<()> {
+    clean_up(&mut conn).await?;
+    let migrator = Migrator::new(Path::new("tests/postgres/migrations_split")).await?;
+
+    // run migration
+    migrator.run(&mut conn).await?;
+
+    // check outcome
+    let res: i32 = conn
+        .fetch_one("SELECT * FROM test_table")
+        .await?
+        .get(0);
+
+    assert_eq!(res, 1);
+
+    Ok(())
+}
+
 /// Ensure that we have a clean initial state.
 async fn clean_up(conn: &mut PgConnection) -> anyhow::Result<()> {
     conn.execute("DROP DATABASE IF EXISTS test_db").await.ok();

From f62651112c5c60a03b952ca35c99ad4f2c3362e8 Mon Sep 17 00:00:00 2001
From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com>
Date: Sun, 19 Jan 2025 04:51:40 +0000
Subject: [PATCH 2/4] feat(postgres): allow running multiple statements in no
 tx migrations

---
 tests/postgres/migrations_split/0_create_table.sql | 7 +++++++
 1 file changed, 7 insertions(+)
 create mode 100644 tests/postgres/migrations_split/0_create_table.sql

diff --git a/tests/postgres/migrations_split/0_create_table.sql b/tests/postgres/migrations_split/0_create_table.sql
new file mode 100644
index 0000000000..33ecbedcfd
--- /dev/null
+++ b/tests/postgres/migrations_split/0_create_table.sql
@@ -0,0 +1,7 @@
+-- no-transaction
+
+CREATE TABLE test_table (x int);
+/* sqlx: split */
+CREATE INDEX CONCURRENTLY test_table_x_idx ON test_table (x);
+/* sqlx: split */
+INSERT INTO test_table (x) VALUES (1);

From 42c6e7ce6cf8e001adf550f9c8498e22ea8208fe Mon Sep 17 00:00:00 2001
From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com>
Date: Mon, 20 Jan 2025 13:48:02 +0000
Subject: [PATCH 3/4] rename and match full line only

---
 sqlx-postgres/src/migrate.rs                       | 4 +++-
 tests/postgres/migrations_split/0_create_table.sql | 7 -------
 2 files changed, 3 insertions(+), 8 deletions(-)
 delete mode 100644 tests/postgres/migrations_split/0_create_table.sql

diff --git a/sqlx-postgres/src/migrate.rs b/sqlx-postgres/src/migrate.rs
index 054bcb1815..01f7ee7952 100644
--- a/sqlx-postgres/src/migrate.rs
+++ b/sqlx-postgres/src/migrate.rs
@@ -277,7 +277,9 @@ async fn execute_migration(
     migration: &Migration,
 ) -> Result<(), MigrateError> {
     let sql = migration.sql.trim();
-    let split_migrations = sql.split("/* sqlx: split */");
+    // note: this would _not_ match the split if the file starts with `-- split-migration`
+    // because it requires a new line prefix, but that doesn't really make sense anyway so it's fine
+    let split_migrations = sql.split("\n-- split-migration\n");
     for part in split_migrations {
         if part.trim().is_empty() {
             continue;
diff --git a/tests/postgres/migrations_split/0_create_table.sql b/tests/postgres/migrations_split/0_create_table.sql
deleted file mode 100644
index 33ecbedcfd..0000000000
--- a/tests/postgres/migrations_split/0_create_table.sql
+++ /dev/null
@@ -1,7 +0,0 @@
--- no-transaction
-
-CREATE TABLE test_table (x int);
-/* sqlx: split */
-CREATE INDEX CONCURRENTLY test_table_x_idx ON test_table (x);
-/* sqlx: split */
-INSERT INTO test_table (x) VALUES (1);

From f4cafdcbe48dc784172b4f23c85cfe4bf0402dbf Mon Sep 17 00:00:00 2001
From: Adrian Garcia Badaracco <1755071+adriangb@users.noreply.github.com>
Date: Mon, 20 Jan 2025 13:49:00 +0000
Subject: [PATCH 4/4] add file

---
 tests/postgres/migrations_split/0_create_index.sql | 8 ++++++++
 1 file changed, 8 insertions(+)
 create mode 100644 tests/postgres/migrations_split/0_create_index.sql

diff --git a/tests/postgres/migrations_split/0_create_index.sql b/tests/postgres/migrations_split/0_create_index.sql
new file mode 100644
index 0000000000..f8bc50ecdc
--- /dev/null
+++ b/tests/postgres/migrations_split/0_create_index.sql
@@ -0,0 +1,8 @@
+-- no-transaction
+
+CREATE TABLE test_table (x int);
+-- split-migration
+CREATE INDEX CONCURRENTLY test_table_x_idx ON test_table (x);
+-- split-migration
+INSERT INTO test_table (x) VALUES (1);
+-- prove that you can have a comment that won't split -- split-migration DROP TABLE does_not_exist;