Skip to content

Commit 44fa41b

Browse files
authored
Merge pull request #57 from sqlcollaborative/Xplat-tests
Postgres tests and async SqlDataReqder
2 parents cb601dd + aa94601 commit 44fa41b

31 files changed

+1835
-68
lines changed

appveyor.yml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ image:
1313
environment:
1414
environment: development
1515
version: 0.1.$(appveyor_build_number)
16+
PGUSER: postgres
17+
PGPASSWORD: Password12!
1618

1719
matrix:
1820
- scenario: all
@@ -29,6 +31,12 @@ for:
2931
services:
3032
- mssql2017
3133
- mysql
34+
- postgresql
35+
before_test:
36+
- SET PATH=C:\Program Files\PostgreSQL\9.6\bin\;%PATH%
37+
- psql -c "CREATE USER sa WITH PASSWORD 'Password12!';" -U postgres
38+
- psql -c "ALTER USER sa WITH SUPERUSER;" -U postgres
39+
- ps: .\tests\appveyor.prep.ps1
3240

3341
- matrix:
3442
only:
@@ -39,11 +47,18 @@ for:
3947
services:
4048
- mssql
4149
- mysql
50+
- postgresql
51+
before_test:
52+
- sudo -u postgres psql -c "CREATE USER sa WITH PASSWORD 'Password12!';"
53+
- sudo -u postgres psql -c "ALTER USER sa WITH SUPERUSER;"
54+
- ps: .\tests\appveyor.prep.ps1
55+
56+
# before_test:
57+
# # run preparation scripts
58+
# - ps: .\tests\appveyor.prep.ps1
59+
# # create postres user
4260

4361

44-
before_test:
45-
# run preparation scripts
46-
- ps: .\tests\appveyor.prep.ps1
4762
test_script:
4863
# Test with native PS version
4964
- ps: .\tests\appveyor.pester.ps1

bin/deploy.ps1

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ $config = Get-DBOConfig -Path "$PSScriptRoot\dbops.config.json" -Configuration $
4343
$newConfig = @{}
4444
foreach ($key in ($PSBoundParameters.Keys)) {
4545
if ($key -in [DBOpsConfig]::EnumProperties()) {
46-
Write-PSFMessage -Level Debug -Message "Overriding parameter $key with $($PSBoundParameters[$key])"
4746
$newConfig.$key = $PSBoundParameters[$key]
4847
}
4948
}

functions/Install-DBOPackage.ps1

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,6 @@
190190
$newConfig = @{}
191191
foreach ($key in ($PSBoundParameters.Keys)) {
192192
if ($key -in [DBOpsConfig]::EnumProperties()) {
193-
Write-PSFMessage -Level Debug -Message "Overriding parameter $key with $($PSBoundParameters[$key])"
194193
$newConfig.$key = $PSBoundParameters[$key]
195194
}
196195
}

functions/Install-DBOSqlScript.ps1

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@
191191
$newConfig = @{}
192192
foreach ($key in ($PSBoundParameters.Keys)) {
193193
if ($key -in [DBOpsConfig]::EnumProperties()) {
194-
Write-PSFMessage -Level Debug -Message "Overriding parameter $key with $($PSBoundParameters[$key])"
195194
$newConfig.$key = $PSBoundParameters[$key]
196195
}
197196
}

functions/Invoke-DBOQuery.ps1

Lines changed: 72 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@ function Invoke-DBOQuery {
158158
$newConfig = @{}
159159
foreach ($key in ($PSBoundParameters.Keys)) {
160160
if ($key -in [DBOpsConfig]::EnumProperties()) {
161-
Write-PSFMessage -Level Debug -Message "Overriding parameter $key with $($PSBoundParameters[$key])"
162161
$newConfig.$key = $PSBoundParameters[$key]
163162
}
164163
}
@@ -176,6 +175,8 @@ function Invoke-DBOQuery {
176175
Write-PSFMessage -Level Debug -Message "Getting the connection object"
177176
$dbUpConnection = Get-ConnectionManager -ConnectionString $null -Type $Type # only needed for query parsing for now, connection string is pointless
178177
$dataConnection = Get-DatabaseConnection -Configuration $config -Type $Type # the 'real' connection
178+
$dbUpLog = [DBOpsLog]::new($config.Silent, $OutputFile, $Append)
179+
$dbUpLog.CallStack = (Get-PSCallStack)[0]
179180
Write-PSFMessage -Level Verbose -Message "Establishing connection with $Type $($config.SqlInstance)"
180181
try {
181182
$dataConnection.Open()
@@ -211,13 +212,19 @@ function Invoke-DBOQuery {
211212

212213
Write-PSFMessage -Level Debug -Message "Preparing to run $($queryList.Count) queries"
213214
$ds = [System.Data.DataSet]::new()
214-
try {
215-
$qCount = 0
216-
foreach ($queryItem in $queryList) {
217-
$qCount++
218-
if ($PSCmdlet.ShouldProcess("Executing query $qCount", $config.SqlInstance)) {
219-
# split commands using DbUp parser
220-
foreach ($splitQuery in $dbUpConnection.SplitScriptIntoCommands($queryItem)) {
215+
$qCount = 0
216+
foreach ($queryItem in $queryList) {
217+
$qCount++
218+
if ($PSCmdlet.ShouldProcess("Executing query $qCount", $config.SqlInstance)) {
219+
# split commands using DbUp parser
220+
foreach ($splitQuery in $dbUpConnection.SplitScriptIntoCommands($queryItem)) {
221+
try {
222+
# only Sql Server supports messaging right now
223+
if ($Type -eq 'SqlServer') {
224+
# Add message events
225+
Unregister-Event -SourceIdentifier "DBOpsMessaging" -ErrorAction SilentlyContinue
226+
$eventOutput = Register-ObjectEvent -InputObject $dataConnection -EventName "InfoMessage" -SourceIdentifier "DBOpsMessaging" -Action { $EventArgs.Message }
227+
}
221228
# create a new command object and define text/parameters
222229
$command = $dataConnection.CreateCommand()
223230
$command.CommandText = $splitQuery
@@ -227,40 +234,73 @@ function Invoke-DBOQuery {
227234
default { $command.Parameters.AddWithValue($key, $Parameter[$key]) }
228235
}
229236
}
230-
# create a reader and define output table columns
231-
$reader = $command.ExecuteReader()
232-
$table = [System.Data.DataTable]::new()
233-
$definition = $reader.GetSchemaTable()
234-
foreach ($column in $definition) {
235-
$name = $column.ColumnName
236-
$datatype = $column.DataType
237-
for ($j = 1; -not $name; $j++) {
238-
if ($table.Columns.ColumnName -notcontains "Column$j") { $name = "Column$j" }
237+
# create an async reader and wait for output receiving logs in the process
238+
$readerTask = $command.ExecuteReaderAsync()
239+
if ($Type -eq 'SqlServer') {
240+
$logScript = {
241+
# receive events we got so far and put them in the log
242+
$events = $eventOutput | Receive-Job
243+
foreach ($logEntry in $events) {
244+
$dbUpLog.WriteInformation($logEntry, $null)
245+
}
239246
}
240-
$null = $table.Columns.Add($name, $datatype)
241-
}
242-
# read rows and assign values
243-
while ($reader.Read()) {
244-
$row = $table.NewRow()
245-
for ($i = 0; $i -lt $reader.FieldCount; $i++) {
246-
$row[$table.Columns[$i].ColumnName] = $reader.GetValue($i);
247+
while (-not $readerTask.IsCompleted) {
248+
$logScript.Invoke()
249+
Start-Sleep -Milliseconds 50
247250
}
248-
$table.Rows.Add($row)
251+
# once completed, receive the final part and unregister the ivent
252+
$logScript.Invoke()
253+
# lastly, unregister the event
254+
Unregister-Event -SourceIdentifier "DBOpsMessaging"
249255
}
250-
$ds.Tables.Add($table)
256+
$reader = $readerTask.GetAwaiter().GetResult()
257+
$setCounter = 0
258+
do {
259+
$setCounter++
260+
$table = [System.Data.DataTable]::new()
261+
$definition = $reader.GetSchemaTable()
262+
foreach ($column in $definition) {
263+
$name = $column.ColumnName
264+
$datatype = $column.DataType
265+
for ($j = 1; -not $name; $j++) {
266+
if ($table.Columns.ColumnName -notcontains "Column$j") { $name = "Column$j" }
267+
}
268+
if ($datatype.FullName -eq 'System.DBNull') {
269+
$datatype = [string]
270+
}
271+
$null = $table.Columns.Add($name, $datatype)
272+
}
273+
# read rows async and assign values
274+
$rowCount = 0
275+
while ($reader.ReadAsync().GetAwaiter().GetResult()) {
276+
$rowCount++
277+
$row = $table.NewRow()
278+
for ($i = 0; $i -lt $reader.FieldCount; $i++) {
279+
$row[$table.Columns[$i].ColumnName] = $reader.GetValue($i);
280+
}
281+
$table.Rows.Add($row)
282+
}
283+
Write-PSFMessage -Level Debug -Message "Received $rowCount rows from resultset $setCounter"
284+
$ds.Tables.Add($table)
285+
} while ($reader.NextResult())
251286
$reader.Close()
252287
$reader.Dispose()
253288
$command.Dispose()
254289
}
290+
catch {
291+
$dbUpLog.WriteError($_.Exception.InnerException.Message, $null)
292+
if ($Type -eq 'SqlServer') {
293+
Unregister-Event -SourceIdentifier "DBOpsMessaging" -ErrorAction SilentlyContinue
294+
}
295+
$dataConnection.Dispose()
296+
Stop-PSFFunction -EnableException $true -Message "Failed to run the query" -ErrorRecord $_
297+
}
255298
}
256299
}
257300
}
258-
catch {
259-
Stop-PSFFunction -EnableException $true -Message "Failed to run the query" -ErrorRecord $_
260-
}
261-
finally {
262-
$dataConnection.Dispose()
263-
}
301+
# close the connection
302+
$dataConnection.Dispose()
303+
264304
switch ($As) {
265305
'DataSet' {
266306
$ds

functions/Register-DBOPackage.ps1

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,6 @@ function Register-DBOPackage {
176176
$newConfig = @{}
177177
foreach ($key in ($PSBoundParameters.Keys)) {
178178
if ($key -in [DBOpsConfig]::EnumProperties()) {
179-
Write-PSFMessage -Level Debug -Message "Overriding parameter $key with $($PSBoundParameters[$key])"
180179
$newConfig.$key = $PSBoundParameters[$key]
181180
}
182181
}

functions/Send-DBOMailMessage.ps1

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ function Send-DBOMailMessage {
9898
if ($null -eq $PSBoundParameters['from']) {
9999
Stop-PSFFunction -Message "No sender email address specified, exiting" -EnableException $true
100100
}
101-
if ($InputObject -and $InputObject -isnot [DBOpsDeploymentStatus]) {
102-
Stop-PSFFunction -Message "Wrong object in the pipeline. Usable only with output from the deployment commands." -EnableException $true
101+
if ($InputObject -and $InputObject.GetType().FullName -ne 'DBOpsDeploymentStatus') {
102+
Stop-PSFFunction -Message "Wrong object in the pipeline: $($InputObject.GetType().FullName). Usable only with output from the deployment commands." -EnableException $true
103103
}
104104
#Get template from the parameter or read it from the default path
105105
if (Test-PSFParameterBinding -ParameterName Template) {
@@ -138,15 +138,15 @@ function Send-DBOMailMessage {
138138

139139
# Get HTML variable
140140
$htmlbody = Resolve-VariableToken $htmlTemplate $tokens
141-
141+
142142
# Modify the params as required
143143
$null = $PSBoundParameters.Remove("InputObject")
144144
$null = $PSBoundParameters.Remove("Template")
145145
$null = $PSBoundParameters.Remove("PassThru")
146146
foreach ($p in (@('Subject', 'From', 'To', 'CC') | Where-Object { $_ -in $PSBoundParameters.Keys })) {
147147
$PSBoundParameters[$p] = Resolve-VariableToken $PSBoundParameters[$p] $tokens
148148
}
149-
149+
150150
try {
151151
Send-MailMessage -BodyAsHtml -Body $htmlbody -ErrorAction Stop @PSBoundParameters
152152
}

functions/Test-DBOSupportedSystem.ps1

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,6 @@ Function Test-DBOSupportedSystem {
2424
)
2525
begin {}
2626
process {
27-
# try looking up already loaded assemblies
28-
$lookupClass = switch ($Type) {
29-
SqlServer { 'System.Data.SqlClient.SqlConnection' }
30-
Oracle { 'Oracle.DataAccess.Client.OracleConnection' }
31-
MySQL { 'MySql.Data.MySqlClient.MySqlConnection' }
32-
PostgreSQL { 'Npgsql.NpgsqlConnection' }
33-
default { Stop-PSFFunction -Message "Unknown type $Type" -EnableException $true }
34-
}
35-
if ([System.AppDomain]::CurrentDomain.GetAssemblies() | ForEach-Object { $_.GetType($lookupClass, 0) }) {
36-
return $true
37-
}
38-
# otherwise get package from the local system
3927
$dependencies = Get-ExternalLibrary -Type $Type
4028
foreach ($package in $dependencies) {
4129
$packageEntry = Get-Package $package.Name -RequiredVersion $package.Version -ProviderName nuget -ErrorAction SilentlyContinue

internal/classes/DBOpsLog.class.ps1

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ class DBOpsLog : DbUp.Engine.Output.IUpgradeLog {
5151
if ($this.logToFile) {
5252
$this.WriteToFile($format, $params)
5353
}
54-
$this.Status.DeploymentLog += $splatParam.Message
54+
if ($this.Status) {
55+
$this.Status.DeploymentLog += $splatParam.Message
56+
}
5557
}
5658
[void] WriteError([string]$format, [object[]]$params) {
5759
$level = switch ($this.silent) {
@@ -72,7 +74,9 @@ class DBOpsLog : DbUp.Engine.Output.IUpgradeLog {
7274
if ($this.logToFile) {
7375
$this.WriteToFile($format, $params)
7476
}
75-
$this.Status.DeploymentLog += $splatParam.Message
77+
if ($this.Status) {
78+
$this.Status.DeploymentLog += $splatParam.Message
79+
}
7680
}
7781
[void] WriteWarning([string]$format, [object[]]$params) {
7882
$level = switch ($this.silent) {
@@ -93,7 +97,9 @@ class DBOpsLog : DbUp.Engine.Output.IUpgradeLog {
9397
if ($this.logToFile) {
9498
$this.WriteToFile($format, $params)
9599
}
96-
$this.Status.DeploymentLog += $splatParam.Message
100+
if ($this.Status) {
101+
$this.Status.DeploymentLog += $splatParam.Message
102+
}
97103
}
98104
[void] WriteToFile([string]$format, [object[]]$params) {
99105
$format -f $params | Out-File $this.logToFile -Append

internal/functions/Get-ConnectionString.ps1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ function Get-ConnectionString {
6868
if ($Configuration.ApplicationName -and $csBuilder.ContainsKey('Application Name')) { $csBuilder["Application Name"] = $Configuration.ApplicationName }
6969
if ($Configuration.ExecutionTimeout -and $csBuilder.ContainsKey('Command Timeout')) { $csBuilder["Command Timeout"] = $Configuration.ExecutionTimeout }
7070
$csBuilder[$conn.ConnectionTimeout] = $Configuration.ConnectionTimeout
71+
if ($csBuilder.ContainsKey('Pooling')) { $csBuilder.Pooling = $false }
7172
# define authentication
7273
if ($Configuration.Credential) {
7374
$csBuilder["User ID"] = $Configuration.Credential.UserName

0 commit comments

Comments
 (0)