Skip to content

Commit 8eaa0da

Browse files
committed
sql/jsonpath: validate JSON column in jsonb_path_exists for inverted index acceleration
Informs: #154729 Previously, the jsonb_path_exists function would attempt inverted index acceleration even when the JSON parameter referenced a column that was not the source column of the inverted index, or when it was a constant JSON value. This resulted in incorrect query plans and potentially wrong results. This commit adds proper validation to ensure that inverted index acceleration is only used when the JSON parameter is a variable expression that references the actual source column of the inverted index. For all other cases, the query will fall back to a full table scan with post-filtering. Release note: None
1 parent e942b71 commit 8eaa0da

File tree

2 files changed

+53
-9
lines changed

2 files changed

+53
-9
lines changed

pkg/sql/logictest/testdata/logic_test/jsonb_path_exists_index_acceleration

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
statement ok
55
CREATE TABLE json_tab (
66
a INT PRIMARY KEY,
7-
b JSONB
7+
b JSONB,
8+
c JSONB
89
)
910

1011
statement ok
@@ -25,7 +26,7 @@ INSERT INTO json_tab VALUES
2526

2627
# To confirm which rows contain the specified path.
2728
query IT
28-
SELECT * FROM json_tab@primary WHERE jsonb_path_exists(b, '$.a.b') ORDER BY a;
29+
SELECT a, b FROM json_tab@primary WHERE jsonb_path_exists(b, '$.a.b') ORDER BY a, b;
2930
----
3031
3 {"a": {"b": "c", "d": "e"}}
3132
4 {"a": {"b": [1, 2, 3, 4]}}
@@ -35,7 +36,7 @@ SELECT * FROM json_tab@primary WHERE jsonb_path_exists(b, '$.a.b') ORDER BY a;
3536
9 {"a": {"b": "c"}}
3637

3738
query IT
38-
SELECT * FROM json_tab@foo_inv WHERE jsonb_path_exists(b, '$.a.b') ORDER BY a;
39+
SELECT a, b FROM json_tab@foo_inv WHERE jsonb_path_exists(b, '$.a.b') ORDER BY a, b;
3940
----
4041
3 {"a": {"b": "c", "d": "e"}}
4142
4 {"a": {"b": [1, 2, 3, 4]}}
@@ -505,3 +506,42 @@ SELECT a FROM json_tab@foo_inv WHERE jsonb_path_exists(b, '$.a[*][*] ? (@.b == 1
505506
16
506507
17
507508
18
509+
510+
# If json parameter is not part of the inverted index, the filter should
511+
# not be index accelerated.
512+
statement ok
513+
INSERT INTO json_tab VALUES (19, '{"a": {"b": "c"}}', '{"a": {"b": "c"}}')
514+
515+
query I
516+
SELECT a FROM json_tab@primary WHERE jsonb_path_exists(c, '$.a.b') ORDER BY a;
517+
----
518+
19
519+
520+
statement error index "foo_inv" is inverted and cannot be used for this query
521+
SELECT a FROM json_tab@foo_inv WHERE jsonb_path_exists(c, '$.a.b') ORDER BY a;
522+
523+
query I
524+
SELECT a FROM json_tab@primary WHERE jsonb_path_exists('{"a": {"b": "c"}}', '$.a.b') ORDER BY a;
525+
----
526+
1
527+
2
528+
3
529+
4
530+
5
531+
6
532+
7
533+
8
534+
9
535+
10
536+
11
537+
12
538+
13
539+
14
540+
15
541+
16
542+
17
543+
18
544+
19
545+
546+
statement error index "foo_inv" is inverted and cannot be used for this query
547+
SELECT a FROM json_tab@foo_inv WHERE jsonb_path_exists('{"a": {"b": "c"}}', '$.a.b') ORDER BY a;

pkg/sql/opt/invertedidx/json_array.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -417,15 +417,19 @@ func (j *jsonOrArrayFilterPlanner) extractInvertedFilterConditionFromLeaf(
417417
case *memo.FunctionExpr:
418418
if t.Properties.Category == builtinconstants.CategoryJsonpath && t.Name == "jsonb_path_exists" {
419419
if len(t.Args) > 1 {
420-
if ce, ok := t.Args[1].(*memo.ConstExpr); ok {
421-
if dJsonPath, ok := ce.Value.(*tree.DJsonpath); ok {
422-
if dJsonPath.Strict {
423-
return inverted.NonInvertedColExpression{}, expr, nil
420+
// The first parameter has to be a column reference.
421+
if isIndexColumn(j.tabID, j.index, t.Args[0], j.computedColumns) {
422+
if ce, ok := t.Args[1].(*memo.ConstExpr); ok {
423+
if dJsonPath, ok := ce.Value.(*tree.DJsonpath); ok {
424+
if dJsonPath.Strict {
425+
return inverted.NonInvertedColExpression{}, expr, nil
426+
}
427+
jp := dJsonPath.Path
428+
invertedExpr = j.extractJSONPathCondition(ctx, evalCtx, jp)
424429
}
425-
jp := dJsonPath.Path
426-
invertedExpr = j.extractJSONPathCondition(ctx, evalCtx, jp)
427430
}
428431
}
432+
429433
}
430434
}
431435
}

0 commit comments

Comments
 (0)