Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitaef3088

Browse files
author
Nikita Glukhov
committed
Enable RETURNING clause for JSON_EXISTS
1 parent33c1fd3 commitaef3088

File tree

7 files changed

+146
-16
lines changed

7 files changed

+146
-16
lines changed

‎doc/src/sgml/func.sgml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17727,6 +17727,7 @@ INSERT INTO my_films VALUES (
1772717727
<refsynopsisdiv>
1772817728
<synopsis>JSON_EXISTS (
1772917729
<replaceable class="parameter">json_api_common_syntax</replaceable>
17730+
[ RETURNING <replaceable class="parameter">data_type</replaceable> ]
1773017731
[ { TRUE | FALSE | UNKNOWN | ERROR } ON ERROR ]
1773117732
)
1773217733
</synopsis>
@@ -17757,6 +17758,19 @@ INSERT INTO my_films VALUES (
1775717758
</listitem>
1775817759
</varlistentry>
1775917760

17761+
<varlistentry>
17762+
<term>
17763+
<literal>RETURNING <replaceable class="parameter">data_type</replaceable></literal>
17764+
</term>
17765+
<listitem>
17766+
<para>
17767+
The output clause that specifies the data type of the returned value.
17768+
The specified data type should have a cast from a <literal>boolean</literal>
17769+
type, which is returned by default.
17770+
</para>
17771+
</listitem>
17772+
</varlistentry>
17773+
1776017774
<varlistentry>
1776117775
<term>
1776217776
<literal>{ TRUE | FALSE | UNKNOWN | ERROR } ON ERROR</literal>

‎src/backend/executor/execExprInterp.c

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4519,7 +4519,8 @@ ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
45194519

45204520
if (estate)/* coerce using specified expression */
45214521
returnExecEvalExpr(estate,econtext,isNull);
4522-
else
4522+
4523+
if (op->d.jsonexpr.jsexpr->op!=IS_JSON_EXISTS)
45234524
{
45244525
JsonCoercion*coercion=op->d.jsonexpr.jsexpr->result_coercion;
45254526
JsonExpr*jexpr=op->d.jsonexpr.jsexpr;
@@ -4855,11 +4856,21 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
48554856

48564857
caseIS_JSON_EXISTS:
48574858
{
4858-
boolres=JsonPathExists(item,path,
4859-
op->d.jsonexpr.args,error);
4859+
boolexists=JsonPathExists(item,path,
4860+
op->d.jsonexpr.args,
4861+
error);
48604862

48614863
*resnull=error&&*error;
4862-
returnBoolGetDatum(res);
4864+
res=BoolGetDatum(exists);
4865+
4866+
if (!op->d.jsonexpr.result_expr)
4867+
returnres;
4868+
4869+
/* coerce using result expression */
4870+
estate=op->d.jsonexpr.result_expr;
4871+
op->d.jsonexpr.res_expr->value=res;
4872+
op->d.jsonexpr.res_expr->isnull=*resnull;
4873+
break;
48634874
}
48644875

48654876
default:
@@ -4909,7 +4920,7 @@ ExecEvalJsonNeedsSubTransaction(JsonExpr *jsexpr,
49094920
if (jsexpr->on_error->btype==JSON_BEHAVIOR_ERROR)
49104921
return false;
49114922

4912-
if (jsexpr->op==IS_JSON_EXISTS)
4923+
if (jsexpr->op==IS_JSON_EXISTS&& !jsexpr->result_coercion)
49134924
return false;
49144925

49154926
if (!coercions)
@@ -4980,9 +4991,8 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
49804991
op->d.jsonexpr.default_on_error,
49814992
op->resnull);
49824993

4983-
if (jexpr->op!=IS_JSON_EXISTS&&
4984-
/* result is already coerced in DEFAULT behavior case */
4985-
jexpr->on_error->btype!=JSON_BEHAVIOR_DEFAULT)
4994+
/* result is already coerced in DEFAULT behavior case */
4995+
if (jexpr->on_error->btype!=JSON_BEHAVIOR_DEFAULT)
49864996
res=ExecEvalJsonExprCoercion(op,econtext,res,
49874997
op->resnull,
49884998
NULL,NULL);

‎src/backend/parser/gram.y

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15061,13 +15061,15 @@ json_output_clause_opt:
1506115061
json_exists_predicate:
1506215062
JSON_EXISTS'('
1506315063
json_api_common_syntax
15064+
json_returning_clause_opt
1506415065
json_exists_error_clause_opt
1506515066
')'
1506615067
{
1506715068
JsonFuncExpr *p =makeNode(JsonFuncExpr);
1506815069
p->op = IS_JSON_EXISTS;
1506915070
p->common = (JsonCommon *) $3;
15070-
p->on_error = $4;
15071+
p->output = (JsonOutput *) $4;
15072+
p->on_error = $5;
1507115073
p->location = @1;
1507215074
$$ = (Node *) p;
1507315075
}

‎src/backend/parser/parse_expr.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4828,11 +4828,45 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
48284828
caseIS_JSON_EXISTS:
48294829
func_name="JSON_EXISTS";
48304830

4831-
jsexpr->returning=makeNode(JsonReturning);
4832-
jsexpr->returning->format=makeJsonFormat(JS_FORMAT_DEFAULT,JS_ENC_DEFAULT,-1);
4833-
jsexpr->returning->typid=BOOLOID;
4834-
jsexpr->returning->typmod=-1;
4831+
jsexpr->returning=transformJsonOutput(pstate,func->output, false);
48354832

4833+
jsexpr->returning->format->format=JS_FORMAT_DEFAULT;
4834+
jsexpr->returning->format->encoding=JS_ENC_DEFAULT;
4835+
4836+
if (!OidIsValid(jsexpr->returning->typid))
4837+
{
4838+
jsexpr->returning->typid=BOOLOID;
4839+
jsexpr->returning->typmod=-1;
4840+
}
4841+
elseif (jsexpr->returning->typid!=BOOLOID)
4842+
{
4843+
CaseTestExpr*placeholder=makeNode(CaseTestExpr);
4844+
intlocation=exprLocation((Node*)jsexpr);
4845+
4846+
placeholder->typeId=BOOLOID;
4847+
placeholder->typeMod=-1;
4848+
placeholder->collation=InvalidOid;
4849+
4850+
jsexpr->result_coercion=makeNode(JsonCoercion);
4851+
jsexpr->result_coercion->expr=
4852+
coerce_to_target_type(pstate, (Node*)placeholder,BOOLOID,
4853+
jsexpr->returning->typid,
4854+
jsexpr->returning->typmod,
4855+
COERCION_EXPLICIT,
4856+
COERCE_INTERNAL_CAST,
4857+
location);
4858+
4859+
if (!jsexpr->result_coercion->expr)
4860+
ereport(ERROR,
4861+
(errcode(ERRCODE_CANNOT_COERCE),
4862+
errmsg("cannot cast type %s to %s",
4863+
format_type_be(BOOLOID),
4864+
format_type_be(jsexpr->returning->typid)),
4865+
parser_coercion_errposition(pstate,location, (Node*)jsexpr)));
4866+
4867+
if (jsexpr->result_coercion->expr== (Node*)placeholder)
4868+
jsexpr->result_coercion->expr=NULL;
4869+
}
48364870
break;
48374871
}
48384872

‎src/backend/utils/adt/ruleutils.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9306,9 +9306,10 @@ get_rule_expr(Node *node, deparse_context *context,
93069306
}
93079307
}
93089308

9309-
if (jexpr->op!=IS_JSON_EXISTS)
9309+
if (jexpr->op!=IS_JSON_EXISTS||
9310+
jexpr->returning->typid!=BOOLOID)
93109311
get_json_returning(jexpr->returning,context->buf,
9311-
jexpr->op!=IS_JSON_VALUE);
9312+
jexpr->op==IS_JSON_QUERY);
93129313

93139314
get_json_expr_options(jexpr,context,
93149315
jexpr->op==IS_JSON_EXISTS ?

‎src/test/regress/expected/jsonb_sqljson.out

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,57 @@ SELECT JSON_EXISTS(jsonb '1', '$.a > 2' ERROR ON ERROR);
140140
t
141141
(1 row)
142142

143+
-- extension: RETURNING clause
144+
SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING bool);
145+
json_exists
146+
-------------
147+
t
148+
(1 row)
149+
150+
SELECT JSON_EXISTS(jsonb '1', '$[1]' RETURNING bool);
151+
json_exists
152+
-------------
153+
f
154+
(1 row)
155+
156+
SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING int);
157+
json_exists
158+
-------------
159+
1
160+
(1 row)
161+
162+
SELECT JSON_EXISTS(jsonb '1', '$[1]' RETURNING int);
163+
json_exists
164+
-------------
165+
0
166+
(1 row)
167+
168+
SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING text);
169+
json_exists
170+
-------------
171+
true
172+
(1 row)
173+
174+
SELECT JSON_EXISTS(jsonb '1', '$[1]' RETURNING text);
175+
json_exists
176+
-------------
177+
false
178+
(1 row)
179+
180+
SELECT JSON_EXISTS(jsonb '1', 'strict $[1]' RETURNING text FALSE ON ERROR);
181+
json_exists
182+
-------------
183+
false
184+
(1 row)
185+
186+
SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING jsonb);
187+
ERROR: cannot cast type boolean to jsonb
188+
LINE 1: SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING jsonb);
189+
^
190+
SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING float4);
191+
ERROR: cannot cast type boolean to real
192+
LINE 1: SELECT JSON_EXISTS(jsonb '1', '$[0]' RETURNING float4);
193+
^
143194
-- JSON_VALUE
144195
SELECT JSON_VALUE(NULL::jsonb, '$');
145196
json_value
@@ -866,6 +917,8 @@ CREATE TABLE test_jsonb_constraints (
866917
CHECK (JSON_QUERY(js::jsonb, '$.a' WITH CONDITIONAL WRAPPER EMPTY OBJECT ON ERROR) < jsonb '[10]')
867918
CONSTRAINT test_jsonb_constraint5
868919
CHECK (JSON_QUERY(js::jsonb, '$.a' RETURNING char(5) OMIT QUOTES EMPTY ARRAY ON EMPTY) > 'a' COLLATE "C")
920+
CONSTRAINT test_jsonb_constraint6
921+
CHECK (JSON_EXISTS(js::jsonb, 'strict $.a' RETURNING int TRUE ON ERROR) < 2)
869922
);
870923
\d test_jsonb_constraints
871924
Table "public.test_jsonb_constraints"
@@ -880,6 +933,7 @@ Check constraints:
880933
"test_jsonb_constraint3" CHECK (JSON_VALUE(js::jsonb, '$."a"' RETURNING integer DEFAULT ('12'::text || i)::integer ON EMPTY ERROR ON ERROR) > i)
881934
"test_jsonb_constraint4" CHECK (JSON_QUERY(js::jsonb, '$."a"' RETURNING jsonb WITH CONDITIONAL WRAPPER EMPTY OBJECT ON ERROR) < '[10]'::jsonb)
882935
"test_jsonb_constraint5" CHECK (JSON_QUERY(js::jsonb, '$."a"' RETURNING character(5) OMIT QUOTES EMPTY ARRAY ON EMPTY) > ('a'::bpchar COLLATE "C"))
936+
"test_jsonb_constraint6" CHECK (JSON_EXISTS(js::jsonb, 'strict $."a"' RETURNING integer TRUE ON ERROR) < 2)
883937

884938
SELECT check_clause
885939
FROM information_schema.check_constraints
@@ -891,7 +945,8 @@ WHERE constraint_name LIKE 'test_jsonb_constraint%';
891945
((JSON_VALUE((js)::jsonb, '$."a"' RETURNING integer DEFAULT (('12'::text || i))::integer ON EMPTY ERROR ON ERROR) > i))
892946
((JSON_QUERY((js)::jsonb, '$."a"' RETURNING jsonb WITH CONDITIONAL WRAPPER EMPTY OBJECT ON ERROR) < '[10]'::jsonb))
893947
((JSON_QUERY((js)::jsonb, '$."a"' RETURNING character(5) OMIT QUOTES EMPTY ARRAY ON EMPTY) > ('a'::bpchar COLLATE "C")))
894-
(5 rows)
948+
((JSON_EXISTS((js)::jsonb, 'strict $."a"' RETURNING integer TRUE ON ERROR) < 2))
949+
(6 rows)
895950

896951
SELECT pg_get_expr(adbin, adrelid) FROM pg_attrdef WHERE adrelid = 'test_jsonb_constraints'::regclass;
897952
pg_get_expr

‎src/test/regress/sql/jsonb_sqljson.sql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,18 @@ SELECT JSON_EXISTS(jsonb '{"a": 1, "b": 2}', '$.* ? (@ > $x && @ < $y)' PASSING
3232
SELECT JSON_EXISTS(jsonb'1','$ > 2');
3333
SELECT JSON_EXISTS(jsonb'1','$.a > 2' ERRORON ERROR);
3434

35+
-- extension: RETURNING clause
36+
SELECT JSON_EXISTS(jsonb'1','$[0]' RETURNING bool);
37+
SELECT JSON_EXISTS(jsonb'1','$[1]' RETURNING bool);
38+
SELECT JSON_EXISTS(jsonb'1','$[0]' RETURNINGint);
39+
SELECT JSON_EXISTS(jsonb'1','$[1]' RETURNINGint);
40+
SELECT JSON_EXISTS(jsonb'1','$[0]' RETURNINGtext);
41+
SELECT JSON_EXISTS(jsonb'1','$[1]' RETURNINGtext);
42+
SELECT JSON_EXISTS(jsonb'1','strict $[1]' RETURNINGtext FALSEON ERROR);
43+
SELECT JSON_EXISTS(jsonb'1','$[0]' RETURNING jsonb);
44+
SELECT JSON_EXISTS(jsonb'1','$[0]' RETURNING float4);
45+
46+
3547
-- JSON_VALUE
3648

3749
SELECT JSON_VALUE(NULL::jsonb,'$');
@@ -258,6 +270,8 @@ CREATE TABLE test_jsonb_constraints (
258270
CHECK (JSON_QUERY(js::jsonb,'$.a' WITH CONDITIONAL WRAPPER EMPTY OBJECTON ERROR)< jsonb'[10]')
259271
CONSTRAINT test_jsonb_constraint5
260272
CHECK (JSON_QUERY(js::jsonb,'$.a' RETURNINGchar(5) OMIT QUOTES EMPTY ARRAYON EMPTY)>'a' COLLATE"C")
273+
CONSTRAINT test_jsonb_constraint6
274+
CHECK (JSON_EXISTS(js::jsonb,'strict $.a' RETURNINGint TRUEON ERROR)<2)
261275
);
262276

263277
\d test_jsonb_constraints

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp