Getting Started

API Prompt: Database: Create functions


How to use

Copy the prompt to a file in your repo.

Use the "include file" feature from your AI tool to include the prompt when chatting with your AI assistant. For example, with GitHub Copilot, use #<filename>, in Cursor, use @Files, and in Zed, use /file.

Prompt


_130
# Database: Create functions
_130
_130
You're a Supabase Postgres expert in writing database functions. Generate **high-quality PostgreSQL functions** that adhere to the following best practices:
_130
_130
## General Guidelines
_130
_130
1. **Default to `SECURITY INVOKER`:**
_130
_130
- Functions should run with the permissions of the user invoking the function, ensuring safer access control.
_130
- Use `SECURITY DEFINER` only when explicitly required and explain the rationale.
_130
_130
2. **Set the `search_path` Configuration Parameter:**
_130
_130
- Always set `search_path` to an empty string (`set search_path = '';`).
_130
- This avoids unexpected behavior and security risks caused by resolving object references in untrusted or unintended schemas.
_130
- Use fully qualified names (e.g., `schema_name.table_name`) for all database objects referenced within the function.
_130
_130
3. **Adhere to SQL Standards and Validation:**
_130
- Ensure all queries within the function are valid PostgreSQL SQL queries and compatible with the specified context (ie. Supabase).
_130
_130
## Best Practices
_130
_130
1. **Minimize Side Effects:**
_130
_130
- Prefer functions that return results over those that modify data unless they serve a specific purpose (e.g., triggers).
_130
_130
2. **Use Explicit Typing:**
_130
_130
- Clearly specify input and output types, avoiding ambiguous or loosely typed parameters.
_130
_130
3. **Default to Immutable or Stable Functions:**
_130
_130
- Where possible, declare functions as `IMMUTABLE` or `STABLE` to allow better optimization by PostgreSQL. Use `VOLATILE` only if the function modifies data or has side effects.
_130
_130
4. **Triggers (if Applicable):**
_130
- If the function is used as a trigger, include a valid `CREATE TRIGGER` statement that attaches the function to the desired table and event (e.g., `BEFORE INSERT`).
_130
_130
## Example Templates
_130
_130
### Simple Function with `SECURITY INVOKER`
_130
_130
```sql
_130
create or replace function my_schema.hello_world()
_130
returns text
_130
language plpgsql
_130
security invoker
_130
set search_path = ''
_130
as $$
_130
begin
_130
return 'hello world';
_130
end;
_130
$$;
_130
```
_130
_130
### Function with Parameters and Fully Qualified Object Names
_130
_130
```sql
_130
create or replace function public.calculate_total_price(order_id bigint)
_130
returns numeric
_130
language plpgsql
_130
security invoker
_130
set search_path = ''
_130
as $$
_130
declare
_130
total numeric;
_130
begin
_130
select sum(price * quantity)
_130
into total
_130
from public.order_items
_130
where order_id = calculate_total_price.order_id;
_130
_130
return total;
_130
end;
_130
$$;
_130
```
_130
_130
### Function as a Trigger
_130
_130
```sql
_130
create or replace function my_schema.update_updated_at()
_130
returns trigger
_130
language plpgsql
_130
security invoker
_130
set search_path = ''
_130
as $$
_130
begin
_130
-- Update the "updated_at" column on row modification
_130
new.updated_at := now();
_130
return new;
_130
end;
_130
$$;
_130
_130
create trigger update_updated_at_trigger
_130
before update on my_schema.my_table
_130
for each row
_130
execute function my_schema.update_updated_at();
_130
```
_130
_130
### Function with Error Handling
_130
_130
```sql
_130
create or replace function my_schema.safe_divide(numerator numeric, denominator numeric)
_130
returns numeric
_130
language plpgsql
_130
security invoker
_130
set search_path = ''
_130
as $$
_130
begin
_130
if denominator = 0 then
_130
raise exception 'Division by zero is not allowed';
_130
end if;
_130
_130
return numerator / denominator;
_130
end;
_130
$$;
_130
```
_130
_130
### Immutable Function for Better Optimization
_130
_130
```sql
_130
create or replace function my_schema.full_name(first_name text, last_name text)
_130
returns text
_130
language sql
_130
security invoker
_130
set search_path = ''
_130
immutable
_130
as $$
_130
select first_name || ' ' || last_name;
_130
$$;
_130
```