Skip to content

Commit d2d0ccc

Browse files
Get-DbaDbIdentity - Fix escaped bracket table-name normalization (review of #10318)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 177aa89 commit d2d0ccc

7 files changed

Lines changed: 168 additions & 18 deletions

docs/trackers/features/commit-bug-review-TRACKER.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ Find real bugs (logic errors, null refs, incorrect behavior) and fix them. Skip
134134
| b09063aa0 | Get-DbaWaitStatistic - Fix bug from recent refactoring (#10323) | DONE | Reviewed commit; later commit 9a9236a13 fixed unsafe wait-type SQL filtering and missing normalization. |
135135
| eddfeeeca | Find-DbaInstance - Fix TcpConnected false for default instances (#10327) | DONE | Added fallback port scanning for Browser default instances without reusing named-instance ports; added unit regression test. |
136136
| 5f483d42c | Get-DbaPermission - Fix Azure SQL DB compatibility (#10320) | DONE | Reviewed Azure SQL DB compatibility fix; no bugs found. |
137-
| a38bc6b35 | Get-DbaDbIdentity, Set-DbaDbIdentity, Invoke-DbaDbDbccUpdateUsage - Normalize table names (#10318) | PENDING | |
137+
| a38bc6b35 | Get-DbaDbIdentity, Set-DbaDbIdentity, Invoke-DbaDbDbccUpdateUsage - Normalize table names (#10318) | DONE | Fixed escaped-bracket table name regression and added unit regression tests. |
138138
| 9899bd274 | Copy-DbaDbTableData - Add -ScriptingOptionsObject parameter (#10317) | PENDING | |
139139
| 0c486b964 | Backup-DbaDbCertificate: Don't use decryption password if cert encrypted by master key (#10329) | PENDING | |
140140
| db77a3476 | Find-DbaObject - Add unified command to search database objects by name (#10321) | PENDING | |

public/Get-DbaDbIdentity.ps1

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,16 @@ function Get-DbaDbIdentity {
130130
try {
131131
$query = $StringBuilder.ToString()
132132
$nameParts = Get-ObjectNameParts -ObjectName $tbl
133-
if ($nameParts.Schema) {
134-
$tblIdentifier = "[$($nameParts.Schema)].[$($nameParts.Name)]"
133+
if ($nameParts.Name) {
134+
$escapedTableName = $nameParts.Name.Replace("]", "]]")
135+
if ($nameParts.Schema) {
136+
$escapedTableSchema = $nameParts.Schema.Replace("]", "]]")
137+
$tblIdentifier = "[$escapedTableSchema].[$escapedTableName]"
138+
} else {
139+
$tblIdentifier = "[$escapedTableName]"
140+
}
135141
} else {
136-
$tblIdentifier = "[$($nameParts.Name)]"
142+
$tblIdentifier = $tbl
137143
}
138144
$query = $query.Replace('#options#', "'$($tblIdentifier)'")
139145

public/Invoke-DbaDbDbccUpdateUsage.ps1

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,30 +163,36 @@ function Invoke-DbaDbDbccUpdateUsage {
163163
try {
164164
$query = $StringBuilder.ToString()
165165
if (Test-Bound -ParameterName Table) {
166-
if ($Table -notmatch '^\d+$') {
166+
if ($Table -notmatch "^\d+$") {
167167
$tableNameParts = Get-ObjectNameParts -ObjectName $Table
168-
if ($tableNameParts.Schema) {
169-
$tableIdentifier = "[$($tableNameParts.Schema)].[$($tableNameParts.Name)]"
168+
if ($tableNameParts.Name) {
169+
$escapedTableName = $tableNameParts.Name.Replace("]", "]]")
170+
if ($tableNameParts.Schema) {
171+
$escapedTableSchema = $tableNameParts.Schema.Replace("]", "]]")
172+
$tableIdentifier = "[$escapedTableSchema].[$escapedTableName]"
173+
} else {
174+
$tableIdentifier = "[$escapedTableName]"
175+
}
170176
} else {
171-
$tableIdentifier = "[$($tableNameParts.Name)]"
177+
$tableIdentifier = $Table
172178
}
173179
}
174180
if (Test-Bound -ParameterName Index) {
175-
if ($Table -match '^\d+$') {
176-
if ($Index -match '^\d+$') {
181+
if ($Table -match "^\d+$") {
182+
if ($Index -match "^\d+$") {
177183
$query = $query.Replace('#options#', "'$($db.name)', $Table, $Index")
178184
} else {
179185
$query = $query.Replace('#options#', "'$($db.name)', $Table, '$Index'")
180186
}
181187
} else {
182-
if ($Index -match '^\d+$') {
188+
if ($Index -match "^\d+$") {
183189
$query = $query.Replace('#options#', "'$($db.name)', '$tableIdentifier', $Index")
184190
} else {
185191
$query = $query.Replace('#options#', "'$($db.name)', '$tableIdentifier', '$Index'")
186192
}
187193
}
188194
} else {
189-
if ($Table -match '^\d+$') {
195+
if ($Table -match "^\d+$") {
190196
$query = $query.Replace('#options#', "'$($db.name)', $Table")
191197
} else {
192198
$query = $query.Replace('#options#', "'$($db.name)', '$tableIdentifier'")

public/Set-DbaDbIdentity.ps1

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,16 @@ function Set-DbaDbIdentity {
146146
try {
147147
$query = $StringBuilder.ToString()
148148
$nameParts = Get-ObjectNameParts -ObjectName $tbl
149-
if ($nameParts.Schema) {
150-
$tblIdentifier = "[$($nameParts.Schema)].[$($nameParts.Name)]"
149+
if ($nameParts.Name) {
150+
$escapedTableName = $nameParts.Name.Replace("]", "]]")
151+
if ($nameParts.Schema) {
152+
$escapedTableSchema = $nameParts.Schema.Replace("]", "]]")
153+
$tblIdentifier = "[$escapedTableSchema].[$escapedTableName]"
154+
} else {
155+
$tblIdentifier = "[$escapedTableName]"
156+
}
151157
} else {
152-
$tblIdentifier = "[$($nameParts.Name)]"
158+
$tblIdentifier = $tbl
153159
}
154160
if (Test-Bound -Not -ParameterName ReSeedValue) {
155161
$query = $query.Replace('#options#', "'$($tblIdentifier)'")

tests/Get-DbaDbIdentity.Tests.ps1

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#Requires -Module @{ ModuleName="Pester"; ModuleVersion="5.0" }
22
param(
3-
$ModuleName = "dbatools",
3+
$ModuleName = "dbatools",
44
$CommandName = "Get-DbaDbIdentity",
55
$PSDefaultParameterValues = $TestConfig.Defaults
66
)
@@ -20,6 +20,50 @@ Describe $CommandName -Tag UnitTests {
2020
Compare-Object -ReferenceObject $expectedParameters -DifferenceObject $hasParameters | Should -BeNullOrEmpty
2121
}
2222
}
23+
24+
InModuleScope dbatools {
25+
Context "Table name normalization" {
26+
BeforeAll {
27+
$script:lastQuery = $null
28+
$script:mockDatabase = [PSCustomObject]@{
29+
Name = "db1"
30+
IsAccessible = $true
31+
}
32+
$script:mockServer = [PSCustomObject]@{
33+
Name = "sql1"
34+
ComputerName = "sql1"
35+
ServiceName = "MSSQLSERVER"
36+
DomainInstanceName = "sql1"
37+
Databases = @($script:mockDatabase)
38+
}
39+
40+
function Invoke-DbaQuery {
41+
param(
42+
[Parameter(ValueFromPipeline)]
43+
$InputObject,
44+
$Query,
45+
$Database,
46+
[switch]$MessagesToOutput
47+
)
48+
49+
process {
50+
$script:lastQuery = $Query
51+
"Checking identity information: current identity value '5', current column value '5'."
52+
}
53+
}
54+
Mock Connect-DbaInstance { $script:mockServer }
55+
}
56+
57+
It "escapes closing brackets in normalized table names" {
58+
$script:lastQuery = $null
59+
60+
$result = Get-DbaDbIdentity -SqlInstance "sql1" -Database "db1" -Table "[dbo].[Bad]]Name]"
61+
62+
$script:lastQuery | Should -Be "DBCC CHECKIDENT('[dbo].[Bad]]Name]', NORESEED)"
63+
$result.Cmd | Should -Be "DBCC CHECKIDENT('[dbo].[Bad]]Name]', NORESEED)"
64+
}
65+
}
66+
}
2367
}
2468

2569
Describe $CommandName -Tag IntegrationTests {

tests/Invoke-DbaDbDbccUpdateUsage.Tests.ps1

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#Requires -Module @{ ModuleName="Pester"; ModuleVersion="5.0" }
22
param(
3-
$ModuleName = "dbatools",
3+
$ModuleName = "dbatools",
44
$CommandName = "Invoke-DbaDbDbccUpdateUsage",
55
$PSDefaultParameterValues = $TestConfig.Defaults
66
)
@@ -23,6 +23,50 @@ Describe $CommandName -Tag UnitTests {
2323
Compare-Object -ReferenceObject $expectedParameters -DifferenceObject $hasParameters | Should -BeNullOrEmpty
2424
}
2525
}
26+
27+
InModuleScope dbatools {
28+
Context "Table name normalization" {
29+
BeforeAll {
30+
$script:lastQuery = $null
31+
$script:mockDatabase = [PSCustomObject]@{
32+
Name = "db1"
33+
ID = 5
34+
IsAccessible = $true
35+
}
36+
$script:mockServer = [PSCustomObject]@{
37+
Name = "sql1"
38+
ComputerName = "sql1"
39+
ServiceName = "MSSQLSERVER"
40+
DomainInstanceName = "sql1"
41+
Databases = @($script:mockDatabase)
42+
}
43+
44+
function Invoke-DbaQuery {
45+
param(
46+
[Parameter(ValueFromPipeline)]
47+
$InputObject,
48+
$Query,
49+
[switch]$MessagesToOutput
50+
)
51+
52+
process {
53+
$script:lastQuery = $Query
54+
@("DBCC execution completed. If DBCC printed error messages, contact your system administrator.")
55+
}
56+
}
57+
Mock Connect-DbaInstance { $script:mockServer }
58+
}
59+
60+
It "escapes closing brackets in normalized table names" {
61+
$script:lastQuery = $null
62+
63+
$result = Invoke-DbaDbDbccUpdateUsage -SqlInstance "sql1" -Database "db1" -Table "[dbo].[Bad]]Name]" -Confirm:$false
64+
65+
$script:lastQuery | Should -Be "DBCC UPDATEUSAGE('db1', '[dbo].[Bad]]Name]')"
66+
$result.Cmd | Should -Be "DBCC UPDATEUSAGE('db1', '[dbo].[Bad]]Name]')"
67+
}
68+
}
69+
}
2670
}
2771
Describe $CommandName -Tag IntegrationTests {
2872
BeforeAll {

tests/Set-DbaDbIdentity.Tests.ps1

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#Requires -Module @{ ModuleName="Pester"; ModuleVersion="5.0" }
22
param(
3-
$ModuleName = "dbatools",
3+
$ModuleName = "dbatools",
44
$CommandName = "Set-DbaDbIdentity",
55
$PSDefaultParameterValues = $TestConfig.Defaults
66
)
@@ -21,6 +21,50 @@ Describe $CommandName -Tag UnitTests {
2121
Compare-Object -ReferenceObject $expectedParameters -DifferenceObject $hasParameters | Should -BeNullOrEmpty
2222
}
2323
}
24+
25+
InModuleScope dbatools {
26+
Context "Table name normalization" {
27+
BeforeAll {
28+
$script:lastQuery = $null
29+
$script:mockDatabase = [PSCustomObject]@{
30+
Name = "db1"
31+
IsAccessible = $true
32+
}
33+
$script:mockServer = [PSCustomObject]@{
34+
Name = "sql1"
35+
ComputerName = "sql1"
36+
ServiceName = "MSSQLSERVER"
37+
DomainInstanceName = "sql1"
38+
Databases = @($script:mockDatabase)
39+
}
40+
41+
function Invoke-DbaQuery {
42+
param(
43+
[Parameter(ValueFromPipeline)]
44+
$InputObject,
45+
$Query,
46+
$Database,
47+
[switch]$MessagesToOutput
48+
)
49+
50+
process {
51+
$script:lastQuery = $Query
52+
"Checking identity information: current identity value '5'."
53+
}
54+
}
55+
Mock Connect-DbaInstance { $script:mockServer }
56+
}
57+
58+
It "escapes closing brackets in normalized table names for reseed" {
59+
$script:lastQuery = $null
60+
61+
$result = Set-DbaDbIdentity -SqlInstance "sql1" -Database "db1" -Table "[dbo].[Bad]]Name]" -ReSeedValue 400 -Confirm:$false
62+
63+
$script:lastQuery | Should -Be "DBCC CHECKIDENT('[dbo].[Bad]]Name]', RESEED, 400)"
64+
$result.Cmd | Should -Be "DBCC CHECKIDENT('[dbo].[Bad]]Name]', RESEED, 400)"
65+
}
66+
}
67+
}
2468
}
2569

2670
Describe $CommandName -Tag IntegrationTests {

0 commit comments

Comments
 (0)