/* * ExecutorStart hook: start up tracking if needed */ static void pgss_ExecutorStart(QueryDesc *queryDesc, int eflags) { if (prev_ExecutorStart) prev_ExecutorStart(queryDesc, eflags); else standard_ExecutorStart(queryDesc, eflags); if (pgss_enabled()) { /* * Set up to track total elapsed time in ExecutorRun. Make sure the * space is allocated in the per-query context so it will go away at * ExecutorEnd. */ if (queryDesc->totaltime == NULL) { MemoryContext oldcxt; oldcxt = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt); queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL); MemoryContextSwitchTo(oldcxt); } } }
/* * ExecutorStart hook: start up logging if needed */ static void explain_ExecutorStart(QueryDesc *queryDesc, int eflags) { /* decide */ collect = collecting_enabled(); if (collect) { gettimeofday(&start_time, NULL); } if (prev_ExecutorStart) prev_ExecutorStart(queryDesc, eflags); else standard_ExecutorStart(queryDesc, eflags); /* Enable the histogram whenever the histogram is dynamic or (bins>0). */ if (collect) { /* * Set up to track total elapsed time in ExecutorRun. Make sure the * space is allocated in the per-query context so it will go away at * ExecutorEnd. */ if (queryDesc->totaltime == NULL) { MemoryContext oldcxt; oldcxt = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt); queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL); MemoryContextSwitchTo(oldcxt); } } }
static void collectLocalMemoryStats(QueryDesc *queryDesc, int eflags) { BackendMemoryStat *myStat; MemoryContextIteratorState state; if (prev_ExecutorStart) prev_ExecutorStart(queryDesc, eflags); else standard_ExecutorStart(queryDesc, eflags); if (MyBackendProcNo < 0) { on_proc_exit(cleanupMyStat, 0); MyBackendProcNo = MyProc->pgprocno; Assert(MyBackendProcNo >= 0); } if (checkTick() == false) return; Assert(MyBackendProcNo < PROCARRAY_MAXPROCS); myStat = NthBMS(MyBackendProcNo); /* * do not wait if reader currently locks our slot */ if (LWLockConditionalAcquire(myStat->lock, LW_EXCLUSIVE) == false) return; myStat->pid = MyProc->pid; myStat->nContext = 0; state.context = TopMemoryContext; state.level = 0; /* * walk through all memory context and fill stat table in shared memory */ do { MemoryContextStat *mcs = myStat->stats + myStat->nContext; int namelen = strlen(state.context->name); if (namelen > NAMEDATALEN - 1) namelen = NAMEDATALEN - 1; memcpy(mcs->name.data, state.context->name, namelen); mcs->name.data[namelen] = '\0'; mcs->level = state.level; getMemoryContextStat(state.context, &mcs->stat); myStat->nContext++; iterateMemoryContext(&state); } while (state.context && myStat->nContext < N_MC_STAT); LWLockRelease(myStat->lock); }
static void grab_ExecutorStart(QueryDesc * queryDesc, int eflags) { if (prev_ExecutorStart) prev_ExecutorStart(queryDesc, eflags); else standard_ExecutorStart(queryDesc, eflags); if (queryDesc->totaltime == NULL) { MemoryContext oldcxt; oldcxt = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt); queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL); MemoryContextSwitchTo(oldcxt); } }
/* * ExecutorStart hook: start up logging if needed */ static void explain_ExecutorStart(QueryDesc *queryDesc, int eflags) { /* * For rate sampling, randomly choose top-level statement. Either all * nested statements will be explained or none will. */ if (auto_explain_log_min_duration >= 0 && nesting_level == 0) current_query_sampled = (random() < auto_explain_sample_rate * MAX_RANDOM_VALUE); if (auto_explain_enabled() && current_query_sampled) { /* Enable per-node instrumentation iff log_analyze is required. */ if (auto_explain_log_analyze && (eflags & EXEC_FLAG_EXPLAIN_ONLY) == 0) { if (auto_explain_log_timing) queryDesc->instrument_options |= INSTRUMENT_TIMER; else queryDesc->instrument_options |= INSTRUMENT_ROWS; if (auto_explain_log_buffers) queryDesc->instrument_options |= INSTRUMENT_BUFFERS; } } if (prev_ExecutorStart) prev_ExecutorStart(queryDesc, eflags); else standard_ExecutorStart(queryDesc, eflags); if (auto_explain_enabled() && current_query_sampled) { /* * Set up to track total elapsed time in ExecutorRun. Make sure the * space is allocated in the per-query context so it will go away at * ExecutorEnd. */ if (queryDesc->totaltime == NULL) { MemoryContext oldcxt; oldcxt = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt); queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL); MemoryContextSwitchTo(oldcxt); } } }
/* * ExecutorStart hook: start up logging if needed */ static void explain_ExecutorStart(QueryDesc *queryDesc, int eflags) { if (auto_explain_enabled()) { /* Enable per-node instrumentation iff log_analyze is required. */ if (auto_explain_log_analyze && (eflags & EXEC_FLAG_EXPLAIN_ONLY) == 0) { if (auto_explain_log_timing) queryDesc->instrument_options |= INSTRUMENT_TIMER; else queryDesc->instrument_options |= INSTRUMENT_ROWS; if (auto_explain_log_buffers) queryDesc->instrument_options |= INSTRUMENT_BUFFERS; } } if (prev_ExecutorStart) prev_ExecutorStart(queryDesc, eflags); else standard_ExecutorStart(queryDesc, eflags); if (auto_explain_enabled()) { /* * Set up to track total elapsed time in ExecutorRun. Make sure the * space is allocated in the per-query context so it will go away at * ExecutorEnd. */ if (queryDesc->totaltime == NULL) { MemoryContext oldcxt; oldcxt = MemoryContextSwitchTo(queryDesc->estate->es_query_cxt); queryDesc->totaltime = InstrAlloc(1, INSTRUMENT_ALL); MemoryContextSwitchTo(oldcxt); } } }
/* * PgPaxosExecutorStart blocks until the table is ready to read. */ static void PgPaxosExecutorStart(QueryDesc *queryDesc, int eflags) { PlannedStmt *plannedStmt = queryDesc->plannedstmt; List *rangeTableList = plannedStmt->rtable; CmdType commandType = queryDesc->operation; if (IsPgPaxosActive() && HasPaxosTable(rangeTableList)) { char *sqlQuery = (char *) queryDesc->sourceText; char *groupId = NULL; bool topLevel = true; /* disallow transactions during paxos commands */ PreventTransactionChain(topLevel, "paxos commands"); groupId = DeterminePaxosGroup(rangeTableList); if (commandType == CMD_INSERT || commandType == CMD_UPDATE || commandType == CMD_DELETE) { PrepareConsistentWrite(groupId, sqlQuery); } else { PrepareConsistentRead(groupId); } queryDesc->snapshot->curcid = GetCurrentCommandId(false); } /* call into the standard executor start, or hook if set */ if (PreviousExecutorStartHook != NULL) { PreviousExecutorStartHook(queryDesc, eflags); } else { standard_ExecutorStart(queryDesc, eflags); } }
/* * multi_ExecutorStart is a hook called at at the beginning of any execution * of any query plan. * * If a distributed relation is the target of the query, perform some validity * checks. If a legal statement, start the distributed execution. After that * the to-be-executed query is replaced with the portion executing solely on * the master. */ void multi_ExecutorStart(QueryDesc *queryDesc, int eflags) { PlannedStmt *planStatement = queryDesc->plannedstmt; if (HasCitusToplevelNode(planStatement)) { MultiPlan *multiPlan = GetMultiPlan(planStatement); MultiExecutorType executorType = MULTI_EXECUTOR_INVALID_FIRST; Job *workerJob = multiPlan->workerJob; ExecCheckRTPerms(planStatement->rtable, true); executorType = JobExecutorType(multiPlan); if (executorType == MULTI_EXECUTOR_ROUTER) { Task *task = NULL; List *taskList = workerJob->taskList; TupleDesc tupleDescriptor = ExecCleanTypeFromTL( planStatement->planTree->targetlist, false); List *dependendJobList PG_USED_FOR_ASSERTS_ONLY = workerJob->dependedJobList; /* router executor can only execute distributed plans with a single task */ Assert(list_length(taskList) == 1); Assert(dependendJobList == NIL); task = (Task *) linitial(taskList); /* we need to set tupleDesc in executorStart */ queryDesc->tupDesc = tupleDescriptor; /* drop into the router executor */ RouterExecutorStart(queryDesc, eflags, task); } else { PlannedStmt *masterSelectPlan = MasterNodeSelectPlan(multiPlan); CreateStmt *masterCreateStmt = MasterNodeCreateStatement(multiPlan); List *masterCopyStmtList = MasterNodeCopyStatementList(multiPlan); RangeTblEntry *masterRangeTableEntry = NULL; StringInfo jobDirectoryName = NULL; /* * We create a directory on the master node to keep task execution results. * We also register this directory for automatic cleanup on portal delete. */ jobDirectoryName = JobDirectoryName(workerJob->jobId); CreateDirectory(jobDirectoryName); ResourceOwnerEnlargeJobDirectories(CurrentResourceOwner); ResourceOwnerRememberJobDirectory(CurrentResourceOwner, workerJob->jobId); /* pick distributed executor to use */ if (eflags & EXEC_FLAG_EXPLAIN_ONLY) { /* skip distributed query execution for EXPLAIN commands */ } else if (executorType == MULTI_EXECUTOR_REAL_TIME) { MultiRealTimeExecute(workerJob); } else if (executorType == MULTI_EXECUTOR_TASK_TRACKER) { MultiTaskTrackerExecute(workerJob); } /* then create the result relation */ ProcessUtility((Node *) masterCreateStmt, "(temp table creation)", PROCESS_UTILITY_QUERY, NULL, None_Receiver, NULL); /* make the temporary table visible */ CommandCounterIncrement(); if (!(eflags & EXEC_FLAG_EXPLAIN_ONLY)) { CopyQueryResults(masterCopyStmtList); } /* * Update the QueryDesc's snapshot so it sees the table. That's not * particularly pretty, but we don't have much of a choice. One might * think we could unregister the snapshot, push a new active one, * update it, register it, and be happy. That only works if it's only * registered once though... */ queryDesc->snapshot->curcid = GetCurrentCommandId(false); /* * Set the OID of the RTE used in the master select statement to point * to the now created (and filled) temporary table. The target * relation's oid is only known now. */ masterRangeTableEntry = (RangeTblEntry *) linitial(masterSelectPlan->rtable); masterRangeTableEntry->relid = RelnameGetRelid(masterRangeTableEntry->eref->aliasname); /* * Replace to-be-run query with the master select query. As the * planned statement is now replaced we can't call GetMultiPlan() in * the later hooks, so we set a flag marking this as a distributed * statement running on the master. That e.g. allows us to drop the * temp table later. * * We copy the original statement's queryId, to allow * pg_stat_statements and similar extension to associate the * statement with the toplevel statement. */ masterSelectPlan->queryId = queryDesc->plannedstmt->queryId; queryDesc->plannedstmt = masterSelectPlan; eflags |= EXEC_FLAG_CITUS_MASTER_SELECT; } } /* if the execution is not done for router executor, drop into standard executor */ if (queryDesc->estate == NULL || !(queryDesc->estate->es_top_eflags & EXEC_FLAG_CITUS_ROUTER_EXECUTOR)) { standard_ExecutorStart(queryDesc, eflags); } }