1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-12 02:30:53 +09:00

GO-3273 Merge branch 'main' of github.com:anyproto/anytype-heart into go-3273-fix-history-protocol-and-implementation

This commit is contained in:
AnastasiaShemyakinskaya 2024-08-19 12:32:23 +02:00
commit 02d9f662b5
No known key found for this signature in database
GPG key ID: CCD60ED83B103281
16 changed files with 1650 additions and 653 deletions

View file

@ -436,6 +436,9 @@ func validate(snapshot *pb.SnapshotWithType, info *useCaseInfo) (err error) {
}
func insertAnalyticsData(s *pb.ChangeSnapshot, info *useCaseInfo) {
if s == nil || s.Data == nil || len(s.Data.Blocks) == 0 {
return
}
root := s.Data.Blocks[0]
id := pbtypes.GetString(s.Data.Details, bundle.RelationKeyId.String())
f := root.GetFields().GetFields()

View file

@ -101,7 +101,7 @@ func (s *Service) updateCollection(ctx session.Context, contextID string, modifi
s.UpdateStoreSlice(template.CollectionStoreKey, lst)
internalflag.Set{}.AddToState(s)
return nil
})
}, smartblock.KeepInternalFlags)
}
func (s *Service) collectionAddHookOnce(sb smartblock.SmartBlock) {

View file

@ -23,6 +23,7 @@ import (
"github.com/anyproto/anytype-heart/pkg/lib/localstore/objectstore"
"github.com/anyproto/anytype-heart/pkg/lib/logging"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/internalflag"
"github.com/anyproto/anytype-heart/util/pbtypes"
"github.com/anyproto/anytype-heart/util/slice"
)
@ -84,10 +85,15 @@ func (d *sdataview) SetSource(ctx session.Context, blockId string, source []stri
return
}
flags := internalflag.NewFromState(s)
// set with source is no longer empty
flags.Remove(model.InternalFlag_editorDeleteEmpty)
flags.AddToState(s)
if len(source) == 0 {
s.Unlink(blockId)
s.SetLocalDetail(bundle.RelationKeySetOf.String(), pbtypes.StringList(source))
return d.Apply(s, smartblock.NoRestrictions)
return d.Apply(s, smartblock.NoRestrictions, smartblock.KeepInternalFlags)
}
dvContent, err := BlockBySource(d.objectStore, source)
@ -105,7 +111,7 @@ func (d *sdataview) SetSource(ctx session.Context, blockId string, source []stri
}
s.SetLocalDetail(bundle.RelationKeySetOf.String(), pbtypes.StringList(source))
return d.Apply(s, smartblock.NoRestrictions)
return d.Apply(s, smartblock.NoRestrictions, smartblock.KeepInternalFlags)
}
func (d *sdataview) AddRelations(ctx session.Context, blockId string, relationKeys []string, showEvent bool) error {

View file

@ -238,7 +238,7 @@ func (mw *Middleware) enrichWithDateSuggestion(ctx context.Context, records []da
if err != nil {
return nil, fmt.Errorf("make date record: %w", err)
}
f, _ := database.MakeFiltersAnd(req.Filters, store) //nolint:errcheck
f, _ := database.MakeFilters(req.Filters, store) //nolint:errcheck
if f.FilterObject(rec.Details) {
return append([]database.Record{rec}, records...), nil
}

View file

@ -12,8 +12,8 @@ import (
mb2 "github.com/cheggaaa/mb/v3"
"github.com/globalsign/mgo/bson"
"github.com/gogo/protobuf/types"
"golang.org/x/exp/slices"
"github.com/valyala/fastjson"
"golang.org/x/exp/slices"
"github.com/anyproto/anytype-heart/core/domain"
@ -648,14 +648,11 @@ func (s *service) filtersFromSource(sources []string) (database.Filter, error) {
}
if len(typeUniqueKeys) > 0 {
nestedFiler, err := database.MakeFilter("",
&model.BlockContentDataviewFilter{
RelationKey: database.NestedRelationKey(bundle.RelationKeyType, bundle.RelationKeyUniqueKey),
Condition: model.BlockContentDataviewFilter_In,
Value: pbtypes.StringList(typeUniqueKeys),
},
s.objectStore,
)
nestedFiler, err := database.MakeFilter("", &model.BlockContentDataviewFilter{
RelationKey: database.NestedRelationKey(bundle.RelationKeyType, bundle.RelationKeyUniqueKey),
Condition: model.BlockContentDataviewFilter_In,
Value: pbtypes.StringList(typeUniqueKeys),
}, s.objectStore)
if err != nil {
return nil, fmt.Errorf("make nested filter: %w", err)
}

View file

@ -97,6 +97,209 @@ func TestService_Search(t *testing.T) {
assert.NoError(t, fx.Unsubscribe("test"))
assert.Len(t, fx.Service.(*service).cache.entries, 0)
})
t.Run("search with filters: one filter None", func(t *testing.T) {
fx := newFixtureWithRealObjectStore(t)
defer fx.a.Close(context.Background())
defer fx.ctrl.Finish()
source := "source"
spaceID := "spaceId"
relationKey := "key"
option1 := "option1"
option2 := "option2"
err := addTestObjects(t, source, relationKey, option1, option2, spaceID, fx)
require.NoError(t, err)
resp, err := fx.Search(SubscribeRequest{
Keys: []string{bundle.RelationKeyId.String()},
Filters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: relationKey,
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String(option1),
Format: model.RelationFormat_status,
},
},
NoDepSubscription: true,
})
require.NoError(t, err)
assert.Len(t, resp.Records, 1)
assert.Equal(t, "1", resp.Records[0].Fields[bundle.RelationKeyId.String()].GetStringValue())
})
t.Run("search with filters: linear structure with none filters", func(t *testing.T) {
fx := newFixtureWithRealObjectStore(t)
defer fx.a.Close(context.Background())
defer fx.ctrl.Finish()
source := "source"
spaceID := "spaceId"
relationKey := "key"
option1 := "option1"
option2 := "option2"
err := addTestObjects(t, source, relationKey, option1, option2, spaceID, fx)
require.NoError(t, err)
resp, err := fx.Search(SubscribeRequest{
Keys: []string{bundle.RelationKeyId.String()},
Filters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: relationKey,
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String(option1),
Format: model.RelationFormat_status,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: relationKey,
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String(option2),
Format: model.RelationFormat_status,
},
},
NoDepSubscription: true,
})
require.NoError(t, err)
assert.Len(t, resp.Records, 0)
})
t.Run("search with filters: tree structure with And filter in root and None filters in NesterFilters", func(t *testing.T) {
fx := newFixtureWithRealObjectStore(t)
defer fx.a.Close(context.Background())
defer fx.ctrl.Finish()
source := "source"
spaceID := "spaceId"
relationKey := "key"
option1 := "option1"
option2 := "option2"
err := addTestObjects(t, source, relationKey, option1, option2, spaceID, fx)
require.NoError(t, err)
resp, err := fx.Search(SubscribeRequest{
Keys: []string{bundle.RelationKeyId.String()},
Filters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_And,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: relationKey,
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String(option2),
Format: model.RelationFormat_status,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("Object 1"),
Format: model.RelationFormat_shorttext,
},
},
},
},
NoDepSubscription: true,
})
require.NoError(t, err)
assert.Len(t, resp.Records, 0)
})
t.Run("search with filters: tree structure with Or filter in root and None filters in NesterFilters", func(t *testing.T) {
fx := newFixtureWithRealObjectStore(t)
defer fx.a.Close(context.Background())
defer fx.ctrl.Finish()
source := "source"
spaceID := "spaceId"
relationKey := "key"
option1 := "option1"
option2 := "option2"
err := addTestObjects(t, source, relationKey, option1, option2, spaceID, fx)
require.NoError(t, err)
resp, err := fx.Search(SubscribeRequest{
Keys: []string{bundle.RelationKeyId.String()},
Filters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_Or,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: relationKey,
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String(option2),
Format: model.RelationFormat_status,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("Object 1"),
Format: model.RelationFormat_shorttext,
},
},
},
},
NoDepSubscription: true,
})
require.NoError(t, err)
assert.Len(t, resp.Records, 2)
assert.Equal(t, "1", resp.Records[0].Fields[bundle.RelationKeyId.String()].GetStringValue())
assert.Equal(t, "2", resp.Records[1].Fields[bundle.RelationKeyId.String()].GetStringValue())
})
t.Run("search with filters: tree structure with And filter in root and combined filters as NestedFilter", func(t *testing.T) {
fx := newFixtureWithRealObjectStore(t)
defer fx.a.Close(context.Background())
defer fx.ctrl.Finish()
spaceID := "spaceId"
option1 := "option1"
option2 := "option2"
option3 := "option3"
tag1 := "work"
tag2 := "university"
addTestObjectsForNestedFilters(t, fx, spaceID, option1, option2, option3, tag1, tag2)
resp, err := fx.Search(SubscribeRequest{
Keys: []string{bundle.RelationKeyId.String()},
Filters: prepareNestedFiltersWithOperator(model.BlockContentDataviewFilter_And, option1, option2, tag1),
NoDepSubscription: true,
})
require.NoError(t, err)
assert.Len(t, resp.Records, 1)
assert.Equal(t, "1", resp.Records[0].Fields[bundle.RelationKeyId.String()].GetStringValue())
})
t.Run("search with filters: tree structure with Or filter in root and combined filters as NestedFilter", func(t *testing.T) {
fx := newFixtureWithRealObjectStore(t)
defer fx.a.Close(context.Background())
defer fx.ctrl.Finish()
spaceID := "spaceId"
option1 := "option1"
option2 := "option2"
option3 := "option3"
tag1 := "work"
tag2 := "university"
addTestObjectsForNestedFilters(t, fx, spaceID, option1, option2, option3, tag1, tag2)
resp, err := fx.Search(SubscribeRequest{
Keys: []string{bundle.RelationKeyId.String()},
Filters: prepareNestedFiltersWithOperator(model.BlockContentDataviewFilter_Or, option1, option2, tag1),
NoDepSubscription: true,
})
require.NoError(t, err)
assert.Len(t, resp.Records, 3)
assert.Equal(t, "1", resp.Records[0].Fields[bundle.RelationKeyId.String()].GetStringValue())
assert.Equal(t, "2", resp.Records[1].Fields[bundle.RelationKeyId.String()].GetStringValue())
assert.Equal(t, "3", resp.Records[2].Fields[bundle.RelationKeyId.String()].GetStringValue())
})
t.Run("cache ref counter", func(t *testing.T) {
fx := newFixture(t)
defer fx.a.Close(context.Background())
@ -958,6 +1161,148 @@ func TestService_Search(t *testing.T) {
})
}
func addTestObjects(t *testing.T, source, relationKey, option1, option2, spaceID string, fx *fixtureRealStore) error {
objectTypeKey, err := domain.NewUniqueKey(smartblock.SmartBlockTypeObjectType, source)
assert.Nil(t, err)
fx.store.AddObjects(t, []objectstore.TestObject{
{
bundle.RelationKeyId: pbtypes.String("1"),
bundle.RelationKeySpaceId: pbtypes.String(spaceID),
domain.RelationKey(relationKey): pbtypes.String(option1),
bundle.RelationKeyLayout: pbtypes.Int64(int64(model.ObjectType_basic)),
bundle.RelationKeyName: pbtypes.String("Object 1"),
bundle.RelationKeyType: pbtypes.String(objectTypeKey.Marshal()),
},
{
bundle.RelationKeyId: pbtypes.String("2"),
bundle.RelationKeySpaceId: pbtypes.String(spaceID),
domain.RelationKey(relationKey): pbtypes.String(option2),
bundle.RelationKeyLayout: pbtypes.Int64(int64(model.ObjectType_basic)),
bundle.RelationKeyName: pbtypes.String("Object 2"),
bundle.RelationKeyType: pbtypes.String(objectTypeKey.Marshal()),
},
})
return err
}
func addTestObjectsForNestedFilters(t *testing.T, fx *fixtureRealStore, spaceID, option1, option2, option3, tag1, tag2 string) {
fx.store.AddObjects(t, []objectstore.TestObject{
{
bundle.RelationKeyId: pbtypes.String("1"),
bundle.RelationKeySpaceId: pbtypes.String(spaceID),
bundle.RelationKeyStatus: pbtypes.String(option1),
bundle.RelationKeyLayout: pbtypes.Int64(int64(model.ObjectType_basic)),
bundle.RelationKeyName: pbtypes.String("Object 1"),
bundle.RelationKeyType: pbtypes.String(bundle.TypeKeyPage.String()),
bundle.RelationKeyTag: pbtypes.StringList([]string{tag1}),
bundle.RelationKeyDueDate: pbtypes.Int64(1704070917),
},
{
bundle.RelationKeyId: pbtypes.String("2"),
bundle.RelationKeySpaceId: pbtypes.String(spaceID),
bundle.RelationKeyStatus: pbtypes.String(option3),
bundle.RelationKeyLayout: pbtypes.Int64(int64(model.ObjectType_basic)),
bundle.RelationKeyName: pbtypes.String("Object 2"),
bundle.RelationKeyType: pbtypes.String(bundle.TypeKeyPage.String()),
bundle.RelationKeyTag: pbtypes.StringList([]string{tag2}),
bundle.RelationKeyDueDate: pbtypes.Int64(1709254917),
},
{
bundle.RelationKeyId: pbtypes.String("3"),
bundle.RelationKeySpaceId: pbtypes.String(spaceID),
bundle.RelationKeyStatus: pbtypes.String(option2),
bundle.RelationKeyLayout: pbtypes.Int64(int64(model.ObjectType_basic)),
bundle.RelationKeyName: pbtypes.String("Object 3"),
bundle.RelationKeyType: pbtypes.String(bundle.TypeKeyPage.String()),
bundle.RelationKeyTag: pbtypes.StringList([]string{tag1, tag2}),
bundle.RelationKeyDueDate: pbtypes.Int64(1711933317),
},
{
bundle.RelationKeyId: pbtypes.String("4"),
bundle.RelationKeySpaceId: pbtypes.String(spaceID),
bundle.RelationKeyStatus: pbtypes.String(option1),
bundle.RelationKeyLayout: pbtypes.Int64(int64(model.ObjectType_basic)),
bundle.RelationKeyName: pbtypes.String("Object 4"),
bundle.RelationKeyType: pbtypes.String(bundle.TypeKeyPage.String()),
bundle.RelationKeyDueDate: pbtypes.Int64(1714525317),
},
})
}
func prepareNestedFiltersWithOperator(operator model.BlockContentDataviewFilterOperator, option1 string, option2 string, tag1 string) []*model.BlockContentDataviewFilter {
return []*model.BlockContentDataviewFilter{
{
Operator: operator,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_Or,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("Object 1"),
Format: model.RelationFormat_shorttext,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("Object 2"),
Format: model.RelationFormat_shorttext,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("Object 3"),
Format: model.RelationFormat_shorttext,
},
},
},
{
Operator: model.BlockContentDataviewFilter_And,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyTag.String(),
Condition: model.BlockContentDataviewFilter_In,
Value: pbtypes.StringList([]string{tag1}),
Format: model.RelationFormat_tag,
},
{
Operator: model.BlockContentDataviewFilter_Or,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyStatus.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String(option1),
Format: model.RelationFormat_shorttext,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String(option2),
Format: model.RelationFormat_shorttext,
},
},
},
},
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyDueDate.String(),
Condition: model.BlockContentDataviewFilter_Less,
Value: pbtypes.Int64(1709254917),
Format: model.RelationFormat_shorttext,
},
},
},
}
}
func xTestNestedSubscription(t *testing.T) {
t.Run("update nested object, so it's not satisfying filter anymore", func(t *testing.T) {
fx := testCreateSubscriptionWithNestedFilter(t)

View file

@ -26340,6 +26340,7 @@ Bookmark is to keep a web-link and to preview a content.
| quickOption | [Block.Content.Dataview.Filter.QuickOption](#anytype-model-Block-Content-Dataview-Filter-QuickOption) | | |
| format | [RelationFormat](#anytype-model-RelationFormat) | | |
| includeTime | [bool](#bool) | | |
| nestedFilters | [Block.Content.Dataview.Filter](#anytype-model-Block-Content-Dataview-Filter) | repeated | |
@ -27816,8 +27817,9 @@ stored |
| Name | Number | Description |
| ---- | ------ | ----------- |
| And | 0 | |
| No | 0 | |
| Or | 1 | |
| And | 2 | |

25
go.mod
View file

@ -57,7 +57,7 @@ require (
github.com/joho/godotenv v1.5.1
github.com/jsummers/gobmp v0.0.0-20151104160322-e2ba15ffa76e
github.com/kelseyhightower/envconfig v1.4.0
github.com/klauspost/compress v1.17.8
github.com/klauspost/compress v1.17.9
github.com/libp2p/go-libp2p v0.35.1
github.com/libp2p/zeroconf/v2 v2.2.0
github.com/logrusorgru/aurora v2.0.3+incompatible
@ -75,11 +75,11 @@ require (
github.com/otiai10/copy v1.14.0
github.com/otiai10/opengraph/v2 v2.1.0
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.19.1
github.com/prometheus/client_golang v1.20.0
github.com/pseudomuto/protoc-gen-doc v1.5.1
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
github.com/samber/lo v1.46.0
github.com/sasha-s/go-deadlock v0.3.1
github.com/samber/lo v1.47.0
github.com/sasha-s/go-deadlock v0.3.5
github.com/shirou/gopsutil/v3 v3.24.4
github.com/stretchr/testify v1.9.0
github.com/uber/jaeger-client-go v2.30.0+incompatible
@ -92,11 +92,11 @@ require (
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.27.0
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
golang.org/x/image v0.18.0
golang.org/x/image v0.19.0
golang.org/x/mobile v0.0.0-20240520174638-fa72addaaa1b
golang.org/x/net v0.27.0
golang.org/x/oauth2 v0.21.0
golang.org/x/text v0.16.0
golang.org/x/oauth2 v0.22.0
golang.org/x/text v0.17.0
google.golang.org/grpc v1.65.0
gopkg.in/Graylog2/go-gelf.v2 v2.0.0-20180125164251-1832d8546a9f
gopkg.in/yaml.v3 v3.0.1
@ -216,16 +216,17 @@ require (
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mwitkow/go-proto-validators v0.3.2 // indirect
github.com/onsi/ginkgo/v2 v2.17.1 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/pseudomuto/protokit v0.2.1 // indirect
github.com/quic-go/quic-go v0.44.0 // indirect
github.com/rs/cors v1.7.0 // indirect
@ -257,14 +258,14 @@ require (
go.opentelemetry.io/otel/trace v1.14.0 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/mod v0.19.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/term v0.22.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.23.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
google.golang.org/protobuf v1.34.1 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
lukechampine.com/blake3 v1.2.1 // indirect

60
go.sum
View file

@ -83,8 +83,6 @@ github.com/andybalholm/cascadia v1.2.0/go.mod h1:YCyR8vOZT9aZ1CHEd8ap0gMVm2aFgxB
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/anyproto/any-store v0.0.0-20240719163025-8a3657f8e01c h1:rRlF97BLA+4/jV82lMHEQGbNS4qgsed+HuoAJtYaLUM=
github.com/anyproto/any-store v0.0.0-20240719163025-8a3657f8e01c/go.mod h1:JV7dJ8+xF1VaCQgFQsD8SZSNlxxTGFbDiF8llkB2ILc=
github.com/anyproto/any-store v0.0.1 h1:RiZi3cHVSpIebcNeHYOUaDShH7E9Ahto33zdnqCaUHM=
github.com/anyproto/any-store v0.0.1/go.mod h1:JV7dJ8+xF1VaCQgFQsD8SZSNlxxTGFbDiF8llkB2ILc=
github.com/anyproto/any-sync v0.4.22 h1:f9iAbCv/clTzYtzOzkX1IOXahVM/Art1WkUtIgnwl8U=
@ -758,8 +756,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
@ -781,6 +779,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ=
@ -1092,6 +1092,8 @@ github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS
github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@ -1156,8 +1158,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7 h1:Dx7Ovyv/SFnMFw3fD4oEoeorXc6saIiQ23LrGLth0Gw=
github.com/petermattis/goid v0.0.0-20240813172612-4fcff4a6cae7/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pion/datachannel v1.5.6 h1:1IxKJntfSlYkpUj8LlYRSWpYiTTC02nUrOE8T3DqGeg=
@ -1214,8 +1216,8 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI=
github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@ -1231,8 +1233,8 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE=
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
@ -1240,8 +1242,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/pseudomuto/protoc-gen-doc v1.5.1 h1:Ah259kcrio7Ix1Rhb6u8FCaOkzf9qRBqXnvAufg061w=
github.com/pseudomuto/protoc-gen-doc v1.5.1/go.mod h1:XpMKYg6zkcpgfpCfQ8GcWBDRtRxOmMR5w7pz4Xo+dYM=
@ -1270,11 +1272,11 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samber/lo v1.46.0 h1:w8G+oaCPgz1PoCJztqymCFaKwXt+5cCXn51uPxExFfQ=
github.com/samber/lo v1.46.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0=
github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
github.com/sasha-s/go-deadlock v0.3.5 h1:tNCOEEDG6tBqrNDOX35j/7hL5FcFViG6awUGROb2NsU=
github.com/sasha-s/go-deadlock v0.3.5/go.mod h1:bugP6EGbdGYObIlx7pUZtWqlvo8k9H6vCBBsiChJQ5U=
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
@ -1527,16 +1529,14 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/image v0.19.0 h1:D9FX4QWkLfkeqaC62SonffIIuYdOk/UE2XKUBgRIBIQ=
golang.org/x/image v0.19.0/go.mod h1:y0zrRqlQRWQ5PXaYCOMLTW2fpsxZ8Qh9I/ohnInJEys=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -1563,8 +1563,6 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1641,8 +1639,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA=
golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1656,8 +1654,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -1773,8 +1771,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1843,8 +1841,6 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1966,8 +1962,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View file

@ -35,13 +35,57 @@ type Query struct {
}
func injectDefaultFilters(filters []*model.BlockContentDataviewFilter) []*model.BlockContentDataviewFilter {
hasArchivedFilter, hasDeletedFilter, hasTypeFilter := hasDefaultFilters(filters)
if len(filters) > 0 && len(filters[0].NestedFilters) > 0 {
return addDefaultFiltersToNested(filters, hasArchivedFilter, hasDeletedFilter, hasTypeFilter)
}
return addDefaultFilters(filters, hasArchivedFilter, hasDeletedFilter, hasTypeFilter)
}
func addDefaultFiltersToNested(filters []*model.BlockContentDataviewFilter, hasArchivedFilter, hasDeletedFilter, hasTypeFilter bool) []*model.BlockContentDataviewFilter {
if filters[0].Operator == model.BlockContentDataviewFilter_And {
filters[0].NestedFilters = addDefaultFilters(filters[0].NestedFilters, hasArchivedFilter, hasDeletedFilter, hasTypeFilter)
}
// build And filter based on original Or filter and default filters
if filters[0].Operator != model.BlockContentDataviewFilter_And {
filters = addDefaultFilters(filters, hasArchivedFilter, hasDeletedFilter, hasTypeFilter)
return []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_And,
NestedFilters: filters,
},
}
}
return filters
}
func addDefaultFilters(filters []*model.BlockContentDataviewFilter, hasArchivedFilter, hasDeletedFilter, hasTypeFilter bool) []*model.BlockContentDataviewFilter {
if !hasArchivedFilter {
filters = append(filters, &model.BlockContentDataviewFilter{RelationKey: bundle.RelationKeyIsArchived.String(), Condition: model.BlockContentDataviewFilter_NotEqual, Value: pbtypes.Bool(true)})
}
if !hasDeletedFilter {
filters = append(filters, &model.BlockContentDataviewFilter{RelationKey: bundle.RelationKeyIsDeleted.String(), Condition: model.BlockContentDataviewFilter_NotEqual, Value: pbtypes.Bool(true)})
}
if !hasTypeFilter {
// temporarily exclude Space objects from search if we don't have explicit type filter
filters = append(filters, &model.BlockContentDataviewFilter{RelationKey: bundle.RelationKeyType.String(), Condition: model.BlockContentDataviewFilter_NotIn, Value: pbtypes.Float64(float64(model.ObjectType_space))})
}
return filters
}
func hasDefaultFilters(filters []*model.BlockContentDataviewFilter) (bool, bool, bool) {
var (
hasArchivedFilter bool
hasDeletedFilter bool
hasTypeFilter bool
)
if len(filters) == 0 {
return false, false, false
}
for _, filter := range filters {
if len(filter.NestedFilters) > 0 {
return hasDefaultFilters(filters[0].NestedFilters)
}
// include archived objects if we have explicit filter about it
if filter.RelationKey == bundle.RelationKeyIsArchived.String() {
hasArchivedFilter = true
@ -55,18 +99,7 @@ func injectDefaultFilters(filters []*model.BlockContentDataviewFilter) []*model.
hasDeletedFilter = true
}
}
if !hasArchivedFilter {
filters = append(filters, &model.BlockContentDataviewFilter{RelationKey: bundle.RelationKeyIsArchived.String(), Condition: model.BlockContentDataviewFilter_NotEqual, Value: pbtypes.Bool(true)})
}
if !hasDeletedFilter {
filters = append(filters, &model.BlockContentDataviewFilter{RelationKey: bundle.RelationKeyIsDeleted.String(), Condition: model.BlockContentDataviewFilter_NotEqual, Value: pbtypes.Bool(true)})
}
if !hasTypeFilter {
// temporarily exclude Space objects from search if we don't have explicit type filter
filters = append(filters, &model.BlockContentDataviewFilter{RelationKey: bundle.RelationKeyLayout.String(), Condition: model.BlockContentDataviewFilter_NotEqual, Value: pbtypes.Float64(float64(model.ObjectType_space))})
}
return filters
return hasArchivedFilter, hasDeletedFilter, hasTypeFilter
}
func injectDefaultOrder(qry Query, sorts []*model.BlockContentDataviewSort) []*model.BlockContentDataviewSort {
@ -104,7 +137,7 @@ func NewFilters(qry Query, store ObjectStore, arena *fastjson.Arena) (filters *F
objectStore: store,
}
filterObj, err := MakeFiltersAnd(qry.Filters, store)
filterObj, err := MakeFilters(qry.Filters, store)
if err != nil {
return
}

View file

@ -10,6 +10,7 @@ import (
"github.com/anyproto/anytype-heart/core/domain"
"github.com/anyproto/anytype-heart/pkg/lib/bundle"
"github.com/anyproto/anytype-heart/pkg/lib/pb/model"
"github.com/anyproto/anytype-heart/util/pbtypes"
)
func TestDatabase(t *testing.T) {
@ -136,3 +137,207 @@ func givenSingleIncludeTime() []*model.BlockContentDataviewSort {
}
return sorts
}
func Test_NewFilters(t *testing.T) {
t.Run("only default filters", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
// when
filters, err := NewFilters(Query{}, mockStore, &fastjson.Arena{})
// then
assert.Nil(t, err)
assert.Len(t, filters.FilterObj, 3)
})
t.Run("and filter with 3 default", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_And,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: "relationKey",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("option2"),
Format: model.RelationFormat_status,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("Object 1"),
Format: model.RelationFormat_shorttext,
},
},
},
}
// when
filters, err := NewFilters(Query{Filters: filter}, mockStore, &fastjson.Arena{})
// when
assert.Nil(t, err)
assert.NotNil(t, filters.FilterObj)
assert.NotNil(t, filters.FilterObj.(FiltersAnd))
assert.Len(t, filters.FilterObj.(FiltersAnd), 5)
})
t.Run("deleted filter", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_And,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: "relationKey",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("option2"),
Format: model.RelationFormat_status,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("Object 1"),
Format: model.RelationFormat_shorttext,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyIsDeleted.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
},
},
}
// then
filters, err := NewFilters(Query{Filters: filter}, mockStore, &fastjson.Arena{})
// when
assert.Nil(t, err)
assert.NotNil(t, filters.FilterObj)
assert.NotNil(t, filters.FilterObj.(FiltersAnd))
assert.Len(t, filters.FilterObj.(FiltersAnd), 5)
})
t.Run("archived filter", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_And,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: "relationKey",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("option2"),
Format: model.RelationFormat_status,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("Object 1"),
Format: model.RelationFormat_shorttext,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyIsArchived.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
},
},
}
// then
filters, err := NewFilters(Query{Filters: filter}, mockStore, &fastjson.Arena{})
// when
assert.Nil(t, err)
assert.NotNil(t, filters.FilterObj)
assert.NotNil(t, filters.FilterObj.(FiltersAnd))
assert.Len(t, filters.FilterObj.(FiltersAnd), 5)
})
t.Run("type filter", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_And,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: "relationKey",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("option2"),
Format: model.RelationFormat_status,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("Object 1"),
Format: model.RelationFormat_shorttext,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyType.String(),
Condition: model.BlockContentDataviewFilter_In,
Value: pbtypes.Float64(float64(model.ObjectType_space)),
},
},
},
}
// then
filters, err := NewFilters(Query{Filters: filter}, mockStore, &fastjson.Arena{})
// when
assert.Nil(t, err)
assert.NotNil(t, filters.FilterObj)
assert.NotNil(t, filters.FilterObj.(FiltersAnd))
assert.Len(t, filters.FilterObj.(FiltersAnd), 6)
})
t.Run("or filter with 3 default", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_Or,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: "relationKey",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("option2"),
Format: model.RelationFormat_status,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("Object 1"),
Format: model.RelationFormat_shorttext,
},
},
},
}
// then
filters, err := NewFilters(Query{Filters: filter}, mockStore, &fastjson.Arena{})
// when
assert.Nil(t, err)
assert.NotNil(t, filters.FilterObj)
assert.NotNil(t, filters.FilterObj.(FiltersAnd))
assert.Len(t, filters.FilterObj.(FiltersAnd), 4)
assert.NotNil(t, filters.FilterObj.(FiltersAnd)[0].(FiltersOr))
assert.Len(t, filters.FilterObj.(FiltersAnd)[0].(FiltersOr), 2)
})
}

View file

@ -23,34 +23,69 @@ var (
ErrValueMustBeListSupporting = errors.New("value must be list supporting")
)
func MakeFiltersAnd(protoFilters []*model.BlockContentDataviewFilter, store ObjectStore) (FiltersAnd, error) {
if store == nil {
return FiltersAnd{}, fmt.Errorf("objectStore dependency is nil")
func MakeFilters(protoFilters []*model.BlockContentDataviewFilter, store ObjectStore) (Filter, error) {
spaceId := getSpaceIDFromFilters(protoFilters)
// to avoid unnecessary nested filter
if len(protoFilters) == 1 && len(protoFilters[0].NestedFilters) > 0 && protoFilters[0].Operator != model.BlockContentDataviewFilter_No {
return MakeFilter(spaceId, protoFilters[0], store)
}
spaceID := getSpaceIDFromFilters(protoFilters)
protoFilters = TransformQuickOption(protoFilters, nil)
return MakeFilter(spaceId, &model.BlockContentDataviewFilter{
Operator: model.BlockContentDataviewFilter_And,
NestedFilters: protoFilters,
}, store)
}
var and FiltersAnd
for _, pf := range protoFilters {
if pf.Condition != model.BlockContentDataviewFilter_None {
f, err := MakeFilter(spaceID, pf, store)
if err != nil {
return nil, err
}
and = append(and, f)
func MakeFilter(spaceId string, protoFilter *model.BlockContentDataviewFilter, store ObjectStore) (Filter, error) {
if protoFilter.Operator == model.BlockContentDataviewFilter_No {
return makeFilter(spaceId, protoFilter, store)
}
filters := make([]Filter, 0, len(protoFilter.NestedFilters))
for _, nestedFilter := range protoFilter.NestedFilters {
filter, err := MakeFilter(spaceId, nestedFilter, store)
if err != nil {
return nil, err
}
if filter != nil {
filters = append(filters, filter)
}
}
return and, nil
switch protoFilter.Operator {
case model.BlockContentDataviewFilter_And, model.BlockContentDataviewFilter_No:
return FiltersAnd(filters), nil
case model.BlockContentDataviewFilter_Or:
return FiltersOr(filters), nil
}
return nil, fmt.Errorf("unsupported filter operator %v", protoFilter.Operator)
}
func NestedRelationKey(baseRelationKey domain.RelationKey, nestedRelationKey domain.RelationKey) string {
return fmt.Sprintf("%s.%s", baseRelationKey.String(), nestedRelationKey.String())
}
func MakeFilter(spaceID string, rawFilter *model.BlockContentDataviewFilter, store ObjectStore) (Filter, error) {
func makeFilter(spaceID string, rawFilter *model.BlockContentDataviewFilter, store ObjectStore) (Filter, error) {
if store == nil {
return nil, fmt.Errorf("objectStore dependency is nil")
}
if rawFilter.Condition == model.BlockContentDataviewFilter_None {
return nil, nil
}
rawFilters := transformQuickOption(rawFilter, nil)
if len(rawFilters) == 1 {
return makeFilterByCondition(spaceID, rawFilters[0], store)
}
resultFilters := FiltersAnd{}
for _, filter := range rawFilters {
filterByCondition, err := makeFilterByCondition(spaceID, filter, store)
if err != nil {
return nil, err
}
resultFilters = append(resultFilters, filterByCondition)
}
return resultFilters, nil
}
func makeFilterByCondition(spaceID string, rawFilter *model.BlockContentDataviewFilter, store ObjectStore) (Filter, error) {
parts := strings.SplitN(rawFilter.RelationKey, ".", 2)
if len(parts) == 2 {
return makeFilterNestedIn(spaceID, rawFilter, store, parts[0], parts[1])

View file

@ -2,6 +2,7 @@ package database
import (
"testing"
"time"
"github.com/anyproto/any-store/query"
"github.com/gogo/protobuf/types"
@ -366,7 +367,7 @@ func TestMakeAndFilter(t *testing.T) {
Value: pbtypes.StringList([]string{"14"}),
},
}
andFilter, err := MakeFiltersAnd(filters, store)
andFilter, err := MakeFilters(filters, store)
require.NoError(t, err)
assert.Len(t, andFilter, 14)
})
@ -377,7 +378,7 @@ func TestMakeAndFilter(t *testing.T) {
model.BlockContentDataviewFilter_AllIn,
model.BlockContentDataviewFilter_NotAllIn,
} {
_, err := MakeFiltersAnd([]*model.BlockContentDataviewFilter{
_, err := MakeFilters([]*model.BlockContentDataviewFilter{
{Condition: cond, Value: pbtypes.Null()},
}, store)
assert.Equal(t, ErrValueMustBeListSupporting, err)
@ -385,13 +386,13 @@ func TestMakeAndFilter(t *testing.T) {
})
t.Run("unexpected condition", func(t *testing.T) {
_, err := MakeFiltersAnd([]*model.BlockContentDataviewFilter{
_, err := MakeFilters([]*model.BlockContentDataviewFilter{
{Condition: 10000},
}, store)
assert.Error(t, err)
})
t.Run("replace 'value == false' to 'value != true'", func(t *testing.T) {
f, err := MakeFiltersAnd([]*model.BlockContentDataviewFilter{
f, err := MakeFilters([]*model.BlockContentDataviewFilter{
{
RelationKey: "b",
Condition: model.BlockContentDataviewFilter_Equal,
@ -410,7 +411,7 @@ func TestMakeAndFilter(t *testing.T) {
assertFilter(t, f, g, false)
})
t.Run("replace 'value != false' to 'value == true'", func(t *testing.T) {
f, err := MakeFiltersAnd([]*model.BlockContentDataviewFilter{
f, err := MakeFilters([]*model.BlockContentDataviewFilter{
{
RelationKey: "b",
Condition: model.BlockContentDataviewFilter_NotEqual,
@ -453,7 +454,7 @@ func TestNestedFilters(t *testing.T) {
},
}, nil)
f, err := MakeFilter("", &model.BlockContentDataviewFilter{
f, err := MakeFilter("spaceId", &model.BlockContentDataviewFilter{
RelationKey: "type.typeKey",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("note"),
@ -542,3 +543,315 @@ func TestFilterOptionsEqual(t *testing.T) {
assertFilter(t, eq, obj, false)
})
}
func TestMakeFilters(t *testing.T) {
t.Run("no filters", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
// when
filters, err := MakeFilters(nil, mockStore)
// then
assert.Nil(t, err)
assert.Len(t, filters, 0)
})
t.Run("or filter", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_Or,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: "relationKey",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("option2"),
Format: model.RelationFormat_status,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("Object 1"),
Format: model.RelationFormat_shorttext,
},
},
},
}
// when
filters, err := MakeFilters(filter, mockStore)
// then
assert.Nil(t, err)
assert.Len(t, filters, 2)
assert.NotNil(t, filters.(FiltersOr))
assert.NotNil(t, filters.(FiltersOr)[0].(FilterEq))
assert.NotNil(t, filters.(FiltersOr)[1].(FilterEq))
assert.Equal(t, "relationKey", filters.(FiltersOr)[0].(FilterEq).Key)
assert.Equal(t, pbtypes.String("option2"), filters.(FiltersOr)[0].(FilterEq).Value)
assert.Equal(t, "name", filters.(FiltersOr)[1].(FilterEq).Key)
assert.Equal(t, pbtypes.String("Object 1"), filters.(FiltersOr)[1].(FilterEq).Value)
})
t.Run("and filter", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_And,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: "relationKey",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("option2"),
Format: model.RelationFormat_status,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyName.String(),
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("Object 1"),
Format: model.RelationFormat_shorttext,
},
},
},
}
// when
filters, err := MakeFilters(filter, mockStore)
// then
assert.Nil(t, err)
assert.Len(t, filters, 2)
assert.NotNil(t, filters.(FiltersAnd))
assert.NotNil(t, filters.(FiltersAnd)[0].(FilterEq))
assert.NotNil(t, filters.(FiltersAnd)[1].(FilterEq))
assert.Equal(t, "relationKey", filters.(FiltersAnd)[0].(FilterEq).Key)
assert.Equal(t, pbtypes.String("option2"), filters.(FiltersAnd)[0].(FilterEq).Value)
assert.Equal(t, "name", filters.(FiltersAnd)[1].(FilterEq).Key)
assert.Equal(t, pbtypes.String("Object 1"), filters.(FiltersAnd)[1].(FilterEq).Value)
})
t.Run("none filter", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: "relationKey",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("option1"),
Format: model.RelationFormat_status,
},
}
// when
filters, err := MakeFilters(filter, mockStore)
// then
assert.Nil(t, err)
assert.Len(t, filters, 1)
assert.NotNil(t, filters.(FiltersAnd))
assert.NotNil(t, filters.(FiltersAnd)[0].(FilterEq))
assert.Equal(t, "relationKey", filters.(FiltersAnd)[0].(FilterEq).Key)
assert.Equal(t, pbtypes.String("option1"), filters.(FiltersAnd)[0].(FilterEq).Value)
})
t.Run("combined filter", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_And,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_Or,
NestedFilters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: "relationKey",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("option1"),
Format: model.RelationFormat_status,
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: "relationKey1",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("option2"),
Format: model.RelationFormat_status,
},
},
},
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: "relationKey3",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.String("option3"),
Format: model.RelationFormat_status,
},
},
},
}
// when
filters, err := MakeFilters(filter, mockStore)
// then
assert.Nil(t, err)
assert.Len(t, filters, 2)
assert.NotNil(t, filters.(FiltersAnd))
assert.NotNil(t, filters.(FiltersAnd)[0].(FiltersOr))
assert.NotNil(t, filters.(FiltersAnd)[1].(FilterEq))
})
t.Run("linear and nested filters", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
RelationKey: "key1",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
{
Operator: model.BlockContentDataviewFilter_Or,
NestedFilters: []*model.BlockContentDataviewFilter{
{
RelationKey: "key2",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
},
},
}
// when
filters, err := MakeFilters(filter, mockStore)
// then
assert.Nil(t, err)
assert.Len(t, filters, 2)
assert.NotNil(t, filters.(FiltersAnd))
assert.NotNil(t, filters.(FiltersAnd)[0].(FilterEq))
assert.NotNil(t, filters.(FiltersAnd)[1].(FiltersOr))
})
t.Run("linear and nested filters", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_And,
RelationKey: "key1",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
{
Operator: model.BlockContentDataviewFilter_And,
RelationKey: "key1",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
{
Operator: model.BlockContentDataviewFilter_And,
RelationKey: "key1",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
{
Operator: model.BlockContentDataviewFilter_And,
RelationKey: "key1",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
{
Operator: model.BlockContentDataviewFilter_And,
RelationKey: "key1",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
{
Operator: model.BlockContentDataviewFilter_And,
RelationKey: "key1",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
{
Operator: model.BlockContentDataviewFilter_And,
RelationKey: "key1",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
}
// when
_, err := MakeFilters(filter, mockStore)
// then
assert.Nil(t, err)
})
t.Run("transform quick options", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_Or,
NestedFilters: []*model.BlockContentDataviewFilter{
{
RelationKey: "key2",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Int64(time.Now().Unix()),
QuickOption: model.BlockContentDataviewFilter_CurrentMonth,
},
{
RelationKey: "key3",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
},
},
}
// when
filters, err := MakeFilters(filter, mockStore)
// then
assert.Nil(t, err)
assert.Len(t, filters, 2)
assert.NotNil(t, filters.(FiltersOr))
assert.NotNil(t, filters.(FiltersOr)[0].(FiltersAnd))
assert.NotNil(t, filters.(FiltersOr)[1].(FilterEq))
})
t.Run("transform quick options", func(t *testing.T) {
// given
mockStore := NewMockObjectStore(t)
filter := []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_Or,
NestedFilters: []*model.BlockContentDataviewFilter{
{
RelationKey: "key2",
Condition: model.BlockContentDataviewFilter_Less,
Value: pbtypes.Int64(time.Now().Unix()),
QuickOption: model.BlockContentDataviewFilter_CurrentMonth,
},
{
RelationKey: "key3",
Condition: model.BlockContentDataviewFilter_Equal,
Value: pbtypes.Bool(true),
},
},
},
}
// when
filters, err := MakeFilters(filter, mockStore)
// then
assert.Nil(t, err)
assert.Len(t, filters, 2)
assert.NotNil(t, filters.(FiltersOr))
assert.NotNil(t, filters.(FiltersOr)[0].(FilterEq))
assert.NotNil(t, filters.(FiltersOr)[1].(FilterEq))
})
}

View file

@ -8,50 +8,43 @@ import (
timeutil "github.com/anyproto/anytype-heart/util/time"
)
func TransformQuickOption(protoFilters []*model.BlockContentDataviewFilter, loc *time.Location) []*model.BlockContentDataviewFilter {
if protoFilters == nil {
func transformQuickOption(protoFilter *model.BlockContentDataviewFilter, loc *time.Location) []*model.BlockContentDataviewFilter {
if protoFilter == nil {
return nil
}
var filters []*model.BlockContentDataviewFilter
filters = append(filters, protoFilter)
if protoFilter.QuickOption > model.BlockContentDataviewFilter_ExactDate || protoFilter.Format == model.RelationFormat_date {
d1, d2 := getRange(protoFilter, loc)
switch protoFilter.Condition {
case model.BlockContentDataviewFilter_Equal:
protoFilter.Condition = model.BlockContentDataviewFilter_GreaterOrEqual
protoFilter.Value = pbtypes.ToValue(d1)
filters := make([]*model.BlockContentDataviewFilter, len(protoFilters))
for i, f := range protoFilters {
filters[i] = pbtypes.CopyFilter(f)
}
filters = append(filters, &model.BlockContentDataviewFilter{
RelationKey: protoFilter.RelationKey,
Condition: model.BlockContentDataviewFilter_LessOrEqual,
Value: pbtypes.ToValue(d2),
})
case model.BlockContentDataviewFilter_Less:
protoFilter.Value = pbtypes.ToValue(d1)
case model.BlockContentDataviewFilter_Greater:
protoFilter.Value = pbtypes.ToValue(d2)
case model.BlockContentDataviewFilter_LessOrEqual:
protoFilter.Value = pbtypes.ToValue(d2)
case model.BlockContentDataviewFilter_GreaterOrEqual:
protoFilter.Value = pbtypes.ToValue(d1)
case model.BlockContentDataviewFilter_In:
protoFilter.Condition = model.BlockContentDataviewFilter_GreaterOrEqual
protoFilter.Value = pbtypes.ToValue(d1)
for _, f := range filters {
if f.QuickOption > model.BlockContentDataviewFilter_ExactDate || f.Format == model.RelationFormat_date {
d1, d2 := getRange(f, loc)
switch f.Condition {
case model.BlockContentDataviewFilter_Equal:
f.Condition = model.BlockContentDataviewFilter_GreaterOrEqual
f.Value = pbtypes.ToValue(d1)
filters = append(filters, &model.BlockContentDataviewFilter{
RelationKey: f.RelationKey,
Condition: model.BlockContentDataviewFilter_LessOrEqual,
Value: pbtypes.ToValue(d2),
})
case model.BlockContentDataviewFilter_Less:
f.Value = pbtypes.ToValue(d1)
case model.BlockContentDataviewFilter_Greater:
f.Value = pbtypes.ToValue(d2)
case model.BlockContentDataviewFilter_LessOrEqual:
f.Value = pbtypes.ToValue(d2)
case model.BlockContentDataviewFilter_GreaterOrEqual:
f.Value = pbtypes.ToValue(d1)
case model.BlockContentDataviewFilter_In:
f.Condition = model.BlockContentDataviewFilter_GreaterOrEqual
f.Value = pbtypes.ToValue(d1)
filters = append(filters, &model.BlockContentDataviewFilter{
RelationKey: f.RelationKey,
Condition: model.BlockContentDataviewFilter_LessOrEqual,
Value: pbtypes.ToValue(d2),
})
}
filters = append(filters, &model.BlockContentDataviewFilter{
RelationKey: protoFilter.RelationKey,
Condition: model.BlockContentDataviewFilter_LessOrEqual,
Value: pbtypes.ToValue(d2),
})
}
}
return filters
}

File diff suppressed because it is too large Load diff

View file

@ -432,10 +432,12 @@ message Block {
QuickOption quickOption = 6;
RelationFormat format = 7;
bool includeTime = 8;
repeated Filter nestedFilters = 10;
enum Operator {
And = 0;
No = 0;
Or = 1;
And = 2;
}
enum Condition {