Skip to content

Commit ef1705b

Browse files
sliftyRemi Koenig
and
Remi Koenig
committed
Check table exists in current search path
* If a `migrations` table did exist in a schema outside of the search path, `doesTableExist` would return true but the migration would then fail with 'relation "migrations" does not exist' * See https://dba.stackexchange.com/a/86098 for the details on the query * This new query makes it possible to have one `migrations` table per schema Issue #92 Migrations can't be run on multiple schemas in the same database Co-authored-by: Remi Koenig <r.koenig@agricool.co>
1 parent dbfc5cc commit ef1705b

File tree

4 files changed

+50
-8
lines changed

4 files changed

+50
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CREATE TABLE another (
2+
id integer
3+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CREATE TABLE success (
2+
id integer
3+
);

src/__tests__/migrate.ts

+37
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,35 @@ test("concurrent migrations - index concurrently", async (t) => {
7575
t.truthy(exists)
7676
})
7777

78+
test("multiple schemas", async (t) => {
79+
const databaseName = "migration-test-multiple-schemas"
80+
const dbConfig = {
81+
database: databaseName,
82+
user: "postgres",
83+
password: PASSWORD,
84+
host: "localhost",
85+
port,
86+
}
87+
88+
await createDb(databaseName, dbConfig)
89+
const client = new pg.Client(dbConfig)
90+
await client.connect()
91+
92+
await createSchema(client, "schema_1")
93+
await useSchema(client, "schema_1")
94+
await migrate({ client }, "src/__tests__/fixtures/multiple-schemas")
95+
const firstMigrationSucceeded = await doesTableExist(dbConfig, "success")
96+
t.truthy(firstMigrationSucceeded)
97+
98+
await createSchema(client, "schema_2")
99+
await useSchema(client, "schema_2")
100+
await migrate({ client }, "src/__tests__/fixtures/multiple-schemas-2")
101+
const secondMigrationSucceeded = await doesTableExist(dbConfig, "another")
102+
t.truthy(secondMigrationSucceeded)
103+
104+
await client.end()
105+
})
106+
78107
// can't test with unconnected client because `pg` just hangs on the first query...
79108
test("with connected client", async (t) => {
80109
const databaseName = "migration-test-with-connected-client"
@@ -720,3 +749,11 @@ function doesTableExist(dbConfig: pg.ClientConfig, tableName: string) {
720749
}
721750
})
722751
}
752+
753+
async function createSchema(client: pg.Client, schemaName: string): Promise<void> {
754+
await client.query(`CREATE SCHEMA ${schemaName};`)
755+
}
756+
757+
async function useSchema(client: pg.Client, schemaName: string): Promise<void> {
758+
await client.query(`SET search_path TO ${schemaName};`)
759+
}

src/migrate.ts

+7-8
Original file line numberDiff line numberDiff line change
@@ -200,14 +200,13 @@ function logResult(completedMigrations: Array<Migration>, log: Logger) {
200200
}
201201
}
202202

203-
/** Check whether table exists in postgres - http://stackoverflow.com/a/24089729 */
203+
/** Check whether table exists in postgres in the current search path
204+
* http://stackoverflow.com/a/24089729
205+
* https://dba.stackexchange.com/a/86098
206+
*/
204207
async function doesTableExist(client: BasicPgClient, tableName: string) {
205-
const result = await client.query(SQL`SELECT EXISTS (
206-
SELECT 1
207-
FROM pg_catalog.pg_class c
208-
WHERE c.relname = ${tableName}
209-
AND c.relkind = 'r'
210-
);`)
211-
208+
const result = await client.query(
209+
SQL`SELECT to_regclass(${tableName}) is not NULL as exists;`,
210+
)
212211
return result.rows.length > 0 && result.rows[0].exists
213212
}

0 commit comments

Comments
 (0)