sqlite: add tagged template · nodejs/node@5563361

@@ -351,6 +351,53 @@ added: v22.5.0

351351

Compiles a SQL statement into a [prepared statement][]. This method is a wrapper

352352

around [`sqlite3_prepare_v2()`][].

353353354+

### `database.createSQLTagStore([maxSize])`

355+356+

<!-- YAML

357+

added: REPLACEME

358+

-->

359+360+

* `maxSize` {integer} The maximum number of prepared statements to cache.

361+

**Default:** `1000`.

362+

* Returns: {SQLTagStore} A new SQL tag store for caching prepared statements.

363+364+

Creates a new `SQLTagStore`, which is an LRU (Least Recently Used) cache for

365+

storing prepared statements. This allows for the efficient reuse of prepared

366+

statements by tagging them with a unique identifier.

367+368+

When a tagged SQL literal is executed, the `SQLTagStore` checks if a prepared

369+

statement for that specific SQL string already exists in the cache. If it does,

370+

the cached statement is used. If not, a new prepared statement is created,

371+

executed, and then stored in the cache for future use. This mechanism helps to

372+

avoid the overhead of repeatedly parsing and preparing the same SQL statements.

373+374+

```mjs

375+

import { DatabaseSync } from 'node:sqlite';

376+377+

const db = new DatabaseSync(':memory:');

378+

const sql = db.createSQLTagStore();

379+380+

db.exec('CREATE TABLE users (id INT, name TEXT)');

381+382+

// Using the 'run' method to insert data.

383+

// The tagged literal is used to identify the prepared statement.

384+

sql.run`INSERT INTO users VALUES (1, 'Alice')`;

385+

sql.run`INSERT INTO users VALUES (2, 'Bob')`;

386+387+

// Using the 'get' method to retrieve a single row.

388+

const id = 1;

389+

const user = sql.get`SELECT * FROM users WHERE id = ${id}`;

390+

console.log(user); // { id: 1, name: 'Alice' }

391+392+

// Using the 'all' method to retrieve all rows.

393+

const allUsers = sql.all`SELECT * FROM users ORDER BY id`;

394+

console.log(allUsers);

395+

// [

396+

// { id: 1, name: 'Alice' },

397+

// { id: 2, name: 'Bob' }

398+

// ]

399+

```

400+354401

### `database.createSession([options])`

355402356403

<!-- YAML

@@ -494,6 +541,120 @@ times with different bound values. Parameters also offer protection against

494541

[SQL injection][] attacks. For these reasons, prepared statements are preferred

495542

over hand-crafted SQL strings when handling user input.

496543544+

## Class: `SQLTagStore`

545+546+

<!-- YAML

547+

added: REPLACEME

548+

-->

549+550+

This class represents a single LRU (Least Recently Used) cache for storing

551+

prepared statements.

552+553+

Instances of this class are created via the database.createSQLTagStore() method,

554+

not by using a constructor. The store caches prepared statements based on the

555+

provided SQL query string. When the same query is seen again, the store

556+

retrieves the cached statement and safely applies the new values through

557+

parameter binding, thereby preventing attacks like SQL injection.

558+559+

The cache has a maxSize that defaults to 1000 statements, but a custom size can

560+

be provided (e.g., database.createSQLTagStore(100)). All APIs exposed by this

561+

class execute synchronously.

562+563+

### `sqlTagStore.all(sqlTemplate[, ...values])`

564+565+

<!-- YAML

566+

added: REPLACEME

567+

-->

568+569+

* `sqlTemplate` {Template Literal} A template literal containing the SQL query.

570+

* `...values` {any} Values to be interpolated into the template literal.

571+

* Returns: {Array} An array of objects representing the rows returned by the query.

572+573+

Executes the given SQL query and returns all resulting rows as an array of objects.

574+575+

### `sqlTagStore.get(sqlTemplate[, ...values])`

576+577+

<!-- YAML

578+

added: REPLACEME

579+

-->

580+581+

* `sqlTemplate` {Template Literal} A template literal containing the SQL query.

582+

* `...values` {any} Values to be interpolated into the template literal.

583+

* Returns: {Object | undefined} An object representing the first row returned by

584+

the query, or `undefined` if no rows are returned.

585+586+

Executes the given SQL query and returns the first resulting row as an object.

587+588+

### `sqlTagStore.iterate(sqlTemplate[, ...values])`

589+590+

<!-- YAML

591+

added: REPLACEME

592+

-->

593+594+

* `sqlTemplate` {Template Literal} A template literal containing the SQL query.

595+

* `...values` {any} Values to be interpolated into the template literal.

596+

* Returns: {Iterator} An iterator that yields objects representing the rows returned by the query.

597+598+

Executes the given SQL query and returns an iterator over the resulting rows.

599+600+

### `sqlTagStore.run(sqlTemplate[, ...values])`

601+602+

<!-- YAML

603+

added: REPLACEME

604+

-->

605+606+

* `sqlTemplate` {Template Literal} A template literal containing the SQL query.

607+

* `...values` {any} Values to be interpolated into the template literal.

608+

* Returns: {Object} An object containing information about the execution, including `changes` and `lastInsertRowid`.

609+610+

Executes the given SQL query, which is expected to not return any rows (e.g., INSERT, UPDATE, DELETE).

611+612+

### `sqlTagStore.size()`

613+614+

<!-- YAML

615+

added: REPLACEME

616+

-->

617+618+

* Returns: {integer} The number of prepared statements currently in the cache.

619+620+

A read-only property that returns the number of prepared statements currently in the cache.

621+622+

### `sqlTagStore.capacity`

623+624+

<!-- YAML

625+

added: REPLACEME

626+

-->

627+628+

* Returns: {integer} The maximum number of prepared statements the cache can hold.

629+630+

A read-only property that returns the maximum number of prepared statements the cache can hold.

631+632+

### `sqlTagStore.db`

633+634+

<!-- YAML

635+

added: REPLACEME

636+

-->

637+638+

* {DatabaseSync} The `DatabaseSync` instance that created this `SQLTagStore`.

639+640+

A read-only property that returns the `DatabaseSync` object associated with this `SQLTagStore`.

641+642+

### `sqlTagStore.reset()`

643+644+

<!-- YAML

645+

added: REPLACEME

646+

-->

647+648+

Resets the LRU cache, clearing all stored prepared statements.

649+650+

### `sqlTagStore.clear()`

651+652+

<!-- YAML

653+

added: REPLACEME

654+

-->

655+656+

An alias for `sqlTagStore.reset()`.

657+497658

### `statement.all([namedParameters][, ...anonymousParameters])`

498659499660

<!-- YAML