nodejs / nodejs/node

sqlite: incremental BLOB I/O via sqlite3_blob_open()

Offen
#65,445 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

sqlite
Vorherrschende Sprache
JavaScript
Sterne
122k
Forks
37.3k
Ø Merge
4 T. 2 Std.
Gemergte PRs (30 T.)
283

Beschreibung

What is the problem this feature will solve?

The public node:sqlite JavaScript API can only read or write a BLOB or TEXT value in full. Reading a 512 MiB value materializes 512 MiB in JavaScript, and there is no API for overwriting part of a value in place.

SQLite has an API for exactly this. sqlite3_blob_open() and the related calls give a handle that reads and writes one value in chunks. node:sqlite owns the sqlite3* connection and does not expose it to JavaScript, so an ordinary userland implementation cannot use the existing connection.

A custom loadable SQLite extension can receive that connection and call the incremental BLOB API, so this is not literally impossible outside core. It does, however, require shipping native code and designing an extension-specific bridge instead of using the public JavaScript API.

What is the feature you are proposing to solve the problem?

database.openBlob(options), returning a BlobHandle with byteLength, read(), write(), reopen(), close(), and [Symbol.dispose].

const { lastInsertRowid } = database
  .prepare('INSERT INTO files (name, data) VALUES (?, zeroblob(?))')
  .run('greeting.txt', 11);

using blob = database.openBlob({
  table: 'files',
  column: 'data',
  row: lastInsertRowid,
});

blob.write(Buffer.from('hello'), { position: 0 });
blob.write(Buffer.from(' world'), { position: 5 });

reopen() moves an existing handle to another row in the same column, which is how SQLite supports reusing a handle across many rows.

The handle cannot resize a value. Writable handles keep SQLite's transaction open until the last one is closed, and close or disposal can therefore report a deferred commit error. Incremental writes modify raw bytes rather than executing an SQL UPDATE: they do not run triggers or re-check constraints, and writing TEXT can create invalid UTF-8. SQLite also disallows virtual tables, tables with generated columns, WITHOUT ROWID tables, and writable handles on certain indexed or foreign-key columns.

The change is additive and wraps the already-bundled SQLite. It adds no new dependency and does not change existing statement behavior.

What alternatives have you considered?

Rewriting or reading the whole value. This is the public API available today. It is simplest for small values, but a partial update still replaces the whole value and reading any range materializes all of it.

A loadable SQLite extension. This can use sqlite3_blob_open() on node:sqlite's existing connection. It avoids a second connection, but requires custom native code and an extension-specific JavaScript/SQL bridge for a facility SQLite already exposes directly.

A second connection from userland. A native addon or another SQLite binding can open the same file and use incremental BLOB I/O while the application keeps using node:sqlite. This is workable, but transaction ownership, snapshots, busy handling, and locking are then split across connections.

Splitting large values across rows. With control of the schema, ordered chunk rows provide bounded-memory reads and logical partial replacement. They do not help with existing or externally produced schemas and are not in-place updates of one SQLite value.

A stream or async API in core. Streams can be composed over the primitive in userland. SQLite's handle and transaction are still synchronous and stateful, so an async API would require a broader worker and connection design rather than simply making these calls non-blocking.

I have a working implementation in draft at #65444, with API documentation, tests, and a one-machine large-value benchmark. I am opening the issue as the first-contributor guide suggests, to check whether there is appetite for the feature and whether the API shape is right before it goes further.

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne mit der bestehenden node:sqlite-API und der funktionierenden Implementierung in Entwurf #65444, einschließlich ihrer API-Dokumentation, Tests und des Benchmarks für große Werte. Vergleiche die vorgeschlagene Form von openBlob und BlobHandle mit dem aktuellen Verbindungsverhalten; abgeschlossen ist die Aufgabe, wenn die API-Form vereinbart und die zugehörige Dokumentation, die Tests und der Benchmark vollständig sind.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
javascript, sqlite
Bereich
databases
Issue-Typ
Feature
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Aktiv
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.