Escape Functions

Escape functions provide safe handling of identifiers and values in SurrealQL queries when you need to construct queries manually.

Import:

import { 
escapeIdent,
escapeKey,
escapeRid,
escapeValue
} from 'surrealdb';

Source: utils/escape.ts

Functions

escapeIdent(name)

Escape table names, field names, and other identifiers.

Signature

function escapeIdent(name: string): string

Parameters

ParameterTypeDescription
name stringThe identifier to escape.

Returns

string - Escaped identifier

Examples

import { escapeIdent } from 'surrealdb';

// Simple identifiers (no escaping needed)
console.log(escapeIdent('users')); // 'users'
console.log(escapeIdent('first_name')); // 'first_name'

// Special characters (wrapped in backticks)
console.log(escapeIdent('user-table')); // '`user-table`'
console.log(escapeIdent('my table')); // '`my table`'
console.log(escapeIdent('user.name')); // '`user.name`'

// Reserved keywords
console.log(escapeIdent('select')); // '`select`'
console.log(escapeIdent('from')); // '`from`'

escapeKey(key)

Escape object keys for use in queries.

Signature

function escapeKey(key: string): string

Returns

string - Escaped key

Example

const key = 'user-property';
console.log(escapeKey(key)); // Properly escaped for object notation

escapeRid(value)

Escape record ID components.

Signature

function escapeRid(value: string | number): string

Parameters

ParameterTypeDescription
value string | numberThe record ID component to escape.

Returns

string - Escaped record ID component

Examples

import { escapeRid } from 'surrealdb';

// Simple IDs
console.log(escapeRid('john')); // 'john'
console.log(escapeRid(123)); // '123'

// IDs with special characters
console.log(escapeRid('user-123')); // '`user-123`'
console.log(escapeRid('user@email.com')); // '`user@email.com`'

escapeValue(value)

Escape values for use in queries.

Signature

function escapeValue(value: unknown): string

Parameters

ParameterTypeDescription
value unknownThe value to escape.

Returns

string - Escaped value representation

Examples

import { escapeValue } from 'surrealdb';

// Strings
console.log(escapeValue('hello')); // "'hello'"
console.log(escapeValue("O'Reilly")); // "'O\\'Reilly'"

// Numbers
console.log(escapeValue(42)); // '42'
console.log(escapeValue(3.14)); // '3.14'

// Booleans
console.log(escapeValue(true)); // 'true'
console.log(escapeValue(false)); // 'false'

// null/undefined
console.log(escapeValue(null)); // 'null'
console.log(escapeValue(undefined)); // 'none'

Complete Examples

Dynamic Table Names

import { escapeIdent } from 'surrealdb';

async function selectFromTable(tableName: string) {
// Validate and escape table name
const safeTable = escapeIdent(tableName);

// Use in query (still prefer Table class)
const query = `SELECT * FROM ${safeTable}`;
const [results] = await db.query(query).collect();

return results;
}

await selectFromTable('user-sessions'); // Safe

Dynamic Field Selection

import { escapeIdent } from 'surrealdb';

async function selectFields(table: string, fields: string[]) {
const escapedFields = fields.map(escapeIdent).join(', ');
const escapedTable = escapeIdent(table);

const query = `SELECT ${escapedFields} FROM ${escapedTable}`;
const [results] = await db.query(query).collect();

return results;
}

await selectFields('users', ['first-name', 'last-name', 'email']);
// Only when you absolutely must build raw queries
import { escapeIdent, escapeValue } from 'surrealdb';

function buildUnsafeQuery(table: string, filters: Record<string, unknown>) {
const escapedTable = escapeIdent(table);

const conditions = Object.entries(filters)
.map(([key, value]) => {
const field = escapeIdent(key);
const val = escapeValue(value);
return `${field} = ${val}`;
})
.join(' AND ');

return `SELECT * FROM ${escapedTable} WHERE ${conditions}`;
}

// Better: Use surql instead!
const filters = { status: 'active', age: 18 };
const query = surql`
SELECT * FROM users
WHERE status = ${filters.status}
AND age = ${filters.age}
`;

When to Use

✅ Use Escape Functions When:

  • Constructing queries with user-provided table/field names

  • Working with identifiers that have special characters

  • Building dynamic schema definitions

  • Interfacing with external query builders

❌ Prefer Other Solutions:

Best Practices

1. Prefer Type-Safe Alternatives

// Good: Type-safe
const table = new Table('users');
const users = await db.select(table);

// Avoid: Manual escaping
const escaped = escapeIdent('users');
const users = await db.query(`SELECT * FROM ${escaped}`).collect();

2. Validate Before Escaping

// Good: Validate first
function safeQuery(tableName: string) {
if (!isValidTable(tableName)) {
throw new Error('Invalid table name');
}

const escaped = escapeIdent(tableName);
return `SELECT * FROM ${escaped}`;
}

// Avoid: Blind escaping
function unsafeQuery(tableName: string) {
return `SELECT * FROM ${escapeIdent(tableName)}`;
}

3. Use surql for Complex Queries

// Good: Automatic parameterization
const query = surql`SELECT * FROM users WHERE name = ${name}`;

// Avoid: Manual escaping
const query = `SELECT * FROM users WHERE name = ${escapeValue(name)}`;

Security Considerations

// Secure: Parameterized
const query = surql`SELECT * FROM users WHERE name = ${userInput}`;

// Less secure: Manual escaping
const query = `SELECT * FROM users WHERE name = ${escapeValue(userInput)}`;

// Insecure: No escaping
const query = `SELECT * FROM users WHERE name = '${userInput}'`;

See Also

  • surql - Recommended for parameterized queries

  • BoundQuery - Parameterized query class

  • Table - Type-safe table references

  • RecordId - Type-safe record identifiers