Custom SQL
Write advanced WHERE clauses with raw SQL for cases that standard operators cannot express.
When MongoDB-style operators are not enough, you can use custom SQL expressions in filters. This is an escape hatch for complex access control logic.
permissions: {
view_recent_orders: {
name: 'View recent orders',
table: 'main.orders',
operations: { select: true },
columns: '*',
filter: {
$sql: "created_at > NOW() - INTERVAL '30 days'",
},
},
}Syntax
Use $sql as a filter key with a SQL string value:
filter: {
$sql: "your_sql_expression",
}The expression is injected directly into the WHERE clause.
Examples
Date Range
filter: {
$sql: "created_at > NOW() - INTERVAL '90 days'",
}SELECT * FROM main.orders
WHERE created_at > NOW() - INTERVAL '90 days'Computed Conditions
filter: {
$sql: "amount * quantity <= 10000",
}SELECT * FROM main.orders
WHERE amount * quantity <= 10000Combining with Standard Filters
Custom SQL can be combined with standard operator-based filters:
filter: {
organization_id: { $in: '$user.org_ids' },
status: { $ne: 'deleted' },
$sql: "created_at > NOW() - INTERVAL '30 days'",
}SELECT * FROM main.orders
WHERE organization_id IN ('org_1', 'org_2')
AND status != 'deleted'
AND created_at > NOW() - INTERVAL '30 days'Using Session Variables in SQL
Reference session variables with the $user. prefix inside the SQL string:
filter: {
$sql: "created_by = '$user.id' OR assigned_to = '$user.id'",
}The engine replaces $user.* tokens with their actual values before executing.
Safety Rules
Custom SQL is powerful but comes with constraints to prevent abuse:
-
Read-only — Only expressions valid in a WHERE clause are allowed. No subqueries with
INSERT,UPDATE,DELETE, orDROP. -
No semicolons — The engine rejects any SQL containing
;to prevent statement injection. -
No comments — SQL comments (
--and/* */) are stripped. -
Parameterized session variables —
$user.*references are parameterized, not string-interpolated, to prevent SQL injection. -
Schema-scoped — You can only reference columns from the permission's table and its known relationships.
-
Allowlisted functions — Only safe SQL functions are permitted (e.g.,
NOW(),COALESCE,LOWER,UPPER,LENGTH). System functions and file access functions are blocked.
When to Use Custom SQL
| Use Case | Recommendation |
|---|---|
| Simple equality | Use $eq operator |
| IN / NOT IN | Use $in / $nin |
| Range checks | Use $gt, $gte, $lt, $lte |
| Date math | Use $sql |
| Computed columns | Use $sql |
| Cross-column logic | Use $sql |
| String patterns | Use $sql with LIKE |
Prefer standard operators when possible. Use $sql only when the built-in operators cannot express your access rule.