From 14973ac9d1190cb94d1232aa3ed8d478e77fe6e8 Mon Sep 17 00:00:00 2001 From: Weston Pace Date: Fri, 13 Feb 2026 10:10:56 -0800 Subject: [PATCH] fix: support dynamic projection on remote table (#3023) The remote server expects an object (`{"alias": "col"}`) and the client was previously sending a list of tuples `[["alias", "col"]]` --- rust/lancedb/src/remote/table.rs | 11 +++++------ rust/lancedb/src/table.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/rust/lancedb/src/remote/table.rs b/rust/lancedb/src/remote/table.rs index 04d4ce489..cf0989b0b 100644 --- a/rust/lancedb/src/remote/table.rs +++ b/rust/lancedb/src/remote/table.rs @@ -423,12 +423,11 @@ impl RemoteTable { ); } Select::Dynamic(pairs) => { - body["columns"] = serde_json::Value::Array( - pairs - .iter() - .map(|(name, expr)| serde_json::json!([name, expr])) - .collect(), - ); + let alias_map = + serde_json::Map::from_iter(pairs.iter().map(|(name, expr)| { + (name.clone(), serde_json::Value::String(expr.clone())) + })); + body["columns"] = alias_map.into(); } } diff --git a/rust/lancedb/src/table.rs b/rust/lancedb/src/table.rs index 29d6bc642..776479a8b 100644 --- a/rust/lancedb/src/table.rs +++ b/rust/lancedb/src/table.rs @@ -3163,6 +3163,7 @@ mod tests { use arrow_array::{BinaryArray, LargeBinaryArray}; use arrow_data::ArrayDataBuilder; use arrow_schema::{DataType, Field, Schema}; + use futures::TryStreamExt; use lance::dataset::WriteMode; use lance::io::{ObjectStoreParams, WrappingObjectStore}; use lance::Dataset; @@ -3174,6 +3175,8 @@ mod tests { use crate::connection::ConnectBuilder; use crate::index::scalar::{BTreeIndexBuilder, BitmapIndexBuilder}; use crate::index::vector::{IvfHnswPqIndexBuilder, IvfHnswSqIndexBuilder}; + use crate::query::{ExecutableQuery, QueryBase}; + use crate::test_utils::connection::new_test_connection; #[tokio::test] async fn test_open() { @@ -3604,6 +3607,31 @@ mod tests { assert_eq!(table.list_indices().await.unwrap().len(), 0); } + #[tokio::test] + async fn test_dynamic_select() { + let tc = new_test_connection().await.unwrap(); + let db = tc.connection; + + let table = db + .create_table("test", some_sample_data()) + .execute() + .await + .unwrap(); + + let query = table.query().select(Select::dynamic(&[("i_alias", "i")])); + + let result = query.execute().await; + let batches = result + .expect("should have result") + .try_collect::>() + .await + .unwrap(); + + for batch in batches { + assert!(batch.column_by_name("i_alias").is_some()); + } + } + #[tokio::test] async fn test_ivf_pq_uses_default_partition_size_for_num_partitions() { use arrow_array::{Float32Array, RecordBatch};