diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index f87afefeae..ee515cec8f 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -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>
diff --git a/doc/src/sgml/keywords/sql2016-02-reserved.txt b/doc/src/sgml/keywords/sql2016-02-reserved.txt
index 7e1a5e4d89..b1bb0776dc 100644
--- a/doc/src/sgml/keywords/sql2016-02-reserved.txt
+++ b/doc/src/sgml/keywords/sql2016-02-reserved.txt
@@ -157,7 +157,6 @@ INTERVAL
 INTO
 IS
 JOIN
-JSON
 JSON_ARRAY
 JSON_ARRAYAGG
 JSON_EXISTS
diff --git a/src/backend/catalog/sql_features.txt b/src/backend/catalog/sql_features.txt
index 0a9c7df4f4..da7c9c772e 100644
--- a/src/backend/catalog/sql_features.txt
+++ b/src/backend/catalog/sql_features.txt
@@ -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	
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index e078456b19..053d2ca5ae 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -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:
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index d0a57c7aae..25a94bbaaa 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -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));
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 636794ca6f..9b9bbf00a9 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -57,31 +57,22 @@
 #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;
-}
diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c
index 691c3e28ce..0db4ed0c2f 100644
--- a/src/backend/executor/nodeTableFuncscan.c
+++ b/src/backend/executor/nodeTableFuncscan.c
@@ -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.
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index bd3965143d..95d0807bdd 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -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;
diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c
index 373471ad27..90ac6b83b5 100644
--- a/src/backend/jit/llvm/llvmjit_types.c
+++ b/src/backend/jit/llvm/llvmjit_types.c
@@ -133,9 +133,6 @@ void	   *referenced_functions[] =
 	ExecEvalSysVar,
 	ExecEvalWholeRowVar,
 	ExecEvalXmlExpr,
-	ExecEvalJsonConstructor,
-	ExecEvalJsonIsPredicate,
-	ExecEvalJson,
 	MakeExpandedObjectReadOnlyInternal,
 	slot_getmissingattrs,
 	slot_getsomeattrs_int,
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 28288dcfc1..c85d8fe975 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -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;
-}
diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index c334daae39..3bac350bf5 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -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));
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 75acea149c..f486d42441 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -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;
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 533df86ff7..5c54171fee 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -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;
 	}
diff --git a/src/backend/parser/Makefile b/src/backend/parser/Makefile
index f4c0cc7f10..9f1c4022bb 100644
--- a/src/backend/parser/Makefile
+++ b/src/backend/parser/Makefile
@@ -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 \
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index b5ab9d9c9a..0492ff9a66 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -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
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index b85fbebd00..061d0bcc50 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -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);
diff --git a/src/backend/parser/parse_collate.c b/src/backend/parser/parse_collate.c
index e90af4c477..7582faabb3 100644
--- a/src/backend/parser/parse_collate.c
+++ b/src/backend/parser/parse_collate.c
@@ -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:
 
 						/*
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index fabb5f7207..7aaf1c673f 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -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
index 3e94071248..0000000000
--- a/src/backend/parser/parse_jsontable.c
+++ /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);
-}
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index f6b740df0a..f44937a8bb 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -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;
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 16a0fe59e2..4e1593d900 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -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;
 	}
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index eee0a29c08..50227cc098 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -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;
 
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index 060fd7e183..2918fdbfb6 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -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)
diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 6f8734a947..26f498b5df 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -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;
-}
diff --git a/src/backend/utils/adt/json.c b/src/backend/utils/adt/json.c
index 5fdb7e32ce..fee2ffb55c 100644
--- a/src/backend/utils/adt/json.c
+++ b/src/backend/utils/adt/json.c
@@ -13,10 +13,7 @@
  */
 #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"
@@ -30,41 +27,20 @@
 #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
+typedef enum					/* type categories for datum_to_json */
 {
-	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
-{
-	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;
+
+	json = PG_GETARG_TEXT_PP(0);
+	lex = makeJsonLexContext(json, false);
 
 	/* Lex exactly one token from the input and check its type. */
-	tok = json_get_first_token(json, true);
-
+	result = json_lex(lex);
+	if (result != JSON_SUCCESS)
+		json_ereport_error(result, lex);
+	tok = lex->token_type;
 	switch (tok)
 	{
 		case JSON_TOKEN_OBJECT_START:
diff --git a/src/backend/utils/adt/jsonb.c b/src/backend/utils/adt/jsonb.c
index f700c5b4c9..88b0000f9a 100644
--- a/src/backend/utils/adt/jsonb.c
+++ b/src/backend/utils/adt/jsonb.c
@@ -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));
-}
diff --git a/src/backend/utils/adt/jsonb_util.c b/src/backend/utils/adt/jsonb_util.c
index 5318eda9cf..60442758b3 100644
--- a/src/backend/utils/adt/jsonb_util.c
+++ b/src/backend/utils/adt/jsonb_util.c
@@ -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)
diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c
index 9819e1a45c..82c43617d8 100644
--- a/src/backend/utils/adt/jsonfuncs.c
+++ b/src/backend/utils/adt/jsonfuncs.c
@@ -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 */
-}
diff --git a/src/backend/utils/adt/jsonpath.c b/src/backend/utils/adt/jsonpath.c
index da9df4ae76..91af030095 100644
--- a/src/backend/utils/adt/jsonpath.c
+++ b/src/backend/utils/adt/jsonpath.c
@@ -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);
-				jspIsMutableWalker(&arg, cxt);
-				break;
-
-			case jpiAnd:
-			case jpiOr:
-			case jpiAdd:
-			case jpiSub:
-			case jpiMul:
-			case jpiDiv:
-			case jpiMod:
-			case jpiStartsWith:
-				Assert(status == jpdsNonDateTime);
-				jspGetLeftArg(jpi, &arg);
-				jspIsMutableWalker(&arg, cxt);
-				jspGetRightArg(jpi, &arg);
-				jspIsMutableWalker(&arg, cxt);
-				break;
-
-			case jpiIndexArray:
-				for (int i = 0; i < jpi->content.array.nelems; i++)
-				{
-					JsonPathItem from;
-					JsonPathItem to;
-
-					if (jspGetArraySubscript(jpi, &from, &to, i))
-						jspIsMutableWalker(&to, cxt);
-
-					jspIsMutableWalker(&from, cxt);
-				}
-				/* FALLTHROUGH */
-
-			case jpiAnyArray:
-				if (!cxt->lax)
-					status = jpdsNonDateTime;
-				break;
-
-			case jpiAny:
-				if (jpi->content.anybounds.first > 0)
-					status = jpdsNonDateTime;
-				break;
-
-			case jpiDatetime:
-				if (jpi->content.arg)
-				{
-					char	   *template;
-					int			flags;
-
-					jspGetArg(jpi, &arg);
-					if (arg.type != jpiString)
-					{
-						status = jpdsNonDateTime;
-						break;	/* there will be runtime error */
-					}
-
-					template = jspGetString(&arg, NULL);
-					flags = datetime_format_flags(template, NULL);
-					if (flags & DCH_ZONED)
-						status = jpdsDateTimeZoned;
-					else
-						status = jpdsDateTimeNonZoned;
-				}
-				else
-				{
-					status = jpdsUnknownDateTime;
-				}
-				break;
-
-			case jpiLikeRegex:
-				Assert(status == jpdsNonDateTime);
-				jspInitByBuffer(&arg, jpi->base, jpi->content.like_regex.expr);
-				jspIsMutableWalker(&arg, cxt);
-				break;
-
-				/* literals */
-			case jpiNull:
-			case jpiString:
-			case jpiNumeric:
-			case jpiBool:
-				/* accessors */
-			case jpiKey:
-			case jpiAnyKey:
-				/* special items */
-			case jpiSubscript:
-			case jpiLast:
-				/* item methods */
-			case jpiType:
-			case jpiSize:
-			case jpiAbs:
-			case jpiFloor:
-			case jpiCeiling:
-			case jpiDouble:
-			case jpiKeyValue:
-				status = jpdsNonDateTime;
-				break;
-		}
-
-		if (!jspGetNext(jpi, &next))
-			break;
-
-		jpi = &next;
-	}
-
-	return status;
-}
-
-/*
- * Check whether jsonpath expression is immutable or not.
- */
-bool
-jspIsMutable(JsonPath *path, List *varnames, List *varexprs)
-{
-	JsonPathMutableContext cxt;
-	JsonPathItem jpi;
-
-	cxt.varnames = varnames;
-	cxt.varexprs = varexprs;
-	cxt.current = jpdsNonDateTime;
-	cxt.lax = (path->header & JSONPATH_LAX) != 0;
-	cxt.mutable = false;
-
-	jspInit(&jpi, path);
-	jspIsMutableWalker(&jpi, &cxt);
-
-	return cxt.mutable;
-}
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 9c381ae727..9f4192e079 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -61,11 +61,9 @@
 
 #include "catalog/pg_collation.h"
 #include "catalog/pg_type.h"
-#include "executor/execExpr.h"
 #include "funcapi.h"
 #include "lib/stringinfo.h"
 #include "miscadmin.h"
-#include "nodes/nodeFuncs.h"
 #include "regex/regex.h"
 #include "utils/builtins.h"
 #include "utils/date.h"
@@ -76,8 +74,6 @@
 #include "utils/guc.h"
 #include "utils/json.h"
 #include "utils/jsonpath.h"
-#include "utils/lsyscache.h"
-#include "utils/memutils.h"
 #include "utils/timestamp.h"
 #include "utils/varlena.h"
 
@@ -90,16 +86,12 @@ typedef struct JsonBaseObjectInfo
 	int			id;
 } JsonBaseObjectInfo;
 
-typedef int (*JsonPathVarCallback) (void *vars, char *varName, int varNameLen,
-									JsonbValue *val, JsonbValue *baseObject);
-
 /*
  * Context of jsonpath execution.
  */
 typedef struct JsonPathExecContext
 {
-	void	   *vars;			/* variables to substitute into jsonpath */
-	JsonPathVarCallback getVar;
+	Jsonb	   *vars;			/* variables to substitute into jsonpath */
 	JsonbValue *root;			/* for $ evaluation */
 	JsonbValue *current;		/* for @ evaluation */
 	JsonBaseObjectInfo baseObject;	/* "base object" for .keyvalue()
@@ -159,59 +151,6 @@ typedef struct JsonValueListIterator
 	ListCell   *next;
 } JsonValueListIterator;
 
-/* Structures for JSON_TABLE execution  */
-typedef struct JsonTableScanState JsonTableScanState;
-typedef struct JsonTableJoinState JsonTableJoinState;
-
-struct JsonTableScanState
-{
-	JsonTableScanState *parent;
-	JsonTableJoinState *nested;
-	MemoryContext mcxt;
-	JsonPath   *path;
-	List	   *args;
-	JsonValueList found;
-	JsonValueListIterator iter;
-	Datum		current;
-	int			ordinal;
-	bool		currentIsNull;
-	bool		outerJoin;
-	bool		errorOnError;
-	bool		advanceNested;
-	bool		reset;
-};
-
-struct JsonTableJoinState
-{
-	union
-	{
-		struct
-		{
-			JsonTableJoinState *left;
-			JsonTableJoinState *right;
-			bool		cross;
-			bool		advanceRight;
-		}			join;
-		JsonTableScanState scan;
-	}			u;
-	bool		is_join;
-};
-
-/* random number to identify JsonTableContext */
-#define JSON_TABLE_CONTEXT_MAGIC	418352867
-
-typedef struct JsonTableContext
-{
-	int			magic;
-	struct
-	{
-		ExprState  *expr;
-		JsonTableScanState *scan;
-	}		   *colexprs;
-	JsonTableScanState root;
-	bool		empty;
-} JsonTableContext;
-
 /* strict/lax flags is decomposed into four [un]wrap/error flags */
 #define jspStrictAbsenseOfErrors(cxt)	(!(cxt)->laxMode)
 #define jspAutoUnwrap(cxt)				((cxt)->laxMode)
@@ -234,8 +173,7 @@ typedef JsonPathBool (*JsonPathPredicateCallback) (JsonPathItem *jsp,
 												   void *param);
 typedef Numeric (*BinaryArithmFunc) (Numeric num1, Numeric num2, bool *error);
 
-static JsonPathExecResult executeJsonPath(JsonPath *path, void *vars,
-										  JsonPathVarCallback getVar,
+static JsonPathExecResult executeJsonPath(JsonPath *path, Jsonb *vars,
 										  Jsonb *json, bool throwErrors,
 										  JsonValueList *result, bool useTz);
 static JsonPathExecResult executeItem(JsonPathExecContext *cxt,
@@ -287,10 +225,7 @@ static JsonPathExecResult appendBoolResult(JsonPathExecContext *cxt,
 static void getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
 							JsonbValue *value);
 static void getJsonPathVariable(JsonPathExecContext *cxt,
-								JsonPathItem *variable, JsonbValue *value);
-static int	getJsonPathVariableFromJsonb(void *varsJsonb, char *varName,
-										 int varNameLen, JsonbValue *val,
-										 JsonbValue *baseObject);
+								JsonPathItem *variable, Jsonb *vars, JsonbValue *value);
 static int	JsonbArraySize(JsonbValue *jb);
 static JsonPathBool executeComparison(JsonPathItem *cmp, JsonbValue *lv,
 									  JsonbValue *rv, void *p);
@@ -302,7 +237,6 @@ static JsonPathExecResult getArrayIndex(JsonPathExecContext *cxt,
 										JsonPathItem *jsp, JsonbValue *jb, int32 *index);
 static JsonBaseObjectInfo setBaseObject(JsonPathExecContext *cxt,
 										JsonbValue *jbv, int32 id);
-static void JsonValueListClear(JsonValueList *jvl);
 static void JsonValueListAppend(JsonValueList *jvl, JsonbValue *jbv);
 static int	JsonValueListLength(const JsonValueList *jvl);
 static bool JsonValueListIsEmpty(JsonValueList *jvl);
@@ -320,12 +254,6 @@ static JsonbValue *wrapItemsInArray(const JsonValueList *items);
 static int	compareDatetime(Datum val1, Oid typid1, Datum val2, Oid typid2,
 							bool useTz, bool *have_error);
 
-
-static JsonTableJoinState *JsonTableInitPlanState(JsonTableContext *cxt,
-												  Node *plan, JsonTableScanState *parent);
-static bool JsonTableNextRow(JsonTableScanState *scan);
-
-
 /****************** User interface to JsonPath executor ********************/
 
 /*
@@ -355,8 +283,7 @@ jsonb_path_exists_internal(FunctionCallInfo fcinfo, bool tz)
 		silent = PG_GETARG_BOOL(3);
 	}
 
-	res = executeJsonPath(jp, vars, getJsonPathVariableFromJsonb,
-						  jb, !silent, NULL, tz);
+	res = executeJsonPath(jp, vars, jb, !silent, NULL, tz);
 
 	PG_FREE_IF_COPY(jb, 0);
 	PG_FREE_IF_COPY(jp, 1);
@@ -411,8 +338,7 @@ jsonb_path_match_internal(FunctionCallInfo fcinfo, bool tz)
 		silent = PG_GETARG_BOOL(3);
 	}
 
-	(void) executeJsonPath(jp, vars, getJsonPathVariableFromJsonb,
-						   jb, !silent, &found, tz);
+	(void) executeJsonPath(jp, vars, jb, !silent, &found, tz);
 
 	PG_FREE_IF_COPY(jb, 0);
 	PG_FREE_IF_COPY(jp, 1);
@@ -490,8 +416,7 @@ jsonb_path_query_internal(FunctionCallInfo fcinfo, bool tz)
 		vars = PG_GETARG_JSONB_P_COPY(2);
 		silent = PG_GETARG_BOOL(3);
 
-		(void) executeJsonPath(jp, vars, getJsonPathVariableFromJsonb,
-							   jb, !silent, &found, tz);
+		(void) executeJsonPath(jp, vars, jb, !silent, &found, tz);
 
 		funcctx->user_fctx = JsonValueListGetList(&found);
 
@@ -538,8 +463,7 @@ jsonb_path_query_array_internal(FunctionCallInfo fcinfo, bool tz)
 	Jsonb	   *vars = PG_GETARG_JSONB_P(2);
 	bool		silent = PG_GETARG_BOOL(3);
 
-	(void) executeJsonPath(jp, vars, getJsonPathVariableFromJsonb,
-						   jb, !silent, &found, tz);
+	(void) executeJsonPath(jp, vars, jb, !silent, &found, tz);
 
 	PG_RETURN_JSONB_P(JsonbValueToJsonb(wrapItemsInArray(&found)));
 }
@@ -570,8 +494,7 @@ jsonb_path_query_first_internal(FunctionCallInfo fcinfo, bool tz)
 	Jsonb	   *vars = PG_GETARG_JSONB_P(2);
 	bool		silent = PG_GETARG_BOOL(3);
 
-	(void) executeJsonPath(jp, vars, getJsonPathVariableFromJsonb,
-						   jb, !silent, &found, tz);
+	(void) executeJsonPath(jp, vars, jb, !silent, &found, tz);
 
 	if (JsonValueListLength(&found) >= 1)
 		PG_RETURN_JSONB_P(JsonbValueToJsonb(JsonValueListHead(&found)));
@@ -613,9 +536,8 @@ jsonb_path_query_first_tz(PG_FUNCTION_ARGS)
  * In other case it tries to find all the satisfied result items.
  */
 static JsonPathExecResult
-executeJsonPath(JsonPath *path, void *vars, JsonPathVarCallback getVar,
-				Jsonb *json, bool throwErrors, JsonValueList *result,
-				bool useTz)
+executeJsonPath(JsonPath *path, Jsonb *vars, Jsonb *json, bool throwErrors,
+				JsonValueList *result, bool useTz)
 {
 	JsonPathExecContext cxt;
 	JsonPathExecResult res;
@@ -627,16 +549,22 @@ executeJsonPath(JsonPath *path, void *vars, JsonPathVarCallback getVar,
 	if (!JsonbExtractScalar(&json->root, &jbv))
 		JsonbInitBinary(&jbv, json);
 
+	if (vars && !JsonContainerIsObject(&vars->root))
+	{
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				 errmsg("\"vars\" argument is not an object"),
+				 errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object.")));
+	}
+
 	cxt.vars = vars;
-	cxt.getVar = getVar;
 	cxt.laxMode = (path->header & JSONPATH_LAX) != 0;
 	cxt.ignoreStructuralErrors = cxt.laxMode;
 	cxt.root = &jbv;
 	cxt.current = &jbv;
 	cxt.baseObject.jbc = NULL;
 	cxt.baseObject.id = 0;
-	/* 1 + number of base objects in vars */
-	cxt.lastGeneratedObjectId = 1 + getVar(vars, NULL, 0, NULL, NULL);
+	cxt.lastGeneratedObjectId = vars ? 2 : 1;
 	cxt.innermostArraySize = -1;
 	cxt.throwErrors = throwErrors;
 	cxt.useTz = useTz;
@@ -2165,7 +2093,7 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
 												 &value->val.string.len);
 			break;
 		case jpiVariable:
-			getJsonPathVariable(cxt, item, value);
+			getJsonPathVariable(cxt, item, cxt->vars, value);
 			return;
 		default:
 			elog(ERROR, "unexpected jsonpath item type");
@@ -2177,63 +2105,42 @@ getJsonPathItem(JsonPathExecContext *cxt, JsonPathItem *item,
  */
 static void
 getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable,
-					JsonbValue *value)
+					Jsonb *vars, JsonbValue *value)
 {
 	char	   *varName;
 	int			varNameLength;
-	JsonbValue	baseObject;
-	int			baseObjectId;
-
-	Assert(variable->type == jpiVariable);
-	varName = jspGetString(variable, &varNameLength);
-
-	if (!cxt->vars ||
-		(baseObjectId = cxt->getVar(cxt->vars, varName, varNameLength, value,
-									&baseObject)) < 0)
-		ereport(ERROR,
-				(errcode(ERRCODE_UNDEFINED_OBJECT),
-				 errmsg("could not find jsonpath variable \"%s\"",
-						pnstrdup(varName, varNameLength))));
-
-	if (baseObjectId > 0)
-		setBaseObject(cxt, &baseObject, baseObjectId);
-}
-
-static int
-getJsonPathVariableFromJsonb(void *varsJsonb, char *varName, int varNameLength,
-							 JsonbValue *value, JsonbValue *baseObject)
-{
-	Jsonb	   *vars = varsJsonb;
 	JsonbValue	tmp;
 	JsonbValue *v;
 
-	if (!varName)
+	if (!vars)
 	{
-		if (vars && !JsonContainerIsObject(&vars->root))
-		{
-			ereport(ERROR,
-					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-					 errmsg("\"vars\" argument is not an object"),
-					 errdetail("Jsonpath parameters should be encoded as key-value pairs of \"vars\" object.")));
-		}
-
-		return vars ? 1 : 0;	/* count of base objects */
+		value->type = jbvNull;
+		return;
 	}
 
+	Assert(variable->type == jpiVariable);
+	varName = jspGetString(variable, &varNameLength);
 	tmp.type = jbvString;
 	tmp.val.string.val = varName;
 	tmp.val.string.len = varNameLength;
 
 	v = findJsonbValueFromContainer(&vars->root, JB_FOBJECT, &tmp);
 
-	if (!v)
-		return -1;
+	if (v)
+	{
+		*value = *v;
+		pfree(v);
+	}
+	else
+	{
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("could not find jsonpath variable \"%s\"",
+						pnstrdup(varName, varNameLength))));
+	}
 
-	*value = *v;
-	pfree(v);
-
-	JsonbInitBinary(baseObject, vars);
-	return 1;
+	JsonbInitBinary(&tmp, vars);
+	setBaseObject(cxt, &tmp, 1);
 }
 
 /**************** Support functions for JsonPath execution *****************/
@@ -2522,13 +2429,6 @@ setBaseObject(JsonPathExecContext *cxt, JsonbValue *jbv, int32 id)
 	return baseObject;
 }
 
-static void
-JsonValueListClear(JsonValueList *jvl)
-{
-	jvl->singleton = NULL;
-	jvl->list = NULL;
-}
-
 static void
 JsonValueListAppend(JsonValueList *jvl, JsonbValue *jbv)
 {
@@ -2897,667 +2797,3 @@ compareDatetime(Datum val1, Oid typid1, Datum val2, Oid typid2,
 
 	return DatumGetInt32(DirectFunctionCall2(cmpfunc, val1, val2));
 }
-
-/********************Interface to pgsql's executor***************************/
-
-bool
-JsonPathExists(Datum jb, JsonPath *jp, List *vars, bool *error)
-{
-	JsonPathExecResult res = executeJsonPath(jp, vars, EvalJsonPathVar,
-											 DatumGetJsonbP(jb), !error, NULL,
-											 true);
-
-	Assert(error || !jperIsError(res));
-
-	if (error && jperIsError(res))
-		*error = true;
-
-	return res == jperOk;
-}
-
-Datum
-JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper, bool *empty,
-			  bool *error, List *vars)
-{
-	JsonbValue *first;
-	bool		wrap;
-	JsonValueList found = {0};
-	JsonPathExecResult res PG_USED_FOR_ASSERTS_ONLY;
-	int			count;
-
-	res = executeJsonPath(jp, vars, EvalJsonPathVar, DatumGetJsonbP(jb), !error,
-						  &found, true);
-
-	Assert(error || !jperIsError(res));
-
-	if (error && jperIsError(res))
-	{
-		*error = true;
-		*empty = false;
-		return (Datum) 0;
-	}
-
-	count = JsonValueListLength(&found);
-
-	first = count ? JsonValueListHead(&found) : NULL;
-
-	if (!first)
-		wrap = false;
-	else if (wrapper == JSW_NONE)
-		wrap = false;
-	else if (wrapper == JSW_UNCONDITIONAL)
-		wrap = true;
-	else if (wrapper == JSW_CONDITIONAL)
-		wrap = count > 1 ||
-			IsAJsonbScalar(first) ||
-			(first->type == jbvBinary &&
-			 JsonContainerIsScalar(first->val.binary.data));
-	else
-	{
-		elog(ERROR, "unrecognized json wrapper %d", wrapper);
-		wrap = false;
-	}
-
-	if (wrap)
-		return JsonbPGetDatum(JsonbValueToJsonb(wrapItemsInArray(&found)));
-
-	if (count > 1)
-	{
-		if (error)
-		{
-			*error = true;
-			return (Datum) 0;
-		}
-
-		ereport(ERROR,
-				(errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
-				 errmsg("JSON path expression in JSON_QUERY should return "
-						"singleton item without wrapper"),
-				 errhint("Use WITH WRAPPER clause to wrap SQL/JSON item "
-						 "sequence into array.")));
-	}
-
-	if (first)
-		return JsonbPGetDatum(JsonbValueToJsonb(first));
-
-	*empty = true;
-	return PointerGetDatum(NULL);
-}
-
-JsonbValue *
-JsonPathValue(Datum jb, JsonPath *jp, bool *empty, bool *error, List *vars)
-{
-	JsonbValue *res;
-	JsonValueList found = {0};
-	JsonPathExecResult jper PG_USED_FOR_ASSERTS_ONLY;
-	int			count;
-
-	jper = executeJsonPath(jp, vars, EvalJsonPathVar, DatumGetJsonbP(jb), !error,
-						   &found, true);
-
-	Assert(error || !jperIsError(jper));
-
-	if (error && jperIsError(jper))
-	{
-		*error = true;
-		*empty = false;
-		return NULL;
-	}
-
-	count = JsonValueListLength(&found);
-
-	*empty = !count;
-
-	if (*empty)
-		return NULL;
-
-	if (count > 1)
-	{
-		if (error)
-		{
-			*error = true;
-			return NULL;
-		}
-
-		ereport(ERROR,
-				(errcode(ERRCODE_MORE_THAN_ONE_SQL_JSON_ITEM),
-				 errmsg("JSON path expression in JSON_VALUE should return "
-						"singleton scalar item")));
-	}
-
-	res = JsonValueListHead(&found);
-
-	if (res->type == jbvBinary &&
-		JsonContainerIsScalar(res->val.binary.data))
-		JsonbExtractScalar(res->val.binary.data, res);
-
-	if (!IsAJsonbScalar(res))
-	{
-		if (error)
-		{
-			*error = true;
-			return NULL;
-		}
-
-		ereport(ERROR,
-				(errcode(ERRCODE_SQL_JSON_SCALAR_REQUIRED),
-				 errmsg("JSON path expression in JSON_VALUE should return "
-						"singleton scalar item")));
-	}
-
-	if (res->type == jbvNull)
-		return NULL;
-
-	return res;
-}
-
-static void
-JsonbValueInitNumericDatum(JsonbValue *jbv, Datum num)
-{
-	jbv->type = jbvNumeric;
-	jbv->val.numeric = DatumGetNumeric(num);
-}
-
-void
-JsonItemFromDatum(Datum val, Oid typid, int32 typmod, JsonbValue *res)
-{
-	switch (typid)
-	{
-		case BOOLOID:
-			res->type = jbvBool;
-			res->val.boolean = DatumGetBool(val);
-			break;
-		case NUMERICOID:
-			JsonbValueInitNumericDatum(res, val);
-			break;
-		case INT2OID:
-			JsonbValueInitNumericDatum(res, DirectFunctionCall1(int2_numeric, val));
-			break;
-		case INT4OID:
-			JsonbValueInitNumericDatum(res, DirectFunctionCall1(int4_numeric, val));
-			break;
-		case INT8OID:
-			JsonbValueInitNumericDatum(res, DirectFunctionCall1(int8_numeric, val));
-			break;
-		case FLOAT4OID:
-			JsonbValueInitNumericDatum(res, DirectFunctionCall1(float4_numeric, val));
-			break;
-		case FLOAT8OID:
-			JsonbValueInitNumericDatum(res, DirectFunctionCall1(float8_numeric, val));
-			break;
-		case TEXTOID:
-		case VARCHAROID:
-			res->type = jbvString;
-			res->val.string.val = VARDATA_ANY(val);
-			res->val.string.len = VARSIZE_ANY_EXHDR(val);
-			break;
-		case DATEOID:
-		case TIMEOID:
-		case TIMETZOID:
-		case TIMESTAMPOID:
-		case TIMESTAMPTZOID:
-			res->type = jbvDatetime;
-			res->val.datetime.value = val;
-			res->val.datetime.typid = typid;
-			res->val.datetime.typmod = typmod;
-			res->val.datetime.tz = 0;
-			break;
-		case JSONBOID:
-			{
-				JsonbValue *jbv = res;
-				Jsonb	   *jb = DatumGetJsonbP(val);
-
-				if (JsonContainerIsScalar(&jb->root))
-				{
-					bool		result PG_USED_FOR_ASSERTS_ONLY;
-
-					result = JsonbExtractScalar(&jb->root, jbv);
-					Assert(result);
-				}
-				else
-					JsonbInitBinary(jbv, jb);
-				break;
-			}
-		case JSONOID:
-			{
-				text	   *txt = DatumGetTextP(val);
-				char	   *str = text_to_cstring(txt);
-				Jsonb	   *jb =
-				DatumGetJsonbP(DirectFunctionCall1(jsonb_in,
-												   CStringGetDatum(str)));
-
-				pfree(str);
-
-				JsonItemFromDatum(JsonbPGetDatum(jb), JSONBOID, -1, res);
-				break;
-			}
-		default:
-			ereport(ERROR,
-					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-					 errmsg("only bool, numeric, and text types could be "
-							"casted to supported jsonpath types.")));
-	}
-}
-
-/************************ JSON_TABLE functions ***************************/
-
-/*
- * Returns private data from executor state. Ensure validity by check with
- * MAGIC number.
- */
-static inline JsonTableContext *
-GetJsonTableContext(TableFuncScanState *state, const char *fname)
-{
-	JsonTableContext *result;
-
-	if (!IsA(state, TableFuncScanState))
-		elog(ERROR, "%s called with invalid TableFuncScanState", fname);
-	result = (JsonTableContext *) state->opaque;
-	if (result->magic != JSON_TABLE_CONTEXT_MAGIC)
-		elog(ERROR, "%s called with invalid TableFuncScanState", fname);
-
-	return result;
-}
-
-/* Recursively initialize JSON_TABLE scan state */
-static void
-JsonTableInitScanState(JsonTableContext *cxt, JsonTableScanState *scan,
-					   JsonTableParent *node, JsonTableScanState *parent,
-					   List *args, MemoryContext mcxt)
-{
-	int			i;
-
-	scan->parent = parent;
-	scan->outerJoin = node->outerJoin;
-	scan->errorOnError = node->errorOnError;
-	scan->path = DatumGetJsonPathP(node->path->constvalue);
-	scan->args = args;
-	scan->mcxt = AllocSetContextCreate(mcxt, "JsonTableContext",
-									   ALLOCSET_DEFAULT_SIZES);
-	scan->nested = node->child ?
-		JsonTableInitPlanState(cxt, node->child, scan) : NULL;
-	scan->current = PointerGetDatum(NULL);
-	scan->currentIsNull = true;
-
-	for (i = node->colMin; i <= node->colMax; i++)
-		cxt->colexprs[i].scan = scan;
-}
-
-/* Recursively initialize JSON_TABLE scan state */
-static JsonTableJoinState *
-JsonTableInitPlanState(JsonTableContext *cxt, Node *plan,
-					   JsonTableScanState *parent)
-{
-	JsonTableJoinState *state = palloc0(sizeof(*state));
-
-	if (IsA(plan, JsonTableSibling))
-	{
-		JsonTableSibling *join = castNode(JsonTableSibling, plan);
-
-		state->is_join = true;
-		state->u.join.cross = join->cross;
-		state->u.join.left = JsonTableInitPlanState(cxt, join->larg, parent);
-		state->u.join.right = JsonTableInitPlanState(cxt, join->rarg, parent);
-	}
-	else
-	{
-		JsonTableParent *node = castNode(JsonTableParent, plan);
-
-		state->is_join = false;
-
-		JsonTableInitScanState(cxt, &state->u.scan, node, parent,
-							   parent->args, parent->mcxt);
-	}
-
-	return state;
-}
-
-/*
- * JsonTableInitOpaque
- *		Fill in TableFuncScanState->opaque for JsonTable processor
- */
-static void
-JsonTableInitOpaque(TableFuncScanState *state, int natts)
-{
-	JsonTableContext *cxt;
-	PlanState  *ps = &state->ss.ps;
-	TableFuncScan *tfs = castNode(TableFuncScan, ps->plan);
-	TableFunc  *tf = tfs->tablefunc;
-	JsonExpr   *ci = castNode(JsonExpr, tf->docexpr);
-	JsonTableParent *root = castNode(JsonTableParent, tf->plan);
-	List	   *args = NIL;
-	ListCell   *lc;
-	int			i;
-
-	cxt = palloc0(sizeof(JsonTableContext));
-	cxt->magic = JSON_TABLE_CONTEXT_MAGIC;
-
-	if (ci->passing_values)
-	{
-		ListCell   *exprlc;
-		ListCell   *namelc;
-
-		forboth(exprlc, ci->passing_values,
-				namelc, ci->passing_names)
-		{
-			Expr	   *expr = (Expr *) lfirst(exprlc);
-			String	   *name = lfirst_node(String, namelc);
-			JsonPathVariableEvalContext *var = palloc(sizeof(*var));
-
-			var->name = pstrdup(name->sval);
-			var->typid = exprType((Node *) expr);
-			var->typmod = exprTypmod((Node *) expr);
-			var->estate = ExecInitExpr(expr, ps);
-			var->econtext = ps->ps_ExprContext;
-			var->mcxt = CurrentMemoryContext;
-			var->evaluated = false;
-			var->value = (Datum) 0;
-			var->isnull = true;
-
-			args = lappend(args, var);
-		}
-	}
-
-	cxt->colexprs = palloc(sizeof(*cxt->colexprs) *
-						   list_length(tf->colvalexprs));
-
-	JsonTableInitScanState(cxt, &cxt->root, root, NULL, args,
-						   CurrentMemoryContext);
-
-	i = 0;
-
-	foreach(lc, tf->colvalexprs)
-	{
-		Expr	   *expr = lfirst(lc);
-
-		cxt->colexprs[i].expr =
-			ExecInitExprWithCaseValue(expr, ps,
-									  &cxt->colexprs[i].scan->current,
-									  &cxt->colexprs[i].scan->currentIsNull);
-
-		i++;
-	}
-
-	state->opaque = cxt;
-}
-
-/* Reset scan iterator to the beginning of the item list */
-static void
-JsonTableRescan(JsonTableScanState *scan)
-{
-	JsonValueListInitIterator(&scan->found, &scan->iter);
-	scan->current = PointerGetDatum(NULL);
-	scan->currentIsNull = true;
-	scan->advanceNested = false;
-	scan->ordinal = 0;
-}
-
-/* Reset context item of a scan, execute JSON path and reset a scan */
-static void
-JsonTableResetContextItem(JsonTableScanState *scan, Datum item)
-{
-	MemoryContext oldcxt;
-	JsonPathExecResult res;
-	Jsonb	   *js = (Jsonb *) DatumGetJsonbP(item);
-
-	JsonValueListClear(&scan->found);
-
-	MemoryContextResetOnly(scan->mcxt);
-
-	oldcxt = MemoryContextSwitchTo(scan->mcxt);
-
-	res = executeJsonPath(scan->path, scan->args, EvalJsonPathVar, js,
-						  scan->errorOnError, &scan->found, false /* FIXME */ );
-
-	MemoryContextSwitchTo(oldcxt);
-
-	if (jperIsError(res))
-	{
-		Assert(!scan->errorOnError);
-		JsonValueListClear(&scan->found);	/* EMPTY ON ERROR case */
-	}
-
-	JsonTableRescan(scan);
-}
-
-/*
- * JsonTableSetDocument
- *		Install the input document
- */
-static void
-JsonTableSetDocument(TableFuncScanState *state, Datum value)
-{
-	JsonTableContext *cxt = GetJsonTableContext(state, "JsonTableSetDocument");
-
-	JsonTableResetContextItem(&cxt->root, value);
-}
-
-/* Recursively reset scan and its child nodes */
-static void
-JsonTableRescanRecursive(JsonTableJoinState *state)
-{
-	if (state->is_join)
-	{
-		JsonTableRescanRecursive(state->u.join.left);
-		JsonTableRescanRecursive(state->u.join.right);
-		state->u.join.advanceRight = false;
-	}
-	else
-	{
-		JsonTableRescan(&state->u.scan);
-		if (state->u.scan.nested)
-			JsonTableRescanRecursive(state->u.scan.nested);
-	}
-}
-
-/*
- * Fetch next row from a cross/union joined scan.
- *
- * Returns false at the end of a scan, true otherwise.
- */
-static bool
-JsonTableNextJoinRow(JsonTableJoinState *state)
-{
-	if (!state->is_join)
-		return JsonTableNextRow(&state->u.scan);
-
-	if (state->u.join.advanceRight)
-	{
-		/* fetch next inner row */
-		if (JsonTableNextJoinRow(state->u.join.right))
-			return true;
-
-		/* inner rows are exhausted */
-		if (state->u.join.cross)
-			state->u.join.advanceRight = false; /* next outer row */
-		else
-			return false;		/* end of scan */
-	}
-
-	while (!state->u.join.advanceRight)
-	{
-		/* fetch next outer row */
-		bool		left = JsonTableNextJoinRow(state->u.join.left);
-
-		if (state->u.join.cross)
-		{
-			if (!left)
-				return false;	/* end of scan */
-
-			JsonTableRescanRecursive(state->u.join.right);
-
-			if (!JsonTableNextJoinRow(state->u.join.right))
-				continue;		/* next outer row */
-
-			state->u.join.advanceRight = true;	/* next inner row */
-		}
-		else if (!left)
-		{
-			if (!JsonTableNextJoinRow(state->u.join.right))
-				return false;	/* end of scan */
-
-			state->u.join.advanceRight = true;	/* next inner row */
-		}
-
-		break;
-	}
-
-	return true;
-}
-
-/* Recursively set 'reset' flag of scan and its child nodes */
-static void
-JsonTableJoinReset(JsonTableJoinState *state)
-{
-	if (state->is_join)
-	{
-		JsonTableJoinReset(state->u.join.left);
-		JsonTableJoinReset(state->u.join.right);
-		state->u.join.advanceRight = false;
-	}
-	else
-	{
-		state->u.scan.reset = true;
-		state->u.scan.advanceNested = false;
-
-		if (state->u.scan.nested)
-			JsonTableJoinReset(state->u.scan.nested);
-	}
-}
-
-/*
- * Fetch next row from a simple scan with outer/inner joined nested subscans.
- *
- * Returns false at the end of a scan, true otherwise.
- */
-static bool
-JsonTableNextRow(JsonTableScanState *scan)
-{
-	/* reset context item if requested */
-	if (scan->reset)
-	{
-		Assert(!scan->parent->currentIsNull);
-		JsonTableResetContextItem(scan, scan->parent->current);
-		scan->reset = false;
-	}
-
-	if (scan->advanceNested)
-	{
-		/* fetch next nested row */
-		scan->advanceNested = JsonTableNextJoinRow(scan->nested);
-
-		if (scan->advanceNested)
-			return true;
-	}
-
-	for (;;)
-	{
-		/* fetch next row */
-		JsonbValue *jbv = JsonValueListNext(&scan->found, &scan->iter);
-		MemoryContext oldcxt;
-
-		if (!jbv)
-		{
-			scan->current = PointerGetDatum(NULL);
-			scan->currentIsNull = true;
-			return false;		/* end of scan */
-		}
-
-		/* set current row item */
-		oldcxt = MemoryContextSwitchTo(scan->mcxt);
-		scan->current = JsonbPGetDatum(JsonbValueToJsonb(jbv));
-		scan->currentIsNull = false;
-		MemoryContextSwitchTo(oldcxt);
-
-		scan->ordinal++;
-
-		if (!scan->nested)
-			break;
-
-		JsonTableJoinReset(scan->nested);
-
-		scan->advanceNested = JsonTableNextJoinRow(scan->nested);
-
-		if (scan->advanceNested || scan->outerJoin)
-			break;
-	}
-
-	return true;
-}
-
-/*
- * JsonTableFetchRow
- *		Prepare the next "current" tuple for upcoming GetValue calls.
- *		Returns FALSE if the row-filter expression returned no more rows.
- */
-static bool
-JsonTableFetchRow(TableFuncScanState *state)
-{
-	JsonTableContext *cxt = GetJsonTableContext(state, "JsonTableFetchRow");
-
-	if (cxt->empty)
-		return false;
-
-	return JsonTableNextRow(&cxt->root);
-}
-
-/*
- * JsonTableGetValue
- *		Return the value for column number 'colnum' for the current row.
- *
- * This leaks memory, so be sure to reset often the context in which it's
- * called.
- */
-static Datum
-JsonTableGetValue(TableFuncScanState *state, int colnum,
-				  Oid typid, int32 typmod, bool *isnull)
-{
-	JsonTableContext *cxt = GetJsonTableContext(state, "JsonTableGetValue");
-	ExprContext *econtext = state->ss.ps.ps_ExprContext;
-	ExprState  *estate = cxt->colexprs[colnum].expr;
-	JsonTableScanState *scan = cxt->colexprs[colnum].scan;
-	Datum		result;
-
-	if (scan->currentIsNull)	/* NULL from outer/union join */
-	{
-		result = (Datum) 0;
-		*isnull = true;
-	}
-	else if (estate)			/* regular column */
-	{
-		result = ExecEvalExpr(estate, econtext, isnull);
-	}
-	else
-	{
-		result = Int32GetDatum(scan->ordinal);	/* ordinality column */
-		*isnull = false;
-	}
-
-	return result;
-}
-
-/*
- * JsonTableDestroyOpaque
- */
-static void
-JsonTableDestroyOpaque(TableFuncScanState *state)
-{
-	JsonTableContext *cxt = GetJsonTableContext(state, "JsonTableDestroyOpaque");
-
-	/* not valid anymore */
-	cxt->magic = 0;
-
-	state->opaque = NULL;
-}
-
-const TableFuncRoutine JsonbTableRoutine =
-{
-	JsonTableInitOpaque,
-	JsonTableSetDocument,
-	NULL,
-	NULL,
-	NULL,
-	JsonTableFetchRow,
-	JsonTableGetValue,
-	JsonTableDestroyOpaque
-};
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 9959f6910e..6594a9aac7 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -466,12 +466,6 @@ static void get_coercion_expr(Node *arg, deparse_context *context,
 							  Node *parentNode);
 static void get_const_expr(Const *constval, deparse_context *context,
 						   int showtype);
-static void get_json_constructor(JsonConstructorExpr *ctor,
-								 deparse_context *context, bool showimplicit);
-static void get_json_agg_constructor(JsonConstructorExpr *ctor,
-									 deparse_context *context,
-									 const char *funcname,
-									 bool is_json_objectagg);
 static void get_const_collation(Const *constval, deparse_context *context);
 static void simple_quote_literal(StringInfo buf, const char *val);
 static void get_sublink_expr(SubLink *sublink, deparse_context *context);
@@ -505,10 +499,6 @@ static char *generate_qualified_type_name(Oid typid);
 static text *string_to_text(char *str);
 static char *flatten_reloptions(Oid relid);
 static void get_reloptions(StringInfo buf, Datum reloptions);
-static void get_json_path_spec(Node *path_spec, deparse_context *context,
-							   bool showimplicit);
-static void get_json_table_columns(TableFunc *tf, JsonTableParent *node,
-								   deparse_context *context, bool showimplicit);
 
 #define only_marker(rte)  ((rte)->inh ? "" : "ONLY ")
 
@@ -6338,8 +6328,7 @@ get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno,
 		bool		need_paren = (PRETTY_PAREN(context)
 								  || IsA(expr, FuncExpr)
 								  || IsA(expr, Aggref)
-								  || IsA(expr, WindowFunc)
-								  || IsA(expr, JsonConstructorExpr));
+								  || IsA(expr, WindowFunc));
 
 		if (need_paren)
 			appendStringInfoChar(context->buf, '(');
@@ -8198,8 +8187,6 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
 		case T_GroupingFunc:
 		case T_WindowFunc:
 		case T_FuncExpr:
-		case T_JsonConstructorExpr:
-		case T_JsonExpr:
 			/* function-like: name(..) or name[..] */
 			return true;
 
@@ -8293,7 +8280,6 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
 		case T_NullTest:
 		case T_BooleanTest:
 		case T_DistinctExpr:
-		case T_JsonIsPredicate:
 			switch (nodeTag(parentNode))
 			{
 				case T_FuncExpr:
@@ -8318,7 +8304,6 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
 				case T_GroupingFunc:	/* own parentheses */
 				case T_WindowFunc:	/* own parentheses */
 				case T_CaseExpr:	/* other separators */
-				case T_JsonExpr:	/* own parentheses */
 					return true;
 				default:
 					return false;
@@ -8375,11 +8360,6 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
 					return false;
 			}
 
-		case T_JsonValueExpr:
-			/* maybe simple, check args */
-			return isSimpleNode((Node *) ((JsonValueExpr *) node)->raw_expr,
-								node, prettyFlags);
-
 		default:
 			break;
 	}
@@ -8486,122 +8466,6 @@ get_rule_expr_paren(Node *node, deparse_context *context,
 }
 
 
-/*
- * get_json_path_spec		- Parse back a JSON path specification
- */
-static void
-get_json_path_spec(Node *path_spec, deparse_context *context, bool showimplicit)
-{
-	if (IsA(path_spec, Const))
-		get_const_expr((Const *) path_spec, context, -1);
-	else
-		get_rule_expr(path_spec, context, showimplicit);
-}
-
-/*
- * get_json_format			- Parse back a JsonFormat node
- */
-static void
-get_json_format(JsonFormat *format, StringInfo buf)
-{
-	if (format->format_type == JS_FORMAT_DEFAULT)
-		return;
-
-	appendStringInfoString(buf,
-						   format->format_type == JS_FORMAT_JSONB ?
-						   " FORMAT JSONB" : " FORMAT JSON");
-
-	if (format->encoding != JS_ENC_DEFAULT)
-	{
-		const char *encoding =
-		format->encoding == JS_ENC_UTF16 ? "UTF16" :
-		format->encoding == JS_ENC_UTF32 ? "UTF32" : "UTF8";
-
-		appendStringInfo(buf, " ENCODING %s", encoding);
-	}
-}
-
-/*
- * get_json_returning		- Parse back a JsonReturning structure
- */
-static void
-get_json_returning(JsonReturning *returning, StringInfo buf,
-				   bool json_format_by_default)
-{
-	if (!OidIsValid(returning->typid))
-		return;
-
-	appendStringInfo(buf, " RETURNING %s",
-					 format_type_with_typemod(returning->typid,
-											  returning->typmod));
-
-	if (!json_format_by_default ||
-		returning->format->format_type !=
-		(returning->typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON))
-		get_json_format(returning->format, buf);
-}
-
-static void
-get_json_behavior(JsonBehavior *behavior, deparse_context *context,
-				  const char *on)
-{
-	/*
-	 * The order of array elements must correspond to the order of
-	 * JsonBehaviorType members.
-	 */
-	const char *behavior_names[] =
-	{
-		" NULL",
-		" ERROR",
-		" EMPTY",
-		" TRUE",
-		" FALSE",
-		" UNKNOWN",
-		" EMPTY ARRAY",
-		" EMPTY OBJECT",
-		" DEFAULT "
-	};
-
-	if ((int) behavior->btype < 0 || behavior->btype >= lengthof(behavior_names))
-		elog(ERROR, "invalid json behavior type: %d", behavior->btype);
-
-	appendStringInfoString(context->buf, behavior_names[behavior->btype]);
-
-	if (behavior->btype == JSON_BEHAVIOR_DEFAULT)
-		get_rule_expr(behavior->default_expr, context, false);
-
-	appendStringInfo(context->buf, " ON %s", on);
-}
-
-/*
- * get_json_expr_options
- *
- * Parse back common options for JSON_QUERY, JSON_VALUE, JSON_EXISTS and
- * JSON_TABLE columns.
- */
-static void
-get_json_expr_options(JsonExpr *jsexpr, deparse_context *context,
-					  JsonBehaviorType default_behavior)
-{
-	if (jsexpr->op == JSON_QUERY_OP)
-	{
-		if (jsexpr->wrapper == JSW_CONDITIONAL)
-			appendStringInfo(context->buf, " WITH CONDITIONAL WRAPPER");
-		else if (jsexpr->wrapper == JSW_UNCONDITIONAL)
-			appendStringInfo(context->buf, " WITH UNCONDITIONAL WRAPPER");
-
-		if (jsexpr->omit_quotes)
-			appendStringInfo(context->buf, " OMIT QUOTES");
-	}
-
-	if (jsexpr->op != JSON_EXISTS_OP &&
-		jsexpr->on_empty->btype != default_behavior)
-		get_json_behavior(jsexpr->on_empty, context, "EMPTY");
-
-	if (jsexpr->on_error->btype != default_behavior)
-		get_json_behavior(jsexpr->on_error, context, "ERROR");
-}
-
 /* ----------
  * get_rule_expr			- Parse back an expression
  *
@@ -9760,116 +9624,6 @@ get_rule_expr(Node *node, deparse_context *context,
 			}
 			break;
 
-
-		case T_JsonValueExpr:
-			{
-				JsonValueExpr *jve = (JsonValueExpr *) node;
-
-				get_rule_expr((Node *) jve->raw_expr, context, false);
-				get_json_format(jve->format, context->buf);
-			}
-			break;
-
-		case T_JsonConstructorExpr:
-			get_json_constructor((JsonConstructorExpr *) node, context, false);
-			break;
-
-		case T_JsonIsPredicate:
-			{
-				JsonIsPredicate *pred = (JsonIsPredicate *) node;
-
-				if (!PRETTY_PAREN(context))
-					appendStringInfoChar(context->buf, '(');
-
-				get_rule_expr_paren(pred->expr, context, true, node);
-
-				appendStringInfoString(context->buf, " IS JSON");
-
-				/* TODO: handle FORMAT clause */
-
-				switch (pred->item_type)
-				{
-					case JS_TYPE_SCALAR:
-						appendStringInfoString(context->buf, " SCALAR");
-						break;
-					case JS_TYPE_ARRAY:
-						appendStringInfoString(context->buf, " ARRAY");
-						break;
-					case JS_TYPE_OBJECT:
-						appendStringInfoString(context->buf, " OBJECT");
-						break;
-					default:
-						break;
-				}
-
-				if (pred->unique_keys)
-					appendStringInfoString(context->buf, " WITH UNIQUE KEYS");
-
-				if (!PRETTY_PAREN(context))
-					appendStringInfoChar(context->buf, ')');
-			}
-			break;
-
-		case T_JsonExpr:
-			{
-				JsonExpr   *jexpr = (JsonExpr *) node;
-
-				switch (jexpr->op)
-				{
-					case JSON_QUERY_OP:
-						appendStringInfoString(buf, "JSON_QUERY(");
-						break;
-					case JSON_VALUE_OP:
-						appendStringInfoString(buf, "JSON_VALUE(");
-						break;
-					case JSON_EXISTS_OP:
-						appendStringInfoString(buf, "JSON_EXISTS(");
-						break;
-					default:
-						elog(ERROR, "unexpected JsonExpr type: %d", jexpr->op);
-						break;
-				}
-
-				get_rule_expr(jexpr->formatted_expr, context, showimplicit);
-
-				appendStringInfoString(buf, ", ");
-
-				get_json_path_spec(jexpr->path_spec, context, showimplicit);
-
-				if (jexpr->passing_values)
-				{
-					ListCell   *lc1,
-							   *lc2;
-					bool		needcomma = false;
-
-					appendStringInfoString(buf, " PASSING ");
-
-					forboth(lc1, jexpr->passing_names,
-							lc2, jexpr->passing_values)
-					{
-						if (needcomma)
-							appendStringInfoString(buf, ", ");
-						needcomma = true;
-
-						get_rule_expr((Node *) lfirst(lc2), context, showimplicit);
-						appendStringInfo(buf, " AS %s",
-										 ((String *) lfirst_node(String, lc1))->sval);
-					}
-				}
-
-				if (jexpr->op != JSON_EXISTS_OP ||
-					jexpr->returning->typid != BOOLOID)
-					get_json_returning(jexpr->returning, context->buf,
-									   jexpr->op == JSON_QUERY_OP);
-
-				get_json_expr_options(jexpr, context,
-									  jexpr->op == JSON_EXISTS_OP ?
-									  JSON_BEHAVIOR_FALSE : JSON_BEHAVIOR_NULL);
-
-				appendStringInfoString(buf, ")");
-			}
-			break;
-
 		case T_List:
 			{
 				char	   *sep;
@@ -9993,7 +9747,6 @@ looks_like_function(Node *node)
 		case T_MinMaxExpr:
 		case T_SQLValueFunction:
 		case T_XmlExpr:
-		case T_JsonExpr:
 			/* these are all accepted by func_expr_common_subexpr */
 			return true;
 		default:
@@ -10139,103 +9892,17 @@ get_func_expr(FuncExpr *expr, deparse_context *context,
 	appendStringInfoChar(buf, ')');
 }
 
-static void
-get_json_constructor_options(JsonConstructorExpr *ctor, StringInfo buf)
-{
-	if (ctor->absent_on_null)
-	{
-		if (ctor->type == JSCTOR_JSON_OBJECT ||
-			ctor->type == JSCTOR_JSON_OBJECTAGG)
-			appendStringInfoString(buf, " ABSENT ON NULL");
-	}
-	else
-	{
-		if (ctor->type == JSCTOR_JSON_ARRAY ||
-			ctor->type == JSCTOR_JSON_ARRAYAGG)
-			appendStringInfoString(buf, " NULL ON NULL");
-	}
-
-	if (ctor->unique)
-		appendStringInfoString(buf, " WITH UNIQUE KEYS");
-
-	if (!((ctor->type == JSCTOR_JSON_PARSE ||
-		   ctor->type == JSCTOR_JSON_SCALAR) &&
-		  ctor->returning->typid == JSONOID))
-		get_json_returning(ctor->returning, buf, true);
-}
-
-static void
-get_json_constructor(JsonConstructorExpr *ctor, deparse_context *context,
-					 bool showimplicit)
-{
-	StringInfo	buf = context->buf;
-	const char *funcname;
-	int			nargs;
-	ListCell   *lc;
-
-	switch (ctor->type)
-	{
-		case JSCTOR_JSON_PARSE:
-			funcname = "JSON";
-			break;
-		case JSCTOR_JSON_SCALAR:
-			funcname = "JSON_SCALAR";
-			break;
-		case JSCTOR_JSON_SERIALIZE:
-			funcname = "JSON_SERIALIZE";
-			break;
-		case JSCTOR_JSON_OBJECT:
-			funcname = "JSON_OBJECT";
-			break;
-		case JSCTOR_JSON_ARRAY:
-			funcname = "JSON_ARRAY";
-			break;
-		case JSCTOR_JSON_OBJECTAGG:
-			get_json_agg_constructor(ctor, context, "JSON_OBJECTAGG", true);
-			return;
-		case JSCTOR_JSON_ARRAYAGG:
-			get_json_agg_constructor(ctor, context, "JSON_ARRAYAGG", false);
-			return;
-		default:
-			elog(ERROR, "invalid JsonConstructorExprType %d", ctor->type);
-	}
-
-	appendStringInfo(buf, "%s(", funcname);
-
-	nargs = 0;
-	foreach(lc, ctor->args)
-	{
-		if (nargs > 0)
-		{
-			const char *sep = ctor->type == JSCTOR_JSON_OBJECT &&
-			(nargs % 2) != 0 ? " : " : ", ";
-
-			appendStringInfoString(buf, sep);
-		}
-
-		get_rule_expr((Node *) lfirst(lc), context, true);
-
-		nargs++;
-	}
-
-	get_json_constructor_options(ctor, buf);
-
-	appendStringInfo(buf, ")");
-}
-
-
 /*
- * get_agg_expr_helper			- Parse back an Aggref node
+ * get_agg_expr			- Parse back an Aggref node
  */
 static void
-get_agg_expr_helper(Aggref *aggref, deparse_context *context,
-					Aggref *original_aggref, const char *funcname,
-					const char *options, bool is_json_objectagg)
+get_agg_expr(Aggref *aggref, deparse_context *context,
+			 Aggref *original_aggref)
 {
 	StringInfo	buf = context->buf;
 	Oid			argtypes[FUNC_MAX_ARGS];
 	int			nargs;
-	bool		use_variadic = false;
+	bool		use_variadic;
 
 	/*
 	 * For a combining aggregate, we look up and deparse the corresponding
@@ -10265,14 +9932,13 @@ get_agg_expr_helper(Aggref *aggref, deparse_context *context,
 	/* Extract the argument types as seen by the parser */
 	nargs = get_aggregate_argtypes(aggref, argtypes);
 
-	if (!funcname)
-		funcname = generate_function_name(aggref->aggfnoid, nargs, NIL,
-										  argtypes, aggref->aggvariadic,
-										  &use_variadic,
-										  context->special_exprkind);
-
 	/* Print the aggregate name, schema-qualified if needed */
-	appendStringInfo(buf, "%s(%s", funcname,
+	appendStringInfo(buf, "%s(%s",
+					 generate_function_name(aggref->aggfnoid, nargs,
+											NIL, argtypes,
+											aggref->aggvariadic,
+											&use_variadic,
+											context->special_exprkind),
 					 (aggref->aggdistinct != NIL) ? "DISTINCT " : "");
 
 	if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
@@ -10308,18 +9974,7 @@ get_agg_expr_helper(Aggref *aggref, deparse_context *context,
 				if (tle->resjunk)
 					continue;
 				if (i++ > 0)
-				{
-					if (is_json_objectagg)
-					{
-						if (i > 2)
-							break;	/* skip ABSENT ON NULL and WITH UNIQUE
-									 * args */
-
-						appendStringInfoString(buf, " : ");
-					}
-					else
-						appendStringInfoString(buf, ", ");
-				}
+					appendStringInfoString(buf, ", ");
 				if (use_variadic && i == nargs)
 					appendStringInfoString(buf, "VARIADIC ");
 				get_rule_expr(arg, context, true);
@@ -10333,9 +9988,6 @@ get_agg_expr_helper(Aggref *aggref, deparse_context *context,
 		}
 	}
 
-	if (options)
-		appendStringInfoString(buf, options);
-
 	if (aggref->aggfilter != NULL)
 	{
 		appendStringInfoString(buf, ") FILTER (WHERE ");
@@ -10345,16 +9997,6 @@ get_agg_expr_helper(Aggref *aggref, deparse_context *context,
 	appendStringInfoChar(buf, ')');
 }
 
-/*
- * get_agg_expr			- Parse back an Aggref node
- */
-static void
-get_agg_expr(Aggref *aggref, deparse_context *context, Aggref *original_aggref)
-{
-	get_agg_expr_helper(aggref, context, original_aggref, NULL, NULL,
-						false);
-}
-
 /*
  * This is a helper function for get_agg_expr().  It's used when we deparse
  * a combining Aggref; resolve_special_varno locates the corresponding partial
@@ -10374,12 +10016,10 @@ get_agg_combine_expr(Node *node, deparse_context *context, void *callback_arg)
 }
 
 /*
- * get_windowfunc_expr_helper	- Parse back a WindowFunc node
+ * get_windowfunc_expr	- Parse back a WindowFunc node
  */
 static void
-get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context,
-						   const char *funcname, const char *options,
-						   bool is_json_objectagg)
+get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
 {
 	StringInfo	buf = context->buf;
 	Oid			argtypes[FUNC_MAX_ARGS];
@@ -10403,30 +10043,16 @@ get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context,
 		nargs++;
 	}
 
-	if (!funcname)
-		funcname = generate_function_name(wfunc->winfnoid, nargs, argnames,
-										  argtypes, false, NULL,
-										  context->special_exprkind);
-
-	appendStringInfo(buf, "%s(", funcname);
-
+	appendStringInfo(buf, "%s(",
+					 generate_function_name(wfunc->winfnoid, nargs,
+											argnames, argtypes,
+											false, NULL,
+											context->special_exprkind));
 	/* winstar can be set only in zero-argument aggregates */
 	if (wfunc->winstar)
 		appendStringInfoChar(buf, '*');
 	else
-	{
-		if (is_json_objectagg)
-		{
-			get_rule_expr((Node *) linitial(wfunc->args), context, false);
-			appendStringInfoString(buf, " : ");
-			get_rule_expr((Node *) lsecond(wfunc->args), context, false);
-		}
-		else
-			get_rule_expr((Node *) wfunc->args, context, true);
-	}
-
-	if (options)
-		appendStringInfoString(buf, options);
+		get_rule_expr((Node *) wfunc->args, context, true);
 
 	if (wfunc->aggfilter != NULL)
 	{
@@ -10463,15 +10089,6 @@ get_windowfunc_expr_helper(WindowFunc *wfunc, deparse_context *context,
 	}
 }
 
-/*
- * get_windowfunc_expr	- Parse back a WindowFunc node
- */
-static void
-get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context)
-{
-	get_windowfunc_expr_helper(wfunc, context, NULL, NULL, false);
-}
-
 /*
  * get_func_sql_syntax		- Parse back a SQL-syntax function call
  *
@@ -10712,31 +10329,6 @@ get_func_sql_syntax(FuncExpr *expr, deparse_context *context)
 	return false;
 }
 
-/*
- * get_json_agg_constructor - Parse back an aggregate JsonConstructorExpr node
- */
-static void
-get_json_agg_constructor(JsonConstructorExpr *ctor, deparse_context *context,
-						 const char *funcname, bool is_json_objectagg)
-{
-	StringInfoData options;
-
-	initStringInfo(&options);
-	get_json_constructor_options(ctor, &options);
-
-	if (IsA(ctor->func, Aggref))
-		get_agg_expr_helper((Aggref *) ctor->func, context,
-							(Aggref *) ctor->func,
-							funcname, options.data, is_json_objectagg);
-	else if (IsA(ctor->func, WindowFunc))
-		get_windowfunc_expr_helper((WindowFunc *) ctor->func, context,
-								   funcname, options.data,
-								   is_json_objectagg);
-	else
-		elog(ERROR, "invalid JsonConstructorExpr underlying node type: %d",
-			 nodeTag(ctor->func));
-}
-
 /* ----------
  * get_coercion_expr
  *
@@ -11106,14 +10698,16 @@ get_sublink_expr(SubLink *sublink, deparse_context *context)
 
 
 /* ----------
- * get_xmltable			- Parse back a XMLTABLE function
+ * get_tablefunc			- Parse back a table function
  * ----------
  */
 static void
-get_xmltable(TableFunc *tf, deparse_context *context, bool showimplicit)
+get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
 {
 	StringInfo	buf = context->buf;
 
+	/* XMLTABLE is the only existing implementation.  */
+
 	appendStringInfoString(buf, "XMLTABLE(");
 
 	if (tf->ns_uris != NIL)
@@ -11204,271 +10798,6 @@ get_xmltable(TableFunc *tf, deparse_context *context, bool showimplicit)
 	appendStringInfoChar(buf, ')');
 }
 
-/*
- * get_json_nested_columns - Parse back nested JSON_TABLE columns
- */
-static void
-get_json_table_nested_columns(TableFunc *tf, Node *node,
-							  deparse_context *context, bool showimplicit,
-							  bool needcomma)
-{
-	if (IsA(node, JsonTableSibling))
-	{
-		JsonTableSibling *n = (JsonTableSibling *) node;
-
-		get_json_table_nested_columns(tf, n->larg, context, showimplicit,
-									  needcomma);
-		get_json_table_nested_columns(tf, n->rarg, context, showimplicit, true);
-	}
-	else
-	{
-		JsonTableParent *n = castNode(JsonTableParent, node);
-
-		if (needcomma)
-			appendStringInfoChar(context->buf, ',');
-
-		appendStringInfoChar(context->buf, ' ');
-		appendContextKeyword(context, "NESTED PATH ", 0, 0, 0);
-		get_const_expr(n->path, context, -1);
-		appendStringInfo(context->buf, " AS %s", quote_identifier(n->name));
-		get_json_table_columns(tf, n, context, showimplicit);
-	}
-}
-
-/*
- * get_json_table_plan - Parse back a JSON_TABLE plan
- */
-static void
-get_json_table_plan(TableFunc *tf, Node *node, deparse_context *context,
-					bool parenthesize)
-{
-	if (parenthesize)
-		appendStringInfoChar(context->buf, '(');
-
-	if (IsA(node, JsonTableSibling))
-	{
-		JsonTableSibling *n = (JsonTableSibling *) node;
-
-		get_json_table_plan(tf, n->larg, context,
-							IsA(n->larg, JsonTableSibling) ||
-							castNode(JsonTableParent, n->larg)->child);
-
-		appendStringInfoString(context->buf, n->cross ? " CROSS " : " UNION ");
-
-		get_json_table_plan(tf, n->rarg, context,
-							IsA(n->rarg, JsonTableSibling) ||
-							castNode(JsonTableParent, n->rarg)->child);
-	}
-	else
-	{
-		JsonTableParent *n = castNode(JsonTableParent, node);
-
-		appendStringInfoString(context->buf, quote_identifier(n->name));
-
-		if (n->child)
-		{
-			appendStringInfoString(context->buf,
-								   n->outerJoin ? " OUTER " : " INNER ");
-			get_json_table_plan(tf, n->child, context,
-								IsA(n->child, JsonTableSibling));
-		}
-	}
-
-	if (parenthesize)
-		appendStringInfoChar(context->buf, ')');
-}
-
-/*
- * get_json_table_columns - Parse back JSON_TABLE columns
- */
-static void
-get_json_table_columns(TableFunc *tf, JsonTableParent *node,
-					   deparse_context *context, bool showimplicit)
-{
-	StringInfo	buf = context->buf;
-	JsonExpr   *jexpr = castNode(JsonExpr, tf->docexpr);
-	ListCell   *lc_colname;
-	ListCell   *lc_coltype;
-	ListCell   *lc_coltypmod;
-	ListCell   *lc_colvarexpr;
-	int			colnum = 0;
-
-	appendStringInfoChar(buf, ' ');
-	appendContextKeyword(context, "COLUMNS (", 0, 0, 0);
-
-	if (PRETTY_INDENT(context))
-		context->indentLevel += PRETTYINDENT_VAR;
-
-	forfour(lc_colname, tf->colnames,
-			lc_coltype, tf->coltypes,
-			lc_coltypmod, tf->coltypmods,
-			lc_colvarexpr, tf->colvalexprs)
-	{
-		char	   *colname = strVal(lfirst(lc_colname));
-		JsonExpr   *colexpr;
-		Oid			typid;
-		int32		typmod;
-		bool		ordinality;
-		JsonBehaviorType default_behavior;
-
-		typid = lfirst_oid(lc_coltype);
-		typmod = lfirst_int(lc_coltypmod);
-		colexpr = castNode(JsonExpr, lfirst(lc_colvarexpr));
-
-		if (colnum < node->colMin)
-		{
-			colnum++;
-			continue;
-		}
-
-		if (colnum > node->colMax)
-			break;
-
-		if (colnum > node->colMin)
-			appendStringInfoString(buf, ", ");
-
-		colnum++;
-
-		ordinality = !colexpr;
-
-		appendContextKeyword(context, "", 0, 0, 0);
-
-		appendStringInfo(buf, "%s %s", quote_identifier(colname),
-						 ordinality ? "FOR ORDINALITY" :
-						 format_type_with_typemod(typid, typmod));
-		if (ordinality)
-			continue;
-
-		if (colexpr->op == JSON_EXISTS_OP)
-		{
-			appendStringInfoString(buf, " EXISTS");
-			default_behavior = JSON_BEHAVIOR_FALSE;
-		}
-		else
-		{
-			if (colexpr->op == JSON_QUERY_OP)
-			{
-				char		typcategory;
-				bool		typispreferred;
-
-				get_type_category_preferred(typid, &typcategory, &typispreferred);
-
-				if (typcategory == TYPCATEGORY_STRING)
-					appendStringInfoString(buf,
-										   colexpr->format->format_type == JS_FORMAT_JSONB ?
-										   " FORMAT JSONB" : " FORMAT JSON");
-			}
-
-			default_behavior = JSON_BEHAVIOR_NULL;
-		}
-
-		if (jexpr->on_error->btype == JSON_BEHAVIOR_ERROR)
-			default_behavior = JSON_BEHAVIOR_ERROR;
-
-		appendStringInfoString(buf, " PATH ");
-
-		get_json_path_spec(colexpr->path_spec, context, showimplicit);
-
-		get_json_expr_options(colexpr, context, default_behavior);
-	}
-
-	if (node->child)
-		get_json_table_nested_columns(tf, node->child, context, showimplicit,
-									  node->colMax >= node->colMin);
-
-	if (PRETTY_INDENT(context))
-		context->indentLevel -= PRETTYINDENT_VAR;
-
-	appendContextKeyword(context, ")", 0, 0, 0);
-}
-
-/* ----------
- * get_json_table			- Parse back a JSON_TABLE function
- * ----------
- */
-static void
-get_json_table(TableFunc *tf, deparse_context *context, bool showimplicit)
-{
-	StringInfo	buf = context->buf;
-	JsonExpr   *jexpr = castNode(JsonExpr, tf->docexpr);
-	JsonTableParent *root = castNode(JsonTableParent, tf->plan);
-
-	appendStringInfoString(buf, "JSON_TABLE(");
-
-	if (PRETTY_INDENT(context))
-		context->indentLevel += PRETTYINDENT_VAR;
-
-	appendContextKeyword(context, "", 0, 0, 0);
-
-	get_rule_expr(jexpr->formatted_expr, context, showimplicit);
-
-	appendStringInfoString(buf, ", ");
-
-	get_const_expr(root->path, context, -1);
-
-	appendStringInfo(buf, " AS %s", quote_identifier(root->name));
-
-	if (jexpr->passing_values)
-	{
-		ListCell   *lc1,
-				   *lc2;
-		bool		needcomma = false;
-
-		appendStringInfoChar(buf, ' ');
-		appendContextKeyword(context, "PASSING ", 0, 0, 0);
-
-		if (PRETTY_INDENT(context))
-			context->indentLevel += PRETTYINDENT_VAR;
-
-		forboth(lc1, jexpr->passing_names,
-				lc2, jexpr->passing_values)
-		{
-			if (needcomma)
-				appendStringInfoString(buf, ", ");
-			needcomma = true;
-
-			appendContextKeyword(context, "", 0, 0, 0);
-
-			get_rule_expr((Node *) lfirst(lc2), context, false);
-			appendStringInfo(buf, " AS %s",
-							 quote_identifier((lfirst_node(String, lc1))->sval)
-				);
-		}
-
-		if (PRETTY_INDENT(context))
-			context->indentLevel -= PRETTYINDENT_VAR;
-	}
-
-	get_json_table_columns(tf, root, context, showimplicit);
-
-	appendStringInfoChar(buf, ' ');
-	appendContextKeyword(context, "PLAN ", 0, 0, 0);
-	get_json_table_plan(tf, (Node *) root, context, true);
-
-	if (jexpr->on_error->btype != JSON_BEHAVIOR_EMPTY)
-		get_json_behavior(jexpr->on_error, context, "ERROR");
-
-	if (PRETTY_INDENT(context))
-		context->indentLevel -= PRETTYINDENT_VAR;
-
-	appendContextKeyword(context, ")", 0, 0, 0);
-}
-
-/* ----------
- * get_tablefunc			- Parse back a table function
- * ----------
- */
-static void
-get_tablefunc(TableFunc *tf, deparse_context *context, bool showimplicit)
-{
-	/* XMLTABLE and JSON_TABLE are the only existing implementations.  */
-
-	if (tf->functype == TFT_XMLTABLE)
-		get_xmltable(tf, context, showimplicit);
-	else if (tf->functype == TFT_JSON_TABLE)
-		get_json_table(tf, context, showimplicit);
-}
-
 /* ----------
  * get_from_clause			- Parse back a FROM clause
  *
diff --git a/src/backend/utils/misc/queryjumble.c b/src/backend/utils/misc/queryjumble.c
index eeaa0b31fe..a67487e5fe 100644
--- a/src/backend/utils/misc/queryjumble.c
+++ b/src/backend/utils/misc/queryjumble.c
@@ -737,76 +737,6 @@ JumbleExpr(JumbleState *jstate, Node *node)
 				JumbleExpr(jstate, (Node *) conf->exclRelTlist);
 			}
 			break;
-		case T_JsonFormat:
-			{
-				JsonFormat *format = (JsonFormat *) node;
-
-				APP_JUMB(format->format_type);
-				APP_JUMB(format->encoding);
-			}
-			break;
-		case T_JsonReturning:
-			{
-				JsonReturning *returning = (JsonReturning *) node;
-
-				JumbleExpr(jstate, (Node *) returning->format);
-				APP_JUMB(returning->typid);
-				APP_JUMB(returning->typmod);
-			}
-			break;
-		case T_JsonValueExpr:
-			{
-				JsonValueExpr *expr = (JsonValueExpr *) node;
-
-				JumbleExpr(jstate, (Node *) expr->raw_expr);
-				JumbleExpr(jstate, (Node *) expr->formatted_expr);
-				JumbleExpr(jstate, (Node *) expr->format);
-			}
-			break;
-		case T_JsonConstructorExpr:
-			{
-				JsonConstructorExpr *ctor = (JsonConstructorExpr *) node;
-
-				APP_JUMB(ctor->type);
-				JumbleExpr(jstate, (Node *) ctor->args);
-				JumbleExpr(jstate, (Node *) ctor->func);
-				JumbleExpr(jstate, (Node *) ctor->coercion);
-				JumbleExpr(jstate, (Node *) ctor->returning);
-				APP_JUMB(ctor->absent_on_null);
-				APP_JUMB(ctor->unique);
-			}
-			break;
-		case T_JsonIsPredicate:
-			{
-				JsonIsPredicate *pred = (JsonIsPredicate *) node;
-
-				JumbleExpr(jstate, (Node *) pred->expr);
-				JumbleExpr(jstate, (Node *) pred->format);
-				APP_JUMB(pred->item_type);
-				APP_JUMB(pred->unique_keys);
-			}
-			break;
-		case T_JsonExpr:
-			{
-				JsonExpr   *jexpr = (JsonExpr *) node;
-
-				APP_JUMB(jexpr->op);
-				JumbleExpr(jstate, jexpr->formatted_expr);
-				JumbleExpr(jstate, jexpr->path_spec);
-				foreach(temp, jexpr->passing_names)
-				{
-					APP_JUMB_STRING(lfirst_node(String, temp)->sval);
-				}
-				JumbleExpr(jstate, (Node *) jexpr->passing_values);
-				if (jexpr->on_empty)
-				{
-					APP_JUMB(jexpr->on_empty->btype);
-					JumbleExpr(jstate, jexpr->on_empty->default_expr);
-				}
-				APP_JUMB(jexpr->on_error->btype);
-				JumbleExpr(jstate, jexpr->on_error->default_expr);
-			}
-			break;
 		case T_List:
 			foreach(temp, (List *) node)
 			{
@@ -879,11 +809,9 @@ JumbleExpr(JumbleState *jstate, Node *node)
 			{
 				TableFunc  *tablefunc = (TableFunc *) node;
 
-				APP_JUMB(tablefunc->functype);
 				JumbleExpr(jstate, tablefunc->docexpr);
 				JumbleExpr(jstate, tablefunc->rowexpr);
 				JumbleExpr(jstate, (Node *) tablefunc->colexprs);
-				JumbleExpr(jstate, (Node *) tablefunc->colvalexprs);
 			}
 			break;
 		case T_TableSampleClause:
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 7482c85a86..78d25036b3 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	202208251
+#define CATALOG_VERSION_NO	202209011
 
 #endif
diff --git a/src/include/catalog/pg_aggregate.dat b/src/include/catalog/pg_aggregate.dat
index 86cc650798..b9110a5298 100644
--- a/src/include/catalog/pg_aggregate.dat
+++ b/src/include/catalog/pg_aggregate.dat
@@ -571,36 +571,14 @@
 # json
 { aggfnoid => 'json_agg', aggtransfn => 'json_agg_transfn',
   aggfinalfn => 'json_agg_finalfn', aggtranstype => 'internal' },
-{ aggfnoid => 'json_agg_strict', aggtransfn => 'json_agg_strict_transfn',
-  aggfinalfn => 'json_agg_finalfn', aggtranstype => 'internal' },
 { aggfnoid => 'json_object_agg', aggtransfn => 'json_object_agg_transfn',
   aggfinalfn => 'json_object_agg_finalfn', aggtranstype => 'internal' },
-{ aggfnoid => 'json_object_agg_unique',
-  aggtransfn => 'json_object_agg_unique_transfn',
-  aggfinalfn => 'json_object_agg_finalfn', aggtranstype => 'internal' },
-{ aggfnoid => 'json_object_agg_strict',
-  aggtransfn => 'json_object_agg_strict_transfn',
-  aggfinalfn => 'json_object_agg_finalfn', aggtranstype => 'internal' },
-{ aggfnoid => 'json_object_agg_unique_strict',
-  aggtransfn => 'json_object_agg_unique_strict_transfn',
-  aggfinalfn => 'json_object_agg_finalfn', aggtranstype => 'internal' },
 
 # jsonb
 { aggfnoid => 'jsonb_agg', aggtransfn => 'jsonb_agg_transfn',
   aggfinalfn => 'jsonb_agg_finalfn', aggtranstype => 'internal' },
-{ aggfnoid => 'jsonb_agg_strict', aggtransfn => 'jsonb_agg_strict_transfn',
-  aggfinalfn => 'jsonb_agg_finalfn', aggtranstype => 'internal' },
 { aggfnoid => 'jsonb_object_agg', aggtransfn => 'jsonb_object_agg_transfn',
   aggfinalfn => 'jsonb_object_agg_finalfn', aggtranstype => 'internal' },
-{ aggfnoid => 'jsonb_object_agg_unique',
-  aggtransfn => 'jsonb_object_agg_unique_transfn',
-  aggfinalfn => 'jsonb_object_agg_finalfn', aggtranstype => 'internal' },
-{ aggfnoid => 'jsonb_object_agg_strict',
-  aggtransfn => 'jsonb_object_agg_strict_transfn',
-  aggfinalfn => 'jsonb_object_agg_finalfn', aggtranstype => 'internal' },
-{ aggfnoid => 'jsonb_object_agg_unique_strict',
-  aggtransfn => 'jsonb_object_agg_unique_strict_transfn',
-  aggfinalfn => 'jsonb_object_agg_finalfn', aggtranstype => 'internal' },
 
 # ordered-set and hypothetical-set aggregates
 { aggfnoid => 'percentile_disc(float8,anyelement)', aggkind => 'o',
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index be47583122..a07e737a33 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -8785,10 +8785,6 @@
   proname => 'json_agg_transfn', proisstrict => 'f', provolatile => 's',
   prorettype => 'internal', proargtypes => 'internal anyelement',
   prosrc => 'json_agg_transfn' },
-{ oid => '6208', descr => 'json aggregate transition function',
-  proname => 'json_agg_strict_transfn', proisstrict => 'f', provolatile => 's',
-  prorettype => 'internal', proargtypes => 'internal anyelement',
-  prosrc => 'json_agg_strict_transfn' },
 { oid => '3174', descr => 'json aggregate final function',
   proname => 'json_agg_finalfn', proisstrict => 'f', prorettype => 'json',
   proargtypes => 'internal', prosrc => 'json_agg_finalfn' },
@@ -8796,29 +8792,10 @@
   proname => 'json_agg', prokind => 'a', proisstrict => 'f', provolatile => 's',
   prorettype => 'json', proargtypes => 'anyelement',
   prosrc => 'aggregate_dummy' },
-{ oid => '6209', descr => 'aggregate input into json',
-  proname => 'json_agg_strict', prokind => 'a', proisstrict => 'f',
-  provolatile => 's', prorettype => 'json', proargtypes => 'anyelement',
-  prosrc => 'aggregate_dummy' },
 { oid => '3180', descr => 'json object aggregate transition function',
   proname => 'json_object_agg_transfn', proisstrict => 'f', provolatile => 's',
   prorettype => 'internal', proargtypes => 'internal any any',
   prosrc => 'json_object_agg_transfn' },
-{ oid => '6210', descr => 'json object aggregate transition function',
-  proname => 'json_object_agg_strict_transfn', proisstrict => 'f',
-  provolatile => 's', prorettype => 'internal',
-  proargtypes => 'internal any any',
-  prosrc => 'json_object_agg_strict_transfn' },
-{ oid => '6211', descr => 'json object aggregate transition function',
-  proname => 'json_object_agg_unique_transfn', proisstrict => 'f',
-  provolatile => 's', prorettype => 'internal',
-  proargtypes => 'internal any any',
-  prosrc => 'json_object_agg_unique_transfn' },
-{ oid => '6212', descr => 'json object aggregate transition function',
-  proname => 'json_object_agg_unique_strict_transfn', proisstrict => 'f',
-  provolatile => 's', prorettype => 'internal',
-  proargtypes => 'internal any any',
-  prosrc => 'json_object_agg_unique_strict_transfn' },
 { oid => '3196', descr => 'json object aggregate final function',
   proname => 'json_object_agg_finalfn', proisstrict => 'f',
   prorettype => 'json', proargtypes => 'internal',
@@ -8827,20 +8804,6 @@
   proname => 'json_object_agg', prokind => 'a', proisstrict => 'f',
   provolatile => 's', prorettype => 'json', proargtypes => 'any any',
   prosrc => 'aggregate_dummy' },
-{ oid => '6213', descr => 'aggregate non-NULL input into a json object',
-  proname => 'json_object_agg_strict', prokind => 'a', proisstrict => 'f',
-  provolatile => 's', prorettype => 'json', proargtypes => 'any any',
-  prosrc => 'aggregate_dummy' },
-{ oid => '6214',
-  descr => 'aggregate input into a json object with unique keys',
-  proname => 'json_object_agg_unique', prokind => 'a', proisstrict => 'f',
-  provolatile => 's', prorettype => 'json', proargtypes => 'any any',
-  prosrc => 'aggregate_dummy' },
-{ oid => '6215',
-  descr => 'aggregate non-NULL input into a json object with unique keys',
-  proname => 'json_object_agg_unique_strict', prokind => 'a',
-  proisstrict => 'f', provolatile => 's', prorettype => 'json',
-  proargtypes => 'any any', prosrc => 'aggregate_dummy' },
 { oid => '3198', descr => 'build a json array from any inputs',
   proname => 'json_build_array', provariadic => 'any', proisstrict => 'f',
   provolatile => 's', prorettype => 'json', proargtypes => 'any',
@@ -9713,10 +9676,6 @@
   proname => 'jsonb_agg_transfn', proisstrict => 'f', provolatile => 's',
   prorettype => 'internal', proargtypes => 'internal anyelement',
   prosrc => 'jsonb_agg_transfn' },
-{ oid => '6216', descr => 'jsonb aggregate transition function',
-  proname => 'jsonb_agg_strict_transfn', proisstrict => 'f', provolatile => 's',
-  prorettype => 'internal', proargtypes => 'internal anyelement',
-  prosrc => 'jsonb_agg_strict_transfn' },
 { oid => '3266', descr => 'jsonb aggregate final function',
   proname => 'jsonb_agg_finalfn', proisstrict => 'f', provolatile => 's',
   prorettype => 'jsonb', proargtypes => 'internal',
@@ -9725,29 +9684,10 @@
   proname => 'jsonb_agg', prokind => 'a', proisstrict => 'f',
   provolatile => 's', prorettype => 'jsonb', proargtypes => 'anyelement',
   prosrc => 'aggregate_dummy' },
-{ oid => '6217', descr => 'aggregate input into jsonb skipping nulls',
-  proname => 'jsonb_agg_strict', prokind => 'a', proisstrict => 'f',
-  provolatile => 's', prorettype => 'jsonb', proargtypes => 'anyelement',
-  prosrc => 'aggregate_dummy' },
 { oid => '3268', descr => 'jsonb object aggregate transition function',
   proname => 'jsonb_object_agg_transfn', proisstrict => 'f', provolatile => 's',
   prorettype => 'internal', proargtypes => 'internal any any',
   prosrc => 'jsonb_object_agg_transfn' },
-{ oid => '6218', descr => 'jsonb object aggregate transition function',
-  proname => 'jsonb_object_agg_strict_transfn', proisstrict => 'f',
-  provolatile => 's', prorettype => 'internal',
-  proargtypes => 'internal any any',
-  prosrc => 'jsonb_object_agg_strict_transfn' },
-{ oid => '6219', descr => 'jsonb object aggregate transition function',
-  proname => 'jsonb_object_agg_unique_transfn', proisstrict => 'f',
-  provolatile => 's', prorettype => 'internal',
-  proargtypes => 'internal any any',
-  prosrc => 'jsonb_object_agg_unique_transfn' },
-{ oid => '6220', descr => 'jsonb object aggregate transition function',
-  proname => 'jsonb_object_agg_unique_strict_transfn', proisstrict => 'f',
-  provolatile => 's', prorettype => 'internal',
-  proargtypes => 'internal any any',
-  prosrc => 'jsonb_object_agg_unique_strict_transfn' },
 { oid => '3269', descr => 'jsonb object aggregate final function',
   proname => 'jsonb_object_agg_finalfn', proisstrict => 'f', provolatile => 's',
   prorettype => 'jsonb', proargtypes => 'internal',
@@ -9756,20 +9696,6 @@
   proname => 'jsonb_object_agg', prokind => 'a', proisstrict => 'f',
   prorettype => 'jsonb', proargtypes => 'any any',
   prosrc => 'aggregate_dummy' },
-{ oid => '6221', descr => 'aggregate non-NULL inputs into jsonb object',
-  proname => 'jsonb_object_agg_strict', prokind => 'a', proisstrict => 'f',
-  prorettype => 'jsonb', proargtypes => 'any any',
-  prosrc => 'aggregate_dummy' },
-{ oid => '6222',
-  descr => 'aggregate inputs into jsonb object checking key uniqueness',
-  proname => 'jsonb_object_agg_unique', prokind => 'a', proisstrict => 'f',
-  prorettype => 'jsonb', proargtypes => 'any any',
-  prosrc => 'aggregate_dummy' },
-{ oid => '6223',
-  descr => 'aggregate non-NULL inputs into jsonb object checking key uniqueness',
-  proname => 'jsonb_object_agg_unique_strict', prokind => 'a',
-  proisstrict => 'f', prorettype => 'jsonb', proargtypes => 'any any',
-  prosrc => 'aggregate_dummy' },
 { oid => '3271', descr => 'build a jsonb array from any inputs',
   proname => 'jsonb_build_array', provariadic => 'any', proisstrict => 'f',
   provolatile => 's', prorettype => 'jsonb', proargtypes => 'any',
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index c8ef917ffe..e14f15d435 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -21,9 +21,6 @@
 struct ExprEvalStep;
 struct SubscriptingRefState;
 struct ScalarArrayOpExprHashTable;
-struct JsonbValue;
-struct JsonExprState;
-struct JsonConstructorExprState;
 
 /* Bits in ExprState->flags (see also execnodes.h for public flag bits): */
 /* expression's interpreter has been initialized */
@@ -242,9 +239,6 @@ typedef enum ExprEvalOp
 	EEOP_GROUPING_FUNC,
 	EEOP_WINDOW_FUNC,
 	EEOP_SUBPLAN,
-	EEOP_JSON_CONSTRUCTOR,
-	EEOP_IS_JSON,
-	EEOP_JSONEXPR,
 
 	/* aggregation related nodes */
 	EEOP_AGG_STRICT_DESERIALIZE,
@@ -679,25 +673,6 @@ typedef struct ExprEvalStep
 			int			transno;
 			int			setoff;
 		}			agg_trans;
-
-		/* for EEOP_JSON_CONSTRUCTOR */
-		struct
-		{
-			struct JsonConstructorExprState *jcstate;
-		}			json_constructor;
-
-		/* for EEOP_IS_JSON */
-		struct
-		{
-			JsonIsPredicate *pred;	/* original expression node */
-		}			is_json;
-
-		/* for EEOP_JSONEXPR */
-		struct
-		{
-			struct JsonExprState *jsestate;
-		}			jsonexpr;
-
 	}			d;
 } ExprEvalStep;
 
@@ -742,64 +717,6 @@ typedef struct SubscriptExecSteps
 	ExecEvalSubroutine sbs_fetch_old;	/* fetch old value for assignment */
 } SubscriptExecSteps;
 
-/* EEOP_JSON_CONSTRUCTOR state, too big to inline */
-typedef struct JsonConstructorExprState
-{
-	JsonConstructorExpr *constructor;
-	Datum	   *arg_values;
-	bool	   *arg_nulls;
-	Oid		   *arg_types;
-	struct
-	{
-		int			category;
-		Oid			outfuncid;
-	}		   *arg_type_cache; /* cache for datum_to_json[b]() */
-	int			nargs;
-} JsonConstructorExprState;
-
-/* EEOP_JSONEXPR state, too big to inline */
-typedef struct JsonExprState
-{
-	JsonExpr   *jsexpr;			/* original expression node */
-
-	struct
-	{
-		FmgrInfo	func;		/* typinput function for output type */
-		Oid			typioparam;
-	}			input;			/* I/O info for output type */
-
-	NullableDatum
-			   *formatted_expr, /* formatted context item value */
-			   *res_expr,		/* result item */
-			   *coercion_expr,	/* input for JSON item coercion */
-			   *pathspec;		/* path specification value */
-
-	ExprState  *result_expr;	/* coerced to output type */
-	ExprState  *default_on_empty;	/* ON EMPTY DEFAULT expression */
-	ExprState  *default_on_error;	/* ON ERROR DEFAULT expression */
-	List	   *args;			/* passing arguments */
-
-	void	   *cache;			/* cache for json_populate_type() */
-
-	struct JsonCoercionsState
-	{
-		struct JsonCoercionState
-		{
-			JsonCoercion *coercion; /* coercion expression */
-			ExprState  *estate; /* coercion expression state */
-		}			null,
-					string,
-		numeric    ,
-					boolean,
-					date,
-					time,
-					timetz,
-					timestamp,
-					timestamptz,
-					composite;
-	}			coercions;		/* states for coercion from SQL/JSON item
-								 * types directly to the output type */
-} JsonExprState;
 
 /* functions in execExpr.c */
 extern void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s);
@@ -850,7 +767,6 @@ extern void ExecEvalHashedScalarArrayOp(ExprState *state, ExprEvalStep *op,
 extern void ExecEvalConstraintNotNull(ExprState *state, ExprEvalStep *op);
 extern void ExecEvalConstraintCheck(ExprState *state, ExprEvalStep *op);
 extern void ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op);
-extern void ExecEvalJsonIsPredicate(ExprState *state, ExprEvalStep *op);
 extern void ExecEvalGroupingFunc(ExprState *state, ExprEvalStep *op);
 extern void ExecEvalSubPlan(ExprState *state, ExprEvalStep *op,
 							ExprContext *econtext);
@@ -858,20 +774,6 @@ extern void ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op,
 								ExprContext *econtext);
 extern void ExecEvalSysVar(ExprState *state, ExprEvalStep *op,
 						   ExprContext *econtext, TupleTableSlot *slot);
-extern void ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op,
-									ExprContext *econtext);
-extern void ExecEvalJson(ExprState *state, ExprEvalStep *op,
-						 ExprContext *econtext);
-extern Datum ExecPrepareJsonItemCoercion(struct JsonbValue *item,
-										 JsonReturning *returning,
-										 struct JsonCoercionsState *coercions,
-										 struct JsonCoercionState **pjcstate);
-extern bool ExecEvalJsonNeedsSubTransaction(JsonExpr *jsexpr,
-											struct JsonCoercionsState *);
-extern Datum ExecEvalExprPassingCaseValue(ExprState *estate,
-										  ExprContext *econtext, bool *isnull,
-										  Datum caseval_datum,
-										  bool caseval_isnull);
 
 extern void ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup,
 							 ExprContext *aggcontext);
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index d68a6b9d28..82925b4b63 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -265,8 +265,6 @@ ExecProcNode(PlanState *node)
  */
 extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
 extern ExprState *ExecInitExprWithParams(Expr *node, ParamListInfo ext_params);
-extern ExprState *ExecInitExprWithCaseValue(Expr *node, PlanState *parent,
-											Datum *caseval, bool *casenull);
 extern ExprState *ExecInitQual(List *qual, PlanState *parent);
 extern ExprState *ExecInitCheck(List *qual, PlanState *parent);
 extern List *ExecInitExprList(List *nodes, PlanState *parent);
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index 06e6369026..50de4c62af 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -106,16 +106,4 @@ extern GroupingSet *makeGroupingSet(GroupingSetKind kind, List *content, int loc
 
 extern VacuumRelation *makeVacuumRelation(RangeVar *relation, Oid oid, List *va_cols);
 
-extern JsonFormat *makeJsonFormat(JsonFormatType type, JsonEncoding encoding,
-								  int location);
-extern JsonValueExpr *makeJsonValueExpr(Expr *expr, JsonFormat *format);
-extern JsonBehavior *makeJsonBehavior(JsonBehaviorType type, Node *expr);
-extern Node *makeJsonTableJoinedPlan(JsonTablePlanJoinType type,
-									 Node *plan1, Node *plan2, int location);
-extern Node *makeJsonKeyValue(Node *key, Node *value);
-extern Node *makeJsonIsPredicate(Node *expr, JsonFormat *format,
-								 JsonValueType item_type, bool unique_keys,
-								 int location);
-extern JsonEncoding makeJsonEncoding(char *name);
-
 #endif							/* MAKEFUNC_H */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 469a5c46f6..6958306a7d 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1606,293 +1606,6 @@ typedef struct TriggerTransition
 	bool		isTable;
 } TriggerTransition;
 
-/* Nodes for SQL/JSON support */
-
-/*
- * JsonQuotes -
- *		representation of [KEEP|OMIT] QUOTES clause for JSON_QUERY()
- */
-typedef enum JsonQuotes
-{
-	JS_QUOTES_UNSPEC,			/* unspecified */
-	JS_QUOTES_KEEP,				/* KEEP QUOTES */
-	JS_QUOTES_OMIT				/* OMIT QUOTES */
-} JsonQuotes;
-
-/*
- * JsonTableColumnType -
- *		enumeration of JSON_TABLE column types
- */
-typedef enum JsonTableColumnType
-{
-	JTC_FOR_ORDINALITY,
-	JTC_REGULAR,
-	JTC_EXISTS,
-	JTC_FORMATTED,
-	JTC_NESTED,
-} JsonTableColumnType;
-
-/*
- * JsonOutput -
- *		representation of JSON output clause (RETURNING type [FORMAT format])
- */
-typedef struct JsonOutput
-{
-	NodeTag		type;
-	TypeName   *typeName;		/* RETURNING type name, if specified */
-	JsonReturning *returning;	/* RETURNING FORMAT clause and type Oids */
-} JsonOutput;
-
-/*
- * JsonArgument -
- *		representation of argument from JSON PASSING clause
- */
-typedef struct JsonArgument
-{
-	NodeTag		type;
-	JsonValueExpr *val;			/* argument value expression */
-	char	   *name;			/* argument name */
-} JsonArgument;
-
-/*
- * JsonCommon -
- *		representation of common syntax of functions using JSON path
- */
-typedef struct JsonCommon
-{
-	NodeTag		type;
-	JsonValueExpr *expr;		/* context item expression */
-	Node	   *pathspec;		/* JSON path specification expression */
-	char	   *pathname;		/* path name, if any */
-	List	   *passing;		/* list of PASSING clause arguments, if any */
-	int			location;		/* token location, or -1 if unknown */
-} JsonCommon;
-
-/*
- * JsonFuncExpr -
- *		untransformed representation of JSON function expressions
- */
-typedef struct JsonFuncExpr
-{
-	NodeTag		type;
-	JsonExprOp	op;				/* expression type */
-	JsonCommon *common;			/* common syntax */
-	JsonOutput *output;			/* output clause, if specified */
-	JsonBehavior *on_empty;		/* ON EMPTY behavior, if specified */
-	JsonBehavior *on_error;		/* ON ERROR behavior, if specified */
-	JsonWrapper wrapper;		/* array wrapper behavior (JSON_QUERY only) */
-	bool		omit_quotes;	/* omit or keep quotes? (JSON_QUERY only) */
-	int			location;		/* token location, or -1 if unknown */
-} JsonFuncExpr;
-
-/*
- * JsonTableColumn -
- *		untransformed representation of JSON_TABLE column
- */
-typedef struct JsonTableColumn
-{
-	NodeTag		type;
-	JsonTableColumnType coltype;	/* column type */
-	char	   *name;			/* column name */
-	TypeName   *typeName;		/* column type name */
-	char	   *pathspec;		/* path specification, if any */
-	char	   *pathname;		/* path name, if any */
-	JsonFormat *format;			/* JSON format clause, if specified */
-	JsonWrapper wrapper;		/* WRAPPER behavior for formatted columns */
-	bool		omit_quotes;	/* omit or keep quotes on scalar strings? */
-	List	   *columns;		/* nested columns */
-	JsonBehavior *on_empty;		/* ON EMPTY behavior */
-	JsonBehavior *on_error;		/* ON ERROR behavior */
-	int			location;		/* token location, or -1 if unknown */
-} JsonTableColumn;
-
-/*
- * JsonTablePlanType -
- *		flags for JSON_TABLE plan node types representation
- */
-typedef enum JsonTablePlanType
-{
-	JSTP_DEFAULT,
-	JSTP_SIMPLE,
-	JSTP_JOINED,
-} JsonTablePlanType;
-
-/*
- * JsonTablePlanJoinType -
- *		flags for JSON_TABLE join types representation
- */
-typedef enum JsonTablePlanJoinType
-{
-	JSTPJ_INNER = 0x01,
-	JSTPJ_OUTER = 0x02,
-	JSTPJ_CROSS = 0x04,
-	JSTPJ_UNION = 0x08,
-} JsonTablePlanJoinType;
-
-typedef struct JsonTablePlan JsonTablePlan;
-
-/*
- * JsonTablePlan -
- *		untransformed representation of JSON_TABLE plan node
- */
-struct JsonTablePlan
-{
-	NodeTag		type;
-	JsonTablePlanType plan_type;	/* plan type */
-	JsonTablePlanJoinType join_type;	/* join type (for joined plan only) */
-	JsonTablePlan *plan1;		/* first joined plan */
-	JsonTablePlan *plan2;		/* second joined plan */
-	char	   *pathname;		/* path name (for simple plan only) */
-	int			location;		/* token location, or -1 if unknown */
-};
-
-/*
- * JsonTable -
- *		untransformed representation of JSON_TABLE
- */
-typedef struct JsonTable
-{
-	NodeTag		type;
-	JsonCommon *common;			/* common JSON path syntax fields */
-	List	   *columns;		/* list of JsonTableColumn */
-	JsonTablePlan *plan;		/* join plan, if specified */
-	JsonBehavior *on_error;		/* ON ERROR behavior, if specified */
-	Alias	   *alias;			/* table alias in FROM clause */
-	bool		lateral;		/* does it have LATERAL prefix? */
-	int			location;		/* token location, or -1 if unknown */
-} JsonTable;
-
-/*
- * JsonKeyValue -
- *		untransformed representation of JSON object key-value pair for
- *		JSON_OBJECT() and JSON_OBJECTAGG()
- */
-typedef struct JsonKeyValue
-{
-	NodeTag		type;
-	Expr	   *key;			/* key expression */
-	JsonValueExpr *value;		/* JSON value expression */
-} JsonKeyValue;
-
-/*
- * JsonParseExpr -
- *		untransformed representation of JSON()
- */
-typedef struct JsonParseExpr
-{
-	NodeTag		type;
-	JsonValueExpr *expr;		/* string expression */
-	JsonOutput *output;			/* RETURNING clause, if specified */
-	bool		unique_keys;	/* WITH UNIQUE KEYS? */
-	int			location;		/* token location, or -1 if unknown */
-} JsonParseExpr;
-
-/*
- * JsonScalarExpr -
- *		untransformed representation of JSON_SCALAR()
- */
-typedef struct JsonScalarExpr
-{
-	NodeTag		type;
-	Expr	   *expr;			/* scalar expression */
-	JsonOutput *output;			/* RETURNING clause, if specified */
-	int			location;		/* token location, or -1 if unknown */
-} JsonScalarExpr;
-
-/*
- * JsonSerializeExpr -
- *		untransformed representation of JSON_SERIALIZE() function
- */
-typedef struct JsonSerializeExpr
-{
-	NodeTag		type;
-	JsonValueExpr *expr;		/* json value expression */
-	JsonOutput *output;			/* RETURNING clause, if specified  */
-	int			location;		/* token location, or -1 if unknown */
-} JsonSerializeExpr;
-
-/*
- * JsonObjectConstructor -
- *		untransformed representation of JSON_OBJECT() constructor
- */
-typedef struct JsonObjectConstructor
-{
-	NodeTag		type;
-	List	   *exprs;			/* list of JsonKeyValue pairs */
-	JsonOutput *output;			/* RETURNING clause, if specified  */
-	bool		absent_on_null; /* skip NULL values? */
-	bool		unique;			/* check key uniqueness? */
-	int			location;		/* token location, or -1 if unknown */
-} JsonObjectConstructor;
-
-/*
- * JsonArrayConstructor -
- *		untransformed representation of JSON_ARRAY(element,...) constructor
- */
-typedef struct JsonArrayConstructor
-{
-	NodeTag		type;
-	List	   *exprs;			/* list of JsonValueExpr elements */
-	JsonOutput *output;			/* RETURNING clause, if specified  */
-	bool		absent_on_null; /* skip NULL elements? */
-	int			location;		/* token location, or -1 if unknown */
-} JsonArrayConstructor;
-
-/*
- * JsonArrayQueryConstructor -
- *		untransformed representation of JSON_ARRAY(subquery) constructor
- */
-typedef struct JsonArrayQueryConstructor
-{
-	NodeTag		type;
-	Node	   *query;			/* subquery */
-	JsonOutput *output;			/* RETURNING clause, if specified  */
-	JsonFormat *format;			/* FORMAT clause for subquery, if specified */
-	bool		absent_on_null; /* skip NULL elements? */
-	int			location;		/* token location, or -1 if unknown */
-} JsonArrayQueryConstructor;
-
-/*
- * JsonAggConstructor -
- *		common fields of untransformed representation of
- *		JSON_ARRAYAGG() and JSON_OBJECTAGG()
- */
-typedef struct JsonAggConstructor
-{
-	NodeTag		type;
-	JsonOutput *output;			/* RETURNING clause, if any */
-	Node	   *agg_filter;		/* FILTER clause, if any */
-	List	   *agg_order;		/* ORDER BY clause, if any */
-	struct WindowDef *over;		/* OVER clause, if any */
-	int			location;		/* token location, or -1 if unknown */
-} JsonAggConstructor;
-
-/*
- * JsonObjectAgg -
- *		untransformed representation of JSON_OBJECTAGG()
- */
-typedef struct JsonObjectAgg
-{
-	NodeTag		type;
-	JsonAggConstructor *constructor;	/* common fields */
-	JsonKeyValue *arg;			/* object key-value pair */
-	bool		absent_on_null; /* skip NULL values? */
-	bool		unique;			/* check key uniqueness? */
-} JsonObjectAgg;
-
-/*
- * JsonArrayAgg -
- *		untransformed representation of JSON_ARRRAYAGG()
- */
-typedef struct JsonArrayAgg
-{
-	NodeTag		type;
-	JsonAggConstructor *constructor;	/* common fields */
-	JsonValueExpr *arg;			/* array element expression */
-	bool		absent_on_null; /* skip NULL elements? */
-} JsonArrayAgg;
-
-
 /*****************************************************************************
  *		Raw Grammar Output Statements
  *****************************************************************************/
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 3aa96bb685..40661334bb 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -89,14 +89,8 @@ typedef struct RangeVar
 	int			location;
 } RangeVar;
 
-typedef enum TableFuncType
-{
-	TFT_XMLTABLE,
-	TFT_JSON_TABLE
-} TableFuncType;
-
 /*
- * TableFunc - node for a table function, such as XMLTABLE or JSON_TABLE.
+ * TableFunc - node for a table function, such as XMLTABLE.
  *
  * Entries in the ns_names list are either String nodes containing
  * literal namespace names, or NULL pointers to represent DEFAULT.
@@ -104,7 +98,6 @@ typedef enum TableFuncType
 typedef struct TableFunc
 {
 	NodeTag		type;
-	TableFuncType functype;		/* XMLTABLE or JSON_TABLE */
 	List	   *ns_uris;		/* list of namespace URI expressions */
 	List	   *ns_names;		/* list of namespace names or NULL */
 	Node	   *docexpr;		/* input document expression */
@@ -115,9 +108,7 @@ typedef struct TableFunc
 	List	   *colcollations;	/* OID list of column collation OIDs */
 	List	   *colexprs;		/* list of column filter expressions */
 	List	   *coldefexprs;	/* list of column default expressions */
-	List	   *colvalexprs;	/* list of column value expressions */
 	Bitmapset  *notnulls;		/* nullability flag for each output column */
-	Node	   *plan;			/* JSON_TABLE plan */
 	int			ordinalitycol;	/* counts from 0; -1 if none specified */
 	int			location;		/* token location, or -1 if unknown */
 } TableFunc;
@@ -1383,260 +1374,6 @@ typedef struct XmlExpr
 	int			location;		/* token location, or -1 if unknown */
 } XmlExpr;
 
-/*
- * JsonExprOp -
- *		enumeration of JSON functions using JSON path
- */
-typedef enum JsonExprOp
-{
-	JSON_VALUE_OP,				/* JSON_VALUE() */
-	JSON_QUERY_OP,				/* JSON_QUERY() */
-	JSON_EXISTS_OP,				/* JSON_EXISTS() */
-	JSON_TABLE_OP				/* JSON_TABLE() */
-} JsonExprOp;
-
-/*
- * JsonEncoding -
- *		representation of JSON ENCODING clause
- */
-typedef enum JsonEncoding
-{
-	JS_ENC_DEFAULT,				/* unspecified */
-	JS_ENC_UTF8,
-	JS_ENC_UTF16,
-	JS_ENC_UTF32,
-} JsonEncoding;
-
-/*
- * JsonFormatType -
- *		enumeration of JSON formats used in JSON FORMAT clause
- */
-typedef enum JsonFormatType
-{
-	JS_FORMAT_DEFAULT,			/* unspecified */
-	JS_FORMAT_JSON,				/* FORMAT JSON [ENCODING ...] */
-	JS_FORMAT_JSONB				/* implicit internal format for RETURNING
-								 * jsonb */
-} JsonFormatType;
-
-/*
- * JsonBehaviorType -
- *		enumeration of behavior types used in JSON ON ... BEHAVIOR clause
- *
- * 		If enum members are reordered, get_json_behavior() from ruleutils.c
- * 		must be updated accordingly.
- */
-typedef enum JsonBehaviorType
-{
-	JSON_BEHAVIOR_NULL = 0,
-	JSON_BEHAVIOR_ERROR,
-	JSON_BEHAVIOR_EMPTY,
-	JSON_BEHAVIOR_TRUE,
-	JSON_BEHAVIOR_FALSE,
-	JSON_BEHAVIOR_UNKNOWN,
-	JSON_BEHAVIOR_EMPTY_ARRAY,
-	JSON_BEHAVIOR_EMPTY_OBJECT,
-	JSON_BEHAVIOR_DEFAULT
-} JsonBehaviorType;
-
-/*
- * JsonWrapper -
- *		representation of WRAPPER clause for JSON_QUERY()
- */
-typedef enum JsonWrapper
-{
-	JSW_NONE,
-	JSW_CONDITIONAL,
-	JSW_UNCONDITIONAL,
-} JsonWrapper;
-
-/*
- * JsonFormat -
- *		representation of JSON FORMAT clause
- */
-typedef struct JsonFormat
-{
-	NodeTag		type;
-	JsonFormatType format_type; /* format type */
-	JsonEncoding encoding;		/* JSON encoding */
-	int			location;		/* token location, or -1 if unknown */
-} JsonFormat;
-
-/*
- * JsonReturning -
- *		transformed representation of JSON RETURNING clause
- */
-typedef struct JsonReturning
-{
-	NodeTag		type;
-	JsonFormat *format;			/* output JSON format */
-	Oid			typid;			/* target type Oid */
-	int32		typmod;			/* target type modifier */
-} JsonReturning;
-
-/*
- * JsonValueExpr -
- *		representation of JSON value expression (expr [FORMAT json_format])
- */
-typedef struct JsonValueExpr
-{
-	NodeTag		type;
-	Expr	   *raw_expr;		/* raw expression */
-	Expr	   *formatted_expr; /* formatted expression or NULL */
-	JsonFormat *format;			/* FORMAT clause, if specified */
-} JsonValueExpr;
-
-typedef enum JsonConstructorType
-{
-	JSCTOR_JSON_OBJECT = 1,
-	JSCTOR_JSON_ARRAY = 2,
-	JSCTOR_JSON_OBJECTAGG = 3,
-	JSCTOR_JSON_ARRAYAGG = 4,
-	JSCTOR_JSON_SCALAR = 5,
-	JSCTOR_JSON_SERIALIZE = 6,
-	JSCTOR_JSON_PARSE = 7
-} JsonConstructorType;
-
-/*
- * JsonConstructorExpr -
- *		wrapper over FuncExpr/Aggref/WindowFunc for SQL/JSON constructors
- */
-typedef struct JsonConstructorExpr
-{
-	Expr		xpr;
-	JsonConstructorType type;	/* constructor type */
-	List	   *args;
-	Expr	   *func;			/* underlying json[b]_xxx() function call */
-	Expr	   *coercion;		/* coercion to RETURNING type */
-	JsonReturning *returning;	/* RETURNING clause */
-	bool		absent_on_null; /* ABSENT ON NULL? */
-	bool		unique;			/* WITH UNIQUE KEYS? (JSON_OBJECT[AGG] only) */
-	int			location;
-} JsonConstructorExpr;
-
-/*
- * JsonValueType -
- *		representation of JSON item type in IS JSON predicate
- */
-typedef enum JsonValueType
-{
-	JS_TYPE_ANY,				/* IS JSON [VALUE] */
-	JS_TYPE_OBJECT,				/* IS JSON OBJECT */
-	JS_TYPE_ARRAY,				/* IS JSON ARRAY */
-	JS_TYPE_SCALAR				/* IS JSON SCALAR */
-} JsonValueType;
-
-/*
- * JsonIsPredicate -
- *		representation of IS JSON predicate
- */
-typedef struct JsonIsPredicate
-{
-	NodeTag		type;
-	Node	   *expr;			/* subject expression */
-	JsonFormat *format;			/* FORMAT clause, if specified */
-	JsonValueType item_type;	/* JSON item type */
-	bool		unique_keys;	/* check key uniqueness? */
-	int			location;		/* token location, or -1 if unknown */
-} JsonIsPredicate;
-
-/*
- * JsonBehavior -
- *		representation of JSON ON ... BEHAVIOR clause
- */
-typedef struct JsonBehavior
-{
-	NodeTag		type;
-	JsonBehaviorType btype;		/* behavior type */
-	Node	   *default_expr;	/* default expression, if any */
-} JsonBehavior;
-
-/*
- * JsonCoercion -
- *		coercion from SQL/JSON item types to SQL types
- */
-typedef struct JsonCoercion
-{
-	NodeTag		type;
-	Node	   *expr;			/* resulting expression coerced to target type */
-	bool		via_populate;	/* coerce result using json_populate_type()? */
-	bool		via_io;			/* coerce result using type input function? */
-	Oid			collation;		/* collation for coercion via I/O or populate */
-} JsonCoercion;
-
-/*
- * JsonItemCoercions -
- *		expressions for coercion from SQL/JSON item types directly to the
- *		output SQL type
- */
-typedef struct JsonItemCoercions
-{
-	NodeTag		type;
-	JsonCoercion *null;
-	JsonCoercion *string;
-	JsonCoercion *numeric;
-	JsonCoercion *boolean;
-	JsonCoercion *date;
-	JsonCoercion *time;
-	JsonCoercion *timetz;
-	JsonCoercion *timestamp;
-	JsonCoercion *timestamptz;
-	JsonCoercion *composite;	/* arrays and objects */
-} JsonItemCoercions;
-
-/*
- * JsonExpr -
- *		transformed representation of JSON_VALUE(), JSON_QUERY(), JSON_EXISTS()
- */
-typedef struct JsonExpr
-{
-	Expr		xpr;
-	JsonExprOp	op;				/* json function ID */
-	Node	   *formatted_expr; /* formatted context item expression */
-	JsonCoercion *result_coercion;	/* resulting coercion to RETURNING type */
-	JsonFormat *format;			/* context item format (JSON/JSONB) */
-	Node	   *path_spec;		/* JSON path specification expression */
-	List	   *passing_names;	/* PASSING argument names */
-	List	   *passing_values; /* PASSING argument values */
-	JsonReturning *returning;	/* RETURNING clause type/format info */
-	JsonBehavior *on_empty;		/* ON EMPTY behavior */
-	JsonBehavior *on_error;		/* ON ERROR behavior */
-	JsonItemCoercions *coercions;	/* coercions for JSON_VALUE */
-	JsonWrapper wrapper;		/* WRAPPER for JSON_QUERY */
-	bool		omit_quotes;	/* KEEP/OMIT QUOTES for JSON_QUERY */
-	int			location;		/* token location, or -1 if unknown */
-} JsonExpr;
-
-/*
- * JsonTableParent -
- *		transformed representation of parent JSON_TABLE plan node
- */
-typedef struct JsonTableParent
-{
-	NodeTag		type;
-	Const	   *path;			/* jsonpath constant */
-	char	   *name;			/* path name */
-	Node	   *child;			/* nested columns, if any */
-	bool		outerJoin;		/* outer or inner join for nested columns? */
-	int			colMin;			/* min column index in the resulting column
-								 * list */
-	int			colMax;			/* max column index in the resulting column
-								 * list */
-	bool		errorOnError;	/* ERROR/EMPTY ON ERROR behavior */
-} JsonTableParent;
-
-/*
- * JsonTableSibling -
- *		transformed representation of joined sibling JSON_TABLE plan node
- */
-typedef struct JsonTableSibling
-{
-	NodeTag		type;
-	Node	   *larg;			/* left join node */
-	Node	   *rarg;			/* right join node */
-	bool		cross;			/* cross or union join? */
-} JsonTableSibling;
-
 /* ----------------
  * NullTest
  *
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index ae35f03251..9a7cc0c6bd 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -26,7 +26,6 @@
 
 /* name, value, category, is-bare-label */
 PG_KEYWORD("abort", ABORT_P, UNRESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("absent", ABSENT, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("absolute", ABSOLUTE_P, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("access", ACCESS, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("action", ACTION, UNRESERVED_KEYWORD, BARE_LABEL)
@@ -93,7 +92,6 @@ PG_KEYWORD("commit", COMMIT, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("committed", COMMITTED, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("compression", COMPRESSION, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("concurrently", CONCURRENTLY, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("conditional", CONDITIONAL, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("configuration", CONFIGURATION, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("conflict", CONFLICT, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("connection", CONNECTION, UNRESERVED_KEYWORD, BARE_LABEL)
@@ -148,13 +146,11 @@ PG_KEYWORD("double", DOUBLE_P, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("drop", DROP, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("each", EACH, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("else", ELSE, RESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("empty", EMPTY_P, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("enable", ENABLE_P, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("encoding", ENCODING, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("encrypted", ENCRYPTED, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("end", END_P, RESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("enum", ENUM_P, UNRESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("error", ERROR_P, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("escape", ESCAPE, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("event", EVENT, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("except", EXCEPT, RESERVED_KEYWORD, AS_LABEL)
@@ -179,7 +175,6 @@ PG_KEYWORD("following", FOLLOWING, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("for", FOR, RESERVED_KEYWORD, AS_LABEL)
 PG_KEYWORD("force", FORCE, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("foreign", FOREIGN, RESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("format", FORMAT, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("forward", FORWARD, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("freeze", FREEZE, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
 PG_KEYWORD("from", FROM, RESERVED_KEYWORD, AS_LABEL)
@@ -232,20 +227,7 @@ PG_KEYWORD("is", IS, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
 PG_KEYWORD("isnull", ISNULL, TYPE_FUNC_NAME_KEYWORD, AS_LABEL)
 PG_KEYWORD("isolation", ISOLATION, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("join", JOIN, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("json", JSON, COL_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("json_array", JSON_ARRAY, COL_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("json_arrayagg", JSON_ARRAYAGG, COL_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("json_exists", JSON_EXISTS, COL_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("json_object", JSON_OBJECT, COL_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("json_objectagg", JSON_OBJECTAGG, COL_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("json_query", JSON_QUERY, COL_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("json_scalar", JSON_SCALAR, COL_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("json_serialize", JSON_SERIALIZE, COL_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("json_table", JSON_TABLE, COL_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("json_value", JSON_VALUE, COL_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("keep", KEEP, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("key", KEY, UNRESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("keys", KEYS, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("label", LABEL, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("language", LANGUAGE, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("large", LARGE_P, UNRESERVED_KEYWORD, BARE_LABEL)
@@ -284,7 +266,6 @@ PG_KEYWORD("names", NAMES, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("national", NATIONAL, COL_NAME_KEYWORD, BARE_LABEL)
 PG_KEYWORD("natural", NATURAL, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL)
 PG_KEYWORD("nchar", NCHAR, COL_NAME_KEYWORD, BARE_LABEL)
-PG_KEYWORD("nested", NESTED, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("new", NEW, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("next", NEXT, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("nfc", NFC, UNRESERVED_KEYWORD, BARE_LABEL)
@@ -310,7 +291,6 @@ PG_KEYWORD("off", OFF, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("offset", OFFSET, RESERVED_KEYWORD, AS_LABEL)
 PG_KEYWORD("oids", OIDS, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("old", OLD, UNRESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("omit", OMIT, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("on", ON, RESERVED_KEYWORD, AS_LABEL)
 PG_KEYWORD("only", ONLY, RESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("operator", OPERATOR, UNRESERVED_KEYWORD, BARE_LABEL)
@@ -335,9 +315,7 @@ PG_KEYWORD("partial", PARTIAL, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("partition", PARTITION, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("passing", PASSING, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("password", PASSWORD, UNRESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("path", PATH, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("placing", PLACING, RESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("plan", PLAN, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("plans", PLANS, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("policy", POLICY, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("position", POSITION, COL_NAME_KEYWORD, BARE_LABEL)
@@ -355,7 +333,6 @@ PG_KEYWORD("procedures", PROCEDURES, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("program", PROGRAM, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("publication", PUBLICATION, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("quote", QUOTE, UNRESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("quotes", QUOTES, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("range", RANGE, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("read", READ, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("real", REAL, COL_NAME_KEYWORD, BARE_LABEL)
@@ -390,7 +367,6 @@ PG_KEYWORD("row", ROW, COL_NAME_KEYWORD, BARE_LABEL)
 PG_KEYWORD("rows", ROWS, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("rule", RULE, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("savepoint", SAVEPOINT, UNRESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("scalar", SCALAR, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("schema", SCHEMA, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("schemas", SCHEMAS, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("scroll", SCROLL, UNRESERVED_KEYWORD, BARE_LABEL)
@@ -426,7 +402,6 @@ PG_KEYWORD("stdout", STDOUT, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("storage", STORAGE, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("stored", STORED, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("strict", STRICT_P, UNRESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("string", STRING, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("strip", STRIP_P, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("subscription", SUBSCRIPTION, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("substring", SUBSTRING, COL_NAME_KEYWORD, BARE_LABEL)
@@ -461,7 +436,6 @@ PG_KEYWORD("types", TYPES_P, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("uescape", UESCAPE, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("unbounded", UNBOUNDED, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("uncommitted", UNCOMMITTED, UNRESERVED_KEYWORD, BARE_LABEL)
-PG_KEYWORD("unconditional", UNCONDITIONAL, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("unencrypted", UNENCRYPTED, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("union", UNION, RESERVED_KEYWORD, AS_LABEL)
 PG_KEYWORD("unique", UNIQUE, RESERVED_KEYWORD, BARE_LABEL)
diff --git a/src/include/parser/parse_clause.h b/src/include/parser/parse_clause.h
index e86b002392..2495c30034 100644
--- a/src/include/parser/parse_clause.h
+++ b/src/include/parser/parse_clause.h
@@ -51,7 +51,4 @@ extern List *addTargetToSortList(ParseState *pstate, TargetEntry *tle,
 extern Index assignSortGroupRef(TargetEntry *tle, List *tlist);
 extern bool targetIsInSortList(TargetEntry *tle, Oid sortop, List *sortList);
 
-/* functions in parse_jsontable.c */
-extern ParseNamespaceItem *transformJsonTable(ParseState *pstate, JsonTable *jt);
-
 #endif							/* PARSE_CLAUSE_H */
diff --git a/src/include/utils/formatting.h b/src/include/utils/formatting.h
index f048eb0869..851e787bfd 100644
--- a/src/include/utils/formatting.h
+++ b/src/include/utils/formatting.h
@@ -17,9 +17,6 @@
 #ifndef _FORMATTING_H_
 #define _FORMATTING_H_
 
-#define DCH_DATED	0x01
-#define DCH_TIMED	0x02
-#define DCH_ZONED	0x04
 
 extern char *str_tolower(const char *buff, size_t nbytes, Oid collid);
 extern char *str_toupper(const char *buff, size_t nbytes, Oid collid);
@@ -32,6 +29,5 @@ extern char *asc_initcap(const char *buff, size_t nbytes);
 extern Datum parse_datetime(text *date_txt, text *fmt, Oid collid, bool strict,
 							Oid *typid, int32 *typmod, int *tz,
 							bool *have_error);
-extern int	datetime_format_flags(const char *fmt_str, bool *have_error);
 
 #endif
diff --git a/src/include/utils/json.h b/src/include/utils/json.h
index da4a9257b3..8a84a0cdb4 100644
--- a/src/include/utils/json.h
+++ b/src/include/utils/json.h
@@ -16,35 +16,9 @@
 
 #include "lib/stringinfo.h"
 
-typedef enum					/* type categories for datum_to_json */
-{
-	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;
-
 /* functions in json.c */
 extern void escape_json(StringInfo buf, const char *str);
 extern char *JsonEncodeDateTime(char *buf, Datum value, Oid typid,
 								const int *tzp);
-extern bool to_json_is_immutable(Oid typoid);
-extern void json_categorize_type(Oid typoid, JsonTypeCategory *tcategory,
-								 Oid *outfuncoid);
-extern Datum to_json_worker(Datum val, JsonTypeCategory tcategory,
-							Oid outfuncoid);
-extern Datum json_build_object_worker(int nargs, Datum *args, bool *nulls,
-									  Oid *types, bool absent_on_null,
-									  bool unique_keys);
-extern Datum json_build_array_worker(int nargs, Datum *args, bool *nulls,
-									 Oid *types, bool absent_on_null);
-extern bool json_validate(text *json, bool check_unique_keys, bool throw_error);
 
 #endif							/* JSON_H */
diff --git a/src/include/utils/jsonb.h b/src/include/utils/jsonb.h
index bae466b523..4cbe6edf21 100644
--- a/src/include/utils/jsonb.h
+++ b/src/include/utils/jsonb.h
@@ -329,8 +329,6 @@ typedef struct JsonbParseState
 	JsonbValue	contVal;
 	Size		size;
 	struct JsonbParseState *next;
-	bool		unique_keys;	/* Check object key uniqueness */
-	bool		skip_nulls;		/* Skip null object fields */
 } JsonbParseState;
 
 /*
@@ -376,22 +374,6 @@ typedef struct JsonbIterator
 	struct JsonbIterator *parent;
 } JsonbIterator;
 
-/* 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;
 
 /* Support functions */
 extern uint32 getJsonbOffset(const JsonbContainer *jc, int index);
@@ -419,14 +401,10 @@ extern void JsonbHashScalarValueExtended(const JsonbValue *scalarVal,
 										 uint64 *hash, uint64 seed);
 
 /* jsonb.c support functions */
-extern Datum jsonb_from_text(text *js, bool unique_keys);
 extern char *JsonbToCString(StringInfo out, JsonbContainer *in,
 							int estimated_len);
 extern char *JsonbToCStringIndent(StringInfo out, JsonbContainer *in,
 								  int estimated_len);
-extern Jsonb *JsonbMakeEmptyArray(void);
-extern Jsonb *JsonbMakeEmptyObject(void);
-extern char *JsonbUnquote(Jsonb *jb);
 extern bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res);
 extern const char *JsonbTypeName(JsonbValue *jb);
 
@@ -434,15 +412,4 @@ extern Datum jsonb_set_element(Jsonb *jb, Datum *path, int path_len,
 							   JsonbValue *newval);
 extern Datum jsonb_get_element(Jsonb *jb, Datum *path, int npath,
 							   bool *isnull, bool as_text);
-extern bool to_jsonb_is_immutable(Oid typoid);
-extern void jsonb_categorize_type(Oid typoid, JsonbTypeCategory *tcategory,
-								  Oid *outfuncoid);
-extern Datum to_jsonb_worker(Datum val, JsonbTypeCategory tcategory,
-							 Oid outfuncoid);
-extern Datum jsonb_build_object_worker(int nargs, Datum *args, bool *nulls,
-									   Oid *types, bool absent_on_null,
-									   bool unique_keys);
-extern Datum jsonb_build_array_worker(int nargs, Datum *args, bool *nulls,
-									  Oid *types, bool absent_on_null);
-
 #endif							/* __JSONB_H__ */
diff --git a/src/include/utils/jsonfuncs.h b/src/include/utils/jsonfuncs.h
index 62dc3d88a4..865b2ff7c1 100644
--- a/src/include/utils/jsonfuncs.h
+++ b/src/include/utils/jsonfuncs.h
@@ -45,9 +45,6 @@ extern void pg_parse_json_or_ereport(JsonLexContext *lex, JsonSemAction *sem);
 /* report an error during json lexing or parsing */
 extern void json_ereport_error(JsonParseErrorType error, JsonLexContext *lex);
 
-/* get first JSON token */
-extern JsonTokenType json_get_first_token(text *json, bool throw_error);
-
 extern uint32 parse_jsonb_index_flags(Jsonb *jb);
 extern void iterate_jsonb_values(Jsonb *jb, uint32 flags, void *state,
 								 JsonIterateStringValuesAction action);
@@ -58,8 +55,4 @@ extern Jsonb *transform_jsonb_string_values(Jsonb *jsonb, void *action_state,
 extern text *transform_json_string_values(text *json, void *action_state,
 										  JsonTransformStringValuesAction transform_action);
 
-extern Datum json_populate_type(Datum json_val, Oid json_type,
-								Oid typid, int32 typmod,
-								void **cache, MemoryContext mcxt, bool *isnull);
-
 #endif
diff --git a/src/include/utils/jsonpath.h b/src/include/utils/jsonpath.h
index 8e79b8dc9f..cd0b5d5b61 100644
--- a/src/include/utils/jsonpath.h
+++ b/src/include/utils/jsonpath.h
@@ -15,11 +15,8 @@
 #define JSONPATH_H
 
 #include "fmgr.h"
-#include "executor/tablefunc.h"
 #include "nodes/pg_list.h"
-#include "nodes/primnodes.h"
 #include "utils/jsonb.h"
-#include "utils/jsonfuncs.h"
 
 typedef struct
 {
@@ -177,7 +174,6 @@ extern bool jspGetBool(JsonPathItem *v);
 extern char *jspGetString(JsonPathItem *v, int32 *len);
 extern bool jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from,
 								 JsonPathItem *to, int i);
-extern bool jspIsMutable(JsonPath *path, List *varnames, List *varexprs);
 
 extern const char *jspOperationName(JsonPathItemType type);
 
@@ -252,37 +248,4 @@ extern JsonPathParseResult *parsejsonpath(const char *str, int len);
 
 extern int	jspConvertRegexFlags(uint32 xflags);
 
-/*
- * Evaluation of jsonpath
- */
-
-/* External variable passed into jsonpath. */
-typedef struct JsonPathVariableEvalContext
-{
-	char	   *name;
-	Oid			typid;
-	int32		typmod;
-	struct ExprContext *econtext;
-	struct ExprState *estate;
-	MemoryContext mcxt;			/* memory context for cached value */
-	Datum		value;
-	bool		isnull;
-	bool		evaluated;
-} JsonPathVariableEvalContext;
-
-/* SQL/JSON item */
-extern void JsonItemFromDatum(Datum val, Oid typid, int32 typmod,
-							  JsonbValue *res);
-
-extern bool JsonPathExists(Datum jb, JsonPath *path, List *vars, bool *error);
-extern Datum JsonPathQuery(Datum jb, JsonPath *jp, JsonWrapper wrapper,
-						   bool *empty, bool *error, List *vars);
-extern JsonbValue *JsonPathValue(Datum jb, JsonPath *jp, bool *empty,
-								 bool *error, List *vars);
-
-extern int	EvalJsonPathVar(void *vars, char *varName, int varNameLen,
-							JsonbValue *val, JsonbValue *baseObject);
-
-extern PGDLLIMPORT const TableFuncRoutine JsonbTableRoutine;
-
 #endif
diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer
index fba35f6be6..0b100b9b04 100644
--- a/src/interfaces/ecpg/preproc/ecpg.trailer
+++ b/src/interfaces/ecpg/preproc/ecpg.trailer
@@ -657,34 +657,6 @@ var_type:	simple_type
 			$$.type_index = mm_strdup("-1");
 			$$.type_sizeof = NULL;
 		}
-		| STRING
-		{
-			if (INFORMIX_MODE)
-			{
-				/* In Informix mode, "string" is automatically a typedef */
-				$$.type_enum = ECPGt_string;
-				$$.type_str = mm_strdup("char");
-				$$.type_dimension = mm_strdup("-1");
-				$$.type_index = mm_strdup("-1");
-				$$.type_sizeof = NULL;
-			}
-			else
-			{
-				/* Otherwise, legal only if user typedef'ed it */
-				struct typedefs *this = get_typedef("string", false);
-
-				$$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? EMPTY : mm_strdup(this->name);
-				$$.type_enum = this->type->type_enum;
-				$$.type_dimension = this->type->type_dimension;
-				$$.type_index = this->type->type_index;
-				if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
-					$$.type_sizeof = this->type->type_sizeof;
-				else
-					$$.type_sizeof = cat_str(3, mm_strdup("sizeof("), mm_strdup(this->name), mm_strdup(")"));
-
-				struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
-			}
-		}
 		| IDENT ecpg_interval
 		{
 			/*
diff --git a/src/interfaces/ecpg/preproc/parse.pl b/src/interfaces/ecpg/preproc/parse.pl
index 8de5c4457b..8925e24a30 100644
--- a/src/interfaces/ecpg/preproc/parse.pl
+++ b/src/interfaces/ecpg/preproc/parse.pl
@@ -58,8 +58,6 @@ my %replace_string = (
 	'NOT_LA'         => 'not',
 	'NULLS_LA'       => 'nulls',
 	'WITH_LA'        => 'with',
-	'WITH_LA_UNIQUE' => 'with',
-	'WITHOUT_LA'     => 'without',
 	'TYPECAST'       => '::',
 	'DOT_DOT'        => '..',
 	'COLON_EQUALS'   => ':=',
diff --git a/src/interfaces/ecpg/preproc/parser.c b/src/interfaces/ecpg/preproc/parser.c
index 5e2b606f9b..a44e07a17a 100644
--- a/src/interfaces/ecpg/preproc/parser.c
+++ b/src/interfaces/ecpg/preproc/parser.c
@@ -83,7 +83,6 @@ filtered_base_yylex(void)
 		case WITH:
 		case UIDENT:
 		case USCONST:
-		case WITHOUT:
 			break;
 		default:
 			return cur_token;
@@ -144,19 +143,6 @@ filtered_base_yylex(void)
 				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;
 		case UIDENT:
diff --git a/src/test/regress/expected/json_sqljson.out b/src/test/regress/expected/json_sqljson.out
deleted file mode 100644
index 995f267404..0000000000
--- a/src/test/regress/expected/json_sqljson.out
+++ /dev/null
@@ -1,24 +0,0 @@
--- JSON_EXISTS
-SELECT JSON_EXISTS(NULL FORMAT JSON, '$');
-ERROR:  JSON_EXISTS() is not yet implemented for the json type
-LINE 1: SELECT JSON_EXISTS(NULL FORMAT JSON, '$');
-               ^
-HINT:  Try casting the argument to jsonb
--- JSON_VALUE
-SELECT JSON_VALUE(NULL FORMAT JSON, '$');
-ERROR:  JSON_VALUE() is not yet implemented for the json type
-LINE 1: SELECT JSON_VALUE(NULL FORMAT JSON, '$');
-               ^
-HINT:  Try casting the argument to jsonb
--- JSON_QUERY
-SELECT JSON_QUERY(NULL FORMAT JSON, '$');
-ERROR:  JSON_QUERY() is not yet implemented for the json type
-LINE 1: SELECT JSON_QUERY(NULL FORMAT JSON, '$');
-               ^
-HINT:  Try casting the argument to jsonb
--- JSON_TABLE
-SELECT * FROM JSON_TABLE(NULL FORMAT JSON, '$' COLUMNS (foo text));
-ERROR:  JSON_TABLE() is not yet implemented for the json type
-LINE 1: SELECT * FROM JSON_TABLE(NULL FORMAT JSON, '$' COLUMNS (foo ...
-                                 ^
-HINT:  Try casting the argument to jsonb
diff --git a/src/test/regress/expected/jsonb_sqljson.out b/src/test/regress/expected/jsonb_sqljson.out
deleted file mode 100644
index ef496110af..0000000000
--- a/src/test/regress/expected/jsonb_sqljson.out
+++ /dev/null
@@ -1,2135 +0,0 @@
--- JSON_EXISTS
-SELECT JSON_EXISTS(NULL::jsonb, '$');
- json_exists 
--------------
- 
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '[]', '$');
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_EXISTS(JSON_OBJECT(RETURNING jsonb), '$');
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', '$');
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_EXISTS(jsonb 'null', '$');
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '[]', '$');
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', '$.a');
- json_exists 
--------------
- f
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', 'strict $.a');
- json_exists 
--------------
- f
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', 'strict $.a' ERROR ON ERROR);
-ERROR:  jsonpath member accessor can only be applied to an object
-SELECT JSON_EXISTS(jsonb 'null', '$.a');
- json_exists 
--------------
- f
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '[]', '$.a');
- json_exists 
--------------
- f
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '[1, "aaa", {"a": 1}]', 'strict $.a');
- json_exists 
--------------
- f
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '[1, "aaa", {"a": 1}]', 'lax $.a');
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '{}', '$.a');
- json_exists 
--------------
- f
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '{"b": 1, "a": 2}', '$.a');
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', '$.a.b');
- json_exists 
--------------
- f
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '{"a": {"b": 1}}', '$.a.b');
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '{"a": 1, "b": 2}', '$.a.b');
- json_exists 
--------------
- f
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '{"a": 1, "b": 2}', '$.* ? (@ > $x)' PASSING 1 AS x);
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '{"a": 1, "b": 2}', '$.* ? (@ > $x)' PASSING '1' AS x);
- json_exists 
--------------
- f
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '{"a": 1, "b": 2}', '$.* ? (@ > $x && @ < $y)' PASSING 0 AS x, 2 AS y);
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '{"a": 1, "b": 2}', '$.* ? (@ > $x && @ < $y)' PASSING 0 AS x, 1 AS y);
- json_exists 
--------------
- f
-(1 row)
-
--- extension: boolean expressions
-SELECT JSON_EXISTS(jsonb '1', '$ > 2');
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', '$.a > 2' ERROR ON ERROR);
- json_exists 
--------------
- t
-(1 row)
-
--- extension: RETURNING clause
-SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING bool);
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', '$[1]' RETURNING bool);
- json_exists 
--------------
- f
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING int);
- json_exists 
--------------
-           1
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', '$[1]' RETURNING int);
- json_exists 
--------------
-           0
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING text);
- json_exists 
--------------
- true
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', '$[1]' RETURNING text);
- json_exists 
--------------
- false
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', 'strict $[1]' RETURNING text FALSE ON ERROR);
- json_exists 
--------------
- false
-(1 row)
-
-SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING jsonb);
-ERROR:  cannot cast type boolean to jsonb
-LINE 1: SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING jsonb);
-               ^
-SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING float4);
-ERROR:  cannot cast type boolean to real
-LINE 1: SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING float4);
-               ^
--- JSON_VALUE
-SELECT JSON_VALUE(NULL::jsonb, '$');
- json_value 
-------------
- 
-(1 row)
-
-SELECT JSON_VALUE(jsonb 'null', '$');
- json_value 
-------------
- 
-(1 row)
-
-SELECT JSON_VALUE(jsonb 'null', '$' RETURNING int);
- json_value 
-------------
-           
-(1 row)
-
-SELECT JSON_VALUE(jsonb 'true', '$');
- json_value 
-------------
- true
-(1 row)
-
-SELECT JSON_VALUE(jsonb 'true', '$' RETURNING bool);
- json_value 
-------------
- t
-(1 row)
-
-SELECT JSON_VALUE(jsonb '123', '$');
- json_value 
-------------
- 123
-(1 row)
-
-SELECT JSON_VALUE(jsonb '123', '$' RETURNING int) + 234;
- ?column? 
-----------
-      357
-(1 row)
-
-SELECT JSON_VALUE(jsonb '123', '$' RETURNING text);
- json_value 
-------------
- 123
-(1 row)
-
-/* jsonb bytea ??? */
-SELECT JSON_VALUE(jsonb '123', '$' RETURNING bytea ERROR ON ERROR);
-ERROR:  SQL/JSON item cannot be cast to target type
-SELECT JSON_VALUE(jsonb '1.23', '$');
- json_value 
-------------
- 1.23
-(1 row)
-
-SELECT JSON_VALUE(jsonb '1.23', '$' RETURNING int);
- json_value 
-------------
-          1
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"1.23"', '$' RETURNING numeric);
- json_value 
-------------
-       1.23
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"1.23"', '$' RETURNING int ERROR ON ERROR);
-ERROR:  invalid input syntax for type integer: "1.23"
-SELECT JSON_VALUE(jsonb '"aaa"', '$');
- json_value 
-------------
- aaa
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING text);
- json_value 
-------------
- aaa
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING char(5));
- json_value 
-------------
- aaa  
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING char(2));
- json_value 
-------------
- aa
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING json);
- json_value 
-------------
- "aaa"
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING jsonb);
- json_value 
-------------
- "aaa"
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING json ERROR ON ERROR);
- json_value 
-------------
- "aaa"
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING jsonb ERROR ON ERROR);
- json_value 
-------------
- "aaa"
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"\"aaa\""', '$' RETURNING json);
- json_value 
-------------
- "\"aaa\""
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"\"aaa\""', '$' RETURNING jsonb);
- json_value 
-------------
- "\"aaa\""
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING int);
- json_value 
-------------
-           
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING int ERROR ON ERROR);
-ERROR:  invalid input syntax for type integer: "aaa"
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING int DEFAULT 111 ON ERROR);
- json_value 
-------------
-        111
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"123"', '$' RETURNING int) + 234;
- ?column? 
-----------
-      357
-(1 row)
-
-SELECT JSON_VALUE(jsonb '"2017-02-20"', '$' RETURNING date) + 9;
-  ?column?  
-------------
- 03-01-2017
-(1 row)
-
--- Test NULL checks execution in domain types
-CREATE DOMAIN sqljsonb_int_not_null AS int NOT NULL;
-SELECT JSON_VALUE(jsonb '1', '$.a' RETURNING sqljsonb_int_not_null);
-ERROR:  domain sqljsonb_int_not_null does not allow null values
-SELECT JSON_VALUE(jsonb '1', '$.a' RETURNING sqljsonb_int_not_null NULL ON ERROR);
-ERROR:  domain sqljsonb_int_not_null does not allow null values
-SELECT JSON_VALUE(jsonb '1', '$.a' RETURNING sqljsonb_int_not_null DEFAULT NULL ON ERROR);
-ERROR:  domain sqljsonb_int_not_null does not allow null values
-SELECT JSON_VALUE(jsonb '[]', '$');
- json_value 
-------------
- 
-(1 row)
-
-SELECT JSON_VALUE(jsonb '[]', '$' ERROR ON ERROR);
-ERROR:  JSON path expression in JSON_VALUE should return singleton scalar item
-SELECT JSON_VALUE(jsonb '{}', '$');
- json_value 
-------------
- 
-(1 row)
-
-SELECT JSON_VALUE(jsonb '{}', '$' ERROR ON ERROR);
-ERROR:  JSON path expression in JSON_VALUE should return singleton scalar item
-SELECT JSON_VALUE(jsonb '1', '$.a');
- json_value 
-------------
- 
-(1 row)
-
-SELECT JSON_VALUE(jsonb '1', 'strict $.a' ERROR ON ERROR);
-ERROR:  jsonpath member accessor can only be applied to an object
-SELECT JSON_VALUE(jsonb '1', 'strict $.a' DEFAULT 'error' ON ERROR);
- json_value 
-------------
- error
-(1 row)
-
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' ERROR ON ERROR);
- json_value 
-------------
- 
-(1 row)
-
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' ERROR ON EMPTY ERROR ON ERROR);
-ERROR:  no SQL/JSON item
-SELECT JSON_VALUE(jsonb '1', 'strict $.a' DEFAULT 2 ON ERROR);
- json_value 
-------------
- 2
-(1 row)
-
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' DEFAULT 2 ON ERROR);
- json_value 
-------------
- 
-(1 row)
-
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' DEFAULT '2' ON ERROR);
- json_value 
-------------
- 
-(1 row)
-
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' NULL ON EMPTY DEFAULT '2' ON ERROR);
- json_value 
-------------
- 
-(1 row)
-
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' DEFAULT '2' ON EMPTY DEFAULT '3' ON ERROR);
- json_value 
-------------
- 2
-(1 row)
-
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' ERROR ON EMPTY DEFAULT '3' ON ERROR);
- json_value 
-------------
- 3
-(1 row)
-
-SELECT JSON_VALUE(jsonb '[1,2]', '$[*]' ERROR ON ERROR);
-ERROR:  JSON path expression in JSON_VALUE should return singleton scalar item
-SELECT JSON_VALUE(jsonb '[1,2]', '$[*]' DEFAULT '0' ON ERROR);
- json_value 
-------------
- 0
-(1 row)
-
-SELECT JSON_VALUE(jsonb '[" "]', '$[*]' RETURNING int ERROR ON ERROR);
-ERROR:  invalid input syntax for type integer: " "
-SELECT JSON_VALUE(jsonb '[" "]', '$[*]' RETURNING int DEFAULT 2 + 3 ON ERROR);
- json_value 
-------------
-          5
-(1 row)
-
-SELECT JSON_VALUE(jsonb '["1"]', '$[*]' RETURNING int DEFAULT 2 + 3 ON ERROR);
- json_value 
-------------
-          1
-(1 row)
-
-SELECT
-	x,
-	JSON_VALUE(
-		jsonb '{"a": 1, "b": 2}',
-		'$.* ? (@ > $x)' PASSING x AS x
-		RETURNING int
-		DEFAULT -1 ON EMPTY
-		DEFAULT -2 ON ERROR
-	) y
-FROM
-	generate_series(0, 2) x;
- x | y  
----+----
- 0 | -2
- 1 |  2
- 2 | -1
-(3 rows)
-
-SELECT JSON_VALUE(jsonb 'null', '$a' PASSING point ' (1, 2 )' AS a);
- json_value 
-------------
- (1,2)
-(1 row)
-
-SELECT JSON_VALUE(jsonb 'null', '$a' PASSING point ' (1, 2 )' AS a RETURNING point);
- json_value 
-------------
- (1,2)
-(1 row)
-
--- Test timestamptz passing and output
-SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts);
-          json_value          
-------------------------------
- Tue Feb 20 18:34:56 2018 PST
-(1 row)
-
-SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING timestamptz);
-          json_value          
-------------------------------
- Tue Feb 20 18:34:56 2018 PST
-(1 row)
-
-SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING timestamp);
-        json_value        
---------------------------
- Tue Feb 20 18:34:56 2018
-(1 row)
-
-SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING json);
-         json_value          
------------------------------
- "2018-02-21T02:34:56+00:00"
-(1 row)
-
-SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING jsonb);
-         json_value          
------------------------------
- "2018-02-21T02:34:56+00:00"
-(1 row)
-
--- JSON_QUERY
-SELECT
-	JSON_QUERY(js, '$'),
-	JSON_QUERY(js, '$' WITHOUT WRAPPER),
-	JSON_QUERY(js, '$' WITH CONDITIONAL WRAPPER),
-	JSON_QUERY(js, '$' WITH UNCONDITIONAL ARRAY WRAPPER),
-	JSON_QUERY(js, '$' WITH ARRAY WRAPPER)
-FROM
-	(VALUES
-		(jsonb 'null'),
-		('12.3'),
-		('true'),
-		('"aaa"'),
-		('[1, null, "2"]'),
-		('{"a": 1, "b": [2]}')
-	) foo(js);
-     json_query     |     json_query     |     json_query     |      json_query      |      json_query      
---------------------+--------------------+--------------------+----------------------+----------------------
- null               | null               | [null]             | [null]               | [null]
- 12.3               | 12.3               | [12.3]             | [12.3]               | [12.3]
- true               | true               | [true]             | [true]               | [true]
- "aaa"              | "aaa"              | ["aaa"]            | ["aaa"]              | ["aaa"]
- [1, null, "2"]     | [1, null, "2"]     | [1, null, "2"]     | [[1, null, "2"]]     | [[1, null, "2"]]
- {"a": 1, "b": [2]} | {"a": 1, "b": [2]} | {"a": 1, "b": [2]} | [{"a": 1, "b": [2]}] | [{"a": 1, "b": [2]}]
-(6 rows)
-
-SELECT
-	JSON_QUERY(js, 'strict $[*]') AS "unspec",
-	JSON_QUERY(js, 'strict $[*]' WITHOUT WRAPPER) AS "without",
-	JSON_QUERY(js, 'strict $[*]' WITH CONDITIONAL WRAPPER) AS "with cond",
-	JSON_QUERY(js, 'strict $[*]' WITH UNCONDITIONAL ARRAY WRAPPER) AS "with uncond",
-	JSON_QUERY(js, 'strict $[*]' WITH ARRAY WRAPPER) AS "with"
-FROM
-	(VALUES
-		(jsonb '1'),
-		('[]'),
-		('[null]'),
-		('[12.3]'),
-		('[true]'),
-		('["aaa"]'),
-		('[[1, 2, 3]]'),
-		('[{"a": 1, "b": [2]}]'),
-		('[1, "2", null, [3]]')
-	) foo(js);
-       unspec       |      without       |      with cond      |     with uncond      |         with         
---------------------+--------------------+---------------------+----------------------+----------------------
-                    |                    |                     |                      | 
-                    |                    |                     |                      | 
- null               | null               | [null]              | [null]               | [null]
- 12.3               | 12.3               | [12.3]              | [12.3]               | [12.3]
- true               | true               | [true]              | [true]               | [true]
- "aaa"              | "aaa"              | ["aaa"]             | ["aaa"]              | ["aaa"]
- [1, 2, 3]          | [1, 2, 3]          | [1, 2, 3]           | [[1, 2, 3]]          | [[1, 2, 3]]
- {"a": 1, "b": [2]} | {"a": 1, "b": [2]} | {"a": 1, "b": [2]}  | [{"a": 1, "b": [2]}] | [{"a": 1, "b": [2]}]
-                    |                    | [1, "2", null, [3]] | [1, "2", null, [3]]  | [1, "2", null, [3]]
-(9 rows)
-
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING text);
- json_query 
-------------
- "aaa"
-(1 row)
-
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING text KEEP QUOTES);
- json_query 
-------------
- "aaa"
-(1 row)
-
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING text KEEP QUOTES ON SCALAR STRING);
- json_query 
-------------
- "aaa"
-(1 row)
-
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING text OMIT QUOTES);
- json_query 
-------------
- aaa
-(1 row)
-
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING text OMIT QUOTES ON SCALAR STRING);
- json_query 
-------------
- aaa
-(1 row)
-
-SELECT JSON_QUERY(jsonb '"aaa"', '$' OMIT QUOTES ERROR ON ERROR);
-ERROR:  invalid input syntax for type json
-DETAIL:  Token "aaa" is invalid.
-CONTEXT:  JSON data, line 1: aaa
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING json OMIT QUOTES ERROR ON ERROR);
-ERROR:  invalid input syntax for type json
-DETAIL:  Token "aaa" is invalid.
-CONTEXT:  JSON data, line 1: aaa
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING bytea FORMAT JSON OMIT QUOTES ERROR ON ERROR);
- json_query 
-------------
- \x616161
-(1 row)
-
--- QUOTES behavior should not be specified when WITH WRAPPER used:
--- Should fail
-SELECT JSON_QUERY(jsonb '[1]', '$' WITH WRAPPER OMIT QUOTES);
-ERROR:  SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used
-LINE 1: SELECT JSON_QUERY(jsonb '[1]', '$' WITH WRAPPER OMIT QUOTES)...
-                                                        ^
-SELECT JSON_QUERY(jsonb '[1]', '$' WITH WRAPPER KEEP QUOTES);
-ERROR:  SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used
-LINE 1: SELECT JSON_QUERY(jsonb '[1]', '$' WITH WRAPPER KEEP QUOTES)...
-                                                        ^
-SELECT JSON_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER KEEP QUOTES);
-ERROR:  SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used
-LINE 1: ...N_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER KEEP QUOTE...
-                                                             ^
-SELECT JSON_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER OMIT QUOTES);
-ERROR:  SQL/JSON QUOTES behavior must not be specified when WITH WRAPPER is used
-LINE 1: ...N_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER OMIT QUOTE...
-                                                             ^
--- Should succeed
-SELECT JSON_QUERY(jsonb '[1]', '$' WITHOUT WRAPPER OMIT QUOTES);
- json_query 
-------------
- [1]
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1]', '$' WITHOUT WRAPPER KEEP QUOTES);
- json_query 
-------------
- [1]
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]');
- json_query 
-------------
- 
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]' NULL ON EMPTY);
- json_query 
-------------
- 
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]' EMPTY ON EMPTY);
- json_query 
-------------
- []
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]' EMPTY ARRAY ON EMPTY);
- json_query 
-------------
- []
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]' EMPTY OBJECT ON EMPTY);
- json_query 
-------------
- {}
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON EMPTY);
- json_query 
-------------
- 
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]' DEFAULT '"empty"' ON EMPTY);
- json_query 
-------------
- "empty"
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON EMPTY NULL ON ERROR);
- json_query 
-------------
- 
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON EMPTY EMPTY ARRAY ON ERROR);
- json_query 
-------------
- []
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON EMPTY EMPTY OBJECT ON ERROR);
- json_query 
-------------
- {}
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON EMPTY ERROR ON ERROR);
-ERROR:  no SQL/JSON item
-SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON ERROR);
- json_query 
-------------
- 
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' ERROR ON ERROR);
-ERROR:  JSON path expression in JSON_QUERY should return singleton item without wrapper
-HINT:  Use WITH WRAPPER clause to wrap SQL/JSON item sequence into array.
-SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' DEFAULT '"empty"' ON ERROR);
- json_query 
-------------
- "empty"
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING json);
- json_query 
-------------
- [1, 2]
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING json FORMAT JSON);
- json_query 
-------------
- [1, 2]
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING jsonb);
- json_query 
-------------
- [1, 2]
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING jsonb FORMAT JSON);
- json_query 
-------------
- [1, 2]
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING text);
- json_query 
-------------
- [1, 2]
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING char(10));
- json_query 
-------------
- [1, 2]    
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING char(3));
- json_query 
-------------
- [1,
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING text FORMAT JSON);
- json_query 
-------------
- [1, 2]
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING bytea);
-   json_query   
-----------------
- \x5b312c20325d
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING bytea FORMAT JSON);
-   json_query   
-----------------
- \x5b312c20325d
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING bytea EMPTY OBJECT ON ERROR);
- json_query 
-------------
- \x7b7d
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING bytea FORMAT JSON EMPTY OBJECT ON ERROR);
- json_query 
-------------
- \x7b7d
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING json EMPTY OBJECT ON ERROR);
- json_query 
-------------
- {}
-(1 row)
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING jsonb EMPTY OBJECT ON ERROR);
- json_query 
-------------
- {}
-(1 row)
-
-SELECT
-	x, y,
-	JSON_QUERY(
-		jsonb '[1,2,3,4,5,null]',
-		'$[*] ? (@ >= $x && @ <= $y)'
-		PASSING x AS x, y AS y
-		WITH CONDITIONAL WRAPPER
-		EMPTY ARRAY ON EMPTY
-	) list
-FROM
-	generate_series(0, 4) x,
-	generate_series(0, 4) y;
- x | y |     list     
----+---+--------------
- 0 | 0 | []
- 0 | 1 | [1]
- 0 | 2 | [1, 2]
- 0 | 3 | [1, 2, 3]
- 0 | 4 | [1, 2, 3, 4]
- 1 | 0 | []
- 1 | 1 | [1]
- 1 | 2 | [1, 2]
- 1 | 3 | [1, 2, 3]
- 1 | 4 | [1, 2, 3, 4]
- 2 | 0 | []
- 2 | 1 | []
- 2 | 2 | [2]
- 2 | 3 | [2, 3]
- 2 | 4 | [2, 3, 4]
- 3 | 0 | []
- 3 | 1 | []
- 3 | 2 | []
- 3 | 3 | [3]
- 3 | 4 | [3, 4]
- 4 | 0 | []
- 4 | 1 | []
- 4 | 2 | []
- 4 | 3 | []
- 4 | 4 | [4]
-(25 rows)
-
--- Extension: record types returning
-CREATE TYPE sqljsonb_rec AS (a int, t text, js json, jb jsonb, jsa json[]);
-CREATE TYPE sqljsonb_reca AS (reca sqljsonb_rec[]);
-SELECT JSON_QUERY(jsonb '[{"a": 1, "b": "foo", "t": "aaa", "js": [1, "2", {}], "jb": {"x": [1, "2", {}]}},  {"a": 2}]', '$[0]' RETURNING sqljsonb_rec);
-                     json_query                      
------------------------------------------------------
- (1,aaa,"[1, ""2"", {}]","{""x"": [1, ""2"", {}]}",)
-(1 row)
-
-SELECT * FROM unnest((JSON_QUERY(jsonb '{"jsa":  [{"a": 1, "b": ["foo"]}, {"a": 2, "c": {}}, 123]}', '$' RETURNING sqljsonb_rec)).jsa);
-         unnest         
-------------------------
- {"a": 1, "b": ["foo"]}
- {"a": 2, "c": {}}
- 123
-(3 rows)
-
-SELECT * FROM unnest((JSON_QUERY(jsonb '{"reca": [{"a": 1, "t": ["foo", []]}, {"a": 2, "jb": [{}, true]}]}', '$' RETURNING sqljsonb_reca)).reca);
- a |      t      | js |     jb     | jsa 
----+-------------+----+------------+-----
- 1 | ["foo", []] |    |            | 
- 2 |             |    | [{}, true] | 
-(2 rows)
-
--- Extension: array types returning
-SELECT JSON_QUERY(jsonb '[1,2,null,"3"]', '$[*]' RETURNING int[] WITH WRAPPER);
-  json_query  
---------------
- {1,2,NULL,3}
-(1 row)
-
-SELECT * FROM unnest(JSON_QUERY(jsonb '[{"a": 1, "t": ["foo", []]}, {"a": 2, "jb": [{}, true]}]', '$' RETURNING sqljsonb_rec[]));
- a |      t      | js |     jb     | jsa 
----+-------------+----+------------+-----
- 1 | ["foo", []] |    |            | 
- 2 |             |    | [{}, true] | 
-(2 rows)
-
--- Extension: domain types returning
-SELECT JSON_QUERY(jsonb '{"a": 1}', '$.a' RETURNING sqljsonb_int_not_null);
- json_query 
-------------
-          1
-(1 row)
-
-SELECT JSON_QUERY(jsonb '{"a": 1}', '$.b' RETURNING sqljsonb_int_not_null);
-ERROR:  domain sqljsonb_int_not_null does not allow null values
--- Test timestamptz passing and output
-SELECT JSON_QUERY(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts);
-         json_query          
------------------------------
- "2018-02-21T02:34:56+00:00"
-(1 row)
-
-SELECT JSON_QUERY(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING json);
-         json_query          
------------------------------
- "2018-02-21T02:34:56+00:00"
-(1 row)
-
-SELECT JSON_QUERY(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING jsonb);
-         json_query          
------------------------------
- "2018-02-21T02:34:56+00:00"
-(1 row)
-
--- Test constraints
-CREATE TABLE test_jsonb_constraints (
-	js text,
-	i int,
-	x jsonb DEFAULT JSON_QUERY(jsonb '[1,2]', '$[*]' WITH WRAPPER)
-	CONSTRAINT test_jsonb_constraint1
-		CHECK (js IS JSON)
-	CONSTRAINT test_jsonb_constraint2
-		CHECK (JSON_EXISTS(js::jsonb, '$.a' PASSING i + 5 AS int, i::text AS txt, array[1,2,3] as arr))
-	CONSTRAINT test_jsonb_constraint3
-		CHECK (JSON_VALUE(js::jsonb, '$.a' RETURNING int DEFAULT ('12' || i)::int ON EMPTY ERROR ON ERROR) > i)
-	CONSTRAINT test_jsonb_constraint4
-		CHECK (JSON_QUERY(js::jsonb, '$.a' WITH CONDITIONAL WRAPPER EMPTY OBJECT ON ERROR) < jsonb '[10]')
-	CONSTRAINT test_jsonb_constraint5
-		CHECK (JSON_QUERY(js::jsonb, '$.a' RETURNING char(5) OMIT QUOTES EMPTY ARRAY ON EMPTY) >  'a' COLLATE "C")
-	CONSTRAINT test_jsonb_constraint6
-		CHECK (JSON_EXISTS(js::jsonb, 'strict $.a' RETURNING int TRUE ON ERROR) < 2)
-);
-\d test_jsonb_constraints
-                                          Table "public.test_jsonb_constraints"
- Column |  Type   | Collation | Nullable |                                    Default                                     
---------+---------+-----------+----------+--------------------------------------------------------------------------------
- js     | text    |           |          | 
- i      | integer |           |          | 
- x      | jsonb   |           |          | JSON_QUERY('[1, 2]'::jsonb, '$[*]' RETURNING jsonb WITH UNCONDITIONAL WRAPPER)
-Check constraints:
-    "test_jsonb_constraint1" CHECK (js IS JSON)
-    "test_jsonb_constraint2" CHECK (JSON_EXISTS(js::jsonb, '$."a"' PASSING i + 5 AS int, i::text AS txt, ARRAY[1, 2, 3] AS arr))
-    "test_jsonb_constraint3" CHECK (JSON_VALUE(js::jsonb, '$."a"' RETURNING integer DEFAULT ('12'::text || i)::integer ON EMPTY ERROR ON ERROR) > i)
-    "test_jsonb_constraint4" CHECK (JSON_QUERY(js::jsonb, '$."a"' RETURNING jsonb WITH CONDITIONAL WRAPPER EMPTY OBJECT ON ERROR) < '[10]'::jsonb)
-    "test_jsonb_constraint5" CHECK (JSON_QUERY(js::jsonb, '$."a"' RETURNING character(5) OMIT QUOTES EMPTY ARRAY ON EMPTY) > ('a'::bpchar COLLATE "C"))
-    "test_jsonb_constraint6" CHECK (JSON_EXISTS(js::jsonb, 'strict $."a"' RETURNING integer TRUE ON ERROR) < 2)
-
-SELECT check_clause
-FROM information_schema.check_constraints
-WHERE constraint_name LIKE 'test_jsonb_constraint%'
-ORDER BY 1;
-                                                       check_clause                                                       
---------------------------------------------------------------------------------------------------------------------------
- ((JSON_EXISTS((js)::jsonb, 'strict $."a"' RETURNING integer TRUE ON ERROR) < 2))
- ((JSON_QUERY((js)::jsonb, '$."a"' RETURNING character(5) OMIT QUOTES EMPTY ARRAY ON EMPTY) > ('a'::bpchar COLLATE "C")))
- ((JSON_QUERY((js)::jsonb, '$."a"' RETURNING jsonb WITH CONDITIONAL WRAPPER EMPTY OBJECT ON ERROR) < '[10]'::jsonb))
- ((JSON_VALUE((js)::jsonb, '$."a"' RETURNING integer DEFAULT (('12'::text || i))::integer ON EMPTY ERROR ON ERROR) > i))
- ((js IS JSON))
- (JSON_EXISTS((js)::jsonb, '$."a"' PASSING (i + 5) AS int, (i)::text AS txt, ARRAY[1, 2, 3] AS arr))
-(6 rows)
-
-SELECT pg_get_expr(adbin, adrelid)
-FROM pg_attrdef
-WHERE adrelid = 'test_jsonb_constraints'::regclass
-ORDER BY 1;
-                                  pg_get_expr                                   
---------------------------------------------------------------------------------
- JSON_QUERY('[1, 2]'::jsonb, '$[*]' RETURNING jsonb WITH UNCONDITIONAL WRAPPER)
-(1 row)
-
-INSERT INTO test_jsonb_constraints VALUES ('', 1);
-ERROR:  new row for relation "test_jsonb_constraints" violates check constraint "test_jsonb_constraint1"
-DETAIL:  Failing row contains (, 1, [1, 2]).
-INSERT INTO test_jsonb_constraints VALUES ('1', 1);
-ERROR:  new row for relation "test_jsonb_constraints" violates check constraint "test_jsonb_constraint2"
-DETAIL:  Failing row contains (1, 1, [1, 2]).
-INSERT INTO test_jsonb_constraints VALUES ('[]');
-ERROR:  new row for relation "test_jsonb_constraints" violates check constraint "test_jsonb_constraint2"
-DETAIL:  Failing row contains ([], null, [1, 2]).
-INSERT INTO test_jsonb_constraints VALUES ('{"b": 1}', 1);
-ERROR:  new row for relation "test_jsonb_constraints" violates check constraint "test_jsonb_constraint2"
-DETAIL:  Failing row contains ({"b": 1}, 1, [1, 2]).
-INSERT INTO test_jsonb_constraints VALUES ('{"a": 1}', 1);
-ERROR:  new row for relation "test_jsonb_constraints" violates check constraint "test_jsonb_constraint3"
-DETAIL:  Failing row contains ({"a": 1}, 1, [1, 2]).
-INSERT INTO test_jsonb_constraints VALUES ('{"a": 7}', 1);
-ERROR:  new row for relation "test_jsonb_constraints" violates check constraint "test_jsonb_constraint5"
-DETAIL:  Failing row contains ({"a": 7}, 1, [1, 2]).
-INSERT INTO test_jsonb_constraints VALUES ('{"a": 10}', 1);
-ERROR:  new row for relation "test_jsonb_constraints" violates check constraint "test_jsonb_constraint4"
-DETAIL:  Failing row contains ({"a": 10}, 1, [1, 2]).
-DROP TABLE test_jsonb_constraints;
--- Test mutabilily od query functions
-CREATE TABLE test_jsonb_mutability(js jsonb);
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a[0]'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime()'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a ? (@ < $.datetime())'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a ? (@.datetime() < $.datetime())'));
-ERROR:  functions in index expression must be marked IMMUTABLE
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a ? (@.datetime() < $.datetime("HH:MI TZH"))'));
-ERROR:  functions in index expression must be marked IMMUTABLE
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a ? (@.datetime("HH:MI TZH") < $.datetime("HH:MI TZH"))'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a ? (@.datetime("HH:MI") < $.datetime("YY-MM-DD HH:MI"))'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a ? (@.datetime("HH:MI TZH") < $.datetime("YY-MM-DD HH:MI"))'));
-ERROR:  functions in index expression must be marked IMMUTABLE
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime("HH:MI TZH") < $x' PASSING '12:34'::timetz AS x));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime("HH:MI TZH") < $y' PASSING '12:34'::timetz AS x));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime() < $x' PASSING '12:34'::timetz AS x));
-ERROR:  functions in index expression must be marked IMMUTABLE
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime() < $x' PASSING '1234'::int AS x));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime() ? (@ == $x)' PASSING '12:34'::time AS x));
-ERROR:  functions in index expression must be marked IMMUTABLE
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime("YY-MM-DD") ? (@ == $x)' PASSING '2020-07-14'::date AS x));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$[1, $.a ? (@.datetime() == $x)]' PASSING '12:34'::time AS x));
-ERROR:  functions in index expression must be marked IMMUTABLE
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$[1, 0 to $.a ? (@.datetime() == $x)]' PASSING '12:34'::time AS x));
-ERROR:  functions in index expression must be marked IMMUTABLE
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$[1, $.a ? (@.datetime("HH:MI") == $x)]' PASSING '12:34'::time AS x));
-DROP TABLE test_jsonb_mutability;
--- JSON_TABLE
--- Should fail (JSON_TABLE can be used only in FROM clause)
-SELECT JSON_TABLE('[]', '$');
-ERROR:  syntax error at or near "("
-LINE 1: SELECT JSON_TABLE('[]', '$');
-                         ^
--- Should fail (no columns)
-SELECT * FROM JSON_TABLE(NULL, '$' COLUMNS ());
-ERROR:  syntax error at or near ")"
-LINE 1: SELECT * FROM JSON_TABLE(NULL, '$' COLUMNS ());
-                                                    ^
-SELECT * FROM JSON_TABLE (NULL::jsonb, '$' COLUMNS (v1 timestamp)) AS f (v1, v2);
-ERROR:  JSON_TABLE function has 1 columns available but 2 columns specified
--- NULL => empty table
-SELECT * FROM JSON_TABLE(NULL::jsonb, '$' COLUMNS (foo int)) bar;
- foo 
------
-(0 rows)
-
---
-SELECT * FROM JSON_TABLE(jsonb '123', '$'
-	COLUMNS (item int PATH '$', foo int)) bar;
- item | foo 
-------+-----
-  123 |    
-(1 row)
-
--- JSON_TABLE: basic functionality
-CREATE DOMAIN jsonb_test_domain AS text CHECK (value <> 'foo');
-SELECT *
-FROM
-	(VALUES
-		('1'),
-		('[]'),
-		('{}'),
-		('[1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""]')
-	) vals(js)
-	LEFT OUTER JOIN
--- JSON_TABLE is implicitly lateral
-	JSON_TABLE(
-		vals.js::jsonb, 'lax $[*]'
-		COLUMNS (
-			id FOR ORDINALITY,
-			id2 FOR ORDINALITY, -- allowed additional ordinality columns
-			"int" int PATH '$',
-			"text" text PATH '$',
-			"char(4)" char(4) PATH '$',
-			"bool" bool PATH '$',
-			"numeric" numeric PATH '$',
-			"domain" jsonb_test_domain PATH '$',
-			js json PATH '$',
-			jb jsonb PATH '$',
-			jst text    FORMAT JSON  PATH '$',
-			jsc char(4) FORMAT JSON  PATH '$',
-			jsv varchar(4) FORMAT JSON  PATH '$',
-			jsb jsonb FORMAT JSON PATH '$',
-			jsbq jsonb FORMAT JSON PATH '$' OMIT QUOTES,
-			aaa int, -- implicit path '$."aaa"',
-			aaa1 int PATH '$.aaa',
-			exists1 bool EXISTS PATH '$.aaa',
-			exists2 int EXISTS PATH '$.aaa',
-			exists3 int EXISTS PATH 'strict $.aaa' UNKNOWN ON ERROR,
-			exists4 text EXISTS PATH 'strict $.aaa' FALSE ON ERROR,
-			js2 json PATH '$',
-			jsb2w jsonb PATH '$' WITH WRAPPER,
-			jsb2q jsonb PATH '$' OMIT QUOTES,
-			ia int[] PATH '$',
-			ta text[] PATH '$',
-			jba jsonb[] PATH '$'
-		)
-	) jt
-	ON true;
-                                          js                                           | id | id2 | int |  text   | char(4) | bool | numeric | domain  |      js      |      jb      |     jst      | jsc  | jsv  |     jsb      |     jsbq     | aaa | aaa1 | exists1 | exists2 | exists3 | exists4 |     js2      |     jsb2w      |    jsb2q     | ia | ta | jba 
----------------------------------------------------------------------------------------+----+-----+-----+---------+---------+------+---------+---------+--------------+--------------+--------------+------+------+--------------+--------------+-----+------+---------+---------+---------+---------+--------------+----------------+--------------+----+----+-----
- 1                                                                                     |  1 |   1 |   1 | 1       | 1       |      |       1 | 1       | 1            | 1            | 1            | 1    | 1    | 1            | 1            |     |      | f       |       0 |         | false   | 1            | [1]            | 1            |    |    | 
- []                                                                                    |    |     |     |         |         |      |         |         |              |              |              |      |      |              |              |     |      |         |         |         |         |              |                |              |    |    | 
- {}                                                                                    |  1 |   1 |     |         |         |      |         |         | {}           | {}           | {}           | {}   | {}   | {}           | {}           |     |      | f       |       0 |         | false   | {}           | [{}]           | {}           |    |    | 
- [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] |  1 |   1 |   1 | 1       | 1       |      |       1 | 1       | 1            | 1            | 1            | 1    | 1    | 1            | 1            |     |      | f       |       0 |         | false   | 1            | [1]            | 1            |    |    | 
- [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] |  2 |   2 |   1 | 1.23    | 1.23    |      |    1.23 | 1.23    | 1.23         | 1.23         | 1.23         | 1.23 | 1.23 | 1.23         | 1.23         |     |      | f       |       0 |         | false   | 1.23         | [1.23]         | 1.23         |    |    | 
- [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] |  3 |   3 |   2 | 2       | 2       |      |       2 | 2       | "2"          | "2"          | "2"          | "2"  | "2"  | "2"          | 2            |     |      | f       |       0 |         | false   | "2"          | ["2"]          | 2            |    |    | 
- [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] |  4 |   4 |     | aaaaaaa | aaaa    |      |         | aaaaaaa | "aaaaaaa"    | "aaaaaaa"    | "aaaaaaa"    | "aaa | "aaa | "aaaaaaa"    |              |     |      | f       |       0 |         | false   | "aaaaaaa"    | ["aaaaaaa"]    |              |    |    | 
- [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] |  5 |   5 |     | foo     | foo     |      |         |         | "foo"        | "foo"        | "foo"        | "foo | "foo | "foo"        |              |     |      | f       |       0 |         | false   | "foo"        | ["foo"]        |              |    |    | 
- [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] |  6 |   6 |     |         |         |      |         |         | null         | null         | null         | null | null | null         | null         |     |      | f       |       0 |         | false   | null         | [null]         | null         |    |    | 
- [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] |  7 |   7 |   0 | false   | fals    | f    |         | false   | false        | false        | false        | fals | fals | false        | false        |     |      | f       |       0 |         | false   | false        | [false]        | false        |    |    | 
- [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] |  8 |   8 |   1 | true    | true    | t    |         | true    | true         | true         | true         | true | true | true         | true         |     |      | f       |       0 |         | false   | true         | [true]         | true         |    |    | 
- [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] |  9 |   9 |     |         |         |      |         |         | {"aaa": 123} | {"aaa": 123} | {"aaa": 123} | {"aa | {"aa | {"aaa": 123} | {"aaa": 123} | 123 |  123 | t       |       1 |       1 | true    | {"aaa": 123} | [{"aaa": 123}] | {"aaa": 123} |    |    | 
- [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] | 10 |  10 |     | [1,2]   | [1,2    |      |         | [1,2]   | "[1,2]"      | "[1,2]"      | "[1,2]"      | "[1, | "[1, | "[1,2]"      | [1, 2]       |     |      | f       |       0 |         | false   | "[1,2]"      | ["[1,2]"]      | [1, 2]       |    |    | 
- [1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""] | 11 |  11 |     | "str"   | "str    |      |         | "str"   | "\"str\""    | "\"str\""    | "\"str\""    | "\"s | "\"s | "\"str\""    | "str"        |     |      | f       |       0 |         | false   | "\"str\""    | ["\"str\""]    | "str"        |    |    | 
-(14 rows)
-
--- JSON_TABLE: Test backward parsing
-CREATE VIEW jsonb_table_view AS
-SELECT * FROM
-	JSON_TABLE(
-		jsonb 'null', 'lax $[*]' PASSING 1 + 2 AS a, json '"foo"' AS "b c"
-		COLUMNS (
-			id FOR ORDINALITY,
-			id2 FOR ORDINALITY, -- allowed additional ordinality columns
-			"int" int PATH '$',
-			"text" text PATH '$',
-			"char(4)" char(4) PATH '$',
-			"bool" bool PATH '$',
-			"numeric" numeric PATH '$',
-			"domain" jsonb_test_domain PATH '$',
-			js json PATH '$',
-			jb jsonb PATH '$',
-			jst text    FORMAT JSON  PATH '$',
-			jsc char(4) FORMAT JSON  PATH '$',
-			jsv varchar(4) FORMAT JSON  PATH '$',
-			jsb jsonb   FORMAT JSON PATH '$',
-			jsbq jsonb FORMAT JSON PATH '$' OMIT QUOTES,
-			aaa int, -- implicit path '$."aaa"',
-			aaa1 int PATH '$.aaa',
-			exists1 bool EXISTS PATH '$.aaa',
-			exists2 int EXISTS PATH '$.aaa' TRUE ON ERROR,
-			exists3 text EXISTS PATH 'strict $.aaa' UNKNOWN ON ERROR,
-			js2 json PATH '$',
-			jsb2w jsonb PATH '$' WITH WRAPPER,
-			jsb2q jsonb PATH '$' OMIT QUOTES,
-			ia int[] PATH '$',
-			ta text[] PATH '$',
-			jba jsonb[] PATH '$',
-			NESTED PATH '$[1]' AS p1 COLUMNS (
-				a1 int,
-				NESTED PATH '$[*]' AS "p1 1" COLUMNS (
-					a11 text
-				),
-				b1 text
-			),
-			NESTED PATH '$[2]' AS p2 COLUMNS (
-				NESTED PATH '$[*]' AS "p2:1" COLUMNS (
-					a21 text
-				),
-				NESTED PATH '$[*]' AS p22 COLUMNS (
-					a22 text
-				)
-			)
-		)
-	);
-\sv jsonb_table_view
-CREATE OR REPLACE VIEW public.jsonb_table_view AS
- SELECT "json_table".id,
-    "json_table".id2,
-    "json_table"."int",
-    "json_table".text,
-    "json_table"."char(4)",
-    "json_table".bool,
-    "json_table"."numeric",
-    "json_table".domain,
-    "json_table".js,
-    "json_table".jb,
-    "json_table".jst,
-    "json_table".jsc,
-    "json_table".jsv,
-    "json_table".jsb,
-    "json_table".jsbq,
-    "json_table".aaa,
-    "json_table".aaa1,
-    "json_table".exists1,
-    "json_table".exists2,
-    "json_table".exists3,
-    "json_table".js2,
-    "json_table".jsb2w,
-    "json_table".jsb2q,
-    "json_table".ia,
-    "json_table".ta,
-    "json_table".jba,
-    "json_table".a1,
-    "json_table".b1,
-    "json_table".a11,
-    "json_table".a21,
-    "json_table".a22
-   FROM JSON_TABLE(
-            'null'::jsonb, '$[*]' AS json_table_path_1
-            PASSING
-                1 + 2 AS a,
-                '"foo"'::json AS "b c"
-            COLUMNS (
-                id FOR ORDINALITY,
-                id2 FOR ORDINALITY,
-                "int" integer PATH '$',
-                text text PATH '$',
-                "char(4)" character(4) PATH '$',
-                bool boolean PATH '$',
-                "numeric" numeric PATH '$',
-                domain jsonb_test_domain PATH '$',
-                js json PATH '$',
-                jb jsonb PATH '$',
-                jst text FORMAT JSON PATH '$',
-                jsc character(4) FORMAT JSON PATH '$',
-                jsv character varying(4) FORMAT JSON PATH '$',
-                jsb jsonb PATH '$',
-                jsbq jsonb PATH '$' OMIT QUOTES,
-                aaa integer PATH '$."aaa"',
-                aaa1 integer PATH '$."aaa"',
-                exists1 boolean EXISTS PATH '$."aaa"',
-                exists2 integer EXISTS PATH '$."aaa"' TRUE ON ERROR,
-                exists3 text EXISTS PATH 'strict $."aaa"' UNKNOWN ON ERROR,
-                js2 json PATH '$',
-                jsb2w jsonb PATH '$' WITH UNCONDITIONAL WRAPPER,
-                jsb2q jsonb PATH '$' OMIT QUOTES,
-                ia integer[] PATH '$',
-                ta text[] PATH '$',
-                jba jsonb[] PATH '$',
-                NESTED PATH '$[1]' AS p1
-                COLUMNS (
-                    a1 integer PATH '$."a1"',
-                    b1 text PATH '$."b1"',
-                    NESTED PATH '$[*]' AS "p1 1"
-                    COLUMNS (
-                        a11 text PATH '$."a11"'
-                    )
-                ),
-                NESTED PATH '$[2]' AS p2
-                COLUMNS (
-                    NESTED PATH '$[*]' AS "p2:1"
-                    COLUMNS (
-                        a21 text PATH '$."a21"'
-                    ),
-                    NESTED PATH '$[*]' AS p22
-                    COLUMNS (
-                        a22 text PATH '$."a22"'
-                    )
-                )
-            )
-            PLAN (json_table_path_1 OUTER ((p1 OUTER "p1 1") UNION (p2 OUTER ("p2:1" UNION p22))))
-        )
-EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM jsonb_table_view;
-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         QUERY PLAN                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- Table Function Scan on "json_table"
-   Output: "json_table".id, "json_table".id2, "json_table"."int", "json_table".text, "json_table"."char(4)", "json_table".bool, "json_table"."numeric", "json_table".domain, "json_table".js, "json_table".jb, "json_table".jst, "json_table".jsc, "json_table".jsv, "json_table".jsb, "json_table".jsbq, "json_table".aaa, "json_table".aaa1, "json_table".exists1, "json_table".exists2, "json_table".exists3, "json_table".js2, "json_table".jsb2w, "json_table".jsb2q, "json_table".ia, "json_table".ta, "json_table".jba, "json_table".a1, "json_table".b1, "json_table".a11, "json_table".a21, "json_table".a22
-   Table Function Call: JSON_TABLE('null'::jsonb, '$[*]' AS json_table_path_1 PASSING 3 AS a, '"foo"'::jsonb AS "b c" COLUMNS (id FOR ORDINALITY, id2 FOR ORDINALITY, "int" integer PATH '$', text text PATH '$', "char(4)" character(4) PATH '$', bool boolean PATH '$', "numeric" numeric PATH '$', domain jsonb_test_domain PATH '$', js json PATH '$', jb jsonb PATH '$', jst text FORMAT JSON PATH '$', jsc character(4) FORMAT JSON PATH '$', jsv character varying(4) FORMAT JSON PATH '$', jsb jsonb PATH '$', jsbq jsonb PATH '$' OMIT QUOTES, aaa integer PATH '$."aaa"', aaa1 integer PATH '$."aaa"', exists1 boolean EXISTS PATH '$."aaa"', exists2 integer EXISTS PATH '$."aaa"' TRUE ON ERROR, exists3 text EXISTS PATH 'strict $."aaa"' UNKNOWN ON ERROR, js2 json PATH '$', jsb2w jsonb PATH '$' WITH UNCONDITIONAL WRAPPER, jsb2q jsonb PATH '$' OMIT QUOTES, ia integer[] PATH '$', ta text[] PATH '$', jba jsonb[] PATH '$', NESTED PATH '$[1]' AS p1 COLUMNS (a1 integer PATH '$."a1"', b1 text PATH '$."b1"', NESTED PATH '$[*]' AS "p1 1" COLUMNS (a11 text PATH '$."a11"')), NESTED PATH '$[2]' AS p2 COLUMNS ( NESTED PATH '$[*]' AS "p2:1" COLUMNS (a21 text PATH '$."a21"'), NESTED PATH '$[*]' AS p22 COLUMNS (a22 text PATH '$."a22"'))) PLAN (json_table_path_1 OUTER ((p1 OUTER "p1 1") UNION (p2 OUTER ("p2:1" UNION p22)))))
-(3 rows)
-
-DROP VIEW jsonb_table_view;
-DROP DOMAIN jsonb_test_domain;
--- JSON_TABLE: ON EMPTY/ON ERROR behavior
-SELECT *
-FROM
-	(VALUES ('1'), ('"err"')) vals(js),
-	JSON_TABLE(vals.js::jsonb, '$' COLUMNS (a int PATH '$')) jt;
-  js   | a 
--------+---
- 1     | 1
- "err" |  
-(2 rows)
-
-SELECT *
-FROM
-	(VALUES ('1'), ('"err"')) vals(js)
-		LEFT OUTER JOIN
-	JSON_TABLE(vals.js::jsonb, '$' COLUMNS (a int PATH '$') ERROR ON ERROR) jt
-		ON true;
-ERROR:  invalid input syntax for type integer: "err"
-SELECT *
-FROM
-	(VALUES ('1'), ('"err"')) vals(js)
-		LEFT OUTER JOIN
-	JSON_TABLE(vals.js::jsonb, '$' COLUMNS (a int PATH '$' ERROR ON ERROR)) jt
-		ON true;
-ERROR:  invalid input syntax for type integer: "err"
-SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int PATH '$.a' ERROR ON EMPTY)) jt;
- a 
----
-  
-(1 row)
-
-SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int PATH 'strict $.a' ERROR ON EMPTY) ERROR ON ERROR) jt;
-ERROR:  jsonpath member accessor can only be applied to an object
-SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int PATH 'lax $.a' ERROR ON EMPTY) ERROR ON ERROR) jt;
-ERROR:  no SQL/JSON item
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int PATH '$'   DEFAULT 1 ON EMPTY DEFAULT 2 ON ERROR)) jt;
- a 
----
- 2
-(1 row)
-
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int PATH 'strict $.a' DEFAULT 1 ON EMPTY DEFAULT 2 ON ERROR)) jt;
- a 
----
- 2
-(1 row)
-
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int PATH 'lax $.a' DEFAULT 1 ON EMPTY DEFAULT 2 ON ERROR)) jt;
- a 
----
- 1
-(1 row)
-
--- JSON_TABLE: EXISTS PATH types
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int4 EXISTS PATH '$.a'));
- a 
----
- 0
-(1 row)
-
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int2 EXISTS PATH '$.a'));
-ERROR:  cannot cast type boolean to smallint
-LINE 1: ...ELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int2 EXI...
-                                                             ^
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int8 EXISTS PATH '$.a'));
-ERROR:  cannot cast type boolean to bigint
-LINE 1: ...ELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int8 EXI...
-                                                             ^
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a float4 EXISTS PATH '$.a'));
-ERROR:  cannot cast type boolean to real
-LINE 1: ...ELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a float4 E...
-                                                             ^
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(3) EXISTS PATH '$.a'));
-  a  
------
- fal
-(1 row)
-
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a json EXISTS PATH '$.a'));
-ERROR:  cannot cast type boolean to json
-LINE 1: ...ELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a json EXI...
-                                                             ^
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a jsonb EXISTS PATH '$.a'));
-ERROR:  cannot cast type boolean to jsonb
-LINE 1: ...ELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a jsonb EX...
-                                                             ^
--- JSON_TABLE: nested paths and plans
--- Should fail (JSON_TABLE columns must contain explicit AS path
--- specifications if explicit PLAN clause is used)
-SELECT * FROM JSON_TABLE(
-	jsonb '[]', '$' -- AS <path name> required here
-	COLUMNS (
-		foo int PATH '$'
-	)
-	PLAN DEFAULT (UNION)
-) jt;
-ERROR:  invalid JSON_TABLE expression
-LINE 2:  jsonb '[]', '$' -- AS <path name> required here
-         ^
-DETAIL:  JSON_TABLE columns must contain explicit AS pathname specification if explicit PLAN clause is used
-SELECT * FROM JSON_TABLE(
-	jsonb '[]', '$' AS path1
-	COLUMNS (
-		NESTED PATH '$' COLUMNS ( -- AS <path name> required here
-			foo int PATH '$'
-		)
-	)
-	PLAN DEFAULT (UNION)
-) jt;
-ERROR:  invalid JSON_TABLE expression
-LINE 4:   NESTED PATH '$' COLUMNS ( -- AS <path name> required here
-          ^
-DETAIL:  JSON_TABLE columns must contain explicit AS pathname specification if explicit PLAN clause is used
--- Should fail (column names must be distinct)
-SELECT * FROM JSON_TABLE(
-	jsonb '[]', '$' AS a
-	COLUMNS (
-		a int
-	)
-) jt;
-ERROR:  duplicate JSON_TABLE column name: a
-HINT:  JSON_TABLE column names must be distinct from one another.
-SELECT * FROM JSON_TABLE(
-	jsonb '[]', '$' AS a
-	COLUMNS (
-		b int,
-		NESTED PATH '$' AS a
-		COLUMNS (
-			c int
-		)
-	)
-) jt;
-ERROR:  duplicate JSON_TABLE column name: a
-HINT:  JSON_TABLE column names must be distinct from one another.
-SELECT * FROM JSON_TABLE(
-	jsonb '[]', '$'
-	COLUMNS (
-		b int,
-		NESTED PATH '$' AS b
-		COLUMNS (
-			c int
-		)
-	)
-) jt;
-ERROR:  duplicate JSON_TABLE column name: b
-HINT:  JSON_TABLE column names must be distinct from one another.
-SELECT * FROM JSON_TABLE(
-	jsonb '[]', '$'
-	COLUMNS (
-		NESTED PATH '$' AS a
-		COLUMNS (
-			b int
-		),
-		NESTED PATH '$'
-		COLUMNS (
-			NESTED PATH '$' AS a
-			COLUMNS (
-				c int
-			)
-		)
-	)
-) jt;
-ERROR:  duplicate JSON_TABLE column name: a
-HINT:  JSON_TABLE column names must be distinct from one another.
--- JSON_TABLE: plan validation
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p1)
-) jt;
-ERROR:  invalid JSON_TABLE plan
-LINE 12:  PLAN (p1)
-                ^
-DETAIL:  Path name mismatch: expected p0 but p1 is given.
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0)
-) jt;
-ERROR:  invalid JSON_TABLE plan
-LINE 4:   NESTED PATH '$' AS p1 COLUMNS (
-          ^
-DETAIL:  Plan node for nested path p1 was not found in plan.
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER p3)
-) jt;
-ERROR:  invalid JSON_TABLE plan
-LINE 4:   NESTED PATH '$' AS p1 COLUMNS (
-          ^
-DETAIL:  Plan node for nested path p1 was not found in plan.
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 UNION p1 UNION p11)
-) jt;
-ERROR:  invalid JSON_TABLE plan
-LINE 12:  PLAN (p0 UNION p1 UNION p11)
-                ^
-DETAIL:  Expected INNER or OUTER JSON_TABLE plan node.
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER (p1 CROSS p13))
-) jt;
-ERROR:  invalid JSON_TABLE plan
-LINE 8:   NESTED PATH '$' AS p2 COLUMNS (
-          ^
-DETAIL:  Plan node for nested path p2 was not found in plan.
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER (p1 CROSS p2))
-) jt;
-ERROR:  invalid JSON_TABLE plan
-LINE 5:    NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-           ^
-DETAIL:  Plan node for nested path p11 was not found in plan.
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER ((p1 UNION p11) CROSS p2))
-) jt;
-ERROR:  invalid JSON_TABLE plan
-LINE 12:  PLAN (p0 OUTER ((p1 UNION p11) CROSS p2))
-                         ^
-DETAIL:  Plan node contains some extra or duplicate sibling nodes.
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER ((p1 INNER p11) CROSS p2))
-) jt;
-ERROR:  invalid JSON_TABLE plan
-LINE 6:    NESTED PATH '$' AS p12 COLUMNS ( bar int )
-           ^
-DETAIL:  Plan node for nested path p12 was not found in plan.
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER ((p1 INNER (p12 CROSS p11)) CROSS p2))
-) jt;
-ERROR:  invalid JSON_TABLE plan
-LINE 9:    NESTED PATH '$' AS p21 COLUMNS ( baz int )
-           ^
-DETAIL:  Plan node for nested path p21 was not found in plan.
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', 'strict $[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER ((p1 INNER (p12 CROSS p11)) CROSS (p2 INNER p21)))
-) jt;
- bar | foo | baz 
------+-----+-----
-(0 rows)
-
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', 'strict $[*]' -- without root path name
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN ((p1 INNER (p12 CROSS p11)) CROSS (p2 INNER p21))
-) jt;
-ERROR:  invalid JSON_TABLE expression
-LINE 2:  jsonb 'null', 'strict $[*]' -- without root path name
-         ^
-DETAIL:  JSON_TABLE columns must contain explicit AS pathname specification if explicit PLAN clause is used
--- JSON_TABLE: plan execution
-CREATE TEMP TABLE jsonb_table_test (js jsonb);
-INSERT INTO jsonb_table_test
-VALUES (
-	'[
-		{"a":  1,  "b": [], "c": []},
-		{"a":  2,  "b": [1, 2, 3], "c": [10, null, 20]},
-		{"a":  3,  "b": [1, 2], "c": []},
-		{"x": "4", "b": [1, 2], "c": 123}
-	 ]'
-);
--- unspecified plan (outer, union)
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-	) jt;
- n | a  | b | c  
----+----+---+----
- 1 |  1 |   |   
- 2 |  2 | 1 |   
- 2 |  2 | 2 |   
- 2 |  2 | 3 |   
- 2 |  2 |   | 10
- 2 |  2 |   |   
- 2 |  2 |   | 20
- 3 |  3 | 1 |   
- 3 |  3 | 2 |   
- 4 | -1 | 1 |   
- 4 | -1 | 2 |   
-(11 rows)
-
--- default plan (outer, union)
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan default (outer, union)
-	) jt;
- n | a  | b | c  
----+----+---+----
- 1 |  1 |   |   
- 2 |  2 | 1 |   
- 2 |  2 | 2 |   
- 2 |  2 | 3 |   
- 2 |  2 |   | 10
- 2 |  2 |   |   
- 2 |  2 |   | 20
- 3 |  3 | 1 |   
- 3 |  3 | 2 |   
- 4 | -1 | 1 |   
- 4 | -1 | 2 |   
-(11 rows)
-
--- specific plan (p outer (pb union pc))
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan (p outer (pb union pc))
-	) jt;
- n | a  | b | c  
----+----+---+----
- 1 |  1 |   |   
- 2 |  2 | 1 |   
- 2 |  2 | 2 |   
- 2 |  2 | 3 |   
- 2 |  2 |   | 10
- 2 |  2 |   |   
- 2 |  2 |   | 20
- 3 |  3 | 1 |   
- 3 |  3 | 2 |   
- 4 | -1 | 1 |   
- 4 | -1 | 2 |   
-(11 rows)
-
--- specific plan (p outer (pc union pb))
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan (p outer (pc union pb))
-	) jt;
- n | a  | c  | b 
----+----+----+---
- 1 |  1 |    |  
- 2 |  2 | 10 |  
- 2 |  2 |    |  
- 2 |  2 | 20 |  
- 2 |  2 |    | 1
- 2 |  2 |    | 2
- 2 |  2 |    | 3
- 3 |  3 |    | 1
- 3 |  3 |    | 2
- 4 | -1 |    | 1
- 4 | -1 |    | 2
-(11 rows)
-
--- default plan (inner, union)
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan default (inner)
-	) jt;
- n | a  | b | c  
----+----+---+----
- 2 |  2 | 1 |   
- 2 |  2 | 2 |   
- 2 |  2 | 3 |   
- 2 |  2 |   | 10
- 2 |  2 |   |   
- 2 |  2 |   | 20
- 3 |  3 | 1 |   
- 3 |  3 | 2 |   
- 4 | -1 | 1 |   
- 4 | -1 | 2 |   
-(10 rows)
-
--- specific plan (p inner (pb union pc))
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan (p inner (pb union pc))
-	) jt;
- n | a  | b | c  
----+----+---+----
- 2 |  2 | 1 |   
- 2 |  2 | 2 |   
- 2 |  2 | 3 |   
- 2 |  2 |   | 10
- 2 |  2 |   |   
- 2 |  2 |   | 20
- 3 |  3 | 1 |   
- 3 |  3 | 2 |   
- 4 | -1 | 1 |   
- 4 | -1 | 2 |   
-(10 rows)
-
--- default plan (inner, cross)
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan default (cross, inner)
-	) jt;
- n | a | b | c  
----+---+---+----
- 2 | 2 | 1 | 10
- 2 | 2 | 1 |   
- 2 | 2 | 1 | 20
- 2 | 2 | 2 | 10
- 2 | 2 | 2 |   
- 2 | 2 | 2 | 20
- 2 | 2 | 3 | 10
- 2 | 2 | 3 |   
- 2 | 2 | 3 | 20
-(9 rows)
-
--- specific plan (p inner (pb cross pc))
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan (p inner (pb cross pc))
-	) jt;
- n | a | b | c  
----+---+---+----
- 2 | 2 | 1 | 10
- 2 | 2 | 1 |   
- 2 | 2 | 1 | 20
- 2 | 2 | 2 | 10
- 2 | 2 | 2 |   
- 2 | 2 | 2 | 20
- 2 | 2 | 3 | 10
- 2 | 2 | 3 |   
- 2 | 2 | 3 | 20
-(9 rows)
-
--- default plan (outer, cross)
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan default (outer, cross)
-	) jt;
- n | a  | b | c  
----+----+---+----
- 1 |  1 |   |   
- 2 |  2 | 1 | 10
- 2 |  2 | 1 |   
- 2 |  2 | 1 | 20
- 2 |  2 | 2 | 10
- 2 |  2 | 2 |   
- 2 |  2 | 2 | 20
- 2 |  2 | 3 | 10
- 2 |  2 | 3 |   
- 2 |  2 | 3 | 20
- 3 |  3 |   |   
- 4 | -1 |   |   
-(12 rows)
-
--- specific plan (p outer (pb cross pc))
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan (p outer (pb cross pc))
-	) jt;
- n | a  | b | c  
----+----+---+----
- 1 |  1 |   |   
- 2 |  2 | 1 | 10
- 2 |  2 | 1 |   
- 2 |  2 | 1 | 20
- 2 |  2 | 2 | 10
- 2 |  2 | 2 |   
- 2 |  2 | 2 | 20
- 2 |  2 | 3 | 10
- 2 |  2 | 3 |   
- 2 |  2 | 3 | 20
- 3 |  3 |   |   
- 4 | -1 |   |   
-(12 rows)
-
-select
-	jt.*, b1 + 100 as b
-from
-	json_table (jsonb
-		'[
-			{"a":  1,  "b": [[1, 10], [2], [3, 30, 300]], "c": [1, null, 2]},
-			{"a":  2,  "b": [10, 20], "c": [1, null, 2]},
-			{"x": "3", "b": [11, 22, 33, 44]}
-		 ]',
-		'$[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on error,
-			nested path 'strict $.b[*]' as pb columns (
-				b text format json path '$',
-				nested path 'strict $[*]' as pb1 columns (
-					b1 int path '$'
-				)
-			),
-			nested path 'strict $.c[*]' as pc columns (
-				c text format json path '$',
-				nested path 'strict $[*]' as pc1 columns (
-					c1 int path '$'
-				)
-			)
-		)
-		--plan default(outer, cross)
-		plan(p outer ((pb inner pb1) cross (pc outer pc1)))
-	) jt;
- n | a |      b       | b1  |  c   | c1 |  b  
----+---+--------------+-----+------+----+-----
- 1 | 1 | [1, 10]      |   1 | 1    |    | 101
- 1 | 1 | [1, 10]      |   1 | null |    | 101
- 1 | 1 | [1, 10]      |   1 | 2    |    | 101
- 1 | 1 | [1, 10]      |  10 | 1    |    | 110
- 1 | 1 | [1, 10]      |  10 | null |    | 110
- 1 | 1 | [1, 10]      |  10 | 2    |    | 110
- 1 | 1 | [2]          |   2 | 1    |    | 102
- 1 | 1 | [2]          |   2 | null |    | 102
- 1 | 1 | [2]          |   2 | 2    |    | 102
- 1 | 1 | [3, 30, 300] |   3 | 1    |    | 103
- 1 | 1 | [3, 30, 300] |   3 | null |    | 103
- 1 | 1 | [3, 30, 300] |   3 | 2    |    | 103
- 1 | 1 | [3, 30, 300] |  30 | 1    |    | 130
- 1 | 1 | [3, 30, 300] |  30 | null |    | 130
- 1 | 1 | [3, 30, 300] |  30 | 2    |    | 130
- 1 | 1 | [3, 30, 300] | 300 | 1    |    | 400
- 1 | 1 | [3, 30, 300] | 300 | null |    | 400
- 1 | 1 | [3, 30, 300] | 300 | 2    |    | 400
- 2 | 2 |              |     |      |    |    
- 3 |   |              |     |      |    |    
-(20 rows)
-
--- Should succeed (JSON arguments are passed to root and nested paths)
-SELECT *
-FROM
-	generate_series(1, 4) x,
-	generate_series(1, 3) y,
-	JSON_TABLE(jsonb
-		'[[1,2,3],[2,3,4,5],[3,4,5,6]]',
-		'strict $[*] ? (@[*] < $x)'
-		PASSING x AS x, y AS y
-		COLUMNS (
-			y text FORMAT JSON PATH '$',
-			NESTED PATH 'strict $[*] ? (@ >= $y)'
-			COLUMNS (
-				z int PATH '$'
-			)
-		)
-	) jt;
- x | y |      y       | z 
----+---+--------------+---
- 2 | 1 | [1, 2, 3]    | 1
- 2 | 1 | [1, 2, 3]    | 2
- 2 | 1 | [1, 2, 3]    | 3
- 3 | 1 | [1, 2, 3]    | 1
- 3 | 1 | [1, 2, 3]    | 2
- 3 | 1 | [1, 2, 3]    | 3
- 3 | 1 | [2, 3, 4, 5] | 2
- 3 | 1 | [2, 3, 4, 5] | 3
- 3 | 1 | [2, 3, 4, 5] | 4
- 3 | 1 | [2, 3, 4, 5] | 5
- 4 | 1 | [1, 2, 3]    | 1
- 4 | 1 | [1, 2, 3]    | 2
- 4 | 1 | [1, 2, 3]    | 3
- 4 | 1 | [2, 3, 4, 5] | 2
- 4 | 1 | [2, 3, 4, 5] | 3
- 4 | 1 | [2, 3, 4, 5] | 4
- 4 | 1 | [2, 3, 4, 5] | 5
- 4 | 1 | [3, 4, 5, 6] | 3
- 4 | 1 | [3, 4, 5, 6] | 4
- 4 | 1 | [3, 4, 5, 6] | 5
- 4 | 1 | [3, 4, 5, 6] | 6
- 2 | 2 | [1, 2, 3]    | 2
- 2 | 2 | [1, 2, 3]    | 3
- 3 | 2 | [1, 2, 3]    | 2
- 3 | 2 | [1, 2, 3]    | 3
- 3 | 2 | [2, 3, 4, 5] | 2
- 3 | 2 | [2, 3, 4, 5] | 3
- 3 | 2 | [2, 3, 4, 5] | 4
- 3 | 2 | [2, 3, 4, 5] | 5
- 4 | 2 | [1, 2, 3]    | 2
- 4 | 2 | [1, 2, 3]    | 3
- 4 | 2 | [2, 3, 4, 5] | 2
- 4 | 2 | [2, 3, 4, 5] | 3
- 4 | 2 | [2, 3, 4, 5] | 4
- 4 | 2 | [2, 3, 4, 5] | 5
- 4 | 2 | [3, 4, 5, 6] | 3
- 4 | 2 | [3, 4, 5, 6] | 4
- 4 | 2 | [3, 4, 5, 6] | 5
- 4 | 2 | [3, 4, 5, 6] | 6
- 2 | 3 | [1, 2, 3]    | 3
- 3 | 3 | [1, 2, 3]    | 3
- 3 | 3 | [2, 3, 4, 5] | 3
- 3 | 3 | [2, 3, 4, 5] | 4
- 3 | 3 | [2, 3, 4, 5] | 5
- 4 | 3 | [1, 2, 3]    | 3
- 4 | 3 | [2, 3, 4, 5] | 3
- 4 | 3 | [2, 3, 4, 5] | 4
- 4 | 3 | [2, 3, 4, 5] | 5
- 4 | 3 | [3, 4, 5, 6] | 3
- 4 | 3 | [3, 4, 5, 6] | 4
- 4 | 3 | [3, 4, 5, 6] | 5
- 4 | 3 | [3, 4, 5, 6] | 6
-(52 rows)
-
--- Should fail (JSON arguments are not passed to column paths)
-SELECT *
-FROM JSON_TABLE(
-	jsonb '[1,2,3]',
-	'$[*] ? (@ < $x)'
-		PASSING 10 AS x
-		COLUMNS (y text FORMAT JSON PATH '$ ? (@ < $x)')
-	) jt;
-ERROR:  could not find jsonpath variable "x"
--- Extension: non-constant JSON path
-SELECT JSON_EXISTS(jsonb '{"a": 123}', '$' || '.' || 'a');
- json_exists 
--------------
- t
-(1 row)
-
-SELECT JSON_VALUE(jsonb '{"a": 123}', '$' || '.' || 'a');
- json_value 
-------------
- 123
-(1 row)
-
-SELECT JSON_VALUE(jsonb '{"a": 123}', '$' || '.' || 'b' DEFAULT 'foo' ON EMPTY);
- json_value 
-------------
- foo
-(1 row)
-
-SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a');
- json_query 
-------------
- 123
-(1 row)
-
-SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a' WITH WRAPPER);
- json_query 
-------------
- [123]
-(1 row)
-
--- Should fail (invalid path)
-SELECT JSON_QUERY(jsonb '{"a": 123}', 'error' || ' ' || 'error');
-ERROR:  syntax error at or near " " of jsonpath input
--- Should fail (not supported)
-SELECT * FROM JSON_TABLE(jsonb '{"a": 123}', '$' || '.' || 'a' COLUMNS (foo int));
-ERROR:  only string constants supported in JSON_TABLE path specification
-LINE 1: SELECT * FROM JSON_TABLE(jsonb '{"a": 123}', '$' || '.' || '...
-                                                     ^
--- Test parallel JSON_VALUE()
-CREATE UNLOGGED TABLE test_parallel_jsonb_value AS
-SELECT i::text::jsonb AS js
-FROM generate_series(1, 50000) i;
--- encourage use of parallel plans
-set parallel_setup_cost=0;
-set parallel_tuple_cost=0;
-set min_parallel_table_scan_size=0;
-set max_parallel_workers_per_gather=4;
-set parallel_leader_participation = off;
--- Should be non-parallel due to subtransactions
-EXPLAIN (COSTS OFF)
-SELECT sum(JSON_VALUE(js, '$' RETURNING numeric)) FROM test_parallel_jsonb_value;
-                 QUERY PLAN                  
----------------------------------------------
- Aggregate
-   ->  Seq Scan on test_parallel_jsonb_value
-(2 rows)
-
-SELECT sum(JSON_VALUE(js, '$' RETURNING numeric)) FROM test_parallel_jsonb_value;
-    sum     
-------------
- 1250025000
-(1 row)
-
--- Should be parallel
-EXPLAIN (COSTS OFF)
-SELECT sum(JSON_VALUE(js, '$' RETURNING numeric ERROR ON ERROR)) FROM test_parallel_jsonb_value;
-                            QUERY PLAN                            
-------------------------------------------------------------------
- Finalize Aggregate
-   ->  Gather
-         Workers Planned: 4
-         ->  Partial Aggregate
-               ->  Parallel Seq Scan on test_parallel_jsonb_value
-(5 rows)
-
-SELECT sum(JSON_VALUE(js, '$' RETURNING numeric ERROR ON ERROR)) FROM test_parallel_jsonb_value;
-    sum     
-------------
- 1250025000
-(1 row)
-
-DROP TABLE test_parallel_jsonb_value;
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 86d755aa44..330eb0f765 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -1474,10 +1474,8 @@ WHERE a.aggfnoid = p.oid AND
          NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
      OR (p.pronargs > 2 AND
          NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
-     OR (p.pronargs > 3 AND
-         NOT binary_coercible(p.proargtypes[3], ptr.proargtypes[4]))
-     -- we could carry the check further, but 4 args is enough for now
-     OR (p.pronargs > 4)
+     -- we could carry the check further, but 3 args is enough for now
+     OR (p.pronargs > 3)
     );
  aggfnoid | proname | oid | proname 
 ----------+---------+-----+---------
diff --git a/src/test/regress/expected/sqljson.out b/src/test/regress/expected/sqljson.out
deleted file mode 100644
index 748dfdb04d..0000000000
--- a/src/test/regress/expected/sqljson.out
+++ /dev/null
@@ -1,1320 +0,0 @@
--- JSON()
-SELECT JSON();
-ERROR:  syntax error at or near ")"
-LINE 1: SELECT JSON();
-                    ^
-SELECT JSON(NULL);
- json 
-------
- 
-(1 row)
-
-SELECT JSON('{ "a" : 1 } ');
-     json     
---------------
- { "a" : 1 } 
-(1 row)
-
-SELECT JSON('{ "a" : 1 } ' FORMAT JSON);
-     json     
---------------
- { "a" : 1 } 
-(1 row)
-
-SELECT JSON('{ "a" : 1 } ' FORMAT JSON ENCODING UTF8);
-ERROR:  JSON ENCODING clause is only allowed for bytea input type
-LINE 1: SELECT JSON('{ "a" : 1 } ' FORMAT JSON ENCODING UTF8);
-                                   ^
-SELECT JSON('{ "a" : 1 } '::bytea FORMAT JSON ENCODING UTF8);
-     json     
---------------
- { "a" : 1 } 
-(1 row)
-
-SELECT pg_typeof(JSON('{ "a" : 1 } '));
- pg_typeof 
------------
- json
-(1 row)
-
-SELECT JSON('   1   '::json);
-  json   
----------
-    1   
-(1 row)
-
-SELECT JSON('   1   '::jsonb);
- json 
-------
- 1
-(1 row)
-
-SELECT JSON('   1   '::json WITH UNIQUE KEYS);
-ERROR:  cannot use non-string types with WITH UNIQUE KEYS clause
-LINE 1: SELECT JSON('   1   '::json WITH UNIQUE KEYS);
-               ^
-SELECT JSON(123);
-ERROR:  cannot cast type integer to json
-LINE 1: SELECT JSON(123);
-                    ^
-SELECT JSON('{"a": 1, "a": 2}');
-       json       
-------------------
- {"a": 1, "a": 2}
-(1 row)
-
-SELECT JSON('{"a": 1, "a": 2}' WITH UNIQUE KEYS);
-ERROR:  duplicate JSON object key value
-SELECT JSON('{"a": 1, "a": 2}' WITHOUT UNIQUE KEYS);
-       json       
-------------------
- {"a": 1, "a": 2}
-(1 row)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123');
-         QUERY PLAN          
------------------------------
- Result
-   Output: JSON('123'::json)
-(2 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' FORMAT JSON);
-         QUERY PLAN          
------------------------------
- Result
-   Output: JSON('123'::json)
-(2 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123'::bytea FORMAT JSON);
-                  QUERY PLAN                   
------------------------------------------------
- Result
-   Output: JSON('\x313233'::bytea FORMAT JSON)
-(2 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123'::bytea FORMAT JSON ENCODING UTF8);
-                         QUERY PLAN                          
--------------------------------------------------------------
- Result
-   Output: JSON('\x313233'::bytea FORMAT JSON ENCODING UTF8)
-(2 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' WITH UNIQUE KEYS);
-                  QUERY PLAN                  
-----------------------------------------------
- Result
-   Output: JSON('123'::text WITH UNIQUE KEYS)
-(2 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' WITHOUT UNIQUE KEYS);
-         QUERY PLAN          
------------------------------
- Result
-   Output: JSON('123'::json)
-(2 rows)
-
-SELECT JSON('123' RETURNING text);
-ERROR:  cannot use RETURNING type text in JSON()
-LINE 1: SELECT JSON('123' RETURNING text);
-                                    ^
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123');
-         QUERY PLAN          
------------------------------
- Result
-   Output: JSON('123'::json)
-(2 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING json);
-         QUERY PLAN          
------------------------------
- Result
-   Output: JSON('123'::json)
-(2 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING jsonb);
-                  QUERY PLAN                  
-----------------------------------------------
- Result
-   Output: JSON('123'::jsonb RETURNING jsonb)
-(2 rows)
-
-SELECT pg_typeof(JSON('123'));
- pg_typeof 
------------
- json
-(1 row)
-
-SELECT pg_typeof(JSON('123' RETURNING json));
- pg_typeof 
------------
- json
-(1 row)
-
-SELECT pg_typeof(JSON('123' RETURNING jsonb));
- pg_typeof 
------------
- jsonb
-(1 row)
-
--- JSON_SCALAR()
-SELECT JSON_SCALAR();
-ERROR:  syntax error at or near ")"
-LINE 1: SELECT JSON_SCALAR();
-                           ^
-SELECT JSON_SCALAR(NULL);
- json_scalar 
--------------
- 
-(1 row)
-
-SELECT JSON_SCALAR(NULL::int);
- json_scalar 
--------------
- 
-(1 row)
-
-SELECT JSON_SCALAR(123);
- json_scalar 
--------------
- 123
-(1 row)
-
-SELECT JSON_SCALAR(123.45);
- json_scalar 
--------------
- 123.45
-(1 row)
-
-SELECT JSON_SCALAR(123.45::numeric);
- json_scalar 
--------------
- 123.45
-(1 row)
-
-SELECT JSON_SCALAR(true);
- json_scalar 
--------------
- true
-(1 row)
-
-SELECT JSON_SCALAR(false);
- json_scalar 
--------------
- false
-(1 row)
-
-SELECT JSON_SCALAR(' 123.45');
- json_scalar 
--------------
- " 123.45"
-(1 row)
-
-SELECT JSON_SCALAR('2020-06-07'::date);
- json_scalar  
---------------
- "2020-06-07"
-(1 row)
-
-SELECT JSON_SCALAR('2020-06-07 01:02:03'::timestamp);
-      json_scalar      
------------------------
- "2020-06-07T01:02:03"
-(1 row)
-
-SELECT JSON_SCALAR('{}'::json);
- json_scalar 
--------------
- {}
-(1 row)
-
-SELECT JSON_SCALAR('{}'::jsonb);
- json_scalar 
--------------
- {}
-(1 row)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123);
-         QUERY PLAN         
-----------------------------
- Result
-   Output: JSON_SCALAR(123)
-(2 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR('123');
-             QUERY PLAN             
-------------------------------------
- Result
-   Output: JSON_SCALAR('123'::text)
-(2 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING json);
-         QUERY PLAN         
-----------------------------
- Result
-   Output: JSON_SCALAR(123)
-(2 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING jsonb);
-                 QUERY PLAN                 
---------------------------------------------
- Result
-   Output: JSON_SCALAR(123 RETURNING jsonb)
-(2 rows)
-
--- JSON_SERIALIZE()
-SELECT JSON_SERIALIZE();
-ERROR:  syntax error at or near ")"
-LINE 1: SELECT JSON_SERIALIZE();
-                              ^
-SELECT JSON_SERIALIZE(NULL);
- json_serialize 
-----------------
- 
-(1 row)
-
-SELECT JSON_SERIALIZE(JSON('{ "a" : 1 } '));
- json_serialize 
-----------------
- { "a" : 1 } 
-(1 row)
-
-SELECT JSON_SERIALIZE('{ "a" : 1 } ');
- json_serialize 
-----------------
- { "a" : 1 } 
-(1 row)
-
-SELECT JSON_SERIALIZE('1');
- json_serialize 
-----------------
- 1
-(1 row)
-
-SELECT JSON_SERIALIZE('1' FORMAT JSON);
- json_serialize 
-----------------
- 1
-(1 row)
-
-SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING bytea);
-       json_serialize       
-----------------------------
- \x7b20226122203a2031207d20
-(1 row)
-
-SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING varchar);
- json_serialize 
-----------------
- { "a" : 1 } 
-(1 row)
-
-SELECT pg_typeof(JSON_SERIALIZE(NULL));
- pg_typeof 
------------
- text
-(1 row)
-
--- only string types or bytea allowed
-SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING jsonb);
-ERROR:  cannot use RETURNING type jsonb in JSON_SERIALIZE()
-HINT:  Try returning a string type or bytea.
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SERIALIZE('{}');
-                     QUERY PLAN                      
------------------------------------------------------
- Result
-   Output: JSON_SERIALIZE('{}'::json RETURNING text)
-(2 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SERIALIZE('{}' RETURNING bytea);
-                      QUERY PLAN                      
-------------------------------------------------------
- Result
-   Output: JSON_SERIALIZE('{}'::json RETURNING bytea)
-(2 rows)
-
--- JSON_OBJECT()
-SELECT JSON_OBJECT();
- json_object 
--------------
- {}
-(1 row)
-
-SELECT JSON_OBJECT(RETURNING json);
- json_object 
--------------
- {}
-(1 row)
-
-SELECT JSON_OBJECT(RETURNING json FORMAT JSON);
- json_object 
--------------
- {}
-(1 row)
-
-SELECT JSON_OBJECT(RETURNING jsonb);
- json_object 
--------------
- {}
-(1 row)
-
-SELECT JSON_OBJECT(RETURNING jsonb FORMAT JSON);
- json_object 
--------------
- {}
-(1 row)
-
-SELECT JSON_OBJECT(RETURNING text);
- json_object 
--------------
- {}
-(1 row)
-
-SELECT JSON_OBJECT(RETURNING text FORMAT JSON);
- json_object 
--------------
- {}
-(1 row)
-
-SELECT JSON_OBJECT(RETURNING text FORMAT JSON ENCODING UTF8);
-ERROR:  cannot set JSON encoding for non-bytea output types
-LINE 1: SELECT JSON_OBJECT(RETURNING text FORMAT JSON ENCODING UTF8)...
-                                          ^
-SELECT JSON_OBJECT(RETURNING text FORMAT JSON ENCODING INVALID_ENCODING);
-ERROR:  unrecognized JSON encoding: invalid_encoding
-SELECT JSON_OBJECT(RETURNING bytea);
- json_object 
--------------
- \x7b7d
-(1 row)
-
-SELECT JSON_OBJECT(RETURNING bytea FORMAT JSON);
- json_object 
--------------
- \x7b7d
-(1 row)
-
-SELECT JSON_OBJECT(RETURNING bytea FORMAT JSON ENCODING UTF8);
- json_object 
--------------
- \x7b7d
-(1 row)
-
-SELECT JSON_OBJECT(RETURNING bytea FORMAT JSON ENCODING UTF16);
-ERROR:  unsupported JSON encoding
-LINE 1: SELECT JSON_OBJECT(RETURNING bytea FORMAT JSON ENCODING UTF1...
-                                           ^
-HINT:  Only UTF8 JSON encoding is supported.
-SELECT JSON_OBJECT(RETURNING bytea FORMAT JSON ENCODING UTF32);
-ERROR:  unsupported JSON encoding
-LINE 1: SELECT JSON_OBJECT(RETURNING bytea FORMAT JSON ENCODING UTF3...
-                                           ^
-HINT:  Only UTF8 JSON encoding is supported.
-SELECT JSON_OBJECT('foo': NULL::int FORMAT JSON);
-ERROR:  cannot use non-string types with explicit FORMAT JSON clause
-LINE 1: SELECT JSON_OBJECT('foo': NULL::int FORMAT JSON);
-                                            ^
-SELECT JSON_OBJECT('foo': NULL::int FORMAT JSON ENCODING UTF8);
-ERROR:  JSON ENCODING clause is only allowed for bytea input type
-LINE 1: SELECT JSON_OBJECT('foo': NULL::int FORMAT JSON ENCODING UTF...
-                                            ^
-SELECT JSON_OBJECT('foo': NULL::json FORMAT JSON);
-WARNING:  FORMAT JSON has no effect for json and jsonb types
-LINE 1: SELECT JSON_OBJECT('foo': NULL::json FORMAT JSON);
-                                             ^
-  json_object   
-----------------
- {"foo" : null}
-(1 row)
-
-SELECT JSON_OBJECT('foo': NULL::json FORMAT JSON ENCODING UTF8);
-ERROR:  JSON ENCODING clause is only allowed for bytea input type
-LINE 1: SELECT JSON_OBJECT('foo': NULL::json FORMAT JSON ENCODING UT...
-                                             ^
-SELECT JSON_OBJECT('foo': NULL::jsonb FORMAT JSON);
-WARNING:  FORMAT JSON has no effect for json and jsonb types
-LINE 1: SELECT JSON_OBJECT('foo': NULL::jsonb FORMAT JSON);
-                                              ^
-  json_object  
----------------
- {"foo": null}
-(1 row)
-
-SELECT JSON_OBJECT('foo': NULL::jsonb FORMAT JSON ENCODING UTF8);
-ERROR:  JSON ENCODING clause is only allowed for bytea input type
-LINE 1: SELECT JSON_OBJECT('foo': NULL::jsonb FORMAT JSON ENCODING U...
-                                              ^
-SELECT JSON_OBJECT(NULL: 1);
-ERROR:  argument 1 cannot be null
-HINT:  Object keys should be text.
-SELECT JSON_OBJECT('a': 2 + 3);
- json_object 
--------------
- {"a" : 5}
-(1 row)
-
-SELECT JSON_OBJECT('a' VALUE 2 + 3);
- json_object 
--------------
- {"a" : 5}
-(1 row)
-
---SELECT JSON_OBJECT(KEY 'a' VALUE 2 + 3);
-SELECT JSON_OBJECT('a' || 2: 1);
- json_object 
--------------
- {"a2" : 1}
-(1 row)
-
-SELECT JSON_OBJECT(('a' || 2) VALUE 1);
- json_object 
--------------
- {"a2" : 1}
-(1 row)
-
---SELECT JSON_OBJECT('a' || 2 VALUE 1);
---SELECT JSON_OBJECT(KEY 'a' || 2 VALUE 1);
-SELECT JSON_OBJECT('a': 2::text);
- json_object 
--------------
- {"a" : "2"}
-(1 row)
-
-SELECT JSON_OBJECT('a' VALUE 2::text);
- json_object 
--------------
- {"a" : "2"}
-(1 row)
-
---SELECT JSON_OBJECT(KEY 'a' VALUE 2::text);
-SELECT JSON_OBJECT(1::text: 2);
- json_object 
--------------
- {"1" : 2}
-(1 row)
-
-SELECT JSON_OBJECT((1::text) VALUE 2);
- json_object 
--------------
- {"1" : 2}
-(1 row)
-
---SELECT JSON_OBJECT(1::text VALUE 2);
---SELECT JSON_OBJECT(KEY 1::text VALUE 2);
-SELECT JSON_OBJECT(json '[1]': 123);
-ERROR:  key value must be scalar, not array, composite, or json
-SELECT JSON_OBJECT(ARRAY[1,2,3]: 'aaa');
-ERROR:  key value must be scalar, not array, composite, or json
-SELECT JSON_OBJECT(
-	'a': '123',
-	1.23: 123,
-	'c': json '[ 1,true,{ } ]',
-	'd': jsonb '{ "x" : 123.45 }'
-);
-                            json_object                            
--------------------------------------------------------------------
- {"a": "123", "c": [1, true, {}], "d": {"x": 123.45}, "1.23": 123}
-(1 row)
-
-SELECT JSON_OBJECT(
-	'a': '123',
-	1.23: 123,
-	'c': json '[ 1,true,{ } ]',
-	'd': jsonb '{ "x" : 123.45 }'
-	RETURNING jsonb
-);
-                            json_object                            
--------------------------------------------------------------------
- {"a": "123", "c": [1, true, {}], "d": {"x": 123.45}, "1.23": 123}
-(1 row)
-
-/*
-SELECT JSON_OBJECT(
-	'a': '123',
-	KEY 1.23 VALUE 123,
-	'c' VALUE json '[1, true, {}]'
-);
-*/
-SELECT JSON_OBJECT('a': '123', 'b': JSON_OBJECT('a': 111, 'b': 'aaa'));
-                  json_object                  
------------------------------------------------
- {"a" : "123", "b" : {"a" : 111, "b" : "aaa"}}
-(1 row)
-
-SELECT JSON_OBJECT('a': '123', 'b': JSON_OBJECT('a': 111, 'b': 'aaa' RETURNING jsonb));
-                json_object                
--------------------------------------------
- {"a": "123", "b": {"a": 111, "b": "aaa"}}
-(1 row)
-
-SELECT JSON_OBJECT('a': JSON_OBJECT('b': 1 RETURNING text));
-      json_object      
------------------------
- {"a" : "{\"b\" : 1}"}
-(1 row)
-
-SELECT JSON_OBJECT('a': JSON_OBJECT('b': 1 RETURNING text) FORMAT JSON);
-    json_object    
--------------------
- {"a" : {"b" : 1}}
-(1 row)
-
-SELECT JSON_OBJECT('a': JSON_OBJECT('b': 1 RETURNING bytea));
-           json_object           
----------------------------------
- {"a" : "\\x7b226222203a20317d"}
-(1 row)
-
-SELECT JSON_OBJECT('a': JSON_OBJECT('b': 1 RETURNING bytea) FORMAT JSON);
-    json_object    
--------------------
- {"a" : {"b" : 1}}
-(1 row)
-
-SELECT JSON_OBJECT('a': '1', 'b': NULL, 'c': 2);
-           json_object            
-----------------------------------
- {"a" : "1", "b" : null, "c" : 2}
-(1 row)
-
-SELECT JSON_OBJECT('a': '1', 'b': NULL, 'c': 2 NULL ON NULL);
-           json_object            
-----------------------------------
- {"a" : "1", "b" : null, "c" : 2}
-(1 row)
-
-SELECT JSON_OBJECT('a': '1', 'b': NULL, 'c': 2 ABSENT ON NULL);
-     json_object      
-----------------------
- {"a" : "1", "c" : 2}
-(1 row)
-
-SELECT JSON_OBJECT(1: 1, '1': NULL WITH UNIQUE);
-ERROR:  duplicate JSON key "1"
-SELECT JSON_OBJECT(1: 1, '1': NULL ABSENT ON NULL WITH UNIQUE);
-ERROR:  duplicate JSON key "1"
-SELECT JSON_OBJECT(1: 1, '1': NULL NULL ON NULL WITH UNIQUE RETURNING jsonb);
-ERROR:  duplicate JSON object key value
-SELECT JSON_OBJECT(1: 1, '1': NULL ABSENT ON NULL WITH UNIQUE RETURNING jsonb);
-ERROR:  duplicate JSON object key value
-SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 NULL ON NULL WITH UNIQUE);
-ERROR:  duplicate JSON key "1"
-SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 ABSENT ON NULL WITH UNIQUE);
-ERROR:  duplicate JSON key "1"
-SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 ABSENT ON NULL WITHOUT UNIQUE);
-    json_object     
---------------------
- {"1" : 1, "1" : 1}
-(1 row)
-
-SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 ABSENT ON NULL WITH UNIQUE RETURNING jsonb);
-ERROR:  duplicate JSON object key value
-SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 ABSENT ON NULL WITHOUT UNIQUE RETURNING jsonb);
- json_object 
--------------
- {"1": 1}
-(1 row)
-
-SELECT JSON_OBJECT(1: 1, '2': NULL, '3': 1, 4: NULL, '5': 'a' ABSENT ON NULL WITH UNIQUE RETURNING jsonb);
-        json_object         
-----------------------------
- {"1": 1, "3": 1, "5": "a"}
-(1 row)
-
--- JSON_ARRAY()
-SELECT JSON_ARRAY();
- json_array 
-------------
- []
-(1 row)
-
-SELECT JSON_ARRAY(RETURNING json);
- json_array 
-------------
- []
-(1 row)
-
-SELECT JSON_ARRAY(RETURNING json FORMAT JSON);
- json_array 
-------------
- []
-(1 row)
-
-SELECT JSON_ARRAY(RETURNING jsonb);
- json_array 
-------------
- []
-(1 row)
-
-SELECT JSON_ARRAY(RETURNING jsonb FORMAT JSON);
- json_array 
-------------
- []
-(1 row)
-
-SELECT JSON_ARRAY(RETURNING text);
- json_array 
-------------
- []
-(1 row)
-
-SELECT JSON_ARRAY(RETURNING text FORMAT JSON);
- json_array 
-------------
- []
-(1 row)
-
-SELECT JSON_ARRAY(RETURNING text FORMAT JSON ENCODING UTF8);
-ERROR:  cannot set JSON encoding for non-bytea output types
-LINE 1: SELECT JSON_ARRAY(RETURNING text FORMAT JSON ENCODING UTF8);
-                                         ^
-SELECT JSON_ARRAY(RETURNING text FORMAT JSON ENCODING INVALID_ENCODING);
-ERROR:  unrecognized JSON encoding: invalid_encoding
-SELECT JSON_ARRAY(RETURNING bytea);
- json_array 
-------------
- \x5b5d
-(1 row)
-
-SELECT JSON_ARRAY(RETURNING bytea FORMAT JSON);
- json_array 
-------------
- \x5b5d
-(1 row)
-
-SELECT JSON_ARRAY(RETURNING bytea FORMAT JSON ENCODING UTF8);
- json_array 
-------------
- \x5b5d
-(1 row)
-
-SELECT JSON_ARRAY(RETURNING bytea FORMAT JSON ENCODING UTF16);
-ERROR:  unsupported JSON encoding
-LINE 1: SELECT JSON_ARRAY(RETURNING bytea FORMAT JSON ENCODING UTF16...
-                                          ^
-HINT:  Only UTF8 JSON encoding is supported.
-SELECT JSON_ARRAY(RETURNING bytea FORMAT JSON ENCODING UTF32);
-ERROR:  unsupported JSON encoding
-LINE 1: SELECT JSON_ARRAY(RETURNING bytea FORMAT JSON ENCODING UTF32...
-                                          ^
-HINT:  Only UTF8 JSON encoding is supported.
-SELECT JSON_ARRAY('aaa', 111, true, array[1,2,3], NULL, json '{"a": [1]}', jsonb '["a",3]');
-                     json_array                      
------------------------------------------------------
- ["aaa", 111, true, [1, 2, 3], {"a": [1]}, ["a", 3]]
-(1 row)
-
-SELECT JSON_ARRAY('a',  NULL, 'b' NULL   ON NULL);
-    json_array    
-------------------
- ["a", null, "b"]
-(1 row)
-
-SELECT JSON_ARRAY('a',  NULL, 'b' ABSENT ON NULL);
- json_array 
-------------
- ["a", "b"]
-(1 row)
-
-SELECT JSON_ARRAY(NULL, NULL, 'b' ABSENT ON NULL);
- json_array 
-------------
- ["b"]
-(1 row)
-
-SELECT JSON_ARRAY('a',  NULL, 'b' NULL   ON NULL RETURNING jsonb);
-    json_array    
-------------------
- ["a", null, "b"]
-(1 row)
-
-SELECT JSON_ARRAY('a',  NULL, 'b' ABSENT ON NULL RETURNING jsonb);
- json_array 
-------------
- ["a", "b"]
-(1 row)
-
-SELECT JSON_ARRAY(NULL, NULL, 'b' ABSENT ON NULL RETURNING jsonb);
- json_array 
-------------
- ["b"]
-(1 row)
-
-SELECT JSON_ARRAY(JSON_ARRAY('{ "a" : 123 }' RETURNING text));
-          json_array           
--------------------------------
- ["[\"{ \\\"a\\\" : 123 }\"]"]
-(1 row)
-
-SELECT JSON_ARRAY(JSON_ARRAY('{ "a" : 123 }' FORMAT JSON RETURNING text));
-      json_array       
------------------------
- ["[{ \"a\" : 123 }]"]
-(1 row)
-
-SELECT JSON_ARRAY(JSON_ARRAY('{ "a" : 123 }' FORMAT JSON RETURNING text) FORMAT JSON);
-    json_array     
--------------------
- [[{ "a" : 123 }]]
-(1 row)
-
-SELECT JSON_ARRAY(SELECT i FROM (VALUES (1), (2), (NULL), (4)) foo(i));
- json_array 
-------------
- [1, 2, 4]
-(1 row)
-
-SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i));
- json_array 
-------------
- [[1,2],   +
-  [3,4]]
-(1 row)
-
-SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) RETURNING jsonb);
-    json_array    
-------------------
- [[1, 2], [3, 4]]
-(1 row)
-
---SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) NULL ON NULL);
---SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) NULL ON NULL RETURNING jsonb);
-SELECT JSON_ARRAY(SELECT i FROM (VALUES (3), (1), (NULL), (2)) foo(i) ORDER BY i);
- json_array 
-------------
- [1, 2, 3]
-(1 row)
-
--- Should fail
-SELECT JSON_ARRAY(SELECT FROM (VALUES (1)) foo(i));
-ERROR:  subquery must return only one column
-LINE 1: SELECT JSON_ARRAY(SELECT FROM (VALUES (1)) foo(i));
-               ^
-SELECT JSON_ARRAY(SELECT i, i FROM (VALUES (1)) foo(i));
-ERROR:  subquery must return only one column
-LINE 1: SELECT JSON_ARRAY(SELECT i, i FROM (VALUES (1)) foo(i));
-               ^
-SELECT JSON_ARRAY(SELECT * FROM (VALUES (1, 2)) foo(i, j));
-ERROR:  subquery must return only one column
-LINE 1: SELECT JSON_ARRAY(SELECT * FROM (VALUES (1, 2)) foo(i, j));
-               ^
--- JSON_ARRAYAGG()
-SELECT	JSON_ARRAYAGG(i) IS NULL,
-		JSON_ARRAYAGG(i RETURNING jsonb) IS NULL
-FROM generate_series(1, 0) i;
- ?column? | ?column? 
-----------+----------
- t        | t
-(1 row)
-
-SELECT	JSON_ARRAYAGG(i),
-		JSON_ARRAYAGG(i RETURNING jsonb)
-FROM generate_series(1, 5) i;
-  json_arrayagg  |  json_arrayagg  
------------------+-----------------
- [1, 2, 3, 4, 5] | [1, 2, 3, 4, 5]
-(1 row)
-
-SELECT JSON_ARRAYAGG(i ORDER BY i DESC)
-FROM generate_series(1, 5) i;
-  json_arrayagg  
------------------
- [5, 4, 3, 2, 1]
-(1 row)
-
-SELECT JSON_ARRAYAGG(i::text::json)
-FROM generate_series(1, 5) i;
-  json_arrayagg  
------------------
- [1, 2, 3, 4, 5]
-(1 row)
-
-SELECT JSON_ARRAYAGG(JSON_ARRAY(i, i + 1 RETURNING text) FORMAT JSON)
-FROM generate_series(1, 5) i;
-              json_arrayagg               
-------------------------------------------
- [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]
-(1 row)
-
-SELECT	JSON_ARRAYAGG(NULL),
-		JSON_ARRAYAGG(NULL RETURNING jsonb)
-FROM generate_series(1, 5);
- json_arrayagg | json_arrayagg 
----------------+---------------
- []            | []
-(1 row)
-
-SELECT	JSON_ARRAYAGG(NULL NULL ON NULL),
-		JSON_ARRAYAGG(NULL NULL ON NULL RETURNING jsonb)
-FROM generate_series(1, 5);
-         json_arrayagg          |         json_arrayagg          
---------------------------------+--------------------------------
- [null, null, null, null, null] | [null, null, null, null, null]
-(1 row)
-
-SELECT
-	JSON_ARRAYAGG(bar),
-	JSON_ARRAYAGG(bar RETURNING jsonb),
-	JSON_ARRAYAGG(bar ABSENT ON NULL),
-	JSON_ARRAYAGG(bar ABSENT ON NULL RETURNING jsonb),
-	JSON_ARRAYAGG(bar NULL ON NULL),
-	JSON_ARRAYAGG(bar NULL ON NULL RETURNING jsonb),
-	JSON_ARRAYAGG(foo),
-	JSON_ARRAYAGG(foo RETURNING jsonb),
-	JSON_ARRAYAGG(foo ORDER BY bar) FILTER (WHERE bar > 2),
-	JSON_ARRAYAGG(foo ORDER BY bar RETURNING jsonb) FILTER (WHERE bar > 2)
-FROM
-	(VALUES (NULL), (3), (1), (NULL), (NULL), (5), (2), (4), (NULL)) foo(bar);
-  json_arrayagg  |  json_arrayagg  |  json_arrayagg  |  json_arrayagg  |              json_arrayagg              |              json_arrayagg              |  json_arrayagg  |                                                      json_arrayagg                                                       | json_arrayagg |            json_arrayagg             
------------------+-----------------+-----------------+-----------------+-----------------------------------------+-----------------------------------------+-----------------+--------------------------------------------------------------------------------------------------------------------------+---------------+--------------------------------------
- [1, 2, 3, 4, 5] | [1, 2, 3, 4, 5] | [1, 2, 3, 4, 5] | [1, 2, 3, 4, 5] | [1, 2, 3, 4, 5, null, null, null, null] | [1, 2, 3, 4, 5, null, null, null, null] | [{"bar":1},    +| [{"bar": 1}, {"bar": 2}, {"bar": 3}, {"bar": 4}, {"bar": 5}, {"bar": null}, {"bar": null}, {"bar": null}, {"bar": null}] | [{"bar":3},  +| [{"bar": 3}, {"bar": 4}, {"bar": 5}]
-                 |                 |                 |                 |                                         |                                         |  {"bar":2},    +|                                                                                                                          |  {"bar":4},  +| 
-                 |                 |                 |                 |                                         |                                         |  {"bar":3},    +|                                                                                                                          |  {"bar":5}]   | 
-                 |                 |                 |                 |                                         |                                         |  {"bar":4},    +|                                                                                                                          |               | 
-                 |                 |                 |                 |                                         |                                         |  {"bar":5},    +|                                                                                                                          |               | 
-                 |                 |                 |                 |                                         |                                         |  {"bar":null}, +|                                                                                                                          |               | 
-                 |                 |                 |                 |                                         |                                         |  {"bar":null}, +|                                                                                                                          |               | 
-                 |                 |                 |                 |                                         |                                         |  {"bar":null}, +|                                                                                                                          |               | 
-                 |                 |                 |                 |                                         |                                         |  {"bar":null}]  |                                                                                                                          |               | 
-(1 row)
-
-SELECT
-	bar, JSON_ARRAYAGG(bar) FILTER (WHERE bar > 2) OVER (PARTITION BY foo.bar % 2)
-FROM
-	(VALUES (NULL), (3), (1), (NULL), (NULL), (5), (2), (4), (NULL), (5), (4)) foo(bar);
- bar | json_arrayagg 
------+---------------
-   4 | [4, 4]
-   4 | [4, 4]
-   2 | [4, 4]
-   5 | [5, 3, 5]
-   3 | [5, 3, 5]
-   1 | [5, 3, 5]
-   5 | [5, 3, 5]
-     | 
-     | 
-     | 
-     | 
-(11 rows)
-
--- JSON_OBJECTAGG()
-SELECT	JSON_OBJECTAGG('key': 1) IS NULL,
-		JSON_OBJECTAGG('key': 1 RETURNING jsonb) IS NULL
-WHERE FALSE;
- ?column? | ?column? 
-----------+----------
- t        | t
-(1 row)
-
-SELECT JSON_OBJECTAGG(NULL: 1);
-ERROR:  field name must not be null
-SELECT JSON_OBJECTAGG(NULL: 1 RETURNING jsonb);
-ERROR:  field name must not be null
-SELECT
-	JSON_OBJECTAGG(i: i),
---	JSON_OBJECTAGG(i VALUE i),
---	JSON_OBJECTAGG(KEY i VALUE i),
-	JSON_OBJECTAGG(i: i RETURNING jsonb)
-FROM
-	generate_series(1, 5) i;
-                 json_objectagg                  |              json_objectagg              
--------------------------------------------------+------------------------------------------
- { "1" : 1, "2" : 2, "3" : 3, "4" : 4, "5" : 5 } | {"1": 1, "2": 2, "3": 3, "4": 4, "5": 5}
-(1 row)
-
-SELECT
-	JSON_OBJECTAGG(k: v),
-	JSON_OBJECTAGG(k: v NULL ON NULL),
-	JSON_OBJECTAGG(k: v ABSENT ON NULL),
-	JSON_OBJECTAGG(k: v RETURNING jsonb),
-	JSON_OBJECTAGG(k: v NULL ON NULL RETURNING jsonb),
-	JSON_OBJECTAGG(k: v ABSENT ON NULL RETURNING jsonb)
-FROM
-	(VALUES (1, 1), (1, NULL), (2, NULL), (3, 3)) foo(k, v);
-                json_objectagg                |                json_objectagg                |    json_objectagg    |         json_objectagg         |         json_objectagg         |  json_objectagg  
-----------------------------------------------+----------------------------------------------+----------------------+--------------------------------+--------------------------------+------------------
- { "1" : 1, "1" : null, "2" : null, "3" : 3 } | { "1" : 1, "1" : null, "2" : null, "3" : 3 } | { "1" : 1, "3" : 3 } | {"1": null, "2": null, "3": 3} | {"1": null, "2": null, "3": 3} | {"1": 1, "3": 3}
-(1 row)
-
-SELECT JSON_OBJECTAGG(k: v WITH UNIQUE KEYS)
-FROM (VALUES (1, 1), (1, NULL), (2, 2)) foo(k, v);
-ERROR:  duplicate JSON key "1"
-SELECT JSON_OBJECTAGG(k: v ABSENT ON NULL WITH UNIQUE KEYS)
-FROM (VALUES (1, 1), (1, NULL), (2, 2)) foo(k, v);
-ERROR:  duplicate JSON key "1"
-SELECT JSON_OBJECTAGG(k: v ABSENT ON NULL WITH UNIQUE KEYS)
-FROM (VALUES (1, 1), (0, NULL), (3, NULL), (2, 2), (4, NULL)) foo(k, v);
-    json_objectagg    
-----------------------
- { "1" : 1, "2" : 2 }
-(1 row)
-
-SELECT JSON_OBJECTAGG(k: v WITH UNIQUE KEYS RETURNING jsonb)
-FROM (VALUES (1, 1), (1, NULL), (2, 2)) foo(k, v);
-ERROR:  duplicate JSON object key value
-SELECT JSON_OBJECTAGG(k: v ABSENT ON NULL WITH UNIQUE KEYS RETURNING jsonb)
-FROM (VALUES (1, 1), (1, NULL), (2, 2)) foo(k, v);
-ERROR:  duplicate JSON object key value
-SELECT JSON_OBJECTAGG(k: v ABSENT ON NULL WITH UNIQUE KEYS RETURNING jsonb)
-FROM (VALUES (1, 1), (0, NULL),(4, null), (5, null),(6, null),(2, 2)) foo(k, v);
-  json_objectagg  
-------------------
- {"1": 1, "2": 2}
-(1 row)
-
--- Test JSON_OBJECT deparsing
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_OBJECT('foo' : '1' FORMAT JSON, 'bar' : 'baz' RETURNING json);
-                                  QUERY PLAN                                  
-------------------------------------------------------------------------------
- Result
-   Output: JSON_OBJECT('foo' : '1'::json, 'bar' : 'baz'::text RETURNING json)
-(2 rows)
-
-CREATE VIEW json_object_view AS
-SELECT JSON_OBJECT('foo' : '1' FORMAT JSON, 'bar' : 'baz' RETURNING json);
-\sv json_object_view
-CREATE OR REPLACE VIEW public.json_object_view AS
- SELECT JSON_OBJECT('foo' : '1'::text FORMAT JSON, 'bar' : 'baz'::text RETURNING json) AS "json_object"
-DROP VIEW json_object_view;
-SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v WITH UNIQUE KEYS) OVER (ORDER BY k)
-FROM (VALUES (1,1), (2,2)) a(k,v);
-       a       |    json_objectagg    
----------------+----------------------
- {"k":1,"v":1} | { "1" : 1 }
- {"k":2,"v":2} | { "1" : 1, "2" : 2 }
-(2 rows)
-
-SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v WITH UNIQUE KEYS) OVER (ORDER BY k)
-FROM (VALUES (1,1), (1,2), (2,2)) a(k,v);
-ERROR:  duplicate JSON key "1"
-SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v ABSENT ON NULL WITH UNIQUE KEYS)
-   OVER (ORDER BY k)
-FROM (VALUES (1,1), (1,null), (2,2)) a(k,v);
-ERROR:  duplicate JSON key "1"
-SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v ABSENT ON NULL)
-OVER (ORDER BY k)
-FROM (VALUES (1,1), (1,null), (2,2)) a(k,v);
-        a         |    json_objectagg    
-------------------+----------------------
- {"k":1,"v":1}    | { "1" : 1 }
- {"k":1,"v":null} | { "1" : 1 }
- {"k":2,"v":2}    | { "1" : 1, "2" : 2 }
-(3 rows)
-
-SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v ABSENT ON NULL)
-OVER (ORDER BY k RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
-FROM (VALUES (1,1), (1,null), (2,2)) a(k,v);
-        a         |    json_objectagg    
-------------------+----------------------
- {"k":1,"v":1}    | { "1" : 1, "2" : 2 }
- {"k":1,"v":null} | { "1" : 1, "2" : 2 }
- {"k":2,"v":2}    | { "1" : 1, "2" : 2 }
-(3 rows)
-
--- Test JSON_ARRAY deparsing
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_ARRAY('1' FORMAT JSON, 2 RETURNING json);
-                    QUERY PLAN                     
----------------------------------------------------
- Result
-   Output: JSON_ARRAY('1'::json, 2 RETURNING json)
-(2 rows)
-
-CREATE VIEW json_array_view AS
-SELECT JSON_ARRAY('1' FORMAT JSON, 2 RETURNING json);
-\sv json_array_view
-CREATE OR REPLACE VIEW public.json_array_view AS
- SELECT JSON_ARRAY('1'::text FORMAT JSON, 2 RETURNING json) AS "json_array"
-DROP VIEW json_array_view;
--- Test JSON_OBJECTAGG deparsing
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_OBJECTAGG(i: ('111' || i)::bytea FORMAT JSON WITH UNIQUE RETURNING text) FILTER (WHERE i > 3)
-FROM generate_series(1,5) i;
-                                                              QUERY PLAN                                                              
---------------------------------------------------------------------------------------------------------------------------------------
- Aggregate
-   Output: JSON_OBJECTAGG(i : (('111'::text || (i)::text))::bytea FORMAT JSON WITH UNIQUE KEYS RETURNING text) FILTER (WHERE (i > 3))
-   ->  Function Scan on pg_catalog.generate_series i
-         Output: i
-         Function Call: generate_series(1, 5)
-(5 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_OBJECTAGG(i: ('111' || i)::bytea FORMAT JSON WITH UNIQUE RETURNING text) OVER (PARTITION BY i % 2)
-FROM generate_series(1,5) i;
-                                                            QUERY PLAN                                                             
------------------------------------------------------------------------------------------------------------------------------------
- WindowAgg
-   Output: JSON_OBJECTAGG(i : (('111'::text || (i)::text))::bytea FORMAT JSON WITH UNIQUE KEYS RETURNING text) OVER (?), ((i % 2))
-   ->  Sort
-         Output: ((i % 2)), i
-         Sort Key: ((i.i % 2))
-         ->  Function Scan on pg_catalog.generate_series i
-               Output: (i % 2), i
-               Function Call: generate_series(1, 5)
-(8 rows)
-
-CREATE VIEW json_objectagg_view AS
-SELECT JSON_OBJECTAGG(i: ('111' || i)::bytea FORMAT JSON WITH UNIQUE RETURNING text) FILTER (WHERE i > 3)
-FROM generate_series(1,5) i;
-\sv json_objectagg_view
-CREATE OR REPLACE VIEW public.json_objectagg_view AS
- SELECT JSON_OBJECTAGG(i.i : ('111'::text || i.i)::bytea FORMAT JSON WITH UNIQUE KEYS RETURNING text) FILTER (WHERE i.i > 3) AS "json_objectagg"
-   FROM generate_series(1, 5) i(i)
-DROP VIEW json_objectagg_view;
--- Test JSON_ARRAYAGG deparsing
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_ARRAYAGG(('111' || i)::bytea FORMAT JSON NULL ON NULL RETURNING text) FILTER (WHERE i > 3)
-FROM generate_series(1,5) i;
-                                                         QUERY PLAN                                                          
------------------------------------------------------------------------------------------------------------------------------
- Aggregate
-   Output: JSON_ARRAYAGG((('111'::text || (i)::text))::bytea FORMAT JSON NULL ON NULL RETURNING text) FILTER (WHERE (i > 3))
-   ->  Function Scan on pg_catalog.generate_series i
-         Output: i
-         Function Call: generate_series(1, 5)
-(5 rows)
-
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_ARRAYAGG(('111' || i)::bytea FORMAT JSON NULL ON NULL RETURNING text) OVER (PARTITION BY i % 2)
-FROM generate_series(1,5) i;
-                                                        QUERY PLAN                                                        
---------------------------------------------------------------------------------------------------------------------------
- WindowAgg
-   Output: JSON_ARRAYAGG((('111'::text || (i)::text))::bytea FORMAT JSON NULL ON NULL RETURNING text) OVER (?), ((i % 2))
-   ->  Sort
-         Output: ((i % 2)), i
-         Sort Key: ((i.i % 2))
-         ->  Function Scan on pg_catalog.generate_series i
-               Output: (i % 2), i
-               Function Call: generate_series(1, 5)
-(8 rows)
-
-CREATE VIEW json_arrayagg_view AS
-SELECT JSON_ARRAYAGG(('111' || i)::bytea FORMAT JSON NULL ON NULL RETURNING text) FILTER (WHERE i > 3)
-FROM generate_series(1,5) i;
-\sv json_arrayagg_view
-CREATE OR REPLACE VIEW public.json_arrayagg_view AS
- SELECT JSON_ARRAYAGG(('111'::text || i.i)::bytea FORMAT JSON NULL ON NULL RETURNING text) FILTER (WHERE i.i > 3) AS "json_arrayagg"
-   FROM generate_series(1, 5) i(i)
-DROP VIEW json_arrayagg_view;
--- Test JSON_ARRAY(subquery) deparsing
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_ARRAY(SELECT i FROM (VALUES (1), (2), (NULL), (4)) foo(i) RETURNING jsonb);
-                             QUERY PLAN                              
----------------------------------------------------------------------
- Result
-   Output: $0
-   InitPlan 1 (returns $0)
-     ->  Aggregate
-           Output: JSON_ARRAYAGG("*VALUES*".column1 RETURNING jsonb)
-           ->  Values Scan on "*VALUES*"
-                 Output: "*VALUES*".column1
-(7 rows)
-
-CREATE VIEW json_array_subquery_view AS
-SELECT JSON_ARRAY(SELECT i FROM (VALUES (1), (2), (NULL), (4)) foo(i) RETURNING jsonb);
-\sv json_array_subquery_view
-CREATE OR REPLACE VIEW public.json_array_subquery_view AS
- SELECT ( SELECT JSON_ARRAYAGG(q.a RETURNING jsonb) AS "json_arrayagg"
-           FROM ( SELECT foo.i
-                   FROM ( VALUES (1), (2), (NULL::integer), (4)) foo(i)) q(a)) AS "json_array"
-DROP VIEW json_array_subquery_view;
--- IS JSON predicate
-SELECT NULL IS JSON;
- ?column? 
-----------
- 
-(1 row)
-
-SELECT NULL IS NOT JSON;
- ?column? 
-----------
- 
-(1 row)
-
-SELECT NULL::json IS JSON;
- ?column? 
-----------
- 
-(1 row)
-
-SELECT NULL::jsonb IS JSON;
- ?column? 
-----------
- 
-(1 row)
-
-SELECT NULL::text IS JSON;
- ?column? 
-----------
- 
-(1 row)
-
-SELECT NULL::bytea IS JSON;
- ?column? 
-----------
- 
-(1 row)
-
-SELECT NULL::int IS JSON;
-ERROR:  cannot use type integer in IS JSON predicate
-SELECT '' IS JSON;
- ?column? 
-----------
- f
-(1 row)
-
-SELECT bytea '\x00' IS JSON;
-ERROR:  invalid byte sequence for encoding "UTF8": 0x00
-CREATE TABLE test_is_json (js text);
-INSERT INTO test_is_json VALUES
- (NULL),
- (''),
- ('123'),
- ('"aaa "'),
- ('true'),
- ('null'),
- ('[]'),
- ('[1, "2", {}]'),
- ('{}'),
- ('{ "a": 1, "b": null }'),
- ('{ "a": 1, "a": null }'),
- ('{ "a": 1, "b": [{ "a": 1 }, { "a": 2 }] }'),
- ('{ "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] }'),
- ('aaa'),
- ('{a:1}'),
- ('["a",]');
-SELECT
-	js,
-	js IS JSON "IS JSON",
-	js IS NOT JSON "IS NOT JSON",
-	js IS JSON VALUE "IS VALUE",
-	js IS JSON OBJECT "IS OBJECT",
-	js IS JSON ARRAY "IS ARRAY",
-	js IS JSON SCALAR "IS SCALAR",
-	js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE",
-	js IS JSON WITH UNIQUE KEYS "WITH UNIQUE"
-FROM
-	test_is_json;
-                      js                       | IS JSON | IS NOT JSON | IS VALUE | IS OBJECT | IS ARRAY | IS SCALAR | WITHOUT UNIQUE | WITH UNIQUE 
------------------------------------------------+---------+-------------+----------+-----------+----------+-----------+----------------+-------------
-                                               |         |             |          |           |          |           |                | 
-                                               | f       | t           | f        | f         | f        | f         | f              | f
- 123                                           | t       | f           | t        | f         | f        | t         | t              | t
- "aaa "                                        | t       | f           | t        | f         | f        | t         | t              | t
- true                                          | t       | f           | t        | f         | f        | t         | t              | t
- null                                          | t       | f           | t        | f         | f        | t         | t              | t
- []                                            | t       | f           | t        | f         | t        | f         | t              | t
- [1, "2", {}]                                  | t       | f           | t        | f         | t        | f         | t              | t
- {}                                            | t       | f           | t        | t         | f        | f         | t              | t
- { "a": 1, "b": null }                         | t       | f           | t        | t         | f        | f         | t              | t
- { "a": 1, "a": null }                         | t       | f           | t        | t         | f        | f         | t              | f
- { "a": 1, "b": [{ "a": 1 }, { "a": 2 }] }     | t       | f           | t        | t         | f        | f         | t              | t
- { "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t       | f           | t        | t         | f        | f         | t              | f
- aaa                                           | f       | t           | f        | f         | f        | f         | f              | f
- {a:1}                                         | f       | t           | f        | f         | f        | f         | f              | f
- ["a",]                                        | f       | t           | f        | f         | f        | f         | f              | f
-(16 rows)
-
-SELECT
-	js,
-	js IS JSON "IS JSON",
-	js IS NOT JSON "IS NOT JSON",
-	js IS JSON VALUE "IS VALUE",
-	js IS JSON OBJECT "IS OBJECT",
-	js IS JSON ARRAY "IS ARRAY",
-	js IS JSON SCALAR "IS SCALAR",
-	js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE",
-	js IS JSON WITH UNIQUE KEYS "WITH UNIQUE"
-FROM
-	(SELECT js::json FROM test_is_json WHERE js IS JSON) foo(js);
-                      js                       | IS JSON | IS NOT JSON | IS VALUE | IS OBJECT | IS ARRAY | IS SCALAR | WITHOUT UNIQUE | WITH UNIQUE 
------------------------------------------------+---------+-------------+----------+-----------+----------+-----------+----------------+-------------
- 123                                           | t       | f           | t        | f         | f        | t         | t              | t
- "aaa "                                        | t       | f           | t        | f         | f        | t         | t              | t
- true                                          | t       | f           | t        | f         | f        | t         | t              | t
- null                                          | t       | f           | t        | f         | f        | t         | t              | t
- []                                            | t       | f           | t        | f         | t        | f         | t              | t
- [1, "2", {}]                                  | t       | f           | t        | f         | t        | f         | t              | t
- {}                                            | t       | f           | t        | t         | f        | f         | t              | t
- { "a": 1, "b": null }                         | t       | f           | t        | t         | f        | f         | t              | t
- { "a": 1, "a": null }                         | t       | f           | t        | t         | f        | f         | t              | f
- { "a": 1, "b": [{ "a": 1 }, { "a": 2 }] }     | t       | f           | t        | t         | f        | f         | t              | t
- { "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t       | f           | t        | t         | f        | f         | t              | f
-(11 rows)
-
-SELECT
-	js0,
-	js IS JSON "IS JSON",
-	js IS NOT JSON "IS NOT JSON",
-	js IS JSON VALUE "IS VALUE",
-	js IS JSON OBJECT "IS OBJECT",
-	js IS JSON ARRAY "IS ARRAY",
-	js IS JSON SCALAR "IS SCALAR",
-	js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE",
-	js IS JSON WITH UNIQUE KEYS "WITH UNIQUE"
-FROM
-	(SELECT js, js::bytea FROM test_is_json WHERE js IS JSON) foo(js0, js);
-                      js0                      | IS JSON | IS NOT JSON | IS VALUE | IS OBJECT | IS ARRAY | IS SCALAR | WITHOUT UNIQUE | WITH UNIQUE 
------------------------------------------------+---------+-------------+----------+-----------+----------+-----------+----------------+-------------
- 123                                           | t       | f           | t        | f         | f        | t         | t              | t
- "aaa "                                        | t       | f           | t        | f         | f        | t         | t              | t
- true                                          | t       | f           | t        | f         | f        | t         | t              | t
- null                                          | t       | f           | t        | f         | f        | t         | t              | t
- []                                            | t       | f           | t        | f         | t        | f         | t              | t
- [1, "2", {}]                                  | t       | f           | t        | f         | t        | f         | t              | t
- {}                                            | t       | f           | t        | t         | f        | f         | t              | t
- { "a": 1, "b": null }                         | t       | f           | t        | t         | f        | f         | t              | t
- { "a": 1, "a": null }                         | t       | f           | t        | t         | f        | f         | t              | f
- { "a": 1, "b": [{ "a": 1 }, { "a": 2 }] }     | t       | f           | t        | t         | f        | f         | t              | t
- { "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] } | t       | f           | t        | t         | f        | f         | t              | f
-(11 rows)
-
-SELECT
-	js,
-	js IS JSON "IS JSON",
-	js IS NOT JSON "IS NOT JSON",
-	js IS JSON VALUE "IS VALUE",
-	js IS JSON OBJECT "IS OBJECT",
-	js IS JSON ARRAY "IS ARRAY",
-	js IS JSON SCALAR "IS SCALAR",
-	js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE",
-	js IS JSON WITH UNIQUE KEYS "WITH UNIQUE"
-FROM
-	(SELECT js::jsonb FROM test_is_json WHERE js IS JSON) foo(js);
-                 js                  | IS JSON | IS NOT JSON | IS VALUE | IS OBJECT | IS ARRAY | IS SCALAR | WITHOUT UNIQUE | WITH UNIQUE 
--------------------------------------+---------+-------------+----------+-----------+----------+-----------+----------------+-------------
- 123                                 | t       | f           | t        | f         | f        | t         | t              | t
- "aaa "                              | t       | f           | t        | f         | f        | t         | t              | t
- true                                | t       | f           | t        | f         | f        | t         | t              | t
- null                                | t       | f           | t        | f         | f        | t         | t              | t
- []                                  | t       | f           | t        | f         | t        | f         | t              | t
- [1, "2", {}]                        | t       | f           | t        | f         | t        | f         | t              | t
- {}                                  | t       | f           | t        | t         | f        | f         | t              | t
- {"a": 1, "b": null}                 | t       | f           | t        | t         | f        | f         | t              | t
- {"a": null}                         | t       | f           | t        | t         | f        | f         | t              | t
- {"a": 1, "b": [{"a": 1}, {"a": 2}]} | t       | f           | t        | t         | f        | f         | t              | t
- {"a": 1, "b": [{"a": 2, "b": 0}]}   | t       | f           | t        | t         | f        | f         | t              | t
-(11 rows)
-
--- Test IS JSON deparsing
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT '1' IS JSON AS "any", ('1' || i) IS JSON SCALAR AS "scalar", '[]' IS NOT JSON ARRAY AS "array", '{}' IS JSON OBJECT WITH UNIQUE AS "object" FROM generate_series(1, 3) i;
-                                                                        QUERY PLAN                                                                        
-----------------------------------------------------------------------------------------------------------------------------------------------------------
- Function Scan on pg_catalog.generate_series i
-   Output: ('1'::text IS JSON), (('1'::text || (i)::text) IS JSON SCALAR), (NOT ('[]'::text IS JSON ARRAY)), ('{}'::text IS JSON OBJECT WITH UNIQUE KEYS)
-   Function Call: generate_series(1, 3)
-(3 rows)
-
-CREATE VIEW is_json_view AS
-SELECT '1' IS JSON AS "any", ('1' || i) IS JSON SCALAR AS "scalar", '[]' IS NOT JSON ARRAY AS "array", '{}' IS JSON OBJECT WITH UNIQUE AS "object" FROM generate_series(1, 3) i;
-\sv is_json_view
-CREATE OR REPLACE VIEW public.is_json_view AS
- SELECT '1'::text IS JSON AS "any",
-    ('1'::text || i.i) IS JSON SCALAR AS scalar,
-    NOT '[]'::text IS JSON ARRAY AS "array",
-    '{}'::text IS JSON OBJECT WITH UNIQUE KEYS AS object
-   FROM generate_series(1, 3) i(i)
-DROP VIEW is_json_view;
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 103e11483d..9f644a0c1b 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -111,7 +111,7 @@ test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combo
 # ----------
 # Another group of parallel tests (JSON related)
 # ----------
-test: json jsonb json_encoding jsonpath jsonpath_encoding jsonb_jsonpath sqljson json_sqljson jsonb_sqljson
+test: json jsonb json_encoding jsonpath jsonpath_encoding jsonb_jsonpath
 
 # ----------
 # Another group of parallel tests
diff --git a/src/test/regress/sql/json_sqljson.sql b/src/test/regress/sql/json_sqljson.sql
deleted file mode 100644
index df4a430d88..0000000000
--- a/src/test/regress/sql/json_sqljson.sql
+++ /dev/null
@@ -1,15 +0,0 @@
--- JSON_EXISTS
-
-SELECT JSON_EXISTS(NULL FORMAT JSON, '$');
-
--- JSON_VALUE
-
-SELECT JSON_VALUE(NULL FORMAT JSON, '$');
-
--- JSON_QUERY
-
-SELECT JSON_QUERY(NULL FORMAT JSON, '$');
-
--- JSON_TABLE
-
-SELECT * FROM JSON_TABLE(NULL FORMAT JSON, '$' COLUMNS (foo text));
diff --git a/src/test/regress/sql/jsonb_sqljson.sql b/src/test/regress/sql/jsonb_sqljson.sql
deleted file mode 100644
index fff2537480..0000000000
--- a/src/test/regress/sql/jsonb_sqljson.sql
+++ /dev/null
@@ -1,977 +0,0 @@
--- JSON_EXISTS
-
-SELECT JSON_EXISTS(NULL::jsonb, '$');
-
-SELECT JSON_EXISTS(jsonb '[]', '$');
-SELECT JSON_EXISTS(JSON_OBJECT(RETURNING jsonb), '$');
-
-SELECT JSON_EXISTS(jsonb '1', '$');
-SELECT JSON_EXISTS(jsonb 'null', '$');
-SELECT JSON_EXISTS(jsonb '[]', '$');
-
-SELECT JSON_EXISTS(jsonb '1', '$.a');
-SELECT JSON_EXISTS(jsonb '1', 'strict $.a');
-SELECT JSON_EXISTS(jsonb '1', 'strict $.a' ERROR ON ERROR);
-SELECT JSON_EXISTS(jsonb 'null', '$.a');
-SELECT JSON_EXISTS(jsonb '[]', '$.a');
-SELECT JSON_EXISTS(jsonb '[1, "aaa", {"a": 1}]', 'strict $.a');
-SELECT JSON_EXISTS(jsonb '[1, "aaa", {"a": 1}]', 'lax $.a');
-SELECT JSON_EXISTS(jsonb '{}', '$.a');
-SELECT JSON_EXISTS(jsonb '{"b": 1, "a": 2}', '$.a');
-
-SELECT JSON_EXISTS(jsonb '1', '$.a.b');
-SELECT JSON_EXISTS(jsonb '{"a": {"b": 1}}', '$.a.b');
-SELECT JSON_EXISTS(jsonb '{"a": 1, "b": 2}', '$.a.b');
-
-SELECT JSON_EXISTS(jsonb '{"a": 1, "b": 2}', '$.* ? (@ > $x)' PASSING 1 AS x);
-SELECT JSON_EXISTS(jsonb '{"a": 1, "b": 2}', '$.* ? (@ > $x)' PASSING '1' AS x);
-SELECT JSON_EXISTS(jsonb '{"a": 1, "b": 2}', '$.* ? (@ > $x && @ < $y)' PASSING 0 AS x, 2 AS y);
-SELECT JSON_EXISTS(jsonb '{"a": 1, "b": 2}', '$.* ? (@ > $x && @ < $y)' PASSING 0 AS x, 1 AS y);
-
--- extension: boolean expressions
-SELECT JSON_EXISTS(jsonb '1', '$ > 2');
-SELECT JSON_EXISTS(jsonb '1', '$.a > 2' ERROR ON ERROR);
-
--- extension: RETURNING clause
-SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING bool);
-SELECT JSON_EXISTS(jsonb '1', '$[1]' RETURNING bool);
-SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING int);
-SELECT JSON_EXISTS(jsonb '1', '$[1]' RETURNING int);
-SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING text);
-SELECT JSON_EXISTS(jsonb '1', '$[1]' RETURNING text);
-SELECT JSON_EXISTS(jsonb '1', 'strict $[1]' RETURNING text FALSE ON ERROR);
-SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING jsonb);
-SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING float4);
-
-
--- JSON_VALUE
-
-SELECT JSON_VALUE(NULL::jsonb, '$');
-
-SELECT JSON_VALUE(jsonb 'null', '$');
-SELECT JSON_VALUE(jsonb 'null', '$' RETURNING int);
-
-SELECT JSON_VALUE(jsonb 'true', '$');
-SELECT JSON_VALUE(jsonb 'true', '$' RETURNING bool);
-
-SELECT JSON_VALUE(jsonb '123', '$');
-SELECT JSON_VALUE(jsonb '123', '$' RETURNING int) + 234;
-SELECT JSON_VALUE(jsonb '123', '$' RETURNING text);
-/* jsonb bytea ??? */
-SELECT JSON_VALUE(jsonb '123', '$' RETURNING bytea ERROR ON ERROR);
-
-SELECT JSON_VALUE(jsonb '1.23', '$');
-SELECT JSON_VALUE(jsonb '1.23', '$' RETURNING int);
-SELECT JSON_VALUE(jsonb '"1.23"', '$' RETURNING numeric);
-SELECT JSON_VALUE(jsonb '"1.23"', '$' RETURNING int ERROR ON ERROR);
-
-SELECT JSON_VALUE(jsonb '"aaa"', '$');
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING text);
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING char(5));
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING char(2));
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING json);
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING jsonb);
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING json ERROR ON ERROR);
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING jsonb ERROR ON ERROR);
-SELECT JSON_VALUE(jsonb '"\"aaa\""', '$' RETURNING json);
-SELECT JSON_VALUE(jsonb '"\"aaa\""', '$' RETURNING jsonb);
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING int);
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING int ERROR ON ERROR);
-SELECT JSON_VALUE(jsonb '"aaa"', '$' RETURNING int DEFAULT 111 ON ERROR);
-SELECT JSON_VALUE(jsonb '"123"', '$' RETURNING int) + 234;
-
-SELECT JSON_VALUE(jsonb '"2017-02-20"', '$' RETURNING date) + 9;
-
--- Test NULL checks execution in domain types
-CREATE DOMAIN sqljsonb_int_not_null AS int NOT NULL;
-SELECT JSON_VALUE(jsonb '1', '$.a' RETURNING sqljsonb_int_not_null);
-SELECT JSON_VALUE(jsonb '1', '$.a' RETURNING sqljsonb_int_not_null NULL ON ERROR);
-SELECT JSON_VALUE(jsonb '1', '$.a' RETURNING sqljsonb_int_not_null DEFAULT NULL ON ERROR);
-
-SELECT JSON_VALUE(jsonb '[]', '$');
-SELECT JSON_VALUE(jsonb '[]', '$' ERROR ON ERROR);
-SELECT JSON_VALUE(jsonb '{}', '$');
-SELECT JSON_VALUE(jsonb '{}', '$' ERROR ON ERROR);
-
-SELECT JSON_VALUE(jsonb '1', '$.a');
-SELECT JSON_VALUE(jsonb '1', 'strict $.a' ERROR ON ERROR);
-SELECT JSON_VALUE(jsonb '1', 'strict $.a' DEFAULT 'error' ON ERROR);
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' ERROR ON ERROR);
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' ERROR ON EMPTY ERROR ON ERROR);
-SELECT JSON_VALUE(jsonb '1', 'strict $.a' DEFAULT 2 ON ERROR);
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' DEFAULT 2 ON ERROR);
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' DEFAULT '2' ON ERROR);
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' NULL ON EMPTY DEFAULT '2' ON ERROR);
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' DEFAULT '2' ON EMPTY DEFAULT '3' ON ERROR);
-SELECT JSON_VALUE(jsonb '1', 'lax $.a' ERROR ON EMPTY DEFAULT '3' ON ERROR);
-
-SELECT JSON_VALUE(jsonb '[1,2]', '$[*]' ERROR ON ERROR);
-SELECT JSON_VALUE(jsonb '[1,2]', '$[*]' DEFAULT '0' ON ERROR);
-SELECT JSON_VALUE(jsonb '[" "]', '$[*]' RETURNING int ERROR ON ERROR);
-SELECT JSON_VALUE(jsonb '[" "]', '$[*]' RETURNING int DEFAULT 2 + 3 ON ERROR);
-SELECT JSON_VALUE(jsonb '["1"]', '$[*]' RETURNING int DEFAULT 2 + 3 ON ERROR);
-
-SELECT
-	x,
-	JSON_VALUE(
-		jsonb '{"a": 1, "b": 2}',
-		'$.* ? (@ > $x)' PASSING x AS x
-		RETURNING int
-		DEFAULT -1 ON EMPTY
-		DEFAULT -2 ON ERROR
-	) y
-FROM
-	generate_series(0, 2) x;
-
-SELECT JSON_VALUE(jsonb 'null', '$a' PASSING point ' (1, 2 )' AS a);
-SELECT JSON_VALUE(jsonb 'null', '$a' PASSING point ' (1, 2 )' AS a RETURNING point);
-
--- Test timestamptz passing and output
-SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts);
-SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING timestamptz);
-SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING timestamp);
-SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING json);
-SELECT JSON_VALUE(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING jsonb);
-
--- JSON_QUERY
-
-SELECT
-	JSON_QUERY(js, '$'),
-	JSON_QUERY(js, '$' WITHOUT WRAPPER),
-	JSON_QUERY(js, '$' WITH CONDITIONAL WRAPPER),
-	JSON_QUERY(js, '$' WITH UNCONDITIONAL ARRAY WRAPPER),
-	JSON_QUERY(js, '$' WITH ARRAY WRAPPER)
-FROM
-	(VALUES
-		(jsonb 'null'),
-		('12.3'),
-		('true'),
-		('"aaa"'),
-		('[1, null, "2"]'),
-		('{"a": 1, "b": [2]}')
-	) foo(js);
-
-SELECT
-	JSON_QUERY(js, 'strict $[*]') AS "unspec",
-	JSON_QUERY(js, 'strict $[*]' WITHOUT WRAPPER) AS "without",
-	JSON_QUERY(js, 'strict $[*]' WITH CONDITIONAL WRAPPER) AS "with cond",
-	JSON_QUERY(js, 'strict $[*]' WITH UNCONDITIONAL ARRAY WRAPPER) AS "with uncond",
-	JSON_QUERY(js, 'strict $[*]' WITH ARRAY WRAPPER) AS "with"
-FROM
-	(VALUES
-		(jsonb '1'),
-		('[]'),
-		('[null]'),
-		('[12.3]'),
-		('[true]'),
-		('["aaa"]'),
-		('[[1, 2, 3]]'),
-		('[{"a": 1, "b": [2]}]'),
-		('[1, "2", null, [3]]')
-	) foo(js);
-
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING text);
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING text KEEP QUOTES);
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING text KEEP QUOTES ON SCALAR STRING);
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING text OMIT QUOTES);
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING text OMIT QUOTES ON SCALAR STRING);
-SELECT JSON_QUERY(jsonb '"aaa"', '$' OMIT QUOTES ERROR ON ERROR);
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING json OMIT QUOTES ERROR ON ERROR);
-SELECT JSON_QUERY(jsonb '"aaa"', '$' RETURNING bytea FORMAT JSON OMIT QUOTES ERROR ON ERROR);
-
--- QUOTES behavior should not be specified when WITH WRAPPER used:
--- Should fail
-SELECT JSON_QUERY(jsonb '[1]', '$' WITH WRAPPER OMIT QUOTES);
-SELECT JSON_QUERY(jsonb '[1]', '$' WITH WRAPPER KEEP QUOTES);
-SELECT JSON_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER KEEP QUOTES);
-SELECT JSON_QUERY(jsonb '[1]', '$' WITH CONDITIONAL WRAPPER OMIT QUOTES);
--- Should succeed
-SELECT JSON_QUERY(jsonb '[1]', '$' WITHOUT WRAPPER OMIT QUOTES);
-SELECT JSON_QUERY(jsonb '[1]', '$' WITHOUT WRAPPER KEEP QUOTES);
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]');
-SELECT JSON_QUERY(jsonb '[]', '$[*]' NULL ON EMPTY);
-SELECT JSON_QUERY(jsonb '[]', '$[*]' EMPTY ON EMPTY);
-SELECT JSON_QUERY(jsonb '[]', '$[*]' EMPTY ARRAY ON EMPTY);
-SELECT JSON_QUERY(jsonb '[]', '$[*]' EMPTY OBJECT ON EMPTY);
-SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON EMPTY);
-SELECT JSON_QUERY(jsonb '[]', '$[*]' DEFAULT '"empty"' ON EMPTY);
-
-SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON EMPTY NULL ON ERROR);
-SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON EMPTY EMPTY ARRAY ON ERROR);
-SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON EMPTY EMPTY OBJECT ON ERROR);
-SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON EMPTY ERROR ON ERROR);
-SELECT JSON_QUERY(jsonb '[]', '$[*]' ERROR ON ERROR);
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' ERROR ON ERROR);
-SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' DEFAULT '"empty"' ON ERROR);
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING json);
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING json FORMAT JSON);
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING jsonb);
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING jsonb FORMAT JSON);
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING text);
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING char(10));
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING char(3));
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING text FORMAT JSON);
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING bytea);
-SELECT JSON_QUERY(jsonb '[1,2]', '$' RETURNING bytea FORMAT JSON);
-
-SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING bytea EMPTY OBJECT ON ERROR);
-SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING bytea FORMAT JSON EMPTY OBJECT ON ERROR);
-SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING json EMPTY OBJECT ON ERROR);
-SELECT JSON_QUERY(jsonb '[1,2]', '$[*]' RETURNING jsonb EMPTY OBJECT ON ERROR);
-
-SELECT
-	x, y,
-	JSON_QUERY(
-		jsonb '[1,2,3,4,5,null]',
-		'$[*] ? (@ >= $x && @ <= $y)'
-		PASSING x AS x, y AS y
-		WITH CONDITIONAL WRAPPER
-		EMPTY ARRAY ON EMPTY
-	) list
-FROM
-	generate_series(0, 4) x,
-	generate_series(0, 4) y;
-
--- Extension: record types returning
-CREATE TYPE sqljsonb_rec AS (a int, t text, js json, jb jsonb, jsa json[]);
-CREATE TYPE sqljsonb_reca AS (reca sqljsonb_rec[]);
-
-SELECT JSON_QUERY(jsonb '[{"a": 1, "b": "foo", "t": "aaa", "js": [1, "2", {}], "jb": {"x": [1, "2", {}]}},  {"a": 2}]', '$[0]' RETURNING sqljsonb_rec);
-SELECT * FROM unnest((JSON_QUERY(jsonb '{"jsa":  [{"a": 1, "b": ["foo"]}, {"a": 2, "c": {}}, 123]}', '$' RETURNING sqljsonb_rec)).jsa);
-SELECT * FROM unnest((JSON_QUERY(jsonb '{"reca": [{"a": 1, "t": ["foo", []]}, {"a": 2, "jb": [{}, true]}]}', '$' RETURNING sqljsonb_reca)).reca);
-
--- Extension: array types returning
-SELECT JSON_QUERY(jsonb '[1,2,null,"3"]', '$[*]' RETURNING int[] WITH WRAPPER);
-SELECT * FROM unnest(JSON_QUERY(jsonb '[{"a": 1, "t": ["foo", []]}, {"a": 2, "jb": [{}, true]}]', '$' RETURNING sqljsonb_rec[]));
-
--- Extension: domain types returning
-SELECT JSON_QUERY(jsonb '{"a": 1}', '$.a' RETURNING sqljsonb_int_not_null);
-SELECT JSON_QUERY(jsonb '{"a": 1}', '$.b' RETURNING sqljsonb_int_not_null);
-
--- Test timestamptz passing and output
-SELECT JSON_QUERY(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts);
-SELECT JSON_QUERY(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING json);
-SELECT JSON_QUERY(jsonb 'null', '$ts' PASSING timestamptz '2018-02-21 12:34:56 +10' AS ts RETURNING jsonb);
-
--- Test constraints
-
-CREATE TABLE test_jsonb_constraints (
-	js text,
-	i int,
-	x jsonb DEFAULT JSON_QUERY(jsonb '[1,2]', '$[*]' WITH WRAPPER)
-	CONSTRAINT test_jsonb_constraint1
-		CHECK (js IS JSON)
-	CONSTRAINT test_jsonb_constraint2
-		CHECK (JSON_EXISTS(js::jsonb, '$.a' PASSING i + 5 AS int, i::text AS txt, array[1,2,3] as arr))
-	CONSTRAINT test_jsonb_constraint3
-		CHECK (JSON_VALUE(js::jsonb, '$.a' RETURNING int DEFAULT ('12' || i)::int ON EMPTY ERROR ON ERROR) > i)
-	CONSTRAINT test_jsonb_constraint4
-		CHECK (JSON_QUERY(js::jsonb, '$.a' WITH CONDITIONAL WRAPPER EMPTY OBJECT ON ERROR) < jsonb '[10]')
-	CONSTRAINT test_jsonb_constraint5
-		CHECK (JSON_QUERY(js::jsonb, '$.a' RETURNING char(5) OMIT QUOTES EMPTY ARRAY ON EMPTY) >  'a' COLLATE "C")
-	CONSTRAINT test_jsonb_constraint6
-		CHECK (JSON_EXISTS(js::jsonb, 'strict $.a' RETURNING int TRUE ON ERROR) < 2)
-);
-
-\d test_jsonb_constraints
-
-SELECT check_clause
-FROM information_schema.check_constraints
-WHERE constraint_name LIKE 'test_jsonb_constraint%'
-ORDER BY 1;
-
-SELECT pg_get_expr(adbin, adrelid)
-FROM pg_attrdef
-WHERE adrelid = 'test_jsonb_constraints'::regclass
-ORDER BY 1;
-
-INSERT INTO test_jsonb_constraints VALUES ('', 1);
-INSERT INTO test_jsonb_constraints VALUES ('1', 1);
-INSERT INTO test_jsonb_constraints VALUES ('[]');
-INSERT INTO test_jsonb_constraints VALUES ('{"b": 1}', 1);
-INSERT INTO test_jsonb_constraints VALUES ('{"a": 1}', 1);
-INSERT INTO test_jsonb_constraints VALUES ('{"a": 7}', 1);
-INSERT INTO test_jsonb_constraints VALUES ('{"a": 10}', 1);
-
-DROP TABLE test_jsonb_constraints;
-
--- Test mutabilily od query functions
-CREATE TABLE test_jsonb_mutability(js jsonb);
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a[0]'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime()'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a ? (@ < $.datetime())'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a ? (@.datetime() < $.datetime())'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a ? (@.datetime() < $.datetime("HH:MI TZH"))'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a ? (@.datetime("HH:MI TZH") < $.datetime("HH:MI TZH"))'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a ? (@.datetime("HH:MI") < $.datetime("YY-MM-DD HH:MI"))'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.a ? (@.datetime("HH:MI TZH") < $.datetime("YY-MM-DD HH:MI"))'));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime("HH:MI TZH") < $x' PASSING '12:34'::timetz AS x));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime("HH:MI TZH") < $y' PASSING '12:34'::timetz AS x));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime() < $x' PASSING '12:34'::timetz AS x));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime() < $x' PASSING '1234'::int AS x));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime() ? (@ == $x)' PASSING '12:34'::time AS x));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$.datetime("YY-MM-DD") ? (@ == $x)' PASSING '2020-07-14'::date AS x));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$[1, $.a ? (@.datetime() == $x)]' PASSING '12:34'::time AS x));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$[1, 0 to $.a ? (@.datetime() == $x)]' PASSING '12:34'::time AS x));
-CREATE INDEX ON test_jsonb_mutability (JSON_QUERY(js, '$[1, $.a ? (@.datetime("HH:MI") == $x)]' PASSING '12:34'::time AS x));
-DROP TABLE test_jsonb_mutability;
-
--- JSON_TABLE
-
--- Should fail (JSON_TABLE can be used only in FROM clause)
-SELECT JSON_TABLE('[]', '$');
-
--- Should fail (no columns)
-SELECT * FROM JSON_TABLE(NULL, '$' COLUMNS ());
-
-SELECT * FROM JSON_TABLE (NULL::jsonb, '$' COLUMNS (v1 timestamp)) AS f (v1, v2);
-
--- NULL => empty table
-SELECT * FROM JSON_TABLE(NULL::jsonb, '$' COLUMNS (foo int)) bar;
-
---
-SELECT * FROM JSON_TABLE(jsonb '123', '$'
-	COLUMNS (item int PATH '$', foo int)) bar;
-
--- JSON_TABLE: basic functionality
-CREATE DOMAIN jsonb_test_domain AS text CHECK (value <> 'foo');
-
-SELECT *
-FROM
-	(VALUES
-		('1'),
-		('[]'),
-		('{}'),
-		('[1, 1.23, "2", "aaaaaaa", "foo", null, false, true, {"aaa": 123}, "[1,2]", "\"str\""]')
-	) vals(js)
-	LEFT OUTER JOIN
--- JSON_TABLE is implicitly lateral
-	JSON_TABLE(
-		vals.js::jsonb, 'lax $[*]'
-		COLUMNS (
-			id FOR ORDINALITY,
-			id2 FOR ORDINALITY, -- allowed additional ordinality columns
-			"int" int PATH '$',
-			"text" text PATH '$',
-			"char(4)" char(4) PATH '$',
-			"bool" bool PATH '$',
-			"numeric" numeric PATH '$',
-			"domain" jsonb_test_domain PATH '$',
-			js json PATH '$',
-			jb jsonb PATH '$',
-			jst text    FORMAT JSON  PATH '$',
-			jsc char(4) FORMAT JSON  PATH '$',
-			jsv varchar(4) FORMAT JSON  PATH '$',
-			jsb jsonb FORMAT JSON PATH '$',
-			jsbq jsonb FORMAT JSON PATH '$' OMIT QUOTES,
-			aaa int, -- implicit path '$."aaa"',
-			aaa1 int PATH '$.aaa',
-			exists1 bool EXISTS PATH '$.aaa',
-			exists2 int EXISTS PATH '$.aaa',
-			exists3 int EXISTS PATH 'strict $.aaa' UNKNOWN ON ERROR,
-			exists4 text EXISTS PATH 'strict $.aaa' FALSE ON ERROR,
-
-			js2 json PATH '$',
-			jsb2w jsonb PATH '$' WITH WRAPPER,
-			jsb2q jsonb PATH '$' OMIT QUOTES,
-			ia int[] PATH '$',
-			ta text[] PATH '$',
-			jba jsonb[] PATH '$'
-		)
-	) jt
-	ON true;
-
--- JSON_TABLE: Test backward parsing
-
-CREATE VIEW jsonb_table_view AS
-SELECT * FROM
-	JSON_TABLE(
-		jsonb 'null', 'lax $[*]' PASSING 1 + 2 AS a, json '"foo"' AS "b c"
-		COLUMNS (
-			id FOR ORDINALITY,
-			id2 FOR ORDINALITY, -- allowed additional ordinality columns
-			"int" int PATH '$',
-			"text" text PATH '$',
-			"char(4)" char(4) PATH '$',
-			"bool" bool PATH '$',
-			"numeric" numeric PATH '$',
-			"domain" jsonb_test_domain PATH '$',
-			js json PATH '$',
-			jb jsonb PATH '$',
-			jst text    FORMAT JSON  PATH '$',
-			jsc char(4) FORMAT JSON  PATH '$',
-			jsv varchar(4) FORMAT JSON  PATH '$',
-			jsb jsonb   FORMAT JSON PATH '$',
-			jsbq jsonb FORMAT JSON PATH '$' OMIT QUOTES,
-			aaa int, -- implicit path '$."aaa"',
-			aaa1 int PATH '$.aaa',
-			exists1 bool EXISTS PATH '$.aaa',
-			exists2 int EXISTS PATH '$.aaa' TRUE ON ERROR,
-			exists3 text EXISTS PATH 'strict $.aaa' UNKNOWN ON ERROR,
-
-			js2 json PATH '$',
-			jsb2w jsonb PATH '$' WITH WRAPPER,
-			jsb2q jsonb PATH '$' OMIT QUOTES,
-			ia int[] PATH '$',
-			ta text[] PATH '$',
-			jba jsonb[] PATH '$',
-
-			NESTED PATH '$[1]' AS p1 COLUMNS (
-				a1 int,
-				NESTED PATH '$[*]' AS "p1 1" COLUMNS (
-					a11 text
-				),
-				b1 text
-			),
-			NESTED PATH '$[2]' AS p2 COLUMNS (
-				NESTED PATH '$[*]' AS "p2:1" COLUMNS (
-					a21 text
-				),
-				NESTED PATH '$[*]' AS p22 COLUMNS (
-					a22 text
-				)
-			)
-		)
-	);
-
-\sv jsonb_table_view
-
-EXPLAIN (COSTS OFF, VERBOSE) SELECT * FROM jsonb_table_view;
-
-DROP VIEW jsonb_table_view;
-DROP DOMAIN jsonb_test_domain;
-
--- JSON_TABLE: ON EMPTY/ON ERROR behavior
-SELECT *
-FROM
-	(VALUES ('1'), ('"err"')) vals(js),
-	JSON_TABLE(vals.js::jsonb, '$' COLUMNS (a int PATH '$')) jt;
-
-SELECT *
-FROM
-	(VALUES ('1'), ('"err"')) vals(js)
-		LEFT OUTER JOIN
-	JSON_TABLE(vals.js::jsonb, '$' COLUMNS (a int PATH '$') ERROR ON ERROR) jt
-		ON true;
-
-SELECT *
-FROM
-	(VALUES ('1'), ('"err"')) vals(js)
-		LEFT OUTER JOIN
-	JSON_TABLE(vals.js::jsonb, '$' COLUMNS (a int PATH '$' ERROR ON ERROR)) jt
-		ON true;
-
-SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int PATH '$.a' ERROR ON EMPTY)) jt;
-SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int PATH 'strict $.a' ERROR ON EMPTY) ERROR ON ERROR) jt;
-SELECT * FROM JSON_TABLE(jsonb '1', '$' COLUMNS (a int PATH 'lax $.a' ERROR ON EMPTY) ERROR ON ERROR) jt;
-
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int PATH '$'   DEFAULT 1 ON EMPTY DEFAULT 2 ON ERROR)) jt;
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int PATH 'strict $.a' DEFAULT 1 ON EMPTY DEFAULT 2 ON ERROR)) jt;
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int PATH 'lax $.a' DEFAULT 1 ON EMPTY DEFAULT 2 ON ERROR)) jt;
-
--- JSON_TABLE: EXISTS PATH types
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int4 EXISTS PATH '$.a'));
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int2 EXISTS PATH '$.a'));
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a int8 EXISTS PATH '$.a'));
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a float4 EXISTS PATH '$.a'));
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(3) EXISTS PATH '$.a'));
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a json EXISTS PATH '$.a'));
-SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a jsonb EXISTS PATH '$.a'));
-
--- JSON_TABLE: nested paths and plans
-
--- Should fail (JSON_TABLE columns must contain explicit AS path
--- specifications if explicit PLAN clause is used)
-SELECT * FROM JSON_TABLE(
-	jsonb '[]', '$' -- AS <path name> required here
-	COLUMNS (
-		foo int PATH '$'
-	)
-	PLAN DEFAULT (UNION)
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb '[]', '$' AS path1
-	COLUMNS (
-		NESTED PATH '$' COLUMNS ( -- AS <path name> required here
-			foo int PATH '$'
-		)
-	)
-	PLAN DEFAULT (UNION)
-) jt;
-
--- Should fail (column names must be distinct)
-SELECT * FROM JSON_TABLE(
-	jsonb '[]', '$' AS a
-	COLUMNS (
-		a int
-	)
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb '[]', '$' AS a
-	COLUMNS (
-		b int,
-		NESTED PATH '$' AS a
-		COLUMNS (
-			c int
-		)
-	)
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb '[]', '$'
-	COLUMNS (
-		b int,
-		NESTED PATH '$' AS b
-		COLUMNS (
-			c int
-		)
-	)
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb '[]', '$'
-	COLUMNS (
-		NESTED PATH '$' AS a
-		COLUMNS (
-			b int
-		),
-		NESTED PATH '$'
-		COLUMNS (
-			NESTED PATH '$' AS a
-			COLUMNS (
-				c int
-			)
-		)
-	)
-) jt;
-
--- JSON_TABLE: plan validation
-
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p1)
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0)
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER p3)
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 UNION p1 UNION p11)
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER (p1 CROSS p13))
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER (p1 CROSS p2))
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER ((p1 UNION p11) CROSS p2))
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER ((p1 INNER p11) CROSS p2))
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', '$[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER ((p1 INNER (p12 CROSS p11)) CROSS p2))
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', 'strict $[*]' AS p0
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN (p0 OUTER ((p1 INNER (p12 CROSS p11)) CROSS (p2 INNER p21)))
-) jt;
-
-SELECT * FROM JSON_TABLE(
-	jsonb 'null', 'strict $[*]' -- without root path name
-	COLUMNS (
-		NESTED PATH '$' AS p1 COLUMNS (
-			NESTED PATH '$' AS p11 COLUMNS ( foo int ),
-			NESTED PATH '$' AS p12 COLUMNS ( bar int )
-		),
-		NESTED PATH '$' AS p2 COLUMNS (
-			NESTED PATH '$' AS p21 COLUMNS ( baz int )
-		)
-	)
-	PLAN ((p1 INNER (p12 CROSS p11)) CROSS (p2 INNER p21))
-) jt;
-
--- JSON_TABLE: plan execution
-
-CREATE TEMP TABLE jsonb_table_test (js jsonb);
-
-INSERT INTO jsonb_table_test
-VALUES (
-	'[
-		{"a":  1,  "b": [], "c": []},
-		{"a":  2,  "b": [1, 2, 3], "c": [10, null, 20]},
-		{"a":  3,  "b": [1, 2], "c": []},
-		{"x": "4", "b": [1, 2], "c": 123}
-	 ]'
-);
-
--- unspecified plan (outer, union)
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-	) jt;
-
--- default plan (outer, union)
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan default (outer, union)
-	) jt;
-
--- specific plan (p outer (pb union pc))
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan (p outer (pb union pc))
-	) jt;
-
--- specific plan (p outer (pc union pb))
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan (p outer (pc union pb))
-	) jt;
-
--- default plan (inner, union)
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan default (inner)
-	) jt;
-
--- specific plan (p inner (pb union pc))
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan (p inner (pb union pc))
-	) jt;
-
--- default plan (inner, cross)
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan default (cross, inner)
-	) jt;
-
--- specific plan (p inner (pb cross pc))
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan (p inner (pb cross pc))
-	) jt;
-
--- default plan (outer, cross)
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan default (outer, cross)
-	) jt;
-
--- specific plan (p outer (pb cross pc))
-select
-	jt.*
-from
-	jsonb_table_test jtt,
-	json_table (
-		jtt.js,'strict $[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on empty,
-			nested path 'strict $.b[*]' as pb columns ( b int path '$' ),
-			nested path 'strict $.c[*]' as pc columns ( c int path '$' )
-		)
-		plan (p outer (pb cross pc))
-	) jt;
-
-
-select
-	jt.*, b1 + 100 as b
-from
-	json_table (jsonb
-		'[
-			{"a":  1,  "b": [[1, 10], [2], [3, 30, 300]], "c": [1, null, 2]},
-			{"a":  2,  "b": [10, 20], "c": [1, null, 2]},
-			{"x": "3", "b": [11, 22, 33, 44]}
-		 ]',
-		'$[*]' as p
-		columns (
-			n for ordinality,
-			a int path 'lax $.a' default -1 on error,
-			nested path 'strict $.b[*]' as pb columns (
-				b text format json path '$',
-				nested path 'strict $[*]' as pb1 columns (
-					b1 int path '$'
-				)
-			),
-			nested path 'strict $.c[*]' as pc columns (
-				c text format json path '$',
-				nested path 'strict $[*]' as pc1 columns (
-					c1 int path '$'
-				)
-			)
-		)
-		--plan default(outer, cross)
-		plan(p outer ((pb inner pb1) cross (pc outer pc1)))
-	) jt;
-
--- Should succeed (JSON arguments are passed to root and nested paths)
-SELECT *
-FROM
-	generate_series(1, 4) x,
-	generate_series(1, 3) y,
-	JSON_TABLE(jsonb
-		'[[1,2,3],[2,3,4,5],[3,4,5,6]]',
-		'strict $[*] ? (@[*] < $x)'
-		PASSING x AS x, y AS y
-		COLUMNS (
-			y text FORMAT JSON PATH '$',
-			NESTED PATH 'strict $[*] ? (@ >= $y)'
-			COLUMNS (
-				z int PATH '$'
-			)
-		)
-	) jt;
-
--- Should fail (JSON arguments are not passed to column paths)
-SELECT *
-FROM JSON_TABLE(
-	jsonb '[1,2,3]',
-	'$[*] ? (@ < $x)'
-		PASSING 10 AS x
-		COLUMNS (y text FORMAT JSON PATH '$ ? (@ < $x)')
-	) jt;
-
--- Extension: non-constant JSON path
-SELECT JSON_EXISTS(jsonb '{"a": 123}', '$' || '.' || 'a');
-SELECT JSON_VALUE(jsonb '{"a": 123}', '$' || '.' || 'a');
-SELECT JSON_VALUE(jsonb '{"a": 123}', '$' || '.' || 'b' DEFAULT 'foo' ON EMPTY);
-SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a');
-SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a' WITH WRAPPER);
--- Should fail (invalid path)
-SELECT JSON_QUERY(jsonb '{"a": 123}', 'error' || ' ' || 'error');
--- Should fail (not supported)
-SELECT * FROM JSON_TABLE(jsonb '{"a": 123}', '$' || '.' || 'a' COLUMNS (foo int));
-
--- Test parallel JSON_VALUE()
-
-
-CREATE UNLOGGED TABLE test_parallel_jsonb_value AS
-SELECT i::text::jsonb AS js
-FROM generate_series(1, 50000) i;
-
-
--- encourage use of parallel plans
-set parallel_setup_cost=0;
-set parallel_tuple_cost=0;
-set min_parallel_table_scan_size=0;
-set max_parallel_workers_per_gather=4;
-set parallel_leader_participation = off;
-
--- Should be non-parallel due to subtransactions
-EXPLAIN (COSTS OFF)
-SELECT sum(JSON_VALUE(js, '$' RETURNING numeric)) FROM test_parallel_jsonb_value;
-SELECT sum(JSON_VALUE(js, '$' RETURNING numeric)) FROM test_parallel_jsonb_value;
-
--- Should be parallel
-EXPLAIN (COSTS OFF)
-SELECT sum(JSON_VALUE(js, '$' RETURNING numeric ERROR ON ERROR)) FROM test_parallel_jsonb_value;
-SELECT sum(JSON_VALUE(js, '$' RETURNING numeric ERROR ON ERROR)) FROM test_parallel_jsonb_value;
-
-DROP TABLE test_parallel_jsonb_value;
diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql
index 63fe114fed..2b292851e3 100644
--- a/src/test/regress/sql/opr_sanity.sql
+++ b/src/test/regress/sql/opr_sanity.sql
@@ -854,10 +854,8 @@ WHERE a.aggfnoid = p.oid AND
          NOT binary_coercible(p.proargtypes[1], ptr.proargtypes[2]))
      OR (p.pronargs > 2 AND
          NOT binary_coercible(p.proargtypes[2], ptr.proargtypes[3]))
-     OR (p.pronargs > 3 AND
-         NOT binary_coercible(p.proargtypes[3], ptr.proargtypes[4]))
-     -- we could carry the check further, but 4 args is enough for now
-     OR (p.pronargs > 4)
+     -- we could carry the check further, but 3 args is enough for now
+     OR (p.pronargs > 3)
     );
 
 -- Cross-check finalfn (if present) against its entry in pg_proc.
diff --git a/src/test/regress/sql/sqljson.sql b/src/test/regress/sql/sqljson.sql
deleted file mode 100644
index c2742b40f1..0000000000
--- a/src/test/regress/sql/sqljson.sql
+++ /dev/null
@@ -1,471 +0,0 @@
--- JSON()
-SELECT JSON();
-SELECT JSON(NULL);
-SELECT JSON('{ "a" : 1 } ');
-SELECT JSON('{ "a" : 1 } ' FORMAT JSON);
-SELECT JSON('{ "a" : 1 } ' FORMAT JSON ENCODING UTF8);
-SELECT JSON('{ "a" : 1 } '::bytea FORMAT JSON ENCODING UTF8);
-SELECT pg_typeof(JSON('{ "a" : 1 } '));
-
-SELECT JSON('   1   '::json);
-SELECT JSON('   1   '::jsonb);
-SELECT JSON('   1   '::json WITH UNIQUE KEYS);
-SELECT JSON(123);
-
-SELECT JSON('{"a": 1, "a": 2}');
-SELECT JSON('{"a": 1, "a": 2}' WITH UNIQUE KEYS);
-SELECT JSON('{"a": 1, "a": 2}' WITHOUT UNIQUE KEYS);
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123');
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' FORMAT JSON);
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123'::bytea FORMAT JSON);
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123'::bytea FORMAT JSON ENCODING UTF8);
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' WITH UNIQUE KEYS);
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' WITHOUT UNIQUE KEYS);
-
-SELECT JSON('123' RETURNING text);
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123');
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING json);
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON('123' RETURNING jsonb);
-SELECT pg_typeof(JSON('123'));
-SELECT pg_typeof(JSON('123' RETURNING json));
-SELECT pg_typeof(JSON('123' RETURNING jsonb));
-
--- JSON_SCALAR()
-SELECT JSON_SCALAR();
-SELECT JSON_SCALAR(NULL);
-SELECT JSON_SCALAR(NULL::int);
-SELECT JSON_SCALAR(123);
-SELECT JSON_SCALAR(123.45);
-SELECT JSON_SCALAR(123.45::numeric);
-SELECT JSON_SCALAR(true);
-SELECT JSON_SCALAR(false);
-SELECT JSON_SCALAR(' 123.45');
-SELECT JSON_SCALAR('2020-06-07'::date);
-SELECT JSON_SCALAR('2020-06-07 01:02:03'::timestamp);
-SELECT JSON_SCALAR('{}'::json);
-SELECT JSON_SCALAR('{}'::jsonb);
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123);
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR('123');
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING json);
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SCALAR(123 RETURNING jsonb);
-
--- JSON_SERIALIZE()
-SELECT JSON_SERIALIZE();
-SELECT JSON_SERIALIZE(NULL);
-SELECT JSON_SERIALIZE(JSON('{ "a" : 1 } '));
-SELECT JSON_SERIALIZE('{ "a" : 1 } ');
-SELECT JSON_SERIALIZE('1');
-SELECT JSON_SERIALIZE('1' FORMAT JSON);
-SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING bytea);
-SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING varchar);
-SELECT pg_typeof(JSON_SERIALIZE(NULL));
-
--- only string types or bytea allowed
-SELECT JSON_SERIALIZE('{ "a" : 1 } ' RETURNING jsonb);
-
-
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SERIALIZE('{}');
-EXPLAIN (VERBOSE, COSTS OFF) SELECT JSON_SERIALIZE('{}' RETURNING bytea);
-
--- JSON_OBJECT()
-SELECT JSON_OBJECT();
-SELECT JSON_OBJECT(RETURNING json);
-SELECT JSON_OBJECT(RETURNING json FORMAT JSON);
-SELECT JSON_OBJECT(RETURNING jsonb);
-SELECT JSON_OBJECT(RETURNING jsonb FORMAT JSON);
-SELECT JSON_OBJECT(RETURNING text);
-SELECT JSON_OBJECT(RETURNING text FORMAT JSON);
-SELECT JSON_OBJECT(RETURNING text FORMAT JSON ENCODING UTF8);
-SELECT JSON_OBJECT(RETURNING text FORMAT JSON ENCODING INVALID_ENCODING);
-SELECT JSON_OBJECT(RETURNING bytea);
-SELECT JSON_OBJECT(RETURNING bytea FORMAT JSON);
-SELECT JSON_OBJECT(RETURNING bytea FORMAT JSON ENCODING UTF8);
-SELECT JSON_OBJECT(RETURNING bytea FORMAT JSON ENCODING UTF16);
-SELECT JSON_OBJECT(RETURNING bytea FORMAT JSON ENCODING UTF32);
-
-SELECT JSON_OBJECT('foo': NULL::int FORMAT JSON);
-SELECT JSON_OBJECT('foo': NULL::int FORMAT JSON ENCODING UTF8);
-SELECT JSON_OBJECT('foo': NULL::json FORMAT JSON);
-SELECT JSON_OBJECT('foo': NULL::json FORMAT JSON ENCODING UTF8);
-SELECT JSON_OBJECT('foo': NULL::jsonb FORMAT JSON);
-SELECT JSON_OBJECT('foo': NULL::jsonb FORMAT JSON ENCODING UTF8);
-
-SELECT JSON_OBJECT(NULL: 1);
-SELECT JSON_OBJECT('a': 2 + 3);
-SELECT JSON_OBJECT('a' VALUE 2 + 3);
---SELECT JSON_OBJECT(KEY 'a' VALUE 2 + 3);
-SELECT JSON_OBJECT('a' || 2: 1);
-SELECT JSON_OBJECT(('a' || 2) VALUE 1);
---SELECT JSON_OBJECT('a' || 2 VALUE 1);
---SELECT JSON_OBJECT(KEY 'a' || 2 VALUE 1);
-SELECT JSON_OBJECT('a': 2::text);
-SELECT JSON_OBJECT('a' VALUE 2::text);
---SELECT JSON_OBJECT(KEY 'a' VALUE 2::text);
-SELECT JSON_OBJECT(1::text: 2);
-SELECT JSON_OBJECT((1::text) VALUE 2);
---SELECT JSON_OBJECT(1::text VALUE 2);
---SELECT JSON_OBJECT(KEY 1::text VALUE 2);
-SELECT JSON_OBJECT(json '[1]': 123);
-SELECT JSON_OBJECT(ARRAY[1,2,3]: 'aaa');
-
-SELECT JSON_OBJECT(
-	'a': '123',
-	1.23: 123,
-	'c': json '[ 1,true,{ } ]',
-	'd': jsonb '{ "x" : 123.45 }'
-);
-
-SELECT JSON_OBJECT(
-	'a': '123',
-	1.23: 123,
-	'c': json '[ 1,true,{ } ]',
-	'd': jsonb '{ "x" : 123.45 }'
-	RETURNING jsonb
-);
-
-/*
-SELECT JSON_OBJECT(
-	'a': '123',
-	KEY 1.23 VALUE 123,
-	'c' VALUE json '[1, true, {}]'
-);
-*/
-
-SELECT JSON_OBJECT('a': '123', 'b': JSON_OBJECT('a': 111, 'b': 'aaa'));
-SELECT JSON_OBJECT('a': '123', 'b': JSON_OBJECT('a': 111, 'b': 'aaa' RETURNING jsonb));
-
-SELECT JSON_OBJECT('a': JSON_OBJECT('b': 1 RETURNING text));
-SELECT JSON_OBJECT('a': JSON_OBJECT('b': 1 RETURNING text) FORMAT JSON);
-SELECT JSON_OBJECT('a': JSON_OBJECT('b': 1 RETURNING bytea));
-SELECT JSON_OBJECT('a': JSON_OBJECT('b': 1 RETURNING bytea) FORMAT JSON);
-
-SELECT JSON_OBJECT('a': '1', 'b': NULL, 'c': 2);
-SELECT JSON_OBJECT('a': '1', 'b': NULL, 'c': 2 NULL ON NULL);
-SELECT JSON_OBJECT('a': '1', 'b': NULL, 'c': 2 ABSENT ON NULL);
-
-SELECT JSON_OBJECT(1: 1, '1': NULL WITH UNIQUE);
-SELECT JSON_OBJECT(1: 1, '1': NULL ABSENT ON NULL WITH UNIQUE);
-SELECT JSON_OBJECT(1: 1, '1': NULL NULL ON NULL WITH UNIQUE RETURNING jsonb);
-SELECT JSON_OBJECT(1: 1, '1': NULL ABSENT ON NULL WITH UNIQUE RETURNING jsonb);
-
-SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 NULL ON NULL WITH UNIQUE);
-SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 ABSENT ON NULL WITH UNIQUE);
-SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 ABSENT ON NULL WITHOUT UNIQUE);
-SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 ABSENT ON NULL WITH UNIQUE RETURNING jsonb);
-SELECT JSON_OBJECT(1: 1, '2': NULL, '1': 1 ABSENT ON NULL WITHOUT UNIQUE RETURNING jsonb);
-SELECT JSON_OBJECT(1: 1, '2': NULL, '3': 1, 4: NULL, '5': 'a' ABSENT ON NULL WITH UNIQUE RETURNING jsonb);
-
-
--- JSON_ARRAY()
-SELECT JSON_ARRAY();
-SELECT JSON_ARRAY(RETURNING json);
-SELECT JSON_ARRAY(RETURNING json FORMAT JSON);
-SELECT JSON_ARRAY(RETURNING jsonb);
-SELECT JSON_ARRAY(RETURNING jsonb FORMAT JSON);
-SELECT JSON_ARRAY(RETURNING text);
-SELECT JSON_ARRAY(RETURNING text FORMAT JSON);
-SELECT JSON_ARRAY(RETURNING text FORMAT JSON ENCODING UTF8);
-SELECT JSON_ARRAY(RETURNING text FORMAT JSON ENCODING INVALID_ENCODING);
-SELECT JSON_ARRAY(RETURNING bytea);
-SELECT JSON_ARRAY(RETURNING bytea FORMAT JSON);
-SELECT JSON_ARRAY(RETURNING bytea FORMAT JSON ENCODING UTF8);
-SELECT JSON_ARRAY(RETURNING bytea FORMAT JSON ENCODING UTF16);
-SELECT JSON_ARRAY(RETURNING bytea FORMAT JSON ENCODING UTF32);
-
-SELECT JSON_ARRAY('aaa', 111, true, array[1,2,3], NULL, json '{"a": [1]}', jsonb '["a",3]');
-
-SELECT JSON_ARRAY('a',  NULL, 'b' NULL   ON NULL);
-SELECT JSON_ARRAY('a',  NULL, 'b' ABSENT ON NULL);
-SELECT JSON_ARRAY(NULL, NULL, 'b' ABSENT ON NULL);
-SELECT JSON_ARRAY('a',  NULL, 'b' NULL   ON NULL RETURNING jsonb);
-SELECT JSON_ARRAY('a',  NULL, 'b' ABSENT ON NULL RETURNING jsonb);
-SELECT JSON_ARRAY(NULL, NULL, 'b' ABSENT ON NULL RETURNING jsonb);
-
-SELECT JSON_ARRAY(JSON_ARRAY('{ "a" : 123 }' RETURNING text));
-SELECT JSON_ARRAY(JSON_ARRAY('{ "a" : 123 }' FORMAT JSON RETURNING text));
-SELECT JSON_ARRAY(JSON_ARRAY('{ "a" : 123 }' FORMAT JSON RETURNING text) FORMAT JSON);
-
-SELECT JSON_ARRAY(SELECT i FROM (VALUES (1), (2), (NULL), (4)) foo(i));
-SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i));
-SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) RETURNING jsonb);
---SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) NULL ON NULL);
---SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) NULL ON NULL RETURNING jsonb);
-SELECT JSON_ARRAY(SELECT i FROM (VALUES (3), (1), (NULL), (2)) foo(i) ORDER BY i);
--- Should fail
-SELECT JSON_ARRAY(SELECT FROM (VALUES (1)) foo(i));
-SELECT JSON_ARRAY(SELECT i, i FROM (VALUES (1)) foo(i));
-SELECT JSON_ARRAY(SELECT * FROM (VALUES (1, 2)) foo(i, j));
-
--- JSON_ARRAYAGG()
-SELECT	JSON_ARRAYAGG(i) IS NULL,
-		JSON_ARRAYAGG(i RETURNING jsonb) IS NULL
-FROM generate_series(1, 0) i;
-
-SELECT	JSON_ARRAYAGG(i),
-		JSON_ARRAYAGG(i RETURNING jsonb)
-FROM generate_series(1, 5) i;
-
-SELECT JSON_ARRAYAGG(i ORDER BY i DESC)
-FROM generate_series(1, 5) i;
-
-SELECT JSON_ARRAYAGG(i::text::json)
-FROM generate_series(1, 5) i;
-
-SELECT JSON_ARRAYAGG(JSON_ARRAY(i, i + 1 RETURNING text) FORMAT JSON)
-FROM generate_series(1, 5) i;
-
-SELECT	JSON_ARRAYAGG(NULL),
-		JSON_ARRAYAGG(NULL RETURNING jsonb)
-FROM generate_series(1, 5);
-
-SELECT	JSON_ARRAYAGG(NULL NULL ON NULL),
-		JSON_ARRAYAGG(NULL NULL ON NULL RETURNING jsonb)
-FROM generate_series(1, 5);
-
-SELECT
-	JSON_ARRAYAGG(bar),
-	JSON_ARRAYAGG(bar RETURNING jsonb),
-	JSON_ARRAYAGG(bar ABSENT ON NULL),
-	JSON_ARRAYAGG(bar ABSENT ON NULL RETURNING jsonb),
-	JSON_ARRAYAGG(bar NULL ON NULL),
-	JSON_ARRAYAGG(bar NULL ON NULL RETURNING jsonb),
-	JSON_ARRAYAGG(foo),
-	JSON_ARRAYAGG(foo RETURNING jsonb),
-	JSON_ARRAYAGG(foo ORDER BY bar) FILTER (WHERE bar > 2),
-	JSON_ARRAYAGG(foo ORDER BY bar RETURNING jsonb) FILTER (WHERE bar > 2)
-FROM
-	(VALUES (NULL), (3), (1), (NULL), (NULL), (5), (2), (4), (NULL)) foo(bar);
-
-SELECT
-	bar, JSON_ARRAYAGG(bar) FILTER (WHERE bar > 2) OVER (PARTITION BY foo.bar % 2)
-FROM
-	(VALUES (NULL), (3), (1), (NULL), (NULL), (5), (2), (4), (NULL), (5), (4)) foo(bar);
-
--- JSON_OBJECTAGG()
-SELECT	JSON_OBJECTAGG('key': 1) IS NULL,
-		JSON_OBJECTAGG('key': 1 RETURNING jsonb) IS NULL
-WHERE FALSE;
-
-SELECT JSON_OBJECTAGG(NULL: 1);
-
-SELECT JSON_OBJECTAGG(NULL: 1 RETURNING jsonb);
-
-SELECT
-	JSON_OBJECTAGG(i: i),
---	JSON_OBJECTAGG(i VALUE i),
---	JSON_OBJECTAGG(KEY i VALUE i),
-	JSON_OBJECTAGG(i: i RETURNING jsonb)
-FROM
-	generate_series(1, 5) i;
-
-SELECT
-	JSON_OBJECTAGG(k: v),
-	JSON_OBJECTAGG(k: v NULL ON NULL),
-	JSON_OBJECTAGG(k: v ABSENT ON NULL),
-	JSON_OBJECTAGG(k: v RETURNING jsonb),
-	JSON_OBJECTAGG(k: v NULL ON NULL RETURNING jsonb),
-	JSON_OBJECTAGG(k: v ABSENT ON NULL RETURNING jsonb)
-FROM
-	(VALUES (1, 1), (1, NULL), (2, NULL), (3, 3)) foo(k, v);
-
-SELECT JSON_OBJECTAGG(k: v WITH UNIQUE KEYS)
-FROM (VALUES (1, 1), (1, NULL), (2, 2)) foo(k, v);
-
-SELECT JSON_OBJECTAGG(k: v ABSENT ON NULL WITH UNIQUE KEYS)
-FROM (VALUES (1, 1), (1, NULL), (2, 2)) foo(k, v);
-
-SELECT JSON_OBJECTAGG(k: v ABSENT ON NULL WITH UNIQUE KEYS)
-FROM (VALUES (1, 1), (0, NULL), (3, NULL), (2, 2), (4, NULL)) foo(k, v);
-
-SELECT JSON_OBJECTAGG(k: v WITH UNIQUE KEYS RETURNING jsonb)
-FROM (VALUES (1, 1), (1, NULL), (2, 2)) foo(k, v);
-
-SELECT JSON_OBJECTAGG(k: v ABSENT ON NULL WITH UNIQUE KEYS RETURNING jsonb)
-FROM (VALUES (1, 1), (1, NULL), (2, 2)) foo(k, v);
-
-SELECT JSON_OBJECTAGG(k: v ABSENT ON NULL WITH UNIQUE KEYS RETURNING jsonb)
-FROM (VALUES (1, 1), (0, NULL),(4, null), (5, null),(6, null),(2, 2)) foo(k, v);
-
--- Test JSON_OBJECT deparsing
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_OBJECT('foo' : '1' FORMAT JSON, 'bar' : 'baz' RETURNING json);
-
-CREATE VIEW json_object_view AS
-SELECT JSON_OBJECT('foo' : '1' FORMAT JSON, 'bar' : 'baz' RETURNING json);
-
-\sv json_object_view
-
-DROP VIEW json_object_view;
-
-SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v WITH UNIQUE KEYS) OVER (ORDER BY k)
-FROM (VALUES (1,1), (2,2)) a(k,v);
-
-SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v WITH UNIQUE KEYS) OVER (ORDER BY k)
-FROM (VALUES (1,1), (1,2), (2,2)) a(k,v);
-
-SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v ABSENT ON NULL WITH UNIQUE KEYS)
-   OVER (ORDER BY k)
-FROM (VALUES (1,1), (1,null), (2,2)) a(k,v);
-
-SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v ABSENT ON NULL)
-OVER (ORDER BY k)
-FROM (VALUES (1,1), (1,null), (2,2)) a(k,v);
-
-SELECT to_json(a) AS a, JSON_OBJECTAGG(k : v ABSENT ON NULL)
-OVER (ORDER BY k RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
-FROM (VALUES (1,1), (1,null), (2,2)) a(k,v);
-
--- Test JSON_ARRAY deparsing
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_ARRAY('1' FORMAT JSON, 2 RETURNING json);
-
-CREATE VIEW json_array_view AS
-SELECT JSON_ARRAY('1' FORMAT JSON, 2 RETURNING json);
-
-\sv json_array_view
-
-DROP VIEW json_array_view;
-
--- Test JSON_OBJECTAGG deparsing
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_OBJECTAGG(i: ('111' || i)::bytea FORMAT JSON WITH UNIQUE RETURNING text) FILTER (WHERE i > 3)
-FROM generate_series(1,5) i;
-
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_OBJECTAGG(i: ('111' || i)::bytea FORMAT JSON WITH UNIQUE RETURNING text) OVER (PARTITION BY i % 2)
-FROM generate_series(1,5) i;
-
-CREATE VIEW json_objectagg_view AS
-SELECT JSON_OBJECTAGG(i: ('111' || i)::bytea FORMAT JSON WITH UNIQUE RETURNING text) FILTER (WHERE i > 3)
-FROM generate_series(1,5) i;
-
-\sv json_objectagg_view
-
-DROP VIEW json_objectagg_view;
-
--- Test JSON_ARRAYAGG deparsing
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_ARRAYAGG(('111' || i)::bytea FORMAT JSON NULL ON NULL RETURNING text) FILTER (WHERE i > 3)
-FROM generate_series(1,5) i;
-
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_ARRAYAGG(('111' || i)::bytea FORMAT JSON NULL ON NULL RETURNING text) OVER (PARTITION BY i % 2)
-FROM generate_series(1,5) i;
-
-CREATE VIEW json_arrayagg_view AS
-SELECT JSON_ARRAYAGG(('111' || i)::bytea FORMAT JSON NULL ON NULL RETURNING text) FILTER (WHERE i > 3)
-FROM generate_series(1,5) i;
-
-\sv json_arrayagg_view
-
-DROP VIEW json_arrayagg_view;
-
--- Test JSON_ARRAY(subquery) deparsing
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT JSON_ARRAY(SELECT i FROM (VALUES (1), (2), (NULL), (4)) foo(i) RETURNING jsonb);
-
-CREATE VIEW json_array_subquery_view AS
-SELECT JSON_ARRAY(SELECT i FROM (VALUES (1), (2), (NULL), (4)) foo(i) RETURNING jsonb);
-
-\sv json_array_subquery_view
-
-DROP VIEW json_array_subquery_view;
-
--- IS JSON predicate
-SELECT NULL IS JSON;
-SELECT NULL IS NOT JSON;
-SELECT NULL::json IS JSON;
-SELECT NULL::jsonb IS JSON;
-SELECT NULL::text IS JSON;
-SELECT NULL::bytea IS JSON;
-SELECT NULL::int IS JSON;
-
-SELECT '' IS JSON;
-
-SELECT bytea '\x00' IS JSON;
-
-CREATE TABLE test_is_json (js text);
-
-INSERT INTO test_is_json VALUES
- (NULL),
- (''),
- ('123'),
- ('"aaa "'),
- ('true'),
- ('null'),
- ('[]'),
- ('[1, "2", {}]'),
- ('{}'),
- ('{ "a": 1, "b": null }'),
- ('{ "a": 1, "a": null }'),
- ('{ "a": 1, "b": [{ "a": 1 }, { "a": 2 }] }'),
- ('{ "a": 1, "b": [{ "a": 1, "b": 0, "a": 2 }] }'),
- ('aaa'),
- ('{a:1}'),
- ('["a",]');
-
-SELECT
-	js,
-	js IS JSON "IS JSON",
-	js IS NOT JSON "IS NOT JSON",
-	js IS JSON VALUE "IS VALUE",
-	js IS JSON OBJECT "IS OBJECT",
-	js IS JSON ARRAY "IS ARRAY",
-	js IS JSON SCALAR "IS SCALAR",
-	js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE",
-	js IS JSON WITH UNIQUE KEYS "WITH UNIQUE"
-FROM
-	test_is_json;
-
-SELECT
-	js,
-	js IS JSON "IS JSON",
-	js IS NOT JSON "IS NOT JSON",
-	js IS JSON VALUE "IS VALUE",
-	js IS JSON OBJECT "IS OBJECT",
-	js IS JSON ARRAY "IS ARRAY",
-	js IS JSON SCALAR "IS SCALAR",
-	js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE",
-	js IS JSON WITH UNIQUE KEYS "WITH UNIQUE"
-FROM
-	(SELECT js::json FROM test_is_json WHERE js IS JSON) foo(js);
-
-SELECT
-	js0,
-	js IS JSON "IS JSON",
-	js IS NOT JSON "IS NOT JSON",
-	js IS JSON VALUE "IS VALUE",
-	js IS JSON OBJECT "IS OBJECT",
-	js IS JSON ARRAY "IS ARRAY",
-	js IS JSON SCALAR "IS SCALAR",
-	js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE",
-	js IS JSON WITH UNIQUE KEYS "WITH UNIQUE"
-FROM
-	(SELECT js, js::bytea FROM test_is_json WHERE js IS JSON) foo(js0, js);
-
-SELECT
-	js,
-	js IS JSON "IS JSON",
-	js IS NOT JSON "IS NOT JSON",
-	js IS JSON VALUE "IS VALUE",
-	js IS JSON OBJECT "IS OBJECT",
-	js IS JSON ARRAY "IS ARRAY",
-	js IS JSON SCALAR "IS SCALAR",
-	js IS JSON WITHOUT UNIQUE KEYS "WITHOUT UNIQUE",
-	js IS JSON WITH UNIQUE KEYS "WITH UNIQUE"
-FROM
-	(SELECT js::jsonb FROM test_is_json WHERE js IS JSON) foo(js);
-
--- Test IS JSON deparsing
-EXPLAIN (VERBOSE, COSTS OFF)
-SELECT '1' IS JSON AS "any", ('1' || i) IS JSON SCALAR AS "scalar", '[]' IS NOT JSON ARRAY AS "array", '{}' IS JSON OBJECT WITH UNIQUE AS "object" FROM generate_series(1, 3) i;
-
-CREATE VIEW is_json_view AS
-SELECT '1' IS JSON AS "any", ('1' || i) IS JSON SCALAR AS "scalar", '[]' IS NOT JSON ARRAY AS "array", '{}' IS JSON OBJECT WITH UNIQUE AS "object" FROM generate_series(1, 3) i;
-
-\sv is_json_view
-
-DROP VIEW is_json_view;
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 8ad112c44d..5b3b305963 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1237,12 +1237,10 @@ JsonBehaviorType
 JsonCoercion
 JsonCommon
 JsonConstructorExpr
-JsonConstructorExprState
 JsonConstructorType
 JsonEncoding
 JsonExpr
 JsonExprOp
-JsonExprState
 JsonFormat
 JsonFormatType
 JsonFunc
@@ -1291,18 +1289,6 @@ JsonQuotes
 JsonReturning
 JsonScalarExpr
 JsonSemAction
-JsonSerializeExpr
-JsonTable
-JsonTableColumn
-JsonTableColumnType
-JsonTableContext
-JsonTableJoinState
-JsonTableParent
-JsonTablePlan
-JsonTablePlanJoinType
-JsonTablePlanType
-JsonTableScanState
-JsonTableSibling
 JsonTokenType
 JsonTransformStringValuesAction
 JsonTypeCategory
@@ -2724,7 +2710,6 @@ TableFunc
 TableFuncRoutine
 TableFuncScan
 TableFuncScanState
-TableFuncType
 TableInfo
 TableLikeClause
 TableSampleClause