0006-GUC-sql_json-v62.patch
text/x-patch
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v62-0006
Subject: GUC sql_json
| File | + | − |
|---|---|---|
| doc/src/sgml/config.sgml | 19 | 0 |
| src/backend/parser/gram.y | 8 | 3 |
| src/backend/parser/parse_expr.c | 38 | 10 |
| src/backend/utils/adt/format_type.c | 6 | 1 |
| src/backend/utils/adt/jsonb.c | 2 | 0 |
| src/backend/utils/adt/ruleutils.c | 4 | 2 |
| src/backend/utils/misc/guc.c | 19 | 0 |
| src/backend/utils/misc/postgresql.conf.sample | 1 | 0 |
| src/include/nodes/parsenodes.h | 2 | 0 |
| src/include/utils/jsonb.h | 14 | 0 |
| src/test/regress/expected/jsonb.out | 130 | 0 |
| src/test/regress/expected/sqljson.out | 141 | 0 |
| src/test/regress/sql/jsonb.sql | 38 | 0 |
| src/test/regress/sql/sqljson.sql | 32 | 0 |
From 3f802769631306f844d849a379a5fd165fbc6dc9 Mon Sep 17 00:00:00 2001
From: Andrew Dunstan <andrew@dunslane.net>
Date: Mon, 31 Jan 2022 17:59:40 -0500
Subject: [PATCH 6/6] GUC sql_json
---
doc/src/sgml/config.sgml | 19 +++
src/backend/parser/gram.y | 11 +-
src/backend/parser/parse_expr.c | 48 ++++--
src/backend/utils/adt/format_type.c | 7 +-
src/backend/utils/adt/jsonb.c | 2 +
src/backend/utils/adt/ruleutils.c | 6 +-
src/backend/utils/misc/guc.c | 19 +++
src/backend/utils/misc/postgresql.conf.sample | 1 +
src/include/nodes/parsenodes.h | 2 +
src/include/utils/jsonb.h | 14 ++
src/test/regress/expected/jsonb.out | 130 ++++++++++++++++
src/test/regress/expected/sqljson.out | 141 ++++++++++++++++++
src/test/regress/sql/jsonb.sql | 38 +++++
src/test/regress/sql/sqljson.sql | 32 ++++
14 files changed, 454 insertions(+), 16 deletions(-)
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 692d8a2a17..f59ef4a6dd 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -9735,6 +9735,25 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
</listitem>
</varlistentry>
+ <varlistentry id="guc-sql-json" xreflabel="sql_json">
+ <term><varname>sql_json</varname> (<type>enum</type>)
+ <indexterm><primary>json</primary></indexterm>
+ <indexterm><primary>jsonb</primary></indexterm>
+ <indexterm>
+ <primary><varname>sql_json</varname> configuration parameter</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Valid values are <literal>json</literal> and <literal>jsonb</literal>.
+ Specifies what <productname>PostgreSQL</productname> type is used
+ as an implementation of SQL type <type>JSON</type>.
+ When <varname>sql_json</varname> is set to <literal>jsonb</literal>,
+ <productname>PostgreSQL</productname> type <type>json</type> can be
+ accessed using explicit qualification <type>pg_catalog.json</type>.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</sect2>
</sect1>
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index de40ba5caf..00f90eeb5b 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -62,6 +62,7 @@
#include "storage/lmgr.h"
#include "utils/date.h"
#include "utils/datetime.h"
+#include "utils/jsonb.h"
#include "utils/numeric.h"
#include "utils/xml.h"
@@ -13488,10 +13489,11 @@ interval_second:
}
;
+/* Mapping of PG jsonb types to SQL/JSON JSON type */
JsonType:
JSON
{
- $$ = SystemTypeName("json");
+ $$ = SystemTypeName(SQLJSON_TYPE_NAME());
$$->location = @1;
}
;
@@ -15366,21 +15368,24 @@ json_func_expr:
;
json_parse_expr:
- JSON '(' json_value_expr json_key_uniqueness_constraint_opt ')'
+ JSON '(' json_value_expr json_key_uniqueness_constraint_opt
+ json_returning_clause_opt ')'
{
JsonParseExpr *n = makeNode(JsonParseExpr);
n->expr = (JsonValueExpr *) $3;
n->unique_keys = $4;
+ n->output = (JsonOutput *) $5;
n->location = @1;
$$ = (Node *) n;
}
;
json_scalar_expr:
- JSON_SCALAR '(' a_expr ')'
+ JSON_SCALAR '(' a_expr json_returning_clause_opt ')'
{
JsonScalarExpr *n = makeNode(JsonScalarExpr);
n->expr = (Expr *) $3;
+ n->output = (JsonOutput *) $4;
n->location = @1;
$$ = (Node *) n;
}
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index bbd80e5c6e..8644eb2e74 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -37,6 +37,7 @@
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/fmgroids.h"
+#include "utils/jsonb.h"
#include "utils/lsyscache.h"
#include "utils/timestamp.h"
#include "utils/xml.h"
@@ -4450,19 +4451,49 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
return (Node *) jsexpr;
}
+static JsonReturning *
+transformJsonConstructorRet(ParseState *pstate, JsonOutput *output, const char *fname)
+{
+ JsonReturning *returning;
+
+ if (output)
+ {
+ returning = transformJsonOutput(pstate, output, false);
+
+ Assert(OidIsValid(returning->typid));
+
+ if (returning->typid != JSONOID && returning->typid != JSONBOID)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("cannot use RETURNING type %s in %s",
+ format_type_be(returning->typid), fname),
+ parser_errposition(pstate, output->typeName->location)));
+ }
+ else
+ {
+ Oid targettype = SQLJSON_TYPE_OID();
+ JsonFormatType format =
+ SQLJSON_TYPE_IS_JSONB() ? JS_FORMAT_JSONB : JS_FORMAT_JSON;
+
+ returning = makeNode(JsonReturning);
+ returning->format = makeJsonFormat(format, JS_ENC_DEFAULT, -1);
+ returning->typid = targettype;
+ returning->typmod = -1;
+ }
+
+ return returning;
+}
+
/*
* Transform a JSON() expression.
*/
static Node *
transformJsonParseExpr(ParseState *pstate, JsonParseExpr *jsexpr)
{
- JsonReturning *returning = makeNode(JsonReturning);
+ JsonReturning *returning = transformJsonConstructorRet(pstate, jsexpr->output,
+ "JSON()");
Node *arg;
- returning->format = makeJsonFormat(JS_FORMAT_JSON, JS_ENC_DEFAULT, -1);
- returning->typid = JSONOID;
- returning->typmod = -1;
-
if (jsexpr->unique_keys)
{
/*
@@ -4502,12 +4533,9 @@ transformJsonParseExpr(ParseState *pstate, JsonParseExpr *jsexpr)
static Node *
transformJsonScalarExpr(ParseState *pstate, JsonScalarExpr *jsexpr)
{
- JsonReturning *returning = makeNode(JsonReturning);
Node *arg = transformExprRecurse(pstate, (Node *) jsexpr->expr);
-
- returning->format = makeJsonFormat(JS_FORMAT_JSON, JS_ENC_DEFAULT, -1);
- returning->typid = JSONOID;
- returning->typmod = -1;
+ JsonReturning *returning = transformJsonConstructorRet(pstate, jsexpr->output,
+ "JSON_SCALAR()");
if (exprType(arg) == UNKNOWNOID)
arg = coerce_to_specific_type(pstate, arg, TEXTOID, "JSON_SCALAR");
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index 060fd7e183..fe1627dedc 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -23,6 +23,7 @@
#include "mb/pg_wchar.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
+#include "utils/jsonb.h"
#include "utils/lsyscache.h"
#include "utils/numeric.h"
#include "utils/syscache.h"
@@ -296,7 +297,11 @@ format_type_extended(Oid type_oid, int32 typemod, bits16 flags)
break;
case JSONOID:
- buf = pstrdup("json");
+ buf = pstrdup(SQLJSON_TYPE_IS_JSONB() ? "pg_catalog.json" : "json");
+ break;
+
+ case JSONBOID:
+ buf = pstrdup(SQLJSON_TYPE_IS_JSONB() ? "json" : "jsonb");
break;
}
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index 2043f2e74a..9089b3b22e 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -69,6 +69,8 @@ static JsonbParseState *clone_parse_state(JsonbParseState *state);
static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent);
static void add_indent(StringInfo out, bool indent, int level);
+int sql_json_type; /* GUC for mapping jsonb to SQL/JSON JSON */
+
/*
* jsonb type input function
*/
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 938a5407f6..fc3617f550 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -63,6 +63,7 @@
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/hsearch.h"
+#include "utils/jsonb.h"
#include "utils/lsyscache.h"
#include "utils/partcache.h"
#include "utils/rel.h"
@@ -10043,8 +10044,9 @@ get_json_constructor_options(JsonConstructorExpr *ctor, StringInfo buf)
if (ctor->unique)
appendStringInfoString(buf, " WITH UNIQUE KEYS");
- if (ctor->type != JSCTOR_JSON_PARSE &&
- ctor->type != JSCTOR_JSON_SCALAR)
+ if (!((ctor->type == JSCTOR_JSON_PARSE ||
+ ctor->type == JSCTOR_JSON_SCALAR) &&
+ ctor->returning->typid == SQLJSON_TYPE_OID()))
get_json_returning(ctor->returning, buf, true);
}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index b3fd42e0f1..5ca946fb9b 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -97,6 +97,7 @@
#include "utils/bytea.h"
#include "utils/float.h"
#include "utils/guc_tables.h"
+#include "utils/jsonb.h"
#include "utils/memutils.h"
#include "utils/pg_locale.h"
#include "utils/pg_lsn.h"
@@ -558,6 +559,12 @@ static const struct config_enum_entry wal_compression_options[] = {
{NULL, 0, false}
};
+const struct config_enum_entry sql_json_type_info[] = {
+ {"json", SQLJSON_TYPE_JSON, false},
+ {"jsonb", SQLJSON_TYPE_JSONB, false},
+ {NULL, 0, false}
+};
+
/*
* Options for enum values stored in other modules
*/
@@ -5025,6 +5032,18 @@ static struct config_enum ConfigureNamesEnum[] =
NULL, NULL, NULL
},
+ {
+ {"sql_json", PGC_USERSET, COMPAT_OPTIONS_CLIENT,
+ gettext_noop("Sets what PostgreSQL type to use as an implementaion of SQL JSON type."),
+ gettext_noop("When turned on, jsonb type is mapped to SQL JSON type, "
+ "json type is mapped to JSON TEXT type.")
+ },
+ &sql_json_type,
+ SQLJSON_TYPE_JSON,
+ sql_json_type_info,
+ NULL, NULL, NULL
+ },
+
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, 0, NULL, NULL, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 817d5f5324..72b54a4da9 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -768,6 +768,7 @@
# - Other Platforms and Clients -
#transform_null_equals = off
+#sql_json = json # jsonb
#------------------------------------------------------------------------------
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 6ec1662315..27ec40dd7f 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1643,6 +1643,7 @@ typedef struct JsonParseExpr
{
NodeTag type;
JsonValueExpr *expr; /* string expression */
+ JsonOutput *output; /* RETURNING clause, if specified */
bool unique_keys; /* WITH UNIQUE KEYS? */
int location; /* token location, or -1 if unknown */
} JsonParseExpr;
@@ -1655,6 +1656,7 @@ typedef struct JsonScalarExpr
{
NodeTag type;
Expr *expr; /* scalar expression */
+ JsonOutput *output; /* RETURNING clause, if specified */
int location; /* token location, or -1 if unknown */
} JsonScalarExpr;
diff --git a/src/include/utils/jsonb.h b/src/include/utils/jsonb.h
index bae466b523..7534c2e7d1 100644
--- a/src/include/utils/jsonb.h
+++ b/src/include/utils/jsonb.h
@@ -393,6 +393,20 @@ typedef enum /* type categories for datum_to_jsonb */
JSONBTYPE_OTHER /* all else */
} JsonbTypeCategory;
+/* values for the sql+json_type GUC. */
+typedef enum SqlJsonType
+{
+ SQLJSON_TYPE_JSON = 0,
+ SQLJSON_TYPE_JSONB = 1
+} SqlJsonType;
+
+#define SQLJSON_TYPE_IS_JSONB() (sql_json_type == SQLJSON_TYPE_JSONB)
+#define SQLJSON_TYPE_OID() (SQLJSON_TYPE_IS_JSONB() ? JSONBOID : JSONOID)
+#define SQLJSON_TYPE_NAME() (SQLJSON_TYPE_IS_JSONB() ? "jsonb" : "json")
+
+/* GUC */
+extern int sql_json_type;
+
/* Support functions */
extern uint32 getJsonbOffset(const JsonbContainer *jc, int index);
extern uint32 getJsonbLength(const JsonbContainer *jc, int index);
diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out
index a9cd145aec..905b50e850 100644
--- a/src/test/regress/expected/jsonb.out
+++ b/src/test/regress/expected/jsonb.out
@@ -5509,3 +5509,133 @@ select '12345.0000000000000000000000000000000000000000000005'::jsonb::int8;
12345
(1 row)
+-- test mapping of jsonb to SQL/JSON JSON type
+select json(' { "aa": 1, "b" : 2 }');
+ json
+-----------------------
+ { "aa": 1, "b" : 2 }
+(1 row)
+
+select json ' { "aa": 1, "b" : 2 }';
+ json
+-----------------------
+ { "aa": 1, "b" : 2 }
+(1 row)
+
+select pg_catalog.json ' { "aa": 1, "b" : 2 }';
+ json
+-----------------------
+ { "aa": 1, "b" : 2 }
+(1 row)
+
+create table test_json_as_json (js json, jb jsonb);
+\d test_json_as_json
+ Table "public.test_json_as_json"
+ Column | Type | Collation | Nullable | Default
+--------+-------+-----------+----------+---------
+ js | json | | |
+ jb | jsonb | | |
+
+set sql_json = jsonb;
+select json(' { "aa": 1, "b" : 2 }');
+ json
+-------------------
+ {"b": 2, "aa": 1}
+(1 row)
+
+select json ' { "aa": 1, "b" : 2 }';
+ jsonb
+-------------------
+ {"b": 2, "aa": 1}
+(1 row)
+
+select pg_catalog.json ' { "aa": 1, "b" : 2 }';
+ json
+-----------------------
+ { "aa": 1, "b" : 2 }
+(1 row)
+
+\d test_json_as_json
+ Table "public.test_json_as_json"
+ Column | Type | Collation | Nullable | Default
+--------+-----------------+-----------+----------+---------
+ js | pg_catalog.json | | |
+ jb | json | | |
+
+create table test_json_as_jsonb (js json, jb jsonb, jt pg_catalog.json);
+\d test_json_as_jsonb
+ Table "public.test_json_as_jsonb"
+ Column | Type | Collation | Nullable | Default
+--------+-----------------+-----------+----------+---------
+ js | json | | |
+ jb | json | | |
+ jt | pg_catalog.json | | |
+
+insert into test_json_as_jsonb values ('{ "a" : 1 }', '{ "a" : 1 }', '{ "a" : 1 }');
+select * from test_json_as_jsonb;
+ js | jb | jt
+----------+----------+-------------
+ {"a": 1} | {"a": 1} | { "a" : 1 }
+(1 row)
+
+select jsonb_object_field(js, 'a') from test_json_as_jsonb;
+ jsonb_object_field
+--------------------
+ 1
+(1 row)
+
+select jsonb_object_field(jb, 'a') from test_json_as_jsonb;
+ jsonb_object_field
+--------------------
+ 1
+(1 row)
+
+select jsonb_object_field(jt, 'a') from test_json_as_jsonb;
+ERROR: function jsonb_object_field(pg_catalog.json, unknown) does not exist
+LINE 1: select jsonb_object_field(jt, 'a') from test_json_as_jsonb;
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+select json_object_field(jt, 'a') from test_json_as_jsonb;
+ json_object_field
+-------------------
+ 1
+(1 row)
+
+set sql_json = json;
+\d test_json_as_jsonb
+ Table "public.test_json_as_jsonb"
+ Column | Type | Collation | Nullable | Default
+--------+-------+-----------+----------+---------
+ js | jsonb | | |
+ jb | jsonb | | |
+ jt | json | | |
+
+select * from test_json_as_jsonb;
+ js | jb | jt
+----------+----------+-------------
+ {"a": 1} | {"a": 1} | { "a" : 1 }
+(1 row)
+
+select jsonb_object_field(js, 'a') from test_json_as_jsonb;
+ jsonb_object_field
+--------------------
+ 1
+(1 row)
+
+select jsonb_object_field(jb, 'a') from test_json_as_jsonb;
+ jsonb_object_field
+--------------------
+ 1
+(1 row)
+
+select jsonb_object_field(jt, 'a') from test_json_as_jsonb;
+ERROR: function jsonb_object_field(json, unknown) does not exist
+LINE 1: select jsonb_object_field(jt, 'a') from test_json_as_jsonb;
+ ^
+HINT: No function matches the given name and argument types. You might need to add explicit type casts.
+select json_object_field(jt, 'a') from test_json_as_jsonb;
+ json_object_field
+-------------------
+ 1
+(1 row)
+
diff --git a/src/test/regress/expected/sqljson.out b/src/test/regress/expected/sqljson.out
index 11f5eb2d2c..51bd216120 100644
--- a/src/test/regress/expected/sqljson.out
+++ b/src/test/regress/expected/sqljson.out
@@ -113,6 +113,103 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' WITHOUT UNIQUE KEYS);
Output: JSON('123'::json)
(2 rows)
+SELECT JSON('123' RETURNING text);
+ERROR: cannot use RETURNING type text in JSON()
+LINE 1: SELECT JSON('123' RETURNING text);
+ ^
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123');
+ QUERY PLAN
+-----------------------------
+ Result
+ Output: JSON('123'::json)
+(2 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING json);
+ QUERY PLAN
+-----------------------------
+ Result
+ Output: JSON('123'::json)
+(2 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING jsonb);
+ QUERY PLAN
+----------------------------------------------
+ Result
+ Output: JSON('123'::jsonb RETURNING jsonb)
+(2 rows)
+
+SELECT pg_typeof(JSON('123'));
+ pg_typeof
+-----------
+ json
+(1 row)
+
+SELECT pg_typeof(JSON('123' RETURNING json));
+ pg_typeof
+-----------
+ json
+(1 row)
+
+SELECT pg_typeof(JSON('123' RETURNING jsonb));
+ pg_typeof
+-----------
+ jsonb
+(1 row)
+
+SET sql_json = jsonb;
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123');
+ QUERY PLAN
+-----------------------------
+ Result
+ Output: JSON('123'::json)
+(2 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING json);
+ QUERY PLAN
+-----------------------------
+ Result
+ Output: JSON('123'::json)
+(2 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING jsonb);
+ QUERY PLAN
+-----------------------------
+ Result
+ Output: JSON('123'::json)
+(2 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING pg_catalog.json);
+ QUERY PLAN
+------------------------------------------------------------------
+ Result
+ Output: JSON('123'::pg_catalog.json RETURNING pg_catalog.json)
+(2 rows)
+
+SELECT pg_typeof(JSON('123'));
+ pg_typeof
+-----------
+ json
+(1 row)
+
+SELECT pg_typeof(JSON('123' RETURNING json));
+ pg_typeof
+-----------
+ json
+(1 row)
+
+SELECT pg_typeof(JSON('123' RETURNING jsonb));
+ pg_typeof
+-----------
+ json
+(1 row)
+
+SELECT pg_typeof(JSON('123' RETURNING pg_catalog.json));
+ pg_typeof
+-----------------
+ pg_catalog.json
+(1 row)
+
+SET sql_json = json;
-- JSON_SCALAR()
SELECT JSON_SCALAR();
ERROR: syntax error at or near ")"
@@ -204,6 +301,50 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR('123');
Output: JSON_SCALAR('123'::text)
(2 rows)
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING json);
+ QUERY PLAN
+----------------------------
+ Result
+ Output: JSON_SCALAR(123)
+(2 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING jsonb);
+ QUERY PLAN
+--------------------------------------------
+ Result
+ Output: JSON_SCALAR(123 RETURNING jsonb)
+(2 rows)
+
+SET sql_json = jsonb;
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123);
+ QUERY PLAN
+----------------------------
+ Result
+ Output: JSON_SCALAR(123)
+(2 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING json);
+ QUERY PLAN
+----------------------------
+ Result
+ Output: JSON_SCALAR(123)
+(2 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING jsonb);
+ QUERY PLAN
+----------------------------
+ Result
+ Output: JSON_SCALAR(123)
+(2 rows)
+
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING pg_catalog.json);
+ QUERY PLAN
+------------------------------------------------------
+ Result
+ Output: JSON_SCALAR(123 RETURNING pg_catalog.json)
+(2 rows)
+
+SET sql_json = json;
-- JSON_SERIALIZE()
SELECT JSON_SERIALIZE();
ERROR: syntax error at or near ")"
diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql
index 5016f29c15..4af2a0cb11 100644
--- a/src/test/regress/sql/jsonb.sql
+++ b/src/test/regress/sql/jsonb.sql
@@ -1482,3 +1482,41 @@ select '12345.0000000000000000000000000000000000000000000005'::jsonb::float8;
select '12345.0000000000000000000000000000000000000000000005'::jsonb::int2;
select '12345.0000000000000000000000000000000000000000000005'::jsonb::int4;
select '12345.0000000000000000000000000000000000000000000005'::jsonb::int8;
+
+-- test mapping of jsonb to SQL/JSON JSON type
+select json(' { "aa": 1, "b" : 2 }');
+select json ' { "aa": 1, "b" : 2 }';
+select pg_catalog.json ' { "aa": 1, "b" : 2 }';
+
+create table test_json_as_json (js json, jb jsonb);
+\d test_json_as_json
+
+set sql_json = jsonb;
+
+select json(' { "aa": 1, "b" : 2 }');
+select json ' { "aa": 1, "b" : 2 }';
+select pg_catalog.json ' { "aa": 1, "b" : 2 }';
+
+\d test_json_as_json
+
+create table test_json_as_jsonb (js json, jb jsonb, jt pg_catalog.json);
+\d test_json_as_jsonb
+
+insert into test_json_as_jsonb values ('{ "a" : 1 }', '{ "a" : 1 }', '{ "a" : 1 }');
+
+select * from test_json_as_jsonb;
+
+select jsonb_object_field(js, 'a') from test_json_as_jsonb;
+select jsonb_object_field(jb, 'a') from test_json_as_jsonb;
+select jsonb_object_field(jt, 'a') from test_json_as_jsonb;
+select json_object_field(jt, 'a') from test_json_as_jsonb;
+
+set sql_json = json;
+\d test_json_as_jsonb
+
+select * from test_json_as_jsonb;
+
+select jsonb_object_field(js, 'a') from test_json_as_jsonb;
+select jsonb_object_field(jb, 'a') from test_json_as_jsonb;
+select jsonb_object_field(jt, 'a') from test_json_as_jsonb;
+select json_object_field(jt, 'a') from test_json_as_jsonb;
diff --git a/src/test/regress/sql/sqljson.sql b/src/test/regress/sql/sqljson.sql
index 98bd93c110..4ff6076763 100644
--- a/src/test/regress/sql/sqljson.sql
+++ b/src/test/regress/sql/sqljson.sql
@@ -23,6 +23,27 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123'::bytea FORMAT JSON ENCODING UTF8)
EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' WITH UNIQUE KEYS);
EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' WITHOUT UNIQUE KEYS);
+SELECT JSON('123' RETURNING text);
+
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123');
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING json);
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING jsonb);
+SELECT pg_typeof(JSON('123'));
+SELECT pg_typeof(JSON('123' RETURNING json));
+SELECT pg_typeof(JSON('123' RETURNING jsonb));
+
+SET sql_json = jsonb;
+
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123');
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING json);
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING jsonb);
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING pg_catalog.json);
+SELECT pg_typeof(JSON('123'));
+SELECT pg_typeof(JSON('123' RETURNING json));
+SELECT pg_typeof(JSON('123' RETURNING jsonb));
+SELECT pg_typeof(JSON('123' RETURNING pg_catalog.json));
+
+SET sql_json = json;
-- JSON_SCALAR()
SELECT JSON_SCALAR();
@@ -41,6 +62,17 @@ SELECT JSON_SCALAR('{}'::jsonb);
EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123);
EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR('123');
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING json);
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING jsonb);
+
+SET sql_json = jsonb;
+
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123);
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING json);
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING jsonb);
+EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING pg_catalog.json);
+
+SET sql_json = json;
-- JSON_SERIALIZE()
SELECT JSON_SERIALIZE();
--
2.25.1