Skip to content
Permalink
Browse files

Copy-DbaDbViewData - Merge pull request #6355 from jaxnoth/copy-view-…

…data

Added Copy-DbaDbViewData
  • Loading branch information
potatoqualitee committed Feb 12, 2020
2 parents 2dac935 + a7d13a6 commit ed695b1bdde2140b944748d58245e2e14b929998
@@ -660,7 +660,8 @@
# Unknown
'Get-DbaErrorLog',
'Get-DbaManagementObject',
'Test-DbaManagementObject'
'Test-DbaManagementObject',
'Copy-DbaDbViewData'
)

# Cmdlets to export from this module
@@ -562,6 +562,7 @@ $script:xplat = @(
'Select-DbaBackupInformation',
'Publish-DbaDacPackage',
'Copy-DbaDbTableData',
'Copy-DbaDbViewData',
'Invoke-DbaQuery',
'Remove-DbaLogin',
'Get-DbaAgentJobCategory',

Large diffs are not rendered by default.

@@ -132,6 +132,7 @@ function Get-DbaDbTable {
$server = $db.Parent
Write-Message -Level Verbose -Message "Processing $db"

$db.Tables.Refresh($true) # This will ensure the list of tables is up-to-date
if ($fqtns) {
$tables = @()
foreach ($fqtn in $fqtns) {
@@ -25,6 +25,9 @@ function Get-DbaDbView {
.PARAMETER ExcludeSystemView
This switch removes all system objects from the view collection.
.PARAMETER View
The view(s) to include - all views are selected if not populated
.PARAMETER InputObject
Enables piping from Get-DbaDatabase
@@ -74,6 +77,11 @@ function Get-DbaDbView {
Pipe the databases from Get-DbaDatabase into Get-DbaDbView
.EXAMPLE
PS C:\> Get-DbaDbView -SqlInstance Server1 -Database db1 -View vw1
Gets the view vw1 for the db1 database
#>
[CmdletBinding()]
param (
@@ -83,17 +91,66 @@ function Get-DbaDbView {
[object[]]$Database,
[object[]]$ExcludeDatabase,
[switch]$ExcludeSystemView,
[string[]]$View,
[Parameter(ValueFromPipeline)]
[Microsoft.SqlServer.Management.Smo.Database[]]$InputObject,
[switch]$EnableException
)

begin {
if ($View) {
$fqtns = @()
foreach ($v in $View) {
$fqtn = Get-ObjectNameParts -ObjectName $v

if (-not $fqtn.Parsed) {
Write-Message -Level Warning -Message "Please check you are using proper three-part names. If your search value contains special characters you must use [ ] to wrap the name. The value $t could not be parsed as a valid name."
Continue
}

$fqtns += [PSCustomObject] @{
Database = $fqtn.Database
Schema = $fqtn.Schema
View = $fqtn.Name
InputValue = $fqtn.InputValue
}
}
if (-not $fqtns) {
Stop-Function -Message "No Valid View specified" -ErrorRecord $_ -Target $instance -Continue
}
}
}

process {
if (Test-Bound SqlInstance) {
$InputObject = Get-DbaDatabase -SqlInstance $SqlInstance -SqlCredential $SqlCredential -Database $Database -ExcludeDatabase $ExcludeDatabase
}

foreach ($db in $InputObject) {
$views = $db.views

$db.Views.Refresh($true) # This will ensure the list of views is up-to-date
if ($fqtns) {
$views = @()
foreach ($fqtn in $fqtns) {
# If the user specified a database in a three-part name, and it's not the
# database currently being processed, skip this view.
if ($fqtn.Database) {
if ($fqtn.Database -ne $db.Name) {
continue
}
}

$vw = $db.Views | Where-Object { $_.Name -in $fqtn.View -and $fqtn.Schema -in ($_.Schema, $null) -and $fqtn.Database -in ($_.Parent.Name, $null) }

if (-not $vw) {
Write-Message -Level Verbose -Message "Could not find view $($fqtn.Name) in $db on $server"
}
$views += $vw
}
} else {
$views = $db.Views
}

if (-not $db.IsAccessible) {
Write-Message -Level Warning -Message "Database $db is not accessible. Skipping"
continue
@@ -108,14 +165,14 @@ function Get-DbaDbView {
}

$defaults = 'ComputerName', 'InstanceName', 'SqlInstance', 'Database', 'Schema', 'CreateDate', 'DateLastModified', 'Name'
foreach ($view in $views) {
foreach ($sqlview in $views) {

Add-Member -Force -InputObject $view -MemberType NoteProperty -Name ComputerName -value $view.Parent.ComputerName
Add-Member -Force -InputObject $view -MemberType NoteProperty -Name InstanceName -value $view.Parent.InstanceName
Add-Member -Force -InputObject $view -MemberType NoteProperty -Name SqlInstance -value $view.Parent.SqlInstance
Add-Member -Force -InputObject $view -MemberType NoteProperty -Name Database -value $db.Name
Add-Member -Force -InputObject $sqlview -MemberType NoteProperty -Name ComputerName -value $sqlview.Parent.ComputerName
Add-Member -Force -InputObject $sqlview -MemberType NoteProperty -Name InstanceName -value $sqlview.Parent.InstanceName
Add-Member -Force -InputObject $sqlview -MemberType NoteProperty -Name SqlInstance -value $sqlview.Parent.SqlInstance
Add-Member -Force -InputObject $sqlview -MemberType NoteProperty -Name Database -value $db.Name

Select-DefaultView -InputObject $view -Property $defaults
Select-DefaultView -InputObject $sqlview -Property $defaults
}
}
}
@@ -0,0 +1,117 @@
$CommandName = $MyInvocation.MyCommand.Name.Replace(".Tests.ps1", "")
Write-Host -Object "Running $PSCommandPath" -ForegroundColor Cyan
. "$PSScriptRoot\constants.ps1"

Describe "$CommandName Unit Tests" -Tag 'UnitTests' {
Context "Validate parameters" {
[object[]]$params = (Get-Command $CommandName).Parameters.Keys | Where-Object { $_ -notin ('whatif', 'confirm') }
[object[]]$knownParameters = 'SqlInstance', 'SqlCredential', 'Destination', 'DestinationSqlCredential', 'Database', 'DestinationDatabase', 'View', 'Query', 'AutoCreateTable', 'BatchSize', 'NotifyAfter', 'DestinationTable', 'NoTableLock', 'CheckConstraints', 'FireTriggers', 'KeepIdentity', 'KeepNulls', 'Truncate', 'bulkCopyTimeOut', 'InputObject', 'EnableException'
$knownParameters += [System.Management.Automation.PSCmdlet]::CommonParameters
It "Should only contain our specific parameters" {
(@(Compare-Object -ReferenceObject ($knownParameters | Where-Object { $_ }) -DifferenceObject $params).Count ) | Should Be 0
}
}
}

Describe "$commandname Integration Tests" -Tags "IntegrationTests" {
BeforeAll {
$db = Get-DbaDatabase -SqlInstance $script:instance1 -Database tempdb
$db2 = Get-DbaDatabase -SqlInstance $script:instance2 -Database tempdb
$null = $db.Query("CREATE TABLE dbo.dbatoolsci_example (id int);
INSERT dbo.dbatoolsci_example
SELECT top 10 1
FROM sys.objects")
$null = $db.Query("CREATE TABLE dbo.dbatoolsci_example2 (id int)")
$null = $db.Query("CREATE TABLE dbo.dbatoolsci_example3 (id int)")
$null = $db.Query("CREATE TABLE dbo.dbatoolsci_example4 (id int);
INSERT dbo.dbatoolsci_example4
SELECT top 13 1
FROM sys.objects")
$null = $db.Query("CREATE VIEW dbo.dbatoolsci_view_example AS SELECT * FROM dbo.dbatoolsci_example")
$null = $db.Query("CREATE VIEW dbo.dbatoolsci_view_example2 AS SELECT * FROM dbo.dbatoolsci_example2")
$null = $db.Query("CREATE VIEW dbo.dbatoolsci_view_example3 AS SELECT * FROM dbo.dbatoolsci_example3")
$null = $db.Query("CREATE VIEW dbo.dbatoolsci_view_example4 AS SELECT * FROM dbo.dbatoolsci_example4")
$null = $db2.Query("CREATE TABLE dbo.dbatoolsci_view_example (id int)")
$null = $db2.Query("CREATE TABLE dbo.dbatoolsci_view_example3 (id int)")
$null = $db2.Query("CREATE TABLE dbo.dbatoolsci_view_example4 (id int);
INSERT dbo.dbatoolsci_view_example4
SELECT top 13 2
FROM sys.objects")
}
AfterAll {
try {
$null = $db.Query("DROP TABLE dbo.dbatoolsci_example")
$null = $db.Query("DROP TABLE dbo.dbatoolsci_example2")
$null = $db.Query("DROP TABLE dbo.dbatoolsci_example3")
$null = $db.Query("DROP TABLE dbo.dbatoolsci_example4")
$null = $db.Query("DROP VIEW dbo.dbatoolsci_view_example")
$null = $db.Query("DROP VIEW dbo.dbatoolsci_view_example2")
$null = $db.Query("DROP VIEW dbo.dbatoolsci_view_example3")
$null = $db.Query("DROP VIEW dbo.dbatoolsci_view_example4")
$null = $db2.Query("DROP TABLE dbo.dbatoolsci_view_example3")
$null = $db2.Query("DROP TABLE dbo.dbatoolsci_view_example4")
$null = $db2.Query("DROP TABLE dbo.dbatoolsci_view_example")
$null = $db.Query("DROP TABLE dbo.dbatoolsci_view_will_exist")
} catch {
$null = 1
}
}

It "copies the table data" {
$null = Copy-DbaDbViewData -SqlInstance $script:instance1 -Database tempdb -View dbatoolsci_view_example -DestinationTable dbatoolsci_example2
$table1count = $db.Query("select id from dbo.dbatoolsci_view_example")
$table2count = $db.Query("select id from dbo.dbatoolsci_example2")
$table1count.Count | Should -Be $table2count.Count
}

It "copies the table data to another instance" {
$null = Copy-DbaDbViewData -SqlInstance $script:instance1 -Destination $script:instance2 -Database tempdb -View dbatoolsci_view_example -DestinationTable dbatoolsci_view_example3
$table1count = $db.Query("select id from dbo.dbatoolsci_view_example")
$table2count = $db2.Query("select id from dbo.dbatoolsci_view_example3")
$table1count.Count | Should -Be $table2count.Count
}

It "supports piping" {
$null = Get-DbaDbView -SqlInstance $script:instance1 -Database tempdb -View dbatoolsci_view_example | Copy-DbaDbViewData -DestinationTable dbatoolsci_example2 -Truncate
$table1count = $db.Query("select id from dbo.dbatoolsci_view_example")
$table2count = $db.Query("select id from dbo.dbatoolsci_example2")
$table1count.Count | Should -Be $table2count.Count
}

It "supports piping more than one table" {
$results = Get-DbaDbView -SqlInstance $script:instance1 -Database tempdb -View dbatoolsci_view_example2, dbatoolsci_view_example | Copy-DbaDbViewData -DestinationTable dbatoolsci_example3
$results.Count | Should -Be 2
}

It "opens and closes connections properly" {
#regression test, see #3468
$results = Get-DbaDbView -SqlInstance $script:instance1 -Database tempdb -View 'dbo.dbatoolsci_view_example', 'dbo.dbatoolsci_view_example4' | Copy-DbaDbViewData -Destination $script:instance2 -DestinationDatabase tempdb -KeepIdentity -KeepNulls -BatchSize 5000 -Truncate
$results.Count | Should -Be 2
$table1dbcount = $db.Query("select id from dbo.dbatoolsci_view_example")
$table4dbcount = $db2.Query("select id from dbo.dbatoolsci_view_example4")
$table1db2count = $db.Query("select id from dbo.dbatoolsci_view_example")
$table4db2count = $db2.Query("select id from dbo.dbatoolsci_view_example4")
$table1dbcount.Count | Should -Be $table1db2count.Count
$table4dbcount.Count | Should -Be $table4db2count.Count
$results[0].RowsCopied | Should -Be 10
$results[1].RowsCopied | Should -Be 13
$table4db2check = $db2.Query("select id from dbo.dbatoolsci_view_example4 where id = 1")
$table4db2check.Count | Should -Be 13
}

It "Should warn and return nothing if Source and Destination are same" {
$result = Copy-DbaDbViewData -SqlInstance $script:instance1 -Database tempdb -View dbatoolsci_view_example -Truncate -WarningVariable tablewarning
$result | Should Be $null
$tablewarning | Should -match "Cannot copy dbatoolsci_view_example into itself"
}

It "Should warn if the destination table doesn't exist" {
$result = Copy-DbaDbViewData -SqlInstance $script:instance1 -Database tempdb -View dbatoolsci_view_example -DestinationTable dbatoolsci_view_does_not_exist -WarningVariable tablewarning
$tablewarning | Should -match Auto
}

It "automatically creates the table" {
$result = Copy-DbaDbViewData -SqlInstance $script:instance1 -Database tempdb -View dbatoolsci_view_example -DestinationTable dbatoolsci_view_will_exist -AutoCreateTable
$result.DestinationTable | Should -Be 'dbatoolsci_view_will_exist'
}
}
@@ -5,7 +5,7 @@ Write-Host -Object "Running $PSCommandPath" -ForegroundColor Cyan
Describe "$CommandName Unit Tests" -Tag 'UnitTests' {
Context "Validate parameters" {
[object[]]$params = (Get-Command $CommandName).Parameters.Keys | Where-Object { $_ -notin ('whatif', 'confirm') }
[object[]]$knownParameters = 'SqlInstance', 'SqlCredential', 'Database', 'ExcludeDatabase', 'ExcludeSystemView', 'InputObject', 'EnableException'
[object[]]$knownParameters = 'SqlInstance', 'SqlCredential', 'Database', 'ExcludeDatabase', 'ExcludeSystemView', 'View', 'InputObject', 'EnableException'
$knownParameters += [System.Management.Automation.PSCmdlet]::CommonParameters
It "Should only contain our specific parameters" {
(@(Compare-Object -ReferenceObject ($knownParameters | Where-Object { $_ }) -DifferenceObject $params).Count ) | Should Be 0

0 comments on commit ed695b1

Please sign in to comment.
You can’t perform that action at this time.