Skip to content

Commit a02c277

Browse files
committed
jsonpath: add support for .type() method
This commit adds support for the `.type()` method in JSONPath queries, which returns a string descripbing the type of the current JSON value ("object", "array", "string", "number", "boolean", "null"). Release note (sql change): Add support for `.type()` method for JSONPath queries. For example, `SELECT jsonb_path_query('[1, 2, 3]', '$.type()');`.
1 parent 091d88b commit a02c277

File tree

6 files changed

+102
-4
lines changed

6 files changed

+102
-4
lines changed

pkg/sql/logictest/testdata/logic_test/jsonb_path_query

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,3 +1469,85 @@ SELECT jsonb_path_query('[12, {"a": 13}, {"b": 14}, "ccc", true]', '$[2 - 1 to $
14691469
{"a": 13}
14701470
{"b": 14}
14711471
"ccc"
1472+
1473+
query T
1474+
SELECT jsonb_path_query('{}', '$.type()');
1475+
----
1476+
"object"
1477+
1478+
query T
1479+
SELECT jsonb_path_query('[]', '$.type()');
1480+
----
1481+
"array"
1482+
1483+
query T
1484+
SELECT jsonb_path_query('"hello"', '$.type()');
1485+
----
1486+
"string"
1487+
1488+
query T
1489+
SELECT jsonb_path_query('0', '$.type()');
1490+
----
1491+
"number"
1492+
1493+
query T
1494+
SELECT jsonb_path_query('0.1', '$.type()');
1495+
----
1496+
"number"
1497+
1498+
query T
1499+
SELECT jsonb_path_query('true', '$.type()');
1500+
----
1501+
"boolean"
1502+
1503+
query T
1504+
SELECT jsonb_path_query('false', '$.type()');
1505+
----
1506+
"boolean"
1507+
1508+
query T
1509+
SELECT jsonb_path_query('null', '$.type()');
1510+
----
1511+
"null"
1512+
1513+
query T
1514+
SELECT jsonb_path_query('null', '"123".type()');
1515+
----
1516+
"string"
1517+
1518+
# TODO(#144258): should be "number", but the scanner doesn't scan this properly.
1519+
statement error pgcode 42601 pq: at or near \"trailing junk after numeric literal
1520+
SELECT jsonb_path_query('null', '(123).type()');
1521+
1522+
query T
1523+
SELECT jsonb_path_query('null', 'true.type()');
1524+
----
1525+
"boolean"
1526+
1527+
query T
1528+
SELECT jsonb_path_query('null', 'null.type()');
1529+
----
1530+
"null"
1531+
1532+
query T rowsort
1533+
SELECT jsonb_path_query('[null,1,true,"a",[],{}]', '$[*].type()');
1534+
----
1535+
"null"
1536+
"number"
1537+
"boolean"
1538+
"string"
1539+
"array"
1540+
"object"
1541+
1542+
query T
1543+
SELECT jsonb_path_query('[null,1,true,"a",[],{}]', 'lax $.type()');
1544+
----
1545+
"array"
1546+
1547+
statement error pgcode 22033 pq: jsonpath array subscript is not a single numeric value
1548+
SELECT jsonb_path_query('[1,2,3]', '$[last ? (@.type() == "string")]');
1549+
1550+
query T
1551+
SELECT jsonb_path_query('[1,2,3]', '$[last ? (@.type() == "number")]');
1552+
----
1553+
3

pkg/sql/logictest/testdata/logic_test/jsonpath

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,6 @@ SELECT '@'::JSONPATH
162162
statement error unimplemented
163163
SELECT '$ ? (@ like_regex ".*" flag "i")'::JSONPATH;
164164

165-
statement error unimplemented
166-
SELECT '$.type()'::JSONPATH;
167-
168165
statement error unimplemented
169166
SELECT '$.keyvalue()'::JSONPATH;
170167

pkg/util/jsonpath/eval/method.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ func (ctx *jsonpathCtx) evalMethod(
2626
return nil, err
2727
}
2828
return []json.JSON{json.FromInt(size)}, nil
29+
case jsonpath.TypeMethod:
30+
t := ctx.evalType(jsonValue)
31+
return []json.JSON{json.FromString(t)}, nil
2932
default:
3033
return nil, errUnimplemented
3134
}
@@ -40,3 +43,12 @@ func (ctx *jsonpathCtx) evalSize(jsonValue json.JSON) (int, error) {
4043
}
4144
return jsonValue.Len(), nil
4245
}
46+
47+
func (ctx *jsonpathCtx) evalType(jsonValue json.JSON) string {
48+
// When jsonValue is a number, json.Type.String() returns "numeric", but
49+
// postgres returns "number".
50+
if jsonValue.Type() == json.NumberJSONType {
51+
return "number"
52+
}
53+
return jsonValue.Type().String()
54+
}

pkg/util/jsonpath/method.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ type MethodType int
1212
const (
1313
InvalidMethod MethodType = iota
1414
SizeMethod
15+
TypeMethod
1516
)
1617

1718
var MethodTypeStrings = map[MethodType]string{
1819
SizeMethod: "size",
20+
TypeMethod: "type",
1921
}
2022

2123
type Method struct {

pkg/util/jsonpath/parser/jsonpath.y

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ method:
529529
}
530530
| TYPE
531531
{
532-
return unimplemented(jsonpathlex, ".type()")
532+
$$.val = jsonpath.Method{Type: jsonpath.TypeMethod}
533533
}
534534
| KEYVALUE
535535
{

pkg/util/jsonpath/parser/testdata/jsonpath

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,11 @@ parse
594594
----
595595
$."a".size() -- normalized!
596596

597+
parse
598+
$.a.type()
599+
----
600+
$."a".type() -- normalized!
601+
597602
# postgres allows floats as array indexes
598603
# parse
599604
# $.abc[1.0]

0 commit comments

Comments
 (0)