31 #include "utils/fmgroids.h"
42 #define JB_PATH_CREATE 0x0001
43 #define JB_PATH_DELETE 0x0002
44 #define JB_PATH_REPLACE 0x0004
45 #define JB_PATH_INSERT_BEFORE 0x0008
46 #define JB_PATH_INSERT_AFTER 0x0010
47 #define JB_PATH_CREATE_OR_INSERT \
48 (JB_PATH_INSERT_BEFORE | JB_PATH_INSERT_AFTER | JB_PATH_CREATE)
49 #define JB_PATH_FILL_GAPS 0x0020
50 #define JB_PATH_CONSISTENT_POSITION 0x0040
316 #define JsValueIsNull(jsv) \
318 (!(jsv)->val.json.str || (jsv)->val.json.type == JSON_TOKEN_NULL) : \
319 (!(jsv)->val.jsonb || (jsv)->val.jsonb->type == jbvNull))
321 #define JsValueIsString(jsv) \
322 ((jsv)->is_json ? (jsv)->val.json.type == JSON_TOKEN_STRING \
323 : ((jsv)->val.jsonb && (jsv)->val.jsonb->type == jbvString))
325 #define JsObjectIsEmpty(jso) \
327 ? hash_get_num_entries((jso)->val.json_hash) == 0 \
328 : ((jso)->val.jsonb_cont == NULL || \
329 JsonContainerSize((jso)->val.jsonb_cont) == 0))
331 #define JsObjectFree(jso) \
333 if ((jso)->is_json) \
334 hash_destroy((jso)->val.json_hash); \
358 bool normalize_results);
426 bool is_json,
bool have_record_arg);
428 bool is_json,
bool have_record_arg);
435 const char *funcname,
438 const char *funcname,
469 bool *path_nulls,
int path_len,
564 bool skipNested =
false;
571 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
572 errmsg(
"cannot call %s on a scalar",
573 "jsonb_object_keys")));
576 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
577 errmsg(
"cannot call %s on an array",
578 "jsonb_object_keys")));
586 state->result_count = 0;
587 state->sent_count = 0;
600 cstr =
palloc(v.
val.string.len + 1 *
sizeof(
char));
601 memcpy(cstr, v.
val.string.val, v.
val.string.len);
602 cstr[v.
val.string.len] =
'\0';
616 char *nxt =
state->result[
state->sent_count++];
635 (
errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
636 errmsg(
"unsupported Unicode escape sequence"),
643 elog(
ERROR,
"JSON semantic action function did not provide error information");
647 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
648 errmsg(
"invalid input syntax for type %s",
"json"),
666 const char *context_start;
667 const char *context_end;
668 const char *line_start;
676 context_start = line_start;
680 while (context_end - context_start >= 50)
684 context_start +=
pg_mblen(context_start);
694 if (context_start - line_start <= 3)
695 context_start = line_start;
698 ctxtlen = context_end - context_start;
699 ctxt =
palloc(ctxtlen + 1);
700 memcpy(ctxt, context_start, ctxtlen);
701 ctxt[ctxtlen] =
'\0';
707 prefix = (context_start > line_start) ?
"..." :
"";
710 *context_end !=
'\n' && *context_end !=
'\r') ?
"..." :
"";
712 return errcontext(
"JSON data, line %d: %s%s%s",
737 state->result_size = 256;
738 state->result_count = 0;
739 state->sent_count = 0;
765 char *nxt =
state->result[
state->sent_count++];
786 _state->
result = (
char **)
804 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
805 errmsg(
"cannot call %s on an array",
806 "json_object_keys")));
819 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
820 errmsg(
"cannot call %s on a scalar",
821 "json_object_keys")));
841 result =
get_worker(json, &fnamestr, NULL, 1,
false);
879 result =
get_worker(json, &fnamestr, NULL, 1,
true);
1036 tpath =
palloc(npath *
sizeof(
char *));
1037 ipath =
palloc(npath *
sizeof(
int));
1039 for (
i = 0;
i < npath;
i++)
1049 if (*tpath[
i] !=
'\0')
1056 if (endptr == tpath[
i] || *endptr !=
'\0' || errno != 0)
1065 result =
get_worker(json, tpath, ipath, npath, as_text);
1095 bool normalize_results)
1105 state->normalize_results = normalize_results;
1106 state->npath = npath;
1107 state->path_names = tpath;
1108 state->path_indexes = ipath;
1110 state->array_cur_index =
palloc(
sizeof(
int) * npath);
1113 state->pathok[0] =
true;
1143 return state->tresult;
1152 if (lex_level == 0 && _state->
npath == 0)
1171 if (lex_level == 0 && _state->
npath == 0)
1187 bool get_next =
false;
1190 if (lex_level <= _state->npath &&
1191 _state->
pathok[lex_level - 1] &&
1194 strcmp(fname, _state->
path_names[lex_level - 1]) == 0)
1196 if (lex_level < _state->npath)
1199 _state->
pathok[lex_level] =
true;
1234 bool get_last =
false;
1238 if (lex_level <= _state->npath &&
1239 _state->
pathok[lex_level - 1] &&
1242 strcmp(fname, _state->
path_names[lex_level - 1]) == 0)
1244 if (lex_level < _state->npath)
1247 _state->
pathok[lex_level] =
false;
1287 if (lex_level < _state->npath)
1308 else if (lex_level == 0 && _state->
npath == 0)
1327 if (lex_level == 0 && _state->
npath == 0)
1343 bool get_next =
false;
1347 if (lex_level <= _state->npath)
1350 if (lex_level <= _state->npath &&
1351 _state->
pathok[lex_level - 1] &&
1355 if (lex_level < _state->npath)
1358 _state->
pathok[lex_level] =
true;
1391 bool get_last =
false;
1395 if (lex_level <= _state->npath &&
1396 _state->
pathok[lex_level - 1] &&
1400 if (lex_level < _state->npath)
1403 _state->
pathok[lex_level] =
false;
1438 if (lex_level == 0 && _state->
npath == 0)
1523 bool have_object =
false,
1549 if (npath <= 0 && jbvp == NULL)
1564 for (
i = 0;
i < npath;
i++)
1575 else if (have_array)
1583 lindex =
strtoint(indextext, &endptr, 10);
1584 if (endptr == indextext || *endptr !=
'\0' || errno != 0)
1605 if (lindex == INT_MIN || -lindex > nelements)
1611 index = nelements + lindex;
1628 else if (
i == npath - 1)
1633 container = jbvp->
val.binary.data;
1641 have_object =
false;
1672 bool *path_nulls =
palloc0(path_len *
sizeof(
bool));
1725 for (
int i = level + 1;
i < path_len;
i++)
1741 if (badp ==
c || *badp !=
'\0' || errno != 0)
1745 newkey.
val.string.val =
c;
1746 newkey.
val.string.len = strlen(
c);
1765 if (tpath[(path_len - level) - 1] ==
jbvArray)
1776 for (
int i = path_len - 1;
i > level;
i--)
1800 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};
2071 state->normalize_results = as_text;
2072 state->next_scalar =
false;
2075 "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};
2321 state->function_name = funcname;
2322 state->normalize_results = as_text;
2323 state->next_scalar =
false;
2326 "json_array_elements temporary cxt",
2367 bool nulls[1] = {
false};
2412 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2413 errmsg(
"cannot call %s on a non-array",
2427 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2428 errmsg(
"cannot call %s on a scalar",
2486 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2487 errmsg(
"expected JSON array"),
2491 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2492 errmsg(
"expected JSON array")));
2503 for (
i = 0;
i < ndim;
i++)
2508 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2509 errmsg(
"expected JSON array"),
2510 errhint(
"See the array element %s of key \"%s\".",
2514 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2515 errmsg(
"expected JSON array"),
2516 errhint(
"See the array element %s.",
2536 for (
i = 0;
i < ndims;
i++)
2544 int dim = ctx->
sizes[ndim];
2546 if (ctx->
dims[ndim] == -1)
2547 ctx->
dims[ndim] = dim;
2548 else if (ctx->
dims[ndim] != dim)
2550 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
2551 errmsg(
"malformed JSON array"),
2552 errdetail(
"Multidimensional arrays must have "
2553 "sub-arrays with matching dimensions.")));
2556 ctx->
sizes[ndim] = 0;
2560 ctx->
sizes[ndim - 1]++;
2567 bool element_isnull;
2574 jsv, &element_isnull);
2580 ctx->
sizes[ndim - 1]++;
2588 int ndim =
state->lex->lex_level;
2590 if (
state->ctx->ndims <= 0)
2592 else if (ndim < state->ctx->ndims)
2604 int ndim =
state->lex->lex_level;
2606 if (ctx->
ndims <= 0)
2609 if (ndim < ctx->ndims)
2620 int ndim =
state->lex->lex_level;
2622 if (
state->ctx->ndims <= 0 || ndim ==
state->ctx->ndims)
2625 state->element_start =
state->lex->token_start;
2626 state->element_type =
state->lex->token_type;
2627 state->element_scalar = NULL;
2639 int ndim =
state->lex->lex_level;
2643 if (ndim == ctx->
ndims)
2656 else if (
state->element_scalar)
2664 jsv.
val.
json.len = (
state->lex->prev_token_terminator -
2665 state->element_start) *
sizeof(
char);
2680 int ndim =
state->lex->lex_level;
2682 if (ctx->
ndims <= 0)
2684 else if (ndim < ctx->ndims)
2687 if (ndim == ctx->
ndims)
2690 state->element_scalar = token;
2708 memset(&sem, 0,
sizeof(sem));
2758 if (ctx->
ndims <= 0 &&
2801 const char *colname,
2859 "populate_composite");
2878 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2880 ?
errmsg(
"cannot call %s on a scalar",
2881 "populate_composite")
2882 :
errmsg(
"cannot call %s on an array",
2883 "populate_composite")));
2916 const char *colname,
2939 defaultval, mcxt, &jso);
2950 if (typid != io->
base_typid && typid != RECORDOID)
2981 if ((typid == JSONOID || typid == JSONBOID) &&
2998 if (typid == JSONBOID)
3024 jbv->
val.binary.len);
3026 elog(
ERROR,
"unrecognized jsonb type: %d", (
int) jbv->
type);
3041 const char *colname,
3075 column->
typid = typid;
3080 elog(
ERROR,
"cache lookup failed for type %u", typid);
3084 if (
type->typtype == TYPTYPE_DOMAIN)
3091 int32 base_typmod = typmod;
3115 else if (
type->typtype == TYPTYPE_COMPOSITE || typid == RECORDOID)
3124 else if (IsTrueArrayType(
type))
3156 const char *colname,
3212 elog(
ERROR,
"unrecognized type category '%c'", typcat);
3226 data->record_typmod = 0;
3227 data->ncolumns = ncolumns;
3248 return hashentry != NULL;
3272 int ncolumns = tupdesc->
natts;
3284 if (record == NULL ||
3300 nulls = (
bool *)
palloc(ncolumns *
sizeof(
bool));
3310 tuple.
t_data = defaultval;
3317 for (
i = 0;
i < ncolumns; ++
i)
3324 for (
i = 0;
i < ncolumns; ++
i)
3327 char *colname =
NameStr(att->attname);
3332 if (att->attisdropped)
3348 if (defaultval && !found)
3376 const char *funcname,
3386 (
errcode(ERRCODE_DATATYPE_MISMATCH),
3388 errmsg(
"first argument of %s must be a row type",
3402 const char *funcname,
3410 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3412 errmsg(
"could not determine row type for result of %s",
3414 errhint(
"Provide a non-null record argument, "
3415 "or call the function in the FROM clause "
3416 "using a column definition list.")));
3439 bool is_json,
bool have_record_arg)
3441 int json_arg_num = have_record_arg ? 1 : 0;
3460 if (have_record_arg)
3467 if (!have_record_arg)
3477 if (cache->
argtype == RECORDOID)
3491 if (cache->
argtype == RECORDOID)
3527 jbv.
val.binary.data = &jb->
root;
3532 NULL, fnmcxt, rec, &jsv,
false);
3562 state->function_name = funcname;
3661 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3674 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3765 bool is_json,
bool have_record_arg)
3767 int json_arg_num = have_record_arg ? 1 : 0;
3778 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3779 errmsg(
"set-valued function called in context that cannot accept a set")));
3783 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3784 errmsg(
"materialize mode required, but it is not allowed in this context")));
3799 if (have_record_arg)
3806 if (!have_record_arg)
3816 if (cache->
argtype == RECORDOID)
3830 if (cache->
argtype == RECORDOID)
3857 state->function_name = funcname;
3858 state->cache = cache;
3889 bool skipNested =
false;
3894 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3895 errmsg(
"cannot call %s on a non-array",
3911 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3912 errmsg(
"argument of %s must be an array of objects",
3944 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3945 errmsg(
"cannot call %s on an object",
3995 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
3996 errmsg(
"argument of %s must be an array of objects",
4016 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4017 errmsg(
"cannot call %s on a scalar",
4226 state->skip_next_null =
false;
4241 state->strval->len));
4257 bool last_was_key =
false;
4272 last_was_key =
true;
4279 last_was_key =
false;
4373 bool skipNested =
false;
4378 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4379 errmsg(
"cannot delete from scalar")));
4392 memcmp(keyptr, v.
val.string.val, keylen) == 0))
4427 bool skipNested =
false;
4432 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4433 errmsg(
"wrong number of array subscripts")));
4437 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4438 errmsg(
"cannot delete from scalar")));
4459 for (
i = 0;
i < keys_len;
i++)
4470 if (keylen == v.
val.string.len &&
4471 memcmp(keyptr, v.
val.string.val, keylen) == 0)
4517 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4518 errmsg(
"cannot delete from scalar")));
4522 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4523 errmsg(
"cannot delete from object using integer index")));
4532 n = v.
val.array.nElems;
4585 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4586 errmsg(
"wrong number of array subscripts")));
4590 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4591 errmsg(
"cannot set path in scalar")));
4603 res =
setPath(&it, path_elems, path_nulls, path_len, &st,
4631 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4632 errmsg(
"null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4641 if (strcmp(handle_val,
"raise_exception") == 0)
4644 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4645 errmsg(
"JSON value must not be null"),
4646 errdetail(
"Exception was raised because null_value_treatment is \"raise_exception\"."),
4647 errhint(
"To avoid, either change the null_value_treatment argument or ensure that an SQL NULL is not passed.")));
4650 else if (strcmp(handle_val,
"use_json_null") == 0)
4656 fcinfo->args[2].value =
newval;
4657 fcinfo->args[2].isnull =
false;
4660 else if (strcmp(handle_val,
"delete_key") == 0)
4664 else if (strcmp(handle_val,
"return_target") == 0)
4673 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4674 errmsg(
"null_value_treatment must be \"delete_key\", \"return_target\", \"use_json_null\", or \"raise_exception\"")));
4696 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4697 errmsg(
"wrong number of array subscripts")));
4701 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4702 errmsg(
"cannot delete path in scalar")));
4714 res =
setPath(&it, path_elems, path_nulls, path_len, &st,
4744 (
errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
4745 errmsg(
"wrong number of array subscripts")));
4749 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4750 errmsg(
"cannot set path in scalar")));
4904 bool *path_nulls,
int path_len,
4913 if (path_nulls[level])
4915 (
errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
4916 errmsg(
"path element at position %d is null",
4932 v.
val.array.rawScalar)
4934 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4935 errmsg(
"cannot replace existing key"),
4936 errdetail(
"The path assumes key is a composite object, "
4937 "but it is a scalar value.")));
4940 setPathArray(it, path_elems, path_nulls, path_len, st, level,
4948 setPathObject(it, path_elems, path_nulls, path_len, st, level,
4965 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
4966 errmsg(
"cannot replace existing key"),
4967 errdetail(
"The path assumes key is a composite object, "
4968 "but it is a scalar value.")));
4973 elog(
ERROR,
"unrecognized iterator result: %d", (
int) r);
4989 text *pathelem = NULL;
4995 if (level >= path_len || path_nulls[level])
5005 (level == path_len - 1))
5017 for (
i = 0;
i < npairs;
i++)
5026 k.
val.string.len) == 0)
5030 if (level == path_len - 1)
5038 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5039 errmsg(
"cannot replace existing key"),
5040 errhint(
"Try using the function jsonb_set "
5041 "to replace key value.")));
5053 setPath(it, path_elems, path_nulls, path_len,
5054 st, level + 1,
newval, op_type);
5060 level == path_len - 1 &&
i == npairs - 1)
5077 int walking_level = 1;
5079 while (walking_level != 0)
5113 (void)
push_path(st, level, path_elems, path_nulls,
5134 if (level < path_len && !path_nulls[level])
5141 if (badp ==
c || *badp !=
'\0' || errno != 0)
5143 (
errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
5144 errmsg(
"path element at position %d is not an integer: \"%s\"",
5160 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
5161 errmsg(
"path element at position %d is out of range: %d",
5176 if (
idx > 0 &&
idx > nelems)
5185 if ((
idx == INT_MIN || nelems == 0) && (level == path_len - 1) &&
5199 for (
i = 0;
i < nelems;
i++)
5203 if (
i ==
idx && level < path_len)
5207 if (level == path_len - 1)
5226 (
void)
setPath(it, path_elems, path_nulls, path_len,
5227 st, level + 1,
newval, op_type);
5237 int walking_level = 1;
5239 while (walking_level != 0)
5282 (void)
push_path(st, level, path_elems, path_nulls,