|
|
|
@ -336,20 +336,20 @@ typedef struct JsObject
|
|
|
|
|
static int report_json_context(JsonLexContext *lex);
|
|
|
|
|
|
|
|
|
|
/* semantic action functions for json_object_keys */
|
|
|
|
|
static void okeys_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static void okeys_array_start(void *state);
|
|
|
|
|
static void okeys_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static JsonParseErrorType okeys_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static JsonParseErrorType okeys_array_start(void *state);
|
|
|
|
|
static JsonParseErrorType okeys_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
|
|
|
|
|
/* semantic action functions for json_get* functions */
|
|
|
|
|
static void get_object_start(void *state);
|
|
|
|
|
static void get_object_end(void *state);
|
|
|
|
|
static void get_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static void get_object_field_end(void *state, char *fname, bool isnull);
|
|
|
|
|
static void get_array_start(void *state);
|
|
|
|
|
static void get_array_end(void *state);
|
|
|
|
|
static void get_array_element_start(void *state, bool isnull);
|
|
|
|
|
static void get_array_element_end(void *state, bool isnull);
|
|
|
|
|
static void get_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static JsonParseErrorType get_object_start(void *state);
|
|
|
|
|
static JsonParseErrorType get_object_end(void *state);
|
|
|
|
|
static JsonParseErrorType get_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static JsonParseErrorType get_object_field_end(void *state, char *fname, bool isnull);
|
|
|
|
|
static JsonParseErrorType get_array_start(void *state);
|
|
|
|
|
static JsonParseErrorType get_array_end(void *state);
|
|
|
|
|
static JsonParseErrorType get_array_element_start(void *state, bool isnull);
|
|
|
|
|
static JsonParseErrorType get_array_element_end(void *state, bool isnull);
|
|
|
|
|
static JsonParseErrorType get_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
|
|
|
|
|
/* common worker function for json getter functions */
|
|
|
|
|
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
|
|
|
|
@ -359,9 +359,9 @@ static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
|
|
|
|
|
static text *JsonbValueAsText(JsonbValue *v);
|
|
|
|
|
|
|
|
|
|
/* semantic action functions for json_array_length */
|
|
|
|
|
static void alen_object_start(void *state);
|
|
|
|
|
static void alen_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static void alen_array_element_start(void *state, bool isnull);
|
|
|
|
|
static JsonParseErrorType alen_object_start(void *state);
|
|
|
|
|
static JsonParseErrorType alen_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static JsonParseErrorType alen_array_element_start(void *state, bool isnull);
|
|
|
|
|
|
|
|
|
|
/* common workers for json{b}_each* functions */
|
|
|
|
|
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
|
|
|
|
@ -369,10 +369,10 @@ static Datum each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
|
|
|
|
|
bool as_text);
|
|
|
|
|
|
|
|
|
|
/* semantic action functions for json_each */
|
|
|
|
|
static void each_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static void each_object_field_end(void *state, char *fname, bool isnull);
|
|
|
|
|
static void each_array_start(void *state);
|
|
|
|
|
static void each_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static JsonParseErrorType each_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static JsonParseErrorType each_object_field_end(void *state, char *fname, bool isnull);
|
|
|
|
|
static JsonParseErrorType each_array_start(void *state);
|
|
|
|
|
static JsonParseErrorType each_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
|
|
|
|
|
/* common workers for json{b}_array_elements_* functions */
|
|
|
|
|
static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname,
|
|
|
|
@ -381,44 +381,44 @@ static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname
|
|
|
|
|
bool as_text);
|
|
|
|
|
|
|
|
|
|
/* semantic action functions for json_array_elements */
|
|
|
|
|
static void elements_object_start(void *state);
|
|
|
|
|
static void elements_array_element_start(void *state, bool isnull);
|
|
|
|
|
static void elements_array_element_end(void *state, bool isnull);
|
|
|
|
|
static void elements_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static JsonParseErrorType elements_object_start(void *state);
|
|
|
|
|
static JsonParseErrorType elements_array_element_start(void *state, bool isnull);
|
|
|
|
|
static JsonParseErrorType elements_array_element_end(void *state, bool isnull);
|
|
|
|
|
static JsonParseErrorType elements_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
|
|
|
|
|
/* turn a json object into a hash table */
|
|
|
|
|
static HTAB *get_json_object_as_hash(char *json, int len, const char *funcname);
|
|
|
|
|
|
|
|
|
|
/* semantic actions for populate_array_json */
|
|
|
|
|
static void populate_array_object_start(void *_state);
|
|
|
|
|
static void populate_array_array_end(void *_state);
|
|
|
|
|
static void populate_array_element_start(void *_state, bool isnull);
|
|
|
|
|
static void populate_array_element_end(void *_state, bool isnull);
|
|
|
|
|
static void populate_array_scalar(void *_state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static JsonParseErrorType populate_array_object_start(void *_state);
|
|
|
|
|
static JsonParseErrorType populate_array_array_end(void *_state);
|
|
|
|
|
static JsonParseErrorType populate_array_element_start(void *_state, bool isnull);
|
|
|
|
|
static JsonParseErrorType populate_array_element_end(void *_state, bool isnull);
|
|
|
|
|
static JsonParseErrorType populate_array_scalar(void *_state, char *token, JsonTokenType tokentype);
|
|
|
|
|
|
|
|
|
|
/* semantic action functions for get_json_object_as_hash */
|
|
|
|
|
static void hash_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static void hash_object_field_end(void *state, char *fname, bool isnull);
|
|
|
|
|
static void hash_array_start(void *state);
|
|
|
|
|
static void hash_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static JsonParseErrorType hash_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static JsonParseErrorType hash_object_field_end(void *state, char *fname, bool isnull);
|
|
|
|
|
static JsonParseErrorType hash_array_start(void *state);
|
|
|
|
|
static JsonParseErrorType hash_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
|
|
|
|
|
/* semantic action functions for populate_recordset */
|
|
|
|
|
static void populate_recordset_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static void populate_recordset_object_field_end(void *state, char *fname, bool isnull);
|
|
|
|
|
static void populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static void populate_recordset_object_start(void *state);
|
|
|
|
|
static void populate_recordset_object_end(void *state);
|
|
|
|
|
static void populate_recordset_array_start(void *state);
|
|
|
|
|
static void populate_recordset_array_element_start(void *state, bool isnull);
|
|
|
|
|
static JsonParseErrorType populate_recordset_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static JsonParseErrorType populate_recordset_object_field_end(void *state, char *fname, bool isnull);
|
|
|
|
|
static JsonParseErrorType populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static JsonParseErrorType populate_recordset_object_start(void *state);
|
|
|
|
|
static JsonParseErrorType populate_recordset_object_end(void *state);
|
|
|
|
|
static JsonParseErrorType populate_recordset_array_start(void *state);
|
|
|
|
|
static JsonParseErrorType populate_recordset_array_element_start(void *state, bool isnull);
|
|
|
|
|
|
|
|
|
|
/* semantic action functions for json_strip_nulls */
|
|
|
|
|
static void sn_object_start(void *state);
|
|
|
|
|
static void sn_object_end(void *state);
|
|
|
|
|
static void sn_array_start(void *state);
|
|
|
|
|
static void sn_array_end(void *state);
|
|
|
|
|
static void sn_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static void sn_array_element_start(void *state, bool isnull);
|
|
|
|
|
static void sn_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static JsonParseErrorType sn_object_start(void *state);
|
|
|
|
|
static JsonParseErrorType sn_object_end(void *state);
|
|
|
|
|
static JsonParseErrorType sn_array_start(void *state);
|
|
|
|
|
static JsonParseErrorType sn_array_end(void *state);
|
|
|
|
|
static JsonParseErrorType sn_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static JsonParseErrorType sn_array_element_start(void *state, bool isnull);
|
|
|
|
|
static JsonParseErrorType sn_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
|
|
|
|
|
/* worker functions for populate_record, to_record, populate_recordset and to_recordset */
|
|
|
|
|
static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
|
|
|
|
@ -478,17 +478,17 @@ static void setPathArray(JsonbIterator **it, Datum *path_elems,
|
|
|
|
|
JsonbValue *newval, uint32 nelems, int op_type);
|
|
|
|
|
|
|
|
|
|
/* function supporting iterate_json_values */
|
|
|
|
|
static void iterate_values_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static void iterate_values_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static JsonParseErrorType iterate_values_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static JsonParseErrorType iterate_values_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
|
|
|
|
|
/* functions supporting transform_json_string_values */
|
|
|
|
|
static void transform_string_values_object_start(void *state);
|
|
|
|
|
static void transform_string_values_object_end(void *state);
|
|
|
|
|
static void transform_string_values_array_start(void *state);
|
|
|
|
|
static void transform_string_values_array_end(void *state);
|
|
|
|
|
static void transform_string_values_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static void transform_string_values_array_element_start(void *state, bool isnull);
|
|
|
|
|
static void transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
static JsonParseErrorType transform_string_values_object_start(void *state);
|
|
|
|
|
static JsonParseErrorType transform_string_values_object_end(void *state);
|
|
|
|
|
static JsonParseErrorType transform_string_values_array_start(void *state);
|
|
|
|
|
static JsonParseErrorType transform_string_values_array_end(void *state);
|
|
|
|
|
static JsonParseErrorType transform_string_values_object_field_start(void *state, char *fname, bool isnull);
|
|
|
|
|
static JsonParseErrorType transform_string_values_array_element_start(void *state, bool isnull);
|
|
|
|
|
static JsonParseErrorType transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* pg_parse_json_or_ereport
|
|
|
|
@ -745,14 +745,14 @@ json_object_keys(PG_FUNCTION_ARGS)
|
|
|
|
|
SRF_RETURN_DONE(funcctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
okeys_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
OkeysState *_state = (OkeysState *) state;
|
|
|
|
|
|
|
|
|
|
/* only collecting keys for the top level object */
|
|
|
|
|
if (_state->lex->lex_level != 1)
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
|
|
|
|
|
/* enlarge result array if necessary */
|
|
|
|
|
if (_state->result_count >= _state->result_size)
|
|
|
|
@ -764,9 +764,11 @@ okeys_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
|
|
|
|
|
/* save a copy of the field name */
|
|
|
|
|
_state->result[_state->result_count++] = pstrdup(fname);
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
okeys_array_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
OkeysState *_state = (OkeysState *) state;
|
|
|
|
@ -777,9 +779,11 @@ okeys_array_start(void *state)
|
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
|
errmsg("cannot call %s on an array",
|
|
|
|
|
"json_object_keys")));
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
okeys_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
{
|
|
|
|
|
OkeysState *_state = (OkeysState *) state;
|
|
|
|
@ -790,6 +794,8 @@ okeys_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
|
errmsg("cannot call %s on a scalar",
|
|
|
|
|
"json_object_keys")));
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -1112,7 +1118,7 @@ get_worker(text *json,
|
|
|
|
|
return state->tresult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
get_object_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
GetState *_state = (GetState *) state;
|
|
|
|
@ -1127,9 +1133,11 @@ get_object_start(void *state)
|
|
|
|
|
*/
|
|
|
|
|
_state->result_start = _state->lex->token_start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
get_object_end(void *state)
|
|
|
|
|
{
|
|
|
|
|
GetState *_state = (GetState *) state;
|
|
|
|
@ -1143,9 +1151,11 @@ get_object_end(void *state)
|
|
|
|
|
|
|
|
|
|
_state->tresult = cstring_to_text_with_len(start, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
get_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
GetState *_state = (GetState *) state;
|
|
|
|
@ -1188,9 +1198,11 @@ get_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
_state->result_start = _state->lex->token_start;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
get_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
GetState *_state = (GetState *) state;
|
|
|
|
@ -1237,9 +1249,11 @@ get_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
/* this should be unnecessary but let's do it for cleanliness: */
|
|
|
|
|
_state->result_start = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
get_array_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
GetState *_state = (GetState *) state;
|
|
|
|
@ -1275,9 +1289,11 @@ get_array_start(void *state)
|
|
|
|
|
*/
|
|
|
|
|
_state->result_start = _state->lex->token_start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
get_array_end(void *state)
|
|
|
|
|
{
|
|
|
|
|
GetState *_state = (GetState *) state;
|
|
|
|
@ -1291,9 +1307,11 @@ get_array_end(void *state)
|
|
|
|
|
|
|
|
|
|
_state->tresult = cstring_to_text_with_len(start, len);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
get_array_element_start(void *state, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
GetState *_state = (GetState *) state;
|
|
|
|
@ -1337,9 +1355,11 @@ get_array_element_start(void *state, bool isnull)
|
|
|
|
|
_state->result_start = _state->lex->token_start;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
get_array_element_end(void *state, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
GetState *_state = (GetState *) state;
|
|
|
|
@ -1379,9 +1399,11 @@ get_array_element_end(void *state, bool isnull)
|
|
|
|
|
|
|
|
|
|
_state->result_start = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
get_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
{
|
|
|
|
|
GetState *_state = (GetState *) state;
|
|
|
|
@ -1420,6 +1442,8 @@ get_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
/* make sure the next call to get_scalar doesn't overwrite it */
|
|
|
|
|
_state->next_scalar = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Datum
|
|
|
|
@ -1834,7 +1858,7 @@ jsonb_array_length(PG_FUNCTION_ARGS)
|
|
|
|
|
* a scalar or an object).
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
alen_object_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
AlenState *_state = (AlenState *) state;
|
|
|
|
@ -1844,9 +1868,11 @@ alen_object_start(void *state)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
|
errmsg("cannot get array length of a non-array")));
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
alen_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
{
|
|
|
|
|
AlenState *_state = (AlenState *) state;
|
|
|
|
@ -1856,9 +1882,11 @@ alen_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
|
errmsg("cannot get array length of a scalar")));
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
alen_array_element_start(void *state, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
AlenState *_state = (AlenState *) state;
|
|
|
|
@ -1866,6 +1894,8 @@ alen_array_element_start(void *state, bool isnull)
|
|
|
|
|
/* just count up all the level 1 elements */
|
|
|
|
|
if (_state->lex->lex_level == 1)
|
|
|
|
|
_state->count++;
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -2026,7 +2056,7 @@ each_worker(FunctionCallInfo fcinfo, bool as_text)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
each_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
EachState *_state = (EachState *) state;
|
|
|
|
@ -2044,9 +2074,11 @@ each_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
else
|
|
|
|
|
_state->result_start = _state->lex->token_start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
each_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
EachState *_state = (EachState *) state;
|
|
|
|
@ -2059,7 +2091,7 @@ each_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
|
|
|
|
|
/* skip over nested objects */
|
|
|
|
|
if (_state->lex->lex_level != 1)
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
|
|
|
|
|
/* use the tmp context so we can clean up after each tuple is done */
|
|
|
|
|
old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
|
|
|
|
@ -2090,9 +2122,11 @@ each_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
/* clean up and switch back */
|
|
|
|
|
MemoryContextSwitchTo(old_cxt);
|
|
|
|
|
MemoryContextReset(_state->tmp_cxt);
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
each_array_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
EachState *_state = (EachState *) state;
|
|
|
|
@ -2102,9 +2136,11 @@ each_array_start(void *state)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
|
errmsg("cannot deconstruct an array as an object")));
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
each_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
{
|
|
|
|
|
EachState *_state = (EachState *) state;
|
|
|
|
@ -2118,6 +2154,8 @@ each_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
/* supply de-escaped value if required */
|
|
|
|
|
if (_state->next_scalar)
|
|
|
|
|
_state->normalized_scalar = token;
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -2268,7 +2306,7 @@ elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
|
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
elements_array_element_start(void *state, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
ElementsState *_state = (ElementsState *) state;
|
|
|
|
@ -2286,9 +2324,11 @@ elements_array_element_start(void *state, bool isnull)
|
|
|
|
|
else
|
|
|
|
|
_state->result_start = _state->lex->token_start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
elements_array_element_end(void *state, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
ElementsState *_state = (ElementsState *) state;
|
|
|
|
@ -2301,7 +2341,7 @@ elements_array_element_end(void *state, bool isnull)
|
|
|
|
|
|
|
|
|
|
/* skip over nested objects */
|
|
|
|
|
if (_state->lex->lex_level != 1)
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
|
|
|
|
|
/* use the tmp context so we can clean up after each tuple is done */
|
|
|
|
|
old_cxt = MemoryContextSwitchTo(_state->tmp_cxt);
|
|
|
|
@ -2330,9 +2370,11 @@ elements_array_element_end(void *state, bool isnull)
|
|
|
|
|
/* clean up and switch back */
|
|
|
|
|
MemoryContextSwitchTo(old_cxt);
|
|
|
|
|
MemoryContextReset(_state->tmp_cxt);
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
elements_object_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
ElementsState *_state = (ElementsState *) state;
|
|
|
|
@ -2343,9 +2385,11 @@ elements_object_start(void *state)
|
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
|
errmsg("cannot call %s on a non-array",
|
|
|
|
|
_state->function_name)));
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
elements_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
{
|
|
|
|
|
ElementsState *_state = (ElementsState *) state;
|
|
|
|
@ -2360,6 +2404,8 @@ elements_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
/* supply de-escaped value if required */
|
|
|
|
|
if (_state->next_scalar)
|
|
|
|
|
_state->normalized_scalar = token;
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -2508,7 +2554,7 @@ populate_array_element(PopulateArrayContext *ctx, int ndim, JsValue *jsv)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* json object start handler for populate_array_json() */
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
populate_array_object_start(void *_state)
|
|
|
|
|
{
|
|
|
|
|
PopulateArrayState *state = (PopulateArrayState *) _state;
|
|
|
|
@ -2518,10 +2564,12 @@ populate_array_object_start(void *_state)
|
|
|
|
|
populate_array_assign_ndims(state->ctx, ndim);
|
|
|
|
|
else if (ndim < state->ctx->ndims)
|
|
|
|
|
populate_array_report_expected_array(state->ctx, ndim);
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* json array end handler for populate_array_json() */
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
populate_array_array_end(void *_state)
|
|
|
|
|
{
|
|
|
|
|
PopulateArrayState *state = (PopulateArrayState *) _state;
|
|
|
|
@ -2533,10 +2581,12 @@ populate_array_array_end(void *_state)
|
|
|
|
|
|
|
|
|
|
if (ndim < ctx->ndims)
|
|
|
|
|
populate_array_check_dimension(ctx, ndim);
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* json array element start handler for populate_array_json() */
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
populate_array_element_start(void *_state, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
PopulateArrayState *state = (PopulateArrayState *) _state;
|
|
|
|
@ -2549,10 +2599,12 @@ populate_array_element_start(void *_state, bool isnull)
|
|
|
|
|
state->element_type = state->lex->token_type;
|
|
|
|
|
state->element_scalar = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* json array element end handler for populate_array_json() */
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
populate_array_element_end(void *_state, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
PopulateArrayState *state = (PopulateArrayState *) _state;
|
|
|
|
@ -2588,10 +2640,12 @@ populate_array_element_end(void *_state, bool isnull)
|
|
|
|
|
|
|
|
|
|
populate_array_element(ctx, ndim, &jsv);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* json scalar handler for populate_array_json() */
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
|
|
|
|
|
{
|
|
|
|
|
PopulateArrayState *state = (PopulateArrayState *) _state;
|
|
|
|
@ -2610,6 +2664,8 @@ populate_array_scalar(void *_state, char *token, JsonTokenType tokentype)
|
|
|
|
|
/* element_type must already be set in populate_array_element_start() */
|
|
|
|
|
Assert(state->element_type == tokentype);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* parse a json array and populate array */
|
|
|
|
@ -3491,13 +3547,13 @@ get_json_object_as_hash(char *json, int len, const char *funcname)
|
|
|
|
|
return tab;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
hash_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
JHashState *_state = (JHashState *) state;
|
|
|
|
|
|
|
|
|
|
if (_state->lex->lex_level > 1)
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
|
|
|
|
|
/* remember token type */
|
|
|
|
|
_state->saved_token_type = _state->lex->token_type;
|
|
|
|
@ -3513,9 +3569,11 @@ hash_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
/* must be a scalar */
|
|
|
|
|
_state->save_json_start = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
hash_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
JHashState *_state = (JHashState *) state;
|
|
|
|
@ -3526,7 +3584,7 @@ hash_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
* Ignore nested fields.
|
|
|
|
|
*/
|
|
|
|
|
if (_state->lex->lex_level > 1)
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Ignore field names >= NAMEDATALEN - they can't match a record field.
|
|
|
|
@ -3536,7 +3594,7 @@ hash_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
* has previously insisted on exact equality, so we keep this behavior.)
|
|
|
|
|
*/
|
|
|
|
|
if (strlen(fname) >= NAMEDATALEN)
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
|
|
|
|
|
hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
|
|
|
|
|
|
|
|
|
@ -3562,9 +3620,11 @@ hash_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
/* must have had a scalar instead */
|
|
|
|
|
hashentry->val = _state->saved_scalar;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
hash_array_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
JHashState *_state = (JHashState *) state;
|
|
|
|
@ -3573,9 +3633,11 @@ hash_array_start(void *state)
|
|
|
|
|
ereport(ERROR,
|
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
|
errmsg("cannot call %s on an array", _state->function_name)));
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
hash_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
{
|
|
|
|
|
JHashState *_state = (JHashState *) state;
|
|
|
|
@ -3591,6 +3653,8 @@ hash_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
/* saved_token_type must already be set in hash_object_field_start() */
|
|
|
|
|
Assert(_state->saved_token_type == tokentype);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -3840,7 +3904,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
|
|
|
|
|
PG_RETURN_NULL();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
populate_recordset_object_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
|
|
|
|
@ -3856,7 +3920,7 @@ populate_recordset_object_start(void *state)
|
|
|
|
|
|
|
|
|
|
/* Nested objects require no special processing */
|
|
|
|
|
if (lex_level > 1)
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
|
|
|
|
|
/* Object at level 1: set up a new hash table for this object */
|
|
|
|
|
ctl.keysize = NAMEDATALEN;
|
|
|
|
@ -3866,9 +3930,11 @@ populate_recordset_object_start(void *state)
|
|
|
|
|
100,
|
|
|
|
|
&ctl,
|
|
|
|
|
HASH_ELEM | HASH_STRINGS | HASH_CONTEXT);
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
populate_recordset_object_end(void *state)
|
|
|
|
|
{
|
|
|
|
|
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
|
|
|
|
@ -3876,7 +3942,7 @@ populate_recordset_object_end(void *state)
|
|
|
|
|
|
|
|
|
|
/* Nested objects require no special processing */
|
|
|
|
|
if (_state->lex->lex_level > 1)
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
|
|
|
|
|
obj.is_json = true;
|
|
|
|
|
obj.val.json_hash = _state->json_hash;
|
|
|
|
@ -3887,9 +3953,11 @@ populate_recordset_object_end(void *state)
|
|
|
|
|
/* Done with hash for this object */
|
|
|
|
|
hash_destroy(_state->json_hash);
|
|
|
|
|
_state->json_hash = NULL;
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
populate_recordset_array_element_start(void *state, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
|
|
|
|
@ -3900,15 +3968,18 @@ populate_recordset_array_element_start(void *state, bool isnull)
|
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
|
errmsg("argument of %s must be an array of objects",
|
|
|
|
|
_state->function_name)));
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
populate_recordset_array_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
/* nothing to do */
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
{
|
|
|
|
|
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
|
|
|
|
@ -3921,15 +3992,17 @@ populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
|
|
|
|
|
if (_state->lex->lex_level == 2)
|
|
|
|
|
_state->saved_scalar = token;
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
populate_recordset_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
|
|
|
|
|
|
|
|
|
|
if (_state->lex->lex_level > 2)
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
|
|
|
|
|
_state->saved_token_type = _state->lex->token_type;
|
|
|
|
|
|
|
|
|
@ -3942,9 +4015,11 @@ populate_recordset_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
_state->save_json_start = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
populate_recordset_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
|
|
|
|
@ -3955,7 +4030,7 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
* Ignore nested fields.
|
|
|
|
|
*/
|
|
|
|
|
if (_state->lex->lex_level > 2)
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Ignore field names >= NAMEDATALEN - they can't match a record field.
|
|
|
|
@ -3965,7 +4040,7 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
* has previously insisted on exact equality, so we keep this behavior.)
|
|
|
|
|
*/
|
|
|
|
|
if (strlen(fname) >= NAMEDATALEN)
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
|
|
|
|
|
hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
|
|
|
|
|
|
|
|
|
@ -3991,6 +4066,8 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
/* must have had a scalar instead */
|
|
|
|
|
hashentry->val = _state->saved_scalar;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -4002,39 +4079,47 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull)
|
|
|
|
|
* is called.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
sn_object_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
StripnullState *_state = (StripnullState *) state;
|
|
|
|
|
|
|
|
|
|
appendStringInfoCharMacro(_state->strval, '{');
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
sn_object_end(void *state)
|
|
|
|
|
{
|
|
|
|
|
StripnullState *_state = (StripnullState *) state;
|
|
|
|
|
|
|
|
|
|
appendStringInfoCharMacro(_state->strval, '}');
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
sn_array_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
StripnullState *_state = (StripnullState *) state;
|
|
|
|
|
|
|
|
|
|
appendStringInfoCharMacro(_state->strval, '[');
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
sn_array_end(void *state)
|
|
|
|
|
{
|
|
|
|
|
StripnullState *_state = (StripnullState *) state;
|
|
|
|
|
|
|
|
|
|
appendStringInfoCharMacro(_state->strval, ']');
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
sn_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
StripnullState *_state = (StripnullState *) state;
|
|
|
|
@ -4047,7 +4132,7 @@ sn_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
* object or array. The flag will be reset in the scalar action.
|
|
|
|
|
*/
|
|
|
|
|
_state->skip_next_null = true;
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_state->strval->data[_state->strval->len - 1] != '{')
|
|
|
|
@ -4060,18 +4145,22 @@ sn_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
escape_json(_state->strval, fname);
|
|
|
|
|
|
|
|
|
|
appendStringInfoCharMacro(_state->strval, ':');
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
sn_array_element_start(void *state, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
StripnullState *_state = (StripnullState *) state;
|
|
|
|
|
|
|
|
|
|
if (_state->strval->data[_state->strval->len - 1] != '[')
|
|
|
|
|
appendStringInfoCharMacro(_state->strval, ',');
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
sn_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
{
|
|
|
|
|
StripnullState *_state = (StripnullState *) state;
|
|
|
|
@ -4080,13 +4169,15 @@ sn_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
{
|
|
|
|
|
Assert(tokentype == JSON_TOKEN_NULL);
|
|
|
|
|
_state->skip_next_null = false;
|
|
|
|
|
return;
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tokentype == JSON_TOKEN_STRING)
|
|
|
|
|
escape_json(_state->strval, token);
|
|
|
|
|
else
|
|
|
|
|
appendStringInfoString(_state->strval, token);
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -5326,7 +5417,7 @@ iterate_json_values(text *json, uint32 flags, void *action_state,
|
|
|
|
|
* An auxiliary function for iterate_json_values to invoke a specified
|
|
|
|
|
* JsonIterateStringValuesAction for specified values.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
{
|
|
|
|
|
IterateJsonStringValuesState *_state = (IterateJsonStringValuesState *) state;
|
|
|
|
@ -5350,9 +5441,11 @@ iterate_values_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
/* do not call callback for any other token */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
iterate_values_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
IterateJsonStringValuesState *_state = (IterateJsonStringValuesState *) state;
|
|
|
|
@ -5363,6 +5456,8 @@ iterate_values_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
|
|
|
|
|
_state->action(_state->action_state, val, strlen(val));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -5430,7 +5525,6 @@ transform_json_string_values(text *json, void *action_state,
|
|
|
|
|
state->action_state = action_state;
|
|
|
|
|
|
|
|
|
|
sem->semstate = (void *) state;
|
|
|
|
|
sem->scalar = transform_string_values_scalar;
|
|
|
|
|
sem->object_start = transform_string_values_object_start;
|
|
|
|
|
sem->object_end = transform_string_values_object_end;
|
|
|
|
|
sem->array_start = transform_string_values_array_start;
|
|
|
|
@ -5449,39 +5543,47 @@ transform_json_string_values(text *json, void *action_state,
|
|
|
|
|
* specified JsonTransformStringValuesAction for all values and left everything
|
|
|
|
|
* else untouched.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
transform_string_values_object_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
|
|
|
|
|
|
|
|
|
|
appendStringInfoCharMacro(_state->strval, '{');
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
transform_string_values_object_end(void *state)
|
|
|
|
|
{
|
|
|
|
|
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
|
|
|
|
|
|
|
|
|
|
appendStringInfoCharMacro(_state->strval, '}');
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
transform_string_values_array_start(void *state)
|
|
|
|
|
{
|
|
|
|
|
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
|
|
|
|
|
|
|
|
|
|
appendStringInfoCharMacro(_state->strval, '[');
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
transform_string_values_array_end(void *state)
|
|
|
|
|
{
|
|
|
|
|
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
|
|
|
|
|
|
|
|
|
|
appendStringInfoCharMacro(_state->strval, ']');
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
transform_string_values_object_field_start(void *state, char *fname, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
|
|
|
|
@ -5495,18 +5597,22 @@ transform_string_values_object_field_start(void *state, char *fname, bool isnull
|
|
|
|
|
*/
|
|
|
|
|
escape_json(_state->strval, fname);
|
|
|
|
|
appendStringInfoCharMacro(_state->strval, ':');
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
transform_string_values_array_element_start(void *state, bool isnull)
|
|
|
|
|
{
|
|
|
|
|
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
|
|
|
|
|
|
|
|
|
|
if (_state->strval->data[_state->strval->len - 1] != '[')
|
|
|
|
|
appendStringInfoCharMacro(_state->strval, ',');
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static JsonParseErrorType
|
|
|
|
|
transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype)
|
|
|
|
|
{
|
|
|
|
|
TransformJsonStringValuesState *_state = (TransformJsonStringValuesState *) state;
|
|
|
|
@ -5519,4 +5625,6 @@ transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
appendStringInfoString(_state->strval, token);
|
|
|
|
|
|
|
|
|
|
return JSON_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|