Re: SQL/JSON: functions
Nikita Glukhov <n.gluhov@postgrespro.ru>
Attachments
- 0001-Jsonpath-support-for-json-v42.patch.gz (application/gzip) patch v42-0001
- 0002-Add-common-SQL-JSON-clauses-v42.patch.gz (application/gzip) patch v42-0002
- 0003-Add-invisible-coercion-form-v42.patch.gz (application/gzip) patch v42-0003
- 0004-Add-function-formats-v42.patch.gz (application/gzip) patch v42-0004
- 0005-SQL-JSON-constructors-v42.patch.gz (application/gzip) patch v42-0005
- 0006-IS-JSON-predicate-v42.patch.gz (application/gzip) patch v42-0006
- 0007-SQL-JSON-query-functions-v42.patch.gz (application/gzip) patch v42-0007
Attached 42th version of the patches.
On 18.01.2020 21:21, Pavel Stehule wrote:
> On 18. 1. 2020 v 18:46 Nikita Glukhov <n.gluhov@postgrespro.ru
> <mailto:n.gluhov@postgrespro.ru>> wrote:
>
> Attached 41th version of the patches.
>
> Changes since previous version:
> * Enabled DEFAULT clause for ON ERROR/ON EMPTY behaviors in JSON_QUERY()
> * Added RETURNING clause to JSON_EXISTS() ("side effect" of implementation
> EXISTS PATH columns in JSON_TABLE)
> * ARRAY in EMPTY ARRAY ON ERROR clause is optional now for better Oracle
> compatibility
>
>
> On 17.01.2020 9:54, Pavel Stehule wrote:
>
>> I tested cumulative patch - sent in json_table patch.
>>
>> I almost satisfied by quality of this patch. There is very good
>> conformance with standard and with Oracle. Unfortunately MySQL in
>> this part of JSON support is not compatible.
>>
>> I found one issue, when I tested some examples from Oracle.
>>
>> SELECT JSON_VALUE('{a:100}', '$.a' RETURNING int) AS value;
>>
>> then the result was null.
>>
>> But it is wrong, because it should to raise a exception, because
>> this json is broken on Postgres (Postgres requires quoted
>> attribute names)
>>
>> json_query has same problem
>>
>> postgres=# SELECT JSON_QUERY('{a:100, b:200, c:300}', '$') AS value;
>> ┌───────┐
>> │ value │
>> ╞═══════╡
>> │ ∅ │
>> └───────┘
>> (1 row)
>>
>> It should to check if input is correct json
>
> By the standard, it is implementation-defined whether JSON parsing errors
> should be caught by ON ERROR clause.
>
> SQL/JSON query functions use "JSON API common syntax" which is a combination
> of JSON context item and JSON path. It passes context item to JSON path
> engine with ALREADY PARSED flag set to False. ALREADY PARSED flag can enable
> special parsing rules.
>
> Corresponding quotes from the standard:
>
> 10.14 <JSON API common syntax>
> <JSON API common syntax> (
> Parameter: "JSON API COMMON SYNTAX"
> ) Returns: "STATUS" and "SQL/JSON SEQUENCE"
>
> General Rules:
> ...
> 3) General Rules of Subclause 9.39, "SQL/JSON path language: syntax and
> semantics", are applied with P as PATH SPECIFICATION, C as CONTEXT ITEM,
> False as ALREADY PARSED, and PC as PASSING CLAUSE; let ST be the STATUS
> and let SEQ be the SQL/JSON SEQUENCE returned from the application of
> those General Rules.
>
> 9.39 SQL/JSON path language: syntax and semantics
>
> "SQL/JSON path language: syntax and semantics" [General Rules] (
> Parameter: "PATH SPECIFICATION",
> Parameter: "CONTEXT ITEM",
> Parameter: "ALREADY PARSED",
> Parameter: "PASSING CLAUSE"
> ) Returns: "STATUS" and "SQL/JSON SEQUENCE"
>
> General Rules:
> ...
>
> 4) If ALREADY PARSED is False, then it is implementation-defined whether the
> following rules are applied:
> a) The General Rules of Subclause 9.36, "Parsing JSON text", are applied with
> JT as JSON TEXT, an implementation-defined <JSON key uniqueness constraint>
> as UNIQUENESS CONSTRAINT, and FO as FORMAT OPTION; let ST be the STATUS and
> let CISJI be the SQL/JSON ITEM returned from the application of those
> General Rules.
> b) If ST is not successful completion, then ST is returned as the STATUS of
> this application of these General Rules, and no further General Rules of
> this Subclause are applied.
>
>
> I decided to apply this rules, so the parsing errors are caught now by ON ERROR
> (NULL ON ERROR is by default).
>
> postgres=# SELECT JSON_VALUE('error', '$' ERROR ON ERROR);
> ERROR: invalid input syntax for type json
> DETAIL: Token "error" is invalid.
> CONTEXT: JSON data, line 1: error
>
> I'm not sure if it would be better to add an implicit cast to json type that
> will be executed before so that parsing errors can no longer be caught.
> But implicit casting can simplify a bit execution of SQL/JSON query functions.
>
>
> I have checked error handling in JSON parsing in Oracle 18c/19c, and it behaves
> like our current implementation. But Oracle seems to do JSON parsing on demand:
>
> Oracle19c> SELECT JSON_VALUE('{a:1 error, b:2}', '$.a' ERROR ON ERROR) FROM dual;
> 1
>
> Oracle19c> SELECT JSON_VALUE('{a:1 error, b:2}', '$.b' ERROR ON ERROR) FROM dual;
> ORA-40441: JSON syntax error
>
> Oracle19c> SELECT JSON_VALUE('{a:1 error, b:2}', '$.b') FROM dual;
> NULL
>
>
> Everywhere I don't like default masking error. I think so can be very
> confusing to get NULL
> (by default) instead a error of broken format.
>
> I vote for check of input is correct JSON, and if it, then start
> processing. Else to raise a error.
>
> More - our JSON Parser is different than Oracle's JSON parser. And if
> somebody will run Oracle's JSONs,
> then he get some result on Oracle. But on Postgres, same JSON can be
> invalid, and he get NULL.
>
> The raising some errors looks like only one safe variant.
I have removed handling of parsing errors in SQL/JSON functions and JSON_TABLE.
Now, FORMAT JSON expressions (implicit or explicit) are simply transformed into
ordinary casts to json type, and these casts are executed before execution of
SQL/JSON functions. Previously, separate expression was created for such casts,
and it was executed in the separate subtransaction in ExecEvalJsonExpr(). So,
this change also simplifies the code a bit.
--
Nikita Glukhov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
JSON_TABLE: Add support for NESTED paths and columns
- bb766cde63b4 17.0 landed
-
Add basic JSON_TABLE() functionality
- de3600452b61 17.0 landed
-
Add SQL/JSON query functions
- 6185c9737cf4 17.0 landed
-
Add soft error handling to some expression nodes
- aaaf9449ec6b 17.0 landed
-
Adjust populate_record_field() to handle errors softly
- 1edb3b491bee 17.0 landed
-
Refactor code used by jsonpath executor to fetch variables
- faa2b953ba3b 17.0 landed
-
Add more SQL/JSON constructor functions
- 03734a7fed7d 17.0 landed
-
SQL/JSON: support the IS JSON predicate
- 6ee30209a6f1 16.0 landed
-
SQL/JSON: add standard JSON constructor functions
- 7081ac46ace8 16.0 landed
-
Improve readability of SQL/JSON documentation.
- b46bcf7a4b6f 15.0 landed
-
Documentation for SQL/JSON features
- a6baa4baddd5 15.0 landed
-
RETURNING clause for JSON() and JSON_SCALAR()
- 49082c2cc3d8 15.0 landed
-
SQL JSON functions
- 606948b058dc 15.0 landed
-
SQL/JSON query functions
- 1a36bc9dba8e 15.0 landed
-
IS JSON predicate
- 33a377608fc2 15.0 landed
-
SQL/JSON constructors
- f4fb45d15c59 15.0 landed
-
Common SQL/JSON clauses
- f79b803dcc98 15.0 landed
- 865fe4d5df56 15.0 landed
-
Doc: remove obsolete entries in table of BRIN strategy numbers.
- 0ce4cd04da55 14.0 cited
-
Doc: standardize markup a bit more.
- 47046763c3ed 13.0 cited
-
Make pg_regress.c unset PGDATABASE during make installcheck.
- 5ee96b3e2221 13.0 cited
-
Fix handling of GENERATED columns in CREATE TABLE LIKE INCLUDING DEFAULTS.
- b81a9c2fc525 13.0 cited