# Copyright 2010 - 2011 Adam Boddington
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
param(
[string]$Server = $(throw "Server required."),
[string]$Database = $(throw "Database required."),
[switch]$Maximum,
[switch]$Minimum,
[switch]$Rollback,
[string]$Target)
$ErrorActionPreference = "Stop"
"" # Write line.
# Ensure the Version table exists and has a record.
SQLCMD.EXE -S $Server -d $Database -E -i ensure-version-table.sql -b
""
# Get the current version from the database.
$CurrentVersion = SQLCMD.EXE -S $Server -d $Database -E -i print-current-version.sql -b
# Find all migrations. Each subdirectory is a migration.
$MigrationDirectories = Get-ChildItem | Where-Object { $_.PSIsContainer }
if (!$MigrationDirectories) { "No migrations to run."; ""; exit }
# [NONE] is a special case for no migrations applied.
$Migrations = @("[NONE]") + ($MigrationDirectories | ForEach-Object -Process { $_.Name })
$CurrentVersionIndex = [array]::IndexOf($Migrations, $CurrentVersion)
if ($CurrentVersionIndex -eq -1) { throw "Current version not found. (" + $CurrentVersion + ")" }
"Current Version: " + $CurrentVersion
# Determine target version index from the flags or target.
if ($Maximum) { $TargetVersionIndex = $Migrations.Count - 1 }
elseif ($Minimum) { $TargetVersionIndex = 0 }
elseif ($Rollback) { $TargetVersionIndex = $CurrentVersionIndex - 1 }
else { $TargetVersionIndex = [array]::IndexOf($Migrations, $Target) }
if ($Rollback -and $TargetVersionIndex -eq -1) { throw "Nothing to rollback." }
if ($TargetVersionIndex -eq -1) { throw "Target version not found. (" + $Target + ")" }
$TargetVersion = $Migrations[$TargetVersionIndex]
" Target Version: " + $TargetVersion
""
if ($CurrentVersionIndex -eq $TargetVersionIndex) { "No migrations to run."; ""; exit }
# Initialise an empty array to collect the migration scripts.
$MigrationScripts = @()
# Collect the up migration scripts.
for ($x = $CurrentVersionIndex + 1; $x -le $TargetVersionIndex; $x++) {
$MigrationScripts += $MigrationDirectories[$x - 1].Name | Join-Path -ChildPath up.sql }
# Collect the down migration scripts.
for ($x = $CurrentVersionIndex; $x -gt $TargetVersionIndex; $x--) {
$MigrationScripts += $MigrationDirectories[$x - 1].Name | Join-Path -ChildPath down.sql }
"Migration Scripts"
"================="
$MigrationScripts
""
# Build the migration script.
$Go = "`r`nGO`r`n"
"BEGIN TRANSACTION" + $Go | Out-File -FilePath migration.sql
$MigrationScripts | ForEach-Object -Process { (Get-Content -Path $_) + $Go | Out-File -FilePath migration.sql -Append }
"UPDATE [dbo].[Version] SET [Current] = '" + $TargetVersion + "'" + $Go | Out-File -FilePath migration.sql -Append
"COMMIT TRANSACTION" + $Go | Out-File -FilePath migration.sql -Append
# Execute the migration script.
"Executing Migration Scripts"
"==========================="
SQLCMD.EXE -S $Server -d $Database -E -i migration.sql -b
""
PRINT 'Checking the existence of the Version table.'
IF NOT EXISTS (SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Version]') AND type IN (N'U'))
BEGIN
PRINT 'The Version table does not exist.'
PRINT 'Creating the Version table...'
CREATE TABLE [dbo].[Version] ([Current] [nvarchar](100) NOT NULL)
END
PRINT 'Checking the existence of a row in the Version table.'
IF NOT EXISTS (SELECT 1 FROM [dbo].[Version])
BEGIN
PRINT 'A row does not exist in the Version table.'
PRINT 'Creating a row in the Version table...'
INSERT [dbo].[Version] VALUES ('[NONE]')
END