fix(rust): fix update, open_table, fts search in remote client (#1785)

* `open_table` uses `POST` not `GET`
* `update` uses `predicate` key not `only_if`
* For FTS search, vector cannot be omitted. It must be passed as empty.
* Added logging of JSON request bodies to debug level logging.
This commit is contained in:
Will Jones
2024-11-04 08:27:55 -08:00
committed by GitHub
parent 15ed7f75a0
commit 059c9794b5
3 changed files with 31 additions and 10 deletions
+16 -1
View File
@@ -341,7 +341,22 @@ impl<S: HttpSend> RestfulLanceDbClient<S> {
request_id
};
debug!("Sending request_id={}: {:?}", request_id, &request);
if log::log_enabled!(log::Level::Debug) {
let content_type = request
.headers()
.get("content-type")
.map(|v| v.to_str().unwrap());
if content_type == Some("application/json") {
let body = request.body().as_ref().unwrap().as_bytes().unwrap();
let body = String::from_utf8_lossy(body);
debug!(
"Sending request_id={}: {:?} with body {}",
request_id, request, body
);
} else {
debug!("Sending request_id={}: {:?}", request_id, request);
}
}
if with_retry {
self.send_with_retry_impl(client, request, request_id).await
+2 -2
View File
@@ -161,7 +161,7 @@ impl<S: HttpSend> ConnectionInternal for RemoteDatabase<S> {
if self.table_cache.get(&options.name).is_none() {
let req = self
.client
.get(&format!("/v1/table/{}/describe/", options.name));
.post(&format!("/v1/table/{}/describe/", options.name));
let (request_id, resp) = self.client.send(req, true).await?;
if resp.status() == StatusCode::NOT_FOUND {
return Err(crate::Error::TableNotFound { name: options.name });
@@ -301,7 +301,7 @@ mod tests {
#[tokio::test]
async fn test_open_table() {
let conn = Connection::new_with_handler(|request| {
assert_eq!(request.method(), &reqwest::Method::GET);
assert_eq!(request.method(), &reqwest::Method::POST);
assert_eq!(request.url().path(), "/v1/table/table1/describe/");
assert_eq!(request.url().query(), None);
+13 -7
View File
@@ -310,8 +310,8 @@ impl<S: HttpSend> TableInternal for RemoteTable<S> {
body["nprobes"] = query.nprobes.into();
body["refine_factor"] = query.refine_factor.into();
if let Some(vector) = query.query_vector.as_ref() {
let vector: Vec<f32> = match vector.data_type() {
let vector: Vec<f32> = if let Some(vector) = query.query_vector.as_ref() {
match vector.data_type() {
DataType::Float32 => vector
.as_any()
.downcast_ref::<arrow_array::Float32Array>()
@@ -325,9 +325,12 @@ impl<S: HttpSend> TableInternal for RemoteTable<S> {
message: "VectorQuery vector must be of type Float32".into(),
})
}
};
body["vector"] = serde_json::json!(vector);
}
}
} else {
// Server takes empty vector, not null or undefined.
Vec::new()
};
body["vector"] = serde_json::json!(vector);
if let Some(vector_column) = query.column.as_ref() {
body["vector_column"] = serde_json::Value::String(vector_column.clone());
@@ -358,6 +361,8 @@ impl<S: HttpSend> TableInternal for RemoteTable<S> {
let mut body = serde_json::Value::Object(Default::default());
Self::apply_query_params(&mut body, query)?;
// Empty vector can be passed if no vector search is performed.
body["vector"] = serde_json::Value::Array(Vec::new());
let request = request.json(&body);
@@ -379,7 +384,7 @@ impl<S: HttpSend> TableInternal for RemoteTable<S> {
let request = request.json(&serde_json::json!({
"updates": updates,
"only_if": update.filter,
"predicate": update.filter,
}));
let (request_id, response) = self.client.send(request, false).await?;
@@ -933,7 +938,7 @@ mod tests {
assert_eq!(col_name, "b");
assert_eq!(expression, "b - 1");
let only_if = value.get("only_if").unwrap().as_str().unwrap();
let only_if = value.get("predicate").unwrap().as_str().unwrap();
assert_eq!(only_if, "b > 10");
}
@@ -1167,6 +1172,7 @@ mod tests {
"query": "hello world",
},
"k": 10,
"vector": [],
});
assert_eq!(body, expected_body);