Private/Container/Invoke-NAVGitContainerSql.ps1

function Invoke-NAVGitContainerSql {
    <#
    .SYNOPSIS
        Runs a SQL query against the container's NAV database from inside the container (Invoke-Sqlcmd as the
        container administrator, the same way BcContainerHelper does). Rows come back as PSCustomObjects.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string] $ContainerName,

        [Parameter(Mandatory)]
        [string] $Query
    )

    $json = Invoke-ScriptInBcContainer -containerName $ContainerName -argumentList $Query -scriptblock {
        param($Query)

        $customConfigFile = Join-Path (Get-Item 'C:\Program Files\Microsoft Dynamics NAV\*\Service').FullName 'CustomSettings.config'
        [xml]$customConfig = [System.IO.File]::ReadAllText($customConfigFile)
        $databaseServer = $customConfig.SelectSingleNode("//appSettings/add[@key='DatabaseServer']").Value
        $databaseInstance = $customConfig.SelectSingleNode("//appSettings/add[@key='DatabaseInstance']").Value
        $databaseName = $customConfig.SelectSingleNode("//appSettings/add[@key='DatabaseName']").Value
        if ($databaseInstance) { $databaseServer += "\$databaseInstance" }

        $rows = @(Invoke-Sqlcmd -ServerInstance $databaseServer -Database $databaseName -Query $Query -QueryTimeout 600 -MaxCharLength 8000)
        $result = @(foreach ($row in $rows) {
                if ($null -eq $row -or -not $row.Table) { continue }
                $item = [ordered]@{}
                foreach ($column in $row.Table.Columns) {
                    $value = $row[$column.ColumnName]
                    if ($value -is [System.DBNull]) { $value = $null }
                    $item[$column.ColumnName] = $value
                }
                $item
            })
        ConvertTo-Json -InputObject $result -Depth 3 -Compress
    }

    if (-not $json) {
        return @()
    }
    return @(ConvertFrom-Json -InputObject ($json -join '') | ForEach-Object { $_ })
}

function Get-NAVGitDbObjects {
    <#
    .SYNOPSIS
        Objects in the container database (no TableData). System objects (>= 2000000000) are included so exported
        system tables in the repository compare as unchanged; Compare-NAVGitObjects never reports them as missing.
        Returns [pscustomobject]@{ Type; TypeId; Id; Name; Modified; VersionList; Date; Time; Compiled }.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string] $ContainerName
    )

    $query = @'
SELECT [Type], [ID], [Name], [Modified], [Version List] AS VersionList,
       CONVERT(varchar(19), [Date], 120) AS DateText, CONVERT(varchar(19), [Time], 120) AS TimeText, [Compiled]
FROM [dbo].[Object]
WHERE [Type] > 0 AND [Company Name] = ''
'@

    $rows = Invoke-NAVGitContainerSql -ContainerName $ContainerName -Query $query
    return @(foreach ($row in $rows) {
            [pscustomobject]@{
                Type        = Get-NAVGitObjectTypeName -TypeId ([int]$row.Type)
                TypeId      = [int]$row.Type
                Id          = [int]$row.ID
                Name        = $row.Name
                Modified    = ([int]$row.Modified -eq 1)
                VersionList = "$($row.VersionList)"
                Date        = ConvertFrom-NAVGitSqlDateTime -Text $row.DateText -Part Date
                Time        = ConvertFrom-NAVGitSqlDateTime -Text $row.TimeText -Part Time
                Compiled    = ([int]$row.Compiled -eq 1)
            }
        })
}

function Set-NAVGitUidOffset {
    <#
    .SYNOPSIS
        Sets the database's Uid Offset (C/SIDE Tools > Options), which C/SIDE uses to number new objects and fields.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string] $ContainerName,

        [Parameter(Mandatory)]
        [int] $UidOffset
    )

    $null = Invoke-NAVGitContainerSql -ContainerName $ContainerName -Query ('UPDATE [dbo].[$ndo$dbproperty] SET [uidoffset] = {0}' -f $UidOffset)
}

function Set-NAVGitObjectsDeleted {
    <#
    .SYNOPSIS
        Marks objects as deleted by setting their Version List to '#DELETE' (as AdvaniaGIT did); they can then be
        removed in C/SIDE with the filter Version List=#DELETE.
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string] $ContainerName,

        [Parameter(Mandatory)]
        [object[]] $Objects
    )

    $conditions = @($Objects | ForEach-Object { "([Type] = $([int]$_.TypeId) AND [ID] = $([int]$_.Id))" })
    # Keep statements reasonably small.
    for ($i = 0; $i -lt $conditions.Count; $i += 200) {
        $batch = $conditions[$i..([Math]::Min($i + 199, $conditions.Count - 1))] -join ' OR '
        $null = Invoke-NAVGitContainerSql -ContainerName $ContainerName -Query "UPDATE [dbo].[Object] SET [Version List] = '#DELETE' WHERE [Company Name] = '' AND ($batch)"
    }
}

function Get-NAVGitUncompiledObjects {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string] $ContainerName
    )

    return @(Get-NAVGitDbObjects -ContainerName $ContainerName | Where-Object { -not $_.Compiled -and $_.Id -lt 2000000000 })
}