| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365 |
- import { afterAll, beforeAll, expect, test } from 'vitest'
- import pgMeta, { safeSql } from '../src/index'
- import { cleanupRoot, createTestDatabase } from './db/utils'
- beforeAll(async () => {
- // Any global setup if needed
- })
- afterAll(async () => {
- await cleanupRoot()
- })
- const withTestDatabase = (
- name: string,
- fn: (db: Awaited<ReturnType<typeof createTestDatabase>>) => Promise<void>
- ) => {
- test(name, async () => {
- const db = await createTestDatabase()
- try {
- await fn(db)
- } finally {
- await db.cleanup()
- }
- })
- }
- withTestDatabase('retrieve, create, update, delete', async ({ executeQuery }) => {
- // Create trigger
- const { sql: createSql } = pgMeta.triggers.create({
- name: 'test_trigger',
- schema: 'public',
- table: 'users_audit',
- function_schema: 'public',
- function_name: 'audit_action',
- function_args: ['test1', 'test2'],
- activation: 'AFTER',
- events: ['UPDATE'],
- orientation: 'ROW',
- condition: safeSql`(old.* IS DISTINCT FROM new.*)`,
- })
- await executeQuery(createSql)
- const { sql: listTriggers, zod: listZod } = pgMeta.triggers.list()
- const listedTriggers = await listZod.parse(await executeQuery(listTriggers))
- const createdTriggers = listedTriggers.find(
- (t) => t.name === 'test_trigger' && t.table === 'users_audit' && t.schema === 'public'
- )
- expect(createdTriggers!).toMatchInlineSnapshot(
- { id: expect.any(Number), table_id: expect.any(Number) },
- `
- {
- "activation": "AFTER",
- "condition": "(old.* IS DISTINCT FROM new.*)",
- "enabled_mode": "ORIGIN",
- "events": [
- "UPDATE",
- ],
- "function_args": [
- "test1",
- "test2",
- ],
- "function_name": "audit_action",
- "function_schema": "public",
- "id": Any<Number>,
- "name": "test_trigger",
- "orientation": "ROW",
- "schema": "public",
- "table": "users_audit",
- "table_id": Any<Number>,
- }
- `
- )
- // Retrieve created trigger by name
- const { sql: retrieveSqlByName, zod: retrieveZod } = pgMeta.triggers.retrieve({
- name: 'test_trigger',
- table: 'users_audit',
- schema: 'public',
- })
- const trigger = retrieveZod.parse((await executeQuery(retrieveSqlByName))[0])
- expect(trigger!).toMatchInlineSnapshot(
- { id: expect.any(Number), table_id: expect.any(Number) },
- `
- {
- "activation": "AFTER",
- "condition": "(old.* IS DISTINCT FROM new.*)",
- "enabled_mode": "ORIGIN",
- "events": [
- "UPDATE",
- ],
- "function_args": [
- "test1",
- "test2",
- ],
- "function_name": "audit_action",
- "function_schema": "public",
- "id": Any<Number>,
- "name": "test_trigger",
- "orientation": "ROW",
- "schema": "public",
- "table": "users_audit",
- "table_id": Any<Number>,
- }
- `
- )
- // Retrieve created trigger by id
- const { sql: retrieveSqlById } = pgMeta.triggers.retrieve({
- id: trigger!.id,
- })
- const triggerById = retrieveZod.parse((await executeQuery(retrieveSqlById))[0])
- expect(triggerById!).toMatchInlineSnapshot(
- { id: expect.any(Number), table_id: expect.any(Number) },
- `
- {
- "activation": "AFTER",
- "condition": "(old.* IS DISTINCT FROM new.*)",
- "enabled_mode": "ORIGIN",
- "events": [
- "UPDATE",
- ],
- "function_args": [
- "test1",
- "test2",
- ],
- "function_name": "audit_action",
- "function_schema": "public",
- "id": Any<Number>,
- "name": "test_trigger",
- "orientation": "ROW",
- "schema": "public",
- "table": "users_audit",
- "table_id": Any<Number>,
- }
- `
- )
- // Update trigger
- const { sql: updateSql } = pgMeta.triggers.update(trigger!, {
- name: 'test_trigger_renamed',
- enabled_mode: 'DISABLED',
- })
- await executeQuery(updateSql)
- // Verify update
- const { sql: retrieveUpdatedSql } = pgMeta.triggers.retrieve({
- id: trigger!.id,
- })
- const updatedTrigger = retrieveZod.parse((await executeQuery(retrieveUpdatedSql))[0])
- expect(updatedTrigger).toMatchInlineSnapshot(
- { id: expect.any(Number), table_id: expect.any(Number) },
- `
- {
- "activation": "AFTER",
- "condition": "(old.* IS DISTINCT FROM new.*)",
- "enabled_mode": "DISABLED",
- "events": [
- "UPDATE",
- ],
- "function_args": [
- "test1",
- "test2",
- ],
- "function_name": "audit_action",
- "function_schema": "public",
- "id": Any<Number>,
- "name": "test_trigger_renamed",
- "orientation": "ROW",
- "schema": "public",
- "table": "users_audit",
- "table_id": Any<Number>,
- }
- `
- )
- // Update trigger again
- const { sql: updateSql2 } = pgMeta.triggers.update(updatedTrigger!, {
- enabled_mode: 'REPLICA',
- })
- await executeQuery(updateSql2)
- // Verify second update
- const { sql: retrieveUpdated2Sql } = pgMeta.triggers.retrieve({
- name: 'test_trigger_renamed',
- table: 'users_audit',
- schema: 'public',
- })
- const updatedTrigger2 = retrieveZod.parse((await executeQuery(retrieveUpdated2Sql))[0])
- expect(updatedTrigger2).toMatchObject({
- enabled_mode: 'REPLICA',
- })
- // Remove trigger
- const { sql: removeSql } = pgMeta.triggers.remove(updatedTrigger2!)
- await executeQuery(removeSql)
- // Verify removal
- const { sql: verifyRemoveSql } = pgMeta.triggers.retrieve({
- name: 'test_trigger_renamed',
- table: 'users_audit',
- schema: 'public',
- })
- const result = retrieveZod.parse((await executeQuery(verifyRemoveSql))[0])
- expect(result).toBeUndefined()
- })
- withTestDatabase('multi event', async ({ executeQuery }) => {
- // Create trigger
- const { sql: createSql } = pgMeta.triggers.create({
- name: 'test_multi_event_trigger',
- schema: 'public',
- table: 'users_audit',
- function_schema: 'public',
- function_name: 'audit_action',
- function_args: ['test1', 'test2'],
- activation: 'AFTER',
- events: ['insert', 'update', 'delete'],
- orientation: 'ROW',
- })
- await executeQuery(createSql)
- // Verify created trigger
- const { sql: retrieveSql, zod: retrieveZod } = pgMeta.triggers.retrieve({
- name: 'test_multi_event_trigger',
- table: 'users_audit',
- schema: 'public',
- })
- const trigger = retrieveZod.parse((await executeQuery(retrieveSql))[0])
- expect(trigger).toMatchInlineSnapshot(
- { id: expect.any(Number), table_id: expect.any(Number) },
- `
- {
- "activation": "AFTER",
- "condition": null,
- "enabled_mode": "ORIGIN",
- "events": [
- "INSERT",
- "DELETE",
- "UPDATE",
- ],
- "function_args": [
- "test1",
- "test2",
- ],
- "function_name": "audit_action",
- "function_schema": "public",
- "id": Any<Number>,
- "name": "test_multi_event_trigger",
- "orientation": "ROW",
- "schema": "public",
- "table": "users_audit",
- "table_id": Any<Number>,
- }
- `
- )
- // Remove trigger
- const { sql: removeSql } = pgMeta.triggers.remove(trigger!)
- await executeQuery(removeSql)
- // Verify removal
- const { sql: verifyRemoveSql } = pgMeta.triggers.retrieve({
- name: 'test_multi_event_trigger',
- table: 'users_audit',
- schema: 'public',
- })
- const result = retrieveZod.parse((await executeQuery(verifyRemoveSql))[0])
- expect(result).toBeUndefined()
- })
- withTestDatabase('triggers with the same name on different schemas', async ({ executeQuery }) => {
- // Create test schemas and triggers
- await executeQuery(`
- create function tr_f() returns trigger language plpgsql as 'begin end';
- create schema s1; create table s1.t(); create trigger tr before insert on s1.t execute function tr_f();
- create schema s2; create table s2.t(); create trigger tr before insert on s2.t execute function tr_f();
- `)
- // List and verify triggers
- const { sql: listSql, zod: listZod } = pgMeta.triggers.list()
- const triggers = listZod.parse(await executeQuery(listSql))
- expect(triggers.map(({ id, table_id, ...trigger }) => trigger)).toMatchInlineSnapshot(`
- [
- {
- "activation": "BEFORE",
- "condition": null,
- "enabled_mode": "ORIGIN",
- "events": [
- "INSERT",
- ],
- "function_args": [],
- "function_name": "tr_f",
- "function_schema": "public",
- "name": "tr",
- "orientation": "STATEMENT",
- "schema": "s1",
- "table": "t",
- },
- {
- "activation": "BEFORE",
- "condition": null,
- "enabled_mode": "ORIGIN",
- "events": [
- "INSERT",
- ],
- "function_args": [],
- "function_name": "tr_f",
- "function_schema": "public",
- "name": "tr",
- "orientation": "STATEMENT",
- "schema": "s2",
- "table": "t",
- },
- ]
- `)
- })
- withTestDatabase('triggers on capitalized schema and table names', async ({ executeQuery }) => {
- // Create test schema and trigger
- await executeQuery(`
- CREATE SCHEMA "MySchema";
- CREATE TABLE "MySchema"."MyTable" (
- id SERIAL PRIMARY KEY,
- name TEXT NOT NULL,
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- updated_at TIMESTAMP
- );
- CREATE OR REPLACE FUNCTION "MySchema"."my_trigger_function"()
- RETURNS TRIGGER AS $$
- BEGIN
- NEW.updated_at := CURRENT_TIMESTAMP;
- RETURN NEW;
- END;
- $$ LANGUAGE plpgsql;
- CREATE TRIGGER "my_trigger"
- BEFORE INSERT ON "MySchema"."MyTable"
- FOR EACH ROW
- EXECUTE FUNCTION "MySchema"."my_trigger_function"();
- `)
- // List and verify triggers
- const { sql: listSql, zod: listZod } = pgMeta.triggers.list()
- const triggers = listZod.parse(await executeQuery(listSql))
- expect(triggers.map(({ id, table_id, ...trigger }) => trigger)).toMatchInlineSnapshot(`
- [
- {
- "activation": "BEFORE",
- "condition": null,
- "enabled_mode": "ORIGIN",
- "events": [
- "INSERT",
- ],
- "function_args": [],
- "function_name": "my_trigger_function",
- "function_schema": "MySchema",
- "name": "my_trigger",
- "orientation": "ROW",
- "schema": "MySchema",
- "table": "MyTable",
- },
- ]
- `)
- })
|