<% 'Represents a single migration (either up or down) Class Migration_Class Private m_name Private m_migration_instance Private m_sql_array Private m_sql_array_size Private m_connection Private m_has_errors Public Tracing 'bool Public Property Get Name Name = m_name End Property Public Property Get Migration set Migration = m_migration_instance End Property Public Property Set Migration(obj) set m_migration_instance = obj End Property Public Property Get HasErrors HasErrors = m_has_errors End Property Private Sub Class_Initialize m_sql_array = array() redim m_sql_array(-1) m_has_errors = false End Sub Public Sub Initialize(name, migration_instance, connection) m_name = name set m_migration_instance = migration_instance set m_migration_instance.Migration = Me 'how circular can we get? ... set m_connection = connection End Sub Private Sub Class_Terminate 'm_connection.Close 'set m_connection = Nothing End Sub Public Sub [Do](sql) dim new_size : new_size = ubound(m_sql_array) + 1 redim preserve m_sql_array(new_size) m_sql_array(new_size) = sql 'put "Added command: " & sql End Sub Public Sub Irreversible Err.Raise 1, "Migration_Class:Irreversible", "Migration cannot proceed because this migration is irreversible." End Sub Public Sub DownDataWarning put "Migration can be downversioned but data changes cannot take place due to the nature of the Up migration in this set." End Sub Public Function Query(sql) put "Query: " & sql set Query = m_connection.Execute(sql) End Function Public Sub DoUp Migration.Up ShowCommands ExecuteCommands End Sub Public Sub DoDown Migration.Down ShowCommands ExecuteCommands End Sub Private Sub ShowCommands put "" put "Commands:" dim i : i = 0 For i = 0 to ubound(m_sql_array) put "    Command: " & m_sql_array(i) Next put "" End Sub Private Sub ExecuteCommands dim i : i = 0 dim sql m_connection.BeginTrans 'wrap entire process in transaction, rollback If error encountered on any statement For i = 0 to ubound(m_sql_array) sql = m_sql_array(i) If not m_has_errors then 'avoid further processing If errors exist On Error Resume Next put "Executing: " & sql m_connection.Execute sql If Err.Number <> 0 then 'something went wrong, rollback the transaction and display an error m_has_errors = true m_connection.RollbackTrans put_error "Error during migration: " & Err.Description put_error "SQL: " & sql exit sub End If On Error Goto 0 End If Next m_connection.CommitTrans 'surprisingly no errors were encountered, so commit the entire transaction End Sub 'force font color dIfference Private Sub put(s) If Me.Tracing then response.write "
" & s & "
" End Sub End Class '--------------------------------------------------------------------------------------------------------------------- 'Represents the collection of migrations to be performed Class Migrations_Class Private m_migrations_array ' 1-based to match migration naming scheme, ignore the first element Private m_migrations_array_size Private m_version Private m_connection Private m_connection_string Private m_has_errors Public Tracing 'bool Private Sub Class_Initialize m_migrations_array = array() m_migrations_array_size = 0 ' 1-based, ignore the first element redim m_migrations_array(m_migrations_array_size) m_has_errors = false End Sub Private Sub Class_Terminate On Error Resume Next m_connection.Close set m_connection = Nothing On Error Goto 0 End Sub 'force font color dIfference Private Sub put(s) If Me.Tracing then response.write "
" & s & "
" End Sub Public Sub Initialize(connection_string) m_connection_string = connection_string set m_connection = Server.CreateObject("ADODB.Connection") m_connection.Open m_connection_string put "Initialized: " & typename(m_connection) End Sub Public Sub Add(name) m_migrations_array_size = m_migrations_array_size + 1 redim preserve m_migrations_array(m_migrations_array_size) dim M : set M = new Migration_Class dim migration_instance : set migration_instance = eval("new " & name) M.Initialize name, migration_instance, m_connection M.Tracing = Me.Tracing set m_migrations_array(m_migrations_array_size) = M End Sub Public Sub MigrateUp MigrateUpTo m_migrations_array_size End Sub Public Sub MigrateUpBy(num) MigrateUpTo Version + num End Sub Public Sub MigrateUpTo(requested_version) requested_version = CInt(requested_version) put "Migrating Up To Version " & requested_version dim M, class_name If Version >= requested_version then put_error "DB already at higher version than requested up migration." ElseIf requested_version > m_migrations_array_size then put_error "Requested version exceeds available migrations. Only " & m_migrations_array_size & " migrations are available." Else While (NextVersion <= requested_version) and (not m_has_errors) set M = m_migrations_array(NextVersion) put "" put "Up: " & M.name & "" M.DoUp m_has_errors = M.HasErrors If not m_has_errors then IncrementVersion Wend End If End Sub Public Sub MigrateDown MigrateDownTo 0 End Sub Public Sub MigrateDownBy(num) MigrateDownTo Version - num End Sub Public Sub MigrateDownTo(requested_version) requested_version = CInt(requested_version) put "Migrating Down To Version: " & requested_version dim M, class_name If requested_version < 0 then put_error "Cannot migrate down to a version less than 0." ElseIf requested_version > Version then put_error "Cannot migrate down to a version higher than the current version." ElseIf requested_version = Version then put_error "Cannot migrate down to the current version, already there." Else While (Version > requested_version) and (not m_has_errors) set M = m_migrations_array(Version) put "" put "Down: " & M.Name & "" M.DoDown m_has_errors = M.HasErrors If not m_has_errors then DecrementVersion Wend End If End Sub Public Property Get Version If IsEmpty(m_version) then m_version = GetDBVersion() End If Version = m_version End Property Private Property Let Version(val) m_version = val m_connection.Execute "update meta_migrations set version = " & m_version End Property Public Property Get NextVersion NextVersion = Version + 1 End Property Private Function GetDBVersion() dim rs : set rs = m_connection.Execute("select version from meta_migrations") If rs.BOF or rs.EOF then GetDBVersion = NULL Else GetDBVersion = rs("version") End If rs.Close set rs = Nothing End Function Private Sub IncrementVersion If not m_has_errors then Version = Version + 1 End Sub Private Sub DecrementVersion If not m_has_errors then Version = Version - 1 End Sub End Class dim Migrations_Class__Singleton Function Migrations() If IsEmpty(Migrations_Class__Singleton) then set Migrations_Class__Singleton = new Migrations_Class set Migrations = Migrations_Class__Singleton End Function %>