Re: pgsql: Add more SQL/JSON constructor functions
jian he <jian.universality@gmail.com>
hi.
I have assembled a list of simple examples, some works (for comparison
sake), most not work
as intended.
CREATE DOMAIN queryfuncs_char2 AS char(2) CHECK (VALUE NOT IN ('12'));
CREATE DOMAIN queryfuncs_d_interval AS interval(2) CHECK (VALUE is not null);
SELECT JSON_VALUE(jsonb '111', '$' RETURNING queryfuncs_char2 default
'12' on error);
SELECT JSON_VALUE(jsonb '12', '$' RETURNING queryfuncs_char2 default
'11' on error);
SELECT JSON_VALUE(jsonb '111', '$' RETURNING queryfuncs_char2 default
'13' on error);
SELECT JSON_VALUE(jsonb '"111"', '$' RETURNING queryfuncs_char2
default '17' on error);
SELECT JSON_QUERY(jsonb '111', '$' RETURNING queryfuncs_char2 default
'14' on error);
SELECT JSON_QUERY(jsonb '111', '$' RETURNING queryfuncs_char2 omit
quotes default '15' on error);
SELECT JSON_QUERY(jsonb '111', '$' RETURNING queryfuncs_char2 keep
quotes default '16' on error);
SELECT JSON_VALUE(jsonb '"01:23:45.6789"', '$' RETURNING
queryfuncs_d_interval default '01:23:45.6789' on error);
SELECT JSON_VALUE(jsonb '"01:23:45.6789"', '$' RETURNING
queryfuncs_d_interval default '01:23:45.6789' on empty);
SELECT JSON_QUERY(jsonb '"01:23:45.6789"', '$' RETURNING
queryfuncs_d_interval default '01:23:45.6789' on error);
SELECT JSON_QUERY(jsonb '"01:23:45.6789"', '$' RETURNING
queryfuncs_d_interval default '01:23:45.6789' on empty);
above 4 queries fails, meaning the changes you propose within
transformJsonBehavior is wrong?
i think it's because the COERCION_IMPLICIT cast from text to domain
queryfuncs_d_interval is not doable.
json_table seems also have problem with "exists" cast to other type, example:
SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a char(2) EXISTS
PATH '$.a' ));
SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a queryfuncs_char2
EXISTS PATH '$.a'));
SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a queryfuncs_char2
EXISTS PATH '$.a' error on error));
SELECT * FROM JSON_TABLE(jsonb '"a"', '$' COLUMNS (a queryfuncs_char2
EXISTS PATH '$.a' error on empty));
----------------------------------------------------------------------------------------------------
SELECT JSON_VALUE(jsonb '111', '$' RETURNING queryfuncs_char2 default
'13' on error);
for the above example:
coerceJsonExprOutput, coerceJsonFuncExpr set the result datum coercion
node to RelabelType:
RelabelType is not error safe. so the above query will fail converting
text 111 to queryfuncs_char2
which is not what we want.
I think making coerceJsonExprOutput the following way can solve this problem.
your patch cannot apply cleanly, I just posted the actual code snippet
of coerceJsonExprOutput, not a diff file.
static void
coerceJsonExprOutput(ParseState *pstate, JsonExpr *jsexpr)
{
JsonReturning *returning = jsexpr->returning;
Node *context_item = jsexpr->formatted_expr;
int default_typmod;
Oid default_typid;
bool omit_quotes =
jsexpr->op == JSON_QUERY_OP && jsexpr->omit_quotes;
Node *coercion_expr = NULL;
int32 baseTypmod = returning->typmod;
Assert(returning);
/*
* Check for cases where the coercion should be handled at runtime, that
* is, without using a cast expression.
*/
if (jsexpr->op == JSON_VALUE_OP)
{
/*
* Use cast expression for domain types; we need CoerceToDomain here.
*/
if (get_typtype(returning->typid) != TYPTYPE_DOMAIN)
{
jsexpr->use_io_coercion = true;
return;
}
else
{
/* domain type, typmod > 0 can only use use_io_coercion */
(void) getBaseTypeAndTypmod(returning->typid, &baseTypmod);
if (baseTypmod > 0)
{
jsexpr->use_io_coercion = true;
return;
}
}
}
else if (jsexpr->op == JSON_QUERY_OP)
{
/*
* Cast functions from jsonb to the following types (jsonb_bool() et
* al) don't handle errors softly, so coerce either by calling
* json_populate_type() or the type's input function so that any
* errors are handled appropriately. The latter only if OMIT QUOTES is
* true.
*/
switch (returning->typid)
{
case BOOLOID:
case NUMERICOID:
case INT2OID:
case INT4OID:
case INT8OID:
case FLOAT4OID:
case FLOAT8OID:
if (jsexpr->omit_quotes)
jsexpr->use_io_coercion = true;
else
jsexpr->use_json_coercion = true;
return;
default:
break;
}
/*
* for returning domain type, we cannot use coercion expression.
* it may not be able to catch the error, for example RelabelType
* for we either use_io_coercion or use_json_coercion.
*/
if (get_typtype(returning->typid) == TYPTYPE_DOMAIN)
(void) getBaseTypeAndTypmod(returning->typid, &baseTypmod);
/*
* coerceJsonFuncExpr() creates implicit casts for types with typmod,
* which (if present) don't handle errors softly, so use runtime
* coercion.
*/
if (baseTypmod > 0)
{
if (jsexpr->omit_quotes)
jsexpr->use_io_coercion = true;
else
jsexpr->use_json_coercion = true;
return;
}
}
...
-------------------------------
Commits
-
SQL/JSON: Avoid initializing unnecessary ON ERROR / ON EMPTY steps
- 77aebe9a8d3c 17.0 landed
- dd8bea88abf4 18.0 landed
- 3a97460970f3 18.0 landed
- e4e27976a687 17.0 landed
-
SQL/JSON: Fix default ON ERROR behavior for JSON_TABLE
- 446d5ad7ae7d 17.0 landed
- bbd4c058a89b 18.0 landed
- 5067c230b8ee 17.0 landed
- 565caaa79af9 18.0 landed
-
SQL/JSON: Fix JSON_TABLE() column deparsing
- cd680b39211c 17.0 landed
- ee75a03f37fc 18.0 landed
- c88ce386c4d7 17.0 landed
- 68222851d5a8 18.0 landed
-
Update comment about ExprState.escontext
- fe323438140f 17.0 landed
- 3422f5f93fcf 18.0 landed
-
SQL/JSON: Fix casting for integer EXISTS columns in JSON_TABLE
- f95c5090d975 17.0 landed
- 7f56eaff2fb0 18.0 landed
-
SQL/JSON: Some fixes to JsonBehavior expression casting
- 847ee701bd3a 17.0 landed
- 74c96699be3f 18.0 landed
-
SQL/JSON: Remove useless code in ExecInitJsonExpr()
- 6f9a62b454e8 18.0 landed
- 8a1a4087bd5f 17.0 landed
-
SQL/JSON: Respect OMIT QUOTES when RETURNING domains over jsonb
- 3c3ccd4ca801 17.0 landed
- 4fc6a555606d 18.0 landed
-
SQL/JSON: Improve error-handling of JsonBehavior expressions
- d1dc4ae5608d 17.0 landed
- 231b7d670b21 18.0 landed
-
SQL/JSON: Fix error-handling of some JsonBehavior expressions
- 79fa052e7880 17.0 landed
- 63e6c5f4a2ee 18.0 landed
-
SQL/JSON: Rethink c2d93c3802b
- 86d33987e8b0 18.0 landed
- 2177306a6413 17.0 landed
-
SQL/JSON: Always coerce JsonExpr result at runtime
- 716bd12d22c5 17.0 landed
-
SQL/JSON: Fix coercion of constructor outputs to types with typmod
- c2d93c3802b2 17.0 landed