From 81dcca6113a32e7cddb66ef7aa16e04906fc4e0a Mon Sep 17 00:00:00 2001 From: Islam Aleiv Date: Mon, 19 Aug 2024 23:01:23 +0200 Subject: [PATCH] Check if filter condition is empty --- internal/db/fetcher/indexer.go | 30 ++++++++------ internal/db/fetcher/indexer_iterators.go | 5 +++ .../query_with_index_only_filter_test.go | 41 +++++++++++++++++++ 3 files changed, 63 insertions(+), 13 deletions(-) diff --git a/internal/db/fetcher/indexer.go b/internal/db/fetcher/indexer.go index e75cc18067..7eb8f5b117 100644 --- a/internal/db/fetcher/indexer.go +++ b/internal/db/fetcher/indexer.go @@ -31,7 +31,6 @@ type IndexFetcher struct { col client.Collection txn datastore.Txn indexFilter *mapper.Filter - docFilter *mapper.Filter doc *encodedDocument mapping *core.DocumentMapping indexedFields []client.FieldDefinition @@ -71,7 +70,6 @@ func (f *IndexFetcher) Init( f.resetState() f.col = col - f.docFilter = filter f.doc = &encodedDocument{} f.mapping = docMapper f.txn = txn @@ -100,7 +98,12 @@ outer: } f.indexIter = iter - if f.docFetcher != nil && len(f.docFields) > 0 { + // if it turns out that we can't use the index, we need to fall back to the document fetcher + if f.indexIter == nil { + f.docFields = fields + } + + if len(f.docFields) > 0 { err = f.docFetcher.Init( ctx, identity, @@ -108,7 +111,7 @@ outer: acp, f.col, f.docFields, - f.docFilter, + filter, f.mapping, false, false, @@ -119,14 +122,16 @@ outer: } func (f *IndexFetcher) Start(ctx context.Context, spans core.Spans) error { - err := f.indexIter.Init(ctx, f.txn.Datastore()) - if err != nil { - return err + if f.indexIter == nil { + return f.docFetcher.Start(ctx, spans) } - return nil + return f.indexIter.Init(ctx, f.txn.Datastore()) } func (f *IndexFetcher) FetchNext(ctx context.Context) (EncodedDocument, ExecInfo, error) { + if f.indexIter == nil { + return f.docFetcher.FetchNext(ctx) + } totalExecInfo := f.execInfo defer func() { f.execInfo.Add(totalExecInfo) }() f.execInfo.Reset() @@ -176,7 +181,7 @@ func (f *IndexFetcher) FetchNext(ctx context.Context) (EncodedDocument, ExecInfo } } - if f.docFetcher != nil && len(f.docFields) > 0 { + if len(f.docFields) > 0 { targetKey := base.MakeDataStoreKeyWithCollectionAndDocID(f.col.Description(), string(f.doc.id)) spans := core.NewSpans(core.NewSpan(targetKey, targetKey.PrefixEnd())) err := f.docFetcher.Start(ctx, spans) @@ -204,10 +209,10 @@ func (f *IndexFetcher) FetchNext(ctx context.Context) (EncodedDocument, ExecInfo } func (f *IndexFetcher) Close() error { - if f.indexIter != nil { - return f.indexIter.Close() + if f.indexIter == nil { + return f.docFetcher.Close() } - return nil + return f.indexIter.Close() } // resetState resets the mutable state of this IndexFetcher, returning the state to how it @@ -217,7 +222,6 @@ func (f *IndexFetcher) resetState() { f.col = nil f.txn = nil - f.docFilter = nil f.doc = nil f.mapping = nil f.indexedFields = nil diff --git a/internal/db/fetcher/indexer_iterators.go b/internal/db/fetcher/indexer_iterators.go index 9f01379fa6..c36d679355 100644 --- a/internal/db/fetcher/indexer_iterators.go +++ b/internal/db/fetcher/indexer_iterators.go @@ -538,6 +538,11 @@ func (f *IndexFetcher) createIndexIterator() (indexIterator, error) { return nil, err } + // this can happen if a query contains an empty condition like User(filter: {name: {}}) + if len(fieldConditions) == 0 { + return nil, nil + } + matchers, err := createValueMatchers(fieldConditions) if err != nil { return nil, err diff --git a/tests/integration/index/query_with_index_only_filter_test.go b/tests/integration/index/query_with_index_only_filter_test.go index 1800b855aa..5de362ec81 100644 --- a/tests/integration/index/query_with_index_only_filter_test.go +++ b/tests/integration/index/query_with_index_only_filter_test.go @@ -677,3 +677,44 @@ func TestQueryWithIndex_WithNotLikeFilter_ShouldFetch(t *testing.T) { testUtils.ExecuteTestCase(t, test) } + +func TestQueryWithIndex_EmptyFilterOnIndexedField_ShouldSucceed(t *testing.T) { + test := testUtils.TestCase{ + Actions: []any{ + testUtils.SchemaUpdate{ + Schema: ` + type User { + name: String @index + age: Int + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "name": "Islam", + "age": 33 + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "age": 21 + }`, + }, + testUtils.Request{ + Request: `query { + User(filter: {name: {}}) { + name + } + }`, + Results: map[string]any{ + "User": []map[string]any{ + {"name": "Islam"}, + {"name": "John"}, + }, + }, + }, + }, + } + + testUtils.ExecuteTestCase(t, test) +}