feat(data): complete portable SQL backend parity

Align MySQL and SQLite schemas, migrations, usage, stats, export, and backfill behavior with the shared data contracts. Extend gateway startup and maintenance support across all SQL drivers.
This commit is contained in:
elky
2026-07-25 21:28:21 +08:00
parent 764e9fd131
commit 778cfb1a5c
85 changed files with 32096 additions and 2328 deletions
@@ -14,11 +14,11 @@ impl MysqlBackend {
let table_name = maintenance_identifier(table_name)?;
summary.attempted += 1;
let statement = format!("ANALYZE TABLE `{table_name}`");
if sqlx::raw_sql(&statement)
.execute(self.pool())
if sqlx::query_as::<_, (String, String, String, String)>(&statement)
.fetch_all(self.pool())
.await
.map_sql_err()
.is_ok()
.is_ok_and(|rows| mysql_analyze_succeeded(&rows))
{
summary.succeeded += 1;
}
@@ -26,3 +26,42 @@ impl MysqlBackend {
Ok(summary)
}
}
fn mysql_analyze_succeeded(rows: &[(String, String, String, String)]) -> bool {
!rows.is_empty()
&& rows.iter().any(|(_, _, message_type, message)| {
message_type.eq_ignore_ascii_case("status") && message.eq_ignore_ascii_case("ok")
})
&& rows
.iter()
.all(|(_, _, message_type, _)| !message_type.eq_ignore_ascii_case("error"))
}
#[cfg(test)]
mod tests {
use super::mysql_analyze_succeeded;
fn row(message_type: &str, message: &str) -> (String, String, String, String) {
(
"aether.usage".to_string(),
"analyze".to_string(),
message_type.to_string(),
message.to_string(),
)
}
#[test]
fn analyze_requires_an_explicit_ok_status() {
assert!(mysql_analyze_succeeded(&[row("status", "OK")]));
assert!(!mysql_analyze_succeeded(&[]));
assert!(!mysql_analyze_succeeded(&[row("note", "skipped")]));
}
#[test]
fn analyze_rejects_error_rows_even_when_an_ok_row_is_present() {
assert!(!mysql_analyze_succeeded(&[
row("Error", "Table does not exist"),
row("status", "OK"),
]));
}
}