feat(manticore): add Manticore Search support
Add Manticore Search table data editing, structure editing, metadata handling, and SQL completion support.
This commit is contained in:
1 parent
93d2e7dc18
commit
f385386284
34 files changed
+1250
-130
No files matched your search
@@ -252,7 +252,10 @@ pub fn build_data_grid_copy_update_statements(options: DataGridCopyUpdateStateme
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(" AND ");
|
||||
statements.push(format!("UPDATE {table} SET {sets} WHERE {where_clause};"));
|
||||
statements.push(data_grid_statement(
|
||||
options.database_type,
|
||||
format!("UPDATE {table} SET {sets} WHERE {where_clause}"),
|
||||
));
|
||||
}
|
||||
statements
|
||||
}
|
||||
@@ -528,7 +531,10 @@ fn build_data_grid_save_statements(options: &DataGridSaveStatementOptions) -> Ve
|
||||
row,
|
||||
column_info,
|
||||
);
|
||||
statements.push(format!("UPDATE {table} SET {sets} WHERE {where_clause};"));
|
||||
statements.push(data_grid_statement(
|
||||
options.database_type,
|
||||
format!("UPDATE {table} SET {sets} WHERE {where_clause}"),
|
||||
));
|
||||
}
|
||||
|
||||
for row_index in &options.deleted_rows {
|
||||
@@ -542,7 +548,8 @@ fn build_data_grid_save_statements(options: &DataGridSaveStatementOptions) -> Ve
|
||||
row,
|
||||
column_info,
|
||||
);
|
||||
statements.push(format!("DELETE FROM {table} WHERE {where_clause};"));
|
||||
statements
|
||||
.push(data_grid_statement(options.database_type, format!("DELETE FROM {table} WHERE {where_clause}")));
|
||||
}
|
||||
|
||||
for row in &options.new_rows {
|
||||
@@ -568,7 +575,10 @@ fn build_data_grid_save_statements(options: &DataGridSaveStatementOptions) -> Ve
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
statements.push(format!("INSERT INTO {table} ({columns}) VALUES ({values});"));
|
||||
statements.push(data_grid_statement(
|
||||
options.database_type,
|
||||
format!("INSERT INTO {table} ({columns}) VALUES ({values})"),
|
||||
));
|
||||
}
|
||||
|
||||
statements
|
||||
@@ -591,7 +601,8 @@ fn build_data_grid_rollback_statements(options: &DataGridSaveStatementOptions) -
|
||||
for row in &options.new_rows {
|
||||
let where_clause = build_row_where(options.database_type, &save_columns, row, column_info);
|
||||
if !where_clause.is_empty() {
|
||||
statements.push(format!("DELETE FROM {table} WHERE {where_clause};"));
|
||||
statements
|
||||
.push(data_grid_statement(options.database_type, format!("DELETE FROM {table} WHERE {where_clause}")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -617,7 +628,10 @@ fn build_data_grid_rollback_statements(options: &DataGridSaveStatementOptions) -
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
statements.push(format!("INSERT INTO {table} ({columns}) VALUES ({values});"));
|
||||
statements.push(data_grid_statement(
|
||||
options.database_type,
|
||||
format!("INSERT INTO {table} ({columns}) VALUES ({values})"),
|
||||
));
|
||||
}
|
||||
|
||||
for (row_index, changes) in &options.dirty_rows {
|
||||
@@ -668,9 +682,12 @@ fn build_data_grid_rollback_statements(options: &DataGridSaveStatementOptions) -
|
||||
predicates.extend(writable_changes.iter().map(|((_, value), column)| {
|
||||
build_column_predicate(options.database_type, column, value, column_info_for(column_info, column))
|
||||
}));
|
||||
statements.push(format!(
|
||||
"UPDATE {table} SET {sets} WHERE {};",
|
||||
predicates.into_iter().filter(|part| !part.is_empty()).collect::<Vec<_>>().join(" AND ")
|
||||
statements.push(data_grid_statement(
|
||||
options.database_type,
|
||||
format!(
|
||||
"UPDATE {table} SET {sets} WHERE {}",
|
||||
predicates.into_iter().filter(|part| !part.is_empty()).collect::<Vec<_>>().join(" AND ")
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -749,6 +766,11 @@ pub fn format_grid_sql_literal(
|
||||
return format_pg_array_sql_literal(arr);
|
||||
}
|
||||
let text = value.as_str().map_or_else(|| value.to_string(), ToString::to_string);
|
||||
if database_type == Some(DatabaseType::ManticoreSearch) {
|
||||
if let Some(typed_value) = manticore_typed_attribute_value(&text, column_info) {
|
||||
return format_grid_sql_literal(&typed_value, database_type, column_info);
|
||||
}
|
||||
}
|
||||
if text.is_empty() {
|
||||
return if database_type == Some(DatabaseType::SqlServer) { "N''" } else { "''" }.to_string();
|
||||
}
|
||||
@@ -779,6 +801,20 @@ fn is_bit_column_type(data_type: &str) -> bool {
|
||||
lower.split(|ch: char| !ch.is_ascii_alphanumeric()).any(|token| token == "bit")
|
||||
}
|
||||
|
||||
fn manticore_typed_attribute_value(text: &str, column_info: Option<&DataGridColumnInfo>) -> Option<Value> {
|
||||
let data_type = column_info?.data_type.to_ascii_lowercase();
|
||||
if is_boolean_type(&data_type) && text.eq_ignore_ascii_case("true") {
|
||||
return Some(Value::Bool(true));
|
||||
}
|
||||
if is_boolean_type(&data_type) && text.eq_ignore_ascii_case("false") {
|
||||
return Some(Value::Bool(false));
|
||||
}
|
||||
if is_numeric_type(&data_type) && is_numeric_literal(text) {
|
||||
return text.parse::<serde_json::Number>().ok().map(Value::Number);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn format_mysql_bit_literal_text(text: &str) -> Option<String> {
|
||||
let trimmed = text.trim();
|
||||
if trimmed.eq_ignore_ascii_case("true") {
|
||||
@@ -1032,6 +1068,14 @@ fn build_column_predicate(
|
||||
}
|
||||
}
|
||||
|
||||
fn data_grid_statement(database_type: Option<DatabaseType>, sql: String) -> String {
|
||||
if database_type == Some(DatabaseType::ManticoreSearch) {
|
||||
sql
|
||||
} else {
|
||||
format!("{sql};")
|
||||
}
|
||||
}
|
||||
|
||||
fn uses_mysql_binary_text_predicate(
|
||||
database_type: Option<DatabaseType>,
|
||||
value: &Value,
|
||||
@@ -1250,6 +1294,7 @@ fn uses_keyless_row_predicate(database_type: Option<DatabaseType>) -> bool {
|
||||
database_type,
|
||||
Some(
|
||||
DatabaseType::Mysql
|
||||
| DatabaseType::ManticoreSearch
|
||||
| DatabaseType::Postgres
|
||||
| DatabaseType::Sqlite
|
||||
| DatabaseType::DuckDb
|
||||
@@ -1568,6 +1613,35 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prepares_manticore_save_statements_without_trailing_semicolons() {
|
||||
let result = prepare_data_grid_save(DataGridSaveStatementOptions {
|
||||
database_type: Some(DatabaseType::ManticoreSearch),
|
||||
table_meta: DataGridTableMeta {
|
||||
schema: None,
|
||||
table_name: "rt_products".to_string(),
|
||||
primary_keys: vec![],
|
||||
columns: Some(vec![column("id", "bigint", false, None), column("title", "text", true, None)]),
|
||||
},
|
||||
columns: vec!["id".to_string(), "title".to_string()],
|
||||
source_columns: None,
|
||||
rows: vec![vec![json!("1"), json!("old")], vec![json!("2"), json!("deleted")]],
|
||||
dirty_rows: vec![(0, vec![(1, json!("new"))])],
|
||||
deleted_rows: vec![1],
|
||||
new_rows: vec![vec![json!("3"), json!("inserted")]],
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
result.statements,
|
||||
vec![
|
||||
"UPDATE `rt_products` SET `title` = 'new' WHERE `id` = 1 AND `title` = 'old'",
|
||||
"DELETE FROM `rt_products` WHERE `id` = 2 AND `title` = 'deleted'",
|
||||
"INSERT INTO `rt_products` (`id`, `title`) VALUES (3, 'inserted')",
|
||||
]
|
||||
);
|
||||
assert!(result.rollback_statements.iter().all(|statement| !statement.ends_with(';')));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validates_duplicate_inserted_primary_keys() {
|
||||
let result = prepare_data_grid_save(DataGridSaveStatementOptions {
|
||||
|
||||
Reference in new issue
Block a user