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

Commit4d1e2ae

Browse files
Speed up COPY into tables with DEFAULT nextval()
Previously the presence of a nextval() prevented theuse of batch-mode COPY. This patch introduces aspecial case just for nextval() functions. In futurewe will introduce a general case solution forlabelling volatile functions as safe for use.
1 parent74a72ec commit4d1e2ae

File tree

3 files changed

+130
-2
lines changed

3 files changed

+130
-2
lines changed

‎src/backend/commands/copy.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2519,9 +2519,20 @@ BeginCopyFrom(Relation rel,
25192519
defmap[num_defaults]=attnum-1;
25202520
num_defaults++;
25212521

2522-
/* Check to see if we have any volatile expressions */
2522+
/*
2523+
* If a default expression looks at the table being loaded, then
2524+
* it could give the wrong answer when using multi-insert. Since
2525+
* database access can be dynamic this is hard to test for
2526+
* exactly, so we use the much wider test of whether the
2527+
* default expression is volatile. We allow for the special case
2528+
* of when the default expression is the nextval() of a sequence
2529+
* which in this specific case is known to be safe for use with
2530+
* the multi-insert optimisation. Hence we use this special case
2531+
* function checker rather than the standard check for
2532+
* contain_volatile_functions().
2533+
*/
25232534
if (!volatile_defexprs)
2524-
volatile_defexprs=contain_volatile_functions((Node*)defexpr);
2535+
volatile_defexprs=contain_volatile_functions_not_nextval((Node*)defexpr);
25252536
}
25262537
}
25272538
}

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

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include"utils/acl.h"
4646
#include"utils/builtins.h"
4747
#include"utils/datum.h"
48+
#include"utils/fmgroids.h"
4849
#include"utils/lsyscache.h"
4950
#include"utils/memutils.h"
5051
#include"utils/syscache.h"
@@ -94,6 +95,7 @@ static bool expression_returns_set_rows_walker(Node *node, double *count);
9495
staticboolcontain_subplans_walker(Node*node,void*context);
9596
staticboolcontain_mutable_functions_walker(Node*node,void*context);
9697
staticboolcontain_volatile_functions_walker(Node*node,void*context);
98+
staticboolcontain_volatile_functions_not_nextval_walker(Node*node,void*context);
9799
staticboolcontain_nonstrict_functions_walker(Node*node,void*context);
98100
staticboolcontain_leaky_functions_walker(Node*node,void*context);
99101
staticRelidsfind_nonnullable_rels_walker(Node*node,booltop_level);
@@ -971,6 +973,19 @@ contain_volatile_functions(Node *clause)
971973
returncontain_volatile_functions_walker(clause,NULL);
972974
}
973975

976+
bool
977+
contain_volatile_functions_not_nextval(Node*clause)
978+
{
979+
returncontain_volatile_functions_not_nextval_walker(clause,NULL);
980+
}
981+
982+
/*
983+
* General purpose code for checking expression volatility.
984+
*
985+
* Special purpose code for use in COPY is almost identical to this,
986+
* so any changes here may also be needed in other contain_volatile...
987+
* functions.
988+
*/
974989
staticbool
975990
contain_volatile_functions_walker(Node*node,void*context)
976991
{
@@ -1072,6 +1087,107 @@ contain_volatile_functions_walker(Node *node, void *context)
10721087
context);
10731088
}
10741089

1090+
/*
1091+
* Special purpose version of contain_volatile_functions for use in COPY
1092+
*/
1093+
staticbool
1094+
contain_volatile_functions_not_nextval_walker(Node*node,void*context)
1095+
{
1096+
if (node==NULL)
1097+
return false;
1098+
if (IsA(node,FuncExpr))
1099+
{
1100+
FuncExpr*expr= (FuncExpr*)node;
1101+
1102+
/*
1103+
* For this case only, we want to ignore the volatility of the
1104+
* nextval() function, since some callers want this.
1105+
*/
1106+
if (expr->funcid!=F_NEXTVAL_OID&&
1107+
func_volatile(expr->funcid)==PROVOLATILE_VOLATILE)
1108+
return true;
1109+
/* else fall through to check args */
1110+
}
1111+
elseif (IsA(node,OpExpr))
1112+
{
1113+
OpExpr*expr= (OpExpr*)node;
1114+
1115+
set_opfuncid(expr);
1116+
if (func_volatile(expr->opfuncid)==PROVOLATILE_VOLATILE)
1117+
return true;
1118+
/* else fall through to check args */
1119+
}
1120+
elseif (IsA(node,DistinctExpr))
1121+
{
1122+
DistinctExpr*expr= (DistinctExpr*)node;
1123+
1124+
set_opfuncid((OpExpr*)expr);/* rely on struct equivalence */
1125+
if (func_volatile(expr->opfuncid)==PROVOLATILE_VOLATILE)
1126+
return true;
1127+
/* else fall through to check args */
1128+
}
1129+
elseif (IsA(node,NullIfExpr))
1130+
{
1131+
NullIfExpr*expr= (NullIfExpr*)node;
1132+
1133+
set_opfuncid((OpExpr*)expr);/* rely on struct equivalence */
1134+
if (func_volatile(expr->opfuncid)==PROVOLATILE_VOLATILE)
1135+
return true;
1136+
/* else fall through to check args */
1137+
}
1138+
elseif (IsA(node,ScalarArrayOpExpr))
1139+
{
1140+
ScalarArrayOpExpr*expr= (ScalarArrayOpExpr*)node;
1141+
1142+
set_sa_opfuncid(expr);
1143+
if (func_volatile(expr->opfuncid)==PROVOLATILE_VOLATILE)
1144+
return true;
1145+
/* else fall through to check args */
1146+
}
1147+
elseif (IsA(node,CoerceViaIO))
1148+
{
1149+
CoerceViaIO*expr= (CoerceViaIO*)node;
1150+
Oidiofunc;
1151+
Oidtypioparam;
1152+
booltypisvarlena;
1153+
1154+
/* check the result type's input function */
1155+
getTypeInputInfo(expr->resulttype,
1156+
&iofunc,&typioparam);
1157+
if (func_volatile(iofunc)==PROVOLATILE_VOLATILE)
1158+
return true;
1159+
/* check the input type's output function */
1160+
getTypeOutputInfo(exprType((Node*)expr->arg),
1161+
&iofunc,&typisvarlena);
1162+
if (func_volatile(iofunc)==PROVOLATILE_VOLATILE)
1163+
return true;
1164+
/* else fall through to check args */
1165+
}
1166+
elseif (IsA(node,ArrayCoerceExpr))
1167+
{
1168+
ArrayCoerceExpr*expr= (ArrayCoerceExpr*)node;
1169+
1170+
if (OidIsValid(expr->elemfuncid)&&
1171+
func_volatile(expr->elemfuncid)==PROVOLATILE_VOLATILE)
1172+
return true;
1173+
/* else fall through to check args */
1174+
}
1175+
elseif (IsA(node,RowCompareExpr))
1176+
{
1177+
/* RowCompare probably can't have volatile ops, but check anyway */
1178+
RowCompareExpr*rcexpr= (RowCompareExpr*)node;
1179+
ListCell*opid;
1180+
1181+
foreach(opid,rcexpr->opnos)
1182+
{
1183+
if (op_volatile(lfirst_oid(opid))==PROVOLATILE_VOLATILE)
1184+
return true;
1185+
}
1186+
/* else fall through to check args */
1187+
}
1188+
returnexpression_tree_walker(node,contain_volatile_functions_not_nextval_walker,
1189+
context);
1190+
}
10751191

10761192
/*****************************************************************************
10771193
*Check clauses for nonstrict functions

‎src/include/optimizer/clauses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ extern bool contain_subplans(Node *clause);
6161

6262
externboolcontain_mutable_functions(Node*clause);
6363
externboolcontain_volatile_functions(Node*clause);
64+
externboolcontain_volatile_functions_not_nextval(Node*clause);
6465
externboolcontain_nonstrict_functions(Node*clause);
6566
externboolcontain_leaky_functions(Node*clause);
6667

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp