Skip to content

Commit

Permalink
updated verbiage of various documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
JoshuaWise committed Jan 18, 2025
1 parent 2e86258 commit 084819a
Show file tree
Hide file tree
Showing 12 changed files with 42 additions and 42 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# better-sqlite3 [![Build Status](https://github.com/JoshuaWise/better-sqlite3/actions/workflows/build.yml/badge.svg)](https://github.com/JoshuaWise/better-sqlite3/actions/workflows/build.yml?query=branch%3Amaster)

The fastest and simplest library for SQLite3 in Node.js.
The fastest and simplest library for SQLite in Node.js.

- Full transaction support
- High performance, efficiency, and safety
Expand Down Expand Up @@ -32,7 +32,7 @@ The fastest and simplest library for SQLite3 in Node.js.
npm install better-sqlite3
```

> Prebuilt binaries are available for [LTS versions](https://nodejs.org/en/about/releases/). If you have trouble installing, check the [troubleshooting guide](./docs/troubleshooting.md).
> Requires Node.js v14.21.1 or later. Prebuilt binaries are available for [LTS versions](https://nodejs.org/en/about/releases/). If you have trouble installing, check the [troubleshooting guide](./docs/troubleshooting.md).
## Usage

Expand Down Expand Up @@ -66,7 +66,7 @@ db.pragma('journal_mode = WAL');

#### When is this library not appropriate?

In most cases, if you're attempting something that cannot be reasonably accomplished with `better-sqlite3`, it probably cannot be reasonably accomplished with SQLite3 in general. For example, if you're executing queries that take one second to complete, and you expect to have many concurrent users executing those queries, no amount of asynchronicity will save you from SQLite3's serialized nature. Fortunately, SQLite3 is very *very* fast. With proper indexing, we've been able to achieve upward of 2000 queries per second with 5-way-joins in a 60 GB database, where each query was handling 5–50 kilobytes of real data.
In most cases, if you're attempting something that cannot be reasonably accomplished with `better-sqlite3`, it probably cannot be reasonably accomplished with SQLite in general. For example, if you're executing queries that take one second to complete, and you expect to have many concurrent users executing those queries, no amount of asynchronicity will save you from SQLite's serialized nature. Fortunately, SQLite is very *very* fast. With proper indexing, we've been able to achieve upward of 2000 queries per second with 5-way-joins in a 60 GB database, where each query was handling 5–50 kilobytes of real data.

If you have a performance problem, the most likely causes are inefficient queries, improper indexing, or a lack of [WAL mode](./docs/performance.md)—not `better-sqlite3` itself. However, there are some cases where `better-sqlite3` could be inappropriate:

Expand All @@ -78,10 +78,10 @@ For these situations, you should probably use a full-fledged RDBMS such as [Post

## Upgrading

Upgrading your `better-sqlite3` dependency can potentially introduce breaking changes, either in the `better-sqlite3` API, or between your existing database(s) and the underlying version of SQLite. Before upgrading, review:
Upgrading your `better-sqlite3` dependency can potentially introduce breaking changes, either in the `better-sqlite3` API (if you upgrade to a new [major version](https://semver.org/)), or between your existing database(s) and the underlying version of SQLite. Before upgrading, review:

* `better-sqlite3` release notes: https://github.com/WiseLibs/better-sqlite3/releases
* SQLite changelog: https://www.sqlite.org/changes.html
* [`better-sqlite3` release notes](https://github.com/WiseLibs/better-sqlite3/releases)
* [SQLite release history](https://www.sqlite.org/changes.html)

# Documentation

Expand All @@ -90,7 +90,7 @@ Upgrading your `better-sqlite3` dependency can potentially introduce breaking ch
- [64-bit integer support](./docs/integer.md)
- [Worker thread support](./docs/threads.md)
- [Unsafe mode (advanced)](./docs/unsafe.md)
- [SQLite3 compilation (advanced)](./docs/compilation.md)
- [SQLite compilation (advanced)](./docs/compilation.md)
- [Contribution rules](./docs/contribution.md)
- [Code of conduct](./docs/conduct.md)

Expand Down
2 changes: 1 addition & 1 deletion benchmark/drivers.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

/*
Every benchmark trial will be executed once for each SQLite3 driver listed
Every benchmark trial will be executed once for each SQLite driver listed
below. Each driver has a function to open a new database connection on a
given filename and a list of PRAGMA statements.
*/
Expand Down
2 changes: 1 addition & 1 deletion binding.gyp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ===
# This is the main GYP file, which builds better-sqlite3 with SQLite3 itself.
# This is the main GYP file, which builds better-sqlite3 with SQLite itself.
# ===

{
Expand Down
4 changes: 2 additions & 2 deletions deps/download.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#!/usr/bin/env bash

# ===
# This script defines and generates the bundled SQLite3 unit (sqlite3.c).
# This script defines and generates the bundled SQLite unit (sqlite3.c).
#
# The following steps are taken:
# 1. populate the shell environment with the defined compile-time options.
# 2. download and extract the SQLite3 source code into a temporary directory.
# 2. download and extract the SQLite source code into a temporary directory.
# 3. run "sh configure" and "make sqlite3.c" within the source directory.
# 4. copy the generated amalgamation into the output directory (./sqlite3).
# 5. export the defined compile-time options to a gyp file (./defines.gypi).
Expand Down
2 changes: 1 addition & 1 deletion deps/sqlite3.gyp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ===
# This configuration defines options specific to compiling SQLite3 itself.
# This configuration defines options specific to compiling SQLite itself.
# Compile-time options are loaded by the auto-generated file "defines.gypi".
# The --sqlite3 option can be provided to use a custom amalgamation instead.
# ===
Expand Down
2 changes: 1 addition & 1 deletion deps/test_extension.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
SQLITE_EXTENSION_INIT1

/*
This SQLite3 extension is used only for testing purposes (npm test).
This SQLite extension is used only for testing purposes (npm test).
*/

static void TestExtensionFunction(sqlite3_context* pCtx, int nVal, sqlite3_value** _) {
Expand Down
34 changes: 17 additions & 17 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ Any arguments passed to the transaction function will be forwarded to the wrappe

If you'd like to manage transactions manually, you're free to do so with regular [prepared statements](#preparestring---statement) (using `BEGIN`, `COMMIT`, etc.). However, manually managed transactions should not be mixed with transactions managed by this `.transaction()` method. In other words, using raw `COMMIT` or `ROLLBACK` statements inside a transaction function is not supported.

Transaction functions do not work with async functions. Technically speaking, async functions always return after the first `await`, which means the transaction will already be committed before any async code executes. Also, because SQLite3 serializes all transactions, it's generally a very bad idea to keep a transaction open across event loop ticks anyways.
Transaction functions do not work with async functions. Technically speaking, async functions always return after the first `await`, which means the transaction will already be committed before any async code executes. Also, because SQLite serializes all transactions, it's generally a very bad idea to keep a transaction open across event loop ticks anyways.

It's important to know that SQLite3 may sometimes rollback a transaction without us asking it to. This can happen either because of an [`ON CONFLICT`](https://sqlite.org/lang_conflict.html) clause, the [`RAISE()`](https://www.sqlite.org/lang_createtrigger.html) trigger function, or certain errors such as `SQLITE_FULL` or `SQLITE_BUSY`. In other words, if you catch an SQLite3 error *within* a transaction, you must be aware that any further SQL that you execute might not be within the same transaction. Usually, the best course of action for such cases is to simply re-throw the error, exiting the transaction function.
It's important to know that SQLite may sometimes rollback a transaction without us asking it to. This can happen either because of an [`ON CONFLICT`](https://sqlite.org/lang_conflict.html) clause, the [`RAISE()`](https://www.sqlite.org/lang_createtrigger.html) trigger function, or certain errors such as `SQLITE_FULL` or `SQLITE_BUSY`. In other words, if you catch an SQLite error *within* a transaction, you must be aware that any further SQL that you execute might not be within the same transaction. Usually, the best course of action for such cases is to simply re-throw the error, exiting the transaction function.

```js
try {
Expand All @@ -124,11 +124,11 @@ console.log(db.pragma('cache_size', { simple: true })); // => 32000

If execution of the PRAGMA fails, an `Error` is thrown.

It's better to use this method instead of normal [prepared statements](#preparestring---statement) when executing PRAGMA, because this method normalizes some odd behavior that may otherwise be experienced. The documentation on SQLite3 PRAGMA can be found [here](https://www.sqlite.org/pragma.html).
It's better to use this method instead of normal [prepared statements](#preparestring---statement) when executing PRAGMA, because this method normalizes some odd behavior that may otherwise be experienced. The documentation on SQLite PRAGMA can be found [here](https://www.sqlite.org/pragma.html).

### .backup(*destination*, [*options*]) -> *promise*

Initiates a [backup](https://www.sqlite.org/backup.html) of the database, returning a [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) for when the backup is complete. If the backup fails, the promise will be rejected with an `Error`. You can optionally backup an attached database instead by setting the `attached` option to the name of the desired attached database. A backup file is just a regular SQLite3 database file. It can be opened by [`new Database()`](#new-databasepath-options) just like any SQLite3 database.
Initiates a [backup](https://www.sqlite.org/backup.html) of the database, returning a [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) for when the backup is complete. If the backup fails, the promise will be rejected with an `Error`. You can optionally backup an attached database instead by setting the `attached` option to the name of the desired attached database. A backup file is just a regular SQLite database file. It can be opened by [`new Database()`](#new-databasepath-options) just like any SQLite database.

```js
db.backup(`backup-${Date.now()}.db`)
Expand Down Expand Up @@ -165,7 +165,7 @@ db.backup(`backup-${Date.now()}.db`, {

Returns a [buffer](https://nodejs.org/api/buffer.html#buffer_class_buffer) containing the serialized contents of the database. You can optionally serialize an attached database instead by setting the `attached` option to the name of the desired attached database.

The returned buffer can be written to disk to create a regular SQLite3 database file, or it can be opened directly as an in-memory database by passing it to [`new Database()`](#new-databasepath-options).
The returned buffer can be written to disk to create a regular SQLite database file, or it can be opened directly as an in-memory database by passing it to [`new Database()`](#new-databasepath-options).

```js
const buffer = db.serialize();
Expand All @@ -185,7 +185,7 @@ db.prepare('SELECT add2(?, ?)').pluck().get('foo', 'bar'); // => "foobar"
db.prepare('SELECT add2(?, ?, ?)').pluck().get(12, 4, 18); // => Error: wrong number of arguments
```

By default, user-defined functions have a strict number of arguments (determined by `function.length`). You can register multiple functions of the same name, each with a different number of arguments, causing SQLite3 to execute a different function depending on how many arguments were passed to it. If you register two functions with same name and the same number of arguments, the second registration will erase the first one.
By default, user-defined functions have a strict number of arguments (determined by `function.length`). You can register multiple functions of the same name, each with a different number of arguments, causing SQLite to execute a different function depending on how many arguments were passed to it. If you register two functions with same name and the same number of arguments, the second registration will erase the first one.

If `options.varargs` is `true`, the registered function can accept any number of arguments.

Expand Down Expand Up @@ -231,7 +231,7 @@ db.aggregate('getAverage', {
db.prepare('SELECT getAverage(dollars) FROM expenses').pluck().get(); // => 20.2
```

As shown above, you can use arbitrary JavaScript objects as your aggregation context, as long as a valid SQLite3 value is returned by `result()` in the end. If `step()` doesn't return anything (`undefined`), the aggregate value will not be replaced (be careful of this when using functions that return `undefined` when `null` is desired).
As shown above, you can use arbitrary JavaScript objects as your aggregation context, as long as a valid SQLite value is returned by `result()` in the end. If `step()` doesn't return anything (`undefined`), the aggregate value will not be replaced (be careful of this when using functions that return `undefined` when `null` is desired).

Just like regular [user-defined functions](#functionname-options-function---this), user-defined aggregates can accept multiple arguments. Furthermore, `options.varargs`, `options.directOnly`, and `options.deterministic` [are also](#functionname-options-function---this) accepted.

Expand Down Expand Up @@ -358,17 +358,17 @@ db.exec('CREATE VIRTUAL TABLE my_data USING csv(my_data.csv)');
const allData = db.prepare('SELECT * FROM my_data').all();
```

The factory function will be invoked each time a corresponding `CREATE VIRTUAL TABLE` statement runs. The arguments to the factory function correspond to the module arguments passed in the `CREATE VIRTUAL TABLE` statement; always a list of arbitrary strings separated by commas. It's your responsibility to parse and interpret those module arguments. Note that SQLite3 does not allow [bound parameters](#binding-parameters) inside module arguments.
The factory function will be invoked each time a corresponding `CREATE VIRTUAL TABLE` statement runs. The arguments to the factory function correspond to the module arguments passed in the `CREATE VIRTUAL TABLE` statement; always a list of arbitrary strings separated by commas. It's your responsibility to parse and interpret those module arguments. Note that SQLite does not allow [bound parameters](#binding-parameters) inside module arguments.

Just like [user-defined functions](#functionname-options-function---this) and [user-defined aggregates](#aggregatename-options---this), virtual tables support `options.directOnly`, which prevents the table from being used inside [VIEWs](https://sqlite.org/lang_createview.html), [TRIGGERs](https://sqlite.org/lang_createtrigger.html), or schema structures such as [CHECK constraints](https://www.sqlite.org/lang_createtable.html#ckconst), [DEFAULT clauses](https://www.sqlite.org/lang_createtable.html#dfltval), etc.

> Some [extensions](#loadextensionpath-entrypoint---this) can provide virtual tables that have write capabilities, but `db.table()` is only capable of creating read-only virtual tables, primarily for the purpose of supporting table-valued functions.
### .loadExtension(*path*, [*entryPoint*]) -> *this*

Loads a compiled [SQLite3 extension](https://sqlite.org/loadext.html) and applies it to the current database connection.
Loads a compiled [SQLite extension](https://sqlite.org/loadext.html) and applies it to the current database connection.

It's your responsibility to make sure the extensions you load are compiled/linked against a version of [SQLite3](https://www.sqlite.org/) that is compatible with `better-sqlite3`. Keep in mind that new versions of `better-sqlite3` will periodically use newer versions of [SQLite3](https://www.sqlite.org/). You can see which version is being used [here](./compilation.md#bundled-configuration).
It's your responsibility to make sure the extensions you load are compiled/linked against a version of [SQLite](https://www.sqlite.org/) that is compatible with `better-sqlite3`. Keep in mind that new versions of `better-sqlite3` will periodically use newer versions of [SQLite](https://www.sqlite.org/). You can see which version is being used [here](./compilation.md#bundled-configuration).

```js
db.loadExtension('./my-extensions/compress.so');
Expand Down Expand Up @@ -421,7 +421,7 @@ An object representing a single SQL statement.
- [Statement#bind()](#bindbindparameters---this)
- [Properties](#properties-1)

> NOTE: Statements are [finalized](https://www.sqlite.org/c3ref/finalize.html) when garbage collected so there is no explicit API for it. Statements are also finalized when the associated database is closed.
> NOTE: If you've used the [SQLite C API](https://www.sqlite.org/c3ref), you might except there to be a ["finalize"](https://www.sqlite.org/c3ref/finalize.html) method, but `better-sqlite3` automatically handles this during garbage collection (or when the associated database is closed).
### .run([*...bindParameters*]) -> *object*

Expand Down Expand Up @@ -608,11 +608,11 @@ console.log(cat.name); // => "Joey"

# class *SqliteError*

Whenever an error occurs within SQLite3, a `SqliteError` object will be thrown. `SqliteError` is a subclass of `Error`. Every `SqliteError` object has a `code` property, which is a string matching one of the "extended result codes" defined [here](https://sqlite.org/rescode.html) (for example, `"SQLITE_CONSTRAINT_UNIQUE"`).
Whenever an error occurs within SQLite, a `SqliteError` object will be thrown. `SqliteError` is a subclass of `Error`. Every `SqliteError` object has a `code` property, which is a string matching one of the "extended result codes" defined [here](https://sqlite.org/rescode.html) (for example, `"SQLITE_CONSTRAINT_UNIQUE"`).

If you receive a `SqliteError`, it probably means you're using SQLite3 incorrectly. The error didn't originate in `better-sqlite3`, so it's probably not an issue with `better-sqlite3`. It's recommended that you learn about the meaning of the error [here](https://sqlite.org/rescode.html), and perhaps learn more about how to use SQLite3 by reading [their docs](https://sqlite.org/docs.html).
If you receive a `SqliteError`, it probably means you're using SQLite incorrectly. The error didn't originate in `better-sqlite3`, so it's probably not an issue with `better-sqlite3`. It's recommended that you learn about the meaning of the error [here](https://sqlite.org/rescode.html), and perhaps learn more about how to use SQLite by reading [their docs](https://sqlite.org/docs.html).

> In the unlikely scenario that SQLite3 throws an error that is not recognized by `better-sqlite3` (this would be considered a bug in `better-sqlite3`), the `code` property will be `"UNKNOWN_SQLITE_ERROR_NNNN"`, where `NNNN` is the numeric error code. If this happens to you, please report it as an [issue](https://github.com/JoshuaWise/better-sqlite3/issues).
> In the unlikely scenario that SQLite throws an error that is not recognized by `better-sqlite3` (this would be considered a bug in `better-sqlite3`), the `code` property will be `"UNKNOWN_SQLITE_ERROR_NNNN"`, where `NNNN` is the numeric error code. If this happens to you, please report it as an [issue](https://github.com/JoshuaWise/better-sqlite3/issues).
# Binding Parameters

Expand All @@ -629,7 +629,7 @@ stmt.run(['John', 'Smith', 45]);
stmt.run(['John'], ['Smith', 45]);
```

You can also use named parameters. SQLite3 provides [3 different syntaxes for named parameters](https://www.sqlite.org/lang_expr.html) (`@foo`, `:foo`, and `$foo`), all of which are supported by `better-sqlite3`.
You can also use named parameters. SQLite provides [3 different syntaxes for named parameters](https://www.sqlite.org/lang_expr.html) (`@foo`, `:foo`, and `$foo`), all of which are supported by `better-sqlite3`.

```js
// The following are equivalent.
Expand All @@ -652,9 +652,9 @@ const stmt = db.prepare('INSERT INTO people VALUES (@name, @name, ?)');
stmt.run(45, { name: 'Henry' });
```

Here is how `better-sqlite3` converts values between SQLite3 and JavaScript:
Here is how `better-sqlite3` converts values between SQLite and JavaScript:

|SQLite3|JavaScript|
|SQLite|JavaScript|
|---|---|
|`NULL`|`null`|
|`REAL`|`number`|
Expand Down
Loading

0 comments on commit 084819a

Please sign in to comment.