Beispiel #1
0
/*
 * Executor state preparation for evaluation of constraint expressions,
 * indexes and triggers.
 *
 * This is based on similar code in copy.c
 */
static EState *
create_estate_for_relation(LogicalRepRelMapEntry *rel)
{
	EState	   *estate;
	ResultRelInfo *resultRelInfo;
	RangeTblEntry *rte;

	estate = CreateExecutorState();

	rte = makeNode(RangeTblEntry);
	rte->rtekind = RTE_RELATION;
	rte->relid = RelationGetRelid(rel->localrel);
	rte->relkind = rel->localrel->rd_rel->relkind;
	estate->es_range_table = list_make1(rte);

	resultRelInfo = makeNode(ResultRelInfo);
	InitResultRelInfo(resultRelInfo, rel->localrel, 1, NULL, 0);

	estate->es_result_relations = resultRelInfo;
	estate->es_num_result_relations = 1;
	estate->es_result_relation_info = resultRelInfo;

	estate->es_output_cid = GetCurrentCommandId(true);

	/* Triggers might need a slot */
	if (resultRelInfo->ri_TrigDesc)
		estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);

	/* Prepare to catch AFTER triggers. */
	AfterTriggerBeginQuery();

	return estate;
}
Beispiel #2
0
/*
 * ProcessQuery
 *		Execute a single plannable query within a PORTAL_MULTI_QUERY
 *		or PORTAL_ONE_RETURNING portal
 *
 *	parsetree: the query tree
 *	plan: the plan tree for the query
 *	params: any parameters needed
 *	dest: where to send results
 *	completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
 *		in which to store a command completion status string.
 *
 * completionTag may be NULL if caller doesn't want a status string.
 *
 * Must be called in a memory context that will be reset or deleted on
 * error; otherwise the executor's memory usage will be leaked.
 */
static void
ProcessQuery(Query *parsetree,
             Plan *plan,
             ParamListInfo params,
             DestReceiver *dest,
             char *completionTag)
{
    int			operation = parsetree->commandType;
    QueryDesc  *queryDesc;

    ereport(DEBUG3,
            (errmsg_internal("ProcessQuery")));

    /*
     * Must always set snapshot for plannable queries.	Note we assume that
     * caller will take care of restoring ActiveSnapshot on exit/error.
     */
    ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());

    /*
     * Create the QueryDesc object
     */
    queryDesc = CreateQueryDesc(parsetree, plan,
                                ActiveSnapshot, InvalidSnapshot,
                                dest, params, false);

    /*
     * Set up to collect AFTER triggers
     */
    AfterTriggerBeginQuery();

    /*
     * Call ExecutorStart to prepare the plan for execution
     */
    ExecutorStart(queryDesc, 0);

    /*
     * Run the plan to completion.
     */
    ExecutorRun(queryDesc, ForwardScanDirection, 0L);

    /*
     * Build command completion status string, if caller wants one.
     */
    if (completionTag)
    {
        Oid			lastOid;

        switch (operation)
        {
        case CMD_SELECT:
            strcpy(completionTag, "SELECT");
            break;
        case CMD_INSERT:
            if (queryDesc->estate->es_processed == 1)
                lastOid = queryDesc->estate->es_lastoid;
            else
                lastOid = InvalidOid;
            snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
                     "INSERT %u %u", lastOid, queryDesc->estate->es_processed);
            break;
        case CMD_UPDATE:
            snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
                     "UPDATE %u", queryDesc->estate->es_processed);
            break;
        case CMD_DELETE:
            snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
                     "DELETE %u", queryDesc->estate->es_processed);
            break;
        default:
            strcpy(completionTag, "???");
            break;
        }
    }

    /* Now take care of any queued AFTER triggers */
    AfterTriggerEndQuery(queryDesc->estate);

    /*
     * Now, we close down all the scans and free allocated resources.
     */
    ExecutorEnd(queryDesc);

    FreeQueryDesc(queryDesc);

    FreeSnapshot(ActiveSnapshot);
    ActiveSnapshot = NULL;
}
/*
 * ProcessQuery
 *		Execute a single plannable query within a PORTAL_MULTI_QUERY
 *		or PORTAL_ONE_RETURNING portal
 *
 *	plan: the plan tree for the query
 *	sourceText: the source text of the query
 *	params: any parameters needed
 *	dest: where to send results
 *	completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
 *		in which to store a command completion status string.
 *
 * completionTag may be NULL if caller doesn't want a status string.
 *
 * Must be called in a memory context that will be reset or deleted on
 * error; otherwise the executor's memory usage will be leaked.
 */
static void
ProcessQuery(PlannedStmt *plan,
			 const char *sourceText,
			 ParamListInfo params,
			 DestReceiver *dest,
			 char *completionTag)
{
	QueryDesc  *queryDesc;

	elog(DEBUG3, "ProcessQuery");

	/*
	 * Must always set a snapshot for plannable queries.
	 */
	PushActiveSnapshot(GetTransactionSnapshot());

	/*
	 * Create the QueryDesc object
	 */
	queryDesc = CreateQueryDesc(plan, sourceText,
								GetActiveSnapshot(), InvalidSnapshot,
								dest, params, 0);

	/*
	 * Set up to collect AFTER triggers
	 */
	AfterTriggerBeginQuery();

	/*
	 * Call ExecutorStart to prepare the plan for execution
	 */
	ExecutorStart(queryDesc, 0);

	/*
	 * Run the plan to completion.
	 */
	ExecutorRun(queryDesc, ForwardScanDirection, 0L);

	/*
	 * Build command completion status string, if caller wants one.
	 */
	if (completionTag)
	{
		Oid			lastOid;

		switch (queryDesc->operation)
		{
			case CMD_SELECT:
				snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
						 "SELECT %u", queryDesc->estate->es_processed);
				break;
			case CMD_INSERT:
				if (queryDesc->estate->es_processed == 1)
					lastOid = queryDesc->estate->es_lastoid;
				else
					lastOid = InvalidOid;
				snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
				   "INSERT %u %u", lastOid, queryDesc->estate->es_processed);
				break;
			case CMD_UPDATE:
				snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
						 "UPDATE %u", queryDesc->estate->es_processed);
				break;
			case CMD_DELETE:
				snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
						 "DELETE %u", queryDesc->estate->es_processed);
				break;
			default:
				strcpy(completionTag, "???");
				break;
		}
	}

	/* Now take care of any queued AFTER triggers */
	AfterTriggerEndQuery(queryDesc->estate);

	PopActiveSnapshot();

	/*
	 * Now, we close down all the scans and free allocated resources.
	 */
	ExecutorEnd(queryDesc);

	FreeQueryDesc(queryDesc);
}