import { ident , literal } from 'pg-format' ; import { triggersSql } from './sql' ; import { PostgresMetaResult , PostgresTrigger } from './types' ; export default class PostgresMetaTriggers { query : ( sql : string ) => Promise < PostgresMetaResult < any > > ; constructor ( query ) { this . query = query ; } async list ( { limit , offset , } = { } ) { let sql = enrichedTriggersSql ; if ( limit ) { sql = `${ sql } LIMIT ${ limit }` ; } if ( offset ) { sql = `${ sql } OFFSET ${ offset }` ; } return await this . query ( sql ) ; } async retrieve ( { id } ) ; async retrieve ( { name , table , schema , } ) ; async retrieve ( { id , name , schema = 'public' , table , } ) { if ( id ) { const sql = `${ enrichedTriggersSql } WHERE id = ${ literal ( id ) };` ; const { data , error } = await this . query ( sql ) ; if ( error ) { return { data : null , error } ; } const triggerRecord = data && data [ 0 ] ; if ( triggerRecord ) { return { data : triggerRecord , error : null } ; } return { data : null , error : { message : `Cannot find a trigger with ID ${ id }` } } ; } if ( name && schema && table ) { const sql = `${ enrichedTriggersSql } WHERE name = ${ literal ( name ) } AND schema = ${ literal ( schema ) } AND triggers.table = ${ literal ( table ) };` ; const { data , error } = await this . query ( sql ) ; if ( error ) { return { data : null , error } ; } const triggerRecord = data && data [ 0 ] ; if ( triggerRecord ) { return { data : triggerRecord , error : null } ; } return { data : null , error : { message : `Cannot find a trigger with name ${ name } on table "${ schema }"."${ table }"` , } , } ; } return { data : null , error : { message : 'Invalid parameters on trigger retrieve' } } ; } param obj param { string } obj . name param { string } obj . schema param { string } obj . table param { string } obj . function_schema param { string } obj . function_name param { ( 'BEFORE' | 'AFTER' | 'INSTEAD OF' ) } obj . activation param { Array < string > } obj . events param { ( 'ROW' | 'STATEMENT' ) } obj . orientation param { string } obj . condition param { Array < string > } obj . function_args async create ( { name , schema = 'public' , table , function_schema = 'public' , function_name , function_args , activation , events , orientation , condition , } ) { const qualifiedTableName = `${ ident ( schema ) }.${ ident ( table ) }` ; const qualifiedFunctionName = `${ ident ( function_schema ) }.${ ident ( function_name ) }` ; const triggerEvents = events . join ( ' OR ' ) ; const triggerOrientation = orientation ? `FOR EACH ${ orientation }` : '' ; const triggerCondition = condition ? `WHEN (${ condition })` : '' ; const functionArgs = `${ function_args ?. map ( literal ) . join ( ',' ) ?? '' }` ; const sql = `CREATE TRIGGER ${ ident ( name ) } ${ activation } ${ triggerEvents } ON ${ qualifiedTableName } ${ triggerOrientation } ${ triggerCondition } EXECUTE FUNCTION ${ qualifiedFunctionName }(${ functionArgs });` ; const { error } = await this . query ( sql ) ; if ( error ) { return { data : null , error } ; } return await this . retrieve ( { name , table , schema , } ) ; } async update ( id , { name , enabled_mode , } ) { const { data : old , error } = await this . retrieve ( { id } ) ; if ( error ) { return { data : null , error } ; } let enabledModeSql = '' ; switch ( enabled_mode ) { case 'ORIGIN' : enabledModeSql = `ALTER TABLE ${ ident ( old ! . schema ) }.${ ident ( old ! . table ) } ENABLE TRIGGER ${ ident ( old ! . name ) };` ; break ; case 'DISABLED' : enabledModeSql = `ALTER TABLE ${ ident ( old ! . schema ) }.${ ident ( old ! . table ) } DISABLE TRIGGER ${ ident ( old ! . name ) };` ; break ; case 'REPLICA' : case 'ALWAYS' : enabledModeSql = `ALTER TABLE ${ ident ( old ! . schema ) }.${ ident ( old ! . table ) } ENABLE ${ enabled_mode } TRIGGER ${ ident ( old ! . name ) };` ; break ; default : break ; } const nameSql = name && name !== old ! . name ? `ALTER TRIGGER ${ ident ( old ! . name ) } ON ${ ident ( old ! . schema ) }.${ ident ( old ! . table ) } RENAME TO ${ ident ( name ) };` : '' ; const sql = `BEGIN; ${ enabledModeSql }; ${ nameSql }; COMMIT;` ; { const { error } = await this . query ( sql ) ; if ( error ) { return { data : null , error } ; } } return await this . retrieve ( { id } ) ; } async remove ( id , { cascade = false } = { } ) { const { data : triggerRecord , error } = await this . retrieve ( { id } ) ; if ( error ) { return { data : null , error } ; } const { name , schema , table } = triggerRecord ! ; const sql = `DROP TRIGGER ${ ident ( name ) } ON ${ ident ( schema ) }.${ ident ( table ) } ${ cascade ? 'CASCADE' : '' };` ; { const { error } = await this . query ( sql ) ; if ( error ) { return { data : null , error } ; } } return { data : triggerRecord ! , error : null } ; } } const enrichedTriggersSql = `
  WITH triggers AS (
    ${ triggersSql }
  )
  SELECT
    *
  FROM triggers
` ;