@@ -37,6 +37,7 @@ typedef struct
3737#define JSONB_VODKA_FLAG_STRING 0x02
3838#define JSONB_VODKA_FLAG_NUMERIC 0x04
3939#define JSONB_VODKA_FLAG_BOOL 0x06
40+ #define JSONB_VODKA_FLAG_TYPE 0x06
4041#define JSONB_VODKA_FLAG_TRUE 0x08
4142#define JSONB_VODKA_FLAG_NAN 0x08
4243#define JSONB_VODKA_FLAG_NEGATIVE 0x10
@@ -184,10 +185,7 @@ get_vodka_key(PathStack *stack, const JsonbValue *val)
184185vallen = 5 ;
185186break ;
186187case jbvNumeric :
187- if (NUMERIC_IS_NAN (val -> val .numeric ))
188- vallen = 1 ;
189- else
190- vallen = get_ndigits (val -> val .numeric )+ 6 ;
188+ vallen = 1 + VARSIZE_ANY (val -> val .numeric );
191189break ;
192190default :
193191elog (ERROR ,"invalid jsonb scalar type" );
@@ -234,8 +232,8 @@ get_vodka_key(PathStack *stack, const JsonbValue *val)
234232memcpy (ptr + 1 ,& hash ,sizeof (hash ));
235233break ;
236234case jbvNumeric :
237- * ptr = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_STRING ;
238- write_numeric_key (ptr ,val -> val .numeric );
235+ * ptr = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_NUMERIC ;
236+ memcpy (ptr + 1 ,val -> val .numeric , VARSIZE_ANY ( val -> val . numeric ) );
239237break ;
240238default :
241239elog (ERROR ,"invalid jsonb scalar type" );
@@ -244,116 +242,103 @@ get_vodka_key(PathStack *stack, const JsonbValue *val)
244242return result ;
245243}
246244
247- static int
248- make_entry_handler (ExtractedNode * node ,Pointer extra )
245+ typedef struct
249246{
250- Entries * e = (Entries * )extra ;
251- PathItem * item ;
252- int totallen = VARHDRSZ ,vallen ,jqPos ,len ;
253- Pointer ptr ;
254- JsQueryValue * value ;
255- Numeric numeric = NULL ;
256- char * jqBase ;
257- uint32 hash ;
258- bytea * result ;
259-
260- Assert (node -> type == eScalar );
261-
262- if (node -> bounds .inequality || node -> bounds .exact -> type == jqiAny )
263- return -1 ;
264-
265- item = node -> path ;
266- while (item )
267- {
268- if (item -> type == iKey )
269- totallen += item -> len + 2 ;
270- else if (item -> type == iAnyArray )
271- totallen += 1 ;
272- else
273- return -1 ;
274- item = item -> parent ;
275- }
247+ uint8 type ;
248+ uint32 hash ;
249+ Numeric n ;
250+ }JsonbVodkaValue ;
276251
277- value = node -> bounds .exact ;
278- switch (value -> type )
279- {
280- case jqiNull :
281- case jqiBool :
282- vallen = 1 ;
283- break ;
284- case jqiString :
285- vallen = 5 ;
286- break ;
287- case jqiNumeric :
288- numeric = (Numeric )(value -> jqBase + value -> jqPos );
289- if (NUMERIC_IS_NAN (numeric ))
290- vallen = 1 ;
291- else
292- vallen = get_ndigits (numeric )+ 6 ;
293- break ;
294- default :
295- elog (ERROR ,"Wrong state" );
296- }
252+ typedef struct
253+ {
254+ int pathLength ;
255+ PathItem * path ;
256+ JsonbVodkaValue * exact ,* leftBound ,* rightBound ;
257+ bool inequality ,leftInclusive ,rightInclusive ;
258+ }JsonbVodkaKey ;
259+
260+ static JsonbVodkaValue *
261+ make_vodka_value (JsQueryValue * value )
262+ {
263+ JsonbVodkaValue * result ;
264+ int32 len ,jqPos ;
265+ char * jqBase ;
297266
298- totallen += vallen ;
299- result = (bytea * )palloc (totallen );
300- SET_VARSIZE (result ,totallen );
301- ptr = (Pointer )result + totallen - vallen ;
267+ if (!value )
268+ return NULL ;
302269
303- item = node -> path ;
304- while (item )
305- {
306- if (item -> type == iKey )
307- {
308- ptr -= item -> len + 2 ;
309- ptr [0 ]= 0 ;
310- memcpy (ptr + 1 ,item -> s ,item -> len );
311- ptr [item -> len + 1 ]= 0 ;
312- }
313- else if (item -> type == iAnyArray )
314- {
315- ptr -- ;
316- * ptr = JSONB_VODKA_FLAG_ARRAY ;
317- }
318- else
319- {
320- return -1 ;
321- }
322- item = item -> parent ;
323- }
270+ result = (JsonbVodkaValue * )palloc (sizeof (JsonbVodkaValue ));
324271
325- ptr = (Pointer )result + totallen - vallen ;
326272jqBase = value -> jqBase ;
327273jqPos = value -> jqPos ;
328274
329275switch (value -> type )
330276{
331277case jbvNull :
332- * ptr = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_NULL ;
278+ result -> type = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_NULL ;
333279break ;
334280case jbvBool :
335- * ptr = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_BOOL ;
281+ result -> type = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_BOOL ;
336282read_byte (len ,jqBase ,jqPos );
337283if (len )
338- * ptr |=JSONB_VODKA_FLAG_TRUE ;
284+ result -> type |=JSONB_VODKA_FLAG_TRUE ;
339285break ;
340286case jbvString :
341- * ptr = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_STRING ;
287+ result -> type = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_STRING ;
342288read_int32 (len ,jqBase ,jqPos );
343- hash = hash_any ((unsignedchar * )jqBase + jqPos ,len );
344- memcpy (ptr + 1 ,& hash ,sizeof (hash ));
289+ result -> hash = hash_any ((unsignedchar * )jqBase + jqPos ,len );
345290break ;
346291case jbvNumeric :
347- * ptr = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_STRING ;
348- write_numeric_key ( ptr , numeric );
292+ result -> type = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_NUMERIC ;
293+ result -> n = ( Numeric )( jqBase + jqPos );
349294break ;
350295default :
351296elog (ERROR ,"invalid jsonb scalar type" );
352297}
353-
354- return add_entry (e ,PointerGetDatum (result ),NULL ,ByteaEqualOperator , false);
298+ return result ;
355299}
356300
301+ static int
302+ make_entry_handler (ExtractedNode * node ,Pointer extra )
303+ {
304+ Entries * e = (Entries * )extra ;
305+ PathItem * item ;
306+ JsonbVodkaKey * key = (JsonbVodkaKey * )palloc (sizeof (JsonbVodkaKey ));
307+ int length = 0 ,i ;
308+
309+ item = node -> path ;
310+ while (item )
311+ {
312+ length ++ ;
313+ item = item -> parent ;
314+ }
315+ key -> pathLength = length ;
316+ key -> path = (PathItem * )palloc (sizeof (PathItem )* length );
317+
318+ i = length - 1 ;
319+ item = node -> path ;
320+ while (item )
321+ {
322+ key -> path [i ]= * item ;
323+ i -- ;
324+ item = item -> parent ;
325+ }
326+
327+ key -> inequality = node -> bounds .inequality ;
328+ key -> leftInclusive = node -> bounds .leftInclusive ;
329+ key -> rightInclusive = node -> bounds .rightInclusive ;
330+ if (key -> inequality )
331+ {
332+ key -> leftBound = make_vodka_value (node -> bounds .leftBound );
333+ key -> rightBound = make_vodka_value (node -> bounds .rightBound );
334+ }
335+ else
336+ {
337+ key -> exact = make_vodka_value (node -> bounds .exact );
338+ }
339+
340+ return add_entry (e ,PointerGetDatum (key ),NULL ,VodkaMatchOperator , false);
341+ }
357342
358343/*
359344 * extractValue support function
@@ -474,15 +459,11 @@ vodkaqueryjsonbextract(PG_FUNCTION_ARGS)
474459keys [i ].extra = (Pointer )root ;
475460break ;
476461
477-
478- break ;
479-
480462default :
481463elog (ERROR ,"unrecognized strategy number: %d" ,strategy );
482464break ;
483465}
484466
485-
486467/* ...although "contains {}" requires a full index scan */
487468if (* nentries == 0 )
488469* searchMode = VODKA_SEARCH_MODE_ALL ;