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; } } ... -------------------------------