fix(oracle): defer XMLTYPE in manual transactions

This commit is contained in:
zipg authored and GitHub committed 2026-08-21 19:44:13 +08:00
1 parent e50bd26141
commit 47e02b8da7
8 files changed
+209 -17

No files matched your search

+55 -6
View File
@@ -4502,10 +4502,24 @@ pub async fn execute_in_manual_transaction(
state: &AppState,
txn_session_id: &str,
sql: &str,
_database: &str,
_schema: Option<&str>,
database: &str,
schema: Option<&str>,
max_rows: Option<usize>,
) -> Result<Vec<db::QueryResult>, String> {
execute_in_manual_transaction_with_options(state, txn_session_id, sql, database, schema, max_rows, false)
.await
.map(|results| results.into_iter().map(ExecuteMultiResult::into_query_result).collect())
}
pub async fn execute_in_manual_transaction_with_options(
state: &AppState,
txn_session_id: &str,
sql: &str,
database: &str,
schema: Option<&str>,
max_rows: Option<usize>,
table_data_preview: bool,
) -> Result<Vec<ExecuteMultiResult>, String> {
const TXN_IDLE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(300);
// Resolve statements and validate before taking the per-session connection
@@ -4525,7 +4539,10 @@ pub async fn execute_in_manual_transaction(
|db_type| crate::sql::split_sql_statements_for_database(sql, db_type),
);
if statements.is_empty() {
return Ok(vec![empty_query_result(0)]);
return Ok(vec![ExecuteMultiResult::success_with_optional_server_large_values(
empty_query_result(0),
table_data_preview,
)]);
}
// Read-only check while the session is still in the map. If this fails the
@@ -4577,11 +4594,25 @@ pub async fn execute_in_manual_transaction(
}
TxnConnection::Mysql(conn) => execute_manual_txn_mysql_statement(conn, statement, row_limit).await,
TxnConnection::Agent { client, .. } => {
execute_manual_txn_agent_statement(client, db_type, statement, _database, _schema, row_limit).await
execute_manual_txn_agent_statement(
client,
db_type,
statement,
database,
schema,
row_limit,
table_data_preview,
)
.await
}
};
match result {
Ok(query_result) => results.push(query_result),
Ok(query_result) => {
results.push(ExecuteMultiResult::success_with_optional_server_large_values(
query_result,
table_data_preview,
));
}
Err(e) => {
// Statement failure ends the transaction. If another cleanup path
// already removed the session, it owns the final rollback.
@@ -4792,6 +4823,10 @@ async fn release_manual_txn_agent_pool(state: &AppState, connection_id: &str, co
}
}
fn manual_txn_agent_query_options(row_limit: usize, table_data_preview: bool) -> QueryExecutionOptions {
QueryExecutionOptions { max_rows: Some(row_limit.max(1)), table_data_preview, ..QueryExecutionOptions::default() }
}
async fn execute_manual_txn_agent_statement(
client: &Arc<crate::db::agent_driver::PooledAgentClient>,
db_type: Option<DatabaseType>,
@@ -4799,10 +4834,11 @@ async fn execute_manual_txn_agent_statement(
database: &str,
schema: Option<&str>,
row_limit: usize,
table_data_preview: bool,
) -> Result<db::QueryResult, String> {
let sql = sql_for_execution_context(db_type, statement, schema);
let execution_schema = schema_for_execution_context(db_type, schema);
let options = QueryExecutionOptions { max_rows: Some(row_limit.max(1)), ..QueryExecutionOptions::default() };
let options = manual_txn_agent_query_options(row_limit, table_data_preview);
let params =
agent_execute_query_params(&sql, Some(database).filter(|value| !value.is_empty()), execution_schema, options);
let mut locked = client.lock().await;
@@ -7314,6 +7350,19 @@ for line in sys.stdin:
assert_eq!(params["deferLobs"], true);
}
#[test]
fn manual_transaction_agent_query_options_preserve_preview_mode() {
let params = agent_execute_query_params(
"SELECT * FROM documents",
Some("ORCL"),
Some("APP"),
manual_txn_agent_query_options(250, true),
);
assert_eq!(params["maxRows"], 250);
assert_eq!(params["deferLobs"], true);
}
#[test]
fn iris_execution_context_omits_schema() {
assert_eq!(schema_for_execution_context(Some(DatabaseType::Iris), Some("SQLUser")), None);