* ExecuteQuery --- implement the 'EXECUTE' utility statement. * * This code also supports CREATE TABLE ... AS EXECUTE. That case is * indicated by passing a non-null intoClause. The DestReceiver is already * set up correctly for CREATE TABLE AS, but we still have to make a few * other adjustments here. */
| 190 | * other adjustments here. |
| 191 | */ |
| 192 | void |
| 193 | ExecuteQuery(ParseState *pstate, |
| 194 | ExecuteStmt *stmt, IntoClause *intoClause, |
| 195 | ParamListInfo params, |
| 196 | DestReceiver *dest, QueryCompletion *qc) |
| 197 | { |
| 198 | PreparedStatement *entry; |
| 199 | CachedPlan *cplan; |
| 200 | List *plan_list; |
| 201 | ParamListInfo paramLI = NULL; |
| 202 | EState *estate = NULL; |
| 203 | Portal portal; |
| 204 | char *query_string; |
| 205 | int eflags; |
| 206 | long count; |
| 207 | |
| 208 | /* Look it up in the hash table */ |
| 209 | entry = FetchPreparedStatement(stmt->name, true); |
| 210 | |
| 211 | /* Shouldn't find a non-fixed-result cached plan */ |
| 212 | if (!entry->plansource->fixed_result) |
| 213 | elog(ERROR, "EXECUTE does not support variable-result cached plans"); |
| 214 | |
| 215 | /* Evaluate parameters, if any */ |
| 216 | if (entry->plansource->num_params > 0) |
| 217 | { |
| 218 | /* |
| 219 | * Need an EState to evaluate parameters; must not delete it till end |
| 220 | * of query, in case parameters are pass-by-reference. Note that the |
| 221 | * passed-in "params" could possibly be referenced in the parameter |
| 222 | * expressions. |
| 223 | */ |
| 224 | estate = CreateExecutorState(); |
| 225 | estate->es_param_list_info = params; |
| 226 | paramLI = EvaluateParams(pstate, entry, stmt->params, estate); |
| 227 | } |
| 228 | |
| 229 | /* Create a new portal to run the query in */ |
| 230 | portal = CreateNewPortal(); |
| 231 | /* Don't display the portal in pg_cursors, it is for internal use only */ |
| 232 | portal->visible = false; |
| 233 | |
| 234 | /* Copy the plan's saved query string into the portal's memory */ |
| 235 | query_string = MemoryContextStrdup(portal->portalContext, |
| 236 | entry->plansource->query_string); |
| 237 | |
| 238 | /* Replan if needed, and increment plan refcount for portal */ |
| 239 | cplan = GetCachedPlan(entry->plansource, paramLI, NULL, NULL, intoClause); |
| 240 | plan_list = cplan->stmt_list; |
| 241 | |
| 242 | /* |
| 243 | * DO NOT add any logic that could possibly throw an error between |
| 244 | * GetCachedPlan and PortalDefineQuery, or you'll leak the plan refcount. |
| 245 | */ |
| 246 | PortalDefineQuery(portal, |
| 247 | NULL, |
| 248 | query_string, |
| 249 | entry->plansource->sourceTag, |
no test coverage detected