1- import { literal } from 'pg-format'
1+ import { ident , literal } from 'pg-format'
22import { DEFAULT_SYSTEM_SCHEMAS } from './constants'
33import { functionsSql } from './sql'
44import { PostgresMetaResult , PostgresFunction } from './types'
@@ -22,13 +22,21 @@ export default class PostgresMetaFunctions {
2222 }
2323
2424 async retrieve ( { id } : { id : number } ) : Promise < PostgresMetaResult < PostgresFunction > >
25- async retrieve ( { name } : { name : string } ) : Promise < PostgresMetaResult < PostgresFunction > >
25+ async retrieve ( {
26+ name,
27+ schema,
28+ } : {
29+ name : string
30+ schema : string
31+ } ) : Promise < PostgresMetaResult < PostgresFunction > >
2632 async retrieve ( {
2733 id,
2834 name,
35+ schema = 'public' ,
2936 } : {
3037 id ?: number
3138 name ?: string
39+ schema ?: string
3240 } ) : Promise < PostgresMetaResult < PostgresFunction > > {
3341 if ( id ) {
3442 const sql = `${ functionsSql } WHERE p.oid = ${ literal ( id ) } ;`
@@ -41,14 +49,16 @@ export default class PostgresMetaFunctions {
4149 return { data : data [ 0 ] , error }
4250 }
4351 } else if ( name ) {
44- const sql = `${ functionsSql } WHERE p.proname = ${ literal ( name ) } ;`
52+ const sql = `${ functionsSql } WHERE p.proname = ${ literal ( name ) } AND n.nspname = ${ literal (
53+ schema
54+ ) } ;`
4555 const { data, error } = await this . query ( sql )
4656 if ( error ) {
4757 return { data, error }
4858 } else if ( data . length === 0 ) {
4959 return {
5060 data : null ,
51- error : { message : `Cannot find a function named ${ name } ` } ,
61+ error : { message : `Cannot find a function named ${ name } in schema ${ schema } ` } ,
5262 }
5363 } else {
5464 return { data : data [ 0 ] , error }
@@ -57,4 +67,92 @@ export default class PostgresMetaFunctions {
5767 return { data : null , error : { message : 'Invalid parameters on function retrieve' } }
5868 }
5969 }
70+
71+ async create ( {
72+ name,
73+ schema = 'public' ,
74+ params,
75+ definition,
76+ rettype = 'void' ,
77+ language = 'sql' ,
78+ } : {
79+ name : string
80+ schema ?: string
81+ params ?: string [ ]
82+ definition : string
83+ rettype ?: string
84+ language ?: string
85+ } ) : Promise < PostgresMetaResult < PostgresFunction > > {
86+ const sql = `
87+ CREATE FUNCTION ${ ident ( schema ) } .${ ident ( name ) }
88+ ${ params && params . length ? `(${ params . join ( ',' ) } )` : '()' }
89+ RETURNS ${ rettype }
90+ AS ${ literal ( definition ) }
91+ LANGUAGE ${ language }
92+ RETURNS NULL ON NULL INPUT;
93+ `
94+ const { error } = await this . query ( sql )
95+ if ( error ) {
96+ return { data : null , error }
97+ }
98+ return await this . retrieve ( { name, schema } )
99+ }
100+
101+ async update (
102+ id : number ,
103+ {
104+ name,
105+ schema,
106+ } : {
107+ name ?: string
108+ schema ?: string
109+ }
110+ ) : Promise < PostgresMetaResult < PostgresFunction > > {
111+ const { data : old , error : retrieveError } = await this . retrieve ( { id } )
112+ if ( retrieveError ) {
113+ return { data : null , error : retrieveError }
114+ }
115+
116+ const updateNameSql =
117+ name && name !== old ! . name
118+ ? `ALTER FUNCTION ${ ident ( old ! . schema ) } .${ ident ( old ! . name ) } (${
119+ old ! . argument_types
120+ } ) RENAME TO ${ ident ( name ) } ;`
121+ : ''
122+
123+ const updateSchemaSql =
124+ schema && schema !== old ! . schema
125+ ? `ALTER FUNCTION ${ ident ( old ! . schema ) } .${ ident ( name || old ! . name ) } (${
126+ old ! . argument_types
127+ } ) SET SCHEMA ${ ident ( schema ) } ;`
128+ : ''
129+
130+ const sql = `BEGIN;${ updateNameSql } ${ updateSchemaSql } COMMIT;`
131+
132+ const { error } = await this . query ( sql )
133+ if ( error ) {
134+ return { data : null , error }
135+ }
136+ return await this . retrieve ( { id } )
137+ }
138+
139+ async remove (
140+ id : number ,
141+ { cascade = false } = { }
142+ ) : Promise < PostgresMetaResult < PostgresFunction > > {
143+ const { data : func , error } = await this . retrieve ( { id } )
144+ if ( error ) {
145+ return { data : null , error }
146+ }
147+ const sql = `DROP FUNCTION ${ ident ( func ! . schema ) } .${ ident ( func ! . name ) }
148+ ${ func ! . argument_types ? `(${ func ! . argument_types } )` : '()' }
149+ ${ cascade ? 'CASCADE' : 'RESTRICT' } ;`
150+ {
151+ const { error } = await this . query ( sql )
152+ if ( error ) {
153+ return { data : null , error }
154+ }
155+ }
156+ return { data : func ! , error : null }
157+ }
60158}
0 commit comments