Skip to content

Commit 5a6a8b1

Browse files
committed
jsonpath: update error handling for undefined variable errors
This commit updates error handling logic for undefined variable errors within JSONPath queries. Instead of silencing all errors into jsonpathBoolUnknown in evalPredicate, we explicitly check if it's the variable not found error. Additionally, this commit also allows for assertion failures to be not silenced when passed to evalPredicate. Release note: None
1 parent 82f46d5 commit 5a6a8b1

File tree

4 files changed

+64
-8
lines changed

4 files changed

+64
-8
lines changed

pkg/sql/logictest/testdata/logic_test/jsonb_path_query

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,3 +1600,43 @@ query T
16001600
SELECT jsonb_path_query('[1, 2, 3]', '$[-0.99999999]');
16011601
----
16021602
1
1603+
1604+
statement error pgcode 42704 pq: could not find jsonpath variable "value"
1605+
SELECT jsonb_path_query('{"a": 10}', '$ ? (@.a < $value)');
1606+
1607+
statement error pgcode 42704 pq: could not find jsonpath variable "value"
1608+
SELECT jsonb_path_query('{"a": 10}', '$ ? (@.a < $value)', '{}');
1609+
1610+
statement error pgcode 42704 pq: could not find jsonpath variable "value"
1611+
SELECT jsonb_path_query('{"a": 10}', '$ ? (@.a < $value)', '{"other": 10}');
1612+
1613+
query T
1614+
SELECT jsonb_path_query('{"a": 10}', '$ ? (@.a < $value)', '{"value": 11}');
1615+
----
1616+
{"a": 10}
1617+
1618+
statement error pgcode 42704 pq: could not find jsonpath variable "value"
1619+
SELECT jsonb_path_query('{"a": 10, "b": 20}', '$ ? (@.a < $value && @.b > $value)');
1620+
1621+
statement error pgcode 42704 pq: could not find jsonpath variable "min"
1622+
SELECT jsonb_path_query('{"a": 10, "b": 20}', '$ ? (@.a < $min && @.b > $max)');
1623+
1624+
statement error pgcode 42704 pq: could not find jsonpath variable "value"
1625+
SELECT jsonb_path_query('{"a": 10}', 'strict $ ? (@.a < $value)', '{}', true);
1626+
1627+
statement error pgcode 42704 pq: could not find jsonpath variable "value"
1628+
SELECT jsonb_path_query('{"a": 10}', 'strict $ ? (@.a < $value)', '{}', false);
1629+
1630+
statement error pgcode 42704 pq: could not find jsonpath variable "value"
1631+
SELECT jsonb_path_query('{"a": 10}', '$ ? (@.a < $value)', '{}', true);
1632+
1633+
statement error pgcode 42704 pq: could not find jsonpath variable "value"
1634+
SELECT jsonb_path_query('{"a": 10}', '$ ? (@.a < $value)', '{}', false);
1635+
1636+
statement error pgcode 42704 pq: could not find jsonpath variable "d"
1637+
SELECT jsonb_path_query('{}', '$ ? ($d < $a && @.c > $b)');
1638+
1639+
query T
1640+
SELECT jsonb_path_query('{"a": 10}', '$ ? ((@.a < 12) || (@.a < $value))');
1641+
----
1642+
{"a": 10}

pkg/util/jsonpath/eval/filter.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,8 @@ func (ctx *jsonpathCtx) evalFilter(
2424
}
2525
b, err := ctx.evalBoolean(op, jsonValue)
2626
if err != nil {
27-
// Postgres doesn't error when there's a structure error within filter
28-
// conditions, and will return nothing instead.
29-
return nil, nil //nolint:returnerrcheck
27+
return nil, err
3028
}
31-
3229
if b == jsonpathBoolTrue {
3330
return []json.JSON{jsonValue}, nil
3431
}

pkg/util/jsonpath/eval/operation.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func (ctx *jsonpathCtx) evalIsUnknown(
129129
}
130130
leftBool, err := ctx.evalBoolean(leftOp, jsonValue)
131131
if err != nil {
132-
return jsonpathBoolUnknown, errors.AssertionFailedf("left is not a boolean")
132+
return jsonpathBoolUnknown, err
133133
}
134134
if leftBool == jsonpathBoolUnknown {
135135
return jsonpathBoolTrue, nil
@@ -204,7 +204,7 @@ func (ctx *jsonpathCtx) evalLogical(
204204
}
205205
leftBool, err := ctx.evalBoolean(leftOp, jsonValue)
206206
if err != nil {
207-
return jsonpathBoolUnknown, errors.AssertionFailedf("left is not a boolean")
207+
return jsonpathBoolUnknown, err
208208
}
209209
switch op.Type {
210210
case jsonpath.OpLogicalAnd:
@@ -233,7 +233,7 @@ func (ctx *jsonpathCtx) evalLogical(
233233
}
234234
rightBool, err := ctx.evalBoolean(rightOp, jsonValue)
235235
if err != nil {
236-
return jsonpathBoolUnknown, errors.AssertionFailedf("right is not a boolean")
236+
return jsonpathBoolUnknown, err
237237
}
238238
switch op.Type {
239239
case jsonpath.OpLogicalAnd:
@@ -251,6 +251,10 @@ func (ctx *jsonpathCtx) evalLogical(
251251
}
252252
}
253253

254+
func isIgnorableError(err error) bool {
255+
return err == nil || (!errors.HasAssertionFailure(err) && !errors.Is(err, &errVariableNotFound{}))
256+
}
257+
254258
// evalPredicate evaluates a predicate operation. Predicates have existence
255259
// semantics. True is returned if any pair of items from the left and right
256260
// paths satisfy the condition. In strict mode, even if a pair has been found,
@@ -263,13 +267,19 @@ func (ctx *jsonpathCtx) evalPredicate(
263267
) (jsonpathBool, error) {
264268
// The left argument results are always auto-unwrapped.
265269
left, err := ctx.evalAndUnwrapResult(op.Left, jsonValue, true /* unwrap */)
270+
if !isIgnorableError(err) {
271+
return jsonpathBoolUnknown, err
272+
}
266273
if err != nil || left == nil {
267274
return jsonpathBoolUnknown, nil //nolint:returnerrcheck
268275
}
269276
var right []json.JSON
270277
if evalRight {
271278
// The right argument results are conditionally evaluated and unwrapped.
272279
right, err = ctx.evalAndUnwrapResult(op.Right, jsonValue, unwrapRight)
280+
if !isIgnorableError(err) {
281+
return jsonpathBoolUnknown, err
282+
}
273283
if err != nil || right == nil {
274284
return jsonpathBoolUnknown, nil //nolint:returnerrcheck
275285
}

pkg/util/jsonpath/eval/scalar.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,25 @@ import (
1010
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
1111
"github.com/cockroachdb/cockroach/pkg/util/json"
1212
"github.com/cockroachdb/cockroach/pkg/util/jsonpath"
13+
"github.com/cockroachdb/errors"
1314
)
1415

16+
type errVariableNotFound struct{}
17+
18+
func (e *errVariableNotFound) Error() string {
19+
return ""
20+
}
21+
1522
func (ctx *jsonpathCtx) resolveScalar(scalar jsonpath.Scalar) (json.JSON, error) {
1623
if scalar.Type == jsonpath.ScalarVariable {
1724
val, err := ctx.vars.FetchValKey(scalar.Variable)
1825
if err != nil {
1926
return nil, err
2027
}
2128
if val == nil {
22-
return nil, pgerror.Newf(pgcode.UndefinedObject, "could not find jsonpath variable %q", scalar.Variable)
29+
return nil, errors.Mark(pgerror.Newf(pgcode.UndefinedObject,
30+
"could not find jsonpath variable %q", scalar.Variable),
31+
&errVariableNotFound{})
2332
}
2433
return val, nil
2534
}

0 commit comments

Comments
 (0)