#include "utils/jsonb.h"
static inline Datum deserialize_json_text(char *json, int len);
+static void jsonb_put_escaped_value(StringInfo out, JsonbValue *v);
+static void jsonb_in_scalar(void *state, char *token, JsonTokenType tokentype);
+typedef struct JsonbInState
+{
+ ToJsonbState *state;
+ JsonbValue *res;
+} JsonbInState;
static size_t
checkStringLen(size_t len)
return len;
}
-typedef struct JsonbInState
-{
- ToJsonbState *state;
- JsonbValue *res;
-} JsonbInState;
-
-
-/*
- * for jsonb we always want the de-escaped value - that's what's in token
- */
-static void
-jsonb_in_scalar(void *state, char *token, JsonTokenType tokentype)
-{
- JsonbInState *_state = (JsonbInState *) state;
- JsonbValue v;
-
- v.size = sizeof(JEntry);
-
- switch (tokentype)
- {
-
- case JSON_TOKEN_STRING:
- v.type = jbvString;
- v.string.len = token ? checkStringLen(strlen(token)) : 0;
- v.string.val = token ? pnstrdup(token, v.string.len) : NULL;
- v.size += v.string.len;
- break;
- case JSON_TOKEN_NUMBER:
- v.type = jbvNumeric;
- v.numeric = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(token), 0, -1));
-
- v.size += VARSIZE_ANY(v.numeric) + sizeof(JEntry) /* alignment */ ;
- break;
- case JSON_TOKEN_TRUE:
- v.type = jbvBool;
- v.boolean = true;
- break;
- case JSON_TOKEN_FALSE:
- v.type = jbvBool;
- v.boolean = false;
- break;
- case JSON_TOKEN_NULL:
- v.type = jbvNull;
- break;
- default:
- /* nothing else should be here in fact */
- Assert(false);
- break;
- }
-
- if (_state->state == NULL)
- {
- /* single scalar */
- JsonbValue va;
-
- va.type = jbvArray;
- va.array.scalar = true;
- va.array.nelems = 1;
-
- _state->res = pushJsonbValue(&_state->state, WJB_BEGIN_ARRAY, &va);
- _state->res = pushJsonbValue(&_state->state, WJB_ELEM, &v);
- _state->res = pushJsonbValue(&_state->state, WJB_END_ARRAY, NULL);
- }
- else
- {
- JsonbValue *o = &_state->state->v;
-
- switch (o->type)
- {
- case jbvArray:
- _state->res = pushJsonbValue(&_state->state, WJB_ELEM, &v);
- break;
- case jbvHash:
- _state->res = pushJsonbValue(&_state->state, WJB_VALUE, &v);
- break;
- default:
- elog(ERROR, "unexpected parent of nested structure");
- }
- }
-}
-
static void
jsonb_in_object_start(void *state)
{
_state->res = pushJsonbValue(&_state->state, WJB_KEY, &v);
}
+static void
+jsonb_put_escaped_value(StringInfo out, JsonbValue *v)
+{
+ switch (v->type)
+ {
+ case jbvNull:
+ appendBinaryStringInfo(out, "null", 4);
+ break;
+ case jbvString:
+ escape_json(out, pnstrdup(v->string.val, v->string.len));
+ break;
+ case jbvBool:
+ if (v->boolean)
+ appendBinaryStringInfo(out, "true", 4);
+ else
+ appendBinaryStringInfo(out, "false", 5);
+ break;
+ case jbvNumeric:
+ appendStringInfoString(out, DatumGetCString(DirectFunctionCall1(numeric_out, PointerGetDatum(v->numeric))));
+ break;
+ default:
+ elog(ERROR, "unknown jsonb scalar type");
+ }
+}
+
/*
* jsonb type input function
*
return deserialize_json_text(str, nbytes);
}
+/*
+ * For jsonb we always want the de-escaped value - that's what's in token
+ */
+static void
+jsonb_in_scalar(void *state, char *token, JsonTokenType tokentype)
+{
+ JsonbInState *_state = (JsonbInState *) state;
+ JsonbValue v;
+
+ v.size = sizeof(JEntry);
+
+ switch (tokentype)
+ {
+
+ case JSON_TOKEN_STRING:
+ v.type = jbvString;
+ v.string.len = token ? checkStringLen(strlen(token)) : 0;
+ v.string.val = token ? pnstrdup(token, v.string.len) : NULL;
+ v.size += v.string.len;
+ break;
+ case JSON_TOKEN_NUMBER:
+ v.type = jbvNumeric;
+ v.numeric = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(token), 0, -1));
+
+ v.size += VARSIZE_ANY(v.numeric) + sizeof(JEntry) /* alignment */ ;
+ break;
+ case JSON_TOKEN_TRUE:
+ v.type = jbvBool;
+ v.boolean = true;
+ break;
+ case JSON_TOKEN_FALSE:
+ v.type = jbvBool;
+ v.boolean = false;
+ break;
+ case JSON_TOKEN_NULL:
+ v.type = jbvNull;
+ break;
+ default:
+ /* nothing else should be here in fact */
+ Assert(false);
+ break;
+ }
+
+ if (_state->state == NULL)
+ {
+ /* single scalar */
+ JsonbValue va;
+
+ va.type = jbvArray;
+ va.array.scalar = true;
+ va.array.nelems = 1;
+
+ _state->res = pushJsonbValue(&_state->state, WJB_BEGIN_ARRAY, &va);
+ _state->res = pushJsonbValue(&_state->state, WJB_ELEM, &v);
+ _state->res = pushJsonbValue(&_state->state, WJB_END_ARRAY, NULL);
+ }
+ else
+ {
+ JsonbValue *o = &_state->state->v;
+
+ switch (o->type)
+ {
+ case jbvArray:
+ _state->res = pushJsonbValue(&_state->state, WJB_ELEM, &v);
+ break;
+ case jbvHash:
+ _state->res = pushJsonbValue(&_state->state, WJB_VALUE, &v);
+ break;
+ default:
+ elog(ERROR, "unexpected parent of nested structure");
+ }
+ }
+}
/*
* deserialize_json_text
PG_RETURN_POINTER(JsonbValueToJsonb(state.res));
}
-void
-JsonbPutEscapedValue(StringInfo out, JsonbValue *v)
-{
- switch (v->type)
- {
- case jbvNull:
- appendBinaryStringInfo(out, "null", 4);
- break;
- case jbvString:
- escape_json(out, pnstrdup(v->string.val, v->string.len));
- break;
- case jbvBool:
- if (v->boolean)
- appendBinaryStringInfo(out, "true", 4);
- else
- appendBinaryStringInfo(out, "false", 5);
- break;
- case jbvNumeric:
- appendStringInfoString(out, DatumGetCString(DirectFunctionCall1(numeric_out, PointerGetDatum(v->numeric))));
- break;
- default:
- elog(ERROR, "unknown jsonb scalar type");
- }
-}
-
/*
* JsonbToCString
* Converts jsonb value in C-string. If out argument is not null
first = true;
/* json rules guarantee this is a string */
- JsonbPutEscapedValue(out, &v);
+ jsonb_put_escaped_value(out, &v);
appendBinaryStringInfo(out, ": ", 2);
type = JsonbIteratorGet(&it, &v, false);
if (type == WJB_VALUE)
{
first = false;
- JsonbPutEscapedValue(out, &v);
+ jsonb_put_escaped_value(out, &v);
}
else
{
else
first = false;
- JsonbPutEscapedValue(out, &v);
+ jsonb_put_escaped_value(out, &v);
break;
case WJB_END_ARRAY:
level--;
#define JBE_LEN(he_) (JBE_ISFIRST(he_) \
? JBE_ENDPOS(he_) \
: JBE_ENDPOS(he_) - JBE_ENDPOS((&(he_))[-1]))
+
+typedef void (*walk_jsonb_cb) (void * /* arg */ , JsonbValue * /* value */ ,
+ uint32 /* flags */ , uint32 /* level */ );
+
+static void walkUncompressedJsonb(JsonbValue *v, walk_jsonb_cb cb, void *cb_arg);
+static uint32 compressJsonb(JsonbValue *v, char *buffer);
+static void uniqueJsonbValue(JsonbValue *v);
+
/*
* Turn a JsonbValue into a Jsonb
*/
return out;
}
-/*
- * Sort and unique pairs in hash-like JsonbValue
- */
-void
-uniqueJsonbValue(JsonbValue *v)
-{
- bool hasNonUniq = false;
-
- Assert(v->type == jbvHash);
-
- if (v->hash.npairs > 1)
- qsort_arg(v->hash.pairs, v->hash.npairs, sizeof(*v->hash.pairs),
- compareJsonbPair, &hasNonUniq);
-
- if (hasNonUniq)
- {
- JsonbPair *ptr = v->hash.pairs + 1,
- *res = v->hash.pairs;
-
- while (ptr - v->hash.pairs < v->hash.npairs)
- {
- if (ptr->key.string.len == res->key.string.len &&
- memcmp(ptr->key.string.val, res->key.string.val,
- ptr->key.string.len) == 0)
- {
- v->size -= ptr->key.size + ptr->value.size;
- }
- else
- {
- res++;
- if (ptr != res)
- memcpy(res, ptr, sizeof(*res));
- }
- ptr++;
- }
-
- v->hash.npairs = res + 1 - v->hash.pairs;
- }
-}
-
/****************************************************************************
* Compare Functions *
****************************************************************************/
}
}
-void
+static void
walkUncompressedJsonb(JsonbValue *v, walk_jsonb_cb cb, void *cb_arg)
{
if (v)
/*
* puts JsonbValue tree into preallocated buffer
*/
-uint32
+static uint32
compressJsonb(JsonbValue *v, char *buffer)
{
uint32 l = 0;
h->size += v->size;
}
+/*
+ * Sort and unique pairs in hash-like JsonbValue
+ */
+static void
+uniqueJsonbValue(JsonbValue *v)
+{
+ bool hasNonUniq = false;
+
+ Assert(v->type == jbvHash);
+
+ if (v->hash.npairs > 1)
+ qsort_arg(v->hash.pairs, v->hash.npairs, sizeof(*v->hash.pairs),
+ compareJsonbPair, &hasNonUniq);
+
+ if (hasNonUniq)
+ {
+ JsonbPair *ptr = v->hash.pairs + 1,
+ *res = v->hash.pairs;
+
+ while (ptr - v->hash.pairs < v->hash.npairs)
+ {
+ if (ptr->key.string.len == res->key.string.len &&
+ memcmp(ptr->key.string.val, res->key.string.val,
+ ptr->key.string.len) == 0)
+ {
+ v->size -= ptr->key.size + ptr->value.size;
+ }
+ else
+ {
+ res++;
+ if (ptr != res)
+ memcpy(res, ptr, sizeof(*res));
+ }
+ ptr++;
+ }
+
+ v->hash.npairs = res + 1 - v->hash.pairs;
+ }
+}
+
/*
* Pushes the value into state. With r = WJB_END_OBJECT and v = NULL
* it will order and unique hash's keys otherwise we believe that
struct JsonbIterator *next;
} JsonbIterator;
-typedef void (*walk_jsonb_cb) (void * /* arg */ , JsonbValue * /* value */ ,
- uint32 /* flags */ , uint32 /* level */ );
-
-/*
- * jsonb support functions
- */
-extern void walkUncompressedJsonb(JsonbValue *v, walk_jsonb_cb cb, void *cb_arg);
-extern int compareJsonbStringValue(const void *a, const void *b, void *arg);
-extern int compareJsonbPair(const void *a, const void *b, void *arg);
-extern int compareJsonbBinaryValue(char *a, char *b);
-extern int compareJsonbValue(JsonbValue *a, JsonbValue *b);
-extern JsonbValue *findUncompressedJsonbValueByValue(char *buffer, uint32 flags,
- uint32 *lowbound, JsonbValue *key);
-extern JsonbValue *findUncompressedJsonbValue(char *buffer, uint32 flags,
- uint32 *lowbound, char *key, uint32 keylen);
-extern JsonbValue *getJsonbValue(char *buffer, uint32 flags, int32 i);
-extern JsonbValue *pushJsonbValue(ToJsonbState ** state, int r, JsonbValue *v);
-extern void uniqueJsonbValue(JsonbValue *v);
-extern uint32 compressJsonb(JsonbValue *v, char *buffer);
-extern JsonbIterator *JsonbIteratorInit(char *buffer);
-extern int JsonbIteratorGet(JsonbIterator **it, JsonbValue *v, bool skipNested);
-extern char *JsonbToCString(StringInfo out, char *in, int estimated_len);
-extern Jsonb *JsonbValueToJsonb(JsonbValue *v);
-extern void JsonbPutEscapedValue(StringInfo out, JsonbValue *v);
-
/* I/O routines */
extern Datum jsonb_in(PG_FUNCTION_ARGS);
extern Datum jsonb_out(PG_FUNCTION_ARGS);
extern Datum gjsonb_in(PG_FUNCTION_ARGS);
extern Datum gjsonb_out(PG_FUNCTION_ARGS);
+/* Support functions */
+extern int compareJsonbStringValue(const void *a, const void *b, void *arg);
+extern int compareJsonbPair(const void *a, const void *b, void *arg);
+extern int compareJsonbBinaryValue(char *a, char *b);
+extern int compareJsonbValue(JsonbValue *a, JsonbValue *b);
+extern JsonbValue *findUncompressedJsonbValueByValue(char *buffer, uint32 flags,
+ uint32 *lowbound, JsonbValue *key);
+extern JsonbValue *findUncompressedJsonbValue(char *buffer, uint32 flags,
+ uint32 *lowbound, char *key, uint32 keylen);
+extern JsonbValue *getJsonbValue(char *buffer, uint32 flags, int32 i);
+extern JsonbValue *pushJsonbValue(ToJsonbState ** state, int r, JsonbValue *v);
+extern JsonbIterator *JsonbIteratorInit(char *buffer);
+extern int JsonbIteratorGet(JsonbIterator **it, JsonbValue *v, bool skipNested);
+extern Jsonb *JsonbValueToJsonb(JsonbValue *v);
+
+/* jsonb.c support function */
+extern char *JsonbToCString(StringInfo out, char *in, int estimated_len);
+
#endif /* __JSONB_H__ */