@@ -33,14 +33,15 @@ typedef struct
3333
3434#define JSONB_VODKA_FLAG_VALUE 0x01
3535
36- #define JSONB_VODKA_FLAG_NULL 0x00
37- #define JSONB_VODKA_FLAG_STRING 0x02
38- #define JSONB_VODKA_FLAG_NUMERIC 0x04
39- #define JSONB_VODKA_FLAG_BOOL 0x06
40- #define JSONB_VODKA_FLAG_TYPE 0x06
41- #define JSONB_VODKA_FLAG_TRUE 0x08
42- #define JSONB_VODKA_FLAG_NAN 0x08
43- #define JSONB_VODKA_FLAG_NEGATIVE 0x10
36+ #define JSONB_VODKA_FLAG_NULL 0x00
37+ #define JSONB_VODKA_FLAG_STRING 0x02
38+ #define JSONB_VODKA_FLAG_NUMERIC 0x04
39+ #define JSONB_VODKA_FLAG_BOOL 0x06
40+ #define JSONB_VODKA_FLAG_EMPTY_ARRAY 0x08
41+ #define JSONB_VODKA_FLAG_EMPTY_OBJECT 0x0A
42+ #define JSONB_VODKA_FLAG_TYPE 0x0E
43+ #define JSONB_VODKA_FLAG_TRUE 0x10
44+ #define JSONB_VODKA_FLAG_NAN 0x10
4445
4546#define JSONB_VODKA_FLAG_ARRAY 0x02
4647
@@ -100,58 +101,6 @@ typedef struct PathStack
100101 struct PathStack * parent ;
101102} PathStack ;
102103
103- static int
104- get_ndigits (Numeric val )
105- {
106- const NumericDigit * digits ;
107- int ndigits ;
108-
109- ndigits = NUMERIC_NDIGITS (val );
110- digits = NUMERIC_DIGITS (val );
111-
112- while (ndigits > 0 && * digits == 0 )
113- {
114- ndigits -- ;
115- digits ++ ;
116- }
117- return ndigits ;
118- }
119-
120- static void
121- write_numeric_key (Pointer ptr , Numeric val )
122- {
123- * ptr = JSONB_VODKA_FLAG_VALUE | JSONB_VODKA_FLAG_NUMERIC ;
124- if (NUMERIC_IS_NAN (val ))
125- {
126- * ptr |= JSONB_VODKA_FLAG_NAN ;
127- }
128- else
129- {
130- const NumericDigit * digits = NUMERIC_DIGITS (val );
131- int ndigits = NUMERIC_NDIGITS (val );
132- int weight = NUMERIC_WEIGHT (val );
133- int sign = NUMERIC_SIGN (val );
134-
135- if (sign == NUMERIC_NEG )
136- * ptr |= JSONB_VODKA_FLAG_NEGATIVE ;
137- ptr ++ ;
138-
139- while (ndigits > 0 && * digits == 0 )
140- {
141- ndigits -- ;
142- digits ++ ;
143- }
144-
145- memcpy (ptr , & weight , sizeof (weight ));
146- ptr += sizeof (weight );
147-
148- memcpy (ptr , digits , sizeof (NumericDigit ) * ndigits );
149- ptr += sizeof (NumericDigit ) * ndigits ;
150-
151- * ptr = 0 ;
152- }
153- }
154-
155104static bytea *
156105get_vodka_key (PathStack * stack , const JsonbValue * val )
157106{
@@ -179,6 +128,8 @@ get_vodka_key(PathStack *stack, const JsonbValue *val)
179128 {
180129 case jbvNull :
181130 case jbvBool :
131+ case jbvObject :
132+ case jbvArray :
182133 vallen = 1 ;
183134 break ;
184135 case jbvString :
@@ -226,6 +177,12 @@ get_vodka_key(PathStack *stack, const JsonbValue *val)
226177 if (val -> val .boolean )
227178 * ptr |= JSONB_VODKA_FLAG_TRUE ;
228179 break ;
180+ case jbvArray :
181+ * ptr = JSONB_VODKA_FLAG_VALUE | JSONB_VODKA_FLAG_EMPTY_ARRAY ;
182+ break ;
183+ case jbvObject :
184+ * ptr = JSONB_VODKA_FLAG_VALUE | JSONB_VODKA_FLAG_EMPTY_OBJECT ;
185+ break ;
229186 case jbvString :
230187 * ptr = JSONB_VODKA_FLAG_VALUE | JSONB_VODKA_FLAG_STRING ;
231188 hash = hash_any ((unsigned char * )val -> val .string .val , val -> val .string .len );
@@ -302,11 +259,19 @@ static int
302259make_entry_handler (ExtractedNode * node , Pointer extra )
303260{
304261 Entries * e = (Entries * )extra ;
305- PathItem * item ;
262+ PathItem * item , * leaf = node -> path ;
306263 JsonbVodkaKey * key = (JsonbVodkaKey * )palloc (sizeof (JsonbVodkaKey ));
307264 int length = 0 , i ;
308265
309- item = node -> path ;
266+ if (!node -> bounds .inequality && node -> bounds .exact && node -> bounds .exact -> type == jqiAny )
267+ {
268+ item = (PathItem * )palloc (sizeof (PathItem ));
269+ item -> type = iAny ;
270+ item -> parent = leaf ;
271+ leaf = item ;
272+ }
273+
274+ item = leaf ;
310275 while (item )
311276 {
312277 length ++ ;
@@ -316,7 +281,7 @@ make_entry_handler(ExtractedNode *node, Pointer extra)
316281 key -> path = (PathItem * )palloc (sizeof (PathItem ) * length );
317282
318283 i = length - 1 ;
319- item = node -> path ;
284+ item = leaf ;
320285 while (item )
321286 {
322287 key -> path [i ] = * item ;
@@ -380,7 +345,17 @@ vodkajsonbextract(PG_FUNCTION_ARGS)
380345 switch (r )
381346 {
382347 case WJB_BEGIN_ARRAY :
348+ if (v .val .array .nElems == 0 )
349+ entries [i ++ ] = PointerGetDatum (get_vodka_key (stack , & v ));
350+ tmp = stack ;
351+ stack = (PathStack * ) palloc (sizeof (PathStack ));
352+ stack -> s = NULL ;
353+ stack -> len = 0 ;
354+ stack -> parent = tmp ;
355+ break ;
383356 case WJB_BEGIN_OBJECT :
357+ if (v .val .object .nPairs == 0 )
358+ entries [i ++ ] = PointerGetDatum (get_vodka_key (stack , & v ));
384359 tmp = stack ;
385360 stack = (PathStack * ) palloc (sizeof (PathStack ));
386361 stack -> s = NULL ;
0 commit comments