mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
Cosmetic improvements in jsonfuncs.c.
Re-pgindent, remove a lot of random vertical whitespace, remove useless (if not counterproductive) inline markings, get rid of unnecessary zero-padding of strings for hashtable searches. No functional changes.
This commit is contained in:
parent
57d8c1270e
commit
8d2d7ad5ab
@ -16,19 +16,19 @@
|
|||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#include "fmgr.h"
|
|
||||||
#include "funcapi.h"
|
|
||||||
#include "miscadmin.h"
|
|
||||||
#include "access/htup_details.h"
|
#include "access/htup_details.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
|
#include "fmgr.h"
|
||||||
|
#include "funcapi.h"
|
||||||
#include "lib/stringinfo.h"
|
#include "lib/stringinfo.h"
|
||||||
#include "mb/pg_wchar.h"
|
#include "mb/pg_wchar.h"
|
||||||
|
#include "miscadmin.h"
|
||||||
#include "utils/array.h"
|
#include "utils/array.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/hsearch.h"
|
#include "utils/hsearch.h"
|
||||||
#include "utils/json.h"
|
#include "utils/json.h"
|
||||||
#include "utils/jsonb.h"
|
|
||||||
#include "utils/jsonapi.h"
|
#include "utils/jsonapi.h"
|
||||||
|
#include "utils/jsonb.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/memutils.h"
|
#include "utils/memutils.h"
|
||||||
#include "utils/typcache.h"
|
#include "utils/typcache.h"
|
||||||
@ -48,11 +48,11 @@ static void get_array_element_end(void *state, bool isnull);
|
|||||||
static void get_scalar(void *state, char *token, JsonTokenType tokentype);
|
static void get_scalar(void *state, char *token, JsonTokenType tokentype);
|
||||||
|
|
||||||
/* common worker function for json getter functions */
|
/* common worker function for json getter functions */
|
||||||
static inline Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
|
static Datum get_path_all(FunctionCallInfo fcinfo, bool as_text);
|
||||||
static inline text *get_worker(text *json, char *field, int elem_index,
|
static text *get_worker(text *json, char *field, int elem_index,
|
||||||
char **tpath, int *ipath, int npath,
|
char **tpath, int *ipath, int npath,
|
||||||
bool normalize_results);
|
bool normalize_results);
|
||||||
static inline Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
|
static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
|
||||||
|
|
||||||
/* semantic action functions for json_array_length */
|
/* semantic action functions for json_array_length */
|
||||||
static void alen_object_start(void *state);
|
static void alen_object_start(void *state);
|
||||||
@ -60,8 +60,8 @@ static void alen_scalar(void *state, char *token, JsonTokenType tokentype);
|
|||||||
static void alen_array_element_start(void *state, bool isnull);
|
static void alen_array_element_start(void *state, bool isnull);
|
||||||
|
|
||||||
/* common workers for json{b}_each* functions */
|
/* common workers for json{b}_each* functions */
|
||||||
static inline Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
|
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
|
||||||
static inline Datum each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text);
|
static Datum each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text);
|
||||||
|
|
||||||
/* semantic action functions for json_each */
|
/* semantic action functions for json_each */
|
||||||
static void each_object_field_start(void *state, char *fname, bool isnull);
|
static void each_object_field_start(void *state, char *fname, bool isnull);
|
||||||
@ -70,8 +70,8 @@ static void each_array_start(void *state);
|
|||||||
static void each_scalar(void *state, char *token, JsonTokenType tokentype);
|
static void each_scalar(void *state, char *token, JsonTokenType tokentype);
|
||||||
|
|
||||||
/* common workers for json{b}_array_elements_* functions */
|
/* common workers for json{b}_array_elements_* functions */
|
||||||
static inline Datum elements_worker(FunctionCallInfo fcinfo, bool as_text);
|
static Datum elements_worker(FunctionCallInfo fcinfo, bool as_text);
|
||||||
static inline Datum elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text);
|
static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text);
|
||||||
|
|
||||||
/* semantic action functions for json_array_elements */
|
/* semantic action functions for json_array_elements */
|
||||||
static void elements_object_start(void *state);
|
static void elements_object_start(void *state);
|
||||||
@ -83,7 +83,7 @@ static void elements_scalar(void *state, char *token, JsonTokenType tokentype);
|
|||||||
static HTAB *get_json_object_as_hash(text *json, char *funcname, bool use_json_as_text);
|
static HTAB *get_json_object_as_hash(text *json, char *funcname, bool use_json_as_text);
|
||||||
|
|
||||||
/* common worker for populate_record and to_record */
|
/* common worker for populate_record and to_record */
|
||||||
static inline Datum populate_record_worker(FunctionCallInfo fcinfo,
|
static Datum populate_record_worker(FunctionCallInfo fcinfo,
|
||||||
bool have_record_arg);
|
bool have_record_arg);
|
||||||
|
|
||||||
/* semantic action functions for get_json_object_as_hash */
|
/* semantic action functions for get_json_object_as_hash */
|
||||||
@ -102,14 +102,14 @@ static void populate_recordset_array_start(void *state);
|
|||||||
static void populate_recordset_array_element_start(void *state, bool isnull);
|
static void populate_recordset_array_element_start(void *state, bool isnull);
|
||||||
|
|
||||||
/* worker function for populate_recordset and to_recordset */
|
/* worker function for populate_recordset and to_recordset */
|
||||||
static inline Datum populate_recordset_worker(FunctionCallInfo fcinfo,
|
static Datum populate_recordset_worker(FunctionCallInfo fcinfo,
|
||||||
bool have_record_arg);
|
bool have_record_arg);
|
||||||
|
|
||||||
/* Worker that takes care of common setup for us */
|
/* Worker that takes care of common setup for us */
|
||||||
static JsonbValue *findJsonbValueFromContainerLen(JsonbContainer *container,
|
static JsonbValue *findJsonbValueFromContainerLen(JsonbContainer *container,
|
||||||
uint32 flags,
|
uint32 flags,
|
||||||
char *key,
|
char *key,
|
||||||
uint32 keylen);
|
uint32 keylen);
|
||||||
|
|
||||||
/* search type classification for json_get* functions */
|
/* search type classification for json_get* functions */
|
||||||
typedef enum
|
typedef enum
|
||||||
@ -194,10 +194,10 @@ typedef struct JhashState
|
|||||||
char *function_name;
|
char *function_name;
|
||||||
} JHashState;
|
} JHashState;
|
||||||
|
|
||||||
/* used to build the hashtable */
|
/* hashtable element */
|
||||||
typedef struct JsonHashEntry
|
typedef struct JsonHashEntry
|
||||||
{
|
{
|
||||||
char fname[NAMEDATALEN];
|
char fname[NAMEDATALEN]; /* hash key (MUST BE FIRST) */
|
||||||
char *val;
|
char *val;
|
||||||
char *json;
|
char *json;
|
||||||
bool isnull;
|
bool isnull;
|
||||||
@ -303,10 +303,8 @@ jsonb_object_keys(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MemoryContextSwitchTo(oldcontext);
|
MemoryContextSwitchTo(oldcontext);
|
||||||
funcctx->user_fctx = (void *) state;
|
funcctx->user_fctx = (void *) state;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
funcctx = SRF_PERCALL_SETUP();
|
funcctx = SRF_PERCALL_SETUP();
|
||||||
@ -341,7 +339,6 @@ json_object_keys(PG_FUNCTION_ARGS)
|
|||||||
text *json = PG_GETARG_TEXT_P(0);
|
text *json = PG_GETARG_TEXT_P(0);
|
||||||
JsonLexContext *lex = makeJsonLexContext(json, true);
|
JsonLexContext *lex = makeJsonLexContext(json, true);
|
||||||
JsonSemAction *sem;
|
JsonSemAction *sem;
|
||||||
|
|
||||||
MemoryContext oldcontext;
|
MemoryContext oldcontext;
|
||||||
|
|
||||||
funcctx = SRF_FIRSTCALL_INIT();
|
funcctx = SRF_FIRSTCALL_INIT();
|
||||||
@ -372,7 +369,6 @@ json_object_keys(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
MemoryContextSwitchTo(oldcontext);
|
MemoryContextSwitchTo(oldcontext);
|
||||||
funcctx->user_fctx = (void *) state;
|
funcctx->user_fctx = (void *) state;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
funcctx = SRF_PERCALL_SETUP();
|
funcctx = SRF_PERCALL_SETUP();
|
||||||
@ -407,7 +403,7 @@ okeys_object_field_start(void *state, char *fname, bool isnull)
|
|||||||
if (_state->result_count >= _state->result_size)
|
if (_state->result_count >= _state->result_size)
|
||||||
{
|
{
|
||||||
_state->result_size *= 2;
|
_state->result_size *= 2;
|
||||||
_state->result =
|
_state->result = (char **)
|
||||||
repalloc(_state->result, sizeof(char *) * _state->result_size);
|
repalloc(_state->result, sizeof(char *) * _state->result_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,9 +446,9 @@ Datum
|
|||||||
json_object_field(PG_FUNCTION_ARGS)
|
json_object_field(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *json = PG_GETARG_TEXT_P(0);
|
text *json = PG_GETARG_TEXT_P(0);
|
||||||
text *result;
|
|
||||||
text *fname = PG_GETARG_TEXT_P(1);
|
text *fname = PG_GETARG_TEXT_P(1);
|
||||||
char *fnamestr = text_to_cstring(fname);
|
char *fnamestr = text_to_cstring(fname);
|
||||||
|
text *result;
|
||||||
|
|
||||||
result = get_worker(json, fnamestr, -1, NULL, NULL, -1, false);
|
result = get_worker(json, fnamestr, -1, NULL, NULL, -1, false);
|
||||||
|
|
||||||
@ -481,7 +477,7 @@ jsonb_object_field(PG_FUNCTION_ARGS)
|
|||||||
Assert(JB_ROOT_IS_OBJECT(jb));
|
Assert(JB_ROOT_IS_OBJECT(jb));
|
||||||
|
|
||||||
v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
|
v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
|
||||||
VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
|
VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
|
||||||
|
|
||||||
if (v != NULL)
|
if (v != NULL)
|
||||||
PG_RETURN_JSONB(JsonbValueToJsonb(v));
|
PG_RETURN_JSONB(JsonbValueToJsonb(v));
|
||||||
@ -493,9 +489,9 @@ Datum
|
|||||||
json_object_field_text(PG_FUNCTION_ARGS)
|
json_object_field_text(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *json = PG_GETARG_TEXT_P(0);
|
text *json = PG_GETARG_TEXT_P(0);
|
||||||
text *result;
|
|
||||||
text *fname = PG_GETARG_TEXT_P(1);
|
text *fname = PG_GETARG_TEXT_P(1);
|
||||||
char *fnamestr = text_to_cstring(fname);
|
char *fnamestr = text_to_cstring(fname);
|
||||||
|
text *result;
|
||||||
|
|
||||||
result = get_worker(json, fnamestr, -1, NULL, NULL, -1, true);
|
result = get_worker(json, fnamestr, -1, NULL, NULL, -1, true);
|
||||||
|
|
||||||
@ -524,13 +520,13 @@ jsonb_object_field_text(PG_FUNCTION_ARGS)
|
|||||||
Assert(JB_ROOT_IS_OBJECT(jb));
|
Assert(JB_ROOT_IS_OBJECT(jb));
|
||||||
|
|
||||||
v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
|
v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT,
|
||||||
VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
|
VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
|
||||||
|
|
||||||
if (v != NULL)
|
if (v != NULL)
|
||||||
{
|
{
|
||||||
text *result = NULL;
|
text *result = NULL;
|
||||||
|
|
||||||
switch(v->type)
|
switch (v->type)
|
||||||
{
|
{
|
||||||
case jbvNull:
|
case jbvNull:
|
||||||
break;
|
break;
|
||||||
@ -542,11 +538,11 @@ jsonb_object_field_text(PG_FUNCTION_ARGS)
|
|||||||
break;
|
break;
|
||||||
case jbvNumeric:
|
case jbvNumeric:
|
||||||
result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
|
result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
|
||||||
PointerGetDatum(v->val.numeric))));
|
PointerGetDatum(v->val.numeric))));
|
||||||
break;
|
break;
|
||||||
case jbvBinary:
|
case jbvBinary:
|
||||||
{
|
{
|
||||||
StringInfo jtext = makeStringInfo();
|
StringInfo jtext = makeStringInfo();
|
||||||
|
|
||||||
(void) JsonbToCString(jtext, v->val.binary.data, -1);
|
(void) JsonbToCString(jtext, v->val.binary.data, -1);
|
||||||
result = cstring_to_text_with_len(jtext->data, jtext->len);
|
result = cstring_to_text_with_len(jtext->data, jtext->len);
|
||||||
@ -567,8 +563,8 @@ Datum
|
|||||||
json_array_element(PG_FUNCTION_ARGS)
|
json_array_element(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *json = PG_GETARG_TEXT_P(0);
|
text *json = PG_GETARG_TEXT_P(0);
|
||||||
text *result;
|
|
||||||
int element = PG_GETARG_INT32(1);
|
int element = PG_GETARG_INT32(1);
|
||||||
|
text *result;
|
||||||
|
|
||||||
result = get_worker(json, NULL, element, NULL, NULL, -1, false);
|
result = get_worker(json, NULL, element, NULL, NULL, -1, false);
|
||||||
|
|
||||||
@ -607,8 +603,8 @@ Datum
|
|||||||
json_array_element_text(PG_FUNCTION_ARGS)
|
json_array_element_text(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *json = PG_GETARG_TEXT_P(0);
|
text *json = PG_GETARG_TEXT_P(0);
|
||||||
text *result;
|
|
||||||
int element = PG_GETARG_INT32(1);
|
int element = PG_GETARG_INT32(1);
|
||||||
|
text *result;
|
||||||
|
|
||||||
result = get_worker(json, NULL, element, NULL, NULL, -1, true);
|
result = get_worker(json, NULL, element, NULL, NULL, -1, true);
|
||||||
|
|
||||||
@ -641,7 +637,7 @@ jsonb_array_element_text(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
text *result = NULL;
|
text *result = NULL;
|
||||||
|
|
||||||
switch(v->type)
|
switch (v->type)
|
||||||
{
|
{
|
||||||
case jbvNull:
|
case jbvNull:
|
||||||
break;
|
break;
|
||||||
@ -653,11 +649,11 @@ jsonb_array_element_text(PG_FUNCTION_ARGS)
|
|||||||
break;
|
break;
|
||||||
case jbvNumeric:
|
case jbvNumeric:
|
||||||
result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
|
result = cstring_to_text(DatumGetCString(DirectFunctionCall1(numeric_out,
|
||||||
PointerGetDatum(v->val.numeric))));
|
PointerGetDatum(v->val.numeric))));
|
||||||
break;
|
break;
|
||||||
case jbvBinary:
|
case jbvBinary:
|
||||||
{
|
{
|
||||||
StringInfo jtext = makeStringInfo();
|
StringInfo jtext = makeStringInfo();
|
||||||
|
|
||||||
(void) JsonbToCString(jtext, v->val.binary.data, -1);
|
(void) JsonbToCString(jtext, v->val.binary.data, -1);
|
||||||
result = cstring_to_text_with_len(jtext->data, jtext->len);
|
result = cstring_to_text_with_len(jtext->data, jtext->len);
|
||||||
@ -689,10 +685,10 @@ json_extract_path_text(PG_FUNCTION_ARGS)
|
|||||||
/*
|
/*
|
||||||
* common routine for extract_path functions
|
* common routine for extract_path functions
|
||||||
*/
|
*/
|
||||||
static inline Datum
|
static Datum
|
||||||
get_path_all(FunctionCallInfo fcinfo, bool as_text)
|
get_path_all(FunctionCallInfo fcinfo, bool as_text)
|
||||||
{
|
{
|
||||||
text *json;
|
text *json = PG_GETARG_TEXT_P(0);
|
||||||
ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
|
ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
|
||||||
text *result;
|
text *result;
|
||||||
Datum *pathtext;
|
Datum *pathtext;
|
||||||
@ -704,21 +700,17 @@ get_path_all(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
long ind;
|
long ind;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
json = PG_GETARG_TEXT_P(0);
|
|
||||||
|
|
||||||
if (array_contains_nulls(path))
|
if (array_contains_nulls(path))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
errmsg("cannot call function with null path elements")));
|
errmsg("cannot call function with null path elements")));
|
||||||
|
|
||||||
|
|
||||||
deconstruct_array(path, TEXTOID, -1, false, 'i',
|
deconstruct_array(path, TEXTOID, -1, false, 'i',
|
||||||
&pathtext, &pathnulls, &npath);
|
&pathtext, &pathnulls, &npath);
|
||||||
|
|
||||||
tpath = palloc(npath * sizeof(char *));
|
tpath = palloc(npath * sizeof(char *));
|
||||||
ipath = palloc(npath * sizeof(int));
|
ipath = palloc(npath * sizeof(int));
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < npath; i++)
|
for (i = 0; i < npath; i++)
|
||||||
{
|
{
|
||||||
tpath[i] = TextDatumGetCString(pathtext[i]);
|
tpath[i] = TextDatumGetCString(pathtext[i]);
|
||||||
@ -740,7 +732,6 @@ get_path_all(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
ipath[i] = -1;
|
ipath[i] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
result = get_worker(json, NULL, -1, tpath, ipath, npath, as_text);
|
result = get_worker(json, NULL, -1, tpath, ipath, npath, as_text);
|
||||||
|
|
||||||
if (result != NULL)
|
if (result != NULL)
|
||||||
@ -755,7 +746,7 @@ get_path_all(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
*
|
*
|
||||||
* common worker for all the json getter functions
|
* common worker for all the json getter functions
|
||||||
*/
|
*/
|
||||||
static inline text *
|
static text *
|
||||||
get_worker(text *json,
|
get_worker(text *json,
|
||||||
char *field,
|
char *field,
|
||||||
int elem_index,
|
int elem_index,
|
||||||
@ -795,7 +786,6 @@ get_worker(text *json,
|
|||||||
state->pathok[0] = true;
|
state->pathok[0] = true;
|
||||||
state->array_level_index = palloc(sizeof(int) * npath);
|
state->array_level_index = palloc(sizeof(int) * npath);
|
||||||
state->path_level_index = ipath;
|
state->path_level_index = ipath;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -852,7 +842,6 @@ get_object_field_start(void *state, char *fname, bool isnull)
|
|||||||
if (lex_level == 1 && _state->search_type == JSON_SEARCH_OBJECT &&
|
if (lex_level == 1 && _state->search_type == JSON_SEARCH_OBJECT &&
|
||||||
strcmp(fname, _state->search_term) == 0)
|
strcmp(fname, _state->search_term) == 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
_state->tresult = NULL;
|
_state->tresult = NULL;
|
||||||
_state->result_start = NULL;
|
_state->result_start = NULL;
|
||||||
get_next = true;
|
get_next = true;
|
||||||
@ -865,7 +854,6 @@ get_object_field_start(void *state, char *fname, bool isnull)
|
|||||||
/* path search, path so far is ok, and we have a match */
|
/* path search, path so far is ok, and we have a match */
|
||||||
|
|
||||||
/* this object overrides any previous matching object */
|
/* this object overrides any previous matching object */
|
||||||
|
|
||||||
_state->tresult = NULL;
|
_state->tresult = NULL;
|
||||||
_state->result_start = NULL;
|
_state->result_start = NULL;
|
||||||
|
|
||||||
@ -901,7 +889,6 @@ get_object_field_end(void *state, char *fname, bool isnull)
|
|||||||
bool get_last = false;
|
bool get_last = false;
|
||||||
int lex_level = _state->lex->lex_level;
|
int lex_level = _state->lex->lex_level;
|
||||||
|
|
||||||
|
|
||||||
/* same tests as in get_object_field_start, mutatis mutandis */
|
/* same tests as in get_object_field_start, mutatis mutandis */
|
||||||
if (lex_level == 1 && _state->search_type == JSON_SEARCH_OBJECT &&
|
if (lex_level == 1 && _state->search_type == JSON_SEARCH_OBJECT &&
|
||||||
strcmp(fname, _state->search_term) == 0)
|
strcmp(fname, _state->search_term) == 0)
|
||||||
@ -957,7 +944,7 @@ get_array_start(void *state)
|
|||||||
errmsg("cannot extract field from a non-object")));
|
errmsg("cannot extract field from a non-object")));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize array count for this nesting level Note: the lex_level seen
|
* initialize array count for this nesting level. Note: the lex_level seen
|
||||||
* by array_start is one less than that seen by the elements of the array.
|
* by array_start is one less than that seen by the elements of the array.
|
||||||
*/
|
*/
|
||||||
if (_state->search_type == JSON_SEARCH_PATH &&
|
if (_state->search_type == JSON_SEARCH_PATH &&
|
||||||
@ -991,7 +978,6 @@ get_array_element_start(void *state, bool isnull)
|
|||||||
*
|
*
|
||||||
* then check if we have a match.
|
* then check if we have a match.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (++_state->array_level_index[lex_level - 1] ==
|
if (++_state->array_level_index[lex_level - 1] ==
|
||||||
_state->path_level_index[lex_level - 1])
|
_state->path_level_index[lex_level - 1])
|
||||||
{
|
{
|
||||||
@ -1006,7 +992,6 @@ get_array_element_start(void *state, bool isnull)
|
|||||||
_state->pathok[lex_level] = true;
|
_state->pathok[lex_level] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* same logic as for objects */
|
/* same logic as for objects */
|
||||||
@ -1078,7 +1063,6 @@ get_scalar(void *state, char *token, JsonTokenType tokentype)
|
|||||||
/* make sure the next call to get_scalar doesn't overwrite it */
|
/* make sure the next call to get_scalar doesn't overwrite it */
|
||||||
_state->next_scalar = false;
|
_state->next_scalar = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
@ -1093,7 +1077,7 @@ jsonb_extract_path_text(PG_FUNCTION_ARGS)
|
|||||||
return get_jsonb_path_all(fcinfo, true);
|
return get_jsonb_path_all(fcinfo, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Datum
|
static Datum
|
||||||
get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
|
get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
|
||||||
{
|
{
|
||||||
Jsonb *jb = PG_GETARG_JSONB(0);
|
Jsonb *jb = PG_GETARG_JSONB(0);
|
||||||
@ -1206,13 +1190,11 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
Datum
|
Datum
|
||||||
json_array_length(PG_FUNCTION_ARGS)
|
json_array_length(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *json;
|
text *json = PG_GETARG_TEXT_P(0);
|
||||||
|
|
||||||
AlenState *state;
|
AlenState *state;
|
||||||
JsonLexContext *lex;
|
JsonLexContext *lex;
|
||||||
JsonSemAction *sem;
|
JsonSemAction *sem;
|
||||||
|
|
||||||
json = PG_GETARG_TEXT_P(0);
|
|
||||||
lex = makeJsonLexContext(json, false);
|
lex = makeJsonLexContext(json, false);
|
||||||
state = palloc0(sizeof(AlenState));
|
state = palloc0(sizeof(AlenState));
|
||||||
sem = palloc0(sizeof(JsonSemAction));
|
sem = palloc0(sizeof(JsonSemAction));
|
||||||
@ -1251,7 +1233,7 @@ jsonb_array_length(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These next two check ensure that the json is an array (since it can't be
|
* These next two checks ensure that the json is an array (since it can't be
|
||||||
* a scalar or an object).
|
* a scalar or an object).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -1323,7 +1305,7 @@ jsonb_each_text(PG_FUNCTION_ARGS)
|
|||||||
return each_worker_jsonb(fcinfo, true);
|
return each_worker_jsonb(fcinfo, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Datum
|
static Datum
|
||||||
each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
|
each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
|
||||||
{
|
{
|
||||||
Jsonb *jb = PG_GETARG_JSONB(0);
|
Jsonb *jb = PG_GETARG_JSONB(0);
|
||||||
@ -1354,7 +1336,6 @@ each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
errmsg("set-valued function called in context that "
|
errmsg("set-valued function called in context that "
|
||||||
"cannot accept a set")));
|
"cannot accept a set")));
|
||||||
|
|
||||||
|
|
||||||
rsi->returnMode = SFRM_Materialize;
|
rsi->returnMode = SFRM_Materialize;
|
||||||
|
|
||||||
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
|
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
|
||||||
@ -1379,7 +1360,6 @@ each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
ALLOCSET_DEFAULT_INITSIZE,
|
ALLOCSET_DEFAULT_INITSIZE,
|
||||||
ALLOCSET_DEFAULT_MAXSIZE);
|
ALLOCSET_DEFAULT_MAXSIZE);
|
||||||
|
|
||||||
|
|
||||||
it = JsonbIteratorInit(&jb->root);
|
it = JsonbIteratorInit(&jb->root);
|
||||||
|
|
||||||
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
|
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
|
||||||
@ -1463,10 +1443,10 @@ each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline Datum
|
static Datum
|
||||||
each_worker(FunctionCallInfo fcinfo, bool as_text)
|
each_worker(FunctionCallInfo fcinfo, bool as_text)
|
||||||
{
|
{
|
||||||
text *json;
|
text *json = PG_GETARG_TEXT_P(0);
|
||||||
JsonLexContext *lex;
|
JsonLexContext *lex;
|
||||||
JsonSemAction *sem;
|
JsonSemAction *sem;
|
||||||
ReturnSetInfo *rsi;
|
ReturnSetInfo *rsi;
|
||||||
@ -1474,8 +1454,6 @@ each_worker(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
TupleDesc tupdesc;
|
TupleDesc tupdesc;
|
||||||
EachState *state;
|
EachState *state;
|
||||||
|
|
||||||
json = PG_GETARG_TEXT_P(0);
|
|
||||||
|
|
||||||
lex = makeJsonLexContext(json, true);
|
lex = makeJsonLexContext(json, true);
|
||||||
state = palloc0(sizeof(EachState));
|
state = palloc0(sizeof(EachState));
|
||||||
sem = palloc0(sizeof(JsonSemAction));
|
sem = palloc0(sizeof(JsonSemAction));
|
||||||
@ -1490,7 +1468,6 @@ each_worker(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
errmsg("set-valued function called in context that "
|
errmsg("set-valued function called in context that "
|
||||||
"cannot accept a set")));
|
"cannot accept a set")));
|
||||||
|
|
||||||
|
|
||||||
rsi->returnMode = SFRM_Materialize;
|
rsi->returnMode = SFRM_Materialize;
|
||||||
|
|
||||||
(void) get_call_result_type(fcinfo, NULL, &tupdesc);
|
(void) get_call_result_type(fcinfo, NULL, &tupdesc);
|
||||||
@ -1514,7 +1491,6 @@ each_worker(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
|
|
||||||
state->normalize_results = as_text;
|
state->normalize_results = as_text;
|
||||||
state->next_scalar = false;
|
state->next_scalar = false;
|
||||||
|
|
||||||
state->lex = lex;
|
state->lex = lex;
|
||||||
state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
|
state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
|
||||||
"json_each temporary cxt",
|
"json_each temporary cxt",
|
||||||
@ -1576,7 +1552,7 @@ each_object_field_end(void *state, char *fname, bool isnull)
|
|||||||
if (isnull && _state->normalize_results)
|
if (isnull && _state->normalize_results)
|
||||||
{
|
{
|
||||||
nulls[1] = true;
|
nulls[1] = true;
|
||||||
values[1] = (Datum) NULL;
|
values[1] = (Datum) 0;
|
||||||
}
|
}
|
||||||
else if (_state->next_scalar)
|
else if (_state->next_scalar)
|
||||||
{
|
{
|
||||||
@ -1590,7 +1566,6 @@ each_object_field_end(void *state, char *fname, bool isnull)
|
|||||||
values[1] = PointerGetDatum(val);
|
values[1] = PointerGetDatum(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
|
tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
|
||||||
|
|
||||||
tuplestore_puttuple(_state->tuple_store, tuple);
|
tuplestore_puttuple(_state->tuple_store, tuple);
|
||||||
@ -1648,7 +1623,7 @@ jsonb_array_elements_text(PG_FUNCTION_ARGS)
|
|||||||
return elements_worker_jsonb(fcinfo, true);
|
return elements_worker_jsonb(fcinfo, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Datum
|
static Datum
|
||||||
elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
|
elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
|
||||||
{
|
{
|
||||||
Jsonb *jb = PG_GETARG_JSONB(0);
|
Jsonb *jb = PG_GETARG_JSONB(0);
|
||||||
@ -1682,7 +1657,6 @@ elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
errmsg("set-valued function called in context that "
|
errmsg("set-valued function called in context that "
|
||||||
"cannot accept a set")));
|
"cannot accept a set")));
|
||||||
|
|
||||||
|
|
||||||
rsi->returnMode = SFRM_Materialize;
|
rsi->returnMode = SFRM_Materialize;
|
||||||
|
|
||||||
/* it's a simple type, so don't use get_call_result_type() */
|
/* it's a simple type, so don't use get_call_result_type() */
|
||||||
@ -1699,12 +1673,11 @@ elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
MemoryContextSwitchTo(old_cxt);
|
MemoryContextSwitchTo(old_cxt);
|
||||||
|
|
||||||
tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
|
tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
|
||||||
"jsonb_each temporary cxt",
|
"jsonb_array_elements temporary cxt",
|
||||||
ALLOCSET_DEFAULT_MINSIZE,
|
ALLOCSET_DEFAULT_MINSIZE,
|
||||||
ALLOCSET_DEFAULT_INITSIZE,
|
ALLOCSET_DEFAULT_INITSIZE,
|
||||||
ALLOCSET_DEFAULT_MAXSIZE);
|
ALLOCSET_DEFAULT_MAXSIZE);
|
||||||
|
|
||||||
|
|
||||||
it = JsonbIteratorInit(&jb->root);
|
it = JsonbIteratorInit(&jb->root);
|
||||||
|
|
||||||
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
|
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
|
||||||
@ -1787,7 +1760,7 @@ json_array_elements_text(PG_FUNCTION_ARGS)
|
|||||||
return elements_worker(fcinfo, true);
|
return elements_worker(fcinfo, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Datum
|
static Datum
|
||||||
elements_worker(FunctionCallInfo fcinfo, bool as_text)
|
elements_worker(FunctionCallInfo fcinfo, bool as_text)
|
||||||
{
|
{
|
||||||
text *json = PG_GETARG_TEXT_P(0);
|
text *json = PG_GETARG_TEXT_P(0);
|
||||||
@ -1813,7 +1786,6 @@ elements_worker(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
errmsg("set-valued function called in context that "
|
errmsg("set-valued function called in context that "
|
||||||
"cannot accept a set")));
|
"cannot accept a set")));
|
||||||
|
|
||||||
|
|
||||||
rsi->returnMode = SFRM_Materialize;
|
rsi->returnMode = SFRM_Materialize;
|
||||||
|
|
||||||
/* it's a simple type, so don't use get_call_result_type() */
|
/* it's a simple type, so don't use get_call_result_type() */
|
||||||
@ -1838,7 +1810,6 @@ elements_worker(FunctionCallInfo fcinfo, bool as_text)
|
|||||||
|
|
||||||
state->normalize_results = as_text;
|
state->normalize_results = as_text;
|
||||||
state->next_scalar = false;
|
state->next_scalar = false;
|
||||||
|
|
||||||
state->lex = lex;
|
state->lex = lex;
|
||||||
state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
|
state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
|
||||||
"json_array_elements temporary cxt",
|
"json_array_elements temporary cxt",
|
||||||
@ -1911,7 +1882,6 @@ elements_array_element_end(void *state, bool isnull)
|
|||||||
values[0] = PointerGetDatum(val);
|
values[0] = PointerGetDatum(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
|
tuple = heap_form_tuple(_state->ret_tdesc, values, nulls);
|
||||||
|
|
||||||
tuplestore_puttuple(_state->tuple_store, tuple);
|
tuplestore_puttuple(_state->tuple_store, tuple);
|
||||||
@ -1985,7 +1955,7 @@ json_to_record(PG_FUNCTION_ARGS)
|
|||||||
return populate_record_worker(fcinfo, false);
|
return populate_record_worker(fcinfo, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline Datum
|
static Datum
|
||||||
populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
|
populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
|
||||||
{
|
{
|
||||||
int json_arg_num = have_record_arg ? 1 : 0;
|
int json_arg_num = have_record_arg ? 1 : 0;
|
||||||
@ -2048,8 +2018,8 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
|
|||||||
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* json{b}_to_record case */
|
{
|
||||||
|
/* json{b}_to_record case */
|
||||||
if (PG_ARGISNULL(0))
|
if (PG_ARGISNULL(0))
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
|
|
||||||
@ -2152,7 +2122,6 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
|
|||||||
ColumnIOData *column_info = &my_extra->columns[i];
|
ColumnIOData *column_info = &my_extra->columns[i];
|
||||||
Oid column_type = tupdesc->attrs[i]->atttypid;
|
Oid column_type = tupdesc->attrs[i]->atttypid;
|
||||||
JsonbValue *v = NULL;
|
JsonbValue *v = NULL;
|
||||||
char fname[NAMEDATALEN];
|
|
||||||
JsonHashEntry *hashentry = NULL;
|
JsonHashEntry *hashentry = NULL;
|
||||||
|
|
||||||
/* Ignore dropped columns in datatype */
|
/* Ignore dropped columns in datatype */
|
||||||
@ -2164,10 +2133,9 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
|
|||||||
|
|
||||||
if (jtype == JSONOID)
|
if (jtype == JSONOID)
|
||||||
{
|
{
|
||||||
|
hashentry = hash_search(json_hash,
|
||||||
memset(fname, 0, NAMEDATALEN);
|
NameStr(tupdesc->attrs[i]->attname),
|
||||||
strncpy(fname, NameStr(tupdesc->attrs[i]->attname), NAMEDATALEN);
|
HASH_FIND, NULL);
|
||||||
hashentry = hash_search(json_hash, fname, HASH_FIND, NULL);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2337,19 +2305,24 @@ hash_object_field_end(void *state, char *fname, bool isnull)
|
|||||||
JHashState *_state = (JHashState *) state;
|
JHashState *_state = (JHashState *) state;
|
||||||
JsonHashEntry *hashentry;
|
JsonHashEntry *hashentry;
|
||||||
bool found;
|
bool found;
|
||||||
char name[NAMEDATALEN];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ignore field names >= NAMEDATALEN - they can't match a record field
|
* Ignore nested fields.
|
||||||
* ignore nested fields.
|
|
||||||
*/
|
*/
|
||||||
if (_state->lex->lex_level > 2 || strlen(fname) >= NAMEDATALEN)
|
if (_state->lex->lex_level > 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memset(name, 0, NAMEDATALEN);
|
/*
|
||||||
strncpy(name, fname, NAMEDATALEN);
|
* Ignore field names >= NAMEDATALEN - they can't match a record field.
|
||||||
|
* (Note: without this test, the hash code would truncate the string at
|
||||||
|
* NAMEDATALEN-1, and could then match against a similarly-truncated
|
||||||
|
* record field name. That would be a reasonable behavior, but this code
|
||||||
|
* has previously insisted on exact equality, so we keep this behavior.)
|
||||||
|
*/
|
||||||
|
if (strlen(fname) >= NAMEDATALEN)
|
||||||
|
return;
|
||||||
|
|
||||||
hashentry = hash_search(_state->hash, name, HASH_ENTER, &found);
|
hashentry = hash_search(_state->hash, fname, HASH_ENTER, &found);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* found being true indicates a duplicate. We don't do anything about
|
* found being true indicates a duplicate. We don't do anything about
|
||||||
@ -2558,7 +2531,7 @@ make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state)
|
|||||||
/*
|
/*
|
||||||
* common worker for json_populate_recordset() and json_to_recordset()
|
* common worker for json_populate_recordset() and json_to_recordset()
|
||||||
*/
|
*/
|
||||||
static inline Datum
|
static Datum
|
||||||
populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
|
populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
|
||||||
{
|
{
|
||||||
int json_arg_num = have_record_arg ? 1 : 0;
|
int json_arg_num = have_record_arg ? 1 : 0;
|
||||||
@ -2596,7 +2569,6 @@ populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
|
|||||||
errmsg("set-valued function called in context that "
|
errmsg("set-valued function called in context that "
|
||||||
"cannot accept a set")));
|
"cannot accept a set")));
|
||||||
|
|
||||||
|
|
||||||
rsi->returnMode = SFRM_Materialize;
|
rsi->returnMode = SFRM_Materialize;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2669,7 +2641,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
|
|||||||
|
|
||||||
if (jtype == JSONOID)
|
if (jtype == JSONOID)
|
||||||
{
|
{
|
||||||
text *json = PG_GETARG_TEXT_P(have_record_arg ? 1 : 0);
|
text *json = PG_GETARG_TEXT_P(json_arg_num);
|
||||||
JsonLexContext *lex;
|
JsonLexContext *lex;
|
||||||
JsonSemAction *sem;
|
JsonSemAction *sem;
|
||||||
|
|
||||||
@ -2689,18 +2661,16 @@ populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
|
|||||||
state->lex = lex;
|
state->lex = lex;
|
||||||
|
|
||||||
pg_parse_json(lex, sem);
|
pg_parse_json(lex, sem);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Jsonb *jb;
|
Jsonb *jb = PG_GETARG_JSONB(json_arg_num);
|
||||||
JsonbIterator *it;
|
JsonbIterator *it;
|
||||||
JsonbValue v;
|
JsonbValue v;
|
||||||
bool skipNested = false;
|
bool skipNested = false;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
Assert(jtype == JSONBOID);
|
Assert(jtype == JSONBOID);
|
||||||
jb = PG_GETARG_JSONB(have_record_arg ? 1 : 0);
|
|
||||||
|
|
||||||
if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
|
if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -2730,7 +2700,6 @@ populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
|
|||||||
rsi->setDesc = state->ret_tdesc;
|
rsi->setDesc = state->ret_tdesc;
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -2774,7 +2743,6 @@ populate_recordset_object_end(void *state)
|
|||||||
HTAB *json_hash = _state->json_hash;
|
HTAB *json_hash = _state->json_hash;
|
||||||
Datum *values;
|
Datum *values;
|
||||||
bool *nulls;
|
bool *nulls;
|
||||||
char fname[NAMEDATALEN];
|
|
||||||
int i;
|
int i;
|
||||||
RecordIOData *my_extra = _state->my_extra;
|
RecordIOData *my_extra = _state->my_extra;
|
||||||
int ncolumns = my_extra->ncolumns;
|
int ncolumns = my_extra->ncolumns;
|
||||||
@ -2826,9 +2794,9 @@ populate_recordset_object_end(void *state)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(fname, 0, NAMEDATALEN);
|
hashentry = hash_search(json_hash,
|
||||||
strncpy(fname, NameStr(tupdesc->attrs[i]->attname), NAMEDATALEN);
|
NameStr(tupdesc->attrs[i]->attname),
|
||||||
hashentry = hash_search(json_hash, fname, HASH_FIND, NULL);
|
HASH_FIND, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we can't just skip here if the key wasn't found since we might have
|
* we can't just skip here if the key wasn't found since we might have
|
||||||
@ -2950,19 +2918,24 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull)
|
|||||||
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
|
PopulateRecordsetState *_state = (PopulateRecordsetState *) state;
|
||||||
JsonHashEntry *hashentry;
|
JsonHashEntry *hashentry;
|
||||||
bool found;
|
bool found;
|
||||||
char name[NAMEDATALEN];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ignore field names >= NAMEDATALEN - they can't match a record field
|
* Ignore nested fields.
|
||||||
* ignore nested fields.
|
|
||||||
*/
|
*/
|
||||||
if (_state->lex->lex_level > 2 || strlen(fname) >= NAMEDATALEN)
|
if (_state->lex->lex_level > 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memset(name, 0, NAMEDATALEN);
|
/*
|
||||||
strncpy(name, fname, NAMEDATALEN);
|
* Ignore field names >= NAMEDATALEN - they can't match a record field.
|
||||||
|
* (Note: without this test, the hash code would truncate the string at
|
||||||
|
* NAMEDATALEN-1, and could then match against a similarly-truncated
|
||||||
|
* record field name. That would be a reasonable behavior, but this code
|
||||||
|
* has previously insisted on exact equality, so we keep this behavior.)
|
||||||
|
*/
|
||||||
|
if (strlen(fname) >= NAMEDATALEN)
|
||||||
|
return;
|
||||||
|
|
||||||
hashentry = hash_search(_state->json_hash, name, HASH_ENTER, &found);
|
hashentry = hash_search(_state->json_hash, fname, HASH_ENTER, &found);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* found being true indicates a duplicate. We don't do anything about
|
* found being true indicates a duplicate. We don't do anything about
|
||||||
|
Loading…
x
Reference in New Issue
Block a user