Revert SQL/JSON features
authorAndrew Dunstan <[email protected]>
Thu, 1 Sep 2022 21:07:14 +0000 (17:07 -0400)
committerAndrew Dunstan <[email protected]>
Thu, 1 Sep 2022 21:07:14 +0000 (17:07 -0400)
The reverts the following and makes some associated cleanups:

    commit f79b803dc: Common SQL/JSON clauses
    commit f4fb45d15: SQL/JSON constructors
    commit 5f0adec25: Make STRING an unreserved_keyword.
    commit 33a377608: IS JSON predicate
    commit 1a36bc9db: SQL/JSON query functions
    commit 606948b05: SQL JSON functions
    commit 49082c2cc: RETURNING clause for JSON() and JSON_SCALAR()
    commit 4e34747c8: JSON_TABLE
    commit fadb48b00: PLAN clauses for JSON_TABLE
    commit 2ef6f11b0: Reduce running time of jsonb_sqljson test
    commit 14d3f24fa: Further improve jsonb_sqljson parallel test
    commit a6baa4bad: Documentation for SQL/JSON features
    commit b46bcf7a4: Improve readability of SQL/JSON documentation.
    commit 112fdb352: Fix finalization for json_objectagg and friends
    commit fcdb35c32: Fix transformJsonBehavior
    commit 4cd8717af: Improve a couple of sql/json error messages
    commit f7a605f63: Small cleanups in SQL/JSON code
    commit 9c3d25e17: Fix JSON_OBJECTAGG uniquefying bug
    commit a79153b7a: Claim SQL standard compliance for SQL/JSON features
    commit a1e7616d6: Rework SQL/JSON documentation
    commit 8d9f9634e: Fix errors in copyfuncs/equalfuncs support for JSON node types.
    commit 3c633f32b: Only allow returning string types or bytea from json_serialize
    commit 67b26703b: expression eval: Fix EEOP_JSON_CONSTRUCTOR and EEOP_JSONEXPR size.

The release notes are also adjusted.

Backpatch to release 15.

Discussion: https://postgr.es/m/40d2c882-bcac-19a9-754d-4299e1d87ac7@postgresql.org

60 files changed:
doc/src/sgml/func.sgml
doc/src/sgml/keywords/sql2016-02-reserved.txt
src/backend/catalog/sql_features.txt
src/backend/commands/explain.c
src/backend/executor/execExpr.c
src/backend/executor/execExprInterp.c
src/backend/executor/nodeTableFuncscan.c
src/backend/jit/llvm/llvmjit_expr.c
src/backend/jit/llvm/llvmjit_types.c
src/backend/nodes/makefuncs.c
src/backend/nodes/nodeFuncs.c
src/backend/optimizer/path/costsize.c
src/backend/optimizer/util/clauses.c
src/backend/parser/Makefile
src/backend/parser/gram.y
src/backend/parser/parse_clause.c
src/backend/parser/parse_collate.c
src/backend/parser/parse_expr.c
src/backend/parser/parse_jsontable.c [deleted file]
src/backend/parser/parse_relation.c
src/backend/parser/parse_target.c
src/backend/parser/parser.c
src/backend/utils/adt/format_type.c
src/backend/utils/adt/formatting.c
src/backend/utils/adt/json.c
src/backend/utils/adt/jsonb.c
src/backend/utils/adt/jsonb_util.c
src/backend/utils/adt/jsonfuncs.c
src/backend/utils/adt/jsonpath.c
src/backend/utils/adt/jsonpath_exec.c
src/backend/utils/adt/ruleutils.c
src/backend/utils/misc/queryjumble.c
src/include/catalog/catversion.h
src/include/catalog/pg_aggregate.dat
src/include/catalog/pg_proc.dat
src/include/executor/execExpr.h
src/include/executor/executor.h
src/include/nodes/makefuncs.h
src/include/nodes/parsenodes.h
src/include/nodes/primnodes.h
src/include/parser/kwlist.h
src/include/parser/parse_clause.h
src/include/utils/formatting.h
src/include/utils/json.h
src/include/utils/jsonb.h
src/include/utils/jsonfuncs.h
src/include/utils/jsonpath.h
src/interfaces/ecpg/preproc/ecpg.trailer
src/interfaces/ecpg/preproc/parse.pl
src/interfaces/ecpg/preproc/parser.c
src/test/regress/expected/json_sqljson.out [deleted file]
src/test/regress/expected/jsonb_sqljson.out [deleted file]
src/test/regress/expected/opr_sanity.out
src/test/regress/expected/sqljson.out [deleted file]
src/test/regress/parallel_schedule
src/test/regress/sql/json_sqljson.sql [deleted file]
src/test/regress/sql/jsonb_sqljson.sql [deleted file]
src/test/regress/sql/opr_sanity.sql
src/test/regress/sql/sqljson.sql [deleted file]
src/tools/pgindent/typedefs.list

index f87afefeae74c8bcf545230c73e199916cf0aab1..ee515cec8f35213b2d28771a1c49d0beb60b1b76 100644 (file)
@@ -16294,7 +16294,7 @@ table2-mapping
        </para>
        <para>
         <literal>jsonb_set_lax('[{"f1":1,"f2":null},2,null,3]', '{0,f1}', null)</literal>
-        <returnvalue>[{"f1": null, "f2": null}, 2, null, 3]</returnvalue>
+        <returnvalue>[{"f1":null,"f2":null},2,null,3]</returnvalue>
        </para>
        <para>
         <literal>jsonb_set_lax('[{"f1":99,"f2":null},2]', '{0,f3}', null, true, 'return_target')</literal>
@@ -16533,7 +16533,7 @@ table2-mapping
         comparisons.
        </para>
        <para>
-        <literal>jsonb_path_exists_tz('["2015-08-01 12:00:00-05"]', '$[*] ? (@.datetime() &lt; "2015-08-02".datetime())')</literal>
+        <literal>jsonb_path_exists_tz('["2015-08-01 12:00:00 -05"]', '$[*] ? (@.datetime() &lt; "2015-08-02".datetime())')</literal>
         <returnvalue>t</returnvalue>
        </para></entry>
       </row>
@@ -17571,937 +17571,7 @@ $.* ? (@ like_regex "^\\d+$")
 </programlisting>
     </para>
    </sect3>
- </sect2>
-
- <sect2 id="functions-sqljson">
-  <title>SQL/JSON Functions and Expressions</title>
-  <indexterm zone="functions-json">
-   <primary>SQL/JSON</primary>
-   <secondary>functions and expressions</secondary>
-  </indexterm>
-
-  <para>
-   To provide native support for JSON data types within the SQL environment,
-   <productname>PostgreSQL</productname> implements the
-   <firstterm>SQL/JSON data model</firstterm>.
-   This model comprises sequences of items. Each item can hold SQL scalar
-   values, with an additional SQL/JSON null value, and composite data structures
-   that use JSON arrays and objects. The model is a formalization of the implied
-   data model in the JSON specification
-   <ulink url="https://tools.ietf.org/html/rfc7159">RFC 7159</ulink>.
-  </para>
-
-  <para>
-   SQL/JSON allows you to handle JSON data alongside regular SQL data,
-   with transaction support, including:
-  </para>
-
-  <itemizedlist>
-   <listitem>
-    <para>
-     Uploading JSON data into the database and storing it in
-     regular SQL columns as character or binary strings.
-    </para>
-   </listitem>
-   <listitem>
-    <para>
-     Generating JSON objects and arrays from relational data.
-    </para>
-   </listitem>
-   <listitem>
-    <para>
-     Querying JSON data using SQL/JSON query functions and
-     SQL/JSON path language expressions.
-    </para>
-   </listitem>
-  </itemizedlist>
-
-  <para>
-   There are two groups of SQL/JSON functions.
-   <link linkend="functions-sqljson-producing">Constructor functions</link>
-   generate JSON data from values of SQL types.
-   <link linkend="functions-sqljson-querying">Query functions</link>
-   evaluate SQL/JSON path language expressions against JSON values
-   and produce values of SQL/JSON types, which are converted to SQL types.
-  </para>
-
-  <para>
-   Many SQL/JSON functions have an optional <literal>FORMAT</literal>
-   clause. This is provided to conform with the SQL standard, but has no
-   effect except where noted otherwise.
-  </para>
-
-  <para>
-   <xref linkend="functions-sqljson-producing" /> lists the SQL/JSON
-   Constructor functions. Each function has a <literal>RETURNING</literal>
-   clause specifying the data type returned. For the <function>json</function> and
-   <function>json_scalar</function> functions, this needs to be either <type>json</type> or
-   <type>jsonb</type>. For the other constructor functions it must be one of <type>json</type>,
-   <type>jsonb</type>, <type>bytea</type>, a character string type (<type>text</type>, <type>char</type>,
-   <type>varchar</type>, or <type>nchar</type>), or a type for which there is a cast
-   from <type>json</type> to that type.
-   By default, the <type>json</type> type is returned.
-  </para>
-
-  <note>
-   <para>
-    Many of the results that can be obtained from the SQL/JSON Constructor
-    functions can also be obtained by calling
-    <productname>PostgreSQL</productname>-specific functions detailed in
-    <xref linkend="functions-json-creation-table" /> and
-    <xref linkend="functions-aggregate-table"/>.
-   </para>
-  </note>
-
-  <table id="functions-sqljson-producing">
-   <title>SQL/JSON Constructor Functions</title>
-   <tgroup cols="1">
-    <thead>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        Function signature
-       </para>
-       <para>
-        Description
-       </para>
-       <para>
-        Example(s)
-      </para></entry>
-     </row>
-    </thead>
-    <tbody>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        <indexterm><primary>json constructor</primary></indexterm>
-          <function>json</function> (
-          <parameter>expression</parameter>
-          <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional></optional>
-          <optional> { <literal>WITH</literal> | <literal>WITHOUT</literal> } <literal>UNIQUE</literal> <optional> <literal>KEYS</literal> </optional></optional>
-          <optional> <literal>RETURNING</literal> <replaceable>json_data_type</replaceable> </optional>)
-       </para>
-       <para>
-        The <parameter>expression</parameter> can be any text type or a
-        <type>bytea</type> in UTF8 encoding. If the
-        <parameter>expression</parameter> is NULL, an
-        <acronym>SQL</acronym> null value is returned.
-        If <literal>WITH UNIQUE</literal> is specified, the
-        <parameter>expression</parameter> must not contain any duplicate
-        object keys.
-       </para>
-       <para>
-        <literal>json('{"a":123, "b":[true,"foo"], "a":"bar"}')</literal>
-        <returnvalue>{"a":123, "b":[true,"foo"], "a":"bar"}</returnvalue>
-       </para>
-       <para>
-        <literal>json('{"a":123,"b":[true,"foo"],"a":"bar"}' returning jsonb)</literal>
-        <returnvalue>{"a": "bar", "b": [true, "foo"]}</returnvalue>
-      </para></entry>
-     </row>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        <indexterm><primary>json_scalar</primary></indexterm>
-        <function>json_scalar</function> (<parameter>expression</parameter>
-        <optional> <literal>RETURNING</literal> <replaceable>json_data_type</replaceable> </optional>)
-       </para>
-       <para>
-        Returns a JSON scalar value representing
-        <parameter>expression</parameter>.
-        If the input is NULL, an SQL NULL is returned. If the input is a number
-        or a boolean value, a corresponding JSON number or boolean value is
-        returned. For any other value a JSON string is returned.
-       </para>
-       <para>
-        <literal>json_scalar(123.45)</literal>
-        <returnvalue>123.45</returnvalue>
-       </para>
-       <para>
-        <literal>json_scalar(CURRENT_TIMESTAMP)</literal>
-        <returnvalue>"2022-05-10T10:51:04.62128-04:00"</returnvalue>
-      </para></entry>
-     </row>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        <indexterm><primary>json_object</primary></indexterm>
-        <function>json_object</function> (
-        <optional> { <parameter>key_expression</parameter> { <literal>VALUE</literal> | ':' }
-         <parameter>value_expression</parameter> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> }<optional>, ...</optional> </optional>
-        <optional> { <literal>NULL</literal> | <literal>ABSENT</literal> } <literal>ON NULL</literal> </optional>
-        <optional> { <literal>WITH</literal> | <literal>WITHOUT</literal> } <literal>UNIQUE</literal> <optional> <literal>KEYS</literal> </optional> </optional>
-        <optional> <literal>RETURNING</literal> <replaceable>data_type</replaceable> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> </optional>)
-       </para>
-       <para>
-        Constructs a JSON object of all the key value pairs given,
-        or an empty object if none are given.
-        <parameter>key_expression</parameter> is a scalar expression
-        defining the <acronym>JSON</acronym> key, which is
-        converted to the <type>text</type> type.
-        It cannot be <literal>NULL</literal> nor can it
-        belong to a type that has a cast to the <type>json</type>.
-        If <literal>WITH UNIQUE</literal> is specified, there must not
-        be any duplicate <parameter>key_expression</parameter>.
-        If <literal>ABSENT ON NULL</literal> is specified, the entire
-        pair is omitted if the <parameter>value_expression</parameter>
-        is <literal>NULL</literal>.
-       </para>
-       <para>
-        <literal>json_object('code' VALUE 'P123', 'title': 'Jaws')</literal>
-        <returnvalue>{"code" : "P123", "title" : "Jaws"}</returnvalue>
-      </para></entry>
-     </row>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        <indexterm><primary>json_objectagg</primary></indexterm>
-        <function>json_objectagg</function> (
-        <optional> { <parameter>key_expression</parameter> { <literal>VALUE</literal> | ':' } <parameter>value_expression</parameter> } </optional>
-        <optional> { <literal>NULL</literal> | <literal>ABSENT</literal> } <literal>ON NULL</literal> </optional>
-        <optional> { <literal>WITH</literal> | <literal>WITHOUT</literal> } <literal>UNIQUE</literal> <optional> <literal>KEYS</literal> </optional> </optional>
-        <optional> <literal>RETURNING</literal> <replaceable>data_type</replaceable> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> </optional>)
-       </para>
-       <para>
-        Behaves like <function>json_object</function> above, but as an
-        aggregate function, so it only takes one
-        <parameter>key_expression</parameter> and one
-        <parameter>value_expression</parameter> parameter.
-       </para>
-       <para>
-        <literal>SELECT json_objectagg(k:v) FROM (VALUES ('a'::text,current_date),('b',current_date + 1)) AS t(k,v)</literal>
-        <returnvalue>{ "a" : "2022-05-10", "b" : "2022-05-11" }</returnvalue>
-      </para></entry>
-     </row>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        <indexterm><primary>json_array</primary></indexterm>
-        <function>json_array</function> (
-        <optional> { <parameter>value_expression</parameter> <optional> <literal>FORMAT JSON</literal> </optional> } <optional>, ...</optional> </optional>
-        <optional> { <literal>NULL</literal> | <literal>ABSENT</literal> } <literal>ON NULL</literal> </optional>
-        <optional> <literal>RETURNING</literal> <replaceable>data_type</replaceable> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> </optional>)
-       </para>
-       <para role="func_signature">
-        <function>json_array</function> (
-        <optional> <replaceable>query_expression</replaceable> </optional>
-        <optional> <literal>RETURNING</literal> <replaceable>data_type</replaceable> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> </optional>)
-        </para>
-       <para>
-        Constructs a JSON array from either a series of
-        <parameter>value_expression</parameter> parameters or from the results
-        of <replaceable>query_expression</replaceable>,
-        which must be a SELECT query returning a single column. If
-        <literal>ABSENT ON NULL</literal> is specified, NULL values are ignored.
-        This is always the case if a
-        <replaceable>query_expression</replaceable> is used.
-       </para>
-       <para>
-        <literal>json_array(1,true,json '{"a":null}')</literal>
-        <returnvalue>[1, true, {"a":null}]</returnvalue>
-       </para>
-       <para>
-        <literal>json_array(SELECT * FROM (VALUES(1),(2)) t)</literal>
-        <returnvalue>[1, 2]</returnvalue>
-      </para></entry>
-     </row>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        <indexterm><primary>json_arrayagg</primary></indexterm>
-        <function>json_arrayagg</function> (
-        <optional> <parameter>value_expression</parameter> </optional>
-        <optional> <literal>ORDER BY</literal> <replaceable>sort_expression</replaceable> </optional>
-        <optional> { <literal>NULL</literal> | <literal>ABSENT</literal> } <literal>ON NULL</literal> </optional>
-        <optional> <literal>RETURNING</literal> <replaceable>data_type</replaceable> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> </optional>)
-       </para>
-       <para>
-        Behaves in the same way as <function>json_array</function>
-        but as an aggregate function so it only takes one
-        <parameter>value_expression</parameter> parameter.
-        If <literal>ABSENT ON NULL</literal> is specified, any NULL
-        values are omitted.
-        If <literal>ORDER BY</literal> is specified, the elements will
-        appear in the array in that order rather than in the input order.
-       </para>
-       <para>
-        <literal>SELECT json_arrayagg(v) FROM (VALUES(2),(1)) t(v)</literal>
-        <returnvalue>[2, 1]</returnvalue>
-      </para></entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <para>
-   <xref linkend="functions-sqljson-misc" /> details SQL/JSON
-   facilities for testing and serializing JSON.
-  </para>
-
-  <table id="functions-sqljson-misc">
-   <title>SQL/JSON Testing and Serializing Functions</title>
-   <tgroup cols="1">
-    <thead>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        Function signature
-       </para>
-       <para>
-        Description
-       </para>
-       <para>
-        Example(s)
-      </para></entry>
-     </row>
-    </thead>
-    <tbody>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        <indexterm><primary>IS JSON</primary></indexterm>
-        <parameter>expression</parameter> <literal>IS</literal> <optional> <literal>NOT</literal> </optional> <literal>JSON</literal>
-        <optional> { <literal>VALUE</literal> | <literal>SCALAR</literal> | <literal>ARRAY</literal> | <literal>OBJECT</literal> } </optional>
-        <optional> { <literal>WITH</literal> | <literal>WITHOUT</literal> } <literal>UNIQUE</literal> <optional> <literal>KEYS</literal> </optional> </optional>
-       </para>
-       <para>
-        This predicate tests whether <parameter>expression</parameter> can be
-        parsed as JSON, possibly of a specified type.
-        If <literal>SCALAR</literal> or <literal>ARRAY</literal> or
-        <literal>OBJECT</literal> is specified, the
-        test is whether or not the JSON is of that particular type. If
-        <literal>WITH UNIQUE</literal> is specified, then an any object in the
-        <parameter>expression</parameter> is also tested to see if it
-        has duplicate keys.
-       </para>
-       <para>
-<screen>
-SELECT js,
-  js IS JSON "json?",
-  js IS JSON SCALAR "scalar?",
-  js IS JSON OBJECT "object?",
-  js IS JSON ARRAY "array?"
-FROM
-(VALUES ('123'), ('"abc"'), ('{"a": "b"}'),
-('[1,2]'),('abc')) foo(js);
-     js     | json? | scalar? | object? | array?
-------------+-------+---------+---------+--------
- 123        | t     | t       | f       | f
- "abc"      | t     | t       | f       | f
- {"a": "b"} | t     | f       | t       | f
- [1,2]      | t     | f       | f       | t
- abc        | f     | f       | f       | f
-</screen>
-      </para></entry>
-     </row>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        <function>json_serialize</function> (
-        <parameter>expression</parameter> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional>
-        <optional> <literal>RETURNING</literal> <parameter>data_type</parameter> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> </optional>)
-       </para>
-       <para>
-        Transforms an SQL/JSON value into a character or binary string. The
-        <parameter>expression</parameter> can be of any JSON type, any
-        character string type, or <type>bytea</type> in UTF8 encoding.
-        The returned type can be any character string type or
-        <type>bytea</type>. The default is <type>text</type>.
-       </para>
-       <para>
-        <literal>json_serialize('{ "a" : 1 } ' RETURNING bytea)</literal>
-        <returnvalue>\x7b20226122203a2031207d20</returnvalue>
-      </para></entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <para>
-   <xref linkend="functions-sqljson-querying"/> details the SQL/JSON
-   functions that can be used to query JSON data, except
-   for <function>json_table</function>.
-  </para>
-
-  <note>
-   <para>
-    SQL/JSON paths can only be applied to the <type>jsonb</type> type, so it
-    might be necessary to cast the <parameter>context_item</parameter>
-    argument of these functions to <type>jsonb</type>.
-   </para>
-  </note>
-
-  <table id="functions-sqljson-querying">
-   <title>SQL/JSON Query Functions</title>
-   <tgroup cols="1">
-    <thead>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        Function signature
-       </para>
-       <para>
-        Description
-       </para>
-       <para>
-        Example(s)
-      </para></entry>
-     </row>
-    </thead>
-    <tbody>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        <indexterm><primary>json_exists</primary></indexterm>
-        <function>json_exists</function> (
-        <parameter>context_item</parameter>, <parameter>path_expression</parameter> <optional> <literal>PASSING</literal> { <parameter>value</parameter> <literal>AS</literal> <replaceable>varname</replaceable> } <optional>, ...</optional></optional>
-        <optional> <literal>RETURNING</literal> <replaceable>data_type</replaceable> </optional>
-        <optional> { <literal>TRUE</literal> | <literal>FALSE</literal> |<literal> UNKNOWN</literal> | <literal>ERROR</literal> } <literal>ON ERROR</literal> </optional>)
-       </para>
-       <para>
-        Returns true if the SQL/JSON <parameter>path_expression</parameter>
-        applied to the <parameter>context_item</parameter> using the
-        <parameter>value</parameter>s yields any items.
-        The <literal>ON ERROR</literal> clause specifies what is returned if
-        an error occurs. Note that if the <parameter>path_expression</parameter>
-        is <literal>strict</literal>, an error is generated if it yields no items.
-        The default value is <literal>UNKNOWN</literal> which causes a NULL
-        result.
-       </para>
-       <para>
-        <literal>json_exists(jsonb '{"key1": [1,2,3]}', 'strict $.key1[*] ? (@ > 2)')</literal>
-        <returnvalue>t</returnvalue>
-       </para>
-       <para>
-        <literal>json_exists(jsonb '{"a": [1,2,3]}', 'lax $.a[5]' ERROR ON ERROR)</literal>
-        <returnvalue>f</returnvalue>
-       </para>
-       <para>
-        <literal>json_exists(jsonb '{"a": [1,2,3]}', 'strict $.a[5]' ERROR ON ERROR)</literal>
-        <returnvalue>ERROR:  jsonpath array subscript is out of bounds</returnvalue>
-      </para></entry>
-     </row>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        <indexterm><primary>json_value</primary></indexterm>
-        <function>json_value</function> (
-        <parameter>context_item</parameter>, <parameter>path_expression</parameter>
-        <optional> <literal>PASSING</literal> { <parameter>value</parameter> <literal>AS</literal> <parameter>varname</parameter> } <optional>, ...</optional></optional>
-        <optional> <literal>RETURNING</literal> <parameter>data_type</parameter> </optional>
-        <optional> { <literal>ERROR</literal> | <literal>NULL</literal> | <literal>DEFAULT</literal> <parameter>expression</parameter> } <literal>ON EMPTY</literal> </optional>
-        <optional> { <literal>ERROR</literal> | <literal>NULL</literal> | <literal>DEFAULT</literal> <parameter>expression</parameter> } <literal>ON ERROR</literal> </optional>)
-       </para>
-       <para>
-        Returns the result of applying the
-        <parameter>path_expression</parameter> to the
-        <parameter>context_item</parameter> using the
-        <parameter>value</parameter>s. The extracted value must be
-        a single <acronym>SQL/JSON</acronym> scalar item. For results that
-        are objects or arrays, use the <function>json_query</function>
-        instead.
-        The returned <parameter>data_type</parameter> has the same semantics
-        as for constructor functions like <function>json_objectagg</function>.
-        The default returned type is <type>text</type>.
-        The <literal>ON EMPTY</literal> clause specifies the behavior if the
-        <parameter>path_expression</parameter> yields no value at all.
-        The <literal>ON ERROR</literal> clause specifies the behavior if an
-        error occurs, as a result of either the evaluation or the application
-        of the <literal>ON EMPTY</literal> clause.
-       </para>
-       <para>
-        <literal>json_value(jsonb '"123.45"', '$' RETURNING float)</literal>
-        <returnvalue>123.45</returnvalue>
-       </para>
-       <para>
-        <literal>json_value(jsonb '"03:04 2015-02-01"', '$.datetime("HH24:MI&nbsp;YYYY-MM-DD")' RETURNING date)</literal>
-        <returnvalue>2015-02-01</returnvalue>
-       </para>
-       <para>
-        <literal>json_value(jsonb '[1,2]', 'strict $[*]' DEFAULT 9 ON ERROR)</literal>
-        <returnvalue>9</returnvalue>
-      </para></entry>
-     </row>
-     <row>
-      <entry role="func_table_entry"><para role="func_signature">
-        <indexterm><primary>json_query</primary></indexterm>
-        <function>json_query</function> (
-        <parameter>context_item</parameter>, <parameter>path_expression</parameter> <optional> <literal>PASSING</literal> { <parameter>value</parameter> <literal>AS</literal> <parameter>varname</parameter> } <optional>, ...</optional></optional>
-        <optional> <literal>RETURNING</literal> <parameter>data_type</parameter> <optional> <literal>FORMAT JSON</literal> <optional> <literal>ENCODING UTF8</literal> </optional> </optional> </optional>
-        <optional> { <literal>WITHOUT</literal> | <literal>WITH</literal> { <literal>CONDITIONAL</literal> | <optional><literal>UNCONDITIONAL</literal></optional> } } <optional> <literal>ARRAY</literal> </optional> <literal>WRAPPER</literal> </optional>
-        <optional> { <literal>KEEP</literal> | <literal>OMIT</literal> } <literal>QUOTES</literal> <optional> <literal>ON SCALAR STRING</literal> </optional> </optional>
-        <optional> { <literal>ERROR</literal> | <literal>NULL</literal> | <literal>EMPTY</literal> { <optional> <literal>ARRAY</literal> </optional> | <literal>OBJECT</literal> } | <literal>DEFAULT</literal> <parameter>expression</parameter> } <literal>ON EMPTY</literal> </optional>
-        <optional> { <literal>ERROR</literal> | <literal>NULL</literal> | <literal>EMPTY</literal> { <optional> <literal>ARRAY</literal> </optional> | <literal>OBJECT</literal> } | <literal>DEFAULT</literal> <parameter>expression</parameter> } <literal>ON ERROR</literal> </optional>)
-      </para>
-       <para>
-        Returns the result of applying the
-        <parameter>path_expression</parameter> to the
-        <parameter>context_item</parameter> using the
-        <parameter>value</parameter>s.
-        This function must return a JSON string, so if the path expression
-        returns multiple SQL/JSON items, you must wrap the result using the
-        <literal>WITH WRAPPER</literal> clause. If the wrapper is
-        <literal>UNCONDITIONAL</literal>, an array wrapper will always
-        be applied, even if the returned value is already a single JSON object
-        or array, but if it is <literal>CONDITIONAL</literal> it will not be
-        applied to a single array or object. <literal>UNCONDITIONAL</literal>
-        is the default.
-        If the result is a scalar string, by default the value returned will have
-        surrounding quotes making it a valid JSON value. However, this behavior
-        is reversed if <literal>OMIT QUOTES</literal> is specified.
-        The <literal>ON ERROR</literal> and <literal>ON EMPTY</literal>
-        clauses have similar semantics to those clauses for
-        <function>json_value</function>.
-        The returned <parameter>data_type</parameter> has the same semantics
-        as for constructor functions like <function>json_objectagg</function>.
-        The default returned type is <type>text</type>.
-       </para>
-       <para>
-        <literal>json_query(jsonb '[1,[2,3],null]', 'lax $[*][1]' WITH CONDITIONAL WRAPPER)</literal>
-        <returnvalue>[3]</returnvalue>
-      </para></entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
- </sect2>
-
- <sect2 id="functions-sqljson-table">
-  <title>JSON_TABLE</title>
-  <indexterm>
-   <primary>json_table</primary>
-  </indexterm>
-
-  <para>
-   <function>json_table</function> is an SQL/JSON function which
-   queries <acronym>JSON</acronym> data
-   and presents the results as a relational view, which can be accessed as a
-   regular SQL table. You can only use <function>json_table</function> inside the
-   <literal>FROM</literal> clause of a <literal>SELECT</literal> statement.
-  </para>
-
-  <para>
-   Taking JSON data as input, <function>json_table</function> uses
-   a path expression to extract a part of the provided data that
-   will be used as a <firstterm>row pattern</firstterm> for the
-   constructed view. Each SQL/JSON item at the top level of the row pattern serves
-   as the source for a separate row in the constructed relational view.
-  </para>
-
-  <para>
-   To split the row pattern into columns, <function>json_table</function>
-   provides the <literal>COLUMNS</literal> clause that defines the
-   schema of the created view. For each column to be constructed,
-   this clause provides a separate path expression that evaluates
-   the row pattern, extracts a JSON item, and returns it as a
-   separate SQL value for the specified column. If the required value
-   is stored in a nested level of the row pattern, it can be extracted
-   using the <literal>NESTED PATH</literal> subclause. Joining the
-   columns returned by <literal>NESTED PATH</literal> can add multiple
-   new rows to the constructed view. Such rows are called
-   <firstterm>child rows</firstterm>, as opposed to the <firstterm>parent row</firstterm>
-   that generates them.
-  </para>
-
-  <para>
-   The rows produced by <function>JSON_TABLE</function> are laterally
-   joined to the row that generated them, so you do not have to explicitly join
-   the constructed view with the original table holding <acronym>JSON</acronym>
-   data. Optionally, you can specify how to join the columns returned
-   by <literal>NESTED PATH</literal> using the <literal>PLAN</literal> clause.
-  </para>
-
-  <para>
-   Each <literal>NESTED PATH</literal> clause can generate one or more
-   columns. Columns produced by <literal>NESTED PATH</literal>s at the
-   same level are considered to be <firstterm>siblings</firstterm>,
-   while a column produced by a <literal>NESTED PATH</literal> is
-   considered to be a child of the column produced by and
-   <literal>NESTED PATH</literal> or row expression at a higher level.
-   Sibling columns are always joined first. Once they are processed,
-   the resulting rows are joined to the parent row.
-  </para>
-
-  <variablelist>
-   <varlistentry>
-    <term>
-     <literal><parameter>context_item</parameter>, <parameter>path_expression</parameter> <optional> <literal>AS</literal> <parameter>json_path_name</parameter> </optional> <optional> <literal>PASSING</literal> { <parameter>value</parameter> <literal>AS</literal> <parameter>varname</parameter> } <optional>, ...</optional></optional></literal>
-    </term>
-    <listitem>
-    <para>
-     The input data to query, the JSON path expression defining the query,
-     and an optional <literal>PASSING</literal> clause, which can provide data
-     values to the <parameter>path_expression</parameter>.
-     The result of the input data
-     evaluation is called the <firstterm>row pattern</firstterm>. The row
-     pattern is used as the source for row values in the constructed view.
-    </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>
-     <literal>COLUMNS</literal>( <parameter>json_table_column</parameter> <optional>, ...</optional> )
-    </term>
-    <listitem>
-
-    <para>
-     The <literal>COLUMNS</literal> clause defining the schema of the
-     constructed view. In this clause, you must specify all the columns
-     to be filled with SQL/JSON items.
-     The <parameter>json_table_column</parameter>
-     expression has the following syntax variants:
-    </para>
-
-  <variablelist>
-   <varlistentry>
-    <term>
-     <literal><parameter>name</parameter> <parameter>type</parameter>
-          <optional> <literal>PATH</literal> <parameter>json_path_specification</parameter> </optional></literal>
-    </term>
-    <listitem>
-
-    <para>
-     Inserts a single SQL/JSON item into each row of
-     the specified column.
-    </para>
-    <para>
-     The provided <literal>PATH</literal> expression parses the
-     row pattern defined by <parameter>json_api_common_syntax</parameter>
-     and fills the column with produced SQL/JSON items, one for each row.
-     If the <literal>PATH</literal> expression is omitted,
-     <function>JSON_TABLE</function> uses the
-     <literal>$.<replaceable>name</replaceable></literal> path expression,
-     where <replaceable>name</replaceable> is the provided column name.
-     In this case, the column name must correspond to one of the
-     keys within the SQL/JSON item produced by the row pattern.
-    </para>
-    <para>
-     Optionally, you can add <literal>ON EMPTY</literal> and
-     <literal>ON ERROR</literal> clauses to define how to handle missing values
-     or structural errors.
-     <literal>WRAPPER</literal> and <literal>QUOTES</literal> clauses can only
-     be used with JSON, array, and composite types.
-     These clauses have the same syntax and semantics as for
-     <function>json_value</function> and <function>json_query</function>.
-    </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>
-     <parameter>name</parameter> <parameter>type</parameter> <literal>FORMAT</literal> <parameter>json_representation</parameter>
-          <optional> <literal>PATH</literal> <parameter>json_path_specification</parameter> </optional>
-    </term>
-    <listitem>
-
-    <para>
-     Generates a column and inserts a composite SQL/JSON
-     item into each row of this column.
-    </para>
-    <para>
-     The provided <literal>PATH</literal> expression parses the
-     row pattern defined by <parameter>json_api_common_syntax</parameter>
-     and fills the column with produced SQL/JSON items, one for each row.
-     If the <literal>PATH</literal> expression is omitted,
-     <function>JSON_TABLE</function> uses the
-     <literal>$.<parameter>name</parameter></literal> path expression,
-     where <parameter>name</parameter> is the provided column name.
-     In this case, the column name must correspond to one of the
-     keys within the SQL/JSON item produced by the row pattern.
-    </para>
-    <para>
-     Optionally, you can add <literal>WRAPPER</literal>, <literal>QUOTES</literal>,
-     <literal>ON EMPTY</literal> and <literal>ON ERROR</literal> clauses
-     to define additional settings for the returned SQL/JSON items.
-     These clauses have the same syntax and semantics as
-     for <function>json_query</function>.
-    </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>
-       <parameter>name</parameter> <parameter>type</parameter>
-       <literal>EXISTS</literal> <optional> <literal>PATH</literal> <parameter>json_path_specification</parameter> </optional>
-    </term>
-    <listitem>
-
-    <para>
-     Generates a column and inserts a boolean item into each row of this column.
-    </para>
-    <para>
-     The provided <literal>PATH</literal> expression parses the
-     row pattern defined by <parameter>json_api_common_syntax</parameter>,
-     checks whether any SQL/JSON items were returned, and fills the column with
-     resulting boolean value, one for each row.
-     The specified <parameter>type</parameter> should have cast from
-     <type>boolean</type>.
-     If the <literal>PATH</literal> expression is omitted,
-     <function>JSON_TABLE</function> uses the
-     <literal>$.<replaceable>name</replaceable></literal> path expression,
-     where <replaceable>name</replaceable> is the provided column name.
-    </para>
-    <para>
-     Optionally, you can add <literal>ON ERROR</literal> clause to define
-     error behavior.  This clause has the same syntax and semantics as
-     for <function>json_exists</function>.
-    </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>
-     <literal>NESTED PATH</literal> <parameter>json_path_specification</parameter> <optional> <literal>AS</literal> <parameter>json_path_name</parameter> </optional>
-          <literal>COLUMNS</literal> ( <parameter>json_table_column</parameter> <optional>, ...</optional> )
-    </term>
-    <listitem>
-
-    <para>
-     Extracts SQL/JSON items from nested levels of the row pattern,
-     generates one or more columns as defined by the <literal>COLUMNS</literal>
-     subclause, and inserts the extracted SQL/JSON items into each row of these columns.
-     The <parameter>json_table_column</parameter> expression in the
-     <literal>COLUMNS</literal> subclause uses the same syntax as in the
-     parent <literal>COLUMNS</literal> clause.
-    </para>
-
-    <para>
-     The <literal>NESTED PATH</literal> syntax is recursive,
-     so you can go down multiple nested levels by specifying several
-     <literal>NESTED PATH</literal> subclauses within each other.
-     It allows to unnest the hierarchy of JSON objects and arrays
-     in a single function invocation rather than chaining several
-     <function>JSON_TABLE</function> expressions in an SQL statement.
-    </para>
-
-    <para>
-     You can use the <literal>PLAN</literal> clause to define how
-     to join the columns returned by <parameter>NESTED PATH</parameter> clauses.
-    </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>
-     <parameter>name</parameter> <literal>FOR ORDINALITY</literal>
-    </term>
-    <listitem>
-
-    <para>
-     Adds an ordinality column that provides sequential row numbering.
-     You can have only one ordinality column per table. Row numbering
-     is 1-based. For child rows that result from the <literal>NESTED PATH</literal>
-     clauses, the parent row number is repeated.
-    </para>
-    </listitem>
-   </varlistentry>
-  </variablelist>
-
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>
-     <literal>AS</literal> <parameter>json_path_name</parameter>
-    </term>
-    <listitem>
-
-    <para>
-     The optional <parameter>json_path_name</parameter> serves as an
-     identifier of the provided <parameter>json_path_specification</parameter>.
-     The path name must be unique and distinct from the column names.
-     When using the <literal>PLAN</literal> clause, you must specify the names
-     for all the paths, including the row pattern. Each path name can appear in
-     the <literal>PLAN</literal> clause only once.
-    </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>
-     <literal>PLAN</literal> ( <parameter>json_table_plan</parameter> )
-    </term>
-    <listitem>
-
-    <para>
-     Defines how to join the data returned by <literal>NESTED PATH</literal>
-     clauses to the constructed view.
-    </para>
-    <para>
-     To join columns with parent/child relationship, you can use:
-    </para>
-  <variablelist>
-   <varlistentry>
-    <term>
-     <literal>INNER</literal>
-    </term>
-    <listitem>
-
-    <para>
-     Use <literal>INNER JOIN</literal>, so that the parent row
-     is omitted from the output if it does not have any child rows
-     after joining the data returned by <literal>NESTED PATH</literal>.
-    </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>
-     <literal>OUTER</literal>
-    </term>
-    <listitem>
-
-    <para>
-     Use <literal>LEFT OUTER JOIN</literal>, so that the parent row
-     is always included into the output even if it does not have any child rows
-     after joining the data returned by <literal>NESTED PATH</literal>, with NULL values
-     inserted into the child columns if the corresponding
-     values are missing.
-    </para>
-    <para>
-     This is the default option for joining columns with parent/child relationship.
-    </para>
-    </listitem>
-   </varlistentry>
-  </variablelist>
-
-     <para>
-     To join sibling columns, you can use:
-    </para>
-
-  <variablelist>
-   <varlistentry>
-    <term>
-     <literal>UNION</literal>
-    </term>
-    <listitem>
-
-    <para>
-     Generate one row for each value produced by each of the sibling
-     columns. The columns from the other siblings are set to null.
-    </para>
-    <para>
-     This is the default option for joining sibling columns.
-    </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>
-     <literal>CROSS</literal>
-    </term>
-    <listitem>
-
-    <para>
-     Generate one row for each combination of values from the sibling columns.
-    </para>
-    </listitem>
-   </varlistentry>
-
-  </variablelist>
-
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term>
-     <literal>PLAN DEFAULT</literal> ( <replaceable>OUTER | INNER</replaceable> <optional>, <replaceable>UNION | CROSS</replaceable> </optional> )
-    </term>
-    <listitem>
-     <para>
-      The terms can also be specified in reverse order. The
-      <literal>INNER</literal> or <literal>OUTER</literal> option defines the
-      joining plan for parent/child columns, while <literal>UNION</literal> or
-      <literal>CROSS</literal> affects joins of sibling columns. This form
-      of <literal>PLAN</literal> overrides the default plan for
-      all columns at once. Even though the path names are not included in the
-      <literal>PLAN DEFAULT</literal> form, to conform to the SQL/JSON standard
-      they must be provided for all the paths if the <literal>PLAN</literal>
-      clause is used.
-     </para>
-     <para>
-      <literal>PLAN DEFAULT</literal> is simpler than specifying a complete
-      <literal>PLAN</literal>, and is often all that is required to get the desired
-      output.
-     </para>
-    </listitem>
-   </varlistentry>
-  </variablelist>
-
-  <para>Examples</para>
-
-     <para>
-     In these examples the following small table storing some JSON data will be used:
-<programlisting>
-CREATE TABLE my_films ( js jsonb );
-
-INSERT INTO my_films VALUES (
-'{ "favorites" : [
-   { "kind" : "comedy", "films" : [
-     { "title" : "Bananas",
-       "director" : "Woody Allen"},
-     { "title" : "The Dinner Game",
-       "director" : "Francis Veber" } ] },
-   { "kind" : "horror", "films" : [
-     { "title" : "Psycho",
-       "director" : "Alfred Hitchcock" } ] },
-   { "kind" : "thriller", "films" : [
-     { "title" : "Vertigo",
-       "director" : "Alfred Hitchcock" } ] },
-   { "kind" : "drama", "films" : [
-     { "title" : "Yojimbo",
-       "director" : "Akira Kurosawa" } ] }
-  ] }');
-</programlisting>
-     </para>
-     <para>
-      Query the <structname>my_films</structname> table holding
-      some JSON data about the films and create a view that
-      distributes the film genre, title, and director between separate columns:
-<screen>
-SELECT jt.* FROM
- my_films,
- JSON_TABLE ( js, '$.favorites[*]' COLUMNS (
-   id FOR ORDINALITY,
-   kind text PATH '$.kind',
-   NESTED PATH '$.films[*]' COLUMNS (
-     title text PATH '$.title',
-     director text PATH '$.director'))) AS jt;
-----+----------+------------------+-------------------
- id |   kind   |       title      |    director
-----+----------+------------------+-------------------
- 1  | comedy   | Bananas          | Woody Allen
- 1  | comedy   | The Dinner Game  | Francis Veber
- 2  | horror   | Psycho           | Alfred Hitchcock
- 3  | thriller | Vertigo          | Alfred Hitchcock
- 4  | drama    | Yojimbo          | Akira Kurosawa
- (5 rows)
-</screen>
-     </para>
-
-     <para>
-      Find a director that has done films in two different genres:
-<screen>
-SELECT
-  director1 AS director, title1, kind1, title2, kind2
-FROM
-  my_films,
-  JSON_TABLE ( js, '$.favorites' AS favs COLUMNS (
-    NESTED PATH '$[*]' AS films1 COLUMNS (
-      kind1 text PATH '$.kind',
-      NESTED PATH '$.films[*]' AS film1 COLUMNS (
-        title1 text PATH '$.title',
-        director1 text PATH '$.director')
-    ),
-    NESTED PATH '$[*]' AS films2 COLUMNS (
-      kind2 text PATH '$.kind',
-      NESTED PATH '$.films[*]' AS film2 COLUMNS (
-        title2 text PATH '$.title',
-        director2 text PATH '$.director'
-      )
-    )
-   )
-   PLAN (favs OUTER ((films1 INNER film1) CROSS (films2 INNER film2)))
-  ) AS jt
- WHERE kind1 > kind2 AND director1 = director2;
-
-     director     | title1  |  kind1   | title2 | kind2
-------------------+---------+----------+--------+--------
- Alfred Hitchcock | Vertigo | thriller | Psycho | horror
-(1 row)
-</screen>
-     </para>
- </sect2>
-
+  </sect2>
  </sect1>
 
  <sect1 id="functions-sequence">
@@ -20879,29 +19949,6 @@ SELECT NULLIF(value, '(none)') ...
        <entry>No</entry>
       </row>
 
-      <row>
-       <entry role="func_table_entry"><para role="func_signature">
-        <indexterm>
-         <primary>json_agg_strict</primary>
-        </indexterm>
-        <function>json_agg_strict</function> ( <type>anyelement</type> )
-        <returnvalue>json</returnvalue>
-       </para>
-       <para role="func_signature">
-        <indexterm>
-         <primary>jsonb_agg_strict</primary>
-        </indexterm>
-        <function>jsonb_agg_strict</function> ( <type>anyelement</type> )
-        <returnvalue>jsonb</returnvalue>
-       </para>
-       <para>
-        Collects all the input values, skipping nulls, into a JSON array.
-        Values are converted to JSON as per <function>to_json</function>
-        or <function>to_jsonb</function>.
-       </para></entry>
-       <entry>No</entry>
-      </row>
-
       <row>
        <entry role="func_table_entry"><para role="func_signature">
         <indexterm>
@@ -20923,97 +19970,9 @@ SELECT NULLIF(value, '(none)') ...
        </para>
        <para>
         Collects all the key/value pairs into a JSON object.  Key arguments
-        are coerced to text; value arguments are converted as per
-        <function>to_json</function> or <function>to_jsonb</function>
-        Values can be null, but keys cannot.
-       </para></entry>
-       <entry>No</entry>
-      </row>
-
-      <row>
-       <entry role="func_table_entry"><para role="func_signature">
-        <indexterm>
-         <primary>json_object_agg_strict</primary>
-        </indexterm>
-        <function>json_object_agg_strict</function> (
-         <parameter>key</parameter> <type>"any"</type>,
-         <parameter>value</parameter> <type>"any"</type> )
-        <returnvalue>json</returnvalue>
-       </para>
-       <para role="func_signature">
-        <indexterm>
-         <primary>jsonb_object_agg_strict</primary>
-        </indexterm>
-        <function>jsonb_object_agg_strict</function> (
-         <parameter>key</parameter> <type>"any"</type>,
-         <parameter>value</parameter> <type>"any"</type> )
-        <returnvalue>jsonb</returnvalue>
-       </para>
-       <para>
-        Collects all the key/value pairs into a JSON object.  Key arguments
-        are coerced to text; value arguments are converted as per
-        <function>to_json</function> or <function>to_jsonb</function>.
-        The <parameter>key</parameter> can not be null. If the
-        <parameter>value</parameter> is null then the entry is skipped,
-       </para></entry>
-       <entry>No</entry>
-      </row>
-
-      <row>
-       <entry role="func_table_entry"><para role="func_signature">
-        <indexterm>
-         <primary>json_object_agg_unique</primary>
-        </indexterm>
-        <function>json_object_agg_unique</function> (
-         <parameter>key</parameter> <type>"any"</type>,
-         <parameter>value</parameter> <type>"any"</type> )
-        <returnvalue>json</returnvalue>
-       </para>
-       <para role="func_signature">
-        <indexterm>
-         <primary>jsonb_object_agg_unique</primary>
-        </indexterm>
-        <function>jsonb_object_agg_unique</function> (
-         <parameter>key</parameter> <type>"any"</type>,
-         <parameter>value</parameter> <type>"any"</type> )
-        <returnvalue>jsonb</returnvalue>
-       </para>
-       <para>
-        Collects all the key/value pairs into a JSON object.  Key arguments
-        are coerced to text; value arguments are converted as per
-        <function>to_json</function> or <function>to_jsonb</function>.
-        Values can be null, but keys cannot.
-        If there is a duplicate key an error is thrown.
-       </para></entry>
-       <entry>No</entry>
-      </row>
-
-      <row>
-       <entry role="func_table_entry"><para role="func_signature">
-        <indexterm>
-         <primary>json_object_agg_unique_strict</primary>
-        </indexterm>
-        <function>json_object_agg_unique_strict</function> (
-         <parameter>key</parameter> <type>"any"</type>,
-         <parameter>value</parameter> <type>"any"</type> )
-        <returnvalue>json</returnvalue>
-       </para>
-       <para role="func_signature">
-        <indexterm>
-         <primary>jsonb_object_agg_unique_strict</primary>
-        </indexterm>
-        <function>jsonb_object_agg_unique_strict</function> (
-         <parameter>key</parameter> <type>"any"</type>,
-         <parameter>value</parameter> <type>"any"</type> )
-        <returnvalue>jsonb</returnvalue>
-       </para>
-       <para>
-        Collects all the key/value pairs into a JSON object.  Key arguments
-        are coerced to text; value arguments are converted as per
-        <function>to_json</function> or <function>to_jsonb</function>.
-        The <parameter>key</parameter> can not be null. If the
-        <parameter>value</parameter> is null then the entry is skipped,
-        If there is a duplicate key an error is thrown.
+        are coerced to text; value arguments are converted as
+        per <function>to_json</function> or <function>to_jsonb</function>.
+        Values can be null, but not keys.
        </para></entry>
        <entry>No</entry>
       </row>
@@ -21191,12 +20150,7 @@ SELECT NULLIF(value, '(none)') ...
   <para>
    The aggregate functions <function>array_agg</function>,
    <function>json_agg</function>, <function>jsonb_agg</function>,
-   <function>json_agg_strict</function>, <function>jsonb_agg_strict</function>,
    <function>json_object_agg</function>, <function>jsonb_object_agg</function>,
-   <function>json_object_agg_strict</function>, <function>jsonb_object_agg_strict</function>,
-   <function>json_object_agg_unique</function>, <function>jsonb_object_agg_unique</function>,
-   <function>json_object_agg_unique_strict</function>,
-   <function>jsonb_object_agg_unique_strict</function>,
    <function>string_agg</function>,
    and <function>xmlagg</function>, as well as similar user-defined
    aggregate functions, produce meaningfully different result values
@@ -21216,13 +20170,6 @@ SELECT xmlagg(x) FROM (SELECT x FROM test ORDER BY y DESC) AS tab;
    subquery's output to be reordered before the aggregate is computed.
   </para>
 
-  <note>
-   <para>
-    In addition to the JSON aggregates shown here, see the <function>json_objectagg</function>
-    and <function>json_arrayagg</function> constructors in <xref linkend="functions-sqljson"/>.
-   </para>
-  </note>
-
   <note>
     <indexterm>
       <primary>ANY</primary>
index 7e1a5e4d893d0ef0d4de3a46dfe80a68d6f4f037..b1bb0776dcb9bc937a166b1ea44eb010fdea02e5 100644 (file)
@@ -157,7 +157,6 @@ INTERVAL
 INTO
 IS
 JOIN
-JSON
 JSON_ARRAY
 JSON_ARRAYAGG
 JSON_EXISTS
index 0a9c7df4f4973c949d30e2df279952e003ea9714..da7c9c772e0918484ec1420fe53c6a58640b0392 100644 (file)
@@ -527,20 +527,20 @@ T652      SQL-dynamic statements in SQL routines                  NO
 T653   SQL-schema statements in external routines                      YES     
 T654   SQL-dynamic statements in external routines                     NO      
 T655   Cyclically dependent routines                   YES     
-T811   Basic SQL/JSON constructor functions                    YES     
-T812   SQL/JSON: JSON_OBJECTAGG                        YES     
-T813   SQL/JSON: JSON_ARRAYAGG with ORDER BY                   YES     
-T814   Colon in JSON_OBJECT or JSON_OBJECTAGG                  YES     
-T821   Basic SQL/JSON query operators                  YES     
-T822   SQL/JSON: IS JSON WITH UNIQUE KEYS predicate                    YES     
-T823   SQL/JSON: PASSING clause                        YES     
-T824   JSON_TABLE: specific PLAN clause                        YES     
-T825   SQL/JSON: ON EMPTY and ON ERROR clauses                 YES     
-T826   General value expression in ON ERROR or ON EMPTY clauses                        YES     
-T827   JSON_TABLE: sibling NESTED COLUMNS clauses                      YES     
-T828   JSON_QUERY                      YES     
-T829   JSON_QUERY: array wrapper options                       YES     
-T830   Enforcing unique keys in SQL/JSON constructor functions                 YES     
+T811   Basic SQL/JSON constructor functions                    NO      
+T812   SQL/JSON: JSON_OBJECTAGG                        NO      
+T813   SQL/JSON: JSON_ARRAYAGG with ORDER BY                   NO      
+T814   Colon in JSON_OBJECT or JSON_OBJECTAGG                  NO      
+T821   Basic SQL/JSON query operators                  NO      
+T822   SQL/JSON: IS JSON WITH UNIQUE KEYS predicate                    NO      
+T823   SQL/JSON: PASSING clause                        NO      
+T824   JSON_TABLE: specific PLAN clause                        NO      
+T825   SQL/JSON: ON EMPTY and ON ERROR clauses                 NO      
+T826   General value expression in ON ERROR or ON EMPTY clauses                        NO      
+T827   JSON_TABLE: sibling NESTED COLUMNS clauses                      NO      
+T828   JSON_QUERY                      NO      
+T829   JSON_QUERY: array wrapper options                       NO      
+T830   Enforcing unique keys in SQL/JSON constructor functions                 NO      
 T831   SQL/JSON path language: strict mode                     YES     
 T832   SQL/JSON path language: item method                     YES     
 T833   SQL/JSON path language: multiple subscripts                     YES     
@@ -548,7 +548,7 @@ T834        SQL/JSON path language: wildcard member accessor                        YES
 T835   SQL/JSON path language: filter expressions                      YES     
 T836   SQL/JSON path language: starts with predicate                   YES     
 T837   SQL/JSON path language: regex_like predicate                    YES     
-T838   JSON_TABLE: PLAN DEFAULT clause                 YES     
+T838   JSON_TABLE: PLAN DEFAULT clause                 NO      
 T839   Formatted cast of datetimes to/from character strings                   NO      
 M001   Datalinks                       NO      
 M002   Datalinks via SQL/CLI                   NO      
index e078456b191cf51721c335ee57e4809dd501532a..053d2ca5ae496a2df9bd1c7620bf5ca184538f26 100644 (file)
@@ -3851,13 +3851,7 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es)
                        break;
                case T_TableFuncScan:
                        Assert(rte->rtekind == RTE_TABLEFUNC);
-                       if (rte->tablefunc)
-                               if (rte->tablefunc->functype == TFT_XMLTABLE)
-                                       objectname = "xmltable";
-                               else                    /* Must be TFT_JSON_TABLE */
-                                       objectname = "json_table";
-                       else
-                               objectname = NULL;
+                       objectname = "xmltable";
                        objecttag = "Table Function Name";
                        break;
                case T_ValuesScan:
index d0a57c7aaee7f2dfebdc004f411a43561c2d9797..25a94bbaaaa477e7a97ff2be2cb017e124aee787 100644 (file)
@@ -47,9 +47,6 @@
 #include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/datum.h"
-#include "utils/json.h"
-#include "utils/jsonb.h"
-#include "utils/jsonpath.h"
 #include "utils/lsyscache.h"
 #include "utils/typcache.h"
 
@@ -88,40 +85,6 @@ static void ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
                                                                  bool nullcheck);
 
 
-static ExprState *
-ExecInitExprInternal(Expr *node, PlanState *parent, ParamListInfo ext_params,
-                                        Datum *caseval, bool *casenull)
-{
-       ExprState  *state;
-       ExprEvalStep scratch = {0};
-
-       /* Special case: NULL expression produces a NULL ExprState pointer */
-       if (node == NULL)
-               return NULL;
-
-       /* Initialize ExprState with empty step list */
-       state = makeNode(ExprState);
-       state->expr = node;
-       state->parent = parent;
-       state->ext_params = ext_params;
-       state->innermost_caseval = caseval;
-       state->innermost_casenull = casenull;
-
-       /* Insert EEOP_*_FETCHSOME steps as needed */
-       ExecInitExprSlots(state, (Node *) node);
-
-       /* Compile the expression proper */
-       ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
-
-       /* Finally, append a DONE step */
-       scratch.opcode = EEOP_DONE;
-       ExprEvalPushStep(state, &scratch);
-
-       ExecReadyExpr(state);
-
-       return state;
-}
-
 /*
  * ExecInitExpr: prepare an expression tree for execution
  *
@@ -159,7 +122,32 @@ ExecInitExprInternal(Expr *node, PlanState *parent, ParamListInfo ext_params,
 ExprState *
 ExecInitExpr(Expr *node, PlanState *parent)
 {
-       return ExecInitExprInternal(node, parent, NULL, NULL, NULL);
+       ExprState  *state;
+       ExprEvalStep scratch = {0};
+
+       /* Special case: NULL expression produces a NULL ExprState pointer */
+       if (node == NULL)
+               return NULL;
+
+       /* Initialize ExprState with empty step list */
+       state = makeNode(ExprState);
+       state->expr = node;
+       state->parent = parent;
+       state->ext_params = NULL;
+
+       /* Insert EEOP_*_FETCHSOME steps as needed */
+       ExecInitExprSlots(state, (Node *) node);
+
+       /* Compile the expression proper */
+       ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
+
+       /* Finally, append a DONE step */
+       scratch.opcode = EEOP_DONE;
+       ExprEvalPushStep(state, &scratch);
+
+       ExecReadyExpr(state);
+
+       return state;
 }
 
 /*
@@ -171,20 +159,32 @@ ExecInitExpr(Expr *node, PlanState *parent)
 ExprState *
 ExecInitExprWithParams(Expr *node, ParamListInfo ext_params)
 {
-       return ExecInitExprInternal(node, NULL, ext_params, NULL, NULL);
-}
+       ExprState  *state;
+       ExprEvalStep scratch = {0};
 
-/*
- * ExecInitExprWithCaseValue: prepare an expression tree for execution
- *
- * This is the same as ExecInitExpr, except that a pointer to the value for
- * CasTestExpr is passed here.
- */
-ExprState *
-ExecInitExprWithCaseValue(Expr *node, PlanState *parent,
-                                                 Datum *caseval, bool *casenull)
-{
-       return ExecInitExprInternal(node, parent, NULL, caseval, casenull);
+       /* Special case: NULL expression produces a NULL ExprState pointer */
+       if (node == NULL)
+               return NULL;
+
+       /* Initialize ExprState with empty step list */
+       state = makeNode(ExprState);
+       state->expr = node;
+       state->parent = NULL;
+       state->ext_params = ext_params;
+
+       /* Insert EEOP_*_FETCHSOME steps as needed */
+       ExecInitExprSlots(state, (Node *) node);
+
+       /* Compile the expression proper */
+       ExecInitExprRec(node, state, &state->resvalue, &state->resnull);
+
+       /* Finally, append a DONE step */
+       scratch.opcode = EEOP_DONE;
+       ExprEvalPushStep(state, &scratch);
+
+       ExecReadyExpr(state);
+
+       return state;
 }
 
 /*
@@ -2411,263 +2411,6 @@ ExecInitExprRec(Expr *node, ExprState *state,
                                break;
                        }
 
-               case T_JsonValueExpr:
-                       {
-                               JsonValueExpr *jve = (JsonValueExpr *) node;
-
-                               ExecInitExprRec(jve->raw_expr, state, resv, resnull);
-
-                               if (jve->formatted_expr)
-                               {
-                                       Datum      *innermost_caseval = state->innermost_caseval;
-                                       bool       *innermost_isnull = state->innermost_casenull;
-
-                                       state->innermost_caseval = resv;
-                                       state->innermost_casenull = resnull;
-
-                                       ExecInitExprRec(jve->formatted_expr, state, resv, resnull);
-
-                                       state->innermost_caseval = innermost_caseval;
-                                       state->innermost_casenull = innermost_isnull;
-                               }
-                               break;
-                       }
-
-               case T_JsonConstructorExpr:
-                       {
-                               JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
-                               List       *args = ctor->args;
-                               ListCell   *lc;
-                               int                     nargs = list_length(args);
-                               int                     argno = 0;
-
-                               if (ctor->func)
-                               {
-                                       ExecInitExprRec(ctor->func, state, resv, resnull);
-                               }
-                               else if ((ctor->type == JSCTOR_JSON_PARSE && !ctor->unique) ||
-                                                ctor->type == JSCTOR_JSON_SERIALIZE)
-                               {
-                                       /* Use the value of the first argument as a result */
-                                       ExecInitExprRec(linitial(args), state, resv, resnull);
-                               }
-                               else
-                               {
-                                       JsonConstructorExprState *jcstate;
-
-                                       jcstate = palloc0(sizeof(JsonConstructorExprState));
-
-                                       scratch.opcode = EEOP_JSON_CONSTRUCTOR;
-                                       scratch.d.json_constructor.jcstate = jcstate;
-
-                                       jcstate->constructor = ctor;
-                                       jcstate->arg_values = palloc(sizeof(Datum) * nargs);
-                                       jcstate->arg_nulls = palloc(sizeof(bool) * nargs);
-                                       jcstate->arg_types = palloc(sizeof(Oid) * nargs);
-                                       jcstate->nargs = nargs;
-
-                                       foreach(lc, args)
-                                       {
-                                               Expr       *arg = (Expr *) lfirst(lc);
-
-                                               jcstate->arg_types[argno] = exprType((Node *) arg);
-
-                                               if (IsA(arg, Const))
-                                               {
-                                                       /* Don't evaluate const arguments every round */
-                                                       Const      *con = (Const *) arg;
-
-                                                       jcstate->arg_values[argno] = con->constvalue;
-                                                       jcstate->arg_nulls[argno] = con->constisnull;
-                                               }
-                                               else
-                                               {
-                                                       ExecInitExprRec(arg, state,
-                                                                                       &jcstate->arg_values[argno],
-                                                                                       &jcstate->arg_nulls[argno]);
-                                               }
-                                               argno++;
-                                       }
-
-                                       /* prepare type cache for datum_to_json[b]() */
-                                       if (ctor->type == JSCTOR_JSON_SCALAR)
-                                       {
-                                               bool            is_jsonb =
-                                               ctor->returning->format->format_type == JS_FORMAT_JSONB;
-
-                                               jcstate->arg_type_cache =
-                                                       palloc(sizeof(*jcstate->arg_type_cache) * nargs);
-
-                                               for (int i = 0; i < nargs; i++)
-                                               {
-                                                       int                     category;
-                                                       Oid                     outfuncid;
-                                                       Oid                     typid = jcstate->arg_types[i];
-
-                                                       if (is_jsonb)
-                                                       {
-                                                               JsonbTypeCategory jbcat;
-
-                                                               jsonb_categorize_type(typid, &jbcat, &outfuncid);
-
-                                                               category = (int) jbcat;
-                                                       }
-                                                       else
-                                                       {
-                                                               JsonTypeCategory jscat;
-
-                                                               json_categorize_type(typid, &jscat, &outfuncid);
-
-                                                               category = (int) jscat;
-                                                       }
-
-                                                       jcstate->arg_type_cache[i].outfuncid = outfuncid;
-                                                       jcstate->arg_type_cache[i].category = category;
-                                               }
-                                       }
-
-                                       ExprEvalPushStep(state, &scratch);
-                               }
-
-                               if (ctor->coercion)
-                               {
-                                       Datum      *innermost_caseval = state->innermost_caseval;
-                                       bool       *innermost_isnull = state->innermost_casenull;
-
-                                       state->innermost_caseval = resv;
-                                       state->innermost_casenull = resnull;
-
-                                       ExecInitExprRec(ctor->coercion, state, resv, resnull);
-
-                                       state->innermost_caseval = innermost_caseval;
-                                       state->innermost_casenull = innermost_isnull;
-                               }
-                       }
-                       break;
-
-               case T_JsonIsPredicate:
-                       {
-                               JsonIsPredicate *pred = (JsonIsPredicate *) node;
-
-                               ExecInitExprRec((Expr *) pred->expr, state, resv, resnull);
-
-                               scratch.opcode = EEOP_IS_JSON;
-                               scratch.d.is_json.pred = pred;
-
-                               ExprEvalPushStep(state, &scratch);
-                               break;
-                       }
-
-               case T_JsonExpr:
-                       {
-                               JsonExpr   *jexpr = castNode(JsonExpr, node);
-                               JsonExprState *jsestate = palloc0(sizeof(JsonExprState));
-                               ListCell   *argexprlc;
-                               ListCell   *argnamelc;
-
-                               scratch.opcode = EEOP_JSONEXPR;
-                               scratch.d.jsonexpr.jsestate = jsestate;
-
-                               jsestate->jsexpr = jexpr;
-
-                               jsestate->formatted_expr =
-                                       palloc(sizeof(*jsestate->formatted_expr));
-
-                               ExecInitExprRec((Expr *) jexpr->formatted_expr, state,
-                                                               &jsestate->formatted_expr->value,
-                                                               &jsestate->formatted_expr->isnull);
-
-                               jsestate->pathspec =
-                                       palloc(sizeof(*jsestate->pathspec));
-
-                               ExecInitExprRec((Expr *) jexpr->path_spec, state,
-                                                               &jsestate->pathspec->value,
-                                                               &jsestate->pathspec->isnull);
-
-                               jsestate->res_expr =
-                                       palloc(sizeof(*jsestate->res_expr));
-
-                               jsestate->result_expr = jexpr->result_coercion
-                                       ? ExecInitExprWithCaseValue((Expr *) jexpr->result_coercion->expr,
-                                                                                               state->parent,
-                                                                                               &jsestate->res_expr->value,
-                                                                                               &jsestate->res_expr->isnull)
-                                       : NULL;
-
-                               jsestate->default_on_empty = !jexpr->on_empty ? NULL :
-                                       ExecInitExpr((Expr *) jexpr->on_empty->default_expr,
-                                                                state->parent);
-
-                               jsestate->default_on_error =
-                                       ExecInitExpr((Expr *) jexpr->on_error->default_expr,
-                                                                state->parent);
-
-                               if (jexpr->omit_quotes ||
-                                       (jexpr->result_coercion && jexpr->result_coercion->via_io))
-                               {
-                                       Oid                     typinput;
-
-                                       /* lookup the result type's input function */
-                                       getTypeInputInfo(jexpr->returning->typid, &typinput,
-                                                                        &jsestate->input.typioparam);
-                                       fmgr_info(typinput, &jsestate->input.func);
-                               }
-
-                               jsestate->args = NIL;
-
-                               forboth(argexprlc, jexpr->passing_values,
-                                               argnamelc, jexpr->passing_names)
-                               {
-                                       Expr       *argexpr = (Expr *) lfirst(argexprlc);
-                                       String     *argname = lfirst_node(String, argnamelc);
-                                       JsonPathVariableEvalContext *var = palloc(sizeof(*var));
-
-                                       var->name = pstrdup(argname->sval);
-                                       var->typid = exprType((Node *) argexpr);
-                                       var->typmod = exprTypmod((Node *) argexpr);
-                                       var->estate = ExecInitExpr(argexpr, state->parent);
-                                       var->econtext = NULL;
-                                       var->mcxt = NULL;
-                                       var->evaluated = false;
-                                       var->value = (Datum) 0;
-                                       var->isnull = true;
-
-                                       jsestate->args =
-                                               lappend(jsestate->args, var);
-                               }
-
-                               jsestate->cache = NULL;
-
-                               if (jexpr->coercions)
-                               {
-                                       JsonCoercion **coercion;
-                                       struct JsonCoercionState *cstate;
-                                       Datum      *caseval;
-                                       bool       *casenull;
-
-                                       jsestate->coercion_expr =
-                                               palloc(sizeof(*jsestate->coercion_expr));
-
-                                       caseval = &jsestate->coercion_expr->value;
-                                       casenull = &jsestate->coercion_expr->isnull;
-
-                                       for (cstate = &jsestate->coercions.null,
-                                                coercion = &jexpr->coercions->null;
-                                                coercion <= &jexpr->coercions->composite;
-                                                coercion++, cstate++)
-                                       {
-                                               cstate->coercion = *coercion;
-                                               cstate->estate = *coercion ?
-                                                       ExecInitExprWithCaseValue((Expr *) (*coercion)->expr,
-                                                                                                         state->parent,
-                                                                                                         caseval, casenull) : NULL;
-                                       }
-                               }
-
-                               ExprEvalPushStep(state, &scratch);
-                               break;
-                       }
-
                default:
                        elog(ERROR, "unrecognized node type: %d",
                                 (int) nodeTag(node));
index 636794ca6f164145d1e46957135624b2b50f9bf8..9b9bbf00a9727250ee510d4ff07e57e01ac9ef30 100644 (file)
 #include "postgres.h"
 
 #include "access/heaptoast.h"
-#include "access/xact.h"
-#include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "commands/sequence.h"
 #include "executor/execExpr.h"
 #include "executor/nodeSubplan.h"
 #include "funcapi.h"
 #include "miscadmin.h"
-#include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
 #include "parser/parsetree.h"
-#include "parser/parse_expr.h"
 #include "pgstat.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/date.h"
 #include "utils/datum.h"
 #include "utils/expandedrecord.h"
-#include "utils/json.h"
-#include "utils/jsonb.h"
-#include "utils/jsonfuncs.h"
-#include "utils/jsonpath.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
-#include "utils/resowner.h"
 #include "utils/timestamp.h"
 #include "utils/typcache.h"
 #include "utils/xml.h"
@@ -488,9 +479,6 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
                &&CASE_EEOP_GROUPING_FUNC,
                &&CASE_EEOP_WINDOW_FUNC,
                &&CASE_EEOP_SUBPLAN,
-               &&CASE_EEOP_JSON_CONSTRUCTOR,
-               &&CASE_EEOP_IS_JSON,
-               &&CASE_EEOP_JSONEXPR,
                &&CASE_EEOP_AGG_STRICT_DESERIALIZE,
                &&CASE_EEOP_AGG_DESERIALIZE,
                &&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
@@ -1824,27 +1812,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
                {
                        /* too complex for an inline implementation */
                        ExecEvalAggOrderedTransTuple(state, op, econtext);
-                       EEO_NEXT();
-               }
-
-               EEO_CASE(EEOP_JSON_CONSTRUCTOR)
-               {
-                       /* too complex for an inline implementation */
-                       ExecEvalJsonConstructor(state, op, econtext);
-                       EEO_NEXT();
-               }
-
-               EEO_CASE(EEOP_IS_JSON)
-               {
-                       /* too complex for an inline implementation */
-                       ExecEvalJsonIsPredicate(state, op);
-                       EEO_NEXT();
-               }
 
-               EEO_CASE(EEOP_JSONEXPR)
-               {
-                       /* too complex for an inline implementation */
-                       ExecEvalJson(state, op, econtext);
                        EEO_NEXT();
                }
 
@@ -3972,91 +3940,6 @@ ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
        }
 }
 
-void
-ExecEvalJsonIsPredicate(ExprState *state, ExprEvalStep *op)
-{
-       JsonIsPredicate *pred = op->d.is_json.pred;
-       Datum           js = *op->resvalue;
-       Oid                     exprtype;
-       bool            res;
-
-       if (*op->resnull)
-       {
-               *op->resvalue = BoolGetDatum(false);
-               return;
-       }
-
-       exprtype = exprType(pred->expr);
-
-       if (exprtype == TEXTOID || exprtype == JSONOID)
-       {
-               text       *json = DatumGetTextP(js);
-
-               if (pred->item_type == JS_TYPE_ANY)
-                       res = true;
-               else
-               {
-                       switch (json_get_first_token(json, false))
-                       {
-                               case JSON_TOKEN_OBJECT_START:
-                                       res = pred->item_type == JS_TYPE_OBJECT;
-                                       break;
-                               case JSON_TOKEN_ARRAY_START:
-                                       res = pred->item_type == JS_TYPE_ARRAY;
-                                       break;
-                               case JSON_TOKEN_STRING:
-                               case JSON_TOKEN_NUMBER:
-                               case JSON_TOKEN_TRUE:
-                               case JSON_TOKEN_FALSE:
-                               case JSON_TOKEN_NULL:
-                                       res = pred->item_type == JS_TYPE_SCALAR;
-                                       break;
-                               default:
-                                       res = false;
-                                       break;
-                       }
-               }
-
-               /*
-                * Do full parsing pass only for uniqueness check or for JSON text
-                * validation.
-                */
-               if (res && (pred->unique_keys || exprtype == TEXTOID))
-                       res = json_validate(json, pred->unique_keys, false);
-       }
-       else if (exprtype == JSONBOID)
-       {
-               if (pred->item_type == JS_TYPE_ANY)
-                       res = true;
-               else
-               {
-                       Jsonb      *jb = DatumGetJsonbP(js);
-
-                       switch (pred->item_type)
-                       {
-                               case JS_TYPE_OBJECT:
-                                       res = JB_ROOT_IS_OBJECT(jb);
-                                       break;
-                               case JS_TYPE_ARRAY:
-                                       res = JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb);
-                                       break;
-                               case JS_TYPE_SCALAR:
-                                       res = JB_ROOT_IS_ARRAY(jb) && JB_ROOT_IS_SCALAR(jb);
-                                       break;
-                               default:
-                                       res = false;
-                                       break;
-                       }
-               }
-
-               /* Key uniqueness check is redundant for jsonb */
-       }
-       else
-               res = false;
-
-       *op->resvalue = BoolGetDatum(res);
-}
-
 /*
  * ExecEvalGroupingFunc
  *
@@ -4619,629 +4502,3 @@ ExecAggPlainTransByRef(AggState *aggstate, AggStatePerTrans pertrans,
 
        MemoryContextSwitchTo(oldContext);
 }
-
-/*
- * Evaluate a JSON constructor expression.
- */
-void
-ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op,
-                                               ExprContext *econtext)
-{
-       Datum           res;
-       JsonConstructorExprState *jcstate = op->d.json_constructor.jcstate;
-       JsonConstructorExpr *ctor = jcstate->constructor;
-       bool            is_jsonb = ctor->returning->format->format_type == JS_FORMAT_JSONB;
-       bool            isnull = false;
-
-       if (ctor->type == JSCTOR_JSON_ARRAY)
-               res = (is_jsonb ?
-                          jsonb_build_array_worker :
-                          json_build_array_worker) (jcstate->nargs,
-                                                                                jcstate->arg_values,
-                                                                                jcstate->arg_nulls,
-                                                                                jcstate->arg_types,
-                                                                                ctor->absent_on_null);
-       else if (ctor->type == JSCTOR_JSON_OBJECT)
-               res = (is_jsonb ?
-                          jsonb_build_object_worker :
-                          json_build_object_worker) (jcstate->nargs,
-                                                                                 jcstate->arg_values,
-                                                                                 jcstate->arg_nulls,
-                                                                                 jcstate->arg_types,
-                                                                                 ctor->absent_on_null,
-                                                                                 ctor->unique);
-       else if (ctor->type == JSCTOR_JSON_SCALAR)
-       {
-               if (jcstate->arg_nulls[0])
-               {
-                       res = (Datum) 0;
-                       isnull = true;
-               }
-               else
-               {
-                       Datum           value = jcstate->arg_values[0];
-                       int                     category = jcstate->arg_type_cache[0].category;
-                       Oid                     outfuncid = jcstate->arg_type_cache[0].outfuncid;
-
-                       if (is_jsonb)
-                               res = to_jsonb_worker(value, category, outfuncid);
-                       else
-                               res = to_json_worker(value, category, outfuncid);
-               }
-       }
-       else if (ctor->type == JSCTOR_JSON_PARSE)
-       {
-               if (jcstate->arg_nulls[0])
-               {
-                       res = (Datum) 0;
-                       isnull = true;
-               }
-               else
-               {
-                       Datum           value = jcstate->arg_values[0];
-                       text       *js = DatumGetTextP(value);
-
-                       if (is_jsonb)
-                               res = jsonb_from_text(js, true);
-                       else
-                       {
-                               (void) json_validate(js, true, true);
-                               res = value;
-                       }
-               }
-       }
-       else
-       {
-               res = (Datum) 0;
-               elog(ERROR, "invalid JsonConstructorExpr type %d", ctor->type);
-       }
-
-       *op->resvalue = res;
-       *op->resnull = isnull;
-}
-
-/*
- * Evaluate a JSON error/empty behavior result.
- */
-static Datum
-ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior,
-                                        ExprState *default_estate, bool *is_null)
-{
-       *is_null = false;
-
-       switch (behavior->btype)
-       {
-               case JSON_BEHAVIOR_EMPTY_ARRAY:
-                       return JsonbPGetDatum(JsonbMakeEmptyArray());
-
-               case JSON_BEHAVIOR_EMPTY_OBJECT:
-                       return JsonbPGetDatum(JsonbMakeEmptyObject());
-
-               case JSON_BEHAVIOR_TRUE:
-                       return BoolGetDatum(true);
-
-               case JSON_BEHAVIOR_FALSE:
-                       return BoolGetDatum(false);
-
-               case JSON_BEHAVIOR_NULL:
-               case JSON_BEHAVIOR_UNKNOWN:
-               case JSON_BEHAVIOR_EMPTY:
-                       *is_null = true;
-                       return (Datum) 0;
-
-               case JSON_BEHAVIOR_DEFAULT:
-                       return ExecEvalExpr(default_estate, econtext, is_null);
-
-               default:
-                       elog(ERROR, "unrecognized SQL/JSON behavior %d", behavior->btype);
-                       return (Datum) 0;
-       }
-}
-
-/*
- * Evaluate a coercion of a JSON item to the target type.
- */
-static Datum
-ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
-                                                Datum res, bool *isNull, void *p, bool *error)
-{
-       ExprState  *estate = p;
-       JsonExprState *jsestate;
-
-       if (estate)                                     /* coerce using specified expression */
-               return ExecEvalExpr(estate, econtext, isNull);
-
-       jsestate = op->d.jsonexpr.jsestate;
-
-       if (jsestate->jsexpr->op != JSON_EXISTS_OP)
-       {
-               JsonCoercion *coercion = jsestate->jsexpr->result_coercion;
-               JsonExpr   *jexpr = jsestate->jsexpr;
-               Jsonb      *jb = *isNull ? NULL : DatumGetJsonbP(res);
-
-               if ((coercion && coercion->via_io) ||
-                       (jexpr->omit_quotes && !*isNull &&
-                        JB_ROOT_IS_SCALAR(jb)))
-               {
-                       /* strip quotes and call typinput function */
-                       char       *str = *isNull ? NULL : JsonbUnquote(jb);
-
-                       return InputFunctionCall(&jsestate->input.func, str,
-                                                                        jsestate->input.typioparam,
-                                                                        jexpr->returning->typmod);
-               }
-               else if (coercion && coercion->via_populate)
-                       return json_populate_type(res, JSONBOID,
-                                                                         jexpr->returning->typid,
-                                                                         jexpr->returning->typmod,
-                                                                         &jsestate->cache,
-                                                                         econtext->ecxt_per_query_memory,
-                                                                         isNull);
-       }
-
-       if (jsestate->result_expr)
-       {
-               jsestate->res_expr->value = res;
-               jsestate->res_expr->isnull = *isNull;
-
-               res = ExecEvalExpr(jsestate->result_expr, econtext, isNull);
-       }
-
-       return res;
-}
-
-/*
- * Evaluate a JSON path variable caching computed value.
- */
-int
-EvalJsonPathVar(void *cxt, char *varName, int varNameLen,
-                               JsonbValue *val, JsonbValue *baseObject)
-{
-       JsonPathVariableEvalContext *var = NULL;
-       List       *vars = cxt;
-       ListCell   *lc;
-       int                     id = 1;
-
-       if (!varName)
-               return list_length(vars);
-
-       foreach(lc, vars)
-       {
-               var = lfirst(lc);
-
-               if (!strncmp(var->name, varName, varNameLen))
-                       break;
-
-               var = NULL;
-               id++;
-       }
-
-       if (!var)
-               return -1;
-
-       if (!var->evaluated)
-       {
-               MemoryContext oldcxt = var->mcxt ?
-               MemoryContextSwitchTo(var->mcxt) : NULL;
-
-               var->value = ExecEvalExpr(var->estate, var->econtext, &var->isnull);
-               var->evaluated = true;
-
-               if (oldcxt)
-                       MemoryContextSwitchTo(oldcxt);
-       }
-
-       if (var->isnull)
-       {
-               val->type = jbvNull;
-               return 0;
-       }
-
-       JsonItemFromDatum(var->value, var->typid, var->typmod, val);
-
-       *baseObject = *val;
-       return id;
-}
-
-/*
- * Prepare SQL/JSON item coercion to the output type. Returned a datum of the
- * corresponding SQL type and a pointer to the coercion state.
- */
-Datum
-ExecPrepareJsonItemCoercion(JsonbValue *item,
-                                                       JsonReturning *returning,
-                                                       struct JsonCoercionsState *coercions,
-                                                       struct JsonCoercionState **pcoercion)
-{
-       struct JsonCoercionState *coercion;
-       Datum           res;
-       JsonbValue      buf;
-
-       if (item->type == jbvBinary &&
-               JsonContainerIsScalar(item->val.binary.data))
-       {
-               bool            res PG_USED_FOR_ASSERTS_ONLY;
-
-               res = JsonbExtractScalar(item->val.binary.data, &buf);
-               item = &buf;
-               Assert(res);
-       }
-
-       /* get coercion state reference and datum of the corresponding SQL type */
-       switch (item->type)
-       {
-               case jbvNull:
-                       coercion = &coercions->null;
-                       res = (Datum) 0;
-                       break;
-
-               case jbvString:
-                       coercion = &coercions->string;
-                       res = PointerGetDatum(cstring_to_text_with_len(item->val.string.val,
-                                                                                                                  item->val.string.len));
-                       break;
-
-               case jbvNumeric:
-                       coercion = &coercions->numeric;
-                       res = NumericGetDatum(item->val.numeric);
-                       break;
-
-               case jbvBool:
-                       coercion = &coercions->boolean;
-                       res = BoolGetDatum(item->val.boolean);
-                       break;
-
-               case jbvDatetime:
-                       res = item->val.datetime.value;
-                       switch (item->val.datetime.typid)
-                       {
-                               case DATEOID:
-                                       coercion = &coercions->date;
-                                       break;
-                               case TIMEOID:
-                                       coercion = &coercions->time;
-                                       break;
-                               case TIMETZOID:
-                                       coercion = &coercions->timetz;
-                                       break;
-                               case TIMESTAMPOID:
-                                       coercion = &coercions->timestamp;
-                                       break;
-                               case TIMESTAMPTZOID:
-                                       coercion = &coercions->timestamptz;
-                                       break;
-                               default:
-                                       elog(ERROR, "unexpected jsonb datetime type oid %u",
-                                                item->val.datetime.typid);
-                                       return (Datum) 0;
-                       }
-                       break;
-
-               case jbvArray:
-               case jbvObject:
-               case jbvBinary:
-                       coercion = &coercions->composite;
-                       res = JsonbPGetDatum(JsonbValueToJsonb(item));
-                       break;
-
-               default:
-                       elog(ERROR, "unexpected jsonb value type %d", item->type);
-                       return (Datum) 0;
-       }
-
-       *pcoercion = coercion;
-
-       return res;
-}
-
-typedef Datum (*JsonFunc) (ExprEvalStep *op, ExprContext *econtext,
-                                                  Datum item, bool *resnull, void *p, bool *error);
-
-static Datum
-ExecEvalJsonExprSubtrans(JsonFunc func, ExprEvalStep *op,
-                                                ExprContext *econtext,
-                                                Datum res, bool *resnull,
-                                                void *p, bool *error, bool subtrans)
-{
-       MemoryContext oldcontext;
-       ResourceOwner oldowner;
-
-       if (!subtrans)
-               /* No need to use subtransactions. */
-               return func(op, econtext, res, resnull, p, error);
-
-       /*
-        * We should catch exceptions of category ERRCODE_DATA_EXCEPTION and
-        * execute the corresponding ON ERROR behavior then.
-        */
-       oldcontext = CurrentMemoryContext;
-       oldowner = CurrentResourceOwner;
-
-       Assert(error);
-
-       BeginInternalSubTransaction(NULL);
-       /* Want to execute expressions inside function's memory context */
-       MemoryContextSwitchTo(oldcontext);
-
-       PG_TRY();
-       {
-               res = func(op, econtext, res, resnull, p, error);
-
-               /* Commit the inner transaction, return to outer xact context */
-               ReleaseCurrentSubTransaction();
-               MemoryContextSwitchTo(oldcontext);
-               CurrentResourceOwner = oldowner;
-       }
-       PG_CATCH();
-       {
-               ErrorData  *edata;
-               int                     ecategory;
-
-               /* Save error info in oldcontext */
-               MemoryContextSwitchTo(oldcontext);
-               edata = CopyErrorData();
-               FlushErrorState();
-
-               /* Abort the inner transaction */
-               RollbackAndReleaseCurrentSubTransaction();
-               MemoryContextSwitchTo(oldcontext);
-               CurrentResourceOwner = oldowner;
-
-               ecategory = ERRCODE_TO_CATEGORY(edata->sqlerrcode);
-
-               if (ecategory != ERRCODE_DATA_EXCEPTION &&      /* jsonpath and other data
-                                                                                                        * errors */
-                       ecategory != ERRCODE_INTEGRITY_CONSTRAINT_VIOLATION)    /* domain errors */
-                       ReThrowError(edata);
-
-               res = (Datum) 0;
-               *error = true;
-       }
-       PG_END_TRY();
-
-       return res;
-}
-
-
-typedef struct
-{
-       JsonPath   *path;
-       bool       *error;
-       bool            coercionInSubtrans;
-} ExecEvalJsonExprContext;
-
-static Datum
-ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
-                                Datum item, bool *resnull, void *pcxt,
-                                bool *error)
-{
-       ExecEvalJsonExprContext *cxt = pcxt;
-       JsonPath   *path = cxt->path;
-       JsonExprState *jsestate = op->d.jsonexpr.jsestate;
-       JsonExpr   *jexpr = jsestate->jsexpr;
-       ExprState  *estate = NULL;
-       bool            empty = false;
-       Datum           res = (Datum) 0;
-
-       switch (jexpr->op)
-       {
-               case JSON_QUERY_OP:
-                       res = JsonPathQuery(item, path, jexpr->wrapper, &empty, error,
-                                                               jsestate->args);
-                       if (error && *error)
-                       {
-                               *resnull = true;
-                               return (Datum) 0;
-                       }
-                       *resnull = !DatumGetPointer(res);
-                       break;
-
-               case JSON_VALUE_OP:
-                       {
-                               struct JsonCoercionState *jcstate;
-                               JsonbValue *jbv = JsonPathValue(item, path, &empty, error,
-                                                                                               jsestate->args);
-
-                               if (error && *error)
-                                       return (Datum) 0;
-
-                               if (!jbv)               /* NULL or empty */
-                                       break;
-
-                               Assert(!empty);
-
-                               *resnull = false;
-
-                               /* coerce scalar item to the output type */
-                               if (jexpr->returning->typid == JSONOID ||
-                                       jexpr->returning->typid == JSONBOID)
-                               {
-                                       /* Use result coercion from json[b] to the output type */
-                                       res = JsonbPGetDatum(JsonbValueToJsonb(jbv));
-                                       break;
-                               }
-
-                               /* Use coercion from SQL/JSON item type to the output type */
-                               res = ExecPrepareJsonItemCoercion(jbv,
-                                                                                                 jsestate->jsexpr->returning,
-                                                                                                 &jsestate->coercions,
-                                                                                                 &jcstate);
-
-                               if (jcstate->coercion &&
-                                       (jcstate->coercion->via_io ||
-                                        jcstate->coercion->via_populate))
-                               {
-                                       if (error)
-                                       {
-                                               *error = true;
-                                               return (Datum) 0;
-                                       }
-
-                                       /*
-                                        * Coercion via I/O means here that the cast to the target
-                                        * type simply does not exist.
-                                        */
-                                       ereport(ERROR,
-                                                       (errcode(ERRCODE_SQL_JSON_ITEM_CANNOT_BE_CAST_TO_TARGET_TYPE),
-                                                        errmsg("SQL/JSON item cannot be cast to target type")));
-                               }
-                               else if (!jcstate->estate)
-                                       return res; /* no coercion */
-
-                               /* coerce using specific expression */
-                               estate = jcstate->estate;
-                               jsestate->coercion_expr->value = res;
-                               jsestate->coercion_expr->isnull = *resnull;
-                               break;
-                       }
-
-               case JSON_EXISTS_OP:
-                       {
-                               bool            exists = JsonPathExists(item, path,
-                                                                                                       jsestate->args,
-                                                                                                       error);
-
-                               *resnull = error && *error;
-                               res = BoolGetDatum(exists);
-
-                               if (!jsestate->result_expr)
-                                       return res;
-
-                               /* coerce using result expression */
-                               estate = jsestate->result_expr;
-                               jsestate->res_expr->value = res;
-                               jsestate->res_expr->isnull = *resnull;
-                               break;
-                       }
-
-               case JSON_TABLE_OP:
-                       *resnull = false;
-                       return item;
-
-               default:
-                       elog(ERROR, "unrecognized SQL/JSON expression op %d", jexpr->op);
-                       return (Datum) 0;
-       }
-
-       if (empty)
-       {
-               Assert(jexpr->on_empty);        /* it is not JSON_EXISTS */
-
-               if (jexpr->on_empty->btype == JSON_BEHAVIOR_ERROR)
-               {
-                       if (error)
-                       {
-                               *error = true;
-                               return (Datum) 0;
-                       }
-
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_NO_SQL_JSON_ITEM),
-                                        errmsg("no SQL/JSON item")));
-               }
-
-               if (jexpr->on_empty->btype == JSON_BEHAVIOR_DEFAULT)
-
-                       /*
-                        * Execute DEFAULT expression as a coercion expression, because
-                        * its result is already coerced to the target type.
-                        */
-                       estate = jsestate->default_on_empty;
-               else
-                       /* Execute ON EMPTY behavior */
-                       res = ExecEvalJsonBehavior(econtext, jexpr->on_empty,
-                                                                          jsestate->default_on_empty,
-                                                                          resnull);
-       }
-
-       return ExecEvalJsonExprSubtrans(ExecEvalJsonExprCoercion, op, econtext,
-                                                                       res, resnull, estate, error,
-                                                                       cxt->coercionInSubtrans);
-}
-
-bool
-ExecEvalJsonNeedsSubTransaction(JsonExpr *jsexpr,
-                                                               struct JsonCoercionsState *coercions)
-{
-       if (jsexpr->on_error->btype == JSON_BEHAVIOR_ERROR)
-               return false;
-
-       if (jsexpr->op == JSON_EXISTS_OP && !jsexpr->result_coercion)
-               return false;
-
-       if (!coercions)
-               return true;
-
-       return false;
-}
-
-/* ----------------------------------------------------------------
- *             ExecEvalJson
- * ----------------------------------------------------------------
- */
-void
-ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
-{
-       ExecEvalJsonExprContext cxt;
-       JsonExprState *jsestate = op->d.jsonexpr.jsestate;
-       JsonExpr   *jexpr = jsestate->jsexpr;
-       Datum           item;
-       Datum           res = (Datum) 0;
-       JsonPath   *path;
-       ListCell   *lc;
-       bool            error = false;
-       bool            needSubtrans;
-       bool            throwErrors = jexpr->on_error->btype == JSON_BEHAVIOR_ERROR;
-
-       *op->resnull = true;            /* until we get a result */
-       *op->resvalue = (Datum) 0;
-
-       if (jsestate->formatted_expr->isnull || jsestate->pathspec->isnull)
-       {
-               /* execute domain checks for NULLs */
-               (void) ExecEvalJsonExprCoercion(op, econtext, res, op->resnull,
-                                                                               NULL, NULL);
-
-               Assert(*op->resnull);
-               return;
-       }
-
-       item = jsestate->formatted_expr->value;
-       path = DatumGetJsonPathP(jsestate->pathspec->value);
-
-       /* reset JSON path variable contexts */
-       foreach(lc, jsestate->args)
-       {
-               JsonPathVariableEvalContext *var = lfirst(lc);
-
-               var->econtext = econtext;
-               var->evaluated = false;
-       }
-
-       needSubtrans = ExecEvalJsonNeedsSubTransaction(jexpr, &jsestate->coercions);
-
-       cxt.path = path;
-       cxt.error = throwErrors ? NULL : &error;
-       cxt.coercionInSubtrans = !needSubtrans && !throwErrors;
-       Assert(!needSubtrans || cxt.error);
-
-       res = ExecEvalJsonExprSubtrans(ExecEvalJsonExpr, op, econtext, item,
-                                                                  op->resnull, &cxt, cxt.error,
-                                                                  needSubtrans);
-
-       if (error)
-       {
-               /* Execute ON ERROR behavior */
-               res = ExecEvalJsonBehavior(econtext, jexpr->on_error,
-                                                                  jsestate->default_on_error,
-                                                                  op->resnull);
-
-               /* result is already coerced in DEFAULT behavior case */
-               if (jexpr->on_error->btype != JSON_BEHAVIOR_DEFAULT)
-                       res = ExecEvalJsonExprCoercion(op, econtext, res,
-                                                                                  op->resnull,
-                                                                                  NULL, NULL);
-       }
-
-       *op->resvalue = res;
-}
index 691c3e28cef3e9061a856cf554b7867e5750ce50..0db4ed0c2feca9827b3c5ca3aaea6a9223b0054b 100644 (file)
@@ -28,7 +28,6 @@
 #include "miscadmin.h"
 #include "nodes/execnodes.h"
 #include "utils/builtins.h"
-#include "utils/jsonpath.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 #include "utils/xml.h"
@@ -162,9 +161,8 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
        scanstate->ss.ps.qual =
                ExecInitQual(node->scan.plan.qual, &scanstate->ss.ps);
 
-       /* Only XMLTABLE and JSON_TABLE are supported currently */
-       scanstate->routine =
-               tf->functype == TFT_XMLTABLE ? &XmlTableRoutine : &JsonbTableRoutine;
+       /* Only XMLTABLE is supported currently */
+       scanstate->routine = &XmlTableRoutine;
 
        scanstate->perTableCxt =
                AllocSetContextCreate(CurrentMemoryContext,
@@ -383,17 +381,14 @@ tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
                routine->SetNamespace(tstate, ns_name, ns_uri);
        }
 
-       if (routine->SetRowFilter)
-       {
-               /* Install the row filter expression into the table builder context */
-               value = ExecEvalExpr(tstate->rowexpr, econtext, &isnull);
-               if (isnull)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
-                                        errmsg("row filter expression must not be null")));
+       /* Install the row filter expression into the table builder context */
+       value = ExecEvalExpr(tstate->rowexpr, econtext, &isnull);
+       if (isnull)
+               ereport(ERROR,
+                               (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+                                errmsg("row filter expression must not be null")));
 
-               routine->SetRowFilter(tstate, TextDatumGetCString(value));
-       }
+       routine->SetRowFilter(tstate, TextDatumGetCString(value));
 
        /*
         * Install the column filter expressions into the table builder context.
index bd3965143da270ff007b1af5600950469b1887bb..95d0807bddeeda82679b1144e38571d1a5b91915 100644 (file)
@@ -2395,24 +2395,6 @@ llvm_compile_expr(ExprState *state)
                                LLVMBuildBr(b, opblocks[opno + 1]);
                                break;
 
-                       case EEOP_JSON_CONSTRUCTOR:
-                               build_EvalXFunc(b, mod, "ExecEvalJsonConstructor",
-                                                               v_state, op, v_econtext);
-                               LLVMBuildBr(b, opblocks[opno + 1]);
-                               break;
-
-                       case EEOP_IS_JSON:
-                               build_EvalXFunc(b, mod, "ExecEvalJsonIsPredicate",
-                                                               v_state, op);
-                               LLVMBuildBr(b, opblocks[opno + 1]);
-                               break;
-
-                       case EEOP_JSONEXPR:
-                               build_EvalXFunc(b, mod, "ExecEvalJson",
-                                                               v_state, op, v_econtext);
-                               LLVMBuildBr(b, opblocks[opno + 1]);
-                               break;
-
                        case EEOP_LAST:
                                Assert(false);
                                break;
index 373471ad27fee85a071207e41a46153216712793..90ac6b83b5a020b769645aa8bcbaec60d67a4dbf 100644 (file)
@@ -133,9 +133,6 @@ void           *referenced_functions[] =
        ExecEvalSysVar,
        ExecEvalWholeRowVar,
        ExecEvalXmlExpr,
-       ExecEvalJsonConstructor,
-       ExecEvalJsonIsPredicate,
-       ExecEvalJson,
        MakeExpandedObjectReadOnlyInternal,
        slot_getmissingattrs,
        slot_getsomeattrs_int,
index 28288dcfc101c0530f80c506fc164ad90f9530cf..c85d8fe97511ce3f9ec21ff2f28722bc9ce27f64 100644 (file)
@@ -19,7 +19,6 @@
 #include "catalog/pg_type.h"
 #include "nodes/makefuncs.h"
 #include "nodes/nodeFuncs.h"
-#include "utils/errcodes.h"
 #include "utils/lsyscache.h"
 
 
@@ -819,124 +818,3 @@ makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols)
        v->va_cols = va_cols;
        return v;
 }
-
-/*
- * makeJsonFormat -
- *       creates a JsonFormat node
- */
-JsonFormat *
-makeJsonFormat(JsonFormatType type, JsonEncoding encoding, int location)
-{
-       JsonFormat *jf = makeNode(JsonFormat);
-
-       jf->format_type = type;
-       jf->encoding = encoding;
-       jf->location = location;
-
-       return jf;
-}
-
-/*
- * makeJsonValueExpr -
- *       creates a JsonValueExpr node
- */
-JsonValueExpr *
-makeJsonValueExpr(Expr *expr, JsonFormat *format)
-{
-       JsonValueExpr *jve = makeNode(JsonValueExpr);
-
-       jve->raw_expr = expr;
-       jve->formatted_expr = NULL;
-       jve->format = format;
-
-       return jve;
-}
-
-/*
- * makeJsonBehavior -
- *       creates a JsonBehavior node
- */
-JsonBehavior *
-makeJsonBehavior(JsonBehaviorType type, Node *default_expr)
-{
-       JsonBehavior *behavior = makeNode(JsonBehavior);
-
-       behavior->btype = type;
-       behavior->default_expr = default_expr;
-
-       return behavior;
-}
-
-/*
- * makeJsonTableJoinedPlan -
- *        creates a joined JsonTablePlan node
- */
-Node *
-makeJsonTableJoinedPlan(JsonTablePlanJoinType type, Node *plan1, Node *plan2,
-                                               int location)
-{
-       JsonTablePlan *n = makeNode(JsonTablePlan);
-
-       n->plan_type = JSTP_JOINED;
-       n->join_type = type;
-       n->plan1 = castNode(JsonTablePlan, plan1);
-       n->plan2 = castNode(JsonTablePlan, plan2);
-       n->location = location;
-
-       return (Node *) n;
-}
-
-/*
- * makeJsonEncoding -
- *       converts JSON encoding name to enum JsonEncoding
- */
-JsonEncoding
-makeJsonEncoding(char *name)
-{
-       if (!pg_strcasecmp(name, "utf8"))
-               return JS_ENC_UTF8;
-       if (!pg_strcasecmp(name, "utf16"))
-               return JS_ENC_UTF16;
-       if (!pg_strcasecmp(name, "utf32"))
-               return JS_ENC_UTF32;
-
-       ereport(ERROR,
-                       (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                        errmsg("unrecognized JSON encoding: %s", name)));
-
-       return JS_ENC_DEFAULT;
-}
-
-/*
- * makeJsonKeyValue -
- *       creates a JsonKeyValue node
- */
-Node *
-makeJsonKeyValue(Node *key, Node *value)
-{
-       JsonKeyValue *n = makeNode(JsonKeyValue);
-
-       n->key = (Expr *) key;
-       n->value = castNode(JsonValueExpr, value);
-
-       return (Node *) n;
-}
-
-/*
- * makeJsonIsPredicate -
- *       creates a JsonIsPredicate node
- */
-Node *
-makeJsonIsPredicate(Node *expr, JsonFormat *format, JsonValueType item_type,
-                                       bool unique_keys, int location)
-{
-       JsonIsPredicate *n = makeNode(JsonIsPredicate);
-
-       n->expr = expr;
-       n->format = format;
-       n->item_type = item_type;
-       n->unique_keys = unique_keys;
-       n->location = location;
-
-       return (Node *) n;
-}
index c334daae3928576d5c40d0f4190b09b66e973a3a..3bac350bf50cd167ebfc57647f388a2ecfb655bd 100644 (file)
@@ -250,25 +250,6 @@ exprType(const Node *expr)
                case T_PlaceHolderVar:
                        type = exprType((Node *) ((const PlaceHolderVar *) expr)->phexpr);
                        break;
-               case T_JsonValueExpr:
-                       {
-                               const JsonValueExpr *jve = (const JsonValueExpr *) expr;
-
-                               type = exprType((Node *) (jve->formatted_expr ? jve->formatted_expr : jve->raw_expr));
-                       }
-                       break;
-               case T_JsonConstructorExpr:
-                       type = ((const JsonConstructorExpr *) expr)->returning->typid;
-                       break;
-               case T_JsonIsPredicate:
-                       type = BOOLOID;
-                       break;
-               case T_JsonExpr:
-                       type = ((const JsonExpr *) expr)->returning->typid;
-                       break;
-               case T_JsonCoercion:
-                       type = exprType(((const JsonCoercion *) expr)->expr);
-                       break;
                default:
                        elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
                        type = InvalidOid;      /* keep compiler quiet */
@@ -501,14 +482,6 @@ exprTypmod(const Node *expr)
                        return ((const SetToDefault *) expr)->typeMod;
                case T_PlaceHolderVar:
                        return exprTypmod((Node *) ((const PlaceHolderVar *) expr)->phexpr);
-               case T_JsonValueExpr:
-                       return exprTypmod((Node *) ((const JsonValueExpr *) expr)->formatted_expr);
-               case T_JsonConstructorExpr:
-                       return ((const JsonConstructorExpr *) expr)->returning->typmod;
-               case T_JsonExpr:
-                       return ((JsonExpr *) expr)->returning->typmod;
-               case T_JsonCoercion:
-                       return exprTypmod(((const JsonCoercion *) expr)->expr);
                default:
                        break;
        }
@@ -991,37 +964,6 @@ exprCollation(const Node *expr)
                case T_PlaceHolderVar:
                        coll = exprCollation((Node *) ((const PlaceHolderVar *) expr)->phexpr);
                        break;
-               case T_JsonValueExpr:
-                       coll = exprCollation((Node *) ((const JsonValueExpr *) expr)->formatted_expr);
-                       break;
-               case T_JsonConstructorExpr:
-                       {
-                               const JsonConstructorExpr *ctor = (const JsonConstructorExpr *) expr;
-
-                               if (ctor->coercion)
-                                       coll = exprCollation((Node *) ctor->coercion);
-                               else
-                                       coll = InvalidOid;
-                       }
-                       break;
-               case T_JsonIsPredicate:
-                       coll = InvalidOid;      /* result is always an boolean type */
-                       break;
-               case T_JsonExpr:
-                       {
-                               JsonExpr   *jexpr = (JsonExpr *) expr;
-                               JsonCoercion *coercion = jexpr->result_coercion;
-
-                               if (!coercion)
-                                       coll = InvalidOid;
-                               else if (coercion->expr)
-                                       coll = exprCollation(coercion->expr);
-                               else if (coercion->via_io || coercion->via_populate)
-                                       coll = coercion->collation;
-                               else
-                                       coll = InvalidOid;
-                       }
-                       break;
                default:
                        elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
                        coll = InvalidOid;      /* keep compiler quiet */
@@ -1234,39 +1176,6 @@ exprSetCollation(Node *expr, Oid collation)
                        /* NextValueExpr's result is an integer type ... */
                        Assert(!OidIsValid(collation)); /* ... so never set a collation */
                        break;
-               case T_JsonValueExpr:
-                       exprSetCollation((Node *) ((JsonValueExpr *) expr)->formatted_expr,
-                                                        collation);
-                       break;
-               case T_JsonConstructorExpr:
-                       {
-                               JsonConstructorExpr *ctor = (JsonConstructorExpr *) expr;
-
-                               if (ctor->coercion)
-                                       exprSetCollation((Node *) ctor->coercion, collation);
-                               else
-                                       Assert(!OidIsValid(collation)); /* result is always a
-                                                                                                        * json[b] type */
-                       }
-                       break;
-               case T_JsonIsPredicate:
-                       Assert(!OidIsValid(collation)); /* result is always boolean */
-                       break;
-               case T_JsonExpr:
-                       {
-                               JsonExpr   *jexpr = (JsonExpr *) expr;
-                               JsonCoercion *coercion = jexpr->result_coercion;
-
-                               if (!coercion)
-                                       Assert(!OidIsValid(collation));
-                               else if (coercion->expr)
-                                       exprSetCollation(coercion->expr, collation);
-                               else if (coercion->via_io || coercion->via_populate)
-                                       coercion->collation = collation;
-                               else
-                                       Assert(!OidIsValid(collation));
-                       }
-                       break;
                default:
                        elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
                        break;
@@ -1713,24 +1622,6 @@ exprLocation(const Node *expr)
                case T_PartitionRangeDatum:
                        loc = ((const PartitionRangeDatum *) expr)->location;
                        break;
-               case T_JsonValueExpr:
-                       loc = exprLocation((Node *) ((const JsonValueExpr *) expr)->raw_expr);
-                       break;
-               case T_JsonConstructorExpr:
-                       loc = ((const JsonConstructorExpr *) expr)->location;
-                       break;
-               case T_JsonIsPredicate:
-                       loc = ((const JsonIsPredicate *) expr)->location;
-                       break;
-               case T_JsonExpr:
-                       {
-                               const JsonExpr *jsexpr = (const JsonExpr *) expr;
-
-                               /* consider both function name and leftmost arg */
-                               loc = leftmostLoc(jsexpr->location,
-                                                                 exprLocation(jsexpr->formatted_expr));
-                       }
-                       break;
                default:
                        /* for any other node type it's just unknown... */
                        loc = -1;
@@ -2473,80 +2364,6 @@ expression_tree_walker(Node *node,
                                        return true;
                                if (walker(tf->coldefexprs, context))
                                        return true;
-                               if (walker(tf->colvalexprs, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonValueExpr:
-                       {
-                               JsonValueExpr *jve = (JsonValueExpr *) node;
-
-                               if (walker(jve->raw_expr, context))
-                                       return true;
-                               if (walker(jve->formatted_expr, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonConstructorExpr:
-                       {
-                               JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
-
-                               if (walker(ctor->args, context))
-                                       return true;
-                               if (walker(ctor->func, context))
-                                       return true;
-                               if (walker(ctor->coercion, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonIsPredicate:
-                       return walker(((JsonIsPredicate *) node)->expr, context);
-               case T_JsonExpr:
-                       {
-                               JsonExpr   *jexpr = (JsonExpr *) node;
-
-                               if (walker(jexpr->formatted_expr, context))
-                                       return true;
-                               if (walker(jexpr->result_coercion, context))
-                                       return true;
-                               if (walker(jexpr->passing_values, context))
-                                       return true;
-                               /* we assume walker doesn't care about passing_names */
-                               if (jexpr->on_empty &&
-                                       walker(jexpr->on_empty->default_expr, context))
-                                       return true;
-                               if (walker(jexpr->on_error->default_expr, context))
-                                       return true;
-                               if (walker(jexpr->coercions, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonCoercion:
-                       return walker(((JsonCoercion *) node)->expr, context);
-               case T_JsonItemCoercions:
-                       {
-                               JsonItemCoercions *coercions = (JsonItemCoercions *) node;
-
-                               if (walker(coercions->null, context))
-                                       return true;
-                               if (walker(coercions->string, context))
-                                       return true;
-                               if (walker(coercions->numeric, context))
-                                       return true;
-                               if (walker(coercions->boolean, context))
-                                       return true;
-                               if (walker(coercions->date, context))
-                                       return true;
-                               if (walker(coercions->time, context))
-                                       return true;
-                               if (walker(coercions->timetz, context))
-                                       return true;
-                               if (walker(coercions->timestamp, context))
-                                       return true;
-                               if (walker(coercions->timestamptz, context))
-                                       return true;
-                               if (walker(coercions->composite, context))
-                                       return true;
                        }
                        break;
                default:
@@ -2876,7 +2693,6 @@ expression_tree_mutator(Node *node,
                case T_RangeTblRef:
                case T_SortGroupClause:
                case T_CTESearchClause:
-               case T_JsonFormat:
                        return (Node *) copyObject(node);
                case T_WithCheckOption:
                        {
@@ -3517,102 +3333,6 @@ expression_tree_mutator(Node *node,
                                MUTATE(newnode->rowexpr, tf->rowexpr, Node *);
                                MUTATE(newnode->colexprs, tf->colexprs, List *);
                                MUTATE(newnode->coldefexprs, tf->coldefexprs, List *);
-                               MUTATE(newnode->colvalexprs, tf->colvalexprs, List *);
-                               return (Node *) newnode;
-                       }
-                       break;
-               case T_JsonReturning:
-                       {
-                               JsonReturning *jr = (JsonReturning *) node;
-                               JsonReturning *newnode;
-
-                               FLATCOPY(newnode, jr, JsonReturning);
-                               MUTATE(newnode->format, jr->format, JsonFormat *);
-
-                               return (Node *) newnode;
-                       }
-               case T_JsonValueExpr:
-                       {
-                               JsonValueExpr *jve = (JsonValueExpr *) node;
-                               JsonValueExpr *newnode;
-
-                               FLATCOPY(newnode, jve, JsonValueExpr);
-                               MUTATE(newnode->raw_expr, jve->raw_expr, Expr *);
-                               MUTATE(newnode->formatted_expr, jve->formatted_expr, Expr *);
-                               MUTATE(newnode->format, jve->format, JsonFormat *);
-
-                               return (Node *) newnode;
-                       }
-               case T_JsonConstructorExpr:
-                       {
-                               JsonConstructorExpr *jve = (JsonConstructorExpr *) node;
-                               JsonConstructorExpr *newnode;
-
-                               FLATCOPY(newnode, jve, JsonConstructorExpr);
-                               MUTATE(newnode->args, jve->args, List *);
-                               MUTATE(newnode->func, jve->func, Expr *);
-                               MUTATE(newnode->coercion, jve->coercion, Expr *);
-                               MUTATE(newnode->returning, jve->returning, JsonReturning *);
-
-                               return (Node *) newnode;
-                       }
-                       break;
-               case T_JsonIsPredicate:
-                       {
-                               JsonIsPredicate *pred = (JsonIsPredicate *) node;
-                               JsonIsPredicate *newnode;
-
-                               FLATCOPY(newnode, pred, JsonIsPredicate);
-                               MUTATE(newnode->expr, pred->expr, Node *);
-
-                               return (Node *) newnode;
-                       }
-                       break;
-               case T_JsonExpr:
-                       {
-                               JsonExpr   *jexpr = (JsonExpr *) node;
-                               JsonExpr   *newnode;
-
-                               FLATCOPY(newnode, jexpr, JsonExpr);
-                               MUTATE(newnode->path_spec, jexpr->path_spec, Node *);
-                               MUTATE(newnode->formatted_expr, jexpr->formatted_expr, Node *);
-                               MUTATE(newnode->result_coercion, jexpr->result_coercion, JsonCoercion *);
-                               MUTATE(newnode->passing_values, jexpr->passing_values, List *);
-                               /* assume mutator does not care about passing_names */
-                               if (newnode->on_empty)
-                                       MUTATE(newnode->on_empty->default_expr,
-                                                  jexpr->on_empty->default_expr, Node *);
-                               MUTATE(newnode->on_error->default_expr,
-                                          jexpr->on_error->default_expr, Node *);
-                               return (Node *) newnode;
-                       }
-                       break;
-               case T_JsonCoercion:
-                       {
-                               JsonCoercion *coercion = (JsonCoercion *) node;
-                               JsonCoercion *newnode;
-
-                               FLATCOPY(newnode, coercion, JsonCoercion);
-                               MUTATE(newnode->expr, coercion->expr, Node *);
-                               return (Node *) newnode;
-                       }
-                       break;
-               case T_JsonItemCoercions:
-                       {
-                               JsonItemCoercions *coercions = (JsonItemCoercions *) node;
-                               JsonItemCoercions *newnode;
-
-                               FLATCOPY(newnode, coercions, JsonItemCoercions);
-                               MUTATE(newnode->null, coercions->null, JsonCoercion *);
-                               MUTATE(newnode->string, coercions->string, JsonCoercion *);
-                               MUTATE(newnode->numeric, coercions->numeric, JsonCoercion *);
-                               MUTATE(newnode->boolean, coercions->boolean, JsonCoercion *);
-                               MUTATE(newnode->date, coercions->date, JsonCoercion *);
-                               MUTATE(newnode->time, coercions->time, JsonCoercion *);
-                               MUTATE(newnode->timetz, coercions->timetz, JsonCoercion *);
-                               MUTATE(newnode->timestamp, coercions->timestamp, JsonCoercion *);
-                               MUTATE(newnode->timestamptz, coercions->timestamptz, JsonCoercion *);
-                               MUTATE(newnode->composite, coercions->composite, JsonCoercion *);
                                return (Node *) newnode;
                        }
                        break;
@@ -3888,7 +3608,6 @@ raw_expression_tree_walker(Node *node,
                case T_ParamRef:
                case T_A_Const:
                case T_A_Star:
-               case T_JsonFormat:
                        /* primitive node types with no subnodes */
                        break;
                case T_Alias:
@@ -4351,211 +4070,6 @@ raw_expression_tree_walker(Node *node,
                case T_CommonTableExpr:
                        /* search_clause and cycle_clause are not interesting here */
                        return walker(((CommonTableExpr *) node)->ctequery, context);
-               case T_JsonReturning:
-                       return walker(((JsonReturning *) node)->format, context);
-               case T_JsonValueExpr:
-                       {
-                               JsonValueExpr *jve = (JsonValueExpr *) node;
-
-                               if (walker(jve->raw_expr, context))
-                                       return true;
-                               if (walker(jve->formatted_expr, context))
-                                       return true;
-                               if (walker(jve->format, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonParseExpr:
-                       {
-                               JsonParseExpr *jpe = (JsonParseExpr *) node;
-
-                               if (walker(jpe->expr, context))
-                                       return true;
-                               if (walker(jpe->output, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonScalarExpr:
-                       {
-                               JsonScalarExpr *jse = (JsonScalarExpr *) node;
-
-                               if (walker(jse->expr, context))
-                                       return true;
-                               if (walker(jse->output, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonSerializeExpr:
-                       {
-                               JsonSerializeExpr *jse = (JsonSerializeExpr *) node;
-
-                               if (walker(jse->expr, context))
-                                       return true;
-                               if (walker(jse->output, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonConstructorExpr:
-                       {
-                               JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
-
-                               if (walker(ctor->args, context))
-                                       return true;
-                               if (walker(ctor->func, context))
-                                       return true;
-                               if (walker(ctor->coercion, context))
-                                       return true;
-                               if (walker(ctor->returning, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonOutput:
-                       {
-                               JsonOutput *out = (JsonOutput *) node;
-
-                               if (walker(out->typeName, context))
-                                       return true;
-                               if (walker(out->returning, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonKeyValue:
-                       {
-                               JsonKeyValue *jkv = (JsonKeyValue *) node;
-
-                               if (walker(jkv->key, context))
-                                       return true;
-                               if (walker(jkv->value, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonObjectConstructor:
-                       {
-                               JsonObjectConstructor *joc = (JsonObjectConstructor *) node;
-
-                               if (walker(joc->output, context))
-                                       return true;
-                               if (walker(joc->exprs, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonArrayConstructor:
-                       {
-                               JsonArrayConstructor *jac = (JsonArrayConstructor *) node;
-
-                               if (walker(jac->output, context))
-                                       return true;
-                               if (walker(jac->exprs, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonAggConstructor:
-                       {
-                               JsonAggConstructor *ctor = (JsonAggConstructor *) node;
-
-                               if (walker(ctor->output, context))
-                                       return true;
-                               if (walker(ctor->agg_order, context))
-                                       return true;
-                               if (walker(ctor->agg_filter, context))
-                                       return true;
-                               if (walker(ctor->over, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonObjectAgg:
-                       {
-                               JsonObjectAgg *joa = (JsonObjectAgg *) node;
-
-                               if (walker(joa->constructor, context))
-                                       return true;
-                               if (walker(joa->arg, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonArrayAgg:
-                       {
-                               JsonArrayAgg *jaa = (JsonArrayAgg *) node;
-
-                               if (walker(jaa->constructor, context))
-                                       return true;
-                               if (walker(jaa->arg, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonArrayQueryConstructor:
-                       {
-                               JsonArrayQueryConstructor *jaqc = (JsonArrayQueryConstructor *) node;
-
-                               if (walker(jaqc->output, context))
-                                       return true;
-                               if (walker(jaqc->query, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonIsPredicate:
-                       return walker(((JsonIsPredicate *) node)->expr, context);
-               case T_JsonArgument:
-                       return walker(((JsonArgument *) node)->val, context);
-               case T_JsonCommon:
-                       {
-                               JsonCommon *jc = (JsonCommon *) node;
-
-                               if (walker(jc->expr, context))
-                                       return true;
-                               if (walker(jc->pathspec, context))
-                                       return true;
-                               if (walker(jc->passing, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonBehavior:
-                       {
-                               JsonBehavior *jb = (JsonBehavior *) node;
-
-                               if (jb->btype == JSON_BEHAVIOR_DEFAULT &&
-                                       walker(jb->default_expr, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonFuncExpr:
-                       {
-                               JsonFuncExpr *jfe = (JsonFuncExpr *) node;
-
-                               if (walker(jfe->common, context))
-                                       return true;
-                               if (jfe->output && walker(jfe->output, context))
-                                       return true;
-                               if (walker(jfe->on_empty, context))
-                                       return true;
-                               if (walker(jfe->on_error, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonTable:
-                       {
-                               JsonTable  *jt = (JsonTable *) node;
-
-                               if (walker(jt->common, context))
-                                       return true;
-                               if (walker(jt->columns, context))
-                                       return true;
-                       }
-                       break;
-               case T_JsonTableColumn:
-                       {
-                               JsonTableColumn *jtc = (JsonTableColumn *) node;
-
-                               if (walker(jtc->typeName, context))
-                                       return true;
-                               if (walker(jtc->on_empty, context))
-                                       return true;
-                               if (walker(jtc->on_error, context))
-                                       return true;
-                               if (jtc->coltype == JTC_NESTED && walker(jtc->columns, context))
-                                       return true;
-                       }
-                       break;
                default:
                        elog(ERROR, "unrecognized node type: %d",
                                 (int) nodeTag(node));
index 75acea149c74677015d789d9aca656e246cbe2c6..f486d42441b960f7f48928b772ccb381c7034f9f 100644 (file)
@@ -4923,8 +4923,7 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context)
                         IsA(node, SQLValueFunction) ||
                         IsA(node, XmlExpr) ||
                         IsA(node, CoerceToDomain) ||
-                        IsA(node, NextValueExpr) ||
-                        IsA(node, JsonExpr))
+                        IsA(node, NextValueExpr))
        {
                /* Treat all these as having cost 1 */
                context->total.per_tuple += cpu_operator_cost;
index 533df86ff77291ede9d2f77ee4f6f29612cde177..5c54171fee01b7141680c81b4b0020b58ad0a221 100644 (file)
@@ -28,7 +28,6 @@
 #include "catalog/pg_type.h"
 #include "executor/executor.h"
 #include "executor/functions.h"
-#include "executor/execExpr.h"
 #include "funcapi.h"
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
@@ -51,9 +50,6 @@
 #include "utils/builtins.h"
 #include "utils/datum.h"
 #include "utils/fmgroids.h"
-#include "utils/json.h"
-#include "utils/jsonb.h"
-#include "utils/jsonpath.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 #include "utils/syscache.h"
@@ -386,45 +382,6 @@ contain_mutable_functions_walker(Node *node, void *context)
                                                                context))
                return true;
 
-       if (IsA(node, JsonConstructorExpr))
-       {
-               const JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
-               ListCell   *lc;
-               bool            is_jsonb =
-               ctor->returning->format->format_type == JS_FORMAT_JSONB;
-
-               /* Check argument_type => json[b] conversions */
-               foreach(lc, ctor->args)
-               {
-                       Oid                     typid = exprType(lfirst(lc));
-
-                       if (is_jsonb ?
-                               !to_jsonb_is_immutable(typid) :
-                               !to_json_is_immutable(typid))
-                               return true;
-               }
-
-               /* Check all subnodes */
-       }
-
-       if (IsA(node, JsonExpr))
-       {
-               JsonExpr   *jexpr = castNode(JsonExpr, node);
-               Const      *cnst;
-
-               if (!IsA(jexpr->path_spec, Const))
-                       return true;
-
-               cnst = castNode(Const, jexpr->path_spec);
-
-               Assert(cnst->consttype == JSONPATHOID);
-               if (cnst->constisnull)
-                       return false;
-
-               return jspIsMutable(DatumGetJsonPathP(cnst->constvalue),
-                                                       jexpr->passing_names, jexpr->passing_values);
-       }
-
        if (IsA(node, SQLValueFunction))
        {
                /* all variants of SQLValueFunction are stable */
@@ -896,18 +853,6 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
                                                                 context, 0);
        }
 
-       /* JsonExpr is parallel-unsafe if subtransactions can be used. */
-       else if (IsA(node, JsonExpr))
-       {
-               JsonExpr   *jsexpr = (JsonExpr *) node;
-
-               if (ExecEvalJsonNeedsSubTransaction(jsexpr, NULL))
-               {
-                       context->max_hazard = PROPARALLEL_UNSAFE;
-                       return true;
-               }
-       }
-
        /* Recurse to check arguments */
        return expression_tree_walker(node,
                                                                  max_parallel_hazard_walker,
@@ -3567,29 +3512,6 @@ eval_const_expressions_mutator(Node *node,
                                        return ece_evaluate_expr((Node *) newcre);
                                return (Node *) newcre;
                        }
-               case T_JsonValueExpr:
-                       {
-                               JsonValueExpr *jve = (JsonValueExpr *) node;
-                               Node       *raw = eval_const_expressions_mutator((Node *) jve->raw_expr,
-                                                                                                                                context);
-
-                               if (raw && IsA(raw, Const))
-                               {
-                                       Node       *formatted;
-                                       Node       *save_case_val = context->case_val;
-
-                                       context->case_val = raw;
-
-                                       formatted = eval_const_expressions_mutator((Node *) jve->formatted_expr,
-                                                                                                                          context);
-
-                                       context->case_val = save_case_val;
-
-                                       if (formatted && IsA(formatted, Const))
-                                               return formatted;
-                               }
-                               break;
-                       }
                default:
                        break;
        }
index f4c0cc7f101bf00ef4df86ffc3baf184ecf4016a..9f1c4022bbe00176d747150d6f7840ac91b1afc6 100644 (file)
@@ -23,7 +23,6 @@ OBJS = \
        parse_enr.o \
        parse_expr.o \
        parse_func.o \
-       parse_jsontable.o \
        parse_merge.o \
        parse_node.o \
        parse_oper.o \
index b5ab9d9c9a3451c4fd83ff70829b73fdd5b8b2b2..0492ff9a666c33c177261860e92ffe50f05e2e2b 100644 (file)
@@ -281,13 +281,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
        MergeWhenClause *mergewhen;
        struct KeyActions *keyactions;
        struct KeyAction *keyaction;
-       JsonBehavior *jsbehavior;
-       struct
-       {
-               JsonBehavior *on_empty;
-               JsonBehavior *on_error;
-       }                       on_behavior;
-       JsonQuotes      js_quotes;
 }
 
 %type <node>   stmt toplevel_stmt schema_stmt routine_body_stmt
@@ -576,7 +569,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <list>   copy_options
 
 %type <typnam> Typename SimpleTypename ConstTypename
-                               GenericType Numeric opt_float JsonType
+                               GenericType Numeric opt_float
                                Character ConstCharacter
                                CharacterWithLength CharacterWithoutLength
                                ConstDatetime ConstInterval
@@ -656,101 +649,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <defelt>         hash_partbound_elem
 
 
-%type <node>           json_format_clause_opt
-                                       json_representation
-                                       json_value_expr
-                                       json_func_expr
-                                       json_value_func_expr
-                                       json_query_expr
-                                       json_exists_predicate
-                                       json_parse_expr
-                                       json_scalar_expr
-                                       json_serialize_expr
-                                       json_api_common_syntax
-                                       json_context_item
-                                       json_argument
-                                       json_output_clause_opt
-                                       json_returning_clause_opt
-                                       json_value_constructor
-                                       json_object_constructor
-                                       json_object_constructor_args
-                                       json_object_constructor_args_opt
-                                       json_object_args
-                                       json_object_func_args
-                                       json_array_constructor
-                                       json_name_and_value
-                                       json_aggregate_func
-                                       json_object_aggregate_constructor
-                                       json_array_aggregate_constructor
-                                       json_path_specification
-                                       json_table
-                                       json_table_column_definition
-                                       json_table_ordinality_column_definition
-                                       json_table_regular_column_definition
-                                       json_table_formatted_column_definition
-                                       json_table_exists_column_definition
-                                       json_table_nested_columns
-                                       json_table_plan_clause_opt
-                                       json_table_specific_plan
-                                       json_table_plan
-                                       json_table_plan_simple
-                                       json_table_plan_parent_child
-                                       json_table_plan_outer
-                                       json_table_plan_inner
-                                       json_table_plan_sibling
-                                       json_table_plan_union
-                                       json_table_plan_cross
-                                       json_table_plan_primary
-                                       json_table_default_plan
-
-%type <list>           json_name_and_value_list
-                                       json_value_expr_list
-                                       json_array_aggregate_order_by_clause_opt
-                                       json_arguments
-                                       json_passing_clause_opt
-                                       json_table_columns_clause
-                                       json_table_column_definition_list
-
-%type <str>                    json_table_path_name
-                                       json_as_path_name_clause_opt
-                                       json_table_column_path_specification_clause_opt
-
-%type <ival>           json_encoding
-                                       json_encoding_clause_opt
-                                       json_table_default_plan_choices
-                                       json_table_default_plan_inner_outer
-                                       json_table_default_plan_union_cross
-                                       json_wrapper_clause_opt
-                                       json_wrapper_behavior
-                                       json_conditional_or_unconditional_opt
-                                       json_predicate_type_constraint_opt
-
-%type <jsbehavior>     json_behavior_error
-                                       json_behavior_null
-                                       json_behavior_true
-                                       json_behavior_false
-                                       json_behavior_unknown
-                                       json_behavior_empty
-                                       json_behavior_empty_array
-                                       json_behavior_empty_object
-                                       json_behavior_default
-                                       json_value_behavior
-                                       json_query_behavior
-                                       json_exists_error_behavior
-                                       json_exists_error_clause_opt
-                                       json_table_error_behavior
-                                       json_table_error_clause_opt
-
-%type <on_behavior> json_value_on_behavior_clause_opt
-                                       json_query_on_behavior_clause_opt
-
-%type <js_quotes>      json_quotes_behavior
-                                       json_quotes_clause_opt
-
-%type <boolean>                json_key_uniqueness_constraint_opt
-                                       json_object_constructor_null_clause_opt
-                                       json_array_constructor_null_clause_opt
-
 /*
  * Non-keyword token types.  These are hard-wired into the "flex" lexer.
  * They must be listed first so that their numeric codes do not depend on
@@ -776,7 +674,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
  */
 
 /* ordinary key words in alphabetical order */
-%token <keyword> ABORT_P ABSENT ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
+%token <keyword> ABORT_P ABSOLUTE_P ACCESS ACTION ADD_P ADMIN AFTER
        AGGREGATE ALL ALSO ALTER ALWAYS ANALYSE ANALYZE AND ANY ARRAY AS ASC
        ASENSITIVE ASSERTION ASSIGNMENT ASYMMETRIC ATOMIC AT ATTACH ATTRIBUTE AUTHORIZATION
 
@@ -786,7 +684,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
        CACHE CALL CALLED CASCADE CASCADED CASE CAST CATALOG_P CHAIN CHAR_P
        CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE
        CLUSTER COALESCE COLLATE COLLATION COLUMN COLUMNS COMMENT COMMENTS COMMIT
-       COMMITTED COMPRESSION CONCURRENTLY CONDITIONAL CONFIGURATION CONFLICT
+       COMMITTED COMPRESSION CONCURRENTLY CONFIGURATION CONFLICT
        CONNECTION CONSTRAINT CONSTRAINTS CONTENT_P CONTINUE_P CONVERSION_P COPY
        COST CREATE CROSS CSV CUBE CURRENT_P
        CURRENT_CATALOG CURRENT_DATE CURRENT_ROLE CURRENT_SCHEMA
@@ -797,12 +695,12 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
        DETACH DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P
        DOUBLE_P DROP
 
-       EACH ELSE EMPTY_P ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ERROR_P ESCAPE
-       EVENT EXCEPT EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXPRESSION
+       EACH ELSE ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ESCAPE EVENT EXCEPT
+       EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXPRESSION
        EXTENSION EXTERNAL EXTRACT
 
        FALSE_P FAMILY FETCH FILTER FINALIZE FIRST_P FLOAT_P FOLLOWING FOR
-       FORCE FOREIGN FORMAT FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS
+       FORCE FOREIGN FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS
 
        GENERATED GLOBAL GRANT GRANTED GREATEST GROUP_P GROUPING GROUPS
 
@@ -813,10 +711,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
        INNER_P INOUT INPUT_P INSENSITIVE INSERT INSTEAD INT_P INTEGER
        INTERSECT INTERVAL INTO INVOKER IS ISNULL ISOLATION
 
-       JOIN JSON JSON_ARRAY JSON_ARRAYAGG JSON_EXISTS JSON_OBJECT JSON_OBJECTAGG
-       JSON_QUERY JSON_SCALAR JSON_SERIALIZE JSON_TABLE JSON_VALUE
+       JOIN
 
-       KEY KEYS KEEP
+       KEY
 
        LABEL LANGUAGE LARGE_P LAST_P LATERAL_P
        LEADING LEAKPROOF LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL
@@ -825,31 +722,31 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
        MAPPING MATCH MATCHED MATERIALIZED MAXVALUE MERGE METHOD
        MINUTE_P MINVALUE MODE MONTH_P MOVE
 
-       NAME_P NAMES NATIONAL NATURAL NCHAR NESTED NEW NEXT NFC NFD NFKC NFKD NO
-       NONE NORMALIZE NORMALIZED
+       NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NFC NFD NFKC NFKD NO NONE
+       NORMALIZE NORMALIZED
        NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF
        NULLS_P NUMERIC
 
-       OBJECT_P OF OFF OFFSET OIDS OLD OMIT ON ONLY OPERATOR OPTION OPTIONS OR
+       OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OPTIONS OR
        ORDER ORDINALITY OTHERS OUT_P OUTER_P
        OVER OVERLAPS OVERLAY OVERRIDING OWNED OWNER
 
-       PARALLEL PARAMETER PARSER PARTIAL PARTITION PASSING PASSWORD PATH
-       PLACING PLAN PLANS POLICY
+       PARALLEL PARAMETER PARSER PARTIAL PARTITION PASSING PASSWORD
+       PLACING PLANS POLICY
        POSITION PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY
        PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROCEDURES PROGRAM PUBLICATION
 
-       QUOTE QUOTES
+       QUOTE
 
        RANGE READ REAL REASSIGN RECHECK RECURSIVE REF REFERENCES REFERENCING
        REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA
        RESET RESTART RESTRICT RETURN RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP
        ROUTINE ROUTINES ROW ROWS RULE
 
-       SAVEPOINT SCALAR SCHEMA SCHEMAS SCROLL SEARCH SECOND_P SECURITY SELECT
-       SEQUENCE SEQUENCES SERIALIZABLE SERVER SESSION SESSION_USER SET SETS SETOF
-       SHARE SHOW SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME SQL_P STABLE STANDALONE_P
-       START STATEMENT STATISTICS STDIN STDOUT STORAGE STORED STRICT_P STRING STRIP_P
+       SAVEPOINT SCHEMA SCHEMAS SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES
+       SERIALIZABLE SERVER SESSION SESSION_USER SET SETS SETOF SHARE SHOW
+       SIMILAR SIMPLE SKIP SMALLINT SNAPSHOT SOME SQL_P STABLE STANDALONE_P
+       START STATEMENT STATISTICS STDIN STDOUT STORAGE STORED STRICT_P STRIP_P
        SUBSCRIPTION SUBSTRING SUPPORT SYMMETRIC SYSID SYSTEM_P
 
        TABLE TABLES TABLESAMPLE TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THEN
@@ -857,7 +754,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
        TREAT TRIGGER TRIM TRUE_P
        TRUNCATE TRUSTED TYPE_P TYPES_P
 
-       UESCAPE UNBOUNDED UNCONDITIONAL UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN
+       UESCAPE UNBOUNDED UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN
        UNLISTEN UNLOGGED UNTIL UPDATE USER USING
 
        VACUUM VALID VALIDATE VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING
@@ -882,7 +779,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
  * as NOT, at least with respect to their left-hand subexpression.
  * NULLS_LA and WITH_LA are needed to make the grammar LALR(1).
  */
-%token         NOT_LA NULLS_LA WITH_LA WITH_LA_UNIQUE WITHOUT_LA
+%token         NOT_LA NULLS_LA WITH_LA
 
 /*
  * The grammar likewise thinks these tokens are keywords, but they are never
@@ -900,7 +797,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 
 /* Precedence: lowest to highest */
 %nonassoc      SET                             /* see relation_expr_opt_alias */
-%right         FORMAT
 %left          UNION EXCEPT
 %left          INTERSECT
 %left          OR
@@ -936,15 +832,11 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
  * Using the same precedence as IDENT seems right for the reasons given above.
  */
 %nonassoc      UNBOUNDED               /* ideally would have same precedence as IDENT */
-%nonassoc      ERROR_P EMPTY_P DEFAULT ABSENT /* JSON error/empty behavior */
-%nonassoc      FALSE_P KEEP OMIT PASSING TRUE_P UNKNOWN UNIQUE JSON COLUMNS
 %nonassoc      IDENT PARTITION RANGE ROWS GROUPS PRECEDING FOLLOWING CUBE ROLLUP
 %left          Op OPERATOR             /* multi-character ops and user-defined operators */
 %left          '+' '-'
 %left          '*' '/' '%'
 %left          '^'
-%left          KEYS                                            /* UNIQUE [ KEYS ] */
-%left          OBJECT_P SCALAR VALUE_P         /* JSON [ OBJECT | SCALAR | VALUE ] */
 /* Unary Operators */
 %left          AT                              /* sets precedence for AT TIME ZONE */
 %left          COLLATE
@@ -962,13 +854,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
  */
 %left          JOIN CROSS LEFT FULL RIGHT INNER_P NATURAL
 
-%nonassoc      json_table_column
-%nonassoc      NESTED
-%left          PATH
-
-%nonassoc      empty_json_unique
-%left          WITHOUT WITH_LA_UNIQUE
-
 %%
 
 /*
@@ -13407,21 +13292,6 @@ table_ref:     relation_expr opt_alias_clause
                                        $2->alias = $4;
                                        $$ = (Node *) $2;
                                }
-                       | json_table opt_alias_clause
-                               {
-                                       JsonTable  *jt = castNode(JsonTable, $1);
-
-                                       jt->alias = $2;
-                                       $$ = (Node *) jt;
-                               }
-                       | LATERAL_P json_table opt_alias_clause
-                               {
-                                       JsonTable  *jt = castNode(JsonTable, $2);
-
-                                       jt->alias = $3;
-                                       jt->lateral = true;
-                                       $$ = (Node *) jt;
-                               }
                ;
 
 
@@ -13989,8 +13859,6 @@ xmltable_column_option_el:
                                { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(true), @1); }
                        | NULL_P
                                { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(false), @1); }
-                       | PATH b_expr
-                               { $$ = makeDefElem("path", $2, @1); }
                ;
 
 xml_namespace_list:
@@ -14091,7 +13959,6 @@ SimpleTypename:
                                        $$->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1),
                                                                                         makeIntConst($3, @3));
                                }
-                       | JsonType                                                              { $$ = $1; }
                ;
 
 /* We have a separate ConstTypename to allow defaulting fixed-length
@@ -14110,7 +13977,6 @@ ConstTypename:
                        | ConstBit                                                              { $$ = $1; }
                        | ConstCharacter                                                { $$ = $1; }
                        | ConstDatetime                                                 { $$ = $1; }
-                       | JsonType                                                              { $$ = $1; }
                ;
 
 /*
@@ -14404,7 +14270,7 @@ ConstInterval:
 
 opt_timezone:
                        WITH_LA TIME ZONE                                               { $$ = true; }
-                       | WITHOUT_LA TIME ZONE                                  { $$ = false; }
+                       | WITHOUT TIME ZONE                                             { $$ = false; }
                        | /*EMPTY*/                                                             { $$ = false; }
                ;
 
@@ -14479,13 +14345,6 @@ interval_second:
                                }
                ;
 
-JsonType:
-                       JSON
-                               {
-                                       $$ = SystemTypeName("json");
-                                       $$->location = @1;
-                               }
-               ;
 
 /*****************************************************************************
  *
@@ -14956,47 +14815,6 @@ a_expr:                c_expr                                                                  { $$ = $1; }
                                                                                                                   @2),
                                                                         @2);
                                }
-                       | a_expr
-                               IS json_predicate_type_constraint_opt
-                                       json_key_uniqueness_constraint_opt              %prec IS
-                               {
-                                       JsonFormat *format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
-                                       $$ = makeJsonIsPredicate($1, format, $3, $4, @1);
-                               }
-                       /*
-                        * Required by standard, but it would conflict with expressions
-                        * like: 'str' || format(...)
-                       | a_expr
-                               FORMAT json_representation
-                               IS  json_predicate_type_constraint_opt
-                                       json_key_uniqueness_constraint_opt              %prec FORMAT
-                               {
-                                       $3.location = @2;
-                                       $$ = makeJsonIsPredicate($1, $3, $5, $6, @1);
-                               }
-                       */
-                       | a_expr
-                               IS NOT
-                                       json_predicate_type_constraint_opt
-                                       json_key_uniqueness_constraint_opt              %prec IS
-                               {
-                                       JsonFormat *format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
-
-                                       $$ = makeNotExpr(makeJsonIsPredicate($1, format, $4, $5, @1), @1);
-                               }
-                       /*
-                        * Required by standard, but it would conflict with expressions
-                        * like: 'str' || format(...)
-                       | a_expr
-                               FORMAT json_representation
-                               IS NOT
-                                       json_predicate_type_constraint_opt
-                                       json_key_uniqueness_constraint_opt              %prec FORMAT
-                               {
-                                       $3.location = @2;
-                                       $$ = makeNotExpr(makeJsonIsPredicate($1, $3, $6, $7, @1), @1);
-                               }
-                       */
                        | DEFAULT
                                {
                                        /*
@@ -15080,25 +14898,6 @@ b_expr:                c_expr
                                }
                ;
 
-json_predicate_type_constraint_opt:
-                       JSON                                                                    { $$ = JS_TYPE_ANY; }
-                       | JSON VALUE_P                                                  { $$ = JS_TYPE_ANY; }
-                       | JSON ARRAY                                                    { $$ = JS_TYPE_ARRAY; }
-                       | JSON OBJECT_P                                                 { $$ = JS_TYPE_OBJECT; }
-                       | JSON SCALAR                                                   { $$ = JS_TYPE_SCALAR; }
-               ;
-
-json_key_uniqueness_constraint_opt:
-                       WITH_LA_UNIQUE unique_keys                              { $$ = true; }
-                       | WITHOUT unique_keys                                   { $$ = false; }
-                       | /* EMPTY */ %prec empty_json_unique   { $$ = false; }
-               ;
-
-unique_keys:
-                       UNIQUE
-                       | UNIQUE KEYS
-               ;
-
 /*
  * Productions that can be used in both a_expr and b_expr.
  *
@@ -15369,16 +15168,6 @@ func_expr: func_application within_group_clause filter_clause over_clause
                                        n->over = $4;
                                        $$ = (Node *) n;
                                }
-                       | json_aggregate_func filter_clause over_clause
-                               {
-                                       JsonAggConstructor *n = IsA($1, JsonObjectAgg) ?
-                                               ((JsonObjectAgg *) $1)->constructor :
-                                               ((JsonArrayAgg *) $1)->constructor;
-
-                                       n->agg_filter = $2;
-                                       n->over = $3;
-                                       $$ = (Node *) $1;
-                               }
                        | func_expr_common_subexpr
                                { $$ = $1; }
                ;
@@ -15392,7 +15181,6 @@ func_expr: func_application within_group_clause filter_clause over_clause
 func_expr_windowless:
                        func_application                                                { $$ = $1; }
                        | func_expr_common_subexpr                              { $$ = $1; }
-                       | json_aggregate_func                                   { $$ = $1; }
                ;
 
 /*
@@ -15685,8 +15473,6 @@ func_expr_common_subexpr:
                                        n->location = @1;
                                        $$ = (Node *) n;
                                }
-                       | json_func_expr
-                               { $$ = $1; }
                ;
 
 /*
@@ -16406,813 +16192,6 @@ opt_asymmetric: ASYMMETRIC
                        | /*EMPTY*/
                ;
 
-/* SQL/JSON support */
-json_func_expr:
-                       json_value_constructor
-                       | json_value_func_expr
-                       | json_query_expr
-                       | json_exists_predicate
-                       | json_parse_expr
-                       | json_scalar_expr
-                       | json_serialize_expr
-               ;
-
-json_parse_expr:
-                       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_returning_clause_opt ')'
-                               {
-                                       JsonScalarExpr *n = makeNode(JsonScalarExpr);
-
-                                       n->expr = (Expr *) $3;
-                                       n->output = (JsonOutput *) $4;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_serialize_expr:
-                       JSON_SERIALIZE '(' json_value_expr json_output_clause_opt ')'
-                               {
-                                       JsonSerializeExpr *n = makeNode(JsonSerializeExpr);
-
-                                       n->expr = (JsonValueExpr *) $3;
-                                       n->output = (JsonOutput *) $4;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_value_func_expr:
-                       JSON_VALUE '('
-                               json_api_common_syntax
-                               json_returning_clause_opt
-                               json_value_on_behavior_clause_opt
-                       ')'
-                               {
-                                       JsonFuncExpr *n = makeNode(JsonFuncExpr);
-
-                                       n->op = JSON_VALUE_OP;
-                                       n->common = (JsonCommon *) $3;
-                                       n->output = (JsonOutput *) $4;
-                                       n->on_empty = $5.on_empty;
-                                       n->on_error = $5.on_error;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_api_common_syntax:
-                       json_context_item ',' json_path_specification
-                       json_as_path_name_clause_opt
-                       json_passing_clause_opt
-                               {
-                                       JsonCommon *n = makeNode(JsonCommon);
-
-                                       n->expr = (JsonValueExpr *) $1;
-                                       n->pathspec = $3;
-                                       n->pathname = $4;
-                                       n->passing = $5;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_context_item:
-                       json_value_expr                                                 { $$ = $1; }
-               ;
-
-json_path_specification:
-                       a_expr                                                                  { $$ = $1; }
-               ;
-
-json_as_path_name_clause_opt:
-                        AS json_table_path_name                                { $$ = $2; }
-                        | /* EMPTY */                                                  { $$ = NULL; }
-               ;
-
-json_table_path_name:
-                       name                                                                    { $$ = $1; }
-               ;
-
-json_passing_clause_opt:
-                       PASSING json_arguments                                  { $$ = $2; }
-                       | /* EMPTY */                                                   { $$ = NIL; }
-               ;
-
-json_arguments:
-                       json_argument                                                   { $$ = list_make1($1); }
-                       | json_arguments ',' json_argument              { $$ = lappend($1, $3); }
-               ;
-
-json_argument:
-                       json_value_expr AS ColLabel
-                       {
-                               JsonArgument *n = makeNode(JsonArgument);
-
-                               n->val = (JsonValueExpr *) $1;
-                               n->name = $3;
-                               $$ = (Node *) n;
-                       }
-               ;
-
-json_value_expr:
-                       a_expr json_format_clause_opt
-                       {
-                               $$ = (Node *) makeJsonValueExpr((Expr *) $1, castNode(JsonFormat, $2));
-                       }
-               ;
-
-json_format_clause_opt:
-                       FORMAT json_representation
-                               {
-                                       $$ = $2;
-                                       castNode(JsonFormat, $$)->location = @1;
-                               }
-                       | /* EMPTY */
-                               {
-                                       $$ = (Node *) makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
-                               }
-               ;
-
-json_representation:
-                       JSON json_encoding_clause_opt
-                               {
-                                       $$ = (Node *) makeJsonFormat(JS_FORMAT_JSON, $2, @1);
-                               }
-               /*      | other implementation defined JSON representation options (BSON, AVRO etc) */
-               ;
-
-json_encoding_clause_opt:
-                       ENCODING json_encoding                                  { $$ = $2; }
-                       | /* EMPTY */                                                   { $$ = JS_ENC_DEFAULT; }
-               ;
-
-json_encoding:
-                       name                                                                    { $$ = makeJsonEncoding($1); }
-               ;
-
-json_behavior_error:
-                       ERROR_P         { $$ = makeJsonBehavior(JSON_BEHAVIOR_ERROR, NULL); }
-               ;
-
-json_behavior_null:
-                       NULL_P          { $$ = makeJsonBehavior(JSON_BEHAVIOR_NULL, NULL); }
-               ;
-
-json_behavior_true:
-                       TRUE_P          { $$ = makeJsonBehavior(JSON_BEHAVIOR_TRUE, NULL); }
-               ;
-
-json_behavior_false:
-                       FALSE_P         { $$ = makeJsonBehavior(JSON_BEHAVIOR_FALSE, NULL); }
-               ;
-
-json_behavior_unknown:
-                       UNKNOWN         { $$ = makeJsonBehavior(JSON_BEHAVIOR_UNKNOWN, NULL); }
-               ;
-
-json_behavior_empty:
-                       EMPTY_P         { $$ = makeJsonBehavior(JSON_BEHAVIOR_EMPTY_OBJECT, NULL); }
-               ;
-
-json_behavior_empty_array:
-                       EMPTY_P ARRAY   { $$ = makeJsonBehavior(JSON_BEHAVIOR_EMPTY_ARRAY, NULL); }
-                       /* non-standard, for Oracle compatibility only */
-                       | EMPTY_P               { $$ = makeJsonBehavior(JSON_BEHAVIOR_EMPTY_ARRAY, NULL); }
-               ;
-
-json_behavior_empty_object:
-                       EMPTY_P OBJECT_P        { $$ = makeJsonBehavior(JSON_BEHAVIOR_EMPTY_OBJECT, NULL); }
-               ;
-
-json_behavior_default:
-                       DEFAULT a_expr  { $$ = makeJsonBehavior(JSON_BEHAVIOR_DEFAULT, $2); }
-               ;
-
-
-json_value_behavior:
-                       json_behavior_null
-                       | json_behavior_error
-                       | json_behavior_default
-               ;
-
-json_value_on_behavior_clause_opt:
-                       json_value_behavior ON EMPTY_P
-                                                                       { $$.on_empty = $1; $$.on_error = NULL; }
-                       | json_value_behavior ON EMPTY_P json_value_behavior ON ERROR_P
-                                                                       { $$.on_empty = $1; $$.on_error = $4; }
-                       | json_value_behavior ON ERROR_P
-                                                                       { $$.on_empty = NULL; $$.on_error = $1; }
-                       |  /* EMPTY */
-                                                                       { $$.on_empty = NULL; $$.on_error = NULL; }
-               ;
-
-json_query_expr:
-                       JSON_QUERY '('
-                               json_api_common_syntax
-                               json_output_clause_opt
-                               json_wrapper_clause_opt
-                               json_quotes_clause_opt
-                               json_query_on_behavior_clause_opt
-                       ')'
-                               {
-                                       JsonFuncExpr *n = makeNode(JsonFuncExpr);
-
-                                       n->op = JSON_QUERY_OP;
-                                       n->common = (JsonCommon *) $3;
-                                       n->output = (JsonOutput *) $4;
-                                       n->wrapper = $5;
-                                       if (n->wrapper != JSW_NONE && $6 != JS_QUOTES_UNSPEC)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                errmsg("SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used"),
-                                                                parser_errposition(@6)));
-                                       n->omit_quotes = $6 == JS_QUOTES_OMIT;
-                                       n->on_empty = $7.on_empty;
-                                       n->on_error = $7.on_error;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_wrapper_clause_opt:
-                       json_wrapper_behavior WRAPPER                   { $$ = $1; }
-                       | /* EMPTY */                                                   { $$ = 0; }
-               ;
-
-json_wrapper_behavior:
-                       WITHOUT array_opt                                               { $$ = JSW_NONE; }
-                       | WITH json_conditional_or_unconditional_opt array_opt { $$ = $2; }
-               ;
-
-array_opt:
-                       ARRAY                                                                   { }
-                       | /* EMPTY */                                                   { }
-               ;
-
-json_conditional_or_unconditional_opt:
-                       CONDITIONAL                                                             { $$ = JSW_CONDITIONAL; }
-                       | UNCONDITIONAL                                                 { $$ = JSW_UNCONDITIONAL; }
-                       | /* EMPTY */                                                   { $$ = JSW_UNCONDITIONAL; }
-               ;
-
-json_quotes_clause_opt:
-                       json_quotes_behavior QUOTES json_on_scalar_string_opt { $$ = $1; }
-                       | /* EMPTY */                                                   { $$ = JS_QUOTES_UNSPEC; }
-               ;
-
-json_quotes_behavior:
-                       KEEP                                                                    { $$ = JS_QUOTES_KEEP; }
-                       | OMIT                                                                  { $$ = JS_QUOTES_OMIT; }
-               ;
-
-json_on_scalar_string_opt:
-                       ON SCALAR STRING                                                { }
-                       | /* EMPTY */                                                   { }
-               ;
-
-json_query_behavior:
-                       json_behavior_error
-                       | json_behavior_null
-                       | json_behavior_empty_array
-                       | json_behavior_empty_object
-                       | json_behavior_default
-               ;
-
-json_query_on_behavior_clause_opt:
-                       json_query_behavior ON EMPTY_P
-                                                                       { $$.on_empty = $1; $$.on_error = NULL; }
-                       | json_query_behavior ON EMPTY_P json_query_behavior ON ERROR_P
-                                                                       { $$.on_empty = $1; $$.on_error = $4; }
-                       | json_query_behavior ON ERROR_P
-                                                                       { $$.on_empty = NULL; $$.on_error = $1; }
-                       |  /* EMPTY */
-                                                                       { $$.on_empty = NULL; $$.on_error = NULL; }
-               ;
-
-json_table:
-                       JSON_TABLE '('
-                               json_api_common_syntax
-                               json_table_columns_clause
-                               json_table_plan_clause_opt
-                               json_table_error_clause_opt
-                       ')'
-                               {
-                                       JsonTable *n = makeNode(JsonTable);
-
-                                       n->common = (JsonCommon *) $3;
-                                       n->columns = $4;
-                                       n->plan = (JsonTablePlan *) $5;
-                                       n->on_error = $6;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_table_columns_clause:
-                       COLUMNS '('     json_table_column_definition_list ')' { $$ = $3; }
-               ;
-
-json_table_column_definition_list:
-                       json_table_column_definition
-                               { $$ = list_make1($1); }
-                       | json_table_column_definition_list ',' json_table_column_definition
-                               { $$ = lappend($1, $3); }
-               ;
-
-json_table_column_definition:
-                       json_table_ordinality_column_definition         %prec json_table_column
-                       | json_table_regular_column_definition          %prec json_table_column
-                       | json_table_formatted_column_definition        %prec json_table_column
-                       | json_table_exists_column_definition           %prec json_table_column
-                       | json_table_nested_columns
-               ;
-
-json_table_ordinality_column_definition:
-                       ColId FOR ORDINALITY
-                               {
-                                       JsonTableColumn *n = makeNode(JsonTableColumn);
-
-                                       n->coltype = JTC_FOR_ORDINALITY;
-                                       n->name = $1;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_table_regular_column_definition:
-                       ColId Typename
-                       json_table_column_path_specification_clause_opt
-                       json_wrapper_clause_opt
-                       json_quotes_clause_opt
-                       json_value_on_behavior_clause_opt
-                               {
-                                       JsonTableColumn *n = makeNode(JsonTableColumn);
-
-                                       n->coltype = JTC_REGULAR;
-                                       n->name = $1;
-                                       n->typeName = $2;
-                                       n->format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
-                                       n->wrapper = $4; /* JSW_NONE */
-                                       n->omit_quotes = $5; /* false */
-                                       n->pathspec = $3;
-                                       n->on_empty = $6.on_empty;
-                                       n->on_error = $6.on_error;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_table_exists_column_definition:
-                       ColId Typename
-                       EXISTS json_table_column_path_specification_clause_opt
-                       json_exists_error_clause_opt
-                               {
-                                       JsonTableColumn *n = makeNode(JsonTableColumn);
-
-                                       n->coltype = JTC_EXISTS;
-                                       n->name = $1;
-                                       n->typeName = $2;
-                                       n->format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
-                                       n->wrapper = JSW_NONE;
-                                       n->omit_quotes = false;
-                                       n->pathspec = $4;
-                                       n->on_empty = NULL;
-                                       n->on_error = $5;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_table_error_behavior:
-                       json_behavior_error
-                       | json_behavior_empty
-               ;
-
-json_table_error_clause_opt:
-                       json_table_error_behavior ON ERROR_P    { $$ = $1; }
-                       | /* EMPTY */                                                   { $$ = NULL; }
-               ;
-
-json_table_column_path_specification_clause_opt:
-                       PATH Sconst                                                             { $$ = $2; }
-                       | /* EMPTY */ %prec json_table_column   { $$ = NULL; }
-               ;
-
-json_table_formatted_column_definition:
-                       ColId Typename FORMAT json_representation
-                       json_table_column_path_specification_clause_opt
-                       json_wrapper_clause_opt
-                       json_quotes_clause_opt
-                       json_query_on_behavior_clause_opt
-                               {
-                                       JsonTableColumn *n = makeNode(JsonTableColumn);
-
-                                       n->coltype = JTC_FORMATTED;
-                                       n->name = $1;
-                                       n->typeName = $2;
-                                       n->format = castNode(JsonFormat, $4);
-                                       n->pathspec = $5;
-                                       n->wrapper = $6;
-                                       if (n->wrapper != JSW_NONE && $7 != JS_QUOTES_UNSPEC)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                errmsg("SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used"),
-                                                                parser_errposition(@7)));
-                                       n->omit_quotes = $7 == JS_QUOTES_OMIT;
-                                       n->on_empty = $8.on_empty;
-                                       n->on_error = $8.on_error;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_table_nested_columns:
-                       NESTED path_opt Sconst
-                                                       json_as_path_name_clause_opt
-                                                       json_table_columns_clause
-                               {
-                                       JsonTableColumn *n = makeNode(JsonTableColumn);
-
-                                       n->coltype = JTC_NESTED;
-                                       n->pathspec = $3;
-                                       n->pathname = $4;
-                                       n->columns = $5;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-path_opt:
-                       PATH                                                                    { }
-                       | /* EMPTY */                                                   { }
-               ;
-
-json_table_plan_clause_opt:
-                       json_table_specific_plan                                { $$ = $1; }
-                       | json_table_default_plan                               { $$ = $1; }
-                       | /* EMPTY */                                                   { $$ = NULL; }
-               ;
-
-json_table_specific_plan:
-                       PLAN '(' json_table_plan ')'                    { $$ = $3; }
-               ;
-
-json_table_plan:
-                       json_table_plan_simple
-                       | json_table_plan_parent_child
-                       | json_table_plan_sibling
-               ;
-
-json_table_plan_simple:
-                       json_table_path_name
-                               {
-                                       JsonTablePlan *n = makeNode(JsonTablePlan);
-
-                                       n->plan_type = JSTP_SIMPLE;
-                                       n->pathname = $1;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_table_plan_parent_child:
-                       json_table_plan_outer
-                       | json_table_plan_inner
-               ;
-
-json_table_plan_outer:
-                       json_table_plan_simple OUTER_P json_table_plan_primary
-                               { $$ = makeJsonTableJoinedPlan(JSTPJ_OUTER, $1, $3, @1); }
-               ;
-
-json_table_plan_inner:
-                       json_table_plan_simple INNER_P json_table_plan_primary
-                               { $$ = makeJsonTableJoinedPlan(JSTPJ_INNER, $1, $3, @1); }
-               ;
-
-json_table_plan_sibling:
-                       json_table_plan_union
-                       | json_table_plan_cross
-               ;
-
-json_table_plan_union:
-                       json_table_plan_primary UNION json_table_plan_primary
-                               { $$ = makeJsonTableJoinedPlan(JSTPJ_UNION, $1, $3, @1); }
-                       | json_table_plan_union UNION json_table_plan_primary
-                               { $$ = makeJsonTableJoinedPlan(JSTPJ_UNION, $1, $3, @1); }
-               ;
-
-json_table_plan_cross:
-                       json_table_plan_primary CROSS json_table_plan_primary
-                               { $$ = makeJsonTableJoinedPlan(JSTPJ_CROSS, $1, $3, @1); }
-                       | json_table_plan_cross CROSS json_table_plan_primary
-                               { $$ = makeJsonTableJoinedPlan(JSTPJ_CROSS, $1, $3, @1); }
-               ;
-
-json_table_plan_primary:
-                       json_table_plan_simple                                          { $$ = $1; }
-                       | '(' json_table_plan ')'
-                               {
-                                       castNode(JsonTablePlan, $2)->location = @1;
-                                       $$ = $2;
-                               }
-               ;
-
-json_table_default_plan:
-                       PLAN DEFAULT '(' json_table_default_plan_choices ')'
-                       {
-                               JsonTablePlan *n = makeNode(JsonTablePlan);
-
-                               n->plan_type = JSTP_DEFAULT;
-                               n->join_type = $4;
-                               n->location = @1;
-                               $$ = (Node *) n;
-                       }
-               ;
-
-json_table_default_plan_choices:
-                       json_table_default_plan_inner_outer                     { $$ = $1 | JSTPJ_UNION; }
-                       | json_table_default_plan_inner_outer ','
-                         json_table_default_plan_union_cross           { $$ = $1 | $3; }
-                       | json_table_default_plan_union_cross           { $$ = $1 | JSTPJ_OUTER; }
-                       | json_table_default_plan_union_cross ','
-                         json_table_default_plan_inner_outer           { $$ = $1 | $3; }
-               ;
-
-json_table_default_plan_inner_outer:
-                       INNER_P                                                                         { $$ = JSTPJ_INNER; }
-                       | OUTER_P                                                                       { $$ = JSTPJ_OUTER; }
-               ;
-
-json_table_default_plan_union_cross:
-                       UNION                                                                           { $$ = JSTPJ_UNION; }
-                       | CROSS                                                                         { $$ = JSTPJ_CROSS; }
-               ;
-
-json_returning_clause_opt:
-                       RETURNING Typename
-                               {
-                                       JsonOutput *n = makeNode(JsonOutput);
-
-                                       n->typeName = $2;
-                                       n->returning = makeNode(JsonReturning);
-                                       n->returning->format =
-                                               makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, @2);
-                                       $$ = (Node *) n;
-                               }
-                       | /* EMPTY */                                                   { $$ = NULL; }
-                       ;
-
-json_output_clause_opt:
-                       RETURNING Typename json_format_clause_opt
-                               {
-                                       JsonOutput *n = makeNode(JsonOutput);
-
-                                       n->typeName = $2;
-                                       n->returning = makeNode(JsonReturning);
-                                       n->returning->format = (JsonFormat *) $3;
-                                       $$ = (Node *) n;
-                               }
-                       | /* EMPTY */                                                   { $$ = NULL; }
-                       ;
-
-json_exists_predicate:
-                       JSON_EXISTS '('
-                               json_api_common_syntax
-                               json_returning_clause_opt
-                               json_exists_error_clause_opt
-                       ')'
-                               {
-                                       JsonFuncExpr *p = makeNode(JsonFuncExpr);
-
-                                       p->op = JSON_EXISTS_OP;
-                                       p->common = (JsonCommon *) $3;
-                                       p->output = (JsonOutput *) $4;
-                                       p->on_error = $5;
-                                       p->location = @1;
-                                       $$ = (Node *) p;
-                               }
-               ;
-
-json_exists_error_clause_opt:
-                       json_exists_error_behavior ON ERROR_P           { $$ = $1; }
-                       | /* EMPTY */                                                           { $$ = NULL; }
-               ;
-
-json_exists_error_behavior:
-                       json_behavior_error
-                       | json_behavior_true
-                       | json_behavior_false
-                       | json_behavior_unknown
-               ;
-
-json_value_constructor:
-                       json_object_constructor
-                       | json_array_constructor
-               ;
-
-json_object_constructor:
-                       JSON_OBJECT '(' json_object_args ')'
-                               {
-                                       $$ = $3;
-                               }
-               ;
-
-json_object_args:
-                       json_object_constructor_args
-                       | json_object_func_args
-               ;
-
-json_object_func_args:
-                       func_arg_list
-                               {
-                                       List       *func = list_make1(makeString("json_object"));
-
-                                       $$ = (Node *) makeFuncCall(func, $1, COERCE_EXPLICIT_CALL, @1);
-                               }
-               ;
-
-json_object_constructor_args:
-                       json_object_constructor_args_opt json_output_clause_opt
-                               {
-                                       JsonObjectConstructor *n = (JsonObjectConstructor *) $1;
-
-                                       n->output = (JsonOutput *) $2;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_object_constructor_args_opt:
-                       json_name_and_value_list
-                       json_object_constructor_null_clause_opt
-                       json_key_uniqueness_constraint_opt
-                               {
-                                       JsonObjectConstructor *n = makeNode(JsonObjectConstructor);
-
-                                       n->exprs = $1;
-                                       n->absent_on_null = $2;
-                                       n->unique = $3;
-                                       $$ = (Node *) n;
-                               }
-                       | /* EMPTY */
-                               {
-                                       JsonObjectConstructor *n = makeNode(JsonObjectConstructor);
-
-                                       n->exprs = NULL;
-                                       n->absent_on_null = false;
-                                       n->unique = false;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_name_and_value_list:
-                       json_name_and_value
-                               { $$ = list_make1($1); }
-                       | json_name_and_value_list ',' json_name_and_value
-                               { $$ = lappend($1, $3); }
-               ;
-
-json_name_and_value:
-/* TODO This is not supported due to conflicts
-                       KEY c_expr VALUE_P json_value_expr %prec POSTFIXOP
-                               { $$ = makeJsonKeyValue($2, $4); }
-                       |
-*/
-                       c_expr VALUE_P json_value_expr
-                               { $$ = makeJsonKeyValue($1, $3); }
-                       |
-                       a_expr ':' json_value_expr
-                               { $$ = makeJsonKeyValue($1, $3); }
-               ;
-
-json_object_constructor_null_clause_opt:
-                       NULL_P ON NULL_P                                        { $$ = false; }
-                       | ABSENT ON NULL_P                                      { $$ = true; }
-                       | /* EMPTY */                                           { $$ = false; }
-               ;
-
-json_array_constructor:
-                       JSON_ARRAY '('
-                               json_value_expr_list
-                               json_array_constructor_null_clause_opt
-                               json_output_clause_opt
-                       ')'
-                               {
-                                       JsonArrayConstructor *n = makeNode(JsonArrayConstructor);
-
-                                       n->exprs = $3;
-                                       n->absent_on_null = $4;
-                                       n->output = (JsonOutput *) $5;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-                       | JSON_ARRAY '('
-                               select_no_parens
-                               /* json_format_clause_opt */
-                               /* json_array_constructor_null_clause_opt */
-                               json_output_clause_opt
-                       ')'
-                               {
-                                       JsonArrayQueryConstructor *n = makeNode(JsonArrayQueryConstructor);
-
-                                       n->query = $3;
-                                       n->format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
-                                       /* n->format = $4; */
-                                       n->absent_on_null = true /* $5 */;
-                                       n->output = (JsonOutput *) $4;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-                       | JSON_ARRAY '('
-                               json_output_clause_opt
-                       ')'
-                               {
-                                       JsonArrayConstructor *n = makeNode(JsonArrayConstructor);
-
-                                       n->exprs = NIL;
-                                       n->absent_on_null = true;
-                                       n->output = (JsonOutput *) $3;
-                                       n->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_value_expr_list:
-                       json_value_expr                                                         { $$ = list_make1($1); }
-                       | json_value_expr_list ',' json_value_expr      { $$ = lappend($1, $3);}
-               ;
-
-json_array_constructor_null_clause_opt:
-                       NULL_P ON NULL_P                                                { $$ = false; }
-                       | ABSENT ON NULL_P                                              { $$ = true; }
-                       | /* EMPTY */                                                   { $$ = true; }
-               ;
-
-json_aggregate_func:
-                       json_object_aggregate_constructor
-                       | json_array_aggregate_constructor
-               ;
-
-json_object_aggregate_constructor:
-                       JSON_OBJECTAGG '('
-                               json_name_and_value
-                               json_object_constructor_null_clause_opt
-                               json_key_uniqueness_constraint_opt
-                               json_output_clause_opt
-                       ')'
-                               {
-                                       JsonObjectAgg *n = makeNode(JsonObjectAgg);
-
-                                       n->arg = (JsonKeyValue *) $3;
-                                       n->absent_on_null = $4;
-                                       n->unique = $5;
-                                       n->constructor = makeNode(JsonAggConstructor);
-                                       n->constructor->output = (JsonOutput *) $6;
-                                       n->constructor->agg_order = NULL;
-                                       n->constructor->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_array_aggregate_constructor:
-                       JSON_ARRAYAGG '('
-                               json_value_expr
-                               json_array_aggregate_order_by_clause_opt
-                               json_array_constructor_null_clause_opt
-                               json_output_clause_opt
-                       ')'
-                               {
-                                       JsonArrayAgg *n = makeNode(JsonArrayAgg);
-
-                                       n->arg = (JsonValueExpr *) $3;
-                                       n->absent_on_null = $5;
-                                       n->constructor = makeNode(JsonAggConstructor);
-                                       n->constructor->agg_order = $4;
-                                       n->constructor->output = (JsonOutput *) $6;
-                                       n->constructor->location = @1;
-                                       $$ = (Node *) n;
-                               }
-               ;
-
-json_array_aggregate_order_by_clause_opt:
-                       ORDER BY sortby_list                                    { $$ = $3; }
-                       | /* EMPTY */                                                   { $$ = NIL; }
-               ;
 
 /*****************************************************************************
  *
@@ -17664,7 +16643,6 @@ BareColLabel:   IDENT                                                           { $$ = $1; }
  */
 unreserved_keyword:
                          ABORT_P
-                       | ABSENT
                        | ABSOLUTE_P
                        | ACCESS
                        | ACTION
@@ -17705,7 +16683,6 @@ unreserved_keyword:
                        | COMMIT
                        | COMMITTED
                        | COMPRESSION
-                       | CONDITIONAL
                        | CONFIGURATION
                        | CONFLICT
                        | CONNECTION
@@ -17742,12 +16719,10 @@ unreserved_keyword:
                        | DOUBLE_P
                        | DROP
                        | EACH
-                       | EMPTY_P
                        | ENABLE_P
                        | ENCODING
                        | ENCRYPTED
                        | ENUM_P
-                       | ERROR_P
                        | ESCAPE
                        | EVENT
                        | EXCLUDE
@@ -17764,7 +16739,6 @@ unreserved_keyword:
                        | FIRST_P
                        | FOLLOWING
                        | FORCE
-                       | FORMAT
                        | FORWARD
                        | FUNCTION
                        | FUNCTIONS
@@ -17796,9 +16770,7 @@ unreserved_keyword:
                        | INSTEAD
                        | INVOKER
                        | ISOLATION
-                       | KEEP
                        | KEY
-                       | KEYS
                        | LABEL
                        | LANGUAGE
                        | LARGE_P
@@ -17826,7 +16798,6 @@ unreserved_keyword:
                        | MOVE
                        | NAME_P
                        | NAMES
-                       | NESTED
                        | NEW
                        | NEXT
                        | NFC
@@ -17844,7 +16815,6 @@ unreserved_keyword:
                        | OFF
                        | OIDS
                        | OLD
-                       | OMIT
                        | OPERATOR
                        | OPTION
                        | OPTIONS
@@ -17861,8 +16831,6 @@ unreserved_keyword:
                        | PARTITION
                        | PASSING
                        | PASSWORD
-                       | PATH
-                       | PLAN
                        | PLANS
                        | POLICY
                        | PRECEDING
@@ -17877,7 +16845,6 @@ unreserved_keyword:
                        | PROGRAM
                        | PUBLICATION
                        | QUOTE
-                       | QUOTES
                        | RANGE
                        | READ
                        | REASSIGN
@@ -17907,7 +16874,6 @@ unreserved_keyword:
                        | ROWS
                        | RULE
                        | SAVEPOINT
-                       | SCALAR
                        | SCHEMA
                        | SCHEMAS
                        | SCROLL
@@ -17937,7 +16903,6 @@ unreserved_keyword:
                        | STORAGE
                        | STORED
                        | STRICT_P
-                       | STRING
                        | STRIP_P
                        | SUBSCRIPTION
                        | SUPPORT
@@ -17960,7 +16925,6 @@ unreserved_keyword:
                        | UESCAPE
                        | UNBOUNDED
                        | UNCOMMITTED
-                       | UNCONDITIONAL
                        | UNENCRYPTED
                        | UNKNOWN
                        | UNLISTEN
@@ -18018,17 +16982,6 @@ col_name_keyword:
                        | INT_P
                        | INTEGER
                        | INTERVAL
-                       | JSON
-                       | JSON_ARRAY
-                       | JSON_ARRAYAGG
-                       | JSON_EXISTS
-                       | JSON_OBJECT
-                       | JSON_OBJECTAGG
-                       | JSON_QUERY
-                       | JSON_SCALAR
-                       | JSON_SERIALIZE
-                       | JSON_TABLE
-                       | JSON_VALUE
                        | LEAST
                        | NATIONAL
                        | NCHAR
@@ -18197,7 +17150,6 @@ reserved_keyword:
  */
 bare_label_keyword:
                          ABORT_P
-                       | ABSENT
                        | ABSOLUTE_P
                        | ACCESS
                        | ACTION
@@ -18260,7 +17212,6 @@ bare_label_keyword:
                        | COMMITTED
                        | COMPRESSION
                        | CONCURRENTLY
-                       | CONDITIONAL
                        | CONFIGURATION
                        | CONFLICT
                        | CONNECTION
@@ -18313,13 +17264,11 @@ bare_label_keyword:
                        | DROP
                        | EACH
                        | ELSE
-                       | EMPTY_P
                        | ENABLE_P
                        | ENCODING
                        | ENCRYPTED
                        | END_P
                        | ENUM_P
-                       | ERROR_P
                        | ESCAPE
                        | EVENT
                        | EXCLUDE
@@ -18340,7 +17289,6 @@ bare_label_keyword:
                        | FOLLOWING
                        | FORCE
                        | FOREIGN
-                       | FORMAT
                        | FORWARD
                        | FREEZE
                        | FULL
@@ -18385,20 +17333,7 @@ bare_label_keyword:
                        | IS
                        | ISOLATION
                        | JOIN
-                       | JSON
-                       | JSON_ARRAY
-                       | JSON_ARRAYAGG
-                       | JSON_EXISTS
-                       | JSON_OBJECT
-                       | JSON_OBJECTAGG
-                       | JSON_QUERY
-                       | JSON_SCALAR
-                       | JSON_SERIALIZE
-                       | JSON_TABLE
-                       | JSON_VALUE
-                       | KEEP
                        | KEY
-                       | KEYS
                        | LABEL
                        | LANGUAGE
                        | LARGE_P
@@ -18434,7 +17369,6 @@ bare_label_keyword:
                        | NATIONAL
                        | NATURAL
                        | NCHAR
-                       | NESTED
                        | NEW
                        | NEXT
                        | NFC
@@ -18458,7 +17392,6 @@ bare_label_keyword:
                        | OFF
                        | OIDS
                        | OLD
-                       | OMIT
                        | ONLY
                        | OPERATOR
                        | OPTION
@@ -18479,9 +17412,7 @@ bare_label_keyword:
                        | PARTITION
                        | PASSING
                        | PASSWORD
-                       | PATH
                        | PLACING
-                       | PLAN
                        | PLANS
                        | POLICY
                        | POSITION
@@ -18498,7 +17429,6 @@ bare_label_keyword:
                        | PROGRAM
                        | PUBLICATION
                        | QUOTE
-                       | QUOTES
                        | RANGE
                        | READ
                        | REAL
@@ -18532,7 +17462,6 @@ bare_label_keyword:
                        | ROWS
                        | RULE
                        | SAVEPOINT
-                       | SCALAR
                        | SCHEMA
                        | SCHEMAS
                        | SCROLL
@@ -18567,7 +17496,6 @@ bare_label_keyword:
                        | STORAGE
                        | STORED
                        | STRICT_P
-                       | STRING
                        | STRIP_P
                        | SUBSCRIPTION
                        | SUBSTRING
@@ -18601,7 +17529,6 @@ bare_label_keyword:
                        | UESCAPE
                        | UNBOUNDED
                        | UNCOMMITTED
-                       | UNCONDITIONAL
                        | UNENCRYPTED
                        | UNIQUE
                        | UNKNOWN
index b85fbebd00eca4c6c6578a9ee792590c5101be24..061d0bcc505559c055d1c2730fae1140095ee33a 100644 (file)
@@ -690,9 +690,7 @@ transformRangeTableFunc(ParseState *pstate, RangeTableFunc *rtf)
        char      **names;
        int                     colno;
 
-       /* Currently only XMLTABLE and JSON_TABLE are supported */
-
-       tf->functype = TFT_XMLTABLE;
+       /* Currently only XMLTABLE is supported */
        constructName = "XMLTABLE";
        docType = XMLOID;
 
@@ -1099,17 +1097,13 @@ transformFromClauseItem(ParseState *pstate, Node *n,
                rtr->rtindex = nsitem->p_rtindex;
                return (Node *) rtr;
        }
-       else if (IsA(n, RangeTableFunc) || IsA(n, JsonTable))
+       else if (IsA(n, RangeTableFunc))
        {
                /* table function is like a plain relation */
                RangeTblRef *rtr;
                ParseNamespaceItem *nsitem;
 
-               if (IsA(n, RangeTableFunc))
-                       nsitem = transformRangeTableFunc(pstate, (RangeTableFunc *) n);
-               else
-                       nsitem = transformJsonTable(pstate, (JsonTable *) n);
-
+               nsitem = transformRangeTableFunc(pstate, (RangeTableFunc *) n);
                *top_nsitem = nsitem;
                *namespace = list_make1(nsitem);
                rtr = makeNode(RangeTblRef);
index e90af4c4771a1aadff46ed2d8e1881c36521a5eb..7582faabb377c760938bb56af4dc75ec56d2553f 100644 (file)
@@ -691,13 +691,6 @@ assign_collations_walker(Node *node, assign_collations_context *context)
                                                                                                                        &loccontext);
                                                }
                                                break;
-                                       case T_JsonExpr:
-
-                                               /*
-                                                * Context item and PASSING arguments are already
-                                                * marked with collations in parse_expr.c.
-                                                */
-                                               break;
                                        default:
 
                                                /*
index fabb5f72076cba4adef566b95cebc01585456645..7aaf1c673f85f2cc1f65a41d41cb8ab46df76650 100644 (file)
@@ -15,8 +15,6 @@
 
 #include "postgres.h"
 
-#include "catalog/pg_aggregate.h"
-#include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "commands/dbcommands.h"
 #include "miscadmin.h"
@@ -36,7 +34,6 @@
 #include "parser/parse_type.h"
 #include "utils/builtins.h"
 #include "utils/date.h"
-#include "utils/fmgroids.h"
 #include "utils/lsyscache.h"
 #include "utils/timestamp.h"
 #include "utils/xml.h"
@@ -77,21 +74,6 @@ static Node *transformWholeRowRef(ParseState *pstate,
 static Node *transformIndirection(ParseState *pstate, A_Indirection *ind);
 static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
 static Node *transformCollateClause(ParseState *pstate, CollateClause *c);
-static Node *transformJsonObjectConstructor(ParseState *pstate,
-                                                                                       JsonObjectConstructor *ctor);
-static Node *transformJsonArrayConstructor(ParseState *pstate,
-                                                                                  JsonArrayConstructor *ctor);
-static Node *transformJsonArrayQueryConstructor(ParseState *pstate,
-                                                                                               JsonArrayQueryConstructor *ctor);
-static Node *transformJsonObjectAgg(ParseState *pstate, JsonObjectAgg *agg);
-static Node *transformJsonArrayAgg(ParseState *pstate, JsonArrayAgg *agg);
-static Node *transformJsonIsPredicate(ParseState *pstate, JsonIsPredicate *p);
-static Node *transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *p);
-static Node *transformJsonValueExpr(ParseState *pstate, JsonValueExpr *jve);
-static Node *transformJsonParseExpr(ParseState *pstate, JsonParseExpr *expr);
-static Node *transformJsonScalarExpr(ParseState *pstate, JsonScalarExpr *expr);
-static Node *transformJsonSerializeExpr(ParseState *pstate,
-                                                                               JsonSerializeExpr *expr);
 static Node *make_row_comparison_op(ParseState *pstate, List *opname,
                                                                        List *largs, List *rargs, int location);
 static Node *make_row_distinct_op(ParseState *pstate, List *opname,
@@ -319,50 +301,6 @@ transformExprRecurse(ParseState *pstate, Node *expr)
                                break;
                        }
 
-               case T_JsonObjectConstructor:
-                       result = transformJsonObjectConstructor(pstate, (JsonObjectConstructor *) expr);
-                       break;
-
-               case T_JsonArrayConstructor:
-                       result = transformJsonArrayConstructor(pstate, (JsonArrayConstructor *) expr);
-                       break;
-
-               case T_JsonArrayQueryConstructor:
-                       result = transformJsonArrayQueryConstructor(pstate, (JsonArrayQueryConstructor *) expr);
-                       break;
-
-               case T_JsonObjectAgg:
-                       result = transformJsonObjectAgg(pstate, (JsonObjectAgg *) expr);
-                       break;
-
-               case T_JsonArrayAgg:
-                       result = transformJsonArrayAgg(pstate, (JsonArrayAgg *) expr);
-                       break;
-
-               case T_JsonIsPredicate:
-                       result = transformJsonIsPredicate(pstate, (JsonIsPredicate *) expr);
-                       break;
-
-               case T_JsonFuncExpr:
-                       result = transformJsonFuncExpr(pstate, (JsonFuncExpr *) expr);
-                       break;
-
-               case T_JsonValueExpr:
-                       result = transformJsonValueExpr(pstate, (JsonValueExpr *) expr);
-                       break;
-
-               case T_JsonParseExpr:
-                       result = transformJsonParseExpr(pstate, (JsonParseExpr *) expr);
-                       break;
-
-               case T_JsonScalarExpr:
-                       result = transformJsonScalarExpr(pstate, (JsonScalarExpr *) expr);
-                       break;
-
-               case T_JsonSerializeExpr:
-                       result = transformJsonSerializeExpr(pstate, (JsonSerializeExpr *) expr);
-                       break;
-
                default:
                        /* should not reach here */
                        elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
@@ -3163,1444 +3101,3 @@ ParseExprKindName(ParseExprKind exprKind)
        }
        return "unrecognized expression kind";
 }
-
-/*
- * Make string Const node from JSON encoding name.
- *
- * UTF8 is default encoding.
- */
-static Const *
-getJsonEncodingConst(JsonFormat *format)
-{
-       JsonEncoding encoding;
-       const char *enc;
-       Name            encname = palloc(sizeof(NameData));
-
-       if (!format ||
-               format->format_type == JS_FORMAT_DEFAULT ||
-               format->encoding == JS_ENC_DEFAULT)
-               encoding = JS_ENC_UTF8;
-       else
-               encoding = format->encoding;
-
-       switch (encoding)
-       {
-               case JS_ENC_UTF16:
-                       enc = "UTF16";
-                       break;
-               case JS_ENC_UTF32:
-                       enc = "UTF32";
-                       break;
-               case JS_ENC_UTF8:
-                       enc = "UTF8";
-                       break;
-               default:
-                       elog(ERROR, "invalid JSON encoding: %d", encoding);
-                       break;
-       }
-
-       namestrcpy(encname, enc);
-
-       return makeConst(NAMEOID, -1, InvalidOid, NAMEDATALEN,
-                                        NameGetDatum(encname), false, false);
-}
-
-/*
- * Make bytea => text conversion using specified JSON format encoding.
- */
-static Node *
-makeJsonByteaToTextConversion(Node *expr, JsonFormat *format, int location)
-{
-       Const      *encoding = getJsonEncodingConst(format);
-       FuncExpr   *fexpr = makeFuncExpr(F_CONVERT_FROM, TEXTOID,
-                                                                        list_make2(expr, encoding),
-                                                                        InvalidOid, InvalidOid,
-                                                                        COERCE_EXPLICIT_CALL);
-
-       fexpr->location = location;
-
-       return (Node *) fexpr;
-}
-
-/*
- * Make CaseTestExpr node.
- */
-static Node *
-makeCaseTestExpr(Node *expr)
-{
-       CaseTestExpr *placeholder = makeNode(CaseTestExpr);
-
-       placeholder->typeId = exprType(expr);
-       placeholder->typeMod = exprTypmod(expr);
-       placeholder->collation = exprCollation(expr);
-
-       return (Node *) placeholder;
-}
-
-/*
- * Transform JSON value expression using specified input JSON format or
- * default format otherwise.
- */
-static Node *
-transformJsonValueExprExt(ParseState *pstate, JsonValueExpr *ve,
-                                                 JsonFormatType default_format, bool isarg,
-                                                 Oid targettype)
-{
-       Node       *expr = transformExprRecurse(pstate, (Node *) ve->raw_expr);
-       Node       *rawexpr;
-       JsonFormatType format;
-       Oid                     exprtype;
-       int                     location;
-       char            typcategory;
-       bool            typispreferred;
-
-       if (exprType(expr) == UNKNOWNOID)
-               expr = coerce_to_specific_type(pstate, expr, TEXTOID, "JSON_VALUE_EXPR");
-
-       rawexpr = expr;
-       exprtype = exprType(expr);
-       location = exprLocation(expr);
-
-       get_type_category_preferred(exprtype, &typcategory, &typispreferred);
-
-       rawexpr = expr;
-
-       if (ve->format->format_type != JS_FORMAT_DEFAULT)
-       {
-               if (ve->format->encoding != JS_ENC_DEFAULT && exprtype != BYTEAOID)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_DATATYPE_MISMATCH),
-                                        errmsg("JSON ENCODING clause is only allowed for bytea input type"),
-                                        parser_errposition(pstate, ve->format->location)));
-
-               if (exprtype == JSONOID || exprtype == JSONBOID)
-               {
-                       format = JS_FORMAT_DEFAULT; /* do not format json[b] types */
-                       ereport(WARNING,
-                                       (errmsg("FORMAT JSON has no effect for json and jsonb types"),
-                                        parser_errposition(pstate, ve->format->location)));
-               }
-               else
-                       format = ve->format->format_type;
-       }
-       else if (isarg)
-       {
-               /* Pass SQL/JSON item types directly without conversion to json[b]. */
-               switch (exprtype)
-               {
-                       case TEXTOID:
-                       case NUMERICOID:
-                       case BOOLOID:
-                       case INT2OID:
-                       case INT4OID:
-                       case INT8OID:
-                       case FLOAT4OID:
-                       case FLOAT8OID:
-                       case DATEOID:
-                       case TIMEOID:
-                       case TIMETZOID:
-                       case TIMESTAMPOID:
-                       case TIMESTAMPTZOID:
-                               return expr;
-
-                       default:
-                               if (typcategory == TYPCATEGORY_STRING)
-                                       return coerce_to_specific_type(pstate, expr, TEXTOID,
-                                                                                                  "JSON_VALUE_EXPR");
-                               /* else convert argument to json[b] type */
-                               break;
-               }
-
-               format = default_format;
-       }
-       else if (exprtype == JSONOID || exprtype == JSONBOID)
-               format = JS_FORMAT_DEFAULT; /* do not format json[b] types */
-       else
-               format = default_format;
-
-       if (format == JS_FORMAT_DEFAULT &&
-               (!OidIsValid(targettype) || exprtype == targettype))
-               expr = rawexpr;
-       else
-       {
-               Node       *orig = makeCaseTestExpr(expr);
-               Node       *coerced;
-               bool            cast_is_needed = OidIsValid(targettype);
-
-               if (!isarg && !cast_is_needed &&
-                       exprtype != BYTEAOID && typcategory != TYPCATEGORY_STRING)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_DATATYPE_MISMATCH),
-                                        errmsg(ve->format->format_type == JS_FORMAT_DEFAULT ?
-                                                       "cannot use non-string types with implicit FORMAT JSON clause" :
-                                                       "cannot use non-string types with explicit FORMAT JSON clause"),
-                                        parser_errposition(pstate, ve->format->location >= 0 ?
-                                                                               ve->format->location : location)));
-
-               expr = orig;
-
-               /* Convert encoded JSON text from bytea. */
-               if (format == JS_FORMAT_JSON && exprtype == BYTEAOID)
-               {
-                       expr = makeJsonByteaToTextConversion(expr, ve->format, location);
-                       exprtype = TEXTOID;
-               }
-
-               if (!OidIsValid(targettype))
-                       targettype = format == JS_FORMAT_JSONB ? JSONBOID : JSONOID;
-
-               /* Try to coerce to the target type. */
-               coerced = coerce_to_target_type(pstate, expr, exprtype,
-                                                                               targettype, -1,
-                                                                               COERCION_EXPLICIT,
-                                                                               COERCE_EXPLICIT_CAST,
-                                                                               location);
-
-               if (!coerced)
-               {
-                       /* If coercion failed, use to_json()/to_jsonb() functions. */
-                       FuncExpr   *fexpr;
-                       Oid                     fnoid;
-
-                       if (cast_is_needed) /* only CAST is allowed */
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_CANNOT_COERCE),
-                                                errmsg("cannot cast type %s to %s",
-                                                               format_type_be(exprtype),
-                                                               format_type_be(targettype)),
-                                                parser_errposition(pstate, location)));
-
-                       fnoid = targettype == JSONOID ? F_TO_JSON : F_TO_JSONB;
-                       fexpr = makeFuncExpr(fnoid, targettype, list_make1(expr),
-                                                                InvalidOid, InvalidOid, COERCE_EXPLICIT_CALL);
-
-                       fexpr->location = location;
-
-                       coerced = (Node *) fexpr;
-               }
-
-               if (coerced == orig)
-                       expr = rawexpr;
-               else
-               {
-                       ve = copyObject(ve);
-                       ve->raw_expr = (Expr *) rawexpr;
-                       ve->formatted_expr = (Expr *) coerced;
-
-                       expr = (Node *) ve;
-               }
-       }
-
-       return expr;
-}
-
-/*
- * Transform JSON value expression using FORMAT JSON by default.
- */
-static Node *
-transformJsonValueExpr(ParseState *pstate, JsonValueExpr *jve)
-{
-       return transformJsonValueExprExt(pstate, jve, JS_FORMAT_JSON, false,
-                                                                        InvalidOid);
-}
-
-/*
- * Transform JSON value expression using unspecified format by default.
- */
-static Node *
-transformJsonValueExprDefault(ParseState *pstate, JsonValueExpr *jve)
-{
-       return transformJsonValueExprExt(pstate, jve, JS_FORMAT_DEFAULT, false,
-                                                                        InvalidOid);
-}
-
-/*
- * Checks specified output format for its applicability to the target type.
- */
-static void
-checkJsonOutputFormat(ParseState *pstate, const JsonFormat *format,
-                                         Oid targettype, bool allow_format_for_non_strings)
-{
-       if (!allow_format_for_non_strings &&
-               format->format_type != JS_FORMAT_DEFAULT &&
-               (targettype != BYTEAOID &&
-                targettype != JSONOID &&
-                targettype != JSONBOID))
-       {
-               char            typcategory;
-               bool            typispreferred;
-
-               get_type_category_preferred(targettype, &typcategory, &typispreferred);
-
-               if (typcategory != TYPCATEGORY_STRING)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                        parser_errposition(pstate, format->location),
-                                        errmsg("cannot use JSON format with non-string output types")));
-       }
-
-       if (format->format_type == JS_FORMAT_JSON)
-       {
-               JsonEncoding enc = format->encoding != JS_ENC_DEFAULT ?
-               format->encoding : JS_ENC_UTF8;
-
-               if (targettype != BYTEAOID &&
-                       format->encoding != JS_ENC_DEFAULT)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                        parser_errposition(pstate, format->location),
-                                        errmsg("cannot set JSON encoding for non-bytea output types")));
-
-               if (enc != JS_ENC_UTF8)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                        errmsg("unsupported JSON encoding"),
-                                        errhint("Only UTF8 JSON encoding is supported."),
-                                        parser_errposition(pstate, format->location)));
-       }
-}
-
-/*
- * Transform JSON output clause.
- *
- * Assigns target type oid and modifier.
- * Assigns default format or checks specified format for its applicability to
- * the target type.
- */
-static JsonReturning *
-transformJsonOutput(ParseState *pstate, const JsonOutput *output,
-                                       bool allow_format)
-{
-       JsonReturning *ret;
-
-       /* if output clause is not specified, make default clause value */
-       if (!output)
-       {
-               ret = makeNode(JsonReturning);
-
-               ret->format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
-               ret->typid = InvalidOid;
-               ret->typmod = -1;
-
-               return ret;
-       }
-
-       ret = copyObject(output->returning);
-
-       typenameTypeIdAndMod(pstate, output->typeName, &ret->typid, &ret->typmod);
-
-       if (output->typeName->setof)
-               ereport(ERROR,
-                               (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                errmsg("returning SETOF types is not supported in SQL/JSON functions")));
-
-       if (ret->format->format_type == JS_FORMAT_DEFAULT)
-               /* assign JSONB format when returning jsonb, or JSON format otherwise */
-               ret->format->format_type =
-                       ret->typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON;
-       else
-               checkJsonOutputFormat(pstate, ret->format, ret->typid, allow_format);
-
-       return ret;
-}
-
-/*
- * Transform JSON output clause of JSON constructor functions.
- *
- * Derive RETURNING type, if not specified, from argument types.
- */
-static JsonReturning *
-transformJsonConstructorOutput(ParseState *pstate, JsonOutput *output,
-                                                          List *args)
-{
-       JsonReturning *returning = transformJsonOutput(pstate, output, true);
-
-       if (!OidIsValid(returning->typid))
-       {
-               ListCell   *lc;
-               bool            have_jsonb = false;
-
-               foreach(lc, args)
-               {
-                       Node       *expr = lfirst(lc);
-                       Oid                     typid = exprType(expr);
-
-                       have_jsonb |= typid == JSONBOID;
-
-                       if (have_jsonb)
-                               break;
-               }
-
-               if (have_jsonb)
-               {
-                       returning->typid = JSONBOID;
-                       returning->format->format_type = JS_FORMAT_JSONB;
-               }
-               else
-               {
-                       /* XXX TEXT is default by the standard, but we return JSON */
-                       returning->typid = JSONOID;
-                       returning->format->format_type = JS_FORMAT_JSON;
-               }
-
-               returning->typmod = -1;
-       }
-
-       return returning;
-}
-
-/*
- * Coerce json[b]-valued function expression to the output type.
- */
-static Node *
-coerceJsonFuncExpr(ParseState *pstate, Node *expr,
-                                  const JsonReturning *returning, bool report_error)
-{
-       Node       *res;
-       int                     location;
-       Oid                     exprtype = exprType(expr);
-
-       /* if output type is not specified or equals to function type, return */
-       if (!OidIsValid(returning->typid) || returning->typid == exprtype)
-               return expr;
-
-       location = exprLocation(expr);
-
-       if (location < 0)
-               location = returning->format->location;
-
-       /* special case for RETURNING bytea FORMAT json */
-       if (returning->format->format_type == JS_FORMAT_JSON &&
-               returning->typid == BYTEAOID)
-       {
-               /* encode json text into bytea using pg_convert_to() */
-               Node       *texpr = coerce_to_specific_type(pstate, expr, TEXTOID,
-                                                                                                       "JSON_FUNCTION");
-               Const      *enc = getJsonEncodingConst(returning->format);
-               FuncExpr   *fexpr = makeFuncExpr(F_CONVERT_TO, BYTEAOID,
-                                                                                list_make2(texpr, enc),
-                                                                                InvalidOid, InvalidOid,
-                                                                                COERCE_EXPLICIT_CALL);
-
-               fexpr->location = location;
-
-               return (Node *) fexpr;
-       }
-
-       /* try to coerce expression to the output type */
-       res = coerce_to_target_type(pstate, expr, exprtype,
-                                                               returning->typid, returning->typmod,
-       /* XXX throwing errors when casting to char(N) */
-                                                               COERCION_EXPLICIT,
-                                                               COERCE_EXPLICIT_CAST,
-                                                               location);
-
-       if (!res && report_error)
-               ereport(ERROR,
-                               (errcode(ERRCODE_CANNOT_COERCE),
-                                errmsg("cannot cast type %s to %s",
-                                               format_type_be(exprtype),
-                                               format_type_be(returning->typid)),
-                                parser_coercion_errposition(pstate, location, expr)));
-
-       return res;
-}
-
-static Node *
-makeJsonConstructorExpr(ParseState *pstate, JsonConstructorType type,
-                                               List *args, Expr *fexpr, JsonReturning *returning,
-                                               bool unique, bool absent_on_null, int location)
-{
-       JsonConstructorExpr *jsctor = makeNode(JsonConstructorExpr);
-       Node       *placeholder;
-       Node       *coercion;
-       Oid                     intermediate_typid =
-       returning->format->format_type == JS_FORMAT_JSONB ? JSONBOID : JSONOID;
-
-       jsctor->args = args;
-       jsctor->func = fexpr;
-       jsctor->type = type;
-       jsctor->returning = returning;
-       jsctor->unique = unique;
-       jsctor->absent_on_null = absent_on_null;
-       jsctor->location = location;
-
-       if (fexpr)
-               placeholder = makeCaseTestExpr((Node *) fexpr);
-       else
-       {
-               CaseTestExpr *cte = makeNode(CaseTestExpr);
-
-               cte->typeId = intermediate_typid;
-               cte->typeMod = -1;
-               cte->collation = InvalidOid;
-
-               placeholder = (Node *) cte;
-       }
-
-       coercion = coerceJsonFuncExpr(pstate, placeholder, returning, true);
-
-       if (coercion != placeholder)
-               jsctor->coercion = (Expr *) coercion;
-
-       return (Node *) jsctor;
-}
-
-/*
- * Transform JSON_OBJECT() constructor.
- *
- * JSON_OBJECT() is transformed into json[b]_build_object[_ext]() call
- * depending on the output JSON format. The first two arguments of
- * json[b]_build_object_ext() are absent_on_null and check_key_uniqueness.
- *
- * Then function call result is coerced to the target type.
- */
-static Node *
-transformJsonObjectConstructor(ParseState *pstate, JsonObjectConstructor *ctor)
-{
-       JsonReturning *returning;
-       List       *args = NIL;
-
-       /* transform key-value pairs, if any */
-       if (ctor->exprs)
-       {
-               ListCell   *lc;
-
-               /* transform and append key-value arguments */
-               foreach(lc, ctor->exprs)
-               {
-                       JsonKeyValue *kv = castNode(JsonKeyValue, lfirst(lc));
-                       Node       *key = transformExprRecurse(pstate, (Node *) kv->key);
-                       Node       *val = transformJsonValueExprDefault(pstate, kv->value);
-
-                       args = lappend(args, key);
-                       args = lappend(args, val);
-               }
-       }
-
-       returning = transformJsonConstructorOutput(pstate, ctor->output, args);
-
-       return makeJsonConstructorExpr(pstate, JSCTOR_JSON_OBJECT, args, NULL,
-                                                                  returning, ctor->unique,
-                                                                  ctor->absent_on_null, ctor->location);
-}
-
-/*
- * Transform JSON_ARRAY(query [FORMAT] [RETURNING] [ON NULL]) into
- *  (SELECT  JSON_ARRAYAGG(a  [FORMAT] [RETURNING] [ON NULL]) FROM (query) q(a))
- */
-static Node *
-transformJsonArrayQueryConstructor(ParseState *pstate,
-                                                                  JsonArrayQueryConstructor *ctor)
-{
-       SubLink    *sublink = makeNode(SubLink);
-       SelectStmt *select = makeNode(SelectStmt);
-       RangeSubselect *range = makeNode(RangeSubselect);
-       Alias      *alias = makeNode(Alias);
-       ResTarget  *target = makeNode(ResTarget);
-       JsonArrayAgg *agg = makeNode(JsonArrayAgg);
-       ColumnRef  *colref = makeNode(ColumnRef);
-       Query      *query;
-       ParseState *qpstate;
-
-       /* Transform query only for counting target list entries. */
-       qpstate = make_parsestate(pstate);
-
-       query = transformStmt(qpstate, ctor->query);
-
-       if (count_nonjunk_tlist_entries(query->targetList) != 1)
-               ereport(ERROR,
-                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                errmsg("subquery must return only one column"),
-                                parser_errposition(pstate, ctor->location)));
-
-       free_parsestate(qpstate);
-
-       colref->fields = list_make2(makeString(pstrdup("q")),
-                                                               makeString(pstrdup("a")));
-       colref->location = ctor->location;
-
-       agg->arg = makeJsonValueExpr((Expr *) colref, ctor->format);
-       agg->absent_on_null = ctor->absent_on_null;
-       agg->constructor = makeNode(JsonAggConstructor);
-       agg->constructor->agg_order = NIL;
-       agg->constructor->output = ctor->output;
-       agg->constructor->location = ctor->location;
-
-       target->name = NULL;
-       target->indirection = NIL;
-       target->val = (Node *) agg;
-       target->location = ctor->location;
-
-       alias->aliasname = pstrdup("q");
-       alias->colnames = list_make1(makeString(pstrdup("a")));
-
-       range->lateral = false;
-       range->subquery = ctor->query;
-       range->alias = alias;
-
-       select->targetList = list_make1(target);
-       select->fromClause = list_make1(range);
-
-       sublink->subLinkType = EXPR_SUBLINK;
-       sublink->subLinkId = 0;
-       sublink->testexpr = NULL;
-       sublink->operName = NIL;
-       sublink->subselect = (Node *) select;
-       sublink->location = ctor->location;
-
-       return transformExprRecurse(pstate, (Node *) sublink);
-}
-
-/*
- * Common code for JSON_OBJECTAGG and JSON_ARRAYAGG transformation.
- */
-static Node *
-transformJsonAggConstructor(ParseState *pstate, JsonAggConstructor *agg_ctor,
-                                                       JsonReturning *returning, List *args,
-                                                       const char *aggfn, Oid aggtype,
-                                                       JsonConstructorType ctor_type,
-                                                       bool unique, bool absent_on_null)
-{
-       Oid                     aggfnoid;
-       Node       *node;
-       Expr       *aggfilter = agg_ctor->agg_filter ? (Expr *)
-       transformWhereClause(pstate, agg_ctor->agg_filter,
-                                                EXPR_KIND_FILTER, "FILTER") : NULL;
-
-       aggfnoid = DatumGetInt32(DirectFunctionCall1(regprocin,
-                                                                                                CStringGetDatum(aggfn)));
-
-       if (agg_ctor->over)
-       {
-               /* window function */
-               WindowFunc *wfunc = makeNode(WindowFunc);
-
-               wfunc->winfnoid = aggfnoid;
-               wfunc->wintype = aggtype;
-               /* wincollid and inputcollid will be set by parse_collate.c */
-               wfunc->args = args;
-               /* winref will be set by transformWindowFuncCall */
-               wfunc->winstar = false;
-               wfunc->winagg = true;
-               wfunc->aggfilter = aggfilter;
-               wfunc->location = agg_ctor->location;
-
-               /*
-                * ordered aggs not allowed in windows yet
-                */
-               if (agg_ctor->agg_order != NIL)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                        errmsg("aggregate ORDER BY is not implemented for window functions"),
-                                        parser_errposition(pstate, agg_ctor->location)));
-
-               /* parse_agg.c does additional window-func-specific processing */
-               transformWindowFuncCall(pstate, wfunc, agg_ctor->over);
-
-               node = (Node *) wfunc;
-       }
-       else
-       {
-               Aggref     *aggref = makeNode(Aggref);
-
-               aggref->aggfnoid = aggfnoid;
-               aggref->aggtype = aggtype;
-
-               /* aggcollid and inputcollid will be set by parse_collate.c */
-               aggref->aggtranstype = InvalidOid;      /* will be set by planner */
-               /* aggargtypes will be set by transformAggregateCall */
-               /* aggdirectargs and args will be set by transformAggregateCall */
-               /* aggorder and aggdistinct will be set by transformAggregateCall */
-               aggref->aggfilter = aggfilter;
-               aggref->aggstar = false;
-               aggref->aggvariadic = false;
-               aggref->aggkind = AGGKIND_NORMAL;
-               aggref->aggpresorted = false;
-               /* agglevelsup will be set by transformAggregateCall */
-               aggref->aggsplit = AGGSPLIT_SIMPLE; /* planner might change this */
-               aggref->location = agg_ctor->location;
-
-               transformAggregateCall(pstate, aggref, args, agg_ctor->agg_order, false);
-
-               node = (Node *) aggref;
-       }
-
-       return makeJsonConstructorExpr(pstate, ctor_type, NIL, (Expr *) node,
-                                                                  returning, unique, absent_on_null,
-                                                                  agg_ctor->location);
-}
-
-/*
- * Transform JSON_OBJECTAGG() aggregate function.
- *
- * JSON_OBJECTAGG() is transformed into
- * json[b]_objectagg(key, value, absent_on_null, check_unique) call depending on
- * the output JSON format.  Then the function call result is coerced to the
- * target output type.
- */
-static Node *
-transformJsonObjectAgg(ParseState *pstate, JsonObjectAgg *agg)
-{
-       JsonReturning *returning;
-       Node       *key;
-       Node       *val;
-       List       *args;
-       const char *aggfnname;
-       Oid                     aggtype;
-
-       key = transformExprRecurse(pstate, (Node *) agg->arg->key);
-       val = transformJsonValueExprDefault(pstate, agg->arg->value);
-       args = list_make2(key, val);
-
-       returning = transformJsonConstructorOutput(pstate, agg->constructor->output,
-                                                                                          args);
-
-       if (returning->format->format_type == JS_FORMAT_JSONB)
-       {
-               if (agg->absent_on_null)
-                       if (agg->unique)
-                               aggfnname = "pg_catalog.jsonb_object_agg_unique_strict";        /* F_JSONB_OBJECT_AGG_UNIQUE_STRICT */
-                       else
-                               aggfnname = "pg_catalog.jsonb_object_agg_strict";       /* F_JSONB_OBJECT_AGG_STRICT */
-               else if (agg->unique)
-                       aggfnname = "pg_catalog.jsonb_object_agg_unique";       /* F_JSONB_OBJECT_AGG_UNIQUE */
-               else
-                       aggfnname = "pg_catalog.jsonb_object_agg";      /* F_JSONB_OBJECT_AGG */
-
-               aggtype = JSONBOID;
-       }
-       else
-       {
-               if (agg->absent_on_null)
-                       if (agg->unique)
-                               aggfnname = "pg_catalog.json_object_agg_unique_strict"; /* F_JSON_OBJECT_AGG_UNIQUE_STRICT */
-                       else
-                               aggfnname = "pg_catalog.json_object_agg_strict";        /* F_JSON_OBJECT_AGG_STRICT */
-               else if (agg->unique)
-                       aggfnname = "pg_catalog.json_object_agg_unique";        /* F_JSON_OBJECT_AGG_UNIQUE */
-               else
-                       aggfnname = "pg_catalog.json_object_agg";       /* F_JSON_OBJECT_AGG */
-
-               aggtype = JSONOID;
-       }
-
-       return transformJsonAggConstructor(pstate, agg->constructor, returning,
-                                                                          args, aggfnname, aggtype,
-                                                                          JSCTOR_JSON_OBJECTAGG,
-                                                                          agg->unique, agg->absent_on_null);
-}
-
-/*
- * Transform JSON_ARRAYAGG() aggregate function.
- *
- * JSON_ARRAYAGG() is transformed into json[b]_agg[_strict]() call depending
- * on the output JSON format and absent_on_null.  Then the function call result
- * is coerced to the target output type.
- */
-static Node *
-transformJsonArrayAgg(ParseState *pstate, JsonArrayAgg *agg)
-{
-       JsonReturning *returning;
-       Node       *arg;
-       const char *aggfnname;
-       Oid                     aggtype;
-
-       arg = transformJsonValueExprDefault(pstate, agg->arg);
-
-       returning = transformJsonConstructorOutput(pstate, agg->constructor->output,
-                                                                                          list_make1(arg));
-
-       if (returning->format->format_type == JS_FORMAT_JSONB)
-       {
-               aggfnname = agg->absent_on_null ?
-                       "pg_catalog.jsonb_agg_strict" : "pg_catalog.jsonb_agg";
-               aggtype = JSONBOID;
-       }
-       else
-       {
-               aggfnname = agg->absent_on_null ?
-                       "pg_catalog.json_agg_strict" : "pg_catalog.json_agg";
-               aggtype = JSONOID;
-       }
-
-       return transformJsonAggConstructor(pstate, agg->constructor, returning,
-                                                                          list_make1(arg), aggfnname, aggtype,
-                                                                          JSCTOR_JSON_ARRAYAGG,
-                                                                          false, agg->absent_on_null);
-}
-
-/*
- * Transform JSON_ARRAY() constructor.
- *
- * JSON_ARRAY() is transformed into json[b]_build_array[_ext]() call
- * depending on the output JSON format. The first argument of
- * json[b]_build_array_ext() is absent_on_null.
- *
- * Then function call result is coerced to the target type.
- */
-static Node *
-transformJsonArrayConstructor(ParseState *pstate, JsonArrayConstructor *ctor)
-{
-       JsonReturning *returning;
-       List       *args = NIL;
-
-       /* transform element expressions, if any */
-       if (ctor->exprs)
-       {
-               ListCell   *lc;
-
-               /* transform and append element arguments */
-               foreach(lc, ctor->exprs)
-               {
-                       JsonValueExpr *jsval = castNode(JsonValueExpr, lfirst(lc));
-                       Node       *val = transformJsonValueExprDefault(pstate, jsval);
-
-                       args = lappend(args, val);
-               }
-       }
-
-       returning = transformJsonConstructorOutput(pstate, ctor->output, args);
-
-       return makeJsonConstructorExpr(pstate, JSCTOR_JSON_ARRAY, args, NULL,
-                                                                  returning, false, ctor->absent_on_null,
-                                                                  ctor->location);
-}
-
-static Node *
-transformJsonParseArg(ParseState *pstate, Node *jsexpr, JsonFormat *format,
-                                         Oid *exprtype)
-{
-       Node       *raw_expr = transformExprRecurse(pstate, jsexpr);
-       Node       *expr = raw_expr;
-
-       *exprtype = exprType(expr);
-
-       /* prepare input document */
-       if (*exprtype == BYTEAOID)
-       {
-               JsonValueExpr *jve;
-
-               expr = makeCaseTestExpr(raw_expr);
-               expr = makeJsonByteaToTextConversion(expr, format, exprLocation(expr));
-               *exprtype = TEXTOID;
-
-               jve = makeJsonValueExpr((Expr *) raw_expr, format);
-
-               jve->formatted_expr = (Expr *) expr;
-               expr = (Node *) jve;
-       }
-       else
-       {
-               char            typcategory;
-               bool            typispreferred;
-
-               get_type_category_preferred(*exprtype, &typcategory, &typispreferred);
-
-               if (*exprtype == UNKNOWNOID || typcategory == TYPCATEGORY_STRING)
-               {
-                       expr = coerce_to_target_type(pstate, (Node *) expr, *exprtype,
-                                                                                TEXTOID, -1,
-                                                                                COERCION_IMPLICIT,
-                                                                                COERCE_IMPLICIT_CAST, -1);
-                       *exprtype = TEXTOID;
-               }
-
-               if (format->encoding != JS_ENC_DEFAULT)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                        parser_errposition(pstate, format->location),
-                                        errmsg("cannot use JSON FORMAT ENCODING clause for non-bytea input types")));
-       }
-
-       return expr;
-}
-
-/*
- * Transform IS JSON predicate.
- */
-static Node *
-transformJsonIsPredicate(ParseState *pstate, JsonIsPredicate *pred)
-{
-       Oid                     exprtype;
-       Node       *expr = transformJsonParseArg(pstate, pred->expr, pred->format,
-                                                                                        &exprtype);
-
-       /* make resulting expression */
-       if (exprtype != TEXTOID && exprtype != JSONOID && exprtype != JSONBOID)
-               ereport(ERROR,
-                               (errcode(ERRCODE_DATATYPE_MISMATCH),
-                                errmsg("cannot use type %s in IS JSON predicate",
-                                               format_type_be(exprtype))));
-
-       /* This intentionally(?) drops the format clause. */
-       return makeJsonIsPredicate(expr, NULL, pred->item_type,
-                                                          pred->unique_keys, pred->location);
-}
-
-/*
- * Transform a JSON PASSING clause.
- */
-static void
-transformJsonPassingArgs(ParseState *pstate, JsonFormatType format, List *args,
-                                                List **passing_values, List **passing_names)
-{
-       ListCell   *lc;
-
-       *passing_values = NIL;
-       *passing_names = NIL;
-
-       foreach(lc, args)
-       {
-               JsonArgument *arg = castNode(JsonArgument, lfirst(lc));
-               Node       *expr = transformJsonValueExprExt(pstate, arg->val,
-                                                                                                        format, true, InvalidOid);
-
-               assign_expr_collations(pstate, expr);
-
-               *passing_values = lappend(*passing_values, expr);
-               *passing_names = lappend(*passing_names, makeString(arg->name));
-       }
-}
-
-/*
- * Transform a JSON BEHAVIOR clause.
- */
-static JsonBehavior *
-transformJsonBehavior(ParseState *pstate, JsonBehavior *behavior,
-                                         JsonBehaviorType default_behavior)
-{
-       JsonBehaviorType behavior_type = default_behavior;
-       Node       *default_expr = NULL;
-
-       if (behavior)
-       {
-               behavior_type = behavior->btype;
-               if (behavior_type == JSON_BEHAVIOR_DEFAULT)
-                       default_expr = transformExprRecurse(pstate, behavior->default_expr);
-       }
-       return makeJsonBehavior(behavior_type, default_expr);
-}
-
-/*
- * Common code for JSON_VALUE, JSON_QUERY, JSON_EXISTS transformation
- * into a JsonExpr node.
- */
-static JsonExpr *
-transformJsonExprCommon(ParseState *pstate, JsonFuncExpr *func)
-{
-       JsonExpr   *jsexpr = makeNode(JsonExpr);
-       Node       *pathspec;
-       JsonFormatType format;
-
-       if (func->common->pathname && func->op != JSON_TABLE_OP)
-               ereport(ERROR,
-                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                errmsg("JSON_TABLE path name is not allowed here"),
-                                parser_errposition(pstate, func->location)));
-
-       jsexpr->location = func->location;
-       jsexpr->op = func->op;
-       jsexpr->formatted_expr = transformJsonValueExpr(pstate, func->common->expr);
-
-       assign_expr_collations(pstate, jsexpr->formatted_expr);
-
-       /* format is determined by context item type */
-       format = exprType(jsexpr->formatted_expr) == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON;
-
-       jsexpr->result_coercion = NULL;
-       jsexpr->omit_quotes = false;
-
-       jsexpr->format = func->common->expr->format;
-
-       pathspec = transformExprRecurse(pstate, func->common->pathspec);
-
-       jsexpr->path_spec =
-               coerce_to_target_type(pstate, pathspec, exprType(pathspec),
-                                                         JSONPATHOID, -1,
-                                                         COERCION_EXPLICIT, COERCE_IMPLICIT_CAST,
-                                                         exprLocation(pathspec));
-       if (!jsexpr->path_spec)
-               ereport(ERROR,
-                               (errcode(ERRCODE_DATATYPE_MISMATCH),
-                                errmsg("JSON path expression must be type %s, not type %s",
-                                               "jsonpath", format_type_be(exprType(pathspec))),
-                                parser_errposition(pstate, exprLocation(pathspec))));
-
-       /* transform and coerce to json[b] passing arguments */
-       transformJsonPassingArgs(pstate, format, func->common->passing,
-                                                        &jsexpr->passing_values, &jsexpr->passing_names);
-
-       if (func->op != JSON_EXISTS_OP && func->op != JSON_TABLE_OP)
-               jsexpr->on_empty = transformJsonBehavior(pstate, func->on_empty,
-                                                                                                JSON_BEHAVIOR_NULL);
-
-       if (func->op == JSON_EXISTS_OP)
-               jsexpr->on_error = transformJsonBehavior(pstate, func->on_error,
-                                                                                                JSON_BEHAVIOR_FALSE);
-       else if (func->op == JSON_TABLE_OP)
-               jsexpr->on_error = transformJsonBehavior(pstate, func->on_error,
-                                                                                                JSON_BEHAVIOR_EMPTY);
-       else
-               jsexpr->on_error = transformJsonBehavior(pstate, func->on_error,
-                                                                                                JSON_BEHAVIOR_NULL);
-
-       return jsexpr;
-}
-
-/*
- * Assign default JSON returning type from the specified format or from
- * the context item type.
- */
-static void
-assignDefaultJsonReturningType(Node *context_item, JsonFormat *context_format,
-                                                          JsonReturning *ret)
-{
-       bool            is_jsonb;
-
-       ret->format = copyObject(context_format);
-
-       if (ret->format->format_type == JS_FORMAT_DEFAULT)
-               is_jsonb = exprType(context_item) == JSONBOID;
-       else
-               is_jsonb = ret->format->format_type == JS_FORMAT_JSONB;
-
-       ret->typid = is_jsonb ? JSONBOID : JSONOID;
-       ret->typmod = -1;
-}
-
-/*
- * Try to coerce expression to the output type or
- * use json_populate_type() for composite, array and domain types or
- * use coercion via I/O.
- */
-static JsonCoercion *
-coerceJsonExpr(ParseState *pstate, Node *expr, const JsonReturning *returning)
-{
-       char            typtype;
-       JsonCoercion *coercion = makeNode(JsonCoercion);
-
-       coercion->expr = coerceJsonFuncExpr(pstate, expr, returning, false);
-
-       if (coercion->expr)
-       {
-               if (coercion->expr == expr)
-                       coercion->expr = NULL;
-
-               return coercion;
-       }
-
-       typtype = get_typtype(returning->typid);
-
-       if (returning->typid == RECORDOID ||
-               typtype == TYPTYPE_COMPOSITE ||
-               typtype == TYPTYPE_DOMAIN ||
-               type_is_array(returning->typid))
-               coercion->via_populate = true;
-       else
-               coercion->via_io = true;
-
-       return coercion;
-}
-
-/*
- * Transform a JSON output clause of JSON_VALUE and JSON_QUERY.
- */
-static void
-transformJsonFuncExprOutput(ParseState *pstate, JsonFuncExpr *func,
-                                                       JsonExpr *jsexpr)
-{
-       Node       *expr = jsexpr->formatted_expr;
-
-       jsexpr->returning = transformJsonOutput(pstate, func->output, false);
-
-       /* JSON_VALUE returns text by default */
-       if (func->op == JSON_VALUE_OP && !OidIsValid(jsexpr->returning->typid))
-       {
-               jsexpr->returning->typid = TEXTOID;
-               jsexpr->returning->typmod = -1;
-       }
-
-       if (OidIsValid(jsexpr->returning->typid))
-       {
-               JsonReturning ret;
-
-               if (func->op == JSON_VALUE_OP &&
-                       jsexpr->returning->typid != JSONOID &&
-                       jsexpr->returning->typid != JSONBOID)
-               {
-                       /* Forced coercion via I/O for JSON_VALUE for non-JSON types */
-                       jsexpr->result_coercion = makeNode(JsonCoercion);
-                       jsexpr->result_coercion->expr = NULL;
-                       jsexpr->result_coercion->via_io = true;
-                       return;
-               }
-
-               assignDefaultJsonReturningType(jsexpr->formatted_expr, jsexpr->format, &ret);
-
-               if (ret.typid != jsexpr->returning->typid ||
-                       ret.typmod != jsexpr->returning->typmod)
-               {
-                       Node       *placeholder = makeCaseTestExpr(expr);
-
-                       Assert(((CaseTestExpr *) placeholder)->typeId == ret.typid);
-                       Assert(((CaseTestExpr *) placeholder)->typeMod == ret.typmod);
-
-                       jsexpr->result_coercion = coerceJsonExpr(pstate, placeholder,
-                                                                                                        jsexpr->returning);
-               }
-       }
-       else
-               assignDefaultJsonReturningType(jsexpr->formatted_expr, jsexpr->format,
-                                                                          jsexpr->returning);
-}
-
-/*
- * Coerce an expression in JSON DEFAULT behavior to the target output type.
- */
-static Node *
-coerceDefaultJsonExpr(ParseState *pstate, JsonExpr *jsexpr, Node *defexpr)
-{
-       int                     location;
-       Oid                     exprtype;
-
-       if (!defexpr)
-               return NULL;
-
-       exprtype = exprType(defexpr);
-       location = exprLocation(defexpr);
-
-       if (location < 0)
-               location = jsexpr->location;
-
-       defexpr = coerce_to_target_type(pstate,
-                                                                       defexpr,
-                                                                       exprtype,
-                                                                       jsexpr->returning->typid,
-                                                                       jsexpr->returning->typmod,
-                                                                       COERCION_EXPLICIT,
-                                                                       COERCE_IMPLICIT_CAST,
-                                                                       location);
-
-       if (!defexpr)
-               ereport(ERROR,
-                               (errcode(ERRCODE_CANNOT_COERCE),
-                                errmsg("cannot cast DEFAULT expression type %s to %s",
-                                               format_type_be(exprtype),
-                                               format_type_be(jsexpr->returning->typid)),
-                                parser_errposition(pstate, location)));
-
-       return defexpr;
-}
-
-/*
- * Initialize SQL/JSON item coercion from the SQL type "typid" to the target
- * "returning" type.
- */
-static JsonCoercion *
-initJsonItemCoercion(ParseState *pstate, Oid typid,
-                                        const JsonReturning *returning)
-{
-       Node       *expr;
-
-       if (typid == UNKNOWNOID)
-       {
-               expr = (Node *) makeNullConst(UNKNOWNOID, -1, InvalidOid);
-       }
-       else
-       {
-               CaseTestExpr *placeholder = makeNode(CaseTestExpr);
-
-               placeholder->typeId = typid;
-               placeholder->typeMod = -1;
-               placeholder->collation = InvalidOid;
-
-               expr = (Node *) placeholder;
-       }
-
-       return coerceJsonExpr(pstate, expr, returning);
-}
-
-static void
-initJsonItemCoercions(ParseState *pstate, JsonItemCoercions *coercions,
-                                         const JsonReturning *returning, Oid contextItemTypeId)
-{
-       struct
-       {
-               JsonCoercion **coercion;
-               Oid                     typid;
-       }                  *p,
-                               coercionTypids[] =
-       {
-               {&coercions->null, UNKNOWNOID},
-               {&coercions->string, TEXTOID},
-               {&coercions->numeric, NUMERICOID},
-               {&coercions->boolean, BOOLOID},
-               {&coercions->date, DATEOID},
-               {&coercions->time, TIMEOID},
-               {&coercions->timetz, TIMETZOID},
-               {&coercions->timestamp, TIMESTAMPOID},
-               {&coercions->timestamptz, TIMESTAMPTZOID},
-               {&coercions->composite, contextItemTypeId},
-               {NULL, InvalidOid}
-       };
-
-       for (p = coercionTypids; p->coercion; p++)
-               *p->coercion = initJsonItemCoercion(pstate, p->typid, returning);
-}
-
-/*
- * Transform JSON_VALUE, JSON_QUERY, JSON_EXISTS functions into a JsonExpr node.
- */
-static Node *
-transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
-{
-       JsonExpr   *jsexpr = transformJsonExprCommon(pstate, func);
-       const char *func_name = NULL;
-       Node       *contextItemExpr = jsexpr->formatted_expr;
-
-       switch (func->op)
-       {
-               case JSON_VALUE_OP:
-                       func_name = "JSON_VALUE";
-
-                       transformJsonFuncExprOutput(pstate, func, jsexpr);
-
-                       jsexpr->returning->format->format_type = JS_FORMAT_DEFAULT;
-                       jsexpr->returning->format->encoding = JS_ENC_DEFAULT;
-
-                       jsexpr->on_empty->default_expr =
-                               coerceDefaultJsonExpr(pstate, jsexpr,
-                                                                         jsexpr->on_empty->default_expr);
-
-                       jsexpr->on_error->default_expr =
-                               coerceDefaultJsonExpr(pstate, jsexpr,
-                                                                         jsexpr->on_error->default_expr);
-
-                       jsexpr->coercions = makeNode(JsonItemCoercions);
-                       initJsonItemCoercions(pstate, jsexpr->coercions, jsexpr->returning,
-                                                                 exprType(contextItemExpr));
-
-                       break;
-
-               case JSON_QUERY_OP:
-                       func_name = "JSON_QUERY";
-
-                       transformJsonFuncExprOutput(pstate, func, jsexpr);
-
-                       jsexpr->on_empty->default_expr =
-                               coerceDefaultJsonExpr(pstate, jsexpr,
-                                                                         jsexpr->on_empty->default_expr);
-
-                       jsexpr->on_error->default_expr =
-                               coerceDefaultJsonExpr(pstate, jsexpr,
-                                                                         jsexpr->on_error->default_expr);
-
-                       jsexpr->wrapper = func->wrapper;
-                       jsexpr->omit_quotes = func->omit_quotes;
-
-                       break;
-
-               case JSON_EXISTS_OP:
-                       func_name = "JSON_EXISTS";
-
-                       jsexpr->returning = transformJsonOutput(pstate, func->output, false);
-
-                       jsexpr->returning->format->format_type = JS_FORMAT_DEFAULT;
-                       jsexpr->returning->format->encoding = JS_ENC_DEFAULT;
-
-                       if (!OidIsValid(jsexpr->returning->typid))
-                       {
-                               jsexpr->returning->typid = BOOLOID;
-                               jsexpr->returning->typmod = -1;
-                       }
-                       else if (jsexpr->returning->typid != BOOLOID)
-                       {
-                               CaseTestExpr *placeholder = makeNode(CaseTestExpr);
-                               int                     location = exprLocation((Node *) jsexpr);
-
-                               placeholder->typeId = BOOLOID;
-                               placeholder->typeMod = -1;
-                               placeholder->collation = InvalidOid;
-
-                               jsexpr->result_coercion = makeNode(JsonCoercion);
-                               jsexpr->result_coercion->expr =
-                                       coerce_to_target_type(pstate, (Node *) placeholder, BOOLOID,
-                                                                                 jsexpr->returning->typid,
-                                                                                 jsexpr->returning->typmod,
-                                                                                 COERCION_EXPLICIT,
-                                                                                 COERCE_IMPLICIT_CAST,
-                                                                                 location);
-
-                               if (!jsexpr->result_coercion->expr)
-                                       ereport(ERROR,
-                                                       (errcode(ERRCODE_CANNOT_COERCE),
-                                                        errmsg("cannot cast type %s to %s",
-                                                                       format_type_be(BOOLOID),
-                                                                       format_type_be(jsexpr->returning->typid)),
-                                                        parser_coercion_errposition(pstate, location, (Node *) jsexpr)));
-
-                               if (jsexpr->result_coercion->expr == (Node *) placeholder)
-                                       jsexpr->result_coercion->expr = NULL;
-                       }
-                       break;
-
-               case JSON_TABLE_OP:
-                       jsexpr->returning = makeNode(JsonReturning);
-                       jsexpr->returning->format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
-                       jsexpr->returning->typid = exprType(contextItemExpr);
-                       jsexpr->returning->typmod = -1;
-
-                       if (jsexpr->returning->typid != JSONBOID)
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                                errmsg("JSON_TABLE() is not yet implemented for the json type"),
-                                                errhint("Try casting the argument to jsonb"),
-                                                parser_errposition(pstate, func->location)));
-
-                       break;
-       }
-
-       if (exprType(contextItemExpr) != JSONBOID)
-               ereport(ERROR,
-                               (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                errmsg("%s() is not yet implemented for the json type", func_name),
-                                errhint("Try casting the argument to jsonb"),
-                                parser_errposition(pstate, func->location)));
-
-       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 = JSONOID;
-               JsonFormatType format = 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 = transformJsonConstructorRet(pstate, jsexpr->output,
-                                                                                                                  "JSON()");
-       Node       *arg;
-
-       if (jsexpr->unique_keys)
-       {
-               /*
-                * Coerce string argument to text and then to json[b] in the executor
-                * node with key uniqueness check.
-                */
-               JsonValueExpr *jve = jsexpr->expr;
-               Oid                     arg_type;
-
-               arg = transformJsonParseArg(pstate, (Node *) jve->raw_expr, jve->format,
-                                                                       &arg_type);
-
-               if (arg_type != TEXTOID)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_DATATYPE_MISMATCH),
-                                        errmsg("cannot use non-string types with WITH UNIQUE KEYS clause"),
-                                        parser_errposition(pstate, jsexpr->location)));
-       }
-       else
-       {
-               /*
-                * Coerce argument to target type using CAST for compatibility with PG
-                * function-like CASTs.
-                */
-               arg = transformJsonValueExprExt(pstate, jsexpr->expr, JS_FORMAT_JSON,
-                                                                               false, returning->typid);
-       }
-
-       return makeJsonConstructorExpr(pstate, JSCTOR_JSON_PARSE, list_make1(arg), NULL,
-                                                                  returning, jsexpr->unique_keys, false,
-                                                                  jsexpr->location);
-}
-
-/*
- * Transform a JSON_SCALAR() expression.
- */
-static Node *
-transformJsonScalarExpr(ParseState *pstate, JsonScalarExpr *jsexpr)
-{
-       Node       *arg = transformExprRecurse(pstate, (Node *) jsexpr->expr);
-       JsonReturning *returning = transformJsonConstructorRet(pstate, jsexpr->output,
-                                                                                                                  "JSON_SCALAR()");
-
-       if (exprType(arg) == UNKNOWNOID)
-               arg = coerce_to_specific_type(pstate, arg, TEXTOID, "JSON_SCALAR");
-
-       return makeJsonConstructorExpr(pstate, JSCTOR_JSON_SCALAR, list_make1(arg), NULL,
-                                                                  returning, false, false, jsexpr->location);
-}
-
-/*
- * Transform a JSON_SERIALIZE() expression.
- */
-static Node *
-transformJsonSerializeExpr(ParseState *pstate, JsonSerializeExpr *expr)
-{
-       Node       *arg = transformJsonValueExpr(pstate, expr->expr);
-       JsonReturning *returning;
-
-       if (expr->output)
-       {
-               returning = transformJsonOutput(pstate, expr->output, true);
-
-               if (returning->typid != BYTEAOID)
-               {
-                       char            typcategory;
-                       bool            typispreferred;
-
-                       get_type_category_preferred(returning->typid, &typcategory,
-                                                                               &typispreferred);
-                       if (typcategory != TYPCATEGORY_STRING)
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_DATATYPE_MISMATCH),
-                                                errmsg("cannot use RETURNING type %s in %s",
-                                                               format_type_be(returning->typid),
-                                                               "JSON_SERIALIZE()"),
-                                                errhint("Try returning a string type or bytea.")));
-               }
-       }
-       else
-       {
-               /* RETURNING TEXT FORMAT JSON is by default */
-               returning = makeNode(JsonReturning);
-               returning->format = makeJsonFormat(JS_FORMAT_JSON, JS_ENC_DEFAULT, -1);
-               returning->typid = TEXTOID;
-               returning->typmod = -1;
-       }
-
-       return makeJsonConstructorExpr(pstate, JSCTOR_JSON_SERIALIZE, list_make1(arg),
-                                                                  NULL, returning, false, false, expr->location);
-}
diff --git a/src/backend/parser/parse_jsontable.c b/src/backend/parser/parse_jsontable.c
deleted file mode 100644 (file)
index 3e94071..0000000
+++ /dev/null
@@ -1,732 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * parse_jsontable.c
- *       parsing of JSON_TABLE
- *
- * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *       src/backend/parser/parse_jsontable.c
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres.h"
-
-#include "catalog/pg_collation.h"
-#include "catalog/pg_type.h"
-#include "miscadmin.h"
-#include "nodes/makefuncs.h"
-#include "nodes/nodeFuncs.h"
-#include "optimizer/optimizer.h"
-#include "parser/parse_clause.h"
-#include "parser/parse_collate.h"
-#include "parser/parse_expr.h"
-#include "parser/parse_relation.h"
-#include "parser/parse_type.h"
-#include "utils/builtins.h"
-#include "utils/json.h"
-#include "utils/lsyscache.h"
-
-/* Context for JSON_TABLE transformation */
-typedef struct JsonTableContext
-{
-       ParseState *pstate;                     /* parsing state */
-       JsonTable  *table;                      /* untransformed node */
-       TableFunc  *tablefunc;          /* transformed node     */
-       List       *pathNames;          /* list of all path and columns names */
-       int                     pathNameId;             /* path name id counter */
-       Oid                     contextItemTypid;       /* type oid of context item (json/jsonb) */
-} JsonTableContext;
-
-static JsonTableParent *transformJsonTableColumns(JsonTableContext *cxt,
-                                                                                                 JsonTablePlan *plan,
-                                                                                                 List *columns,
-                                                                                                 char *pathSpec,
-                                                                                                 char **pathName,
-                                                                                                 int location);
-
-static Node *
-makeStringConst(char *str, int location)
-{
-       A_Const    *n = makeNode(A_Const);
-
-       n->val.node.type = T_String;
-       n->val.sval.sval = str;
-       n->location = location;
-
-       return (Node *) n;
-}
-
-/*
- * Transform JSON_TABLE column
- *   - regular column into JSON_VALUE()
- *   - FORMAT JSON column into JSON_QUERY()
- *   - EXISTS column into JSON_EXISTS()
- */
-static Node *
-transformJsonTableColumn(JsonTableColumn *jtc, Node *contextItemExpr,
-                                                List *passingArgs, bool errorOnError)
-{
-       JsonFuncExpr *jfexpr = makeNode(JsonFuncExpr);
-       JsonCommon *common = makeNode(JsonCommon);
-       JsonOutput *output = makeNode(JsonOutput);
-       char       *pathspec;
-       JsonFormat *default_format;
-
-       jfexpr->op =
-               jtc->coltype == JTC_REGULAR ? JSON_VALUE_OP :
-               jtc->coltype == JTC_EXISTS ? JSON_EXISTS_OP : JSON_QUERY_OP;
-       jfexpr->common = common;
-       jfexpr->output = output;
-       jfexpr->on_empty = jtc->on_empty;
-       jfexpr->on_error = jtc->on_error;
-       if (!jfexpr->on_error && errorOnError)
-               jfexpr->on_error = makeJsonBehavior(JSON_BEHAVIOR_ERROR, NULL);
-       jfexpr->omit_quotes = jtc->omit_quotes;
-       jfexpr->wrapper = jtc->wrapper;
-       jfexpr->location = jtc->location;
-
-       output->typeName = jtc->typeName;
-       output->returning = makeNode(JsonReturning);
-       output->returning->format = jtc->format;
-
-       default_format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
-
-       common->pathname = NULL;
-       common->expr = makeJsonValueExpr((Expr *) contextItemExpr, default_format);
-       common->passing = passingArgs;
-
-       if (jtc->pathspec)
-               pathspec = jtc->pathspec;
-       else
-       {
-               /* Construct default path as '$."column_name"' */
-               StringInfoData path;
-
-               initStringInfo(&path);
-
-               appendStringInfoString(&path, "$.");
-               escape_json(&path, jtc->name);
-
-               pathspec = path.data;
-       }
-
-       common->pathspec = makeStringConst(pathspec, -1);
-
-       return (Node *) jfexpr;
-}
-
-static bool
-isJsonTablePathNameDuplicate(JsonTableContext *cxt, const char *pathname)
-{
-       ListCell   *lc;
-
-       foreach(lc, cxt->pathNames)
-       {
-               if (!strcmp(pathname, (const char *) lfirst(lc)))
-                       return true;
-       }
-
-       return false;
-}
-
-/* Register the column name in the path name list. */
-static void
-registerJsonTableColumn(JsonTableContext *cxt, char *colname)
-{
-       if (isJsonTablePathNameDuplicate(cxt, colname))
-               ereport(ERROR,
-                               (errcode(ERRCODE_DUPLICATE_ALIAS),
-                                errmsg("duplicate JSON_TABLE column name: %s", colname),
-                                errhint("JSON_TABLE column names must be distinct from one another.")));
-
-       cxt->pathNames = lappend(cxt->pathNames, colname);
-}
-
-/* Recursively register all nested column names in the path name list. */
-static void
-registerAllJsonTableColumns(JsonTableContext *cxt, List *columns)
-{
-       ListCell   *lc;
-
-       foreach(lc, columns)
-       {
-               JsonTableColumn *jtc = castNode(JsonTableColumn, lfirst(lc));
-
-               if (jtc->coltype == JTC_NESTED)
-               {
-                       if (jtc->pathname)
-                               registerJsonTableColumn(cxt, jtc->pathname);
-
-                       registerAllJsonTableColumns(cxt, jtc->columns);
-               }
-               else
-               {
-                       registerJsonTableColumn(cxt, jtc->name);
-               }
-       }
-}
-
-/* Generate a new unique JSON_TABLE path name. */
-static char *
-generateJsonTablePathName(JsonTableContext *cxt)
-{
-       char            namebuf[32];
-       char       *name = namebuf;
-
-       do
-       {
-               snprintf(namebuf, sizeof(namebuf), "json_table_path_%d",
-                                ++cxt->pathNameId);
-       } while (isJsonTablePathNameDuplicate(cxt, name));
-
-       name = pstrdup(name);
-       cxt->pathNames = lappend(cxt->pathNames, name);
-
-       return name;
-}
-
-/* Collect sibling path names from plan to the specified list. */
-static void
-collectSiblingPathsInJsonTablePlan(JsonTablePlan *plan, List **paths)
-{
-       if (plan->plan_type == JSTP_SIMPLE)
-               *paths = lappend(*paths, plan->pathname);
-       else if (plan->plan_type == JSTP_JOINED)
-       {
-               if (plan->join_type == JSTPJ_INNER ||
-                       plan->join_type == JSTPJ_OUTER)
-               {
-                       Assert(plan->plan1->plan_type == JSTP_SIMPLE);
-                       *paths = lappend(*paths, plan->plan1->pathname);
-               }
-               else if (plan->join_type == JSTPJ_CROSS ||
-                                plan->join_type == JSTPJ_UNION)
-               {
-                       collectSiblingPathsInJsonTablePlan(plan->plan1, paths);
-                       collectSiblingPathsInJsonTablePlan(plan->plan2, paths);
-               }
-               else
-                       elog(ERROR, "invalid JSON_TABLE join type %d",
-                                plan->join_type);
-       }
-}
-
-/*
- * Validate child JSON_TABLE plan by checking that:
- *  - all nested columns have path names specified
- *  - all nested columns have corresponding node in the sibling plan
- *  - plan does not contain duplicate or extra nodes
- */
-static void
-validateJsonTableChildPlan(ParseState *pstate, JsonTablePlan *plan,
-                                                  List *columns)
-{
-       ListCell   *lc1;
-       List       *siblings = NIL;
-       int                     nchildren = 0;
-
-       if (plan)
-               collectSiblingPathsInJsonTablePlan(plan, &siblings);
-
-       foreach(lc1, columns)
-       {
-               JsonTableColumn *jtc = castNode(JsonTableColumn, lfirst(lc1));
-
-               if (jtc->coltype == JTC_NESTED)
-               {
-                       ListCell   *lc2;
-                       bool            found = false;
-
-                       if (!jtc->pathname)
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                errmsg("nested JSON_TABLE columns must contain an explicit AS pathname specification if an explicit PLAN clause is used"),
-                                                parser_errposition(pstate, jtc->location)));
-
-                       /* find nested path name in the list of sibling path names */
-                       foreach(lc2, siblings)
-                       {
-                               if ((found = !strcmp(jtc->pathname, lfirst(lc2))))
-                                       break;
-                       }
-
-                       if (!found)
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                errmsg("invalid JSON_TABLE plan"),
-                                                errdetail("Plan node for nested path %s was not found in plan.", jtc->pathname),
-                                                parser_errposition(pstate, jtc->location)));
-
-                       nchildren++;
-               }
-       }
-
-       if (list_length(siblings) > nchildren)
-               ereport(ERROR,
-                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                errmsg("invalid JSON_TABLE plan"),
-                                errdetail("Plan node contains some extra or duplicate sibling nodes."),
-                                parser_errposition(pstate, plan ? plan->location : -1)));
-}
-
-static JsonTableColumn *
-findNestedJsonTableColumn(List *columns, const char *pathname)
-{
-       ListCell   *lc;
-
-       foreach(lc, columns)
-       {
-               JsonTableColumn *jtc = castNode(JsonTableColumn, lfirst(lc));
-
-               if (jtc->coltype == JTC_NESTED &&
-                       jtc->pathname &&
-                       !strcmp(jtc->pathname, pathname))
-                       return jtc;
-       }
-
-       return NULL;
-}
-
-static Node *
-transformNestedJsonTableColumn(JsonTableContext *cxt, JsonTableColumn *jtc,
-                                                          JsonTablePlan *plan)
-{
-       JsonTableParent *node;
-       char       *pathname = jtc->pathname;
-
-       node = transformJsonTableColumns(cxt, plan, jtc->columns, jtc->pathspec,
-                                                                        &pathname, jtc->location);
-       node->name = pstrdup(pathname);
-
-       return (Node *) node;
-}
-
-static Node *
-makeJsonTableSiblingJoin(bool cross, Node *lnode, Node *rnode)
-{
-       JsonTableSibling *join = makeNode(JsonTableSibling);
-
-       join->larg = lnode;
-       join->rarg = rnode;
-       join->cross = cross;
-
-       return (Node *) join;
-}
-
-/*
- * Recursively transform child JSON_TABLE plan.
- *
- * Default plan is transformed into a cross/union join of its nested columns.
- * Simple and outer/inner plans are transformed into a JsonTableParent by
- * finding and transforming corresponding nested column.
- * Sibling plans are recursively transformed into a JsonTableSibling.
- */
-static Node *
-transformJsonTableChildPlan(JsonTableContext *cxt, JsonTablePlan *plan,
-                                                       List *columns)
-{
-       JsonTableColumn *jtc = NULL;
-
-       if (!plan || plan->plan_type == JSTP_DEFAULT)
-       {
-               /* unspecified or default plan */
-               Node       *res = NULL;
-               ListCell   *lc;
-               bool            cross = plan && (plan->join_type & JSTPJ_CROSS);
-
-               /* transform all nested columns into cross/union join */
-               foreach(lc, columns)
-               {
-                       JsonTableColumn *col = castNode(JsonTableColumn, lfirst(lc));
-                       Node       *node;
-
-                       if (col->coltype != JTC_NESTED)
-                               continue;
-
-                       node = transformNestedJsonTableColumn(cxt, col, plan);
-
-                       /* join transformed node with previous sibling nodes */
-                       res = res ? makeJsonTableSiblingJoin(cross, res, node) : node;
-               }
-
-               return res;
-       }
-       else if (plan->plan_type == JSTP_SIMPLE)
-       {
-               jtc = findNestedJsonTableColumn(columns, plan->pathname);
-       }
-       else if (plan->plan_type == JSTP_JOINED)
-       {
-               if (plan->join_type == JSTPJ_INNER ||
-                       plan->join_type == JSTPJ_OUTER)
-               {
-                       Assert(plan->plan1->plan_type == JSTP_SIMPLE);
-                       jtc = findNestedJsonTableColumn(columns, plan->plan1->pathname);
-               }
-               else
-               {
-                       Node       *node1 = transformJsonTableChildPlan(cxt, plan->plan1,
-                                                                                                                       columns);
-                       Node       *node2 = transformJsonTableChildPlan(cxt, plan->plan2,
-                                                                                                                       columns);
-
-                       return makeJsonTableSiblingJoin(plan->join_type == JSTPJ_CROSS,
-                                                                                       node1, node2);
-               }
-       }
-       else
-               elog(ERROR, "invalid JSON_TABLE plan type %d", plan->plan_type);
-
-       if (!jtc)
-               ereport(ERROR,
-                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                errmsg("invalid JSON_TABLE plan"),
-                                errdetail("Path name was %s not found in nested columns list.",
-                                                  plan->pathname),
-                                parser_errposition(cxt->pstate, plan->location)));
-
-       return transformNestedJsonTableColumn(cxt, jtc, plan);
-}
-
-/* Check whether type is json/jsonb, array, or record. */
-static bool
-typeIsComposite(Oid typid)
-{
-       char            typtype;
-
-       if (typid == JSONOID ||
-               typid == JSONBOID ||
-               typid == RECORDOID ||
-               type_is_array(typid))
-               return true;
-
-       typtype = get_typtype(typid);
-
-       if (typtype == TYPTYPE_COMPOSITE)
-               return true;
-
-       if (typtype == TYPTYPE_DOMAIN)
-               return typeIsComposite(getBaseType(typid));
-
-       return false;
-}
-
-/* Append transformed non-nested JSON_TABLE columns to the TableFunc node */
-static void
-appendJsonTableColumns(JsonTableContext *cxt, List *columns)
-{
-       ListCell   *col;
-       ParseState *pstate = cxt->pstate;
-       JsonTable  *jt = cxt->table;
-       TableFunc  *tf = cxt->tablefunc;
-       bool            errorOnError = jt->on_error &&
-       jt->on_error->btype == JSON_BEHAVIOR_ERROR;
-
-       foreach(col, columns)
-       {
-               JsonTableColumn *rawc = castNode(JsonTableColumn, lfirst(col));
-               Oid                     typid;
-               int32           typmod;
-               Node       *colexpr;
-
-               if (rawc->name)
-               {
-                       /* make sure column names are unique */
-                       ListCell   *colname;
-
-                       foreach(colname, tf->colnames)
-                               if (!strcmp((const char *) colname, rawc->name))
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                errmsg("column name \"%s\" is not unique",
-                                                               rawc->name),
-                                                parser_errposition(pstate, rawc->location)));
-
-                       tf->colnames = lappend(tf->colnames,
-                                                                  makeString(pstrdup(rawc->name)));
-               }
-
-               /*
-                * Determine the type and typmod for the new column. FOR ORDINALITY
-                * columns are INTEGER by standard; the others are user-specified.
-                */
-               switch (rawc->coltype)
-               {
-                       case JTC_FOR_ORDINALITY:
-                               colexpr = NULL;
-                               typid = INT4OID;
-                               typmod = -1;
-                               break;
-
-                       case JTC_REGULAR:
-                               typenameTypeIdAndMod(pstate, rawc->typeName, &typid, &typmod);
-
-                               /*
-                                * Use implicit FORMAT JSON for composite types (arrays and
-                                * records)
-                                */
-                               if (typeIsComposite(typid))
-                                       rawc->coltype = JTC_FORMATTED;
-                               else if (rawc->wrapper != JSW_NONE)
-                                       ereport(ERROR,
-                                                       (errcode(ERRCODE_SYNTAX_ERROR),
-                                                        errmsg("cannot use WITH WRAPPER clause with scalar columns"),
-                                                        parser_errposition(pstate, rawc->location)));
-                               else if (rawc->omit_quotes)
-                                       ereport(ERROR,
-                                                       (errcode(ERRCODE_SYNTAX_ERROR),
-                                                        errmsg("cannot use OMIT QUOTES clause with scalar columns"),
-                                                        parser_errposition(pstate, rawc->location)));
-
-                               /* FALLTHROUGH */
-                       case JTC_EXISTS:
-                       case JTC_FORMATTED:
-                               {
-                                       Node       *je;
-                                       CaseTestExpr *param = makeNode(CaseTestExpr);
-
-                                       param->collation = InvalidOid;
-                                       param->typeId = cxt->contextItemTypid;
-                                       param->typeMod = -1;
-
-                                       je = transformJsonTableColumn(rawc, (Node *) param,
-                                                                                                 NIL, errorOnError);
-
-                                       colexpr = transformExpr(pstate, je, EXPR_KIND_FROM_FUNCTION);
-                                       assign_expr_collations(pstate, colexpr);
-
-                                       typid = exprType(colexpr);
-                                       typmod = exprTypmod(colexpr);
-                                       break;
-                               }
-
-                       case JTC_NESTED:
-                               continue;
-
-                       default:
-                               elog(ERROR, "unknown JSON_TABLE column type: %d", rawc->coltype);
-                               break;
-               }
-
-               tf->coltypes = lappend_oid(tf->coltypes, typid);
-               tf->coltypmods = lappend_int(tf->coltypmods, typmod);
-               tf->colcollations = lappend_oid(tf->colcollations, get_typcollation(typid));
-               tf->colvalexprs = lappend(tf->colvalexprs, colexpr);
-       }
-}
-
-/*
- * Create transformed JSON_TABLE parent plan node by appending all non-nested
- * columns to the TableFunc node and remembering their indices in the
- * colvalexprs list.
- */
-static JsonTableParent *
-makeParentJsonTableNode(JsonTableContext *cxt, char *pathSpec, List *columns)
-{
-       JsonTableParent *node = makeNode(JsonTableParent);
-
-       node->path = makeConst(JSONPATHOID, -1, InvalidOid, -1,
-                                                  DirectFunctionCall1(jsonpath_in,
-                                                                                          CStringGetDatum(pathSpec)),
-                                                  false, false);
-
-       /* save start of column range */
-       node->colMin = list_length(cxt->tablefunc->colvalexprs);
-
-       appendJsonTableColumns(cxt, columns);
-
-       /* save end of column range */
-       node->colMax = list_length(cxt->tablefunc->colvalexprs) - 1;
-
-       node->errorOnError =
-               cxt->table->on_error &&
-               cxt->table->on_error->btype == JSON_BEHAVIOR_ERROR;
-
-       return node;
-}
-
-static JsonTableParent *
-transformJsonTableColumns(JsonTableContext *cxt, JsonTablePlan *plan,
-                                                 List *columns, char *pathSpec, char **pathName,
-                                                 int location)
-{
-       JsonTableParent *node;
-       JsonTablePlan *childPlan;
-       bool            defaultPlan = !plan || plan->plan_type == JSTP_DEFAULT;
-
-       if (!*pathName)
-       {
-               if (cxt->table->plan)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_SYNTAX_ERROR),
-                                        errmsg("invalid JSON_TABLE expression"),
-                                        errdetail("JSON_TABLE columns must contain "
-                                                          "explicit AS pathname specification if "
-                                                          "explicit PLAN clause is used"),
-                                        parser_errposition(cxt->pstate, location)));
-
-               *pathName = generateJsonTablePathName(cxt);
-       }
-
-       if (defaultPlan)
-               childPlan = plan;
-       else
-       {
-               /* validate parent and child plans */
-               JsonTablePlan *parentPlan;
-
-               if (plan->plan_type == JSTP_JOINED)
-               {
-                       if (plan->join_type != JSTPJ_INNER &&
-                               plan->join_type != JSTPJ_OUTER)
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                errmsg("invalid JSON_TABLE plan"),
-                                                errdetail("Expected INNER or OUTER JSON_TABLE plan node."),
-                                                parser_errposition(cxt->pstate, plan->location)));
-
-                       parentPlan = plan->plan1;
-                       childPlan = plan->plan2;
-
-                       Assert(parentPlan->plan_type != JSTP_JOINED);
-                       Assert(parentPlan->pathname);
-               }
-               else
-               {
-                       parentPlan = plan;
-                       childPlan = NULL;
-               }
-
-               if (strcmp(parentPlan->pathname, *pathName))
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_SYNTAX_ERROR),
-                                        errmsg("invalid JSON_TABLE plan"),
-                                        errdetail("Path name mismatch: expected %s but %s is given.",
-                                                          *pathName, parentPlan->pathname),
-                                        parser_errposition(cxt->pstate, plan->location)));
-
-               validateJsonTableChildPlan(cxt->pstate, childPlan, columns);
-       }
-
-       /* transform only non-nested columns */
-       node = makeParentJsonTableNode(cxt, pathSpec, columns);
-       node->name = pstrdup(*pathName);
-
-       if (childPlan || defaultPlan)
-       {
-               /* transform recursively nested columns */
-               node->child = transformJsonTableChildPlan(cxt, childPlan, columns);
-               if (node->child)
-                       node->outerJoin = !plan || (plan->join_type & JSTPJ_OUTER);
-               /* else: default plan case, no children found */
-       }
-
-       return node;
-}
-
-/*
- * transformJsonTable -
- *                     Transform a raw JsonTable into TableFunc.
- *
- * Transform the document-generating expression, the row-generating expression,
- * the column-generating expressions, and the default value expressions.
- */
-ParseNamespaceItem *
-transformJsonTable(ParseState *pstate, JsonTable *jt)
-{
-       JsonTableContext cxt;
-       TableFunc  *tf = makeNode(TableFunc);
-       JsonFuncExpr *jfe = makeNode(JsonFuncExpr);
-       JsonTablePlan *plan = jt->plan;
-       JsonCommon *jscommon;
-       char       *rootPathName = jt->common->pathname;
-       char       *rootPath;
-       bool            is_lateral;
-
-       cxt.pstate = pstate;
-       cxt.table = jt;
-       cxt.tablefunc = tf;
-       cxt.pathNames = NIL;
-       cxt.pathNameId = 0;
-
-       if (rootPathName)
-               registerJsonTableColumn(&cxt, rootPathName);
-
-       registerAllJsonTableColumns(&cxt, jt->columns);
-
-#if 0                                                  /* XXX it' unclear from the standard whether
-                                                                * root path name is mandatory or not */
-       if (plan && plan->plan_type != JSTP_DEFAULT && !rootPathName)
-       {
-               /* Assign root path name and create corresponding plan node */
-               JsonTablePlan *rootNode = makeNode(JsonTablePlan);
-               JsonTablePlan *rootPlan = (JsonTablePlan *)
-               makeJsonTableJoinedPlan(JSTPJ_OUTER, (Node *) rootNode,
-                                                               (Node *) plan, jt->location);
-
-               rootPathName = generateJsonTablePathName(&cxt);
-
-               rootNode->plan_type = JSTP_SIMPLE;
-               rootNode->pathname = rootPathName;
-
-               plan = rootPlan;
-       }
-#endif
-
-       jscommon = copyObject(jt->common);
-       jscommon->pathspec = makeStringConst(pstrdup("$"), -1);
-
-       jfe->op = JSON_TABLE_OP;
-       jfe->common = jscommon;
-       jfe->on_error = jt->on_error;
-       jfe->location = jt->common->location;
-
-       /*
-        * We make lateral_only names of this level visible, whether or not the
-        * RangeTableFunc is explicitly marked LATERAL.  This is needed for SQL
-        * spec compliance and seems useful on convenience grounds for all
-        * functions in FROM.
-        *
-        * (LATERAL can't nest within a single pstate level, so we don't need
-        * save/restore logic here.)
-        */
-       Assert(!pstate->p_lateral_active);
-       pstate->p_lateral_active = true;
-
-       tf->functype = TFT_JSON_TABLE;
-       tf->docexpr = transformExpr(pstate, (Node *) jfe, EXPR_KIND_FROM_FUNCTION);
-
-       cxt.contextItemTypid = exprType(tf->docexpr);
-
-       if (!IsA(jt->common->pathspec, A_Const) ||
-               castNode(A_Const, jt->common->pathspec)->val.node.type != T_String)
-               ereport(ERROR,
-                               (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
-                                errmsg("only string constants supported in JSON_TABLE path specification"),
-                                parser_errposition(pstate,
-                                                                       exprLocation(jt->common->pathspec))));
-
-       rootPath = castNode(A_Const, jt->common->pathspec)->val.sval.sval;
-
-       tf->plan = (Node *) transformJsonTableColumns(&cxt, plan, jt->columns,
-                                                                                                 rootPath, &rootPathName,
-                                                                                                 jt->common->location);
-
-       tf->ordinalitycol = -1;         /* undefine ordinality column number */
-       tf->location = jt->location;
-
-       pstate->p_lateral_active = false;
-
-       /*
-        * Mark the RTE as LATERAL if the user said LATERAL explicitly, or if
-        * there are any lateral cross-references in it.
-        */
-       is_lateral = jt->lateral || contain_vars_of_level((Node *) tf, 0);
-
-       return addRangeTableEntryForTableFunc(pstate,
-                                                                                 tf, jt->alias, is_lateral, true);
-}
index f6b740df0acf31985f819fdf96e040c9d61969d6..f44937a8bba37ce41550fe5cdc0cdab626747c01 100644 (file)
@@ -2017,7 +2017,7 @@ addRangeTableEntryForTableFunc(ParseState *pstate,
                                                           bool inFromCl)
 {
        RangeTblEntry *rte = makeNode(RangeTblEntry);
-       char       *refname;
+       char       *refname = alias ? alias->aliasname : pstrdup("xmltable");
        Alias      *eref;
        int                     numaliases;
 
@@ -2035,8 +2035,7 @@ addRangeTableEntryForTableFunc(ParseState *pstate,
        Assert(list_length(tf->coltypmods) == list_length(tf->colnames));
        Assert(list_length(tf->colcollations) == list_length(tf->colnames));
 
-       refname = alias ? alias->aliasname :
-               pstrdup(tf->functype == TFT_XMLTABLE ? "xmltable" : "json_table");
+       refname = alias ? alias->aliasname :  pstrdup("xmltable");
 
        rte->rtekind = RTE_TABLEFUNC;
        rte->relid = InvalidOid;
@@ -2059,7 +2058,7 @@ addRangeTableEntryForTableFunc(ParseState *pstate,
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
                                 errmsg("%s function has %d columns available but %d columns specified",
-                                               tf->functype == TFT_XMLTABLE ? "XMLTABLE" : "JSON_TABLE",
+                                               "XMLTABLE",
                                                list_length(tf->colnames), numaliases)));
 
        rte->eref = eref;
index 16a0fe59e21dd503d297102df742e4b2ce592545..4e1593d9008293ccad692853f78cc2c9e014e447 100644 (file)
@@ -1957,46 +1957,6 @@ FigureColnameInternal(Node *node, char **name)
                case T_XmlSerialize:
                        *name = "xmlserialize";
                        return 2;
-               case T_JsonParseExpr:
-                       *name = "json";
-                       return 2;
-               case T_JsonScalarExpr:
-                       *name = "json_scalar";
-                       return 2;
-               case T_JsonSerializeExpr:
-                       *name = "json_serialize";
-                       return 2;
-               case T_JsonObjectConstructor:
-                       *name = "json_object";
-                       return 2;
-               case T_JsonArrayConstructor:
-               case T_JsonArrayQueryConstructor:
-                       *name = "json_array";
-                       return 2;
-               case T_JsonObjectAgg:
-                       *name = "json_objectagg";
-                       return 2;
-               case T_JsonArrayAgg:
-                       *name = "json_arrayagg";
-                       return 2;
-               case T_JsonFuncExpr:
-                       /* make SQL/JSON functions act like a regular function */
-                       switch (((JsonFuncExpr *) node)->op)
-                       {
-                               case JSON_QUERY_OP:
-                                       *name = "json_query";
-                                       return 2;
-                               case JSON_VALUE_OP:
-                                       *name = "json_value";
-                                       return 2;
-                               case JSON_EXISTS_OP:
-                                       *name = "json_exists";
-                                       return 2;
-                               case JSON_TABLE_OP:
-                                       *name = "json_table";
-                                       return 2;
-                       }
-                       break;
                default:
                        break;
        }
index eee0a29c08fee5aa18ceae2203f6ac9b60e4d3f3..50227cc0989f4a2a9a318be020b8ba97945087bf 100644 (file)
@@ -150,9 +150,6 @@ base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
                case USCONST:
                        cur_token_length = strlen(yyextra->core_yy_extra.scanbuf + *llocp);
                        break;
-               case WITHOUT:
-                       cur_token_length = 7;
-                       break;
                default:
                        return cur_token;
        }
@@ -224,19 +221,6 @@ base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner)
                                case ORDINALITY:
                                        cur_token = WITH_LA;
                                        break;
-                               case UNIQUE:
-                                       cur_token = WITH_LA_UNIQUE;
-                                       break;
-                       }
-                       break;
-
-               case WITHOUT:
-                       /* Replace WITHOUT by WITHOUT_LA if it's followed by TIME */
-                       switch (next_token)
-                       {
-                               case TIME:
-                                       cur_token = WITHOUT_LA;
-                                       break;
                        }
                        break;
 
index 060fd7e183b233bc5636cc5ce21e6385c24e9ec7..2918fdbfb6505f68d6afef171aa4899ae7c613a5 100644 (file)
@@ -294,10 +294,6 @@ format_type_extended(Oid type_oid, int32 typemod, bits16 flags)
                        else
                                buf = pstrdup("character varying");
                        break;
-
-               case JSONOID:
-                       buf = pstrdup("json");
-                       break;
        }
 
        if (buf == NULL)
index 6f8734a947dd336ab253d69219823358c5d2ea90..26f498b5df4d8eb280a0e6af69fd92d4ce0d89b7 100644 (file)
@@ -1045,6 +1045,11 @@ typedef struct NUMProc
                           *L_currency_symbol;
 } NUMProc;
 
+/* Return flags for DCH_from_char() */
+#define DCH_DATED      0x01
+#define DCH_TIMED      0x02
+#define DCH_ZONED      0x04
+
 /* ----------
  * Functions
  * ----------
@@ -6707,43 +6712,3 @@ float8_to_char(PG_FUNCTION_ARGS)
        NUM_TOCHAR_finish;
        PG_RETURN_TEXT_P(result);
 }
-
-int
-datetime_format_flags(const char *fmt_str, bool *have_error)
-{
-       bool            incache;
-       int                     fmt_len = strlen(fmt_str);
-       int                     result;
-       FormatNode *format;
-
-       if (fmt_len > DCH_CACHE_SIZE)
-       {
-               /*
-                * Allocate new memory if format picture is bigger than static cache
-                * and do not use cache (call parser always)
-                */
-               incache = false;
-
-               format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode));
-
-               parse_format(format, fmt_str, DCH_keywords,
-                                        DCH_suff, DCH_index, DCH_FLAG, NULL);
-       }
-       else
-       {
-               /*
-                * Use cache buffers
-                */
-               DCHCacheEntry *ent = DCH_cache_fetch(fmt_str, false);
-
-               incache = true;
-               format = ent->format;
-       }
-
-       result = DCH_datetime_type(format, have_error);
-
-       if (!incache)
-               pfree(format);
-
-       return result;
-}
index 5fdb7e32ce4459eeabf9a710991f4c4de3815e1a..fee2ffb55c8b745cb24ce4017ae3feddfd4de5bb 100644 (file)
  */
 #include "postgres.h"
 
-#include "access/hash.h"
-#include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
-#include "common/hashfn.h"
 #include "funcapi.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "utils/lsyscache.h"
 #include "utils/typcache.h"
 
-/* Common context for key uniqueness check */
-typedef struct HTAB *JsonUniqueCheckState;     /* hash table for key names */
-
-/* Hash entry for JsonUniqueCheckState */
-typedef struct JsonUniqueHashEntry
-{
-       const char *key;
-       int                     key_len;
-       int                     object_id;
-} JsonUniqueHashEntry;
-
-/* Context for key uniqueness check in builder functions */
-typedef struct JsonUniqueBuilderState
-{
-       JsonUniqueCheckState check; /* unique check */
-       StringInfoData skipped_keys;    /* skipped keys with NULL values */
-       MemoryContext mcxt;                     /* context for saving skipped keys */
-} JsonUniqueBuilderState;
-
-/* Element of object stack for key uniqueness check during json parsing */
-typedef struct JsonUniqueStackEntry
+typedef enum                                   /* type categories for datum_to_json */
 {
-       struct JsonUniqueStackEntry *parent;
-       int                     object_id;
-} JsonUniqueStackEntry;
-
-/* State for key uniqueness check during json parsing */
-typedef struct JsonUniqueParsingState
-{
-       JsonLexContext *lex;
-       JsonUniqueCheckState check;
-       JsonUniqueStackEntry *stack;
-       int                     id_counter;
-       bool            unique;
-} JsonUniqueParsingState;
+       JSONTYPE_NULL,                          /* null, so we didn't bother to identify */
+       JSONTYPE_BOOL,                          /* boolean (built-in types only) */
+       JSONTYPE_NUMERIC,                       /* numeric (ditto) */
+       JSONTYPE_DATE,                          /* we use special formatting for datetimes */
+       JSONTYPE_TIMESTAMP,
+       JSONTYPE_TIMESTAMPTZ,
+       JSONTYPE_JSON,                          /* JSON itself (and JSONB) */
+       JSONTYPE_ARRAY,                         /* array */
+       JSONTYPE_COMPOSITE,                     /* composite */
+       JSONTYPE_CAST,                          /* something with an explicit cast to JSON */
+       JSONTYPE_OTHER                          /* all else */
+} JsonTypeCategory;
 
 typedef struct JsonAggState
 {
@@ -73,7 +49,6 @@ typedef struct JsonAggState
        Oid                     key_output_func;
        JsonTypeCategory val_category;
        Oid                     val_output_func;
-       JsonUniqueBuilderState unique_check;
 } JsonAggState;
 
 static void composite_to_json(Datum composite, StringInfo result,
@@ -84,6 +59,9 @@ static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims,
                                                          bool use_line_feeds);
 static void array_to_json_internal(Datum array, StringInfo result,
                                                                   bool use_line_feeds);
+static void json_categorize_type(Oid typoid,
+                                                                JsonTypeCategory *tcategory,
+                                                                Oid *outfuncoid);
 static void datum_to_json(Datum val, bool is_null, StringInfo result,
                                                  JsonTypeCategory tcategory, Oid outfuncoid,
                                                  bool key_scalar);
@@ -162,7 +140,7 @@ json_recv(PG_FUNCTION_ARGS)
  * output function OID.  If the returned category is JSONTYPE_CAST, we
  * return the OID of the type->JSON cast function instead.
  */
-void
+static void
 json_categorize_type(Oid typoid,
                                         JsonTypeCategory *tcategory,
                                         Oid *outfuncoid)
@@ -744,48 +722,6 @@ row_to_json_pretty(PG_FUNCTION_ARGS)
        PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
 }
 
-Datum
-to_json_worker(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
-{
-       StringInfo      result = makeStringInfo();
-
-       datum_to_json(val, false, result, tcategory, outfuncoid, false);
-
-       return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
-}
-
-bool
-to_json_is_immutable(Oid typoid)
-{
-       JsonTypeCategory tcategory;
-       Oid                     outfuncoid;
-
-       json_categorize_type(typoid, &tcategory, &outfuncoid);
-
-       switch (tcategory)
-       {
-               case JSONTYPE_BOOL:
-               case JSONTYPE_JSON:
-                       return true;
-
-               case JSONTYPE_DATE:
-               case JSONTYPE_TIMESTAMP:
-               case JSONTYPE_TIMESTAMPTZ:
-                       return false;
-
-               case JSONTYPE_ARRAY:
-                       return false;           /* TODO recurse into elements */
-
-               case JSONTYPE_COMPOSITE:
-                       return false;           /* TODO recurse into fields */
-
-               case JSONTYPE_NUMERIC:
-               case JSONTYPE_CAST:
-               default:
-                       return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
-       }
-}
-
 /*
  * SQL function to_json(anyvalue)
  */
@@ -794,6 +730,7 @@ to_json(PG_FUNCTION_ARGS)
 {
        Datum           val = PG_GETARG_DATUM(0);
        Oid                     val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
+       StringInfo      result;
        JsonTypeCategory tcategory;
        Oid                     outfuncoid;
 
@@ -805,7 +742,11 @@ to_json(PG_FUNCTION_ARGS)
        json_categorize_type(val_type,
                                                 &tcategory, &outfuncoid);
 
-       PG_RETURN_DATUM(to_json_worker(val, tcategory, outfuncoid));
+       result = makeStringInfo();
+
+       datum_to_json(val, false, result, tcategory, outfuncoid, false);
+
+       PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
 }
 
 /*
@@ -813,8 +754,8 @@ to_json(PG_FUNCTION_ARGS)
  *
  * aggregate input column as a json array value.
  */
-static Datum
-json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
+Datum
+json_agg_transfn(PG_FUNCTION_ARGS)
 {
        MemoryContext aggcontext,
                                oldcontext;
@@ -854,13 +795,8 @@ json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
        else
        {
                state = (JsonAggState *) PG_GETARG_POINTER(0);
-       }
-
-       if (absent_on_null && PG_ARGISNULL(1))
-               PG_RETURN_POINTER(state);
-
-       if (state->str->len > 1)
                appendStringInfoString(state->str, ", ");
+       }
 
        /* fast path for NULLs */
        if (PG_ARGISNULL(1))
@@ -873,7 +809,7 @@ json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
        val = PG_GETARG_DATUM(1);
 
        /* add some whitespace if structured type and not first item */
-       if (!PG_ARGISNULL(0) && state->str->len > 1 &&
+       if (!PG_ARGISNULL(0) &&
                (state->val_category == JSONTYPE_ARRAY ||
                 state->val_category == JSONTYPE_COMPOSITE))
        {
@@ -891,25 +827,6 @@ json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
        PG_RETURN_POINTER(state);
 }
 
-
-/*
- * json_agg aggregate function
- */
-Datum
-json_agg_transfn(PG_FUNCTION_ARGS)
-{
-       return json_agg_transfn_worker(fcinfo, false);
-}
-
-/*
- * json_agg_strict aggregate function
- */
-Datum
-json_agg_strict_transfn(PG_FUNCTION_ARGS)
-{
-       return json_agg_transfn_worker(fcinfo, true);
-}
-
 /*
  * json_agg final function
  */
@@ -933,108 +850,18 @@ json_agg_finalfn(PG_FUNCTION_ARGS)
        PG_RETURN_TEXT_P(catenate_stringinfo_string(state->str, "]"));
 }
 
-/* Functions implementing hash table for key uniqueness check */
-static uint32
-json_unique_hash(const void *key, Size keysize)
-{
-       const JsonUniqueHashEntry *entry = (JsonUniqueHashEntry *) key;
-       uint32          hash = hash_bytes_uint32(entry->object_id);
-
-       hash ^= hash_bytes((const unsigned char *) entry->key, entry->key_len);
-
-       return DatumGetUInt32(hash);
-}
-
-static int
-json_unique_hash_match(const void *key1, const void *key2, Size keysize)
-{
-       const JsonUniqueHashEntry *entry1 = (const JsonUniqueHashEntry *) key1;
-       const JsonUniqueHashEntry *entry2 = (const JsonUniqueHashEntry *) key2;
-
-       if (entry1->object_id != entry2->object_id)
-               return entry1->object_id > entry2->object_id ? 1 : -1;
-
-       if (entry1->key_len != entry2->key_len)
-               return entry1->key_len > entry2->key_len ? 1 : -1;
-
-       return strncmp(entry1->key, entry2->key, entry1->key_len);
-}
-
-/* Functions implementing object key uniqueness check */
-static void
-json_unique_check_init(JsonUniqueCheckState *cxt)
-{
-       HASHCTL         ctl;
-
-       memset(&ctl, 0, sizeof(ctl));
-       ctl.keysize = sizeof(JsonUniqueHashEntry);
-       ctl.entrysize = sizeof(JsonUniqueHashEntry);
-       ctl.hcxt = CurrentMemoryContext;
-       ctl.hash = json_unique_hash;
-       ctl.match = json_unique_hash_match;
-
-       *cxt = hash_create("json object hashtable",
-                                          32,
-                                          &ctl,
-                                          HASH_ELEM | HASH_CONTEXT | HASH_FUNCTION | HASH_COMPARE);
-}
-
-static bool
-json_unique_check_key(JsonUniqueCheckState *cxt, const char *key, int object_id)
-{
-       JsonUniqueHashEntry entry;
-       bool            found;
-
-       entry.key = key;
-       entry.key_len = strlen(key);
-       entry.object_id = object_id;
-
-       (void) hash_search(*cxt, &entry, HASH_ENTER, &found);
-
-       return !found;
-}
-
-static void
-json_unique_builder_init(JsonUniqueBuilderState *cxt)
-{
-       json_unique_check_init(&cxt->check);
-       cxt->mcxt = CurrentMemoryContext;
-       cxt->skipped_keys.data = NULL;
-}
-
-/* On-demand initialization of skipped_keys StringInfo structure */
-static StringInfo
-json_unique_builder_get_skipped_keys(JsonUniqueBuilderState *cxt)
-{
-       StringInfo      out = &cxt->skipped_keys;
-
-       if (!out->data)
-       {
-               MemoryContext oldcxt = MemoryContextSwitchTo(cxt->mcxt);
-
-               initStringInfo(out);
-               MemoryContextSwitchTo(oldcxt);
-       }
-
-       return out;
-}
-
 /*
  * json_object_agg transition function.
  *
  * aggregate two input columns as a single json object value.
  */
-static Datum
-json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
-                                                          bool absent_on_null, bool unique_keys)
+Datum
+json_object_agg_transfn(PG_FUNCTION_ARGS)
 {
        MemoryContext aggcontext,
                                oldcontext;
        JsonAggState *state;
-       StringInfo      out;
        Datum           arg;
-       bool            skip;
-       int                     key_offset;
 
        if (!AggCheckCallContext(fcinfo, &aggcontext))
        {
@@ -1055,10 +882,6 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
                oldcontext = MemoryContextSwitchTo(aggcontext);
                state = (JsonAggState *) palloc(sizeof(JsonAggState));
                state->str = makeStringInfo();
-               if (unique_keys)
-                       json_unique_builder_init(&state->unique_check);
-               else
-                       memset(&state->unique_check, 0, sizeof(state->unique_check));
                MemoryContextSwitchTo(oldcontext);
 
                arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
@@ -1086,6 +909,7 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
        else
        {
                state = (JsonAggState *) PG_GETARG_POINTER(0);
+               appendStringInfoString(state->str, ", ");
        }
 
        /*
@@ -1101,49 +925,11 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 errmsg("field name must not be null")));
 
-       /* Skip null values if absent_on_null */
-       skip = absent_on_null && PG_ARGISNULL(2);
-
-       if (skip)
-       {
-               /* If key uniqueness check is needed we must save skipped keys */
-               if (!unique_keys)
-                       PG_RETURN_POINTER(state);
-
-               out = json_unique_builder_get_skipped_keys(&state->unique_check);
-       }
-       else
-       {
-               out = state->str;
-
-               /*
-                * Append comma delimiter only if we have already outputted some
-                * fields after the initial string "{ ".
-                */
-               if (out->len > 2)
-                       appendStringInfoString(out, ", ");
-       }
-
        arg = PG_GETARG_DATUM(1);
 
-       key_offset = out->len;
-
-       datum_to_json(arg, false, out, state->key_category,
+       datum_to_json(arg, false, state->str, state->key_category,
                                  state->key_output_func, true);
 
-       if (unique_keys)
-       {
-               const char *key = &out->data[key_offset];
-
-               if (!json_unique_check_key(&state->unique_check.check, key, 0))
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
-                                        errmsg("duplicate JSON key %s", key)));
-
-               if (skip)
-                       PG_RETURN_POINTER(state);
-       }
-
        appendStringInfoString(state->str, " : ");
 
        if (PG_ARGISNULL(2))
@@ -1157,42 +943,6 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
        PG_RETURN_POINTER(state);
 }
 
-/*
- * json_object_agg aggregate function
- */
-Datum
-json_object_agg_transfn(PG_FUNCTION_ARGS)
-{
-       return json_object_agg_transfn_worker(fcinfo, false, false);
-}
-
-/*
- * json_object_agg_strict aggregate function
- */
-Datum
-json_object_agg_strict_transfn(PG_FUNCTION_ARGS)
-{
-       return json_object_agg_transfn_worker(fcinfo, true, false);
-}
-
-/*
- * json_object_agg_unique aggregate function
- */
-Datum
-json_object_agg_unique_transfn(PG_FUNCTION_ARGS)
-{
-       return json_object_agg_transfn_worker(fcinfo, false, true);
-}
-
-/*
- * json_object_agg_unique_strict aggregate function
- */
-Datum
-json_object_agg_unique_strict_transfn(PG_FUNCTION_ARGS)
-{
-       return json_object_agg_transfn_worker(fcinfo, true, true);
-}
-
 /*
  * json_object_agg final function.
  */
@@ -1234,14 +984,25 @@ catenate_stringinfo_string(StringInfo buffer, const char *addon)
        return result;
 }
 
+/*
+ * SQL function json_build_object(variadic "any")
+ */
 Datum
-json_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
-                                                bool absent_on_null, bool unique_keys)
+json_build_object(PG_FUNCTION_ARGS)
 {
+       int                     nargs;
        int                     i;
        const char *sep = "";
        StringInfo      result;
-       JsonUniqueBuilderState unique_check;
+       Datum      *args;
+       bool       *nulls;
+       Oid                *types;
+
+       /* fetch argument values to build the object */
+       nargs = extract_variadic_args(fcinfo, 0, false, &args, &types, &nulls);
+
+       if (nargs < 0)
+               PG_RETURN_NULL();
 
        if (nargs % 2 != 0)
                ereport(ERROR,
@@ -1255,32 +1016,10 @@ json_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
 
        appendStringInfoChar(result, '{');
 
-       if (unique_keys)
-               json_unique_builder_init(&unique_check);
-
        for (i = 0; i < nargs; i += 2)
        {
-               StringInfo      out;
-               bool            skip;
-               int                     key_offset;
-
-               /* Skip null values if absent_on_null */
-               skip = absent_on_null && nulls[i + 1];
-
-               if (skip)
-               {
-                       /* If key uniqueness check is needed we must save skipped keys */
-                       if (!unique_keys)
-                               continue;
-
-                       out = json_unique_builder_get_skipped_keys(&unique_check);
-               }
-               else
-               {
-                       appendStringInfoString(result, sep);
-                       sep = ", ";
-                       out = result;
-               }
+               appendStringInfoString(result, sep);
+               sep = ", ";
 
                /* process key */
                if (nulls[i])
@@ -1289,24 +1028,7 @@ json_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
                                         errmsg("argument %d cannot be null", i + 1),
                                         errhint("Object keys should be text.")));
 
-               /* save key offset before key appending */
-               key_offset = out->len;
-
-               add_json(args[i], false, out, types[i], true);
-
-               if (unique_keys)
-               {
-                       /* check key uniqueness after key appending */
-                       const char *key = &out->data[key_offset];
-
-                       if (!json_unique_check_key(&unique_check.check, key, 0))
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
-                                                errmsg("duplicate JSON key %s", key)));
-
-                       if (skip)
-                               continue;
-               }
+               add_json(args[i], false, result, types[i], true);
 
                appendStringInfoString(result, " : ");
 
@@ -1316,27 +1038,7 @@ json_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
 
        appendStringInfoChar(result, '}');
 
-       return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
-}
-
-/*
- * SQL function json_build_object(variadic "any")
- */
-Datum
-json_build_object(PG_FUNCTION_ARGS)
-{
-       Datum      *args;
-       bool       *nulls;
-       Oid                *types;
-
-       /* build argument values to build the object */
-       int                     nargs = extract_variadic_args(fcinfo, 0, true,
-                                                                                         &args, &types, &nulls);
-
-       if (nargs < 0)
-               PG_RETURN_NULL();
-
-       PG_RETURN_DATUM(json_build_object_worker(nargs, args, nulls, types, false, false));
+       PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
 }
 
 /*
@@ -1348,13 +1050,25 @@ json_build_object_noargs(PG_FUNCTION_ARGS)
        PG_RETURN_TEXT_P(cstring_to_text_with_len("{}", 2));
 }
 
+/*
+ * SQL function json_build_array(variadic "any")
+ */
 Datum
-json_build_array_worker(int nargs, Datum *args, bool *nulls, Oid *types,
-                                               bool absent_on_null)
+json_build_array(PG_FUNCTION_ARGS)
 {
+       int                     nargs;
        int                     i;
        const char *sep = "";
        StringInfo      result;
+       Datum      *args;
+       bool       *nulls;
+       Oid                *types;
+
+       /* fetch argument values to build the array */
+       nargs = extract_variadic_args(fcinfo, 0, false, &args, &types, &nulls);
+
+       if (nargs < 0)
+               PG_RETURN_NULL();
 
        result = makeStringInfo();
 
@@ -1362,9 +1076,6 @@ json_build_array_worker(int nargs, Datum *args, bool *nulls, Oid *types,
 
        for (i = 0; i < nargs; i++)
        {
-               if (absent_on_null && nulls[i])
-                       continue;
-
                appendStringInfoString(result, sep);
                sep = ", ";
                add_json(args[i], nulls[i], result, types[i], false);
@@ -1372,27 +1083,7 @@ json_build_array_worker(int nargs, Datum *args, bool *nulls, Oid *types,
 
        appendStringInfoChar(result, ']');
 
-       return PointerGetDatum(cstring_to_text_with_len(result->data, result->len));
-}
-
-/*
- * SQL function json_build_array(variadic "any")
- */
-Datum
-json_build_array(PG_FUNCTION_ARGS)
-{
-       Datum      *args;
-       bool       *nulls;
-       Oid                *types;
-
-       /* build argument values to build the object */
-       int                     nargs = extract_variadic_args(fcinfo, 0, true,
-                                                                                         &args, &types, &nulls);
-
-       if (nargs < 0)
-               PG_RETURN_NULL();
-
-       PG_RETURN_DATUM(json_build_array_worker(nargs, args, nulls, types, false));
+       PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
 }
 
 /*
@@ -1618,106 +1309,6 @@ escape_json(StringInfo buf, const char *str)
        appendStringInfoCharMacro(buf, '"');
 }
 
-/* Semantic actions for key uniqueness check */
-static void
-json_unique_object_start(void *_state)
-{
-       JsonUniqueParsingState *state = _state;
-       JsonUniqueStackEntry *entry;
-
-       if (!state->unique)
-               return;
-
-       /* push object entry to stack */
-       entry = palloc(sizeof(*entry));
-       entry->object_id = state->id_counter++;
-       entry->parent = state->stack;
-       state->stack = entry;
-}
-
-static void
-json_unique_object_end(void *_state)
-{
-       JsonUniqueParsingState *state = _state;
-       JsonUniqueStackEntry *entry;
-
-       if (!state->unique)
-               return;
-
-       entry = state->stack;
-       state->stack = entry->parent;   /* pop object from stack */
-       pfree(entry);
-}
-
-static void
-json_unique_object_field_start(void *_state, char *field, bool isnull)
-{
-       JsonUniqueParsingState *state = _state;
-       JsonUniqueStackEntry *entry;
-
-       if (!state->unique)
-               return;
-
-       /* find key collision in the current object */
-       if (json_unique_check_key(&state->check, field, state->stack->object_id))
-               return;
-
-       state->unique = false;
-
-       /* pop all objects entries */
-       while ((entry = state->stack))
-       {
-               state->stack = entry->parent;
-               pfree(entry);
-       }
-}
-
-/* Validate JSON text and additionally check key uniqueness */
-bool
-json_validate(text *json, bool check_unique_keys, bool throw_error)
-{
-       JsonLexContext *lex = makeJsonLexContext(json, check_unique_keys);
-       JsonSemAction uniqueSemAction = {0};
-       JsonUniqueParsingState state;
-       JsonParseErrorType result;
-
-       if (check_unique_keys)
-       {
-               state.lex = lex;
-               state.stack = NULL;
-               state.id_counter = 0;
-               state.unique = true;
-               json_unique_check_init(&state.check);
-
-               uniqueSemAction.semstate = &state;
-               uniqueSemAction.object_start = json_unique_object_start;
-               uniqueSemAction.object_field_start = json_unique_object_field_start;
-               uniqueSemAction.object_end = json_unique_object_end;
-       }
-
-       result = pg_parse_json(lex, check_unique_keys ? &uniqueSemAction : &nullSemAction);
-
-       if (result != JSON_SUCCESS)
-       {
-               if (throw_error)
-                       json_ereport_error(result, lex);
-
-               return false;                   /* invalid json */
-       }
-
-       if (check_unique_keys && !state.unique)
-       {
-               if (throw_error)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
-                                        errmsg("duplicate JSON object key value")));
-
-               return false;                   /* not unique keys */
-       }
-
-       return true;                            /* ok */
-}
-
 /*
  * SQL function json_typeof(json) -> text
  *
@@ -1733,13 +1324,21 @@ json_validate(text *json, bool check_unique_keys, bool throw_error)
 Datum
 json_typeof(PG_FUNCTION_ARGS)
 {
-       text       *json = PG_GETARG_TEXT_PP(0);
-       char       *type;
+       text       *json;
+
+       JsonLexContext *lex;
        JsonTokenType tok;
+       char       *type;
+       JsonParseErrorType result;
 
-       /* Lex exactly one token from the input and check its type. */
-       tok = json_get_first_token(json, true);
+       json = PG_GETARG_TEXT_PP(0);
+       lex = makeJsonLexContext(json, false);
 
+       /* Lex exactly one token from the input and check its type. */
+       result = json_lex(lex);
+       if (result != JSON_SUCCESS)
+               json_ereport_error(result, lex);
+       tok = lex->token_type;
        switch (tok)
        {
                case JSON_TOKEN_OBJECT_START:
index f700c5b4c93771b6b7d4ded011f89bbd1c3b7402..88b0000f9a9de56f8e2b616828ed3960ad77224c 100644 (file)
@@ -14,7 +14,6 @@
 
 #include "access/htup_details.h"
 #include "access/transam.h"
-#include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "libpq/pqformat.h"
@@ -34,9 +33,25 @@ typedef struct JsonbInState
 {
        JsonbParseState *parseState;
        JsonbValue *res;
-       bool            unique_keys;
 } JsonbInState;
 
+/* unlike with json categories, we need to treat json and jsonb differently */
+typedef enum                                   /* type categories for datum_to_jsonb */
+{
+       JSONBTYPE_NULL,                         /* null, so we didn't bother to identify */
+       JSONBTYPE_BOOL,                         /* boolean (built-in types only) */
+       JSONBTYPE_NUMERIC,                      /* numeric (ditto) */
+       JSONBTYPE_DATE,                         /* we use special formatting for datetimes */
+       JSONBTYPE_TIMESTAMP,            /* we use special formatting for timestamp */
+       JSONBTYPE_TIMESTAMPTZ,          /* ... and timestamptz */
+       JSONBTYPE_JSON,                         /* JSON */
+       JSONBTYPE_JSONB,                        /* JSONB */
+       JSONBTYPE_ARRAY,                        /* array */
+       JSONBTYPE_COMPOSITE,            /* composite */
+       JSONBTYPE_JSONCAST,                     /* something with an explicit cast to JSON */
+       JSONBTYPE_OTHER                         /* all else */
+} JsonbTypeCategory;
+
 typedef struct JsonbAggState
 {
        JsonbInState *res;
@@ -46,7 +61,7 @@ typedef struct JsonbAggState
        Oid                     val_output_func;
 } JsonbAggState;
 
-static inline Datum jsonb_from_cstring(char *json, int len, bool unique_keys);
+static inline Datum jsonb_from_cstring(char *json, int len);
 static size_t checkStringLen(size_t len);
 static void jsonb_in_object_start(void *pstate);
 static void jsonb_in_object_end(void *pstate);
@@ -55,11 +70,17 @@ static void jsonb_in_array_end(void *pstate);
 static void jsonb_in_object_field_start(void *pstate, char *fname, bool isnull);
 static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal);
 static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype);
+static void jsonb_categorize_type(Oid typoid,
+                                                                 JsonbTypeCategory *tcategory,
+                                                                 Oid *outfuncoid);
 static void composite_to_jsonb(Datum composite, JsonbInState *result);
 static void array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims,
                                                           Datum *vals, bool *nulls, int *valcount,
                                                           JsonbTypeCategory tcategory, Oid outfuncoid);
 static void array_to_jsonb_internal(Datum array, JsonbInState *result);
+static void jsonb_categorize_type(Oid typoid,
+                                                                 JsonbTypeCategory *tcategory,
+                                                                 Oid *outfuncoid);
 static void datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
                                                   JsonbTypeCategory tcategory, Oid outfuncoid,
                                                   bool key_scalar);
@@ -77,7 +98,7 @@ jsonb_in(PG_FUNCTION_ARGS)
 {
        char       *json = PG_GETARG_CSTRING(0);
 
-       return jsonb_from_cstring(json, strlen(json), false);
+       return jsonb_from_cstring(json, strlen(json));
 }
 
 /*
@@ -101,7 +122,7 @@ jsonb_recv(PG_FUNCTION_ARGS)
        else
                elog(ERROR, "unsupported jsonb version number %d", version);
 
-       return jsonb_from_cstring(str, nbytes, false);
+       return jsonb_from_cstring(str, nbytes);
 }
 
 /*
@@ -142,14 +163,6 @@ jsonb_send(PG_FUNCTION_ARGS)
        PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
 }
 
-Datum
-jsonb_from_text(text *js, bool unique_keys)
-{
-       return jsonb_from_cstring(VARDATA_ANY(js),
-                                                         VARSIZE_ANY_EXHDR(js),
-                                                         unique_keys);
-}
-
 /*
  * Get the type name of a jsonb container.
  */
@@ -240,7 +253,7 @@ jsonb_typeof(PG_FUNCTION_ARGS)
  * Uses the json parser (with hooks) to construct a jsonb.
  */
 static inline Datum
-jsonb_from_cstring(char *json, int len, bool unique_keys)
+jsonb_from_cstring(char *json, int len)
 {
        JsonLexContext *lex;
        JsonbInState state;
@@ -250,8 +263,6 @@ jsonb_from_cstring(char *json, int len, bool unique_keys)
        memset(&sem, 0, sizeof(sem));
        lex = makeJsonLexContextCstringLen(json, len, GetDatabaseEncoding(), true);
 
-       state.unique_keys = unique_keys;
-
        sem.semstate = (void *) &state;
 
        sem.object_start = jsonb_in_object_start;
@@ -286,7 +297,6 @@ jsonb_in_object_start(void *pstate)
        JsonbInState *_state = (JsonbInState *) pstate;
 
        _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_OBJECT, NULL);
-       _state->parseState->unique_keys = _state->unique_keys;
 }
 
 static void
@@ -609,7 +619,7 @@ add_indent(StringInfo out, bool indent, int level)
  * output function OID.  If the returned category is JSONBTYPE_JSONCAST,
  * we return the OID of the relevant cast function instead.
  */
-void
+static void
 jsonb_categorize_type(Oid typoid,
                                          JsonbTypeCategory *tcategory,
                                          Oid *outfuncoid)
@@ -1115,51 +1125,6 @@ add_jsonb(Datum val, bool is_null, JsonbInState *result,
        datum_to_jsonb(val, is_null, result, tcategory, outfuncoid, key_scalar);
 }
 
-Datum
-to_jsonb_worker(Datum val, JsonbTypeCategory tcategory, Oid outfuncoid)
-{
-       JsonbInState result;
-
-       memset(&result, 0, sizeof(JsonbInState));
-
-       datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
-
-       return JsonbPGetDatum(JsonbValueToJsonb(result.res));
-}
-
-bool
-to_jsonb_is_immutable(Oid typoid)
-{
-       JsonbTypeCategory tcategory;
-       Oid                     outfuncoid;
-
-       jsonb_categorize_type(typoid, &tcategory, &outfuncoid);
-
-       switch (tcategory)
-       {
-               case JSONBTYPE_BOOL:
-               case JSONBTYPE_JSON:
-               case JSONBTYPE_JSONB:
-                       return true;
-
-               case JSONBTYPE_DATE:
-               case JSONBTYPE_TIMESTAMP:
-               case JSONBTYPE_TIMESTAMPTZ:
-                       return false;
-
-               case JSONBTYPE_ARRAY:
-                       return false;           /* TODO recurse into elements */
-
-               case JSONBTYPE_COMPOSITE:
-                       return false;           /* TODO recurse into fields */
-
-               case JSONBTYPE_NUMERIC:
-               case JSONBTYPE_JSONCAST:
-               default:
-                       return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
-       }
-}
-
 /*
  * SQL function to_jsonb(anyvalue)
  */
@@ -1168,6 +1133,7 @@ to_jsonb(PG_FUNCTION_ARGS)
 {
        Datum           val = PG_GETARG_DATUM(0);
        Oid                     val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
+       JsonbInState result;
        JsonbTypeCategory tcategory;
        Oid                     outfuncoid;
 
@@ -1179,15 +1145,31 @@ to_jsonb(PG_FUNCTION_ARGS)
        jsonb_categorize_type(val_type,
                                                  &tcategory, &outfuncoid);
 
-       PG_RETURN_DATUM(to_jsonb_worker(val, tcategory, outfuncoid));
+       memset(&result, 0, sizeof(JsonbInState));
+
+       datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
+
+       PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
 }
 
+/*
+ * SQL function jsonb_build_object(variadic "any")
+ */
 Datum
-jsonb_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
-                                                 bool absent_on_null, bool unique_keys)
+jsonb_build_object(PG_FUNCTION_ARGS)
 {
+       int                     nargs;
        int                     i;
        JsonbInState result;
+       Datum      *args;
+       bool       *nulls;
+       Oid                *types;
+
+       /* build argument values to build the object */
+       nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
+
+       if (nargs < 0)
+               PG_RETURN_NULL();
 
        if (nargs % 2 != 0)
                ereport(ERROR,
@@ -1200,26 +1182,15 @@ jsonb_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
        memset(&result, 0, sizeof(JsonbInState));
 
        result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
-       result.parseState->unique_keys = unique_keys;
-       result.parseState->skip_nulls = absent_on_null;
 
        for (i = 0; i < nargs; i += 2)
        {
                /* process key */
-               bool            skip;
-
                if (nulls[i])
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                         errmsg("argument %d: key must not be null", i + 1)));
 
-               /* skip null values if absent_on_null */
-               skip = absent_on_null && nulls[i + 1];
-
-               /* we need to save skipped keys for the key uniqueness check */
-               if (skip && !unique_keys)
-                       continue;
-
                add_jsonb(args[i], false, &result, types[i], true);
 
                /* process value */
@@ -1228,27 +1199,7 @@ jsonb_build_object_worker(int nargs, Datum *args, bool *nulls, Oid *types,
 
        result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
 
-       return JsonbPGetDatum(JsonbValueToJsonb(result.res));
-}
-
-/*
- * SQL function jsonb_build_object(variadic "any")
- */
-Datum
-jsonb_build_object(PG_FUNCTION_ARGS)
-{
-       Datum      *args;
-       bool       *nulls;
-       Oid                *types;
-
-       /* build argument values to build the object */
-       int                     nargs = extract_variadic_args(fcinfo, 0, true,
-                                                                                         &args, &types, &nulls);
-
-       if (nargs < 0)
-               PG_RETURN_NULL();
-
-       PG_RETURN_DATUM(jsonb_build_object_worker(nargs, args, nulls, types, false, false));
+       PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
 }
 
 /*
@@ -1267,50 +1218,36 @@ jsonb_build_object_noargs(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
 }
 
-Datum
-jsonb_build_array_worker(int nargs, Datum *args, bool *nulls, Oid *types,
-                                                bool absent_on_null)
-{
-       int                     i;
-       JsonbInState result;
-
-       memset(&result, 0, sizeof(JsonbInState));
-
-       result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
-
-       for (i = 0; i < nargs; i++)
-       {
-               if (absent_on_null && nulls[i])
-                       continue;
-
-               add_jsonb(args[i], nulls[i], &result, types[i], false);
-       }
-
-       result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
-
-       return JsonbPGetDatum(JsonbValueToJsonb(result.res));
-}
-
 /*
  * SQL function jsonb_build_array(variadic "any")
  */
 Datum
 jsonb_build_array(PG_FUNCTION_ARGS)
 {
+       int                     nargs;
+       int                     i;
+       JsonbInState result;
        Datum      *args;
        bool       *nulls;
        Oid                *types;
 
-       /* build argument values to build the object */
-       int                     nargs = extract_variadic_args(fcinfo, 0, true,
-                                                                                         &args, &types, &nulls);
+       /* build argument values to build the array */
+       nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
 
        if (nargs < 0)
                PG_RETURN_NULL();
 
-       PG_RETURN_DATUM(jsonb_build_array_worker(nargs, args, nulls, types, false));
-}
+       memset(&result, 0, sizeof(JsonbInState));
+
+       result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
 
+       for (i = 0; i < nargs; i++)
+               add_jsonb(args[i], nulls[i], &result, types[i], false);
+
+       result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
+
+       PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
+}
 
 /*
  * degenerate case of jsonb_build_array where it gets 0 arguments.
@@ -1545,8 +1482,6 @@ clone_parse_state(JsonbParseState *state)
        {
                ocursor->contVal = icursor->contVal;
                ocursor->size = icursor->size;
-               ocursor->unique_keys = icursor->unique_keys;
-               ocursor->skip_nulls = icursor->skip_nulls;
                icursor = icursor->next;
                if (icursor == NULL)
                        break;
@@ -1558,8 +1493,12 @@ clone_parse_state(JsonbParseState *state)
        return result;
 }
 
-static Datum
-jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
+
+/*
+ * jsonb_agg aggregate function
+ */
+Datum
+jsonb_agg_transfn(PG_FUNCTION_ARGS)
 {
        MemoryContext oldcontext,
                                aggcontext;
@@ -1607,9 +1546,6 @@ jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
                result = state->res;
        }
 
-       if (absent_on_null && PG_ARGISNULL(1))
-               PG_RETURN_POINTER(state);
-
        /* turn the argument into jsonb in the normal function context */
 
        val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
@@ -1679,24 +1615,6 @@ jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
        PG_RETURN_POINTER(state);
 }
 
-/*
- * jsonb_agg aggregate function
- */
-Datum
-jsonb_agg_transfn(PG_FUNCTION_ARGS)
-{
-       return jsonb_agg_transfn_worker(fcinfo, false);
-}
-
-/*
- * jsonb_agg_strict aggregate function
- */
-Datum
-jsonb_agg_strict_transfn(PG_FUNCTION_ARGS)
-{
-       return jsonb_agg_transfn_worker(fcinfo, true);
-}
-
 Datum
 jsonb_agg_finalfn(PG_FUNCTION_ARGS)
 {
@@ -1729,9 +1647,11 @@ jsonb_agg_finalfn(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(out);
 }
 
-static Datum
-jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
-                                                               bool absent_on_null, bool unique_keys)
+/*
+ * jsonb_object_agg aggregate function
+ */
+Datum
+jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
 {
        MemoryContext oldcontext,
                                aggcontext;
@@ -1745,7 +1665,6 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
                           *jbval;
        JsonbValue      v;
        JsonbIteratorToken type;
-       bool            skip;
 
        if (!AggCheckCallContext(fcinfo, &aggcontext))
        {
@@ -1765,9 +1684,6 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
                state->res = result;
                result->res = pushJsonbValue(&result->parseState,
                                                                         WJB_BEGIN_OBJECT, NULL);
-               result->parseState->unique_keys = unique_keys;
-               result->parseState->skip_nulls = absent_on_null;
-
                MemoryContextSwitchTo(oldcontext);
 
                arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
@@ -1803,15 +1719,6 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 errmsg("field name must not be null")));
 
-       /*
-        * Skip null values if absent_on_null unless key uniqueness check is
-        * needed (because we must save keys in this case).
-        */
-       skip = absent_on_null && PG_ARGISNULL(2);
-
-       if (skip && !unique_keys)
-               PG_RETURN_POINTER(state);
-
        val = PG_GETARG_DATUM(1);
 
        memset(&elem, 0, sizeof(JsonbInState));
@@ -1867,16 +1774,6 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
                                }
                                result->res = pushJsonbValue(&result->parseState,
                                                                                         WJB_KEY, &v);
-
-                               if (skip)
-                               {
-                                       v.type = jbvNull;
-                                       result->res = pushJsonbValue(&result->parseState,
-                                                                                                WJB_VALUE, &v);
-                                       MemoryContextSwitchTo(oldcontext);
-                                       PG_RETURN_POINTER(state);
-                               }
-
                                break;
                        case WJB_END_ARRAY:
                                break;
@@ -1949,43 +1846,6 @@ jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo,
        PG_RETURN_POINTER(state);
 }
 
-/*
- * jsonb_object_agg aggregate function
- */
-Datum
-jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
-{
-       return jsonb_object_agg_transfn_worker(fcinfo, false, false);
-}
-
-
-/*
- * jsonb_object_agg_strict aggregate function
- */
-Datum
-jsonb_object_agg_strict_transfn(PG_FUNCTION_ARGS)
-{
-       return jsonb_object_agg_transfn_worker(fcinfo, true, false);
-}
-
-/*
- * jsonb_object_agg_unique aggregate function
- */
-Datum
-jsonb_object_agg_unique_transfn(PG_FUNCTION_ARGS)
-{
-       return jsonb_object_agg_transfn_worker(fcinfo, false, true);
-}
-
-/*
- * jsonb_object_agg_unique_strict aggregate function
- */
-Datum
-jsonb_object_agg_unique_strict_transfn(PG_FUNCTION_ARGS)
-{
-       return jsonb_object_agg_transfn_worker(fcinfo, true, true);
-}
-
 Datum
 jsonb_object_agg_finalfn(PG_FUNCTION_ARGS)
 {
@@ -2217,65 +2077,3 @@ jsonb_float8(PG_FUNCTION_ARGS)
 
        PG_RETURN_DATUM(retValue);
 }
-
-/*
- * Construct an empty array jsonb.
- */
-Jsonb *
-JsonbMakeEmptyArray(void)
-{
-       JsonbValue      jbv;
-
-       jbv.type = jbvArray;
-       jbv.val.array.elems = NULL;
-       jbv.val.array.nElems = 0;
-       jbv.val.array.rawScalar = false;
-
-       return JsonbValueToJsonb(&jbv);
-}
-
-/*
- * Construct an empty object jsonb.
- */
-Jsonb *
-JsonbMakeEmptyObject(void)
-{
-       JsonbValue      jbv;
-
-       jbv.type = jbvObject;
-       jbv.val.object.pairs = NULL;
-       jbv.val.object.nPairs = 0;
-
-       return JsonbValueToJsonb(&jbv);
-}
-
-/*
- * Convert jsonb to a C-string stripping quotes from scalar strings.
- */
-char *
-JsonbUnquote(Jsonb *jb)
-{
-       if (JB_ROOT_IS_SCALAR(jb))
-       {
-               JsonbValue      v;
-
-               (void) JsonbExtractScalar(&jb->root, &v);
-
-               if (v.type == jbvString)
-                       return pnstrdup(v.val.string.val, v.val.string.len);
-               else if (v.type == jbvBool)
-                       return pstrdup(v.val.boolean ? "true" : "false");
-               else if (v.type == jbvNumeric)
-                       return DatumGetCString(DirectFunctionCall1(numeric_out,
-                                                                                                          PointerGetDatum(v.val.numeric)));
-               else if (v.type == jbvNull)
-                       return pstrdup("null");
-               else
-               {
-                       elog(ERROR, "unrecognized jsonb value type %d", v.type);
-                       return NULL;
-               }
-       }
-       else
-               return JsonbToCString(NULL, &jb->root, VARSIZE(jb));
-}
index 5318eda9cfbed11129e74e052386711b2837939d..60442758b3279d025379e229f95bf0382425b81f 100644 (file)
@@ -64,8 +64,7 @@ static int    lengthCompareJsonbStringValue(const void *a, const void *b);
 static int     lengthCompareJsonbString(const char *val1, int len1,
                                                                         const char *val2, int len2);
 static int     lengthCompareJsonbPair(const void *a, const void *b, void *arg);
-static void uniqueifyJsonbObject(JsonbValue *object, bool unique_keys,
-                                                                bool skip_nulls);
+static void uniqueifyJsonbObject(JsonbValue *object);
 static JsonbValue *pushJsonbValueScalar(JsonbParseState **pstate,
                                                                                JsonbIteratorToken seq,
                                                                                JsonbValue *scalarVal);
@@ -690,9 +689,7 @@ pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
                        appendElement(*pstate, scalarVal);
                        break;
                case WJB_END_OBJECT:
-                       uniqueifyJsonbObject(&(*pstate)->contVal,
-                                                                (*pstate)->unique_keys,
-                                                                (*pstate)->skip_nulls);
+                       uniqueifyJsonbObject(&(*pstate)->contVal);
                        /* fall through! */
                case WJB_END_ARRAY:
                        /* Steps here common to WJB_END_OBJECT case */
@@ -735,9 +732,6 @@ pushState(JsonbParseState **pstate)
        JsonbParseState *ns = palloc(sizeof(JsonbParseState));
 
        ns->next = *pstate;
-       ns->unique_keys = false;
-       ns->skip_nulls = false;
-
        return ns;
 }
 
@@ -1942,7 +1936,7 @@ lengthCompareJsonbPair(const void *a, const void *b, void *binequal)
  * Sort and unique-ify pairs in JsonbValue object
  */
 static void
-uniqueifyJsonbObject(JsonbValue *object, bool unique_keys, bool skip_nulls)
+uniqueifyJsonbObject(JsonbValue *object)
 {
        bool            hasNonUniq = false;
 
@@ -1952,32 +1946,15 @@ uniqueifyJsonbObject(JsonbValue *object, bool unique_keys, bool skip_nulls)
                qsort_arg(object->val.object.pairs, object->val.object.nPairs, sizeof(JsonbPair),
                                  lengthCompareJsonbPair, &hasNonUniq);
 
-       if (hasNonUniq && unique_keys)
-               ereport(ERROR,
-                               (errcode(ERRCODE_DUPLICATE_JSON_OBJECT_KEY_VALUE),
-                                errmsg("duplicate JSON object key value")));
-
-       if (hasNonUniq || skip_nulls)
+       if (hasNonUniq)
        {
-               JsonbPair  *ptr,
-                                  *res;
-
-               while (skip_nulls && object->val.object.nPairs > 0 &&
-                          object->val.object.pairs->value.type == jbvNull)
-               {
-                       /* If skip_nulls is true, remove leading items with null */
-                       object->val.object.pairs++;
-                       object->val.object.nPairs--;
-               }
-
-               ptr = object->val.object.pairs + 1;
-               res = object->val.object.pairs;
+               JsonbPair  *ptr = object->val.object.pairs + 1,
+                                  *res = object->val.object.pairs;
 
                while (ptr - object->val.object.pairs < object->val.object.nPairs)
                {
-                       /* Avoid copying over duplicate or null */
-                       if (lengthCompareJsonbStringValue(ptr, res) != 0 &&
-                               (!skip_nulls || ptr->value.type != jbvNull))
+                       /* Avoid copying over duplicate */
+                       if (lengthCompareJsonbStringValue(ptr, res) != 0)
                        {
                                res++;
                                if (ptr != res)
index 9819e1a45ce63f1f47ecfbb1013c05dc08c6e13e..82c43617d85b38cea4c1db69b08a66037f4b2754 100644 (file)
@@ -2656,11 +2656,11 @@ populate_array_dim_jsonb(PopulateArrayContext *ctx, /* context */
 
        check_stack_depth();
 
-       if (jbv->type != jbvBinary ||
-               !JsonContainerIsArray(jbc) ||
-               JsonContainerIsScalar(jbc))
+       if (jbv->type != jbvBinary || !JsonContainerIsArray(jbc))
                populate_array_report_expected_array(ctx, ndim - 1);
 
+       Assert(!JsonContainerIsScalar(jbc));
+
        it = JsonbIteratorInit(jbc);
 
        tok = JsonbIteratorNext(&it, &val, true);
@@ -3132,51 +3132,6 @@ populate_record_field(ColumnIOData *col,
        }
 }
 
-/* recursively populate specified type from a json/jsonb value */
-Datum
-json_populate_type(Datum json_val, Oid json_type, Oid typid, int32 typmod,
-                                  void **cache, MemoryContext mcxt, bool *isnull)
-{
-       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)
-               *cache = MemoryContextAllocZero(mcxt, sizeof(ColumnIOData));
-
-       return populate_record_field(*cache, typid, typmod, NULL, mcxt,
-                                                                PointerGetDatum(NULL), &jsv, isnull);
-}
-
 static RecordIOData *
 allocate_record_info(MemoryContext mcxt, int ncolumns)
 {
@@ -5566,23 +5521,3 @@ transform_string_values_scalar(void *state, char *token, JsonTokenType tokentype
        else
                appendStringInfoString(_state->strval, token);
 }
-
-JsonTokenType
-json_get_first_token(text *json, bool throw_error)
-{
-       JsonLexContext *lex;
-       JsonParseErrorType result;
-
-       lex = makeJsonLexContext(json, false);
-
-       /* Lex exactly one token from the input and check its type. */
-       result = json_lex(lex);
-
-       if (result == JSON_SUCCESS)
-               return lex->token_type;
-
-       if (throw_error)
-               json_ereport_error(result, lex);
-
-       return JSON_TOKEN_INVALID;      /* invalid json */
-}
index da9df4ae766081f2420f15df22625578604ac47a..91af030095239f562e065d00626b89e30aabceed 100644 (file)
@@ -67,9 +67,7 @@
 #include "lib/stringinfo.h"
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
-#include "nodes/nodeFuncs.h"
 #include "utils/builtins.h"
-#include "utils/formatting.h"
 #include "utils/json.h"
 #include "utils/jsonpath.h"
 
@@ -1079,258 +1077,3 @@ jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from, JsonPathItem *to,
 
        return true;
 }
-
-/* SQL/JSON datatype status: */
-typedef enum JsonPathDatatypeStatus
-{
-       jpdsNonDateTime,                        /* null, bool, numeric, string, array, object */
-       jpdsUnknownDateTime,            /* unknown datetime type */
-       jpdsDateTimeZoned,                      /* timetz, timestamptz */
-       jpdsDateTimeNonZoned            /* time, timestamp, date */
-} JsonPathDatatypeStatus;
-
-/* Context for jspIsMutableWalker() */
-typedef struct JsonPathMutableContext
-{
-       List       *varnames;           /* list of variable names */
-       List       *varexprs;           /* list of variable expressions */
-       JsonPathDatatypeStatus current; /* status of @ item */
-       bool            lax;                    /* jsonpath is lax or strict */
-       bool            mutable;                /* resulting mutability status */
-} JsonPathMutableContext;
-
-/*
- * Recursive walker for jspIsMutable()
- */
-static JsonPathDatatypeStatus
-jspIsMutableWalker(JsonPathItem *jpi, JsonPathMutableContext *cxt)
-{
-       JsonPathItem next;
-       JsonPathDatatypeStatus status = jpdsNonDateTime;
-
-       while (!cxt->mutable)
-       {
-               JsonPathItem arg;
-               JsonPathDatatypeStatus leftStatus;
-               JsonPathDatatypeStatus rightStatus;
-
-               switch (jpi->type)
-               {
-                       case jpiRoot:
-                               Assert(status == jpdsNonDateTime);
-                               break;
-
-                       case jpiCurrent:
-                               Assert(status == jpdsNonDateTime);
-                               status = cxt->current;
-                               break;
-
-                       case jpiFilter:
-                               {
-                                       JsonPathDatatypeStatus prevStatus = cxt->current;
-
-                                       cxt->current = status;
-                                       jspGetArg(jpi, &arg);
-                                       jspIsMutableWalker(&arg, cxt);
-
-                                       cxt->current = prevStatus;
-                                       break;
-                               }
-
-                       case jpiVariable:
-                               {
-                                       int32           len;
-                                       const char *name = jspGetString(jpi, &len);
-                                       ListCell   *lc1;
-                                       ListCell   *lc2;
-
-                                       Assert(status == jpdsNonDateTime);
-
-                                       forboth(lc1, cxt->varnames, lc2, cxt->varexprs)
-                                       {
-                                               String     *varname = lfirst_node(String, lc1);
-                                               Node       *varexpr = lfirst(lc2);
-
-                                               if (strncmp(varname->sval, name, len))
-                                                       continue;
-
-                                               switch (exprType(varexpr))
-                                               {
-                                                       case DATEOID:
-                                                       case TIMEOID:
-                                                       case TIMESTAMPOID:
-                                                               status = jpdsDateTimeNonZoned;
-                                                               break;
-
-                                                       case TIMETZOID:
-                                                       case TIMESTAMPTZOID:
-                                                               status = jpdsDateTimeZoned;
-                                                               break;
-
-                                                       default:
-                                                               status = jpdsNonDateTime;
-                                                               break;
-                                               }
-
-                                               break;
-                                       }
-                                       break;
-                               }
-
-                       case jpiEqual:
-                       case jpiNotEqual:
-                       case jpiLess:
-                       case jpiGreater:
-                       case jpiLessOrEqual:
-                       case jpiGreaterOrEqual:
-                               Assert(status == jpdsNonDateTime);
-                               jspGetLeftArg(jpi, &arg);
-                               leftStatus = jspIsMutableWalker(&arg, cxt);
-
-                               jspGetRightArg(jpi, &arg);
-                               rightStatus = jspIsMutableWalker(&arg, cxt);
-
-                               /*
-                                * Comparison of datetime type with different timezone status
-                                * is mutable.
-                                */
-                               if (leftStatus != jpdsNonDateTime &&
-                                       rightStatus != jpdsNonDateTime &&
-                                       (leftStatus == jpdsUnknownDateTime ||
-                                        rightStatus == jpdsUnknownDateTime ||
-                                        leftStatus != rightStatus))
-                                       cxt->mutable = true;
-                               break;
-
-                       case jpiNot:
-                       case jpiIsUnknown:
-                       case jpiExists:
-                       case jpiPlus:
-                       case jpiMinus:
-                               Assert(status == jpdsNonDateTime);
-                               jspGetArg(jpi, &arg);
-                        &nb