Skip to content

Instantly share code, notes, and snippets.

@jhoneill
Last active August 17, 2023 18:01
Show Gist options
  • Save jhoneill/b2b386fa8a512ff74613d562c955c58d to your computer and use it in GitHub Desktop.
Save jhoneill/b2b386fa8a512ff74613d562c955c58d to your computer and use it in GitHub Desktop.
using namespace System.Data
class QueryColumnCache {
#region properties. Static params for Get-SQL, query, column to use, values of that col, when to refresh
static [hashtable]$QueryParams
hidden [string]$SQLQuery
hidden [string]$SQLColumnName
hidden [timeSpan]$MaxAge
[datetime]$_LastRefresh
hidden [String[]]$Values
#endregion
#region constructors Sql query & first column, 60 min timeout, specify col, specify col and timeout
QueryColumnCache ([String]$Sql) {
#Assume first column is the one we want.
$this.SQLQuery = $Sql
$this.MaxAge = 60
$params = [QueryColumnCache]::QueryParams
if ($params.Count -eq 0) {throw 'No Query Parameters have been set'}
else {
$rows = Get-SQL @params -SQL $this.SQLQuery
$this.SQLColumnName = $rows[0] | Get-Member -MemberType Property |
Select-Object -First 1 -ExpandProperty name
$this.Values = $rows | ForEach-Object $this.SQLColumnName
$this.LastRefresh = Get-Date
}
}
QueryColumnCache ([String]$Sql,[String]$Column) {
$this.SQLQuery = $Sql
$this.SQLColumnName = $Column
$this.MaxAge = 60
}
QueryColumnCache ([String]$Sql,[String]$Column, [Int]$LifeInMinutes ) {
$this.SQLQuery = $Sql
$this.SQLColumnName = $Column
$this.MaxAge = [timespan]::new(0,$LifeInMinutes,0)
}
QueryColumnCache ([String]$Sql,[String]$Column,[timespan]$MaxAge ) {
$this.SQLQuery = $Sql
$this.SQLColumnName = $Column
$this.MaxAge = $MaxAge
}
#endregion
#region methods. Replace toString to give sql query. Is cache fresh? Refresh it, is X known, get content
[string] ToString() {return $this.SQLQuery}
[bool] IsStale() {return ((Get-Date) - $this.LastRefresh -gt $this.MaxAge)}
[void] Refresh() {
$params = [QueryColumnCache]::QueryParams
if ($params.Count -eq 0) {Write-Warning 'No Query Parameters have been set'}
else {
$this.Values = Get-SQL @params -SQL $this.SQLQuery | ForEach-Object $this.SQLColumnName
$this.LastRefresh = Get-Date
}
}
[bool] Contains( [string]$Value){
if ( ($this.Values -like $value) -and -not $this.isStale ) {
return $true
}
else {
$this.Refresh()
return ( ($this.Values -like $value ) -as [bool])
}
}
[string[]] Items( [String]$Like) {return ($this.items() | Where-Object {$_ -like $Like}) }
[string[]] Items() {
if ( $this.IsStale() ){$this.Refresh() }
return ($this.values)
}
#endregion
}
class QueryRowCache {
#region properties. Static params for Get-SQL, query, column to use, values of that col, when to refresh
static [hashtable]$QueryParams
hidden [string]$SQLQuery
hidden [string]$SQLColumnName
[timeSpan]$MaxAge #Can be chnaged later
hidden [datetime]$_LastRefresh
hidden [hashtable]$Values = @{}
hidden [bool]$KeyOnly = $false
hidden [bool]$WarnedOfNoParams
#endregion
#region constructors Sql query & Column to index on, cache the whole row or just "$true" for key present and timeout
QueryRowCache ([String]$Sql, [String]$KeyColumn) {
$this.init($sql, $KeyColumn, $false, [timespan]::new(0,60,0) )
}
QueryRowCache ([String]$Sql, [String]$KeyColumn, [bool]$KeyOnly) {
$this.init($sql, $KeyColumn, $keyonly, [timespan]::new(0,60,0) )
}
QueryRowCache ([String]$Sql, [String]$KeyColumn, [timespan]$MaxAge ) {
$this.init($sql, $KeyColumn, $false, $maxAge )
}
QueryRowCache ([String]$Sql, [String]$KeyColumn, [bool]$KeyOnly, [timespan]$MaxAge ) {
$this.init($sql, $KeyColumn, $keyonly, $MaxAge )
}
hidden [void]init([String]$Sql, [String]$KeyColumn, [bool]$KeyOnly, [timespan]$MaxAge) {
$this.SQLQuery = $Sql
$this.SQLColumnName = $KeyColumn
$this.MaxAge = $MaxAge
$this.Keyonly = $keyonly
Add-Member -InputObject $this -MemberType ScriptProperty -Name LastRefresh -Value {$this._LastRefresh}
Add-Member -InputObject $this -MemberType ScriptProperty -Name Count -Value {$this.Values.Count}
}
#endregion
#region methods. Replace toString to give sql query. Is cache fresh? Refresh it, is X known, get content
[string] ToString() {return $this.SQLQuery}
[bool] IsStale() {return ((Get-Date) - $this.LastRefresh -gt $this.MaxAge)}
[void] Refresh() {
$params = [QueryRowCache]::QueryParams
$rows = 0
$this.values.Clear()
if ($params.Count -eq 0 -and -not $this.WarnedOfNoParams) {
Write-Warning 'No Query Parameters have been set'
$this.WarnedOfNoParams = $true
}
elseif ($this.keyOnly) {
$this.Values = Get-SQL -quiet @params -SQL $this.SQLQuery | ForEach-Object {
$rows ++
if ($i = $_."$($this.SQLColumnName)" -and $i -isnot [dbnull]) {$this.values[$i]= $True}
}
$this.LastRefresh = Get-Date
}
else {
$this.Values = Get-SQL -quiet @params -SQL $this.SQLQuery | ForEach-Object {
$rows ++
if ($i = $_."$($this.SQLColumnName)" -and $i -isnot [dbnull]) {$this.values[$i]= $_ }
}
$this.LastRefresh = Get-Date
}
if ($rows -gt $this.Values.count) {
Write-Warning "$($rows - $this.Values.count) rows were skipped"
}
}
[bool] Contains($Value){
if ( $this.isStale ) { $this.Refresh() }
return $this.Values.ContainsKey($Value)
}
[DataRow] Item($value) {
if ( $this.IsStale() ){$this.Refresh() }
return ($this.values[$value])
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment