AI 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
_136---_136# Specify the following for Cursor rules_136description: Guidelines for writing Supabase database functions_136globs: "**/*.sql"_136---_136_136# Database: Create functions_136_136You're a Supabase Postgres expert in writing database functions. Generate **high-quality PostgreSQL functions** that adhere to the following best practices:_136_136## General Guidelines_136_1361. **Default to `SECURITY INVOKER`:**_136_136 - Functions should run with the permissions of the user invoking the function, ensuring safer access control._136 - Use `SECURITY DEFINER` only when explicitly required and explain the rationale._136_1362. **Set the `search_path` Configuration Parameter:**_136_136 - Always set `search_path` to an empty string (`set search_path = '';`)._136 - This avoids unexpected behavior and security risks caused by resolving object references in untrusted or unintended schemas._136 - Use fully qualified names (e.g., `schema_name.table_name`) for all database objects referenced within the function._136_1363. **Adhere to SQL Standards and Validation:**_136 - Ensure all queries within the function are valid PostgreSQL SQL queries and compatible with the specified context (ie. Supabase)._136_136## Best Practices_136_1361. **Minimize Side Effects:**_136_136 - Prefer functions that return results over those that modify data unless they serve a specific purpose (e.g., triggers)._136_1362. **Use Explicit Typing:**_136_136 - Clearly specify input and output types, avoiding ambiguous or loosely typed parameters._136_1363. **Default to Immutable or Stable Functions:**_136_136 - 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._136_1364. **Triggers (if Applicable):**_136 - 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`)._136_136## Example Templates_136_136### Simple Function with `SECURITY INVOKER`_136_136```sql_136create or replace function my_schema.hello_world()_136returns text_136language plpgsql_136security invoker_136set search_path = ''_136as $$_136begin_136 return 'hello world';_136end;_136$$;_136```_136_136### Function with Parameters and Fully Qualified Object Names_136_136```sql_136create or replace function public.calculate_total_price(order_id bigint)_136returns numeric_136language plpgsql_136security invoker_136set search_path = ''_136as $$_136declare_136 total numeric;_136begin_136 select sum(price * quantity)_136 into total_136 from public.order_items_136 where order_id = calculate_total_price.order_id;_136_136 return total;_136end;_136$$;_136```_136_136### Function as a Trigger_136_136```sql_136create or replace function my_schema.update_updated_at()_136returns trigger_136language plpgsql_136security invoker_136set search_path = ''_136as $$_136begin_136 -- Update the "updated_at" column on row modification_136 new.updated_at := now();_136 return new;_136end;_136$$;_136_136create trigger update_updated_at_trigger_136before update on my_schema.my_table_136for each row_136execute function my_schema.update_updated_at();_136```_136_136### Function with Error Handling_136_136```sql_136create or replace function my_schema.safe_divide(numerator numeric, denominator numeric)_136returns numeric_136language plpgsql_136security invoker_136set search_path = ''_136as $$_136begin_136 if denominator = 0 then_136 raise exception 'Division by zero is not allowed';_136 end if;_136_136 return numerator / denominator;_136end;_136$$;_136```_136_136### Immutable Function for Better Optimization_136_136```sql_136create or replace function my_schema.full_name(first_name text, last_name text)_136returns text_136language sql_136security invoker_136set search_path = ''_136immutable_136as $$_136 select first_name || ' ' || last_name;_136$$;_136```