feat(backup): support table filters and MySQL compatibility
This commit is contained in:
1 parent
09c3f7f44c
commit
7abac0959f
15 files changed
+386
-32
No files matched your search
@@ -2918,14 +2918,26 @@ fn postgres_transaction_begin_sql(consistent_snapshot: bool) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
fn mysql_transaction_begin_sql(consistent_snapshot: bool) -> &'static str {
|
||||
fn mysql_transaction_begin_sql_candidates(consistent_snapshot: bool) -> &'static [&'static str] {
|
||||
if consistent_snapshot {
|
||||
"START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY"
|
||||
&[
|
||||
"START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY",
|
||||
"START TRANSACTION WITH CONSISTENT SNAPSHOT",
|
||||
"START TRANSACTION",
|
||||
]
|
||||
} else {
|
||||
"START TRANSACTION"
|
||||
&["START TRANSACTION"]
|
||||
}
|
||||
}
|
||||
|
||||
fn mysql_transaction_isolation_sql(consistent_snapshot: bool) -> Option<&'static str> {
|
||||
consistent_snapshot.then_some("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ")
|
||||
}
|
||||
|
||||
fn mysql_error_is_syntax_error(error: &mysql_async::Error) -> bool {
|
||||
matches!(error, mysql_async::Error::Server(server_error) if server_error.code == 1064)
|
||||
}
|
||||
|
||||
async fn begin_transaction_session(
|
||||
state: &AppState,
|
||||
connection_id: &str,
|
||||
@@ -2968,8 +2980,25 @@ async fn begin_transaction_session(
|
||||
}
|
||||
TxnPoolHandle::Mysql(mysql_pool) => {
|
||||
let mut conn = mysql_pool.get_conn().await.map_err(|e| format!("Failed to get MySQL connection: {e}"))?;
|
||||
let begin_sql = mysql_transaction_begin_sql(consistent_snapshot);
|
||||
conn.query_drop(begin_sql).await.map_err(|e| format!("START TRANSACTION failed: {e}"))?;
|
||||
if let Some(isolation_sql) = mysql_transaction_isolation_sql(consistent_snapshot) {
|
||||
conn.query_drop(isolation_sql).await.map_err(|e| format!("SET TRANSACTION failed: {e}"))?;
|
||||
}
|
||||
let mut syntax_errors = Vec::new();
|
||||
for begin_sql in mysql_transaction_begin_sql_candidates(consistent_snapshot) {
|
||||
match conn.query_drop(*begin_sql).await {
|
||||
Ok(()) => {
|
||||
syntax_errors.clear();
|
||||
break;
|
||||
}
|
||||
Err(error) if mysql_error_is_syntax_error(&error) => {
|
||||
syntax_errors.push(format!("{begin_sql}: {error}"));
|
||||
}
|
||||
Err(error) => return Err(format!("START TRANSACTION failed: {error}")),
|
||||
}
|
||||
}
|
||||
if !syntax_errors.is_empty() {
|
||||
return Err(format!("START TRANSACTION failed for all compatible forms: {}", syntax_errors.join("; ")));
|
||||
}
|
||||
TxnConnection::Mysql(conn)
|
||||
}
|
||||
};
|
||||
@@ -4956,8 +4985,35 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn database_backup_transactions_request_consistent_read_only_snapshots() {
|
||||
fn database_backup_transactions_request_consistent_snapshots() {
|
||||
assert_eq!(postgres_transaction_begin_sql(true), "BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ READ ONLY");
|
||||
assert_eq!(mysql_transaction_begin_sql(true), "START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY");
|
||||
assert_eq!(mysql_transaction_isolation_sql(true), Some("SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"));
|
||||
assert_eq!(
|
||||
mysql_transaction_begin_sql_candidates(true),
|
||||
[
|
||||
"START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY",
|
||||
"START TRANSACTION WITH CONSISTENT SNAPSHOT",
|
||||
"START TRANSACTION",
|
||||
]
|
||||
);
|
||||
assert_eq!(mysql_transaction_isolation_sql(false), None);
|
||||
assert_eq!(mysql_transaction_begin_sql_candidates(false), ["START TRANSACTION"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mysql_backup_transaction_only_falls_back_for_syntax_errors() {
|
||||
let syntax_error = mysql_async::Error::Server(mysql_async::ServerError {
|
||||
code: 1064,
|
||||
message: "unsupported transaction characteristic".to_string(),
|
||||
state: "42000".to_string(),
|
||||
});
|
||||
let permission_error = mysql_async::Error::Server(mysql_async::ServerError {
|
||||
code: 1044,
|
||||
message: "access denied".to_string(),
|
||||
state: "42000".to_string(),
|
||||
});
|
||||
|
||||
assert!(mysql_error_is_syntax_error(&syntax_error));
|
||||
assert!(!mysql_error_is_syntax_error(&permission_error));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user