picovolt 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -15
- package/package.json +1 -1
- package/picovolt.d.ts +16 -0
- package/picovolt_bg.js +35 -0
- package/picovolt_bg.wasm +0 -0
- package/sqlite.js +7 -5
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# PicoVolt (PVDB)
|
|
2
2
|
|
|
3
3
|
[](https://github.com/MiniJe/picovolt/actions/workflows/ci.yml)
|
|
4
|
-
[](CHANGELOG.md)
|
|
5
5
|
[](LICENSE)
|
|
6
6
|

|
|
7
7
|
[](https://github.com/MiniJe/picovolt)
|
|
@@ -56,8 +56,9 @@ Linux and Windows. Changes are tracked in [CHANGELOG.md](CHANGELOG.md).
|
|
|
56
56
|
| [`engine/mvcc.rs`](src/engine/mvcc.rs) | transaction clock and snapshot visibility |
|
|
57
57
|
| [`engine/wasm.rs`](src/engine/wasm.rs) | sandboxed `wasmi` extension runtime and the `WasmExec` backend trait |
|
|
58
58
|
| [`engine/interp.rs`](src/engine/interp.rs) | `pv-wasm`: a from-scratch WASM interpreter (integer subset) |
|
|
59
|
-
| [`engine/query.rs`](src/engine/query.rs) | SQL front-end (CREATE/INSERT/UPDATE/DELETE/DROP, `SELECT` with projection, `AS` aliases, `DISTINCT`, aggregates, `GROUP BY`/`HAVING`, `WHERE` predicates incl. `IN`/`BETWEEN`/`IS NULL`/`LIKE`, `BEFORE`, multi-column `ORDER BY`, `LIMIT`) |
|
|
59
|
+
| [`engine/query.rs`](src/engine/query.rs) | SQL front-end (CREATE/INSERT/UPDATE/DELETE/DROP, `SELECT` with projection, `AS` aliases, `DISTINCT`, aggregates, `GROUP BY`/`HAVING`, `WHERE` predicates incl. `IN`/`BETWEEN`/`IS NULL`/`LIKE`, `BEFORE`, multi-column `ORDER BY`, `LIMIT`/`OFFSET`) |
|
|
60
60
|
| [`engine/compliance.rs`](src/engine/compliance.rs) | optional, app-driven usage-policy hook (not a license requirement) |
|
|
61
|
+
| [`enterprise.rs`](src/enterprise.rs) | optional, host-owned audit events and honest capability discovery for fleet integrations |
|
|
61
62
|
| [`db.rs`](src/db.rs) | the `Database` surface that ties it together |
|
|
62
63
|
| [`ffi.rs`](src/ffi.rs) | C ABI (the `capi` feature): a panic-safe, C-callable surface wrapping the engine for Go, Python, and C bindings |
|
|
63
64
|
|
|
@@ -86,6 +87,10 @@ Linux and Windows. Changes are tracked in [CHANGELOG.md](CHANGELOG.md).
|
|
|
86
87
|
each flush `fsync` the data and commit the manifest atomically (write to a temp
|
|
87
88
|
file, `fsync`, then rename). The default `Fast` mode uses the OS cache only:
|
|
88
89
|
fast and durable on a clean exit, but not power-loss-safe.
|
|
90
|
+
- **Crash-recoverable transactions.** Explicit `BEGIN`, `COMMIT`, and
|
|
91
|
+
`ROLLBACK` group filesystem or in-memory writes. Filesystem transactions keep
|
|
92
|
+
a synced rollback image and recovery marker; reopening after interruption
|
|
93
|
+
restores the last committed state before loading the workspace.
|
|
89
94
|
- **Hardened against untrusted input.** Opening a `.pvdb` or workspace, or running
|
|
90
95
|
a WASM module, validates manifest hashes (no path traversal), bounds-checks CAS
|
|
91
96
|
offsets and page chains (no out-of-bounds reads or infinite loops on a crafted
|
|
@@ -113,22 +118,24 @@ cargo run --release --example bench # evaluation harness across modes and wor
|
|
|
113
118
|
```
|
|
114
119
|
|
|
115
120
|
Install the first-class CLI with `cargo install picovolt`, then use `pv query`,
|
|
116
|
-
`pv inspect`, `pv import`, `pv export`, and `pv bake`. Copyable
|
|
117
|
-
and browser projects are in [`starters/`](starters/README.md); supported adapters
|
|
121
|
+
`pv inspect`, `pv history`, `pv import`, `pv export`, and `pv bake`. Copyable
|
|
122
|
+
Rust, Python, Go, Node, and browser projects are in [`starters/`](starters/README.md); supported adapters
|
|
118
123
|
are catalogued in [`docs/INTEGRATIONS.md`](docs/INTEGRATIONS.md).
|
|
119
124
|
|
|
120
|
-
SQL supported: `CREATE TABLE` with `PRIMARY KEY`, `UNIQUE`, and `NOT NULL`,
|
|
121
|
-
`CREATE [UNIQUE] INDEX ON t (col)`, `INSERT`,
|
|
122
|
-
`UPDATE ... SET ... WHERE`, `DELETE ... WHERE`, `DROP TABLE`, and
|
|
125
|
+
SQL supported: `CREATE TABLE [IF NOT EXISTS]` with `PRIMARY KEY`, `UNIQUE`, and `NOT NULL`,
|
|
126
|
+
`CREATE [UNIQUE] INDEX ON t (col)`, single- and multi-row `INSERT`,
|
|
127
|
+
`UPDATE ... SET ... WHERE`, `DELETE ... WHERE`, `DROP TABLE [IF EXISTS]`, and
|
|
123
128
|
`SELECT [DISTINCT] {* | col [AS alias], ... | COUNT/SUM/MIN/MAX/AVG(...) [AS alias]}
|
|
124
129
|
FROM t [WHERE <pred>] [GROUP BY cols] [HAVING <pred>] [BEFORE tx]
|
|
125
|
-
[ORDER BY col [ASC|DESC], ...] [LIMIT n]`, where `<pred>` combines
|
|
130
|
+
[ORDER BY col [ASC|DESC], ...] [LIMIT n] [OFFSET n]`, where `<pred>` combines
|
|
126
131
|
`col <op> value` (`=`, `!=`, `<`, `<=`, `>`, `>=`, `LIKE`, `NOT LIKE`),
|
|
127
132
|
`col [NOT] IN (...)`, `col [NOT] BETWEEN a AND b`, and `col IS [NOT] NULL` with
|
|
128
133
|
`AND`, `OR`, and parentheses. Integer and decimal values compare by magnitude.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
134
|
+
Two-table equality `INNER`/`LEFT JOIN` queries support qualified references,
|
|
135
|
+
projection, aliases, `DISTINCT`, filters, ordering, and pagination. Rust callers
|
|
136
|
+
can cache `Database::prepare(...)` templates and use explicit transaction
|
|
137
|
+
lifecycle methods or atomic `Database::transaction(...)` closures with both
|
|
138
|
+
filesystem and in-memory databases.
|
|
132
139
|
Durability is selectable via `Database::set_durability` (`Fast` OS-cache default,
|
|
133
140
|
or crash-safe `Sync` with fsync and an atomic manifest).
|
|
134
141
|
|
|
@@ -139,8 +146,9 @@ around 33k rows/s, linear), larger-than-RAM reads through a bounded buffer pool
|
|
|
139
146
|
lookups roughly 11,000 times faster than a scan, plus range predicates), MVCC
|
|
140
147
|
time-travel, opt-in crash-safe durability (`Durability::Sync`), and a fast
|
|
141
148
|
compile-and-publish path (CAS dedup, columnar compression, memory-mappable
|
|
142
|
-
single-file artifacts). Current limits include
|
|
143
|
-
|
|
149
|
+
single-file artifacts). Current limits include full-workspace transaction
|
|
150
|
+
backups rather than an incremental WAL, only basic two-table equality joins,
|
|
151
|
+
and no concurrent writers.
|
|
144
152
|
|
|
145
153
|
## Install and distribution
|
|
146
154
|
|
|
@@ -148,7 +156,7 @@ transactions, only basic two-table equality joins, and no concurrent writers.
|
|
|
148
156
|
|--------|-----|
|
|
149
157
|
| **Rust** (crates.io) | `cargo add picovolt` |
|
|
150
158
|
| **JavaScript / npm** (WebAssembly, browser and Node) | `npm install picovolt` |
|
|
151
|
-
| **Python** (native wheels) | `python -m pip install picovolt`
|
|
159
|
+
| **Python** (native wheels) | `python -m pip install picovolt` |
|
|
152
160
|
| **C / Go** (native, via the C ABI) | `cargo build --release --features capi`, then see [`bindings/`](bindings) |
|
|
153
161
|
| **In-memory** (native, no filesystem) | `Database::open_memory()`, export with `bake_to_bytes()` |
|
|
154
162
|
|
|
@@ -171,7 +179,8 @@ JavaScript API (`import Database from "picovolt/sqlite"`), a Python DB-API 2.0
|
|
|
171
179
|
module (`import picovolt.dbapi2 as sqlite`), and the Go `database/sql` driver
|
|
172
180
|
([`bindings/go/pvsql`](bindings/go/pvsql)). Shared limits include positional `?`
|
|
173
181
|
only and the intentionally compact SQL grammar; JavaScript and in-memory Rust
|
|
174
|
-
also expose rollback-capable transaction wrappers.
|
|
182
|
+
also expose rollback-capable transaction wrappers. Native bindings expose the
|
|
183
|
+
same transaction lifecycle through the C ABI.
|
|
175
184
|
|
|
176
185
|
## Server mode
|
|
177
186
|
|
|
@@ -196,6 +205,11 @@ result rows, and response size are bounded. TLS is not built in, so network
|
|
|
196
205
|
deployments still belong behind a TLS-terminating reverse proxy. See
|
|
197
206
|
[src/bin/server.rs](src/bin/server.rs).
|
|
198
207
|
|
|
208
|
+
The HTTP API is sessionless, so each request is an atomic statement and explicit
|
|
209
|
+
transaction-control statements are rejected. Applications needing a
|
|
210
|
+
multi-statement transaction should use an embedded language binding, where the
|
|
211
|
+
transaction belongs to one database handle.
|
|
212
|
+
|
|
199
213
|
Applications accepting SQL from users can also call `Database::query_with_limits`
|
|
200
214
|
directly and choose their own scan, result, memory, and deadline budgets.
|
|
201
215
|
|
|
@@ -211,6 +225,9 @@ native modules built on the public API. Both are documented in
|
|
|
211
225
|
|--|--|
|
|
212
226
|
| Roadmap | [ROADMAP.md](ROADMAP.md) |
|
|
213
227
|
| One-million-download plan | [docs/ROADMAP_1M_DOWNLOADS.md](docs/ROADMAP_1M_DOWNLOADS.md) |
|
|
228
|
+
| Monetization thesis | [docs/MONETIZATION.md](docs/MONETIZATION.md) |
|
|
229
|
+
| Enterprise integration foundation | [docs/ENTERPRISE.md](docs/ENTERPRISE.md) |
|
|
230
|
+
| Platform and file support | [docs/SUPPORT.md](docs/SUPPORT.md) |
|
|
214
231
|
| Contributing | [CONTRIBUTING.md](CONTRIBUTING.md) |
|
|
215
232
|
| Code of conduct | [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) |
|
|
216
233
|
| Changelog | [CHANGELOG.md](CHANGELOG.md) |
|
package/package.json
CHANGED
package/picovolt.d.ts
CHANGED
|
@@ -7,6 +7,14 @@
|
|
|
7
7
|
export class Db {
|
|
8
8
|
free(): void;
|
|
9
9
|
[Symbol.dispose](): void;
|
|
10
|
+
/**
|
|
11
|
+
* Begin an explicit multi-statement in-memory transaction.
|
|
12
|
+
*/
|
|
13
|
+
beginTransaction(): void;
|
|
14
|
+
/**
|
|
15
|
+
* Commit the active transaction.
|
|
16
|
+
*/
|
|
17
|
+
commitTransaction(): void;
|
|
10
18
|
/**
|
|
11
19
|
* The most recently committed transaction id, the upper bound for a
|
|
12
20
|
* `... BEFORE tx` time-travel query.
|
|
@@ -21,6 +29,10 @@ export class Db {
|
|
|
21
29
|
* [`export`](Db::export)). Writable, with full time-travel history intact.
|
|
22
30
|
*/
|
|
23
31
|
static fromBytes(bytes: Uint8Array): Db;
|
|
32
|
+
/**
|
|
33
|
+
* Whether an explicit transaction is active.
|
|
34
|
+
*/
|
|
35
|
+
inTransaction(): boolean;
|
|
24
36
|
/**
|
|
25
37
|
* Create a new, empty in-memory database.
|
|
26
38
|
*/
|
|
@@ -40,6 +52,10 @@ export class Db {
|
|
|
40
52
|
* `{"done":true}` otherwise. Throws the error message (a string) on failure.
|
|
41
53
|
*/
|
|
42
54
|
query(sql: string, params: any): string;
|
|
55
|
+
/**
|
|
56
|
+
* Roll back the active transaction.
|
|
57
|
+
*/
|
|
58
|
+
rollbackTransaction(): void;
|
|
43
59
|
/**
|
|
44
60
|
* A JSON array of the table names in this database (for introspecting an
|
|
45
61
|
* uploaded `.pvdb` whose schema is unknown).
|
package/picovolt_bg.js
CHANGED
|
@@ -18,6 +18,24 @@ export class Db {
|
|
|
18
18
|
const ptr = this.__destroy_into_raw();
|
|
19
19
|
wasm.__wbg_db_free(ptr, 0);
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Begin an explicit multi-statement in-memory transaction.
|
|
23
|
+
*/
|
|
24
|
+
beginTransaction() {
|
|
25
|
+
const ret = wasm.db_beginTransaction(this.__wbg_ptr);
|
|
26
|
+
if (ret[1]) {
|
|
27
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Commit the active transaction.
|
|
32
|
+
*/
|
|
33
|
+
commitTransaction() {
|
|
34
|
+
const ret = wasm.db_commitTransaction(this.__wbg_ptr);
|
|
35
|
+
if (ret[1]) {
|
|
36
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
21
39
|
/**
|
|
22
40
|
* The most recently committed transaction id, the upper bound for a
|
|
23
41
|
* `... BEFORE tx` time-travel query.
|
|
@@ -55,6 +73,14 @@ export class Db {
|
|
|
55
73
|
}
|
|
56
74
|
return Db.__wrap(ret[0]);
|
|
57
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Whether an explicit transaction is active.
|
|
78
|
+
* @returns {boolean}
|
|
79
|
+
*/
|
|
80
|
+
inTransaction() {
|
|
81
|
+
const ret = wasm.db_inTransaction(this.__wbg_ptr);
|
|
82
|
+
return ret !== 0;
|
|
83
|
+
}
|
|
58
84
|
/**
|
|
59
85
|
* Create a new, empty in-memory database.
|
|
60
86
|
*/
|
|
@@ -110,6 +136,15 @@ export class Db {
|
|
|
110
136
|
wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
|
|
111
137
|
}
|
|
112
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Roll back the active transaction.
|
|
141
|
+
*/
|
|
142
|
+
rollbackTransaction() {
|
|
143
|
+
const ret = wasm.db_rollbackTransaction(this.__wbg_ptr);
|
|
144
|
+
if (ret[1]) {
|
|
145
|
+
throw takeFromExternrefTable0(ret[0]);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
113
148
|
/**
|
|
114
149
|
* A JSON array of the table names in this database (for introspecting an
|
|
115
150
|
* uploaded `.pvdb` whose schema is unknown).
|
package/picovolt_bg.wasm
CHANGED
|
Binary file
|
package/sqlite.js
CHANGED
|
@@ -94,19 +94,21 @@ class Database {
|
|
|
94
94
|
throw new Error("picovolt: pragma is not supported");
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
// Wrap a synchronous callback in an
|
|
98
|
-
//
|
|
97
|
+
// Wrap a synchronous callback in an engine transaction, matching
|
|
98
|
+
// better-sqlite3's common pattern.
|
|
99
99
|
transaction(fn) {
|
|
100
100
|
if (typeof fn !== "function") throw new TypeError("transaction expects a function");
|
|
101
101
|
const db = this;
|
|
102
102
|
function wrapped(...args) {
|
|
103
103
|
if (db._inTransaction) return fn(...args);
|
|
104
|
-
|
|
104
|
+
db._db.beginTransaction();
|
|
105
105
|
db._inTransaction = true;
|
|
106
106
|
try {
|
|
107
|
-
|
|
107
|
+
const value = fn(...args);
|
|
108
|
+
db._db.commitTransaction();
|
|
109
|
+
return value;
|
|
108
110
|
} catch (error) {
|
|
109
|
-
db._db
|
|
111
|
+
if (db._db.inTransaction()) db._db.rollbackTransaction();
|
|
110
112
|
throw error;
|
|
111
113
|
} finally {
|
|
112
114
|
db._inTransaction = false;
|