functions/private/Invoke-UniversalSQLiteQuery.ps1
|
function Invoke-UniversalSQLiteQuery { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$Path, [Parameter(Mandatory)] [string]$Query ) # Verify sqlite3 is available if (-not (Get-Command sqlite3 -ErrorAction SilentlyContinue)) { throw "sqlite3 command not found. Please install SQLite." } # Verify database exists if (-not (Test-Path $Path)) { throw "Database file not found: $Path" } # Resolve full path $dbPath = Resolve-Path $Path | Select-Object -ExpandProperty Path # Use .timeout command for sqlite3 CLI (doesn't return output, just sets connection timeout) # This is critical for concurrent access in web apps (5000ms = 5 seconds) $timeoutCmd = ".timeout 5000" $combinedInput = "$timeoutCmd`n$Query" # Try JSON output first (best for structured data) # Always pass via stdin to ensure .timeout command is processed first $output = $combinedInput | sqlite3 $dbPath -json - 2>&1 # Check for errors if ($LASTEXITCODE -ne 0) { throw "SQLite query failed: $output" } # Parse output if ($output) { try { # Try to parse as JSON $result = $output | ConvertFrom-Json return $result } catch { # JSON parsing failed, try CSV mode for better compatibility $csvOutput = $combinedInput | sqlite3 $dbPath -csv -header - 2>&1 if ($LASTEXITCODE -eq 0 -and $csvOutput) { try { # Convert CSV to objects $result = $csvOutput | ConvertFrom-Csv return $result } catch { # If CSV also fails, return raw output return $csvOutput } } # Fallback to raw output return $output } } return $null } |