添加 Manticore Search 支持 (#1145)
* 添加 Manticore Search 支持 * 更新 Manticore Search 文档
This commit is contained in:
1 parent
6c57169162
commit
799d20a2cf
34 files changed
+258
-49
No files matched your search
@@ -358,7 +358,7 @@ impl AppState {
|
||||
.await?;
|
||||
PoolKind::Mysql(pool, mode)
|
||||
}
|
||||
DatabaseType::Doris | DatabaseType::StarRocks | DatabaseType::Databend => {
|
||||
DatabaseType::Doris | DatabaseType::StarRocks | DatabaseType::ManticoreSearch | DatabaseType::Databend => {
|
||||
let pool = if database.is_none() {
|
||||
connect_bare_metadata_pool(&db_config, &host, port, connect_timeout, mysql_pool_max_connections)
|
||||
.await?
|
||||
|
||||
@@ -29,8 +29,12 @@ impl MySqlQueryDialect {
|
||||
pub fn for_connection(db_type: DatabaseType, driver_profile: Option<&str>) -> Self {
|
||||
let profile = driver_profile.map(str::to_ascii_lowercase);
|
||||
Self {
|
||||
supports_admin_show_results: matches!(db_type, DatabaseType::Doris | DatabaseType::StarRocks)
|
||||
|| profile.as_deref().is_some_and(|profile| matches!(profile, "doris" | "selectdb" | "starrocks")),
|
||||
supports_admin_show_results: matches!(
|
||||
db_type,
|
||||
DatabaseType::Doris | DatabaseType::StarRocks | DatabaseType::ManticoreSearch
|
||||
) || profile
|
||||
.as_deref()
|
||||
.is_some_and(|profile| matches!(profile, "doris" | "selectdb" | "starrocks" | "manticoresearch")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +240,8 @@ pub enum DatabaseType {
|
||||
Doris,
|
||||
#[serde(rename = "starrocks")]
|
||||
StarRocks,
|
||||
#[serde(rename = "manticoresearch")]
|
||||
ManticoreSearch,
|
||||
Databend,
|
||||
Redshift,
|
||||
Dameng,
|
||||
@@ -593,12 +595,10 @@ impl ConnectionConfig {
|
||||
}
|
||||
|
||||
pub fn needs_bare_mysql(&self) -> bool {
|
||||
matches!(self.db_type, DatabaseType::Doris | DatabaseType::StarRocks)
|
||||
|| self
|
||||
.driver_profile
|
||||
.as_deref()
|
||||
.map(|p| p.to_lowercase())
|
||||
.is_some_and(|p| matches!(p.as_str(), "doris" | "starrocks" | "selectdb" | "oceanbase"))
|
||||
matches!(self.db_type, DatabaseType::Doris | DatabaseType::StarRocks | DatabaseType::ManticoreSearch)
|
||||
|| self.driver_profile.as_deref().map(|p| p.to_lowercase()).is_some_and(|p| {
|
||||
matches!(p.as_str(), "doris" | "starrocks" | "manticoresearch" | "selectdb" | "oceanbase")
|
||||
})
|
||||
}
|
||||
|
||||
pub fn canonicalized(&self) -> Self {
|
||||
@@ -656,7 +656,11 @@ impl ConnectionConfig {
|
||||
let fragment = self.redis_tls_insecure_fragment();
|
||||
format!("{scheme}://{host}:{port}/{fragment}")
|
||||
}
|
||||
DatabaseType::Mysql | DatabaseType::Doris | DatabaseType::StarRocks | DatabaseType::Databend => {
|
||||
DatabaseType::Mysql
|
||||
| DatabaseType::Doris
|
||||
| DatabaseType::StarRocks
|
||||
| DatabaseType::ManticoreSearch
|
||||
| DatabaseType::Databend => {
|
||||
let suffix = if params.is_empty() { String::new() } else { format!("?{params}") };
|
||||
format!("mysql://{host}:{port}{db_part}{suffix}")
|
||||
}
|
||||
@@ -777,7 +781,11 @@ impl ConnectionConfig {
|
||||
format!("{scheme}://{username}:{password}@{host}:{port}/{fragment}")
|
||||
}
|
||||
}
|
||||
DatabaseType::Mysql | DatabaseType::Doris | DatabaseType::StarRocks | DatabaseType::Databend => {
|
||||
DatabaseType::Mysql
|
||||
| DatabaseType::Doris
|
||||
| DatabaseType::StarRocks
|
||||
| DatabaseType::ManticoreSearch
|
||||
| DatabaseType::Databend => {
|
||||
let suffix = if params.is_empty() { String::new() } else { format!("?{params}") };
|
||||
format!("mysql://{}:{}@{host}:{port}{db_part}{suffix}", username, password)
|
||||
}
|
||||
@@ -958,7 +966,7 @@ impl ConnectionConfig {
|
||||
DatabaseType::Mysql => {
|
||||
normalize_mysql_url_params(value, self.mysql_uses_tls(), self.ca_cert_path.trim().is_empty())
|
||||
}
|
||||
DatabaseType::Doris | DatabaseType::StarRocks | DatabaseType::Databend => {
|
||||
DatabaseType::Doris | DatabaseType::StarRocks | DatabaseType::ManticoreSearch | DatabaseType::Databend => {
|
||||
normalize_bare_mysql_url_params(value)
|
||||
}
|
||||
DatabaseType::Postgres | DatabaseType::Redshift => normalize_postgres_url_params(value, self.ssl),
|
||||
|
||||
@@ -319,7 +319,9 @@ async fn list_databases_once(state: &AppState, connection_id: &str) -> Result<Ve
|
||||
|
||||
match pool {
|
||||
PoolKind::Mysql(p, _) if db_config.as_ref().is_some_and(is_doris_family_config) => {
|
||||
db::mysql::list_databases_show(p).await
|
||||
db::mysql::list_databases_show(p)
|
||||
.await
|
||||
.map(|databases| filter_mysql_system_databases_for_config(databases, db_config.as_ref()))
|
||||
}
|
||||
PoolKind::Mysql(p, mode) => dispatch_mysql!(p, mode, db::mysql::list_databases, db::ob_oracle::list_databases),
|
||||
PoolKind::Postgres(p) => db::postgres::list_databases(p).await,
|
||||
@@ -599,8 +601,8 @@ fn filter_table_infos(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
clickhouse_metadata_database, deduplicate_column_infos, filter_table_infos,
|
||||
is_agent_postgres_metadata_fallback_config,
|
||||
clickhouse_metadata_database, deduplicate_column_infos, filter_mysql_system_databases_for_config,
|
||||
filter_table_infos, is_agent_postgres_metadata_fallback_config,
|
||||
};
|
||||
#[cfg(feature = "duckdb-bundled")]
|
||||
use super::{duckdb_attach_database, duckdb_list_databases, duckdb_query_tables_in_database};
|
||||
@@ -675,6 +677,39 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn test_database_info(name: &str) -> super::db::DatabaseInfo {
|
||||
super::db::DatabaseInfo { name: name.to_string() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn manticoresearch_database_list_filters_mysql_system_databases() {
|
||||
let databases = vec![
|
||||
test_database_info("Manticore"),
|
||||
test_database_info("information_schema"),
|
||||
test_database_info("mysql"),
|
||||
test_database_info("performance_schema"),
|
||||
test_database_info("sys"),
|
||||
];
|
||||
let config = test_connection_config(DatabaseType::ManticoreSearch);
|
||||
|
||||
let filtered = filter_mysql_system_databases_for_config(databases, Some(&config));
|
||||
|
||||
assert_eq!(filtered.into_iter().map(|database| database.name).collect::<Vec<_>>(), vec!["Manticore"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn doris_database_list_keeps_system_databases() {
|
||||
let databases = vec![test_database_info("information_schema"), test_database_info("analytics")];
|
||||
let config = test_connection_config(DatabaseType::Doris);
|
||||
|
||||
let filtered = filter_mysql_system_databases_for_config(databases, Some(&config));
|
||||
|
||||
assert_eq!(
|
||||
filtered.into_iter().map(|database| database.name).collect::<Vec<_>>(),
|
||||
vec!["information_schema", "analytics"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filter_table_infos_applies_filter_offset_and_limit() {
|
||||
let tables = vec![
|
||||
@@ -1469,8 +1504,28 @@ fn is_opengauss_family_config(config: &ConnectionConfig) -> bool {
|
||||
}
|
||||
|
||||
fn is_doris_family_config(config: &ConnectionConfig) -> bool {
|
||||
matches!(config.db_type, DatabaseType::Doris | DatabaseType::StarRocks)
|
||||
|| matches!(config.driver_profile.as_deref(), Some("doris" | "selectdb" | "starrocks"))
|
||||
matches!(config.db_type, DatabaseType::Doris | DatabaseType::StarRocks | DatabaseType::ManticoreSearch)
|
||||
|| matches!(config.driver_profile.as_deref(), Some("doris" | "selectdb" | "starrocks" | "manticoresearch"))
|
||||
}
|
||||
|
||||
fn is_manticoresearch_config(config: &ConnectionConfig) -> bool {
|
||||
matches!(config.db_type, DatabaseType::ManticoreSearch)
|
||||
|| matches!(config.driver_profile.as_deref(), Some("manticoresearch"))
|
||||
}
|
||||
|
||||
fn filter_mysql_system_databases_for_config(
|
||||
databases: Vec<db::DatabaseInfo>,
|
||||
config: Option<&ConnectionConfig>,
|
||||
) -> Vec<db::DatabaseInfo> {
|
||||
if !config.is_some_and(is_manticoresearch_config) {
|
||||
return databases;
|
||||
}
|
||||
|
||||
databases.into_iter().filter(|database| !is_mysql_system_database(&database.name)).collect()
|
||||
}
|
||||
|
||||
fn is_mysql_system_database(name: &str) -> bool {
|
||||
matches!(name.to_ascii_lowercase().as_str(), "information_schema" | "mysql" | "performance_schema" | "sys")
|
||||
}
|
||||
|
||||
fn sql_string(value: &str) -> String {
|
||||
|
||||
@@ -7,7 +7,9 @@ pub(in crate::schema) async fn list_databases(
|
||||
config: Option<&ConnectionConfig>,
|
||||
) -> Result<Vec<db::DatabaseInfo>, String> {
|
||||
match pool {
|
||||
PoolKind::Mysql(p, _) if config.is_some_and(is_doris_family_config) => db::mysql::list_databases_show(p).await,
|
||||
PoolKind::Mysql(p, _) if config.is_some_and(is_doris_family_config) => db::mysql::list_databases_show(p)
|
||||
.await
|
||||
.map(|databases| filter_mysql_system_databases_for_config(databases, config)),
|
||||
PoolKind::Mysql(p, mode) if *mode == MysqlMode::OceanBaseOracle => db::ob_oracle::list_databases(p).await,
|
||||
PoolKind::Mysql(p, _) => db::mysql::list_databases(p).await,
|
||||
PoolKind::Postgres(p) => db::postgres::list_databases(p).await,
|
||||
@@ -262,6 +264,26 @@ fn is_opengauss_family_config(config: &ConnectionConfig) -> bool {
|
||||
}
|
||||
|
||||
fn is_doris_family_config(config: &ConnectionConfig) -> bool {
|
||||
matches!(config.db_type, DatabaseType::Doris | DatabaseType::StarRocks)
|
||||
|| matches!(config.driver_profile.as_deref(), Some("doris" | "selectdb" | "starrocks"))
|
||||
matches!(config.db_type, DatabaseType::Doris | DatabaseType::StarRocks | DatabaseType::ManticoreSearch)
|
||||
|| matches!(config.driver_profile.as_deref(), Some("doris" | "selectdb" | "starrocks" | "manticoresearch"))
|
||||
}
|
||||
|
||||
fn is_manticoresearch_config(config: &ConnectionConfig) -> bool {
|
||||
matches!(config.db_type, DatabaseType::ManticoreSearch)
|
||||
|| matches!(config.driver_profile.as_deref(), Some("manticoresearch"))
|
||||
}
|
||||
|
||||
fn filter_mysql_system_databases_for_config(
|
||||
databases: Vec<db::DatabaseInfo>,
|
||||
config: Option<&ConnectionConfig>,
|
||||
) -> Vec<db::DatabaseInfo> {
|
||||
if !config.is_some_and(is_manticoresearch_config) {
|
||||
return databases;
|
||||
}
|
||||
|
||||
databases.into_iter().filter(|database| !is_mysql_system_database(&database.name)).collect()
|
||||
}
|
||||
|
||||
fn is_mysql_system_database(name: &str) -> bool {
|
||||
matches!(name.to_ascii_lowercase().as_str(), "information_schema" | "mysql" | "performance_schema" | "sys")
|
||||
}
|
||||
@@ -64,7 +64,11 @@ impl SqlParsingOptions {
|
||||
Self {
|
||||
supports_hash_line_comments: matches!(
|
||||
db_type,
|
||||
DatabaseType::Mysql | DatabaseType::Doris | DatabaseType::StarRocks | DatabaseType::Goldendb
|
||||
DatabaseType::Mysql
|
||||
| DatabaseType::Doris
|
||||
| DatabaseType::StarRocks
|
||||
| DatabaseType::ManticoreSearch
|
||||
| DatabaseType::Goldendb
|
||||
),
|
||||
supports_oracle_plsql_blocks: matches!(
|
||||
db_type,
|
||||
@@ -1203,13 +1207,27 @@ fn executable_sql_keyword_matches(token: &str, keyword: &str) -> bool {
|
||||
}
|
||||
|
||||
fn is_mysql_compatible_import_target(db_type: &DatabaseType, driver_profile: Option<&str>) -> bool {
|
||||
matches!(db_type, DatabaseType::Mysql | DatabaseType::Doris | DatabaseType::StarRocks | DatabaseType::Goldendb)
|
||||
|| driver_profile.map(|profile| profile.to_ascii_lowercase()).is_some_and(|profile| {
|
||||
matches!(
|
||||
profile.as_str(),
|
||||
"mariadb" | "tidb" | "oceanbase" | "custom_mysql" | "doris" | "starrocks" | "selectdb" | "goldendb"
|
||||
)
|
||||
})
|
||||
matches!(
|
||||
db_type,
|
||||
DatabaseType::Mysql
|
||||
| DatabaseType::Doris
|
||||
| DatabaseType::StarRocks
|
||||
| DatabaseType::ManticoreSearch
|
||||
| DatabaseType::Goldendb
|
||||
) || driver_profile.map(|profile| profile.to_ascii_lowercase()).is_some_and(|profile| {
|
||||
matches!(
|
||||
profile.as_str(),
|
||||
"mariadb"
|
||||
| "tidb"
|
||||
| "oceanbase"
|
||||
| "custom_mysql"
|
||||
| "doris"
|
||||
| "starrocks"
|
||||
| "manticoresearch"
|
||||
| "selectdb"
|
||||
| "goldendb"
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn mysql_executable_comment_body(statement: &str) -> Option<&str> {
|
||||
|
||||
@@ -91,7 +91,7 @@ fn starts_with_duckdb_parser_gap_sql(sql: &str) -> bool {
|
||||
fn normalize_dialect(dialect: Option<&str>) -> String {
|
||||
match dialect.unwrap_or("generic").to_ascii_lowercase().as_str() {
|
||||
"postgres" | "postgresql" | "redshift" | "opengauss" | "gaussdb" | "highgo" => "postgres".to_string(),
|
||||
"mysql" | "mariadb" | "doris" | "starrocks" | "oceanbase" => "mysql".to_string(),
|
||||
"mysql" | "mariadb" | "doris" | "starrocks" | "manticoresearch" | "oceanbase" => "mysql".to_string(),
|
||||
"sqlite" => "sqlite".to_string(),
|
||||
"sqlserver" | "mssql" => "sqlserver".to_string(),
|
||||
"clickhouse" => "clickhouse".to_string(),
|
||||
|
||||
@@ -36,6 +36,7 @@ pub fn quote_table_identifier(database_type: Option<DatabaseType>, name: &str) -
|
||||
DatabaseType::Mysql
|
||||
| DatabaseType::Goldendb
|
||||
| DatabaseType::StarRocks
|
||||
| DatabaseType::ManticoreSearch
|
||||
| DatabaseType::Hive
|
||||
| DatabaseType::Databend
|
||||
| DatabaseType::Tdengine
|
||||
|
||||
@@ -34,7 +34,7 @@ impl std::fmt::Display for SqlRisk {
|
||||
fn normalize_dialect(dialect: &str) -> &'static str {
|
||||
match dialect.to_ascii_lowercase().as_str() {
|
||||
"postgres" | "postgresql" | "redshift" | "opengauss" | "gaussdb" | "highgo" => "postgres",
|
||||
"mysql" | "mariadb" | "doris" | "starrocks" | "oceanbase" => "mysql",
|
||||
"mysql" | "mariadb" | "doris" | "starrocks" | "manticoresearch" | "oceanbase" => "mysql",
|
||||
"sqlite" => "sqlite",
|
||||
"sqlserver" | "mssql" => "sqlserver",
|
||||
"clickhouse" => "clickhouse",
|
||||
|
||||
Reference in new issue
Block a user