3
0

Fix dup records on multi-value field

This commit is contained in:
Denis Arh
2021-05-23 21:20:40 +02:00
parent c9009df73b
commit 7bde43856e
3 changed files with 66 additions and 20 deletions
+1
View File
@@ -11,6 +11,7 @@ package rdbms
import (
"context"
"database/sql"
"github.com/Masterminds/squirrel"
"github.com/cortezaproject/corteza-server/compose/types"
"github.com/cortezaproject/corteza-server/pkg/errors"
+35 -19
View File
@@ -482,30 +482,46 @@ func (s Store) convertComposeRecordFilter(m *types.Module, f types.RecordFilter)
return false
}
identResolver = func(i ql.Ident) (ql.Ident, error) {
var is bool
if i.Value, _, is = isRealRecordCol(i.Value); is {
i.Value += " "
return i, nil
}
identResolver = func(sortBy bool) func(i ql.Ident) (ql.Ident, error) {
return func(i ql.Ident) (ql.Ident, error) {
var is bool
if i.Value, _, is = isRealRecordCol(i.Value); is {
i.Value += " "
return i, nil
}
if !m.Fields.HasName(i.Value) {
return i, fmt.Errorf("unknown field %q", i.Value)
}
if !m.Fields.HasName(i.Value) {
return i, fmt.Errorf("unknown field %q", i.Value)
}
if !alreadyJoined(i.Value) {
join := composeRecordValueJoinTpl
join = strings.ReplaceAll(join, "{alias}", composeRecordValueAliasPfx+i.Value)
join = strings.ReplaceAll(join, "{field}", i.Value)
query = query.LeftJoin(join)
}
if !alreadyJoined(i.Value) {
join := composeRecordValueJoinTpl
join = strings.ReplaceAll(join, "{alias}", composeRecordValueAliasPfx+i.Value)
join = strings.ReplaceAll(join, "{field}", i.Value)
query = query.LeftJoin(join)
return s.FieldToColumnTypeCaster(m.Fields.FindByName(i.Value), i)
if sortBy {
var sortCol string
sortCol, _, _, err = s.config.CastModuleFieldToColumnType(m.Fields.FindByName(i.Value), i.Value)
if err != nil {
return i, err
}
query = query.Column(squirrel.Alias(squirrel.Expr(sortCol), composeRecordValueAliasPfx+i.Value))
}
}
return s.FieldToColumnTypeCaster(m.Fields.FindByName(i.Value), i)
}
}
)
// Create query for fetching and counting records.
query = s.composeRecordsSelectBuilder().
Prefix("SELECT "+strings.Join(s.composeRecordColumns("sub"), ", ")+" FROM (").
Suffix(") AS sub").
Distinct().
Where("crd.module_id = ?", m.ID).
Where("crd.rel_namespace = ?", m.NamespaceID)
@@ -528,7 +544,7 @@ func (s Store) convertComposeRecordFilter(m *types.Module, f types.RecordFilter)
// Resolve all identifiers found in the query
// into their table/column counterparts
fp.OnIdent = identResolver
fp.OnIdent = identResolver(false)
if fn, err = fp.ParseExpression(f.Query); err != nil {
return
@@ -547,7 +563,7 @@ func (s Store) convertComposeRecordFilter(m *types.Module, f types.RecordFilter)
// Resolve all identifiers found in sort
// into their table/column counterparts
sp.OnIdent = identResolver
sp.OnIdent = identResolver(true)
if _, err = sp.ParseColumns(f.Sort.String()); err != nil {
return
@@ -562,7 +578,7 @@ func (s Store) convertComposeRecordFilter(m *types.Module, f types.RecordFilter)
// Resolve all identifiers found in sort
// into their table/column counterparts
sp.OnIdent = identResolver
sp.OnIdent = identResolver(true)
if _, err = sp.ParseColumns(strings.Join(f.PageCursor.Keys(), ", ")); err != nil {
return
+30 -1
View File
@@ -360,6 +360,35 @@ func testComposeRecords(t *testing.T, s store.ComposeRecords) {
)
req.NoError(err)
})
t.Run("with multi-value field", func(t *testing.T) {
var (
err error
set types.RecordSet
req, _ = truncAndCreate(t,
makeNew(&types.RecordValue{Name: "strMulti", Value: "v1"}, &types.RecordValue{Name: "strMulti", Value: "v2", Place: 1}, &types.RecordValue{Name: "strMulti", Value: "v3", Place: 2}),
makeNew(&types.RecordValue{Name: "strMulti", Value: "v1"}, &types.RecordValue{Name: "strMulti", Value: "v2", Place: 1}),
makeNew(&types.RecordValue{Name: "strMulti", Value: "v1"}),
makeNew(&types.RecordValue{Name: "strMulti", Value: "same"}, &types.RecordValue{Name: "strMulti", Value: "same", Place: 1}, &types.RecordValue{Name: "strMulti", Value: "same", Place: 2}),
)
f = types.RecordFilter{
ModuleID: mod.ID,
NamespaceID: mod.NamespaceID,
}
)
f.Query = `strMulti = 'v1'`
set, _, err = s.SearchComposeRecords(ctx, mod, f)
req.NoError(err)
req.Len(set, 3)
f.Query = `strMulti = 'same'`
set, _, err = s.SearchComposeRecords(ctx, mod, f)
req.NoError(err)
req.Len(set, 1)
})
})
t.Run("paging and sorting", func(t *testing.T) {
@@ -1167,7 +1196,7 @@ func testComposeRecords(t *testing.T, s store.ComposeRecords) {
if fields[f] == "updatedAt" {
v := set[r].UpdatedAt
if v != nil && !v.IsZero() {
out += v.Format(time.RFC3339)
out += v.UTC().Format(time.RFC3339)
} else {
out += "<NIL>"
}