32 #include "utils/fmgroids.h"
43 #define JB_PATH_CREATE 0x0001
44 #define JB_PATH_DELETE 0x0002
45 #define JB_PATH_REPLACE 0x0004
46 #define JB_PATH_INSERT_BEFORE 0x0008
47 #define JB_PATH_INSERT_AFTER 0x0010
48 #define JB_PATH_CREATE_OR_INSERT \
49 (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
50 #define JB_PATH_FILL_GAPS 0x0020
51 #define JB_PATH_CONSISTENT_POSITION 0x0040
317 #define JsValueIsNull(jsv) \
319 (!(jsv)->val.json.str || (jsv)->val.json.type == JSON_TOKEN_NULL) : \
320 (!(jsv)->val.jsonb || (jsv)->val.jsonb->type == jbvNull))
322 #define JsValueIsString(jsv) \
323 ((jsv)->is_json ? (jsv)->val.json.type == JSON_TOKEN_STRING \
324 : ((jsv)->val.jsonb && (jsv)->val.jsonb->type == jbvString))
326 #define JsObjectIsEmpty(jso) \
328 ? hash_get_num_entries((jso)->val.json_hash) == 0 \
329 : ((jso)->val.jsonb_cont == NULL || \
330 JsonContainerSize((jso)->val.jsonb_cont) == 0))
332 #define JsObjectFree(jso) \
334 if ((jso)->is_json) \
335 hash_destroy((jso)->val.json_hash); \
359 bool normalize_results);
427 bool is_json,
bool have_record_arg);
429 bool is_json,
bool have_record_arg);
470 bool *path_nulls,
int path_len,
566 bool skipNested =
false;
573 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
574 errmsg(
"cannot call %s on a scalar",
575 "jsonb_object_keys")));
578 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
579 errmsg(
"cannot call %s on an array",
580 "jsonb_object_keys")));
588 state->result_count = 0;
589 state->sent_count = 0;
602 cstr =
palloc(v.
val.string.len + 1 *
sizeof(
char));
603 memcpy(cstr, v.
val.string.val, v.
val.string.len);
604 cstr[v.
val.string.len] =
'\0';
618 char *nxt =
state->result[
state->sent_count++];
637 (
errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
638 errmsg(
"unsupported Unicode escape sequence"),
645 elog(
ERROR,
"JSON semantic action function did not provide error information");
649 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
650 errmsg(
"invalid input syntax for type %s",
"json"),
668 const char *context_start;
669 const char *context_end;
670 const char *line_start;
678 context_start = line_start;
680 Assert(context_end >= context_start);
683 while (context_end - context_start >= 50)
687 context_start +=
pg_mblen(context_start);
697 if (context_start - line_start <= 3)
698 context_start = line_start;
701 ctxtlen = context_end - context_start;
702 ctxt =
palloc(ctxtlen + 1);
703 memcpy(ctxt, context_start, ctxtlen);
704 ctxt[ctxtlen] =
'\0';
710 prefix = (context_start > line_start) ?
"..." :
"";
713 *context_end !=
'\n' && *context_end !=
'\r') ?
"..." :
"";
715 return errcontext(
"JSON data, line %d: %s%s%s",
740 state->result_size = 256;
741 state->result_count = 0;
742 state->sent_count = 0;
766 char *nxt =
state->result[
state->sent_count++];
787 _state->
result = (
char **)
805 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
806 errmsg(
"cannot call %s on an array",
807 "json_object_keys")));
820 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
821 errmsg(
"cannot call %s on a scalar",
822 "json_object_keys")));
842 result =
get_worker(json, &fnamestr, NULL, 1,
false);
880 result =
get_worker(json, &fnamestr, NULL, 1,
true);
1037 tpath =
palloc(npath *
sizeof(
char *));
1038 ipath =
palloc(npath *
sizeof(
int));
1040 for (
i = 0;
i < npath;
i++)
1050 if (*tpath[
i] !=
'\0')
1057 if (endptr == tpath[
i] || *endptr !=
'\0' || errno != 0)
1066 result =
get_worker(json, tpath, ipath, npath, as_text);
1096 bool normalize_results)
1106 state->normalize_results = normalize_results;
1107 state->npath = npath;
1108 state->path_names = tpath;
1109 state->path_indexes = ipath;
1111 state->array_cur_index =
palloc(
sizeof(
int) * npath);
1114 state->pathok[0] =
true;
1145 return state->tresult;
1154 if (lex_level == 0 && _state->
npath == 0)
1173 if (lex_level == 0 && _state->
npath == 0)
1189 bool get_next =
false;
1192 if (lex_level <= _state->npath &&
1193 _state->
pathok[lex_level - 1] &&
1196 strcmp(fname, _state->
path_names[lex_level - 1]) == 0)
1198 if (lex_level < _state->npath)
1201 _state->
pathok[lex_level] =
true;
1236 bool get_last =
false;
1240 if (lex_level <= _state->npath &&
1241 _state->
pathok[lex_level - 1] &&
1244 strcmp(fname, _state->
path_names[lex_level - 1]) == 0)
1246 if (lex_level < _state->npath)
1249 _state->
pathok[lex_level] =
false;
1289 if (lex_level < _state->npath)
1310 else if (lex_level == 0 && _state->
npath == 0)
1329 if (lex_level == 0 && _state->
npath == 0)
1345 bool get_next =
false;
1349 if (lex_level <= _state->npath)
1352 if (lex_level <= _state->npath &&
1353 _state->
pathok[lex_level - 1] &&
1357 if (lex_level < _state->npath)
1360 _state->
pathok[lex_level] =
true;
1393 bool get_last =
false;
1397 if (lex_level <= _state->npath &&
1398 _state->
pathok[lex_level - 1] &&
1402 if (lex_level < _state->npath)
1405 _state->
pathok[lex_level] =
false;
1440 if (lex_level == 0 && _state->
npath == 0)
1525 bool have_object =
false,
1551 if (npath <= 0 && jbvp == NULL)
1566 for (
i = 0;
i < npath;
i++)
1577 else if (have_array)
1585 lindex =
strtoint(indextext, &endptr, 10);
1586 if (endptr == indextext || *endptr !=
'\0' || errno != 0)
1607 if (lindex == INT_MIN || -lindex > nelements)
1613 index = nelements + lindex;
1630 else if (
i == npath - 1)
1635 container = jbvp->
val.binary.data;
1643 have_object =
false;
1674 bool *path_nulls =
palloc0(path_len *
sizeof(
bool));
1727 for (
int i = level + 1;
i < path_len;
i++)
1743 if (badp ==
c || *badp !=
'\0' || errno != 0)
1747 newkey.
val.string.val =
c;
1748 newkey.
val.string.len = strlen(
c);
1767 if (tpath[(path_len - level) - 1] ==
jbvArray)
1778 for (
int i = path_len - 1;
i > level;
i--)
1802 return v->
val.boolean ?
1873 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1874 errmsg(
"cannot get array length of a scalar")));
1877 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1878 errmsg(
"cannot get array length of a non-array")));
1896 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1897 errmsg(
"cannot get array length of a non-array")));
1910 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1911 errmsg(
"cannot get array length of a scalar")));
1969 bool skipNested =
false;
1976 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1977 errmsg(
"cannot call %s on a non-object",
1984 "jsonb_each temporary cxt",
1997 bool nulls[2] = {
false,
false};
2070 state->normalize_results = as_text;
2071 state->next_scalar =
false;
2074 "json_each temporary cxt",
2117 bool nulls[2] = {
false,
false};
2164 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2165 errmsg(
"cannot deconstruct an array as an object")));
2178 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2179 errmsg(
"cannot deconstruct a scalar")));
2216 bool skipNested =
false;
2223 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2224 errmsg(
"cannot extract elements from a scalar")));
2227 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2228 errmsg(
"cannot extract elements from an object")));
2235 "jsonb_array_elements temporary cxt",
2247 bool nulls[1] = {
false};
2323 state->normalize_results = as_text;
2324 state->next_scalar =
false;
2327 "json_array_elements temporary cxt",
2369 bool nulls[1] = {
false};
2414 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2415 errmsg(
"cannot call %s on a non-array",
2429 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2430 errmsg(
"cannot call %s on a scalar",
2488 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2489 errmsg(
"expected JSON array"),
2493 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2494 errmsg(
"expected JSON array")));
2505 for (
i = 0;
i < ndim;
i++)
2510 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2511 errmsg(
"expected JSON array"),
2512 errhint(
"See the array element %s of key \"%s\".",
2516 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2517 errmsg(
"expected JSON array"),
2518 errhint(
"See the array element %s.",
2538 for (
i = 0;
i < ndims;
i++)
2546 int dim = ctx->
sizes[ndim];
2548 if (ctx->
dims[ndim] == -1)
2549 ctx->
dims[ndim] = dim;
2550 else if (ctx->
dims[ndim] != dim)
2552 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2553 errmsg(
"malformed JSON array"),
2554 errdetail(
"Multidimensional arrays must have "
2555 "sub-arrays with matching dimensions.")));
2558 ctx->
sizes[ndim] = 0;
2562 ctx->
sizes[ndim - 1]++;
2569 bool element_isnull;
2576 jsv, &element_isnull);
2582 ctx->
sizes[ndim - 1]++;
2590 int ndim =
state->lex->lex_level;
2592 if (
state->ctx->ndims <= 0)
2594 else if (ndim < state->ctx->ndims)
2606 int ndim =
state->lex->lex_level;
2608 if (ctx->
ndims <= 0)
2611 if (ndim < ctx->ndims)
2622 int ndim =
state->lex->lex_level;
2624 if (
state->ctx->ndims <= 0 || ndim ==
state->ctx->ndims)
2627 state->element_start =
state->lex->token_start;
2628 state->element_type =
state->lex->token_type;
2629 state->element_scalar = NULL;
2641 int ndim =
state->lex->lex_level;
2645 if (ndim == ctx->
ndims)
2658 else if (
state->element_scalar)
2666 jsv.
val.
json.len = (
state->lex->prev_token_terminator -
2667 state->element_start) *
sizeof(
char);
2682 int ndim =
state->lex->lex_level;
2684 if (ctx->
ndims <= 0)
2686 else if (ndim < ctx->ndims)
2689 if (ndim == ctx->
ndims)
2711 memset(&sem, 0,
sizeof(sem));
2761 if (ctx->
ndims <= 0 &&
2804 const char *colname,
2862 "populate_composite");
2881 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2883 ?
errmsg(
"cannot call %s on a scalar",
2884 "populate_composite")
2885 :
errmsg(
"cannot call %s on an array",
2886 "populate_composite")));
2919 const char *colname,
2942 defaultval, mcxt, &jso);
2953 if (typid != io->
base_typid && typid != RECORDOID)
2984 if ((typid == JSONOID || typid == JSONBOID) &&
3001 if (typid == JSONBOID)
3027 jbv->
val.binary.len);
3029 elog(
ERROR,
"unrecognized jsonb type: %d", (
int) jbv->
type);
3044 const char *colname,
3078 column->
typid = typid;
3083 elog(
ERROR,
"cache lookup failed for type %u", typid);
3087 if (
type->typtype == TYPTYPE_DOMAIN)
3094 int32 base_typmod = typmod;
3118 else if (
type->typtype == TYPTYPE_COMPOSITE || typid == RECORDOID)
3127 else if (IsTrueArrayType(
type))
3159 const char *colname,
3215 elog(
ERROR,
"unrecognized type category '%c'", typcat);
3229 data->record_typmod = 0;
3230 data->ncolumns = ncolumns;
3251 return hashentry != NULL;
3275 int ncolumns = tupdesc->
natts;
3287 if (record == NULL ||
3303 nulls = (
bool *)
palloc(ncolumns *
sizeof(
bool));
3313 tuple.
t_data = defaultval;
3320 for (
i = 0;
i < ncolumns; ++
i)
3327 for (
i = 0;
i < ncolumns; ++
i)
3330 char *colname =
NameStr(att->attname);
3335 if (att->attisdropped)
3351 if (defaultval && !found)
3389 (
errcode(ERRCODE_DATATYPE_MISMATCH),
3391 errmsg(
"first argument of %s must be a row type",
3413 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3415 errmsg(
"could not determine row type for result of %s",
3417 errhint(
"Provide a non-null record argument, "
3418 "or call the function in the FROM clause "
3419 "using a column definition list.")));
3442 bool is_json,
bool have_record_arg)
3444 int json_arg_num = have_record_arg ? 1 : 0;
3463 if (have_record_arg)
3470 if (!have_record_arg)
3480 if (cache->
argtype == RECORDOID)
3494 if (cache->
argtype == RECORDOID)
3530 jbv.
val.binary.data = &jb->
root;
3535 NULL, fnmcxt, rec, &jsv,
false);
3666 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3679 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3770 bool is_json,
bool have_record_arg)
3772 int json_arg_num = have_record_arg ? 1 : 0;
3783 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3784 errmsg(
"set-valued function called in context that cannot accept a set")));
3788 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3789 errmsg(
"materialize mode required, but it is not allowed in this context")));
3804 if (have_record_arg)
3811 if (!have_record_arg)
3821 if (cache->
argtype == RECORDOID)
3835 if (cache->
argtype == RECORDOID)
3863 state->cache = cache;
3897 bool skipNested =
false;
3902 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3903 errmsg(
"cannot call %s on a non-array",
3919 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3920 errmsg(
"argument of %s must be an array of objects",
3952 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3953 errmsg(
"cannot call %s on an object",
4003 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4004 errmsg(
"argument of %s must be an array of objects",
4024 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4025 errmsg(
"cannot call %s on a scalar",
4234 state->skip_next_null =
false;
4248 state->strval->len));
4264 bool last_was_key =
false;
4279 last_was_key =
true;
4286 last_was_key =
false;
4380 bool skipNested =
false;
4385 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4386 errmsg(
"cannot delete from scalar")));
4399 memcmp(keyptr, v.
val.string.val, keylen) == 0))
4434 bool skipNested =
false;
4439 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4440 errmsg(
"wrong number of array subscripts")));
4444 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4445 errmsg(
"cannot delete from scalar")));
4466 for (
i = 0;
i < keys_len;
i++)
4477 if (keylen == v.
val.string.len &&
4478 memcmp(keyptr, v.
val.string.val, keylen) == 0)
4524 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4525 errmsg(
"cannot delete from scalar")));
4529 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4530 errmsg(
"cannot delete from object using integer index")));
4539 n = v.
val.array.nElems;
4592 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4593 errmsg(
"wrong number of array subscripts")));
4597 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4598 errmsg(
"cannot set path in scalar")));
4610 res =
setPath(&it, path_elems, path_nulls, path_len, &st,
4638 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4639 errmsg(
"null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4648 if (strcmp(handle_val,
"raise_exception") == 0)
4651 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4652 errmsg(
"JSON value must not be null"),
4653 errdetail(
"Exception was raised because null_value_treatment is \"raise_exception\"."),
4654 errhint(
"To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
4657 else if (strcmp(handle_val,
"use_json_null") == 0)
4663 fcinfo->args[2].value =
newval;
4664 fcinfo->args[2].isnull =
false;
4667 else if (strcmp(handle_val,
"delete_key") == 0)
4671 else if (strcmp(handle_val,
"return_target") == 0)
4680 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4681 errmsg(
"null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4703 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4704 errmsg(
"wrong number of array subscripts")));
4708 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4709 errmsg(
"cannot delete path in scalar")));
4721 res =
setPath(&it, path_elems, path_nulls, path_len, &st,
4751 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4752 errmsg(
"wrong number of array subscripts")));
4756 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4757 errmsg(
"cannot set path in scalar")));
4911 bool *path_nulls,
int path_len,
4920 if (path_nulls[level])
4922 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4923 errmsg(
"path element at position %d is null",
4939 v.
val.array.rawScalar)
4941 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4942 errmsg(
"cannot replace existing key"),
4943 errdetail(
"The path assumes key is a composite object, "
4944 "but it is a scalar value.")));
4947 setPathArray(it, path_elems, path_nulls, path_len, st, level,
4955 setPathObject(it, path_elems, path_nulls, path_len, st, level,
4972 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4973 errmsg(
"cannot replace existing key"),
4974 errdetail(
"The path assumes key is a composite object, "
4975 "but it is a scalar value.")));
4980 elog(
ERROR,
"unrecognized iterator result: %d", (
int) r);
4996 text *pathelem = NULL;
5002 if (level >= path_len || path_nulls[level])
5012 (level == path_len - 1))
5024 for (
i = 0;
i < npairs;
i++)
5033 k.
val.string.len) == 0)
5037 if (level == path_len - 1)
5045 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5046 errmsg(
"cannot replace existing key"),
5047 errhint(
"Try using the function jsonb_set "
5048 "to replace key value.")));
5060 setPath(it, path_elems, path_nulls, path_len,
5061 st, level + 1,
newval, op_type);
5067 level == path_len - 1 &&
i == npairs - 1)
5084 int walking_level = 1;
5086 while (walking_level != 0)
5120 (void)
push_path(st, level, path_elems, path_nulls,
5141 if (level < path_len && !path_nulls[level])
5148 if (badp ==
c || *badp !=
'\0' || errno != 0)
5150 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5151 errmsg(
"path element at position %d is not an integer: \"%s\"",
5167 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5168 errmsg(
"path element at position %d is out of range: %d",
5183 if (
idx > 0 &&
idx > nelems)
5192 if ((
idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
5206 for (
i = 0;
i < nelems;
i++)
5210 if (
i ==
idx && level < path_len)
5214 if (level == path_len - 1)
5233 (
void)
setPath(it, path_elems, path_nulls, path_len,
5234 st, level + 1,
newval, op_type);
5244 int walking_level = 1;
5246 while (walking_level != 0)