Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(DQL): ignore ordering of indexes in schema with eq function (DGRAPH-2601) #6996

Merged
merged 3 commits into from
Nov 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions systest/queries_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func TestQuery(t *testing.T) {
t.Run("hash index queries", wrap(QueryHashIndex))
t.Run("fuzzy matching", wrap(FuzzyMatch))
t.Run("regexp with toggled trigram index", wrap(RegexpToggleTrigramIndex))
t.Run("eq with altering order of trigram and term index", wrap(EqWithAlteredIndexOrder))
t.Run("groupby uid that works", wrap(GroupByUidWorks))
t.Run("parameterized cascade", wrap(CascadeParams))
t.Run("cleanup", wrap(SchemaQueryCleanup))
Expand Down Expand Up @@ -1346,6 +1347,41 @@ func RegexpToggleTrigramIndex(t *testing.T, c *dgo.Dgraph) {
require.Contains(t, err.Error(), "Attribute name does not have trigram index for regex matching.")
}

func EqWithAlteredIndexOrder(t *testing.T, c *dgo.Dgraph) {
ctx := context.Background()

// first, let's set the schema with term before trigram
op := &api.Operation{Schema: `name: string @index(term, trigram) .`}
require.NoError(t, c.Alter(ctx, op))

// fill up some data
txn := c.NewTxn()
_, err := txn.Mutate(ctx, &api.Mutation{
SetNquads: []byte(`
_:x1 <name> "Alice" .
_:x2 <name> "Bob" .
`),
})
require.NoError(t, err)
require.NoError(t, txn.Commit(ctx))

// querying with eq should work
q := `{q(func: eq(name, "Alice")) {name}}`
expectedResult := `{"q":[{"name":"Alice"}]}`
resp, err := c.NewReadOnlyTxn().Query(ctx, q)
require.NoError(t, err)
testutil.CompareJSON(t, expectedResult, string(resp.Json))

// now, let's set the schema with trigram before term
op = &api.Operation{Schema: `name: string @index(trigram, term) .`}
require.NoError(t, c.Alter(ctx, op))

// querying with eq should still work
resp, err = c.NewReadOnlyTxn().Query(ctx, q)
require.NoError(t, err)
testutil.CompareJSON(t, expectedResult, string(resp.Json))
}

func GroupByUidWorks(t *testing.T, c *dgo.Dgraph) {
ctx := context.Background()

Expand Down
2 changes: 1 addition & 1 deletion wiki/content/query-language/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ Index Required: An index is required for the `eq(predicate, ...)` forms (see tab
| `int` | `int` |
| `float` | `float` |
| `bool` | `bool` |
| `string` | `exact`, `hash` |
| `string` | `exact`, `hash`, `term`, `fulltext` |
| `dateTime` | `dateTime` |

Test for equality of a predicate or variable to a value or find in a list of values.
Expand Down
14 changes: 12 additions & 2 deletions worker/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func pickTokenizer(ctx context.Context, attr string, f string) (tok.Tokenizer, e

tokenizers := schema.State().Tokenizer(ctx, attr)
for _, t := range tokenizers {
// If function is eq and we found a tokenizer thats !Lossy(), lets return it
// If function is eq and we found a tokenizer that's !Lossy(), lets return it
switch f {
case "eq":
// For equality, find a non-lossy tokenizer.
Expand All @@ -105,7 +105,17 @@ func pickTokenizer(ctx context.Context, attr string, f string) (tok.Tokenizer, e
return nil, errors.Errorf("Attribute:%s does not have proper index for comparison", attr)
}

// We didn't find a sortable or !isLossy() tokenizer, lets return the first one.
// If we didn't find a !isLossy() tokenizer for eq function on string type predicates,
// then let's see if we can find a non-trigram tokenizer
if typ, err := schema.State().TypeOf(attr); err == nil && typ == types.StringID {
for _, t := range tokenizers {
if t.Identifier() != tok.IdentTrigram {
return t, nil
}
}
}

// otherwise, lets return the first one.
return tokenizers[0], nil
}

Expand Down