Repository navigation
lance_fdw: add a foreign-data wrapper that scans Lance datasets - #2140
MisterRaindrop wants to merge 2 commits into
Conversation
af48e60 to
440606a
Compare
Review by Claude Code, FYI. |
| case $(uname -m) in | ||
| x86_64) protoc_arch=x86_64 ;; | ||
| aarch64) protoc_arch=aarch_64 ;; | ||
| *) echo "build-lance-c: no protoc build for $(uname -m)" >&2; exit 1 ;; | ||
| esac | ||
| curl -fsSL --retry 5 --retry-connrefused -o "$work/protoc.zip" \ | ||
| "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-linux-${protoc_arch}.zip" | ||
| unzip -q -o "$work/protoc.zip" -d "$work/protoc" bin/protoc 'include/*' | ||
| export PROTOC=$work/protoc/bin/protoc | ||
| "$PROTOC" --version |
There was a problem hiding this comment.
We should already ship the protoc in our development images.
# Rocky 8
[gpadmin@cdw ~]$ protoc --version
libprotoc 3.5.0
# Rocky 9
[gpadmin@cdw ~]$ protoc --version
libprotoc 3.14.0
# Rocky 10
[gpadmin@cdw ~]$ protoc --version
libprotoc 3.19.6| git init -q "$work/lance-c" | ||
| git -C "$work/lance-c" fetch -q --depth 1 "$LANCE_C_REPO" "$LANCE_C_COMMIT" | ||
| git -C "$work/lance-c" checkout -q FETCH_HEAD | ||
| echo "build-lance-c: building lance-c $LANCE_C_COMMIT" | ||
| (cd "$work/lance-c" && cargo build --release --locked) |
There was a problem hiding this comment.
We can also ship the liblance in the future. FYI.
| * leave the flags undefined and make nanoarrow.h declare ArrowArrayStream a | ||
| * second time, so the order below is not cosmetic. | ||
| * | ||
| * Copyright (c) 2026, Apache Cloudberry (incubating) contributors |
There was a problem hiding this comment.
| * Copyright (c) 2026, Apache Cloudberry (incubating) contributors |
There is no need. Let us remove this line.
There was a problem hiding this comment.
Removed in e09e2b0. It was the only line like it in lance_fdw.
| if test "$with_lance" = yes ; then | ||
| AC_CHECK_HEADER(lance/lance.h, [], [AC_MSG_ERROR([header file <lance/lance.h> is required for Lance support])]) | ||
| fi | ||
|
|
There was a problem hiding this comment.
If other dependencies, like libprotoc, are also required dependencies, we can add their checks too.
There was a problem hiding this comment.
I don't think there are any. liblance_c is lance_fdw's only external dependency; the link check also passes -lpthread -ldl -lm, which it needs. protoc is only used to build lance-c itself: neither lance.h nor lance_fdw uses protobuf, and the module doesn't link it. So once a liblance_c is installed, configure has nothing else to look for. The protoc requirement is checked where it applies, in ci/build-lance-c.sh, which uses the image's protoc if it is 3.15 or newer and otherwise downloads a pinned, checksummed one.
440606a to
6283427
Compare
|
Thanks for the thorough review. Everything below is folded into the two commits (now Must fix1.
Creating a server with
A 2.
The QD now pins the version under 'any' and publishes it with a width of 0, which the QEs read as "every fragment". This is the same plan slot the all-segments path uses, and cached plans republish. A QE under 'any' with no published units is an error, as it is under all segments. The README no longer says "one process reads everything". Suggestions3. Threads. Worse than it looked: So there is a new 4. Signals. Synchronous signals (SEGV, BUS, FPE, ILL, TRAP, SYS) are no longer blocked. On latency, I don't think the mask is what defers a cancel. A backend's handlers only set a flag for the next
I didn't take the other two options:
A real fix for latency would be to read plain scans through 5. ORCA. ORCA does plan these scans itself ( 6. In-tree build. All three reproduced and fixed:
7. Downloads.
On the protoc inline comment, I tried it. lance's build scripts pass On shipping liblance in the images: agreed. 8. LICENSE. nanoarrow is now listed in the top-level LICENSE, next to the other vendored Apache-2.0 code. 9. Stale references. Fixed 10. Nits.
#2141–#2143 will be rebased onto this, together with their own review fixes. |
lance_fdw reads Lance datasets, local or on S3, in place. Servers, user mappings, foreign tables and IMPORT FOREIGN SCHEMA work as for any wrapper. The scan runs on every segment: the coordinator lists the dataset's fragments at a pinned version and gives each segment a disjoint share, so one statement sees one snapshot. Under mpp_execute 'any', where every process that runs the scan reads the whole dataset, the coordinator pins the version for them as well. Only the columns a query refers to are read. Every A-tier Arrow type is converted - booleans, the integer and float families, strings, binaries, date32, timestamps in all four units, decimal128, fixed_size_list<float> embeddings, one-dimensional lists, structs as composite types and map<utf8, ...> as jsonb - and anything else is refused by name rather than guessed at. Who may read what follows file_fdw and postgres_fdw. For a role that is not a superuser, a table's uri has to stay inside the server's base_uri - no absolute uri, and no ".." component however it is spelled - unless the role is a member of pg_read_server_files and the path is local; IMPORT FOREIGN SCHEMA checks each name the same way. A local base_uri needs pg_read_server_files, and aws_endpoint and allow_http need a superuser. Reading an object store needs keys in the role's user mapping, since lance would otherwise sign with whatever credentials the host has; a superuser may waive that with credentials_required 'false', as postgres_fdw's password_required. Arrow batches are allocated by lance on the Rust side, out of sight of gp_vmem_protect_limit and the resource group, so each batch is charged to the vmem tracker once it is bound, and batch_size_bytes bounds what one batch may hold. lance-c's threads block the asynchronous signals a backend is driven by, and every dataset, scanner and stream is closed through the resource owner on the error path as well. A host runs one backend per segment, slice and session, so lance_fdw.runtime_threads and lance_fdw.cpu_threads size lance-c's tokio runtime and lance's compute pool to two threads each rather than one per core. A cancel takes effect when the current call into lance-c returns; the server options connect_timeout, timeout, client_max_retries and client_retry_timeout bound how long that can take against an object store. It links liblance_c, the C binding of Lance. lance-c is written in Rust and is not part of this tree: configure --with-lance finds an installed one through --with-includes and --with-libraries, checks it has the newest function lance_fdw calls, and gives the module a run path to those directories; a PGXS build takes LANCE_C_PREFIX. Only contrib/lance_fdw links it. ci/build-lance-c.sh builds the tested revision from source, with every download pinned and checksummed. The Arrow batches are decoded with a vendored copy of Apache Arrow nanoarrow 0.7.0, its symbols renamed into a namespace of their own. The regression suites read datasets generated with pylance from a local directory and from an S3 bucket, named in test/regress.mk; ci/prepare-tests.sh generates them, starts a SeaweedFS S3 gateway and writes that file. Without it, an in-tree installcheck says so and passes, so that installcheck-world does not need the datasets. The suites create their own C.UTF-8 database, whatever the cluster's locale, and installcheck-orca runs all but scan_core again under ORCA.
Add ic-lance-fdw. Like datalake_fdw it is built through PGXS against the installed server. liblance_c is built from source first, which takes about a quarter of an hour, so it is cached per image and per revision. After the demo cluster is up, ci/prepare-tests.sh generates the datasets and serves them from a local S3 gateway. The suites run under the planner, and all but scan_core again under ORCA.
6283427 to
7a1aacc
Compare
Part of #2139 (1 of 4 for contrib/lance_fdw).
What does this PR do?
Adds
contrib/lance_fdw, a read-only foreign-data wrapper that reads Lancedatasets, local or on S3, in place, with the scan spread over every segment
by fragment and pinned to one dataset version per statement. Every A-tier
Arrow type is converted; anything else is refused by name. Arrow batches,
which lance allocates outside palloc, are charged to the vmem tracker.
It is built only with
configure --with-lance(or with PGXS andLANCE_C_PREFIX) and links an installedliblance_c. No Rust code, crates orcargo invocation enter this tree;
contrib/lance_fdw/ci/build-lance-c.shbuilds the tested lance-c revision for CI. The only bundled third-party code
is Apache Arrow nanoarrow 0.7.0 (Apache-2.0).
CI: a new
ic-lance-fdwentry builds lance-c (cached), builds the extensionwith PGXS, generates the test datasets with pylance, serves them from a local
SeaweedFS S3 gateway, and runs the 15 regression suites.
Type of Change
Test Plan
make installcheck(contrib/lance_fdw, Rocky 8, 9 and 10 in CI)Impact
Dependencies: an installed liblance_c when configured with
--with-lance;nothing otherwise.
Checklist