void CreateModel(CreateModelStmt *stmt,const char *queryString, DestReceiver *dest, char *completionTag) { List *query_list; List *planned_list; const char *commandTag; Portal portal; DestReceiver *tupledest; // create command Tag commandTag = CreateCommandTag(stmt->algorithmclause->trainingdata); // Rewrite the already analyzed Select query for the training data query_list = pg_rewrite_query((Query *)stmt->algorithmclause->trainingdata); // plan the query planned_list = pg_plan_queries(query_list,0,NULL); // results should be send to the ModelReceiver tupledest = CreateModelDestReceiver(stmt->modelname, (TargetEntry *)stmt->outputcolumn, stmt->timecolumns, ((Query *)stmt->algorithmclause->trainingdata)->jointree->quals, queryString,stmt->algorithmclause->algorithmname, ((AlgorithmClause *)copyObject(stmt->algorithmclause))->algorithmparameter, 0); // Create a new portal to run the query in portal = CreateNewPortal(); //Don't display the portal in pg_cursors, it is for internal use only portal->visible = false; PortalDefineQuery(portal, NULL, queryString, commandTag, planned_list, NULL); // Start the portal. No parameters here. PortalStart(portal, NULL, InvalidSnapshot); (void) PortalRun(portal, FETCH_ALL, false, tupledest, tupledest, completionTag); // Drop portal and receiver (*tupledest->rDestroy) (tupledest); PortalDrop(portal, false); }
/* * Implements the 'EXECUTE' utility statement. */ void ExecuteQuery(ExecuteStmt *stmt, ParamListInfo params, DestReceiver *dest, char *completionTag) { PreparedStatement *entry; char *query_string; List *query_list, *plan_list; MemoryContext qcontext; ParamListInfo paramLI = NULL; EState *estate = NULL; Portal portal; /* Look it up in the hash table */ entry = FetchPreparedStatement(stmt->name, true); query_string = entry->query_string; query_list = entry->query_list; plan_list = entry->plan_list; qcontext = entry->context; Assert(list_length(query_list) == list_length(plan_list)); /* Evaluate parameters, if any */ if (entry->argtype_list != NIL) { /* * Need an EState to evaluate parameters; must not delete it till end * of query, in case parameters are pass-by-reference. */ estate = CreateExecutorState(); estate->es_param_list_info = params; paramLI = EvaluateParams(estate, stmt->params, entry->argtype_list); } /* Create a new portal to run the query in */ portal = CreateNewPortal(); /* Don't display the portal in pg_cursors, it is for internal use only */ portal->visible = false; /* * For CREATE TABLE / AS EXECUTE, make a copy of the stored query so that * we can modify its destination (yech, but this has always been ugly). * For regular EXECUTE we can just use the stored query where it sits, * since the executor is read-only. */ if (stmt->into) { MemoryContext oldContext; Query *query; oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); if (query_string) query_string = pstrdup(query_string); query_list = copyObject(query_list); plan_list = copyObject(plan_list); qcontext = PortalGetHeapMemory(portal); if (list_length(query_list) != 1) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("prepared statement is not a SELECT"))); query = (Query *) linitial(query_list); if (query->commandType != CMD_SELECT) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("prepared statement is not a SELECT"))); query->into = copyObject(stmt->into); query->intoOptions = copyObject(stmt->intoOptions); query->intoOnCommit = stmt->into_on_commit; if (stmt->into_tbl_space) query->intoTableSpaceName = pstrdup(stmt->into_tbl_space); MemoryContextSwitchTo(oldContext); } PortalDefineQuery(portal, NULL, query_string, entry->commandTag, query_list, plan_list, qcontext); /* * Run the portal to completion. */ PortalStart(portal, paramLI, ActiveSnapshot); (void) PortalRun(portal, FETCH_ALL, dest, dest, completionTag); PortalDrop(portal, false); if (estate) FreeExecutorState(estate); /* No need to pfree other memory, MemoryContext will be reset */ }
/* * Implements the 'EXECUTE' utility statement. * * Note: this is one of very few places in the code that needs to deal with * two query strings at once. The passed-in queryString is that of the * EXECUTE, which we might need for error reporting while processing the * parameter expressions. The query_string that we copy from the plan * source is that of the original PREPARE. */ void ExecuteQuery(ExecuteStmt *stmt, const char *queryString, ParamListInfo params, DestReceiver *dest, char *completionTag) { PreparedStatement *entry; List *stmt_list; MemoryContext qcontext; ParamListInfo paramLI = NULL; EState *estate = NULL; Portal portal; /* Look it up in the hash table */ entry = FetchPreparedStatement(stmt->name, true); qcontext = entry->context; /* Evaluate parameters, if any */ if (entry->argtype_list != NIL) { /* * Need an EState to evaluate parameters; must not delete it till end * of query, in case parameters are pass-by-reference. */ estate = CreateExecutorState(); estate->es_param_list_info = params; paramLI = EvaluateParams(estate, stmt->params, entry->argtype_list); } /* Create a new portal to run the query in */ portal = CreateNewPortal(); /* Don't display the portal in pg_cursors, it is for internal use only */ portal->visible = false; /* Plan the query. If this is a CTAS, copy the "into" information into * the query so that we construct the plan correctly. Else the table * might not be created on the segments. (MPP-8135) */ { List *query_list = copyObject(entry->query_list); /* planner scribbles on query tree :( */ if ( stmt->into ) { Query *query = (Query*)linitial(query_list); Assert(IsA(query, Query) && query->intoClause == NULL); query->intoClause = copyObject(stmt->into); } stmt_list = pg_plan_queries(query_list, paramLI, false, QRL_ONCE); } /* * For CREATE TABLE / AS EXECUTE, make a copy of the stored query so that * we can modify its destination (yech, but this has always been ugly). * For regular EXECUTE we can just use the stored query where it sits, * since the executor is read-only. */ if (stmt->into) { MemoryContext oldContext; PlannedStmt *pstmt; if (list_length(stmt_list) != 1) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("prepared statement is not a SELECT"))); oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); stmt_list = copyObject(stmt_list); qcontext = PortalGetHeapMemory(portal); pstmt = (PlannedStmt *) linitial(stmt_list); pstmt->qdContext = qcontext; if (pstmt->commandType != CMD_SELECT) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("prepared statement is not a SELECT"), errOmitLocation(true))); pstmt->intoClause = copyObject(stmt->into); /* XXX Is it legitimate to assign a constant default policy without * even checking the relation? */ pstmt->intoPolicy = palloc0(sizeof(GpPolicy)- sizeof(pstmt->intoPolicy->attrs) + 255 * sizeof(pstmt->intoPolicy->attrs[0])); pstmt->intoPolicy->nattrs = 0; pstmt->intoPolicy->ptype = POLICYTYPE_PARTITIONED; pstmt->intoPolicy->bucketnum = GetRelOpt_bucket_num_fromRangeVar(stmt->into->rel, GetRandomDistPartitionNum()); MemoryContextSwitchTo(oldContext); } /* Copy the plan's saved query string into the portal's memory */ Assert(entry->query_string != NULL); char *query_string = MemoryContextStrdup(PortalGetHeapMemory(portal), entry->query_string); PortalDefineQuery(portal, NULL, query_string, entry->sourceTag, entry->commandTag, stmt_list, qcontext); create_filesystem_credentials(portal); /* * Run the portal to completion. */ PortalStart(portal, paramLI, ActiveSnapshot, savedSeqServerHost, savedSeqServerPort); (void) PortalRun(portal, FETCH_ALL, true, /* Effectively always top level. */ dest, dest, completionTag); PortalDrop(portal, false); if (estate) FreeExecutorState(estate); /* No need to pfree other memory, MemoryContext will be reset */ }
/* * SPI_cursor_open() * * Open a prepared SPI plan as a portal */ Portal SPI_cursor_open(const char *name, void *plan, Datum *Values, const char *Nulls, bool read_only) { _SPI_plan *spiplan = (_SPI_plan *) plan; List *qtlist = spiplan->qtlist; List *ptlist = spiplan->ptlist; Query *queryTree; Plan *planTree; ParamListInfo paramLI; Snapshot snapshot; MemoryContext oldcontext; Portal portal; int k; /* Ensure that the plan contains only one query */ if (list_length(ptlist) != 1 || list_length(qtlist) != 1) ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_DEFINITION), errmsg("cannot open multi-query plan as cursor"))); queryTree = (Query *) linitial((List *) linitial(qtlist)); planTree = (Plan *) linitial(ptlist); /* Must be a query that returns tuples */ switch (queryTree->commandType) { case CMD_SELECT: if (queryTree->into != NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_DEFINITION), errmsg("cannot open SELECT INTO query as cursor"))); break; case CMD_UTILITY: if (!UtilityReturnsTuples(queryTree->utilityStmt)) ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_DEFINITION), errmsg("cannot open non-SELECT query as cursor"))); break; default: ereport(ERROR, (errcode(ERRCODE_INVALID_CURSOR_DEFINITION), errmsg("cannot open non-SELECT query as cursor"))); break; } /* Reset SPI result */ SPI_processed = 0; SPI_tuptable = NULL; _SPI_current->processed = 0; _SPI_current->tuptable = NULL; /* Create the portal */ if (name == NULL || name[0] == '\0') { /* Use a random nonconflicting name */ portal = CreateNewPortal(); } else { /* In this path, error if portal of same name already exists */ portal = CreatePortal(name, false, false); } /* Switch to portals memory and copy the parsetree and plan to there */ oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); queryTree = copyObject(queryTree); planTree = copyObject(planTree); /* If the plan has parameters, set them up */ if (spiplan->nargs > 0) { paramLI = (ParamListInfo) palloc0((spiplan->nargs + 1) * sizeof(ParamListInfoData)); for (k = 0; k < spiplan->nargs; k++) { paramLI[k].kind = PARAM_NUM; paramLI[k].id = k + 1; paramLI[k].ptype = spiplan->argtypes[k]; paramLI[k].isnull = (Nulls && Nulls[k] == 'n'); if (paramLI[k].isnull) { /* nulls just copy */ paramLI[k].value = Values[k]; } else { /* pass-by-ref values must be copied into portal context */ int16 paramTypLen; bool paramTypByVal; get_typlenbyval(spiplan->argtypes[k], ¶mTypLen, ¶mTypByVal); paramLI[k].value = datumCopy(Values[k], paramTypByVal, paramTypLen); } } paramLI[k].kind = PARAM_INVALID; } else paramLI = NULL; /* * Set up the portal. */ PortalDefineQuery(portal, NULL, /* unfortunately don't have sourceText */ "SELECT", /* nor the raw parse tree... */ list_make1(queryTree), list_make1(planTree), PortalGetHeapMemory(portal)); MemoryContextSwitchTo(oldcontext); /* * Set up options for portal. */ portal->cursorOptions &= ~(CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL); if (planTree == NULL || ExecSupportsBackwardScan(planTree)) portal->cursorOptions |= CURSOR_OPT_SCROLL; else portal->cursorOptions |= CURSOR_OPT_NO_SCROLL; /* * Set up the snapshot to use. (PortalStart will do CopySnapshot, * so we skip that here.) */ if (read_only) snapshot = ActiveSnapshot; else { CommandCounterIncrement(); snapshot = GetTransactionSnapshot(); } /* * Start portal execution. */ PortalStart(portal, paramLI, snapshot); Assert(portal->strategy == PORTAL_ONE_SELECT || portal->strategy == PORTAL_UTIL_SELECT); /* Return the created portal */ return portal; }