fix(oracle): stop ROWID pagination injection on views

This commit is contained in:
zipg authored and GitHub committed 2026-09-09 22:35:51 +08:00
1 parent c8c7a40e46
commit b84d162049
11 files changed
+196 -17

No files matched your search

@@ -267,11 +267,12 @@ pub fn build_table_data_select_sql_with_database(
};
let order_by = options.order_by.as_deref().filter(|order| !order.trim().is_empty()).or(default_order_by.as_deref());
let order = order_by.map(|order_by| format!(" ORDER BY {order_by}")).unwrap_or_default();
// Oracle join views can raise ORA-01445 when ROWID is selected; keep the
// synthetic ROWID fallback scoped to base-table reads.
// Oracle views with DISTINCT/GROUP BY raise ORA-01446 when ROWID is
// selected. Missing object metadata must therefore fail closed instead of
// being treated as a base table.
let include_oracle_row_id = options.include_row_id
&& uses_oracle_row_id(database_type)
&& !is_view_table_type(options.table_type.as_deref());
&& is_oracle_base_table_type(options.table_type.as_deref());
let include_xugu_row_id =
options.include_row_id && uses_xugu_row_id(database_type) && !is_view_table_type(options.table_type.as_deref());
let offset = options.offset.unwrap_or(0);
@@ -530,6 +531,10 @@ fn is_view_table_type(table_type: Option<&str>) -> bool {
table_type.is_some_and(|value| value.to_ascii_uppercase().contains("VIEW"))
}
fn is_oracle_base_table_type(table_type: Option<&str>) -> bool {
table_type.is_some_and(|value| value.trim().eq_ignore_ascii_case("TABLE"))
}
pub fn build_table_select_sql(options: TableSelectSqlOptions<'_>) -> String {
let database_type = options.database_type;
if database_type == Some(DatabaseType::VictoriaMetrics) {
+21 -2
View File
@@ -1304,7 +1304,7 @@ fn builds_oracle_and_neo4j_table_data_queries() {
database_type: Some(DatabaseType::Oracle),
schema: Some("DBXTEST".to_string()),
table_name: "DBX_LOAD_TABLE_006".to_string(),
table_type: None,
table_type: Some("TABLE".to_string()),
primary_keys: vec![DBX_ROWID_COLUMN.to_string()],
columns: Vec::new(),
fallback_order_columns: Vec::new(),
@@ -1322,7 +1322,7 @@ fn builds_oracle_and_neo4j_table_data_queries() {
database_type: Some(DatabaseType::Oracle),
schema: Some("DBXTEST".to_string()),
table_name: "DBX_LOAD_TABLE_006".to_string(),
table_type: None,
table_type: Some("TABLE".to_string()),
primary_keys: vec![DBX_ROWID_COLUMN.to_string()],
columns: vec!["ID".to_string(), "NAME".to_string()],
fallback_order_columns: Vec::new(),
@@ -1445,6 +1445,25 @@ fn builds_oracle_and_neo4j_table_data_queries() {
);
}
#[test]
fn oracle_unknown_table_type_does_not_assume_rowid_support() {
assert_eq!(
build_table_data_select_sql(TableDataSelectSqlOptions {
database_type: Some(DatabaseType::Oracle),
schema: Some("DBXTEST".to_string()),
table_name: "DBX_DISTINCT_VIEW".to_string(),
table_type: None,
primary_keys: vec![DBX_ROWID_COLUMN.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_DISTINCT_VIEW\") dbx_inner WHERE ROWNUM <= 200) WHERE \"__dbx_row_num\" > 100"
);
}
#[test]
fn builds_oracle_rowid_wrapped_large_value_reload_sql() {
// The data-grid large-value reload selects the synthetic rowid key plus the