Skip to content

Commit

Permalink
implement more function options
Browse files Browse the repository at this point in the history
  • Loading branch information
ab-pm committed Nov 5, 2019
1 parent e883e5b commit 5683dce
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 4 deletions.
5 changes: 4 additions & 1 deletion docs/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@
- `replace` _[boolean]_ - create or replace function
- `window` _[boolean]_ - window function
- `behavior` _[string]_ - `IMMUTABLE`, `STABLE`, or `VOLATILE`
- `onNull` _[boolean]_ - `RETURNS NULL ON NULL INPUT`
- `strict` _[boolean]_ - `RETURNS NULL ON NULL INPUT`
- `onNull` _[string]_ (deprecated) - alias for `strict`, also accepts `NULL` or `CALLED`
- `parallel` _[string]_ - `UNSAFE`, `RESTRICTED`, or `SAFE`
- `cost` _[number]_ - estimated execution cost
- `rows` _[number]_ - estimated number of result rows
- `definition` _[string]_ - definition of function

**Reverse Operation:** `dropFunction`
Expand Down
6 changes: 5 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,12 @@ export interface FunctionOptions {
replace?: boolean
window?: boolean
behavior?: 'IMMUTABLE' | 'STABLE' | 'VOLATILE'
onNull?: boolean
onNull?: boolean | 'NULL' | 'CALLED'
strict?: boolean
security?: 'DEFINER' | 'INVOKER'
parallel?: 'UNSAFE' | 'RESTRICTED' | 'SAFE'
cost?: number
rows?: number
}

interface TriggerOptions {
Expand Down
21 changes: 19 additions & 2 deletions lib/operations/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ function createFunction(mOptions) {
window,
behavior = 'VOLATILE',
onNull,
parallel
strict,
security,
parallel,
cost,
rows,
support
} = functionOptions;
const options = [];
if (behavior) {
Expand All @@ -45,12 +50,24 @@ function createFunction(mOptions) {
if (window) {
options.push('WINDOW');
}
if (onNull) {
if (onNull === true || onNull === 'NULL' || strict) {
options.push('RETURNS NULL ON NULL INPUT');
}
if (security) {
options.push(`SECURITY ${security}`);
}
if (parallel) {
options.push(`PARALLEL ${parallel}`);
}
if (typeof cost !== 'undefined') {
options.push(`COST ${cost}`);
}
if (typeof rows !== 'undefined') {
options.push(`ROWS ${rows}`);
}
if (support) {
options.push(`SUPPORT ${support}`);
}

const replaceStr = replace ? ' OR REPLACE' : '';
const paramsStr = formatParams(functionParams, mOptions);
Expand Down
105 changes: 105 additions & 0 deletions test/functions-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
const { expect } = require('chai');
const Functions = require('../lib/operations/functions');
const { options1, options2 } = require('./utils');

describe('lib/operations/functions', () => {
const params = ['integer', { name: 'arg2', mode: 'in', type: 'integer' }];
describe('.create', () => {
it('check schemas can be used', () => {
const args = [
{ schema: 'mySchema', name: 'f' },
params,
{
returns: 'integer',
language: 'plpgsql',
onNull: 'CALLED'
},
`BEGIN
return $1 + arg2;
END;`
];
const sql1 = Functions.createFunction(options1)(...args);
const sql2 = Functions.createFunction(options2)(...args);
expect(sql1).to.equal(
`CREATE FUNCTION "mySchema"."f"(integer, in "arg2" integer)
RETURNS integer
AS $pg1$BEGIN
return $1 + arg2;
END;$pg1$
VOLATILE
LANGUAGE plpgsql;`
);
expect(sql2).to.equal(
`CREATE FUNCTION "my_schema"."f"(integer, in "arg2" integer)
RETURNS integer
AS $pg1$BEGIN
return $1 + arg2;
END;$pg1$
VOLATILE
LANGUAGE plpgsql;`
);
});

it('check param shorthands work', () => {
const args = [
{ schema: 'mySchema', name: 'f' },
['integer', 'IN arg2 integer'],
{
returns: 'integer',
language: 'sql',
behavior: 'IMMUTABLE',
strict: true
},
`SELECT $1 + arg2;`
];
const sql1 = Functions.createFunction(options1)(...args);
const sql2 = Functions.createFunction(options2)(...args);
expect(sql1).to.equal(
`CREATE FUNCTION "mySchema"."f"(integer, IN arg2 integer)
RETURNS integer
AS $pg1$SELECT $1 + arg2;$pg1$
IMMUTABLE
LANGUAGE sql
RETURNS NULL ON NULL INPUT;`
);
expect(sql2).to.equal(
`CREATE FUNCTION "my_schema"."f"(integer, IN arg2 integer)
RETURNS integer
AS $pg1$SELECT $1 + arg2;$pg1$
IMMUTABLE
LANGUAGE sql
RETURNS NULL ON NULL INPUT;`
);
});

it('check all PG12 options are supported', () => {
const sql = Functions.createFunction(options1)(
'myFunction',
['a integer', 'b real'],
{
returns: 'integer',
language: 'plpgsql',
behavior: 'STABLE',
onNull: 'NULL',
security: 'DEFINER',
parallel: 'RESTRICTED',
cost: 0,
rows: 7
},
'blah-blubb'
);
expect(sql).to.equal(
`CREATE FUNCTION "myFunction"(a integer, b real)
RETURNS integer
AS $pg1$blah-blubb$pg1$
STABLE
LANGUAGE plpgsql
RETURNS NULL ON NULL INPUT
SECURITY DEFINER
PARALLEL RESTRICTED
COST 0
ROWS 7;`
);
});
});
});

0 comments on commit 5683dce

Please sign in to comment.