Files
sql-server-samples/samples/features/sql-data-sync/UpdateSyncSchema.ps1
T
2023-02-20 19:33:29 +00:00

278 lines
11 KiB
PowerShell

using namespace Microsoft.Azure.Commands.Sql.DataSync.Model
using namespace System.Collections.Generic
param (
[Parameter(Mandatory=$true)][string]$SubscriptionId = "",
[Parameter(Mandatory=$true)][string]$ResourceGroupName = "",
[Parameter(Mandatory=$true)][string]$ServerName = "",
[Parameter(Mandatory=$true)][string]$DatabaseName = "",
[Parameter(Mandatory=$true)][string]$SyncGroupName = "",
[string]$MemberName = "",
[int]$TimeoutInSeconds = 900,
[switch]$RefreshDatabaseSchema = $false,
[switch]$AddAllTables = $false,
[string]$TablesAndColumnsToAdd = "",
[string]$TablesAndColumnsToRemove = "")
$TablesAndColumnsToAddList = [System.Collections.ArrayList]::new($TablesAndColumnsToAdd.Split(","))
$TablesAndColumnsToRemoveList = [System.Collections.ArrayList]::new($TablesAndColumnsToRemove.Split(","))
$TempFile = $env:TEMP+"\syncSchema.json"
##login to Azure account
login-azurermaccount
##select the subscription
select-azurermsubscription -SubscriptionId $SubscriptionId
##get sync group and check if sync group exists
$SyncGroup = Get-AzureRmSqlSyncGroup -ResourceGroupName $ResourceGroupName `
-ServerName $ServerName `
-DatabaseName $DatabaseName `
-Name $SyncGroupName
if ($SyncGroup -eq $null)
{
Write-Host "Sync group $SyncGroupName is not found."
exit;
}
##if member name specified, check if member exists
if ($MemberName -ne "")
{
$SyncMember = Get-AzureRmSqlSyncMember -ResourceGroupName $ResourceGroupName `
-ServerName $ServerName `
-DatabaseName $DatabaseName `
-SyncGroupName $SyncGroupName `
-Name $MemberName
if ($SyncMember -eq $null)
{
Write-Error "Sync member $MemberName is not found."
exit;
}
}
## Refresh database schema if -RefreshDatabaseSchema is specified
$DatabaseSchema = ""
if ($RefreshDatabaseSchema)
{
$StartTime = Get-Date
if ($MemberName -eq "")
{
Write-Host "Refreshing database schema from hub database"
Update-AzureRmSqlSyncSchema -ResourceGroupName $ResourceGroupName `
-ServerName $ServerName `
-DatabaseName $DatabaseName `
-SyncGroupName $SyncGroupName
}
else
{
Write-Host "Refreshing database schema from member $MemberName"
Update-AzureRmSqlSyncSchema -ResourceGroupName $ResourceGroupName `
-ServerName $ServerName `
-DatabaseName $DatabaseName `
-SyncGroupName $SyncGroupName `
-SyncMemberName $MemberName
}
## Wait until the database schema is refreshed
$TimeoutTimeSpan = New-TimeSpan -Start $StartTime -End $StartTime
$IsSucceeded = $false
While ($TimeoutTimeSpan.TotalSeconds -le $TimeoutInSeconds)
{
Start-Sleep -s 10
if ($MemberName -eq "")
{
$DatabaseSchema = Get-AzureRmSqlSyncSchema -SyncGroupName $SyncGroupName `
-ServerName $ServerName `
-DatabaseName $DatabaseName `
-ResourceGroupName $ResourceGroupName
}
else
{
$DatabaseSchema = Get-AzureRmSqlSyncSchema -SyncGroupName $SyncGroupName `
-ServerName $ServerName `
-DatabaseName $DatabaseName `
-ResourceGroupName $ResourceGroupName `
-SyncMemberName $MemberName
}
if ($DatabaseSchema.LastUpdateTime -gt $StartTime.ToUniversalTime())
{
Write-Host "Database schema succeeded"
$IsSucceeded = $true
break;
}
}
if (-not $IsSucceeded)
{
Write-Error "Refresh failed or timeout"
exit;
}
}
else
{
if ($MemberName -eq "")
{
$DatabaseSchema = Get-AzureRmSqlSyncSchema -SyncGroupName $SyncGroupName `
-ServerName $ServerName `
-DatabaseName $DatabaseName `
-ResourceGroupName $ResourceGroupName
}
else
{
$DatabaseSchema = Get-AzureRmSqlSyncSchema -SyncGroupName $SyncGroupName `
-ServerName $ServerName `
-DatabaseName $DatabaseName `
-ResourceGroupName $ResourceGroupName `
-SyncMemberName $MemberName
}
}
if ($DatabaseSchema.LastUpdateTime -eq $null)
{
Write-Error "Database schema is not available. Refresh the database schema by specify -RefreshDatabaseSchema"
Exit;
}
## Remove specified tables and columns from sync schema
## Also remove tables and columns which is not defined in the database if database schema is refreshed
$TablesToRemove = New-Object "System.Collections.Generic.List[AzureSqlSyncGroupSchemaTableModel]";
foreach ($TableSchema in $SyncGroup.Schema.Tables)
{
$TableInDatabase = $DatabaseSchema.Tables | ? QuotedName -eq $TableSchema.QuotedName
if ($TablesAndColumnsToRemoveList.Contains($TableSchema.QuotedName) -or $TableInDatabase -eq $null)
{
$TablesToRemove.Add($TableSchema);
}
else
{
$ColumnsToRemove = New-Object "System.Collections.Generic.List[AzureSqlSyncGroupSchemaColumnModel]";
foreach($ColumnSchema in $TableSchema.Columns)
{
$ColumnInTable = $TableInDatabase[0].Columns | ? QuotedName -eq $ColumnSchema.QuotedName
$FullName = $TableSchema.QuotedName+"."+$ColumnSchema.QuotedName
if ($TablesAndColumnsToRemoveList.Contains($FullName) -or $ColumnInTable -eq $null)
{
$ColumnsToRemove.Add($ColumnSchema);
}
}
if ($ColumnsToRemove.Count -gt 0)
{
foreach ($ColumnToRemove in $ColumnsToRemove)
{
$FullName = $TableSchema.QuotedName+"."+$ColumnToRemove.QuotedName
Write-Host "$FullName is being removed from sync schema"
$TableSchema.Columns.Remove($ColumnToRemove);
}
}
}
}
if ($TablesToRemove.Count -gt 0)
{
foreach ($TableToRemove in $TablesToRemove)
{
Write-Host $TableToRemove.QuotedName" is being removed from sync schema"
$SyncGroup.Schema.Tables.Remove($TableToRemove);
}
}
## Add specified tables and columns to the sync schema
foreach ($TableSchema in $DatabaseSchema.Tables)
{
## Reuse if the table already exists in the schema; Otherwise, create a new one
$newTableSchema = $SyncGroup.Schema.Tables | ? QuotedName -eq $TableSchema.QuotedName
$AddNewTable = $false
if ($newTableSchema -eq $null)
{
$AddNewTable = $true
$newTableSchema = [AzureSqlSyncGroupSchemaTableModel]::new()
$newTableSchema.QuotedName = $TableSchema.QuotedName
$newTableSchema.Columns = [List[AzureSqlSyncGroupSchemaColumnModel]]::new();
}
## If the table name is specified, add all valid columns
$addAllColumns = $false
if ($AddAllTables -or $TablesAndColumnsToAddList.Contains($TableSchema.QuotedName))
{
## If the table is not supported, move to next table
if ($TableSchema.HasError)
{
$fullTableName = $TableSchema.QuotedName
Write-Host "Can't add table $fullTableName to the sync schema" -foregroundcolor "Red"
Write-Host $TableSchema.ErrorId -foregroundcolor "Red"
continue;
}
else
{
$addAllColumns = $true
}
}
## Add columns
foreach($columnSchema in $TableSchema.Columns)
{
$fullColumnName = $TableSchema.QuotedName + "." + $columnSchema.QuotedName
if ($addAllColumns -or $TablesAndColumnsToAddList.Contains($fullColumnName))
{
## If the column already exists in the sync schema or not supported, ignore
$Column = $newTableSchema.Columns | ? QuotedName -eq $columnSchema.QuotedName
if ($Column -ne $null)
{
Write-Host "Column $fullColumnName is already in the schema"
}
elseif ((-not $addAllColumns) -and $TableSchema.HasError)
{
Write-Host "Can't add column $fullColumnName to the sync schema" -foregroundcolor "Red"
Write-Host $tableSchema.ErrorId -foregroundcolor "Red"
}
elseif ((-not $addAllColumns) -and $columnSchema.HasError)
{
Write-Host "Can't add column $fullColumnName to the sync schema" -foregroundcolor "Red"
Write-Host $columnSchema.ErrorId -foregroundcolor "Red"
}
else
{
Write-Host "Adding $fullColumnName to the sync schema"
$newColumnSchema = [AzureSqlSyncGroupSchemaColumnModel]::new()
$newColumnSchema.QuotedName = $columnSchema.QuotedName
$newColumnSchema.DataSize = $columnSchema.DataSize
$newColumnSchema.DataType = $columnSchema.DataType
$newTableSchema.Columns.Add($newColumnSchema)
}
}
}
if ($newTableSchema.Columns.Count -gt 0 -and $AddNewTable)
{
$SyncGroup.Schema.Tables.Add($newTableSchema)
}
}
## Update the master sync member name if database metadata is from the member
if ($MemberName -ne "")
{
$SyncGroup.Schema.MasterSyncMemberName = $MemberName
}
else
{
$SyncGroup.Schema.MasterSyncMemberName = $null
}
$schemaString = $SyncGroup.Schema | ConvertTo-Json -depth 5 -Compress
# workaround a powershell bug if the PowerShell version is too early
$schemaString = $schemaString.Replace('"Tables"', '"tables"').Replace('"Columns"', '"columns"').Replace('"QuotedName"', '"quotedName"').Replace('"MasterSyncMemberName"','"masterSyncMemberName"')
Write-Host "Write the schema to $TempFile"
$schemaString | Out-File $TempFile
# Update the sync schema
Update-AzureRmSqlSyncGroup -ResourceGroupName $ResourceGroupName `
-ServerName $ServerName `
-DatabaseName $DatabaseName `
-Name $SyncGroupName `
-SchemaFile $TempFile