Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 94b866a

Browse files
author
Nikita Glukhov
committed
Add helper jsonb functions and macros
1 parent b16f961 commit 94b866a

File tree

3 files changed

+196
-7
lines changed

3 files changed

+196
-7
lines changed

src/backend/utils/adt/jsonb_util.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,22 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
388388
return NULL;
389389
}
390390

391+
/*
392+
* findJsonbValueFromContainer() wrapper that sets up JsonbValue key string.
393+
*/
394+
JsonbValue *
395+
findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags,
396+
const char *key, uint32 keylen)
397+
{
398+
JsonbValue k;
399+
400+
k.type = jbvString;
401+
k.val.string.val = key;
402+
k.val.string.len = keylen;
403+
404+
return findJsonbValueFromContainer(container, flags, &k);
405+
}
406+
391407
/*
392408
* Find value by key in Jsonb object and fetch it into 'res', which is also
393409
* returned.
@@ -602,6 +618,17 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
602618
return pushJsonbValueScalar(pstate, seq, jbval);
603619
}
604620

621+
/*
622+
* XXX I'm not quite sure why we actually do this? Why do we need to change
623+
* how JsonbValue is converted to Jsonb for the statistics patch?
624+
*/
625+
/* push value from scalar container without its enclosing array */
626+
if (*pstate && JsonbExtractScalar(jbval->val.binary.data, &v))
627+
{
628+
Assert(IsAJsonbScalar(&v));
629+
return pushJsonbValueScalar(pstate, seq, &v);
630+
}
631+
605632
/* unpack the binary and add each piece to the pstate */
606633
it = JsonbIteratorInit(jbval->val.binary.data);
607634

src/backend/utils/adt/jsonfuncs.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5371,7 +5371,8 @@ iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state,
53715371
if (type == WJB_KEY)
53725372
{
53735373
if (flags & jtiKey)
5374-
action(state, v.val.string.val, v.val.string.len);
5374+
action(state, unconstify(char *, v.val.string.val),
5375+
v.val.string.len);
53755376

53765377
continue;
53775378
}
@@ -5386,7 +5387,8 @@ iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state,
53865387
{
53875388
case jbvString:
53885389
if (flags & jtiString)
5389-
action(state, v.val.string.val, v.val.string.len);
5390+
action(state, unconstify(char *, v.val.string.val),
5391+
v.val.string.len);
53905392
break;
53915393
case jbvNumeric:
53925394
if (flags & jtiNumeric)
@@ -5508,7 +5510,9 @@ transform_jsonb_string_values(Jsonb *jsonb, void *action_state,
55085510
{
55095511
if ((type == WJB_VALUE || type == WJB_ELEM) && v.type == jbvString)
55105512
{
5511-
out = transform_action(action_state, v.val.string.val, v.val.string.len);
5513+
out = transform_action(action_state,
5514+
unconstify(char *, v.val.string.val),
5515+
v.val.string.len);
55125516
v.val.string.val = VARDATA_ANY(out);
55135517
v.val.string.len = VARSIZE_ANY_EXHDR(out);
55145518
res = pushJsonbValue(&st, type, type < WJB_BEGIN_ARRAY ? &v : NULL);

src/include/utils/jsonb.h

Lines changed: 162 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "lib/stringinfo.h"
1616
#include "utils/array.h"
17+
#include "utils/builtins.h"
1718
#include "utils/numeric.h"
1819

1920
/* Tokens used when sequentially processing a jsonb value */
@@ -229,8 +230,7 @@ typedef struct
229230
#define JB_ROOT_IS_OBJECT(jbp_) ((*(uint32 *) VARDATA(jbp_) & JB_FOBJECT) != 0)
230231
#define JB_ROOT_IS_ARRAY(jbp_) ((*(uint32 *) VARDATA(jbp_) & JB_FARRAY) != 0)
231232

232-
233-
enum jbvType
233+
typedef enum jbvType
234234
{
235235
/* Scalar types */
236236
jbvNull = 0x0,
@@ -250,7 +250,7 @@ enum jbvType
250250
* into JSON strings when outputted to json/jsonb.
251251
*/
252252
jbvDatetime = 0x20,
253-
};
253+
} JsonbValueType;
254254

255255
/*
256256
* JsonbValue: In-memory representation of Jsonb. This is a convenient
@@ -269,7 +269,7 @@ struct JsonbValue
269269
struct
270270
{
271271
int len;
272-
char *val; /* Not necessarily null-terminated */
272+
const char *val; /* Not necessarily null-terminated */
273273
} string; /* String primitive type */
274274

275275
struct
@@ -382,6 +382,10 @@ extern int compareJsonbContainers(JsonbContainer *a, JsonbContainer *b);
382382
extern JsonbValue *findJsonbValueFromContainer(JsonbContainer *sheader,
383383
uint32 flags,
384384
JsonbValue *key);
385+
extern JsonbValue *findJsonbValueFromContainerLen(JsonbContainer *container,
386+
uint32 flags,
387+
const char *key,
388+
uint32 keylen);
385389
extern JsonbValue *getKeyJsonValueFromContainer(JsonbContainer *container,
386390
const char *keyVal, int keyLen,
387391
JsonbValue *res);
@@ -399,6 +403,7 @@ extern bool JsonbDeepContains(JsonbIterator **val,
399403
extern void JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash);
400404
extern void JsonbHashScalarValueExtended(const JsonbValue *scalarVal,
401405
uint64 *hash, uint64 seed);
406+
extern bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res);
402407

403408
/* jsonb.c support functions */
404409
extern char *JsonbToCString(StringInfo out, JsonbContainer *in,
@@ -412,4 +417,157 @@ extern Datum jsonb_set_element(Jsonb *jb, Datum *path, int path_len,
412417
JsonbValue *newval);
413418
extern Datum jsonb_get_element(Jsonb *jb, Datum *path, int npath,
414419
bool *isnull, bool as_text);
420+
421+
/*
422+
* XXX Not sure we want to add these functions to jsonb.h, which is the
423+
* public API. Maybe it belongs rather to jsonb_typanalyze.c or elsewhere,
424+
* closer to how it's used?
425+
*/
426+
427+
/* helper inline functions for JsonbValue initialization */
428+
static inline JsonbValue *
429+
JsonValueInitObject(JsonbValue *val, int nPairs, int nPairsAllocated)
430+
{
431+
val->type = jbvObject;
432+
val->val.object.nPairs = nPairs;
433+
val->val.object.pairs = nPairsAllocated ?
434+
palloc(sizeof(JsonbPair) * nPairsAllocated) : NULL;
435+
436+
return val;
437+
}
438+
439+
static inline JsonbValue *
440+
JsonValueInitArray(JsonbValue *val, int nElems, int nElemsAllocated,
441+
bool rawScalar)
442+
{
443+
val->type = jbvArray;
444+
val->val.array.nElems = nElems;
445+
val->val.array.elems = nElemsAllocated ?
446+
palloc(sizeof(JsonbValue) * nElemsAllocated) : NULL;
447+
val->val.array.rawScalar = rawScalar;
448+
449+
return val;
450+
}
451+
452+
static inline JsonbValue *
453+
JsonValueInitBinary(JsonbValue *val, Jsonb *jb)
454+
{
455+
val->type = jbvBinary;
456+
val->val.binary.data = &(jb)->root;
457+
val->val.binary.len = VARSIZE_ANY_EXHDR(jb);
458+
return val;
459+
}
460+
461+
462+
static inline JsonbValue *
463+
JsonValueInitString(JsonbValue *jbv, const char *str)
464+
{
465+
jbv->type = jbvString;
466+
jbv->val.string.len = strlen(str);
467+
jbv->val.string.val = memcpy(palloc(jbv->val.string.len + 1), str,
468+
jbv->val.string.len + 1);
469+
return jbv;
470+
}
471+
472+
static inline JsonbValue *
473+
JsonValueInitStringWithLen(JsonbValue *jbv, const char *str, int len)
474+
{
475+
jbv->type = jbvString;
476+
jbv->val.string.val = str;
477+
jbv->val.string.len = len;
478+
return jbv;
479+
}
480+
481+
static inline JsonbValue *
482+
JsonValueInitText(JsonbValue *jbv, text *txt)
483+
{
484+
jbv->type = jbvString;
485+
jbv->val.string.val = VARDATA_ANY(txt);
486+
jbv->val.string.len = VARSIZE_ANY_EXHDR(txt);
487+
return jbv;
488+
}
489+
490+
static inline JsonbValue *
491+
JsonValueInitNumeric(JsonbValue *jbv, Numeric num)
492+
{
493+
jbv->type = jbvNumeric;
494+
jbv->val.numeric = num;
495+
return jbv;
496+
}
497+
498+
static inline JsonbValue *
499+
JsonValueInitInteger(JsonbValue *jbv, int64 i)
500+
{
501+
jbv->type = jbvNumeric;
502+
jbv->val.numeric = DatumGetNumeric(DirectFunctionCall1(
503+
int8_numeric, Int64GetDatum(i)));
504+
return jbv;
505+
}
506+
507+
static inline JsonbValue *
508+
JsonValueInitFloat(JsonbValue *jbv, float4 f)
509+
{
510+
jbv->type = jbvNumeric;
511+
jbv->val.numeric = DatumGetNumeric(DirectFunctionCall1(
512+
float4_numeric, Float4GetDatum(f)));
513+
return jbv;
514+
}
515+
516+
static inline JsonbValue *
517+
JsonValueInitDouble(JsonbValue *jbv, float8 f)
518+
{
519+
jbv->type = jbvNumeric;
520+
jbv->val.numeric = DatumGetNumeric(DirectFunctionCall1(
521+
float8_numeric, Float8GetDatum(f)));
522+
return jbv;
523+
}
524+
525+
/* helper macros for jsonb building */
526+
#define pushJsonbKey(pstate, jbv, key) \
527+
pushJsonbValue(pstate, WJB_KEY, JsonValueInitString(jbv, key))
528+
529+
#define pushJsonbValueGeneric(Type, pstate, jbv, val) \
530+
pushJsonbValue(pstate, WJB_VALUE, JsonValueInit##Type(jbv, val))
531+
532+
#define pushJsonbElemGeneric(Type, pstate, jbv, val) \
533+
pushJsonbValue(pstate, WJB_ELEM, JsonValueInit##Type(jbv, val))
534+
535+
#define pushJsonbValueInteger(pstate, jbv, i) \
536+
pushJsonbValueGeneric(Integer, pstate, jbv, i)
537+
538+
#define pushJsonbValueFloat(pstate, jbv, f) \
539+
pushJsonbValueGeneric(Float, pstate, jbv, f)
540+
541+
#define pushJsonbElemFloat(pstate, jbv, f) \
542+
pushJsonbElemGeneric(Float, pstate, jbv, f)
543+
544+
#define pushJsonbElemString(pstate, jbv, txt) \
545+
pushJsonbElemGeneric(String, pstate, jbv, txt)
546+
547+
#define pushJsonbElemText(pstate, jbv, txt) \
548+
pushJsonbElemGeneric(Text, pstate, jbv, txt)
549+
550+
#define pushJsonbElemNumeric(pstate, jbv, num) \
551+
pushJsonbElemGeneric(Numeric, pstate, jbv, num)
552+
553+
#define pushJsonbElemInteger(pstate, jbv, num) \
554+
pushJsonbElemGeneric(Integer, pstate, jbv, num)
555+
556+
#define pushJsonbElemBinary(pstate, jbv, jbcont) \
557+
pushJsonbElemGeneric(Binary, pstate, jbv, jbcont)
558+
559+
#define pushJsonbKeyValueGeneric(Type, pstate, jbv, key, val) ( \
560+
pushJsonbKey(pstate, jbv, key), \
561+
pushJsonbValueGeneric(Type, pstate, jbv, val) \
562+
)
563+
564+
#define pushJsonbKeyValueString(pstate, jbv, key, val) \
565+
pushJsonbKeyValueGeneric(String, pstate, jbv, key, val)
566+
567+
#define pushJsonbKeyValueFloat(pstate, jbv, key, val) \
568+
pushJsonbKeyValueGeneric(Float, pstate, jbv, key, val)
569+
570+
#define pushJsonbKeyValueInteger(pstate, jbv, key, val) \
571+
pushJsonbKeyValueGeneric(Integer, pstate, jbv, key, val)
572+
415573
#endif /* __JSONB_H__ */

0 commit comments

Comments
 (0)