@lancedb/lancedb 0.39.0-beta.1 → 0.39.0-beta.10
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/dist/arrow.d.ts +17 -1
- package/dist/arrow.js +100 -3
- package/dist/blob.d.ts +92 -0
- package/dist/blob.js +165 -0
- package/dist/connection.d.ts +35 -27
- package/dist/connection.js +11 -15
- package/dist/index.d.ts +6 -3
- package/dist/index.js +9 -2
- package/dist/indices.d.ts +3 -3
- package/dist/job.d.ts +93 -0
- package/dist/job.js +163 -0
- package/dist/materialized_view.d.ts +3 -1
- package/dist/materialized_view.js +10 -4
- package/dist/merge.d.ts +1 -1
- package/dist/merge.js +1 -1
- package/dist/native.d.ts +177 -36
- package/dist/native.js +54 -52
- package/dist/oauth.d.ts +171 -0
- package/dist/oauth.js +70 -1
- package/dist/sanitize.js +1 -1
- package/dist/table.d.ts +41 -12
- package/dist/table.js +39 -25
- package/package.json +10 -10
- package/pnpm-workspace.yaml +38 -0
package/dist/arrow.d.ts
CHANGED
|
@@ -14,6 +14,22 @@ export type FieldLike = Field | {
|
|
|
14
14
|
nullable: boolean;
|
|
15
15
|
metadata?: Map<string, string>;
|
|
16
16
|
};
|
|
17
|
+
/**
|
|
18
|
+
* Create an Arrow field backed by LanceDB's JSON extension type.
|
|
19
|
+
*
|
|
20
|
+
* @param name - The field name.
|
|
21
|
+
* @param nullable - Whether the field accepts null values.
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { connect, makeJsonField } from "@lancedb/lancedb";
|
|
25
|
+
* import { Schema } from "apache-arrow";
|
|
26
|
+
*
|
|
27
|
+
* const schema = new Schema([makeJsonField("metadata")]);
|
|
28
|
+
* const db = await connect("/path/to/database");
|
|
29
|
+
* await db.createTable("items", [{ metadata: '{"source":"api"}' }], { schema });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function makeJsonField(name: string, nullable?: boolean): Field;
|
|
17
33
|
export type DataLike = import("apache-arrow").Data | {
|
|
18
34
|
type: any;
|
|
19
35
|
length: number;
|
|
@@ -208,7 +224,7 @@ export declare function makeEmptyTable(schema: SchemaLike, metadata?: Map<string
|
|
|
208
224
|
* customized by the `embeddingDataType` property of the embedding function.
|
|
209
225
|
*
|
|
210
226
|
* If a schema is provided in `makeTableOptions` then it should include the
|
|
211
|
-
* embedding columns. If no schema is
|
|
227
|
+
* embedding columns. If no schema is provided then embedding columns will
|
|
212
228
|
* be placed at the end of the table, after all of the input columns.
|
|
213
229
|
*/
|
|
214
230
|
export declare function convertToTable(data: Array<Record<string, unknown>>, embeddings?: EmbeddingFunctionConfig, makeTableOptions?: Partial<MakeArrowTableOptions>): Promise<ArrowTable>;
|
package/dist/arrow.js
CHANGED
|
@@ -17,6 +17,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
17
17
|
};
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.MakeArrowTableOptions = exports.VectorColumnOptions = void 0;
|
|
20
|
+
exports.makeJsonField = makeJsonField;
|
|
20
21
|
exports.isMultiVector = isMultiVector;
|
|
21
22
|
exports.isIntoVector = isIntoVector;
|
|
22
23
|
exports.extractVectorBuffer = extractVectorBuffer;
|
|
@@ -57,10 +58,29 @@ exports.ensureNestedFieldsExist = ensureNestedFieldsExist;
|
|
|
57
58
|
exports.dataTypeToJson = dataTypeToJson;
|
|
58
59
|
const apache_arrow_1 = require("apache-arrow");
|
|
59
60
|
const arrow_type_1 = require("./arrow_type");
|
|
61
|
+
const blob_1 = require("./blob");
|
|
60
62
|
const registry_1 = require("./embedding/registry");
|
|
61
63
|
const sanitize_1 = require("./sanitize");
|
|
62
64
|
const schema_1 = require("./schema");
|
|
63
65
|
__exportStar(require("apache-arrow"), exports);
|
|
66
|
+
/**
|
|
67
|
+
* Create an Arrow field backed by LanceDB's JSON extension type.
|
|
68
|
+
*
|
|
69
|
+
* @param name - The field name.
|
|
70
|
+
* @param nullable - Whether the field accepts null values.
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* import { connect, makeJsonField } from "@lancedb/lancedb";
|
|
74
|
+
* import { Schema } from "apache-arrow";
|
|
75
|
+
*
|
|
76
|
+
* const schema = new Schema([makeJsonField("metadata")]);
|
|
77
|
+
* const db = await connect("/path/to/database");
|
|
78
|
+
* await db.createTable("items", [{ metadata: '{"source":"api"}' }], { schema });
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
function makeJsonField(name, nullable = true) {
|
|
82
|
+
return new apache_arrow_1.Field(name, new apache_arrow_1.Utf8(), nullable, new Map([["ARROW:extension:name", "arrow.json"]]));
|
|
83
|
+
}
|
|
64
84
|
function isMultiVector(value) {
|
|
65
85
|
return Array.isArray(value) && isIntoVector(value[0]);
|
|
66
86
|
}
|
|
@@ -348,17 +368,39 @@ function makeArrowTable(data, options, metadata) {
|
|
|
348
368
|
}
|
|
349
369
|
else {
|
|
350
370
|
schema = new apache_arrow_1.Schema(schema.fields, schemaMetadata);
|
|
371
|
+
validateBlobSchema(schema);
|
|
351
372
|
return new apache_arrow_1.Table(schema);
|
|
352
373
|
}
|
|
353
374
|
}
|
|
354
375
|
let inferredSchema = (0, schema_1.inferSchema)(data, schema, opt);
|
|
355
376
|
inferredSchema = new apache_arrow_1.Schema(inferredSchema.fields, schemaMetadata);
|
|
377
|
+
validateBlobSchema(inferredSchema);
|
|
356
378
|
const finalColumns = {};
|
|
357
379
|
for (const field of inferredSchema.fields) {
|
|
358
380
|
finalColumns[field.name] = transposeData(data, field);
|
|
359
381
|
}
|
|
360
382
|
return new apache_arrow_1.Table(inferredSchema, finalColumns);
|
|
361
383
|
}
|
|
384
|
+
function validateBlobSchema(schema) {
|
|
385
|
+
for (const field of schema.fields) {
|
|
386
|
+
validateBlobField(field);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
function validateBlobField(field) {
|
|
390
|
+
if (isFixedSizeList(field.type) &&
|
|
391
|
+
containsBlobField(field.type.children[0])) {
|
|
392
|
+
throw new Error("Blob fields inside FixedSizeList are not supported. Use List instead.");
|
|
393
|
+
}
|
|
394
|
+
for (const child of field.type.children ?? []) {
|
|
395
|
+
validateBlobField(child);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
function containsBlobField(field) {
|
|
399
|
+
if ((0, blob_1.isBlobField)(field)) {
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
return (field.type.children ?? []).some((child) => containsBlobField(child));
|
|
403
|
+
}
|
|
362
404
|
function isObject(value) {
|
|
363
405
|
return (typeof value === "object" &&
|
|
364
406
|
value !== null &&
|
|
@@ -387,6 +429,27 @@ function valueAtPath(datum, path) {
|
|
|
387
429
|
}
|
|
388
430
|
function transposeData(data, field, path = []) {
|
|
389
431
|
const valuesPath = [...path, field.name];
|
|
432
|
+
if ((0, blob_1.isBlobField)(field) && field.type instanceof apache_arrow_1.Struct) {
|
|
433
|
+
const blobRows = data.map((datum) => (0, blob_1.coerceBlobValue)(valueAtPath(datum, valuesPath)));
|
|
434
|
+
const childVectors = field.type.children.map((child) => {
|
|
435
|
+
const values = blobRows.map((row) => row == null ? null : (row[child.name] ?? null));
|
|
436
|
+
return makeVector(values, child.type, undefined, child.nullable);
|
|
437
|
+
});
|
|
438
|
+
const nullCount = blobRows.filter((row) => row === null).length;
|
|
439
|
+
const structData = (0, apache_arrow_1.makeData)({
|
|
440
|
+
type: field.type,
|
|
441
|
+
length: blobRows.length,
|
|
442
|
+
nullCount,
|
|
443
|
+
nullBitmap: nullCount > 0
|
|
444
|
+
? apache_arrow_1.util.packBools(blobRows.map((row) => row !== null))
|
|
445
|
+
: undefined,
|
|
446
|
+
children: childVectors.map((v) => v.data[0]),
|
|
447
|
+
});
|
|
448
|
+
return (0, apache_arrow_1.makeVector)(structData);
|
|
449
|
+
}
|
|
450
|
+
if (isList(field.type) && containsBlobField(field.type.children[0])) {
|
|
451
|
+
return transposeListData(data, field, valuesPath);
|
|
452
|
+
}
|
|
390
453
|
const values = data.map((datum) => valueAtPath(datum, valuesPath));
|
|
391
454
|
if (field.type instanceof apache_arrow_1.Struct) {
|
|
392
455
|
const childFields = field.type.children;
|
|
@@ -401,7 +464,7 @@ function transposeData(data, field, path = []) {
|
|
|
401
464
|
nullBitmap: nullCount > 0
|
|
402
465
|
? apache_arrow_1.util.packBools(values.map((value) => value !== null))
|
|
403
466
|
: undefined,
|
|
404
|
-
children: childVectors,
|
|
467
|
+
children: childVectors.map((v) => v.data[0]),
|
|
405
468
|
});
|
|
406
469
|
return (0, apache_arrow_1.makeVector)(structData);
|
|
407
470
|
}
|
|
@@ -409,6 +472,39 @@ function transposeData(data, field, path = []) {
|
|
|
409
472
|
return makeVector(values, field.type, undefined, field.nullable);
|
|
410
473
|
}
|
|
411
474
|
}
|
|
475
|
+
function transposeListData(data, field, valuesPath) {
|
|
476
|
+
const listType = field.type;
|
|
477
|
+
const childField = listType.children[0];
|
|
478
|
+
const lists = data.map((datum) => valueAtPath(datum, valuesPath));
|
|
479
|
+
const flattened = [];
|
|
480
|
+
const validity = [];
|
|
481
|
+
const offsets = [0];
|
|
482
|
+
for (const list of lists) {
|
|
483
|
+
if (list == null) {
|
|
484
|
+
validity.push(false);
|
|
485
|
+
offsets.push(flattened.length);
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
if (!Array.isArray(list)) {
|
|
489
|
+
throw new Error(`expected an array for list field '${field.name}'`);
|
|
490
|
+
}
|
|
491
|
+
validity.push(true);
|
|
492
|
+
for (const element of list) {
|
|
493
|
+
flattened.push({ [childField.name]: element });
|
|
494
|
+
}
|
|
495
|
+
offsets.push(flattened.length);
|
|
496
|
+
}
|
|
497
|
+
const childVector = transposeData(flattened, childField, []);
|
|
498
|
+
const nullCount = validity.filter((valid) => !valid).length;
|
|
499
|
+
return (0, apache_arrow_1.makeVector)((0, apache_arrow_1.makeData)({
|
|
500
|
+
type: listType,
|
|
501
|
+
length: lists.length,
|
|
502
|
+
nullCount,
|
|
503
|
+
nullBitmap: nullCount > 0 ? apache_arrow_1.util.packBools(validity) : undefined,
|
|
504
|
+
valueOffsets: Int32Array.from(offsets),
|
|
505
|
+
child: childVector.data[0],
|
|
506
|
+
}));
|
|
507
|
+
}
|
|
412
508
|
/**
|
|
413
509
|
* Create an empty Arrow table with the provided schema
|
|
414
510
|
*/
|
|
@@ -497,7 +593,7 @@ function makeVector(values, type, stringAsDictionary, nullable) {
|
|
|
497
593
|
return vectorFromArray(values, type);
|
|
498
594
|
}
|
|
499
595
|
if (values.length === 0) {
|
|
500
|
-
throw Error("makeVector requires at least one value or the type must be
|
|
596
|
+
throw Error("makeVector requires at least one value or the type must be specified");
|
|
501
597
|
}
|
|
502
598
|
const sampleValue = values.find((val) => val !== null && val !== undefined);
|
|
503
599
|
if (sampleValue === undefined) {
|
|
@@ -688,7 +784,7 @@ async function applyEmbeddings(table, embeddings, schema) {
|
|
|
688
784
|
* customized by the `embeddingDataType` property of the embedding function.
|
|
689
785
|
*
|
|
690
786
|
* If a schema is provided in `makeTableOptions` then it should include the
|
|
691
|
-
* embedding columns. If no schema is
|
|
787
|
+
* embedding columns. If no schema is provided then embedding columns will
|
|
692
788
|
* be placed at the end of the table, after all of the input columns.
|
|
693
789
|
*/
|
|
694
790
|
async function convertToTable(data, embeddings, makeTableOptions) {
|
|
@@ -752,6 +848,7 @@ async function fromTableToBuffer(table, embeddings, schema) {
|
|
|
752
848
|
schema = (0, sanitize_1.sanitizeSchema)(schema);
|
|
753
849
|
}
|
|
754
850
|
const tableWithEmbeddings = await applyEmbeddings(table, embeddings, schema);
|
|
851
|
+
validateBlobSchema(tableWithEmbeddings.schema);
|
|
755
852
|
const writer = apache_arrow_1.RecordBatchFileWriter.writeAll(tableWithEmbeddings);
|
|
756
853
|
return Buffer.from(await writer.toUint8Array());
|
|
757
854
|
}
|
package/dist/blob.d.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Field } from "apache-arrow";
|
|
2
|
+
import { BlobFile as NativeBlobFile } from "./native";
|
|
3
|
+
export type BlobInput = {
|
|
4
|
+
data: Buffer | Uint8Array | null;
|
|
5
|
+
uri: string | null;
|
|
6
|
+
};
|
|
7
|
+
export type BlobOptions = {
|
|
8
|
+
/** Defaults to true. */
|
|
9
|
+
nullable?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Max payload bytes kept inline in the data file. Zero is allowed. Must be a
|
|
12
|
+
* safe integer.
|
|
13
|
+
*/
|
|
14
|
+
inlineSizeThreshold?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Max payload bytes stored in a packed sidecar before a dedicated file. Must
|
|
17
|
+
* be a positive safe integer.
|
|
18
|
+
*/
|
|
19
|
+
dedicatedSizeThreshold?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Max bytes in one packed sidecar before starting another. Must be a positive
|
|
22
|
+
* safe integer.
|
|
23
|
+
*/
|
|
24
|
+
packFileSizeThreshold?: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Declares a `lance.blob.v2` column.
|
|
28
|
+
*
|
|
29
|
+
* Query results are descriptors, not payload bytes. Use {@link Table.fetchBlobs}
|
|
30
|
+
* or {@link Table.fetchBlobFiles} to read bytes.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* import { readFile } from "node:fs/promises";
|
|
35
|
+
* import { Field, Int64, Schema } from "apache-arrow";
|
|
36
|
+
* import { blob, connect } from "@lancedb/lancedb";
|
|
37
|
+
*
|
|
38
|
+
* const db = await connect("./data");
|
|
39
|
+
* const video = await readFile("clip.mp4");
|
|
40
|
+
* const table = await db.createTable(
|
|
41
|
+
* "videos",
|
|
42
|
+
* [{ id: 1n, video }],
|
|
43
|
+
* {
|
|
44
|
+
* schema: new Schema([
|
|
45
|
+
* new Field("id", new Int64()),
|
|
46
|
+
* blob("video"),
|
|
47
|
+
* ]),
|
|
48
|
+
* },
|
|
49
|
+
* );
|
|
50
|
+
*
|
|
51
|
+
* const rows = await table.query().select(["id"]).withRowId().toArray();
|
|
52
|
+
* const rowIds = rows.map((row) => row._rowid as bigint);
|
|
53
|
+
* const bytes = await table.fetchBlobs("video", rowIds);
|
|
54
|
+
*
|
|
55
|
+
* const [handle] = await table.fetchBlobFiles("video", rowIds);
|
|
56
|
+
* const size = handle!.size();
|
|
57
|
+
* const header = await handle!.readRange(0n, size < 65536n ? size : 65536n);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function blob(name: string, options?: BlobOptions): Field;
|
|
61
|
+
/**
|
|
62
|
+
* Checks for the `lance.blob.v2` extension marker. Does not validate the
|
|
63
|
+
* field's storage type.
|
|
64
|
+
*/
|
|
65
|
+
export declare function isBlobField(field: Field): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* A lazy handle to blob bytes. Create one with {@link Table.fetchBlobFiles}.
|
|
68
|
+
*
|
|
69
|
+
* @hideconstructor
|
|
70
|
+
*/
|
|
71
|
+
export declare class BlobFile {
|
|
72
|
+
private readonly inner;
|
|
73
|
+
private constructor();
|
|
74
|
+
/** @ignore */
|
|
75
|
+
static fromNative(inner: NativeBlobFile): BlobFile;
|
|
76
|
+
/** Returns the blob size in bytes. */
|
|
77
|
+
size(): bigint;
|
|
78
|
+
/**
|
|
79
|
+
* Reads from the cursor to the end and advances the cursor.
|
|
80
|
+
*
|
|
81
|
+
* A second call returns an empty buffer. {@link BlobFile.readRange} does
|
|
82
|
+
* not move the cursor.
|
|
83
|
+
*/
|
|
84
|
+
read(): Promise<Buffer>;
|
|
85
|
+
/**
|
|
86
|
+
* Reads the half-open byte range `[start, end)`.
|
|
87
|
+
*
|
|
88
|
+
* Fails when `end` is past the blob size. Does not move the cursor.
|
|
89
|
+
*/
|
|
90
|
+
readRange(start: bigint, end: bigint): Promise<Buffer>;
|
|
91
|
+
}
|
|
92
|
+
export declare function coerceBlobValue(value: unknown): BlobInput | null;
|
package/dist/blob.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
// SPDX-FileCopyrightText: Copyright The LanceDB Authors
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.BlobFile = void 0;
|
|
6
|
+
exports.blob = blob;
|
|
7
|
+
exports.isBlobField = isBlobField;
|
|
8
|
+
exports.coerceBlobValue = coerceBlobValue;
|
|
9
|
+
const apache_arrow_1 = require("apache-arrow");
|
|
10
|
+
const native_1 = require("./native");
|
|
11
|
+
const BLOB_V2_EXTENSION_NAME = "lance.blob.v2";
|
|
12
|
+
const INLINE_SIZE_THRESHOLD_KEY = "lance-encoding:blob-inline-size-threshold";
|
|
13
|
+
const DEDICATED_SIZE_THRESHOLD_KEY = "lance-encoding:blob-dedicated-size-threshold";
|
|
14
|
+
const PACK_FILE_SIZE_THRESHOLD_KEY = "lance-encoding:blob-pack-file-size-threshold";
|
|
15
|
+
/**
|
|
16
|
+
* Declares a `lance.blob.v2` column.
|
|
17
|
+
*
|
|
18
|
+
* Query results are descriptors, not payload bytes. Use {@link Table.fetchBlobs}
|
|
19
|
+
* or {@link Table.fetchBlobFiles} to read bytes.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { readFile } from "node:fs/promises";
|
|
24
|
+
* import { Field, Int64, Schema } from "apache-arrow";
|
|
25
|
+
* import { blob, connect } from "@lancedb/lancedb";
|
|
26
|
+
*
|
|
27
|
+
* const db = await connect("./data");
|
|
28
|
+
* const video = await readFile("clip.mp4");
|
|
29
|
+
* const table = await db.createTable(
|
|
30
|
+
* "videos",
|
|
31
|
+
* [{ id: 1n, video }],
|
|
32
|
+
* {
|
|
33
|
+
* schema: new Schema([
|
|
34
|
+
* new Field("id", new Int64()),
|
|
35
|
+
* blob("video"),
|
|
36
|
+
* ]),
|
|
37
|
+
* },
|
|
38
|
+
* );
|
|
39
|
+
*
|
|
40
|
+
* const rows = await table.query().select(["id"]).withRowId().toArray();
|
|
41
|
+
* const rowIds = rows.map((row) => row._rowid as bigint);
|
|
42
|
+
* const bytes = await table.fetchBlobs("video", rowIds);
|
|
43
|
+
*
|
|
44
|
+
* const [handle] = await table.fetchBlobFiles("video", rowIds);
|
|
45
|
+
* const size = handle!.size();
|
|
46
|
+
* const header = await handle!.readRange(0n, size < 65536n ? size : 65536n);
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
function blob(name, options = {}) {
|
|
50
|
+
const metadata = new Map([
|
|
51
|
+
["ARROW:extension:name", BLOB_V2_EXTENSION_NAME],
|
|
52
|
+
]);
|
|
53
|
+
setThreshold(metadata, INLINE_SIZE_THRESHOLD_KEY, "inlineSizeThreshold", options.inlineSizeThreshold, 0);
|
|
54
|
+
setThreshold(metadata, DEDICATED_SIZE_THRESHOLD_KEY, "dedicatedSizeThreshold", options.dedicatedSizeThreshold, 1);
|
|
55
|
+
setThreshold(metadata, PACK_FILE_SIZE_THRESHOLD_KEY, "packFileSizeThreshold", options.packFileSizeThreshold, 1);
|
|
56
|
+
return new apache_arrow_1.Field(name, new apache_arrow_1.Struct([
|
|
57
|
+
new apache_arrow_1.Field("data", new apache_arrow_1.LargeBinary(), true),
|
|
58
|
+
new apache_arrow_1.Field("uri", new apache_arrow_1.Utf8(), true),
|
|
59
|
+
]), options.nullable ?? true, metadata);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Checks for the `lance.blob.v2` extension marker. Does not validate the
|
|
63
|
+
* field's storage type.
|
|
64
|
+
*/
|
|
65
|
+
function isBlobField(field) {
|
|
66
|
+
return field.metadata?.get("ARROW:extension:name") === BLOB_V2_EXTENSION_NAME;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A lazy handle to blob bytes. Create one with {@link Table.fetchBlobFiles}.
|
|
70
|
+
*
|
|
71
|
+
* @hideconstructor
|
|
72
|
+
*/
|
|
73
|
+
class BlobFile {
|
|
74
|
+
inner;
|
|
75
|
+
constructor(inner) {
|
|
76
|
+
if (!(inner instanceof native_1.BlobFile)) {
|
|
77
|
+
throw new Error("BlobFile handles come from Table.fetchBlobFiles");
|
|
78
|
+
}
|
|
79
|
+
this.inner = inner;
|
|
80
|
+
}
|
|
81
|
+
/** @ignore */
|
|
82
|
+
static fromNative(inner) {
|
|
83
|
+
return new BlobFile(inner);
|
|
84
|
+
}
|
|
85
|
+
/** Returns the blob size in bytes. */
|
|
86
|
+
size() {
|
|
87
|
+
return this.inner.size();
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Reads from the cursor to the end and advances the cursor.
|
|
91
|
+
*
|
|
92
|
+
* A second call returns an empty buffer. {@link BlobFile.readRange} does
|
|
93
|
+
* not move the cursor.
|
|
94
|
+
*/
|
|
95
|
+
read() {
|
|
96
|
+
return this.inner.read();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Reads the half-open byte range `[start, end)`.
|
|
100
|
+
*
|
|
101
|
+
* Fails when `end` is past the blob size. Does not move the cursor.
|
|
102
|
+
*/
|
|
103
|
+
readRange(start, end) {
|
|
104
|
+
return this.inner.readRange(start, end);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.BlobFile = BlobFile;
|
|
108
|
+
function coerceBlobValue(value) {
|
|
109
|
+
if (value == null) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
if (isBlobBytes(value)) {
|
|
113
|
+
return { data: value, uri: null };
|
|
114
|
+
}
|
|
115
|
+
if (ArrayBuffer.isView(value)) {
|
|
116
|
+
throw new Error("Blob data must be Buffer or Uint8Array");
|
|
117
|
+
}
|
|
118
|
+
if (typeof value === "string") {
|
|
119
|
+
if (value === "") {
|
|
120
|
+
throw new Error("Blob uri cannot be empty");
|
|
121
|
+
}
|
|
122
|
+
return { data: null, uri: value };
|
|
123
|
+
}
|
|
124
|
+
if (typeof value === "object") {
|
|
125
|
+
const record = value;
|
|
126
|
+
if (!("data" in record) && !("uri" in record)) {
|
|
127
|
+
throw new Error("Blob struct values must include a 'data' or 'uri' field");
|
|
128
|
+
}
|
|
129
|
+
const uri = record.uri;
|
|
130
|
+
if (uri === "") {
|
|
131
|
+
throw new Error("Blob uri cannot be empty");
|
|
132
|
+
}
|
|
133
|
+
if (uri != null && typeof uri !== "string") {
|
|
134
|
+
throw new Error(`Blob uri must be a string or null, got ${typeof uri}`);
|
|
135
|
+
}
|
|
136
|
+
const data = record.data;
|
|
137
|
+
if (data != null && !isBlobBytes(data)) {
|
|
138
|
+
throw new Error("Blob data must be Buffer, Uint8Array, or null");
|
|
139
|
+
}
|
|
140
|
+
const bytes = data ?? null;
|
|
141
|
+
const uriValue = uri ?? null;
|
|
142
|
+
if ((bytes == null) === (uriValue == null)) {
|
|
143
|
+
throw new Error("Blob struct values must set exactly one of 'data' or 'uri'");
|
|
144
|
+
}
|
|
145
|
+
return { data: bytes, uri: uriValue };
|
|
146
|
+
}
|
|
147
|
+
throw new Error("Blob column values must be Buffer, Uint8Array, a URI string, null, or { data?, uri? }");
|
|
148
|
+
}
|
|
149
|
+
function isBlobBytes(value) {
|
|
150
|
+
return Buffer.isBuffer(value) || value instanceof Uint8Array;
|
|
151
|
+
}
|
|
152
|
+
function setThreshold(metadata, key, optionName, value, minimum) {
|
|
153
|
+
if (value === undefined) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (!Number.isSafeInteger(value)) {
|
|
157
|
+
throw new Error(`${optionName} must be a safe integer`);
|
|
158
|
+
}
|
|
159
|
+
if (value < minimum) {
|
|
160
|
+
throw new Error(minimum <= 0
|
|
161
|
+
? `${optionName} must be non-negative`
|
|
162
|
+
: `${optionName} must be positive`);
|
|
163
|
+
}
|
|
164
|
+
metadata.set(key, String(value));
|
|
165
|
+
}
|
package/dist/connection.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Data, SchemaLike, TableLike } from "./arrow";
|
|
2
|
-
import { Table as ArrowTable } from "./arrow";
|
|
3
2
|
import { EmbeddingFunctionConfig } from "./embedding/registry";
|
|
3
|
+
import { Job } from "./job";
|
|
4
4
|
import { MaterializedView, MaterializedViewSelect } from "./materialized_view";
|
|
5
5
|
import { Connection as LanceDbConnection } from "./native";
|
|
6
|
-
import type { CreateNamespaceResponse, DescribeNamespaceResponse, DropNamespaceResponse,
|
|
6
|
+
import type { CreateNamespaceResponse, DescribeNamespaceResponse, DropNamespaceResponse, JobInfo, ListNamespacesResponse, ListTablesResponse } from "./native";
|
|
7
7
|
export type { CreateNamespaceResponse, DescribeNamespaceResponse, DropNamespaceResponse, ListNamespacesResponse, ListTablesResponse, };
|
|
8
8
|
import { Table } from "./table";
|
|
9
9
|
export interface CreateTableOptions {
|
|
@@ -256,18 +256,19 @@ export declare abstract class Connection {
|
|
|
256
256
|
/**
|
|
257
257
|
* Define a materialized view named `name` over the table `source`.
|
|
258
258
|
*
|
|
259
|
-
* The view is
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
259
|
+
* The view is populated before creation returns. Set `withNoData` to create
|
|
260
|
+
* only its definition and empty backing table. The view is a normal table:
|
|
261
|
+
* it can be queried, indexed and searched, and it appears in `tableNames`.
|
|
262
|
+
* The source table must have stable row ids (create it with
|
|
263
263
|
* the `newTableEnableStableRowIds` storage option); they keep the view's
|
|
264
264
|
* provenance valid across source compactions and cannot be enabled after
|
|
265
|
-
* a table exists.
|
|
265
|
+
* a table exists.
|
|
266
266
|
*/
|
|
267
267
|
abstract createMaterializedView(name: string, source: string, options?: {
|
|
268
268
|
select?: MaterializedViewSelect;
|
|
269
269
|
where?: string;
|
|
270
270
|
limit?: number;
|
|
271
|
+
withNoData?: boolean;
|
|
271
272
|
}): Promise<MaterializedView>;
|
|
272
273
|
/**
|
|
273
274
|
* Open the materialized view named `name`.
|
|
@@ -281,6 +282,22 @@ export declare abstract class Connection {
|
|
|
281
282
|
* Found by reading every table's schema, so this costs an open per table.
|
|
282
283
|
*/
|
|
283
284
|
abstract listMaterializedViews(): Promise<string[]>;
|
|
285
|
+
/**
|
|
286
|
+
* Drop the materialized view named `name`.
|
|
287
|
+
*
|
|
288
|
+
* The view may become unavailable before physical cleanup finishes. Use
|
|
289
|
+
* {@link dropMaterializedViewAsync} to retain and wait for the cleanup job.
|
|
290
|
+
*
|
|
291
|
+
* Rejects a table that exists but is not a materialized view.
|
|
292
|
+
*/
|
|
293
|
+
abstract dropMaterializedView(name: string, namespacePath?: string[]): Promise<void>;
|
|
294
|
+
/**
|
|
295
|
+
* Start dropping the materialized view named `name` and return its cleanup
|
|
296
|
+
* job without waiting for completion.
|
|
297
|
+
*
|
|
298
|
+
* Rejects a table that exists but is not a materialized view.
|
|
299
|
+
*/
|
|
300
|
+
abstract dropMaterializedViewAsync(name: string, namespacePath?: string[]): Promise<Job>;
|
|
284
301
|
abstract openTable(name: string, namespacePath?: string[], options?: Partial<OpenTableOptions>): Promise<Table>;
|
|
285
302
|
/**
|
|
286
303
|
* Creates a new Table and initialize it with new data.
|
|
@@ -428,21 +445,17 @@ export declare abstract class Connection {
|
|
|
428
445
|
*/
|
|
429
446
|
abstract renameTable(currentName: string, newName: string, options?: RenameTableOptions): Promise<void>;
|
|
430
447
|
/**
|
|
431
|
-
*
|
|
448
|
+
* Open a server-side job by id, returning a handle with its record already
|
|
449
|
+
* populated. Rejects when the server has no such job, the way
|
|
450
|
+
* {@link Connection.openTable} does for a missing table.
|
|
432
451
|
*
|
|
433
|
-
* The
|
|
434
|
-
*
|
|
435
|
-
*
|
|
452
|
+
* The returned {@link Job} answers for its own state, specification,
|
|
453
|
+
* result, failure and event history, so there is no separate
|
|
454
|
+
* connection-level call for any of them.
|
|
436
455
|
*/
|
|
437
|
-
abstract
|
|
456
|
+
abstract openJob(jobId: string): Promise<Job>;
|
|
438
457
|
/** List server-side jobs across the database's tables. */
|
|
439
458
|
abstract listJobs(): Promise<JobInfo[]>;
|
|
440
|
-
/**
|
|
441
|
-
* Describe a single server-side job by id.
|
|
442
|
-
*
|
|
443
|
-
* Resolves to `null` when the server has no such job.
|
|
444
|
-
*/
|
|
445
|
-
abstract getJob(jobId: string): Promise<JobDescription | null>;
|
|
446
459
|
/**
|
|
447
460
|
* Request cancellation of a server-side job by id.
|
|
448
461
|
*
|
|
@@ -450,12 +463,6 @@ export declare abstract class Connection {
|
|
|
450
463
|
* such job exists. Cancelling an already-terminal job is a no-op success.
|
|
451
464
|
*/
|
|
452
465
|
abstract cancelJob(jobId: string): Promise<boolean>;
|
|
453
|
-
/**
|
|
454
|
-
* The lifecycle event history of a server-side job, as an Arrow table.
|
|
455
|
-
*
|
|
456
|
-
* Lists history across all jobs when `jobId` is omitted.
|
|
457
|
-
*/
|
|
458
|
-
abstract jobHistory(jobId?: string): Promise<ArrowTable>;
|
|
459
466
|
}
|
|
460
467
|
/** @hideconstructor */
|
|
461
468
|
export declare class LocalConnection extends Connection {
|
|
@@ -470,9 +477,12 @@ export declare class LocalConnection extends Connection {
|
|
|
470
477
|
select?: MaterializedViewSelect;
|
|
471
478
|
where?: string;
|
|
472
479
|
limit?: number;
|
|
480
|
+
withNoData?: boolean;
|
|
473
481
|
}): Promise<MaterializedView>;
|
|
474
482
|
openMaterializedView(name: string): Promise<MaterializedView>;
|
|
475
483
|
listMaterializedViews(): Promise<string[]>;
|
|
484
|
+
dropMaterializedView(name: string, namespacePath?: string[]): Promise<void>;
|
|
485
|
+
dropMaterializedViewAsync(name: string, namespacePath?: string[]): Promise<Job>;
|
|
476
486
|
listTables(namespacePathOrOptions?: string[] | Partial<ListTablesOptions>, options?: Partial<ListTablesOptions>): Promise<ListTablesResponse>;
|
|
477
487
|
openTable(name: string, namespacePath?: string[], options?: Partial<OpenTableOptions>): Promise<Table>;
|
|
478
488
|
cloneTable(targetTableName: string, sourceUri: string, options?: {
|
|
@@ -496,11 +506,9 @@ export declare class LocalConnection extends Connection {
|
|
|
496
506
|
createNamespace(namespacePath: string[], options?: Partial<CreateNamespaceOptions>): Promise<CreateNamespaceResponse>;
|
|
497
507
|
dropNamespace(namespacePath: string[], options?: Partial<DropNamespaceOptions>): Promise<DropNamespaceResponse>;
|
|
498
508
|
renameTable(currentName: string, newName: string, options?: RenameTableOptions): Promise<void>;
|
|
499
|
-
|
|
509
|
+
openJob(jobId: string): Promise<Job>;
|
|
500
510
|
listJobs(): Promise<JobInfo[]>;
|
|
501
|
-
getJob(jobId: string): Promise<JobDescription | null>;
|
|
502
511
|
cancelJob(jobId: string): Promise<boolean>;
|
|
503
|
-
jobHistory(jobId?: string): Promise<ArrowTable>;
|
|
504
512
|
}
|
|
505
513
|
/**
|
|
506
514
|
* Takes storage options and makes all the keys snake case.
|
package/dist/connection.js
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.LocalConnection = exports.Connection = void 0;
|
|
6
6
|
exports.cleanseStorageOptions = cleanseStorageOptions;
|
|
7
|
-
const apache_arrow_1 = require("apache-arrow");
|
|
8
7
|
const arrow_1 = require("./arrow");
|
|
9
8
|
const arrow_2 = require("./arrow");
|
|
10
9
|
const registry_1 = require("./embedding/registry");
|
|
10
|
+
const job_1 = require("./job");
|
|
11
11
|
const materialized_view_1 = require("./materialized_view");
|
|
12
12
|
const sanitize_1 = require("./sanitize");
|
|
13
13
|
const table_1 = require("./table");
|
|
@@ -71,7 +71,7 @@ class LocalConnection extends Connection {
|
|
|
71
71
|
}
|
|
72
72
|
async createMaterializedView(name, source, options) {
|
|
73
73
|
(0, materialized_view_1.validateNonNegativeInteger)(options?.limit, "limit");
|
|
74
|
-
const innerTable = await this.inner.createMaterializedView(name, source, (0, materialized_view_1.normalizeSelect)(options?.select), options?.where, options?.limit);
|
|
74
|
+
const innerTable = await this.inner.createMaterializedView(name, source, (0, materialized_view_1.normalizeSelect)(options?.select), options?.where, options?.limit, options?.withNoData ?? false);
|
|
75
75
|
return new materialized_view_1.MaterializedView(new table_1.LocalTable(innerTable));
|
|
76
76
|
}
|
|
77
77
|
async openMaterializedView(name) {
|
|
@@ -81,6 +81,12 @@ class LocalConnection extends Connection {
|
|
|
81
81
|
async listMaterializedViews() {
|
|
82
82
|
return await this.inner.listMaterializedViews();
|
|
83
83
|
}
|
|
84
|
+
async dropMaterializedView(name, namespacePath) {
|
|
85
|
+
return this.inner.dropMaterializedView(name, namespacePath ?? []);
|
|
86
|
+
}
|
|
87
|
+
async dropMaterializedViewAsync(name, namespacePath) {
|
|
88
|
+
return new job_1.Job(await this.inner.dropMaterializedViewAsync(name, namespacePath ?? []));
|
|
89
|
+
}
|
|
84
90
|
async listTables(namespacePathOrOptions, options) {
|
|
85
91
|
// Detect if first argument is namespacePath array or options object
|
|
86
92
|
const namespacePath = Array.isArray(namespacePathOrOptions)
|
|
@@ -198,7 +204,7 @@ class LocalConnection extends Connection {
|
|
|
198
204
|
return this.inner.dropTable(name, namespacePath ?? []);
|
|
199
205
|
}
|
|
200
206
|
async dropTableAsync(name, namespacePath) {
|
|
201
|
-
return this.inner.dropTableAsync(name, namespacePath ?? []);
|
|
207
|
+
return new job_1.Job(await this.inner.dropTableAsync(name, namespacePath ?? []));
|
|
202
208
|
}
|
|
203
209
|
async dropAllTables(namespacePath) {
|
|
204
210
|
return this.inner.dropAllTables(namespacePath ?? []);
|
|
@@ -218,25 +224,15 @@ class LocalConnection extends Connection {
|
|
|
218
224
|
async renameTable(currentName, newName, options) {
|
|
219
225
|
return this.inner.renameTable(currentName, newName, options?.namespacePath ?? [], options?.newNamespacePath);
|
|
220
226
|
}
|
|
221
|
-
|
|
222
|
-
return this.inner.
|
|
227
|
+
async openJob(jobId) {
|
|
228
|
+
return new job_1.Job(await this.inner.openJob(jobId));
|
|
223
229
|
}
|
|
224
230
|
async listJobs() {
|
|
225
231
|
return this.inner.listJobs();
|
|
226
232
|
}
|
|
227
|
-
async getJob(jobId) {
|
|
228
|
-
return this.inner.getJob(jobId);
|
|
229
|
-
}
|
|
230
233
|
async cancelJob(jobId) {
|
|
231
234
|
return this.inner.cancelJob(jobId);
|
|
232
235
|
}
|
|
233
|
-
async jobHistory(jobId) {
|
|
234
|
-
const buf = await this.inner.jobHistory(jobId);
|
|
235
|
-
if (buf.length === 0) {
|
|
236
|
-
return new arrow_2.Table();
|
|
237
|
-
}
|
|
238
|
-
return (0, apache_arrow_1.tableFromIPC)(buf);
|
|
239
|
-
}
|
|
240
236
|
}
|
|
241
237
|
exports.LocalConnection = LocalConnection;
|
|
242
238
|
/**
|