Skip to content

basalt / prisma/src / rlsSearchFunctionSql

Function: rlsSearchFunctionSql() ​

> rlsSearchFunctionSql(options): string

Defined in: prisma/src/rls-search.ts:235

SQL for a tenant-scoped full-text search function: a SECURITY DEFINER function that searches table inside the tenant currently in the session's setting, with the GIN index intact.

rlsSearchFunctionSql({
  name: 'basalt_search_scoped',
  table: 'basalt_search',
  vectorColumn: 'tsv',
  partitionColumn: 'idx',
  filterColumn: 'document',
  columns: [{ name: 'document', type: 'jsonb' }],
  role: 'app',        // the role the app connects as
  owner: 'app_owner', // must bypass the table's RLS (BYPASSRLS / superuser)
})

Call it with the tenant already set for the transaction — the same set_config tenancyExtension({ rls: true }) issues:

SELECT * FROM basalt_search_scoped('invoice overdue', 'notes', NULL, 20, 0)

Parameters ​

options ​

RlsSearchFunctionSqlOptions

Returns ​

string

Security ​

The function takes no tenant parameter. There is nothing for a caller to tamper with: the tenant comes from current_setting(<setting>, true), byte for byte the expression in the policy rlsPolicySql installs. An unset setting reads as NULL, tenant = NULL is never true, and the function returns no rows — it fails closed, exactly like the policy. Keep setting in sync with the policy's.

What the generated SQL does, statement by statement:

  • drops and recreates the function (idempotent, like rlsPolicySql);
  • pins search_path inside the function — a SECURITY DEFINER function without one is a privilege-escalation hole;
  • marks it STABLE and PARALLEL SAFE (it only reads);
  • re-applies the tenant predicate itself, so the rows it can return are the rows the policy would have allowed;
  • caps the result (p_limit clamped to maxRows) so one call can never pull the corpus, and returns the pre-LIMIT match count as total;
  • REVOKE ALL … FROM PUBLIC, then GRANT EXECUTE to the application role only — a new function is executable by PUBLIC by default.

Every identifier is validated and quoted; nothing is interpolated raw.

Released under the MIT License.