Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 87508c8

Browse files
author
Nikita Glukhov
committed
Map PG jsonb to SQL JSON type
1 parent 92f9468 commit 87508c8

File tree

9 files changed

+236
-2
lines changed

9 files changed

+236
-2
lines changed

doc/src/sgml/config.sgml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9347,6 +9347,23 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
93479347
</listitem>
93489348
</varlistentry>
93499349

9350+
<varlistentry id="guc-json-as-jsonb" xreflabel="json_as_jsonb">
9351+
<term><varname>json_as_jsonb</varname> (<type>boolean</type>)
9352+
<indexterm><primary>json</primary></indexterm>
9353+
<indexterm><primary>jsonb</primary></indexterm>
9354+
<indexterm>
9355+
<primary><varname>json_as_jsonb</varname> configuration parameter</primary>
9356+
</indexterm>
9357+
</term>
9358+
<listitem>
9359+
<para>
9360+
When on, SQL type <type>JSON</type> is mapped to
9361+
<productname>PostgreSQL</productname> type <type>jsonb</type>.
9362+
But SQL type <type>JSON TEXT</type> is always mapped to
9363+
<productname>PostgreSQL</productname> type <type>json</type>.
9364+
</para>
9365+
</listitem>
9366+
</varlistentry>
93509367
</variablelist>
93519368
</sect2>
93529369
</sect1>

src/backend/parser/gram.y

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#include "storage/lmgr.h"
6464
#include "utils/date.h"
6565
#include "utils/datetime.h"
66+
#include "utils/jsonb.h"
6667
#include "utils/numeric.h"
6768
#include "utils/xml.h"
6869

@@ -529,7 +530,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
529530
%type <list> copy_options
530531

531532
%type <typnam> Typename SimpleTypename ConstTypename
532-
GenericType Numeric opt_float
533+
GenericType Numeric opt_float JsonType
533534
Character ConstCharacter
534535
CharacterWithLength CharacterWithoutLength
535536
ConstDatetime ConstInterval
@@ -663,7 +664,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
663664
INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
664665
INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
665666

666-
JOIN
667+
JOIN JSON
667668

668669
KEY
669670

@@ -12751,6 +12752,7 @@ SimpleTypename:
1275112752
$$->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1),
1275212753
makeIntConst($3, @3));
1275312754
}
12755+
| JsonType { $$ = $1; }
1275412756
;
1275512757

1275612758
/* We have a separate ConstTypename to allow defaulting fixed-length
@@ -12766,6 +12768,7 @@ SimpleTypename:
1276612768
*/
1276712769
ConstTypename:
1276812770
Numeric { $$ = $1; }
12771+
| JsonType { $$ = $1; }
1276912772
| ConstBit { $$ = $1; }
1277012773
| ConstCharacter { $$ = $1; }
1277112774
| ConstDatetime { $$ = $1; }
@@ -13137,6 +13140,20 @@ interval_second:
1313713140
}
1313813141
;
1313913142

13143+
/* Mapping of PG jsonb types to SQL/JSON JSON type */
13144+
JsonType:
13145+
JSON
13146+
{
13147+
$$ = SystemTypeName(json_as_jsonb ? "jsonb" : "json");
13148+
$$->location = @1;
13149+
}
13150+
| JSON TEXT_P
13151+
{
13152+
$$ = SystemTypeName("json");
13153+
$$->location = @1;
13154+
}
13155+
;
13156+
1314013157

1314113158
/*****************************************************************************
1314213159
*
@@ -13825,6 +13842,12 @@ c_expr: columnref { $$ = $1; }
1382513842
g->location = @1;
1382613843
$$ = (Node *)g;
1382713844
}
13845+
| JSON '(' a_expr ')'
13846+
{
13847+
List *typname = list_make1(makeString(json_as_jsonb ? "jsonb" : "json"));
13848+
13849+
$$ = (Node *) makeFuncCall(typname, list_make1($3), @1);
13850+
}
1382813851
;
1382913852

1383013853
func_application: func_name '(' ')'
@@ -15598,6 +15621,7 @@ col_name_keyword:
1559815621
| INT_P
1559915622
| INTEGER
1560015623
| INTERVAL
15624+
| JSON
1560115625
| LEAST
1560215626
| NATIONAL
1560315627
| NCHAR

src/backend/utils/adt/format_type.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "catalog/pg_type.h"
2323
#include "mb/pg_wchar.h"
2424
#include "utils/builtins.h"
25+
#include "utils/jsonb.h"
2526
#include "utils/lsyscache.h"
2627
#include "utils/numeric.h"
2728
#include "utils/syscache.h"
@@ -282,6 +283,14 @@ format_type_extended(Oid type_oid, int32 typemod, bits16 flags)
282283
else
283284
buf = pstrdup("character varying");
284285
break;
286+
287+
case JSONBOID:
288+
buf = pstrdup(json_as_jsonb ? "json" : "jsonb");
289+
break;
290+
291+
case JSONOID:
292+
buf = pstrdup(json_as_jsonb ? "json text" : "json");
293+
break;
285294
}
286295

287296
if (buf == NULL)

src/backend/utils/adt/jsonb.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ static JsonbParseState *clone_parse_state(JsonbParseState *state);
9090
static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent);
9191
static void add_indent(StringInfo out, bool indent, int level);
9292

93+
bool json_as_jsonb; /* GUC for mapping jsonb to SQL/JSON JSON */
94+
9395
/*
9496
* jsonb type input function
9597
*/

src/backend/utils/misc/guc.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
#include "utils/bytea.h"
8888
#include "utils/float.h"
8989
#include "utils/guc_tables.h"
90+
#include "utils/jsonb.h"
9091
#include "utils/memutils.h"
9192
#include "utils/pg_locale.h"
9293
#include "utils/pg_lsn.h"
@@ -2060,6 +2061,17 @@ static struct config_bool ConfigureNamesBool[] =
20602061
NULL, NULL, NULL
20612062
},
20622063

2064+
{
2065+
{"json_as_jsonb", PGC_USERSET, COMPAT_OPTIONS_CLIENT,
2066+
gettext_noop("Use jsonb type as default implementation of SQL JSON type."),
2067+
gettext_noop("When turned on, jsonb type is mapped to SQL JSON type, "
2068+
"json type is mapped to JSON TEXT type.")
2069+
},
2070+
&json_as_jsonb,
2071+
false,
2072+
NULL, NULL, NULL
2073+
},
2074+
20632075
/* End-of-list marker */
20642076
{
20652077
{NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL

src/include/parser/kwlist.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ PG_KEYWORD("is", IS, TYPE_FUNC_NAME_KEYWORD)
221221
PG_KEYWORD("isnull", ISNULL, TYPE_FUNC_NAME_KEYWORD)
222222
PG_KEYWORD("isolation", ISOLATION, UNRESERVED_KEYWORD)
223223
PG_KEYWORD("join", JOIN, TYPE_FUNC_NAME_KEYWORD)
224+
PG_KEYWORD("json", JSON, COL_NAME_KEYWORD)
224225
PG_KEYWORD("key", KEY, UNRESERVED_KEYWORD)
225226
PG_KEYWORD("label", LABEL, UNRESERVED_KEYWORD)
226227
PG_KEYWORD("language", LANGUAGE, UNRESERVED_KEYWORD)

src/include/utils/jsonb.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,5 +407,6 @@ extern char *JsonbToCStringIndent(StringInfo out, JsonbContainer *in,
407407
extern bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res);
408408
extern const char *JsonbTypeName(JsonbValue *jb);
409409

410+
extern bool json_as_jsonb; /* GUC */
410411

411412
#endif /* __JSONB_H__ */

src/test/regress/expected/jsonb.out

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5014,3 +5014,133 @@ select '12345.0000000000000000000000000000000000000000000005'::jsonb::int8;
50145014
12345
50155015
(1 row)
50165016

5017+
-- test mapping of jsonb to SQL/JSON JSON type
5018+
select json(' { "aa": 1, "b" : 2 }');
5019+
json
5020+
-----------------------
5021+
{ "aa": 1, "b" : 2 }
5022+
(1 row)
5023+
5024+
select json ' { "aa": 1, "b" : 2 }';
5025+
json
5026+
-----------------------
5027+
{ "aa": 1, "b" : 2 }
5028+
(1 row)
5029+
5030+
select json text ' { "aa": 1, "b" : 2 }';
5031+
json
5032+
-----------------------
5033+
{ "aa": 1, "b" : 2 }
5034+
(1 row)
5035+
5036+
create table test_json_as_json (js json, jb jsonb);
5037+
\d test_json_as_json
5038+
Table "public.test_json_as_json"
5039+
Column | Type | Collation | Nullable | Default
5040+
--------+-------+-----------+----------+---------
5041+
js | json | | |
5042+
jb | jsonb | | |
5043+
5044+
set json_as_jsonb = on;
5045+
select json(' { "aa": 1, "b" : 2 }');
5046+
jsonb
5047+
-------------------
5048+
{"b": 2, "aa": 1}
5049+
(1 row)
5050+
5051+
select json ' { "aa": 1, "b" : 2 }';
5052+
jsonb
5053+
-------------------
5054+
{"b": 2, "aa": 1}
5055+
(1 row)
5056+
5057+
select json text ' { "aa": 1, "b" : 2 }';
5058+
json
5059+
-----------------------
5060+
{ "aa": 1, "b" : 2 }
5061+
(1 row)
5062+
5063+
\d test_json_as_json
5064+
Table "public.test_json_as_json"
5065+
Column | Type | Collation | Nullable | Default
5066+
--------+-----------+-----------+----------+---------
5067+
js | json text | | |
5068+
jb | json | | |
5069+
5070+
create table test_json_as_jsonb (js json, jb jsonb, jt json text);
5071+
\d test_json_as_jsonb
5072+
Table "public.test_json_as_jsonb"
5073+
Column | Type | Collation | Nullable | Default
5074+
--------+-----------+-----------+----------+---------
5075+
js | json | | |
5076+
jb | json | | |
5077+
jt | json text | | |
5078+
5079+
insert into test_json_as_jsonb values ('{ "a" : 1 }', '{ "a" : 1 }', '{ "a" : 1 }');
5080+
select * from test_json_as_jsonb;
5081+
js | jb | jt
5082+
----------+----------+-------------
5083+
{"a": 1} | {"a": 1} | { "a" : 1 }
5084+
(1 row)
5085+
5086+
select jsonb_object_field(js, 'a') from test_json_as_jsonb;
5087+
jsonb_object_field
5088+
--------------------
5089+
1
5090+
(1 row)
5091+
5092+
select jsonb_object_field(jb, 'a') from test_json_as_jsonb;
5093+
jsonb_object_field
5094+
--------------------
5095+
1
5096+
(1 row)
5097+
5098+
select jsonb_object_field(jt, 'a') from test_json_as_jsonb;
5099+
ERROR: function jsonb_object_field(json text, unknown) does not exist
5100+
LINE 1: select jsonb_object_field(jt, 'a') from test_json_as_jsonb;
5101+
^
5102+
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
5103+
select json_object_field(jt, 'a') from test_json_as_jsonb;
5104+
json_object_field
5105+
-------------------
5106+
1
5107+
(1 row)
5108+
5109+
set json_as_jsonb = off;
5110+
\d test_json_as_jsonb
5111+
Table "public.test_json_as_jsonb"
5112+
Column | Type | Collation | Nullable | Default
5113+
--------+-------+-----------+----------+---------
5114+
js | jsonb | | |
5115+
jb | jsonb | | |
5116+
jt | json | | |
5117+
5118+
select * from test_json_as_jsonb;
5119+
js | jb | jt
5120+
----------+----------+-------------
5121+
{"a": 1} | {"a": 1} | { "a" : 1 }
5122+
(1 row)
5123+
5124+
select jsonb_object_field(js, 'a') from test_json_as_jsonb;
5125+
jsonb_object_field
5126+
--------------------
5127+
1
5128+
(1 row)
5129+
5130+
select jsonb_object_field(jb, 'a') from test_json_as_jsonb;
5131+
jsonb_object_field
5132+
--------------------
5133+
1
5134+
(1 row)
5135+
5136+
select jsonb_object_field(jt, 'a') from test_json_as_jsonb;
5137+
ERROR: function jsonb_object_field(json, unknown) does not exist
5138+
LINE 1: select jsonb_object_field(jt, 'a') from test_json_as_jsonb;
5139+
^
5140+
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
5141+
select json_object_field(jt, 'a') from test_json_as_jsonb;
5142+
json_object_field
5143+
-------------------
5144+
1
5145+
(1 row)
5146+

src/test/regress/sql/jsonb.sql

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,3 +1280,41 @@ select '12345.0000000000000000000000000000000000000000000005'::jsonb::float8;
12801280
select '12345.0000000000000000000000000000000000000000000005'::jsonb::int2;
12811281
select '12345.0000000000000000000000000000000000000000000005'::jsonb::int4;
12821282
select '12345.0000000000000000000000000000000000000000000005'::jsonb::int8;
1283+
1284+
-- test mapping of jsonb to SQL/JSON JSON type
1285+
select json(' { "aa": 1, "b" : 2 }');
1286+
select json ' { "aa": 1, "b" : 2 }';
1287+
select json text ' { "aa": 1, "b" : 2 }';
1288+
1289+
create table test_json_as_json (js json, jb jsonb);
1290+
\d test_json_as_json
1291+
1292+
set json_as_jsonb = on;
1293+
1294+
select json(' { "aa": 1, "b" : 2 }');
1295+
select json ' { "aa": 1, "b" : 2 }';
1296+
select json text ' { "aa": 1, "b" : 2 }';
1297+
1298+
\d test_json_as_json
1299+
1300+
create table test_json_as_jsonb (js json, jb jsonb, jt json text);
1301+
\d test_json_as_jsonb
1302+
1303+
insert into test_json_as_jsonb values ('{ "a" : 1 }', '{ "a" : 1 }', '{ "a" : 1 }');
1304+
1305+
select * from test_json_as_jsonb;
1306+
1307+
select jsonb_object_field(js, 'a') from test_json_as_jsonb;
1308+
select jsonb_object_field(jb, 'a') from test_json_as_jsonb;
1309+
select jsonb_object_field(jt, 'a') from test_json_as_jsonb;
1310+
select json_object_field(jt, 'a') from test_json_as_jsonb;
1311+
1312+
set json_as_jsonb = off;
1313+
\d test_json_as_jsonb
1314+
1315+
select * from test_json_as_jsonb;
1316+
1317+
select jsonb_object_field(js, 'a') from test_json_as_jsonb;
1318+
select jsonb_object_field(jb, 'a') from test_json_as_jsonb;
1319+
select jsonb_object_field(jt, 'a') from test_json_as_jsonb;
1320+
select json_object_field(jt, 'a') from test_json_as_jsonb;

0 commit comments

Comments
 (0)