2929
3030#include "jsquery.h"
3131
32- static bool recursiveExecute (JsQueryItem * jsq , JsonbValue * jb , JsQueryItem * jsqLeftArg );
32+ static bool recursiveExecute (JsQueryItem * jsq , JsonbValue * jb );
3333
3434static int
3535compareNumeric (Numeric a , Numeric b )
@@ -59,6 +59,43 @@ JsonbType(JsonbValue *jb)
5959 return type ;
6060}
6161
62+ static JsonbValue *
63+ JsonbSize (JsonbValue * jb , JsonbValue * size )
64+ {
65+ JsonbValue v ;
66+ JsonbIterator * it ;
67+ JsonbIteratorToken r ;
68+ int32 length ;
69+ int type = JsonbType (jb );
70+
71+ if (type != jbvArray && type != jbvObject )
72+ return NULL ;
73+
74+ Assert (jb -> type == jbvBinary );
75+
76+ it = JsonbIteratorInit (jb -> val .binary .data );
77+ r = JsonbIteratorNext (& it , & v , true);
78+ Assert (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT );
79+
80+ if (r == WJB_BEGIN_ARRAY )
81+ {
82+ length = v .val .array .nElems ;
83+ if (length < 0 )
84+ length = JsonGetArraySize (jb -> val .binary .data );
85+ }
86+ else
87+ {
88+ length = v .val .object .nPairs ;
89+ if (length < 0 )
90+ length = JsonGetObjectSize (jb -> val .binary .data );
91+ }
92+
93+ size -> type = jbvNumeric ;
94+ size -> val .numeric = DatumGetNumeric (DirectFunctionCall1 (
95+ int4_numeric , Int32GetDatum (length )));
96+ return size ;
97+ }
98+
6299static bool
63100recursiveAny (JsQueryItem * jsq , JsonbValue * jb )
64101{
@@ -81,7 +118,7 @@ recursiveAny(JsQueryItem *jsq, JsonbValue *jb)
81118
82119 if (r == WJB_VALUE || r == WJB_ELEM )
83120 {
84- res = recursiveExecute (jsq , & v , NULL );
121+ res = recursiveExecute (jsq , & v );
85122
86123 if (res == false && v .type == jbvBinary )
87124 res = recursiveAny (jsq , & v );
@@ -113,7 +150,7 @@ recursiveAll(JsQueryItem *jsq, JsonbValue *jb)
113150
114151 if (r == WJB_VALUE || r == WJB_ELEM )
115152 {
116- if ((res = recursiveExecute (jsq , & v , NULL )) == true)
153+ if ((res = recursiveExecute (jsq , & v )) == true)
117154 {
118155 if (v .type == jbvBinary )
119156 res = recursiveAll (jsq , & v );
@@ -312,7 +349,7 @@ makeCompare(JsQueryItem *jsq, int32 op, JsonbValue *jb)
312349}
313350
314351static bool
315- executeExpr (JsQueryItem * jsq , int32 op , JsonbValue * jb , JsQueryItem * jsqLeftArg )
352+ executeExpr (JsQueryItem * jsq , int32 op , JsonbValue * jb )
316353{
317354 bool res = false;
318355 /*
@@ -322,100 +359,37 @@ executeExpr(JsQueryItem *jsq, int32 op, JsonbValue *jb, JsQueryItem *jsqLeftArg)
322359 Assert (jsq -> type == jqiAny || jsq -> type == jqiString || jsq -> type == jqiNumeric ||
323360 jsq -> type == jqiNull || jsq -> type == jqiBool || jsq -> type == jqiArray );
324361
325- if ( jsqLeftArg && jsqLeftArg -> type == jqiLength )
362+ switch ( op )
326363 {
327- if (JsonbType (jb ) == jbvArray || JsonbType (jb ) == jbvObject )
328- {
329- int32 length ;
330- JsonbIterator * it ;
331- JsonbValue v ;
332- int r ;
333-
334- it = JsonbIteratorInit (jb -> val .binary .data );
335- r = JsonbIteratorNext (& it , & v , true);
336- Assert (r == WJB_BEGIN_ARRAY || r == WJB_BEGIN_OBJECT );
337-
338- if (r == WJB_BEGIN_ARRAY )
339- {
340- length = v .val .array .nElems ;
341-
342- if (length < 0 )
343- length = JsonGetArraySize (jb -> val .binary .data );
344- }
364+ case jqiEqual :
365+ if (JsonbType (jb ) == jbvArray && jsq -> type == jqiArray )
366+ res = checkArrayEquality (jsq , jb );
345367 else
346- {
347- length = v .val .object .nPairs ;
348-
349- if (length < 0 )
350- {
351- length = 0 ;
352-
353- while ((r = JsonbIteratorNext (& it , & v , true)) != WJB_DONE )
354- {
355- if (r == WJB_KEY )
356- length ++ ;
357- }
358- }
359- }
360-
361- v .type = jbvNumeric ;
362- v .val .numeric = DatumGetNumeric (DirectFunctionCall1 (int4_numeric , Int32GetDatum (length )));
363-
364- switch (op )
365- {
366- case jqiEqual :
367- case jqiLess :
368- case jqiGreater :
369- case jqiLessOrEqual :
370- case jqiGreaterOrEqual :
371- res = makeCompare (jsq , op , & v );
372- break ;
373- case jqiIn :
374- res = checkScalarIn (jsq , & v );
375- break ;
376- case jqiOverlap :
377- case jqiContains :
378- case jqiContained :
379- break ;
380- default :
381- elog (ERROR , "Unknown operation" );
382- }
383- }
384- }
385- else
386- {
387- switch (op )
388- {
389- case jqiEqual :
390- if (JsonbType (jb ) == jbvArray && jsq -> type == jqiArray )
391- res = checkArrayEquality (jsq , jb );
392- else
393- res = checkScalarEquality (jsq , jb );
394- break ;
395- case jqiIn :
396- res = checkScalarIn (jsq , jb );
397- break ;
398- case jqiOverlap :
399- case jqiContains :
400- case jqiContained :
401- res = executeArrayOp (jsq , op , jb );
402- break ;
403- case jqiLess :
404- case jqiGreater :
405- case jqiLessOrEqual :
406- case jqiGreaterOrEqual :
407- res = makeCompare (jsq , op , jb );
408- break ;
409- default :
410- elog (ERROR , "Unknown operation" );
411- }
368+ res = checkScalarEquality (jsq , jb );
369+ break ;
370+ case jqiIn :
371+ res = checkScalarIn (jsq , jb );
372+ break ;
373+ case jqiOverlap :
374+ case jqiContains :
375+ case jqiContained :
376+ res = executeArrayOp (jsq , op , jb );
377+ break ;
378+ case jqiLess :
379+ case jqiGreater :
380+ case jqiLessOrEqual :
381+ case jqiGreaterOrEqual :
382+ res = makeCompare (jsq , op , jb );
383+ break ;
384+ default :
385+ elog (ERROR , "Unknown operation" );
412386 }
413387
414388 return res ;
415389}
416390
417391static bool
418- recursiveExecute (JsQueryItem * jsq , JsonbValue * jb , JsQueryItem * jsqLeftArg )
392+ recursiveExecute (JsQueryItem * jsq , JsonbValue * jb )
419393{
420394 JsQueryItem elem ;
421395 bool res = false;
@@ -425,25 +399,25 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
425399 switch (jsq -> type ) {
426400 case jqiAnd :
427401 jsqGetLeftArg (jsq , & elem );
428- res = recursiveExecute (& elem , jb , jsqLeftArg );
402+ res = recursiveExecute (& elem , jb );
429403 if (res == true)
430404 {
431405 jsqGetRightArg (jsq , & elem );
432- res = recursiveExecute (& elem , jb , jsqLeftArg );
406+ res = recursiveExecute (& elem , jb );
433407 }
434408 break ;
435409 case jqiOr :
436410 jsqGetLeftArg (jsq , & elem );
437- res = recursiveExecute (& elem , jb , jsqLeftArg );
411+ res = recursiveExecute (& elem , jb );
438412 if (res == false)
439413 {
440414 jsqGetRightArg (jsq , & elem );
441- res = recursiveExecute (& elem , jb , jsqLeftArg );
415+ res = recursiveExecute (& elem , jb );
442416 }
443417 break ;
444418 case jqiNot :
445419 jsqGetArg (jsq , & elem );
446- res = !recursiveExecute (& elem , jb , jsqLeftArg );
420+ res = !recursiveExecute (& elem , jb );
447421 break ;
448422 case jqiKey :
449423 if (JsonbType (jb ) == jbvObject ) {
@@ -457,7 +431,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
457431 if (v != NULL )
458432 {
459433 jsqGetNext (jsq , & elem );
460- res = recursiveExecute (& elem , v , NULL );
434+ res = recursiveExecute (& elem , v );
461435 pfree (v );
462436 }
463437 }
@@ -480,23 +454,23 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
480454 r = JsonbIteratorNext (& it , & v , true);
481455 Assert (r == WJB_ELEM );
482456
483- res = recursiveExecute (& elem , & v , jsqLeftArg );
457+ res = recursiveExecute (& elem , & v );
484458 }
485459 else
486460 {
487- res = recursiveExecute (& elem , jb , jsqLeftArg );
461+ res = recursiveExecute (& elem , jb );
488462 }
489463 break ;
490464 case jqiAny :
491465 jsqGetNext (jsq , & elem );
492- if (recursiveExecute (& elem , jb , NULL ))
466+ if (recursiveExecute (& elem , jb ))
493467 res = true;
494468 else if (jb -> type == jbvBinary )
495469 res = recursiveAny (& elem , jb );
496470 break ;
497471 case jqiAll :
498472 jsqGetNext (jsq , & elem );
499- if ((res = recursiveExecute (& elem , jb , NULL )) == true)
473+ if ((res = recursiveExecute (& elem , jb )) == true)
500474 {
501475 if (jb -> type == jbvBinary )
502476 res = recursiveAll (& elem , jb );
@@ -520,7 +494,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
520494 {
521495 if (r == WJB_ELEM )
522496 {
523- res = recursiveExecute (& elem , & v , NULL );
497+ res = recursiveExecute (& elem , & v );
524498
525499 if (jsq -> type == jqiAnyArray )
526500 {
@@ -554,7 +528,7 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
554528 {
555529 if (r == WJB_VALUE )
556530 {
557- res = recursiveExecute (& elem , & v , NULL );
531+ res = recursiveExecute (& elem , & v );
558532
559533 if (jsq -> type == jqiAnyKey )
560534 {
@@ -580,12 +554,19 @@ recursiveExecute(JsQueryItem *jsq, JsonbValue *jb, JsQueryItem *jsqLeftArg)
580554 case jqiContained :
581555 case jqiOverlap :
582556 jsqGetArg (jsq , & elem );
583- res = executeExpr (& elem , jsq -> type , jb , jsqLeftArg );
557+ res = executeExpr (& elem , jsq -> type , jb );
584558 break ;
585559 case jqiLength :
560+ {
561+ JsonbValue size ;
586562 jsqGetNext (jsq , & elem );
587- res = recursiveExecute (& elem , jb , jsq );
563+ if (JsonbSize (jb , & size ))
564+ {
565+ res = recursiveExecute (& elem , & size );
566+ pfree (size .val .numeric );
567+ }
588568 break ;
569+ }
589570 case jqiIs :
590571 if (JsonbType (jb ) == jbvScalar )
591572 {
@@ -631,7 +612,7 @@ jsquery_json_exec(PG_FUNCTION_ARGS)
631612
632613 jsqInit (& jsq , jq );
633614
634- res = recursiveExecute (& jsq , & jbv , NULL );
615+ res = recursiveExecute (& jsq , & jbv );
635616
636617 PG_FREE_IF_COPY (jq , 0 );
637618 PG_FREE_IF_COPY_JSONB (jb , 1 );
@@ -653,7 +634,7 @@ json_jsquery_exec(PG_FUNCTION_ARGS)
653634
654635 jsqInit (& jsq , jq );
655636
656- res = recursiveExecute (& jsq , & jbv , NULL );
637+ res = recursiveExecute (& jsq , & jbv );
657638
658639 PG_FREE_IF_COPY_JSONB (jb , 0 );
659640 PG_FREE_IF_COPY (jq , 1 );
0 commit comments