UNPKG

@worker-tools/deno-kv-storage

Version:

An implementation of the StorageArea (1,2,3) interface for Deno with an extensible system for supporting various database backends.

196 lines 6.53 kB
import { getStr } from "./wasm.js"; import { Status, Types, Values } from "./constants.js"; import SqliteError from "./error.js"; import { RowObjects } from "./row_objects.js"; export class Rows { /** * Rows * * Rows represent a set of results from a query. * They are iterable and yield arrays with * the data from the selected columns. * * This class is not exported from the module * and the only correct way to obtain a `Rows` * object is by making a database query. */ constructor(wasm, stmt, cleanup) { Object.defineProperty(this, "_wasm", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_stmt", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_cleanup", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "_done", { enumerable: true, configurable: true, writable: true, value: void 0 }); this._wasm = wasm; this._stmt = stmt; this._done = false; // if this is set, the Rows object will finalize the statement and remove it from the given set this._cleanup = cleanup; if (wasm == null) { this._done = true; } } /** * Rows.return * * Implements the closing iterator * protocol. See also: * https://exploringjs.com/es6/ch_iteration.html#sec_closing-iterators */ return() { if (!this._done) { // Release transaction slot, if cleanup is // the responsibility of this Rows object if (this._cleanup != null) { this._wasm.finalize(this._stmt); this._cleanup.delete(this._stmt); } this._done = true; } return { done: true, value: null }; } /** * Rows.done * * Deprecated, prefer `Rows.return`. */ done() { this.return(); } /** * Rows.next * * Implements the iterator protocol. */ next() { if (this._done) return { value: null, done: true }; // Load row data and advance statement const row = this._get(); const status = this._wasm.step(this._stmt); switch (status) { case Status.SqliteRow: // NO OP break; case Status.SqliteDone: this.return(); break; default: this.return(); throw new SqliteError(this._wasm, status); } return { value: row, done: false }; } /** * Rows.columns * * Call this if you need column names from the result of a select query. * * This method returns an array of objects, where each object has the following properties: * * | Property | Value | * |--------------|--------------------------------------------| * | `name` | the result of `sqlite3_column_name` | * | `originName` | the result of `sqlite3_column_origin_name` | * | `tableName` | the result of `sqlite3_column_table_name` | */ columns() { if (this._done) { throw new SqliteError("Unable to retrieve column names as Rows already returned."); } const columnCount = this._wasm.column_count(this._stmt); const columns = []; for (let i = 0; i < columnCount; i++) { const name = getStr(this._wasm, this._wasm.column_name(this._stmt, i)); const originName = getStr(this._wasm, this._wasm.column_origin_name(this._stmt, i)); const tableName = getStr(this._wasm, this._wasm.column_table_name(this._stmt, i)); columns.push({ name, originName, tableName }); } return columns; } /** * Rows.asObjects * * Call this if you need to ouput the rows as objects. * * const rows = [...db.query("SELECT name FROM users;").asObjects()]; */ asObjects() { return new RowObjects(this); } [Symbol.iterator]() { return this; } _get() { // Get results from row const row = []; // return row; for (let i = 0, c = this._wasm.column_count(this._stmt); i < c; i++) { switch (this._wasm.column_type(this._stmt, i)) { case Types.Integer: row.push(this._wasm.column_int(this._stmt, i)); break; case Types.Float: row.push(this._wasm.column_double(this._stmt, i)); break; case Types.Text: row.push(getStr(this._wasm, this._wasm.column_text(this._stmt, i))); break; case Types.Blob: { const ptr = this._wasm.column_blob(this._stmt, i); if (ptr === 0) { // Zero pointer results in null row.push(null); } else { const length = this._wasm.column_bytes(this._stmt, i); // Slice should copy the bytes, as it makes a shallow copy row.push(new Uint8Array(this._wasm.memory.buffer, ptr, length).slice()); } break; } case Types.BigInteger: { const ptr = this._wasm.column_text(this._stmt, i); row.push(BigInt(getStr(this._wasm, ptr))); break; } default: // TODO: Differentiate between NULL and not-recognized? row.push(null); break; } } return row; } } /** * Empty * * A special constant. This is a `Rows` object * which has no results. It is still iterable, * however it won't yield any results. * * `Empty` is returned from queries which return * no data. */ export const Empty = new Rows(null, Values.Null); Empty._done = true; // TODO(dyedgreen): This is yikes... //# sourceMappingURL=rows.js.map