mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-20 08:18:52 +00:00
feat: add execute_batch command for executing multiple SQL statements in a single call
This commit is contained in:
@@ -170,3 +170,46 @@ pub async fn execute_query(
|
||||
_ => result,
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn execute_batch(
|
||||
state: State<'_, Arc<AppState>>,
|
||||
connection_id: String,
|
||||
database: String,
|
||||
statements: Vec<String>,
|
||||
) -> Result<db::QueryResult, String> {
|
||||
let pool_key = if database.is_empty() {
|
||||
connection_id.clone()
|
||||
} else {
|
||||
state.get_or_create_pool(&connection_id, Some(&database)).await?
|
||||
};
|
||||
|
||||
let mut total_affected: u64 = 0;
|
||||
let start = std::time::Instant::now();
|
||||
|
||||
for (i, sql) in statements.iter().enumerate() {
|
||||
match do_execute(&state, &pool_key, sql).await {
|
||||
Ok(result) => {
|
||||
total_affected += result.affected_rows;
|
||||
}
|
||||
Err(e) => {
|
||||
if is_connection_error(&e) {
|
||||
let db_opt = if database.is_empty() { None } else { Some(database.as_str()) };
|
||||
let _ = state.reconnect_pool(&connection_id, db_opt).await;
|
||||
}
|
||||
return Err(format!(
|
||||
"Statement {} failed: {}. Previous {} statement(s) may have been committed.",
|
||||
i + 1, e, i
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(db::QueryResult {
|
||||
columns: vec![],
|
||||
rows: vec![],
|
||||
affected_rows: total_affected,
|
||||
execution_time_ms: start.elapsed().as_millis(),
|
||||
truncated: false,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ pub async fn execute_query(conn: &OracleClient, sql: &str) -> Result<QueryResult
|
||||
Err(e) => {
|
||||
let msg = e.to_string();
|
||||
if msg.contains("Server rejected") || msg.contains("closed the connection") {
|
||||
Err("Operation failed — possibly a constraint violation (foreign key, unique, or check constraint).".to_string())
|
||||
Err("Operation failed (connection closed) — possibly a constraint violation (foreign key, unique, or check constraint).".to_string())
|
||||
} else {
|
||||
Err(msg)
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ pub fn run() {
|
||||
commands::schema::list_triggers,
|
||||
commands::schema::get_table_ddl,
|
||||
commands::query::execute_query,
|
||||
commands::query::execute_batch,
|
||||
commands::redis_cmd::redis_list_databases,
|
||||
commands::redis_cmd::redis_scan_keys,
|
||||
commands::redis_cmd::redis_get_value,
|
||||
|
||||
@@ -353,10 +353,12 @@ function deleteSelectedRow() {
|
||||
}
|
||||
|
||||
function escapeVal(v: CellValue): string {
|
||||
if (v === null) return "NULL";
|
||||
if (v === null || v === undefined) return "NULL";
|
||||
if (typeof v === "boolean") return v ? "TRUE" : "FALSE";
|
||||
if (typeof v === "number") return String(v);
|
||||
return `'${String(v).replace(/'/g, "''")}'`;
|
||||
if (typeof v === "number" && Number.isFinite(v)) return String(v);
|
||||
const s = String(v);
|
||||
if (s === "") return "''";
|
||||
return `'${s.replace(/\\/g, "\\\\").replace(/'/g, "''")}'`;
|
||||
}
|
||||
|
||||
function qualifiedTableName(): string {
|
||||
@@ -407,7 +409,15 @@ async function saveChanges() {
|
||||
const stmts = generateSaveStatements();
|
||||
if (stmts.length === 0) return;
|
||||
saveError.value = "";
|
||||
if (props.onExecuteSql) {
|
||||
|
||||
if (props.connectionId && props.database) {
|
||||
try {
|
||||
await api.executeBatch(props.connectionId, props.database, stmts);
|
||||
} catch (e: any) {
|
||||
saveError.value = String(e.message || e);
|
||||
return;
|
||||
}
|
||||
} else if (props.onExecuteSql) {
|
||||
try {
|
||||
for (const sql of stmts) {
|
||||
await props.onExecuteSql(sql);
|
||||
|
||||
@@ -73,6 +73,10 @@ export async function executeQuery(connectionId: string, database: string, sql:
|
||||
return invoke("execute_query", { connectionId, database, sql });
|
||||
}
|
||||
|
||||
export async function executeBatch(connectionId: string, database: string, statements: string[]): Promise<QueryResult> {
|
||||
return invoke("execute_batch", { connectionId, database, statements });
|
||||
}
|
||||
|
||||
export async function listIndexes(connectionId: string, database: string, schema: string, table: string): Promise<IndexInfo[]> {
|
||||
return invoke("list_indexes", { connectionId, database, schema, table });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user