aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/jsonfuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/jsonfuncs.c')
-rw-r--r--src/backend/utils/adt/jsonfuncs.c62
1 files changed, 59 insertions, 3 deletions
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index 1b0f4943292..83125b06a43 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -2830,7 +2830,9 @@ populate_array_dim_jsonb(PopulateArrayContext *ctx, /* context */
check_stack_depth();
- if (jbv->type != jbvBinary || !JsonContainerIsArray(jbc))
+ /* Even scalars can end up here thanks to ExecEvalJsonCoercion(). */
+ if (jbv->type != jbvBinary || !JsonContainerIsArray(jbc) ||
+ JsonContainerIsScalar(jbc))
{
populate_array_report_expected_array(ctx, ndim - 1);
/* Getting here means the error was reported softly. */
@@ -2838,8 +2840,6 @@ populate_array_dim_jsonb(PopulateArrayContext *ctx, /* context */
return false;
}
- Assert(!JsonContainerIsScalar(jbc));
-
it = JsonbIteratorInit(jbc);
tok = JsonbIteratorNext(&it, &val, true);
@@ -3323,6 +3323,62 @@ prepare_column_cache(ColumnIOData *column,
ReleaseSysCache(tup);
}
+/*
+ * Populate and return the value of specified type from a given json/jsonb
+ * value 'json_val'. 'cache' is caller-specified pointer to save the
+ * ColumnIOData that will be initialized on the 1st call and then reused
+ * during any subsequent calls. 'mcxt' gives the memory context to allocate
+ * the ColumnIOData and any other subsidiary memory in. 'escontext',
+ * if not NULL, tells that any errors that occur should be handled softly.
+ */
+Datum
+json_populate_type(Datum json_val, Oid json_type,
+ Oid typid, int32 typmod,
+ void **cache, MemoryContext mcxt,
+ bool *isnull,
+ Node *escontext)
+{
+ JsValue jsv = {0};
+ JsonbValue jbv;
+
+ jsv.is_json = json_type == JSONOID;
+
+ if (*isnull)
+ {
+ if (jsv.is_json)
+ jsv.val.json.str = NULL;
+ else
+ jsv.val.jsonb = NULL;
+ }
+ else if (jsv.is_json)
+ {
+ text *json = DatumGetTextPP(json_val);
+
+ jsv.val.json.str = VARDATA_ANY(json);
+ jsv.val.json.len = VARSIZE_ANY_EXHDR(json);
+ jsv.val.json.type = JSON_TOKEN_INVALID; /* not used in
+ * populate_composite() */
+ }
+ else
+ {
+ Jsonb *jsonb = DatumGetJsonbP(json_val);
+
+ jsv.val.jsonb = &jbv;
+
+ /* fill binary jsonb value pointing to jb */
+ jbv.type = jbvBinary;
+ jbv.val.binary.data = &jsonb->root;
+ jbv.val.binary.len = VARSIZE(jsonb) - VARHDRSZ;
+ }
+
+ if (*cache == NULL)
+ *cache = MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
+
+ return populate_record_field(*cache, typid, typmod, NULL, mcxt,
+ PointerGetDatum(NULL), &jsv, isnull,
+ escontext);
+}
+
/* recursively populate a record field or an array element from a json/jsonb value */
static Datum
populate_record_field(ColumnIOData *col,