@@ -53,13 +53,11 @@ static MIGRATIONS: &[&str] = &[
53
53
"DELETE FROM utxos;" ,
54
54
"DROP INDEX idx_txid_vout;" ,
55
55
"CREATE UNIQUE INDEX idx_utxos_txid_vout ON utxos(txid, vout);" ,
56
- "BEGIN TRANSACTION;\
57
- ALTER TABLE utxos RENAME TO utxos_old;\
58
- CREATE TABLE utxos (value INTEGER, keychain TEXT, vout INTEGER, txid BLOB, script BLOB, is_spent BOOLEAN DEFAULT 0);\
59
- INSERT INTO utxos SELECT value, keychain, vout, txid, script, is_spent FROM utxos_old;\
60
- DROP TABLE utxos_old;\
61
- CREATE UNIQUE INDEX idx_utxos_txid_vout ON utxos(txid, vout);\
62
- COMMIT;"
56
+ "ALTER TABLE utxos RENAME TO utxos_old;" ,
57
+ "CREATE TABLE utxos (value INTEGER, keychain TEXT, vout INTEGER, txid BLOB, script BLOB, is_spent BOOLEAN DEFAULT 0);" ,
58
+ "INSERT INTO utxos SELECT value, keychain, vout, txid, script, is_spent FROM utxos_old;" ,
59
+ "DROP TABLE utxos_old;" ,
60
+ "CREATE UNIQUE INDEX idx_utxos_txid_vout ON utxos(txid, vout);"
63
61
] ;
64
62
65
63
/// Sqlite database stored on filesystem
@@ -921,8 +919,8 @@ impl BatchDatabase for SqliteDatabase {
921
919
}
922
920
923
921
pub fn get_connection < T : AsRef < Path > > ( path : & T ) -> Result < Connection , Error > {
924
- let connection = Connection :: open ( path) ?;
925
- migrate ( & connection) ?;
922
+ let mut connection = Connection :: open ( path) ?;
923
+ migrate ( & mut connection) ?;
926
924
Ok ( connection)
927
925
}
928
926
@@ -957,28 +955,41 @@ pub fn set_schema_version(conn: &Connection, version: i32) -> rusqlite::Result<u
957
955
)
958
956
}
959
957
960
- pub fn migrate ( conn : & Connection ) -> rusqlite :: Result < ( ) > {
958
+ pub fn migrate ( conn : & mut Connection ) -> Result < ( ) , Error > {
961
959
let version = get_schema_version ( conn) ?;
962
960
let stmts = & MIGRATIONS [ ( version as usize ) ..] ;
963
- let mut i: i32 = version;
964
961
965
- if version == MIGRATIONS . len ( ) as i32 {
962
+ // begin transaction, all migration statements and new schema version commit or rollback
963
+ let tx = conn. transaction ( ) ?;
964
+
965
+ // execute every statement and return `Some` new schema version
966
+ // if execution fails, return `Error::Rusqlite`
967
+ // if no statements executed returns `None`
968
+ let new_version = stmts
969
+ . iter ( )
970
+ . enumerate ( )
971
+ . map ( |version_stmt| {
972
+ log:: info!(
973
+ "executing db migration {}: `{}`" ,
974
+ version + version_stmt. 0 as i32 + 1 ,
975
+ version_stmt. 1
976
+ ) ;
977
+ tx. execute ( version_stmt. 1 , [ ] )
978
+ // map result value to next migration version
979
+ . map ( |_| version_stmt. 0 as i32 + version + 1 )
980
+ } )
981
+ . last ( )
982
+ . transpose ( ) ?;
983
+
984
+ // if `Some` new statement version, set new schema version
985
+ if let Some ( version) = new_version {
986
+ set_schema_version ( & tx, version) ?;
987
+ } else {
966
988
log:: info!( "db up to date, no migration needed" ) ;
967
- return Ok ( ( ) ) ;
968
989
}
969
990
970
- for stmt in stmts {
971
- let res = conn. execute ( stmt, [ ] ) ;
972
- if res. is_err ( ) {
973
- println ! ( "migration failed on:\n {}\n {:?}" , stmt, res) ;
974
- break ;
975
- }
976
-
977
- i += 1 ;
978
- }
979
-
980
- set_schema_version ( conn, i) ?;
981
-
991
+ // commit transaction
992
+ tx. commit ( ) ?;
982
993
Ok ( ( ) )
983
994
}
984
995
0 commit comments