Skip to content

Commit

Permalink
Merge pull request #974 from go-kivik/builtinViewsCollation
Browse files Browse the repository at this point in the history
Support proper collation for default views
  • Loading branch information
flimzy committed May 19, 2024
2 parents 19c55f8 + cde48ba commit ac5cb42
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 63 deletions.
2 changes: 1 addition & 1 deletion x/sqlite/designdocs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func TestDBDesignDocs(t *testing.T) {
want: []rowResult{
{
ID: "_design/bar",
Key: "_design/bar",
Key: `"_design/bar"`,
Value: `{"value":{"rev":"` + rev2 + `"}}`,
},
},
Expand Down
2 changes: 1 addition & 1 deletion x/sqlite/localdocs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestDBLocalDocs(t *testing.T) {
want: []rowResult{
{
ID: "_local/bar",
Key: "_local/bar",
Key: `"_local/bar"`,
Value: `{"value":{"rev":"` + rev2 + `"}}`,
},
},
Expand Down
10 changes: 5 additions & 5 deletions x/sqlite/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,18 +384,18 @@ func (v viewOptions) buildWhere(args *[]any) []string {
where := make([]string, 0, 3)
switch v.view {
case viewAllDocs:
where = append(where, "key NOT LIKE '_local/%'")
where = append(where, `view.key NOT LIKE '"_local/%'`)
case viewLocalDocs:
where = append(where, "key LIKE '_local/%'")
where = append(where, `view.key LIKE '"_local/%'`)
case viewDesignDocs:
where = append(where, "key LIKE '_design/%'")
where = append(where, `view.key LIKE '"_design/%'`)
}
if v.endkey != "" {
where = append(where, fmt.Sprintf("key %s $%d", endKeyOp(v.descending, v.inclusiveEnd), len(*args)+1))
where = append(where, fmt.Sprintf("view.key %s $%d", endKeyOp(v.descending, v.inclusiveEnd), len(*args)+1))
*args = append(*args, v.endkey)
}
if v.startkey != "" {
where = append(where, fmt.Sprintf("key %s $%d", startKeyOp(v.descending), len(*args)+1))
where = append(where, fmt.Sprintf("view.key %s $%d", startKeyOp(v.descending), len(*args)+1))
*args = append(*args, v.startkey)
}
return where
Expand Down
17 changes: 9 additions & 8 deletions x/sqlite/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const (
rev.id,
rev.rev,
rev.rev_id,
rev.key,
doc.doc,
doc.deleted
FROM {{ .Revs }} AS rev
Expand Down Expand Up @@ -173,20 +174,20 @@ func (d *db) performQuery(
SELECT *
FROM (
SELECT
map.id,
map.key,
map.value,
view.id,
view.key,
view.value,
IIF($1, docs.rev || '-' || docs.rev_id, "") AS rev,
IIF($1, docs.doc, NULL) AS doc,
IIF($2, GROUP_CONCAT(conflicts.rev || '-' || conflicts.rev_id, ','), NULL) AS conflicts
FROM {{ .Map }} AS map
FROM {{ .Map }} AS view
JOIN reduce
JOIN {{ .Docs }} AS docs ON map.id = docs.id AND map.rev = docs.rev AND map.rev_id = docs.rev_id
LEFT JOIN leaves AS conflicts ON conflicts.id = map.id AND NOT (map.rev = conflicts.rev AND map.rev_id = conflicts.rev_id)
JOIN {{ .Docs }} AS docs ON view.id = docs.id AND view.rev = docs.rev AND view.rev_id = docs.rev_id
LEFT JOIN leaves AS conflicts ON conflicts.id = view.id AND NOT (view.rev = conflicts.rev AND view.rev_id = conflicts.rev_id)
WHERE $3 == FALSE OR NOT reduce.reducible
%[2]s
GROUP BY map.id, map.key, map.value, map.rev, map.rev_id
ORDER BY key %[1]s
GROUP BY view.id, view.key, view.value, view.rev, view.rev_id
ORDER BY view.key %[1]s
LIMIT %[3]d OFFSET %[4]d
)
`), descendingToDirection(vopts.descending), strings.Join(where, " AND "), vopts.limit, vopts.skip)
Expand Down
2 changes: 2 additions & 0 deletions x/sqlite/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ var schema = []string{
id TEXT NOT NULL,
rev INTEGER NOT NULL,
rev_id TEXT NOT NULL,
key TEXT GENERATED ALWAYS AS (json_quote(id)) VIRTUAL COLLATE COUCHDB_UCI,
parent_rev INTEGER,
parent_rev_id TEXT,
FOREIGN KEY (id, parent_rev, parent_rev_id) REFERENCES {{ .Revs }} (id, rev, rev_id) ON DELETE CASCADE,
UNIQUE(id, rev, rev_id)
)`,
`CREATE INDEX default_key ON {{ .Revs }} (key)`,
`CREATE INDEX idx_parent ON {{ .Revs }} (id, parent_rev, parent_rev_id)`,
// the main db table
`CREATE TABLE {{ .Docs }} (
Expand Down
19 changes: 10 additions & 9 deletions x/sqlite/views.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,26 +82,27 @@ func (d *db) queryBuiltinView(
SELECT *
FROM (
SELECT
rev.id AS id,
rev.id AS key,
'{"value":{"rev":"' || rev.rev || '-' || rev.rev_id || '"}}' AS value,
rev.rev || '-' || rev.rev_id AS rev,
rev.doc AS doc,
view.id AS id,
view.key AS key,
'{"value":{"rev":"' || view.rev || '-' || view.rev_id || '"}}' AS value,
view.rev || '-' || view.rev_id AS rev,
view.doc AS doc,
IIF($2, GROUP_CONCAT(conflicts.rev || '-' || conflicts.rev_id, ','), NULL) AS conflicts
FROM (
SELECT
id AS id,
rev AS rev,
rev_id AS rev_id,
key AS key,
IIF($1, doc, NULL) AS doc,
deleted AS deleted, -- TODO:remove this?
ROW_NUMBER() OVER (PARTITION BY id ORDER BY rev DESC, rev_id DESC) AS rank
FROM leaves
) AS rev
LEFT JOIN leaves AS conflicts ON conflicts.id = rev.id AND NOT (rev.rev = conflicts.rev AND rev.rev_id = conflicts.rev_id)
WHERE rev.rank = 1
) AS view
LEFT JOIN leaves AS conflicts ON conflicts.id = view.id AND NOT (view.rev = conflicts.rev AND view.rev_id = conflicts.rev_id)
WHERE view.rank = 1
%[2]s
GROUP BY rev.id, rev.rev, rev.rev_id
GROUP BY view.id, view.rev, view.rev_id
ORDER BY key %[1]s
LIMIT %[3]d OFFSET %[4]d
)
Expand Down
Loading

0 comments on commit ac5cb42

Please sign in to comment.