@@ -32,9 +32,7 @@ use clarity::types::Address;
32
32
use libsigner:: v0:: messages:: { RejectReason , RejectReasonPrefix , StateMachineUpdate } ;
33
33
use libsigner:: BlockProposal ;
34
34
use rusqlite:: functions:: FunctionFlags ;
35
- use rusqlite:: {
36
- params, Connection , Error as SqliteError , OpenFlags , OptionalExtension , Transaction ,
37
- } ;
35
+ use rusqlite:: { params, Connection , Error as SqliteError , OpenFlags , OptionalExtension } ;
38
36
use serde:: { Deserialize , Serialize } ;
39
37
use stacks_common:: codec:: { read_next, write_next, Error as CodecError , StacksMessageCodec } ;
40
38
use stacks_common:: types:: chainstate:: ConsensusHash ;
@@ -708,9 +706,73 @@ static SCHEMA_14: &[&str] = &[
708
706
"INSERT INTO db_config (version) VALUES (14);" ,
709
707
] ;
710
708
709
+ struct Migration {
710
+ version : u32 ,
711
+ statements : & ' static [ & ' static str ] ,
712
+ }
713
+
714
+ static MIGRATIONS : & [ Migration ] = & [
715
+ Migration {
716
+ version : 1 ,
717
+ statements : SCHEMA_1 ,
718
+ } ,
719
+ Migration {
720
+ version : 2 ,
721
+ statements : SCHEMA_2 ,
722
+ } ,
723
+ Migration {
724
+ version : 3 ,
725
+ statements : SCHEMA_3 ,
726
+ } ,
727
+ Migration {
728
+ version : 4 ,
729
+ statements : SCHEMA_4 ,
730
+ } ,
731
+ Migration {
732
+ version : 5 ,
733
+ statements : SCHEMA_5 ,
734
+ } ,
735
+ Migration {
736
+ version : 6 ,
737
+ statements : SCHEMA_6 ,
738
+ } ,
739
+ Migration {
740
+ version : 7 ,
741
+ statements : SCHEMA_7 ,
742
+ } ,
743
+ Migration {
744
+ version : 8 ,
745
+ statements : SCHEMA_8 ,
746
+ } ,
747
+ Migration {
748
+ version : 9 ,
749
+ statements : SCHEMA_9 ,
750
+ } ,
751
+ Migration {
752
+ version : 10 ,
753
+ statements : SCHEMA_10 ,
754
+ } ,
755
+ Migration {
756
+ version : 11 ,
757
+ statements : SCHEMA_11 ,
758
+ } ,
759
+ Migration {
760
+ version : 12 ,
761
+ statements : SCHEMA_12 ,
762
+ } ,
763
+ Migration {
764
+ version : 13 ,
765
+ statements : SCHEMA_13 ,
766
+ } ,
767
+ Migration {
768
+ version : 14 ,
769
+ statements : SCHEMA_14 ,
770
+ } ,
771
+ ] ;
772
+
711
773
impl SignerDb {
712
774
/// The current schema version used in this build of the signer binary.
713
- pub const SCHEMA_VERSION : u32 = 12 ;
775
+ pub const SCHEMA_VERSION : u32 = 14 ;
714
776
715
777
/// Create a new `SignerState` instance.
716
778
/// This will create a new SQLite database at the given path
@@ -740,202 +802,6 @@ impl SignerDb {
740
802
}
741
803
}
742
804
743
- /// Migrate from schema 0 to schema 1
744
- fn schema_1_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
745
- if Self :: get_schema_version ( tx) ? >= 1 {
746
- // no migration necessary
747
- return Ok ( ( ) ) ;
748
- }
749
-
750
- for statement in SCHEMA_1 . iter ( ) {
751
- tx. execute_batch ( statement) ?;
752
- }
753
-
754
- Ok ( ( ) )
755
- }
756
-
757
- /// Migrate from schema 1 to schema 2
758
- fn schema_2_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
759
- if Self :: get_schema_version ( tx) ? >= 2 {
760
- // no migration necessary
761
- return Ok ( ( ) ) ;
762
- }
763
-
764
- for statement in SCHEMA_2 . iter ( ) {
765
- tx. execute_batch ( statement) ?;
766
- }
767
-
768
- Ok ( ( ) )
769
- }
770
-
771
- /// Migrate from schema 2 to schema 3
772
- fn schema_3_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
773
- if Self :: get_schema_version ( tx) ? >= 3 {
774
- // no migration necessary
775
- return Ok ( ( ) ) ;
776
- }
777
-
778
- for statement in SCHEMA_3 . iter ( ) {
779
- tx. execute_batch ( statement) ?;
780
- }
781
-
782
- Ok ( ( ) )
783
- }
784
-
785
- /// Migrate from schema 3 to schema 4
786
- fn schema_4_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
787
- if Self :: get_schema_version ( tx) ? >= 4 {
788
- // no migration necessary
789
- return Ok ( ( ) ) ;
790
- }
791
-
792
- for statement in SCHEMA_4 . iter ( ) {
793
- tx. execute_batch ( statement) ?;
794
- }
795
-
796
- Ok ( ( ) )
797
- }
798
-
799
- /// Migrate from schema 4 to schema 5
800
- fn schema_5_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
801
- if Self :: get_schema_version ( tx) ? >= 5 {
802
- // no migration necessary
803
- return Ok ( ( ) ) ;
804
- }
805
-
806
- for statement in SCHEMA_5 . iter ( ) {
807
- tx. execute_batch ( statement) ?;
808
- }
809
-
810
- Ok ( ( ) )
811
- }
812
-
813
- /// Migrate from schema 5 to schema 6
814
- fn schema_6_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
815
- if Self :: get_schema_version ( tx) ? >= 6 {
816
- // no migration necessary
817
- return Ok ( ( ) ) ;
818
- }
819
-
820
- for statement in SCHEMA_6 . iter ( ) {
821
- tx. execute_batch ( statement) ?;
822
- }
823
-
824
- Ok ( ( ) )
825
- }
826
-
827
- /// Migrate from schema 6 to schema 7
828
- fn schema_7_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
829
- if Self :: get_schema_version ( tx) ? >= 7 {
830
- // no migration necessary
831
- return Ok ( ( ) ) ;
832
- }
833
-
834
- for statement in SCHEMA_7 . iter ( ) {
835
- tx. execute_batch ( statement) ?;
836
- }
837
-
838
- Ok ( ( ) )
839
- }
840
-
841
- /// Migrate from schema 7 to schema 8
842
- fn schema_8_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
843
- if Self :: get_schema_version ( tx) ? >= 8 {
844
- // no migration necessary
845
- return Ok ( ( ) ) ;
846
- }
847
-
848
- for statement in SCHEMA_8 . iter ( ) {
849
- tx. execute_batch ( statement) ?;
850
- }
851
-
852
- Ok ( ( ) )
853
- }
854
-
855
- /// Migrate from schema 8 to schema 9
856
- fn schema_9_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
857
- if Self :: get_schema_version ( tx) ? >= 9 {
858
- // no migration necessary
859
- return Ok ( ( ) ) ;
860
- }
861
-
862
- for statement in SCHEMA_9 . iter ( ) {
863
- tx. execute_batch ( statement) ?;
864
- }
865
-
866
- Ok ( ( ) )
867
- }
868
-
869
- /// Migrate from schema 9 to schema 10
870
- fn schema_10_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
871
- if Self :: get_schema_version ( tx) ? >= 10 {
872
- // no migration necessary
873
- return Ok ( ( ) ) ;
874
- }
875
-
876
- for statement in SCHEMA_10 . iter ( ) {
877
- tx. execute_batch ( statement) ?;
878
- }
879
-
880
- Ok ( ( ) )
881
- }
882
-
883
- /// Migrate from schema 10 to schema 11
884
- fn schema_11_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
885
- if Self :: get_schema_version ( tx) ? >= 11 {
886
- // no migration necessary
887
- return Ok ( ( ) ) ;
888
- }
889
-
890
- for statement in SCHEMA_11 . iter ( ) {
891
- tx. execute_batch ( statement) ?;
892
- }
893
-
894
- Ok ( ( ) )
895
- }
896
-
897
- /// Migrate from schema 11 to schema 12
898
- fn schema_12_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
899
- if Self :: get_schema_version ( tx) ? >= 12 {
900
- // no migration necessary
901
- return Ok ( ( ) ) ;
902
- }
903
-
904
- for statement in SCHEMA_12 . iter ( ) {
905
- tx. execute_batch ( statement) ?;
906
- }
907
-
908
- Ok ( ( ) )
909
- }
910
-
911
- /// Migrate from schema 12 to schema 13
912
- fn schema_13_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
913
- if Self :: get_schema_version ( tx) ? >= 13 {
914
- // no migration necessary
915
- return Ok ( ( ) ) ;
916
- }
917
-
918
- for statement in SCHEMA_13 . iter ( ) {
919
- tx. execute_batch ( statement) ?;
920
- }
921
-
922
- Ok ( ( ) )
923
- }
924
-
925
- /// Migrate from schema 13 to schema 14
926
- fn schema_14_migration ( tx : & Transaction ) -> Result < ( ) , DBError > {
927
- if Self :: get_schema_version ( tx) ? >= 14 {
928
- // no migration necessary
929
- return Ok ( ( ) ) ;
930
- }
931
-
932
- for statement in SCHEMA_14 . iter ( ) {
933
- tx. execute_batch ( statement) ?;
934
- }
935
-
936
- Ok ( ( ) )
937
- }
938
-
939
805
/// Register custom scalar functions used by the database
940
806
fn register_scalar_functions ( & self ) -> Result < ( ) , DBError > {
941
807
// Register helper function for determining if a block is a tenure change transaction
@@ -961,35 +827,70 @@ impl SignerDb {
961
827
}
962
828
963
829
/// Either instantiate a new database, or migrate an existing one
964
- /// If the detected version of the existing database is 0 (i.e., a pre-migration
965
- /// logic DB, the DB will be dropped).
966
830
fn create_or_migrate ( & mut self ) -> Result < ( ) , DBError > {
967
831
self . register_scalar_functions ( ) ?;
968
832
let sql_tx = tx_begin_immediate ( & mut self . db ) ?;
969
- loop {
970
- let version = Self :: get_schema_version ( & sql_tx) ?;
971
- match version {
972
- 0 => Self :: schema_1_migration ( & sql_tx) ?,
973
- 1 => Self :: schema_2_migration ( & sql_tx) ?,
974
- 2 => Self :: schema_3_migration ( & sql_tx) ?,
975
- 3 => Self :: schema_4_migration ( & sql_tx) ?,
976
- 4 => Self :: schema_5_migration ( & sql_tx) ?,
977
- 5 => Self :: schema_6_migration ( & sql_tx) ?,
978
- 6 => Self :: schema_7_migration ( & sql_tx) ?,
979
- 7 => Self :: schema_8_migration ( & sql_tx) ?,
980
- 8 => Self :: schema_9_migration ( & sql_tx) ?,
981
- 9 => Self :: schema_10_migration ( & sql_tx) ?,
982
- 10 => Self :: schema_11_migration ( & sql_tx) ?,
983
- 11 => Self :: schema_12_migration ( & sql_tx) ?,
984
- 12 => Self :: schema_13_migration ( & sql_tx) ?,
985
- 13 => Self :: schema_14_migration ( & sql_tx) ?,
986
- 14 => break ,
987
- x => return Err ( DBError :: Other ( format ! (
988
- "Database schema is newer than supported by this binary. Expected version = {}, Database version = {x}" ,
989
- Self :: SCHEMA_VERSION ,
990
- ) ) ) ,
833
+
834
+ let mut current_db_version = Self :: get_schema_version ( & sql_tx) ?;
835
+ debug ! ( "Current SignerDB schema version: {}" , current_db_version) ;
836
+
837
+ for migration in MIGRATIONS . iter ( ) {
838
+ if current_db_version >= migration. version {
839
+ // don't need this migration, continue to see if we need later migrations
840
+ continue ;
841
+ }
842
+ if current_db_version != migration. version - 1 {
843
+ // This implies a gap or out-of-order migration definition,
844
+ // or the database is at a version X, and the next migration is X+2 instead of X+1.
845
+ sql_tx. rollback ( ) ?;
846
+ return Err ( DBError :: Other ( format ! (
847
+ "Migration step missing or out of order. Current DB version: {}, trying to apply migration for version: {}" ,
848
+ current_db_version, migration. version
849
+ ) ) ) ;
850
+ }
851
+ debug ! (
852
+ "Applying SignerDB migration for schema version {}" ,
853
+ migration. version
854
+ ) ;
855
+ for statement in migration. statements . iter ( ) {
856
+ sql_tx. execute_batch ( statement) ?;
991
857
}
858
+
859
+ // Verify that the migration script updated the version correctly
860
+ let new_version_check = Self :: get_schema_version ( & sql_tx) ?;
861
+ if new_version_check != migration. version {
862
+ sql_tx. rollback ( ) ?;
863
+ return Err ( DBError :: Other ( format ! (
864
+ "Migration to version {} failed to update DB version. Expected {}, got {}." ,
865
+ migration. version, migration. version, new_version_check
866
+ ) ) ) ;
867
+ }
868
+ current_db_version = new_version_check;
869
+ debug ! (
870
+ "Successfully migrated to schema version {}" ,
871
+ current_db_version
872
+ ) ;
992
873
}
874
+
875
+ match current_db_version. cmp ( & Self :: SCHEMA_VERSION ) {
876
+ std:: cmp:: Ordering :: Less => {
877
+ sql_tx. rollback ( ) ?;
878
+ return Err ( DBError :: Other ( format ! (
879
+ "Database migration incomplete. Current version: {}, SCHEMA_VERSION: {}" ,
880
+ current_db_version,
881
+ Self :: SCHEMA_VERSION
882
+ ) ) ) ;
883
+ }
884
+ std:: cmp:: Ordering :: Greater => {
885
+ sql_tx. rollback ( ) ?;
886
+ return Err ( DBError :: Other ( format ! (
887
+ "Database schema is newer than SCHEMA_VERSION. SCHEMA_VERSION = {}, Current version = {}. Did you forget to update SCHEMA_VERSION?" ,
888
+ Self :: SCHEMA_VERSION , current_db_version
889
+ ) ) ) ;
890
+ }
891
+ std:: cmp:: Ordering :: Equal => { }
892
+ }
893
+
993
894
sql_tx. commit ( ) ?;
994
895
self . remove_scalar_functions ( ) ?;
995
896
Ok ( ( ) )
0 commit comments