@@ -8,47 +8,47 @@ function Export-Migration
88 . DESCRIPTION
99 The `Export-Migration` function exports database objects, schemas, and data types as a Rivet migration. By default, it exports *all* non-system, non-Rivet objects, data types, and schemas. You can filter specific objects by passing their full name to the `Include` parameter. Wildcards are supported. Objects are matched on their schema *and* name.
1010
11- Extended properties are *not* exported, except table and column descriptions.
12-
1311 . EXAMPLE
1412 Export-Migration -SqlServerName 'some\instance' -Database 'database'
1513
1614 Demonstrates how to export an entire database.
1715 #>
1816 [CmdletBinding ()]
1917 param (
20- [Parameter (Mandatory )]
21- [string ]
2218 # The connection string for the database to connect to.
23- $SqlServerName ,
24-
2519 [Parameter (Mandatory )]
26- [string ]
27- # The database to connect to.
28- $Database ,
20+ [String ] $SqlServerName ,
2921
30- [string []]
22+ # The database to connect to.
23+ [Parameter (Mandatory )]
24+ [String ] $Database ,
25+
3126 # The names of the objects to export. Must include the schema if exporting a specific object. Wildcards supported.
3227 #
3328 # The default behavior is to export all non-system objects.
34- $Include ,
29+ [String []] $Include ,
30+
31+ # The name of the environment whose settings to return. If not provided, uses the default settings.
32+ [String ] $Environment ,
3533
36- [string []]
3734 # The names of any objects *not* to export. Matches the object name *and* its schema name, i.e. `schema.name`. Wildcards supported.
38- $Exclude ,
35+ [ String []] $Exclude ,
3936
40- [string []]
41- [ValidateSet (' CheckConstraint' , ' DataType' , ' DefaultConstraint' , ' ForeignKey' , ' Function' , ' Index' , ' PrimaryKey' , ' Schema' , ' StoredProcedure' , ' Synonym' , ' Table' , ' Trigger' , ' UniqueKey' , ' View' , ' XmlSchema' )]
4237 # Any object types to exclude.
43- $ExcludeType ,
38+ [ValidateSet (' CheckConstraint' , ' DataType' , ' DefaultConstraint' , ' ForeignKey' , ' Function' , ' Index' , ' PrimaryKey' , ' Schema' , ' StoredProcedure' , ' Synonym' , ' Table' , ' Trigger' , ' UniqueKey' , ' View' , ' XmlSchema' )]
39+ [String []] $ExcludeType ,
4440
45- [Switch ]
46- $NoProgress
41+ # The path to the Rivet configuration file to load. Defaults to `rivet.json` in the current directory.
42+ [String ] $ConfigFilePath ,
43+
44+ [Switch ] $NoProgress
4745 )
4846
4947 Set-StrictMode - Version ' Latest'
5048 Use-CallerPreference - Cmdlet $PSCmdlet - SessionState $ExecutionContext.SessionState
5149
50+ [Rivet.Configuration.Configuration ]$settings = Get-RivetConfig - Path $ConfigFilePath - Environment $Environment
51+
5252 $pops = New-Object ' Collections.Generic.Stack[string]'
5353 $popsHash = @ {}
5454 $exportedObjects = @ { }
@@ -971,9 +971,17 @@ where
971971
972972 if ( $externalDependencies.ContainsKey ($object.object_id ) )
973973 {
974- Write-Warning - Message (' Unable to export {0} {1}: it depends on external object {2}.' -f $object.type_desc , $object.full_name , $externalDependencies [$object.object_id ])
975- $exportedObjects [$object.object_id ] = $true
976- continue
974+ $indexOfReferencedDatabase = [array ]::IndexOf($settings.Databases.Name , $externalDependencies [$object.object_id ].DatabaseName)
975+ $indexOfCurrentDatabase = [array ]::IndexOf($settings.Databases.Name , $Database )
976+
977+ # If the external depenedency's database does not get applied BEFORE the current database, do not allow
978+ # references to the external dependency.
979+ if ( ($indexOfReferencedDatabase -gt $indexOfCurrentDatabase ) -or ($indexOfReferencedDatabase -lt 0 ) -or ($indexOfCurrentDatabase -lt 0 ) )
980+ {
981+ Write-Warning - Message (' Unable to export {0} {1}: it depends on external object {2}.' -f $object.type_desc , $object.full_name , $externalDependencies [$object.object_id ].ExternalName)
982+ $exportedObjects [$object.object_id ] = $true
983+ continue
984+ }
977985 }
978986
979987 switch ($object.type_desc )
@@ -1163,12 +1171,18 @@ where
11631171-- SCHEMAS
11641172select
11651173 sys.schemas.name,
1166- sys.sysusers.name as owner
1174+ sys.sysusers.name as owner,
1175+ sys.extended_properties.value as description
11671176from
11681177 sys.schemas
11691178 join
11701179 sys.sysusers
1171- on sys.schemas.principal_id = sys.sysusers.uid'
1180+ on sys.schemas.principal_id = sys.sysusers.uid
1181+ left join
1182+ sys.extended_properties
1183+ on sys.extended_properties.class = 3
1184+ and sys.extended_properties.major_id = sys.schemas.schema_id
1185+ and sys.extended_properties.name = '' MS_Description'' '
11721186 function Export-Schema
11731187 {
11741188 param (
@@ -1187,9 +1201,14 @@ from
11871201 {
11881202 return
11891203 }
1204+ $description = $schema.description
1205+ if ( $description )
1206+ {
1207+ $description = ' -Description '' {0}'' ' -f ($description -replace ' '' ' , ' '''' ' )
1208+ }
11901209
11911210 Write-ExportingMessage - Schema $Object.schema_name - Type Schema
1192- ' Add-Schema -Name '' {0}'' -Owner '' {1}'' ' -f $schema.name , $schema.owner
1211+ ' Add-Schema -Name '' {0}'' -Owner '' {1}'' {2} ' -f $schema.name , $schema.owner , $description
11931212 $exportedSchemas [$schema.name ] = $true
11941213 Push-PopOperation (' Remove-Schema -Name '' {0}'' ' -f $schema.name )
11951214 }
@@ -1534,8 +1553,22 @@ where
15341553 Write-ExportingMessage - Schema $Object.schema_name - Name $Object.name - Type View
15351554 if ( $view -match $createPreambleRegex )
15361555 {
1556+ $description = $Object.description
1557+ if ( $description )
1558+ {
1559+ $description = ' -Description '' {0}'' ' -f ($description -replace ' '' ' , ' '''' ' )
1560+ }
1561+
15371562 $view = $view -replace $createPreambleRegex , ' '
1538- ' Add-View{0} -Name '' {1}'' -Definition @'' {2}{3}{2}'' @' -f $schema , $Object.name , [Environment ]::NewLine, $view
1563+ ' Add-View{0} -Name '' {1}'' {2} -Definition @'' {3}{4}{3}'' @' -f $schema , $Object.name , $description , [Environment ]::NewLine, $view
1564+
1565+ # Get view's columns that have extended properties
1566+ $viewColumns = Invoke-Query - Query $columnsQuery | Where-Object { $_.object_id -eq $Object.object_id -and $_.description }
1567+ foreach ( $column in $viewColumns )
1568+ {
1569+ $colDescription = ' -Description '' {0}'' ' -f ($column.description -replace ' '' ' , ' '''' ' )
1570+ ' Add-ExtendedProperty -SchemaName '' {0}'' -ViewName '' {1}'' -ColumnName '' {2}'' -Value {3}' -f $Object.schema_name , $Object.object_name , $column.column_name , $colDescription
1571+ }
15391572 }
15401573 else
15411574 {
@@ -1796,7 +1829,7 @@ where
17961829 if ( $objectTypes -contains ' SQL_TRIGGER' )
17971830 {
17981831 $triggers = Invoke-Query - Query $triggersQuery
1799- $triggers | ForEach-Object { $triggersByID [$_.object_id ] = $_ }
1832+ $triggers | ForEach-Object { $triggersByID [$_.object_id ] = $_ }
18001833 $triggers | Group-Object - Property ' parent_id' | ForEach-Object { $triggersByTable [[int ]$_.Name ] = $_.Group }
18011834 }
18021835
@@ -1806,7 +1839,7 @@ where
18061839 $uniqueKeys = Invoke-Query - Query $uniqueKeysQuery
18071840 $uniqueKeys | ForEach-Object { $uniqueKeysByID [$_.object_id ] = $_ }
18081841 $uniqueKeys | Group-Object - Property ' parent_object_id' | ForEach-Object { $uniqueKeysByTable [[int ]$_.Name ] = $_.Group }
1809-
1842+
18101843 # UNIQUE KEY COLUMNS
18111844 $uniqueKeyColumns = Invoke-Query - Query $uniqueKeysColumnsQuery
18121845 $uniqueKeyColumns | Group-Object - Property ' object_id' | ForEach-Object { $uniqueKeyColumnsByObjectID [[int ]$_.Name ] = $_.Group }
@@ -1862,7 +1895,7 @@ where
18621895
18631896 if ( $row.referenced_server_name -or ($row.referenced_database_name -ne $null -and $row.referenced_database_name -ne $Database ) )
18641897 {
1865- $externalDependencies [$row.referencing_id ] = $externalName
1898+ $externalDependencies [$row.referencing_id ] = @ { ExternalName = $externalName ; DatabaseName = $row .referenced_database_name }
18661899 }
18671900 else
18681901 {
@@ -1882,21 +1915,21 @@ where
18821915 $schemas
18831916 $indexes
18841917 $dataTypes
1885- } |
1886- Measure-Object |
1918+ } |
1919+ Measure-Object |
18871920 Select-Object - ExpandProperty ' Count'
18881921
18891922 if ( $writeProgress )
18901923 {
1891- Write-Progress - Activity $activity
1924+ Write-Progress - Activity $activity
18921925 }
18931926
1894- $timer |
1927+ $timer |
18951928 Add-Member - Name ' ExportCount' - Value 0 - MemberType NoteProperty - PassThru |
18961929 Add-Member - MemberType NoteProperty - Name ' Activity' - Value $activity - PassThru |
18971930 Add-Member - MemberType NoteProperty - Name ' CurrentOperation' - Value ' ' - PassThru |
18981931 Add-Member - MemberType NoteProperty - Name ' TotalCount' - Value $totalOperationCount
1899-
1932+
19001933 if ( $writeProgress )
19011934 {
19021935 # Write-Progress is *expensive*. Only do it if the user is interactive and only every 1/10th of a second.
0 commit comments