mirror of
https://github.com/lancedb/lancedb.git
synced 2026-08-27 08:28:28 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c0a9a4d48a | |||
| 32c3d39f2a | |||
| 7a41f4a5eb | |||
| 28fc8f0f26 | |||
| 7677a5279c | |||
| b6c645592a |
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"name": "lancedb",
|
||||
"interface": {
|
||||
"displayName": "LanceDB"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "lancedb",
|
||||
"source": {
|
||||
"source": "local",
|
||||
"path": "./plugins/lancedb"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE",
|
||||
"authentication": "ON_INSTALL"
|
||||
},
|
||||
"category": "Developer Tools"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
# Agent Skills
|
||||
|
||||
This directory contains repo-scoped code agent skills for the LanceDB project.
|
||||
|
||||
Each skill is a folder that contains a required `SKILL.md` and optional bundled resources.
|
||||
|
||||
Codex discovers skills from `.agents/skills` in the current working directory and parent directories.
|
||||
|
||||
The `lancedb` skill lives in the `plugins/lancedb` plugin (see `plugins/lancedb/skills/lancedb`)
|
||||
so it can be installed via the plugin marketplaces (`.claude-plugin/marketplace.json` and
|
||||
`.agents/plugins/marketplace.json`); the `lancedb` entry here is a symlink into that plugin.
|
||||
@@ -1 +0,0 @@
|
||||
../../plugins/lancedb/skills/lancedb
|
||||
@@ -1,98 +0,0 @@
|
||||
---
|
||||
name: lancedb-update-lance-dependency
|
||||
description: Update LanceDB to a specific Lance release or tag. Use when bumping Lance dependencies in the lancedb repository, including Rust workspace Lance crates, Java lance-core, validation, branch creation, commit, push, and PR creation when requested.
|
||||
---
|
||||
|
||||
# LanceDB Update Lance Dependency
|
||||
|
||||
## Scope
|
||||
|
||||
Use this skill in the `lancedb/lancedb` repository when updating the Lance dependency to a specific Lance version or tag.
|
||||
|
||||
Inputs can be a version (`7.2.0-beta.1`), a tag (`v7.2.0-beta.1`), a tag ref (`refs/tags/v7.2.0-beta.1`), or `latest`.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Confirm the worktree status with `git status --short`.
|
||||
2. Resolve the target Lance version:
|
||||
|
||||
- If the input is `latest`, empty, or omitted, run:
|
||||
|
||||
```bash
|
||||
python3 ci/check_lance_release.py
|
||||
```
|
||||
|
||||
Parse the JSON output. If `needs_update` is not `true`, stop without creating a PR. Otherwise use `latest_tag`.
|
||||
|
||||
- If the input is explicit, use it directly.
|
||||
|
||||
3. Compute update metadata without changing files:
|
||||
|
||||
```bash
|
||||
python3 ci/update_lance_dependency.py "$TAG_OR_VERSION" --metadata-only
|
||||
```
|
||||
|
||||
Before making changes, check for an existing open PR with the emitted `pr_title`:
|
||||
|
||||
```bash
|
||||
gh pr list --search "\"$PR_TITLE\" in:title" --state open --limit 1 --json number,url,title
|
||||
```
|
||||
|
||||
If a matching open PR exists, stop and report it instead of creating a duplicate.
|
||||
|
||||
4. Run the deterministic update entrypoint:
|
||||
|
||||
```bash
|
||||
python3 ci/update_lance_dependency.py "$TAG_OR_VERSION"
|
||||
```
|
||||
|
||||
This updates the Rust workspace Lance dependencies through `ci/set_lance_version.py`, updates `java/pom.xml`, refreshes Cargo metadata, and prints JSON metadata containing `branch_name`, `commit_message`, and `pr_title`.
|
||||
|
||||
5. Run validation:
|
||||
|
||||
```bash
|
||||
cargo clippy --quiet --workspace --tests --all-features -- -D warnings
|
||||
cargo fmt --all --quiet
|
||||
```
|
||||
|
||||
Fix real diagnostics and rerun clippy until it succeeds. Do not skip warnings.
|
||||
|
||||
6. Inspect `git status --short` and `git diff` to ensure only the Lance dependency update and required compatibility fixes are present.
|
||||
|
||||
7. If the task only asks to prepare local changes, stop here and report the changed files and validation result.
|
||||
|
||||
8. If the task asks to publish the update, create a branch using the printed `branch_name`, stage all relevant files, and commit using the printed `commit_message`. Do not amend or rewrite existing commits.
|
||||
|
||||
9. Push to `origin`. Before creating the PR, check that the current token has push permission:
|
||||
|
||||
```bash
|
||||
gh api repos/lancedb/lancedb --jq .permissions.push
|
||||
```
|
||||
|
||||
If the remote branch already exists for the same generated branch name, delete the remote ref with `gh api -X DELETE repos/lancedb/lancedb/git/refs/heads/$BRANCH_NAME`, then push. Do not force-push.
|
||||
|
||||
10. Create a PR targeting `main` with the printed `pr_title`. If there is no PR template, keep the body to two or three concise sentences: state the Lance dependency bump, note any required compatibility fixes, and link the triggering Lance tag or release.
|
||||
|
||||
11. Read back the remote PR title after creation. If it is not a Conventional Commit title, fix it immediately.
|
||||
|
||||
12. When running in GitHub Actions after creating the LanceDB PR, trigger the Sophon dependency update:
|
||||
|
||||
```bash
|
||||
gh workflow run codex-bump-lancedb-lance.yml \
|
||||
--repo lancedb/sophon \
|
||||
-f lance_ref="$LANCE_TAG" \
|
||||
-f lancedb_ref="$BRANCH_NAME"
|
||||
gh run list --repo lancedb/sophon --workflow codex-bump-lancedb-lance.yml --limit 1 --json databaseId,url,displayTitle
|
||||
```
|
||||
|
||||
Use the emitted metadata `tag` value as `LANCE_TAG`. Do this only after a new LanceDB PR has been created. If the update was skipped because no update is needed or an open PR already exists, do not trigger Sophon.
|
||||
|
||||
## GitHub Actions
|
||||
|
||||
When this skill is used from GitHub Actions, `TAG`, `GH_TOKEN`, and `GITHUB_TOKEN` may already be set. Resolve `latest` first when `TAG` is empty. Once an explicit tag or version is known, use:
|
||||
|
||||
```bash
|
||||
python3 ci/update_lance_dependency.py "$TAG" --github-output "$GITHUB_OUTPUT"
|
||||
```
|
||||
|
||||
Then use the emitted `branch_name`, `commit_message`, and `pr_title` values for branch, commit, and PR creation.
|
||||
+1
-10
@@ -1,5 +1,5 @@
|
||||
[tool.bumpversion]
|
||||
current_version = "0.37.1-beta.0"
|
||||
current_version = "0.30.0"
|
||||
parse = """(?x)
|
||||
(?P<major>0|[1-9]\\d*)\\.
|
||||
(?P<minor>0|[1-9]\\d*)\\.
|
||||
@@ -23,8 +23,6 @@ allow_dirty = true
|
||||
commit = true
|
||||
message = "Bump version: {current_version} → {new_version}"
|
||||
commit_args = ""
|
||||
# bump-my-version >=1.4.0 rejects pre_commit_hooks containing shell syntax unless opted in.
|
||||
allow_shell_hooks = true
|
||||
|
||||
# Java maven files
|
||||
pre_commit_hooks = [
|
||||
@@ -75,13 +73,6 @@ filename = "nodejs/Cargo.toml"
|
||||
replace = "\nversion = \"{new_version}\""
|
||||
search = "\nversion = \"{current_version}\""
|
||||
|
||||
# The Python package takes its version from here (pyproject.toml declares
|
||||
# `dynamic = ["version"]`, so maturin reads it out of the crate manifest).
|
||||
[[tool.bumpversion.files]]
|
||||
filename = "python/Cargo.toml"
|
||||
replace = "\nversion = \"{new_version}\""
|
||||
search = "\nversion = \"{current_version}\""
|
||||
|
||||
# Java documentation
|
||||
[[tool.bumpversion.files]]
|
||||
filename = "docs/src/java/java.md"
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"name": "lancedb",
|
||||
"owner": {
|
||||
"name": "LanceDB"
|
||||
},
|
||||
"description": "LanceDB plugins for Claude Code.",
|
||||
"plugins": [
|
||||
{
|
||||
"name": "lancedb",
|
||||
"source": "./plugins/lancedb",
|
||||
"description": "Write, review, debug, and document LanceDB pipelines in Python and TypeScript that work across local LanceDB OSS tables and remote LanceDB Enterprise/Cloud tables.",
|
||||
"version": "0.1.0",
|
||||
"author": {
|
||||
"name": "LanceDB"
|
||||
},
|
||||
"category": "development"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -27,31 +27,19 @@ runs:
|
||||
# Extract failed job names
|
||||
FAILED_JOBS=$(echo "$JOB_RESULTS" | jq -r 'to_entries | map(select(.value.result == "failure")) | map(.key) | join(", ")')
|
||||
|
||||
TITLE="$WORKFLOW_NAME Failed ($FAILED_JOBS)"
|
||||
|
||||
# This action now also runs on nightly schedules, so a breakage that
|
||||
# persists for a few days would otherwise file one issue per night.
|
||||
# Comment on the open report instead when one already exists.
|
||||
EXISTING=$(gh issue list --state open --label ci --limit 100 --json number,title \
|
||||
| jq -r --arg title "$TITLE" 'map(select(.title == $title)) | .[0].number // empty')
|
||||
|
||||
if [ -n "$EXISTING" ]; then
|
||||
gh issue comment "$EXISTING" --body "Failed again: $RUN_URL"
|
||||
echo "Commented on existing issue #$EXISTING"
|
||||
else
|
||||
gh issue create \
|
||||
--title "$TITLE" \
|
||||
--body "The workflow **$WORKFLOW_NAME** failed during execution.
|
||||
# Create issue with workflow name, failed jobs, and run URL
|
||||
gh issue create \
|
||||
--title "$WORKFLOW_NAME Failed ($FAILED_JOBS)" \
|
||||
--body "The workflow **$WORKFLOW_NAME** failed during execution.
|
||||
|
||||
**Failed jobs:** $FAILED_JOBS
|
||||
|
||||
**Run URL:** $RUN_URL
|
||||
|
||||
Please investigate the failed jobs and address any issues." \
|
||||
--label "ci"
|
||||
--label "ci"
|
||||
|
||||
echo "Issue created successfully"
|
||||
fi
|
||||
echo "Issue created successfully"
|
||||
else
|
||||
echo "No job failures detected, skipping issue creation"
|
||||
fi
|
||||
|
||||
@@ -21,14 +21,3 @@ updates:
|
||||
update-types:
|
||||
- minor
|
||||
- patch
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: /python
|
||||
schedule:
|
||||
interval: weekly
|
||||
# Only update uv.lock, never widen version requirements in pyproject.toml.
|
||||
versioning-strategy: lockfile-only
|
||||
groups:
|
||||
python-deps:
|
||||
patterns:
|
||||
- "*"
|
||||
|
||||
@@ -18,14 +18,6 @@ inputs:
|
||||
description: "The manylinux version to build for"
|
||||
required: false
|
||||
default: "2_17"
|
||||
package-name:
|
||||
description: "Override [project] name in python/pyproject.toml (e.g. 'lancedb-compat'). Default keeps 'lancedb'."
|
||||
required: false
|
||||
default: "lancedb"
|
||||
rustflags:
|
||||
description: "RUSTFLAGS for the build container, as a single whitespace-free token (e.g. '-Ctarget-cpu=x86-64-v2'). Empty leaves RUSTFLAGS unset, keeping the defaults from .cargo/config.toml."
|
||||
required: false
|
||||
default: ""
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
@@ -35,18 +27,6 @@ runs:
|
||||
ARM_BUILD: ${{ inputs.arm-build }}
|
||||
run: |
|
||||
echo "ARM BUILD: $ARM_BUILD"
|
||||
- name: Patch package name for variant build
|
||||
if: ${{ inputs.package-name != 'lancedb' }}
|
||||
shell: bash
|
||||
env:
|
||||
PACKAGE_NAME: ${{ inputs.package-name }}
|
||||
run: |
|
||||
# Swap the [project] name so this build produces e.g. lancedb-compat
|
||||
# wheels. The package still installs files under the lancedb/
|
||||
# namespace -- import lancedb still works after pip install.
|
||||
sed -i.bak 's/^name = "lancedb"$/name = "'"$PACKAGE_NAME"'"/' python/pyproject.toml
|
||||
rm -f python/pyproject.toml.bak
|
||||
grep '^name = ' python/pyproject.toml
|
||||
- name: Build x86_64 Manylinux wheel
|
||||
if: ${{ inputs.arm-build == 'false' }}
|
||||
uses: PyO3/maturin-action@v1
|
||||
@@ -54,16 +34,15 @@ runs:
|
||||
maturin-version: "1.12.4"
|
||||
command: build
|
||||
working-directory: python
|
||||
docker-options: "-e PIP_EXTRA_INDEX_URL='https://pypi.fury.io/lance-format/ https://pypi.fury.io/lancedb/' -e PROTOC=/usr/local/bin/protoc ${{ inputs.rustflags != '' && format('-e RUSTFLAGS={0}', inputs.rustflags) || '' }}"
|
||||
docker-options: "-e PIP_EXTRA_INDEX_URL='https://pypi.fury.io/lance-format/ https://pypi.fury.io/lancedb/'"
|
||||
target: x86_64-unknown-linux-gnu
|
||||
manylinux: ${{ inputs.manylinux }}
|
||||
args: ${{ inputs.args }}
|
||||
before-script-linux: |
|
||||
set -e
|
||||
curl -fsSL https://github.com/protocolbuffers/protobuf/releases/download/v24.4/protoc-24.4-linux-x86_64.zip -o /tmp/protoc.zip
|
||||
unzip /tmp/protoc.zip -d /usr/local
|
||||
rm /tmp/protoc.zip
|
||||
/usr/local/bin/protoc --version
|
||||
curl -L https://github.com/protocolbuffers/protobuf/releases/download/v24.4/protoc-24.4-linux-$(uname -m).zip > /tmp/protoc.zip \
|
||||
&& unzip /tmp/protoc.zip -d /usr/local \
|
||||
&& rm /tmp/protoc.zip
|
||||
- name: Build Arm Manylinux Wheel
|
||||
if: ${{ inputs.arm-build == 'true' }}
|
||||
uses: PyO3/maturin-action@v1
|
||||
@@ -71,14 +50,13 @@ runs:
|
||||
maturin-version: "1.12.4"
|
||||
command: build
|
||||
working-directory: python
|
||||
docker-options: "-e PIP_EXTRA_INDEX_URL='https://pypi.fury.io/lance-format/ https://pypi.fury.io/lancedb/' -e PROTOC=/usr/local/bin/protoc ${{ inputs.rustflags != '' && format('-e RUSTFLAGS={0}', inputs.rustflags) || '' }}"
|
||||
docker-options: "-e PIP_EXTRA_INDEX_URL='https://pypi.fury.io/lance-format/ https://pypi.fury.io/lancedb/'"
|
||||
target: aarch64-unknown-linux-gnu
|
||||
manylinux: ${{ inputs.manylinux }}
|
||||
args: ${{ inputs.args }}
|
||||
before-script-linux: |
|
||||
set -e
|
||||
yum install -y clang
|
||||
curl -fsSL https://github.com/protocolbuffers/protobuf/releases/download/v24.4/protoc-24.4-linux-aarch_64.zip -o /tmp/protoc.zip
|
||||
unzip /tmp/protoc.zip -d /usr/local
|
||||
rm /tmp/protoc.zip
|
||||
/usr/local/bin/protoc --version
|
||||
yum install -y clang \
|
||||
&& curl -L https://github.com/protocolbuffers/protobuf/releases/download/v24.4/protoc-24.4-linux-aarch_64.zip > /tmp/protoc.zip \
|
||||
&& unzip /tmp/protoc.zip -d /usr/local \
|
||||
&& rm /tmp/protoc.zip
|
||||
|
||||
@@ -6,6 +6,7 @@ on:
|
||||
# We don't publish pre-releases for Rust. Crates.io is just a source
|
||||
# distribution, so we don't need to publish pre-releases.
|
||||
- "v*-beta*"
|
||||
- "*-v*" # for example, python-vX.Y.Z
|
||||
|
||||
env:
|
||||
# This env var is used by Swatinem/rust-cache@v2 for the cache
|
||||
@@ -24,7 +25,7 @@ jobs:
|
||||
# Only runs on tags that matches the make-release action
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: rust
|
||||
@@ -46,7 +47,7 @@ jobs:
|
||||
contents: read
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/create-failure-issue
|
||||
with:
|
||||
job-results: ${{ toJSON(needs) }}
|
||||
|
||||
@@ -36,14 +36,14 @@ jobs:
|
||||
echo "guidelines = ${{ inputs.guidelines }}"
|
||||
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.branch }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: true
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
# pnpm 11 (used by the nodejs install step below) requires
|
||||
# Node >= 22.13; use 24 since 22 hits EOL in October.
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
cache: maven
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 11.1.1
|
||||
- name: Install Node.js dependencies for TypeScript bindings
|
||||
|
||||
@@ -4,16 +4,14 @@ on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Tag name from Lance. If omitted, the skill will use the latest Lance release that needs an update."
|
||||
required: false
|
||||
default: ""
|
||||
description: "Tag name from Lance"
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Tag name from Lance. Leave empty to use the latest Lance release that needs an update."
|
||||
required: false
|
||||
default: ""
|
||||
description: "Tag name from Lance"
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
@@ -27,16 +25,16 @@ jobs:
|
||||
steps:
|
||||
- name: Show inputs
|
||||
run: |
|
||||
echo "tag = ${{ inputs.tag || 'latest' }}"
|
||||
echo "tag = ${{ inputs.tag }}"
|
||||
|
||||
- name: Checkout Repo LanceDB
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: true
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
@@ -73,21 +71,65 @@ jobs:
|
||||
OPENAI_API_KEY: ${{ secrets.CODEX_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TARGET_TAG="${TAG:-latest}"
|
||||
VERSION="${TAG#refs/tags/}"
|
||||
VERSION="${VERSION#v}"
|
||||
BRANCH_NAME="codex/update-lance-${VERSION//[^a-zA-Z0-9]/-}"
|
||||
|
||||
# Use "chore" for beta/rc versions, "feat" for stable releases
|
||||
if [[ "${VERSION}" == *beta* ]] || [[ "${VERSION}" == *rc* ]]; then
|
||||
COMMIT_TYPE="chore"
|
||||
else
|
||||
COMMIT_TYPE="feat"
|
||||
fi
|
||||
|
||||
cat <<EOF >/tmp/codex-prompt.txt
|
||||
You are running inside the lancedb repository on a GitHub Actions runner.
|
||||
You are running inside the lancedb repository on a GitHub Actions runner. Update the Lance dependency to version ${VERSION} and prepare a pull request for maintainers to review.
|
||||
|
||||
Use \$lancedb-update-lance-dependency with target "${TARGET_TAG}".
|
||||
Follow these steps exactly:
|
||||
1. Use script "ci/set_lance_version.py" to update Lance Rust dependencies. The script already refreshes Cargo metadata, so allow it to finish even if it takes time.
|
||||
2. Update the Java lance-core dependency version in "java/pom.xml": change the "<lance-core.version>...</lance-core.version>" property to "${VERSION}".
|
||||
3. Run "cargo clippy --workspace --tests --all-features -- -D warnings". If diagnostics appear, fix them yourself and rerun clippy until it exits cleanly. Do not skip any warnings.
|
||||
4. After clippy succeeds, run "cargo fmt --all" to format the workspace.
|
||||
5. Ensure the repository is clean except for intentional changes. Inspect "git status --short" and "git diff" to confirm the dependency update and any required fixes.
|
||||
6. Create and switch to a new branch named "${BRANCH_NAME}" (replace any duplicated hyphens if necessary).
|
||||
7. Stage all relevant files with "git add -A". Commit using the message "${COMMIT_TYPE}: update lance dependency to v${VERSION}".
|
||||
8. Push the branch to origin. If the remote branch already exists, delete it first with "gh api -X DELETE repos/lancedb/lancedb/git/refs/heads/${BRANCH_NAME}" then push with "git push origin ${BRANCH_NAME}". Do NOT use "git push --force" or "git push -f".
|
||||
9. env "GH_TOKEN" is available, use "gh" tools for github related operations like creating pull request.
|
||||
10. Create a pull request targeting "main" with title "${COMMIT_TYPE}: update lance dependency to v${VERSION}". First, write the PR body to /tmp/pr-body.md using a heredoc (cat <<'EOF' > /tmp/pr-body.md). The body should summarize the dependency bump, clippy/fmt verification, and link the triggering tag (${TAG}). Then run "gh pr create --body-file /tmp/pr-body.md".
|
||||
11. After creating the PR, display the PR URL, "git status --short", and a concise summary of the commands run and their results.
|
||||
|
||||
Constraints:
|
||||
- Use env "GH_TOKEN" for GitHub operations.
|
||||
- Do not merge the pull request.
|
||||
- Do not force-push.
|
||||
- Do not create a duplicate pull request if an open PR already exists for the target Lance version.
|
||||
- If any command fails, diagnose and fix the root cause instead of aborting.
|
||||
- After creating the PR, display the PR URL, "git status --short", and a concise summary of the commands run and their results.
|
||||
- Use bash commands; avoid modifying GitHub workflow files other than through the scripted task above.
|
||||
- Do not merge the PR.
|
||||
- If any command fails, diagnose and fix the issue instead of aborting.
|
||||
EOF
|
||||
|
||||
printenv OPENAI_API_KEY | codex login --with-api-key
|
||||
codex --config shell_environment_policy.ignore_default_excludes=true exec --dangerously-bypass-approvals-and-sandbox "$(cat /tmp/codex-prompt.txt)"
|
||||
|
||||
- name: Trigger sophon dependency update
|
||||
env:
|
||||
TAG: ${{ inputs.tag }}
|
||||
GH_TOKEN: ${{ secrets.ROBOT_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
VERSION="${TAG#refs/tags/}"
|
||||
VERSION="${VERSION#v}"
|
||||
LANCEDB_BRANCH="codex/update-lance-${VERSION//[^a-zA-Z0-9]/-}"
|
||||
|
||||
echo "Triggering sophon workflow with:"
|
||||
echo " lance_ref: ${TAG#refs/tags/}"
|
||||
echo " lancedb_ref: ${LANCEDB_BRANCH}"
|
||||
|
||||
gh workflow run codex-bump-lancedb-lance.yml \
|
||||
--repo lancedb/sophon \
|
||||
-f lance_ref="${TAG#refs/tags/}" \
|
||||
-f lancedb_ref="${LANCEDB_BRANCH}"
|
||||
|
||||
- name: Show latest sophon workflow run
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.ROBOT_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "Latest sophon workflow run:"
|
||||
gh run list --repo lancedb/sophon --workflow codex-bump-lancedb-lance.yml --limit 1 --json databaseId,url,displayTitle
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
name: Verify PR title / description conforms to semantic-release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "18"
|
||||
# These rules are disabled because Github will always ensure there
|
||||
|
||||
@@ -1,222 +0,0 @@
|
||||
name: Check doc links
|
||||
|
||||
# Checking external links is inherently noisy: third-party sites rate-limit
|
||||
# automated clients, reject non-browser user agents, and go down temporarily.
|
||||
# Blocking pull requests on that trades a lot of false failures for very little
|
||||
# signal, so this runs on a schedule and reports findings in a single tracking
|
||||
# issue instead of failing anyone's build.
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 7 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
# The report lives in one repository-global issue, so runs must not overlap: a
|
||||
# lookup racing a create produces duplicate issues, and a healthy run closing
|
||||
# the issue while a failing run only rewrites its body would leave a broken
|
||||
# report closed. The group is deliberately ref-independent so that a manual
|
||||
# dispatch serializes against the scheduled run.
|
||||
concurrency:
|
||||
group: docs-link-check
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions: {}
|
||||
|
||||
env:
|
||||
REPORT_TITLE: "Docs link checker report"
|
||||
|
||||
jobs:
|
||||
scan:
|
||||
name: Scan links
|
||||
runs-on: ubuntu-24.04
|
||||
# lychee-action is pinned by SHA, but its wrapper downloads the lychee
|
||||
# release tarball at run time without verifying a digest, and hands the
|
||||
# resulting binary a GitHub token. Release assets remain replaceable, so
|
||||
# that binary is confined to a job whose token can only read public
|
||||
# content; everything that writes runs in the report job below.
|
||||
permissions:
|
||||
contents: read
|
||||
outputs:
|
||||
exit_code: ${{ steps.lychee.outputs.exit_code }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
# workflow_dispatch can run from any ref, but the report is
|
||||
# repository-global. Always measure the default branch so a manual
|
||||
# run from a topic branch cannot close a report that main warrants,
|
||||
# or overwrite it with branch-only findings.
|
||||
ref: ${{ github.event.repository.default_branch }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Check links
|
||||
id: lychee
|
||||
uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0
|
||||
with:
|
||||
# Restricted to http(s) on purpose. Much of docs/src is generated
|
||||
# API reference (the js/ tree comes from `npm run docs` in nodejs)
|
||||
# and the hand-written pages use mkdocstrings cross-references and
|
||||
# nav-relative paths that only resolve in the site mkdocs builds,
|
||||
# not in this checkout, so relative links would be reported as
|
||||
# broken on every run.
|
||||
args: >-
|
||||
--scheme https
|
||||
--scheme http
|
||||
--no-progress
|
||||
--max-retries 3
|
||||
--timeout 20
|
||||
'docs/src/**/*.md'
|
||||
format: json
|
||||
output: ./lychee/out.json
|
||||
jobSummary: false
|
||||
# The report, not a red build, is the signal for broken links. The
|
||||
# validation step below still fails the run if the check itself
|
||||
# breaks.
|
||||
fail: false
|
||||
|
||||
- name: Validate report
|
||||
# lychee does not reserve exit code 2 for broken links: its CLI
|
||||
# parser also exits 2 on an invalid option, before any link was
|
||||
# checked or any report written. Only a parseable report whose
|
||||
# counts agree with the exit code counts as a link verdict; anything
|
||||
# else fails here, and the report job below is skipped entirely, so
|
||||
# the tracking issue is never touched. Exit 2 covers timeouts as
|
||||
# well as errors, and a timed-out host is exactly the transient
|
||||
# unavailability this report exists to surface, so both count as
|
||||
# findings. Requiring total > 0 also catches a glob that silently
|
||||
# stopped matching any file.
|
||||
if: steps.lychee.outputs.exit_code == 0 || steps.lychee.outputs.exit_code == 2
|
||||
env:
|
||||
EXIT_CODE: ${{ steps.lychee.outputs.exit_code }}
|
||||
run: |
|
||||
jq -e --argjson code "$EXIT_CODE" '
|
||||
(.total > 0) and
|
||||
(if $code == 0
|
||||
then .errors == 0 and .timeouts == 0
|
||||
and (.error_map | length == 0) and (.timeout_map | length == 0)
|
||||
else (.errors + .timeouts) > 0
|
||||
and ((.error_map | length) + (.timeout_map | length)) > 0
|
||||
end)
|
||||
' ./lychee/out.json
|
||||
|
||||
- name: Upload report
|
||||
if: steps.lychee.outputs.exit_code == 2
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: link-report
|
||||
path: ./lychee/out.json
|
||||
retention-days: 7
|
||||
|
||||
report:
|
||||
name: Update report issue
|
||||
needs: scan
|
||||
runs-on: ubuntu-24.04
|
||||
# Deliberately no checkout: this job needs the report artifact and the
|
||||
# issues API, not the repository contents.
|
||||
permissions:
|
||||
issues: write
|
||||
env:
|
||||
EXIT_CODE: ${{ needs.scan.outputs.exit_code }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
steps:
|
||||
- name: Classify checker result
|
||||
# lychee exits 0 when every link resolves and 2 when links fail,
|
||||
# both already cross-checked against the report by the scan job's
|
||||
# validation step. Anything else (1 runtime, 3 bad config) means the
|
||||
# check never produced a link verdict, which must surface as a failed
|
||||
# run rather than be published as "broken documentation links".
|
||||
run: |
|
||||
case "$EXIT_CODE" in
|
||||
0|2)
|
||||
echo "lychee exit code $EXIT_CODE"
|
||||
;;
|
||||
*)
|
||||
echo "::error::lychee exited with '$EXIT_CODE': the link check did not complete. Leaving the report issue untouched."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
- name: Find existing report issue
|
||||
id: report
|
||||
# Matched on title alone, and through search rather than a listing:
|
||||
# the issue action applies labels in a separate call after creating the
|
||||
# issue, so a label filter misses a half-created report, and this
|
||||
# repository has far more open issues than one listing page holds.
|
||||
# Closed issues are included because a healthy run closes the report:
|
||||
# an open-only lookup would forget that identity and the next failing
|
||||
# run would open a duplicate. The oldest match stays the canonical
|
||||
# report and is reopened below when links break again.
|
||||
run: |
|
||||
match=$(gh issue list --repo "$GITHUB_REPOSITORY" --state all \
|
||||
--search "in:title \"$REPORT_TITLE\" author:app/github-actions" \
|
||||
--limit 50 --json number,title,state \
|
||||
--jq "[.[] | select(.title == \"$REPORT_TITLE\")] | sort_by(.number) | first // empty")
|
||||
echo "number=$(jq -r '.number // empty' <<<"$match")" >> "$GITHUB_OUTPUT"
|
||||
echo "state=$(jq -r '.state // empty' <<<"$match")" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Download report
|
||||
if: env.EXIT_CODE == 2
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: link-report
|
||||
path: ./lychee
|
||||
|
||||
- name: Compose report
|
||||
if: env.EXIT_CODE == 2
|
||||
run: |
|
||||
run_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
|
||||
{
|
||||
echo "Broken documentation links found by [\`$GITHUB_WORKFLOW\`]($run_url)."
|
||||
echo
|
||||
echo "This issue is rewritten by every scheduled run and closed automatically once all links resolve."
|
||||
echo
|
||||
echo "Entries can be false positives: some sites rate-limit or block automated clients while working fine in a browser. Confirm before editing the docs, and add persistent offenders to \`--exclude\` in \`.github/workflows/docs-link-check.yml\`."
|
||||
echo
|
||||
# Timeouts are reported alongside errors: entries land in
|
||||
# timeout_map with a status text instead of an HTTP code.
|
||||
jq -r '
|
||||
"\(.errors) of \(.total) links failed, \(.timeouts) timed out.",
|
||||
"",
|
||||
([(.error_map | to_entries[]), (.timeout_map | to_entries[])]
|
||||
| group_by(.key)[] |
|
||||
"### Errors in \(.[0].key)",
|
||||
"",
|
||||
(map(.value[])[] | "* [\(.status.code // .status.text // "ERR")] <\(.url)> — \(.status.details // .status.text // "unknown error")"),
|
||||
"")
|
||||
' ./lychee/out.json
|
||||
} > ./lychee/issue.md
|
||||
|
||||
- name: Reopen report issue
|
||||
# A healthy run closes the report, and the issue action below only
|
||||
# rewrites the body of whatever number it is given. Without an
|
||||
# explicit reopen, the 2 -> 0 -> 2 sequence would keep rewriting a
|
||||
# closed issue while links are broken. A CLOSED state implies the
|
||||
# lookup found a canonical issue, so no separate emptiness check.
|
||||
if: env.EXIT_CODE == 2 && steps.report.outputs.state == 'CLOSED'
|
||||
env:
|
||||
ISSUE_NUMBER: ${{ steps.report.outputs.number }}
|
||||
run: |
|
||||
run_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
|
||||
gh issue reopen "$ISSUE_NUMBER" --repo "$GITHUB_REPOSITORY" \
|
||||
--comment "Broken documentation links found again in [the latest run]($run_url)."
|
||||
|
||||
- name: Report broken links
|
||||
if: env.EXIT_CODE == 2
|
||||
uses: peter-evans/create-issue-from-file@fca9117c27cdc29c6c4db3b86c48e4115a786710 # v6.0.0
|
||||
with:
|
||||
# Empty on the first failing run, which creates the issue; afterwards
|
||||
# the same issue is updated in place.
|
||||
issue-number: ${{ steps.report.outputs.number }}
|
||||
title: ${{ env.REPORT_TITLE }}
|
||||
content-filepath: ./lychee/issue.md
|
||||
labels: documentation
|
||||
|
||||
- name: Close report issue once links are healthy
|
||||
# An OPEN state implies the lookup found a canonical issue; a report
|
||||
# that is already closed needs nothing.
|
||||
if: env.EXIT_CODE == 0 && steps.report.outputs.state == 'OPEN'
|
||||
env:
|
||||
ISSUE_NUMBER: ${{ steps.report.outputs.number }}
|
||||
run: |
|
||||
run_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
|
||||
gh issue close "$ISSUE_NUMBER" --repo "$GITHUB_REPOSITORY" \
|
||||
--comment "All documentation links resolved in [the latest run]($run_url)."
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
- name: Install dependencies needed for ubuntu
|
||||
run: |
|
||||
sudo apt install -y protobuf-compiler libssl-dev
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
python -m pip install --extra-index-url https://pypi.fury.io/lance-format/ --extra-index-url https://pypi.fury.io/lancedb/ -e .
|
||||
python -m pip install --extra-index-url https://pypi.fury.io/lance-format/ --extra-index-url https://pypi.fury.io/lancedb/ -r ../docs/requirements.txt
|
||||
- name: Set up node
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: 'npm'
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
name: GitHub Release
|
||||
|
||||
# All SDKs share one version, so a single `vX.Y.Z` tag produces a single GitHub
|
||||
# release covering all of them. The per-package publish workflows (PyPI, NPM,
|
||||
# Cargo, Maven) trigger off the same tag independently.
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
gh-release:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
- name: Extract version
|
||||
id: extract_version
|
||||
env:
|
||||
GITHUB_REF: ${{ github.ref }}
|
||||
run: |
|
||||
set -e
|
||||
echo "Extracting tag and version from $GITHUB_REF"
|
||||
if [[ $GITHUB_REF =~ refs/tags/v(.*) ]]; then
|
||||
VERSION=${BASH_REMATCH[1]}
|
||||
TAG=v$VERSION
|
||||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Failed to extract version from $GITHUB_REF"
|
||||
exit 1
|
||||
fi
|
||||
echo "Extracted version $VERSION from $GITHUB_REF"
|
||||
if [[ $VERSION =~ beta ]]; then
|
||||
echo "This is a beta release"
|
||||
echo "prerelease=true" >> $GITHUB_OUTPUT
|
||||
|
||||
# Get last release (that is not this one)
|
||||
FROM_TAG=$(git tag --sort='version:refname' \
|
||||
| grep ^v \
|
||||
| grep -vF "$TAG" \
|
||||
| python ci/semver_sort.py v \
|
||||
| tail -n 1)
|
||||
else
|
||||
echo "This is a stable release"
|
||||
echo "prerelease=false" >> $GITHUB_OUTPUT
|
||||
# Get last stable tag (ignore betas)
|
||||
FROM_TAG=$(git tag --sort='version:refname' \
|
||||
| grep ^v \
|
||||
| grep -vF "$TAG" \
|
||||
| grep -v beta \
|
||||
| python ci/semver_sort.py v \
|
||||
| tail -n 1)
|
||||
fi
|
||||
echo "Found from tag $FROM_TAG"
|
||||
echo "from_tag=$FROM_TAG" >> $GITHUB_OUTPUT
|
||||
- name: Create Release Notes
|
||||
id: release_notes
|
||||
uses: mikepenz/release-changelog-builder-action@v4
|
||||
with:
|
||||
configuration: .github/release_notes.json
|
||||
toTag: ${{ steps.extract_version.outputs.tag }}
|
||||
fromTag: ${{ steps.extract_version.outputs.from_tag }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Create GH release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
# Marking betas as pre-releases keeps them from taking the "Latest"
|
||||
# badge on the releases page.
|
||||
prerelease: ${{ steps.extract_version.outputs.prerelease }}
|
||||
make_latest: ${{ steps.extract_version.outputs.prerelease == 'false' }}
|
||||
tag_name: ${{ steps.extract_version.outputs.tag }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
generate_release_notes: false
|
||||
name: LanceDB v${{ steps.extract_version.outputs.version }}
|
||||
body: ${{ steps.release_notes.outputs.changelog }}
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
working-directory: ./java
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Java 8
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
contents: read
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/create-failure-issue
|
||||
with:
|
||||
job-results: ${{ toJSON(needs) }}
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
working-directory: ./java
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Java 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
name: Lance Release Timer
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "*/10 * * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write
|
||||
|
||||
concurrency:
|
||||
group: lance-release-timer
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
trigger-update:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check for new Lance tag
|
||||
id: check
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.ROBOT_TOKEN }}
|
||||
run: |
|
||||
python3 ci/check_lance_release.py --github-output "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Look for existing PR
|
||||
if: steps.check.outputs.needs_update == 'true'
|
||||
id: pr
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.ROBOT_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TITLE="chore: update lance dependency to v${{ steps.check.outputs.latest_version }}"
|
||||
COUNT=$(gh pr list --search "\"$TITLE\" in:title" --state open --limit 1 --json number --jq 'length')
|
||||
if [ "$COUNT" -gt 0 ]; then
|
||||
echo "Open PR already exists for $TITLE"
|
||||
echo "pr_exists=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "No existing PR for $TITLE"
|
||||
echo "pr_exists=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Trigger codex update workflow
|
||||
if: steps.check.outputs.needs_update == 'true' && steps.pr.outputs.pr_exists != 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.ROBOT_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TAG=${{ steps.check.outputs.latest_tag }}
|
||||
gh workflow run codex-update-lance-dependency.yml -f tag=refs/tags/$TAG
|
||||
|
||||
- name: Show latest codex workflow run
|
||||
if: steps.check.outputs.needs_update == 'true' && steps.pr.outputs.pr_exists != 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.ROBOT_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
gh run list --workflow codex-update-lance-dependency.yml --limit 1 --json databaseId,url,displayTitle
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
- name: Install license-header-checker
|
||||
working-directory: /tmp
|
||||
run: |
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
name: Create release commit
|
||||
|
||||
# This workflow increments the version, tags it, and pushes it. All SDKs share
|
||||
# a single version, so one tag releases all of them.
|
||||
# This workflow increments versions, tags the version, and pushes it.
|
||||
# When a tag is pushed, another workflow is triggered that creates a GH release
|
||||
# and uploads the binaries. This workflow is only for creating the tag.
|
||||
|
||||
# This script will enforce that a minor version is incremented if there are any
|
||||
# breaking changes since the last minor increment. A breaking change in any SDK
|
||||
# bumps the minor version for all of them. If you wish to bypass this check, you
|
||||
# can manually increment the version and push the tag.
|
||||
# breaking changes since the last minor increment. However, it isn't able to
|
||||
# differentiate between breaking changes in Node versus Python. If you wish to
|
||||
# bypass this check, you can manually increment the version and push the tag.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
@@ -25,6 +24,16 @@ on:
|
||||
options:
|
||||
- preview
|
||||
- stable
|
||||
python:
|
||||
description: 'Make a Python release'
|
||||
required: true
|
||||
default: true
|
||||
type: boolean
|
||||
other:
|
||||
description: 'Make a Node/Rust/Java release'
|
||||
required: true
|
||||
default: true
|
||||
type: boolean
|
||||
bump-minor:
|
||||
description: 'Bump minor version'
|
||||
required: true
|
||||
@@ -40,7 +49,7 @@ jobs:
|
||||
steps:
|
||||
- name: Output Inputs
|
||||
run: echo "${{ toJSON(github.event.inputs) }}"
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
@@ -56,16 +65,29 @@ jobs:
|
||||
run: |
|
||||
git config user.name 'Lance Release'
|
||||
git config user.email 'lance-dev@lancedb.com'
|
||||
- name: Bump version
|
||||
- name: Bump Python version
|
||||
if: ${{ inputs.python }}
|
||||
working-directory: python
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# Need to get the commit before bumping the version, so we can
|
||||
# determine if there are breaking changes in the next step as well.
|
||||
echo "COMMIT_BEFORE_BUMP=$(git rev-parse HEAD)" >> $GITHUB_ENV
|
||||
|
||||
pip install bump-my-version PyGithub packaging
|
||||
bash ../ci/bump_version.sh ${{ inputs.type }} ${{ inputs.bump-minor }} python-v
|
||||
- name: Bump Node/Rust version
|
||||
if: ${{ inputs.other }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
pip install bump-my-version PyGithub packaging
|
||||
bash ci/bump_version.sh ${{ inputs.type }} ${{ inputs.bump-minor }}
|
||||
bash ci/bump_version.sh ${{ inputs.type }} ${{ inputs.bump-minor }} v $COMMIT_BEFORE_BUMP
|
||||
bash ci/update_lockfiles.sh --amend
|
||||
- name: Push new version tag
|
||||
if: ${{ !inputs.dry_run }}
|
||||
uses: ad-m/github-push-action@881a6320fdb16eb5318c5054f31c218aec2b324c # v1.3.0
|
||||
uses: ad-m/github-push-action@master
|
||||
with:
|
||||
# Need to use PAT here too to trigger next workflow. See comment above.
|
||||
github_token: ${{ secrets.LANCEDB_RELEASE_TOKEN }}
|
||||
|
||||
@@ -38,14 +38,14 @@ jobs:
|
||||
CC: gcc-12
|
||||
CXX: g++-12
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
- uses: pnpm/action-setup@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 11.1.1
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
# pnpm 11 requires Node >= 22.13; use 24 since 22 hits EOL
|
||||
# in October. The library itself still supports Node >= 18
|
||||
@@ -61,11 +61,6 @@ jobs:
|
||||
sudo apt update
|
||||
sudo apt install -y protobuf-compiler libssl-dev
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. Per-PR saves are
|
||||
# unreadable outside their own branch anyway, since GitHub scopes
|
||||
# caches to the creating ref.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Format Rust
|
||||
run: cargo fmt --all -- --check
|
||||
- name: Lint Rust
|
||||
@@ -91,14 +86,14 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: nodejs
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
- uses: pnpm/action-setup@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 11.1.1
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
name: Setup Node.js 24 for build
|
||||
with:
|
||||
# pnpm 11 requires Node >= 22.13; use 24 since 22 hits EOL
|
||||
@@ -108,11 +103,6 @@ jobs:
|
||||
cache: 'pnpm'
|
||||
cache-dependency-path: nodejs/pnpm-lock.yaml
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. Per-PR saves are
|
||||
# unreadable outside their own branch anyway, since GitHub scopes
|
||||
# caches to the creating ref.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
@@ -140,7 +130,7 @@ jobs:
|
||||
echo "Run 'pnpm run docs', fix any warnings, and commit the changes."
|
||||
exit 1
|
||||
fi
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
name: Setup Node.js ${{ matrix.node-version }} for test
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
@@ -176,14 +166,14 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: nodejs
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
- uses: pnpm/action-setup@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 11.1.1
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
# pnpm 11 requires Node >= 22.13; use 24 since 22 hits EOL
|
||||
# in October.
|
||||
@@ -192,11 +182,6 @@ jobs:
|
||||
cache-dependency-path: nodejs/pnpm-lock.yaml
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. Per-PR saves are
|
||||
# unreadable outside their own branch anyway, since GitHub scopes
|
||||
# caches to the creating ref.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install protobuf
|
||||
|
||||
+101
-116
@@ -10,16 +10,10 @@ permissions:
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags:
|
||||
- "v*"
|
||||
# The cross-compiled targets (musl especially) break from toolchain and
|
||||
# dependency changes that nothing else in CI catches, and discovering that
|
||||
# mid-release is expensive. A nightly run keeps that signal while dropping
|
||||
# the full 8-target release matrix from all ~90 pushes to main each month.
|
||||
# `report-failure` files an issue when a nightly breaks.
|
||||
schedule:
|
||||
- cron: "0 8 * * *"
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
# This should trigger a dry run (we skip the final publish step)
|
||||
paths:
|
||||
@@ -32,6 +26,73 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
gh-release:
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
- name: Extract version
|
||||
id: extract_version
|
||||
env:
|
||||
GITHUB_REF: ${{ github.ref }}
|
||||
run: |
|
||||
set -e
|
||||
echo "Extracting tag and version from $GITHUB_REF"
|
||||
if [[ $GITHUB_REF =~ refs/tags/v(.*) ]]; then
|
||||
VERSION=${BASH_REMATCH[1]}
|
||||
TAG=v$VERSION
|
||||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Failed to extract version from $GITHUB_REF"
|
||||
exit 1
|
||||
fi
|
||||
echo "Extracted version $VERSION from $GITHUB_REF"
|
||||
if [[ $VERSION =~ beta ]]; then
|
||||
echo "This is a beta release"
|
||||
|
||||
# Get last release (that is not this one)
|
||||
FROM_TAG=$(git tag --sort='version:refname' \
|
||||
| grep ^v \
|
||||
| grep -vF "$TAG" \
|
||||
| python ci/semver_sort.py v \
|
||||
| tail -n 1)
|
||||
else
|
||||
echo "This is a stable release"
|
||||
# Get last stable tag (ignore betas)
|
||||
FROM_TAG=$(git tag --sort='version:refname' \
|
||||
| grep ^v \
|
||||
| grep -vF "$TAG" \
|
||||
| grep -v beta \
|
||||
| python ci/semver_sort.py v \
|
||||
| tail -n 1)
|
||||
fi
|
||||
echo "Found from tag $FROM_TAG"
|
||||
echo "from_tag=$FROM_TAG" >> $GITHUB_OUTPUT
|
||||
- name: Create Release Notes
|
||||
id: release_notes
|
||||
uses: mikepenz/release-changelog-builder-action@v4
|
||||
with:
|
||||
configuration: .github/release_notes.json
|
||||
toTag: ${{ steps.extract_version.outputs.tag }}
|
||||
fromTag: ${{ steps.extract_version.outputs.from_tag }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Create GH release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
prerelease: ${{ contains('beta', github.ref) }}
|
||||
tag_name: ${{ steps.extract_version.outputs.tag }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
generate_release_notes: false
|
||||
name: Node/Rust LanceDB v${{ steps.extract_version.outputs.version }}
|
||||
body: ${{ steps.release_notes.outputs.changelog }}
|
||||
|
||||
build-lancedb:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -40,18 +101,9 @@ jobs:
|
||||
- target: aarch64-apple-darwin
|
||||
host: macos-latest
|
||||
features: fp16kernels
|
||||
pre_build: |-
|
||||
brew install protobuf
|
||||
# Fat LTO (the workspace default in .cargo/config.toml) is
|
||||
# single-threaded and is the peak-memory step of the build. On
|
||||
# this runner it accounted for ~111 of the job's ~113 minutes,
|
||||
# making it the critical path of the entire publish pipeline.
|
||||
# ThinLTO parallelizes it across the runner's cores, for a few
|
||||
# percent of runtime performance.
|
||||
export CARGO_PROFILE_RELEASE_LTO=thin
|
||||
export CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16
|
||||
pre_build: brew install protobuf
|
||||
- target: x86_64-pc-windows-msvc
|
||||
host: windows-2025
|
||||
host: windows-latest
|
||||
features: ","
|
||||
pre_build: |-
|
||||
choco install --no-progress protoc ninja nasm
|
||||
@@ -59,21 +111,12 @@ jobs:
|
||||
# There is an issue where choco doesn't add nasm to the path
|
||||
export PATH="$PATH:/c/Program Files/NASM"
|
||||
nasm -v
|
||||
# See the ThinLTO note on aarch64-apple-darwin above. Keeping
|
||||
# peak memory down is also what lets this run on the standard
|
||||
# 4-core runner: the 8-core larger runner was only needed to
|
||||
# stop fat LTO from OOMing rustc-LLVM.
|
||||
export CARGO_PROFILE_RELEASE_LTO=thin
|
||||
export CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16
|
||||
- target: aarch64-pc-windows-msvc
|
||||
host: windows-2025
|
||||
host: windows-latest
|
||||
features: ","
|
||||
pre_build: |-
|
||||
choco install --no-progress protoc
|
||||
rustup target add aarch64-pc-windows-msvc
|
||||
# See the ThinLTO note on aarch64-apple-darwin above.
|
||||
export CARGO_PROFILE_RELEASE_LTO=thin
|
||||
export CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
host: ubuntu-latest
|
||||
features: fp16kernels
|
||||
@@ -127,13 +170,13 @@ jobs:
|
||||
run:
|
||||
working-directory: nodejs
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 11.1.1
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
# pnpm 11 requires Node >= 22.13; use 24 since 22 hits EOL
|
||||
# in October.
|
||||
@@ -146,49 +189,16 @@ jobs:
|
||||
with:
|
||||
toolchain: stable
|
||||
targets: ${{ matrix.settings.target }}
|
||||
# These builds were entirely uncached: the old key was static, so
|
||||
# `actions/cache` (which only writes on a miss) could never refresh it,
|
||||
# and the multi-GB whole-`target/` copy it tried to store never fit the
|
||||
# repo's cache budget, so no entry was ever saved. rust-cache prunes
|
||||
# `target/` to dependency artifacts and keys on Cargo.lock plus the rustc
|
||||
# version, which both fixes the key and keeps entries a sane size.
|
||||
#
|
||||
# This caches dependency *compilation* only. The LTO link of the cdylib
|
||||
# re-runs regardless, since the local crate changes every time, so the
|
||||
# win is larger on the non-LTO jobs than here.
|
||||
- name: Cache cargo (native builds)
|
||||
uses: Swatinem/rust-cache@v2
|
||||
if: ${{ !matrix.settings.docker }}
|
||||
- name: Cache cargo
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
# The release profile and per-target dirs differ from what the test
|
||||
# workflows cache, so these need to be separate entries.
|
||||
key: release-${{ matrix.settings.target }}
|
||||
# Only the nightly run on main writes, so tag and PR runs restore a
|
||||
# warm entry without every dependabot PR writing its own (which would
|
||||
# be unreadable elsewhere anyway, since GitHub scopes caches to the
|
||||
# creating ref). The nightly cadence also keeps entries inside
|
||||
# GitHub's 7-day eviction window, which a tag-only trigger would not.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
# Docker builds can use rust-cache too. `target/` already lives on the
|
||||
# host because the whole workspace is bind-mounted into the container, and
|
||||
# rust-cache's prune and save run host-side, so they can manage it -- which
|
||||
# is what keeps the entry to dependency artifacts rather than a multi-GB
|
||||
# copy of everything.
|
||||
#
|
||||
# Two differences from the native builds. The container's CARGO_HOME is
|
||||
# bind-mounted from `.cargo-cache` rather than the host's ~/.cargo, so that
|
||||
# has to be cached explicitly. And the key is derived from the *host* rustc
|
||||
# version, which is not the compiler that produced these artifacts; that is
|
||||
# safe because cargo fingerprints the real compiler and rebuilds on a
|
||||
# mismatch, it just means a base-image toolchain bump costs one cold build
|
||||
# instead of invalidating the key.
|
||||
- name: Cache cargo (docker builds)
|
||||
uses: Swatinem/rust-cache@v2
|
||||
if: ${{ matrix.settings.docker }}
|
||||
with:
|
||||
key: docker-${{ matrix.settings.target }}
|
||||
cache-directories: .cargo-cache
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
path: |
|
||||
~/.cargo/registry/index/
|
||||
~/.cargo/registry/cache/
|
||||
~/.cargo/git/db/
|
||||
.cargo-cache
|
||||
target/
|
||||
key: nodejs-${{ matrix.settings.target }}-cargo-${{ matrix.settings.host }}
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Install Zig
|
||||
@@ -206,13 +216,9 @@ jobs:
|
||||
if: ${{ matrix.settings.docker }}
|
||||
with:
|
||||
image: ${{ matrix.settings.docker }}
|
||||
# All three mounts must live under `.cargo-cache`, which is what the
|
||||
# cache step above saves. Previously the registry mounts pointed at
|
||||
# `.cargo/...`, a path nothing cached, so the container re-downloaded
|
||||
# the whole crate registry on every run.
|
||||
options: "--user 0:0 -v ${{ github.workspace }}/.cargo-cache/git/db:/usr/local/cargo/git/db \
|
||||
-v ${{ github.workspace }}/.cargo-cache/registry/cache:/usr/local/cargo/registry/cache \
|
||||
-v ${{ github.workspace }}/.cargo-cache/registry/index:/usr/local/cargo/registry/index \
|
||||
-v ${{ github.workspace }}/.cargo/registry/cache:/usr/local/cargo/registry/cache \
|
||||
-v ${{ github.workspace }}/.cargo/registry/index:/usr/local/cargo/registry/index \
|
||||
-v ${{ github.workspace }}:/build -w /build/nodejs"
|
||||
run: |
|
||||
set -e
|
||||
@@ -224,16 +230,6 @@ jobs:
|
||||
--js ../lancedb/native.js \
|
||||
--strip \
|
||||
--output-dir dist/
|
||||
# The container runs as root (`--user 0:0`), so everything it wrote to the
|
||||
# mounted cache dirs is root-owned. rust-cache's post step runs as the
|
||||
# runner user and has to both read these and delete from them while
|
||||
# pruning, so hand them back before it runs.
|
||||
- name: Take ownership of docker build output
|
||||
if: ${{ matrix.settings.docker }}
|
||||
run: |
|
||||
sudo chown -R "$(id -u):$(id -g)" \
|
||||
"${{ github.workspace }}/.cargo-cache" \
|
||||
"${{ github.workspace }}/target"
|
||||
- name: Build
|
||||
run: |
|
||||
${{ matrix.settings.pre_build }}
|
||||
@@ -247,17 +243,8 @@ jobs:
|
||||
--output-dir dist/
|
||||
if: ${{ !matrix.settings.docker }}
|
||||
shell: bash
|
||||
# The standard Windows runners have ~14 GB free, and a release `target/`
|
||||
# for this workspace is a large fraction of that. Report the remaining
|
||||
# headroom so a build that only just fits is visible before a dependency
|
||||
# bump turns it into a failed release. `always()` so the numbers are
|
||||
# still there when the build is what ran out of space.
|
||||
- name: Report disk headroom
|
||||
if: always()
|
||||
run: df -h
|
||||
shell: bash
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: lancedb-${{ matrix.settings.target }}
|
||||
path: nodejs/dist/*.node
|
||||
@@ -269,7 +256,7 @@ jobs:
|
||||
run: pnpm tsc
|
||||
- name: Upload Generic Artifacts
|
||||
if: ${{ matrix.settings.target == 'aarch64-apple-darwin' }}
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: nodejs-dist
|
||||
path: |
|
||||
@@ -300,13 +287,13 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: nodejs
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 11.1.1
|
||||
- name: Setup Node.js 24 for install
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
# pnpm 11 requires Node >= 22.13; use 24 since 22 hits EOL
|
||||
# in October.
|
||||
@@ -316,18 +303,18 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
- name: Setup Node.js ${{ matrix.node }} for test
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: lancedb-${{ matrix.settings.target }}
|
||||
path: nodejs/dist/
|
||||
# For testing purposes:
|
||||
# run-id: 13982782871
|
||||
# github-token: ${{ secrets.GITHUB_TOKEN }} # token with actions:read permissions on target repo
|
||||
- uses: actions/download-artifact@v8
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: nodejs-dist
|
||||
path: nodejs/dist
|
||||
@@ -352,13 +339,13 @@ jobs:
|
||||
needs:
|
||||
- test-lancedb
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 11.1.1
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v6
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
cache: pnpm
|
||||
@@ -366,14 +353,14 @@ jobs:
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
- uses: actions/download-artifact@v8
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: nodejs-dist
|
||||
path: nodejs/dist
|
||||
# For testing purposes:
|
||||
# run-id: 13982782871
|
||||
# github-token: ${{ secrets.GITHUB_TOKEN }} # token with actions:read permissions on target repo
|
||||
- uses: actions/download-artifact@v8
|
||||
- uses: actions/download-artifact@v4
|
||||
name: Download arch-specific binaries
|
||||
with:
|
||||
pattern: lancedb-*
|
||||
@@ -406,14 +393,12 @@ jobs:
|
||||
name: Report Workflow Failure
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-lancedb, test-lancedb, publish]
|
||||
# Nightly runs are the only thing watching the cross-compiled targets now,
|
||||
# so they have to report failures too or the signal is silently lost.
|
||||
if: always() && failure() && (startsWith(github.ref, 'refs/tags/v') || github.event_name == 'schedule')
|
||||
if: always() && failure() && startsWith(github.ref, 'refs/tags/v')
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/create-failure-issue
|
||||
with:
|
||||
job-results: ${{ toJSON(needs) }}
|
||||
|
||||
@@ -3,7 +3,7 @@ name: PyPI Publish
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
- 'python-v*'
|
||||
pull_request:
|
||||
# This should trigger a dry run (we skip the final publish step)
|
||||
paths:
|
||||
@@ -20,45 +20,30 @@ env:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# Without this, a force-push to a PR leaves the previous run going -- including
|
||||
# a ~74 minute Windows job and a billed arm64 wheel build.
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
name: Python ${{ matrix.config.package_name }} ${{ matrix.config.platform }} manylinux${{ matrix.config.manylinux }}
|
||||
name: Python ${{ matrix.config.platform }} manylinux${{ matrix.config.manylinux }}
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
matrix:
|
||||
config:
|
||||
- platform: x86_64
|
||||
manylinux: "2_17"
|
||||
extra_args: ""
|
||||
runner: ubuntu-22.04
|
||||
- platform: x86_64
|
||||
manylinux: "2_28"
|
||||
extra_args: "--features fp16kernels"
|
||||
runner: ubuntu-22.04
|
||||
package_name: "lancedb"
|
||||
rustflags: ""
|
||||
# For successful fat LTO builds, we need a large runner to avoid OOM errors.
|
||||
- platform: aarch64
|
||||
manylinux: "2_17"
|
||||
extra_args: ""
|
||||
# For successful fat LTO builds, we need a large runner to avoid OOM errors.
|
||||
runner: ubuntu-2404-8x-arm64
|
||||
- platform: aarch64
|
||||
manylinux: "2_28"
|
||||
extra_args: "--features fp16kernels"
|
||||
runner: ubuntu-2404-8x-arm64
|
||||
package_name: "lancedb"
|
||||
rustflags: ""
|
||||
# `lancedb-compat`: pre-Haswell-friendly variant for x86_64 hosts
|
||||
# without AVX2 (Sandy Bridge / Ivy Bridge / Westmere on Intel,
|
||||
# Bulldozer / Piledriver / Steamroller on AMD). Compiled at the
|
||||
# `x86-64-v2` baseline; runtime SIMD dispatch in lance-linalg
|
||||
# picks the appropriate tier (scalar / AVX / AVX+FMA / AVX2+FMA
|
||||
# / AVX-512) at load time. Same import as `lancedb` -- conflicts
|
||||
# at install time, so users pick one.
|
||||
- platform: x86_64
|
||||
manylinux: "2_28"
|
||||
extra_args: ""
|
||||
runner: ubuntu-22.04
|
||||
package_name: "lancedb-compat"
|
||||
rustflags: "-Ctarget-cpu=x86-64-v2"
|
||||
runs-on: ${{ matrix.config.runner }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -75,13 +60,11 @@ jobs:
|
||||
args: "--release --strip ${{ matrix.config.extra_args }}"
|
||||
arm-build: ${{ matrix.config.platform == 'aarch64' }}
|
||||
manylinux: ${{ matrix.config.manylinux }}
|
||||
package-name: ${{ matrix.config.package_name }}
|
||||
rustflags: ${{ matrix.config.rustflags }}
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
if: startsWith(github.ref, 'refs/tags/python-v')
|
||||
with:
|
||||
name: wheels-linux-${{ matrix.config.package_name }}-${{ matrix.config.platform }}-${{ matrix.config.manylinux }}
|
||||
path: target/wheels/*.whl
|
||||
name: wheels-linux-${{ matrix.config.platform }}-${{ matrix.config.manylinux }}
|
||||
path: target/wheels/lancedb-*.whl
|
||||
if-no-files-found: error
|
||||
mac:
|
||||
timeout-minutes: 90
|
||||
@@ -107,7 +90,7 @@ jobs:
|
||||
python-minor-version: 10
|
||||
args: "--release --strip --target ${{ matrix.config.target }} --features fp16kernels"
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
if: startsWith(github.ref, 'refs/tags/python-v')
|
||||
with:
|
||||
name: wheels-mac-${{ matrix.config.target }}
|
||||
path: target/wheels/lancedb-*.whl
|
||||
@@ -128,26 +111,19 @@ jobs:
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.13"
|
||||
# NOTE: caching cargo here would be a no-op. This workflow only runs on
|
||||
# tags and PRs, and GitHub only lets a run restore caches from its own ref
|
||||
# or the default branch -- so with no run on main there is nothing that
|
||||
# can populate an entry the release build would be allowed to read. Fixing
|
||||
# this needs a main/nightly trigger (which would also catch wheel-build
|
||||
# breakage before a release); the ~74 minutes here is otherwise dominated
|
||||
# by the fat-LTO link, which no cache avoids.
|
||||
- uses: ./.github/workflows/build_windows_wheel
|
||||
with:
|
||||
python-minor-version: 10
|
||||
args: "--release --strip"
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
if: startsWith(github.ref, 'refs/tags/python-v')
|
||||
with:
|
||||
name: wheels-windows
|
||||
path: target/wheels/lancedb-*.whl
|
||||
if-no-files-found: error
|
||||
publish:
|
||||
name: Publish wheels
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
if: startsWith(github.ref, 'refs/tags/python-v')
|
||||
needs: [linux, mac, windows]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
@@ -177,7 +153,7 @@ jobs:
|
||||
FURY_TOKEN: ${{ secrets.FURY_TOKEN }}
|
||||
run: |
|
||||
shopt -s nullglob
|
||||
WHEELS=(target/wheels/*.whl)
|
||||
WHEELS=(target/wheels/lancedb-*.whl)
|
||||
if [[ ${#WHEELS[@]} -eq 0 ]]; then
|
||||
echo "No wheels found in target/wheels/" >&2
|
||||
exit 1
|
||||
@@ -196,6 +172,72 @@ jobs:
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
packages-dir: target/wheels/
|
||||
gh-release:
|
||||
if: startsWith(github.ref, 'refs/tags/python-v')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
- name: Extract version
|
||||
id: extract_version
|
||||
env:
|
||||
GITHUB_REF: ${{ github.ref }}
|
||||
run: |
|
||||
set -e
|
||||
echo "Extracting tag and version from $GITHUB_REF"
|
||||
if [[ $GITHUB_REF =~ refs/tags/python-v(.*) ]]; then
|
||||
VERSION=${BASH_REMATCH[1]}
|
||||
TAG=python-v$VERSION
|
||||
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Failed to extract version from $GITHUB_REF"
|
||||
exit 1
|
||||
fi
|
||||
echo "Extracted version $VERSION from $GITHUB_REF"
|
||||
if [[ $VERSION =~ beta ]]; then
|
||||
echo "This is a beta release"
|
||||
|
||||
# Get last release (that is not this one)
|
||||
FROM_TAG=$(git tag --sort='version:refname' \
|
||||
| grep ^python-v \
|
||||
| grep -vF "$TAG" \
|
||||
| python ci/semver_sort.py python-v \
|
||||
| tail -n 1)
|
||||
else
|
||||
echo "This is a stable release"
|
||||
# Get last stable tag (ignore betas)
|
||||
FROM_TAG=$(git tag --sort='version:refname' \
|
||||
| grep ^python-v \
|
||||
| grep -vF "$TAG" \
|
||||
| grep -v beta \
|
||||
| python ci/semver_sort.py python-v \
|
||||
| tail -n 1)
|
||||
fi
|
||||
echo "Found from tag $FROM_TAG"
|
||||
echo "from_tag=$FROM_TAG" >> $GITHUB_OUTPUT
|
||||
- name: Create Python Release Notes
|
||||
id: python_release_notes
|
||||
uses: mikepenz/release-changelog-builder-action@v4
|
||||
with:
|
||||
configuration: .github/release_notes.json
|
||||
toTag: ${{ steps.extract_version.outputs.tag }}
|
||||
fromTag: ${{ steps.extract_version.outputs.from_tag }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Create Python GH release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
prerelease: ${{ contains('beta', github.ref) }}
|
||||
tag_name: ${{ steps.extract_version.outputs.tag }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
generate_release_notes: false
|
||||
name: Python LanceDB v${{ steps.extract_version.outputs.version }}
|
||||
body: ${{ steps.python_release_notes.outputs.changelog }}
|
||||
report-failure:
|
||||
name: Report Workflow Failure
|
||||
runs-on: ubuntu-latest
|
||||
@@ -203,7 +245,7 @@ jobs:
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
if: always() && failure() && startsWith(github.ref, 'refs/tags/v')
|
||||
if: always() && failure() && startsWith(github.ref, 'refs/tags/python-v')
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/create-failure-issue
|
||||
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: python
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: python
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: python
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
@@ -108,15 +108,6 @@ jobs:
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y protobuf-compiler
|
||||
# `pip install -e .` builds the extension with maturin, which is most of
|
||||
# this job's ~33 minutes. It had no Rust cache, so every dependency was
|
||||
# recompiled from scratch on every run.
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. Per-PR saves are
|
||||
# unreadable outside their own branch anyway, since GitHub scopes
|
||||
# caches to the creating ref.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Install
|
||||
run: |
|
||||
pip install --extra-index-url https://pypi.fury.io/lance-format/ --extra-index-url https://pypi.fury.io/lancedb/ -e .[tests,dev,embeddings]
|
||||
@@ -135,7 +126,7 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: python
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
@@ -169,7 +160,7 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: python
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
@@ -177,14 +168,6 @@ jobs:
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.13"
|
||||
# maturin runs cargo natively on macOS (docker is Linux-only), so the host
|
||||
# target dir is cacheable. This job had no Rust cache.
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. Per-PR saves are
|
||||
# unreadable outside their own branch anyway, since GitHub scopes
|
||||
# caches to the creating ref.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- uses: ./.github/workflows/build_mac_wheel
|
||||
with:
|
||||
args: --profile ci
|
||||
@@ -206,7 +189,7 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: python
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
@@ -214,14 +197,6 @@ jobs:
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.13"
|
||||
# maturin runs cargo natively on Windows (docker is Linux-only), so the
|
||||
# host target dir is cacheable. This job had no Rust cache at all and so
|
||||
# rebuilt every dependency from scratch on every run.
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. The repo sits at
|
||||
# GitHub's cache cap, so per-PR saves just evict main's entries.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- uses: ./.github/workflows/build_windows_wheel
|
||||
with:
|
||||
args: --profile ci
|
||||
@@ -237,7 +212,7 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: python
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
@@ -249,14 +224,6 @@ jobs:
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.10"
|
||||
# As with Doctest, `pip install -e .` compiles the extension and this job
|
||||
# had no Rust cache, which is most of its ~37 minutes.
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. Per-PR saves are
|
||||
# unreadable outside their own branch anyway, since GitHub scopes
|
||||
# caches to the creating ref.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Install lancedb
|
||||
run: |
|
||||
pip install "pydantic<2"
|
||||
|
||||
+26
-82
@@ -40,7 +40,7 @@ jobs:
|
||||
CC: clang-18
|
||||
CXX: clang++-18
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
@@ -48,11 +48,6 @@ jobs:
|
||||
with:
|
||||
components: rustfmt, clippy
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. Per-PR saves are
|
||||
# unreadable outside their own branch anyway, since GitHub scopes
|
||||
# caches to the creating ref.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
@@ -70,7 +65,7 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- uses: EmbarkStudios/cargo-deny-action@v2
|
||||
with:
|
||||
command: check advisories bans licenses sources
|
||||
@@ -83,7 +78,7 @@ jobs:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
# Building without a lock file often requires the latest Rust version since downstream
|
||||
# dependencies may have updated their minimum Rust version.
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
@@ -94,11 +89,6 @@ jobs:
|
||||
run: rm -f Cargo.lock
|
||||
- uses: rui314/setup-mold@v1
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. Per-PR saves are
|
||||
# unreadable outside their own branch anyway, since GitHub scopes
|
||||
# caches to the creating ref.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
@@ -108,7 +98,7 @@ jobs:
|
||||
cargo build --profile ci --benches --all-features --tests
|
||||
|
||||
linux:
|
||||
timeout-minutes: 60
|
||||
timeout-minutes: 30
|
||||
# To build all features, we need more disk space than is available
|
||||
# on the free OSS github runner. This is mostly due to the the
|
||||
# sentence-transformers feature.
|
||||
@@ -123,16 +113,11 @@ jobs:
|
||||
CXX: clang++-18
|
||||
GH_TOKEN: ${{ secrets.SOPHON_READ_TOKEN }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. Per-PR saves are
|
||||
# unreadable outside their own branch anyway, since GitHub scopes
|
||||
# caches to the creating ref.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
@@ -140,26 +125,10 @@ jobs:
|
||||
- uses: rui314/setup-mold@v1
|
||||
- name: Make Swap
|
||||
run: |
|
||||
swapfile=/swapfile
|
||||
min_swap_bytes=$((15 * 1024 * 1024 * 1024))
|
||||
active_swap_bytes="$(sudo swapon --show=NAME,SIZE --bytes --noheadings | awk '$1 == "/swapfile" { print $2 }')"
|
||||
if [ -n "$active_swap_bytes" ]; then
|
||||
if [ "$active_swap_bytes" -ge "$min_swap_bytes" ]; then
|
||||
echo "/swapfile is already active with enough space; skipping swap creation"
|
||||
exit 0
|
||||
fi
|
||||
echo "/swapfile is already active but smaller than 16G; using /mnt/lancedb-swapfile"
|
||||
swapfile=/mnt/lancedb-swapfile
|
||||
fi
|
||||
if sudo swapon --show=NAME --noheadings | grep -Fxq "$swapfile"; then
|
||||
echo "$swapfile is already active; skipping swap creation"
|
||||
exit 0
|
||||
fi
|
||||
sudo rm -f "$swapfile"
|
||||
sudo fallocate -l 16G "$swapfile"
|
||||
sudo chmod 600 "$swapfile"
|
||||
sudo mkswap "$swapfile"
|
||||
sudo swapon "$swapfile"
|
||||
sudo fallocate -l 16G /swapfile
|
||||
sudo chmod 600 /swapfile
|
||||
sudo mkswap /swapfile
|
||||
sudo swapon /swapfile
|
||||
- name: Build
|
||||
run: cargo build --profile ci --all-features --tests --locked --examples
|
||||
- name: Run feature tests
|
||||
@@ -173,7 +142,7 @@ jobs:
|
||||
run: CARGO_ARGS="--profile ci" make -C ./lancedb remote-tests
|
||||
|
||||
macos:
|
||||
timeout-minutes: 60
|
||||
timeout-minutes: 30
|
||||
strategy:
|
||||
matrix:
|
||||
mac-runner: ["macos-14", "macos-15"]
|
||||
@@ -183,18 +152,13 @@ jobs:
|
||||
shell: bash
|
||||
working-directory: rust
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
lfs: true
|
||||
- name: CPU features
|
||||
run: sysctl -a | grep cpu
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. Per-PR saves are
|
||||
# unreadable outside their own branch anyway, since GitHub scopes
|
||||
# caches to the creating ref.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Install dependencies
|
||||
run: brew install protobuf
|
||||
- name: Run tests
|
||||
@@ -207,32 +171,20 @@ jobs:
|
||||
cargo test --profile ci --features $ALL_FEATURES --locked
|
||||
|
||||
windows:
|
||||
runs-on: windows-2022
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: x86_64-pc-windows-msvc
|
||||
runner: windows-2022
|
||||
# windows-11-arm is a standard runner, so it is free on public repos.
|
||||
# Running natively lets the aarch64 tests actually execute -- this
|
||||
# job used to cross-compile them and then skip the test step, paying
|
||||
# full codegen and link cost for a compile check.
|
||||
- target: aarch64-pc-windows-msvc
|
||||
runner: windows-11-arm
|
||||
runs-on: ${{ matrix.runner }}
|
||||
target:
|
||||
- x86_64-pc-windows-msvc
|
||||
- aarch64-pc-windows-msvc
|
||||
defaults:
|
||||
run:
|
||||
working-directory: rust/lancedb
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set target
|
||||
run: rustup target add ${{ matrix.target }}
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. Per-PR saves are
|
||||
# unreadable outside their own branch anyway, since GitHub scopes
|
||||
# caches to the creating ref.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Install Protoc v21.12
|
||||
run: choco install --no-progress protoc
|
||||
- name: Build
|
||||
@@ -240,12 +192,11 @@ jobs:
|
||||
$env:VCPKG_ROOT = $env:VCPKG_INSTALLATION_ROOT
|
||||
cargo build --profile ci --features aws,remote --tests --locked --target ${{ matrix.target }}
|
||||
- name: Run tests
|
||||
# Can only run tests when target matches host
|
||||
if: ${{ matrix.target == 'x86_64-pc-windows-msvc' }}
|
||||
run: |
|
||||
$env:VCPKG_ROOT = $env:VCPKG_INSTALLATION_ROOT
|
||||
# `--target` has to match the build step above. Without it cargo uses
|
||||
# target/ci/ rather than target/<triple>/ci/ and rebuilds the entire
|
||||
# dependency graph a second time.
|
||||
cargo test --profile ci --features aws,remote --locked --target ${{ matrix.target }}
|
||||
cargo test --profile ci --features aws,remote --locked
|
||||
|
||||
msrv:
|
||||
# Check the minimum supported Rust version
|
||||
@@ -259,7 +210,7 @@ jobs:
|
||||
CC: clang-18
|
||||
CXX: clang++-18
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Install dependencies
|
||||
@@ -271,11 +222,6 @@ jobs:
|
||||
with:
|
||||
toolchain: ${{ matrix.msrv }}
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
# Restore everywhere, but only save from main. Per-PR saves are
|
||||
# unreadable outside their own branch anyway, since GitHub scopes
|
||||
# caches to the creating ref.
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
- name: Downgrade dependencies
|
||||
# These packages have newer requirements for MSRV
|
||||
run: |
|
||||
@@ -296,18 +242,16 @@ jobs:
|
||||
cargo update -p aws-types --precise 1.3.9
|
||||
cargo update -p aws-sigv4 --precise 1.3.5
|
||||
cargo update -p aws-credential-types --precise 1.2.8
|
||||
# aws-smithy-checksums must stay at or above 0.63.13: OpenDAL's S3
|
||||
# service needs crc-fast ~1.9, and older releases pin it to ~1.3.
|
||||
cargo update -p aws-smithy-checksums --precise 0.63.13
|
||||
cargo update -p aws-smithy-checksums --precise 0.63.9
|
||||
cargo update -p aws-smithy-runtime --precise 1.9.3
|
||||
cargo update -p aws-smithy-http --precise 0.62.6
|
||||
cargo update -p aws-smithy-eventstream --precise 0.60.14
|
||||
cargo update -p aws-smithy-http --precise 0.62.4
|
||||
cargo update -p aws-smithy-eventstream --precise 0.60.12
|
||||
cargo update -p aws-smithy-http-client --precise 1.1.3
|
||||
cargo update -p aws-smithy-observability --precise 0.1.4
|
||||
cargo update -p aws-smithy-query --precise 0.60.8
|
||||
cargo update -p aws-smithy-runtime-api --precise 1.9.3
|
||||
cargo update -p aws-smithy-async --precise 1.2.7
|
||||
cargo update -p aws-smithy-types --precise 1.3.6
|
||||
cargo update -p aws-smithy-runtime-api --precise 1.9.1
|
||||
cargo update -p aws-smithy-async --precise 1.2.6
|
||||
cargo update -p aws-smithy-types --precise 1.3.5
|
||||
cargo update -p aws-smithy-xml --precise 0.60.11
|
||||
cargo update -p home --precise 0.5.9
|
||||
- name: cargo +${{ matrix.msrv }} check
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: main
|
||||
persist-credentials: false
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: main
|
||||
persist-credentials: false
|
||||
|
||||
@@ -27,7 +27,6 @@ python/dist
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
*.pdb
|
||||
|
||||
## Javascript
|
||||
*.node
|
||||
|
||||
@@ -92,8 +92,6 @@ Python bindings changes:
|
||||
* Should use `LOOP.run()` to call the corresponding `AsyncTable` method.
|
||||
6. Add concrete sync method to `RemoteTable` class in `python/python/lancedb/remote/table.py`.
|
||||
7. Add unit test in `python/tests/test_table.py`.
|
||||
8. If you added a new public class or module-level function (not just a method on an
|
||||
existing class), expose it in the API reference. See "Python API reference" below.
|
||||
|
||||
TypeScript bindings changes:
|
||||
|
||||
@@ -105,33 +103,6 @@ TypeScript bindings changes:
|
||||
5. Add test in `nodejs/__test__/table.test.ts`.
|
||||
6. Run `npm run docs` to generate TypeScript documentation.
|
||||
|
||||
## Python API reference
|
||||
|
||||
`docs/src/python/python.md` is the entire Python API reference. It is maintained by
|
||||
hand, and anything not listed there is not rendered at all, so new public classes and
|
||||
module-level functions have to be added explicitly. How depends on the module:
|
||||
|
||||
* `lancedb.index`, `lancedb.embeddings`, `lancedb.remote`, and `lancedb.rerankers` are
|
||||
rendered by a single directive each, driven by the module's `__all__`. Add the new
|
||||
name to `__all__` and it appears; forget, and it is silently omitted.
|
||||
* Everything else (`lancedb`, `lancedb.table`, `lancedb.query`, `lancedb.db`, ...) is
|
||||
listed symbol by symbol. Add a `::: lancedb.<module>.<Name>` line to the matching
|
||||
section, and remember that the page separates synchronous and asynchronous APIs.
|
||||
|
||||
Deliberately undocumented: concrete implementations reached through an abstract base
|
||||
(`LanceTable`, `LanceDBConnection`, `RemoteDBConnection`), query base classes already
|
||||
covered by `inherited_members`, and internal helpers.
|
||||
|
||||
Cross-references in docstrings use mkdocstrings syntax, `[text][lancedb.table.Table]`.
|
||||
Plain relative links such as `[Table](Table)` do not resolve. To check your work:
|
||||
|
||||
```shell
|
||||
pip install -r docs/requirements.txt
|
||||
cd docs && PYTHONPATH=. mkdocs build
|
||||
```
|
||||
|
||||
The docs site only builds on pushes to `main`, so this is not covered by PR CI.
|
||||
|
||||
## Review Guidelines
|
||||
|
||||
Please consider the following when reviewing code contributions.
|
||||
|
||||
Generated
+643
-1432
File diff suppressed because it is too large
Load Diff
+25
-28
@@ -1,6 +1,5 @@
|
||||
[workspace]
|
||||
members = ["rust/lancedb", "nodejs", "python"]
|
||||
exclude = ["lance-artifact"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
@@ -14,25 +13,24 @@ categories = ["database-implementations"]
|
||||
rust-version = "1.91.0"
|
||||
|
||||
[workspace.dependencies]
|
||||
lance = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a", default-features = false }
|
||||
lance-core = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a" }
|
||||
lance-datagen = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a" }
|
||||
lance-file = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a" }
|
||||
lance-io = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a", default-features = false }
|
||||
lance-index = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a" }
|
||||
lance-linalg = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a" }
|
||||
lance-namespace = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a" }
|
||||
lance-namespace-impls = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a", default-features = false }
|
||||
lance-table = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a" }
|
||||
lance-testing = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a" }
|
||||
lance-datafusion = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a" }
|
||||
lance-encoding = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a" }
|
||||
lance-arrow = { version = "=11.0.0-beta.3", git = "https://github.com/lancedb/lancedb.git", rev = "31b68dd21b60fcbee4354a175c9d65ff6ae02b6a" }
|
||||
lance = { "version" = "=7.0.0", default-features = false }
|
||||
lance-core = "=7.0.0"
|
||||
lance-datagen = "=7.0.0"
|
||||
lance-file = "=7.0.0"
|
||||
lance-io = { "version" = "=7.0.0", default-features = false }
|
||||
lance-index = "=7.0.0"
|
||||
lance-linalg = "=7.0.0"
|
||||
lance-namespace = "=7.0.0"
|
||||
lance-namespace-impls = { "version" = "=7.0.0", default-features = false }
|
||||
lance-table = "=7.0.0"
|
||||
lance-testing = "=7.0.0"
|
||||
lance-datafusion = "=7.0.0"
|
||||
lance-encoding = "=7.0.0"
|
||||
lance-arrow = "=7.0.0"
|
||||
ahash = "0.8"
|
||||
# Note that this one does not include pyarrow
|
||||
arrow = { version = "58.0.0", optional = false }
|
||||
arrow-array = "58.0.0"
|
||||
arrow-buffer = "58.0.0"
|
||||
arrow-data = "58.0.0"
|
||||
arrow-ipc = "58.0.0"
|
||||
arrow-ord = "58.0.0"
|
||||
@@ -40,23 +38,21 @@ arrow-schema = "58.0.0"
|
||||
arrow-select = "58.0.0"
|
||||
arrow-cast = "58.0.0"
|
||||
async-trait = "0"
|
||||
datafusion = { version = "54.0.0", default-features = false }
|
||||
datafusion-catalog = "54.0.0"
|
||||
datafusion-common = { version = "54.0.0", default-features = false }
|
||||
datafusion-execution = "54.0.0"
|
||||
datafusion-expr = "54.0.0"
|
||||
datafusion-functions = "54.0.0"
|
||||
datafusion-physical-plan = "54.0.0"
|
||||
datafusion-physical-expr = "54.0.0"
|
||||
datafusion-sql = "54.0.0"
|
||||
datafusion = { version = "53.0.0", default-features = false }
|
||||
datafusion-catalog = "53.0.0"
|
||||
datafusion-common = { version = "53.0.0", default-features = false }
|
||||
datafusion-execution = "53.0.0"
|
||||
datafusion-expr = "53.0.0"
|
||||
datafusion-functions = "53.0.0"
|
||||
datafusion-physical-plan = "53.0.0"
|
||||
datafusion-physical-expr = "53.0.0"
|
||||
datafusion-sql = "53.0.0"
|
||||
env_logger = "0.11"
|
||||
half = { "version" = "2.7.1", default-features = false, features = [
|
||||
"num-traits",
|
||||
] }
|
||||
futures = "0.3"
|
||||
futures = "0"
|
||||
log = "0.4"
|
||||
metrics = "0.24"
|
||||
metrics-util = "0.19"
|
||||
moka = { version = "0.12", features = ["future"] }
|
||||
object_store = "0.13.2"
|
||||
pin-project = "1.0.7"
|
||||
@@ -65,6 +61,7 @@ snafu = "0.8"
|
||||
url = "2"
|
||||
num-traits = "0.2"
|
||||
regex = "1.10"
|
||||
lazy_static = "1"
|
||||
semver = "1.0.25"
|
||||
chrono = "0.4"
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
# Code review guidelines
|
||||
|
||||
Repo-specific guidance for automated PR reviews.
|
||||
|
||||
## Cross-SDK parity
|
||||
|
||||
LanceDB exposes the same core (`rust/lancedb`) through Python, TypeScript (`nodejs`),
|
||||
and Java bindings. Behavioral drift between SDKs is a recurring problem, so watch for
|
||||
parity gaps when reviewing — but only flag real ones:
|
||||
|
||||
* If the change adds or modifies user-facing API or behavior in the shared core
|
||||
(`rust/lancedb`), check whether each binding that should expose it (`python`,
|
||||
`nodejs`) does. A core change with no corresponding binding update is worth a note.
|
||||
* If the change adds or modifies a public API in one SDK but not the other, open the
|
||||
sibling SDK's corresponding module and state whether an equivalent exists. If not,
|
||||
note it as a possible parity gap and suggest a follow-up issue.
|
||||
* For bug fixes, first read the sibling SDK's analogous code path to check whether the
|
||||
same bug exists there. Only raise parity if it actually does. Do not ask to "port" a
|
||||
fix for a bug that only ever existed in one binding.
|
||||
* Stay silent on internal-only refactors, tests, docs, and changes with no cross-SDK
|
||||
surface.
|
||||
* Parity expectations apply to the Python and TypeScript (`nodejs`) SDKs. Java currently
|
||||
implements only the remote table, not the local/embedded backend, so it is expected to
|
||||
be partial — do not flag Java for missing local-only functionality.
|
||||
* Keep parity feedback to a short, clearly-labeled note (e.g. "Possible SDK parity
|
||||
gap: …"). It is advisory, not a merge blocker.
|
||||
+3
-3
@@ -2,9 +2,9 @@ set -e
|
||||
|
||||
RELEASE_TYPE=${1:-"stable"}
|
||||
BUMP_MINOR=${2:-false}
|
||||
HEAD_SHA=$(git rev-parse HEAD)
|
||||
TAG_PREFIX=${3:-"v"} # Such as "python-v"
|
||||
HEAD_SHA=${4:-$(git rev-parse HEAD)}
|
||||
|
||||
readonly TAG_PREFIX="v"
|
||||
readonly SELF_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
|
||||
PREV_TAG=$(git tag --sort='version:refname' | grep ^$TAG_PREFIX | python $SELF_DIR/semver_sort.py $TAG_PREFIX | tail -n 1)
|
||||
@@ -12,7 +12,7 @@ echo "Found previous tag $PREV_TAG"
|
||||
|
||||
# Initially, we don't want to tag if we are doing stable, because we will bump
|
||||
# again later. See comment at end for why.
|
||||
if [[ "$RELEASE_TYPE" == 'stable' ]]; then
|
||||
if [[ "$RELEASE_TYPE" == 'stable' ]]; then
|
||||
BUMP_ARGS="--no-tag"
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Prepare a Lance dependency update for LanceDB."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Sequence
|
||||
|
||||
try:
|
||||
from check_lance_release import parse_semver
|
||||
except ModuleNotFoundError:
|
||||
# Supports importing as ci.update_lance_dependency from tests or ad hoc checks.
|
||||
from ci.check_lance_release import parse_semver # type: ignore
|
||||
|
||||
|
||||
def normalize_version(raw: str) -> str:
|
||||
value = raw.strip()
|
||||
value = value.removeprefix("refs/tags/")
|
||||
value = value.removeprefix("v")
|
||||
try:
|
||||
parse_semver(value)
|
||||
except ValueError:
|
||||
raise ValueError(f"Unsupported Lance version or tag: {raw}")
|
||||
return value
|
||||
|
||||
|
||||
def normalized_tag(version: str) -> str:
|
||||
return f"v{version}"
|
||||
|
||||
|
||||
def branch_name(version: str) -> str:
|
||||
suffix = re.sub(r"[^a-zA-Z0-9]+", "-", version).strip("-")
|
||||
suffix = re.sub(r"-+", "-", suffix)
|
||||
return f"codex/update-lance-{suffix}"
|
||||
|
||||
|
||||
def commit_type(version: str) -> str:
|
||||
prerelease = version.split("-", maxsplit=1)[1] if "-" in version else ""
|
||||
return "chore" if "beta" in prerelease or "rc" in prerelease else "feat"
|
||||
|
||||
|
||||
def metadata_for(version: str) -> dict[str, str]:
|
||||
kind = commit_type(version)
|
||||
message = f"{kind}: update lance dependency to v{version}"
|
||||
return {
|
||||
"version": version,
|
||||
"tag": normalized_tag(version),
|
||||
"branch_name": branch_name(version),
|
||||
"commit_type": kind,
|
||||
"commit_message": message,
|
||||
"pr_title": message,
|
||||
}
|
||||
|
||||
|
||||
def run_command(cmd: Sequence[str], *, cwd: Path) -> None:
|
||||
subprocess.run(cmd, cwd=cwd, check=True)
|
||||
|
||||
|
||||
def update_java_lance_core_version(repo_root: Path, version: str) -> None:
|
||||
pom_path = repo_root / "java" / "pom.xml"
|
||||
contents = pom_path.read_text(encoding="utf-8")
|
||||
updated, count = re.subn(
|
||||
r"(<lance-core\.version>)[^<]+(</lance-core\.version>)",
|
||||
rf"\g<1>{version}\g<2>",
|
||||
contents,
|
||||
count=1,
|
||||
)
|
||||
if count != 1:
|
||||
raise RuntimeError(
|
||||
"Expected exactly one <lance-core.version> entry in java/pom.xml"
|
||||
)
|
||||
pom_path.write_text(updated, encoding="utf-8")
|
||||
|
||||
|
||||
def write_github_outputs(path: str | None, payload: dict[str, str]) -> None:
|
||||
if not path:
|
||||
return
|
||||
with open(path, "a", encoding="utf-8") as output:
|
||||
for key, value in payload.items():
|
||||
output.write(f"{key}={value}\n")
|
||||
|
||||
|
||||
def main(argv: Sequence[str] | None = None) -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument(
|
||||
"tag_or_version",
|
||||
help="Lance tag or version, for example refs/tags/v7.2.0-beta.1 or 7.2.0",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--repo-root",
|
||||
type=Path,
|
||||
default=Path(__file__).resolve().parents[1],
|
||||
help="Path to the lancedb repository root",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--github-output",
|
||||
default=None,
|
||||
help="Optional GitHub Actions output file to receive metadata fields",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--metadata-only",
|
||||
action="store_true",
|
||||
help="Only print derived metadata; do not modify dependency files",
|
||||
)
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
repo_root = args.repo_root.resolve()
|
||||
version = normalize_version(args.tag_or_version)
|
||||
payload = metadata_for(version)
|
||||
|
||||
if not args.metadata_only:
|
||||
run_command([sys.executable, "ci/set_lance_version.py", version], cwd=repo_root)
|
||||
update_java_lance_core_version(repo_root, version)
|
||||
|
||||
write_github_outputs(args.github_output, payload)
|
||||
print(json.dumps(payload, sort_keys=True))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -51,6 +51,18 @@ ignore = [
|
||||
# https://rustsec.org/advisories/RUSTSEC-2024-0436
|
||||
{ id = "RUSTSEC-2024-0436", reason = "transitive via datafusion; awaiting ecosystem migration" },
|
||||
|
||||
# encoding: unmaintained. Reached through lindera-dictionary, which is
|
||||
# required by the native Lindera tokenizer path. Lindera has not migrated
|
||||
# off this crate yet.
|
||||
# https://rustsec.org/advisories/RUSTSEC-2021-0153
|
||||
{ id = "RUSTSEC-2021-0153", reason = "transitive via lindera-dictionary for native Lindera tokenizer" },
|
||||
|
||||
# fast-float: unsound and unmaintained. Reached only through polars-arrow
|
||||
# from the optional Polars integration; replacement requires a Polars
|
||||
# dependency upgrade.
|
||||
# https://rustsec.org/advisories/RUSTSEC-2024-0379
|
||||
{ id = "RUSTSEC-2024-0379", reason = "transitive via polars-arrow; waiting on Polars migration" },
|
||||
|
||||
# tantivy: segfault on malformed input due to missing bounds check.
|
||||
# Pulled in via lance for full-text search. We only feed tantivy
|
||||
# documents we construct ourselves, not attacker-controlled bytes.
|
||||
@@ -68,6 +80,18 @@ ignore = [
|
||||
# https://rustsec.org/advisories/RUSTSEC-2025-0119
|
||||
{ id = "RUSTSEC-2025-0119", reason = "transitive via hf-hub/indicatif; cosmetic formatting crate" },
|
||||
|
||||
# bincode: unmaintained. Reached through lindera and lindera-dictionary,
|
||||
# which are required by the native Lindera tokenizer path. Lindera has not
|
||||
# migrated to another serialization format yet.
|
||||
# https://rustsec.org/advisories/RUSTSEC-2025-0141
|
||||
{ id = "RUSTSEC-2025-0141", reason = "transitive via lindera/lindera-dictionary for native Lindera tokenizer" },
|
||||
|
||||
# lru: soundness issue in IterMut. Reached only through aws-sdk-s3 in
|
||||
# LanceDB's dev-dependency graph; LanceDB does not use that iterator
|
||||
# directly. Clearing this requires the AWS SDK chain to update lru.
|
||||
# https://rustsec.org/advisories/RUSTSEC-2026-0002
|
||||
{ id = "RUSTSEC-2026-0002", reason = "transitive via aws-sdk-s3 dev-dependency; waiting on AWS SDK lru upgrade" },
|
||||
|
||||
# rustls-webpki 0.101.7 (old major line): name-constraint checks for
|
||||
# URI / wildcard names. Pulled in only via the legacy rustls 0.21 chain
|
||||
# from aws-smithy-http-client. The 0.103 line we actively use is patched.
|
||||
@@ -84,23 +108,11 @@ ignore = [
|
||||
# https://rustsec.org/advisories/RUSTSEC-2026-0104
|
||||
{ id = "RUSTSEC-2026-0104", reason = "only affects rustls-webpki 0.101 from legacy aws-smithy/rustls 0.21 chain" },
|
||||
|
||||
# pyo3 advisories in the Python bindings; tracked pending a patched pyo3 release.
|
||||
# https://rustsec.org/advisories/RUSTSEC-2026-0176
|
||||
# https://rustsec.org/advisories/RUSTSEC-2026-0177
|
||||
{ id = "RUSTSEC-2026-0176", reason = "pyo3 in Python bindings; awaiting patched pyo3 release" },
|
||||
{ id = "RUSTSEC-2026-0177", reason = "pyo3 in Python bindings; awaiting patched pyo3 release" },
|
||||
|
||||
# quick-xml < 0.41.0: quadratic runtime on duplicate attribute names (DoS).
|
||||
# quick-xml < 0.41.0: unbounded namespace-declaration allocation in NsReader (DoS).
|
||||
# Pulled in transitively by inferno (dev-only flame-graph dep), lance-namespace-impls
|
||||
# (git dep from lance), and opendal/reqsign (cloud storage XML parsing). The XML
|
||||
# parsed by opendal/reqsign comes from trusted cloud-storage endpoints (S3, GCS,
|
||||
# Azure), not attacker-controlled input. Clearing requires upstream crates to migrate
|
||||
# to quick-xml >= 0.41.0.
|
||||
# https://rustsec.org/advisories/RUSTSEC-2026-0194
|
||||
# https://rustsec.org/advisories/RUSTSEC-2026-0195
|
||||
{ id = "RUSTSEC-2026-0194", reason = "transitive via inferno/lance/opendal; XML from trusted cloud endpoints, not attacker-controlled" },
|
||||
{ id = "RUSTSEC-2026-0195", reason = "transitive via inferno/lance/opendal; XML from trusted cloud endpoints, not attacker-controlled" },
|
||||
# rand 0.8.5: soundness issue only when ThreadRng reseeds inside a custom
|
||||
# logger. Reached through several transitive chains. LanceDB does not use
|
||||
# rand from a custom logger; upgrade once all pinned chains accept 0.8.6+.
|
||||
# https://rustsec.org/advisories/RUSTSEC-2026-0097
|
||||
{ id = "RUSTSEC-2026-0097", reason = "transitive rand 0.8.5; LanceDB does not call ThreadRng from custom logging" },
|
||||
]
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -135,14 +147,6 @@ allow = [
|
||||
"CDLA-Permissive-2.0",
|
||||
]
|
||||
confidence-threshold = 0.8
|
||||
# Per-crate license exceptions: allow a license for a specific crate only,
|
||||
# rather than globally via the `allow` list above.
|
||||
exceptions = [
|
||||
# CDDL-1.0 (copyleft) is pulled in only as a dev/profiling dependency via
|
||||
# `inferno` -> `pprof` -> `lance-testing`; it is a test dependency that we
|
||||
# do not distribute, so scope the allowance to `inferno` alone.
|
||||
{ allow = ["CDDL-1.0"], crate = "inferno" },
|
||||
]
|
||||
# Crates whose license cannot be determined from Cargo metadata but whose
|
||||
# license we've manually confirmed from upstream. Keep this list minimal.
|
||||
[[licenses.clarify]]
|
||||
|
||||
@@ -51,11 +51,6 @@ plugins:
|
||||
paths: [../python/python]
|
||||
options:
|
||||
docstring_style: numpy
|
||||
docstring_options:
|
||||
# Attributes documented in a `Parameters` section, and pydantic
|
||||
# dataclasses whose `__init__` griffe cannot see statically, both
|
||||
# trip this check. It reports nothing actionable here.
|
||||
warn_unknown_params: false
|
||||
heading_level: 3
|
||||
show_signature_annotations: true
|
||||
show_root_heading: true
|
||||
|
||||
+1
-11
@@ -453,16 +453,6 @@ paths:
|
||||
The metric type to use for the index. l2, Cosine, Dot are supported.
|
||||
index_type:
|
||||
type: string
|
||||
custom_stop_words:
|
||||
type: [array, "null"]
|
||||
items:
|
||||
type: string
|
||||
description: |
|
||||
The custom stop-word list for an FTS index. A non-null
|
||||
array replaces the language's built-in stop-word list and is only
|
||||
applied when remove_stop_words is enabled. Null uses the built-in
|
||||
language list, while an empty array explicitly replaces it with no
|
||||
stop words.
|
||||
responses:
|
||||
"200":
|
||||
description: Index successfully created
|
||||
@@ -520,4 +510,4 @@ paths:
|
||||
"401":
|
||||
$ref: "#/components/responses/unauthorized"
|
||||
"404":
|
||||
$ref: "#/components/responses/not_found"
|
||||
$ref: "#/components/responses/not_found"
|
||||
+30
-165
@@ -14,7 +14,7 @@ Add the following dependency to your `pom.xml`:
|
||||
<dependency>
|
||||
<groupId>com.lancedb</groupId>
|
||||
<artifactId>lancedb-core</artifactId>
|
||||
<version>0.37.1-beta.0</version>
|
||||
<version>0.30.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@@ -249,57 +249,6 @@ try (BufferAllocator allocator = new RootAllocator();
|
||||
}
|
||||
```
|
||||
|
||||
### Creating an Empty Table
|
||||
|
||||
To create an empty table, send an Arrow IPC stream that contains the table schema and no record batches.
|
||||
The schema in the IPC stream becomes the table schema, and rows can be inserted later.
|
||||
|
||||
```java
|
||||
import org.lance.namespace.model.CreateTableRequest;
|
||||
import org.lance.namespace.model.CreateTableResponse;
|
||||
import org.apache.arrow.memory.BufferAllocator;
|
||||
import org.apache.arrow.memory.RootAllocator;
|
||||
import org.apache.arrow.vector.VectorSchemaRoot;
|
||||
import org.apache.arrow.vector.ipc.ArrowStreamWriter;
|
||||
import org.apache.arrow.vector.types.FloatingPointPrecision;
|
||||
import org.apache.arrow.vector.types.pojo.ArrowType;
|
||||
import org.apache.arrow.vector.types.pojo.Field;
|
||||
import org.apache.arrow.vector.types.pojo.FieldType;
|
||||
import org.apache.arrow.vector.types.pojo.Schema;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.channels.Channels;
|
||||
import java.util.Arrays;
|
||||
|
||||
Schema schema = new Schema(Arrays.asList(
|
||||
new Field("id", FieldType.nullable(new ArrowType.Int(32, true)), null),
|
||||
new Field("name", FieldType.nullable(new ArrowType.Utf8()), null),
|
||||
new Field("embedding",
|
||||
FieldType.nullable(new ArrowType.FixedSizeList(128)),
|
||||
Arrays.asList(new Field("item",
|
||||
FieldType.nullable(new ArrowType.FloatingPoint(FloatingPointPrecision.SINGLE)),
|
||||
null)))
|
||||
));
|
||||
|
||||
byte[] emptyTableData;
|
||||
try (BufferAllocator allocator = new RootAllocator();
|
||||
VectorSchemaRoot root = VectorSchemaRoot.create(schema, allocator)) {
|
||||
root.setRowCount(0);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try (ArrowStreamWriter writer = new ArrowStreamWriter(root, null, Channels.newChannel(out))) {
|
||||
writer.start();
|
||||
writer.end();
|
||||
}
|
||||
emptyTableData = out.toByteArray();
|
||||
}
|
||||
|
||||
CreateTableRequest request = new CreateTableRequest();
|
||||
request.setId(Arrays.asList("my_namespace", "empty_table"));
|
||||
|
||||
CreateTableResponse response = namespaceClient.createTable(request, emptyTableData);
|
||||
```
|
||||
|
||||
### Insert
|
||||
|
||||
```java
|
||||
@@ -482,88 +431,9 @@ query.setVector(vector);
|
||||
byte[] result = namespaceClient.queryTable(query);
|
||||
```
|
||||
|
||||
## Indexing
|
||||
### Reading Query Results
|
||||
|
||||
The Java SDK exposes the REST namespace index operations through the same `LanceNamespace` client.
|
||||
Index creation runs asynchronously, so use `listTableIndices` or `describeTableIndexStats` to check progress.
|
||||
|
||||
### Creating a Vector Index
|
||||
|
||||
```java
|
||||
import org.lance.namespace.model.CreateTableIndexRequest;
|
||||
import org.lance.namespace.model.CreateTableIndexResponse;
|
||||
|
||||
CreateTableIndexRequest request = new CreateTableIndexRequest();
|
||||
request.setId(Arrays.asList("my_namespace", "my_table"));
|
||||
request.setColumn("embedding");
|
||||
request.setIndexType("IVF_PQ");
|
||||
request.setDistanceType("cosine");
|
||||
request.setName("embedding_idx");
|
||||
|
||||
CreateTableIndexResponse response = namespaceClient.createTableIndex(request);
|
||||
System.out.println("Index transaction: " + response.getTransactionId());
|
||||
```
|
||||
|
||||
### Creating a Scalar Index
|
||||
|
||||
```java
|
||||
import org.lance.namespace.model.CreateTableIndexRequest;
|
||||
import org.lance.namespace.model.CreateTableScalarIndexResponse;
|
||||
|
||||
CreateTableIndexRequest request = new CreateTableIndexRequest();
|
||||
request.setId(Arrays.asList("my_namespace", "my_table"));
|
||||
request.setColumn("category");
|
||||
request.setIndexType("BTREE");
|
||||
request.setName("category_idx");
|
||||
|
||||
CreateTableScalarIndexResponse response = namespaceClient.createTableScalarIndex(request);
|
||||
System.out.println("Index transaction: " + response.getTransactionId());
|
||||
```
|
||||
|
||||
### Creating a Full Text Search Index
|
||||
|
||||
```java
|
||||
import org.lance.namespace.model.CreateTableIndexRequest;
|
||||
import org.lance.namespace.model.CreateTableScalarIndexResponse;
|
||||
|
||||
CreateTableIndexRequest request = new CreateTableIndexRequest();
|
||||
request.setId(Arrays.asList("my_namespace", "my_table"));
|
||||
request.setColumn("text_column");
|
||||
request.setIndexType("FTS");
|
||||
request.setName("text_idx");
|
||||
request.setBaseTokenizer("simple");
|
||||
request.setLowerCase(true);
|
||||
request.setWithPosition(true);
|
||||
|
||||
CreateTableScalarIndexResponse response = namespaceClient.createTableScalarIndex(request);
|
||||
System.out.println("Index transaction: " + response.getTransactionId());
|
||||
```
|
||||
|
||||
### Listing Indexes
|
||||
|
||||
```java
|
||||
import org.lance.namespace.model.IndexContent;
|
||||
import org.lance.namespace.model.ListTableIndicesRequest;
|
||||
import org.lance.namespace.model.ListTableIndicesResponse;
|
||||
|
||||
ListTableIndicesRequest request = new ListTableIndicesRequest();
|
||||
request.setId(Arrays.asList("my_namespace", "my_table"));
|
||||
|
||||
ListTableIndicesResponse response = namespaceClient.listTableIndices(request);
|
||||
for (IndexContent index : response.getIndexes()) {
|
||||
System.out.println(index.getIndexName() + ": " + index.getStatus());
|
||||
}
|
||||
```
|
||||
|
||||
!!! note
|
||||
The current Java namespace API exposes index type, index name, distance type, and full text search tokenizer options.
|
||||
IVF training parameters such as `num_partitions` are not exposed by `CreateTableIndexRequest` yet.
|
||||
To make those configurable from Java, the namespace API must add those fields first.
|
||||
|
||||
## Reading Query Results
|
||||
|
||||
Query results are returned as bytes in Apache Arrow IPC file format. Put the byte-channel
|
||||
adapter behind a small helper so query code can work with `ArrowFileReader` directly:
|
||||
Query results are returned in Apache Arrow IPC file format. Here's how to read them:
|
||||
|
||||
```java
|
||||
import org.apache.arrow.vector.ipc.ArrowFileReader;
|
||||
@@ -571,50 +441,45 @@ import org.apache.arrow.vector.VectorSchemaRoot;
|
||||
import org.apache.arrow.memory.BufferAllocator;
|
||||
import org.apache.arrow.memory.RootAllocator;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SeekableByteChannel;
|
||||
|
||||
final class ArrowIpc {
|
||||
static ArrowFileReader openFileReader(byte[] data, BufferAllocator allocator) throws IOException {
|
||||
return new ArrowFileReader(new ByteArraySeekableByteChannel(data), allocator);
|
||||
// Helper class to read Arrow data from byte array
|
||||
class ByteArraySeekableByteChannel implements SeekableByteChannel {
|
||||
private final byte[] data;
|
||||
private long position = 0;
|
||||
private boolean isOpen = true;
|
||||
|
||||
public ByteArraySeekableByteChannel(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
private static final class ByteArraySeekableByteChannel implements SeekableByteChannel {
|
||||
private final byte[] data;
|
||||
private long position = 0;
|
||||
private boolean isOpen = true;
|
||||
|
||||
private ByteArraySeekableByteChannel(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(ByteBuffer dst) {
|
||||
int remaining = dst.remaining();
|
||||
int available = (int) (data.length - position);
|
||||
if (available <= 0) return -1;
|
||||
int toRead = Math.min(remaining, available);
|
||||
dst.put(data, (int) position, toRead);
|
||||
position += toRead;
|
||||
return toRead;
|
||||
}
|
||||
|
||||
@Override public long position() { return position; }
|
||||
@Override public SeekableByteChannel position(long newPosition) { position = newPosition; return this; }
|
||||
@Override public long size() { return data.length; }
|
||||
@Override public boolean isOpen() { return isOpen; }
|
||||
@Override public void close() { isOpen = false; }
|
||||
@Override public int write(ByteBuffer src) { throw new UnsupportedOperationException(); }
|
||||
@Override public SeekableByteChannel truncate(long size) { throw new UnsupportedOperationException(); }
|
||||
@Override
|
||||
public int read(ByteBuffer dst) {
|
||||
int remaining = dst.remaining();
|
||||
int available = (int) (data.length - position);
|
||||
if (available <= 0) return -1;
|
||||
int toRead = Math.min(remaining, available);
|
||||
dst.put(data, (int) position, toRead);
|
||||
position += toRead;
|
||||
return toRead;
|
||||
}
|
||||
|
||||
@Override public long position() { return position; }
|
||||
@Override public SeekableByteChannel position(long newPosition) { position = newPosition; return this; }
|
||||
@Override public long size() { return data.length; }
|
||||
@Override public boolean isOpen() { return isOpen; }
|
||||
@Override public void close() { isOpen = false; }
|
||||
@Override public int write(ByteBuffer src) { throw new UnsupportedOperationException(); }
|
||||
@Override public SeekableByteChannel truncate(long size) { throw new UnsupportedOperationException(); }
|
||||
}
|
||||
|
||||
// Read query results
|
||||
byte[] queryResult = namespaceClient.queryTable(query);
|
||||
|
||||
try (BufferAllocator allocator = new RootAllocator();
|
||||
ArrowFileReader reader = ArrowIpc.openFileReader(queryResult, allocator)) {
|
||||
ArrowFileReader reader = new ArrowFileReader(
|
||||
new ByteArraySeekableByteChannel(queryResult), allocator)) {
|
||||
|
||||
for (int i = 0; i < reader.getRecordBlocks().size(); i++) {
|
||||
reader.loadRecordBatch(reader.getRecordBlocks().get(i));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Contributing to LanceDB Typescript
|
||||
|
||||
This document outlines the process for contributing to LanceDB Typescript.
|
||||
For general contribution guidelines, see [CONTRIBUTING.md](https://github.com/lancedb/lancedb/blob/main/CONTRIBUTING.md).
|
||||
For general contribution guidelines, see [CONTRIBUTING.md](../CONTRIBUTING.md).
|
||||
|
||||
## Project layout
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / BranchContents
|
||||
|
||||
# Class: BranchContents
|
||||
|
||||
## Constructors
|
||||
|
||||
### new BranchContents()
|
||||
|
||||
```ts
|
||||
new BranchContents(): BranchContents
|
||||
```
|
||||
|
||||
#### Returns
|
||||
|
||||
[`BranchContents`](BranchContents.md)
|
||||
|
||||
## Properties
|
||||
|
||||
### manifestSize
|
||||
|
||||
```ts
|
||||
manifestSize: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### parentBranch?
|
||||
|
||||
```ts
|
||||
optional parentBranch: string;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### parentVersion
|
||||
|
||||
```ts
|
||||
parentVersion: number;
|
||||
```
|
||||
@@ -1,139 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / Branches
|
||||
|
||||
# Class: Branches
|
||||
|
||||
Branch manager for a [Table](Table.md).
|
||||
|
||||
Unlike tags, `create` and `checkout` return a new [Table](Table.md) handle scoped
|
||||
to the branch; writes on it do not affect `main`.
|
||||
|
||||
## Methods
|
||||
|
||||
### checkout()
|
||||
|
||||
```ts
|
||||
checkout(name, version?): Promise<Table>
|
||||
```
|
||||
|
||||
Check out an existing branch and return a handle scoped to it.
|
||||
|
||||
With `version` set, the returned handle is pinned to that version of the
|
||||
branch (a read-only, detached view); otherwise it tracks the branch's
|
||||
latest and stays writable.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **name**: `string`
|
||||
|
||||
* **version?**: `number`
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<[`Table`](Table.md)>
|
||||
|
||||
***
|
||||
|
||||
### create()
|
||||
|
||||
```ts
|
||||
create(
|
||||
name,
|
||||
fromRef?,
|
||||
fromVersion?): Promise<Table>
|
||||
```
|
||||
|
||||
Create a branch and return a handle scoped to it.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **name**: `string`
|
||||
Name of the new branch.
|
||||
|
||||
* **fromRef?**: `string`
|
||||
Source branch to fork from. Defaults to `main`.
|
||||
|
||||
* **fromVersion?**: `number`
|
||||
A specific version on `fromRef`. Defaults to latest.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<[`Table`](Table.md)>
|
||||
|
||||
***
|
||||
|
||||
### delete()
|
||||
|
||||
```ts
|
||||
delete(name): Promise<void>
|
||||
```
|
||||
|
||||
Delete a branch.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **name**: `string`
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`void`>
|
||||
|
||||
***
|
||||
|
||||
### diff()
|
||||
|
||||
```ts
|
||||
diff(fromBranch): Promise<BranchDiff>
|
||||
```
|
||||
|
||||
Compare a branch against main without modifying either branch.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **fromBranch**: `string`
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<[`BranchDiff`](../interfaces/BranchDiff.md)>
|
||||
|
||||
***
|
||||
|
||||
### list()
|
||||
|
||||
```ts
|
||||
list(): Promise<Record<string, BranchContents>>
|
||||
```
|
||||
|
||||
List all branches, mapping name to branch metadata.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`Record`<`string`, [`BranchContents`](BranchContents.md)>>
|
||||
|
||||
***
|
||||
|
||||
### merge()
|
||||
|
||||
```ts
|
||||
merge(fromBranch, dryRun): Promise<MergeBranchResult>
|
||||
```
|
||||
|
||||
Merge a branch into main.
|
||||
|
||||
Set `dryRun` to `true` to preview the merge. A rejected merge resolves
|
||||
with `status: "rejected"` instead of throwing.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **fromBranch**: `string`
|
||||
Branch to merge from.
|
||||
|
||||
* **dryRun**: `boolean` = `false`
|
||||
When true, only preview the merge. Defaults to false.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<[`MergeBranchResult`](../interfaces/MergeBranchResult.md)>
|
||||
@@ -25,27 +25,6 @@ the underlying connection has been closed.
|
||||
|
||||
## Methods
|
||||
|
||||
### cancelJob()
|
||||
|
||||
```ts
|
||||
abstract cancelJob(jobId): Promise<boolean>
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **jobId**: `string`
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`boolean`>
|
||||
|
||||
***
|
||||
|
||||
### cloneTable()
|
||||
|
||||
```ts
|
||||
@@ -386,26 +365,6 @@ Drop an existing table.
|
||||
|
||||
***
|
||||
|
||||
### getJob()
|
||||
|
||||
```ts
|
||||
abstract getJob(jobId): Promise<null | JobDescription>
|
||||
```
|
||||
|
||||
Describe a single server-side job by id.
|
||||
|
||||
Resolves to `null` when the server has no such job.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **jobId**: `string`
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`null` \| [`JobDescription`](../interfaces/JobDescription.md)>
|
||||
|
||||
***
|
||||
|
||||
### isOpen()
|
||||
|
||||
```ts
|
||||
@@ -420,62 +379,6 @@ Return true if the connection has not been closed
|
||||
|
||||
***
|
||||
|
||||
### job()
|
||||
|
||||
```ts
|
||||
abstract job(jobId): Job
|
||||
```
|
||||
|
||||
A [Job](Job.md) handle for a server-side job by id.
|
||||
|
||||
The handle is constructed without a server round trip; an unknown id
|
||||
surfaces when the handle is used. Dropping the handle has no effect on
|
||||
the job itself.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **jobId**: `string`
|
||||
|
||||
#### Returns
|
||||
|
||||
[`Job`](Job.md)
|
||||
|
||||
***
|
||||
|
||||
### jobHistory()
|
||||
|
||||
```ts
|
||||
abstract jobHistory(jobId?): Promise<Table<any>>
|
||||
```
|
||||
|
||||
The lifecycle event history of a server-side job, as an Arrow table.
|
||||
|
||||
Lists history across all jobs when `jobId` is omitted.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **jobId?**: `string`
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`Table`<`any`>>
|
||||
|
||||
***
|
||||
|
||||
### listJobs()
|
||||
|
||||
```ts
|
||||
abstract listJobs(): Promise<JobInfo[]>
|
||||
```
|
||||
|
||||
List server-side jobs across the database's tables.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<[`JobInfo`](../interfaces/JobInfo.md)[]>
|
||||
|
||||
***
|
||||
|
||||
### listNamespaces()
|
||||
|
||||
```ts
|
||||
|
||||
@@ -57,24 +57,6 @@ block size may be added in the future.
|
||||
|
||||
***
|
||||
|
||||
### fm()
|
||||
|
||||
```ts
|
||||
static fm(): Index
|
||||
```
|
||||
|
||||
Create an FM-Index.
|
||||
|
||||
An FM-Index is a scalar index on string or binary columns that accelerates
|
||||
substring search, i.e. `contains(col, 'needle')`. Unlike the tokenized
|
||||
full-text-search index, it matches arbitrary substrings of the raw bytes.
|
||||
|
||||
#### Returns
|
||||
|
||||
[`Index`](Index.md)
|
||||
|
||||
***
|
||||
|
||||
### fts()
|
||||
|
||||
```ts
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / Job
|
||||
|
||||
# Class: Job
|
||||
|
||||
A handle to an operation that may still be running.
|
||||
|
||||
## Constructors
|
||||
|
||||
### new Job()
|
||||
|
||||
```ts
|
||||
new Job(): Job
|
||||
```
|
||||
|
||||
#### Returns
|
||||
|
||||
[`Job`](Job.md)
|
||||
|
||||
## Accessors
|
||||
|
||||
### id
|
||||
|
||||
```ts
|
||||
get id(): null | string
|
||||
```
|
||||
|
||||
Identifies the operation on the server that is running it. Operations
|
||||
that run in this process have no server id. The value is opaque.
|
||||
|
||||
#### Returns
|
||||
|
||||
`null` \| `string`
|
||||
|
||||
## Methods
|
||||
|
||||
### cancel()
|
||||
|
||||
```ts
|
||||
cancel(): Promise<void>
|
||||
```
|
||||
|
||||
Request cancellation. Cancelling a finished operation is a no-op.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`void`>
|
||||
|
||||
***
|
||||
|
||||
### status()
|
||||
|
||||
```ts
|
||||
status(): Promise<string>
|
||||
```
|
||||
|
||||
The operation's current lifecycle state: "running", "finished",
|
||||
"failed", or "cancelled".
|
||||
|
||||
A point snapshot; unlike [Job.wait](Job.md#wait) it does not block or reject
|
||||
on a terminal failure state. States a newer server reports that this
|
||||
client version does not know pass through as-is.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`string`>
|
||||
|
||||
***
|
||||
|
||||
### wait()
|
||||
|
||||
```ts
|
||||
wait(): Promise<void>
|
||||
```
|
||||
|
||||
Wait until the operation reaches a terminal state.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`void`>
|
||||
@@ -76,56 +76,6 @@ the query optimizer chooses a suboptimal path.
|
||||
|
||||
***
|
||||
|
||||
### useLsm()
|
||||
|
||||
```ts
|
||||
useLsm(enable): MergeInsertBuilder
|
||||
```
|
||||
|
||||
Control MemWAL routing for this merge.
|
||||
|
||||
By default (unset), a `mergeInsert` on a table with an LSM write spec is
|
||||
routed through Lance's MemWAL shard writer, and a table without one uses the
|
||||
standard path.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **enable**: `boolean`
|
||||
`true` forces MemWAL routing and errors if the table has no
|
||||
LSM write spec. `false` forces the standard write path even when a spec is set.
|
||||
|
||||
#### Returns
|
||||
|
||||
[`MergeInsertBuilder`](MergeInsertBuilder.md)
|
||||
|
||||
***
|
||||
|
||||
### validateSingleShard()
|
||||
|
||||
```ts
|
||||
validateSingleShard(validateSingleShard): MergeInsertBuilder
|
||||
```
|
||||
|
||||
Controls how an LSM merge checks that its input targets a single shard.
|
||||
|
||||
When a table has an LSM write spec, every row in a `mergeInsert` call must
|
||||
route to the same shard. When `true` (the default), every row is inspected
|
||||
to verify this. When `false`, only the first row is inspected and the
|
||||
shard it routes to is used for the whole input — a faster path for callers
|
||||
that have already pre-sharded their input. Has no effect on tables without
|
||||
an LSM write spec.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **validateSingleShard**: `boolean`
|
||||
Whether to check every row routes to one shard. Defaults to `true`.
|
||||
|
||||
#### Returns
|
||||
|
||||
[`MergeInsertBuilder`](MergeInsertBuilder.md)
|
||||
|
||||
***
|
||||
|
||||
### whenMatchedUpdateAll()
|
||||
|
||||
```ts
|
||||
|
||||
@@ -33,7 +33,7 @@ protected inner: Query | Promise<Query>;
|
||||
### analyzePlan()
|
||||
|
||||
```ts
|
||||
analyzePlan(distributedMetrics?): Promise<string>
|
||||
analyzePlan(): Promise<string>
|
||||
```
|
||||
|
||||
Executes the query and returns the physical query plan annotated with runtime metrics.
|
||||
@@ -41,12 +41,6 @@ Executes the query and returns the physical query plan annotated with runtime me
|
||||
This is useful for debugging and performance analysis, as it shows how the query was executed
|
||||
and includes metrics such as elapsed time, rows processed, and I/O statistics.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **distributedMetrics?**: [`AnalyzePlanDistributedMetrics`](../type-aliases/AnalyzePlanDistributedMetrics.md)
|
||||
How distributed worker metrics are displayed for remote query plans.
|
||||
Defaults to `"aggregate"`.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`string`>
|
||||
@@ -497,42 +491,6 @@ ArrowTable.
|
||||
|
||||
***
|
||||
|
||||
### useLsm()
|
||||
|
||||
```ts
|
||||
useLsm(enable): this
|
||||
```
|
||||
|
||||
Control MemWAL read routing for this query.
|
||||
|
||||
By default (unset), when the table carries a MemWAL write spec (see
|
||||
[Table#setLsmWriteSpec](Table.md#setlsmwritespec)), reads are routed through the LSM scanner so
|
||||
they also return data written via the `mergeInsert` LSM path that has not yet
|
||||
been compacted into the base table (the active/frozen in-memory memtables and
|
||||
the flushed generations), deduplicated by primary key; a table without a spec
|
||||
reads the base table.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **enable**: `boolean`
|
||||
`true` forces the LSM scanner and errors if the table has no
|
||||
MemWAL write spec. `false` bypasses the MemWAL and reads the base table only,
|
||||
even when a spec is present.
|
||||
Note: the LSM scanner does not support every query shape (e.g. reranking,
|
||||
hybrid search, `orderBy`). On a MemWAL table those shapes error unless
|
||||
`useLsm(false)` is set, because a base-only read would silently exclude
|
||||
un-compacted MemWAL data.
|
||||
|
||||
#### Returns
|
||||
|
||||
`this`
|
||||
|
||||
#### Inherited from
|
||||
|
||||
`StandardQueryBase.useLsm`
|
||||
|
||||
***
|
||||
|
||||
### where()
|
||||
|
||||
```ts
|
||||
@@ -560,9 +518,6 @@ x > 5 OR y = 'test'
|
||||
|
||||
Filtering performance can often be improved by creating a scalar index
|
||||
on the filter column(s).
|
||||
|
||||
Calling this multiple times combines the filters with a logical AND rather
|
||||
than replacing the previous filter.
|
||||
```
|
||||
|
||||
#### Inherited from
|
||||
|
||||
@@ -38,7 +38,7 @@ protected inner: NativeQueryType | Promise<NativeQueryType>;
|
||||
### analyzePlan()
|
||||
|
||||
```ts
|
||||
analyzePlan(distributedMetrics?): Promise<string>
|
||||
analyzePlan(): Promise<string>
|
||||
```
|
||||
|
||||
Executes the query and returns the physical query plan annotated with runtime metrics.
|
||||
@@ -46,12 +46,6 @@ Executes the query and returns the physical query plan annotated with runtime me
|
||||
This is useful for debugging and performance analysis, as it shows how the query was executed
|
||||
and includes metrics such as elapsed time, rows processed, and I/O statistics.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **distributedMetrics?**: [`AnalyzePlanDistributedMetrics`](../type-aliases/AnalyzePlanDistributedMetrics.md)
|
||||
How distributed worker metrics are displayed for remote query plans.
|
||||
Defaults to `"aggregate"`.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`string`>
|
||||
|
||||
@@ -110,23 +110,6 @@ containing the new version number of the table after altering the columns.
|
||||
|
||||
***
|
||||
|
||||
### branches()
|
||||
|
||||
```ts
|
||||
abstract branches(): Promise<Branches>
|
||||
```
|
||||
|
||||
Get the branch manager for this table.
|
||||
|
||||
Branches are isolated, writable lines of history forked from another
|
||||
branch (or version). Writes on a branch do not affect `main`.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<[`Branches`](Branches.md)>
|
||||
|
||||
***
|
||||
|
||||
### checkout()
|
||||
|
||||
```ts
|
||||
@@ -204,25 +187,6 @@ Any attempt to use the table after it is closed will result in an error.
|
||||
|
||||
***
|
||||
|
||||
### closeLsmWriters()
|
||||
|
||||
```ts
|
||||
abstract closeLsmWriters(): Promise<void>
|
||||
```
|
||||
|
||||
Drain and close any cached MemWAL shard writers held for this table.
|
||||
|
||||
When an [LsmWriteSpec](../interfaces/LsmWriteSpec.md) is installed, `mergeInsert` opens MemWAL
|
||||
shard writers and caches them for reuse across calls. This closes them,
|
||||
flushing pending data; writers reopen lazily on the next `mergeInsert`.
|
||||
It is a no-op when no writers are cached.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`void`>
|
||||
|
||||
***
|
||||
|
||||
### countRows()
|
||||
|
||||
```ts
|
||||
@@ -295,46 +259,6 @@ await table.createIndex("my_float_col");
|
||||
|
||||
***
|
||||
|
||||
### createIndexAsync()
|
||||
|
||||
```ts
|
||||
abstract createIndexAsync(column, options?): Promise<Job>
|
||||
```
|
||||
|
||||
Create an index, returning a handle to the indexing job.
|
||||
|
||||
The job may already be complete when returned; callers must not assume
|
||||
the index exists until [Job.wait](Job.md#wait) resolves.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **column**: `string`
|
||||
|
||||
* **options?**: `Partial`<[`IndexOptions`](../interfaces/IndexOptions.md)>
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<[`Job`](Job.md)>
|
||||
|
||||
***
|
||||
|
||||
### currentBranch()
|
||||
|
||||
```ts
|
||||
abstract currentBranch(): null | string
|
||||
```
|
||||
|
||||
The branch this table handle is scoped to, or `null` for the main branch.
|
||||
|
||||
A handle returned by [Branches.create](Branches.md#create) or [Branches.checkout](Branches.md#checkout)
|
||||
reports the branch it targets; a handle opened normally reports `null`.
|
||||
|
||||
#### Returns
|
||||
|
||||
`null` \| `string`
|
||||
|
||||
***
|
||||
|
||||
### delete()
|
||||
|
||||
```ts
|
||||
@@ -421,26 +345,6 @@ Drop an index from the table.
|
||||
|
||||
***
|
||||
|
||||
### getLsmWriteSpec()
|
||||
|
||||
```ts
|
||||
abstract getLsmWriteSpec(): Promise<undefined | LsmWriteSpec>
|
||||
```
|
||||
|
||||
Read the [LsmWriteSpec](../interfaces/LsmWriteSpec.md) currently installed on this table.
|
||||
|
||||
Resolves to `undefined` when the MemWAL LSM write path is not enabled (no
|
||||
spec has been set, or it was removed with [Table#unsetLsmWriteSpec](Table.md#unsetlsmwritespec)).
|
||||
The returned spec — including its `maintainedIndexes` and
|
||||
`writerConfigDefaults` — mirrors what was passed to
|
||||
[Table#setLsmWriteSpec](Table.md#setlsmwritespec).
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`undefined` \| [`LsmWriteSpec`](../interfaces/LsmWriteSpec.md)>
|
||||
|
||||
***
|
||||
|
||||
### indexStats()
|
||||
|
||||
```ts
|
||||
@@ -957,32 +861,6 @@ Return the table as an arrow table
|
||||
|
||||
***
|
||||
|
||||
### tokenize()
|
||||
|
||||
```ts
|
||||
abstract tokenize(query, options): Promise<FtsToken[]>
|
||||
```
|
||||
|
||||
Tokenize a full-text search query using the tokenizer configured on an FTS index.
|
||||
|
||||
Specify exactly one of `column` or `indexName`.
|
||||
|
||||
Model-backed tokenizers such as `jieba/*` and `lindera/*` are rebuilt in
|
||||
the client process from index metadata. For remote tables, this means the
|
||||
same tokenizer model files must also exist locally.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **query**: `string`
|
||||
|
||||
* **options**: [`TokenizeTableOptions`](../type-aliases/TokenizeTableOptions.md)
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<[`FtsToken`](../interfaces/FtsToken.md)[]>
|
||||
|
||||
***
|
||||
|
||||
### unsetLsmWriteSpec()
|
||||
|
||||
```ts
|
||||
@@ -1097,29 +975,6 @@ based on the row being updated (e.g. "my_col + 1")
|
||||
|
||||
***
|
||||
|
||||
### updateFieldMetadata()
|
||||
|
||||
```ts
|
||||
abstract updateFieldMetadata(updates): Promise<UpdateFieldMetadataResult>
|
||||
```
|
||||
|
||||
Update per-field (column) metadata.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **updates**: [`FieldMetadataUpdate`](../interfaces/FieldMetadataUpdate.md)[]
|
||||
One or more per-field updates. Each
|
||||
update's metadata is merged into the field's existing metadata by default;
|
||||
a value of `null` deletes that key, and `replace: true` swaps the whole map.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<[`UpdateFieldMetadataResult`](../interfaces/UpdateFieldMetadataResult.md)>
|
||||
|
||||
resolves to the new table version.
|
||||
|
||||
***
|
||||
|
||||
### vectorSearch()
|
||||
|
||||
```ts
|
||||
|
||||
@@ -29,7 +29,7 @@ protected inner: TakeQuery | Promise<TakeQuery>;
|
||||
### analyzePlan()
|
||||
|
||||
```ts
|
||||
analyzePlan(distributedMetrics?): Promise<string>
|
||||
analyzePlan(): Promise<string>
|
||||
```
|
||||
|
||||
Executes the query and returns the physical query plan annotated with runtime metrics.
|
||||
@@ -37,12 +37,6 @@ Executes the query and returns the physical query plan annotated with runtime me
|
||||
This is useful for debugging and performance analysis, as it shows how the query was executed
|
||||
and includes metrics such as elapsed time, rows processed, and I/O statistics.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **distributedMetrics?**: [`AnalyzePlanDistributedMetrics`](../type-aliases/AnalyzePlanDistributedMetrics.md)
|
||||
How distributed worker metrics are displayed for remote query plans.
|
||||
Defaults to `"aggregate"`.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`string`>
|
||||
@@ -273,29 +267,6 @@ ArrowTable.
|
||||
|
||||
***
|
||||
|
||||
### useLsm()
|
||||
|
||||
```ts
|
||||
useLsm(enable): this
|
||||
```
|
||||
|
||||
Control MemWAL read routing for this take query.
|
||||
|
||||
`false` bypasses the MemWAL and reads the base table only — the escape hatch,
|
||||
since take-by-row-id/offset is not supported on the LSM scanner and, on a
|
||||
MemWAL table, auto-routes to it and errors otherwise.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **enable**: `boolean`
|
||||
`false` reads the base table only.
|
||||
|
||||
#### Returns
|
||||
|
||||
`this`
|
||||
|
||||
***
|
||||
|
||||
### withRowId()
|
||||
|
||||
```ts
|
||||
|
||||
@@ -51,7 +51,7 @@ addQueryVector(vector): VectorQuery
|
||||
### analyzePlan()
|
||||
|
||||
```ts
|
||||
analyzePlan(distributedMetrics?): Promise<string>
|
||||
analyzePlan(): Promise<string>
|
||||
```
|
||||
|
||||
Executes the query and returns the physical query plan annotated with runtime metrics.
|
||||
@@ -59,12 +59,6 @@ Executes the query and returns the physical query plan annotated with runtime me
|
||||
This is useful for debugging and performance analysis, as it shows how the query was executed
|
||||
and includes metrics such as elapsed time, rows processed, and I/O statistics.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **distributedMetrics?**: [`AnalyzePlanDistributedMetrics`](../type-aliases/AnalyzePlanDistributedMetrics.md)
|
||||
How distributed worker metrics are displayed for remote query plans.
|
||||
Defaults to `"aggregate"`.
|
||||
|
||||
#### Returns
|
||||
|
||||
`Promise`<`string`>
|
||||
@@ -746,42 +740,6 @@ ArrowTable.
|
||||
|
||||
***
|
||||
|
||||
### useLsm()
|
||||
|
||||
```ts
|
||||
useLsm(enable): this
|
||||
```
|
||||
|
||||
Control MemWAL read routing for this query.
|
||||
|
||||
By default (unset), when the table carries a MemWAL write spec (see
|
||||
[Table#setLsmWriteSpec](Table.md#setlsmwritespec)), reads are routed through the LSM scanner so
|
||||
they also return data written via the `mergeInsert` LSM path that has not yet
|
||||
been compacted into the base table (the active/frozen in-memory memtables and
|
||||
the flushed generations), deduplicated by primary key; a table without a spec
|
||||
reads the base table.
|
||||
|
||||
#### Parameters
|
||||
|
||||
* **enable**: `boolean`
|
||||
`true` forces the LSM scanner and errors if the table has no
|
||||
MemWAL write spec. `false` bypasses the MemWAL and reads the base table only,
|
||||
even when a spec is present.
|
||||
Note: the LSM scanner does not support every query shape (e.g. reranking,
|
||||
hybrid search, `orderBy`). On a MemWAL table those shapes error unless
|
||||
`useLsm(false)` is set, because a base-only read would silently exclude
|
||||
un-compacted MemWAL data.
|
||||
|
||||
#### Returns
|
||||
|
||||
`this`
|
||||
|
||||
#### Inherited from
|
||||
|
||||
`StandardQueryBase.useLsm`
|
||||
|
||||
***
|
||||
|
||||
### where()
|
||||
|
||||
```ts
|
||||
@@ -809,9 +767,6 @@ x > 5 OR y = 'test'
|
||||
|
||||
Filtering performance can often be improved by creating a scalar index
|
||||
on the filter column(s).
|
||||
|
||||
Calling this multiple times combines the filters with a logical AND rather
|
||||
than replacing the previous filter.
|
||||
```
|
||||
|
||||
#### Inherited from
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / OAuthFlowType
|
||||
|
||||
# Enumeration: OAuthFlowType
|
||||
|
||||
OAuth authentication flow types.
|
||||
|
||||
## Enumeration Members
|
||||
|
||||
### AzureManagedIdentity
|
||||
|
||||
```ts
|
||||
AzureManagedIdentity: "azure_managed_identity";
|
||||
```
|
||||
|
||||
Azure Managed Identity via IMDS.
|
||||
|
||||
***
|
||||
|
||||
### ClientCredentials
|
||||
|
||||
```ts
|
||||
ClientCredentials: "client_credentials";
|
||||
```
|
||||
|
||||
Client Credentials grant (service-to-service / M2M).
|
||||
@@ -1,42 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / instrumentLanceDbMetrics
|
||||
|
||||
# Function: instrumentLanceDbMetrics()
|
||||
|
||||
```ts
|
||||
function instrumentLanceDbMetrics(meterProvider?): boolean
|
||||
```
|
||||
|
||||
Register LanceDB metrics as OpenTelemetry observable instruments.
|
||||
|
||||
Installs a process-global metrics recorder and creates one observable
|
||||
instrument per LanceDB metric (currently object store request counts, bytes,
|
||||
latency, errors, and throttles) on the given (or global) `MeterProvider`. The
|
||||
configured `MetricReader` then collects them on its own schedule.
|
||||
|
||||
Counters and gauges map directly to observable counters/gauges. Because
|
||||
OpenTelemetry has no asynchronous histogram instrument, each histogram is
|
||||
exported Prometheus-style as cumulative `le` bucket counts (`<name>_bucket`,
|
||||
with an `le` attribute) plus `<name>_count` and `<name>_sum`.
|
||||
|
||||
Requires `@opentelemetry/api` (a dependency) and, to actually export, an
|
||||
OpenTelemetry SDK such as `@opentelemetry/sdk-metrics`.
|
||||
|
||||
## Parameters
|
||||
|
||||
* **meterProvider?**: `MeterProvider`
|
||||
The provider to register instruments on. Defaults to the
|
||||
global provider from `@opentelemetry/api`.
|
||||
|
||||
## Returns
|
||||
|
||||
`boolean`
|
||||
|
||||
`true` if the recorder is installed and instruments are registered.
|
||||
`false` if a different `metrics` recorder is already installed in this
|
||||
process (only one global recorder is permitted), in which case a warning is
|
||||
emitted and no instruments are created. Calling this more than once is safe;
|
||||
instruments are created only on the first successful call.
|
||||
@@ -1,26 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / tokenize
|
||||
|
||||
# Function: tokenize()
|
||||
|
||||
```ts
|
||||
function tokenize(query, options?): Promise<FtsToken[]>
|
||||
```
|
||||
|
||||
Tokenize a full-text search query using an explicit tokenizer.
|
||||
|
||||
This does not require a table or FTS index. The tokenizer options match
|
||||
[Index.fts](../classes/Index.md#fts).
|
||||
|
||||
## Parameters
|
||||
|
||||
* **query**: `string`
|
||||
|
||||
* **options?**: `Partial`<[`TokenizeOptions`](../interfaces/TokenizeOptions.md)>
|
||||
|
||||
## Returns
|
||||
|
||||
`Promise`<[`FtsToken`](../interfaces/FtsToken.md)[]>
|
||||
@@ -12,7 +12,6 @@
|
||||
## Enumerations
|
||||
|
||||
- [FullTextQueryType](enumerations/FullTextQueryType.md)
|
||||
- [OAuthFlowType](enumerations/OAuthFlowType.md)
|
||||
- [Occur](enumerations/Occur.md)
|
||||
- [Operator](enumerations/Operator.md)
|
||||
|
||||
@@ -20,12 +19,9 @@
|
||||
|
||||
- [BooleanQuery](classes/BooleanQuery.md)
|
||||
- [BoostQuery](classes/BoostQuery.md)
|
||||
- [BranchContents](classes/BranchContents.md)
|
||||
- [Branches](classes/Branches.md)
|
||||
- [Connection](classes/Connection.md)
|
||||
- [HeaderProvider](classes/HeaderProvider.md)
|
||||
- [Index](classes/Index.md)
|
||||
- [Job](classes/Job.md)
|
||||
- [MakeArrowTableOptions](classes/MakeArrowTableOptions.md)
|
||||
- [MatchQuery](classes/MatchQuery.md)
|
||||
- [MergeInsertBuilder](classes/MergeInsertBuilder.md)
|
||||
@@ -53,11 +49,6 @@
|
||||
- [AddDataOptions](interfaces/AddDataOptions.md)
|
||||
- [AddResult](interfaces/AddResult.md)
|
||||
- [AlterColumnsResult](interfaces/AlterColumnsResult.md)
|
||||
- [BranchColumnChange](interfaces/BranchColumnChange.md)
|
||||
- [BranchColumnSummary](interfaces/BranchColumnSummary.md)
|
||||
- [BranchDiff](interfaces/BranchDiff.md)
|
||||
- [BranchIndexSummary](interfaces/BranchIndexSummary.md)
|
||||
- [BranchRowCountSummary](interfaces/BranchRowCountSummary.md)
|
||||
- [ClientConfig](interfaces/ClientConfig.md)
|
||||
- [ColumnAlteration](interfaces/ColumnAlteration.md)
|
||||
- [ColumnOrdering](interfaces/ColumnOrdering.md)
|
||||
@@ -74,11 +65,9 @@
|
||||
- [DropNamespaceOptions](interfaces/DropNamespaceOptions.md)
|
||||
- [DropNamespaceResponse](interfaces/DropNamespaceResponse.md)
|
||||
- [ExecutableQuery](interfaces/ExecutableQuery.md)
|
||||
- [FieldMetadataUpdate](interfaces/FieldMetadataUpdate.md)
|
||||
- [FragmentStatistics](interfaces/FragmentStatistics.md)
|
||||
- [FragmentSummaryStats](interfaces/FragmentSummaryStats.md)
|
||||
- [FtsOptions](interfaces/FtsOptions.md)
|
||||
- [FtsToken](interfaces/FtsToken.md)
|
||||
- [FullTextQuery](interfaces/FullTextQuery.md)
|
||||
- [FullTextSearchOptions](interfaces/FullTextSearchOptions.md)
|
||||
- [HnswPqOptions](interfaces/HnswPqOptions.md)
|
||||
@@ -89,18 +78,10 @@
|
||||
- [IvfFlatOptions](interfaces/IvfFlatOptions.md)
|
||||
- [IvfPqOptions](interfaces/IvfPqOptions.md)
|
||||
- [IvfRqOptions](interfaces/IvfRqOptions.md)
|
||||
- [JobDescription](interfaces/JobDescription.md)
|
||||
- [JobFailureInfo](interfaces/JobFailureInfo.md)
|
||||
- [JobInfo](interfaces/JobInfo.md)
|
||||
- [ListNamespacesOptions](interfaces/ListNamespacesOptions.md)
|
||||
- [ListNamespacesResponse](interfaces/ListNamespacesResponse.md)
|
||||
- [LsmWriteSpec](interfaces/LsmWriteSpec.md)
|
||||
- [MergeBlocker](interfaces/MergeBlocker.md)
|
||||
- [MergeBranchResult](interfaces/MergeBranchResult.md)
|
||||
- [MergePreview](interfaces/MergePreview.md)
|
||||
- [MergeResult](interfaces/MergeResult.md)
|
||||
- [NativeOAuthConfig](interfaces/NativeOAuthConfig.md)
|
||||
- [OAuthConfig](interfaces/OAuthConfig.md)
|
||||
- [OpenTableOptions](interfaces/OpenTableOptions.md)
|
||||
- [OptimizeOptions](interfaces/OptimizeOptions.md)
|
||||
- [OptimizeStats](interfaces/OptimizeStats.md)
|
||||
@@ -120,8 +101,6 @@
|
||||
- [TimeoutConfig](interfaces/TimeoutConfig.md)
|
||||
- [TlsConfig](interfaces/TlsConfig.md)
|
||||
- [TokenResponse](interfaces/TokenResponse.md)
|
||||
- [TokenizeOptions](interfaces/TokenizeOptions.md)
|
||||
- [UpdateFieldMetadataResult](interfaces/UpdateFieldMetadataResult.md)
|
||||
- [UpdateOptions](interfaces/UpdateOptions.md)
|
||||
- [UpdateResult](interfaces/UpdateResult.md)
|
||||
- [Version](interfaces/Version.md)
|
||||
@@ -130,8 +109,6 @@
|
||||
|
||||
## Type Aliases
|
||||
|
||||
- [AnalyzePlanDistributedMetrics](type-aliases/AnalyzePlanDistributedMetrics.md)
|
||||
- [BaseTokenizer](type-aliases/BaseTokenizer.md)
|
||||
- [Data](type-aliases/Data.md)
|
||||
- [DataLike](type-aliases/DataLike.md)
|
||||
- [FieldLike](type-aliases/FieldLike.md)
|
||||
@@ -141,15 +118,12 @@
|
||||
- [RecordBatchLike](type-aliases/RecordBatchLike.md)
|
||||
- [SchemaLike](type-aliases/SchemaLike.md)
|
||||
- [TableLike](type-aliases/TableLike.md)
|
||||
- [TokenizeTableOptions](type-aliases/TokenizeTableOptions.md)
|
||||
|
||||
## Functions
|
||||
|
||||
- [RecordBatchIterator](functions/RecordBatchIterator.md)
|
||||
- [connect](functions/connect.md)
|
||||
- [connectNamespace](functions/connectNamespace.md)
|
||||
- [instrumentLanceDbMetrics](functions/instrumentLanceDbMetrics.md)
|
||||
- [makeArrowTable](functions/makeArrowTable.md)
|
||||
- [packBits](functions/packBits.md)
|
||||
- [permutationBuilder](functions/permutationBuilder.md)
|
||||
- [tokenize](functions/tokenize.md)
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / BranchColumnChange
|
||||
|
||||
# Interface: BranchColumnChange
|
||||
|
||||
A column whose definition differs between main and the branch.
|
||||
|
||||
## Properties
|
||||
|
||||
### branch
|
||||
|
||||
```ts
|
||||
branch: BranchColumnSummary;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### main
|
||||
|
||||
```ts
|
||||
main: BranchColumnSummary;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### name
|
||||
|
||||
```ts
|
||||
name: string;
|
||||
```
|
||||
@@ -1,33 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / BranchColumnSummary
|
||||
|
||||
# Interface: BranchColumnSummary
|
||||
|
||||
Summary of a column in a branch diff.
|
||||
|
||||
## Properties
|
||||
|
||||
### dataType
|
||||
|
||||
```ts
|
||||
dataType: string;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### name
|
||||
|
||||
```ts
|
||||
name: string;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### nullable
|
||||
|
||||
```ts
|
||||
nullable: boolean;
|
||||
```
|
||||
@@ -1,129 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / BranchDiff
|
||||
|
||||
# Interface: BranchDiff
|
||||
|
||||
Read-only comparison of a branch against main.
|
||||
|
||||
## Properties
|
||||
|
||||
### addedColumns
|
||||
|
||||
```ts
|
||||
addedColumns: BranchColumnSummary[];
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### addedIndexes
|
||||
|
||||
```ts
|
||||
addedIndexes: BranchIndexSummary[];
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### baseMoved
|
||||
|
||||
```ts
|
||||
baseMoved: boolean;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### branchVersion
|
||||
|
||||
```ts
|
||||
branchVersion: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### changedColumns
|
||||
|
||||
```ts
|
||||
changedColumns: BranchColumnChange[];
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### fromBranch
|
||||
|
||||
```ts
|
||||
fromBranch: string;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### mainVersion
|
||||
|
||||
```ts
|
||||
mainVersion: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### mergeBlockers
|
||||
|
||||
```ts
|
||||
mergeBlockers: MergeBlocker[];
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### mergeable
|
||||
|
||||
```ts
|
||||
mergeable: boolean;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### parentVersion
|
||||
|
||||
```ts
|
||||
parentVersion: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### removedColumns
|
||||
|
||||
```ts
|
||||
removedColumns: BranchColumnSummary[];
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### removedIndexes
|
||||
|
||||
```ts
|
||||
removedIndexes: BranchIndexSummary[];
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### rowCountBranch
|
||||
|
||||
```ts
|
||||
rowCountBranch: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### rowCountMain
|
||||
|
||||
```ts
|
||||
rowCountMain: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### rowSummary
|
||||
|
||||
```ts
|
||||
rowSummary: BranchRowCountSummary;
|
||||
```
|
||||
@@ -1,41 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / BranchIndexSummary
|
||||
|
||||
# Interface: BranchIndexSummary
|
||||
|
||||
Summary of an index in a branch diff.
|
||||
|
||||
## Properties
|
||||
|
||||
### columns
|
||||
|
||||
```ts
|
||||
columns: string[];
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### indexName
|
||||
|
||||
```ts
|
||||
indexName: string;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### indexType?
|
||||
|
||||
```ts
|
||||
optional indexType: string;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### status
|
||||
|
||||
```ts
|
||||
status: string;
|
||||
```
|
||||
@@ -1,57 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / BranchRowCountSummary
|
||||
|
||||
# Interface: BranchRowCountSummary
|
||||
|
||||
Row-level comparison between main and the branch.
|
||||
|
||||
## Properties
|
||||
|
||||
### deltaAvailable
|
||||
|
||||
```ts
|
||||
deltaAvailable: boolean;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### inputsChanged
|
||||
|
||||
```ts
|
||||
inputsChanged: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### newOnBase
|
||||
|
||||
```ts
|
||||
newOnBase: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### newOnBranch
|
||||
|
||||
```ts
|
||||
newOnBranch: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### staleRecompute
|
||||
|
||||
```ts
|
||||
staleRecompute: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### unchanged
|
||||
|
||||
```ts
|
||||
unchanged: number;
|
||||
```
|
||||
@@ -64,19 +64,6 @@ client used by manifest-enabled native connections.
|
||||
|
||||
***
|
||||
|
||||
### oauthConfig?
|
||||
|
||||
```ts
|
||||
optional oauthConfig: NativeOAuthConfig;
|
||||
```
|
||||
|
||||
(For LanceDB cloud only): OAuth configuration for IdP-based
|
||||
authentication (e.g., Azure Entra ID). When set, token acquisition
|
||||
and refresh are handled entirely in Rust. TypeScript users should pass
|
||||
the public `OAuthConfig` type exported from `@lancedb/lancedb`.
|
||||
|
||||
***
|
||||
|
||||
### readConsistencyInterval?
|
||||
|
||||
```ts
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / FieldMetadataUpdate
|
||||
|
||||
# Interface: FieldMetadataUpdate
|
||||
|
||||
A per-field metadata update, addressed by dot-path.
|
||||
|
||||
## Properties
|
||||
|
||||
### metadata
|
||||
|
||||
```ts
|
||||
metadata: Record<string, null | string>;
|
||||
```
|
||||
|
||||
Metadata key/value pairs. Merged into the field's existing metadata by
|
||||
default; a value of `null` deletes that key.
|
||||
|
||||
***
|
||||
|
||||
### path
|
||||
|
||||
```ts
|
||||
path: string;
|
||||
```
|
||||
|
||||
Dot-separated path to the field. For a top-level column this is just its
|
||||
name; for a nested field it's the path, e.g. "a.b.c".
|
||||
|
||||
***
|
||||
|
||||
### replace?
|
||||
|
||||
```ts
|
||||
optional replace: boolean;
|
||||
```
|
||||
|
||||
If true, replace the field's entire metadata map instead of merging.
|
||||
@@ -23,7 +23,7 @@ whether to remove punctuation
|
||||
### baseTokenizer?
|
||||
|
||||
```ts
|
||||
optional baseTokenizer: BaseTokenizer;
|
||||
optional baseTokenizer: "raw" | "simple" | "whitespace" | "ngram";
|
||||
```
|
||||
|
||||
The tokenizer to use when building the index.
|
||||
@@ -37,38 +37,6 @@ The following tokenizers are available:
|
||||
|
||||
"raw" - Raw tokenizer. This tokenizer does not split the text into tokens and indexes the entire text as a single token.
|
||||
|
||||
"icu" - ICU dictionary-based word segmentation.
|
||||
|
||||
"icu/split" - ICU segmentation with simple-style delimiter splitting.
|
||||
|
||||
***
|
||||
|
||||
### blockSize?
|
||||
|
||||
```ts
|
||||
optional blockSize: 128 | 256;
|
||||
```
|
||||
|
||||
Number of documents per compressed posting block.
|
||||
|
||||
The default is 128. Supported values are 128 and 256. A value of 256 uses
|
||||
the experimental FTS V3 format and may introduce breaking changes.
|
||||
|
||||
***
|
||||
|
||||
### customStopWords?
|
||||
|
||||
```ts
|
||||
optional customStopWords: string[];
|
||||
```
|
||||
|
||||
Custom stop words that replace the built-in list for `language`.
|
||||
|
||||
This option only affects tokenization when `removeStopWords` is true.
|
||||
|
||||
`undefined` keeps the built-in language list. An empty array explicitly
|
||||
replaces it with no stop words.
|
||||
|
||||
***
|
||||
|
||||
### language?
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / FtsToken
|
||||
|
||||
# Interface: FtsToken
|
||||
|
||||
Token produced by the tokenizer configured on a full-text search index.
|
||||
|
||||
## Properties
|
||||
|
||||
### position
|
||||
|
||||
```ts
|
||||
position: number;
|
||||
```
|
||||
|
||||
Token position used by full-text query matching.
|
||||
|
||||
***
|
||||
|
||||
### text
|
||||
|
||||
```ts
|
||||
text: string;
|
||||
```
|
||||
|
||||
Token text after tokenizer filters have been applied.
|
||||
@@ -23,31 +23,6 @@ be more columns to represent composite indices.
|
||||
|
||||
***
|
||||
|
||||
### createdAt?
|
||||
|
||||
```ts
|
||||
optional createdAt: Date;
|
||||
```
|
||||
|
||||
When the index was created.
|
||||
|
||||
`undefined` for remote tables or indices created before timestamps were tracked.
|
||||
|
||||
***
|
||||
|
||||
### indexDetails?
|
||||
|
||||
```ts
|
||||
optional indexDetails: any;
|
||||
```
|
||||
|
||||
Index-type-specific details parsed as a JavaScript object.
|
||||
|
||||
Falls back to a raw string if JSON parsing fails. `undefined` for
|
||||
remote tables or when details are unavailable.
|
||||
|
||||
***
|
||||
|
||||
### indexType
|
||||
|
||||
```ts
|
||||
@@ -58,30 +33,6 @@ The type of the index
|
||||
|
||||
***
|
||||
|
||||
### indexUuid?
|
||||
|
||||
```ts
|
||||
optional indexUuid: string;
|
||||
```
|
||||
|
||||
The UUID of the first segment of the index.
|
||||
|
||||
`undefined` for remote tables, which do not yet surface this.
|
||||
|
||||
***
|
||||
|
||||
### indexVersion?
|
||||
|
||||
```ts
|
||||
optional indexVersion: number;
|
||||
```
|
||||
|
||||
The on-disk index format version.
|
||||
|
||||
`undefined` for remote tables.
|
||||
|
||||
***
|
||||
|
||||
### name
|
||||
|
||||
```ts
|
||||
@@ -89,63 +40,3 @@ name: string;
|
||||
```
|
||||
|
||||
The name of the index
|
||||
|
||||
***
|
||||
|
||||
### numIndexedRows?
|
||||
|
||||
```ts
|
||||
optional numIndexedRows: number;
|
||||
```
|
||||
|
||||
The number of rows indexed, across all segments.
|
||||
|
||||
`undefined` for remote tables.
|
||||
|
||||
***
|
||||
|
||||
### numSegments?
|
||||
|
||||
```ts
|
||||
optional numSegments: number;
|
||||
```
|
||||
|
||||
The number of segments that make up the index.
|
||||
|
||||
`undefined` for remote tables.
|
||||
|
||||
***
|
||||
|
||||
### numUnindexedRows?
|
||||
|
||||
```ts
|
||||
optional numUnindexedRows: number;
|
||||
```
|
||||
|
||||
The number of rows not yet covered by this index.
|
||||
|
||||
`undefined` for remote tables.
|
||||
|
||||
***
|
||||
|
||||
### sizeBytes?
|
||||
|
||||
```ts
|
||||
optional sizeBytes: number;
|
||||
```
|
||||
|
||||
The total size in bytes of all index files across all segments.
|
||||
|
||||
`undefined` for remote tables or indices without size tracking.
|
||||
|
||||
***
|
||||
|
||||
### typeUrl?
|
||||
|
||||
```ts
|
||||
optional typeUrl: string;
|
||||
```
|
||||
|
||||
The protobuf type URL, a precise type identifier for the index.
|
||||
|
||||
`undefined` for remote tables.
|
||||
|
||||
@@ -30,6 +30,17 @@ The type of the index
|
||||
|
||||
***
|
||||
|
||||
### loss?
|
||||
|
||||
```ts
|
||||
optional loss: number;
|
||||
```
|
||||
|
||||
The KMeans loss value of the index,
|
||||
it is only present for vector indices.
|
||||
|
||||
***
|
||||
|
||||
### numIndexedRows
|
||||
|
||||
```ts
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / JobDescription
|
||||
|
||||
# Interface: JobDescription
|
||||
|
||||
A described job from `Connection.getJob`.
|
||||
|
||||
## Properties
|
||||
|
||||
### creationMs
|
||||
|
||||
```ts
|
||||
creationMs: number;
|
||||
```
|
||||
|
||||
When the job was created, in milliseconds since the epoch.
|
||||
|
||||
***
|
||||
|
||||
### failure?
|
||||
|
||||
```ts
|
||||
optional failure: JobFailureInfo;
|
||||
```
|
||||
|
||||
Why the job failed, when the job is failed and the server reports a
|
||||
reason.
|
||||
|
||||
***
|
||||
|
||||
### jobId
|
||||
|
||||
```ts
|
||||
jobId: string;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### jobType
|
||||
|
||||
```ts
|
||||
jobType: string;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### specJson?
|
||||
|
||||
```ts
|
||||
optional specJson: string;
|
||||
```
|
||||
|
||||
The job-type-specific specification as a JSON string, when present.
|
||||
|
||||
***
|
||||
|
||||
### state
|
||||
|
||||
```ts
|
||||
state: string;
|
||||
```
|
||||
|
||||
Lifecycle state: "running", "finished", "failed", or "cancelled".
|
||||
@@ -1,33 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / JobFailureInfo
|
||||
|
||||
# Interface: JobFailureInfo
|
||||
|
||||
The server's account of why a job failed.
|
||||
|
||||
## Properties
|
||||
|
||||
### message?
|
||||
|
||||
```ts
|
||||
optional message: string;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### phase?
|
||||
|
||||
```ts
|
||||
optional phase: string;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### retryable?
|
||||
|
||||
```ts
|
||||
optional retryable: boolean;
|
||||
```
|
||||
@@ -1,58 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / JobInfo
|
||||
|
||||
# Interface: JobInfo
|
||||
|
||||
A row from `Connection.listJobs`: one server-side job.
|
||||
|
||||
## Properties
|
||||
|
||||
### createdAtMillis
|
||||
|
||||
```ts
|
||||
createdAtMillis: number;
|
||||
```
|
||||
|
||||
When the job was created, in milliseconds since the epoch.
|
||||
|
||||
***
|
||||
|
||||
### jobId
|
||||
|
||||
```ts
|
||||
jobId: string;
|
||||
```
|
||||
|
||||
The job id -- what `Connection.getJob` and `Connection.cancelJob`
|
||||
accept.
|
||||
|
||||
***
|
||||
|
||||
### jobType
|
||||
|
||||
```ts
|
||||
jobType: string;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### state
|
||||
|
||||
```ts
|
||||
state: string;
|
||||
```
|
||||
|
||||
Lifecycle state: "running", "finished", "failed", or "cancelled".
|
||||
|
||||
***
|
||||
|
||||
### table
|
||||
|
||||
```ts
|
||||
table: string;
|
||||
```
|
||||
|
||||
The table the job runs against, without URI or namespace.
|
||||
@@ -11,10 +11,7 @@ Specification selecting Lance's MemWAL LSM-style write path for
|
||||
|
||||
`specType` is `"bucket"`, `"identity"`, or `"unsharded"`. For `"bucket"`,
|
||||
`column` and `numBuckets` are required; for `"identity"`, `column` is
|
||||
required and must be a deterministic function of the unenforced primary
|
||||
key (every row with a given primary key must always produce the same
|
||||
`column` value, or upserts of that key can land in different shards and a
|
||||
stale version can win).
|
||||
required.
|
||||
|
||||
## Properties
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / MergeBlocker
|
||||
|
||||
# Interface: MergeBlocker
|
||||
|
||||
A reason why a branch cannot currently be merged.
|
||||
|
||||
## Properties
|
||||
|
||||
### code
|
||||
|
||||
```ts
|
||||
code: string;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### message
|
||||
|
||||
```ts
|
||||
message: string;
|
||||
```
|
||||
@@ -1,46 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / MergeBranchResult
|
||||
|
||||
# Interface: MergeBranchResult
|
||||
|
||||
Result of previewing or attempting a branch merge.
|
||||
|
||||
## Properties
|
||||
|
||||
### diff
|
||||
|
||||
```ts
|
||||
diff: BranchDiff;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### mainVersionAfter?
|
||||
|
||||
```ts
|
||||
optional mainVersionAfter: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### preview
|
||||
|
||||
```ts
|
||||
preview: MergePreview;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### status
|
||||
|
||||
```ts
|
||||
status:
|
||||
| "unknown"
|
||||
| "rejected"
|
||||
| "ready"
|
||||
| "notImplemented"
|
||||
| "merged";
|
||||
```
|
||||
@@ -1,17 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / MergePreview
|
||||
|
||||
# Interface: MergePreview
|
||||
|
||||
Changes that would be, or were, promoted by a branch merge.
|
||||
|
||||
## Properties
|
||||
|
||||
### promotedColumns
|
||||
|
||||
```ts
|
||||
promotedColumns: string[];
|
||||
```
|
||||
@@ -32,14 +32,6 @@ numInsertedRows: number;
|
||||
|
||||
***
|
||||
|
||||
### numRows
|
||||
|
||||
```ts
|
||||
numRows: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### numUpdatedRows
|
||||
|
||||
```ts
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / NativeOAuthConfig
|
||||
|
||||
# Interface: NativeOAuthConfig
|
||||
|
||||
OAuth configuration for LanceDB authentication.
|
||||
|
||||
This is the generated napi-rs binding shape. TypeScript users should prefer
|
||||
the public `OAuthConfig` type exported from `@lancedb/lancedb`.
|
||||
|
||||
All token acquisition and refresh is handled in the Rust layer.
|
||||
|
||||
## Properties
|
||||
|
||||
### clientId
|
||||
|
||||
```ts
|
||||
clientId: string;
|
||||
```
|
||||
|
||||
Application / Client ID.
|
||||
|
||||
***
|
||||
|
||||
### clientSecret?
|
||||
|
||||
```ts
|
||||
optional clientSecret: string;
|
||||
```
|
||||
|
||||
Client secret (required for client_credentials).
|
||||
|
||||
***
|
||||
|
||||
### flow?
|
||||
|
||||
```ts
|
||||
optional flow: string;
|
||||
```
|
||||
|
||||
Authentication flow: "client_credentials" or "azure_managed_identity"
|
||||
|
||||
***
|
||||
|
||||
### issuerUrl
|
||||
|
||||
```ts
|
||||
issuerUrl: string;
|
||||
```
|
||||
|
||||
OIDC issuer URL or OAuth authority URL.
|
||||
For Azure: `https://login.microsoftonline.com/{tenant_id}/v2.0`
|
||||
|
||||
***
|
||||
|
||||
### managedIdentityClientId?
|
||||
|
||||
```ts
|
||||
optional managedIdentityClientId: string;
|
||||
```
|
||||
|
||||
Client ID for user-assigned managed identity (azure_managed_identity).
|
||||
|
||||
***
|
||||
|
||||
### refreshBufferSecs?
|
||||
|
||||
```ts
|
||||
optional refreshBufferSecs: number;
|
||||
```
|
||||
|
||||
Seconds before expiry to trigger proactive refresh (default: 300).
|
||||
Keep this well below the token TTL; if it is greater than or equal to
|
||||
the TTL, each request refreshes the token.
|
||||
|
||||
***
|
||||
|
||||
### scopes
|
||||
|
||||
```ts
|
||||
scopes: string[];
|
||||
```
|
||||
|
||||
OAuth scopes to request. For Azure managed identity, exactly one scope
|
||||
or resource is required. For example: `["api://{app_id}/.default"]`
|
||||
@@ -1,111 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / OAuthConfig
|
||||
|
||||
# Interface: OAuthConfig
|
||||
|
||||
OAuth configuration for LanceDB authentication.
|
||||
|
||||
This is the public TypeScript OAuth configuration type. The generated
|
||||
`NativeOAuthConfig` type has the same runtime shape but is an implementation
|
||||
detail of the napi-rs binding.
|
||||
|
||||
All token acquisition and refresh is handled in the Rust layer.
|
||||
This config is passed through to Rust via napi-rs.
|
||||
|
||||
## Examples
|
||||
|
||||
```typescript
|
||||
const config: OAuthConfig = {
|
||||
issuerUrl: "https://login.microsoftonline.com/{tenant}/v2.0",
|
||||
clientId: "app-id",
|
||||
clientSecret: "secret",
|
||||
scopes: ["api://lancedb-api/.default"],
|
||||
};
|
||||
```
|
||||
|
||||
```typescript
|
||||
const config: OAuthConfig = {
|
||||
issuerUrl: "https://login.microsoftonline.com/{tenant}/v2.0",
|
||||
clientId: "app-id",
|
||||
scopes: ["api://lancedb-api/.default"],
|
||||
flow: OAuthFlowType.AzureManagedIdentity,
|
||||
};
|
||||
```
|
||||
|
||||
## Properties
|
||||
|
||||
### clientId
|
||||
|
||||
```ts
|
||||
clientId: string;
|
||||
```
|
||||
|
||||
Application / Client ID.
|
||||
|
||||
***
|
||||
|
||||
### clientSecret?
|
||||
|
||||
```ts
|
||||
optional clientSecret: string;
|
||||
```
|
||||
|
||||
Client secret (required for ClientCredentials).
|
||||
|
||||
***
|
||||
|
||||
### flow?
|
||||
|
||||
```ts
|
||||
optional flow: OAuthFlowType;
|
||||
```
|
||||
|
||||
Authentication flow (default: ClientCredentials).
|
||||
|
||||
***
|
||||
|
||||
### issuerUrl
|
||||
|
||||
```ts
|
||||
issuerUrl: string;
|
||||
```
|
||||
|
||||
OIDC issuer URL or OAuth authority URL.
|
||||
For Azure: `https://login.microsoftonline.com/{tenant_id}/v2.0`
|
||||
|
||||
***
|
||||
|
||||
### managedIdentityClientId?
|
||||
|
||||
```ts
|
||||
optional managedIdentityClientId: string;
|
||||
```
|
||||
|
||||
Client ID for user-assigned managed identity (AzureManagedIdentity).
|
||||
|
||||
***
|
||||
|
||||
### refreshBufferSecs?
|
||||
|
||||
```ts
|
||||
optional refreshBufferSecs: number;
|
||||
```
|
||||
|
||||
Seconds before expiry to trigger proactive refresh (default: 300).
|
||||
Keep this well below the token TTL; if it is greater than or equal to
|
||||
the TTL, each request refreshes the token.
|
||||
|
||||
***
|
||||
|
||||
### scopes
|
||||
|
||||
```ts
|
||||
scopes: string[];
|
||||
```
|
||||
|
||||
OAuth scopes to request.
|
||||
For Azure managed identity, exactly one scope or resource is required.
|
||||
For example: `["api://{app_id}/.default"]`
|
||||
@@ -8,18 +8,6 @@
|
||||
|
||||
## Properties
|
||||
|
||||
### branch?
|
||||
|
||||
```ts
|
||||
optional branch: string;
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
***
|
||||
|
||||
### ~~indexCacheSize?~~
|
||||
|
||||
```ts
|
||||
@@ -55,17 +43,3 @@ 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/
|
||||
|
||||
***
|
||||
|
||||
### version?
|
||||
|
||||
```ts
|
||||
optional version: number;
|
||||
```
|
||||
|
||||
Open the table pinned to this version, producing a read-only view.
|
||||
|
||||
Composes with [OpenTableOptions.branch](OpenTableOptions.md#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.
|
||||
|
||||
@@ -8,14 +8,6 @@
|
||||
|
||||
## Properties
|
||||
|
||||
### clumpSize?
|
||||
|
||||
```ts
|
||||
optional clumpSize: number;
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### counts?
|
||||
|
||||
```ts
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / TokenizeOptions
|
||||
|
||||
# Interface: TokenizeOptions
|
||||
|
||||
Options for tokenizing a full-text search query without a table index.
|
||||
|
||||
## Properties
|
||||
|
||||
### asciiFolding?
|
||||
|
||||
```ts
|
||||
optional asciiFolding: boolean;
|
||||
```
|
||||
|
||||
Whether to fold ASCII characters.
|
||||
|
||||
***
|
||||
|
||||
### baseTokenizer?
|
||||
|
||||
```ts
|
||||
optional baseTokenizer: BaseTokenizer;
|
||||
```
|
||||
|
||||
The tokenizer to use. The default is "simple".
|
||||
|
||||
***
|
||||
|
||||
### customStopWords?
|
||||
|
||||
```ts
|
||||
optional customStopWords: string[];
|
||||
```
|
||||
|
||||
Custom stop words that replace the built-in list for `language`.
|
||||
|
||||
This option only affects tokenization when `removeStopWords` is true.
|
||||
|
||||
`undefined` keeps the built-in language list. An empty array explicitly
|
||||
replaces it with no stop words.
|
||||
|
||||
***
|
||||
|
||||
### language?
|
||||
|
||||
```ts
|
||||
optional language: string;
|
||||
```
|
||||
|
||||
Language for stemming and stop words.
|
||||
|
||||
***
|
||||
|
||||
### lowercase?
|
||||
|
||||
```ts
|
||||
optional lowercase: boolean;
|
||||
```
|
||||
|
||||
Whether to lowercase tokens.
|
||||
|
||||
***
|
||||
|
||||
### maxTokenLength?
|
||||
|
||||
```ts
|
||||
optional maxTokenLength: number;
|
||||
```
|
||||
|
||||
Maximum token length; tokens longer than this are ignored.
|
||||
|
||||
***
|
||||
|
||||
### ngramMaxLength?
|
||||
|
||||
```ts
|
||||
optional ngramMaxLength: number;
|
||||
```
|
||||
|
||||
N-gram maximum length.
|
||||
|
||||
***
|
||||
|
||||
### ngramMinLength?
|
||||
|
||||
```ts
|
||||
optional ngramMinLength: number;
|
||||
```
|
||||
|
||||
N-gram minimum length.
|
||||
|
||||
***
|
||||
|
||||
### prefixOnly?
|
||||
|
||||
```ts
|
||||
optional prefixOnly: boolean;
|
||||
```
|
||||
|
||||
Whether to only emit token prefixes for the n-gram tokenizer.
|
||||
|
||||
***
|
||||
|
||||
### removeStopWords?
|
||||
|
||||
```ts
|
||||
optional removeStopWords: boolean;
|
||||
```
|
||||
|
||||
Whether to remove stop words.
|
||||
|
||||
***
|
||||
|
||||
### stem?
|
||||
|
||||
```ts
|
||||
optional stem: boolean;
|
||||
```
|
||||
|
||||
Whether to stem tokens.
|
||||
@@ -1,15 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / UpdateFieldMetadataResult
|
||||
|
||||
# Interface: UpdateFieldMetadataResult
|
||||
|
||||
## Properties
|
||||
|
||||
### version
|
||||
|
||||
```ts
|
||||
version: number;
|
||||
```
|
||||
@@ -1,11 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / AnalyzePlanDistributedMetrics
|
||||
|
||||
# Type Alias: AnalyzePlanDistributedMetrics
|
||||
|
||||
```ts
|
||||
type AnalyzePlanDistributedMetrics: "aggregate" | "per_worker" | "full";
|
||||
```
|
||||
@@ -1,19 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / BaseTokenizer
|
||||
|
||||
# Type Alias: BaseTokenizer
|
||||
|
||||
```ts
|
||||
type BaseTokenizer:
|
||||
| "simple"
|
||||
| "whitespace"
|
||||
| "raw"
|
||||
| "ngram"
|
||||
| "icu"
|
||||
| "icu/split"
|
||||
| `jieba/${string}`
|
||||
| `lindera/${string}`;
|
||||
```
|
||||
@@ -1,11 +0,0 @@
|
||||
[**@lancedb/lancedb**](../README.md) • **Docs**
|
||||
|
||||
***
|
||||
|
||||
[@lancedb/lancedb](../globals.md) / TokenizeTableOptions
|
||||
|
||||
# Type Alias: TokenizeTableOptions
|
||||
|
||||
```ts
|
||||
type TokenizeTableOptions: object | object;
|
||||
```
|
||||
+52
-141
@@ -26,18 +26,6 @@ is also an [asynchronous API client](#connections-asynchronous).
|
||||
|
||||
::: lancedb.db.DBConnection
|
||||
|
||||
::: lancedb.Session
|
||||
|
||||
## Namespaces (Synchronous)
|
||||
|
||||
A namespace-backed connection resolves tables through a
|
||||
[Lance namespace](https://lance-format.github.io/lance-namespace/) service instead of
|
||||
listing a storage directory.
|
||||
|
||||
::: lancedb.connect_namespace
|
||||
|
||||
::: lancedb.namespace.LanceNamespaceDBConnection
|
||||
|
||||
## Tables (Synchronous)
|
||||
|
||||
::: lancedb.table.Table
|
||||
@@ -46,12 +34,8 @@ listing a storage directory.
|
||||
|
||||
::: lancedb.table.FragmentSummaryStats
|
||||
|
||||
::: lancedb.table.TableStatistics
|
||||
|
||||
::: lancedb.table.Tags
|
||||
|
||||
::: lancedb.table.Branches
|
||||
|
||||
## Expressions
|
||||
|
||||
Type-safe expression builder for filters and projections. Use these instead
|
||||
@@ -78,46 +62,29 @@ of raw SQL strings with [where][lancedb.query.LanceQueryBuilder.where] and
|
||||
|
||||
::: lancedb.query.LanceHybridQueryBuilder
|
||||
|
||||
::: lancedb.query.LanceEmptyQueryBuilder
|
||||
|
||||
::: lancedb.query.LanceTakeQueryBuilder
|
||||
|
||||
## Full text queries
|
||||
|
||||
Structured full text queries can be passed to
|
||||
[Table.search][lancedb.table.Table.search] or
|
||||
[AsyncTable.search][lancedb.table.AsyncTable.search] in place of a query string,
|
||||
and combined with [BooleanQuery][lancedb.query.BooleanQuery].
|
||||
|
||||
::: lancedb.query.FullTextQuery
|
||||
|
||||
::: lancedb.query.MatchQuery
|
||||
|
||||
::: lancedb.query.PhraseQuery
|
||||
|
||||
::: lancedb.query.BoostQuery
|
||||
|
||||
::: lancedb.query.MultiMatchQuery
|
||||
|
||||
::: lancedb.query.BooleanQuery
|
||||
|
||||
::: lancedb.query.FullTextOperator
|
||||
|
||||
::: lancedb.query.Occur
|
||||
|
||||
## Embeddings
|
||||
|
||||
::: lancedb.embeddings
|
||||
options:
|
||||
show_root_heading: false
|
||||
show_root_toc_entry: false
|
||||
::: lancedb.embeddings.registry.EmbeddingFunctionRegistry
|
||||
|
||||
::: lancedb.embeddings.base.EmbeddingFunctionConfig
|
||||
|
||||
::: lancedb.embeddings.base.EmbeddingFunction
|
||||
|
||||
::: lancedb.embeddings.base.TextEmbeddingFunction
|
||||
|
||||
::: lancedb.embeddings.sentence_transformers.SentenceTransformerEmbeddings
|
||||
|
||||
::: lancedb.embeddings.openai.OpenAIEmbeddings
|
||||
|
||||
::: lancedb.embeddings.open_clip.OpenClipEmbeddings
|
||||
|
||||
## Remote configuration
|
||||
|
||||
::: lancedb.remote
|
||||
options:
|
||||
show_root_heading: false
|
||||
show_root_toc_entry: false
|
||||
::: lancedb.remote.ClientConfig
|
||||
|
||||
::: lancedb.remote.TimeoutConfig
|
||||
|
||||
::: lancedb.remote.RetryConfig
|
||||
|
||||
## Context
|
||||
|
||||
@@ -127,50 +94,11 @@ and combined with [BooleanQuery][lancedb.query.BooleanQuery].
|
||||
|
||||
## Full text search
|
||||
|
||||
Pass `custom_stop_words` to [lancedb.index.FTS][]:
|
||||
Use [lancedb.table.Table.create_fts_index][] for the synchronous API or
|
||||
[lancedb.table.AsyncTable.create_index][] with [lancedb.index.FTS][] for the
|
||||
asynchronous API.
|
||||
|
||||
```python
|
||||
from lancedb.index import FTS
|
||||
|
||||
table.create_index(
|
||||
"text",
|
||||
config=FTS(remove_stop_words=True, custom_stop_words=["acme", "internal"]),
|
||||
)
|
||||
```
|
||||
|
||||
The list replaces the built-in stop words and is used only when
|
||||
`remove_stop_words=True`:
|
||||
|
||||
- `custom_stop_words=None` uses the built-in list for `language`.
|
||||
- `custom_stop_words=[]` removes no words.
|
||||
- Values are passed through without trimming, lowercasing, or other rewriting.
|
||||
|
||||
The same option is available on `lancedb.tokenize(...)` and the deprecated
|
||||
[lancedb.table.Table.create_fts_index][] compatibility helper:
|
||||
|
||||
```python
|
||||
import lancedb
|
||||
|
||||
tokens = list(lancedb.tokenize("acme makes searchable data",
|
||||
custom_stop_words=["acme"]))
|
||||
```
|
||||
|
||||
::: lancedb.tokenize
|
||||
|
||||
::: lancedb.FtsToken
|
||||
|
||||
## Blobs
|
||||
|
||||
Blob columns store large binary values out of line so they can be read lazily
|
||||
instead of being materialized with the rest of the row.
|
||||
|
||||
::: lancedb.blob
|
||||
|
||||
::: lancedb.BlobType
|
||||
|
||||
::: lancedb._blob.BlobFile
|
||||
options:
|
||||
show_root_full_path: false
|
||||
::: lancedb.index.FTS
|
||||
|
||||
## Utilities
|
||||
|
||||
@@ -178,14 +106,6 @@ instead of being materialized with the rest of the row.
|
||||
|
||||
::: lancedb.merge.LanceMergeInsertBuilder
|
||||
|
||||
::: lancedb.otel.instrument_lancedb_metrics
|
||||
|
||||
## Exceptions
|
||||
|
||||
::: lancedb.exceptions.MissingValueError
|
||||
|
||||
::: lancedb.exceptions.MissingColumnError
|
||||
|
||||
## Integrations
|
||||
|
||||
## Pydantic
|
||||
@@ -194,30 +114,19 @@ instead of being materialized with the rest of the row.
|
||||
|
||||
::: lancedb.pydantic.vector
|
||||
|
||||
::: lancedb.pydantic.Vector
|
||||
|
||||
::: lancedb.pydantic.MultiVector
|
||||
|
||||
::: lancedb.pydantic.LanceModel
|
||||
|
||||
## PyTorch
|
||||
|
||||
::: lancedb.streaming.StreamingDataset
|
||||
|
||||
::: lancedb.permutation.permutation_builder
|
||||
|
||||
::: lancedb.permutation.PermutationBuilder
|
||||
|
||||
::: lancedb.permutation.Permutation
|
||||
|
||||
::: lancedb.permutation.Transforms
|
||||
|
||||
## Reranking
|
||||
|
||||
::: lancedb.rerankers
|
||||
options:
|
||||
show_root_heading: false
|
||||
show_root_toc_entry: false
|
||||
::: lancedb.rerankers.linear_combination.LinearCombinationReranker
|
||||
|
||||
::: lancedb.rerankers.cohere.CohereReranker
|
||||
|
||||
::: lancedb.rerankers.colbert.ColbertReranker
|
||||
|
||||
::: lancedb.rerankers.cross_encoder.CrossEncoderReranker
|
||||
|
||||
::: lancedb.rerankers.openai.OpenaiReranker
|
||||
|
||||
## Connections (Asynchronous)
|
||||
|
||||
@@ -228,12 +137,6 @@ can be used to create, list, or open tables.
|
||||
|
||||
::: lancedb.db.AsyncConnection
|
||||
|
||||
## Namespaces (Asynchronous)
|
||||
|
||||
::: lancedb.connect_namespace_async
|
||||
|
||||
::: lancedb.namespace.AsyncLanceNamespaceDBConnection
|
||||
|
||||
## Tables (Asynchronous)
|
||||
|
||||
Table hold your actual data as a collection of records / rows.
|
||||
@@ -242,20 +145,32 @@ Table hold your actual data as a collection of records / rows.
|
||||
|
||||
::: lancedb.table.AsyncTags
|
||||
|
||||
::: lancedb.table.AsyncBranches
|
||||
|
||||
## Indices (Asynchronous)
|
||||
|
||||
Indices can be created on a table to speed up queries. This section
|
||||
lists the indices that LanceDb supports.
|
||||
|
||||
::: lancedb.index
|
||||
options:
|
||||
show_root_heading: false
|
||||
show_root_toc_entry: false
|
||||
# `lang_mapping` is defined in the module rather than imported, so it is
|
||||
# picked up despite not being in `__all__`. It is an internal lookup table.
|
||||
filters: ["!^_", "!^lang_mapping$"]
|
||||
::: lancedb.index.BTree
|
||||
|
||||
::: lancedb.index.Bitmap
|
||||
|
||||
::: lancedb.index.LabelList
|
||||
|
||||
::: lancedb.index.FTS
|
||||
|
||||
::: lancedb.index.IvfPq
|
||||
|
||||
::: lancedb.index.HnswPq
|
||||
|
||||
::: lancedb.index.HnswSq
|
||||
|
||||
::: lancedb.index.IvfFlat
|
||||
|
||||
::: lancedb.index.IvfSq
|
||||
|
||||
::: lancedb.index.IvfRq
|
||||
|
||||
::: lancedb.index.HnswFlat
|
||||
|
||||
::: lancedb.table.IndexStatistics
|
||||
|
||||
@@ -283,7 +198,3 @@ rows nearest to a query vector and can be created with the
|
||||
::: lancedb.query.AsyncHybridQuery
|
||||
options:
|
||||
inherited_members: true
|
||||
|
||||
::: lancedb.query.AsyncTakeQuery
|
||||
options:
|
||||
inherited_members: true
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>com.lancedb</groupId>
|
||||
<artifactId>lancedb-parent</artifactId>
|
||||
<version>0.37.1-beta.0</version>
|
||||
<version>0.30.0-final.0</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.lancedb</groupId>
|
||||
<artifactId>lancedb-parent</artifactId>
|
||||
<version>0.37.1-beta.0</version>
|
||||
<version>0.30.0-final.0</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>LanceDB Java SDK Parent POM</description>
|
||||
@@ -28,7 +28,7 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<arrow.version>15.0.0</arrow.version>
|
||||
<lance-core.version>11.0.0-beta.3</lance-core.version>
|
||||
<lance-core.version>7.0.0</lance-core.version>
|
||||
<spotless.skip>false</spotless.skip>
|
||||
<spotless.version>2.30.0</spotless.version>
|
||||
<spotless.java.googlejavaformat.version>1.7</spotless.java.googlejavaformat.version>
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"third-party/opendal",
|
||||
"third-party/opendal-service-s3",
|
||||
"rust/examples",
|
||||
"rust/lance",
|
||||
"rust/lance-arrow",
|
||||
"rust/lance-core",
|
||||
"rust/lance-datagen",
|
||||
"rust/lance-encoding",
|
||||
"rust/lance-file",
|
||||
"rust/lance-geo",
|
||||
"rust/lance-index",
|
||||
"rust/lance-index-core",
|
||||
"rust/lance-io",
|
||||
"rust/lance-linalg",
|
||||
"rust/lance-namespace",
|
||||
"rust/lance-namespace-impls",
|
||||
"rust/lance-namespace-datafusion",
|
||||
"rust/lance-select",
|
||||
"rust/lance-tokenizer",
|
||||
"rust/lance-table",
|
||||
"rust/lance-derive",
|
||||
"rust/lance-test-macros",
|
||||
"rust/lance-testing",
|
||||
"rust/lance-tools",
|
||||
"rust/compression/fsst",
|
||||
"rust/compression/bitpacking",
|
||||
"rust/arrow-scalar",
|
||||
"rust/arrow-stats",
|
||||
]
|
||||
exclude = ["python", "java/lance-jni"]
|
||||
# Python package needs to be built by maturin.
|
||||
resolver = "3"
|
||||
|
||||
|
||||
[workspace.package]
|
||||
version = "11.0.0-beta.3"
|
||||
edition = "2024"
|
||||
authors = ["Lance Devs <dev@lance.org>"]
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/lance-format/lance"
|
||||
readme = "README.md"
|
||||
description = "A columnar data format that is 100x faster than Parquet for random access."
|
||||
keywords = [
|
||||
"data-format",
|
||||
"data-science",
|
||||
"machine-learning",
|
||||
"apache-arrow",
|
||||
"data-analytics",
|
||||
]
|
||||
categories = [
|
||||
"database-implementations",
|
||||
"data-structures",
|
||||
"development-tools",
|
||||
"science",
|
||||
]
|
||||
rust-version = "1.91.0"
|
||||
|
||||
[workspace.dependencies]
|
||||
arc-swap = "1.7"
|
||||
libc = "0.2.176"
|
||||
lance = { version = "=11.0.0-beta.3", path = "./rust/lance", default-features = false }
|
||||
lance-arrow = { version = "=11.0.0-beta.3", path = "./rust/lance-arrow" }
|
||||
lance-core = { version = "=11.0.0-beta.3", path = "./rust/lance-core" }
|
||||
lance-datafusion = { version = "=11.0.0-beta.3", path = "./rust/lance-datafusion" }
|
||||
lance-datagen = { version = "=11.0.0-beta.3", path = "./rust/lance-datagen" }
|
||||
lance-derive = { version = "=11.0.0-beta.3", path = "./rust/lance-derive" }
|
||||
lance-encoding = { version = "=11.0.0-beta.3", path = "./rust/lance-encoding" }
|
||||
lance-file = { version = "=11.0.0-beta.3", path = "./rust/lance-file" }
|
||||
lance-geo = { version = "=11.0.0-beta.3", path = "./rust/lance-geo" }
|
||||
lance-index = { version = "=11.0.0-beta.3", path = "./rust/lance-index" }
|
||||
lance-index-core = { version = "=11.0.0-beta.3", path = "./rust/lance-index-core" }
|
||||
lance-io = { version = "=11.0.0-beta.3", path = "./rust/lance-io", default-features = false }
|
||||
lance-linalg = { version = "=11.0.0-beta.3", path = "./rust/lance-linalg" }
|
||||
lance-namespace = { version = "=11.0.0-beta.3", path = "./rust/lance-namespace" }
|
||||
lance-namespace-impls = { version = "=11.0.0-beta.3", path = "./rust/lance-namespace-impls" }
|
||||
lance-namespace-datafusion = { version = "=7.0.0-beta.9", path = "./rust/lance-namespace-datafusion" }
|
||||
lance-namespace-reqwest-client = "0.8.6"
|
||||
lance-select = { version = "=11.0.0-beta.3", path = "./rust/lance-select" }
|
||||
lance-tokenizer = { version = "=11.0.0-beta.3", path = "./rust/lance-tokenizer" }
|
||||
lance-table = { version = "=11.0.0-beta.3", path = "./rust/lance-table" }
|
||||
lance-test-macros = { version = "=11.0.0-beta.3", path = "./rust/lance-test-macros" }
|
||||
lance-testing = { version = "=11.0.0-beta.3", path = "./rust/lance-testing" }
|
||||
approx = "0.5.1"
|
||||
# Note that this one does not include pyarrow
|
||||
arrow = { version = "58.0.0", optional = false, features = ["prettyprint"] }
|
||||
lance-arrow-scalar = { version = "=58.0.0", path = "./rust/arrow-scalar" }
|
||||
lance-arrow-stats = { version = "=58.0.0", path = "./rust/arrow-stats" }
|
||||
arrow-arith = "58.0.0"
|
||||
arrow-array = "58.0.0"
|
||||
arrow-buffer = "58.0.0"
|
||||
arrow-cast = "58.0.0"
|
||||
arrow-data = "58.0.0"
|
||||
arrow-ipc = { version = "58.0.0", features = ["zstd"] }
|
||||
arrow-ord = "58.0.0"
|
||||
arrow-row = "58.0.0"
|
||||
arrow-schema = "58.0.0"
|
||||
arrow-select = "58.0.0"
|
||||
async-recursion = "1.0"
|
||||
async-trait = "0.1"
|
||||
axum = "0.7"
|
||||
aws-config = "1.2.0"
|
||||
aws-credential-types = "1.2.0"
|
||||
aws-sdk-dynamodb = { version = "1.38.0", default-features = false }
|
||||
aws-sdk-s3 = { version = "1.38.0", default-features = false }
|
||||
half = { "version" = "2.1", default-features = false, features = [
|
||||
"num-traits",
|
||||
"std",
|
||||
"bytemuck",
|
||||
] }
|
||||
lance-bitpacking = { version = "=11.0.0-beta.3", path = "./rust/compression/bitpacking" }
|
||||
bitpacking = "0.9"
|
||||
bitvec = "1"
|
||||
blake3 = "1.8.5"
|
||||
bytemuck = { version = "1", default-features = false, features = [
|
||||
"extern_crate_alloc",
|
||||
] }
|
||||
bytes = "1.11.1"
|
||||
byteorder = "1.5"
|
||||
clap = { version = "4", features = ["derive"] }
|
||||
chrono = { version = "0.4.41", default-features = false, features = [
|
||||
"std",
|
||||
"now",
|
||||
"serde",
|
||||
] }
|
||||
criterion = { version = "0.8.2", features = [
|
||||
"async",
|
||||
"async_tokio",
|
||||
"html_reports",
|
||||
] }
|
||||
crossbeam-queue = "0.3"
|
||||
crossbeam-skiplist = "0.1"
|
||||
datafusion = { version = "54.0.0", default-features = false, features = [
|
||||
"crypto_expressions",
|
||||
"datetime_expressions",
|
||||
"encoding_expressions",
|
||||
"nested_expressions",
|
||||
"regex_expressions",
|
||||
"sql",
|
||||
"string_expressions",
|
||||
"unicode_expressions",
|
||||
] }
|
||||
datafusion-common = "54.0.0"
|
||||
datafusion-functions = { version = "54.0.0", default-features = false, features = ["regex_expressions"] }
|
||||
datafusion-sql = "54.0.0"
|
||||
datafusion-expr = "54.0.0"
|
||||
datafusion-ffi = "54.0.0"
|
||||
datafusion-physical-expr = "54.0.0"
|
||||
datafusion-physical-plan = "54.0.0"
|
||||
datafusion-substrait = { version = "54.0.0", default-features = false }
|
||||
dirs = "6.0.0"
|
||||
either = "1.0"
|
||||
fst = { version = "0.4.7", features = ["levenshtein"] }
|
||||
fsst = { version = "=11.0.0-beta.3", path = "./rust/compression/fsst" }
|
||||
futures = "0.3"
|
||||
geoarrow-array = "0.8"
|
||||
geoarrow-schema = "0.8"
|
||||
geodatafusion = "0.5.0"
|
||||
geo-traits = "0.3.0"
|
||||
geo-types = "0.7.16"
|
||||
http = "1.1.0"
|
||||
humantime = "2.2.0"
|
||||
hyperloglogplus = { version = "0.4.1", features = ["const-loop"] }
|
||||
icu_segmenter = { version = "2.2", default-features = false, features = ["compiled_data"] }
|
||||
io-uring = "0.7"
|
||||
itertools = "0.14"
|
||||
jieba-rs = { version = "0.10.0", default-features = false }
|
||||
jsonb = { version = "0.5.3", default-features = false, features = ["databend"] }
|
||||
libm = "0.2.15"
|
||||
log = "0.4"
|
||||
metrics = { version = "0.24" }
|
||||
metrics-util = { version = "0.19" }
|
||||
mockall = { version = "0.14.0" }
|
||||
mock_instant = { version = "0.6.0" }
|
||||
moka = { version = "0.12", features = ["future", "sync"] }
|
||||
ndarray = { version = "0.16.1", features = ["matrixmultiply-threading"] }
|
||||
num-traits = "0.2"
|
||||
object_store = { version = "0.13.2" }
|
||||
opendal = { version = "0.58.1", path = "./third-party/opendal" }
|
||||
object_store_opendal = { version = "0.58" }
|
||||
reqsign-aws-v4 = { version = "3.1.0" }
|
||||
reqsign-core = { version = "3.2.1" }
|
||||
reqsign-file-read-tokio = { version = "3.0.4" }
|
||||
pin-project = "1.0"
|
||||
path_abs = "0.5"
|
||||
pprof = { version = "0.15.0", features = ["flamegraph"] }
|
||||
proptest = "1.3.1"
|
||||
prost = "0.14.1"
|
||||
prost-build = "0.14.1"
|
||||
prost-types = "0.14.1"
|
||||
rand = { version = "0.9.1", features = ["small_rng"] }
|
||||
rand_distr = { version = "0.5.1" }
|
||||
rand_xoshiro = "0.7.0"
|
||||
rangemap = { version = "1.0" }
|
||||
rayon = "1.10"
|
||||
regex-syntax = "0.8.10"
|
||||
roaring = "0.11.4"
|
||||
rstest = "0.26.1"
|
||||
serde = { version = "^1" }
|
||||
serde_json = { version = "1" }
|
||||
semver = "1.0"
|
||||
serial_test = "3"
|
||||
snafu = "0.9"
|
||||
lindera = { version = "3.0.7" }
|
||||
tempfile = "3"
|
||||
test-log = { version = "0.2.15" }
|
||||
tokio = { version = "1.23", features = [
|
||||
"rt-multi-thread",
|
||||
"macros",
|
||||
"fs",
|
||||
"sync",
|
||||
] }
|
||||
tokio-stream = "0.1.14"
|
||||
tokio-util = { version = "0.7.16" }
|
||||
tower = "0.5"
|
||||
tower-http = "0.5"
|
||||
tracing = "0.1"
|
||||
tracing-mock = { version = "=0.1.0-beta.3" }
|
||||
twox-hash = "2.0"
|
||||
url = "2.5.7"
|
||||
uuid = { version = "1.2", features = ["v4", "serde"] }
|
||||
wiremock = "0.6"
|
||||
pretty_assertions = "1.4.0"
|
||||
|
||||
[profile.bench]
|
||||
opt-level = 3
|
||||
debug = true
|
||||
strip = false
|
||||
|
||||
[profile.ci]
|
||||
debug = "line-tables-only"
|
||||
inherits = "dev"
|
||||
incremental = false
|
||||
|
||||
# This rule applies to every package except workspace members (dependencies
|
||||
# such as `arrow` and `tokio`). It disables debug info and related features on
|
||||
# dependencies so their binaries stay smaller, improving cache reuse.
|
||||
[profile.ci.package."*"]
|
||||
debug = false
|
||||
debug-assertions = false
|
||||
strip = "debuginfo"
|
||||
incremental = false
|
||||
|
||||
[workspace.lints.rust]
|
||||
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage,coverage_nightly)'] }
|
||||
unsafe_op_in_unsafe_fn = "allow"
|
||||
|
||||
[workspace.lints.clippy]
|
||||
all = { level = "deny", priority = -1 }
|
||||
style = { level = "deny", priority = -1 }
|
||||
cargo = { level = "deny", priority = -1 }
|
||||
fallible_impl_from = "deny"
|
||||
manual_let_else = "deny"
|
||||
redundant_pub_crate = "deny"
|
||||
string_add_assign = "deny"
|
||||
string_add = "deny"
|
||||
string_lit_as_bytes = "deny"
|
||||
use_self = "deny"
|
||||
dbg_macro = "deny"
|
||||
trait_duplication_in_bounds = "deny"
|
||||
redundant_clone = "deny"
|
||||
# We should always use log instead of println
|
||||
print_stdout = "deny"
|
||||
print_stderr = "deny"
|
||||
# not too much we can do to avoid multiple crate versions
|
||||
multiple-crate-versions = "allow"
|
||||
# We use Vec<Range<u64>> in a lot of places and it is very common to use a single range in the vec.
|
||||
single_range_in_vec_init = "allow"
|
||||
large_futures = "deny"
|
||||
disallowed_macros = "deny"
|
||||
@@ -1,22 +0,0 @@
|
||||
# LanceDB patch provenance
|
||||
|
||||
This artifact vendors the Lance 11.0.0-beta.3 Rust workspace from Lance commit
|
||||
`f7d475539cefbd140cc46a828f3d843e68cd10f1`. The complete workspace keeps all mutually coupled
|
||||
Lance crates on one Cargo source identity when `lancedb` consumes the pinned artifact commit.
|
||||
|
||||
The local patch makes AWS credential-family merging atomic before backend selection and teaches
|
||||
the built-in OpenDAL S3 signer to resolve credential-only storage options at request time. This
|
||||
keeps long-lived multipart uploads refreshable without rebuilding a store or changing its outer
|
||||
metadata. Keeping the change inside `AwsStoreProvider` leaves arbitrary registry providers and
|
||||
their complete `ObjectStore` results untouched. Remove this patch when the same behavior is
|
||||
available in the pinned Lance release.
|
||||
|
||||
The LanceDB workspace pins every coupled Lance crate to the immutable repository commit containing
|
||||
this artifact. That durable source survives transitive Git consumption instead of relying on a
|
||||
root `[patch]`, which Cargo ignores when LanceDB itself is used as a dependency.
|
||||
|
||||
The artifact also contains Apache OpenDAL 0.58.1's `opendal` and `opendal-service-s3` crates. The
|
||||
only OpenDAL change adds a direct custom-provider hook alongside its existing credential-chain
|
||||
hook. Lance uses the direct hook so a selected dynamic authority can propagate refresh and
|
||||
validation errors; static or ambient credentials are considered only when that authority returns
|
||||
`Ok(None)`. Remove these copies when upstream OpenDAL exposes an equivalent hook.
|
||||
@@ -1,255 +0,0 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
This project includes code from Ritchie Vink's Polars project, which is licensed
|
||||
under the MIT license:
|
||||
|
||||
Copyright (c) 2020 Ritchie Vink
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
https://github.com/pola-rs/polars/blob/main/LICENSE
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
This project includes code adapted from the quickwit-oss/bitpacking crate, which
|
||||
is licensed under the MIT license:
|
||||
|
||||
Copyright (c) 2016 Paul Masurel
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
https://github.com/quickwit-oss/bitpacking/blob/main/LICENSE
|
||||
@@ -1,247 +0,0 @@
|
||||
<div align="center">
|
||||
<p align="center">
|
||||
|
||||
<img width="257" alt="Lance Logo" src="https://user-images.githubusercontent.com/917119/199353423-d3e202f7-0269-411d-8ff2-e747e419e492.png">
|
||||
|
||||
**The Open Lakehouse Format for Multimodal AI**<br/>
|
||||
**High-performance vector search, full-text search, random access, and feature engineering capabilities for the lakehouse.**<br/>
|
||||
**Compatible with Pandas, DuckDB, Polars, PyArrow, Ray, Spark, and more integrations on the way.**
|
||||
|
||||
<a href="https://lance.org">Documentation</a> •
|
||||
<a href="https://lance.org/community">Community</a> •
|
||||
<a href="https://discord.gg/lance">Discord</a> •
|
||||
<a href="https://groups.google.com/a/lance.org/g/dev">Mailing List</a>
|
||||
|
||||
[CI]: https://github.com/lance-format/lance/actions/workflows/rust.yml
|
||||
[CI Badge]: https://github.com/lance-format/lance/actions/workflows/rust.yml/badge.svg
|
||||
[Docs]: https://lance.org
|
||||
[Docs Badge]: https://img.shields.io/badge/docs-passing-brightgreen
|
||||
[crates.io]: https://crates.io/crates/lance
|
||||
[crates.io badge]: https://img.shields.io/crates/v/lance.svg
|
||||
[Python versions]: https://pypi.org/project/pylance/
|
||||
[Python versions badge]: https://img.shields.io/pypi/pyversions/pylance
|
||||
|
||||
[![CI Badge]][CI]
|
||||
[![Docs Badge]][Docs]
|
||||
[![crates.io badge]][crates.io]
|
||||
[![Python versions badge]][Python versions]
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
Lance is an open lakehouse format for multimodal AI. It contains a file format, table format, and catalog spec that allows you to build a complete lakehouse on top of object storage to power your AI workflows. Lance is perfect for:
|
||||
|
||||
1. Building search engines and feature stores with hybrid search capabilities.
|
||||
2. Large-scale ML training requiring high performance IO and random access.
|
||||
3. Storing, querying, and managing multimodal data including images, videos, audio, text, and embeddings.
|
||||
|
||||
The key features of Lance include:
|
||||
|
||||
* **Expressive hybrid search:** Combine vector similarity search, full-text search (BM25), and SQL analytics on the same dataset with accelerated secondary indices.
|
||||
|
||||
* **Lightning-fast random access:** 100x faster than Parquet or Iceberg for random access without sacrificing scan performance.
|
||||
|
||||
* **Native multimodal data support:** Store images, videos, audio, text, and embeddings in a single unified format with efficient blob encoding and lazy loading.
|
||||
|
||||
* **Data evolution:** Efficiently add columns with backfilled values without full table rewrites, perfect for ML feature engineering.
|
||||
|
||||
* **Zero-copy versioning:** Automatic versioning with ACID transactions, time travel, tags, and branches—no extra infrastructure needed.
|
||||
|
||||
* **Rich ecosystem integrations:** Apache Arrow, Pandas, Polars, DuckDB, Apache Spark, Ray, Trino, Apache Flink, and open catalogs (Apache Polaris, Unity Catalog, Apache Gravitino).
|
||||
|
||||
For more details, see the full [Lance format specification](https://lance.org/format).
|
||||
|
||||
> [!TIP]
|
||||
> Lance is in active development and we welcome contributions. Please see our [contributing guide](https://lance.org/community/contributing/) for more information.
|
||||
|
||||
## File format stability
|
||||
|
||||
Lance releases frequently because the SDKs, integrations, and performance work are moving quickly. This does not mean the Lance file format changes incompatibly in every release. The Lance file format is identified by the `data_storage_version` stored in each dataset, and stable storage versions are a long-term compatibility contract.
|
||||
|
||||
* Once a dataset is written with a stable `data_storage_version`, future Lance releases will continue to support reading that storage version.
|
||||
* SDK and API compatibility is separate from file format compatibility. SDK/API changes follow semantic versioning and are documented in the [migration guide](https://lance.org/guide/migration/).
|
||||
* Older Lance releases may not understand file format versions introduced later. If you run mixed Lance versions, pin `data_storage_version` for deterministic writes.
|
||||
* The `next` file format alias is unstable and should only be used for experimentation, never for production data.
|
||||
|
||||
For production, write data with a stable `data_storage_version`. See the [format versioning guide](https://lance.org/format/file/versioning/) for the current compatibility matrix.
|
||||
|
||||
## Quick Start
|
||||
|
||||
**Installation**
|
||||
|
||||
```shell
|
||||
pip install pylance
|
||||
```
|
||||
|
||||
To install a preview release:
|
||||
|
||||
```shell
|
||||
pip install --pre --extra-index-url https://pypi.fury.io/lance-format pylance
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> Preview releases are released more often than full releases and contain the
|
||||
> latest features and bug fixes. They receive the same level of testing as full releases.
|
||||
> We guarantee they will remain published and available for download for at
|
||||
> least 6 months. When you want to pin to a specific version, prefer a stable release.
|
||||
|
||||
**Converting to Lance**
|
||||
|
||||
```python
|
||||
import lance
|
||||
|
||||
import pandas as pd
|
||||
import pyarrow as pa
|
||||
import pyarrow.dataset
|
||||
|
||||
df = pd.DataFrame({"a": [5], "b": [10]})
|
||||
uri = "/tmp/test.parquet"
|
||||
tbl = pa.Table.from_pandas(df)
|
||||
pa.dataset.write_dataset(tbl, uri, format='parquet')
|
||||
|
||||
parquet = pa.dataset.dataset(uri, format='parquet')
|
||||
lance.write_dataset(parquet, "/tmp/test.lance")
|
||||
```
|
||||
|
||||
**Reading Lance data**
|
||||
```python
|
||||
dataset = lance.dataset("/tmp/test.lance")
|
||||
assert isinstance(dataset, pa.dataset.Dataset)
|
||||
```
|
||||
|
||||
**Pandas**
|
||||
```python
|
||||
df = dataset.to_table().to_pandas()
|
||||
df
|
||||
```
|
||||
|
||||
**DuckDB**
|
||||
```python
|
||||
import duckdb
|
||||
|
||||
# If this segfaults, make sure you have duckdb v0.7+ installed
|
||||
duckdb.query("SELECT * FROM dataset LIMIT 10").to_df()
|
||||
```
|
||||
|
||||
**Vector search**
|
||||
|
||||
Download the sift1m subset
|
||||
|
||||
```shell
|
||||
wget ftp://ftp.irisa.fr/local/texmex/corpus/sift.tar.gz
|
||||
tar -xzf sift.tar.gz
|
||||
```
|
||||
|
||||
Convert it to Lance
|
||||
|
||||
```python
|
||||
import lance
|
||||
from lance.vector import vec_to_table
|
||||
import numpy as np
|
||||
import struct
|
||||
|
||||
nvecs = 1000000
|
||||
ndims = 128
|
||||
with open("sift/sift_base.fvecs", mode="rb") as fobj:
|
||||
buf = fobj.read()
|
||||
data = np.array(struct.unpack("<128000000f", buf[4 : 4 + 4 * nvecs * ndims])).reshape((nvecs, ndims))
|
||||
dd = dict(zip(range(nvecs), data))
|
||||
|
||||
table = vec_to_table(dd)
|
||||
uri = "vec_data.lance"
|
||||
sift1m = lance.write_dataset(table, uri, max_rows_per_group=8192, max_rows_per_file=1024*1024)
|
||||
```
|
||||
|
||||
Build the index
|
||||
|
||||
```python
|
||||
sift1m.create_index("vector",
|
||||
index_type="IVF_PQ",
|
||||
num_partitions=256, # IVF
|
||||
num_sub_vectors=16) # PQ
|
||||
```
|
||||
|
||||
Search the dataset
|
||||
|
||||
```python
|
||||
# Get top 10 similar vectors
|
||||
import duckdb
|
||||
|
||||
dataset = lance.dataset(uri)
|
||||
|
||||
# Sample 100 query vectors. If this segfaults, make sure you have duckdb v0.7+ installed
|
||||
sample = duckdb.query("SELECT vector FROM dataset USING SAMPLE 100").to_df()
|
||||
query_vectors = np.array([np.array(x) for x in sample.vector])
|
||||
|
||||
# Get nearest neighbors for all of them
|
||||
rs = [dataset.to_table(nearest={"column": "vector", "k": 10, "q": q})
|
||||
for q in query_vectors]
|
||||
```
|
||||
|
||||
## Directory structure
|
||||
|
||||
| Directory | Description |
|
||||
|--------------------|--------------------------|
|
||||
| [rust](./rust) | Core Rust implementation |
|
||||
| [python](./python) | Python bindings (PyO3) |
|
||||
| [java](./java) | Java bindings (JNI) |
|
||||
| [docs](./docs) | Documentation source |
|
||||
|
||||
## Benchmarks
|
||||
|
||||
### Vector search
|
||||
|
||||
We used the SIFT dataset to benchmark our results with 1M vectors of 128D
|
||||
|
||||
1. For 100 randomly sampled query vectors, we get <1ms average response time (on a 2023 m2 MacBook Air)
|
||||
|
||||

|
||||
|
||||
2. ANNs are always a trade-off between recall and performance
|
||||
|
||||

|
||||
|
||||
### Vs. parquet
|
||||
|
||||
We create a Lance dataset using the Oxford Pet dataset to do some preliminary performance testing of Lance as compared to Parquet and raw image/XMLs. For analytics queries, Lance is 50-100x better than reading the raw metadata. For batched random access, Lance is 100x better than both parquet and raw files.
|
||||
|
||||

|
||||
|
||||
## Why Lance for AI/ML workflows?
|
||||
|
||||
The machine learning development cycle involves multiple stages:
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Collection] --> B[Exploration];
|
||||
B --> C[Analytics];
|
||||
C --> D[Feature Engineer];
|
||||
D --> E[Training];
|
||||
E --> F[Evaluation];
|
||||
F --> C;
|
||||
E --> G[Deployment];
|
||||
G --> H[Monitoring];
|
||||
H --> A;
|
||||
```
|
||||
|
||||
Traditional lakehouse formats were designed for SQL analytics and struggle with AI/ML workloads that require:
|
||||
- **Vector search** for similarity and semantic retrieval
|
||||
- **Fast random access** for sampling and interactive exploration
|
||||
- **Multimodal data** storage (images, videos, audio alongside embeddings)
|
||||
- **Data evolution** for feature engineering without full table rewrites
|
||||
- **Hybrid search** combining vectors, full-text, and SQL predicates
|
||||
|
||||
While existing formats (Parquet, Iceberg, Delta Lake) excel at SQL analytics, they require additional specialized systems for AI capabilities. Lance brings these AI-first features directly into the lakehouse format.
|
||||
|
||||
A comparison of different formats across ML development stages:
|
||||
|
||||
| | Lance | Parquet & ORC | JSON & XML | TFRecord | Database | Warehouse |
|
||||
|---------------------|-------|---------------|------------|----------|----------|-----------|
|
||||
| Analytics | Fast | Fast | Slow | Slow | Decent | Fast |
|
||||
| Feature Engineering | Fast | Fast | Decent | Slow | Decent | Good |
|
||||
| Training | Fast | Decent | Slow | Fast | N/A | N/A |
|
||||
| Exploration | Fast | Slow | Fast | Slow | Fast | Decent |
|
||||
| Infra Support | Rich | Rich | Decent | Limited | Rich | Rich |
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# Protobuf Guidelines
|
||||
|
||||
Also see [root AGENTS.md](../AGENTS.md) for cross-language standards.
|
||||
|
||||
## Compatibility
|
||||
|
||||
- Protobuf schemas that are part of a stable file format or any other stable persisted contract must remain backwards compatible. Never reuse or change their existing field numbers.
|
||||
- Protobuf schemas used exclusively by an unstable file format follow the root file-format stability contract: do not preserve compatibility with prior unstable revisions. Before making a breaking protobuf change, verify that the schema is not shared with a stable format or another persisted contract.
|
||||
|
||||
## Schema Design
|
||||
|
||||
- Use `optional` when you need to distinguish "not set" from "zero value" — `optional` enables presence tracking (`has_*` methods) and maps to `Option<T>` in Rust. Bare proto3 fields have no presence semantics: they always hold a value (defaulting to zero), so you cannot tell if the sender explicitly set them.
|
||||
- Use structured message types (e.g., `BasePath`) instead of plain scalars, and scope fields to operation-specific messages (e.g., `InsertTransaction`) rather than generic top-level ones.
|
||||
- Don't duplicate data across messages — store each fact once and derive relationships. Prefer parallel sequences over maps when keys already exist in another field.
|
||||
|
||||
## Documentation
|
||||
|
||||
- Document the semantic meaning of both present and absent states for `optional` fields — explain when each case applies.
|
||||
- Use precise domain terminology in field descriptions — avoid ambiguous abbreviations or terms that collide with domain concepts.
|
||||
@@ -1 +0,0 @@
|
||||
AGENTS.md
|
||||
@@ -1,72 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: Copyright The Lance Authors
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package lance.pb;
|
||||
|
||||
import "table_identifier.proto";
|
||||
import "table.proto";
|
||||
import "index.proto";
|
||||
|
||||
// Query-time approximation mode for vector search.
|
||||
//
|
||||
// This currently only affects RQ-quantized vector indexes, such as IVF_RQ.
|
||||
// Other index types ignore this setting.
|
||||
enum VectorApproxMode {
|
||||
// Use all RQ bits for query-time scoring with u8-quantized lookup tables.
|
||||
Normal = 0;
|
||||
// Use only one RQ bit for query-time scoring, even for multi-bit indexes.
|
||||
Fast = 1;
|
||||
// Use all RQ bits for query-time scoring with u16-quantized lookup tables
|
||||
// to reduce estimator quantization error.
|
||||
Accurate = 2;
|
||||
}
|
||||
|
||||
// Serialized vector query parameters.
|
||||
message VectorQueryProto {
|
||||
// Query vector as Arrow IPC bytes (supports Float16, Float32, Float64, UInt8, etc.)
|
||||
bytes query_vector_arrow_ipc = 1;
|
||||
string column = 2;
|
||||
uint32 k = 3;
|
||||
optional float lower_bound = 4;
|
||||
optional float upper_bound = 5;
|
||||
optional uint32 minimum_nprobes = 6;
|
||||
optional uint32 maximum_nprobes = 7;
|
||||
optional uint32 ef = 8;
|
||||
optional uint32 refine_factor = 9;
|
||||
// Distance metric type. Absent means None (use the index's default metric).
|
||||
optional lance.index.pb.VectorMetricType metric_type = 10;
|
||||
bool use_index = 11;
|
||||
optional float dist_q_c = 12;
|
||||
optional int32 query_parallelism = 13;
|
||||
// Query-time approximation mode. Currently only affects RQ-quantized vector
|
||||
// indexes, such as IVF_RQ. Other index types ignore this setting.
|
||||
VectorApproxMode approx_mode = 14;
|
||||
}
|
||||
|
||||
// Serializable form of ANNIvfSubIndexExec — the IVF sub-index search node.
|
||||
//
|
||||
// The prefilter child ExecutionPlan is serialized by DataFusion's codec
|
||||
// automatically via children() / with_new_children(). The prefilter_type
|
||||
// field tells the decoder which PreFilterSource variant to use when
|
||||
// reconstructing from the deserialized child inputs.
|
||||
message ANNIvfSubIndexExecProto {
|
||||
enum PreFilterType {
|
||||
NONE = 0;
|
||||
FILTERED_ROW_IDS = 1;
|
||||
SCALAR_INDEX_QUERY = 2;
|
||||
}
|
||||
|
||||
VectorQueryProto query = 1;
|
||||
lance.datafusion.TableIdentifier table = 2;
|
||||
repeated lance.table.IndexMetadata indices = 3;
|
||||
PreFilterType prefilter_type = 4;
|
||||
}
|
||||
|
||||
// Serializable form of ANNIvfPartitionExec — the IVF centroid routing node.
|
||||
message ANNIvfPartitionExecProto {
|
||||
VectorQueryProto query = 1;
|
||||
lance.datafusion.TableIdentifier table = 2;
|
||||
repeated string index_uuids = 3;
|
||||
}
|
||||
@@ -1,347 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: Copyright The Lance Authors
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package lance.encodings;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
// This file contains a specification for encodings that can be used
|
||||
// to store and load Arrow data into a Lance file for the 2.0 format. It
|
||||
// has been superseded by encodings21.proto which is used for the 2.1 format.
|
||||
//
|
||||
// # Types
|
||||
//
|
||||
// This file assumes the user wants to load data into Arrow arrays and
|
||||
// explains how to map Arrow arrays into Lance files. Encodings are divided
|
||||
// into "array encoding" (which maps to an Arrow array and may contain multiple
|
||||
// buffers) and "buffer encoding" (which encodes a single buffer of data).
|
||||
//
|
||||
// # Encoding Tree
|
||||
//
|
||||
// Most encodings are layered on top of each other. These form a tree of
|
||||
// encodings with a single root node. To encode an array you will typically
|
||||
// start with the root node and then take the output from that root encoding
|
||||
// and feed it into child encodings. The decoding process works in reverse.
|
||||
//
|
||||
// # Multi-column Encodings
|
||||
//
|
||||
// Some Arrow arrays will map to more than one column of Lance data. For
|
||||
// example, struct arrays and list arrays. This file only contains encodings
|
||||
// for a single column. However, it does describe how multi-column arrays can
|
||||
// be encoded.
|
||||
|
||||
// A pointer to a buffer in a Lance file
|
||||
//
|
||||
// A writer can place a buffer in three different locations. The buffer
|
||||
// can go in the data page, in the column metadata, or in the file metadata.
|
||||
// The writer is free to choose whatever is most appropriate (for example, a dictionary
|
||||
// that is shared across all pages in a column will probably go in the column
|
||||
// metadata). This specification does not dictate where the buffer should go.
|
||||
message Buffer {
|
||||
// The index of the buffer in the collection of buffers
|
||||
uint32 buffer_index = 1;
|
||||
// The collection holding the buffer
|
||||
enum BufferType {
|
||||
// The buffer is stored in the data page itself
|
||||
page = 0;
|
||||
// The buffer is stored in the column metadata
|
||||
column = 1;
|
||||
// The buffer is stored in the file metadata
|
||||
file = 2;
|
||||
};
|
||||
BufferType buffer_type = 2;
|
||||
}
|
||||
|
||||
// An encoding that adds nullability to another array encoding
|
||||
//
|
||||
// This can wrap any array encoding and add nullability information
|
||||
message Nullable {
|
||||
message NoNull {
|
||||
ArrayEncoding values = 1;
|
||||
}
|
||||
message AllNull {}
|
||||
message SomeNull {
|
||||
ArrayEncoding validity = 1;
|
||||
ArrayEncoding values = 2;
|
||||
}
|
||||
oneof nullability {
|
||||
// The array has no nulls and there is a single buffer needed
|
||||
NoNull no_nulls = 1;
|
||||
// The array may have nulls and we need two buffers
|
||||
SomeNull some_nulls = 2;
|
||||
// All values are null (no buffers needed)
|
||||
AllNull all_nulls = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// An array encoding for variable-length list fields
|
||||
message List {
|
||||
// An array containing the offsets into an items array.
|
||||
//
|
||||
// This array will have num_rows items and will never
|
||||
// have nulls.
|
||||
//
|
||||
// If the list at index i is not null then offsets[i] will
|
||||
// contain `base + len(list)` where `base` is defined as:
|
||||
// i == 0: 0
|
||||
// i > 0: (offsets[i-1] % null_offset_adjustment)
|
||||
//
|
||||
// To help understand we can consider the following example list:
|
||||
// [ [A, B], null, [], [C, D, E] ]
|
||||
//
|
||||
// The offsets will be [2, ?, 2, 5]
|
||||
//
|
||||
// If the incoming list at index i IS null then offsets[i] will
|
||||
// contain `base + len(list) + null_offset_adjustment` where `base`
|
||||
// is defined the same as above.
|
||||
//
|
||||
// To complete the above example let's assume that `null_offset_adjustment`
|
||||
// is 7. Then the offsets will be [2, 9, 2, 5]
|
||||
//
|
||||
// If there are no nulls then the offsets we write here are exactly the
|
||||
// same as the offsets in an Arrow list array (except we omit the leading
|
||||
// 0 which is redundant)
|
||||
//
|
||||
// The reason we do this is so that reading a single list at index i only
|
||||
// requires us to load the indices at i and i-1.
|
||||
//
|
||||
// If the offset at index i is greater than `null_offset_adjustment``
|
||||
// then the list at index i is null.
|
||||
//
|
||||
// Otherwise the length of the list is `offsets[i] - base` where
|
||||
// base is defined the same as above.
|
||||
//
|
||||
// Let's consider our example offsets: [2, 9, 2, 5]
|
||||
//
|
||||
// We can take any range of lists and determine how many list items are
|
||||
// referenced by the sublist.
|
||||
//
|
||||
// 0..3: [_, 5] -> items 0..5 (base = 0* and end is 5)
|
||||
// 0..2: [_, 2] -> items 0..2 (base = 0* and end is 2)
|
||||
// 0..1: [_, 9] -> items 0..2 (base = 0* and end is 9 % 7)
|
||||
// 1..3: [2, 5] -> items 2..5 (base = 2 and end is 5)
|
||||
// 1..2: [2, 2] -> items 2..2 (base = 2 and end is 2)
|
||||
// 2..3: [9, 5] -> items 2..5 (base = 9 % 7 and end is 5)
|
||||
//
|
||||
// * When the start of our range is the 0th item the base is always 0 and we only
|
||||
// need to load a single index from disk to determine the range.
|
||||
//
|
||||
// The data type of the offsets array is flexible and does not need
|
||||
// to match the data type of the destination array. Please note that the offsets
|
||||
// array is very likely to be efficiently encoded by bit packing deltas.
|
||||
ArrayEncoding offsets = 1;
|
||||
// If a list is null then we add this value to the offset
|
||||
//
|
||||
// This value must be greater than the length of the items so that
|
||||
// (offset + null_offset_adjustment) is never used by a non-null list.
|
||||
//
|
||||
// Note that this value cannot be equal to the length of the items
|
||||
// because then a page with a single list would store [ X ] and we
|
||||
// couldn't know if that is a null list or a list with X items.
|
||||
//
|
||||
// Therefore, the best choice for this value is 1 + # of items.
|
||||
// Choosing this will maximize the bit packing that we can apply to the offsets.
|
||||
uint64 null_offset_adjustment = 2;
|
||||
// How many items are referenced by these offsets. This is needed in
|
||||
// order to determine which items pages map to this offsets page.
|
||||
uint64 num_items = 3;
|
||||
}
|
||||
|
||||
// An array encoding for fixed-size list fields
|
||||
message FixedSizeList {
|
||||
/// The number of items in each list
|
||||
uint32 dimension = 1;
|
||||
/// True if the list is nullable
|
||||
bool has_validity = 3;
|
||||
/// The items in the list
|
||||
ArrayEncoding items = 2;
|
||||
}
|
||||
|
||||
message Compression {
|
||||
string scheme = 1;
|
||||
optional int32 level = 2;
|
||||
}
|
||||
|
||||
// Fixed width items placed contiguously in a buffer
|
||||
message Flat {
|
||||
// the number of bits per value, must be greater than 0, does
|
||||
// not need to be a multiple of 8
|
||||
uint64 bits_per_value = 1;
|
||||
// the buffer of values
|
||||
Buffer buffer = 2;
|
||||
// The Compression message can specify the compression scheme (e.g. zstd) and any
|
||||
// other information that is needed for decompression.
|
||||
//
|
||||
// If this array is compressed then the bits_per_value refers to the uncompressed
|
||||
// data.
|
||||
Compression compression = 3;
|
||||
}
|
||||
|
||||
// Compression algorithm where all values have a constant value
|
||||
message Constant {
|
||||
// The value (TODO: define encoding for literals?)
|
||||
bytes value = 1;
|
||||
}
|
||||
|
||||
// Items are bitpacked in a buffer
|
||||
message Bitpacked {
|
||||
// the number of bits used for a value in the buffer
|
||||
uint64 compressed_bits_per_value = 1;
|
||||
|
||||
// the number of bits of the uncompressed value. e.g. for a u32, this will be 32
|
||||
uint64 uncompressed_bits_per_value = 2;
|
||||
|
||||
// The items in the list
|
||||
Buffer buffer = 3;
|
||||
|
||||
// Whether or not a sign bit is included in the bitpacked value
|
||||
bool signed = 4;
|
||||
}
|
||||
|
||||
// Items are bitpacked in a buffer
|
||||
message BitpackedForNonNeg {
|
||||
// the number of bits used for a value in the buffer
|
||||
uint64 compressed_bits_per_value = 1;
|
||||
|
||||
// the number of bits of the uncompressed value. e.g. for a u32, this will be 32
|
||||
uint64 uncompressed_bits_per_value = 2;
|
||||
|
||||
// The items in the list
|
||||
Buffer buffer = 3;
|
||||
}
|
||||
|
||||
// Opaque bitpacking variant where the bits per value are stored inline in the chunks themselves
|
||||
message InlineBitpacking {
|
||||
// the number of bits of the uncompressed value. e.g. for a u32, this will be 32
|
||||
uint64 uncompressed_bits_per_value = 2;
|
||||
}
|
||||
|
||||
// Transparent bitpacking variant where the number of bits per value is fixed through the whole buffer
|
||||
message OutOfLineBitpacking {
|
||||
// the number of bits of the uncompressed value. e.g. for a u32, this will be 32
|
||||
uint64 uncompressed_bits_per_value = 2;
|
||||
// The number of compressed bits per value, fixed across the entire buffer
|
||||
uint64 compressed_bits_per_value = 3;
|
||||
}
|
||||
|
||||
// An array encoding for shredded structs that will never be null
|
||||
//
|
||||
// There is no actual data in this column.
|
||||
//
|
||||
// TODO: Struct validity bitmaps will be placed here.
|
||||
message SimpleStruct {}
|
||||
|
||||
// An array encoding for binary fields
|
||||
message Binary {
|
||||
ArrayEncoding indices = 1;
|
||||
ArrayEncoding bytes = 2;
|
||||
uint64 null_adjustment = 3;
|
||||
}
|
||||
|
||||
message Variable {
|
||||
uint32 bits_per_offset = 1;
|
||||
}
|
||||
|
||||
message Fsst {
|
||||
ArrayEncoding binary = 1;
|
||||
bytes symbol_table = 2;
|
||||
}
|
||||
|
||||
// An array encoding for dictionary-encoded fields
|
||||
message Dictionary {
|
||||
ArrayEncoding indices = 1;
|
||||
ArrayEncoding items = 2;
|
||||
uint32 num_dictionary_items = 3;
|
||||
}
|
||||
|
||||
message PackedStruct {
|
||||
repeated ArrayEncoding inner = 1;
|
||||
Buffer buffer = 2;
|
||||
}
|
||||
|
||||
message PackedStructFixedWidthMiniBlock {
|
||||
ArrayEncoding Flat = 1;
|
||||
repeated uint32 bits_per_values = 2;
|
||||
}
|
||||
|
||||
message FixedSizeBinary {
|
||||
ArrayEncoding bytes = 1;
|
||||
uint32 byte_width = 2;
|
||||
}
|
||||
|
||||
message Block {
|
||||
string scheme = 1;
|
||||
}
|
||||
|
||||
// Run-Length Encoding for miniblock format
|
||||
message Rle {
|
||||
// Number of bits per value (8, 16, 32, 64, or 128)
|
||||
uint64 bits_per_value = 1;
|
||||
}
|
||||
|
||||
// Byte Stream Split encoding for floating point values
|
||||
message ByteStreamSplit {
|
||||
// Number of bits per value (32 for float, 64 for double)
|
||||
uint64 bits_per_value = 1;
|
||||
}
|
||||
|
||||
// General miniblock encoding - wraps another miniblock encoding with compression
|
||||
message GeneralMiniBlock {
|
||||
// The inner miniblock encoding (e.g., Rle, Bitpacked, etc.)
|
||||
ArrayEncoding inner = 1;
|
||||
// The compression scheme to apply to the miniblock buffers
|
||||
Compression compression = 2;
|
||||
}
|
||||
|
||||
// Encodings that decode into an Arrow array
|
||||
message ArrayEncoding {
|
||||
oneof array_encoding {
|
||||
Flat flat = 1;
|
||||
Nullable nullable = 2;
|
||||
FixedSizeList fixed_size_list = 3;
|
||||
List list = 4;
|
||||
SimpleStruct struct = 5;
|
||||
Binary binary = 6;
|
||||
Dictionary dictionary = 7;
|
||||
Fsst fsst = 8;
|
||||
PackedStruct packed_struct = 9;
|
||||
Bitpacked bitpacked = 10;
|
||||
FixedSizeBinary fixed_size_binary = 11;
|
||||
BitpackedForNonNeg bitpacked_for_non_neg = 12;
|
||||
Constant constant = 13;
|
||||
InlineBitpacking inline_bitpacking = 14;
|
||||
OutOfLineBitpacking out_of_line_bitpacking = 15;
|
||||
Variable variable = 16;
|
||||
PackedStructFixedWidthMiniBlock packed_struct_fixed_width_mini_block = 17;
|
||||
Block block = 18;
|
||||
Rle rle = 19;
|
||||
GeneralMiniBlock general_mini_block = 20;
|
||||
ByteStreamSplit byte_stream_split = 21;
|
||||
}
|
||||
}
|
||||
|
||||
// Wraps a column with a zone map index that can be used
|
||||
// to apply pushdown filters
|
||||
message ZoneIndex {
|
||||
uint32 rows_per_zone = 1;
|
||||
Buffer zone_map_buffer = 2;
|
||||
ColumnEncoding inner = 3;
|
||||
}
|
||||
|
||||
// Marks a column as blob data. It will contain a packed struct
|
||||
// with fields position and size (u64)
|
||||
message Blob {
|
||||
ColumnEncoding inner = 1;
|
||||
}
|
||||
|
||||
// Encodings that describe a column of values
|
||||
message ColumnEncoding {
|
||||
oneof column_encoding {
|
||||
// No special encoding, just column values
|
||||
google.protobuf.Empty values = 1;
|
||||
ZoneIndex zone_index = 2;
|
||||
Blob blob = 3;
|
||||
}
|
||||
}
|
||||
@@ -1,635 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: Copyright The Lance Authors
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package lance.encodings21;
|
||||
|
||||
// This file contains a specification for encodings that can be used
|
||||
// to store and load Arrow data into a Lance file for the 2.1 format.
|
||||
//
|
||||
// # Types
|
||||
//
|
||||
// This file assumes the user wants to load data into Arrow arrays and
|
||||
// explains how to map Arrow arrays into Lance files. Encodings are divided
|
||||
// into "structural encodings" (which are used to encode the structure of the
|
||||
// data such as any list or struct layers) and "compressive encodings" (which
|
||||
// are used to compress the actual data values).
|
||||
//
|
||||
// # Standardized Interpretation of Counting Terms
|
||||
//
|
||||
// When working with 2.1 encodings we have a number of different "counting terms" and it can be
|
||||
// difficult to understand what we mean when we are talking about a "number of values". Here is
|
||||
// a standard interpretation of these terms:
|
||||
//
|
||||
// To understand these definitions consider a data type FIXED_SIZE_LIST<LIST<INT32>>.
|
||||
//
|
||||
// A "value" is an abstract term when we aren't being specific.
|
||||
//
|
||||
// - num_rows: This is the highest level counting term. A single row includes everything in the
|
||||
// fixed size list. This is what the user asks for when they asks for a range of rows.
|
||||
// - num_elements: The number of elements is the number of rows multiplied by the dimension of any
|
||||
// fixed size list wrappers. This is what you get when you flatten the FSL layer and
|
||||
// is the starting point for structural encoding. Note that an element can be a list
|
||||
// value or a single primitive value.
|
||||
// - num_items: The number of items is the number of values in the repetition and definition vectors
|
||||
// after everything has been flattened.
|
||||
// - num_visible_items: The number of visible items is the number of items after invisible items
|
||||
// have been removed. Invisible items are rep/def levels that don't correspond to an
|
||||
// actual value.
|
||||
|
||||
|
||||
// # Structural Encodings
|
||||
//
|
||||
// The following message are used to describe the structural encoding of the
|
||||
// data. In this document, we refer to these structural encodings as layouts.
|
||||
|
||||
// Repetition and definition levels are described in more detail elsewhere. As we peel through
|
||||
// the structure of an array we will encounter layers of struct and list. Each of these layers
|
||||
// potentially adds a new level to the repetition and definition levels. This message describes
|
||||
// the meaning of each layer.
|
||||
enum RepDefLayer {
|
||||
// Should never be used, included for debugging purporses and general protobuf best practice
|
||||
REPDEF_UNSPECIFIED = 0;
|
||||
// All values are valid (can be primitive or struct)
|
||||
REPDEF_ALL_VALID_ITEM = 1;
|
||||
// All list values are valid
|
||||
REPDEF_ALL_VALID_LIST = 2;
|
||||
// There are one or more null items (can be primitive or struct)
|
||||
REPDEF_NULLABLE_ITEM = 3;
|
||||
// A list layer with null lists but no empty lists
|
||||
REPDEF_NULLABLE_LIST = 4;
|
||||
// A list layer with empty lists but no null lists
|
||||
REPDEF_EMPTYABLE_LIST = 5;
|
||||
// A list layer with both empty lists and null lists
|
||||
REPDEF_NULL_AND_EMPTY_LIST = 6;
|
||||
}
|
||||
|
||||
// A layout used for pages where the data is small
|
||||
//
|
||||
// In this case we can fit many values into a single disk sector and transposing buffers is
|
||||
// expensive. As a result, we do not transpose the buffers but compress the data into small
|
||||
// chunks (called mini blocks) which are roughly the size of a disk sector.
|
||||
//
|
||||
// The end result is a small amount of read amplification (since we must read an entire page
|
||||
// at a time) but we have more flexibility in compression and do less work per value when
|
||||
// compressing and decompressing in bulk.
|
||||
message MiniBlockLayout {
|
||||
// Description of the compression of repetition levels (e.g. how many bits per rep)
|
||||
//
|
||||
// Optional, if there is no repetition then this field is not present
|
||||
CompressiveEncoding rep_compression = 1;
|
||||
// Description of the compression of definition levels (e.g. how many bits per def)
|
||||
//
|
||||
// Optional, if there is no definition then this field is not present
|
||||
CompressiveEncoding def_compression = 2;
|
||||
// Description of the compression of values
|
||||
CompressiveEncoding value_compression = 3;
|
||||
// Description of the compression of the dictionary data
|
||||
//
|
||||
// Optional, if there is no dictionary then this field is not present
|
||||
CompressiveEncoding dictionary = 4;
|
||||
// Number of items in the dictionary
|
||||
uint64 num_dictionary_items = 5;
|
||||
// The meaning of each repdef layer, used to interpret repdef buffers correctly
|
||||
repeated RepDefLayer layers = 6;
|
||||
// The number of buffers in each mini-block, this is determined by the compression and does
|
||||
// NOT include the repetition or definition buffers (the presence of these buffers can be determined
|
||||
// by looking at the rep_compression and def_compression fields)
|
||||
uint64 num_buffers = 7;
|
||||
// The depth of the repetition index.
|
||||
//
|
||||
// If there is repetition then the depth must be at least 1. If there are many layers
|
||||
// of repetition then deeper repetition indices will support deeper nested random access. For
|
||||
// example, given 5 layers of repetition then the repetition index depth must be at least
|
||||
// 3 to support access like `rows[50][17][3]`.
|
||||
//
|
||||
// We require `repetition_index_depth + 1` u64 values per mini-block to store the repetition
|
||||
// index if the `repetition_index_depth` is greater than 0. The +1 is because we need to store
|
||||
// the number of "leftover items" at the end of the chunk. Otherwise, we wouldn't have any way
|
||||
// to know if the final item in a chunk is valid or not.
|
||||
uint32 repetition_index_depth = 8;
|
||||
// The page already records how many rows are in the page. For mini-block we also need to know how
|
||||
// many "items" are in the page. A row and an item are the same thing unless the page has lists.
|
||||
uint64 num_items = 9;
|
||||
|
||||
// Since Lance 2.2, miniblocks have larger chunk sizes (>= 64KB)
|
||||
bool has_large_chunk = 10;
|
||||
}
|
||||
|
||||
// A layout used for pages where the data is large
|
||||
//
|
||||
// In this case the cost of transposing the data is relatively small (compared to the cost of writing the data)
|
||||
// and so we just zip the buffers together
|
||||
message FullZipLayout {
|
||||
// The number of bits of repetition info (0 if there is no repetition)
|
||||
uint32 bits_rep = 1;
|
||||
// The number of bits of definition info (0 if there is no definition)
|
||||
uint32 bits_def = 2;
|
||||
// The number of bits of value info
|
||||
//
|
||||
// Note: we use bits here (and not bytes) for consistency with other encodings. However, in practice,
|
||||
// there is never a reason to use a bits per value that is not a multiple of 8. The complexity is not
|
||||
// worth the small savings in space since this encoding is typically used with large values already.
|
||||
oneof details {
|
||||
// If this is a fixed width block then we need to have a fixed number of bits per value
|
||||
uint32 bits_per_value = 3;
|
||||
// If this is a variable width block then we need to have a fixed number of bits per offset
|
||||
uint32 bits_per_offset = 4;
|
||||
}
|
||||
// The number of items in the page
|
||||
uint32 num_items = 5;
|
||||
// The number of visible items in the page
|
||||
uint32 num_visible_items = 6;
|
||||
// Description of the compression of values
|
||||
CompressiveEncoding value_compression = 7;
|
||||
// The meaning of each repdef layer, used to interpret repdef buffers correctly
|
||||
repeated RepDefLayer layers = 8;
|
||||
}
|
||||
|
||||
// A layout used for sparse flat or nested pages where Arrow structure is represented directly
|
||||
// in layer-local slot domains instead of as dense repetition / definition events.
|
||||
//
|
||||
// Structural layers are ordered from outer-most to inner-most. Values remain mini-block
|
||||
// compressed and are split into independently readable chunks.
|
||||
message SparseLayout {
|
||||
// Description of the compression of values.
|
||||
CompressiveEncoding value_compression = 1;
|
||||
// Number of value buffers in each mini-block chunk. This does not include structural buffers.
|
||||
uint64 num_buffers = 2;
|
||||
// Number of entries in the equivalent dense repetition / definition stream. This equals
|
||||
// num_visible_items plus one structural placeholder for every list slot without children.
|
||||
// Null leaf slots count as visible items because they still occupy positions in Arrow's
|
||||
// leaf value buffer. For example, a nullable primitive with 100 slots, 30 of them null,
|
||||
// has num_items = num_visible_items = 100.
|
||||
uint64 num_items = 3;
|
||||
// Number of leaf value slots encoded in the value chunks, including null leaf slots.
|
||||
uint64 num_visible_items = 4;
|
||||
// If true, chunk-local value buffer sizes use u32. Otherwise they use u16.
|
||||
bool has_large_chunk = 5;
|
||||
// Structural layers ordered from outer-most to inner-most. This may be empty for a flat,
|
||||
// non-nullable leaf page whose scheduling domain equals num_visible_items.
|
||||
repeated SparseStructuralLayer structural_layers = 6;
|
||||
}
|
||||
|
||||
// A domain is a layer-local integer coordinate space [0, num_slots). A slot is one
|
||||
// element in that space. The outer-most domain is the page's top-level rows; each
|
||||
// layer's child domain is the next layer's parent domain, and the terminal child
|
||||
// domain contains num_visible_items leaf value slots.
|
||||
message SparseStructuralLayer {
|
||||
// Exactly one layer kind is required.
|
||||
oneof layer {
|
||||
SparseValidityLayer validity = 1;
|
||||
SparseListLayer list = 2;
|
||||
SparseFixedSizeListLayer fixed_size_list = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message SparseValidityLayer {
|
||||
// Number of nullable item or struct slots in this layer's parent and child domain.
|
||||
uint64 num_slots = 1;
|
||||
// Validity for the slots in this layer.
|
||||
SparseValiditySet validity = 2;
|
||||
}
|
||||
|
||||
message SparseListLayer {
|
||||
// Number of list, large-list, or map slots in this layer's parent domain.
|
||||
uint64 num_slots = 1;
|
||||
// Number of slots in this layer's child domain.
|
||||
uint64 num_child_slots = 2;
|
||||
// Non-empty parent slots. Valid parent slots absent from this set are empty lists.
|
||||
SparsePositionSet non_empty_positions = 3;
|
||||
// Positive child counts corresponding one-for-one with non_empty_positions.
|
||||
SparseCountSet counts = 4;
|
||||
// Validity for the parent slots in this layer.
|
||||
SparseValiditySet validity = 5;
|
||||
}
|
||||
|
||||
message SparseFixedSizeListLayer {
|
||||
// Number of fixed-size-list slots in this layer's parent domain.
|
||||
uint64 num_slots = 1;
|
||||
// Number of children per parent slot. The child domain has num_slots * dimension slots.
|
||||
uint64 dimension = 2;
|
||||
// Validity for the parent slots in this layer.
|
||||
SparseValiditySet validity = 3;
|
||||
}
|
||||
|
||||
message SparseValiditySet {
|
||||
enum Meaning {
|
||||
SPARSE_VALIDITY_UNSPECIFIED = 0;
|
||||
// Stored positions are null; all other positions are valid.
|
||||
SPARSE_VALIDITY_NULL_POSITIONS = 1;
|
||||
// Stored positions are valid; all other positions are null.
|
||||
SPARSE_VALIDITY_VALID_POSITIONS = 2;
|
||||
}
|
||||
|
||||
Meaning meaning = 1;
|
||||
SparsePositionSet positions = 2;
|
||||
}
|
||||
|
||||
message SparsePositionEmpty {}
|
||||
|
||||
message SparsePositionAll {}
|
||||
|
||||
message SparsePositionRange {
|
||||
uint64 start = 1;
|
||||
uint64 length = 2;
|
||||
}
|
||||
|
||||
message SparsePositionSet {
|
||||
oneof positions {
|
||||
// Delta-compressed u64 positions. Cardinality is num_positions.
|
||||
CompressiveEncoding explicit = 1;
|
||||
// One contiguous, non-empty range.
|
||||
SparsePositionRange range = 2;
|
||||
// Every position in the domain.
|
||||
SparsePositionAll all = 3;
|
||||
// No positions in the domain.
|
||||
SparsePositionEmpty empty = 4;
|
||||
}
|
||||
// Semantic cardinality of this set.
|
||||
uint64 num_positions = 5;
|
||||
}
|
||||
|
||||
message SparseCountEmpty {}
|
||||
|
||||
message SparseCountConstant {
|
||||
// Child count shared by every non-empty list slot.
|
||||
uint64 value = 1;
|
||||
}
|
||||
|
||||
message SparseCountSet {
|
||||
oneof counts {
|
||||
// Compressed u64 child counts. Cardinality comes from the containing position set.
|
||||
CompressiveEncoding explicit = 1;
|
||||
// One positive child count shared by every non-empty list slot.
|
||||
SparseCountConstant constant = 2;
|
||||
// No counts; valid only when there are no non-empty list slots.
|
||||
SparseCountEmpty empty = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// A layout used for pages where all (visible) values are the same scalar value.
|
||||
//
|
||||
// This generalizes the prior AllNullLayout semantics for file_version >= 2.2.
|
||||
//
|
||||
// There may be buffers of repetition and definition information if required in order
|
||||
// to interpret what kind of nulls are present / which items are visible.
|
||||
message ConstantLayout {
|
||||
// The meaning of each repdef layer, used to interpret repdef buffers correctly
|
||||
repeated RepDefLayer layers = 5;
|
||||
|
||||
// Inline fixed-width scalar value bytes.
|
||||
//
|
||||
// This MUST only be used for types where a single non-null element is represented by a single
|
||||
// fixed-width Arrow value buffer (i.e. no offsets buffer, no child data).
|
||||
//
|
||||
// Constraints:
|
||||
// - MUST be absent for an all-null page
|
||||
// - MUST be <= 32 bytes if present
|
||||
optional bytes inline_value = 6;
|
||||
|
||||
// Optional compression algorithm used for the repetition buffer.
|
||||
// If absent, repetition levels are stored as raw u16 values.
|
||||
CompressiveEncoding rep_compression = 7;
|
||||
// Optional compression algorithm used for the definition buffer.
|
||||
// If absent, definition levels are stored as raw u16 values.
|
||||
CompressiveEncoding def_compression = 8;
|
||||
// Number of values in repetition buffer after decompression.
|
||||
uint64 num_rep_values = 9;
|
||||
// Number of values in definition buffer after decompression.
|
||||
uint64 num_def_values = 10;
|
||||
}
|
||||
|
||||
// A layout where large binary data is encoded externally and only
|
||||
// the descriptions (position + size) are placed in the page
|
||||
//
|
||||
// Repdef information is stored in the descriptions. A description with a size of
|
||||
// 0 and a position of 0 is an empty value. A description with a size of 0 and a
|
||||
// non-zero position is a null value and the position is the repdef value.
|
||||
message BlobLayout {
|
||||
// The inner layout used to store the descriptions
|
||||
PageLayout inner_layout = 1;
|
||||
// The meaning of each repdef layer, used to interpret repdef buffers correctly
|
||||
//
|
||||
// The inner layout's repdef layers will always be 1 all valid item layer
|
||||
repeated RepDefLayer layers = 2;
|
||||
}
|
||||
|
||||
// Describes the structural encoding of a page
|
||||
message PageLayout {
|
||||
oneof layout {
|
||||
// A layout used for pages where the data is small
|
||||
MiniBlockLayout mini_block_layout = 1;
|
||||
// A layout used for pages where all (visible) values are the same scalar value or null.
|
||||
ConstantLayout constant_layout = 2;
|
||||
// A layout used for pages where the data is large
|
||||
FullZipLayout full_zip_layout = 3;
|
||||
// A layout where large binary data is encoded externally
|
||||
// and only the descriptions are put in the page
|
||||
BlobLayout blob_layout = 4;
|
||||
// A sparse structural layout. This variant requires file version 2.3 or later.
|
||||
SparseLayout sparse_layout = 5;
|
||||
}
|
||||
}
|
||||
|
||||
// # Compressive Encodings
|
||||
//
|
||||
// These encodings describe how an array is compressed. An encoding may split an
|
||||
// array into multiple buffers. The buffers can then be compressed further (and split
|
||||
// into yet more buffers). The entire process forms a tree of encodings with the root
|
||||
// of the tree being the initial array and the leaves being the final compressed buffers.
|
||||
//
|
||||
// # Data blocks and buffers
|
||||
//
|
||||
// Data blocks are a simplified version of arrays and represent a collection of buffers grouped
|
||||
// with some kind of interpretation. Data blocks are the input and output of compressive encodings.
|
||||
// There are different kinds of data blocks:
|
||||
// - Fixed width data blocks (e.g. u8, u16, ...)
|
||||
// - Variable width data blocks (e.g. strings, binary)
|
||||
// - Struct data blocks (note: this is for packed structs, normal structs are encoded in the structural encoding)
|
||||
//
|
||||
// In addition, leaf encodings may output "buffers". These are fully compressed buffers of data that
|
||||
// are stored in the page and no longer compressed.
|
||||
|
||||
enum CompressionScheme {
|
||||
COMPRESSION_ALGORITHM_UNSPECIFIED = 0;
|
||||
COMPRESSION_ALGORITHM_LZ4 = 1;
|
||||
COMPRESSION_ALGORITHM_ZSTD = 2;
|
||||
}
|
||||
|
||||
// Compression applied to a single buffer of data
|
||||
//
|
||||
// A buffer is the leaf of the compression tree. Unlike data blocks, which can
|
||||
// be further compressed with a variety of techniques, a buffer cannot be understood
|
||||
// in any particular way.
|
||||
//
|
||||
// A general compression scheme may be applied to a buffer. This is something like
|
||||
// zstd, lz4, etc. The entire buffer is compressed as a single unit. If this happens
|
||||
// then any parent encoding becomes opaque, even if it would normally be transparent.
|
||||
//
|
||||
// This is a leaf, no further compression is applied to the data.
|
||||
message BufferCompression {
|
||||
// A general compression scheme to apply to the buffer
|
||||
CompressionScheme scheme = 1;
|
||||
// The compression level
|
||||
//
|
||||
// Optional, if not present a scheme-specific default value will be used.
|
||||
//
|
||||
// Interpretation of this value depends on the compression scheme. Generally, larger
|
||||
// values indicate more compression at the expense of more CPU time.
|
||||
optional int32 level = 2;
|
||||
}
|
||||
|
||||
// Fixed width items placed contiguously in a single buffer
|
||||
//
|
||||
// This is a leaf encoding, there is no compression applied to the data.
|
||||
//
|
||||
// This is a transparent encoding by definition.
|
||||
//
|
||||
// The input is a fixed-width data block.
|
||||
// The output is a single buffer.
|
||||
message Flat {
|
||||
// the number of bits per value, must be greater than 0, does
|
||||
// not need to be a multiple of 8
|
||||
uint64 bits_per_value = 1;
|
||||
// The compression applied to the data
|
||||
optional BufferCompression data = 2;
|
||||
}
|
||||
|
||||
// Variable width items have the values stored in one buffer and the
|
||||
// offsets are output as a data block that may be further compressed.
|
||||
//
|
||||
// This is a partial leaf encoding. Values are not compressed but
|
||||
// the offsets may be further compressed.
|
||||
//
|
||||
// This is a transparent encoding by definition.
|
||||
//
|
||||
// The input is a variable-width data block.
|
||||
// The output is a single fixed-width data block (the offsets) and
|
||||
// a single buffer (the values)
|
||||
message Variable {
|
||||
// Describes how the offsets data block is compressed
|
||||
CompressiveEncoding offsets = 1;
|
||||
// The compression applied to the values
|
||||
optional BufferCompression values = 2;
|
||||
}
|
||||
|
||||
// Compression algorithm where all values have a constant value (encoded in the description)
|
||||
//
|
||||
// This is a leaf encoding, there is no compression applied to the data.
|
||||
//
|
||||
// The input can be any kind of data block.
|
||||
// There is no output.
|
||||
message Constant {
|
||||
// The value (TODO: define encoding for literals?)
|
||||
optional bytes value = 1;
|
||||
}
|
||||
|
||||
// A compression scheme in which a single fixed-width block is "packed" into
|
||||
// a smaller fixed-width block values where each value has fewer bits.
|
||||
//
|
||||
// This is typically done by throwing away the most significant bits of each value when
|
||||
// those bits are all the same.
|
||||
//
|
||||
// In this scheme the number of bits per value is fixed across the entire buffer and stored
|
||||
// in this message.
|
||||
//
|
||||
// This is a transparent encoding.
|
||||
//
|
||||
// The input is a fixed-width data block.
|
||||
// The output is a single fixed-width data block.
|
||||
message OutOfLineBitpacking {
|
||||
// the number of bits of the uncompressed value. e.g. for a u32, this will be 32
|
||||
uint64 uncompressed_bits_per_value = 1;
|
||||
// The compression used to store the bitpacked values data block
|
||||
CompressiveEncoding values = 3;
|
||||
}
|
||||
|
||||
// Bitpacking variant where the bits per value are stored inline in the chunks themselves
|
||||
//
|
||||
// This variation of bitpacking allows for the number of bits per value to change throughout the
|
||||
// buffer, which makes the compression more robust to outliers.
|
||||
//
|
||||
// This is an opaque encoding.
|
||||
//
|
||||
// The input is a fixed-width data block.
|
||||
// The output is a single buffer.
|
||||
message InlineBitpacking {
|
||||
// the number of bits of the uncompressed value. e.g. for a u32, this will be 32
|
||||
uint64 uncompressed_bits_per_value = 1;
|
||||
// The compression applied to the values
|
||||
optional BufferCompression values = 2;
|
||||
}
|
||||
|
||||
// A compression scheme for variable-width data
|
||||
//
|
||||
// A small dictionary (referred to as a "symbol table") is used to compress the values.
|
||||
// In this scheme there is a single symbol table for the entire page and it is stored in the
|
||||
// encoding description itself.
|
||||
//
|
||||
// This is a transparent encoding.
|
||||
//
|
||||
// The input is a variable-width data block.
|
||||
// The output is a single variable-width data block.
|
||||
message Fsst {
|
||||
// The FSST symbol table
|
||||
bytes symbol_table = 1;
|
||||
// The compression used to store the compressed values data block
|
||||
CompressiveEncoding values = 2;
|
||||
}
|
||||
|
||||
// A compression scheme where common values are stored in a dictionary and the values are
|
||||
// encoded as indices into the dictionary.
|
||||
//
|
||||
// This is an opaque encoding unless the dictionary is considered metadata.
|
||||
//
|
||||
// The input is a any kind of data block.
|
||||
// There are two outputs:
|
||||
// - A data block of the same kind as the input (the dictionary)
|
||||
// - A fixed-width data block containing the indices into the dictionary.
|
||||
message Dictionary {
|
||||
// The compression used to store the indices data block
|
||||
CompressiveEncoding indices = 1;
|
||||
// The compression used to store the dictionary items data block
|
||||
CompressiveEncoding items = 2;
|
||||
// The number of items in the dictionary
|
||||
uint32 num_dictionary_items = 3;
|
||||
}
|
||||
|
||||
// A compression scheme where runs of common values are encoded as a single value and a count
|
||||
//
|
||||
// This is an opaque encoding unless the run lengths are considered metadata.
|
||||
//
|
||||
// The input is a single data block of any kind.
|
||||
// There are two outputs:
|
||||
// - A data block of the same kind as the input (the run values)
|
||||
// - A fixed-width data block containing the lengths of the runs
|
||||
message Rle {
|
||||
// The compression used to store the run values data block
|
||||
CompressiveEncoding values = 1;
|
||||
// The compression used to store the run lengths data block
|
||||
CompressiveEncoding run_lengths = 2;
|
||||
}
|
||||
|
||||
// Converts a fixed-size-list of values into a flattened list of values
|
||||
//
|
||||
// This encoding does not actually compress the data, it just flattens out the FSL layers.
|
||||
//
|
||||
// This is a transparent encoding.
|
||||
//
|
||||
// The input is a single block of fixed-width data (with a wide width and few items)
|
||||
// The output is a single block of fixed-width data (with a narrow width and many items)
|
||||
message FixedSizeList {
|
||||
// The number of items in this layer of FSL
|
||||
uint64 items_per_value = 1;
|
||||
// Whether or not there is a validity buffer
|
||||
bool has_validity = 3;
|
||||
// The compression used to store the flattened values data block
|
||||
CompressiveEncoding values = 2;
|
||||
}
|
||||
|
||||
// Packs a struct containing only fixed-width children into a single fixed-width data block
|
||||
//
|
||||
// The children are concatenated row by row and stored as a single fixed-width buffer. This is
|
||||
// the legacy packed struct representation and remains available for backwards compatibility.
|
||||
message PackedStruct {
|
||||
// The number of bits contributed by each child field in the packed row
|
||||
repeated uint64 bits_per_value = 1;
|
||||
// The compression used to store the packed fixed-width values
|
||||
CompressiveEncoding values = 2;
|
||||
}
|
||||
|
||||
// Variable-width packed struct encoding (2.2 extension)
|
||||
//
|
||||
// Each child value is compressed independently before being transposed into
|
||||
// a row-major layout. This preserves per-field compression boundaries at the
|
||||
// cost of disabling mini-block compression. Readers must prefer this field
|
||||
// when present and fall back to the legacy encoding otherwise.
|
||||
message VariablePackedStruct {
|
||||
// Per-field encoding metadata in struct order
|
||||
repeated FieldEncoding fields = 1;
|
||||
|
||||
// Encoding description for a single child field
|
||||
message FieldEncoding {
|
||||
// Compression applied to individual field values before transposition
|
||||
CompressiveEncoding value = 1;
|
||||
oneof layout {
|
||||
// Bit width of each compressed value (when fixed width)
|
||||
uint64 bits_per_value = 2;
|
||||
// Bit width of the length prefix for variable-width compressed values
|
||||
uint64 bits_per_length = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A compression scheme that wraps the underlying data with general compression
|
||||
//
|
||||
// Note: The application of wrapped compression will depend on the layout of the data.
|
||||
// If we apply it to mini-block data then we compress entire mini-blocks. If we apply
|
||||
// it to full-zip data then we compress each value individually.
|
||||
//
|
||||
// Note: Wrapped compression is somewhat unique at the moment as it is applied to the
|
||||
// output of the inner encoding and not the input like all other compressive encodings.
|
||||
//
|
||||
// Note: General compression can usually be applied in two spots. We can apply
|
||||
// it to individual buffers or we can apply it here, to the entire array.
|
||||
//
|
||||
// For example, let's say we are storing mini-blocks of strings and we are using
|
||||
// FSST and bitpacking the offsets. We have something like this...
|
||||
//
|
||||
// WRAPPED(†3) -> FSST -> VARIABLE -(offsets)-> INLINE_BITPACKING -(data)-> FLAT -> BUFFER (†1)
|
||||
// -(data)-> BUFFER (†2)
|
||||
//
|
||||
// General compression can be applied at †1, †2, or †3 (or any combination of these).
|
||||
//
|
||||
// If we apply it at †1 then we apply it just to the bitpacked offsets
|
||||
// If we apply it at †2 then we apply it just to the FSST compressed data
|
||||
// If we apply it at †3 then we apply it to the entire mini-block (both offsets and data)
|
||||
//
|
||||
// The input is a single data block of any kind.
|
||||
// The output is a single data block of the same kind as the input.
|
||||
message General {
|
||||
// The compression to apply to the values
|
||||
BufferCompression compression = 1;
|
||||
// The compression used to store the output data block
|
||||
CompressiveEncoding values = 3;
|
||||
}
|
||||
|
||||
// A compression scheme where fixed-width values are transposed into a series of byte streams
|
||||
//
|
||||
// This is commonly used for floating point values where the upper bits (the mantissa) have a
|
||||
// significantly different meaning than the lower bits. By splitting the values into byte streams
|
||||
// we group the mantissa bits together and the exponent bits together. The end result is typically
|
||||
// more compressible.
|
||||
//
|
||||
// Note that this encoding is mostly useful when combined with other encodings. It does not do any
|
||||
// compression on its own.
|
||||
//
|
||||
// This is an opaque encoding.
|
||||
//
|
||||
// The input is a fixed-width data block
|
||||
// The output is a single fixed-width data block
|
||||
message ByteStreamSplit {
|
||||
// The compression used to store the values
|
||||
CompressiveEncoding values = 1;
|
||||
}
|
||||
|
||||
// An encoding that compresses a data block into buffers
|
||||
message CompressiveEncoding {
|
||||
oneof compression {
|
||||
Flat flat = 1;
|
||||
Variable variable = 2;
|
||||
Constant constant = 3;
|
||||
OutOfLineBitpacking out_of_line_bitpacking = 4;
|
||||
InlineBitpacking inline_bitpacking = 5;
|
||||
Fsst fsst = 6;
|
||||
Dictionary dictionary = 7;
|
||||
Rle rle = 8;
|
||||
ByteStreamSplit byte_stream_split = 9;
|
||||
General general = 10;
|
||||
FixedSizeList fixed_size_list = 11;
|
||||
PackedStruct packed_struct = 12;
|
||||
VariablePackedStruct variable_packed_struct = 13;
|
||||
}
|
||||
}
|
||||
@@ -1,207 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: Copyright The Lance Authors
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package lance.file;
|
||||
|
||||
// A file descriptor that describes the contents of a Lance file
|
||||
message FileDescriptor {
|
||||
// The schema of the file
|
||||
Schema schema = 1;
|
||||
// The number of rows in the file
|
||||
uint64 length = 2;
|
||||
}
|
||||
|
||||
// A schema which describes the data type of each of the columns
|
||||
message Schema {
|
||||
// All fields in this file, including the nested fields.
|
||||
repeated lance.file.Field fields = 1;
|
||||
// Schema metadata.
|
||||
map<string, bytes> metadata = 5;
|
||||
}
|
||||
|
||||
// Metadata of one Lance file.
|
||||
message Metadata {
|
||||
// 4 was used for StatisticsMetadata in the past, but has been moved to
|
||||
// prevent a bug in older readers.
|
||||
reserved 4;
|
||||
|
||||
// Position of the manifest in the file. If it is zero, the manifest is stored
|
||||
// externally.
|
||||
uint64 manifest_position = 1;
|
||||
|
||||
// Logical offsets of each chunk group, i.e., number of the rows in each
|
||||
// chunk.
|
||||
repeated int32 batch_offsets = 2;
|
||||
|
||||
// The file position that page table is stored.
|
||||
//
|
||||
// A page table is a matrix of N x M x 2, where N = num_fields, and M =
|
||||
// num_batches. Each cell in the table is a pair of <position:int64,
|
||||
// length:int64> of the page. Both position and length are int64 values. The
|
||||
// <position, length> of all the pages in the same column are then
|
||||
// contiguously stored.
|
||||
//
|
||||
// Every field that is a part of the file will have a run in the page table.
|
||||
// This includes struct columns, which will have a run of length 0 since
|
||||
// they don't store any actual data.
|
||||
//
|
||||
// For example, for the column 5 and batch 4, we have:
|
||||
// ```text
|
||||
// position = page_table[5][4][0];
|
||||
// length = page_table[5][4][1];
|
||||
// ```
|
||||
uint64 page_table_position = 3;
|
||||
|
||||
message StatisticsMetadata {
|
||||
// The schema of the statistics.
|
||||
//
|
||||
// This might be empty, meaning there are no statistics. It also might not
|
||||
// contain statistics for every field.
|
||||
repeated Field schema = 1;
|
||||
|
||||
// The field ids of the statistics leaf fields.
|
||||
//
|
||||
// This plays a similar role to the `fields` field in the DataFile message.
|
||||
// Each of these field ids corresponds to a field in the stats_schema. There
|
||||
// is one per column in the stats page table.
|
||||
repeated int32 fields = 2;
|
||||
|
||||
// The file position of the statistics page table
|
||||
//
|
||||
// The page table is a matrix of N x 2, where N = length of stats_fields.
|
||||
// This is the same layout as the main page table, except there is always
|
||||
// only one batch.
|
||||
//
|
||||
// For example, to get the stats column 5, we have:
|
||||
// ```text
|
||||
// position = stats_page_table[5][0];
|
||||
// length = stats_page_table[5][1];
|
||||
// ```
|
||||
uint64 page_table_position = 3;
|
||||
}
|
||||
|
||||
StatisticsMetadata statistics = 5;
|
||||
} // Metadata
|
||||
|
||||
// Supported encodings.
|
||||
enum Encoding {
|
||||
// Invalid encoding.
|
||||
NONE = 0;
|
||||
// Plain encoding.
|
||||
PLAIN = 1;
|
||||
// Var-length binary encoding.
|
||||
VAR_BINARY = 2;
|
||||
// Dictionary encoding.
|
||||
DICTIONARY = 3;
|
||||
// Run-length encoding.
|
||||
RLE = 4;
|
||||
}
|
||||
|
||||
// Dictionary field metadata
|
||||
message Dictionary {
|
||||
/// The file offset for storing the dictionary value.
|
||||
/// It is only valid if encoding is DICTIONARY.
|
||||
///
|
||||
/// The logic type presents the value type of the column, i.e., string value.
|
||||
int64 offset = 1;
|
||||
|
||||
/// The length of dictionary values.
|
||||
int64 length = 2;
|
||||
}
|
||||
|
||||
// Field metadata for a column.
|
||||
message Field {
|
||||
enum Type {
|
||||
PARENT = 0;
|
||||
REPEATED = 1;
|
||||
LEAF = 2;
|
||||
}
|
||||
Type type = 1;
|
||||
|
||||
// Fully qualified name.
|
||||
string name = 2;
|
||||
/// Field Id.
|
||||
///
|
||||
/// See the comment in `DataFile.fields` for how field ids are assigned.
|
||||
int32 id = 3;
|
||||
/// Parent Field ID. If not set, this is a top-level column.
|
||||
int32 parent_id = 4;
|
||||
|
||||
// Logical types, support parameterized Arrow Type.
|
||||
//
|
||||
// PARENT types will always have logical type "struct".
|
||||
//
|
||||
// REPEATED types may have logical types:
|
||||
// * "list"
|
||||
// * "large_list"
|
||||
// * "list.struct"
|
||||
// * "large_list.struct"
|
||||
// The final two are used if the list values are structs, and therefore the
|
||||
// field is both implicitly REPEATED and PARENT.
|
||||
//
|
||||
// LEAF types may have logical types:
|
||||
// * "null"
|
||||
// * "bool"
|
||||
// * "int8" / "uint8"
|
||||
// * "int16" / "uint16"
|
||||
// * "int32" / "uint32"
|
||||
// * "int64" / "uint64"
|
||||
// * "halffloat" / "float" / "double"
|
||||
// * "string" / "large_string"
|
||||
// * "binary" / "large_binary"
|
||||
// * "date32:day"
|
||||
// * "date64:ms"
|
||||
// * "decimal:128:{precision}:{scale}" / "decimal:256:{precision}:{scale}"
|
||||
// * "time:{unit}" / "timestamp:{unit}" / "duration:{unit}", where unit is
|
||||
// "s", "ms", "us", "ns"
|
||||
// * "dict:{value_type}:{index_type}:false"
|
||||
string logical_type = 5;
|
||||
// If this field is nullable.
|
||||
bool nullable = 6;
|
||||
|
||||
// optional field metadata (e.g. extension type name/parameters)
|
||||
map<string, bytes> metadata = 10;
|
||||
|
||||
bool unenforced_primary_key = 12;
|
||||
|
||||
// Position of this field in the primary key (1-based).
|
||||
// 0 means the field is part of the primary key but uses schema field id for ordering.
|
||||
// When set to a positive value, primary key fields are ordered by this position.
|
||||
uint32 unenforced_primary_key_position = 13;
|
||||
|
||||
// Reserved for future use. Use unenforced_clustering_key_position instead.
|
||||
bool unenforced_clustering_key = 14;
|
||||
|
||||
// Position of this field in the clustering key (1-based).
|
||||
// 0 means the field is not part of the clustering key.
|
||||
uint32 unenforced_clustering_key_position = 15;
|
||||
|
||||
// DEPRECATED ----------------------------------------------------------------
|
||||
|
||||
// Deprecated: Only used in V1 file format. V2 uses variable encodings defined
|
||||
// per page.
|
||||
//
|
||||
// The global encoding to use for this field.
|
||||
Encoding encoding = 7;
|
||||
|
||||
// Deprecated: Only used in V1 file format. V2 dynamically chooses when to
|
||||
// do dictionary encoding and keeps the dictionary in the data files.
|
||||
//
|
||||
// The file offset for storing the dictionary value.
|
||||
// It is only valid if encoding is DICTIONARY.
|
||||
//
|
||||
// The logic type presents the value type of the column, i.e., string value.
|
||||
Dictionary dictionary = 8;
|
||||
|
||||
// Deprecated: optional extension type name, use metadata field
|
||||
// ARROW:extension:name
|
||||
string extension_name = 9;
|
||||
|
||||
// Field number 11 was previously `string storage_class`.
|
||||
// Keep it reserved so older manifests remain compatible while new writers
|
||||
// avoid reusing the slot.
|
||||
reserved 11;
|
||||
reserved "storage_class";
|
||||
}
|
||||
@@ -1,210 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: Copyright The Lance Authors
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package lance.file.v2;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
// # Lance v2.X File Format
|
||||
//
|
||||
// The Lance file format is a barebones format for serializing columnar data
|
||||
// into a file.
|
||||
//
|
||||
// * Each Lance file contains between 0 and 4Gi columns
|
||||
// * Each column contains between 0 and 4Gi pages
|
||||
// * Each page contains between 0 and 2^64 items
|
||||
// * Different pages within a column can have different items counts
|
||||
// * Columns may have up to 2^64 items
|
||||
// * Different columns within a file can have different item counts
|
||||
//
|
||||
// The Lance file format does not have any notion of a type system or schemas.
|
||||
// From the perspective of the file format all data is arbitrary buffers of
|
||||
// bytes with an extensible metadata block to describe the data. It is up to
|
||||
// the user to interpret these bytes meaningfully.
|
||||
//
|
||||
// Data buffers are written to the file first. These data buffers can be
|
||||
// referenced from three different places in the file:
|
||||
//
|
||||
// * Page encodings can reference data buffers. This is the most common way
|
||||
// that actual data is stored.
|
||||
// * Column encodings can reference data buffers. For example, a column encoding
|
||||
// may reference data buffer(s) containing statistics or dictionaries.
|
||||
// * Finally, the global buffer offset table can reference data buffers. This
|
||||
// is useful for storing data that is shared across multiple columns.
|
||||
// This is also useful for global file metadata (e.g. a schema that describes
|
||||
// the file)
|
||||
//
|
||||
// ## File Layout
|
||||
//
|
||||
// Note: the number of buffers (BN) is independent of the number of columns (CN)
|
||||
// and pages.
|
||||
//
|
||||
// Buffers often need to be aligned. 64-byte alignment is common when
|
||||
// working with SIMD operations. 4096-byte alignment is common when
|
||||
// working with direct I/O. In order to ensure these buffers are aligned
|
||||
// writers may need to insert padding before the buffers.
|
||||
//
|
||||
// If direct I/O is required then most (but not all) fields described
|
||||
// below must be sector aligned. We have marked these fields with an
|
||||
// asterisk for clarity. Readers should assume there will be optional
|
||||
// padding inserted before these fields.
|
||||
//
|
||||
// All footer fields are unsigned integers written with little endian
|
||||
// byte order.
|
||||
//
|
||||
// ├──────────────────────────────────┤
|
||||
// | Data Pages |
|
||||
// | Data Buffer 0* |
|
||||
// | ... |
|
||||
// | Data Buffer BN* |
|
||||
// ├──────────────────────────────────┤
|
||||
// | Column Metadatas |
|
||||
// | |A| Column 0 Metadata* |
|
||||
// | Column 1 Metadata* |
|
||||
// | ... |
|
||||
// | Column CN Metadata* |
|
||||
// ├──────────────────────────────────┤
|
||||
// | Column Metadata Offset Table |
|
||||
// | |B| Column 0 Metadata Position* |
|
||||
// | Column 0 Metadata Size |
|
||||
// | ... |
|
||||
// | Column CN Metadata Position |
|
||||
// | Column CN Metadata Size |
|
||||
// ├──────────────────────────────────┤
|
||||
// | Global Buffers Offset Table |
|
||||
// | |C| Global Buffer 0 Position* |
|
||||
// | Global Buffer 0 Size |
|
||||
// | ... |
|
||||
// | Global Buffer GN Position |
|
||||
// | Global Buffer GN Size |
|
||||
// ├──────────────────────────────────┤
|
||||
// | Footer |
|
||||
// | A u64: Offset to column meta 0 |
|
||||
// | B u64: Offset to CMO table |
|
||||
// | C u64: Offset to GBO table |
|
||||
// | u32: Number of global bufs |
|
||||
// | u32: Number of columns |
|
||||
// | u16: Major version |
|
||||
// | u16: Minor version |
|
||||
// | "LANC" |
|
||||
// ├──────────────────────────────────┤
|
||||
//
|
||||
// File Layout-End
|
||||
//
|
||||
// ## Data Pages
|
||||
//
|
||||
// A lot of flexibility is provided in how data is stored. A page's buffers do
|
||||
// not strictly need to be contiguous on the disk. However, it is recommended
|
||||
// that buffers within a page be grouped together for best performance.
|
||||
//
|
||||
// Data pages should be large. The only time a page should be written to disk
|
||||
// is when the writer needs to flush the page to disk because it has accumulated
|
||||
// too much data. Pages are not read in sequential order and if pages are too
|
||||
// small then the seek overhead (or request overhead) will be problematic. We
|
||||
// generally advise that pages be at least 8MB or larger.
|
||||
//
|
||||
// ## Encodings
|
||||
//
|
||||
// Specific encodings are not part of this minimal format. They are provided
|
||||
// by extensions. Readers and writers should be designed so that encodings can
|
||||
// be easily added and removed. Ideally, they should allow for this without
|
||||
// requiring recompilation through some kind of plugin system.
|
||||
|
||||
// The deferred encoding is used to place the encoding itself in a different
|
||||
// part of the file. This is most commonly used to allow encodings to be shared
|
||||
// across different columns. For example, when writing a file with thousands of
|
||||
// columns, where many pages have the exact same encoding, it can be useful
|
||||
// to cut down on the size of the metadata by using a deferred encoding.
|
||||
message DeferredEncoding {
|
||||
// Location of the buffer containing the encoding.
|
||||
//
|
||||
// * If sharing encodings across columns then this will be in a global buffer
|
||||
// * If sharing encodings across pages within a column this could be in a
|
||||
// column metadata buffer.
|
||||
// * This could also be a page buffer if the encoding is not shared, needs
|
||||
// to be written before the file ends, and the encoding is too large to load
|
||||
// unless we first determine the page needs to be read. This combination
|
||||
// seems unusual.
|
||||
uint64 buffer_location = 1;
|
||||
uint64 buffer_length = 2;
|
||||
}
|
||||
|
||||
// The encoding is placed directly in the metadata section
|
||||
message DirectEncoding {
|
||||
// The bytes that make up the encoding embedded directly in the metadata
|
||||
//
|
||||
// This is the most common approach.
|
||||
bytes encoding = 1;
|
||||
}
|
||||
|
||||
// An encoding stores the information needed to decode a column or page
|
||||
//
|
||||
// For example, it could describe if the page is using bit packing, and how many bits
|
||||
// there are in each individual value.
|
||||
//
|
||||
// At the column level it can be used to wrap columns with dictionaries or statistics.
|
||||
message Encoding {
|
||||
oneof location {
|
||||
// The encoding is stored elsewhere and not part of this protobuf message
|
||||
DeferredEncoding indirect = 1;
|
||||
// The encoding is stored within this protobuf message
|
||||
DirectEncoding direct = 2;
|
||||
// There is no encoding information
|
||||
google.protobuf.Empty none = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// ## Metadata
|
||||
|
||||
// Each column has a metadata block that is placed at the end of the file.
|
||||
// These may be read individually to allow for column projection.
|
||||
message ColumnMetadata {
|
||||
|
||||
// This describes a page of column data.
|
||||
message Page {
|
||||
// The file offsets for each of the page buffers
|
||||
//
|
||||
// The number of buffers is variable and depends on the encoding. There
|
||||
// may be zero buffers (e.g. constant encoded data) in which case this
|
||||
// could be empty.
|
||||
repeated uint64 buffer_offsets = 1;
|
||||
// The size (in bytes) of each of the page buffers
|
||||
//
|
||||
// This field will have the same length as `buffer_offsets` and
|
||||
// may be empty.
|
||||
repeated uint64 buffer_sizes = 2;
|
||||
// Logical length (e.g. # rows) of the page
|
||||
uint64 length = 3;
|
||||
// The encoding used to encode the page
|
||||
Encoding encoding = 4;
|
||||
// The priority of the page
|
||||
//
|
||||
// For tabular data this will be the top-level row number of the first row
|
||||
// in the page (and top-level rows should not split across pages).
|
||||
uint64 priority = 5;
|
||||
}
|
||||
// Encoding information about the column itself. This typically describes
|
||||
// how to interpret the column metadata buffers. For example, it could
|
||||
// describe how statistics or dictionaries are stored in the column metadata.
|
||||
Encoding encoding = 1;
|
||||
// The pages in the column
|
||||
repeated Page pages = 2;
|
||||
// The file offsets of each of the column metadata buffers
|
||||
//
|
||||
// There may be zero buffers.
|
||||
repeated uint64 buffer_offsets = 3;
|
||||
// The size (in bytes) of each of the column metadata buffers
|
||||
//
|
||||
// This field will have the same length as `buffer_offsets` and
|
||||
// may be empty.
|
||||
repeated uint64 buffer_sizes = 4;
|
||||
} // Metadata-End
|
||||
|
||||
// ## Where is the rest?
|
||||
//
|
||||
// This file format is extremely minimal. It is a building block for
|
||||
// creating more useful readers and writers and not terribly useful by itself.
|
||||
// Other protobuf files will describe how this can be extended.
|
||||
@@ -1,99 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: Copyright The Lance Authors
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package lance.datafusion;
|
||||
|
||||
import "table_identifier.proto";
|
||||
|
||||
message U64Range {
|
||||
uint64 start = 1;
|
||||
uint64 end = 2;
|
||||
}
|
||||
|
||||
message ProjectionProto {
|
||||
repeated int32 field_ids = 1;
|
||||
bool with_row_id = 2;
|
||||
bool with_row_addr = 3;
|
||||
bool with_row_last_updated_at_version = 4;
|
||||
bool with_row_created_at_version = 5;
|
||||
BlobHandlingProto blob_handling = 6;
|
||||
}
|
||||
|
||||
message BlobHandlingProto {
|
||||
oneof mode {
|
||||
// All blobs read as binary
|
||||
bool all_binary = 1;
|
||||
// Blobs as descriptions, other binary as binary (default)
|
||||
bool blobs_descriptions = 2;
|
||||
// All binary columns as descriptions
|
||||
bool all_descriptions = 3;
|
||||
// Specific blobs read as binary, rest as descriptions (non-blob binary stays binary)
|
||||
FieldIdSet some_blobs_binary = 4;
|
||||
// Specific columns as binary, all other binary as descriptions
|
||||
FieldIdSet some_binary = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message FieldIdSet {
|
||||
repeated uint32 field_ids = 1;
|
||||
}
|
||||
|
||||
message FilteredReadThreadingModeProto {
|
||||
oneof mode {
|
||||
uint64 one_partition_multiple_threads = 1;
|
||||
uint64 multiple_partitions = 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Serializable form of FilteredReadOptions.
|
||||
message FilteredReadOptionsProto {
|
||||
optional U64Range scan_range_before_filter = 1;
|
||||
optional U64Range scan_range_after_filter = 2;
|
||||
bool with_deleted_rows = 3;
|
||||
optional uint32 batch_size = 4;
|
||||
optional uint64 fragment_readahead = 5;
|
||||
repeated uint64 fragment_ids = 6;
|
||||
ProjectionProto projection = 7;
|
||||
optional bytes refine_filter_substrait = 8;
|
||||
optional bytes full_filter_substrait = 9;
|
||||
FilteredReadThreadingModeProto threading_mode = 10;
|
||||
optional uint64 io_buffer_size_bytes = 11;
|
||||
// Arrow IPC schema for decoding Substrait filters (may be wider than projection).
|
||||
optional bytes filter_schema_ipc = 12;
|
||||
}
|
||||
|
||||
// Serializable form of FilteredReadPlan (planned/distributed mode).
|
||||
// RowAddrTreeMap serialized via its built-in serialize_into/deserialize_from.
|
||||
// Per-fragment filters are Substrait-encoded and deduplicated.
|
||||
message FilteredReadPlanProto {
|
||||
bytes row_addr_tree_map = 1;
|
||||
optional U64Range scan_range_after_filter = 2;
|
||||
// Arrow IPC schema for decoding Substrait filters (matches the schema used at encode time).
|
||||
optional bytes filter_schema_ipc = 3;
|
||||
// Per-fragment filter mapping. Key is fragment id, value is a list index into
|
||||
// filter_expressions. Multiple fragments can share the same list index when
|
||||
// they have the same filter, avoiding duplicate Substrait encoding.
|
||||
map<uint32, uint32> fragment_filter_ids = 4;
|
||||
// Deduplicated Substrait-encoded filter expressions. Each entry is referenced
|
||||
// by one or more values in fragment_filter_ids.
|
||||
repeated bytes filter_expressions = 5;
|
||||
}
|
||||
|
||||
// Top-level wrapper for FilteredReadExec serialization.
|
||||
message FilteredReadExecProto {
|
||||
TableIdentifier table = 1;
|
||||
FilteredReadOptionsProto options = 2;
|
||||
// FilteredRead has two modes
|
||||
// Plan-then-execute (distributed): The planner creates a FilteredReadPlan and sends it to a remote executor.
|
||||
// Plan-and-execute (local): The executor creates the plan itself at execution time.
|
||||
optional FilteredReadPlanProto plan = 3;
|
||||
// Note: FilteredReadExec.index_input (child ExecutionPlan) is NOT serialized here.
|
||||
// DataFusion's PhysicalExtensionCodec handles child plans automatically: it walks
|
||||
// the plan tree via children() / with_new_children(), serializes each node, and
|
||||
// passes deserialized children back as the `inputs` parameter in try_decode.
|
||||
// This means any ExecutionPlan in the tree (including index_input) must also
|
||||
// implement try_encode/try_decode in the PhysicalExtensionCodec.
|
||||
// TODO: implement serialize/deserialize for lance-specific index input ExecutionPlans.
|
||||
}
|
||||
@@ -1,251 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: Copyright The Lance Authors
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package lance.index.pb;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
// The type of an index.
|
||||
enum IndexType {
|
||||
// Vector index
|
||||
VECTOR = 0;
|
||||
}
|
||||
|
||||
message Index {
|
||||
// The unique index name in the dataset.
|
||||
string name = 1;
|
||||
|
||||
// Columns to be used to build the index.
|
||||
repeated string columns = 2;
|
||||
|
||||
// The version of the dataset this index was built from.
|
||||
uint64 dataset_version = 3;
|
||||
|
||||
// The [`IndexType`] of the index.
|
||||
IndexType index_type = 4;
|
||||
|
||||
/// Index implementation details.
|
||||
oneof implementation {
|
||||
VectorIndex vector_index = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message Tensor {
|
||||
enum DataType {
|
||||
BFLOAT16 = 0;
|
||||
FLOAT16 = 1;
|
||||
FLOAT32 = 2;
|
||||
FLOAT64 = 3;
|
||||
UINT8 = 4;
|
||||
UINT16 = 5;
|
||||
UINT32 = 6;
|
||||
UINT64 = 7;
|
||||
}
|
||||
|
||||
DataType data_type = 1;
|
||||
|
||||
// Data shape, [dim1, dim2, ...]
|
||||
repeated uint32 shape = 2;
|
||||
|
||||
// Data buffer
|
||||
bytes data = 3;
|
||||
}
|
||||
|
||||
// Inverted Index File Metadata.
|
||||
message IVF {
|
||||
// Centroids of partitions. `dimension * num_partitions` of float32s.
|
||||
//
|
||||
// Deprecated, use centroids_tensor instead.
|
||||
repeated float centroids = 1; // [deprecated = true];
|
||||
|
||||
// File offset of each partition.
|
||||
repeated uint64 offsets = 2;
|
||||
|
||||
// Number of records in the partition.
|
||||
repeated uint32 lengths = 3;
|
||||
|
||||
// Tensor of centroids. `num_partitions * dimension` of float32s.
|
||||
Tensor centroids_tensor = 4;
|
||||
|
||||
// KMeans loss.
|
||||
optional double loss = 5;
|
||||
}
|
||||
|
||||
// Product Quantization.
|
||||
message PQ {
|
||||
// The number of bits to present a centroid.
|
||||
uint32 num_bits = 1;
|
||||
|
||||
// Number of sub vectors.
|
||||
uint32 num_sub_vectors = 2;
|
||||
|
||||
// Vector dimension
|
||||
uint32 dimension = 3;
|
||||
|
||||
// Codebook. `dimension * 2 ^ num_bits` of float32s.
|
||||
repeated float codebook = 4;
|
||||
|
||||
// Tensor of codebook. `2 ^ num_bits * dimension` of floats.
|
||||
Tensor codebook_tensor = 5;
|
||||
}
|
||||
|
||||
// Transform type
|
||||
enum TransformType {
|
||||
OPQ = 0;
|
||||
}
|
||||
|
||||
// A transform matrix to apply to a vector or vectors.
|
||||
message Transform {
|
||||
// The file offset the matrix is stored
|
||||
uint64 position = 1;
|
||||
|
||||
// Data shape of the matrix, [rows, cols].
|
||||
repeated uint32 shape = 2;
|
||||
|
||||
// Transform type.
|
||||
TransformType type = 3;
|
||||
}
|
||||
|
||||
// Flat Index
|
||||
message Flat {}
|
||||
|
||||
// DiskAnn Index
|
||||
message DiskAnn {
|
||||
// Graph spec version
|
||||
uint32 spec = 1;
|
||||
|
||||
// Graph file
|
||||
string filename = 2;
|
||||
|
||||
// r parameter
|
||||
uint32 r = 3;
|
||||
|
||||
// alpha parameter
|
||||
float alpha = 4;
|
||||
|
||||
// L parameter
|
||||
uint32 L = 5;
|
||||
|
||||
/// Entry points to the graph
|
||||
repeated uint64 entries = 6;
|
||||
}
|
||||
|
||||
// One stage in the vector index pipeline.
|
||||
message VectorIndexStage {
|
||||
oneof stage {
|
||||
// Flat index
|
||||
Flat flat = 1;
|
||||
// `IVF` - Inverted File
|
||||
IVF ivf = 2;
|
||||
// Product Quantization
|
||||
PQ pq = 3;
|
||||
// Transformer
|
||||
Transform transform = 4;
|
||||
// DiskANN
|
||||
DiskAnn diskann = 5;
|
||||
}
|
||||
}
|
||||
|
||||
// Metric Type for Vector Index
|
||||
enum VectorMetricType {
|
||||
// L2 (Euclidean) Distance
|
||||
L2 = 0;
|
||||
|
||||
// Cosine Distance
|
||||
Cosine = 1;
|
||||
|
||||
// Dot Product
|
||||
Dot = 2;
|
||||
|
||||
// Hamming Distance
|
||||
Hamming = 3;
|
||||
}
|
||||
|
||||
// Vector Index Metadata
|
||||
message VectorIndex {
|
||||
// Index specification version.
|
||||
uint32 spec_version = 1;
|
||||
|
||||
// Vector dimension;
|
||||
uint32 dimension = 2;
|
||||
|
||||
// Composed vector index stages.
|
||||
//
|
||||
// For example, `IVF_PQ` index type can be expressed as:
|
||||
//
|
||||
// ```text
|
||||
// let stages = vec![Ivf{}, PQ{num_bits: 8, num_sub_vectors: 16}]
|
||||
// ```
|
||||
repeated VectorIndexStage stages = 3;
|
||||
|
||||
// Vector distance metrics type
|
||||
VectorMetricType metric_type = 4;
|
||||
}
|
||||
|
||||
// Details for vector indexes, stored in the manifest's index_details field.
|
||||
message VectorIndexDetails {
|
||||
VectorMetricType metric_type = 1;
|
||||
|
||||
// The target number of vectors per partition.
|
||||
// 0 means unset.
|
||||
uint64 target_partition_size = 2;
|
||||
|
||||
// Optional HNSW index configuration. If set, the index has an HNSW layer.
|
||||
optional HnswParameters hnsw_index_config = 3;
|
||||
|
||||
message ProductQuantization {
|
||||
uint32 num_bits = 1;
|
||||
uint32 num_sub_vectors = 2;
|
||||
}
|
||||
message ScalarQuantization {
|
||||
uint32 num_bits = 1;
|
||||
}
|
||||
message RabitQuantization {
|
||||
enum RotationType {
|
||||
FAST = 0;
|
||||
MATRIX = 1;
|
||||
}
|
||||
uint32 num_bits = 1;
|
||||
RotationType rotation_type = 2;
|
||||
}
|
||||
|
||||
// No quantization; vectors are stored as-is.
|
||||
message FlatCompression {}
|
||||
|
||||
oneof compression {
|
||||
ProductQuantization pq = 4;
|
||||
ScalarQuantization sq = 5;
|
||||
RabitQuantization rq = 6;
|
||||
FlatCompression flat = 8;
|
||||
}
|
||||
|
||||
// Runtime hints: optional build preferences that don't affect index structure.
|
||||
// Keys use reverse-DNS namespacing (e.g., "lance.ivf.max_iters", "lancedb.accelerator").
|
||||
// Unrecognized keys must be silently ignored by all runtimes.
|
||||
map<string, string> runtime_hints = 9;
|
||||
}
|
||||
|
||||
// Hierarchical Navigable Small World (HNSW) parameters, used as an optional configuration for IVF indexes.
|
||||
message HnswParameters {
|
||||
// The maximum number of outgoing edges per node in the HNSW graph. Higher values
|
||||
// means more connections, better recall, but more memory and slower builds.
|
||||
// Referred to as "M" in the HNSW literature.
|
||||
uint32 max_connections = 1;
|
||||
// "construction exploration factor": The size of the dynamic list used during
|
||||
// index construction.
|
||||
uint32 construction_ef = 2;
|
||||
// The maximum number of levels in the HNSW graph.
|
||||
uint32 max_level = 3;
|
||||
}
|
||||
|
||||
message JsonIndexDetails {
|
||||
string path = 1;
|
||||
google.protobuf.Any target_details = 2;
|
||||
}
|
||||
message BloomFilterIndexDetails {}
|
||||
|
||||
message RTreeIndexDetails {}
|
||||
|
||||
message FMIndexDetails {}
|
||||
@@ -1,104 +0,0 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-FileCopyrightText: Copyright The Lance Authors
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package lance.table;
|
||||
|
||||
// NOTE: Do *NOT* add new index details here. Add them to the index.proto file instead.
|
||||
// This file is in the lance.table package namespace while the index.proto file is in the
|
||||
// lance.index package namespace.
|
||||
//
|
||||
// These are only here for forward compatibility. Older versions of Lance expect btree indexes
|
||||
// to have lance.table in the package namespace.
|
||||
//
|
||||
// If you need to modify these messages (e.g. to add new fields to btree or bitmap) then
|
||||
// it is ok to modify them here.
|
||||
|
||||
// Currently many of these are empty messages because all needed details are either hard-coded (e.g.
|
||||
// filenames) or stored in the index itself. However, we may want to add more details in the
|
||||
// future, in particular we can add details that may be useful for planning queries (e.g. don't
|
||||
// force us to load the index until we know we can make use of it)
|
||||
|
||||
message BTreeIndexDetails {}
|
||||
message BitmapIndexDetails {}
|
||||
message LabelListIndexDetails {}
|
||||
message NGramIndexDetails {}
|
||||
message ZoneMapIndexDetails {
|
||||
// Number of rows per zone. Optional for backwards compatibility: absent on
|
||||
// datasets written before this field was added. When absent, no seed writer
|
||||
// is created for the index.
|
||||
optional uint64 rows_per_zone = 1;
|
||||
// Whether seed-based incremental updates are enabled for this index.
|
||||
// On-disk semantics: absent means seeds are disabled (old datasets written
|
||||
// before this field was added). Present false means explicitly disabled.
|
||||
// Present true means seeds are enabled: the index will embed per-fragment
|
||||
// seed buffers in data files and harvest them during incremental updates
|
||||
// to skip full column scans.
|
||||
// Creation-time default: index creation code sets this to true for
|
||||
// variable-length types (strings, binary) and fixed-width types wider than
|
||||
// 8 bytes, and to false for narrow fixed-width types (e.g. Int64, Float64).
|
||||
optional bool use_seeds = 2;
|
||||
// Whether this index tracks exact null row addresses in a separate bitmap.
|
||||
// Absent or false means legacy format: null positions are not tracked and
|
||||
// IS NULL searches fall back to approximate zone-level statistics. Present
|
||||
// true means IS NULL is exact and IS NOT NULL can be answered without a
|
||||
// full scan.
|
||||
optional bool has_null_bitmap = 3;
|
||||
}
|
||||
message InvertedIndexDetails {
|
||||
enum DocumentGranularity {
|
||||
ROW = 0;
|
||||
LIST_ELEMENT = 1;
|
||||
}
|
||||
|
||||
message CodeTokenizerConfig {
|
||||
// Split one lexical identifier into subwords, e.g. getUserName ->
|
||||
// get/user/name.
|
||||
bool split_identifiers = 1;
|
||||
// Split identifier subwords across letter/number boundaries, e.g.
|
||||
// HTML2JSON -> html/2/json. An absent value uses the code tokenizer default;
|
||||
// a present value records the explicit index-time choice.
|
||||
optional bool split_on_numerics = 2;
|
||||
// Keep the complete lexical identifier in addition to subwords, e.g.
|
||||
// user_name plus user/name. An absent value uses the code tokenizer default;
|
||||
// a present value records the explicit index-time choice.
|
||||
optional bool preserve_original = 3;
|
||||
// Index operator tokens such as "::", "->", and "!=". Operators are not
|
||||
// indexed by default because they are often high-frequency noise.
|
||||
bool index_operators = 4;
|
||||
}
|
||||
|
||||
// Lexical tokenizer used after document-level text extraction. This is an
|
||||
// implementation component such as "simple", "icu", "ngram", or "code".
|
||||
// Input-time analyzer profiles are expanded into this field and the concrete
|
||||
// options below before these details are persisted.
|
||||
// Marking this field as optional as old versions of the index store blank details and we
|
||||
// need to make sure we have a proper optional field to detect this.
|
||||
optional string base_tokenizer = 1;
|
||||
string language = 2;
|
||||
bool with_position = 3;
|
||||
optional uint32 max_token_length = 4;
|
||||
bool lower_case = 5;
|
||||
bool stem = 6;
|
||||
bool remove_stop_words = 7;
|
||||
bool ascii_folding = 8;
|
||||
uint32 min_ngram_length = 9;
|
||||
uint32 max_ngram_length = 10;
|
||||
bool prefix_only = 11;
|
||||
// Number of documents per compressed posting block. An absent value means
|
||||
// the index predates this field and must use the legacy block size of 128.
|
||||
// A present value records the block size used by the index; 256 is valid
|
||||
// with format versions 3 and 4.
|
||||
optional uint32 block_size = 12;
|
||||
// Options for base_tokenizer = "code". Presence records the code tokenizer
|
||||
// configuration used to build the index; absence means there is no
|
||||
// code-specific configuration to apply.
|
||||
CodeTokenizerConfig code_config = 13;
|
||||
// The logical FTS document boundary. The protobuf default preserves the
|
||||
// legacy row-document behavior when this field is absent.
|
||||
DocumentGranularity document_granularity = 14;
|
||||
// The posting-list payload format. This is separate from index_version,
|
||||
// which identifies the overall inverted-index layout.
|
||||
optional uint32 posting_format_version = 15;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user