FANNG1 opened a new pull request, #66805:
URL: https://github.com/apache/doris/pull/66805

   ### What problem does this PR solve?
   
   Fixes #66772 (problem 1).
   
   A Lance REST catalog discarded the `storage_options` a namespace vended for 
a table, so any scan relying on credential vending failed:
   
   ```
   open Lance dataset failed: LanceError(IO): ...
   Failed to get AWS credentials: CredentialsNotLoaded("no providers in chain 
provided credentials")
   ```
   
   The options were re-encoded twice on the way to the BE, through one 
five-entry S3-only table used in both directions:
   
   ```
   namespace vends  access_key_id
     -> FE  LanceStorageOptions.forBackend   aws_access_key_id -> AWS_ACCESS_KEY
     -> TFileScanRangeParams.properties
     -> BE  kStorageKeys                     AWS_ACCESS_KEY -> aws_access_key_id
     -> lance-c
   ```
   
   That table was written to *emit* one canonical spelling, which is correct 
outbound. Reading it backwards turns it into a parser that accepts only the 
spelling it happens to emit, so everything else was dropped — credentials under 
any other accepted alias, and every non-S3 provider's keys, which left the 
catalog unable to use credential vending outside S3 at all.
   
   The failure was also split across the two halves, which made it hard to 
read: the FE passes the vended map to the Lance Java SDK untouched, so `SHOW 
TABLES` and `DESC` succeeded and only the scan failed.
   
   The Lance Namespace specification describes `storage_options` as 
configuration *"passed directly to Lance"*, so the protocol defines no key 
vocabulary of its own and a client cannot assume one.
   
   ### Release note
   
   Fixed a Lance REST catalog failing to scan with `CredentialsNotLoaded` when 
it relied on credentials vended by the namespace rather than static 
`s3.access_key` / `s3.secret_key`.
   
   ### What is changed and how it works?
   
   Stop re-encoding server-supplied options.
   
   - **`TFileScanRangeParams.lance_storage_options` (new, id 38)** carries the 
options in Lance's own vocabulary. Set at ScanNode level — the same pattern as 
`paimon_options` — so credentials are not serialized once per fragment split. 
`properties` is deliberately not reused: it is copied wholesale into 
`io::FileSystemProperties` for the shared filesystem layer.
   - **FE** builds a single option map, used both by the Java SDK when it opens 
the dataset and by the BE. The two can no longer disagree about how a dataset 
is reached. `forBackend` is deleted.
   - **BE** `_storage_options` hands that map to lance-c as it arrives; 
`kStorageKeys` and the `allow_http` / `use_path_style` derivations are gone.
   - The `s3()` TVF path populates the same field, including the schema-fetch 
RPC.
   
   Two details worth review attention:
   
   **Vended aliases are renamed before merging.** `object_store` resolves an 
alias and its canonical name to the same config key and keeps only one of the 
two values, chosen by hash order:
   
   ```rust
   // lance-io/src/object_store/providers/aws.rs
   let s3_key = AmazonS3ConfigKey::from_str(&key.to_ascii_lowercase()).ok()?;
   ...collect()   // HashMap — last write wins, iteration order randomized
   ```
   
   So a namespace vending `aws_endpoint` while the catalog contributes 
`endpoint` would not override it; both would survive and Lance would pick 
between them unpredictably. Only the `aws_`-prefixed aliases are renamed — bare 
names such as `token` mean different things across providers (S3 session token 
vs. Azure bearer token) and this layer does not know the provider.
   
   **Catalog options now use the unprefixed spelling.** `object_store` accepts 
both, but the unprefixed name is also the field name used by the OpenDAL 
backend, which performs no alias normalization at all.
   
   `allow_http` is derived after merging, from whichever endpoint ends up in 
use, since a namespace can replace the catalog's endpoint or supply the only 
one there is.
   
   Options that would change *which* data is read (`bucket` and its aliases, 
`root`) are dropped from the vended map, mirroring the keys Lance itself 
protects.
   
   ### Rolling upgrade
   
   An FE upgraded ahead of the BEs no longer puts vended credentials into 
`TFileScanRangeParams.properties`, and an older BE reads only that. A REST 
catalog with no static credentials therefore cannot be scanned until the BEs 
are upgraded too. The Lance catalog is not in a release yet, so this only 
affects development clusters.
   
   ### How was this patch tested?
   
   **Unit tests.** `LanceStorageOptionsTest` is new — `LanceStorageOptions` had 
no test of its own, and `forBackend` had zero call sites in any test, which is 
why this went unnoticed. It covers the emitted spelling, alias renaming, 
`allow_http` derivation, protected keys, non-S3 options, and empty/absent 
input. `LanceThriftContractTest` gains round-trip coverage of the new field.
   
   **Regression.** The docker stub only ever vended `aws_`-prefixed keys, so 
the alias path had no coverage anywhere. It now serves a second table, 
`all_types_unprefixed`, backed by the same dataset but vending the unprefixed 
spelling, and `test_lance_rest_catalog` scans it with no static credentials 
configured.
   
   **End to end**, against Apache Gravitino 1.3.0's `lance-rest` service, which 
vends the unprefixed spelling. Catalog with no `s3.access_key` / 
`s3.secret_key`:
   
   ```sql
   CREATE CATALOG lance_novend PROPERTIES (
       "type" = "lance",
       "lance.catalog.type" = "rest",
       "lance.rest.uri" = "http://127.0.0.1:9101/lance";,
       "lance.namespace.parent" = "lance_catalog"
   );
   
   SELECT count(*), min(row_id), max(row_id), sum(row_id) FROM 
lance_novend.doris_probe.rest_probe;
   -- 1034  1  1034  535095
   ```
   
   against a 1034-row, 2-fragment dataset with an IVF_FLAT index. Predicate 
pushdown and vector search both return correct results on the same catalog, and 
a catalog with static credentials is unaffected. Before this change the same 
statement failed with `CredentialsNotLoaded`.
   
   https://claude.ai/code/session_01M3mYXBKShBonG6Lg3br4Ld
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to