accounting as table defined
This commit is contained in:
2
client
2
client
Submodule client updated: e40a195581...2465eb9ca9
@@ -171,6 +171,9 @@ message ProfileTreeResponse {
|
|||||||
|
|
||||||
// Column whose value is used as the human-readable row label.
|
// Column whose value is used as the human-readable row label.
|
||||||
string row_display_column = 4;
|
string row_display_column = 4;
|
||||||
|
|
||||||
|
// "dynamic" for user-defined tables, "system" for backend-managed tables.
|
||||||
|
string table_kind = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Profile (schema) entry.
|
// Profile (schema) entry.
|
||||||
@@ -247,6 +250,7 @@ message TableDetail {
|
|||||||
string base_currency = 5;
|
string base_currency = 5;
|
||||||
string row_display_column = 6;
|
string row_display_column = 6;
|
||||||
map<string, ColumnBehavior> column_behaviors = 7;
|
map<string, ColumnBehavior> column_behaviors = 7;
|
||||||
|
string table_kind = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server-owned behavior for one logical column returned in table details.
|
// Server-owned behavior for one logical column returned in table details.
|
||||||
|
|||||||
Binary file not shown.
@@ -143,6 +143,9 @@ pub mod profile_tree_response {
|
|||||||
/// Column whose value is used as the human-readable row label.
|
/// Column whose value is used as the human-readable row label.
|
||||||
#[prost(string, tag = "4")]
|
#[prost(string, tag = "4")]
|
||||||
pub row_display_column: ::prost::alloc::string::String,
|
pub row_display_column: ::prost::alloc::string::String,
|
||||||
|
/// "dynamic" for user-defined tables, "system" for backend-managed tables.
|
||||||
|
#[prost(string, tag = "5")]
|
||||||
|
pub table_kind: ::prost::alloc::string::String,
|
||||||
}
|
}
|
||||||
/// Profile (schema) entry.
|
/// Profile (schema) entry.
|
||||||
#[derive(Clone, PartialEq, ::prost::Message)]
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
@@ -252,6 +255,8 @@ pub struct TableDetail {
|
|||||||
::prost::alloc::string::String,
|
::prost::alloc::string::String,
|
||||||
ColumnBehavior,
|
ColumnBehavior,
|
||||||
>,
|
>,
|
||||||
|
#[prost(string, tag = "8")]
|
||||||
|
pub table_kind: ::prost::alloc::string::String,
|
||||||
}
|
}
|
||||||
/// Server-owned behavior for one logical column returned in table details.
|
/// Server-owned behavior for one logical column returned in table details.
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ pub const F_ALL_TEXT: &str = "all_text";
|
|||||||
pub const F_DATA_WORD: &str = "data_word";
|
pub const F_DATA_WORD: &str = "data_word";
|
||||||
pub const F_DATA_NGRAM: &str = "data_ngram";
|
pub const F_DATA_NGRAM: &str = "data_ngram";
|
||||||
pub const F_DATA_EXACT: &str = "data_exact";
|
pub const F_DATA_EXACT: &str = "data_exact";
|
||||||
pub const JOURNAL_SEARCH_TABLE_NAME: &str = "journal_entries";
|
pub const JOURNAL_TABLE_NAME: &str = "journal_entries";
|
||||||
|
|
||||||
pub const TOK_WORD: &str = "kw_word";
|
pub const TOK_WORD: &str = "kw_word";
|
||||||
pub const TOK_NGRAM: &str = "kw_ngram";
|
pub const TOK_NGRAM: &str = "kw_ngram";
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ pub use common::proto::komp_ac::search::searcher_server::SearcherServer;
|
|||||||
use common::proto::komp_ac::search::{
|
use common::proto::komp_ac::search::{
|
||||||
SearchOrderDirection, SearchRequest, SearchResponse, search_response::Hit,
|
SearchOrderDirection, SearchRequest, SearchResponse, search_response::Hit,
|
||||||
};
|
};
|
||||||
use common::search::{
|
use common::search::{SchemaFields, register_tokenizers, search_index_path};
|
||||||
JOURNAL_SEARCH_TABLE_NAME, SchemaFields, register_tokenizers, search_index_path,
|
|
||||||
};
|
|
||||||
use query_builder::{
|
use query_builder::{
|
||||||
ConstraintMode, SearchConstraint, SearchConstraintTarget, build_master_query,
|
ConstraintMode, SearchConstraint, SearchConstraintTarget, build_master_query,
|
||||||
};
|
};
|
||||||
@@ -273,10 +271,6 @@ async fn profile_exists(pool: &PgPool, profile_name: &str) -> Result<bool, Statu
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn table_exists(pool: &PgPool, profile_name: &str, table_name: &str) -> Result<bool, Status> {
|
async fn table_exists(pool: &PgPool, profile_name: &str, table_name: &str) -> Result<bool, Status> {
|
||||||
if table_name == JOURNAL_SEARCH_TABLE_NAME {
|
|
||||||
return profile_exists(pool, profile_name).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
let exists = sqlx::query_scalar::<_, bool>(
|
let exists = sqlx::query_scalar::<_, bool>(
|
||||||
r#"
|
r#"
|
||||||
SELECT EXISTS(
|
SELECT EXISTS(
|
||||||
@@ -481,10 +475,6 @@ async fn table_physical_to_display_map(
|
|||||||
profile_name: &str,
|
profile_name: &str,
|
||||||
table_name: &str,
|
table_name: &str,
|
||||||
) -> Result<HashMap<String, String>, Status> {
|
) -> Result<HashMap<String, String>, Status> {
|
||||||
if table_name == JOURNAL_SEARCH_TABLE_NAME {
|
|
||||||
return Ok(HashMap::new());
|
|
||||||
}
|
|
||||||
|
|
||||||
let rows = sqlx::query(
|
let rows = sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
SELECT tdc.physical_name, tdc.display_name
|
SELECT tdc.physical_name, tdc.display_name
|
||||||
@@ -519,10 +509,6 @@ async fn table_row_display_column(
|
|||||||
profile_name: &str,
|
profile_name: &str,
|
||||||
table_name: &str,
|
table_name: &str,
|
||||||
) -> Result<String, Status> {
|
) -> Result<String, Status> {
|
||||||
if table_name == JOURNAL_SEARCH_TABLE_NAME {
|
|
||||||
return Ok("journal_name".to_string());
|
|
||||||
}
|
|
||||||
|
|
||||||
sqlx::query_scalar(
|
sqlx::query_scalar(
|
||||||
r#"
|
r#"
|
||||||
SELECT td.row_display_column
|
SELECT td.row_display_column
|
||||||
@@ -674,15 +660,6 @@ async fn fetch_ordered_rows(
|
|||||||
limit: usize,
|
limit: usize,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
) -> Result<Vec<Hit>, Status> {
|
) -> Result<Vec<Hit>, Status> {
|
||||||
if table_name == JOURNAL_SEARCH_TABLE_NAME {
|
|
||||||
if order.is_some() {
|
|
||||||
return Err(Status::invalid_argument(
|
|
||||||
"Explicit ordering is not supported for journal search",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return fetch_journal_rows(pool, profile_name, limit, offset).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
let physical_to_display = table_physical_to_display_map(pool, profile_name, table_name).await?;
|
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_column = table_row_display_column(pool, profile_name, table_name).await?;
|
||||||
let (resolved_order, direction) = match order {
|
let (resolved_order, direction) = match order {
|
||||||
@@ -731,53 +708,6 @@ async fn fetch_ordered_rows(
|
|||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn fetch_journal_rows(
|
|
||||||
pool: &PgPool,
|
|
||||||
profile_name: &str,
|
|
||||||
limit: usize,
|
|
||||||
offset: usize,
|
|
||||||
) -> Result<Vec<Hit>, Status> {
|
|
||||||
let rows = sqlx::query(
|
|
||||||
r#"WITH positioned AS (
|
|
||||||
SELECT journal.*,
|
|
||||||
ROW_NUMBER() OVER (ORDER BY journal.id) AS picker_position
|
|
||||||
FROM journal_entries journal
|
|
||||||
JOIN schemas schema_meta ON schema_meta.id = journal.schema_id
|
|
||||||
WHERE schema_meta.name = $1
|
|
||||||
)
|
|
||||||
SELECT id,
|
|
||||||
to_jsonb(positioned) - 'schema_id' - 'picker_position' AS data,
|
|
||||||
picker_position
|
|
||||||
FROM positioned
|
|
||||||
ORDER BY picker_position DESC
|
|
||||||
LIMIT $2 OFFSET $3"#,
|
|
||||||
)
|
|
||||||
.bind(profile_name)
|
|
||||||
.bind(limit as i64)
|
|
||||||
.bind(offset as i64)
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await
|
|
||||||
.map_err(|error| Status::internal(format!("Journal list query failed: {}", error)))?;
|
|
||||||
|
|
||||||
Ok(rows
|
|
||||||
.into_iter()
|
|
||||||
.map(|row| {
|
|
||||||
let id: i64 = row.try_get("id").unwrap_or_default();
|
|
||||||
let json_data: serde_json::Value = row.try_get("data").unwrap_or_default();
|
|
||||||
let position: i64 = row.try_get("picker_position").unwrap_or_default();
|
|
||||||
Hit {
|
|
||||||
id,
|
|
||||||
score: 0.0,
|
|
||||||
row_display_value: row_display_value(&json_data, "journal_name"),
|
|
||||||
content_json: json_data.to_string(),
|
|
||||||
table_name: JOURNAL_SEARCH_TABLE_NAME.to_string(),
|
|
||||||
row_display_column: "journal_name".to_string(),
|
|
||||||
position: u64::try_from(position).ok(),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn run_search(
|
async fn run_search(
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
profile: &ProfileIndex,
|
profile: &ProfileIndex,
|
||||||
@@ -860,11 +790,6 @@ async fn run_search(
|
|||||||
|
|
||||||
if let Some(order) = order {
|
if let Some(order) = order {
|
||||||
let table_name = table_filter.expect("ordered searches require a normalized table filter");
|
let table_name = table_filter.expect("ordered searches require a normalized table filter");
|
||||||
if table_name == JOURNAL_SEARCH_TABLE_NAME {
|
|
||||||
return Err(Status::invalid_argument(
|
|
||||||
"Explicit ordering is not supported for journal search",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return fetch_ordered_candidate_rows(
|
return fetch_ordered_candidate_rows(
|
||||||
pool,
|
pool,
|
||||||
profile_name,
|
profile_name,
|
||||||
@@ -891,27 +816,14 @@ async fn run_search(
|
|||||||
let physical_to_display =
|
let physical_to_display =
|
||||||
table_physical_to_display_map(pool, profile_name, &table_name).await?;
|
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_column = table_row_display_column(pool, profile_name, &table_name).await?;
|
||||||
let rows = if table_name == JOURNAL_SEARCH_TABLE_NAME {
|
let sql = format!(
|
||||||
sqlx::query(
|
"SELECT id, to_jsonb(t) AS data FROM {} t WHERE deleted = FALSE AND id = ANY($1)",
|
||||||
r#"SELECT journal.id, to_jsonb(journal) - 'schema_id' AS data
|
qualify_profile_table(profile_name, &table_name)
|
||||||
FROM journal_entries journal
|
);
|
||||||
JOIN schemas schema_meta ON schema_meta.id = journal.schema_id
|
let rows = sqlx::query(AssertSqlSafe(sql))
|
||||||
WHERE schema_meta.name = $1 AND journal.id = ANY($2)"#,
|
|
||||||
)
|
|
||||||
.bind(profile_name)
|
|
||||||
.bind(&pg_ids)
|
.bind(&pg_ids)
|
||||||
.fetch_all(pool)
|
.fetch_all(pool)
|
||||||
.await
|
.await
|
||||||
} else {
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
sqlx::query(AssertSqlSafe(sql))
|
|
||||||
.bind(&pg_ids)
|
|
||||||
.fetch_all(pool)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
.map_err(|e| Status::internal(format!("Database query failed: {}", e)))?;
|
.map_err(|e| Status::internal(format!("Database query failed: {}", e)))?;
|
||||||
|
|
||||||
for row in rows {
|
for row in rows {
|
||||||
|
|||||||
2
server
2
server
Submodule server updated: 9e7a186a0a...9fa56738c5
Submodule tui-canvas updated: 8e143805fd...2a1849fb95
Submodule tui-pages updated: cfce2e590b...76e6d5688f
Reference in New Issue
Block a user