diff --git a/crates/dbx-core/src/db/mysql.rs b/crates/dbx-core/src/db/mysql.rs index 085e05437d..1b5159422b 100644 --- a/crates/dbx-core/src/db/mysql.rs +++ b/crates/dbx-core/src/db/mysql.rs @@ -132,6 +132,8 @@ fn mysql_value_to_json(row: &MySqlRow, idx: usize, type_name: &str) -> serde_jso .map(serde_json::Value::String) .or_else(|_| row.try_get::(idx).map(super::safe_i64_to_json)) .or_else(|_| row.try_get::(idx).map(super::safe_u64_to_json)) + .or_else(|_| row.try_get::(idx).map(|v| serde_json::Value::Number(v.into()))) + .or_else(|_| row.try_get::(idx).map(|v| serde_json::Value::Number(v.into()))) .or_else(|_| { row.try_get::(idx).map(|v| { serde_json::Number::from_f64(v).map(serde_json::Value::Number).unwrap_or(serde_json::Value::Null) @@ -142,6 +144,11 @@ fn mysql_value_to_json(row: &MySqlRow, idx: usize, type_name: &str) -> serde_jso row.try_get::, _>(idx).map(|b| serde_json::Value::String(String::from_utf8_lossy(&b).to_string())) }) .or_else(|e| mysql_temporal_to_json_value(row, idx).ok_or(e)) + .or_else(|_| row.try_get_unchecked::(idx).map(serde_json::Value::String)) + .or_else(|_| { + row.try_get_unchecked::, _>(idx) + .map(|b| serde_json::Value::String(String::from_utf8_lossy(&b).to_string())) + }) .unwrap_or(serde_json::Value::Null) } diff --git a/crates/dbx-core/src/db/oracle_driver.rs b/crates/dbx-core/src/db/oracle_driver.rs index 83127bc900..f4e64020f1 100644 --- a/crates/dbx-core/src/db/oracle_driver.rs +++ b/crates/dbx-core/src/db/oracle_driver.rs @@ -22,16 +22,6 @@ pub async fn connect( .map_err(|_| format!("Oracle connection timed out ({CONNECTION_TIMEOUT_SECS}s)"))? .map_err(|e| format!("Oracle connection failed: {e}"))?; - // Verify connection works with a simple query - log::info!("[oracle] connect: verifying with SELECT 1 FROM DUAL..."); - conn.query("SELECT 1 FROM DUAL", &[]).await.map_err(|e| format!("Oracle connection verification failed: {e}"))?; - log::info!("[oracle] connect: verification OK, testing multi-row..."); - let r = conn - .query("SELECT username FROM all_users ORDER BY username", &[]) - .await - .map_err(|e| format!("Oracle multi-row test failed: {e}"))?; - log::info!("[oracle] connect: multi-row OK, {} rows", r.rows.len()); - Ok(conn) } @@ -270,6 +260,11 @@ pub async fn list_triggers(conn: &OracleClient, schema: &str, table: &str) -> Re pub async fn execute_query(conn: &OracleClient, sql: &str) -> Result { let start = Instant::now(); let sql = sql.trim().trim_end_matches(';'); + + // Rewrite FETCH FIRST N ROWS ONLY → ROWNUM for Oracle 11g compatibility + let sql = rewrite_fetch_first(sql); + let sql = sql.as_ref(); + let trimmed = sql.to_uppercase(); log::debug!("[oracle] execute_query: sql={}", &sql[..sql.len().min(200)]); @@ -324,3 +319,17 @@ pub async fn execute_query(conn: &OracleClient, sql: &str) -> Result std::borrow::Cow<'_, str> { + let upper = sql.to_uppercase(); + if let Some(pos) = upper.find("FETCH FIRST") { + if let Some(end) = upper[pos..].find("ROWS ONLY") { + let between = sql[pos + 11..pos + end].trim(); + if let Ok(n) = between.parse::() { + let base = sql[..pos].trim_end(); + return std::borrow::Cow::Owned(format!("SELECT * FROM ({base}) WHERE ROWNUM <= {n}")); + } + } + } + std::borrow::Cow::Borrowed(sql) +}