Learn how to define and call database functions with fn::, optional arguments, and permissions.
DEFINE FUNCTION registers reusable SurrealQL under a name beginning with the fn:: prefix. You need appropriate access (root / namespace / database owner or editor), and you must USE the right namespace and database first. For more clauses and edge cases, see the reference documentation.
Define and call
Custom functions are always named with the fn:: prefix.
-- Simple function: build a string from an argument DEFINEFUNCTIONfn::greet($name: string) { "Hello, "+$name+"!" };
RETURNfn::greet("Tobie");
-- More than one parameter; body can use LET, subqueries, RETURN, and so on DEFINEFUNCTIONfn::relation_exists($in: record, $tb: string, $out: record) { LET$results = SELECTVALUEidFROMtype::table($tb) WHEREin=$inANDout=$out; RETURNarray::len($results) >0; };
Optional trailing arguments
If the last parameters use option<T>, callers may omit them.
RETURNfn::last_option(1, 2); -- both set RETURNfn::last_option(1); -- optional omitted
Annotated return types
Adding -> type is recommended for extra type safety, as well as readability. Though the first example can clearly only return a number due to its two arguments being of the same type, it is easier for a casual reader to know what sort of value is being returned.
Though not a commonly used pattern in SurrealQL, a function may call itself. Below, each step relates the first record in a list to all the rest, then recurses on the tail until fewer than two records remain.
PERMISSIONS controls whether record users may invoke the function: FULL (typical default), NONE, or WHERE with a boolean expression (often involving $auth).
-- PERMISSIONS NONE: record users cannot call this (admins / root still can, depending on setup) DEFINEFUNCTIONfn::fetchAllPaymentDetails() { SELECTstored_cards.expiry_yearFROMpayment_detailsLIMIT5 }PERMISSIONSNONE;
-- PERMISSIONS WHERE: only when the expression is true (here, admin flag on $auth) DEFINEFUNCTIONfn::fetchAllProducts() { SELECT * FROMproductLIMIT10 }PERMISSIONSWHERE$auth.admin=true;
Creating or replacing a definition
Clauses like IF NOT EXISTS and `OVERWRITE' can be used when defining a function.
-- IF NOT EXISTS: only define when no function with this name exists yet (no-op if it does) DEFINEFUNCTIONIFNOTEXISTSfn::example() {};
-- OVERWRITE: replace an existing definition with this one DEFINEFUNCTIONOVERWRITEfn::example() {};
Functions as API middleware
Handlers for DEFINE API middleware are ordinary fn:: functions with a specific signature. See custom middleware and the learn page on middleware for more details.