Custom Functions
A function is a reusable block of SQL code that returns a scalar value of a set of rows.
- Functions are transactional by nature. If there is an error somewhere in the function, then the function will be rolled back.
- If a function is called within a transaction block, and the executing code does not reach the concluding
COMMIT
, then all code executed within the function will roll back as well. - Any
BEGIN...EXCEPT
blocks within the function operate like savepoints like theSAVEPOINT
andROLLBACK TO <SAVEPOINT>
SQL statements.
- If a function is called within a transaction block, and the executing code does not reach the concluding
- SQL functions execute an arbitrary list of SQL statements, returning the result of the last query in the list.
- In the simple (non-set) case, the first row of the last query's result will be returned
- Alternatively, an SQL function can be declared to return a set, which allows all rows of the last query's result to be returned
- allows us to write functions that can interact on the database. For instance, we can create a function that combines
first_name
andlast_name
to give usfullName
- Since PostgreSQL permits function overloading, the function name alone does not uniquely identify the function to be called;
- the parser must select the rigt function based on the data types of the supplied arguments.
- Functions and operators in PostgreSQL support polymorphism and almost every part of the system can be extended.
- By default, functions can be executable by public
- anonymous IIFEs can be invoked anywhere in the SQL by escaping the function identifiers:
DO \$\$
BEGIN
EXECUTE 'GRANT appname TO ' || user;
EXECUTE 'GRANT appname_authenticator TO ' || user;
END;
\$\$ LANGUAGE PLPGSQL;
Using functions in queries
- say we have a function that returns a composite type:
CREATE FUNCTION new_emp() RETURNS emp AS $$
SELECT ROW('None', 1000, 25, 'yoyo')::emp;
$$ LANGUAGE SQL;
- here we are returning a single column that is a composite type of the signature: string, int, int, string. We also coerce it to the composite type related to the whole
emp
table. This means that theemp
table has all 4 of those rows, and the act of us coercing means the output of the function can be used anywhere that an explicitemp
type is required. - we could make a SELECT statement to get back a one-column table by using
SELECT new_emp()
- since the composite type is also a sort of virtual table, we can use the function as a "table function":
SELECT * FROM new_emp();
, which will return 4 columns.
Syntax
- use
$$
to open and close the function: - stable means that this function does not mutate the database
Terms
setof
- Sets emulate rows of tables.returns setof
andreturns table(column)
are equivalent- When an SQL function is declared as returning SETOF sometype, the function's final query is executed to completion, and each row it outputs is returned as an element of the result set.
- This feature is normally used when calling the function in the FROM clause, since everything after FROM would get interpreted as if it were a base table. In other words, we can add some columns to a base table, and query it as if those added rows were permanent
- ex. imagine having a function that determined if your salary was above $100,000. we can use a function to get the boolean result and attach it to the base table, so that we can use `FROM employee, getAboveHundred(emp1)
- This feature is normally used when calling the function in the FROM clause, since everything after FROM would get interpreted as if it were a base table. In other words, we can add some columns to a base table, and query it as if those added rows were permanent
CREATE FUNCTION add(a int, b int) returns int as $$
select a + b
$$ language sql stable;
PL/PGSQL
Declare
- Declare a variable of specified type
Function Declarations
Strict
- this means that if the function receives null input, then the function won't be called and the output will automatically be null as well.
- ex. imagine we have a
register_user
function, that takes name, email and password as inputs. If the function does not receivename
, we want it to fail.
- ex. imagine we have a
Security Definer/Invoker
- Security Definer - "the privileges of the function use the privileges (security clearance) of the definer"
- Security invoker - "use privileges (security clearance) of the user who invoked the function
- this means that the function is created with the privileges of the pg role that created it.
- This is a way to heighten the rights of the function, and can be thought of similar to sudo, instead of rights being elevated to superuser, rights are only elevated to the creator of the function itself
- ie. if we run our migrations with user
postgres
, then usingsecurity definer
will give our function the rights ofpostgres
. This is helpful if we want to insert into a table that is part of a very strict schema, such asapp_private
- ie. if we run our migrations with user
- we can use
security definer
to by pass RLS
UE Resource
insert returning into variable
Children
Backlinks