mirror of
https://github.com/lancedb/lancedb.git
synced 2026-10-13 23:32:27 +00:00
Cancellation is the only job control the SDK exposes, and it is terminal, so a long-running server-side job cannot be parked and picked up again. This adds `pause_job` and `resume_job` to the Rust core connection and the Python bindings (sync and async), posting to the server's `/v1/jobs/pause` and `/v1/jobs/resume` endpoints. A pause parks the job until it is resumed: its workers drain and stop. The outcome strings mirror the server's answers — a job finalizing its results reports `"committing"` and cannot be parked, and a resume before the drain is confirmed reports `"still_pausing"`; both are retried rather than failed. Resuming re-queues the job and its workers pick their work back up from checkpoints. Local connections report the operations as unsupported, like the rest of the jobs API.
1154 lines
36 KiB
TypeScript
1154 lines
36 KiB
TypeScript
// SPDX-License-Identifier: Apache-2.0
|
|
// SPDX-FileCopyrightText: Copyright The LanceDB Authors
|
|
|
|
import {
|
|
Data,
|
|
SchemaLike,
|
|
TableLike,
|
|
fromTableToStreamBuffer,
|
|
isArrowTable,
|
|
makeArrowTable,
|
|
} from "./arrow";
|
|
import {
|
|
Table as ArrowTable,
|
|
fromTableToBuffer,
|
|
makeEmptyTable,
|
|
} from "./arrow";
|
|
import { EmbeddingFunctionConfig, getRegistry } from "./embedding/registry";
|
|
import { Job } from "./job";
|
|
import {
|
|
MaterializedView,
|
|
MaterializedViewSelect,
|
|
normalizeSelect,
|
|
validateNonNegativeInteger,
|
|
} from "./materialized_view";
|
|
import { Connection as LanceDbConnection } from "./native";
|
|
import type {
|
|
CreateNamespaceResponse,
|
|
DescribeNamespaceResponse,
|
|
DropNamespaceResponse,
|
|
JobInfo,
|
|
ListNamespacesResponse,
|
|
ListTablesResponse,
|
|
} from "./native";
|
|
import { ViewDescription, viewDescriptionFromNative } from "./view";
|
|
export type {
|
|
CreateNamespaceResponse,
|
|
DescribeNamespaceResponse,
|
|
DropNamespaceResponse,
|
|
ListNamespacesResponse,
|
|
ListTablesResponse,
|
|
};
|
|
import { sanitizeTable } from "./sanitize";
|
|
import { LocalTable, Table } from "./table";
|
|
|
|
export interface CreateTableOptions {
|
|
/**
|
|
* The mode to use when creating the table.
|
|
*
|
|
* If this is set to "create" and the table already exists then either
|
|
* an error will be thrown or, if existOk is true, then nothing will
|
|
* happen. Any provided data will be ignored.
|
|
*
|
|
* If this is set to "overwrite" then any existing table will be replaced.
|
|
*/
|
|
mode: "create" | "overwrite";
|
|
/**
|
|
* If this is true and the table already exists and the mode is "create"
|
|
* then no error will be raised.
|
|
*/
|
|
existOk: boolean;
|
|
|
|
/**
|
|
* Configuration for object storage.
|
|
*
|
|
* Options already set on the connection will be inherited by the table,
|
|
* but can be overridden here.
|
|
*
|
|
* The available options are described at https://docs.lancedb.com/storage/
|
|
*/
|
|
storageOptions?: Record<string, string>;
|
|
|
|
/**
|
|
* The version of the data storage format to use.
|
|
*
|
|
* The default is `stable`.
|
|
* Set to "legacy" to use the old format.
|
|
*
|
|
* @deprecated Pass `new_table_data_storage_version` to storageOptions instead.
|
|
*/
|
|
dataStorageVersion?: string;
|
|
|
|
/**
|
|
* Use the new V2 manifest paths. These paths provide more efficient
|
|
* opening of datasets with many versions on object stores. WARNING:
|
|
* turning this on will make the dataset unreadable for older versions
|
|
* of LanceDB (prior to 0.10.0). To migrate an existing dataset, instead
|
|
* use the {@link LocalTable#migrateManifestPathsV2} method.
|
|
*
|
|
* @deprecated Pass `new_table_enable_v2_manifest_paths` to storageOptions instead.
|
|
*/
|
|
enableV2ManifestPaths?: boolean;
|
|
|
|
schema?: SchemaLike;
|
|
embeddingFunction?: EmbeddingFunctionConfig;
|
|
}
|
|
|
|
export interface OpenTableOptions {
|
|
/**
|
|
* Open the table scoped to this branch instead of the default branch.
|
|
*
|
|
* Reads and writes on the returned table operate in the branch's context.
|
|
*/
|
|
branch?: string;
|
|
/**
|
|
* Open the table pinned to this version, producing a read-only view.
|
|
*
|
|
* Composes with {@link OpenTableOptions.branch}: when both are set, opens
|
|
* that branch at the version; otherwise opens `main` at the version. Call
|
|
* `checkoutLatest` to return to a writable state.
|
|
*/
|
|
version?: number;
|
|
/**
|
|
* Configuration for object storage.
|
|
*
|
|
* Options already set on the connection will be inherited by the table,
|
|
* but can be overridden here.
|
|
*
|
|
* The available options are described at https://docs.lancedb.com/storage/
|
|
*/
|
|
storageOptions?: Record<string, string>;
|
|
/**
|
|
* Set the size of the index cache, specified as a number of entries
|
|
*
|
|
* @deprecated Use session-level cache configuration instead.
|
|
* Create a Session with custom cache sizes and pass it to the connect() function.
|
|
*
|
|
* The exact meaning of an "entry" will depend on the type of index:
|
|
* - IVF: there is one entry for each IVF partition
|
|
* - BTREE: there is one entry for the entire index
|
|
*
|
|
* This cache applies to the entire opened table, across all indices.
|
|
* Setting this value higher will increase performance on larger datasets
|
|
* at the expense of more RAM
|
|
*/
|
|
indexCacheSize?: number;
|
|
}
|
|
|
|
/**
|
|
* @deprecated Use {@link ListTablesOptions} with {@link Connection.listTables}
|
|
* instead.
|
|
*/
|
|
export interface TableNamesOptions {
|
|
/**
|
|
* If present, only return names that come lexicographically after the
|
|
* supplied value.
|
|
*
|
|
* This can be combined with limit to implement pagination by setting this to
|
|
* the last table name from the previous page.
|
|
*/
|
|
startAfter?: string;
|
|
/** An optional limit to the number of results to return. */
|
|
limit?: number;
|
|
}
|
|
|
|
export interface ListTablesOptions {
|
|
/**
|
|
* Token from a previous response, to resume listing where it left off.
|
|
*
|
|
* The token is opaque: it carries whatever the database needs to resume, and
|
|
* callers should not construct or interpret one.
|
|
*/
|
|
pageToken?: string;
|
|
/**
|
|
* An upper bound on how many tables to return.
|
|
*
|
|
* A page may hold fewer than this and still not be the last one, so keep
|
|
* going while the response carries a page token rather than while pages are
|
|
* full.
|
|
*/
|
|
limit?: number;
|
|
}
|
|
|
|
export interface ListNamespacesOptions {
|
|
/** Token from a previous response for pagination. */
|
|
pageToken?: string;
|
|
/** An optional limit to the number of results to return. */
|
|
limit?: number;
|
|
}
|
|
|
|
export interface CreateNamespaceOptions {
|
|
/** Creation mode. */
|
|
mode?: "create" | "exist_ok" | "overwrite";
|
|
/** Properties to set on the new namespace. */
|
|
properties?: Record<string, string>;
|
|
}
|
|
|
|
export interface DropNamespaceOptions {
|
|
/** Whether to skip if the namespace doesn't exist, or fail. */
|
|
mode?: "skip" | "fail";
|
|
/** Refuse to drop if non-empty (restrict) or drop recursively (cascade). */
|
|
behavior?: "restrict" | "cascade";
|
|
}
|
|
|
|
export interface RenameTableOptions {
|
|
/**
|
|
* The namespace path of the table being renamed. Defaults to the root
|
|
* namespace (`[]`) when omitted.
|
|
*/
|
|
namespacePath?: string[];
|
|
/**
|
|
* The namespace path to move the table to as part of the rename. When
|
|
* omitted the table stays in `namespacePath`.
|
|
*/
|
|
newNamespacePath?: string[];
|
|
}
|
|
|
|
/**
|
|
* A LanceDB Connection that allows you to open tables and create new ones.
|
|
*
|
|
* Connection could be local against filesystem or remote against a server.
|
|
*
|
|
* A Connection is intended to be a long lived object and may hold open
|
|
* resources such as HTTP connection pools. This is generally fine and
|
|
* a single connection should be shared if it is going to be used many
|
|
* times. However, if you are finished with a connection, you may call
|
|
* close to eagerly free these resources. Any call to a Connection
|
|
* method after it has been closed will result in an error.
|
|
*
|
|
* Closing a connection is optional. Connections will automatically
|
|
* be closed when they are garbage collected.
|
|
*
|
|
* Any created tables are independent and will continue to work even if
|
|
* the underlying connection has been closed.
|
|
* @hideconstructor
|
|
*/
|
|
export abstract class Connection {
|
|
[Symbol.for("nodejs.util.inspect.custom")](): string {
|
|
return this.display();
|
|
}
|
|
|
|
/**
|
|
* Return true if the connection has not been closed
|
|
*/
|
|
abstract isOpen(): boolean;
|
|
|
|
/**
|
|
* Close the connection, releasing any underlying resources.
|
|
*
|
|
* It is safe to call this method multiple times.
|
|
*
|
|
* Any attempt to use the connection after it is closed will result in an error.
|
|
*/
|
|
abstract close(): void;
|
|
|
|
/**
|
|
* Return a brief description of the connection
|
|
*/
|
|
abstract display(): string;
|
|
|
|
/**
|
|
* List all the table names in this database.
|
|
*
|
|
* Tables will be returned in lexicographical order.
|
|
* @param {Partial<TableNamesOptions>} options - options to control the
|
|
* paging / start point (backwards compatibility)
|
|
*
|
|
* @deprecated Use {@link Connection.listTables} instead.
|
|
*/
|
|
abstract tableNames(options?: Partial<TableNamesOptions>): Promise<string[]>;
|
|
/**
|
|
* List all the table names in this database.
|
|
*
|
|
* Tables will be returned in lexicographical order.
|
|
* @param {string[]} namespacePath - The namespace path to list tables from (defaults to root namespace)
|
|
* @param {Partial<TableNamesOptions>} options - options to control the
|
|
* paging / start point
|
|
*
|
|
* @deprecated Use {@link Connection.listTables} instead.
|
|
*/
|
|
abstract tableNames(
|
|
namespacePath?: string[],
|
|
options?: Partial<TableNamesOptions>,
|
|
): Promise<string[]>;
|
|
|
|
/**
|
|
* List a page of the tables in this database.
|
|
*
|
|
* To retrieve the tables after the page, pass the `pageToken` the response
|
|
* carries back in. A page can be shorter than `limit` without being the last
|
|
* one, so walk until a response carries no page token:
|
|
*
|
|
* ```ts
|
|
* const names = [];
|
|
* let pageToken = undefined;
|
|
* do {
|
|
* const page = await conn.listTables({ pageToken, limit: 100 });
|
|
* names.push(...page.tables);
|
|
* pageToken = page.pageToken;
|
|
* } while (pageToken);
|
|
* ```
|
|
*
|
|
* @param {Partial<ListTablesOptions>} options - Pagination options
|
|
* (`pageToken`, `limit`).
|
|
* @returns {Promise<ListTablesResponse>} A page of table names and an
|
|
* optional token for the tables after it.
|
|
*/
|
|
abstract listTables(
|
|
options?: Partial<ListTablesOptions>,
|
|
): Promise<ListTablesResponse>;
|
|
/**
|
|
* List a page of the tables in this database.
|
|
*
|
|
* @param {string[]} namespacePath - The namespace path to list tables from
|
|
* (defaults to root namespace)
|
|
* @param {Partial<ListTablesOptions>} options - Pagination options
|
|
* (`pageToken`, `limit`).
|
|
* @returns {Promise<ListTablesResponse>} A page of table names and an
|
|
* optional token for the tables after it.
|
|
*/
|
|
abstract listTables(
|
|
namespacePath?: string[],
|
|
options?: Partial<ListTablesOptions>,
|
|
): Promise<ListTablesResponse>;
|
|
|
|
/**
|
|
* Open a table in the database.
|
|
* @param {string} name - The name of the table
|
|
* @param {string[]} namespacePath - The namespace path of the table (defaults to root namespace)
|
|
* @param {Partial<OpenTableOptions>} options - Additional options
|
|
*/
|
|
/**
|
|
* Define a materialized view named `name` over the table `source`.
|
|
*
|
|
* The view is populated before creation returns. Set `withNoData` to create
|
|
* only its definition and empty backing table. The view is a normal table:
|
|
* it can be queried, indexed and searched, and it appears in `tableNames`.
|
|
* The source table must have stable row ids (create it with
|
|
* the `newTableEnableStableRowIds` storage option); they keep the view's
|
|
* provenance valid across source compactions and cannot be enabled after
|
|
* a table exists.
|
|
*/
|
|
abstract createMaterializedView(
|
|
name: string,
|
|
source: string,
|
|
options?: {
|
|
select?: MaterializedViewSelect;
|
|
where?: string;
|
|
limit?: number;
|
|
withNoData?: boolean;
|
|
},
|
|
): Promise<MaterializedView>;
|
|
|
|
/**
|
|
* Open the materialized view named `name`.
|
|
*
|
|
* Rejects a table that exists but is not a materialized view.
|
|
*/
|
|
abstract openMaterializedView(name: string): Promise<MaterializedView>;
|
|
|
|
/**
|
|
* The names of the materialized views in this database.
|
|
*
|
|
* Found by reading every table's schema, so this costs an open per table.
|
|
*/
|
|
abstract listMaterializedViews(): Promise<string[]>;
|
|
|
|
/**
|
|
* Drop the materialized view named `name`.
|
|
*
|
|
* The view may become unavailable before physical cleanup finishes. Use
|
|
* {@link dropMaterializedViewAsync} to retain and wait for the cleanup job.
|
|
*
|
|
* Rejects a table that exists but is not a materialized view.
|
|
*/
|
|
abstract dropMaterializedView(
|
|
name: string,
|
|
namespacePath?: string[],
|
|
): Promise<void>;
|
|
|
|
/**
|
|
* Start dropping the materialized view named `name` and return its cleanup
|
|
* job without waiting for completion.
|
|
*
|
|
* Rejects a table that exists but is not a materialized view.
|
|
*/
|
|
abstract dropMaterializedViewAsync(
|
|
name: string,
|
|
namespacePath?: string[],
|
|
): Promise<Job>;
|
|
|
|
/**
|
|
* Create a view: a named query the database plans on every read.
|
|
*
|
|
* The query is planned once, at creation, so one that cannot be planned is
|
|
* rejected now rather than at the first read. A view holds no rows, and its
|
|
* readers see its sources as they are at read time.
|
|
*
|
|
* There is no replace: a name already taken is an error, and changing a
|
|
* view is a drop followed by a create.
|
|
*/
|
|
abstract createView(
|
|
name: string,
|
|
query: string,
|
|
namespacePath?: string[],
|
|
): Promise<ViewDescription>;
|
|
|
|
/**
|
|
* What this database records about the view named `name`: its defining
|
|
* query and the schema that query resolved to.
|
|
*/
|
|
abstract describeView(
|
|
name: string,
|
|
namespacePath?: string[],
|
|
): Promise<ViewDescription>;
|
|
|
|
/**
|
|
* Drop the view named `name` and wait for its definition to be deleted.
|
|
*
|
|
* The tables it reads are untouched: a view holds no rows of its own. Use
|
|
* {@link dropViewAsync} to retain the cleanup job instead of waiting on it.
|
|
*/
|
|
abstract dropView(name: string, namespacePath?: string[]): Promise<void>;
|
|
|
|
/**
|
|
* Start dropping the view named `name` and return the job deleting its
|
|
* definition, without waiting for completion.
|
|
*
|
|
* The name is free before this resolves. When nothing was bound to it, the
|
|
* returned job is already finished and has no id.
|
|
*/
|
|
abstract dropViewAsync(name: string, namespacePath?: string[]): Promise<Job>;
|
|
|
|
/**
|
|
* The names of the views in one namespace.
|
|
*
|
|
* Names only; a definition comes from {@link describeView}.
|
|
*/
|
|
abstract listViews(namespacePath?: string[]): Promise<string[]>;
|
|
|
|
abstract openTable(
|
|
name: string,
|
|
namespacePath?: string[],
|
|
options?: Partial<OpenTableOptions>,
|
|
): Promise<Table>;
|
|
|
|
/**
|
|
* Creates a new Table and initialize it with new data.
|
|
* @param {object} options - The options object.
|
|
* @param {string} options.name - The name of the table.
|
|
* @param {Data} options.data - Non-empty Array of Records to be inserted into the table
|
|
* @param {string[]} namespacePath - The namespace path to create the table in (defaults to root namespace)
|
|
*
|
|
*/
|
|
abstract createTable(
|
|
options: {
|
|
name: string;
|
|
data: Data;
|
|
} & Partial<CreateTableOptions>,
|
|
namespacePath?: string[],
|
|
): Promise<Table>;
|
|
/**
|
|
* Creates a new Table and initialize it with new data.
|
|
* @param {string} name - The name of the table.
|
|
* @param {Record<string, unknown>[] | TableLike} data - Non-empty Array of Records
|
|
* to be inserted into the table
|
|
* @param {Partial<CreateTableOptions>} options - Additional options (backwards compatibility)
|
|
*/
|
|
abstract createTable(
|
|
name: string,
|
|
data: Record<string, unknown>[] | TableLike,
|
|
options?: Partial<CreateTableOptions>,
|
|
): Promise<Table>;
|
|
/**
|
|
* Creates a new Table and initialize it with new data.
|
|
* @param {string} name - The name of the table.
|
|
* @param {Record<string, unknown>[] | TableLike} data - Non-empty Array of Records
|
|
* to be inserted into the table
|
|
* @param {string[]} namespacePath - The namespace path to create the table in (defaults to root namespace)
|
|
* @param {Partial<CreateTableOptions>} options - Additional options
|
|
*/
|
|
abstract createTable(
|
|
name: string,
|
|
data: Record<string, unknown>[] | TableLike,
|
|
namespacePath?: string[],
|
|
options?: Partial<CreateTableOptions>,
|
|
): Promise<Table>;
|
|
|
|
/**
|
|
* Creates a new empty Table
|
|
* @param {string} name - The name of the table.
|
|
* @param {Schema} schema - The schema of the table
|
|
* @param {Partial<CreateTableOptions>} options - Additional options (backwards compatibility)
|
|
*/
|
|
abstract createEmptyTable(
|
|
name: string,
|
|
schema: import("./arrow").SchemaLike,
|
|
options?: Partial<CreateTableOptions>,
|
|
): Promise<Table>;
|
|
/**
|
|
* Creates a new empty Table
|
|
* @param {string} name - The name of the table.
|
|
* @param {Schema} schema - The schema of the table
|
|
* @param {string[]} namespacePath - The namespace path to create the table in (defaults to root namespace)
|
|
* @param {Partial<CreateTableOptions>} options - Additional options
|
|
*/
|
|
abstract createEmptyTable(
|
|
name: string,
|
|
schema: import("./arrow").SchemaLike,
|
|
namespacePath?: string[],
|
|
options?: Partial<CreateTableOptions>,
|
|
): Promise<Table>;
|
|
|
|
/**
|
|
* Drop an existing table.
|
|
* @param {string} name The name of the table to drop.
|
|
* @param {string[]} namespacePath The namespace path of the table (defaults to root namespace).
|
|
*/
|
|
abstract dropTable(name: string, namespacePath?: string[]): Promise<void>;
|
|
|
|
/**
|
|
* Start dropping a table and return its cleanup job.
|
|
*
|
|
* The table may become unavailable before its data files are removed. Wait
|
|
* on the returned job to know when cleanup has finished.
|
|
*/
|
|
abstract dropTableAsync(name: string, namespacePath?: string[]): Promise<Job>;
|
|
|
|
/**
|
|
* Drop all tables in the database.
|
|
* @param {string[]} namespacePath The namespace path to drop tables from (defaults to root namespace).
|
|
*/
|
|
abstract dropAllTables(namespacePath?: string[]): Promise<void>;
|
|
|
|
/**
|
|
* Describe a namespace, returning its properties.
|
|
*
|
|
* @param {string[]} namespacePath - The namespace path to describe, in
|
|
* parent → child order, e.g. `["analytics", "sales"]`.
|
|
* @returns {Promise<DescribeNamespaceResponse>} The namespace's properties
|
|
* (may be undefined if the namespace has none).
|
|
*/
|
|
abstract describeNamespace(
|
|
namespacePath: string[],
|
|
): Promise<DescribeNamespaceResponse>;
|
|
|
|
/**
|
|
* List the immediate child namespaces under the given parent.
|
|
*
|
|
* Results may be paginated. To retrieve subsequent pages, pass the
|
|
* `pageToken` returned by a previous call.
|
|
*
|
|
* @param {string[]} namespacePath - The parent namespace path. Defaults
|
|
* to the root namespace if omitted.
|
|
* @param {Partial<ListNamespacesOptions>} options - Pagination options
|
|
* (`pageToken`, `limit`).
|
|
* @returns {Promise<ListNamespacesResponse>} Child namespace names and
|
|
* an optional token for fetching the next page.
|
|
*/
|
|
abstract listNamespaces(
|
|
namespacePath?: string[],
|
|
options?: Partial<ListNamespacesOptions>,
|
|
): Promise<ListNamespacesResponse>;
|
|
|
|
/**
|
|
* Create a new namespace at the given path.
|
|
*
|
|
* @param {string[]} namespacePath - The namespace path to create.
|
|
* @param {Partial<CreateNamespaceOptions>} options - Creation `mode`
|
|
* ("create" | "exist_ok" | "overwrite") and optional `properties`
|
|
* to attach to the namespace.
|
|
* @returns {Promise<CreateNamespaceResponse>} The properties of the
|
|
* created namespace and an optional transaction id.
|
|
*/
|
|
abstract createNamespace(
|
|
namespacePath: string[],
|
|
options?: Partial<CreateNamespaceOptions>,
|
|
): Promise<CreateNamespaceResponse>;
|
|
|
|
/**
|
|
* Drop a namespace.
|
|
*
|
|
* Use `behavior: "cascade"` to also drop everything contained in the
|
|
* namespace (sub-namespaces and tables). The default `"restrict"`
|
|
* behavior refuses to drop a non-empty namespace.
|
|
*
|
|
* @param {string[]} namespacePath - The namespace path to drop.
|
|
* @param {Partial<DropNamespaceOptions>} options - `mode` ("skip" | "fail"
|
|
* for missing-namespace handling) and `behavior` ("restrict" | "cascade").
|
|
* @returns {Promise<DropNamespaceResponse>} Any properties returned by
|
|
* the server and an optional transaction id.
|
|
*/
|
|
abstract dropNamespace(
|
|
namespacePath: string[],
|
|
options?: Partial<DropNamespaceOptions>,
|
|
): Promise<DropNamespaceResponse>;
|
|
|
|
/**
|
|
* Clone a table from a source table.
|
|
*
|
|
* A shallow clone creates a new table that shares the underlying data files
|
|
* with the source table but has its own independent manifest. This allows
|
|
* both the source and cloned tables to evolve independently while initially
|
|
* sharing the same data, deletion, and index files.
|
|
*
|
|
* @param {string} targetTableName - The name of the target table to create.
|
|
* @param {string} sourceUri - The URI of the source table to clone from.
|
|
* @param {object} options - Clone options.
|
|
* @param {string[]} options.targetNamespacePath - The namespace path for the target table (defaults to root namespace).
|
|
* @param {number} options.sourceVersion - The version of the source table to clone.
|
|
* @param {string} options.sourceTag - The tag of the source table to clone.
|
|
* @param {boolean} options.isShallow - Whether to perform a shallow clone (defaults to true).
|
|
*/
|
|
abstract cloneTable(
|
|
targetTableName: string,
|
|
sourceUri: string,
|
|
options?: {
|
|
targetNamespacePath?: string[];
|
|
sourceVersion?: number;
|
|
sourceTag?: string;
|
|
isShallow?: boolean;
|
|
},
|
|
): Promise<Table>;
|
|
|
|
/**
|
|
* Rename a table.
|
|
*
|
|
* Currently only supported by LanceDB Cloud. Local OSS connections and
|
|
* namespace-backed connections (via {@link connectNamespace}) reject with
|
|
* a "not supported" error.
|
|
*
|
|
* @param {string} currentName - The current name of the table.
|
|
* @param {string} newName - The new name for the table.
|
|
* @param {RenameTableOptions} options - Optional namespace paths. When
|
|
* `newNamespacePath` is omitted the table stays in `namespacePath`.
|
|
*/
|
|
abstract renameTable(
|
|
currentName: string,
|
|
newName: string,
|
|
options?: RenameTableOptions,
|
|
): Promise<void>;
|
|
|
|
/**
|
|
* Open a server-side job by id, returning a handle with its record already
|
|
* populated. Rejects when the server has no such job, the way
|
|
* {@link Connection.openTable} does for a missing table.
|
|
*
|
|
* The returned {@link Job} answers for its own state, specification,
|
|
* result, failure and event history, so there is no separate
|
|
* connection-level call for any of them.
|
|
*/
|
|
abstract openJob(jobId: string): Promise<Job>;
|
|
|
|
/** List server-side jobs across the database's tables. */
|
|
abstract listJobs(): Promise<JobInfo[]>;
|
|
|
|
/**
|
|
* Request cancellation of a server-side job by id.
|
|
*
|
|
* Resolves to true if the server accepted the cancellation, false if no
|
|
* such job exists. Cancelling an already-terminal job is a no-op success.
|
|
*/
|
|
abstract cancelJob(jobId: string): Promise<boolean>;
|
|
|
|
/**
|
|
* Pause a server-side job by id.
|
|
*
|
|
* The job's workers drain and it stays parked until resumed. Resolves to
|
|
* "pausing", "already_paused", or "committing" -- a job finalizing its
|
|
* results cannot be parked; retry shortly.
|
|
*/
|
|
abstract pauseJob(jobId: string): Promise<string>;
|
|
|
|
/**
|
|
* Resume a paused server-side job by id.
|
|
*
|
|
* Its workers pick their work back up from checkpoints. Resolves to
|
|
* "resumed", "still_pausing" -- the pause's worker drain is not confirmed
|
|
* yet; retry shortly -- or "not_paused".
|
|
*/
|
|
abstract resumeJob(jobId: string): Promise<string>;
|
|
}
|
|
|
|
/** @hideconstructor */
|
|
export class LocalConnection extends Connection {
|
|
readonly inner: LanceDbConnection;
|
|
|
|
/** @hidden */
|
|
constructor(inner: LanceDbConnection) {
|
|
super();
|
|
this.inner = inner;
|
|
}
|
|
|
|
isOpen(): boolean {
|
|
return this.inner.isOpen();
|
|
}
|
|
|
|
close(): void {
|
|
this.inner.close();
|
|
}
|
|
|
|
display(): string {
|
|
return this.inner.display();
|
|
}
|
|
|
|
async tableNames(
|
|
namespacePathOrOptions?: string[] | Partial<TableNamesOptions>,
|
|
options?: Partial<TableNamesOptions>,
|
|
): Promise<string[]> {
|
|
// Detect if first argument is namespacePath array or options object
|
|
let namespacePath: string[] | undefined;
|
|
let tableNamesOptions: Partial<TableNamesOptions> | undefined;
|
|
|
|
if (Array.isArray(namespacePathOrOptions)) {
|
|
// First argument is namespacePath array
|
|
namespacePath = namespacePathOrOptions;
|
|
tableNamesOptions = options;
|
|
} else {
|
|
// First argument is options object (backwards compatibility)
|
|
namespacePath = undefined;
|
|
tableNamesOptions = namespacePathOrOptions;
|
|
}
|
|
|
|
return this.inner.tableNames(
|
|
namespacePath ?? [],
|
|
tableNamesOptions?.startAfter,
|
|
tableNamesOptions?.limit,
|
|
);
|
|
}
|
|
|
|
async createMaterializedView(
|
|
name: string,
|
|
source: string,
|
|
options?: {
|
|
select?: MaterializedViewSelect;
|
|
where?: string;
|
|
limit?: number;
|
|
withNoData?: boolean;
|
|
},
|
|
): Promise<MaterializedView> {
|
|
validateNonNegativeInteger(options?.limit, "limit");
|
|
const innerTable = await this.inner.createMaterializedView(
|
|
name,
|
|
source,
|
|
normalizeSelect(options?.select),
|
|
options?.where,
|
|
options?.limit,
|
|
options?.withNoData ?? false,
|
|
);
|
|
return new MaterializedView(new LocalTable(innerTable));
|
|
}
|
|
|
|
async openMaterializedView(name: string): Promise<MaterializedView> {
|
|
const innerTable = await this.inner.openMaterializedView(name);
|
|
return new MaterializedView(new LocalTable(innerTable));
|
|
}
|
|
|
|
async listMaterializedViews(): Promise<string[]> {
|
|
return await this.inner.listMaterializedViews();
|
|
}
|
|
|
|
async dropMaterializedView(
|
|
name: string,
|
|
namespacePath?: string[],
|
|
): Promise<void> {
|
|
return this.inner.dropMaterializedView(name, namespacePath ?? []);
|
|
}
|
|
|
|
async dropMaterializedViewAsync(
|
|
name: string,
|
|
namespacePath?: string[],
|
|
): Promise<Job> {
|
|
return new Job(
|
|
await this.inner.dropMaterializedViewAsync(name, namespacePath ?? []),
|
|
);
|
|
}
|
|
|
|
async createView(
|
|
name: string,
|
|
query: string,
|
|
namespacePath?: string[],
|
|
): Promise<ViewDescription> {
|
|
return viewDescriptionFromNative(
|
|
await this.inner.createView(name, query, namespacePath ?? []),
|
|
);
|
|
}
|
|
|
|
async describeView(
|
|
name: string,
|
|
namespacePath?: string[],
|
|
): Promise<ViewDescription> {
|
|
return viewDescriptionFromNative(
|
|
await this.inner.describeView(name, namespacePath ?? []),
|
|
);
|
|
}
|
|
|
|
async dropView(name: string, namespacePath?: string[]): Promise<void> {
|
|
return this.inner.dropView(name, namespacePath ?? []);
|
|
}
|
|
|
|
async dropViewAsync(name: string, namespacePath?: string[]): Promise<Job> {
|
|
return new Job(await this.inner.dropViewAsync(name, namespacePath ?? []));
|
|
}
|
|
|
|
async listViews(namespacePath?: string[]): Promise<string[]> {
|
|
return this.inner.listViews(namespacePath ?? []);
|
|
}
|
|
|
|
async listTables(
|
|
namespacePathOrOptions?: string[] | Partial<ListTablesOptions>,
|
|
options?: Partial<ListTablesOptions>,
|
|
): Promise<ListTablesResponse> {
|
|
// Detect if first argument is namespacePath array or options object
|
|
const namespacePath = Array.isArray(namespacePathOrOptions)
|
|
? namespacePathOrOptions
|
|
: undefined;
|
|
const listTablesOptions = Array.isArray(namespacePathOrOptions)
|
|
? options
|
|
: namespacePathOrOptions;
|
|
|
|
return this.inner.listTables(
|
|
namespacePath ?? [],
|
|
listTablesOptions?.pageToken,
|
|
listTablesOptions?.limit,
|
|
);
|
|
}
|
|
|
|
async openTable(
|
|
name: string,
|
|
namespacePath?: string[],
|
|
options?: Partial<OpenTableOptions>,
|
|
): Promise<Table> {
|
|
const innerTable = await this.inner.openTable(
|
|
name,
|
|
namespacePath ?? [],
|
|
cleanseStorageOptions(options?.storageOptions),
|
|
options?.indexCacheSize,
|
|
);
|
|
|
|
let table: Table = new LocalTable(innerTable);
|
|
// "main" is the default branch, so treat it as no branch. On a real branch,
|
|
// scope and pin in one step (yielding "version V of branch B"); otherwise
|
|
// pin the version, if any, against main.
|
|
const branch =
|
|
options?.branch != null && options.branch !== "main"
|
|
? options.branch
|
|
: undefined;
|
|
if (branch != null) {
|
|
table = await (await table.branches()).checkout(branch, options?.version);
|
|
} else if (options?.version != null) {
|
|
await table.checkout(options.version);
|
|
}
|
|
return table;
|
|
}
|
|
|
|
async cloneTable(
|
|
targetTableName: string,
|
|
sourceUri: string,
|
|
options?: {
|
|
targetNamespacePath?: string[];
|
|
sourceVersion?: number;
|
|
sourceTag?: string;
|
|
isShallow?: boolean;
|
|
},
|
|
): Promise<Table> {
|
|
const innerTable = await this.inner.cloneTable(
|
|
targetTableName,
|
|
sourceUri,
|
|
options?.targetNamespacePath ?? [],
|
|
options?.sourceVersion ?? null,
|
|
options?.sourceTag ?? null,
|
|
options?.isShallow ?? true,
|
|
);
|
|
|
|
return new LocalTable(innerTable);
|
|
}
|
|
|
|
private getStorageOptions(
|
|
options?: Partial<CreateTableOptions>,
|
|
): Record<string, string> | undefined {
|
|
if (options?.dataStorageVersion !== undefined) {
|
|
if (options.storageOptions === undefined) {
|
|
options.storageOptions = {};
|
|
}
|
|
options.storageOptions["newTableDataStorageVersion"] =
|
|
options.dataStorageVersion;
|
|
}
|
|
|
|
if (options?.enableV2ManifestPaths !== undefined) {
|
|
if (options.storageOptions === undefined) {
|
|
options.storageOptions = {};
|
|
}
|
|
options.storageOptions["newTableEnableV2ManifestPaths"] =
|
|
options.enableV2ManifestPaths ? "true" : "false";
|
|
}
|
|
|
|
return cleanseStorageOptions(options?.storageOptions);
|
|
}
|
|
|
|
async createTable(
|
|
nameOrOptions:
|
|
| string
|
|
| ({ name: string; data: Data } & Partial<CreateTableOptions>),
|
|
dataOrNamespacePath?: Record<string, unknown>[] | TableLike | string[],
|
|
namespacePathOrOptions?: string[] | Partial<CreateTableOptions>,
|
|
options?: Partial<CreateTableOptions>,
|
|
): Promise<Table> {
|
|
if (typeof nameOrOptions !== "string" && "name" in nameOrOptions) {
|
|
// First overload: createTable(options, namespacePath?)
|
|
const { name, data, ...createOptions } = nameOrOptions;
|
|
const namespacePath = dataOrNamespacePath as string[] | undefined;
|
|
return this._createTableImpl(name, data, namespacePath, createOptions);
|
|
}
|
|
|
|
// Second overload: createTable(name, data, namespacePath?, options?)
|
|
const name = nameOrOptions;
|
|
const data = dataOrNamespacePath as Record<string, unknown>[] | TableLike;
|
|
|
|
// Detect if third argument is namespacePath array or options object
|
|
let namespacePath: string[] | undefined;
|
|
let createOptions: Partial<CreateTableOptions> | undefined;
|
|
|
|
if (Array.isArray(namespacePathOrOptions)) {
|
|
// Third argument is namespacePath array
|
|
namespacePath = namespacePathOrOptions;
|
|
createOptions = options;
|
|
} else {
|
|
// Third argument is options object (backwards compatibility)
|
|
namespacePath = undefined;
|
|
createOptions = namespacePathOrOptions;
|
|
}
|
|
|
|
return this._createTableImpl(name, data, namespacePath, createOptions);
|
|
}
|
|
|
|
private async _createTableImpl(
|
|
name: string,
|
|
data: Data,
|
|
namespacePath?: string[],
|
|
options?: Partial<CreateTableOptions>,
|
|
): Promise<Table> {
|
|
if (data === undefined) {
|
|
throw new Error("data is required");
|
|
}
|
|
const { buf, mode } = await parseTableData(data, options);
|
|
|
|
const storageOptions = this.getStorageOptions(options);
|
|
|
|
const innerTable = await this.inner.createTable(
|
|
name,
|
|
buf,
|
|
mode,
|
|
namespacePath ?? [],
|
|
storageOptions,
|
|
);
|
|
|
|
return new LocalTable(innerTable);
|
|
}
|
|
|
|
async createEmptyTable(
|
|
name: string,
|
|
schema: import("./arrow").SchemaLike,
|
|
namespacePathOrOptions?: string[] | Partial<CreateTableOptions>,
|
|
options?: Partial<CreateTableOptions>,
|
|
): Promise<Table> {
|
|
// Detect if third argument is namespacePath array or options object
|
|
let namespacePath: string[] | undefined;
|
|
let createOptions: Partial<CreateTableOptions> | undefined;
|
|
|
|
if (Array.isArray(namespacePathOrOptions)) {
|
|
// Third argument is namespacePath array
|
|
namespacePath = namespacePathOrOptions;
|
|
createOptions = options;
|
|
} else {
|
|
// Third argument is options object (backwards compatibility)
|
|
namespacePath = undefined;
|
|
createOptions = namespacePathOrOptions;
|
|
}
|
|
|
|
let mode: string = createOptions?.mode ?? "create";
|
|
const existOk = createOptions?.existOk ?? false;
|
|
|
|
if (mode === "create" && existOk) {
|
|
mode = "exist_ok";
|
|
}
|
|
let metadata: Map<string, string> | undefined = undefined;
|
|
if (createOptions?.embeddingFunction !== undefined) {
|
|
const embeddingFunction = createOptions.embeddingFunction;
|
|
const registry = getRegistry();
|
|
metadata = registry.getTableMetadata([embeddingFunction]);
|
|
}
|
|
|
|
const storageOptions = this.getStorageOptions(createOptions);
|
|
const table = makeEmptyTable(schema, metadata);
|
|
const buf = await fromTableToBuffer(table);
|
|
const innerTable = await this.inner.createEmptyTable(
|
|
name,
|
|
buf,
|
|
mode,
|
|
namespacePath ?? [],
|
|
storageOptions,
|
|
);
|
|
return new LocalTable(innerTable);
|
|
}
|
|
|
|
async dropTable(name: string, namespacePath?: string[]): Promise<void> {
|
|
return this.inner.dropTable(name, namespacePath ?? []);
|
|
}
|
|
|
|
async dropTableAsync(name: string, namespacePath?: string[]): Promise<Job> {
|
|
return new Job(await this.inner.dropTableAsync(name, namespacePath ?? []));
|
|
}
|
|
|
|
async dropAllTables(namespacePath?: string[]): Promise<void> {
|
|
return this.inner.dropAllTables(namespacePath ?? []);
|
|
}
|
|
|
|
describeNamespace(
|
|
namespacePath: string[],
|
|
): Promise<DescribeNamespaceResponse> {
|
|
return this.inner.describeNamespace(namespacePath);
|
|
}
|
|
|
|
listNamespaces(
|
|
namespacePath?: string[],
|
|
options?: Partial<ListNamespacesOptions>,
|
|
): Promise<ListNamespacesResponse> {
|
|
return this.inner.listNamespaces(
|
|
namespacePath ?? [],
|
|
options?.pageToken,
|
|
options?.limit,
|
|
);
|
|
}
|
|
|
|
createNamespace(
|
|
namespacePath: string[],
|
|
options?: Partial<CreateNamespaceOptions>,
|
|
): Promise<CreateNamespaceResponse> {
|
|
return this.inner.createNamespace(
|
|
namespacePath,
|
|
options?.mode,
|
|
options?.properties,
|
|
);
|
|
}
|
|
|
|
dropNamespace(
|
|
namespacePath: string[],
|
|
options?: Partial<DropNamespaceOptions>,
|
|
): Promise<DropNamespaceResponse> {
|
|
return this.inner.dropNamespace(
|
|
namespacePath,
|
|
options?.mode,
|
|
options?.behavior,
|
|
);
|
|
}
|
|
|
|
async renameTable(
|
|
currentName: string,
|
|
newName: string,
|
|
options?: RenameTableOptions,
|
|
): Promise<void> {
|
|
return this.inner.renameTable(
|
|
currentName,
|
|
newName,
|
|
options?.namespacePath ?? [],
|
|
options?.newNamespacePath,
|
|
);
|
|
}
|
|
|
|
async openJob(jobId: string): Promise<Job> {
|
|
return new Job(await this.inner.openJob(jobId));
|
|
}
|
|
|
|
async listJobs(): Promise<JobInfo[]> {
|
|
return this.inner.listJobs();
|
|
}
|
|
|
|
async cancelJob(jobId: string): Promise<boolean> {
|
|
return this.inner.cancelJob(jobId);
|
|
}
|
|
|
|
async pauseJob(jobId: string): Promise<string> {
|
|
return this.inner.pauseJob(jobId);
|
|
}
|
|
|
|
async resumeJob(jobId: string): Promise<string> {
|
|
return this.inner.resumeJob(jobId);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Takes storage options and makes all the keys snake case.
|
|
*/
|
|
export function cleanseStorageOptions(
|
|
options?: Record<string, string>,
|
|
): Record<string, string> | undefined {
|
|
if (options === undefined) {
|
|
return undefined;
|
|
}
|
|
const result: Record<string, string> = {};
|
|
for (const [key, value] of Object.entries(options)) {
|
|
if (value !== undefined) {
|
|
const newKey = camelToSnakeCase(key);
|
|
result[newKey] = value;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Convert a string to snake case. It might already be snake case, in which case it is
|
|
* returned unchanged.
|
|
*/
|
|
function camelToSnakeCase(camel: string): string {
|
|
if (camel.includes("_")) {
|
|
// Assume if there is at least one underscore, it is already snake case
|
|
return camel;
|
|
}
|
|
if (camel.toLocaleUpperCase() === camel) {
|
|
// Assume if the string is all uppercase, it is already snake case
|
|
return camel;
|
|
}
|
|
|
|
let result = camel.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
if (result.startsWith("_")) {
|
|
result = result.slice(1);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
async function parseTableData(
|
|
data: Record<string, unknown>[] | TableLike,
|
|
options?: Partial<CreateTableOptions>,
|
|
streaming = false,
|
|
) {
|
|
let mode: string = options?.mode ?? "create";
|
|
const existOk = options?.existOk ?? false;
|
|
|
|
if (mode === "create" && existOk) {
|
|
mode = "exist_ok";
|
|
}
|
|
|
|
let table: ArrowTable;
|
|
if (isArrowTable(data)) {
|
|
table = sanitizeTable(data);
|
|
} else {
|
|
table = makeArrowTable(data as Record<string, unknown>[], options);
|
|
}
|
|
if (streaming) {
|
|
const buf = await fromTableToStreamBuffer(
|
|
table,
|
|
options?.embeddingFunction,
|
|
options?.schema,
|
|
);
|
|
return { buf, mode };
|
|
} else {
|
|
const buf = await fromTableToBuffer(
|
|
table,
|
|
options?.embeddingFunction,
|
|
options?.schema,
|
|
);
|
|
return { buf, mode };
|
|
}
|
|
}
|