@@ -18859,6 +18859,340 @@ DETAIL: Missing "]" after array dimensions.
1885918859 </tgroup>
1886018860 </table>
1886118861 </sect2>
18862+
18863+ <sect2 id="functions-sqljson-table">
18864+ <title>JSON_TABLE</title>
18865+ <indexterm>
18866+ <primary>json_table</primary>
18867+ </indexterm>
18868+
18869+ <para>
18870+ <function>JSON_TABLE</function> is an SQL/JSON function which
18871+ queries <acronym>JSON</acronym> data
18872+ and presents the results as a relational view, which can be accessed as a
18873+ regular SQL table. You can use <function>JSON_TABLE</function> inside
18874+ the <literal>FROM</literal> clause of a <literal>SELECT</literal>,
18875+ <literal>UPDATE</literal>, or <literal>DELETE</literal> and as data source
18876+ in a <literal>MERGE</literal> statement.
18877+ </para>
18878+
18879+ <para>
18880+ Taking JSON data as input, <function>JSON_TABLE</function> uses a JSON path
18881+ expression to extract a part of the provided data to use as a
18882+ <firstterm>row pattern</firstterm> for the constructed view. Each SQL/JSON
18883+ value given by the row pattern serves as source for a separate row in the
18884+ constructed view.
18885+ </para>
18886+
18887+ <para>
18888+ To split the row pattern into columns, <function>JSON_TABLE</function>
18889+ provides the <literal>COLUMNS</literal> clause that defines the
18890+ schema of the created view. For each column, a separate JSON path expression
18891+ can be specified to be evaluated against the row pattern to get an SQL/JSON
18892+ value that will become the value for the specified column in a given output
18893+ row.
18894+ </para>
18895+
18896+ <para>
18897+ The rows produced by <function>JSON_TABLE</function> are laterally
18898+ joined to the row that generated them, so you do not have to explicitly join
18899+ the constructed view with the original table holding <acronym>JSON</acronym>
18900+ data.
18901+ </para>
18902+
18903+ <para>
18904+ The syntax is:
18905+ </para>
18906+
18907+ <synopsis>
18908+ JSON_TABLE (
18909+ <replaceable>context_item</replaceable>, <replaceable>path_expression</replaceable> <optional> AS <replaceable>json_path_name</replaceable> </optional> <optional> PASSING { <replaceable>value</replaceable> AS <replaceable>varname</replaceable> } <optional>, ...</optional> </optional>
18910+ COLUMNS ( <replaceable class="parameter">json_table_column</replaceable> <optional>, ...</optional> )
18911+ <optional> { <literal>ERROR</literal> | <literal>EMPTY</literal> } <literal>ON ERROR</literal> </optional>
18912+ )
18913+
18914+ <phrase>
18915+ where <replaceable class="parameter">json_table_column</replaceable> is:
18916+ </phrase>
18917+ <replaceable>name</replaceable> FOR ORDINALITY
18918+ | <replaceable>name</replaceable> <replaceable>type</replaceable>
18919+ <optional> FORMAT JSON <optional>ENCODING <literal>UTF8</literal></optional></optional>
18920+ <optional> PATH <replaceable>path_expression</replaceable> </optional>
18921+ <optional> { WITHOUT | WITH { CONDITIONAL | <optional>UNCONDITIONAL</optional> } } <optional> ARRAY </optional> WRAPPER </optional>
18922+ <optional> { KEEP | OMIT } QUOTES <optional> ON SCALAR STRING </optional> </optional>
18923+ <optional> { ERROR | NULL | EMPTY { ARRAY | OBJECT } | DEFAULT <replaceable>expression</replaceable> } ON EMPTY </optional>
18924+ <optional> { ERROR | NULL | EMPTY { ARRAY | OBJECT } | DEFAULT <replaceable>expression</replaceable> } ON ERROR </optional>
18925+ | <replaceable>name</replaceable> <replaceable>type</replaceable> EXISTS <optional> PATH <replaceable>path_expression</replaceable> </optional>
18926+ <optional> { ERROR | TRUE | FALSE | UNKNOWN } ON ERROR </optional>
18927+ </synopsis>
18928+
18929+ <para>
18930+ Each syntax element is described below in more detail.
18931+ </para>
18932+
18933+ <variablelist>
18934+ <varlistentry>
18935+ <term>
18936+ <literal><replaceable>context_item</replaceable>, <replaceable>path_expression</replaceable> <optional> <literal>AS</literal> <replaceable>json_path_name</replaceable> </optional> <optional> <literal>PASSING</literal> { <replaceable>value</replaceable> <literal>AS</literal> <replaceable>varname</replaceable> } <optional>, ...</optional></optional></literal>
18937+ </term>
18938+ <listitem>
18939+ <para>
18940+ The input data to query (<replaceable>context_item</replaceable>),
18941+ the JSON path expression defining the query (<replaceable>path_expression</replaceable>)
18942+ with an optional name (<replaceable>json_path_name</replaceable>), and an
18943+ optional <literal>PASSING</literal> clause, which can provide data values
18944+ to the <replaceable>path_expression</replaceable>. The result of the input
18945+ data evaluation using the aforementioned elements is called the
18946+ <firstterm>row pattern</firstterm>, which is used as the source for row
18947+ values in the constructed view.
18948+ </para>
18949+ </listitem>
18950+ </varlistentry>
18951+
18952+ <varlistentry>
18953+ <term>
18954+ <literal>COLUMNS</literal> ( <replaceable>json_table_column</replaceable> <optional>, ...</optional> )
18955+ </term>
18956+ <listitem>
18957+
18958+ <para>
18959+ The <literal>COLUMNS</literal> clause defining the schema of the
18960+ constructed view. In this clause, you can specify each column to be
18961+ filled with an SQL/JSON value obtained by applying a JSON path expression
18962+ against the row pattern. <replaceable>json_table_column</replaceable> has
18963+ the following variants:
18964+ </para>
18965+
18966+ <variablelist>
18967+ <varlistentry>
18968+ <term>
18969+ <replaceable>name</replaceable> <literal>FOR ORDINALITY</literal>
18970+ </term>
18971+ <listitem>
18972+ <para>
18973+ Adds an ordinality column that provides sequential row numbering starting
18974+ from 1.
18975+ </para>
18976+ </listitem>
18977+ </varlistentry>
18978+
18979+ <varlistentry>
18980+ <term>
18981+ <literal><replaceable>name</replaceable> <replaceable>type</replaceable>
18982+ <optional><literal>FORMAT JSON</literal> <optional>ENCODING <literal>UTF8</literal></optional></optional>
18983+ <optional> <literal>PATH</literal> <replaceable>path_expression</replaceable> </optional></literal>
18984+ </term>
18985+ <listitem>
18986+ <para>
18987+ Inserts an SQL/JSON value obtained by applying
18988+ <replaceable>path_expression</replaceable> against the row pattern into
18989+ the view's output row after coercing it to specified
18990+ <replaceable>type</replaceable>.
18991+ </para>
18992+ <para>
18993+ Specifying <literal>FORMAT JSON</literal> makes it explicit that you
18994+ expect the value to be a valid <type>json</type> object. It only
18995+ makes sense to specify <literal>FORMAT JSON</literal> if
18996+ <replaceable>type</replaceable> is one of <type>bpchar</type>,
18997+ <type>bytea</type>, <type>character varying</type>, <type>name</type>,
18998+ <type>json</type>, <type>jsonb</type>, <type>text</type>, or a domain over
18999+ these types.
19000+ </para>
19001+ <para>
19002+ Optionally, you can specify <literal>WRAPPER</literal> and
19003+ <literal>QUOTES</literal> clauses to format the output. Note that
19004+ specifying <literal>OMIT QUOTES</literal> overrides
19005+ <literal>FORMAT JSON</literal> if also specified, because unquoted
19006+ literals do not constitute valid <type>json</type> values.
19007+ </para>
19008+ <para>
19009+ Optionally, you can use <literal>ON EMPTY</literal> and
19010+ <literal>ON ERROR</literal> clauses to specify whether to throw the error
19011+ or return the specified value when the result of JSON path evaluation is
19012+ empty and when an error occurs during JSON path evaluation or when
19013+ coercing the SQL/JSON value to the specified type, respectively. The
19014+ default for both is to return a <literal>NULL</literal> value.
19015+ </para>
19016+ <note>
19017+ <para>
19018+ This clause is internally turned into and has the same semantics as
19019+ <function>JSON_VALUE</function> or <function>JSON_QUERY</function>.
19020+ The latter if the specified type is not a scalar type or if either of
19021+ <literal>FORMAT JSON</literal>, <literal>WRAPPER</literal>, or
19022+ <literal>QUOTES</literal> clause is present.
19023+ </para>
19024+ </note>
19025+ </listitem>
19026+ </varlistentry>
19027+
19028+ <varlistentry>
19029+ <term>
19030+ <replaceable>name</replaceable> <replaceable>type</replaceable>
19031+ <literal>EXISTS</literal> <optional> <literal>PATH</literal> <replaceable>path_expression</replaceable> </optional>
19032+ </term>
19033+ <listitem>
19034+ <para>
19035+ Inserts a boolean value obtained by applying
19036+ <replaceable>path_expression</replaceable> against the row pattern
19037+ into the view's output row after coercing it to specified
19038+ <replaceable>type</replaceable>.
19039+ </para>
19040+ <para>
19041+ The value corresponds to whether applying the <literal>PATH</literal>
19042+ expression to the row pattern yields any values.
19043+ </para>
19044+ <para>
19045+ The specified <replaceable>type</replaceable> should have a cast from the
19046+ <type>boolean</type> type.
19047+ </para>
19048+ <para>
19049+ Optionally, you can use <literal>ON ERROR</literal> to specify whether to
19050+ throw the error or return the specified value when an error occurs during
19051+ JSON path evaluation or when coercing SQL/JSON value to the specified
19052+ type. The default is to return a boolean value
19053+ <literal>FALSE</literal>.
19054+ </para>
19055+ <note>
19056+ <para>
19057+ This clause is internally turned into and has the same semantics as
19058+ <function>JSON_EXISTS</function>.
19059+ </para>
19060+ </note>
19061+ </listitem>
19062+ </varlistentry>
19063+ </variablelist>
19064+
19065+ <note>
19066+ <para>
19067+ In each variant of <replaceable>json_table_column</replaceable> described
19068+ above, if the <literal>PATH</literal> clause is omitted, path expression
19069+ <literal>$.<replaceable>name</replaceable></literal> is used, where
19070+ <replaceable>name</replaceable> is the provided column name.
19071+ </para>
19072+ </note>
19073+
19074+ </listitem>
19075+ </varlistentry>
19076+
19077+ <varlistentry>
19078+ <term>
19079+ <literal>AS</literal> <replaceable>json_path_name</replaceable>
19080+ </term>
19081+ <listitem>
19082+
19083+ <para>
19084+ The optional <replaceable>json_path_name</replaceable> serves as an
19085+ identifier of the provided <replaceable>path_expression</replaceable>.
19086+ The name must be unique and distinct from the column names.
19087+ </para>
19088+ </listitem>
19089+ </varlistentry>
19090+
19091+ <varlistentry>
19092+ <term>
19093+ { <literal>ERROR</literal> | <literal>EMPTY</literal> } <literal>ON ERROR</literal>
19094+ </term>
19095+ <listitem>
19096+
19097+ <para>
19098+ The optional <literal>ON ERROR</literal> can be used to specify how to
19099+ handle errors when evaluating the top-level
19100+ <replaceable>path_expression</replaceable>. Use <literal>ERROR</literal>
19101+ if you want the errors to be thrown and <literal>EMPTY</literal> to
19102+ return an empty table, that is, a table containing 0 rows. Note that
19103+ this clause does not affect the errors that occur when evaluating
19104+ columns, for which the behavior depends on whether the
19105+ <literal>ON ERROR</literal> clause is specified against a given column.
19106+ </para>
19107+ </listitem>
19108+ </varlistentry>
19109+ </variablelist>
19110+
19111+ <para>Examples</para>
19112+
19113+ <para>
19114+ In the examples that follow, the following table containing JSON data
19115+ will be used:
19116+
19117+ <programlisting>
19118+ CREATE TABLE my_films ( js jsonb );
19119+
19120+ INSERT INTO my_films VALUES (
19121+ '{ "favorites" : [
19122+ { "kind" : "comedy", "films" : [
19123+ { "title" : "Bananas",
19124+ "director" : "Woody Allen"},
19125+ { "title" : "The Dinner Game",
19126+ "director" : "Francis Veber" } ] },
19127+ { "kind" : "horror", "films" : [
19128+ { "title" : "Psycho",
19129+ "director" : "Alfred Hitchcock" } ] },
19130+ { "kind" : "thriller", "films" : [
19131+ { "title" : "Vertigo",
19132+ "director" : "Alfred Hitchcock" } ] },
19133+ { "kind" : "drama", "films" : [
19134+ { "title" : "Yojimbo",
19135+ "director" : "Akira Kurosawa" } ] }
19136+ ] }');
19137+ </programlisting>
19138+
19139+ </para>
19140+ <para>
19141+ The following query shows how to use <function>JSON_TABLE</function> to
19142+ turn the JSON objects in the <structname>my_films</structname> table
19143+ to a view containing columns for the keys <literal>kind</literal>,
19144+ <literal>title</literal>, and <literal>director</literal> contained in
19145+ the original JSON along with an ordinality column:
19146+
19147+ <programlisting>
19148+ SELECT jt.* FROM
19149+ my_films,
19150+ JSON_TABLE (js, '$.favorites[*]' COLUMNS (
19151+ id FOR ORDINALITY,
19152+ kind text PATH '$.kind',
19153+ title text PATH '$.films[*].title' WITH WRAPPER,
19154+ director text PATH '$.films[*].director' WITH WRAPPER)) AS jt;
19155+ </programlisting>
19156+
19157+ <screen>
19158+ id | kind | title | director
19159+ ----+----------+--------------------------------+----------------------------------
19160+ 1 | comedy | ["Bananas", "The Dinner Game"] | ["Woody Allen", "Francis Veber"]
19161+ 2 | horror | ["Psycho"] | ["Alfred Hitchcock"]
19162+ 3 | thriller | ["Vertigo"] | ["Alfred Hitchcock"]
19163+ 4 | drama | ["Yojimbo"] | ["Akira Kurosawa"]
19164+ (4 rows)
19165+ </screen>
19166+
19167+ </para>
19168+ <para>
19169+ The following is a modified version of the above query to show the
19170+ usage of <literal>PASSING</literal> arguments in the filter specified in
19171+ the top-level JSON path expression and the various options for the
19172+ individual columns:
19173+
19174+ <programlisting>
19175+ SELECT jt.* FROM
19176+ my_films,
19177+ JSON_TABLE (js, '$.favorites[*] ? (@.films[*].director == $filter)'
19178+ PASSING 'Alfred Hitchcock' AS filter, 'Vertigo' AS filter2
19179+ COLUMNS (
19180+ id FOR ORDINALITY,
19181+ kind text PATH '$.kind',
19182+ title text FORMAT JSON PATH '$.films[*].title' OMIT QUOTES,
19183+ director text PATH '$.films[*].director' KEEP QUOTES)) AS jt;
19184+ </programlisting>
19185+
19186+ <screen>
19187+ id | kind | title | director
19188+ ----+----------+---------+--------------------
19189+ 1 | horror | Psycho | "Alfred Hitchcock"
19190+ 2 | thriller | Vertigo | "Alfred Hitchcock"
19191+ (2 rows)
19192+ </screen>
19193+
19194+ </para>
19195+ </sect2>
1886219196 </sect1>
1886319197
1886419198 <sect1 id="functions-sequence">
0 commit comments