Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] sqlite: add aggregate function #56600

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions doc/api/sqlite.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,85 @@ added: v22.5.0

Constructs a new `DatabaseSync` instance.

### `database.aggregate(name, options)`

<!-- YAML
added: REPLACEME
-->

Registers a new aggregate function with the SQLite database. This method is a wrapper around
[`sqlite3_create_window_function()`][].

* `name` {string} The name of the SQLite function to create.
* `options` {Object} Function configuration settings.
* `deterministic` {boolean} If `true`, the [`SQLITE_DETERMINISTIC`][] flag is
set on the created function. **Default:** `false`.
* `directOnly` {boolean} If `true`, the [`SQLITE_DIRECTONLY`][] flag is set on
the created function. **Default:** `false`.
* `useBigIntArguments` {boolean} If `true`, integer arguments to `options.step` and `options.inverse`
are converted to `BigInt`s. If `false`, integer arguments are passed as
JavaScript numbers. **Default:** `false`.
* `varargs` {boolean} If `true`, `options.step` and `options.inverse` may be invoked with any number of
arguments (between zero and [`SQLITE_MAX_FUNCTION_ARG`][]). If `false`,
`inverse` and `step` must be invoked with exactly `length` arguments.
**Default:** `false`.
* `start` {number | string | null | Array | Object | Function} The identity
value for the aggregation function. This value is used when the aggregation
function is initialized. When a {Function} is passed the identity will be its return.
* `step` {Function} The function to call for each row in the aggregation. The
function receives the current state and the row value. The return value of
this function should be the new state.
* `result` {Function} The function to call to get the result of the
aggregation. The function receives the final state and should return the
result of the aggregation.
* `inverse` {Function} When this function is provided, the `aggregate` method will work as a window function.
The function receives the current state and the dropped row value. The return value of this function should be the
new state.

**NOTE:** When used as a window function, the `result` function will be called multiple times.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
**NOTE:** When used as a window function, the `result` function will be called multiple times.
When used as a window function, the `result` function will be called multiple times.


```cjs
const { DatabaseSync } = require('node:sqlite');

const db = new DatabaseSync(':memory:');
db.exec(`
CREATE TABLE t3(x, y);
INSERT INTO t3 VALUES('a', 4),
('b', 5),
('c', 3),
('d', 8),
('e', 1);
`);

db.aggregate('sumint', {
start: 0,
step: (acc, value) => acc + value,
});

db.prepare('SELECT sumint(y) as total FROM t3').get(); // { total: 21 }
```

```mjs
import { DatabaseSync } from 'node:sqlite';

const db = new DatabaseSync(':memory:');
db.exec(`
CREATE TABLE t3(x, y);
INSERT INTO t3 VALUES('a', 4),
('b', 5),
('c', 3),
('d', 8),
('e', 1);
`);

db.aggregate('sumint', {
start: 0,
step: (acc, value) => acc + value,
});

db.prepare('SELECT sumint(y) as total FROM t3').get(); // { total: 21 }
```

### `database.close()`

<!-- YAML
Expand Down Expand Up @@ -721,6 +800,7 @@ resolution handler passed to [`database.applyChangeset()`][]. See also
[`sqlite3_column_origin_name()`]: https://www.sqlite.org/c3ref/column_database_name.html
[`sqlite3_column_table_name()`]: https://www.sqlite.org/c3ref/column_database_name.html
[`sqlite3_create_function_v2()`]: https://www.sqlite.org/c3ref/create_function.html
[`sqlite3_create_window_function()`]: https://www.sqlite.org/c3ref/create_function.html
[`sqlite3_exec()`]: https://www.sqlite.org/c3ref/exec.html
[`sqlite3_expanded_sql()`]: https://www.sqlite.org/c3ref/expanded_sql.html
[`sqlite3_last_insert_rowid()`]: https://www.sqlite.org/c3ref/last_insert_rowid.html
Expand Down
4 changes: 4 additions & 0 deletions src/env_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@
V(inputs_string, "inputs") \
V(internal_binding_string, "internalBinding") \
V(internal_string, "internal") \
V(inverse_string, "inverse") \
V(ipv4_string, "IPv4") \
V(ipv6_string, "IPv6") \
V(isclosing_string, "isClosing") \
Expand Down Expand Up @@ -334,6 +335,7 @@
"const __esModule = true;") \
V(require_string, "require") \
V(resource_string, "resource") \
V(result_string, "result") \
V(retry_string, "retry") \
V(return_string, "return") \
V(salt_length_string, "saltLength") \
Expand All @@ -360,12 +362,14 @@
V(specifier_string, "specifier") \
V(stack_string, "stack") \
V(standard_name_string, "standardName") \
V(start_string, "start") \
V(start_time_string, "startTime") \
V(state_string, "state") \
V(statement_string, "statement") \
V(stats_string, "stats") \
V(status_string, "status") \
V(stdio_string, "stdio") \
V(step_string, "step") \
V(stream_average_duration_string, "streamAverageDuration") \
V(stream_count_string, "streamCount") \
V(subject_string, "subject") \
Expand Down
Loading
Loading