Skip to content

Commit 4026435

Browse files
committed
feat(lib/tables): support setting primary keys
1 parent 38c8a86 commit 4026435

File tree

2 files changed

+187
-2
lines changed

2 files changed

+187
-2
lines changed

src/lib/PostgresMetaTables.ts

+33-2
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export default class PostgresMetaTables {
118118
rls_forced,
119119
replica_identity,
120120
replica_identity_index,
121+
primary_keys,
121122
comment,
122123
}: {
123124
name?: string
@@ -126,6 +127,7 @@ export default class PostgresMetaTables {
126127
rls_forced?: boolean
127128
replica_identity?: 'DEFAULT' | 'INDEX' | 'FULL' | 'NOTHING'
128129
replica_identity_index?: string
130+
primary_keys?: { name: string }[]
129131
comment?: string
130132
}
131133
): Promise<PostgresMetaResult<PostgresTable>> {
@@ -153,14 +155,42 @@ export default class PostgresMetaTables {
153155
const disable = `${alter} NO FORCE ROW LEVEL SECURITY;`
154156
forceRls = rls_forced ? enable : disable
155157
}
156-
let replicaSql: string
158+
let replicaSql = ''
157159
if (replica_identity === undefined) {
158-
replicaSql = ''
160+
// skip
159161
} else if (replica_identity === 'INDEX') {
160162
replicaSql = `${alter} REPLICA IDENTITY USING INDEX ${replica_identity_index};`
161163
} else {
162164
replicaSql = `${alter} REPLICA IDENTITY ${replica_identity};`
163165
}
166+
let primaryKeysSql = ''
167+
if (primary_keys === undefined) {
168+
// skip
169+
} else {
170+
if (old!.primary_keys.length !== 0) {
171+
primaryKeysSql += `
172+
DO $$
173+
DECLARE
174+
r record;
175+
BEGIN
176+
SELECT conname
177+
INTO r
178+
FROM pg_constraint
179+
WHERE contype = 'p' AND conrelid = ${literal(id)};
180+
EXECUTE ${literal(`${alter} DROP CONSTRAINT `)} || quote_ident(r.conname);
181+
END
182+
$$;
183+
`
184+
}
185+
186+
if (primary_keys.length === 0) {
187+
// skip
188+
} else {
189+
primaryKeysSql += `${alter} ADD PRIMARY KEY (${primary_keys
190+
.map((x) => ident(x.name))
191+
.join(',')});`
192+
}
193+
}
164194
const commentSql =
165195
comment === undefined
166196
? ''
@@ -171,6 +201,7 @@ BEGIN;
171201
${enableRls}
172202
${forceRls}
173203
${replicaSql}
204+
${primaryKeysSql}
174205
${commentSql}
175206
${schemaSql}
176207
${nameSql}

test/lib/tables.ts

+154
Original file line numberDiff line numberDiff line change
@@ -771,3 +771,157 @@ test("allow ' in comments", async () => {
771771
)
772772
await pgMeta.tables.remove(res.data!.id)
773773
})
774+
775+
test('primary keys', async () => {
776+
let res = await pgMeta.tables.create({ name: 't' })
777+
await pgMeta.columns.create({ table_id: res.data!.id, name: 'c', type: 'int8' })
778+
await pgMeta.columns.create({ table_id: res.data!.id, name: 'cc', type: 'text' })
779+
res = await pgMeta.tables.update(res.data!.id, {
780+
primary_keys: [{ name: 'c' }, { name: 'cc' }],
781+
})
782+
expect(cleanNondet(res)).toMatchInlineSnapshot(
783+
{
784+
data: {
785+
bytes: expect.any(Number),
786+
dead_rows_estimate: expect.any(Number),
787+
id: expect.any(Number),
788+
live_rows_estimate: expect.any(Number),
789+
size: expect.any(String),
790+
},
791+
},
792+
`
793+
Object {
794+
"data": Object {
795+
"bytes": Any<Number>,
796+
"columns": Array [
797+
Object {
798+
"comment": null,
799+
"data_type": "bigint",
800+
"default_value": null,
801+
"enums": Array [],
802+
"format": "int8",
803+
"identity_generation": null,
804+
"is_generated": false,
805+
"is_identity": false,
806+
"is_nullable": false,
807+
"is_unique": false,
808+
"is_updatable": true,
809+
"name": "c",
810+
"ordinal_position": 1,
811+
"schema": "public",
812+
"table": "t",
813+
},
814+
Object {
815+
"comment": null,
816+
"data_type": "text",
817+
"default_value": null,
818+
"enums": Array [],
819+
"format": "text",
820+
"identity_generation": null,
821+
"is_generated": false,
822+
"is_identity": false,
823+
"is_nullable": false,
824+
"is_unique": false,
825+
"is_updatable": true,
826+
"name": "cc",
827+
"ordinal_position": 2,
828+
"schema": "public",
829+
"table": "t",
830+
},
831+
],
832+
"comment": null,
833+
"dead_rows_estimate": Any<Number>,
834+
"grants": Array [
835+
Object {
836+
"grantee": "postgres",
837+
"grantor": "postgres",
838+
"is_grantable": true,
839+
"privilege_type": "INSERT",
840+
"schema": "public",
841+
"table_name": "t",
842+
"with_hierarchy": false,
843+
},
844+
Object {
845+
"grantee": "postgres",
846+
"grantor": "postgres",
847+
"is_grantable": true,
848+
"privilege_type": "SELECT",
849+
"schema": "public",
850+
"table_name": "t",
851+
"with_hierarchy": true,
852+
},
853+
Object {
854+
"grantee": "postgres",
855+
"grantor": "postgres",
856+
"is_grantable": true,
857+
"privilege_type": "UPDATE",
858+
"schema": "public",
859+
"table_name": "t",
860+
"with_hierarchy": false,
861+
},
862+
Object {
863+
"grantee": "postgres",
864+
"grantor": "postgres",
865+
"is_grantable": true,
866+
"privilege_type": "DELETE",
867+
"schema": "public",
868+
"table_name": "t",
869+
"with_hierarchy": false,
870+
},
871+
Object {
872+
"grantee": "postgres",
873+
"grantor": "postgres",
874+
"is_grantable": true,
875+
"privilege_type": "TRUNCATE",
876+
"schema": "public",
877+
"table_name": "t",
878+
"with_hierarchy": false,
879+
},
880+
Object {
881+
"grantee": "postgres",
882+
"grantor": "postgres",
883+
"is_grantable": true,
884+
"privilege_type": "REFERENCES",
885+
"schema": "public",
886+
"table_name": "t",
887+
"with_hierarchy": false,
888+
},
889+
Object {
890+
"grantee": "postgres",
891+
"grantor": "postgres",
892+
"is_grantable": true,
893+
"privilege_type": "TRIGGER",
894+
"schema": "public",
895+
"table_name": "t",
896+
"with_hierarchy": false,
897+
},
898+
],
899+
"id": Any<Number>,
900+
"live_rows_estimate": Any<Number>,
901+
"name": "t",
902+
"policies": Array [],
903+
"primary_keys": Array [
904+
Object {
905+
"name": "c",
906+
"schema": "public",
907+
"table_name": "t",
908+
},
909+
Object {
910+
"name": "cc",
911+
"schema": "public",
912+
"table_name": "t",
913+
},
914+
],
915+
"relationships": Array [],
916+
"replica_identity": "DEFAULT",
917+
"rls_enabled": false,
918+
"rls_forced": false,
919+
"schema": "public",
920+
"size": Any<String>,
921+
},
922+
"error": null,
923+
}
924+
`
925+
)
926+
await pgMeta.tables.remove(res.data!.id)
927+
})

0 commit comments

Comments
 (0)