2222#include "jsquery.h"
2323
2424static ExtractedNode * recursiveExtract (JsQueryItem * jsq , bool not , bool indirect , PathItem * path );
25+ static ExtractedNode * makeAnyNode (bool not , bool indirect , PathItem * path );
2526static int coundChildren (ExtractedNode * node , ExtractedNodeType type , bool first , bool * found );
2627static void fillChildren (ExtractedNode * node , ExtractedNodeType type , bool first , ExtractedNode * * items , int * i );
2728static void flatternTree (ExtractedNode * node );
@@ -95,7 +96,8 @@ recursiveExtract(JsQueryItem *jsq, bool not, bool indirect, PathItem *path)
9596 pathItem -> type = iKey ;
9697 pathItem -> s = jsqGetString (jsq , & pathItem -> len );
9798 pathItem -> parent = path ;
98- jsqGetNext (jsq , & elem );
99+ if (!jsqGetNext (jsq , & elem ))
100+ return makeAnyNode (not , indirect , pathItem );
99101 return recursiveExtract (& elem , not , indirect , pathItem );
100102 case jqiAny :
101103 case jqiAll :
@@ -104,14 +106,16 @@ recursiveExtract(JsQueryItem *jsq, bool not, bool indirect, PathItem *path)
104106 pathItem = (PathItem * )palloc (sizeof (PathItem ));
105107 pathItem -> type = iAny ;
106108 pathItem -> parent = path ;
107- jsqGetNext (jsq , & elem );
109+ if (!jsqGetNext (jsq , & elem ))
110+ return makeAnyNode (not , indirect , pathItem );
108111 return recursiveExtract (& elem , not , true, pathItem );
109112 case jqiIndexArray :
110113 pathItem = (PathItem * )palloc (sizeof (PathItem ));
111114 pathItem -> type = iIndexArray ;
112115 pathItem -> arrayIndex = jsq -> arrayIndex ;
113116 pathItem -> parent = path ;
114- jsqGetNext (jsq , & elem );
117+ if (!jsqGetNext (jsq , & elem ))
118+ return makeAnyNode (not , indirect , pathItem );
115119 return recursiveExtract (& elem , not , true, pathItem );
116120 case jqiAnyArray :
117121 case jqiAllArray :
@@ -120,7 +124,8 @@ recursiveExtract(JsQueryItem *jsq, bool not, bool indirect, PathItem *path)
120124 pathItem = (PathItem * )palloc (sizeof (PathItem ));
121125 pathItem -> type = iAnyArray ;
122126 pathItem -> parent = path ;
123- jsqGetNext (jsq , & elem );
127+ if (!jsqGetNext (jsq , & elem ))
128+ return makeAnyNode (not , indirect , pathItem );
124129 return recursiveExtract (& elem , not , true, pathItem );
125130 case jqiAnyKey :
126131 case jqiAllKey :
@@ -129,12 +134,14 @@ recursiveExtract(JsQueryItem *jsq, bool not, bool indirect, PathItem *path)
129134 pathItem = (PathItem * )palloc (sizeof (PathItem ));
130135 pathItem -> type = iAnyKey ;
131136 pathItem -> parent = path ;
132- jsqGetNext (jsq , & elem );
137+ if (!jsqGetNext (jsq , & elem ))
138+ return makeAnyNode (not , indirect , pathItem );
133139 return recursiveExtract (& elem , not , true, pathItem );
134140 case jqiFilter :
135141 /* ignore filter for now */
136142 case jqiCurrent :
137- jsqGetNext (jsq , & elem );
143+ if (!jsqGetNext (jsq , & elem ))
144+ return makeAnyNode (not , indirect , path );
138145 return recursiveExtract (& elem , not , indirect , path );
139146 case jqiEqual :
140147 if (not )
@@ -264,6 +271,25 @@ recursiveExtract(JsQueryItem *jsq, bool not, bool indirect, PathItem *path)
264271 return NULL ;
265272}
266273
274+ /*
275+ * Make node for checking existence of path.
276+ */
277+ static ExtractedNode *
278+ makeAnyNode (bool not , bool indirect , PathItem * path )
279+ {
280+ ExtractedNode * result ;
281+
282+ if (not )
283+ return NULL ;
284+
285+ result = (ExtractedNode * ) palloc (sizeof (ExtractedNode ));
286+ result -> type = eAny ;
287+ result -> hint = false;
288+ result -> path = path ;
289+ result -> indirect = indirect ;
290+ return result ;
291+ }
292+
267293/*
268294 * Count number of children connected with nodes of same type.
269295 */
@@ -857,6 +883,11 @@ execRecursiveTristate(ExtractedNode *node, GinTernaryValue *check)
857883static void
858884debugPath (StringInfo buf , PathItem * path )
859885{
886+ if (!path )
887+ {
888+ appendStringInfoChar (buf , '$' );
889+ return ;
890+ }
860891 if (path -> parent )
861892 {
862893 debugPath (buf , path -> parent );
0 commit comments