@@ -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
100101struct 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{
180129case jbvNull :
181130case jbvBool :
131+ case jbvObject :
132+ case jbvArray :
182133vallen = 1 ;
183134break ;
184135case jbvString :
@@ -226,6 +177,12 @@ get_vodka_key(PathStack *stack, const JsonbValue *val)
226177if (val -> val .boolean )
227178* ptr |=JSONB_VODKA_FLAG_TRUE ;
228179break ;
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 ;
229186case jbvString :
230187* ptr = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_STRING ;
231188hash = hash_any ((unsignedchar * )val -> val .string .val ,val -> val .string .len );
@@ -302,11 +259,19 @@ static int
302259make_entry_handler (ExtractedNode * node ,Pointer extra )
303260{
304261Entries * e = (Entries * )extra ;
305- PathItem * item ;
262+ PathItem * item , * leaf = node -> path ;
306263JsonbVodkaKey * key = (JsonbVodkaKey * )palloc (sizeof (JsonbVodkaKey ));
307264int 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 ;
310275while (item )
311276{
312277length ++ ;
@@ -316,7 +281,7 @@ make_entry_handler(ExtractedNode *node, Pointer extra)
316281key -> path = (PathItem * )palloc (sizeof (PathItem )* length );
317282
318283i = length - 1 ;
319- item = node -> path ;
284+ item = leaf ;
320285while (item )
321286{
322287key -> path [i ]= * item ;
@@ -380,7 +345,17 @@ vodkajsonbextract(PG_FUNCTION_ARGS)
380345switch (r )
381346{
382347case 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 ;
383356case WJB_BEGIN_OBJECT :
357+ if (v .val .object .nPairs == 0 )
358+ entries [i ++ ]= PointerGetDatum (get_vodka_key (stack ,& v ));
384359tmp = stack ;
385360stack = (PathStack * )palloc (sizeof (PathStack ));
386361stack -> s = NULL ;