1 parent
48f4fac89e
commit
bd7ed63468
5 files changed
+63
-27
No files matched your search
@@ -154,6 +154,24 @@ pub fn quote_table_identifier(database_type: Option<DatabaseType>, name: &str) -
|
||||
}
|
||||
}
|
||||
|
||||
/// Quote an IRIS identifier only when its spelling requires a delimited name.
|
||||
///
|
||||
/// Caché/IRIS installations may disable delimited identifiers. The IRIS JDBC
|
||||
/// preparser turns quoted names into `:%qpar(...)` parameters in that mode,
|
||||
/// which is not valid in table references. Ordinary metadata names are
|
||||
/// case-insensitive and can be sent unquoted; names containing separators or
|
||||
/// other punctuation still need the identifier quote character.
|
||||
pub(crate) fn quote_iris_identifier(name: &str, identifier_quote: Option<&str>) -> String {
|
||||
let mut chars = name.chars();
|
||||
let ordinary = chars.next().is_some_and(|first| first == '_' || first == '%' || first.is_alphabetic())
|
||||
&& chars.all(|ch| ch == '_' || ch.is_alphanumeric());
|
||||
if ordinary {
|
||||
return name.to_string();
|
||||
}
|
||||
let quote = identifier_quote.map(str::trim).filter(|quote| !quote.is_empty()).unwrap_or("\"");
|
||||
format!("{quote}{}{quote}", name.replace(quote, &format!("{quote}{quote}")))
|
||||
}
|
||||
|
||||
pub(crate) fn quote_gaussdb_jdbc_identifier(name: &str, identifier_quote: &str) -> String {
|
||||
if is_explicitly_quoted_identifier(name) {
|
||||
return name.to_string();
|
||||
|
||||
@@ -5,7 +5,7 @@ use super::capabilities::{
|
||||
};
|
||||
use super::identifiers::{
|
||||
normalize_where_input, qualified_table_name, qualified_table_name_with_catalog, quote_gaussdb_jdbc_identifier,
|
||||
quote_table_identifier,
|
||||
quote_iris_identifier, quote_table_identifier,
|
||||
};
|
||||
use super::types::{
|
||||
TableDataSelectSqlOptions, TableSelectSqlOptions, DBX_NEO4J_ELEMENT_ID_COLUMN, DBX_ROWID_COLUMN,
|
||||
@@ -209,6 +209,8 @@ pub fn build_table_data_select_sql_with_database(
|
||||
let table = if let Some(database) = jdbc_tdengine_database {
|
||||
qualified_table_name(Some(DatabaseType::Tdengine), Some(database), &options.table_name)
|
||||
// Doris / StarRocks multi-catalog: prefix the catalog for external-catalog tables.
|
||||
} else if database_type == Some(DatabaseType::Iris) {
|
||||
table_data_qualified_table_name(database_type, schema, &options.table_name, options.identifier_quote.as_deref())
|
||||
} else if uses_connection_identifier_quote(database_type, options.identifier_quote.as_deref()) {
|
||||
table_data_qualified_table_name(database_type, schema, &options.table_name, options.identifier_quote.as_deref())
|
||||
} else if include_database_name {
|
||||
@@ -416,6 +418,14 @@ pub(crate) fn table_data_qualified_table_name(
|
||||
table_name: &str,
|
||||
identifier_quote: Option<&str>,
|
||||
) -> String {
|
||||
if database_type == Some(DatabaseType::Iris) {
|
||||
let table = quote_iris_identifier(table_name, identifier_quote);
|
||||
return schema
|
||||
.map(str::trim)
|
||||
.filter(|schema| !schema.is_empty())
|
||||
.map(|schema| format!("{}.{table}", quote_iris_identifier(schema, identifier_quote)))
|
||||
.unwrap_or(table);
|
||||
}
|
||||
if !uses_connection_identifier_quote(database_type, identifier_quote) {
|
||||
return qualified_table_name(database_type, schema, table_name);
|
||||
}
|
||||
@@ -475,7 +485,17 @@ pub fn build_table_select_sql(options: TableSelectSqlOptions<'_>) -> String {
|
||||
if database_type == Some(DatabaseType::VictoriaMetrics) {
|
||||
return format!("{}[1h]", victoriametrics_metric_selector(options.table_name));
|
||||
}
|
||||
let table = qualified_table_name(database_type, options.schema, options.table_name);
|
||||
let table = if database_type == Some(DatabaseType::Iris) {
|
||||
let table = quote_iris_identifier(options.table_name, None);
|
||||
options
|
||||
.schema
|
||||
.map(str::trim)
|
||||
.filter(|schema| !schema.is_empty())
|
||||
.map(|schema| format!("{}.{table}", quote_iris_identifier(schema, None)))
|
||||
.unwrap_or(table)
|
||||
} else {
|
||||
qualified_table_name(database_type, options.schema, options.table_name)
|
||||
};
|
||||
let select_columns = quoted_table_columns_or_star(database_type, options.columns);
|
||||
let order_by = if options.order_columns.is_empty() {
|
||||
String::new()
|
||||
|
||||
@@ -321,7 +321,7 @@ fn builds_select_sql_with_limit_syntax_for_database_type() {
|
||||
order_columns: &[],
|
||||
limit: 100,
|
||||
}),
|
||||
"SELECT TOP 100 * FROM \"Ens\".\"AlarmResponse\""
|
||||
"SELECT TOP 100 * FROM Ens.AlarmResponse"
|
||||
);
|
||||
assert_eq!(
|
||||
build_table_select_sql(TableSelectSqlOptions {
|
||||
@@ -778,7 +778,7 @@ fn builds_table_data_where_and_schema_queries() {
|
||||
include_row_id: false,
|
||||
..Default::default()
|
||||
}),
|
||||
"SELECT TOP 100 * FROM \"Ens\".\"AlarmResponse\""
|
||||
"SELECT TOP 100 * FROM Ens.AlarmResponse"
|
||||
);
|
||||
assert_eq!(
|
||||
build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
@@ -797,7 +797,7 @@ fn builds_table_data_where_and_schema_queries() {
|
||||
include_row_id: false,
|
||||
..Default::default()
|
||||
}),
|
||||
"SELECT * FROM \"Ens\".\"AlarmResponse\" WHERE (Status = 'Open') ORDER BY \"ID\" ASC"
|
||||
"SELECT * FROM Ens.AlarmResponse WHERE (Status = 'Open') ORDER BY \"ID\" ASC"
|
||||
);
|
||||
assert_eq!(
|
||||
build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
@@ -1078,7 +1078,7 @@ fn explicit_table_data_order_is_preserved() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_iris_table_data_sql_with_literal_top_and_quoted_object() {
|
||||
fn builds_iris_table_data_sql_with_literal_top_and_ordinary_object() {
|
||||
let sql = build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
database_type: Some(DatabaseType::Iris),
|
||||
schema: Some("Ens".to_string()),
|
||||
@@ -1095,15 +1095,25 @@ fn builds_iris_table_data_sql_with_literal_top_and_quoted_object() {
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
sql,
|
||||
"SELECT TOP 25 * FROM \"Ens\".\"AlarmResponse\" WHERE (\"Status\" = 'Open') ORDER BY \"Status\" DESC"
|
||||
);
|
||||
assert_eq!(sql, "SELECT TOP 25 * FROM Ens.AlarmResponse WHERE (\"Status\" = 'Open') ORDER BY \"Status\" DESC");
|
||||
assert!(!sql.contains("?"));
|
||||
assert!(!sql.contains(":%qpar"));
|
||||
assert!(!sql.contains(" LIMIT "));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iris_table_data_sql_quotes_only_delimited_object_names() {
|
||||
let sql = build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
database_type: Some(DatabaseType::Iris),
|
||||
schema: Some("App Schema".to_string()),
|
||||
table_name: "Patient Record".to_string(),
|
||||
limit: Some(25),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
assert_eq!(sql, "SELECT TOP 25 * FROM \"App Schema\".\"Patient Record\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_table_data_special_column_queries() {
|
||||
assert_eq!(
|
||||
|
||||
Reference in new issue
Block a user