Skip to content

Commit d04bae9

Browse files
committed
fix(sqlite): select latest search result semantically
1 parent b588a06 commit d04bae9

2 files changed

Lines changed: 106 additions & 5 deletions

File tree

lib/database.ps1

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,52 @@
11
# Description: Functions for interacting with the Scoop database cache
22

3+
if (-not (Get-Command Compare-Version -ErrorAction Ignore)) {
4+
. "$PSScriptRoot\versions.ps1"
5+
}
6+
7+
function Get-LatestScoopDBRow {
8+
param(
9+
[Parameter(Mandatory)]
10+
[object[]]
11+
$Rows
12+
)
13+
14+
$latest = $Rows[0]
15+
foreach ($row in ($Rows | Select-Object -Skip 1)) {
16+
if ((Compare-Version -ReferenceVersion $latest.version -DifferenceVersion $row.version) -gt 0) {
17+
$latest = $row
18+
}
19+
}
20+
21+
return $latest
22+
}
23+
24+
function Select-LatestScoopDBRows {
25+
param(
26+
[Parameter(Mandatory)]
27+
[System.Data.DataTable]
28+
$Table,
29+
[string[]]
30+
$GroupBy
31+
)
32+
33+
$latestRows = $Table.Clone()
34+
$rows = @($Table.Rows)
35+
if ($rows.Count -eq 0) {
36+
return $latestRows
37+
}
38+
39+
if ($GroupBy -and $GroupBy.Count -gt 0) {
40+
foreach ($group in ($rows | Group-Object -Property $GroupBy)) {
41+
$latestRows.ImportRow((Get-LatestScoopDBRow -Rows @($group.Group)))
42+
}
43+
} else {
44+
$latestRows.ImportRow((Get-LatestScoopDBRow -Rows $rows))
45+
}
46+
47+
return $latestRows
48+
}
49+
350
<#
451
.SYNOPSIS
552
Get SQLite .NET driver
@@ -253,7 +300,6 @@ function Select-ScoopDBItem {
253300
$dbAdapter = New-Object -TypeName System.Data.SQLite.SQLiteDataAdapter
254301
$result = New-Object System.Data.DataTable
255302
$dbQuery = "SELECT * FROM app WHERE $(($From -join ' LIKE @Pattern OR ') + ' LIKE @Pattern')"
256-
$dbQuery = "SELECT * FROM ($($dbQuery + ' ORDER BY version DESC')) GROUP BY name, bucket"
257303
$dbCommand = $db.CreateCommand()
258304
$dbCommand.CommandText = $dbQuery
259305
$dbCommand.CommandType = [System.Data.CommandType]::Text
@@ -266,7 +312,7 @@ function Select-ScoopDBItem {
266312
end {
267313
$dbAdapter.Dispose()
268314
$db.Dispose()
269-
return $result
315+
return Select-LatestScoopDBRows -Table $result -GroupBy @('name', 'bucket')
270316
}
271317
}
272318

@@ -311,8 +357,6 @@ function Get-ScoopDBItem {
311357
$dbQuery = 'SELECT * FROM app WHERE name = @Name AND bucket = @Bucket'
312358
if ($Version) {
313359
$dbQuery += ' AND version = @Version'
314-
} else {
315-
$dbQuery += ' ORDER BY version DESC LIMIT 1'
316360
}
317361
$dbCommand = $db.CreateCommand()
318362
$dbCommand.CommandText = $dbQuery
@@ -328,7 +372,11 @@ function Get-ScoopDBItem {
328372
end {
329373
$dbAdapter.Dispose()
330374
$db.Dispose()
331-
return $result
375+
if ($Version) {
376+
return $result
377+
}
378+
379+
return Select-LatestScoopDBRows -Table $result
332380
}
333381
}
334382

test/Scoop-Database.Tests.ps1

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
Describe 'database version selection' -Tag 'Scoop' {
2+
BeforeAll {
3+
. "$PSScriptRoot\Scoop-TestLib.ps1"
4+
. "$PSScriptRoot\..\lib\core.ps1"
5+
. "$PSScriptRoot\..\lib\versions.ps1"
6+
. "$PSScriptRoot\..\lib\database.ps1"
7+
}
8+
9+
It 'chooses the semantically latest row within one result set' {
10+
$rows = @(
11+
[pscustomobject]@{ version = '1.0.7' }
12+
[pscustomobject]@{ version = '1.0.31' }
13+
)
14+
15+
(Get-LatestScoopDBRow -Rows $rows).version | Should -Be '1.0.31'
16+
}
17+
18+
It 'returns the latest semantic version per name and bucket' {
19+
$result = New-Object System.Data.DataTable
20+
[void]$result.Columns.Add('name', [string])
21+
[void]$result.Columns.Add('version', [string])
22+
[void]$result.Columns.Add('bucket', [string])
23+
[void]$result.Columns.Add('binary', [string])
24+
[void]$result.Rows.Add('copilot-cli', '1.0.7', 'main', 'copilot')
25+
[void]$result.Rows.Add('copilot-cli', '1.0.31', 'main', 'copilot')
26+
[void]$result.Rows.Add('zotero', '7.0.9', 'extras', 'zotero')
27+
[void]$result.Rows.Add('zotero', '7.0.20', 'extras', 'zotero')
28+
[void]$result.Rows.Add('zotero', '7.0.9', 'he0119', 'zotero')
29+
[void]$result.Rows.Add('zotero', '7.0.20', 'he0119', 'zotero')
30+
31+
$latest = @(Select-LatestScoopDBRows -Table $result -GroupBy @('name', 'bucket'))
32+
33+
$latest.Count | Should -Be 3
34+
(@($latest | Where-Object { $_.name -eq 'copilot-cli' -and $_.bucket -eq 'main' })[0]).version | Should -Be '1.0.31'
35+
(@($latest | Where-Object { $_.name -eq 'zotero' -and $_.bucket -eq 'extras' })[0]).version | Should -Be '7.0.20'
36+
(@($latest | Where-Object { $_.name -eq 'zotero' -and $_.bucket -eq 'he0119' })[0]).version | Should -Be '7.0.20'
37+
}
38+
39+
It 'returns the latest semantic version when no grouping is requested' {
40+
$result = New-Object System.Data.DataTable
41+
[void]$result.Columns.Add('name', [string])
42+
[void]$result.Columns.Add('version', [string])
43+
[void]$result.Columns.Add('bucket', [string])
44+
[void]$result.Columns.Add('binary', [string])
45+
[void]$result.Rows.Add('zotero', '7.0.9', 'extras', 'zotero')
46+
[void]$result.Rows.Add('zotero', '7.0.20', 'extras', 'zotero')
47+
48+
$latest = @(Select-LatestScoopDBRows -Table $result)
49+
50+
$latest.Count | Should -Be 1
51+
$latest[0].version | Should -Be '7.0.20'
52+
}
53+
}

0 commit comments

Comments
 (0)