@@ -37,6 +37,7 @@ typedef struct
37
37
#define JSONB_VODKA_FLAG_STRING 0x02
38
38
#define JSONB_VODKA_FLAG_NUMERIC 0x04
39
39
#define JSONB_VODKA_FLAG_BOOL 0x06
40
+ #define JSONB_VODKA_FLAG_TYPE 0x06
40
41
#define JSONB_VODKA_FLAG_TRUE 0x08
41
42
#define JSONB_VODKA_FLAG_NAN 0x08
42
43
#define JSONB_VODKA_FLAG_NEGATIVE 0x10
@@ -184,10 +185,7 @@ get_vodka_key(PathStack *stack, const JsonbValue *val)
184
185
vallen = 5 ;
185
186
break ;
186
187
case 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 );
191
189
break ;
192
190
default :
193
191
elog (ERROR ,"invalid jsonb scalar type" );
@@ -234,8 +232,8 @@ get_vodka_key(PathStack *stack, const JsonbValue *val)
234
232
memcpy (ptr + 1 ,& hash ,sizeof (hash ));
235
233
break ;
236
234
case 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 ) );
239
237
break ;
240
238
default :
241
239
elog (ERROR ,"invalid jsonb scalar type" );
@@ -244,116 +242,103 @@ get_vodka_key(PathStack *stack, const JsonbValue *val)
244
242
return result ;
245
243
}
246
244
247
- static int
248
- make_entry_handler (ExtractedNode * node ,Pointer extra )
245
+ typedef struct
249
246
{
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 ;
276
251
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 ;
297
266
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 ;
302
269
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 ));
324
271
325
- ptr = (Pointer )result + totallen - vallen ;
326
272
jqBase = value -> jqBase ;
327
273
jqPos = value -> jqPos ;
328
274
329
275
switch (value -> type )
330
276
{
331
277
case jbvNull :
332
- * ptr = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_NULL ;
278
+ result -> type = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_NULL ;
333
279
break ;
334
280
case jbvBool :
335
- * ptr = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_BOOL ;
281
+ result -> type = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_BOOL ;
336
282
read_byte (len ,jqBase ,jqPos );
337
283
if (len )
338
- * ptr |=JSONB_VODKA_FLAG_TRUE ;
284
+ result -> type |=JSONB_VODKA_FLAG_TRUE ;
339
285
break ;
340
286
case jbvString :
341
- * ptr = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_STRING ;
287
+ result -> type = JSONB_VODKA_FLAG_VALUE |JSONB_VODKA_FLAG_STRING ;
342
288
read_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 );
345
290
break ;
346
291
case 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 );
349
294
break ;
350
295
default :
351
296
elog (ERROR ,"invalid jsonb scalar type" );
352
297
}
353
-
354
- return add_entry (e ,PointerGetDatum (result ),NULL ,ByteaEqualOperator , false);
298
+ return result ;
355
299
}
356
300
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
+ }
357
342
358
343
/*
359
344
* extractValue support function
@@ -474,15 +459,11 @@ vodkaqueryjsonbextract(PG_FUNCTION_ARGS)
474
459
keys [i ].extra = (Pointer )root ;
475
460
break ;
476
461
477
-
478
- break ;
479
-
480
462
default :
481
463
elog (ERROR ,"unrecognized strategy number: %d" ,strategy );
482
464
break ;
483
465
}
484
466
485
-
486
467
/* ...although "contains {}" requires a full index scan */
487
468
if (* nentries == 0 )
488
469
* searchMode = VODKA_SEARCH_MODE_ALL ;