---------- * exec_stmt_execsql Execute an SQL statement (possibly with INTO). * * Note: some callers rely on this not touching stmt_mcontext. If it ever * needs to use that, fix those callers to push/pop stmt_mcontext. * ---------- */
| 4152 | * ---------- |
| 4153 | */ |
| 4154 | static int |
| 4155 | exec_stmt_execsql(PLpgSQL_execstate *estate, |
| 4156 | PLpgSQL_stmt_execsql *stmt) |
| 4157 | { |
| 4158 | ParamListInfo paramLI; |
| 4159 | long tcount; |
| 4160 | int rc; |
| 4161 | PLpgSQL_expr *expr = stmt->sqlstmt; |
| 4162 | int too_many_rows_level = 0; |
| 4163 | |
| 4164 | if (plpgsql_extra_errors & PLPGSQL_XCHECK_TOOMANYROWS) |
| 4165 | too_many_rows_level = ERROR; |
| 4166 | else if (plpgsql_extra_warnings & PLPGSQL_XCHECK_TOOMANYROWS) |
| 4167 | too_many_rows_level = WARNING; |
| 4168 | |
| 4169 | /* |
| 4170 | * On the first call for this statement generate the plan, and detect |
| 4171 | * whether the statement is INSERT/UPDATE/DELETE |
| 4172 | */ |
| 4173 | if (expr->plan == NULL) |
| 4174 | exec_prepare_plan(estate, expr, CURSOR_OPT_PARALLEL_OK); |
| 4175 | |
| 4176 | if (!stmt->mod_stmt_set) |
| 4177 | { |
| 4178 | ListCell *l; |
| 4179 | |
| 4180 | stmt->mod_stmt = false; |
| 4181 | foreach(l, SPI_plan_get_plan_sources(expr->plan)) |
| 4182 | { |
| 4183 | CachedPlanSource *plansource = (CachedPlanSource *) lfirst(l); |
| 4184 | |
| 4185 | /* |
| 4186 | * We could look at the raw_parse_tree, but it seems simpler to |
| 4187 | * check the command tag. Note we should *not* look at the Query |
| 4188 | * tree(s), since those are the result of rewriting and could have |
| 4189 | * been transmogrified into something else entirely. |
| 4190 | */ |
| 4191 | if (plansource->commandTag == CMDTAG_INSERT || |
| 4192 | plansource->commandTag == CMDTAG_UPDATE || |
| 4193 | plansource->commandTag == CMDTAG_DELETE) |
| 4194 | { |
| 4195 | stmt->mod_stmt = true; |
| 4196 | break; |
| 4197 | } |
| 4198 | } |
| 4199 | stmt->mod_stmt_set = true; |
| 4200 | } |
| 4201 | |
| 4202 | /* |
| 4203 | * Set up ParamListInfo to pass to executor |
| 4204 | */ |
| 4205 | paramLI = setup_param_list(estate, expr); |
| 4206 | |
| 4207 | /* |
| 4208 | * If we have INTO, then we only need one row back ... but if we have INTO |
| 4209 | * STRICT or extra check too_many_rows, ask for two rows, so that we can |
| 4210 | * verify the statement returns only one. INSERT/UPDATE/DELETE are always |
| 4211 | * treated strictly. Without INTO, just run the statement to completion |
no test coverage detected