tantivy, datafusion and embedded psql are now separate features
This commit is contained in:
@@ -4,6 +4,10 @@ version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[features]
|
||||
default = []
|
||||
tantivy = ["dep:tantivy"]
|
||||
|
||||
[dependencies]
|
||||
prost-types = { workspace = true }
|
||||
rust_decimal = { workspace = true }
|
||||
@@ -14,7 +18,7 @@ prost = "0.14.4"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
|
||||
# Search
|
||||
tantivy = { workspace = true }
|
||||
tantivy = { workspace = true, optional = true }
|
||||
serde_json.workspace = true
|
||||
tonic-prost = "0.14.6"
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// common/src/lib.rs
|
||||
|
||||
#[cfg_attr(not(feature = "tantivy"), path = "search_light.rs")]
|
||||
pub mod search;
|
||||
pub mod decimal;
|
||||
pub mod grpc_error;
|
||||
|
||||
108
common/src/search_light.rs
Normal file
108
common/src/search_light.rs
Normal file
@@ -0,0 +1,108 @@
|
||||
//! Search constants and dependency-free helpers available without Tantivy.
|
||||
|
||||
pub const F_PG_ID: &str = "pg_id";
|
||||
pub const F_ROW_REVISION: &str = "row_revision";
|
||||
pub const F_IS_ARCHIVED: &str = "is_archived";
|
||||
pub const F_TABLE_DEFINITION_ID: &str = "table_definition_id";
|
||||
pub const F_VERSION_NUMBER: &str = "version_number";
|
||||
pub const F_TABLE_NAME: &str = "table_name";
|
||||
pub const F_ROW_KEY: &str = "row_key";
|
||||
pub const F_ALL_TEXT: &str = "all_text";
|
||||
pub const F_DATA_WORD: &str = "data_word";
|
||||
pub const F_DATA_NGRAM: &str = "data_ngram";
|
||||
pub const F_DATA_EXACT: &str = "data_exact";
|
||||
pub const JOURNAL_TABLE_NAME: &str = "general_ledger";
|
||||
pub const ARCHIVED_ROW_KEY_PREFIX: &str = "__archive__:";
|
||||
pub const SEARCH_INDEX_FORMAT_DIRECTORY: &str = "v4";
|
||||
|
||||
pub fn search_row_key(table_name: &str, row_id: i64) -> String {
|
||||
format!("{table_name}:{row_id}")
|
||||
}
|
||||
|
||||
pub fn archived_search_row_key(
|
||||
table_definition_id: i64,
|
||||
row_id: i64,
|
||||
version_number: i64,
|
||||
) -> String {
|
||||
format!("{ARCHIVED_ROW_KEY_PREFIX}{table_definition_id}:{row_id}:{version_number}")
|
||||
}
|
||||
|
||||
pub fn parse_archived_search_row_key(row_key: &str) -> Option<(i64, i64, i64)> {
|
||||
let encoded = row_key.strip_prefix(ARCHIVED_ROW_KEY_PREFIX)?;
|
||||
let mut parts = encoded.split(':');
|
||||
let table_definition_id = parts.next()?.parse().ok()?;
|
||||
let row_id = parts.next()?.parse().ok()?;
|
||||
let version_number = parts.next()?.parse().ok()?;
|
||||
if parts.next().is_some() {
|
||||
return None;
|
||||
}
|
||||
Some((table_definition_id, row_id, version_number))
|
||||
}
|
||||
|
||||
pub fn canonical_exact_search_value(input: &str, field_type: &str) -> Result<String, String> {
|
||||
let normalized_type = field_type.trim().to_ascii_lowercase();
|
||||
if matches!(normalized_type.as_str(), "numeric" | "money")
|
||||
|| normalized_type.starts_with("decimal(")
|
||||
{
|
||||
return input
|
||||
.parse::<rust_decimal::Decimal>()
|
||||
.map(|value| value.normalize().to_string())
|
||||
.map_err(|error| format!("Exact numeric search value is invalid: {error}"));
|
||||
}
|
||||
if matches!(normalized_type.as_str(), "int" | "bigint") || normalized_type.starts_with("link(")
|
||||
{
|
||||
return input
|
||||
.parse::<i64>()
|
||||
.map(|value| value.to_string())
|
||||
.map_err(|error| format!("Exact integer search value is invalid: {error}"));
|
||||
}
|
||||
Ok(input.to_string())
|
||||
}
|
||||
|
||||
pub fn canonical_search_number(input: &str) -> String {
|
||||
input
|
||||
.parse::<rust_decimal::Decimal>()
|
||||
.map(|value| value.normalize().to_string())
|
||||
.unwrap_or_else(|_| input.to_string())
|
||||
}
|
||||
|
||||
pub fn normalize_column_name(column: &str) -> String {
|
||||
column.to_ascii_lowercase()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
archived_search_row_key, canonical_exact_search_value, parse_archived_search_row_key,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn archived_row_key_round_trips_stable_identity() {
|
||||
let key = archived_search_row_key(42, 7, 3);
|
||||
assert_eq!(parse_archived_search_row_key(&key), Some((42, 7, 3)));
|
||||
assert_eq!(parse_archived_search_row_key("customers:7"), None);
|
||||
assert_eq!(parse_archived_search_row_key("__archive__:42:7"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exact_scalar_values_follow_catalog_field_types() {
|
||||
assert_eq!(canonical_exact_search_value("001", "int").unwrap(), "1");
|
||||
assert_eq!(canonical_exact_search_value("001", "bigint").unwrap(), "1");
|
||||
assert_eq!(
|
||||
canonical_exact_search_value("001", "link(adresar)").unwrap(),
|
||||
"1"
|
||||
);
|
||||
assert_eq!(
|
||||
canonical_exact_search_value("10.50", "numeric").unwrap(),
|
||||
"10.5"
|
||||
);
|
||||
assert_eq!(
|
||||
canonical_exact_search_value("10.50", "money").unwrap(),
|
||||
"10.5"
|
||||
);
|
||||
assert_eq!(
|
||||
canonical_exact_search_value("10.50", "decimal(12, 2)").unwrap(),
|
||||
"10.5"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,6 @@ tonic = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
tantivy = { workspace = true }
|
||||
|
||||
common = { path = "../common" }
|
||||
common = { path = "../common", features = ["tantivy"] }
|
||||
tonic-reflection = "0.14.6"
|
||||
sqlx = { version = "0.9.0", features = ["postgres"] }
|
||||
|
||||
2
server
2
server
Submodule server updated: 8454f4dc20...276b4d5ca1
Reference in New Issue
Block a user