fix(data): align table preview ordering
This commit is contained in:
1 parent
752a695018
commit
2f2fc36b18
6 files changed
+160
-117
No files matched your search
@@ -21,30 +21,9 @@ pub fn build_table_data_select_sql(options: TableDataSelectSqlOptions) -> String
|
||||
let table = qualified_table_name(database_type, options.schema.as_deref(), &options.table_name);
|
||||
let predicate = normalize_where_input(options.where_input.as_deref());
|
||||
let where_clause = if predicate.is_empty() { String::new() } else { format!(" WHERE ({predicate})") };
|
||||
let row_id_alias =
|
||||
if options.include_row_id && database_type == Some(DatabaseType::Oracle) { Some("t") } else { None };
|
||||
let default_order_alias = if database_type == Some(DatabaseType::Jdbc) { None } else { row_id_alias };
|
||||
let default_order_by = if database_type == Some(DatabaseType::InfluxDb) {
|
||||
// InfluxQL only allows sorting of timestamp column
|
||||
Some("time DESC".to_string())
|
||||
} else if !options.primary_keys.is_empty() {
|
||||
Some(
|
||||
options
|
||||
.primary_keys
|
||||
.iter()
|
||||
.map(|pk| format!("{} ASC", quote_order_identifier(database_type, pk, default_order_alias)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
)
|
||||
} else if !options.fallback_order_columns.is_empty() {
|
||||
Some(
|
||||
options
|
||||
.fallback_order_columns
|
||||
.iter()
|
||||
.map(|column| format!("{} ASC", quote_table_identifier(database_type, column)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -193,29 +172,10 @@ fn build_rownum_table_select_sql(
|
||||
format!("SELECT {select_columns} FROM ({inner_select}) WHERE ROWNUM <= {limit}")
|
||||
}
|
||||
|
||||
pub(super) fn is_oracle_row_id(database_type: Option<DatabaseType>, name: &str) -> bool {
|
||||
database_type == Some(DatabaseType::Oracle) && name.eq_ignore_ascii_case(DBX_ROWID_COLUMN)
|
||||
}
|
||||
|
||||
pub(super) fn is_tdengine_tbname(database_type: Option<DatabaseType>, name: &str) -> bool {
|
||||
database_type == Some(DatabaseType::Tdengine) && name.eq_ignore_ascii_case(DBX_TDENGINE_TBNAME_COLUMN)
|
||||
}
|
||||
|
||||
pub(super) fn quote_order_identifier(
|
||||
database_type: Option<DatabaseType>,
|
||||
name: &str,
|
||||
table_alias: Option<&str>,
|
||||
) -> String {
|
||||
if is_oracle_row_id(database_type, name) {
|
||||
return table_alias.map(|alias| format!("{alias}.ROWID")).unwrap_or_else(|| "ROWID".to_string());
|
||||
}
|
||||
if is_tdengine_tbname(database_type, name) {
|
||||
return DBX_TDENGINE_TBNAME_COLUMN.to_string();
|
||||
}
|
||||
let quoted = quote_table_identifier(database_type, name);
|
||||
table_alias.map(|alias| format!("{alias}.{quoted}")).unwrap_or(quoted)
|
||||
}
|
||||
|
||||
pub(super) fn build_select_columns(database_type: Option<DatabaseType>, columns: &[String]) -> String {
|
||||
if columns.is_empty() {
|
||||
return "*".to_string();
|
||||
@@ -338,19 +298,7 @@ pub(super) fn build_neo4j_table_select_sql(options: &TableDataSelectSqlOptions,
|
||||
"elementId(n) AS {}, {returned_columns}",
|
||||
quote_table_identifier(Some(DatabaseType::Neo4j), DBX_NEO4J_ELEMENT_ID_COLUMN)
|
||||
);
|
||||
let default_order_by = if options.primary_keys.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
options
|
||||
.primary_keys
|
||||
.iter()
|
||||
.map(|pk| format!("n.{} ASC", quote_table_identifier(Some(DatabaseType::Neo4j), pk)))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
)
|
||||
};
|
||||
let order_by = options.order_by.as_deref().filter(|order| !order.trim().is_empty()).or(default_order_by.as_deref());
|
||||
let order_by = options.order_by.as_deref().filter(|order| !order.trim().is_empty());
|
||||
let order = order_by.map(|order_by| format!(" ORDER BY {order_by}")).unwrap_or_default();
|
||||
let skip = options.offset.filter(|offset| *offset > 0).map(|offset| format!(" SKIP {offset}")).unwrap_or_default();
|
||||
format!("MATCH (n:{label}){where_clause} RETURN {returns}{order}{skip} LIMIT {limit};")
|
||||
|
||||
@@ -221,7 +221,7 @@ fn builds_table_data_where_and_schema_queries() {
|
||||
where_input: Some("where status = 'active'".to_string()),
|
||||
include_row_id: false,
|
||||
}),
|
||||
"SELECT * FROM `users` WHERE (status = 'active') ORDER BY `id` ASC LIMIT 100;"
|
||||
"SELECT * FROM `users` WHERE (status = 'active') LIMIT 100;"
|
||||
);
|
||||
assert_eq!(
|
||||
build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
@@ -333,7 +333,7 @@ fn builds_table_data_where_and_schema_queries() {
|
||||
where_input: Some("WHERE amount > 10".to_string()),
|
||||
include_row_id: false,
|
||||
}),
|
||||
"SELECT * FROM (SELECT * FROM \"DBXTEST\".\"ORDERS\" WHERE (amount > 10) ORDER BY \"ID\" ASC) WHERE ROWNUM <= 50"
|
||||
"SELECT * FROM (SELECT * FROM \"DBXTEST\".\"ORDERS\" WHERE (amount > 10)) WHERE ROWNUM <= 50"
|
||||
);
|
||||
assert_eq!(
|
||||
build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
@@ -349,7 +349,7 @@ fn builds_table_data_where_and_schema_queries() {
|
||||
where_input: Some("WHERE amount > 10".to_string()),
|
||||
include_row_id: false,
|
||||
}),
|
||||
"SELECT \"ID\", \"AMOUNT\" FROM (SELECT dbx_t.\"ID\", dbx_t.\"AMOUNT\", ROW_NUMBER() OVER (ORDER BY \"ID\" ASC) AS \"__dbx_row_num\" FROM \"DB2INST1\".\"ORDERS\" dbx_t WHERE (amount > 10)) dbx_page WHERE \"__dbx_row_num\" > 100 AND \"__dbx_row_num\" <= 150 ORDER BY \"__dbx_row_num\""
|
||||
"SELECT \"ID\", \"AMOUNT\" FROM (SELECT dbx_t.\"ID\", dbx_t.\"AMOUNT\", ROW_NUMBER() OVER () AS \"__dbx_row_num\" FROM \"DB2INST1\".\"ORDERS\" dbx_t WHERE (amount > 10)) dbx_page WHERE \"__dbx_row_num\" > 100 AND \"__dbx_row_num\" <= 150 ORDER BY \"__dbx_row_num\""
|
||||
);
|
||||
assert_eq!(
|
||||
build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
@@ -401,7 +401,7 @@ fn builds_informix_table_data_with_skip_first_pagination() {
|
||||
where_input: Some("WHERE active = 1".to_string()),
|
||||
include_row_id: false,
|
||||
}),
|
||||
"SELECT SKIP 100 FIRST 50 * FROM users WHERE (active = 1) ORDER BY id ASC"
|
||||
"SELECT SKIP 100 FIRST 50 * FROM users WHERE (active = 1)"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
@@ -418,7 +418,7 @@ fn builds_informix_table_data_with_skip_first_pagination() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn explicit_table_data_order_overrides_default_key_order() {
|
||||
fn explicit_table_data_order_is_preserved() {
|
||||
assert_eq!(
|
||||
build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
database_type: Some(DatabaseType::Postgres),
|
||||
@@ -484,7 +484,7 @@ fn builds_table_data_special_column_queries() {
|
||||
where_input: None,
|
||||
include_row_id: false,
|
||||
}),
|
||||
"SELECT tbname, `ts` AS `ts`, `current` AS `current`, `voltage` AS `voltage`, `location` AS `location`, `groupid` AS `groupid` FROM `test_db`.`meters` ORDER BY `ts` ASC LIMIT 100;"
|
||||
"SELECT tbname, `ts` AS `ts`, `current` AS `current`, `voltage` AS `voltage`, `location` AS `location`, `groupid` AS `groupid` FROM `test_db`.`meters` LIMIT 100;"
|
||||
);
|
||||
assert_eq!(
|
||||
build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
@@ -520,7 +520,7 @@ fn builds_sqlserver_table_data_pages() {
|
||||
where_input: Some("where id = 1".to_string()),
|
||||
include_row_id: false,
|
||||
}),
|
||||
"SELECT TOP (25) * FROM [dbo].[accounts] WHERE (id = 1) ORDER BY [id] ASC"
|
||||
"SELECT TOP (25) * FROM [dbo].[accounts] WHERE (id = 1)"
|
||||
);
|
||||
assert_eq!(
|
||||
build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
@@ -536,28 +536,28 @@ fn builds_sqlserver_table_data_pages() {
|
||||
where_input: None,
|
||||
include_row_id: false,
|
||||
}),
|
||||
"WITH [dbx_page] AS (SELECT [order_id], [customer], ROW_NUMBER() OVER (ORDER BY [order_id] ASC) AS [__dbx_row_num] FROM [sales].[orders]) SELECT [order_id], [customer] FROM [dbx_page] WHERE [__dbx_row_num] > 100 AND [__dbx_row_num] <= 150 ORDER BY [__dbx_row_num]"
|
||||
"WITH [dbx_page] AS (SELECT [order_id], [customer], ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS [__dbx_row_num] FROM [sales].[orders]) SELECT [order_id], [customer] FROM [dbx_page] WHERE [__dbx_row_num] > 100 AND [__dbx_row_num] <= 150 ORDER BY [__dbx_row_num]"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builds_oracle_and_neo4j_table_data_queries() {
|
||||
assert_eq!(
|
||||
build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
database_type: Some(DatabaseType::Oracle),
|
||||
schema: Some("DBXTEST".to_string()),
|
||||
table_name: "DBX_LOAD_TABLE_006".to_string(),
|
||||
primary_keys: vec![DBX_ROWID_COLUMN.to_string()],
|
||||
columns: Vec::new(),
|
||||
fallback_order_columns: Vec::new(),
|
||||
order_by: None,
|
||||
limit: Some(100),
|
||||
offset: None,
|
||||
where_input: None,
|
||||
include_row_id: true,
|
||||
}),
|
||||
"SELECT ROWIDTOCHAR(t.ROWID) AS \"__DBX_ROWID\", t.* FROM \"DBXTEST\".\"DBX_LOAD_TABLE_006\" t ORDER BY t.ROWID ASC"
|
||||
);
|
||||
build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
database_type: Some(DatabaseType::Oracle),
|
||||
schema: Some("DBXTEST".to_string()),
|
||||
table_name: "DBX_LOAD_TABLE_006".to_string(),
|
||||
primary_keys: vec![DBX_ROWID_COLUMN.to_string()],
|
||||
columns: Vec::new(),
|
||||
fallback_order_columns: Vec::new(),
|
||||
order_by: None,
|
||||
limit: Some(100),
|
||||
offset: None,
|
||||
where_input: None,
|
||||
include_row_id: true,
|
||||
}),
|
||||
"SELECT ROWIDTOCHAR(t.ROWID) AS \"__DBX_ROWID\", t.* FROM \"DBXTEST\".\"DBX_LOAD_TABLE_006\" t"
|
||||
);
|
||||
assert_eq!(
|
||||
build_table_data_select_sql(TableDataSelectSqlOptions {
|
||||
database_type: Some(DatabaseType::Neo4j),
|
||||
@@ -572,7 +572,7 @@ fn builds_oracle_and_neo4j_table_data_queries() {
|
||||
where_input: None,
|
||||
include_row_id: false,
|
||||
}),
|
||||
"MATCH (n:`Employee`) RETURN elementId(n) AS `__DBX_ELEMENT_ID`, n.`id` AS `id`, n.`first name` AS `first name`, n.`role` AS `role` ORDER BY n.`id` ASC LIMIT 100;"
|
||||
"MATCH (n:`Employee`) RETURN elementId(n) AS `__DBX_ELEMENT_ID`, n.`id` AS `id`, n.`first name` AS `first name`, n.`role` AS `role` LIMIT 100;"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user