]> granicus.if.org Git - postgresql/commitdiff
Rationalize error messages within jsonfuncs.c.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 25 Jun 2014 22:25:26 +0000 (15:25 -0700)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 25 Jun 2014 22:25:26 +0000 (15:25 -0700)
I noticed that the functions in jsonfuncs.c sometimes printed error
messages that claimed I'd called some other function.  Investigation showed
that this was from repurposing code into "worker" functions without taking
much care as to whether it would mention the right SQL-level function if it
threw an error.  Moreover, there was a weird mismash of messages that
contained a fixed function name, messages that used %s for a function name,
and messages that constructed a function name out of spare parts, like
"json%s_populate_record" (which, quite aside from being ugly as sin, wasn't
even sufficient to cover all the cases).  This would put an undue burden on
our long-suffering translators.  Standardize on inserting the SQL function
name with %s so as to reduce the number of translatable strings, and pass
function names around as needed to make sure we can report the right one.
Fix up some gratuitous variations in wording, too.

src/backend/utils/adt/jsonfuncs.c
src/test/regress/expected/jsonb.out
src/test/regress/expected/jsonb_1.out

index 69508627869a7bdf9eb083a61679edd6fd4de694..bd1241b620fa17a61a45a441da48f9d769585d31 100644 (file)
@@ -48,11 +48,13 @@ static void get_array_element_end(void *state, bool isnull);
 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);
@@ -61,7 +63,8 @@ static void alen_array_element_start(void *state, bool isnull);
 
 /* 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);
@@ -70,8 +73,10 @@ static void each_array_start(void *state);
 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);
@@ -80,10 +85,11 @@ static void elements_array_element_end(void *state, bool isnull);
 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 */
@@ -102,7 +108,7 @@ static void populate_recordset_array_start(void *state);
 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 */
@@ -174,6 +180,7 @@ typedef struct EachState
 typedef struct ElementsState
 {
        JsonLexContext *lex;
+       const char *function_name;
        Tuplestorestate *tuple_store;
        TupleDesc       ret_tdesc;
        MemoryContext tmp_cxt;
@@ -187,11 +194,11 @@ typedef struct ElementsState
 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 */
@@ -224,6 +231,7 @@ typedef struct RecordIOData
 typedef struct PopulateRecordsetState
 {
        JsonLexContext *lex;
+       const char *function_name;
        HTAB       *json_hash;
        char       *saved_scalar;
        char       *save_json_start;
@@ -270,11 +278,13 @@ jsonb_object_keys(PG_FUNCTION_ARGS)
                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);
@@ -420,7 +430,8 @@ okeys_array_start(void *state)
        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
@@ -432,7 +443,8 @@ okeys_scalar(void *state, char *token, JsonTokenType tokentype)
        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")));
 }
 
 /*
@@ -468,11 +480,13 @@ jsonb_object_field(PG_FUNCTION_ARGS)
        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));
 
@@ -511,11 +525,13 @@ jsonb_object_field_text(PG_FUNCTION_ARGS)
        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));
 
@@ -549,7 +565,7 @@ jsonb_object_field_text(PG_FUNCTION_ARGS)
                                }
                                break;
                        default:
-                               elog(ERROR, "Wrong jsonb type: %d", v->type);
+                               elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
                }
 
                if (result)
@@ -584,11 +600,13 @@ jsonb_array_element(PG_FUNCTION_ARGS)
        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));
 
@@ -624,11 +642,13 @@ jsonb_array_element_text(PG_FUNCTION_ARGS)
        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));
 
@@ -660,7 +680,7 @@ jsonb_array_element_text(PG_FUNCTION_ARGS)
                                }
                                break;
                        default:
-                               elog(ERROR, "Wrong jsonb type: %d", v->type);
+                               elog(ERROR, "unrecognized jsonb type: %d", (int) v->type);
                }
 
                if (result)
@@ -673,20 +693,20 @@ jsonb_array_element_text(PG_FUNCTION_ARGS)
 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);
@@ -703,7 +723,8 @@ get_path_all(FunctionCallInfo fcinfo, bool as_text)
        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);
@@ -715,10 +736,10 @@ get_path_all(FunctionCallInfo fcinfo, bool as_text)
        {
                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
@@ -798,8 +819,8 @@ get_worker(text *json,
        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;
@@ -1068,17 +1089,17 @@ get_scalar(void *state, char *token, JsonTokenType tokentype)
 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);
@@ -1096,7 +1117,8 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
        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);
@@ -1135,7 +1157,7 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
                        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();
                }
 
@@ -1290,7 +1312,7 @@ json_each(PG_FUNCTION_ARGS)
 Datum
 jsonb_each(PG_FUNCTION_ARGS)
 {
-       return each_worker_jsonb(fcinfo, false);
+       return each_worker_jsonb(fcinfo, "jsonb_each", false);
 }
 
 Datum
@@ -1302,11 +1324,11 @@ json_each_text(PG_FUNCTION_ARGS)
 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;
@@ -1323,8 +1345,8 @@ each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
        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;
 
@@ -1614,17 +1636,18 @@ each_scalar(void *state, char *token, JsonTokenType tokentype)
 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;
@@ -1751,17 +1774,17 @@ elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
 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);
 
@@ -1808,6 +1831,7 @@ elements_worker(FunctionCallInfo fcinfo, bool as_text)
        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;
@@ -1900,7 +1924,8 @@ elements_object_start(void *state)
        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
@@ -1912,7 +1937,8 @@ elements_scalar(void *state, char *token, JsonTokenType tokentype)
        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)
@@ -1934,29 +1960,30 @@ elements_scalar(void *state, char *token, JsonTokenType tokentype)
 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);
@@ -1988,7 +2015,8 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
                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))
                {
@@ -2037,7 +2065,7 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
                /* 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
@@ -2206,7 +2234,7 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
                                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,
@@ -2238,7 +2266,7 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
  * 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;
@@ -2385,25 +2413,25 @@ hash_scalar(void *state, char *token, JsonTokenType tokentype)
 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
@@ -2514,7 +2542,7 @@ make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state)
                        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,
@@ -2532,7 +2560,8 @@ make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state)
  * 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);
@@ -2556,7 +2585,8 @@ populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
                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;
@@ -2634,6 +2664,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
                                                                                           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;
@@ -2675,7 +2706,8 @@ populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
                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);
 
@@ -2690,7 +2722,8 @@ populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
                                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);
                        }
                }
@@ -2713,7 +2746,8 @@ populate_recordset_object_start(void *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)
@@ -2721,7 +2755,8 @@ populate_recordset_object_start(void *state)
                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;
        }
 
@@ -2861,7 +2896,8 @@ populate_recordset_array_element_start(void *state, bool isnull)
                _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
@@ -2872,7 +2908,8 @@ populate_recordset_array_start(void *state)
        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
@@ -2883,7 +2920,8 @@ populate_recordset_scalar(void *state, char *token, JsonTokenType tokentype)
        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;
@@ -2903,7 +2941,8 @@ populate_recordset_object_field_start(void *state, char *fname, bool isnull)
                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
index 1e46939b6fe9c28a169d0a234c33ada46fdb8ccc..6bc789de293df8c187f6be5ac4bf8c3b7f5b06c4 100644 (file)
@@ -311,9 +311,9 @@ INSERT INTO test_jsonb VALUES
 ('array','["zero", "one","two",null,"four","five", [1,2,3],{"f1":9}]'),
 ('object','{"field1":"val1","field2":"val2","field3":null, "field4": 4, "field5": [1,2,3], "field6": {"f1":9}}');
 SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'scalar';
-ERROR:  cannot call jsonb_object_field (jsonb -> text operator) on a scalar
+ERROR:  cannot call jsonb_object_field (jsonb -> text) on a scalar
 SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'array';
-ERROR:  cannot call jsonb_object_field (jsonb -> text operator) on an array
+ERROR:  cannot call jsonb_object_field (jsonb -> text) on an array
 SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'object';
  ?column? 
 ----------
@@ -327,9 +327,9 @@ SELECT test_json -> 'field2' FROM test_jsonb WHERE json_type = 'object';
 (1 row)
 
 SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'scalar';
-ERROR:  cannot call jsonb_object_field_text (jsonb ->> text operator) on a scalar
+ERROR:  cannot call jsonb_object_field_text (jsonb ->> text) on a scalar
 SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'array';
-ERROR:  cannot call jsonb_object_field_text (jsonb ->> text operator) on an array
+ERROR:  cannot call jsonb_object_field_text (jsonb ->> text) on an array
 SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'object';
  ?column? 
 ----------
@@ -337,7 +337,7 @@ SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'object';
 (1 row)
 
 SELECT test_json -> 2 FROM test_jsonb WHERE json_type = 'scalar';
-ERROR:  cannot call jsonb_array_element (jsonb -> int operator) on a scalar
+ERROR:  cannot call jsonb_array_element (jsonb -> int) on a scalar
 SELECT test_json -> 2 FROM test_jsonb WHERE json_type = 'array';
  ?column? 
 ----------
@@ -351,7 +351,7 @@ SELECT test_json -> 9 FROM test_jsonb WHERE json_type = 'array';
 (1 row)
 
 SELECT test_json -> 2 FROM test_jsonb WHERE json_type = 'object';
-ERROR:  cannot call jsonb_array_element (jsonb -> int operator) on an object
+ERROR:  cannot call jsonb_array_element (jsonb -> int) on an object
 SELECT test_json ->> 6 FROM test_jsonb WHERE json_type = 'array';
  ?column?  
 -----------
@@ -1229,13 +1229,13 @@ SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>'{f2,1}';
 
 -- same on jsonb scalars (expecting errors)
 SELECT '42'::jsonb#>array['f2'];
-ERROR:  cannot call extract path from a scalar
+ERROR:  cannot extract path from a scalar
 SELECT '42'::jsonb#>array['0'];
-ERROR:  cannot call extract path from a scalar
+ERROR:  cannot extract path from a scalar
 SELECT '42'::jsonb#>>array['f2'];
-ERROR:  cannot call extract path from a scalar
+ERROR:  cannot extract path from a scalar
 SELECT '42'::jsonb#>>array['0'];
-ERROR:  cannot call extract path from a scalar
+ERROR:  cannot extract path from a scalar
 -- array_elements
 SELECT jsonb_array_elements('[1,true,[1,[2,3]],null,{"f1":1,"f2":[7,8,9]},false]');
     jsonb_array_elements    
@@ -1923,7 +1923,7 @@ SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'e';
 (1 row)
 
 SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 0; --expecting error
-ERROR:  cannot call jsonb_array_element (jsonb -> int operator) on an object
+ERROR:  cannot call jsonb_array_element (jsonb -> int) on an object
 SELECT '["a","b","c",[1,2],null]'::jsonb -> 0;
  ?column? 
 ----------
index 955dc424dce1b42237d7549b6b079b2a49133d8d..0c861d3b2940db051cf0c9040c7f86fe735fa92d 100644 (file)
@@ -311,9 +311,9 @@ INSERT INTO test_jsonb VALUES
 ('array','["zero", "one","two",null,"four","five", [1,2,3],{"f1":9}]'),
 ('object','{"field1":"val1","field2":"val2","field3":null, "field4": 4, "field5": [1,2,3], "field6": {"f1":9}}');
 SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'scalar';
-ERROR:  cannot call jsonb_object_field (jsonb -> text operator) on a scalar
+ERROR:  cannot call jsonb_object_field (jsonb -> text) on a scalar
 SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'array';
-ERROR:  cannot call jsonb_object_field (jsonb -> text operator) on an array
+ERROR:  cannot call jsonb_object_field (jsonb -> text) on an array
 SELECT test_json -> 'x' FROM test_jsonb WHERE json_type = 'object';
  ?column? 
 ----------
@@ -327,9 +327,9 @@ SELECT test_json -> 'field2' FROM test_jsonb WHERE json_type = 'object';
 (1 row)
 
 SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'scalar';
-ERROR:  cannot call jsonb_object_field_text (jsonb ->> text operator) on a scalar
+ERROR:  cannot call jsonb_object_field_text (jsonb ->> text) on a scalar
 SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'array';
-ERROR:  cannot call jsonb_object_field_text (jsonb ->> text operator) on an array
+ERROR:  cannot call jsonb_object_field_text (jsonb ->> text) on an array
 SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'object';
  ?column? 
 ----------
@@ -337,7 +337,7 @@ SELECT test_json ->> 'field2' FROM test_jsonb WHERE json_type = 'object';
 (1 row)
 
 SELECT test_json -> 2 FROM test_jsonb WHERE json_type = 'scalar';
-ERROR:  cannot call jsonb_array_element (jsonb -> int operator) on a scalar
+ERROR:  cannot call jsonb_array_element (jsonb -> int) on a scalar
 SELECT test_json -> 2 FROM test_jsonb WHERE json_type = 'array';
  ?column? 
 ----------
@@ -351,7 +351,7 @@ SELECT test_json -> 9 FROM test_jsonb WHERE json_type = 'array';
 (1 row)
 
 SELECT test_json -> 2 FROM test_jsonb WHERE json_type = 'object';
-ERROR:  cannot call jsonb_array_element (jsonb -> int operator) on an object
+ERROR:  cannot call jsonb_array_element (jsonb -> int) on an object
 SELECT test_json ->> 6 FROM test_jsonb WHERE json_type = 'array';
  ?column?  
 -----------
@@ -1229,13 +1229,13 @@ SELECT '{"f2":["f3",1],"f4":{"f5":99,"f6":"stringy"}}'::jsonb#>>'{f2,1}';
 
 -- same on jsonb scalars (expecting errors)
 SELECT '42'::jsonb#>array['f2'];
-ERROR:  cannot call extract path from a scalar
+ERROR:  cannot extract path from a scalar
 SELECT '42'::jsonb#>array['0'];
-ERROR:  cannot call extract path from a scalar
+ERROR:  cannot extract path from a scalar
 SELECT '42'::jsonb#>>array['f2'];
-ERROR:  cannot call extract path from a scalar
+ERROR:  cannot extract path from a scalar
 SELECT '42'::jsonb#>>array['0'];
-ERROR:  cannot call extract path from a scalar
+ERROR:  cannot extract path from a scalar
 -- array_elements
 SELECT jsonb_array_elements('[1,true,[1,[2,3]],null,{"f1":1,"f2":[7,8,9]},false]');
     jsonb_array_elements    
@@ -1923,7 +1923,7 @@ SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 'e';
 (1 row)
 
 SELECT '{"n":null,"a":1,"b":[1,2],"c":{"1":2},"d":{"1":[2,3]}}'::jsonb -> 0; --expecting error
-ERROR:  cannot call jsonb_array_element (jsonb -> int operator) on an object
+ERROR:  cannot call jsonb_array_element (jsonb -> int) on an object
 SELECT '["a","b","c",[1,2],null]'::jsonb -> 0;
  ?column? 
 ----------