Skip to content

Commit f21f52b

Browse files
authored
Add Get-SqlDscDateTime and Invoke-SqlDscScalarQuery commands (#2371)
1 parent 5202a10 commit f21f52b

10 files changed

+987
-0
lines changed

CHANGELOG.md

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

88
### Added
99

10+
- Added public command `Invoke-SqlDscScalarQuery` to execute scalar queries using
11+
`Server.ConnectionContext.ExecuteScalar()`. Server-level, lightweight execution
12+
that does not require any database to be online
13+
([issue #2423](https://github.com/dsccommunity/SqlServerDsc/issues/2423)).
14+
- Added public command `Get-SqlDscDateTime` to retrieve current date and time from
15+
SQL Server instance. Supports multiple T-SQL date/time functions to eliminate
16+
clock-skew and timezone issues between client and server
17+
([issue #2423](https://github.com/dsccommunity/SqlServerDsc/issues/2423)).
1018
- Added public command `Backup-SqlDscDatabase` to perform database backups using
1119
SMO's `Microsoft.SqlServer.Management.Smo.Backup` class. Supports full,
1220
differential, and transaction log backups with options for compression,

azure-pipelines.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,8 @@ stages:
302302
'tests/Integration/Commands/Connect-SqlDscDatabaseEngine.Integration.Tests.ps1'
303303
'tests/Integration/Commands/Disconnect-SqlDscDatabaseEngine.Integration.Tests.ps1'
304304
'tests/Integration/Commands/Invoke-SqlDscQuery.Integration.Tests.ps1'
305+
'tests/Integration/Commands/Invoke-SqlDscScalarQuery.Integration.Tests.ps1'
306+
'tests/Integration/Commands/Get-SqlDscDateTime.Integration.Tests.ps1'
305307
# Group 4
306308
'tests/Integration/Commands/Assert-SqlDscLogin.Integration.Tests.ps1'
307309
'tests/Integration/Commands/New-SqlDscLogin.Integration.Tests.ps1'
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
<#
2+
.SYNOPSIS
3+
Retrieves the current date and time from a SQL Server instance.
4+
5+
.DESCRIPTION
6+
Retrieves the current date and time from a SQL Server instance using the
7+
specified T-SQL date/time function. This command helps eliminate clock-skew
8+
and timezone issues when coordinating time-sensitive operations between the
9+
client and SQL Server.
10+
11+
The command queries SQL Server using the server connection context, which
12+
does not require any database to be online.
13+
14+
.PARAMETER ServerObject
15+
Specifies current server connection object.
16+
17+
.PARAMETER DateTimeFunction
18+
Specifies which T-SQL date/time function to use for retrieving the date and time.
19+
Valid values are:
20+
- `SYSDATETIME` (default): Returns datetime2(7) with server local time
21+
- `SYSDATETIMEOFFSET`: Returns datetimeoffset(7) with server local time and timezone offset
22+
- `SYSUTCDATETIME`: Returns datetime2(7) with UTC time
23+
- `GETDATE`: Returns datetime with server local time
24+
- `GETUTCDATE`: Returns datetime with UTC time
25+
26+
.PARAMETER StatementTimeout
27+
Specifies the query StatementTimeout in seconds. Default 600 seconds (10 minutes).
28+
29+
.INPUTS
30+
`Microsoft.SqlServer.Management.Smo.Server`
31+
32+
Accepts input via the pipeline.
33+
34+
.OUTPUTS
35+
`System.DateTime`
36+
37+
Returns the current date and time from the SQL Server instance.
38+
39+
.EXAMPLE
40+
$serverObject = Connect-SqlDscDatabaseEngine
41+
Get-SqlDscDateTime -ServerObject $serverObject
42+
43+
Connects to the default instance and retrieves the current date and time
44+
using the default SYSDATETIME function.
45+
46+
.EXAMPLE
47+
$serverObject = Connect-SqlDscDatabaseEngine
48+
$serverObject | Get-SqlDscDateTime -DateTimeFunction 'SYSUTCDATETIME'
49+
50+
Connects to the default instance and retrieves the current UTC date and time
51+
from the SQL Server instance.
52+
53+
.EXAMPLE
54+
$serverObject = Connect-SqlDscDatabaseEngine
55+
$serverTime = Get-SqlDscDateTime -ServerObject $serverObject
56+
Restore-SqlDscDatabase -ServerObject $serverObject -Name 'MyDatabase' -StopAt $serverTime.AddHours(-1)
57+
58+
Demonstrates using the server's clock for a point-in-time restore operation,
59+
avoiding clock skew issues between client and server.
60+
#>
61+
function Get-SqlDscDateTime
62+
{
63+
[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.')]
64+
[OutputType([System.DateTime])]
65+
[CmdletBinding()]
66+
param
67+
(
68+
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
69+
[Microsoft.SqlServer.Management.Smo.Server]
70+
$ServerObject,
71+
72+
[Parameter()]
73+
[ValidateSet('SYSDATETIME', 'SYSDATETIMEOFFSET', 'SYSUTCDATETIME', 'GETDATE', 'GETUTCDATE')]
74+
[System.String]
75+
$DateTimeFunction = 'SYSDATETIME',
76+
77+
[Parameter()]
78+
[ValidateNotNull()]
79+
[System.Int32]
80+
$StatementTimeout = 600
81+
)
82+
83+
process
84+
{
85+
Write-Verbose -Message (
86+
$script:localizedData.Get_SqlDscDateTime_RetrievingDateTime -f $DateTimeFunction
87+
)
88+
89+
$query = "SELECT $DateTimeFunction()"
90+
91+
$invokeSqlDscScalarQueryParameters = @{
92+
ServerObject = $ServerObject
93+
Query = $query
94+
StatementTimeout = $StatementTimeout
95+
ErrorAction = 'Stop'
96+
Verbose = $VerbosePreference
97+
}
98+
99+
try
100+
{
101+
$result = Invoke-SqlDscScalarQuery @invokeSqlDscScalarQueryParameters
102+
103+
# Convert the result to DateTime if it's a DateTimeOffset
104+
if ($result -is [System.DateTimeOffset])
105+
{
106+
$result = $result.DateTime
107+
}
108+
109+
return $result
110+
}
111+
catch
112+
{
113+
$writeErrorParameters = @{
114+
Message = $script:localizedData.Get_SqlDscDateTime_FailedToRetrieve -f $DateTimeFunction, $_.Exception.Message
115+
Category = 'InvalidOperation'
116+
ErrorId = 'GSDD0001' # cSpell: disable-line
117+
TargetObject = $DateTimeFunction
118+
Exception = $_.Exception
119+
}
120+
121+
Write-Error @writeErrorParameters
122+
123+
return
124+
}
125+
}
126+
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<#
2+
.SYNOPSIS
3+
Executes a scalar query on the specified server.
4+
5+
.DESCRIPTION
6+
Executes a scalar query on the specified server using the server connection
7+
context. This command is designed for queries that return a single value,
8+
such as `SELECT @@VERSION` or `SELECT SYSDATETIME()`.
9+
10+
The command uses `Server.ConnectionContext.ExecuteScalar()` which is
11+
server-level and does not require any database to be online.
12+
13+
.PARAMETER ServerObject
14+
Specifies current server connection object.
15+
16+
.PARAMETER Query
17+
Specifies the scalar query string to execute.
18+
19+
.PARAMETER StatementTimeout
20+
Specifies the query StatementTimeout in seconds. Default 600 seconds (10 minutes).
21+
22+
.PARAMETER RedactText
23+
Specifies one or more text strings to redact from the query when verbose messages
24+
are written to the console. Strings will be escaped so they will not
25+
be interpreted as regular expressions (RegEx).
26+
27+
.INPUTS
28+
`Microsoft.SqlServer.Management.Smo.Server`
29+
30+
Accepts input via the pipeline.
31+
32+
.OUTPUTS
33+
`System.Object`
34+
35+
Returns the scalar value returned by the query.
36+
37+
.EXAMPLE
38+
$serverObject = Connect-SqlDscDatabaseEngine
39+
Invoke-SqlDscScalarQuery -ServerObject $serverObject -Query 'SELECT @@VERSION'
40+
41+
Connects to the default instance and then runs a query to return the SQL Server version.
42+
43+
.EXAMPLE
44+
$serverObject = Connect-SqlDscDatabaseEngine
45+
$serverObject | Invoke-SqlDscScalarQuery -Query 'SELECT SYSDATETIME()'
46+
47+
Connects to the default instance and then runs the query to return the current
48+
date and time from the SQL Server instance.
49+
50+
.EXAMPLE
51+
$serverObject = Connect-SqlDscDatabaseEngine
52+
Invoke-SqlDscScalarQuery -ServerObject $serverObject -Query "SELECT name FROM sys.databases WHERE name = 'MyPassword123'" -RedactText @('MyPassword123') -Verbose
53+
54+
Shows how to redact sensitive information in the query when the query string
55+
is output as verbose information when the parameter Verbose is used.
56+
#>
57+
function Invoke-SqlDscScalarQuery
58+
{
59+
[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.')]
60+
[OutputType([System.Object])]
61+
[CmdletBinding()]
62+
param
63+
(
64+
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
65+
[Microsoft.SqlServer.Management.Smo.Server]
66+
$ServerObject,
67+
68+
[Parameter(Mandatory = $true)]
69+
[System.String]
70+
$Query,
71+
72+
[Parameter()]
73+
[ValidateNotNull()]
74+
[System.Int32]
75+
$StatementTimeout = 600,
76+
77+
[Parameter()]
78+
[ValidateNotNullOrEmpty()]
79+
[System.String[]]
80+
$RedactText
81+
)
82+
83+
process
84+
{
85+
$redactedQuery = $Query
86+
87+
if ($PSBoundParameters.ContainsKey('RedactText'))
88+
{
89+
$redactedQuery = ConvertTo-RedactedText -Text $Query -RedactPhrase $RedactText
90+
}
91+
92+
Write-Verbose -Message (
93+
$script:localizedData.Invoke_SqlDscScalarQuery_ExecutingQuery -f $redactedQuery
94+
)
95+
96+
$previousStatementTimeout = $null
97+
98+
if ($PSBoundParameters.ContainsKey('StatementTimeout'))
99+
{
100+
# Make sure we can return the StatementTimeout before exiting.
101+
$previousStatementTimeout = $ServerObject.ConnectionContext.StatementTimeout
102+
103+
$ServerObject.ConnectionContext.StatementTimeout = $StatementTimeout
104+
}
105+
106+
try
107+
{
108+
$result = $ServerObject.ConnectionContext.ExecuteScalar($Query)
109+
110+
return $result
111+
}
112+
catch
113+
{
114+
$writeErrorParameters = @{
115+
Message = $script:localizedData.Invoke_SqlDscScalarQuery_FailedToExecute -f $_.Exception.Message
116+
Category = 'InvalidOperation'
117+
ErrorId = 'ISDSQ0002' # cSpell: disable-line
118+
TargetObject = $redactedQuery
119+
Exception = $_.Exception
120+
}
121+
122+
Write-Error @writeErrorParameters
123+
124+
return
125+
}
126+
finally
127+
{
128+
if ($null -ne $previousStatementTimeout)
129+
{
130+
$ServerObject.ConnectionContext.StatementTimeout = $previousStatementTimeout
131+
}
132+
}
133+
}
134+
}

source/en-US/SqlServerDsc.strings.psd1

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,4 +632,12 @@ ConvertFrom-StringData @'
632632
Get_SqlDscSetupLog_Header = ==== SQL Server Setup {0} (from {1}) ==== (GSDSL0004)
633633
Get_SqlDscSetupLog_Footer = ==== End of {0} ==== (GSDSL0005)
634634
Get_SqlDscSetupLog_PathNotFound = Path '{0}' does not exist. (GSDSL0006)
635+
636+
## Invoke-SqlDscScalarQuery
637+
Invoke_SqlDscScalarQuery_ExecutingQuery = Executing the scalar query `{0}`. (ISDSQ0001)
638+
Invoke_SqlDscScalarQuery_FailedToExecute = Failed to execute scalar query: {0} (ISDSQ0002)
639+
640+
## Get-SqlDscDateTime
641+
Get_SqlDscDateTime_RetrievingDateTime = Retrieving date and time using {0}(). (GSDD0001)
642+
Get_SqlDscDateTime_FailedToRetrieve = Failed to retrieve date and time using {0}(): {1} (GSDD0002)
635643
'@

0 commit comments

Comments
 (0)