* exec_check_rw_parameter --- can we pass expanded object as read/write param? * * If we have an assignment like "x := array_append(x, foo)" in which the * top-level function is trusted not to corrupt its argument in case of an * error, then when x has an expanded object as value, it is safe to pass the * value as a read/write pointer and let the function modify the value * in-place. * * T
| 8109 | * shakier in the general case. |
| 8110 | */ |
| 8111 | static void |
| 8112 | exec_check_rw_parameter(PLpgSQL_expr *expr) |
| 8113 | { |
| 8114 | int target_dno; |
| 8115 | Oid funcid; |
| 8116 | List *fargs; |
| 8117 | ListCell *lc; |
| 8118 | |
| 8119 | /* Assume unsafe */ |
| 8120 | expr->expr_rw_param = NULL; |
| 8121 | |
| 8122 | /* Done if expression isn't an assignment source */ |
| 8123 | target_dno = expr->target_param; |
| 8124 | if (target_dno < 0) |
| 8125 | return; |
| 8126 | |
| 8127 | /* |
| 8128 | * If target variable isn't referenced by expression, no need to look |
| 8129 | * further. |
| 8130 | */ |
| 8131 | if (!bms_is_member(target_dno, expr->paramnos)) |
| 8132 | return; |
| 8133 | |
| 8134 | /* Shouldn't be here for non-simple expression */ |
| 8135 | Assert(expr->expr_simple_expr != NULL); |
| 8136 | |
| 8137 | /* |
| 8138 | * Top level of expression must be a simple FuncExpr, OpExpr, or |
| 8139 | * SubscriptingRef, else we can't optimize. |
| 8140 | */ |
| 8141 | if (IsA(expr->expr_simple_expr, FuncExpr)) |
| 8142 | { |
| 8143 | FuncExpr *fexpr = (FuncExpr *) expr->expr_simple_expr; |
| 8144 | |
| 8145 | funcid = fexpr->funcid; |
| 8146 | fargs = fexpr->args; |
| 8147 | } |
| 8148 | else if (IsA(expr->expr_simple_expr, OpExpr)) |
| 8149 | { |
| 8150 | OpExpr *opexpr = (OpExpr *) expr->expr_simple_expr; |
| 8151 | |
| 8152 | funcid = opexpr->opfuncid; |
| 8153 | fargs = opexpr->args; |
| 8154 | } |
| 8155 | else if (IsA(expr->expr_simple_expr, SubscriptingRef)) |
| 8156 | { |
| 8157 | SubscriptingRef *sbsref = (SubscriptingRef *) expr->expr_simple_expr; |
| 8158 | |
| 8159 | /* We only trust standard varlena arrays to be safe */ |
| 8160 | if (get_typsubscript(sbsref->refcontainertype, NULL) != |
| 8161 | F_ARRAY_SUBSCRIPT_HANDLER) |
| 8162 | return; |
| 8163 | |
| 8164 | /* We can optimize the refexpr if it's the target, otherwise not */ |
| 8165 | if (sbsref->refexpr && IsA(sbsref->refexpr, Param)) |
| 8166 | { |
| 8167 | Param *param = (Param *) sbsref->refexpr; |
| 8168 |
no test coverage detected