Skip to content

Commit cb51054

Browse files
committed
sql: INVERTED JOIN acceleration for json {?, ?&, ?|} array and array && array
fixes: #81642 fixes: #81643 This commit adds support for accelerating the json ? string, json ?& array, json ?| array and array && array operators for INVERTED JOIN when the json/array argument is a column that has an inverted index over it. Release note (sql change): the json ? string, json ?& array, json ?| array and array && array operators are now index accelerated for INVERTED JOIN statement if there is an inverted index over the json column referred to on the left hand side of the expression.
1 parent 89e2a6b commit cb51054

File tree

4 files changed

+527
-30
lines changed

4 files changed

+527
-30
lines changed

pkg/sql/logictest/testdata/logic_test/inverted_join_json_array

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,6 +1018,94 @@ SELECT * FROM array_tab@foo_inv AS a1, array_tab AS a2 WHERE a1.b @> a2.b ORDER
10181018
6 {1,2,3,4} 6 {1,2,3,4}
10191019
7 {NULL} 1 {}
10201020

1021+
# This query performs an inverted join with && (overlaps) operator in the
1022+
# join condition. We limit it to a2.a > 1 AND a2.a < 7 to avoid empty and
1023+
# null arrays.
1024+
query ITIT
1025+
SELECT * FROM array_tab@array_tab_pkey AS a2
1026+
INNER INVERTED JOIN array_tab@foo_inv AS a1
1027+
ON a1.b && a2.b AND a2.a > 1 AND a2.a < 7
1028+
ORDER BY a1.a, a2.a
1029+
----
1030+
2 {1} 2 {1}
1031+
4 {1,2} 2 {1}
1032+
5 {1,3} 2 {1}
1033+
6 {1,2,3,4} 2 {1}
1034+
3 {2} 3 {2}
1035+
4 {1,2} 3 {2}
1036+
6 {1,2,3,4} 3 {2}
1037+
2 {1} 4 {1,2}
1038+
3 {2} 4 {1,2}
1039+
4 {1,2} 4 {1,2}
1040+
5 {1,3} 4 {1,2}
1041+
6 {1,2,3,4} 4 {1,2}
1042+
2 {1} 5 {1,3}
1043+
4 {1,2} 5 {1,3}
1044+
5 {1,3} 5 {1,3}
1045+
6 {1,2,3,4} 5 {1,3}
1046+
2 {1} 6 {1,2,3,4}
1047+
3 {2} 6 {1,2,3,4}
1048+
4 {1,2} 6 {1,2,3,4}
1049+
5 {1,3} 6 {1,2,3,4}
1050+
6 {1,2,3,4} 6 {1,2,3,4}
1051+
1052+
statement ok
1053+
CREATE TABLE array_tab_not_idx (
1054+
a INT PRIMARY KEY,
1055+
b INT[]
1056+
);
1057+
1058+
statement ok
1059+
INSERT INTO array_tab_not_idx VALUES
1060+
(1, '{}'),
1061+
(2, '{1}'),
1062+
(3, '{2}'),
1063+
(4, '{1, 2}'),
1064+
(5, '{1, 3}'),
1065+
(6, '{1, 2, 5}'),
1066+
(7, ARRAY[NULL]::INT[]),
1067+
(8, NULL)
1068+
1069+
# Ensure that join confition with not-index-array && index-array will be
1070+
# normalized to index-array && not-index-array.
1071+
query ITIT
1072+
SELECT * FROM array_tab_not_idx@array_tab_not_idx_pkey AS a2
1073+
INNER INVERTED JOIN array_tab@foo_inv AS a1
1074+
ON a2.b && a1.b AND a2.a > 1 AND a2.a < 7
1075+
ORDER BY a1.a, a2.a
1076+
----
1077+
2 {1} 2 {1}
1078+
4 {1,2} 2 {1}
1079+
5 {1,3} 2 {1}
1080+
6 {1,2,5} 2 {1}
1081+
3 {2} 3 {2}
1082+
4 {1,2} 3 {2}
1083+
6 {1,2,5} 3 {2}
1084+
2 {1} 4 {1,2}
1085+
3 {2} 4 {1,2}
1086+
4 {1,2} 4 {1,2}
1087+
5 {1,3} 4 {1,2}
1088+
6 {1,2,5} 4 {1,2}
1089+
2 {1} 5 {1,3}
1090+
4 {1,2} 5 {1,3}
1091+
5 {1,3} 5 {1,3}
1092+
6 {1,2,5} 5 {1,3}
1093+
2 {1} 6 {1,2,3,4}
1094+
3 {2} 6 {1,2,3,4}
1095+
4 {1,2} 6 {1,2,3,4}
1096+
5 {1,3} 6 {1,2,3,4}
1097+
6 {1,2,5} 6 {1,2,3,4}
1098+
1099+
# If the given array is directly empty (i.e. Len == 0),
1100+
# or contains only NULLs and thus has effective length 0,
1101+
# we cannot generate an inverted expression.
1102+
# See encodeOverlapsArrayInvertedIndexSpans().
1103+
statement error pq: unable to construct span expression
1104+
SELECT * FROM array_tab@array_tab_pkey AS a2
1105+
INNER INVERTED JOIN array_tab@foo_inv AS a1
1106+
ON a1.b && a2.b
1107+
ORDER BY a1.a, a2.a
1108+
10211109
# This query performs a cross join followed by a filter.
10221110
query ITIT
10231111
SELECT * FROM array_tab@array_tab_pkey AS a1 CROSS HASH JOIN array_tab AS a2 WHERE a1.b @> a2.b ORDER BY a1.a, a2.a
@@ -1336,3 +1424,190 @@ FROM j1 LEFT INVERTED JOIN j2@j_idx
13361424
ORDER BY j1.k, j2.k
13371425
----
13381426
1 {"a": "b"} NULL NULL
1427+
1428+
query ITIT
1429+
SELECT * FROM json_tab AS j2 INNER INVERTED JOIN json_tab AS j1
1430+
ON j1.b ? (j2.b ->> 'a') ORDER BY j1.a, j2.a
1431+
----
1432+
45 {"a": "a"} 1 {"a": "b"}
1433+
45 {"a": "a"} 3 {"a": {"b": "c"}}
1434+
45 {"a": "a"} 4 {"a": {"b": [1]}}
1435+
45 {"a": "a"} 5 {"a": {"b": [1, [2]]}}
1436+
45 {"a": "a"} 6 {"a": {"b": [[2]]}}
1437+
45 {"a": "a"} 7 {"a": "b", "c": "d"}
1438+
46 {"a": "c"} 7 {"a": "b", "c": "d"}
1439+
45 {"a": "a"} 8 {"a": {"b": true}}
1440+
45 {"a": "a"} 9 {"a": {"b": false}}
1441+
45 {"a": "a"} 10 "a"
1442+
45 {"a": "a"} 19 ["a", "a"]
1443+
45 {"a": "a"} 23 {"a": 123.123}
1444+
45 {"a": "a"} 24 {"a": 123.123000}
1445+
45 {"a": "a"} 25 {"a": [{}]}
1446+
45 {"a": "a"} 27 [true, false, null, 1.23, "a"]
1447+
45 {"a": "a"} 28 {"a": {}}
1448+
45 {"a": "a"} 30 {"a": []}
1449+
45 {"a": "a"} 31 {"a": {"b": "c", "d": "e"}, "f": "g"}
1450+
45 {"a": "a"} 32 {"a": [1]}
1451+
45 {"a": "a"} 34 {"a": 1}
1452+
45 {"a": "a"} 39 ["a"]
1453+
45 {"a": "a"} 40 {"a": [[]]}
1454+
45 {"a": "a"} 45 {"a": "a"}
1455+
45 {"a": "a"} 46 {"a": "c"}
1456+
1457+
query ITIT
1458+
SELECT * FROM json_tab AS j2 INNER INVERTED JOIN json_tab AS j1
1459+
ON j1.b @> j2.b AND j1.b ? (j2.b ->> 'a') ORDER BY j1.a, j2.a
1460+
----
1461+
45 {"a": "a"} 45 {"a": "a"}
1462+
1463+
statement ok
1464+
CREATE TABLE text_array_tab (
1465+
a INT PRIMARY KEY,
1466+
b TEXT[]
1467+
);
1468+
1469+
statement ok
1470+
INSERT INTO text_array_tab VALUES
1471+
(1, '{}'),
1472+
(2, '{a}'),
1473+
(3, '{a, b}'),
1474+
(4, '{a, c}'),
1475+
(5, '{a, b, c}'),
1476+
(6, '{1}'),
1477+
(7, NULL);
1478+
1479+
# INNER INVERTED JOIN only works if the right side has an inverted index.
1480+
statement error pq: could not produce a query plan conforming to the INVERTED JOIN hint
1481+
SELECT * FROM json_tab AS j INNER INVERTED JOIN text_array_tab AS t
1482+
ON j.b ?| t.b ORDER BY t.a, j.a
1483+
1484+
query ITIT
1485+
SELECT * FROM text_array_tab AS t INNER INVERTED JOIN json_tab AS j
1486+
ON j.b ?| t.b ORDER BY t.a, j.a
1487+
----
1488+
2 {a} 1 {"a": "b"}
1489+
2 {a} 3 {"a": {"b": "c"}}
1490+
2 {a} 4 {"a": {"b": [1]}}
1491+
2 {a} 5 {"a": {"b": [1, [2]]}}
1492+
2 {a} 6 {"a": {"b": [[2]]}}
1493+
2 {a} 7 {"a": "b", "c": "d"}
1494+
2 {a} 8 {"a": {"b": true}}
1495+
2 {a} 9 {"a": {"b": false}}
1496+
2 {a} 10 "a"
1497+
2 {a} 19 ["a", "a"]
1498+
2 {a} 23 {"a": 123.123}
1499+
2 {a} 24 {"a": 123.123000}
1500+
2 {a} 25 {"a": [{}]}
1501+
2 {a} 27 [true, false, null, 1.23, "a"]
1502+
2 {a} 28 {"a": {}}
1503+
2 {a} 30 {"a": []}
1504+
2 {a} 31 {"a": {"b": "c", "d": "e"}, "f": "g"}
1505+
2 {a} 32 {"a": [1]}
1506+
2 {a} 34 {"a": 1}
1507+
2 {a} 39 ["a"]
1508+
2 {a} 40 {"a": [[]]}
1509+
2 {a} 45 {"a": "a"}
1510+
2 {a} 46 {"a": "c"}
1511+
3 {a,b} 1 {"a": "b"}
1512+
3 {a,b} 3 {"a": {"b": "c"}}
1513+
3 {a,b} 4 {"a": {"b": [1]}}
1514+
3 {a,b} 5 {"a": {"b": [1, [2]]}}
1515+
3 {a,b} 6 {"a": {"b": [[2]]}}
1516+
3 {a,b} 7 {"a": "b", "c": "d"}
1517+
3 {a,b} 8 {"a": {"b": true}}
1518+
3 {a,b} 9 {"a": {"b": false}}
1519+
3 {a,b} 10 "a"
1520+
3 {a,b} 19 ["a", "a"]
1521+
3 {a,b} 23 {"a": 123.123}
1522+
3 {a,b} 24 {"a": 123.123000}
1523+
3 {a,b} 25 {"a": [{}]}
1524+
3 {a,b} 27 [true, false, null, 1.23, "a"]
1525+
3 {a,b} 28 {"a": {}}
1526+
3 {a,b} 30 {"a": []}
1527+
3 {a,b} 31 {"a": {"b": "c", "d": "e"}, "f": "g"}
1528+
3 {a,b} 32 {"a": [1]}
1529+
3 {a,b} 34 {"a": 1}
1530+
3 {a,b} 39 ["a"]
1531+
3 {a,b} 40 {"a": [[]]}
1532+
3 {a,b} 45 {"a": "a"}
1533+
3 {a,b} 46 {"a": "c"}
1534+
4 {a,c} 1 {"a": "b"}
1535+
4 {a,c} 3 {"a": {"b": "c"}}
1536+
4 {a,c} 4 {"a": {"b": [1]}}
1537+
4 {a,c} 5 {"a": {"b": [1, [2]]}}
1538+
4 {a,c} 6 {"a": {"b": [[2]]}}
1539+
4 {a,c} 7 {"a": "b", "c": "d"}
1540+
4 {a,c} 8 {"a": {"b": true}}
1541+
4 {a,c} 9 {"a": {"b": false}}
1542+
4 {a,c} 10 "a"
1543+
4 {a,c} 19 ["a", "a"]
1544+
4 {a,c} 23 {"a": 123.123}
1545+
4 {a,c} 24 {"a": 123.123000}
1546+
4 {a,c} 25 {"a": [{}]}
1547+
4 {a,c} 27 [true, false, null, 1.23, "a"]
1548+
4 {a,c} 28 {"a": {}}
1549+
4 {a,c} 30 {"a": []}
1550+
4 {a,c} 31 {"a": {"b": "c", "d": "e"}, "f": "g"}
1551+
4 {a,c} 32 {"a": [1]}
1552+
4 {a,c} 34 {"a": 1}
1553+
4 {a,c} 39 ["a"]
1554+
4 {a,c} 40 {"a": [[]]}
1555+
4 {a,c} 45 {"a": "a"}
1556+
4 {a,c} 46 {"a": "c"}
1557+
5 {a,b,c} 1 {"a": "b"}
1558+
5 {a,b,c} 3 {"a": {"b": "c"}}
1559+
5 {a,b,c} 4 {"a": {"b": [1]}}
1560+
5 {a,b,c} 5 {"a": {"b": [1, [2]]}}
1561+
5 {a,b,c} 6 {"a": {"b": [[2]]}}
1562+
5 {a,b,c} 7 {"a": "b", "c": "d"}
1563+
5 {a,b,c} 8 {"a": {"b": true}}
1564+
5 {a,b,c} 9 {"a": {"b": false}}
1565+
5 {a,b,c} 10 "a"
1566+
5 {a,b,c} 19 ["a", "a"]
1567+
5 {a,b,c} 23 {"a": 123.123}
1568+
5 {a,b,c} 24 {"a": 123.123000}
1569+
5 {a,b,c} 25 {"a": [{}]}
1570+
5 {a,b,c} 27 [true, false, null, 1.23, "a"]
1571+
5 {a,b,c} 28 {"a": {}}
1572+
5 {a,b,c} 30 {"a": []}
1573+
5 {a,b,c} 31 {"a": {"b": "c", "d": "e"}, "f": "g"}
1574+
5 {a,b,c} 32 {"a": [1]}
1575+
5 {a,b,c} 34 {"a": 1}
1576+
5 {a,b,c} 39 ["a"]
1577+
5 {a,b,c} 40 {"a": [[]]}
1578+
5 {a,b,c} 45 {"a": "a"}
1579+
5 {a,b,c} 46 {"a": "c"}
1580+
1581+
# INNER INVERTED JOIN only works if the right side has an inverted index.
1582+
statement error pq: could not produce a query plan conforming to the INVERTED JOIN hint
1583+
SELECT * FROM json_tab AS j INNER INVERTED JOIN text_array_tab AS t
1584+
ON j.b ?& t.b ORDER BY j.a
1585+
1586+
query ITIT
1587+
SELECT * FROM text_array_tab AS t INNER INVERTED JOIN json_tab AS j
1588+
ON j.b ?& t.b ORDER BY j.a
1589+
----
1590+
2 {a} 1 {"a": "b"}
1591+
2 {a} 3 {"a": {"b": "c"}}
1592+
2 {a} 4 {"a": {"b": [1]}}
1593+
2 {a} 5 {"a": {"b": [1, [2]]}}
1594+
2 {a} 6 {"a": {"b": [[2]]}}
1595+
2 {a} 7 {"a": "b", "c": "d"}
1596+
4 {a,c} 7 {"a": "b", "c": "d"}
1597+
2 {a} 8 {"a": {"b": true}}
1598+
2 {a} 9 {"a": {"b": false}}
1599+
2 {a} 10 "a"
1600+
2 {a} 19 ["a", "a"]
1601+
2 {a} 23 {"a": 123.123}
1602+
2 {a} 24 {"a": 123.123000}
1603+
2 {a} 25 {"a": [{}]}
1604+
2 {a} 27 [true, false, null, 1.23, "a"]
1605+
2 {a} 28 {"a": {}}
1606+
2 {a} 30 {"a": []}
1607+
2 {a} 31 {"a": {"b": "c", "d": "e"}, "f": "g"}
1608+
2 {a} 32 {"a": [1]}
1609+
2 {a} 34 {"a": 1}
1610+
2 {a} 39 ["a"]
1611+
2 {a} 40 {"a": [[]]}
1612+
2 {a} 45 {"a": "a"}
1613+
2 {a} 46 {"a": "c"}

0 commit comments

Comments
 (0)