Commit 8d2d7ad5 authored by Tom Lane's avatar Tom Lane

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.
parent 57d8c127
...@@ -16,19 +16,19 @@ ...@@ -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); ...@@ -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); ...@@ -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); ...@@ -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); ...@@ -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,7 +102,7 @@ static void populate_recordset_array_start(void *state); ...@@ -102,7 +102,7 @@ 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 */
...@@ -194,10 +194,10 @@ typedef struct JhashState ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ...@@ -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);
...@@ -493,9 +489,9 @@ Datum ...@@ -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);
...@@ -530,7 +526,7 @@ jsonb_object_field_text(PG_FUNCTION_ARGS) ...@@ -530,7 +526,7 @@ jsonb_object_field_text(PG_FUNCTION_ARGS)
{ {
text *result = NULL; text *result = NULL;
switch(v->type) switch (v->type)
{ {
case jbvNull: case jbvNull:
break; break;
...@@ -567,8 +563,8 @@ Datum ...@@ -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 ...@@ -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) ...@@ -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;
...@@ -689,10 +685,10 @@ json_extract_path_text(PG_FUNCTION_ARGS) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment