multirow reference in the client
This commit is contained in:
@@ -504,14 +504,14 @@ async fn table_physical_to_display_map(
|
||||
Ok(mapping)
|
||||
}
|
||||
|
||||
async fn table_row_display_column(
|
||||
async fn table_row_display_columns(
|
||||
pool: &PgPool,
|
||||
profile_name: &str,
|
||||
table_name: &str,
|
||||
) -> Result<String, Status> {
|
||||
) -> Result<Vec<String>, Status> {
|
||||
sqlx::query_scalar(
|
||||
r#"
|
||||
SELECT td.row_display_column
|
||||
SELECT td.row_display_columns
|
||||
FROM schemas s
|
||||
JOIN table_definitions td ON td.schema_id = s.id
|
||||
WHERE s.name = $1 AND td.table_name = $2
|
||||
@@ -521,7 +521,7 @@ async fn table_row_display_column(
|
||||
.bind(table_name)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.map_err(|e| Status::internal(format!("Row display column lookup failed: {}", e)))
|
||||
.map_err(|e| Status::internal(format!("Row display columns lookup failed: {}", e)))
|
||||
}
|
||||
|
||||
fn remap_json_to_display_names(
|
||||
@@ -541,13 +541,18 @@ fn remap_json_to_display_names(
|
||||
}
|
||||
}
|
||||
|
||||
fn row_display_value(value: &serde_json::Value, column: &str) -> String {
|
||||
match value.get(column) {
|
||||
Some(serde_json::Value::String(value)) => value.clone(),
|
||||
Some(serde_json::Value::Number(value)) => value.to_string(),
|
||||
Some(serde_json::Value::Bool(value)) => value.to_string(),
|
||||
_ => String::new(),
|
||||
}
|
||||
/// One value per display column, positionally aligned with them, so a column
|
||||
/// that is NULL for this row stays visible as an empty slot.
|
||||
fn row_display_values(value: &serde_json::Value, columns: &[String]) -> Vec<String> {
|
||||
columns
|
||||
.iter()
|
||||
.map(|column| match value.get(column) {
|
||||
Some(serde_json::Value::String(value)) => value.clone(),
|
||||
Some(serde_json::Value::Number(value)) => value.to_string(),
|
||||
Some(serde_json::Value::Bool(value)) => value.to_string(),
|
||||
_ => String::new(),
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
enum ResolvedOrderColumn {
|
||||
@@ -573,8 +578,14 @@ async fn resolve_order_column(
|
||||
return Ok(ResolvedOrderColumn::Position);
|
||||
}
|
||||
|
||||
let requested_column = if requested_column.eq_ignore_ascii_case("row_display_column") {
|
||||
table_row_display_column(pool, profile_name, table_name).await?
|
||||
// Sorting by "the display column" means the first one: it is the part
|
||||
// callers read left to right. A table with none sorts by id instead.
|
||||
let requested_column = if requested_column.eq_ignore_ascii_case("row_display_columns") {
|
||||
table_row_display_columns(pool, profile_name, table_name)
|
||||
.await?
|
||||
.into_iter()
|
||||
.next()
|
||||
.unwrap_or_else(|| "id".to_string())
|
||||
} else {
|
||||
requested_column.to_string()
|
||||
};
|
||||
@@ -661,7 +672,7 @@ async fn fetch_ordered_rows(
|
||||
offset: usize,
|
||||
) -> Result<Vec<Hit>, Status> {
|
||||
let physical_to_display = table_physical_to_display_map(pool, profile_name, table_name).await?;
|
||||
let display_column = table_row_display_column(pool, profile_name, table_name).await?;
|
||||
let display_columns = table_row_display_columns(pool, profile_name, table_name).await?;
|
||||
let (resolved_order, direction) = match order {
|
||||
Some(order) => (
|
||||
resolve_order_column(pool, profile_name, table_name, &order.column).await?,
|
||||
@@ -694,14 +705,14 @@ async fn fetch_ordered_rows(
|
||||
let json_data: serde_json::Value = row.try_get("data").unwrap_or_default();
|
||||
let position: i64 = row.try_get("picker_position").unwrap_or_default();
|
||||
let json_data = remap_json_to_display_names(json_data, &physical_to_display);
|
||||
let row_display_value = row_display_value(&json_data, &display_column);
|
||||
let row_display_values = row_display_values(&json_data, &display_columns);
|
||||
Hit {
|
||||
id,
|
||||
score: 0.0,
|
||||
content_json: json_data.to_string(),
|
||||
table_name: table_name.to_string(),
|
||||
row_display_value,
|
||||
row_display_column: display_column.clone(),
|
||||
row_display_values,
|
||||
row_display_columns: display_columns.clone(),
|
||||
position: u64::try_from(position).ok(),
|
||||
}
|
||||
})
|
||||
@@ -810,12 +821,13 @@ async fn run_search(
|
||||
.push(*pg_id);
|
||||
}
|
||||
|
||||
let mut content_map: HashMap<(String, i64), (String, String, String)> = HashMap::new();
|
||||
let mut content_map: HashMap<(String, i64), (String, Vec<String>, Vec<String>)> =
|
||||
HashMap::new();
|
||||
for (table_name, pg_ids) in ids_by_table {
|
||||
validate_identifier(&table_name, "table_name")?;
|
||||
let physical_to_display =
|
||||
table_physical_to_display_map(pool, profile_name, &table_name).await?;
|
||||
let display_column = table_row_display_column(pool, profile_name, &table_name).await?;
|
||||
let display_columns = table_row_display_columns(pool, profile_name, &table_name).await?;
|
||||
let sql = format!(
|
||||
"SELECT id, to_jsonb(t) AS data FROM {} t WHERE deleted = FALSE AND id = ANY($1)",
|
||||
qualify_profile_table(profile_name, &table_name)
|
||||
@@ -830,10 +842,10 @@ async fn run_search(
|
||||
let id: i64 = row.try_get("id").unwrap_or_default();
|
||||
let json_data: serde_json::Value = row.try_get("data").unwrap_or_default();
|
||||
let json_data = remap_json_to_display_names(json_data, &physical_to_display);
|
||||
let display_value = row_display_value(&json_data, &display_column);
|
||||
let display_values = row_display_values(&json_data, &display_columns);
|
||||
content_map.insert(
|
||||
(table_name.clone(), id),
|
||||
(json_data.to_string(), display_value, display_column.clone()),
|
||||
(json_data.to_string(), display_values, display_columns.clone()),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -843,13 +855,13 @@ async fn run_search(
|
||||
.filter_map(|(score, pg_id, table_name)| {
|
||||
content_map
|
||||
.get(&(table_name.clone(), pg_id))
|
||||
.map(|(content_json, row_display_value, row_display_column)| Hit {
|
||||
.map(|(content_json, row_display_values, row_display_columns)| Hit {
|
||||
id: pg_id,
|
||||
score,
|
||||
content_json: content_json.clone(),
|
||||
table_name,
|
||||
row_display_value: row_display_value.clone(),
|
||||
row_display_column: row_display_column.clone(),
|
||||
row_display_values: row_display_values.clone(),
|
||||
row_display_columns: row_display_columns.clone(),
|
||||
position: None,
|
||||
})
|
||||
})
|
||||
@@ -866,7 +878,7 @@ async fn fetch_ordered_candidate_rows(
|
||||
offset: usize,
|
||||
) -> Result<Vec<Hit>, Status> {
|
||||
let physical_to_display = table_physical_to_display_map(pool, profile_name, table_name).await?;
|
||||
let display_column = table_row_display_column(pool, profile_name, table_name).await?;
|
||||
let display_columns = table_row_display_columns(pool, profile_name, table_name).await?;
|
||||
let resolved_order =
|
||||
resolve_order_column(pool, profile_name, table_name, &order.column).await?;
|
||||
let sql = format!(
|
||||
@@ -919,14 +931,14 @@ async fn fetch_ordered_candidate_rows(
|
||||
let position: i64 = row.try_get("picker_position").unwrap_or_default();
|
||||
let score: f32 = row.try_get("candidate_score").unwrap_or_default();
|
||||
let json_data = remap_json_to_display_names(json_data, &physical_to_display);
|
||||
let display_value = row_display_value(&json_data, &display_column);
|
||||
let display_values = row_display_values(&json_data, &display_columns);
|
||||
Hit {
|
||||
id,
|
||||
score,
|
||||
content_json: json_data.to_string(),
|
||||
table_name: table_name.to_string(),
|
||||
row_display_value: display_value,
|
||||
row_display_column: display_column.clone(),
|
||||
row_display_values: display_values,
|
||||
row_display_columns: display_columns.clone(),
|
||||
position: u64::try_from(position).ok(),
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user