fix: resolve PostgreSQL type mismatches and add willexecutor debug logging
- Fix get_next_address_index: use try_get::<i32> for PG SERIAL/INTEGER columns - Fix search_tx: use try_get::<i32> for PG status column - Fix execute_insert: parse locktime (String→i64) and in_vout (String→i32) before binding to PG INTEGER columns - Fix execute_insert: bind tbl_out vout as i32, amount as String for PG - Fix save_new_address: cast xpub i64 to i32 for PG INTEGER column - Fix get_pending_txs: cast i64 bind params to i32, use try_get::<i32> for reads - Fix get_stats: use try_get::<i32> for all numeric PG INTEGER columns - Add trace logging in parse_request_transactions for xpub address matching - Add trace logging in get_all_addresses_by_xpub for query debugging
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
use sqlite::Connection;
|
||||
use std::collections::HashMap;
|
||||
use sqlx::Row;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
|
||||
@@ -8,39 +7,44 @@ fn test_mutex_poisoning_recovery() {
|
||||
let data = Arc::new(Mutex::new(0));
|
||||
let c = data.clone();
|
||||
let handle = thread::spawn(move || {
|
||||
let _guard = c.lock(); // Acquire lock
|
||||
panic!("test panic"); // Panic while holding the lock
|
||||
// _guard is dropped during panic unwinding, poisoning the mutex
|
||||
let _guard = c.lock();
|
||||
panic!("test panic");
|
||||
});
|
||||
let result = handle.join();
|
||||
assert!(result.is_err()); // Thread panicked
|
||||
assert!(result.is_err());
|
||||
|
||||
// Recovery: the same pattern used in bal-server.rs
|
||||
let guard = match data.lock() {
|
||||
Ok(g) => g,
|
||||
Err(p) => {
|
||||
p.into_inner() // Should not panic
|
||||
}
|
||||
Err(p) => p.into_inner(),
|
||||
};
|
||||
assert_eq!(*guard, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_db_null_unwrap_or() {
|
||||
let db = Connection::open(":memory:").unwrap();
|
||||
let _ = db.execute(
|
||||
"CREATE TABLE test_stats (report_date TEXT, chain TEXT, totals TEXT, waiting TEXT);",
|
||||
);
|
||||
let _ =
|
||||
db.execute("INSERT INTO test_stats (report_date, chain) VALUES ('2024-01-01', 'testnet');");
|
||||
#[tokio::test]
|
||||
async fn test_db_null_unwrap_or() {
|
||||
let pool = bal_server::db::open_database("sqlite", "sqlite::memory:")
|
||||
.await
|
||||
.unwrap();
|
||||
if let bal_server::db::DatabasePool::SQLite(p) = &pool {
|
||||
sqlx::query(
|
||||
"CREATE TABLE test_stats (report_date TEXT, chain TEXT, totals TEXT, waiting TEXT);",
|
||||
)
|
||||
.execute(p)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let mut found_value = None;
|
||||
let _ = db.iterate("SELECT * FROM test_stats;", |pairs| {
|
||||
let row: HashMap<_, _> = pairs.iter().map(|(k, v)| (k.to_string(), *v)).collect();
|
||||
let totals = row["totals"].unwrap_or("0").to_string();
|
||||
found_value = Some(totals);
|
||||
true
|
||||
});
|
||||
sqlx::query("INSERT INTO test_stats (report_date, chain) VALUES ('2024-01-01', 'testnet')")
|
||||
.execute(p)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(found_value.unwrap(), "0");
|
||||
let row = sqlx::query("SELECT * FROM test_stats")
|
||||
.fetch_one(p)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let totals: Option<String> = row.try_get("totals").unwrap_or(None);
|
||||
let totals_value = totals.unwrap_or_else(|| "0".to_string());
|
||||
assert_eq!(totals_value, "0");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user