You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: use f64 precision for UDTF query vectors, add UDTF tests
Parse query vectors as f64 to match the optimizer path's precision,
avoiding silent accuracy loss for F64-quantized indexes.
Add 5 tests for vector_search_vector: basic happy path, projection
pushdown, bad table ref error, registry miss error, k > dataset size.
/// Basic happy path: returns correct rows with _distance column.
946
+
#[tokio::test]
947
+
asyncfnudtf_vector_search_vector_basic(){
948
+
let ctx = make_exec_ctx("conn::schema::items::vector").await;
949
+
let sql = "SELECT id, label, _distance FROM vector_search_vector('conn.schema.items', 'vector', ARRAY[1.0::float, 0.0::float, 0.0::float, 0.0::float], 3) ORDER BY _distance ASC";
950
+
let df = ctx.sql(sql).await.expect("sql");
951
+
let batches = df.collect().await.expect("collect");
952
+
953
+
let total:usize = batches.iter().map(|b| b.num_rows()).sum();
954
+
assert_eq!(total,3,"expected 3 results");
955
+
956
+
// First result should be row 1 (exact match, distance 0)
957
+
let ids = batches[0]
958
+
.column(0)
959
+
.as_any()
960
+
.downcast_ref::<UInt64Array>()
961
+
.expect("id col");
962
+
assert_eq!(ids.value(0),1,"closest must be row 1");
963
+
964
+
let dists = batches[0]
965
+
.column(2)
966
+
.as_any()
967
+
.downcast_ref::<Float32Array>()
968
+
.expect("_distance col");
969
+
assert!(
970
+
(dists.value(0) - 0.0).abs() < 1e-6,
971
+
"row 1 distance must be 0.0, got {}",
972
+
dists.value(0)
973
+
);
974
+
}
975
+
976
+
/// Projection pushdown: only requested columns are returned.
977
+
#[tokio::test]
978
+
asyncfnudtf_vector_search_vector_projection(){
979
+
let ctx = make_exec_ctx("conn::schema::items::vector").await;
980
+
let sql = "SELECT id, _distance FROM vector_search_vector('conn.schema.items', 'vector', ARRAY[1.0::float, 0.0::float, 0.0::float, 0.0::float], 2)";
981
+
let df = ctx.sql(sql).await.expect("sql");
982
+
let batches = df.collect().await.expect("collect");
983
+
assert_eq!(
984
+
batches[0].num_columns(),
985
+
2,
986
+
"expected 2 columns (id, _distance), got {}",
987
+
batches[0].num_columns()
988
+
);
989
+
let schema = batches[0].schema();
990
+
let col_names:Vec<&str> = schema.fields().iter().map(|f| f.name().as_str()).collect();
991
+
assert_eq!(col_names, vec!["id","_distance"]);
992
+
}
993
+
994
+
/// parse_dot_table_ref error: fewer than 3 parts.
995
+
#[tokio::test]
996
+
asyncfnudtf_vector_search_vector_bad_table_ref(){
997
+
let ctx = make_exec_ctx("conn::schema::items::vector").await;
998
+
let sql = "SELECT * FROM vector_search_vector('items', 'vector', ARRAY[1.0::float, 0.0::float, 0.0::float, 0.0::float], 3)";
999
+
let err = ctx.sql(sql).await.unwrap_err();
1000
+
let msg = err.to_string();
1001
+
assert!(
1002
+
msg.contains("connection.schema.table"),
1003
+
"expected table ref format error, got: {msg}"
1004
+
);
1005
+
}
1006
+
1007
+
/// Registry miss: column not in registry returns clear error.
1008
+
#[tokio::test]
1009
+
asyncfnudtf_vector_search_vector_registry_miss(){
1010
+
let ctx = make_exec_ctx("conn::schema::items::vector").await;
1011
+
let sql = "SELECT * FROM vector_search_vector('conn.schema.items', 'nonexistent', ARRAY[1.0::float, 0.0::float, 0.0::float, 0.0::float], 3)";
1012
+
let err = ctx.sql(sql).await.unwrap_err();
1013
+
let msg = err.to_string();
1014
+
assert!(
1015
+
msg.contains("no loaded vector index"),
1016
+
"expected registry miss error, got: {msg}"
1017
+
);
1018
+
}
1019
+
1020
+
/// Empty result: search with k larger than dataset returns all rows.
0 commit comments