Skip to content

Commit

Permalink
Merge pull request #22503 from m-schneider/scalarcontains
Browse files Browse the repository at this point in the history
sql: add support for scalars on the right of @> in index selection
  • Loading branch information
Masha Schneider authored Feb 13, 2018
2 parents 2f48c50 + 12b9095 commit 5e18f7a
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 1 deletion.
30 changes: 30 additions & 0 deletions pkg/sql/logictest/testdata/logic_test/inverted_index
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ SELECT * from d where b @> 'false' ORDER BY a;
query IT
SELECT * from d where b @> '1' ORDER BY a;
----
2 [1, 2, 3, 4, "foo"]
14 1

query IT
Expand Down Expand Up @@ -399,6 +400,34 @@ SELECT * from d where b @> '[[]]' ORDER BY a;
----
26 [[], {}]

statement ok
INSERT INTO d VALUES (27, '[true, false, null, 1.23, "a"]')

query IT
SELECT * from d where b @> 'true' ORDER BY a;
----
12 true
27 [true, false, null, 1.23, "a"]

query IT
SELECT * from d where b @> 'false' ORDER BY a;
----
13 false
27 [true, false, null, 1.23, "a"]

query IT
SELECT * from d where b @> '1.23' ORDER BY a;
----
15 1.23
27 [true, false, null, 1.23, "a"]

query IT
SELECT * from d where b @> '"a"' ORDER BY a;
----
10 "a"
19 ["a", "a"]
27 [true, false, null, 1.23, "a"]

query IT
SELECT * from d where b IS NULL;
----
Expand Down Expand Up @@ -428,3 +457,4 @@ query IT
SELECT * from d where b @> 'null' ORDER BY a;
----
11 null
27 [true, false, null, 1.23, "a"]
36 changes: 35 additions & 1 deletion pkg/sql/opt/index_constraints.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/cockroachdb/cockroach/pkg/sql/sem/types"
"github.com/cockroachdb/cockroach/pkg/util/encoding"
"github.com/cockroachdb/cockroach/pkg/util/json"
)

// makeEqSpan returns a span that constraints column <offset> to a single value.
Expand Down Expand Up @@ -806,10 +807,43 @@ func (c *indexConstraintCtx) makeInvertedIndexSpansForExpr(
switch e.op {
case containsOp:
lhs, rhs := e.children[0], e.children[1]

if !c.isIndexColumn(lhs, 0 /* index */) || rhs.op != constOp {
return nil, false, false
}
return LogicalSpans{c.makeEqSpan(0 /* offset */, rhs.private.(tree.Datum))}, true, true

rightDatum := rhs.private.(tree.Datum)
rd := rightDatum.(*tree.DJSON).JSON

switch rd.Type() {
case json.ArrayJSONType, json.ObjectJSONType:
return LogicalSpans{c.makeEqSpan(0 /* offset */, rhs.private.(tree.Datum))}, true, true
default:
// If we find a scalar on the right side of the @> operator it means that we need to find
// both matching scalars and arrays that contain that value. In order to do this we generate
// two logical spans, one for the original scalar and one for arrays containing the scalar.
// This is valid because in JSON something can either be an array or scalar so the spans are
// guaranteed not to overlap when mapped onto the primary key space. Therefore there won't be
// any duplicate primary keys when we retrieve rows for both sets.
spans := make(LogicalSpans, 2)

j := json.NewArrayBuilder(1)
j.Add(rd)
dJSON, err := tree.MakeDJSON(j.Build())
if err != nil {
break
}

// This is the span for the scalar.
spans[0].Start = LogicalKey{Vals: tree.Datums{rightDatum}, Inclusive: true}
spans[0].End = spans[0].Start

// This is the span to match arrays.
spans[1].Start = LogicalKey{Vals: tree.Datums{dJSON}, Inclusive: true}
spans[1].End = spans[1].Start

return spans, true, true
}

case andOp:
for _, child := range e.children {
Expand Down

0 comments on commit 5e18f7a

Please sign in to comment.