On Fri, Dec 22, 2023 at 9:01 PM jian he <[email protected]> wrote: > > Hi > > + /* FALLTHROUGH */ > + case JTC_EXISTS: > + case JTC_FORMATTED: > + { > + Node *je; > + CaseTestExpr *param = makeNode(CaseTestExpr); > + > + param->collation = InvalidOid; > + param->typeId = cxt->contextItemTypid; > + param->typeMod = -1; > + > + if (rawc->wrapper != JSW_NONE && > + rawc->quotes != JS_QUOTES_UNSPEC) > + ereport(ERROR, > + (errcode(ERRCODE_SYNTAX_ERROR), > + errmsg("cannot use WITH WRAPPER clause for formatted colunmns" > + " without also specifying OMIT/KEEP QUOTES"), > + parser_errposition(pstate, rawc->location))); > > typo, should be "formatted columns". > I suspect people will be confused with the meaning of "formatted column". > maybe we can replace this part:"cannot use WITH WRAPPER clause for > formatted column" > to > "SQL/JSON WITH WRAPPER behavior must not be specified when FORMAT > clause is used" > > SELECT * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text > FORMAT JSON PATH '$' with wrapper KEEP QUOTES)); > ERROR: cannot use WITH WRAPPER clause for formatted colunmns without > also specifying OMIT/KEEP QUOTES > LINE 1: ...T * FROM JSON_TABLE(jsonb '"world"', '$' COLUMNS (item text ... > ^ > this error is misleading, since now I am using WITH WRAPPER clause for > formatted columns and specified KEEP QUOTES. >
Hi. still based on v33.
JSON_TABLE:
I also refactor parse_jsontable.c error reporting, now the error
message will be consistent with json_query.
now you can specify wrapper freely as long as you don't specify
wrapper and quote at the same time.
overall, json_table behavior is more consistent with json_query and json_value.
I also added some tests.
+void
+ExecEvalJsonCoercion(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext)
+{
+ JsonCoercion *coercion = op->d.jsonexpr_coercion.coercion;
+ ErrorSaveContext *escontext = op->d.jsonexpr_coercion.escontext;
+ Datum res = *op->resvalue;
+ bool resnull = *op->resnull;
+
+ if (coercion->via_populate)
+ {
+ void *cache = op->d.jsonexpr_coercion.json_populate_type_cache;
+
+ *op->resvalue = json_populate_type(res, JSONBOID,
+ coercion->targettype,
+ coercion->targettypmod,
+ &cache,
+ econtext->ecxt_per_query_memory,
+ op->resnull, (Node *) escontext);
+ }
+ else if (coercion->via_io)
+ {
+ FmgrInfo *input_finfo = op->d.jsonexpr_coercion.input_finfo;
+ Oid typioparam = op->d.jsonexpr_coercion.typioparam;
+ char *val_string = resnull ? NULL :
+ JsonbUnquote(DatumGetJsonbP(res));
+
+ (void) InputFunctionCallSafe(input_finfo, val_string, typioparam,
+ coercion->targettypmod,
+ (Node *) escontext,
+ op->resvalue);
+ }
via_populate, via_io should be mutually exclusive.
your patch, in some cases, both (coercion->via_io) and
(coercion->via_populate) are true.
(we can use elog find out).
I refactor coerceJsonFuncExprOutput, so now it will be mutually exclusive.
I also add asserts to it.
By default, json_query keeps quotes, json_value omit quotes.
However, json_table will be transformed to json_value or json_query
based on certain criteria,
that means we need to explicitly set the JsonExpr->omit_quotes in the
function transformJsonFuncExpr
for case JSON_QUERY_OP and JSON_VALUE_OP.
We need to know the QUOTE behavior in the function ExecEvalJsonCoercion.
Because for ExecEvalJsonCoercion, the coercion datum source can be a
scalar string item,
scalar items means RETURNING clause is dependent on QUOTE behavior.
keep quotes, omit quotes the results are different.
consider
JSON_QUERY(jsonb'{"rec": "[1,2]"}', '$.rec' returning int4range omit quotes);
and
JSON_QUERY(jsonb'{"rec": "[1,2]"}', '$.rec' returning int4range omit quotes);
to make sure ExecEvalJsonCoercion can distinguish keep and omit quotes,
I added a bool keep_quotes to struct JsonCoercion.
(maybe there is a more simple way, so far, that's what I come up with).
the keep_quotes value will be settled in the function transformJsonFuncExpr.
After refactoring, in ExecEvalJsonCoercion, keep_quotes is true then
call JsonbToCString, else call JsonbUnquote.
example:
SELECT JSON_QUERY(jsonb'{"rec": "{1,2,3}"}', '$.rec' returning int[]
omit quotes);
without my changes, return NULL
with my changes:
{1,2,3}
JSON_VALUE:
main changes:
--- a/src/test/regress/expected/jsonb_sqljson.out
+++ b/src/test/regress/expected/jsonb_sqljson.out
@@ -301,7 +301,11 @@ 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 'null', '$' RETURNING sqljsonb_int_not_null);
-ERROR: domain sqljsonb_int_not_null does not allow null values
+ json_value
+------------
+
+(1 row)
+
I think the change is correct, given `SELECT JSON_VALUE(jsonb 'null',
'$' RETURNING int4range);` returns NULL.
I also attached a test.sql, without_patch.out (apply v33 only),
with_patch.out (my changes based on v33).
So you can see the difference after applying the patch, in case, my
wording is not clear.
v1-0001-refactor-ExecInitJsonExpr.no-cfnot
Description: Binary data
v1-0002-refactor-QUOTE-behavior-for-json_query.no-cfbot
Description: Binary data
v1-0004-refactor-json_table-wrapper-and-quotes-behavior.no-cfbot
Description: Binary data
v1-0003-refactor-the-QUOTE-behavior-for-json_value.no-cfbot
Description: Binary data
test.sql
Description: application/sql
without_patch.out
Description: Binary data
with_patch.out
Description: Binary data
