@@ -53,13 +53,11 @@ static MIGRATIONS: &[&str] = &[
5353 "DELETE FROM utxos;" ,
5454 "DROP INDEX idx_txid_vout;" ,
5555 "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);"
6361] ;
6462
6563/// Sqlite database stored on filesystem
@@ -921,8 +919,8 @@ impl BatchDatabase for SqliteDatabase {
921919}
922920
923921pub 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) ?;
926924 Ok ( connection)
927925}
928926
@@ -957,28 +955,41 @@ pub fn set_schema_version(conn: &Connection, version: i32) -> rusqlite::Result<u
957955 )
958956}
959957
960- pub fn migrate ( conn : & Connection ) -> rusqlite :: Result < ( ) > {
958+ pub fn migrate ( conn : & mut Connection ) -> Result < ( ) , Error > {
961959 let version = get_schema_version ( conn) ?;
962960 let stmts = & MIGRATIONS [ ( version as usize ) ..] ;
963- let mut i: i32 = version;
964961
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_stmt. 0 ,
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 + 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 {
966988 log:: info!( "db up to date, no migration needed" ) ;
967- return Ok ( ( ) ) ;
968989 }
969990
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 ( ) ?;
982993 Ok ( ( ) )
983994}
984995
0 commit comments