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
static bool contain_subplans_walker (Node * node , void * context );
95
96
static bool contain_mutable_functions_walker (Node * node , void * context );
96
97
static bool contain_volatile_functions_walker (Node * node , void * context );
98
+ static bool contain_volatile_functions_not_nextval_walker (Node * node , void * context );
97
99
static bool contain_nonstrict_functions_walker (Node * node , void * context );
98
100
static bool contain_leaky_functions_walker (Node * node , void * context );
99
101
static Relids find_nonnullable_rels_walker (Node * node , bool top_level );
@@ -971,6 +973,19 @@ contain_volatile_functions(Node *clause)
971
973
return contain_volatile_functions_walker (clause , NULL );
972
974
}
973
975
976
+ bool
977
+ contain_volatile_functions_not_nextval (Node * clause )
978
+ {
979
+ return contain_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
static bool
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
+ static bool
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
+ else if (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
+ else if (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
+ else if (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
+ else if (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
+ else if (IsA (node , CoerceViaIO ))
1148
+ {
1149
+ CoerceViaIO * expr = (CoerceViaIO * ) node ;
1150
+ Oid iofunc ;
1151
+ Oid typioparam ;
1152
+ bool typisvarlena ;
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
+ else if (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
+ else if (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
+ return expression_tree_walker (node , contain_volatile_functions_not_nextval_walker ,
1189
+ context );
1190
+ }
1075
1191
1076
1192
/*****************************************************************************
1077
1193
* Check clauses for nonstrict functions
0 commit comments