fix(sqlserver): support legacy index metadata
This commit is contained in:
parent
c4b21cf666
commit
5babaea219
|
|
@ -1835,8 +1835,14 @@ fn sqlserver_columns_sql(schema: &str, table: &str) -> String {
|
|||
|
||||
pub async fn list_indexes(client: &mut SqlServerClient, schema: &str, table: &str) -> Result<Vec<IndexInfo>, String> {
|
||||
let sql = sqlserver_indexes_sql(schema, table);
|
||||
let stream = client.query(&*sql, &[]).await.map_err(|e| e.to_string())?;
|
||||
let rows = stream.into_first_result().await.map_err(|e| e.to_string())?;
|
||||
let rows = match sqlserver_index_rows(client, &sql).await {
|
||||
Ok(rows) => rows,
|
||||
Err(error) if sqlserver_filter_definition_missing(&error) => {
|
||||
let legacy_sql = sqlserver_legacy_indexes_sql(schema, table);
|
||||
sqlserver_index_rows(client, &legacy_sql).await.map_err(|error| error.to_string())?
|
||||
}
|
||||
Err(error) => return Err(error.to_string()),
|
||||
};
|
||||
Ok(rows
|
||||
.iter()
|
||||
.map(|row| {
|
||||
|
|
@ -1860,7 +1866,32 @@ pub async fn list_indexes(client: &mut SqlServerClient, schema: &str, table: &st
|
|||
.collect())
|
||||
}
|
||||
|
||||
async fn sqlserver_index_rows(client: &mut SqlServerClient, sql: &str) -> Result<Vec<Row>, tiberius::error::Error> {
|
||||
client.query(sql, &[]).await?.into_first_result().await
|
||||
}
|
||||
|
||||
fn sqlserver_filter_definition_missing(error: &tiberius::error::Error) -> bool {
|
||||
sqlserver_filter_definition_error(error.code(), &error.to_string())
|
||||
}
|
||||
|
||||
fn sqlserver_filter_definition_error(code: Option<u32>, message: &str) -> bool {
|
||||
code == Some(207) && message.to_ascii_lowercase().contains("filter_definition")
|
||||
}
|
||||
|
||||
fn sqlserver_indexes_sql(schema: &str, table: &str) -> String {
|
||||
sqlserver_indexes_sql_with_filter_definition(schema, table, true)
|
||||
}
|
||||
|
||||
fn sqlserver_legacy_indexes_sql(schema: &str, table: &str) -> String {
|
||||
sqlserver_indexes_sql_with_filter_definition(schema, table, false)
|
||||
}
|
||||
|
||||
fn sqlserver_indexes_sql_with_filter_definition(schema: &str, table: &str, include_filter_definition: bool) -> String {
|
||||
let filter_definition = if include_filter_definition {
|
||||
"i.filter_definition"
|
||||
} else {
|
||||
"CAST(NULL AS NVARCHAR(MAX)) AS filter_definition"
|
||||
};
|
||||
format!(
|
||||
"SELECT i.name, \
|
||||
STUFF((SELECT ',' + c2.name \
|
||||
|
|
@ -1876,7 +1907,7 @@ fn sqlserver_indexes_sql(schema: &str, table: &str) -> String {
|
|||
WHERE ic3.object_id = i.object_id AND ic3.index_id = i.index_id AND ic3.is_included_column = 1 \
|
||||
ORDER BY ic3.index_column_id \
|
||||
FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '') AS included_cols, \
|
||||
i.filter_definition, \
|
||||
{filter_definition}, \
|
||||
ep.value AS index_comment \
|
||||
FROM sys.indexes i \
|
||||
OUTER APPLY (SELECT CAST(ep.value AS NVARCHAR(MAX)) AS value FROM sys.extended_properties ep WHERE ep.major_id = i.object_id AND ep.minor_id = i.index_id AND ep.name = N'MS_Description' AND ep.class = 7) ep \
|
||||
|
|
@ -2298,11 +2329,11 @@ mod tests {
|
|||
is_blocking_sqlserver_unsafe_probe_error, is_sqlserver_spatial_column, is_sqlserver_variant_column,
|
||||
query_result_with_server_messages, requires_simple_query_batch, sqlserver_batch_can_use_execute,
|
||||
sqlserver_cell_to_json, sqlserver_columns_sql, sqlserver_completion_assistant_sql,
|
||||
sqlserver_dml_output_returns_rows, sqlserver_hidden_schema_names, sqlserver_indexes_sql,
|
||||
sqlserver_legacy_probe, sqlserver_list_objects_sql, sqlserver_list_schemas_sql, sqlserver_list_tables_sql,
|
||||
sqlserver_schema_name_predicate, sqlserver_table_comment_sql, sqlserver_visible_object_predicate,
|
||||
strip_dbx_sqlserver_row_number_column, SqlServerDescribedColumn, SqlServerResultSet,
|
||||
SQLSERVER_RESULT_TYPE_PROBE_SQL,
|
||||
sqlserver_dml_output_returns_rows, sqlserver_filter_definition_error, sqlserver_hidden_schema_names,
|
||||
sqlserver_indexes_sql, sqlserver_legacy_indexes_sql, sqlserver_legacy_probe, sqlserver_list_objects_sql,
|
||||
sqlserver_list_schemas_sql, sqlserver_list_tables_sql, sqlserver_schema_name_predicate,
|
||||
sqlserver_table_comment_sql, sqlserver_visible_object_predicate, strip_dbx_sqlserver_row_number_column,
|
||||
SqlServerDescribedColumn, SqlServerResultSet, SQLSERVER_RESULT_TYPE_PROBE_SQL,
|
||||
};
|
||||
use crate::types::{
|
||||
CompletionAssistantMatchMode, CompletionAssistantObjectKind, CompletionAssistantRequest, QueryResult,
|
||||
|
|
@ -2636,6 +2667,35 @@ mod tests {
|
|||
assert!(sql.contains("MS_Description"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sqlserver_legacy_indexes_sql_omits_filtered_index_metadata() {
|
||||
let sql = sqlserver_legacy_indexes_sql("dbo", "orders");
|
||||
|
||||
assert!(!sql.contains("i.filter_definition"));
|
||||
assert!(sql.contains("CAST(NULL AS NVARCHAR(MAX)) AS filter_definition"));
|
||||
assert!(sql.contains("ep.value AS index_comment"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sqlserver_filter_definition_fallback_requires_column_error_207() {
|
||||
assert!(sqlserver_filter_definition_error(
|
||||
Some(207),
|
||||
"Token error: Column name 'filter_definition' is invalid. (code: 207)"
|
||||
));
|
||||
assert!(sqlserver_filter_definition_error(
|
||||
Some(207),
|
||||
"Token error: 列名 'filter_definition' 无效。 (code: 207)"
|
||||
));
|
||||
assert!(!sqlserver_filter_definition_error(
|
||||
Some(207),
|
||||
"Token error: Column name 'other_column' is invalid. (code: 207)"
|
||||
));
|
||||
assert!(!sqlserver_filter_definition_error(
|
||||
Some(229),
|
||||
"Token error: SELECT permission denied for filter_definition. (code: 229)"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sqlserver_columns_sql_reads_column_comment_by_column_id() {
|
||||
let sql = sqlserver_columns_sql("dbo", "orders");
|
||||
|
|
|
|||
Loading…
Reference in New Issue