Skip to main content

PowerShell for creating a Keyword/Value connection string from a hashtable.

<#
.SYNOPSIS
    Creates a new PostgreSQL key/value connection string.

.DESCRIPTION
    Creates a new PostgreSQL key/value connection string from an ordered hashtable.

    This function does not validate whether or not key/value pairs are acceptable connection string parameters.
    For a list of acceptable connection string key/value pairs, see: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-KEYWORD-VALUE

.PARAMETER OrderedHashTable
    An [ordered] hashtable of connection string key/value pairs.

    For a list of acceptable connection string key/value pairs,
    see: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-KEYWORD-VALUE

.PARAMETER NoEscaping
    If present, no escaping will be performed.

    The default behavior is to escape single quotes and backslashes in values, with a backslash.
    e.g., \' and \\.
    Empty values will always be quoted in single quotes.

.PARAMETER OutputInDoubleQuotes
    If present, the entire output will be wrapped in double quotes.

.EXAMPLE
    PS> $connectionProps = [ordered]@{
        'host'          = '127.0.0.1'
        'username'      = "It's my first name"
        'path'          = 'C:\some\path\with spaces\and\back-slashes'
        'empty-value'   = ''
        'null-value'    = $null
    }

    PS> Get-PostgreSqlConnectionString -OrderedHashTable $connectionProps
    host=127.0.0.1 username='It\'s my first name' path='C:\\some\\path\\with spaces\\and\\back-slashes' empty-value='' null-value=''

    PS> Get-PostgreSqlConnectionString -OrderedHashTable $connectionProps -NoEscaping
    host=127.0.0.1 username='It's my first name' path='C:\some\path\with spaces\and\back-slashes' empty-value='' null-value=''

    PS> Get-PostgreSqlConnectionString -OrderedHashTable $connectionProps -OutputInDoubleQuotes
    "host=127.0.0.1 username='It\'s my first name' path='C:\\some\\path\\with spaces\\and\\back-slashes' empty-value='' null-value=''"

    PS> Get-PostgreSqlConnectionString -OrderedHashTable $connectionProps -NoEscaping -OutputInDoubleQuotes
    "host=127.0.0.1 username='It's my first name' path='C:\some\path\with spaces\and\back-slashes' empty-value='' null-value=''"

.LINK
    https://jonlabelle.com/snippets/view/powershell/create-a-postgresql-keywordvalue-connection-string
#>
function Get-PostgreSqlConnectionString
{
    [CmdletBinding()]
    [OutputType([System.String])]
    param(
        [Parameter(Position = 0)]
        [AllowEmptyCollection()]
        [System.Collections.Specialized.OrderedDictionary]
        $OrderedHashTable,

        [Parameter()]
        [switch]
        $NoEscaping,

        [Parameter()]
        [switch]
        $OutputInDoubleQuotes
    )

    $result = New-Object -TypeName System.Text.StringBuilder

    foreach ($kvp in $OrderedHashTable.GetEnumerator())
    {
        if (([string]::IsNullOrWhiteSpace($kvp.Key)) -eq $true)
        {
            Write-Error 'Null or empty keys in your -OrderedHashTable parameter are not allowed'
            return
        }

        $key = $kvp.Key.Trim().ToLower()
        $val = $kvp.Value

        if (([string]::IsNullOrWhiteSpace($val)) -eq $true)
        {
            # To write an empty value, surround it with single quotes
            $null = $result.AppendFormat("{0}='' ", $key)
            continue
        }

        if (-not $NoEscaping)
        {
            $escapedValue = New-Object -TypeName System.Text.StringBuilder -ArgumentList ($val.Length * 2)

            # Single quotes and backslashes within a value must be escaped with a backslash, i.e., \' and \\
            foreach ($char in $val.ToCharArray())
            {
                if ($char -eq [char]"'")
                {
                    $null = $escapedValue.Append("\'")
                    continue
                }

                if ($char -eq [char]'\')
                {
                    $null = $escapedValue.Append('\\')
                    continue
                }

                $null = $escapedValue.Append($char)
            }

            $val = $escapedValue.ToString()
        }

        $val = $val.Trim()

        # To write a value containing spaces, surround it with single quotes
        $needsQuoting = (($val.Contains(' ')) -or ($val -eq ''))
        if ($needsQuoting)
        {
            $null = $result.AppendFormat("{0}='{1}' ", $key, $val)
        }
        else
        {
            $null = $result.AppendFormat('{0}={1} ', $key, $val)
        }
    }

    $output = $result.ToString().Trim()

    if ($OutputInDoubleQuotes)
    {
        '"{0}"' -f $output
    }
    else
    {
        $output
    }
}

# --------------------------------------------------------
# Example
# --------------------------------------------------------

$connectionProps = [ordered]@{
    'host' = '127.0.0.1'
    'username' = "It's my first name"
    'path' = 'C:\some\path\with spaces\and\back-slashes'
    'empty-value' = ''
    'null-value' = $null
}

Get-PostgreSqlConnectionString -OrderedHashTable $connectionProps
# host=127.0.0.1 username='It\'s my first name' path='C:\\some\\path\\with spaces\\and\\back-slashes' empty-value='' null-value=''

Get-PostgreSqlConnectionString -OrderedHashTable $connectionProps -NoEscaping
# host=127.0.0.1 username='It's my first name' path='C:\some\path\with spaces\and\back-slashes' empty-value='' null-value=''

Get-PostgreSqlConnectionString -OrderedHashTable $connectionProps -OutputInDoubleQuotes
# "host=127.0.0.1 username='It\'s my first name' path='C:\\some\\path\\with spaces\\and\\back-slashes' empty-value='' null-value=''"

Get-PostgreSqlConnectionString -OrderedHashTable $connectionProps -NoEscaping -OutputInDoubleQuotes
# "host=127.0.0.1 username='It's my first name' path='C:\some\path\with spaces\and\back-slashes' empty-value='' null-value=''"