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

Commitc863327

Browse files
author
Nikita Glukhov
committed
Add subtransactions for JsonExpr execution
1 parent7247297 commitc863327

File tree

5 files changed

+96
-1
lines changed

5 files changed

+96
-1
lines changed

‎src/backend/executor/execExprInterp.c‎

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
#include"postgres.h"
5858

5959
#include"access/heaptoast.h"
60+
#include"access/xact.h"
61+
#include"catalog/pg_proc.h"
6062
#include"catalog/pg_type.h"
6163
#include"commands/sequence.h"
6264
#include"executor/execExpr.h"
@@ -79,6 +81,7 @@
7981
#include"utils/jsonpath.h"
8082
#include"utils/lsyscache.h"
8183
#include"utils/memutils.h"
84+
#include"utils/resowner.h"
8285
#include"utils/timestamp.h"
8386
#include"utils/typcache.h"
8487
#include"utils/xml.h"
@@ -4816,6 +4819,12 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
48164819
returnres;
48174820
}
48184821

4822+
bool
4823+
ExecEvalJsonNeedsSubTransaction(JsonExpr*jsexpr)
4824+
{
4825+
returnjsexpr->on_error->btype!=JSON_BEHAVIOR_ERROR;
4826+
}
4827+
48194828
/* ----------------------------------------------------------------
48204829
*ExecEvalJson
48214830
* ----------------------------------------------------------------
@@ -4855,20 +4864,34 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
48554864
var->evaluated= false;
48564865
}
48574866

4858-
if (jexpr->on_error->btype==JSON_BEHAVIOR_ERROR)
4867+
if (!ExecEvalJsonNeedsSubTransaction(jexpr))
48594868
{
48604869
/* No need to use PG_TRY/PG_CATCH with subtransactions. */
48614870
res=ExecEvalJsonExpr(state,op,econtext,jexpr,path,item,
48624871
op->resnull);
48634872
}
48644873
else
48654874
{
4875+
/*
4876+
* We should catch exceptions of category ERRCODE_DATA_EXCEPTION and
4877+
* execute corresponding ON ERROR behavior.
4878+
*/
48664879
MemoryContextoldcontext=CurrentMemoryContext;
4880+
ResourceOwneroldowner=CurrentResourceOwner;
4881+
4882+
BeginInternalSubTransaction(NULL);
4883+
/* Want to execute expressions inside function's memory context */
4884+
MemoryContextSwitchTo(oldcontext);
48674885

48684886
PG_TRY();
48694887
{
48704888
res=ExecEvalJsonExpr(state,op,econtext,jexpr,path,item,
48714889
op->resnull);
4890+
4891+
/* Commit the inner transaction, return to outer xact context */
4892+
ReleaseCurrentSubTransaction();
4893+
MemoryContextSwitchTo(oldcontext);
4894+
CurrentResourceOwner=oldowner;
48724895
}
48734896
PG_CATCH();
48744897
{
@@ -4879,6 +4902,11 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
48794902
edata=CopyErrorData();
48804903
FlushErrorState();
48814904

4905+
/* Abort the inner transaction */
4906+
RollbackAndReleaseCurrentSubTransaction();
4907+
MemoryContextSwitchTo(oldcontext);
4908+
CurrentResourceOwner=oldowner;
4909+
48824910
if (ERRCODE_TO_CATEGORY(edata->sqlerrcode)!=ERRCODE_DATA_EXCEPTION)
48834911
ReThrowError(edata);
48844912

‎src/backend/optimizer/util/clauses.c‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include"catalog/pg_type.h"
2929
#include"executor/executor.h"
3030
#include"executor/functions.h"
31+
#include"executor/execExpr.h"
3132
#include"funcapi.h"
3233
#include"miscadmin.h"
3334
#include"nodes/makefuncs.h"
@@ -1092,6 +1093,18 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
10921093
context,0);
10931094
}
10941095

1096+
/* JsonExpr is parallel-unsafe if subtransactions can be used. */
1097+
elseif (IsA(node,JsonExpr))
1098+
{
1099+
JsonExpr*jsexpr= (JsonExpr*)node;
1100+
1101+
if (ExecEvalJsonNeedsSubTransaction(jsexpr))
1102+
{
1103+
context->max_hazard=PROPARALLEL_UNSAFE;
1104+
return true;
1105+
}
1106+
}
1107+
10951108
/* Recurse to check arguments */
10961109
returnexpression_tree_walker(node,
10971110
max_parallel_hazard_walker,

‎src/include/executor/execExpr.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,7 @@ extern Datum ExecPrepareJsonItemCoercion(struct JsonbValue *item,
814814
JsonReturning*returning,
815815
structJsonCoercionsState*coercions,
816816
structJsonCoercionState**pjcstate);
817+
externboolExecEvalJsonNeedsSubTransaction(JsonExpr*jsexpr);
817818

818819
externvoidExecAggInitGroup(AggState*aggstate,AggStatePerTranspertrans,AggStatePerGrouppergroup,
819820
ExprContext*aggcontext);

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,3 +909,40 @@ SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a' WITH WRAPPER);
909909
-- Should fail (invalid path)
910910
SELECT JSON_QUERY(jsonb '{"a": 123}', 'error' || ' ' || 'error');
911911
ERROR: syntax error, unexpected IDENT_P at or near " " of jsonpath input
912+
-- Test parallel JSON_VALUE()
913+
CREATE TABLE test_parallel_jsonb_value AS
914+
SELECT i::text::jsonb AS js
915+
FROM generate_series(1, 1000000) i;
916+
-- Should be non-parallel due to subtransactions
917+
EXPLAIN (COSTS OFF)
918+
SELECT sum(JSON_VALUE(js, '$' RETURNING numeric)) FROM test_parallel_jsonb_value;
919+
QUERY PLAN
920+
---------------------------------------------
921+
Aggregate
922+
-> Seq Scan on test_parallel_jsonb_value
923+
(2 rows)
924+
925+
SELECT sum(JSON_VALUE(js, '$' RETURNING numeric)) FROM test_parallel_jsonb_value;
926+
sum
927+
--------------
928+
500000500000
929+
(1 row)
930+
931+
-- Should be parallel
932+
EXPLAIN (COSTS OFF)
933+
SELECT sum(JSON_VALUE(js, '$' RETURNING numeric ERROR ON ERROR)) FROM test_parallel_jsonb_value;
934+
QUERY PLAN
935+
------------------------------------------------------------------
936+
Finalize Aggregate
937+
-> Gather
938+
Workers Planned: 2
939+
-> Partial Aggregate
940+
-> Parallel Seq Scan on test_parallel_jsonb_value
941+
(5 rows)
942+
943+
SELECT sum(JSON_VALUE(js, '$' RETURNING numeric ERROR ON ERROR)) FROM test_parallel_jsonb_value;
944+
sum
945+
--------------
946+
500000500000
947+
(1 row)
948+

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,19 @@ SELECT JSON_QUERY(jsonb '{"a": 123}', '$' || '.' || 'a');
274274
SELECT JSON_QUERY(jsonb'{"a": 123}','$'||'.'||'a' WITH WRAPPER);
275275
-- Should fail (invalid path)
276276
SELECT JSON_QUERY(jsonb'{"a": 123}','error'||''||'error');
277+
278+
-- Test parallel JSON_VALUE()
279+
CREATETABLEtest_parallel_jsonb_valueAS
280+
SELECT i::text::jsonbAS js
281+
FROM generate_series(1,1000000) i;
282+
283+
-- Should be non-parallel due to subtransactions
284+
EXPLAIN (COSTS OFF)
285+
SELECTsum(JSON_VALUE(js,'$' RETURNINGnumeric))FROM test_parallel_jsonb_value;
286+
SELECTsum(JSON_VALUE(js,'$' RETURNINGnumeric))FROM test_parallel_jsonb_value;
287+
288+
-- Should be parallel
289+
EXPLAIN (COSTS OFF)
290+
SELECTsum(JSON_VALUE(js,'$' RETURNINGnumeric ERRORON ERROR))FROM test_parallel_jsonb_value;
291+
SELECTsum(JSON_VALUE(js,'$' RETURNINGnumeric ERRORON ERROR))FROM test_parallel_jsonb_value;
292+

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp