Skip to content

Commit

Permalink
Merge pull request #3 from webmd-health-services/feature/metadata-fun…
Browse files Browse the repository at this point in the history
…ctions

1.1.0 Metadata functions for Microsoft SQL Server
  • Loading branch information
splatteredbits authored Sep 10, 2024
2 parents f4c1ceb + 326beb2 commit 0783c21
Show file tree
Hide file tree
Showing 37 changed files with 2,531 additions and 522 deletions.
37 changes: 37 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!-- markdownlint-disable MD012 no-multiple-blanks -->

# Yodel Changelog

## 1.1.0

### Added

Functions specific to Microsoft SQL Server:

* `ConvertTo-YMsSqlIdentifier` for converting a string to an identifer, quoted with square brackets.
* `Get-YMsSqlExtendedProperty` for getting extended properties.
* `Get-YMsSqlSchema` for getting metadata about a schema.
* `Get-YMsSqlTable` for getting metadata about a table.
* `Get-YMsSqlTableColumn` for getting metadata about a table.
* `Initialize-YMsSqlDatabase` for creating a database.
* `Initialze-YMsSqlSchema` for creating a schema.
* `Invoke-YMsSqlCommand` for running queries and commands.
* `Remove-YMsSqlTable` for dropping a table.
* `Set-YMsSqlExtendedProperty` for adding/updating extended properties.
* `Test-YMsSqlExtendedProperty` for testing if an extended property exists.
* `Test-YMsSqlSchema` for testing if a schema exists.
* `Test-YMsSqlTable` for testing if a table exists.
* `Test-YMsSqlTableColumn` for testing if a table column exists.

### Deprecated

* The `Invoke-YSqlServerCommand` function. Replaced with `Invoke-YMsSqlCommand`.


## 1.0.0

> Released 18 Mar 2020
* Created Connect-YDatabase function for connecting to an ADO.NET data source, like a SQL Server database.
* Created Invoke-YDbCommand function for executing an ADO.NET command, like a SQL query or stored procedure.
* Created Invoke-YSqlServerCommand function for executing commands against a SQL Server database.
File renamed without changes.
5 changes: 5 additions & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Yodel

Copyright 2023 WebMD Health Services

This product includes software developed at WebMD Health Services (https://www.webmdhealthservices.com/).
44 changes: 22 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Yodel

A PowerShell module for querying databases using the native .NET ADO.NET data access framework.
A PowerShell module for querying databases using the native .NET ADO.NET data access framework.

# System Requirements

Expand Down Expand Up @@ -32,10 +32,10 @@ Save-Module -Name 'Yodel' -Path '.'

## SQL Server

The simplest command to use is `Invoke-YSqlServerCommand`. It connects to a SQL Server instance and database, runs a query, and closes the connection. Pass the name of the SQL Server instance to the `SqlServerName` parameter (`.` or the machine name for the default instance, `HOSTNAME\INSTANCE` for a named instance), the name of the database to the `Database` parameter, and the query to the `Text` parameter:
The simplest command to use is `Invoke-YMsSqlCommand`. It connects to a SQL Server instance and database, runs a query, and closes the connection. Pass the name of the SQL Server instance to the `SqlServerName` parameter (`.` or the machine name for the default instance, `HOSTNAME\INSTANCE` for a named instance), the name of the database to the `Database` parameter, and the query to the `Text` parameter:

```powershell
> Invoke-YSqlServerCommand -SqlServerName '.' -DatabaseName 'master' -Text 'select 1 First, 2, 3'
> Invoke-YMsSqlCommand -SqlServerName '.' -DatabaseName 'master' -Text 'select 1 First, 2, 3'
First Column0 Column1
----- ------- -------
Expand All @@ -47,14 +47,14 @@ You'll get an object back for each row returned. Each object will have propertie
If you have a query that returns a single value, use the `-AsScalar` switch:

```powershell
> Invoke-YSqlServerCommand -SqlServerName '.' -DatabaseName 'master' -Text 'select 1' -AsScalar
> Invoke-YMsSqlCommand -SqlServerName '.' -DatabaseName 'master' -Text 'select 1' -AsScalar
1
```

If your query doesn't return any results, use the `-NonQuery` switch. It will return the number of rows inserted/deleted (if any).

```powershell
> Invoke-YSqlServerCommand -SqlServerName '.' -DatabaseName 'master' -Text 'insert into example (id) values (1),(2),(3),(4)'
> Invoke-YMsSqlCommand -SqlServerName '.' -DatabaseName 'master' -Text 'insert into example (id) values (1),(2),(3),(4)'
4
```

Expand Down Expand Up @@ -102,46 +102,46 @@ finally

## SQL Server: Read Rows

The fastest way to query a SQL Server database is to use the `Invoke-YSqlServerCommand` function:
The fastest way to query a SQL Server database is to use the `Invoke-YMsSqlCommand` function:

```powershell
> Invoke-YSqlServerCommand -SqlServerName '.' -DatabaseName 'master' -Text 'select * from sys.object'
type principal_id is_published name type_desc schema_id is_ms_shipped parent_object_id is_schema_published modify_date
---- ------------ ------------ ---- --------- --------- ------------- ---------------- ------------------- -----------
> Invoke-YMsSqlCommand -SqlServerName '.' -DatabaseName 'master' -Text 'select * from sys.object'
type principal_id is_published name type_desc schema_id is_ms_shipped parent_object_id is_schema_published modify_date
---- ------------ ------------ ---- --------- --------- ------------- ---------------- ------------------- -----------
S False sysrscols SYSTEM_TABLE 4 True 0 False 8/22/2017 7:38:02 PM
S False sysrowsets SYSTEM_TABLE 4 True 0 False 8/22/2017 7:38:03 PM
S False sysclones SYSTEM_TABLE 4 True 0 False 8/22/2017 7:38:03 PM
S False sysallocunits SYSTEM_TABLE 4 True 0 False 8/22/2017 7:38:02 PM
S False sysfiles1 SYSTEM_TABLE 4 True 0 False 4/8/2003 9:13:37 AM
S False sysfiles1 SYSTEM_TABLE 4 True 0 False 4/8/2003 9:13:37 AM
```

The above example will connect to the master database in the local, default intance of SQL Server as the current user, and run the query `select * from sys.object` using integrated authentication. You'll get back an object for each row returned. Each object will have properties that match the column names in the result set. (If a column is missing a name, `Invoke-YSqlServerCommand` will create a generic `ColumnX` name for you, where `X` is number that increments for each nameless column.)
The above example will connect to the master database in the local, default intance of SQL Server as the current user, and run the query `select * from sys.object` using integrated authentication. You'll get back an object for each row returned. Each object will have properties that match the column names in the result set. (If a column is missing a name, `Invoke-YMsSqlCommand` will create a generic `ColumnX` name for you, where `X` is number that increments for each nameless column.)

## SQL Server: Run a Query That Returns a Single/Scalar Value

```powershell
> Invoke-YSqlServerCommand -SqlServerName '.' -DatabaseName 'master' -Text 'select 1' -AsScalar
> Invoke-YMsSqlCommand -SqlServerName '.' -DatabaseName 'master' -Text 'select 1' -AsScalar
1
```

## SQL Server: Run a Query That Returns No Results

```powershell
> Invoke-YSqlServerCommand -SqlServerName '.' -DatabaseName 'tempdb' -Text 'create table yodel (id int)' -NonQuery
> Invoke-YSqlServerCommand -SqlServerName '.' `
> Invoke-YMsSqlCommand -SqlServerName '.' -DatabaseName 'tempdb' -Text 'create table yodel (id int)' -NonQuery
> Invoke-YMsSqlCommand -SqlServerName '.' `
-DatabaseName 'tempdb' `
-Text 'insert into yodel (id) values (1),(2)' `
-NonQuery
2
> Invoke-YSqlServerCommand -SqlServerName '.' -DatabaseName 'tempdb' -Text 'delete from yodel' -NonQuery
> Invoke-YMsSqlCommand -SqlServerName '.' -DatabaseName 'tempdb' -Text 'delete from yodel' -NonQuery
2
```

## SQL Server: Parameterized Queries

```powershell
> Invoke-YSqlServerCommand -SqlServerName '.' `
> Invoke-YMsSqlCommand -SqlServerName '.' `
-DatabaseName 'master' `
-Text 'select * from sys.system_views where name = @name' `
-Parameter @{ '@name' = 'views' }
Expand All @@ -155,7 +155,7 @@ has_unchecked_assembly_data is_tracked_by_cdc is_published modify_date
## SQL Server: Add Properties to Connection String

```powershell
> Invoke-YSqlServerCommand -SqlServerName '.' `
> Invoke-YMsSqlCommand -SqlServerName '.' `
-DatabaseName 'master' `
-ConnectionString 'Application Name=Yodel' `
-Text 'select APP_NAME()' `
Expand All @@ -166,7 +166,7 @@ Yodel
## SQL Server: Change Query Timeout

```powershell
> Invoke-YSqlServerCommand -SqlServerName '.' `
> Invoke-YMsSqlCommand -SqlServerName '.' `
-DatabaseName 'master' `
-Text 'select 1' `
-Timeout 120
Expand All @@ -175,7 +175,7 @@ Yodel
## SQL Server: Execute a Stored Procedure

```powershell
Invoke-YSqlServerCommand -SqlServerName '.' `
Invoke-YMsSqlCommand -SqlServerName '.' `
-DatabaseName 'master' `
-Text 'sp_addrolemember' `
-CommandType [Data.CommandType]::StoredProcedure `
Expand All @@ -186,7 +186,7 @@ Invoke-YSqlServerCommand -SqlServerName '.' `

```powershell
$credential = Get-Credential
$username = Invoke-YSqlServerCommand -SqlServerName '.' `
$username = Invoke-YMsSqlCommand -SqlServerName '.' `
-DatabaseName 'master' `
-Credential $credential `
-Text 'select suser_name()' `
Expand Down Expand Up @@ -402,7 +402,7 @@ Detailed documentation is available via PowerShell's help system. Import the mod
```powershell
Import-Module Yodel
> Get-Help Invoke-YSqlServerCommand
> Get-Help Invoke-YMsSqlCommand
> Get-Help Connect-YDatabase
> Get-Help Invoke-YDbCommand
```
Expand Down
2 changes: 1 addition & 1 deletion Tests/Connect-YDatabase.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ Describe 'Connect-YDatabase.when connecting to SQL Server with credential' {
AfterEach { Reset }
It 'should open the connection' {
Init
$credential = GivenTestUser -SqlServerName $sqlServerName
$credential = GivenMsSqlTestUser -SqlServerName $sqlServerName
WhenOpeningConnection -ToServer $sqlServerName -ToDatabase 'master' -WithCredential $credential
ThenConnectionOpened
}
Expand Down
43 changes: 43 additions & 0 deletions Tests/Get-YMsSqlExtendedProperty.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

#Requires -Version 5.1
Set-StrictMode -Version 'Latest'

BeforeAll {
Set-StrictMode -Version 'Latest'

& (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-YodelTest.ps1' -Resolve)

$script:conn = Get-YTMSSqlConnection
}

Describe 'Get-ExtendedProperty' {
BeforeEach {
}

AfterEach {
}

It 'gets extended property on schema' {
$schemaName = 'get-ymssqlextendedproperty'
$propName = 'Yodel_Get-ExtendedProperty_Test1'
GivenMSSqlSchema $schemaName
GivenMSSqlExtendedProperty $propName -WithValue 'from test 1' -OnSchema $schemaName
ThenMSSqlExtendedProperty $propName -OnSchema $schemaName -HasValue 'from test 1'
}

It 'gets extended property on table' {
$tableName = 'get-extendedproptable'
$propName = 'Yodel_Get-ExtendedProperty_Test2'
GivenMSSqlTable $tableName 'id int not null'
GivenMSSqlExtendedProperty $propName -WithValue 'from test 2' -OnTable $tableName
ThenMSSqlExtendedProperty $propName -OnTable $tableName -HasValue 'from test 2'
}

It 'gets extended property on table column' {
$tableName = 'get-extendedproptable'
$propName = 'Yodel_Get-ExtendedProperty_Test3'
GivenMSSqlTable $tableName 'id int not null'
GivenMSSqlExtendedProperty $propName -WithValue 'from test 3' -OnTable $tableName -OnColumn 'id'
ThenMSSqlExtendedProperty $propName -OnTable $tableName -OnColumn 'id' -HasValue 'from test 3'
}
}
74 changes: 74 additions & 0 deletions Tests/Get-YMsSqlTableColumn.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@

#Requires -Version 5.1
Set-StrictMode -Version 'Latest'

BeforeAll {
Set-StrictMode -Version 'Latest'

& (Join-Path -Path $PSScriptRoot -ChildPath 'Initialize-YodelTest.ps1' -Resolve)

$script:conn = Get-YTMSSqlConnection
$script:schemaName = 'get-ymssqltablecolumn'
}

Describe 'Get-YMsSqlTableColumn' {
BeforeAll {
GivenMSSqlSchema $script:schemaName
}

BeforeEach {
$Global:Error.Clear()
}

AfterEach {
}

It 'gets columns' {
GivenMSSqlTable 'get-ymssqltablecolumn_1' `
-Column @('id int not null', 'id2 nvarchar') `
-InSchema $script:schemaName
$columns = Get-YMsSqlTableColumn -Connection $script:conn `
-SchemaName $script:schemaName `
-TableName 'get-ymssqltablecolumn_1'
$columns | Should -Not -BeNullOrEmpty
$columns | Should -HaveCount 2
$columns[0].name | Should -Be 'id'
$columns[1].name | Should -Be 'id2'
}

It 'gets a column' {
GivenMSSqlTable 'get-ymssqltablecolumn_2' -Column @('id3 int not null', 'id4 nvarchar')
$column = Get-YMSSqlTableColumn -Connection $script:conn -TableName 'get-ymssqltablecolumn_2' -Name 'id3'
$column | Should -Not -BeNullOrEmpty
$column | Should -HaveCount 1
$column.name | Should -Be 'id3'
}

It 'validates table exists' {
$result = Get-YMsSqlTableColumn -Connection $script:conn `
-TableName 'get-ymssqltablecolumn_3' `
-ErrorAction SilentlyContinue
$result | Should -BeNullOrEmpty
$Global:Error | Should -Match ([regex]::Escape('[dbo].[get-ymssqltablecolumn_3] does not exist'))
}

It 'validates column exists' {
GivenMSSqlTable 'get-ymssqltablecolumn_4' -Column @('id5 int not null')
$result = Get-YMsSqlTableColumn -Connection $script:conn `
-TableName 'get-ymssqltablecolumn_4' `
-Name 'id6' `
-ErrorAction SilentlyContinue
$result | Should -BeNullOrEmpty
$Global:Error | Should -Match 'Column \[id6\] does not exist'
}

It 'ignores errors' {
GivenMSSqlTable 'get-ymssqltablecolumn_5' -Column @('id7 int not null')
$result = Get-YMsSqlTableColumn -Connection $script:conn `
-TableName 'get-ymssqltablecolumn_5' `
-Name 'id8' `
-ErrorAction Ignore
$result | Should -BeNullOrEmpty
$Global:Error | Should -BeNullOrEmpty
}
}
Loading

0 comments on commit 0783c21

Please sign in to comment.