Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions packages/migra/test/column-order.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import {createPool, sql} from '@pgkit/client'
import {beforeAll, afterAll, beforeEach, describe, expect, test} from 'vitest'
import {run as runMigra} from '../src/command'

const connectionString = process.env.MIGRA_TEST_URL ?? 'postgresql://postgres:postgres@localhost:5432/postgres'

let admin: Awaited<ReturnType<typeof createPool>>

beforeAll(async () => {
admin = createPool(connectionString)
})

afterAll(async () => {
await admin.pgp.$pool.end()
})

async function setupDb(name: string, setupSql: string) {
await admin.query(sql`drop database if exists ${sql.identifier([name])}`)
await admin.query(sql`create database ${sql.identifier([name])}`)
const url = connectionString.replace(/\/[^/]+$/, `/${name}`)
const pool = createPool(url)
await pool.query(sql.raw(setupSql))
await pool.pgp.$pool.end()
return url
}

async function cleanupDb(name: string) {
await admin.query(sql`
select pg_terminate_backend(pid)
from pg_stat_activity
where datname = ${name} and pid <> pg_backend_pid()
`)
await admin.query(sql`drop database if exists ${sql.identifier([name])}`)
}

describe('column order should not cause spurious view diffs', () => {
const dbA = 'migra_colorder_test_a'
const dbB = 'migra_colorder_test_b'

beforeEach(async () => {
await cleanupDb(dbA)
await cleanupDb(dbB)
})

test('view with explicit columns is not recreated when table column order differs', async () => {
const a = await setupDb(
dbA,
`
create table users (
id serial primary key,
name text not null,
email text not null
);
create view user_emails as select id, email from users;
`,
)
const b = await setupDb(
dbB,
`
create table users (
id serial primary key,
email text not null,
name text not null
);
create view user_emails as select id, email from users;
`,
)

const result = await runMigra(a, b, {unsafe: true})
expect(result.sql.trim()).toBe('')
})

test('view with SELECT * is recreated when table column order differs', async () => {
const a = await setupDb(
dbA,
`
create table users (
id serial primary key,
name text not null,
email text not null
);
create view all_users as select * from users;
`,
)
const b = await setupDb(
dbB,
`
create table users (
id serial primary key,
email text not null,
name text not null
);
create view all_users as select * from users;
`,
)

const result = await runMigra(a, b, {unsafe: true})
expect(result.sql).toContain('drop view')
expect(result.sql).toContain('create or replace view')
})

test('view with explicit columns is not recreated even with many reordered columns', async () => {
const a = await setupDb(
dbA,
`
create table items (
id serial primary key,
alpha text,
beta text,
gamma text,
delta text
);
create view item_summary as select id, delta, alpha from items;
`,
)
const b = await setupDb(
dbB,
`
create table items (
id serial primary key,
delta text,
gamma text,
beta text,
alpha text
);
create view item_summary as select id, delta, alpha from items;
`,
)

const result = await runMigra(a, b, {unsafe: true})
expect(result.sql.trim()).toBe('')
})
})
5 changes: 3 additions & 2 deletions packages/schemainspect/src/inspected.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {AutoThisAssigner, SomeOptional, SomeRequired} from './auto-this'
import {AutoRepr, quoted_identifier, quotify, unquoted_identifier} from './misc'
import {InspectedConstraint, InspectedEnum, InspectedIndex} from './pg'
import {Relationtype} from './types'
import {isEqual} from './util'

export const pick = <T extends {}, K extends keyof T>(obj: T, keys: readonly K[]): Pick<T, K> => {
return Object.fromEntries(keys.map(k => [k, obj[k]])) as Pick<T, K>
Expand All @@ -19,7 +20,7 @@ export abstract class Inspected extends AutoRepr {
abstract get create_statement(): string

equals(other: Inspected): boolean {
return JSON.stringify(this) === JSON.stringify(other)
return isEqual(this.toJSON(), other.toJSON())
}

get quoted_full_name() {
Expand Down Expand Up @@ -87,7 +88,7 @@ export class ColumnInfo extends AutoThisAssigner<ColumnInfoOptions, typeof AutoR
}

equals(other: ColumnInfo): boolean {
return JSON.stringify(this) === JSON.stringify(other)
return isEqual(this, other)
}

alter_clauses(other: ColumnInfo) {
Expand Down
2 changes: 1 addition & 1 deletion packages/schemainspect/src/pg/obj.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2040,6 +2040,6 @@ export class PostgreSQL extends DBInspector {
}

equals(other: PostgreSQL): boolean {
return JSON.stringify(this) === JSON.stringify(other)
return isEqual(this, other)
}
}
Loading