diff --git a/crates/dbx-core/src/sql_dialect/table_select.rs b/crates/dbx-core/src/sql_dialect/table_select.rs index e4b58a7b84..e42eb1b98e 100644 --- a/crates/dbx-core/src/sql_dialect/table_select.rs +++ b/crates/dbx-core/src/sql_dialect/table_select.rs @@ -54,6 +54,9 @@ pub fn build_table_data_select_sql(options: TableDataSelectSqlOptions) -> String let include_oracle_row_id = options.include_row_id && uses_oracle_row_id(database_type) && !is_view_table_type(options.table_type.as_deref()); + let offset = options.offset.unwrap_or(0); + let oracle_view_first_page = + database_type == Some(DatabaseType::Oracle) && is_view_table_type(options.table_type.as_deref()) && offset == 0; let select_columns = if include_oracle_row_id { format!("ROWIDTOCHAR(t.ROWID) AS \"{DBX_ROWID_COLUMN}\", t.*") @@ -109,6 +112,9 @@ pub fn build_table_data_select_sql(options: TableDataSelectSqlOptions) -> String ) } TablePaginationStrategy::Rownum => { + if oracle_view_first_page { + return format!("SELECT {page_select_columns} FROM {table_alias}{where_clause}{order}"); + } let rownum_inner_select_columns = if include_oracle_row_id { &select_columns } else { &rownum_select_columns }; build_rownum_table_select_sql( @@ -118,7 +124,7 @@ pub fn build_table_data_select_sql(options: TableDataSelectSqlOptions) -> String rownum_inner_select_columns, &page_select_columns, limit, - options.offset.unwrap_or(0), + offset, ) } TablePaginationStrategy::Unbounded => { diff --git a/crates/dbx-core/src/sql_dialect/tests.rs b/crates/dbx-core/src/sql_dialect/tests.rs index 54f10fa09b..4f354bf3be 100644 --- a/crates/dbx-core/src/sql_dialect/tests.rs +++ b/crates/dbx-core/src/sql_dialect/tests.rs @@ -819,7 +819,7 @@ fn builds_oracle_and_neo4j_table_data_queries() { include_row_id: true, ..Default::default() }), - "SELECT \"ID\", \"NAME\" FROM (SELECT \"ID\", \"NAME\" FROM \"DBXTEST\".\"DBX_JOIN_VIEW\") WHERE ROWNUM <= 100" + "SELECT \"ID\", \"NAME\" FROM \"DBXTEST\".\"DBX_JOIN_VIEW\"" ); assert_eq!( build_table_data_select_sql(TableDataSelectSqlOptions { @@ -841,6 +841,44 @@ fn builds_oracle_and_neo4j_table_data_queries() { ); } +#[test] +fn oracle_view_first_page_preserves_filter_and_sort_without_rownum() { + assert_eq!( + build_table_data_select_sql(TableDataSelectSqlOptions { + database_type: Some(DatabaseType::Oracle), + schema: Some("DBXTEST".to_string()), + table_name: "DBX_JOIN_VIEW".to_string(), + table_type: Some("VIEW".to_string()), + columns: vec!["ID".to_string(), "NAME".to_string()], + order_by: Some("\"ID\" DESC".to_string()), + limit: Some(100), + offset: Some(0), + where_input: Some("STATUS = 'A'".to_string()), + include_row_id: true, + ..Default::default() + }), + "SELECT \"ID\", \"NAME\" FROM \"DBXTEST\".\"DBX_JOIN_VIEW\" WHERE (STATUS = 'A') ORDER BY \"ID\" DESC" + ); +} + +#[test] +fn oracle_view_later_pages_keep_rownum_pagination() { + assert_eq!( + build_table_data_select_sql(TableDataSelectSqlOptions { + database_type: Some(DatabaseType::Oracle), + schema: Some("DBXTEST".to_string()), + table_name: "DBX_JOIN_VIEW".to_string(), + table_type: Some("VIEW".to_string()), + columns: vec!["ID".to_string(), "NAME".to_string()], + limit: Some(100), + offset: Some(100), + include_row_id: true, + ..Default::default() + }), + "SELECT \"ID\", \"NAME\" FROM (SELECT dbx_inner.*, ROWNUM AS \"__dbx_row_num\" FROM (SELECT \"ID\", \"NAME\" FROM \"DBXTEST\".\"DBX_JOIN_VIEW\") dbx_inner WHERE ROWNUM <= 200) WHERE \"__dbx_row_num\" > 100" + ); +} + #[test] fn normalizes_where_input_with_multibyte_identifier_prefix() { assert_eq!(normalize_where_input(Some("`客户名称` = '示例客户'")), "`客户名称` = '示例客户'");