Home Explore Blog Models CI



postgresql

11th chunk of `doc/src/sgml/ref/create_function.sgml`
b37438929e2f07bfb9ec8e242ba85c6908aea25e5baacfd50000000100000f19
 integer) RETURNS integer
    AS 'select $1 + $2;'
    LANGUAGE SQL
    IMMUTABLE
    RETURNS NULL ON NULL INPUT;
</programlisting>
   The same function written in a more SQL-conforming style, using argument
   names and an unquoted body:
<programlisting>
CREATE FUNCTION add(a integer, b integer) RETURNS integer
    LANGUAGE SQL
    IMMUTABLE
    RETURNS NULL ON NULL INPUT
    RETURN a + b;
</programlisting>
  </para>

  <para>
   Increment an integer, making use of an argument name, in
   <application>PL/pgSQL</application>:
<programlisting>
CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$
        BEGIN
                RETURN i + 1;
        END;
$$ LANGUAGE plpgsql;
</programlisting>
  </para>

  <para>
   Return a record containing multiple output parameters:
<programlisting>
CREATE FUNCTION dup(in int, out f1 int, out f2 text)
    AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
    LANGUAGE SQL;

SELECT * FROM dup(42);
</programlisting>
   You can do the same thing more verbosely with an explicitly named
   composite type:
<programlisting>
CREATE TYPE dup_result AS (f1 int, f2 text);

CREATE FUNCTION dup(int) RETURNS dup_result
    AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
    LANGUAGE SQL;

SELECT * FROM dup(42);
</programlisting>
   Another way to return multiple columns is to use a <literal>TABLE</literal>
   function:
<programlisting>
CREATE FUNCTION dup(int) RETURNS TABLE(f1 int, f2 text)
    AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
    LANGUAGE SQL;

SELECT * FROM dup(42);
</programlisting>
   However, a <literal>TABLE</literal> function is different from the
   preceding examples, because it actually returns a <emphasis>set</emphasis>
   of records, not just one record.
  </para>
 </refsect1>

 <refsect1 id="sql-createfunction-security">
  <title>Writing <literal>SECURITY DEFINER</literal> Functions Safely</title>

  <indexterm>
   <primary><varname>search_path</varname> configuration parameter</primary>
   <secondary>use in securing functions</secondary>
  </indexterm>

  <indexterm>
   <primary><varname>createrole_self_grant</varname> configuration parameter</primary>
   <secondary>use in securing functions</secondary>
  </indexterm>

   <para>
    Because a <literal>SECURITY DEFINER</literal> function is executed
    with the privileges of the user that owns it, care is needed to
    ensure that the function cannot be misused.  For security,
    <xref linkend="guc-search-path"/> should be set to exclude any schemas
    writable by untrusted users.  This prevents
    malicious users from creating objects (e.g., tables, functions, and
    operators) that mask objects intended to be used by the function.
    Particularly important in this regard is the
    temporary-table schema, which is searched first by default, and
    is normally writable by anyone.  A secure arrangement can be obtained
    by forcing the temporary schema to be searched last.  To do this,
    write <literal>pg_temp</literal><indexterm><primary>pg_temp</primary><secondary>securing functions</secondary></indexterm> as the last entry in <varname>search_path</varname>.
    This function illustrates safe usage:

<programlisting>
CREATE FUNCTION check_password(uname TEXT, pass TEXT)
RETURNS BOOLEAN AS $$
DECLARE passed BOOLEAN;
BEGIN
        SELECT  (pwd = $2) INTO passed
        FROM    pwds
        WHERE   username = $1;

        RETURN passed;
END;
$$  LANGUAGE plpgsql
    SECURITY DEFINER
    -- Set a secure search_path: trusted schema(s), then 'pg_temp'.
    SET search_path = admin, pg_temp;
</programlisting>

    This function's intention is to access a table <literal>admin.pwds</literal>.
    But without the <literal>SET</literal> clause, or with a <literal>SET</literal> clause
    mentioning only <literal>admin</literal>, the function could be subverted by
    creating

Title: CREATE FUNCTION: Examples and Security Considerations for SECURITY DEFINER Functions
Summary
Presents examples of SQL functions that add integers, increment an integer using PL/pgSQL, and return multiple output parameters using SQL and composite types or TABLE functions. It also explains how to safely write SECURITY DEFINER functions, emphasizing the importance of setting the search_path to exclude schemas writable by untrusted users, particularly the temporary-table schema, to prevent malicious users from creating objects that mask intended objects. It provides an example of a function designed to access a table safely by setting search_path to admin, pg_temp.