|
45 | 45 | #include"utils/acl.h"
|
46 | 46 | #include"utils/builtins.h"
|
47 | 47 | #include"utils/datum.h"
|
| 48 | +#include"utils/fmgroids.h" |
48 | 49 | #include"utils/lsyscache.h"
|
49 | 50 | #include"utils/memutils.h"
|
50 | 51 | #include"utils/syscache.h"
|
@@ -94,6 +95,7 @@ static bool expression_returns_set_rows_walker(Node *node, double *count);
|
94 | 95 | staticboolcontain_subplans_walker(Node*node,void*context);
|
95 | 96 | staticboolcontain_mutable_functions_walker(Node*node,void*context);
|
96 | 97 | staticboolcontain_volatile_functions_walker(Node*node,void*context);
|
| 98 | +staticboolcontain_volatile_functions_not_nextval_walker(Node*node,void*context); |
97 | 99 | staticboolcontain_nonstrict_functions_walker(Node*node,void*context);
|
98 | 100 | staticboolcontain_leaky_functions_walker(Node*node,void*context);
|
99 | 101 | staticRelidsfind_nonnullable_rels_walker(Node*node,booltop_level);
|
@@ -971,6 +973,19 @@ contain_volatile_functions(Node *clause)
|
971 | 973 | returncontain_volatile_functions_walker(clause,NULL);
|
972 | 974 | }
|
973 | 975 |
|
| 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 | + */ |
974 | 989 | staticbool
|
975 | 990 | contain_volatile_functions_walker(Node*node,void*context)
|
976 | 991 | {
|
@@ -1072,6 +1087,107 @@ contain_volatile_functions_walker(Node *node, void *context)
|
1072 | 1087 | context);
|
1073 | 1088 | }
|
1074 | 1089 |
|
| 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 | +} |
1075 | 1191 |
|
1076 | 1192 | /*****************************************************************************
|
1077 | 1193 | *Check clauses for nonstrict functions
|
|