# Escape functions

Functions for escaping identifiers and values in SurrealQL queries.

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

> [!NOTE: Tip]
> Prefer using [`surql`](/docs/reference/javascript/api/utilities/surql.md) or [`BoundQuery`](/docs/reference/javascript/api/utilities/bound-query.md) for automatic parameterisation. Use escape functions only when absolutely necessary.

**Import:**
```ts
import { 
    escapeIdent,
    escapeNumber,
    escapeIdPart,
    escapeRangeBound
} from 'surrealdb';
```

**Source:** [utils/escape.ts](https://github.com/surrealdb/surrealdb.js/blob/main/packages/sdk/src/utils/escape.ts)

## Functions

### `escapeIdent(name)` {#escapeident}

Escape table names, field names, and other identifiers.

```ts title="Signature"
function escapeIdent(name: string): string
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>name</code> <label label="required" /></td>
            <td><code>string</code></td>
            <td>The identifier to escape.</td>
        </tr>
    </tbody>
</table>

#### Returns
`string` - Escaped identifier

#### Examples

```ts
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`'
```

---

### `escapeNumber(num)` {#escapenumber}

Escape a number to be used as a valid SurrealQL ident.

```ts title="Signature"
function escapeNumber(num: number | bigint): string
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>num</code> <label label="required" /></td>
            <td><code>number | bigint</code></td>
            <td>The number to escape.</td>
        </tr>
    </tbody>
</table>

#### Returns
`string` - Escaped number representation

#### Examples

```ts
import { escapeNumber } from 'surrealdb';

console.log(escapeNumber(123));    // '123'
console.log(escapeNumber(42n));    // '42'
```

---

### `escapeIdPart(id)` {#escapeidpart}

Escape a record ID value part. Handles `Uuid`, `string`, `number`, `bigint`, and object values.

```ts title="Signature"
function escapeIdPart(id: RecordIdValue): string
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>id</code> <label label="required" /></td>
            <td><code>RecordIdValue</code></td>
            <td>The record ID value part to escape.</td>
        </tr>
    </tbody>
</table>

#### Returns
`string` - Escaped record ID part

#### Examples

```ts
import { escapeIdPart } from 'surrealdb';

// String IDs
console.log(escapeIdPart('john'));        // 'john' or escaped equivalent

// Numeric IDs
console.log(escapeIdPart(123));           // '123'
console.log(escapeIdPart(42n));           // '42'

// UUID values
console.log(escapeIdPart(new Uuid('...')));
```

---

### `escapeRangeBound(bound)` {#escaperangebound}

Escape a range bound value for use in SurrealQL range expressions.

```ts title="Signature"
function escapeRangeBound<T>(bound: Bound<T>): string
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>bound</code> <label label="required" /></td>
            <td><code>Bound&lt;T&gt;</code></td>
            <td>The range bound to escape.</td>
        </tr>
    </tbody>
</table>

#### Returns
`string` - Escaped range bound representation

## Complete examples

### Dynamic table names

```ts
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

```ts
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']);
```

### Using surql instead (recommended)

```ts
// Prefer surql for safe parameterisation
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:
- **For values:** Use [`surql`](/docs/reference/javascript/api/utilities/surql.md) or [`BoundQuery`](/docs/reference/javascript/api/utilities/bound-query.md)
- **For tables:** Use [`Table`](/docs/reference/javascript/api/values/table.md) class
- **For record IDs:** Use [`RecordId`](/docs/reference/javascript/api/values/record-id.md) class
- **For conditions:** Use [`expr`](/docs/reference/javascript/api/utilities/expr.md)

## Best practices

### 1. Prefer type-safe alternatives

```ts
// 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

```ts
// 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

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

// Avoid: Manual string construction
const query = `SELECT * FROM users WHERE name = '${name}'`;
```

## Security considerations

> [!WARNING]
> Escaping functions are NOT a complete defense against SQL injection. Always prefer parameterised queries using `surql` or `BoundQuery`.

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

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

## See also

- [surql](/docs/reference/javascript/api/utilities/surql.md) - Recommended for parameterised queries
- [BoundQuery](/docs/reference/javascript/api/utilities/bound-query.md) - Parameterised query class
- [Table](/docs/reference/javascript/api/values/table.md) - Type-safe table references
- [RecordId](/docs/reference/javascript/api/values/record-id.md) - Type-safe record identifiers
