InvokeTranspileSQL.ps1

#requires -Modules PSStringScanner

function ConvertFrom-SQLToPS {
    param(
        [Parameter(Mandatory)]
        $SQL
    )

    Invoke-TranspileSQL $SQL | ConvertFrom-TranspileSQL
}

function Add-PSOp {
    param($target)

    $target | Add-Member -PassThru -MemberType ScriptProperty -Name PSOp -Value {
        switch ($this.operation) {
            "<>" { "-ne" }
            ">=" { "-ge" }
            "<=" { "-le" }
            "=" { "-eq" }
            ">" { "-gt" }
            "<" { "-lt" }
            "like" { "-like" }
            "match" { "-match" }
            default { $_ }
        }
    }
}

function Add-PSLogicOp {
    param($target)

    $target | Add-Member -PassThru -MemberType ScriptProperty -Name PSLogicOp -Value {
        if ($this.LogicOp) {
            "-" + $this.LogicOp
        }
    }
}

function Invoke-TranspileSQL {
    param(
        [Parameter(Mandatory)]
        $SQL
    )

    $ss = New-PSStringScanner $sql

    $SELECT_KW = "^[Ss][Ee][Ll][Ee][Cc][Tt]\s+"
    $FROM_KW = "[Ff][Rr][Oo][Mm]"
    $WHERE_KW = "[Ww][Hh][Ee][Rr][Ee]"
    $OPERATIONS = "<>|<=|>=|>|<|=|like|match"
    $LOGICAL = "[Oo][rR]|[Aa][Nn][Dd]"
    $WHITESPACE = "\s+"

    $h = [Ordered]@{ }

    if ($ss.Check($SELECT_KW)) {
        $null = $ss.Scan($SELECT_KW)

        $h.SelectPropertyNames = ($ss.ScanUntil("(?=$FROM_KW)")).trim()

        if ($h.SelectPropertyNames.Contains(',')) {
            $h.SelectPropertyNames = $h.SelectPropertyNames.Split(',').foreach( { $_.trim() })
        }

        $null = $ss.Skip($FROM_KW)

        if ($ss.Check($WHERE_KW)) {
            $h.DataSetName = $ss.ScanUntil("(?=$WHERE_KW)").trim()
            $null = $ss.Skip("$WHERE_KW")

            $ssWhere = New-PSStringScanner $ss.Scan(".*")

            $whereResults = @()

            while (!$ssWhere.EoS()) {
                $currentResult = [Ordered]@{ }
                $currentResult.propertyName = $ssWhere.ScanUntil("(?=$OPERATIONS)").trim()
                $currentResult.operation = $ssWhere.Scan($OPERATIONS)

                if ($ssWhere.Check("$($WHITESPACE)$($LOGICAL)")) {
                    $currentResult.value = $ssWhere.ScanUntil("(?=$($WHITESPACE)$($LOGICAL))")
                    $currentResult.logicOp = $ssWhere.Scan($LOGICAL)
                }
                else {
                    $currentResult.value = $ssWhere.Scan('.*').Trim()
                }

                $obj = Add-PSOp ([PSCustomObject]$currentResult)
                $obj = Add-PSLogicOp $obj

                $whereResults += [PSCustomObject]$obj
            }
        }
        else {
            $h.DataSetName = $ss.Scan(".*").trim()
        }
    }

    if ($whereResults) {
        $h.where = [PSCustomObject[]]$whereResults
    }
    $h
}

function ConvertFrom-TranspileSQL {
    param(
        [Parameter(ValueFromPipeline)]
        [System.Collections.Specialized.OrderedDictionary]
        $map
    )

    $SelectPropertyNames = $map.SelectPropertyNames

    if ($SelectPropertyNames -ne '*') {
        $SelectPropertyNames = $SelectPropertyNames -join '","'
        $SelectPropertyNames = '"' + $SelectPropertyNames + '"'
    }

    if ($map.Contains("where")) {
        $sqlResult += "| Where-Object {"
        foreach ($whereRecord in $map.Where) {
            $sqlResult += '$_.{0} {1} {2} {3} ' -f $whereRecord.propertyName, $whereRecord.PSOp, $whereRecord.value.trim(), $whereRecord.PSLogicOp
            if ($null -eq $whereRecord.PSLogicOp) { $sqlResult = $sqlResult.Trim() }
        }
        $sqlResult += "}"
    }

    $sqlResult += " | Select-Object -Property $($SelectPropertyNames)"

    $sqlResult
}

Update-TypeData -Force -TypeName Array -MemberType ScriptMethod -MemberName query -Value {
    param($q)

    $psquery = Invoke-TranspileSQL $q | ConvertFrom-TranspileSQL

    Invoke-Expression "`$this $psquery"
}