@@ -383,8 +383,8 @@ executeExpr(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb)
383
383
}
384
384
385
385
static JsonPathExecResult
386
- executeArithmExpr (JsonPathExecContext * cxt , JsonPathItem * jsp , JsonbValue * jb ,
387
- List * * found )
386
+ executeBinaryArithmExpr (JsonPathExecContext * cxt , JsonPathItem * jsp ,
387
+ JsonbValue * jb , List * * found )
388
388
{
389
389
JsonPathExecResult jper ;
390
390
JsonPathItem elem ;
@@ -398,29 +398,18 @@ executeArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
398
398
Datum rdatum ;
399
399
Datum res ;
400
400
401
- if (jsp -> type == jpiMinus )
402
- jspGetArg (jsp , & elem );
403
- else
404
- jspGetLeftArg (jsp , & elem );
401
+ jspGetLeftArg (jsp , & elem );
405
402
406
403
jper = recursiveExecute (cxt , & elem , jb , & lseq );
407
404
408
- if (jper == jperOk && jsp -> type != jpiMinus )
405
+ if (jper == jperOk )
409
406
{
410
407
jspGetRightArg (jsp , & elem );
411
408
jper = recursiveExecute (cxt , & elem , jb , & rseq );
412
409
}
413
410
414
- if (jsp -> type == jpiMinus )
415
- {
416
- if (jper != jperOk || list_length (lseq ) != 1 )
417
- return jperError ; /* ERRCODE_SINGLETON_JSON_ITEM_REQUIRED; */
418
- }
419
- else
420
- {
421
- if (jper != jperOk || list_length (lseq ) != 1 || list_length (rseq ) != 1 )
422
- return jperError ; /* ERRCODE_SINGLETON_JSON_ITEM_REQUIRED; */
423
- }
411
+ if (jper != jperOk || list_length (lseq ) != 1 || list_length (rseq ) != 1 )
412
+ return jperError ; /* ERRCODE_SINGLETON_JSON_ITEM_REQUIRED; */
424
413
425
414
lval = linitial (lseq );
426
415
@@ -430,29 +419,22 @@ executeArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
430
419
if (lval -> type != jbvNumeric )
431
420
return jperError ; /* ERRCODE_SINGLETON_JSON_ITEM_REQUIRED; */
432
421
433
- if (jsp -> type != jpiMinus )
434
- {
435
- rval = linitial (rseq );
422
+ rval = linitial (rseq );
436
423
437
- if (JsonbType (rval ) == jbvScalar )
438
- rval = JsonbExtractScalar (rval -> val .binary .data , & rvalbuf );
424
+ if (JsonbType (rval ) == jbvScalar )
425
+ rval = JsonbExtractScalar (rval -> val .binary .data , & rvalbuf );
439
426
440
- if (rval -> type != jbvNumeric )
441
- return jperError ; /* ERRCODE_SINGLETON_JSON_ITEM_REQUIRED; */
442
- }
427
+ if (rval -> type != jbvNumeric )
428
+ return jperError ; /* ERRCODE_SINGLETON_JSON_ITEM_REQUIRED; */
443
429
444
430
if (!found )
445
431
return jperOk ;
446
432
447
433
ldatum = NumericGetDatum (lval -> val .numeric );
448
- if (jsp -> type != jpiMinus )
449
- rdatum = NumericGetDatum (rval -> val .numeric );
434
+ rdatum = NumericGetDatum (rval -> val .numeric );
450
435
451
436
switch (jsp -> type )
452
437
{
453
- case jpiMinus :
454
- res = DirectFunctionCall1 (numeric_uminus , ldatum );
455
- break ;
456
438
case jpiAdd :
457
439
res = DirectFunctionCall2 (numeric_add , ldatum , rdatum );
458
440
break ;
@@ -481,7 +463,7 @@ executeArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
481
463
return jperOk ;
482
464
}
483
465
484
- static JsonbValue *
466
+ static JsonbValue *
485
467
copyJsonbValue (JsonbValue * src )
486
468
{
487
469
JsonbValue * dst = palloc (sizeof (* dst ));
@@ -491,6 +473,65 @@ copyJsonbValue(JsonbValue *src)
491
473
return dst ;
492
474
}
493
475
476
+ static JsonPathExecResult
477
+ executeUnaryArithmExpr (JsonPathExecContext * cxt , JsonPathItem * jsp ,
478
+ JsonbValue * jb , List * * found )
479
+ {
480
+ JsonPathExecResult jper ;
481
+ JsonPathItem elem ;
482
+ List * seq = NIL ;
483
+ ListCell * lc ;
484
+
485
+ jspGetArg (jsp , & elem );
486
+ jper = recursiveExecute (cxt , & elem , jb , & seq );
487
+
488
+ if (jper == jperError )
489
+ return jperError ; /* ERRCODE_JSON_NUMBER_NOT_FOUND; */
490
+
491
+ jper = jperNotFound ;
492
+
493
+ foreach (lc , seq )
494
+ {
495
+ JsonbValue * val = lfirst (lc );
496
+ JsonbValue valbuf ;
497
+
498
+ if (JsonbType (val ) == jbvScalar )
499
+ val = JsonbExtractScalar (val -> val .binary .data , & valbuf );
500
+
501
+ if (val -> type == jbvNumeric )
502
+ {
503
+ jper = jperOk ;
504
+
505
+ if (!found )
506
+ return jper ;
507
+ }
508
+ else if (!found )
509
+ continue ; /* skip non-numerics processing */
510
+
511
+ if (val -> type != jbvNumeric )
512
+ return jperError ; /* ERRCODE_JSON_NUMBER_NOT_FOUND; */
513
+
514
+ val = copyJsonbValue (val );
515
+
516
+ switch (jsp -> type )
517
+ {
518
+ case jpiPlus :
519
+ break ;
520
+ case jpiMinus :
521
+ val -> val .numeric =
522
+ DatumGetNumeric (DirectFunctionCall1 (
523
+ numeric_uminus , NumericGetDatum (val -> val .numeric )));
524
+ break ;
525
+ default :
526
+ elog (ERROR , "unknown jsonpath arithmetic operation %d" , jsp -> type );
527
+ }
528
+
529
+ * found = lappend (* found , val );
530
+ }
531
+
532
+ return jper ;
533
+ }
534
+
494
535
static JsonPathExecResult
495
536
recursiveAny (JsonPathExecContext * cxt , JsonPathItem * jsp , JsonbValue * jb ,
496
537
List * * found , uint32 level , uint32 first , uint32 last )
@@ -792,8 +833,11 @@ recursiveExecute(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
792
833
case jpiMul :
793
834
case jpiDiv :
794
835
case jpiMod :
836
+ res = executeBinaryArithmExpr (cxt , jsp , jb , found );
837
+ break ;
838
+ case jpiPlus :
795
839
case jpiMinus :
796
- res = executeArithmExpr (cxt , jsp , jb , found );
840
+ res = executeUnaryArithmExpr (cxt , jsp , jb , found );
797
841
break ;
798
842
case jpiRoot :
799
843
if (jspGetNext (jsp , & elem ))
0 commit comments