static void 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);
+static Datum get_path_all(FunctionCallInfo fcinfo, const char *funcname,
+ bool as_text);
static text *get_worker(text *json, char *field, int elem_index,
char **tpath, int *ipath, int npath,
bool normalize_results);
-static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text);
+static Datum get_jsonb_path_all(FunctionCallInfo fcinfo, const char *funcname,
+ bool as_text);
/* semantic action functions for json_array_length */
static void alen_object_start(void *state);
/* common workers for json{b}_each* functions */
static Datum each_worker(FunctionCallInfo fcinfo, bool as_text);
-static Datum each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text);
+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_scalar(void *state, char *token, JsonTokenType tokentype);
/* common workers for json{b}_array_elements_* functions */
-static Datum elements_worker(FunctionCallInfo fcinfo, bool as_text);
-static Datum elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text);
+static Datum elements_worker(FunctionCallInfo fcinfo, const char *funcname,
+ bool as_text);
+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_scalar(void *state, char *token, JsonTokenType tokentype);
/* turn a json object into a hash table */
-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, const char *funcname,
+ bool use_json_as_text);
/* common worker for populate_record and to_record */
-static Datum populate_record_worker(FunctionCallInfo fcinfo,
+static Datum populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
bool have_record_arg);
/* semantic action functions for get_json_object_as_hash */
static void populate_recordset_array_element_start(void *state, bool isnull);
/* worker function for populate_recordset and to_recordset */
-static Datum populate_recordset_worker(FunctionCallInfo fcinfo,
+static Datum populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
bool have_record_arg);
/* Worker that takes care of common setup for us */
typedef struct ElementsState
{
JsonLexContext *lex;
+ const char *function_name;
Tuplestorestate *tuple_store;
TupleDesc ret_tdesc;
MemoryContext tmp_cxt;
typedef struct JhashState
{
JsonLexContext *lex;
+ const char *function_name;
HTAB *hash;
char *saved_scalar;
char *save_json_start;
bool use_json_as_text;
- char *function_name;
} JHashState;
/* hashtable element */
typedef struct PopulateRecordsetState
{
JsonLexContext *lex;
+ const char *function_name;
HTAB *json_hash;
char *saved_scalar;
char *save_json_start;
if (JB_ROOT_IS_SCALAR(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call jsonb_object_keys on a scalar")));
+ errmsg("cannot call %s on a scalar",
+ "jsonb_object_keys")));
else if (JB_ROOT_IS_ARRAY(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call jsonb_object_keys on an array")));
+ errmsg("cannot call %s on an array",
+ "jsonb_object_keys")));
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
if (_state->lex->lex_level == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call json_object_keys on an array")));
+ errmsg("cannot call %s on an array",
+ "json_object_keys")));
}
static void
if (_state->lex->lex_level == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call json_object_keys on a scalar")));
+ errmsg("cannot call %s on a scalar",
+ "json_object_keys")));
}
/*
if (JB_ROOT_IS_SCALAR(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call jsonb_object_field (jsonb -> text operator) on a scalar")));
+ errmsg("cannot call %s on a scalar",
+ "jsonb_object_field (jsonb -> text)")));
else if (JB_ROOT_IS_ARRAY(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call jsonb_object_field (jsonb -> text operator) on an array")));
+ errmsg("cannot call %s on an array",
+ "jsonb_object_field (jsonb -> text)")));
Assert(JB_ROOT_IS_OBJECT(jb));
if (JB_ROOT_IS_SCALAR(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call jsonb_object_field_text (jsonb ->> text operator) on a scalar")));
+ errmsg("cannot call %s on a scalar",
+ "jsonb_object_field_text (jsonb ->> text)")));
else if (JB_ROOT_IS_ARRAY(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call jsonb_object_field_text (jsonb ->> text operator) on an array")));
+ errmsg("cannot call %s on an array",
+ "jsonb_object_field_text (jsonb ->> text)")));
Assert(JB_ROOT_IS_OBJECT(jb));
}
break;
default:
- elog(ERROR, "Wrong jsonb type: %d", v->type);
+ elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
}
if (result)
if (JB_ROOT_IS_SCALAR(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call jsonb_array_element (jsonb -> int operator) on a scalar")));
+ errmsg("cannot call %s on a scalar",
+ "jsonb_array_element (jsonb -> int)")));
else if (JB_ROOT_IS_OBJECT(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call jsonb_array_element (jsonb -> int operator) on an object")));
+ errmsg("cannot call %s on an object",
+ "jsonb_array_element (jsonb -> int)")));
Assert(JB_ROOT_IS_ARRAY(jb));
if (JB_ROOT_IS_SCALAR(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call jsonb_array_element_text on a scalar")));
+ errmsg("cannot call %s on a scalar",
+ "jsonb_array_element_text")));
else if (JB_ROOT_IS_OBJECT(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call jsonb_array_element_text on an object")));
+ errmsg("cannot call %s on an object",
+ "jsonb_array_element_text")));
Assert(JB_ROOT_IS_ARRAY(jb));
}
break;
default:
- elog(ERROR, "Wrong jsonb type: %d", v->type);
+ elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
}
if (result)
Datum
json_extract_path(PG_FUNCTION_ARGS)
{
- return get_path_all(fcinfo, false);
+ return get_path_all(fcinfo, "json_extract_path", false);
}
Datum
json_extract_path_text(PG_FUNCTION_ARGS)
{
- return get_path_all(fcinfo, true);
+ return get_path_all(fcinfo, "json_extract_path_text", true);
}
/*
* common routine for extract_path functions
*/
static Datum
-get_path_all(FunctionCallInfo fcinfo, bool as_text)
+get_path_all(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
{
text *json = PG_GETARG_TEXT_P(0);
ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
if (array_contains_nulls(path))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call function with null path elements")));
+ errmsg("cannot call %s with null path elements",
+ funcname)));
deconstruct_array(path, TEXTOID, -1, false, 'i',
&pathtext, &pathnulls, &npath);
{
tpath[i] = TextDatumGetCString(pathtext[i]);
if (*tpath[i] == '\0')
- ereport(
- ERROR,
+ ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call function with empty path elements")));
+ errmsg("cannot call %s with empty path elements",
+ funcname)));
/*
* we have no idea at this stage what structure the document is so
sem->semstate = (void *) state;
/*
- * Not all variants need all the semantic routines. only set the ones
- * that are actually needed for maximum efficiency.
+ * Not all variants need all the semantic routines. Only set the ones that
+ * are actually needed for maximum efficiency.
*/
sem->object_start = get_object_start;
sem->array_start = get_array_start;
Datum
jsonb_extract_path(PG_FUNCTION_ARGS)
{
- return get_jsonb_path_all(fcinfo, false);
+ return get_jsonb_path_all(fcinfo, "jsonb_extract_path", false);
}
Datum
jsonb_extract_path_text(PG_FUNCTION_ARGS)
{
- return get_jsonb_path_all(fcinfo, true);
+ return get_jsonb_path_all(fcinfo, "jsonb_extract_path_text", true);
}
static Datum
-get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
+get_jsonb_path_all(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
{
Jsonb *jb = PG_GETARG_JSONB(0);
ArrayType *path = PG_GETARG_ARRAYTYPE_P(1);
if (array_contains_nulls(path))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call function with null path elements")));
+ errmsg("cannot call %s with null path elements",
+ funcname)));
deconstruct_array(path, TEXTOID, -1, false, 'i',
&pathtext, &pathnulls, &npath);
if (i == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call extract path from a scalar")));
+ errmsg("cannot extract path from a scalar")));
PG_RETURN_NULL();
}
Datum
jsonb_each(PG_FUNCTION_ARGS)
{
- return each_worker_jsonb(fcinfo, false);
+ return each_worker_jsonb(fcinfo, "jsonb_each", false);
}
Datum
Datum
jsonb_each_text(PG_FUNCTION_ARGS)
{
- return each_worker_jsonb(fcinfo, true);
+ return each_worker_jsonb(fcinfo, "jsonb_each_text", true);
}
static Datum
-each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
+each_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
{
Jsonb *jb = PG_GETARG_JSONB(0);
ReturnSetInfo *rsi;
if (!JB_ROOT_IS_OBJECT(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call jsonb_each%s on a non-object",
- as_text ? "_text" : "")));
+ errmsg("cannot call %s on a non-object",
+ funcname)));
rsi = (ReturnSetInfo *) fcinfo->resultinfo;
Datum
jsonb_array_elements(PG_FUNCTION_ARGS)
{
- return elements_worker_jsonb(fcinfo, false);
+ return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
}
Datum
jsonb_array_elements_text(PG_FUNCTION_ARGS)
{
- return elements_worker_jsonb(fcinfo, true);
+ return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
}
static Datum
-elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
+elements_worker_jsonb(FunctionCallInfo fcinfo, const char *funcname,
+ bool as_text)
{
Jsonb *jb = PG_GETARG_JSONB(0);
ReturnSetInfo *rsi;
Datum
json_array_elements(PG_FUNCTION_ARGS)
{
- return elements_worker(fcinfo, false);
+ return elements_worker(fcinfo, "json_array_elements", false);
}
Datum
json_array_elements_text(PG_FUNCTION_ARGS)
{
- return elements_worker(fcinfo, true);
+ return elements_worker(fcinfo, "json_array_elements_text", true);
}
static Datum
-elements_worker(FunctionCallInfo fcinfo, bool as_text)
+elements_worker(FunctionCallInfo fcinfo, const char *funcname, bool as_text)
{
text *json = PG_GETARG_TEXT_P(0);
sem->array_element_start = elements_array_element_start;
sem->array_element_end = elements_array_element_end;
+ state->function_name = funcname;
state->normalize_results = as_text;
state->next_scalar = false;
state->lex = lex;
if (_state->lex->lex_level == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call json_array_elements on a non-array")));
+ errmsg("cannot call %s on a non-array",
+ _state->function_name)));
}
static void
if (_state->lex->lex_level == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call json_array_elements on a scalar")));
+ errmsg("cannot call %s on a scalar",
+ _state->function_name)));
/* supply de-escaped value if required */
if (_state->next_scalar)
Datum
jsonb_populate_record(PG_FUNCTION_ARGS)
{
- return populate_record_worker(fcinfo, true);
+ return populate_record_worker(fcinfo, "jsonb_populate_record", true);
}
Datum
jsonb_to_record(PG_FUNCTION_ARGS)
{
- return populate_record_worker(fcinfo, false);
+ return populate_record_worker(fcinfo, "jsonb_to_record", false);
}
Datum
json_populate_record(PG_FUNCTION_ARGS)
{
- return populate_record_worker(fcinfo, true);
+ return populate_record_worker(fcinfo, "json_populate_record", true);
}
Datum
json_to_record(PG_FUNCTION_ARGS)
{
- return populate_record_worker(fcinfo, false);
+ return populate_record_worker(fcinfo, "json_to_record", false);
}
static Datum
-populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
+populate_record_worker(FunctionCallInfo fcinfo, const char *funcname,
+ bool have_record_arg)
{
int json_arg_num = have_record_arg ? 1 : 0;
Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
if (!type_is_rowtype(argtype))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("first argument of json%s_populate_record must be a row type", jtype == JSONBOID ? "b" : "")));
+ errmsg("first argument of %s must be a row type",
+ funcname)));
if (PG_ARGISNULL(0))
{
/* just get the text */
json = PG_GETARG_TEXT_P(json_arg_num);
- json_hash = get_json_object_as_hash(json, "json_populate_record", use_json_as_text);
+ json_hash = get_json_object_as_hash(json, funcname, use_json_as_text);
/*
* if the input json is empty, we can only skip the rest if we were
else if (v->type == jbvBinary)
s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
else
- elog(ERROR, "invalid jsonb type");
+ elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
}
values[i] = InputFunctionCall(&column_info->proc, s,
* error messages.
*/
static HTAB *
-get_json_object_as_hash(text *json, char *funcname, bool use_json_as_text)
+get_json_object_as_hash(text *json, const char *funcname, bool use_json_as_text)
{
HASHCTL ctl;
HTAB *tab;
Datum
jsonb_populate_recordset(PG_FUNCTION_ARGS)
{
- return populate_recordset_worker(fcinfo, true);
+ return populate_recordset_worker(fcinfo, "jsonb_populate_recordset", true);
}
Datum
jsonb_to_recordset(PG_FUNCTION_ARGS)
{
- return populate_recordset_worker(fcinfo, false);
+ return populate_recordset_worker(fcinfo, "jsonb_to_recordset", false);
}
Datum
json_populate_recordset(PG_FUNCTION_ARGS)
{
- return populate_recordset_worker(fcinfo, true);
+ return populate_recordset_worker(fcinfo, "json_populate_recordset", true);
}
Datum
json_to_recordset(PG_FUNCTION_ARGS)
{
- return populate_recordset_worker(fcinfo, false);
+ return populate_recordset_worker(fcinfo, "json_to_recordset", false);
}
static void
else if (v->type == jbvBinary)
s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
else
- elog(ERROR, "invalid jsonb type");
+ elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
values[i] = InputFunctionCall(&column_info->proc, s,
column_info->typioparam,
* common worker for json_populate_recordset() and json_to_recordset()
*/
static Datum
-populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
+populate_recordset_worker(FunctionCallInfo fcinfo, const char *funcname,
+ bool have_record_arg)
{
int json_arg_num = have_record_arg ? 1 : 0;
Oid jtype = get_fn_expr_argtype(fcinfo->flinfo, json_arg_num);
if (!type_is_rowtype(argtype))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("first argument must be a row type")));
+ errmsg("first argument of %s must be a row type",
+ funcname)));
}
rsi = (ReturnSetInfo *) fcinfo->resultinfo;
false, work_mem);
MemoryContextSwitchTo(old_cxt);
+ state->function_name = funcname;
state->my_extra = my_extra;
state->rec = rec;
state->use_json_as_text = use_json_as_text;
if (JB_ROOT_IS_SCALAR(jb) || !JB_ROOT_IS_ARRAY(jb))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call jsonb_populate_recordset on non-array")));
+ errmsg("cannot call %s on a non-array",
+ funcname)));
it = JsonbIteratorInit(&jb->root);
if (!JB_ROOT_IS_OBJECT(element))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("jsonb_populate_recordset argument must be an array of objects")));
+ errmsg("argument of %s must be an array of objects",
+ funcname)));
make_row_from_rec_and_jsonb(element, state);
}
}
if (lex_level == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call json_populate_recordset on an object")));
+ errmsg("cannot call %s on an object",
+ _state->function_name)));
/* Nested objects, if allowed, require no special processing */
if (lex_level > 1)
if (!_state->use_json_as_text)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call json_populate_recordset with nested objects")));
+ errmsg("cannot call %s with nested objects",
+ _state->function_name)));
return;
}
_state->lex->token_type != JSON_TOKEN_OBJECT_START)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("must call json_populate_recordset on an array of objects")));
+ errmsg("argument of %s must be an array of objects",
+ _state->function_name)));
}
static void
if (_state->lex->lex_level != 0 && !_state->use_json_as_text)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call json_populate_recordset with nested arrays")));
+ errmsg("cannot call %s with nested arrays",
+ _state->function_name)));
}
static void
if (_state->lex->lex_level == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call json_populate_recordset on a scalar")));
+ errmsg("cannot call %s on a scalar",
+ _state->function_name)));
if (_state->lex->lex_level == 2)
_state->saved_scalar = token;
if (!_state->use_json_as_text)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("cannot call json_populate_recordset on a nested object")));
+ errmsg("cannot call %s on a nested object",
+ _state->function_name)));
_state->save_json_start = _state->lex->token_start;
}
else