Skip to content

Commit a45049f

Browse files
authored
Restore-SqlDscDatabase: New command for database restoration (#2367)
1 parent 84b8793 commit a45049f

22 files changed

+3324
-8
lines changed

.github/instructions/dsc-community-style-guidelines-powershell.instructions.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ function Get-Something
200200
- Assign function results to variables rather than inline calls
201201
- Return a single, consistent object type per function
202202
- return `$null` for no objects/non-terminating errors
203-
- Use `::new()` static method instead of `New-Object` for .NET types, e.g `[System.Management.Automation.ErrorRecord]::new()`
203+
- For most .NET types, use the `::new()` static method instead of `New-Object`, e.g., `[System.DateTime]::new()`.
204+
- For error handling, use dedicated helper commands instead:
205+
- Use `New-Exception` instead of `[System.Exception]::new(...)`
206+
- Use `New-ErrorRecord` instead of `[System.Management.Automation.ErrorRecord]::new(...)`
204207

205208
### Security & Safety
206209

.github/workflows/code-analysis-built-module.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646
.\build.ps1 -Tasks 'noop'
4747
4848
Write-Information -MessageData 'Load SMO stubs into session.' -InformationAction 'Continue'
49-
Add-Type -Path './tests/Unit/Stubs/SMO.cs'
49+
Add-Type -Path './tests/Unit/Stubs/SMO.cs' -ReferencedAssemblies 'System.Data', 'System.Xml'
5050
5151
Write-Information -MessageData 'Import module ConvertToSARIF into the session.' -InformationAction 'Continue'
5252
Import-Module -Name 'ConvertToSARIF' -Force

.github/workflows/code-analysis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ jobs:
4646
.\build.ps1 -Tasks 'noop'
4747
4848
Write-Information -MessageData 'Load SMO stubs into session.' -InformationAction 'Continue'
49-
Add-Type -Path './tests/Unit/Stubs/SMO.cs'
49+
Add-Type -Path './tests/Unit/Stubs/SMO.cs' -ReferencedAssemblies 'System.Data', 'System.Xml'
5050
5151
Write-Information -MessageData 'Import module ConvertToSARIF into the session.' -InformationAction 'Continue'
5252
Import-Module -Name 'ConvertToSARIF' -Force

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
### Added
99

10+
- Added public command `Get-SqlDscBackupFileList` to read the list of database
11+
files contained in a SQL Server backup file. Useful for planning file
12+
relocations during restore operations ([issue #2026](https://github.com/dsccommunity/SqlServerDsc/issues/2026)).
13+
- Added public command `Test-SqlDscBackupFile` to verify the integrity of a
14+
SQL Server backup file ([issue #2026](https://github.com/dsccommunity/SqlServerDsc/issues/2026)).
15+
- Added public command `Restore-SqlDscDatabase` to restore SQL Server databases
16+
from backup files. Supports full, differential, transaction log, and file
17+
restores with options for file relocation (both simple path-based and
18+
explicit RelocateFile objects), point-in-time recovery, NoRecovery/Standby
19+
modes, and various performance tuning options ([issue #2026](https://github.com/dsccommunity/SqlServerDsc/issues/2026)).
20+
- Added public command `Backup-SqlDscDatabase`. Supports full, differential,
21+
and transaction log backups with options for compression, copy-only, checksum,
22+
and retention ([issue #2365](https://github.com/dsccommunity/SqlServerDsc/issues/2365)).
1023
- Added public command `Invoke-SqlDscScalarQuery` to execute scalar queries using
1124
`Server.ConnectionContext.ExecuteScalar()`. Server-level, lightweight execution
1225
that does not require any database to be online

azure-pipelines.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,9 @@ stages:
344344
'tests/Integration/Commands/New-SqlDscDatabase.Integration.Tests.ps1'
345345
'tests/Integration/Commands/New-SqlDscDatabaseSnapshot.Integration.Tests.ps1'
346346
'tests/Integration/Commands/Backup-SqlDscDatabase.Integration.Tests.ps1'
347+
'tests/Integration/Commands/Test-SqlDscBackupFile.Integration.Tests.ps1'
348+
'tests/Integration/Commands/Get-SqlDscBackupFileList.Integration.Tests.ps1'
349+
'tests/Integration/Commands/Restore-SqlDscDatabase.Integration.Tests.ps1'
347350
'tests/Integration/Commands/Resume-SqlDscDatabase.Integration.Tests.ps1'
348351
'tests/Integration/Commands/Suspend-SqlDscDatabase.Integration.Tests.ps1'
349352
'tests/Integration/Commands/Get-SqlDscCompatibilityLevel.Integration.Tests.ps1'
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<#
2+
.SYNOPSIS
3+
Defines a file specification from a SQL Server backup file.
4+
5+
.DESCRIPTION
6+
This class represents a file specification that is returned when reading
7+
the file list from a SQL Server backup file. It contains the properties
8+
describing each file stored in the backup, which is useful for planning
9+
file relocations during database restores.
10+
11+
.PARAMETER LogicalName
12+
The logical name of the file as stored in the backup. This name is used
13+
when specifying file relocations during restore operations.
14+
15+
.PARAMETER PhysicalName
16+
The original physical file path where the file was located when the
17+
backup was created.
18+
19+
.PARAMETER Type
20+
The type of file. Common values are 'D' for data files and 'L' for
21+
log files.
22+
23+
.PARAMETER FileGroupName
24+
The name of the file group that contains the file. This is typically
25+
'PRIMARY' for the primary file group.
26+
27+
.PARAMETER Size
28+
The size of the file in bytes.
29+
30+
.PARAMETER MaxSize
31+
The maximum size to which the file can grow in bytes.
32+
33+
.NOTES
34+
This class is returned by the Get-SqlDscBackupFileList command and can
35+
be used to understand the file structure of a backup before performing
36+
a restore operation.
37+
38+
.EXAMPLE
39+
$serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance'
40+
$files = $serverObject | Get-SqlDscBackupFileList -BackupFile 'C:\Backups\MyDatabase.bak'
41+
$files | ForEach-Object { Write-Host "$($_.LogicalName): $($_.Type)" }
42+
43+
Gets the file list from a backup and displays each file's logical name
44+
and type.
45+
#>
46+
class BackupFileSpec
47+
{
48+
[System.String]
49+
$LogicalName
50+
51+
[System.String]
52+
$PhysicalName
53+
54+
[System.String]
55+
$Type
56+
57+
[System.String]
58+
$FileGroupName
59+
60+
[System.Int64]
61+
$Size
62+
63+
[System.Int64]
64+
$MaxSize
65+
66+
BackupFileSpec()
67+
{
68+
}
69+
70+
BackupFileSpec(
71+
[System.String] $logicalName,
72+
[System.String] $physicalName,
73+
[System.String] $type,
74+
[System.String] $fileGroupName,
75+
[System.Int64] $size,
76+
[System.Int64] $maxSize
77+
)
78+
{
79+
$this.LogicalName = $logicalName
80+
$this.PhysicalName = $physicalName
81+
$this.Type = $type
82+
$this.FileGroupName = $fileGroupName
83+
$this.Size = $size
84+
$this.MaxSize = $maxSize
85+
}
86+
}

source/Public/Backup-SqlDscDatabase.ps1

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@
139139
function Backup-SqlDscDatabase
140140
{
141141
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')]
142-
[OutputType()]
143142
[OutputType([Microsoft.SqlServer.Management.Smo.Database])]
144143
[CmdletBinding(DefaultParameterSetName = 'ServerObject', SupportsShouldProcess = $true, ConfirmImpact = 'Low')]
145144
param
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<#
2+
.SYNOPSIS
3+
Gets the list of files contained in a SQL Server backup file.
4+
5+
.DESCRIPTION
6+
This command reads and returns the list of database files contained in
7+
a SQL Server backup file using SQL Server Management Objects (SMO). This
8+
is useful for understanding the file structure of a backup before
9+
performing a restore operation, especially when file relocation is needed.
10+
11+
.PARAMETER ServerObject
12+
Specifies the current server connection object.
13+
14+
.PARAMETER BackupFile
15+
Specifies the full path to the backup file to read.
16+
17+
.PARAMETER FileNumber
18+
Specifies the backup set number to read when the backup file contains
19+
multiple backup sets. Default is 1.
20+
21+
.EXAMPLE
22+
$serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance'
23+
$serverObject | Get-SqlDscBackupFileList -BackupFile 'C:\Backups\MyDatabase.bak'
24+
25+
Gets the list of files contained in the specified backup file.
26+
27+
.EXAMPLE
28+
$serverObject = Connect-SqlDscDatabaseEngine -InstanceName 'MyInstance'
29+
$files = $serverObject | Get-SqlDscBackupFileList -BackupFile 'C:\Backups\MyDatabase.bak'
30+
$relocateFiles = $files | ForEach-Object {
31+
$newPath = if ($_.Type -eq 'L') { 'L:\SQLLogs' } else { 'D:\SQLData' }
32+
[Microsoft.SqlServer.Management.Smo.RelocateFile]::new(
33+
$_.LogicalName,
34+
(Join-Path -Path $newPath -ChildPath ([System.IO.Path]::GetFileName($_.PhysicalName)))
35+
)
36+
}
37+
$serverObject | Restore-SqlDscDatabase -Name 'MyDatabase' -BackupFile 'C:\Backups\MyDatabase.bak' -RelocateFile $relocateFiles
38+
39+
Gets the file list and creates RelocateFile objects for a restore
40+
operation that moves files to different directories.
41+
42+
.INPUTS
43+
`Microsoft.SqlServer.Management.Smo.Server`
44+
45+
Server object accepted from the pipeline.
46+
47+
.OUTPUTS
48+
`BackupFileSpec[]`
49+
50+
Returns an array of BackupFileSpec objects describing each file in the backup.
51+
#>
52+
function Get-SqlDscBackupFileList
53+
{
54+
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('UseSyntacticallyCorrectExamples', '', Justification = 'Because the rule does not yet support parsing the code when a parameter type is not available. The ScriptAnalyzer rule UseSyntacticallyCorrectExamples will always error in the editor due to https://github.com/indented-automation/Indented.ScriptAnalyzerRules/issues/8.')]
55+
[OutputType([BackupFileSpec[]])]
56+
[CmdletBinding()]
57+
param
58+
(
59+
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
60+
[Microsoft.SqlServer.Management.Smo.Server]
61+
$ServerObject,
62+
63+
[Parameter(Mandatory = $true)]
64+
[ValidateNotNullOrEmpty()]
65+
[System.String]
66+
$BackupFile,
67+
68+
[Parameter()]
69+
[ValidateRange(1, 2147483647)]
70+
[System.Int32]
71+
$FileNumber
72+
)
73+
74+
process
75+
{
76+
Write-Debug -Message ($script:localizedData.Get_SqlDscBackupFileList_Reading -f $BackupFile)
77+
78+
try
79+
{
80+
# Create the restore object to read file list
81+
$restore = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.Restore'
82+
83+
# Create and add the backup device
84+
$backupDevice = New-Object -TypeName 'Microsoft.SqlServer.Management.Smo.BackupDeviceItem' -ArgumentList $BackupFile, 'File'
85+
$restore.Devices.Add($backupDevice)
86+
87+
if ($PSBoundParameters.ContainsKey('FileNumber'))
88+
{
89+
$restore.FileNumber = $FileNumber
90+
}
91+
92+
# Read the file list from the backup
93+
$fileList = $restore.ReadFileList($ServerObject)
94+
95+
# Convert DataTable rows to BackupFileSpec objects
96+
$result = foreach ($row in $fileList.Rows)
97+
{
98+
[BackupFileSpec]::new(
99+
$row['LogicalName'],
100+
$row['PhysicalName'],
101+
$row['Type'],
102+
$row['FileGroupName'],
103+
[System.Int64] $row['Size'],
104+
[System.Int64] $row['MaxSize']
105+
)
106+
}
107+
108+
return $result
109+
}
110+
catch
111+
{
112+
$errorMessage = $script:localizedData.Get_SqlDscBackupFileList_Failed -f $BackupFile
113+
114+
$PSCmdlet.ThrowTerminatingError(
115+
[System.Management.Automation.ErrorRecord]::new(
116+
[System.InvalidOperationException]::new($errorMessage, $_.Exception),
117+
'GSBFL0002', # cspell: disable-line
118+
[System.Management.Automation.ErrorCategory]::InvalidOperation,
119+
$BackupFile
120+
)
121+
)
122+
}
123+
}
124+
}

0 commit comments

Comments
 (0)