Header And Logo

PostgreSQL
| The world's most advanced open source database.

Functions | Variables

pquery.h File Reference

#include "nodes/parsenodes.h"
#include "utils/portal.h"
Include dependency graph for pquery.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

PortalStrategy ChoosePortalStrategy (List *stmts)
ListFetchPortalTargetList (Portal portal)
ListFetchStatementTargetList (Node *stmt)
void PortalStart (Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)
void PortalSetResultFormat (Portal portal, int nFormats, int16 *formats)
bool PortalRun (Portal portal, long count, bool isTopLevel, DestReceiver *dest, DestReceiver *altdest, char *completionTag)
long PortalRunFetch (Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)

Variables

PGDLLIMPORT Portal ActivePortal

Function Documentation

PortalStrategy ChoosePortalStrategy ( List stmts  ) 

Definition at line 241 of file pquery.c.

References PlannedStmt::canSetTag, Query::canSetTag, CMD_SELECT, CMD_UTILITY, PlannedStmt::commandType, Query::commandType, PlannedStmt::hasModifyingCTE, Query::hasModifyingCTE, PlannedStmt::hasReturning, IsA, lfirst, linitial, list_length(), NIL, NULL, PORTAL_UTIL_SELECT, Query::returningList, UtilityReturnsTuples(), PlannedStmt::utilityStmt, and Query::utilityStmt.

Referenced by PlanCacheComputeResultDesc(), and PortalStart().

{
    int         nSetTag;
    ListCell   *lc;

    /*
     * PORTAL_ONE_SELECT and PORTAL_UTIL_SELECT need only consider the
     * single-statement case, since there are no rewrite rules that can add
     * auxiliary queries to a SELECT or a utility command. PORTAL_ONE_MOD_WITH
     * likewise allows only one top-level statement.
     */
    if (list_length(stmts) == 1)
    {
        Node       *stmt = (Node *) linitial(stmts);

        if (IsA(stmt, Query))
        {
            Query      *query = (Query *) stmt;

            if (query->canSetTag)
            {
                if (query->commandType == CMD_SELECT &&
                    query->utilityStmt == NULL)
                {
                    if (query->hasModifyingCTE)
                        return PORTAL_ONE_MOD_WITH;
                    else
                        return PORTAL_ONE_SELECT;
                }
                if (query->commandType == CMD_UTILITY &&
                    query->utilityStmt != NULL)
                {
                    if (UtilityReturnsTuples(query->utilityStmt))
                        return PORTAL_UTIL_SELECT;
                    /* it can't be ONE_RETURNING, so give up */
                    return PORTAL_MULTI_QUERY;
                }
            }
        }
        else if (IsA(stmt, PlannedStmt))
        {
            PlannedStmt *pstmt = (PlannedStmt *) stmt;

            if (pstmt->canSetTag)
            {
                if (pstmt->commandType == CMD_SELECT &&
                    pstmt->utilityStmt == NULL)
                {
                    if (pstmt->hasModifyingCTE)
                        return PORTAL_ONE_MOD_WITH;
                    else
                        return PORTAL_ONE_SELECT;
                }
            }
        }
        else
        {
            /* must be a utility command; assume it's canSetTag */
            if (UtilityReturnsTuples(stmt))
                return PORTAL_UTIL_SELECT;
            /* it can't be ONE_RETURNING, so give up */
            return PORTAL_MULTI_QUERY;
        }
    }

    /*
     * PORTAL_ONE_RETURNING has to allow auxiliary queries added by rewrite.
     * Choose PORTAL_ONE_RETURNING if there is exactly one canSetTag query and
     * it has a RETURNING list.
     */
    nSetTag = 0;
    foreach(lc, stmts)
    {
        Node       *stmt = (Node *) lfirst(lc);

        if (IsA(stmt, Query))
        {
            Query      *query = (Query *) stmt;

            if (query->canSetTag)
            {
                if (++nSetTag > 1)
                    return PORTAL_MULTI_QUERY;  /* no need to look further */
                if (query->returningList == NIL)
                    return PORTAL_MULTI_QUERY;  /* no need to look further */
            }
        }
        else if (IsA(stmt, PlannedStmt))
        {
            PlannedStmt *pstmt = (PlannedStmt *) stmt;

            if (pstmt->canSetTag)
            {
                if (++nSetTag > 1)
                    return PORTAL_MULTI_QUERY;  /* no need to look further */
                if (!pstmt->hasReturning)
                    return PORTAL_MULTI_QUERY;  /* no need to look further */
            }
        }
        /* otherwise, utility command, assumed not canSetTag */
    }
    if (nSetTag == 1)
        return PORTAL_ONE_RETURNING;

    /* Else, it's the general case... */
    return PORTAL_MULTI_QUERY;
}

List* FetchPortalTargetList ( Portal  portal  ) 

Definition at line 357 of file pquery.c.

References FetchStatementTargetList(), PORTAL_MULTI_QUERY, PortalGetPrimaryStmt, and PortalData::strategy.

Referenced by exec_describe_portal_message(), FetchStatementTargetList(), and printtup_startup().

{
    /* no point in looking if we determined it doesn't return tuples */
    if (portal->strategy == PORTAL_MULTI_QUERY)
        return NIL;
    /* get the primary statement and find out what it returns */
    return FetchStatementTargetList(PortalGetPrimaryStmt(portal));
}

List* FetchStatementTargetList ( Node stmt  ) 

Definition at line 379 of file pquery.c.

References Assert, CMD_SELECT, CMD_UTILITY, PlannedStmt::commandType, Query::commandType, FetchPortalTargetList(), FetchPreparedStatement(), FetchPreparedStatementTargetList(), GetPortalByName(), PlannedStmt::hasReturning, IsA, FetchStmt::ismove, ExecuteStmt::name, NULL, PlannedStmt::planTree, PortalIsValid, FetchStmt::portalname, Query::returningList, Plan::targetlist, Query::targetList, PlannedStmt::utilityStmt, and Query::utilityStmt.

Referenced by CachedPlanGetTargetList(), and FetchPortalTargetList().

{
    if (stmt == NULL)
        return NIL;
    if (IsA(stmt, Query))
    {
        Query      *query = (Query *) stmt;

        if (query->commandType == CMD_UTILITY &&
            query->utilityStmt != NULL)
        {
            /* transfer attention to utility statement */
            stmt = query->utilityStmt;
        }
        else
        {
            if (query->commandType == CMD_SELECT &&
                query->utilityStmt == NULL)
                return query->targetList;
            if (query->returningList)
                return query->returningList;
            return NIL;
        }
    }
    if (IsA(stmt, PlannedStmt))
    {
        PlannedStmt *pstmt = (PlannedStmt *) stmt;

        if (pstmt->commandType == CMD_SELECT &&
            pstmt->utilityStmt == NULL)
            return pstmt->planTree->targetlist;
        if (pstmt->hasReturning)
            return pstmt->planTree->targetlist;
        return NIL;
    }
    if (IsA(stmt, FetchStmt))
    {
        FetchStmt  *fstmt = (FetchStmt *) stmt;
        Portal      subportal;

        Assert(!fstmt->ismove);
        subportal = GetPortalByName(fstmt->portalname);
        Assert(PortalIsValid(subportal));
        return FetchPortalTargetList(subportal);
    }
    if (IsA(stmt, ExecuteStmt))
    {
        ExecuteStmt *estmt = (ExecuteStmt *) stmt;
        PreparedStatement *entry;

        entry = FetchPreparedStatement(estmt->name, true);
        return FetchPreparedStatementTargetList(entry);
    }
    return NIL;
}

bool PortalRun ( Portal  portal,
long  count,
bool  isTopLevel,
DestReceiver dest,
DestReceiver altdest,
char *  completionTag 
)

Definition at line 705 of file pquery.c.

References AssertArg, PortalData::atEnd, PortalData::commandTag, COMPLETION_TAG_BUFSIZE, CurrentMemoryContext, CurrentResourceOwner, DEBUG3, elog, ereport, errcode(), errmsg(), ERROR, FillPortalStore(), PortalData::holdStore, log_executor_stats, MarkPortalDone(), MarkPortalFailed(), MemoryContextSwitchTo(), PortalData::name, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PORTAL_MULTI_QUERY, PORTAL_ONE_MOD_WITH, PORTAL_ONE_RETURNING, PORTAL_ONE_SELECT, PORTAL_READY, PORTAL_UTIL_SELECT, PortalContext, PortalGetHeapMemory, PortalIsValid, PortalRunMulti(), PortalRunSelect(), ResetUsage(), PortalData::resowner, ShowUsage(), snprintf(), PortalData::status, PortalData::strategy, TopTransactionContext, and TopTransactionResourceOwner.

Referenced by exec_execute_message(), exec_simple_query(), and ExecuteQuery().

{
    bool        result;
    uint32      nprocessed;
    ResourceOwner saveTopTransactionResourceOwner;
    MemoryContext saveTopTransactionContext;
    Portal      saveActivePortal;
    ResourceOwner saveResourceOwner;
    MemoryContext savePortalContext;
    MemoryContext saveMemoryContext;

    AssertArg(PortalIsValid(portal));

    TRACE_POSTGRESQL_QUERY_EXECUTE_START();

    /* Initialize completion tag to empty string */
    if (completionTag)
        completionTag[0] = '\0';

    if (log_executor_stats && portal->strategy != PORTAL_MULTI_QUERY)
    {
        elog(DEBUG3, "PortalRun");
        /* PORTAL_MULTI_QUERY logs its own stats per query */
        ResetUsage();
    }

    /*
     * Check for improper portal use, and mark portal active.
     */
    if (portal->status != PORTAL_READY)
        ereport(ERROR,
                (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                 errmsg("portal \"%s\" cannot be run", portal->name)));
    portal->status = PORTAL_ACTIVE;

    /*
     * Set up global portal context pointers.
     *
     * We have to play a special game here to support utility commands like
     * VACUUM and CLUSTER, which internally start and commit transactions.
     * When we are called to execute such a command, CurrentResourceOwner will
     * be pointing to the TopTransactionResourceOwner --- which will be
     * destroyed and replaced in the course of the internal commit and
     * restart.  So we need to be prepared to restore it as pointing to the
     * exit-time TopTransactionResourceOwner.  (Ain't that ugly?  This idea of
     * internally starting whole new transactions is not good.)
     * CurrentMemoryContext has a similar problem, but the other pointers we
     * save here will be NULL or pointing to longer-lived objects.
     */
    saveTopTransactionResourceOwner = TopTransactionResourceOwner;
    saveTopTransactionContext = TopTransactionContext;
    saveActivePortal = ActivePortal;
    saveResourceOwner = CurrentResourceOwner;
    savePortalContext = PortalContext;
    saveMemoryContext = CurrentMemoryContext;
    PG_TRY();
    {
        ActivePortal = portal;
        CurrentResourceOwner = portal->resowner;
        PortalContext = PortalGetHeapMemory(portal);

        MemoryContextSwitchTo(PortalContext);

        switch (portal->strategy)
        {
            case PORTAL_ONE_SELECT:
            case PORTAL_ONE_RETURNING:
            case PORTAL_ONE_MOD_WITH:
            case PORTAL_UTIL_SELECT:

                /*
                 * If we have not yet run the command, do so, storing its
                 * results in the portal's tuplestore.  But we don't do that
                 * for the PORTAL_ONE_SELECT case.
                 */
                if (portal->strategy != PORTAL_ONE_SELECT && !portal->holdStore)
                    FillPortalStore(portal, isTopLevel);

                /*
                 * Now fetch desired portion of results.
                 */
                nprocessed = PortalRunSelect(portal, true, count, dest);

                /*
                 * If the portal result contains a command tag and the caller
                 * gave us a pointer to store it, copy it. Patch the "SELECT"
                 * tag to also provide the rowcount.
                 */
                if (completionTag && portal->commandTag)
                {
                    if (strcmp(portal->commandTag, "SELECT") == 0)
                        snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
                                 "SELECT %u", nprocessed);
                    else
                        strcpy(completionTag, portal->commandTag);
                }

                /* Mark portal not active */
                portal->status = PORTAL_READY;

                /*
                 * Since it's a forward fetch, say DONE iff atEnd is now true.
                 */
                result = portal->atEnd;
                break;

            case PORTAL_MULTI_QUERY:
                PortalRunMulti(portal, isTopLevel,
                               dest, altdest, completionTag);

                /* Prevent portal's commands from being re-executed */
                MarkPortalDone(portal);

                /* Always complete at end of RunMulti */
                result = true;
                break;

            default:
                elog(ERROR, "unrecognized portal strategy: %d",
                     (int) portal->strategy);
                result = false; /* keep compiler quiet */
                break;
        }
    }
    PG_CATCH();
    {
        /* Uncaught error while executing portal: mark it dead */
        MarkPortalFailed(portal);

        /* Restore global vars and propagate error */
        if (saveMemoryContext == saveTopTransactionContext)
            MemoryContextSwitchTo(TopTransactionContext);
        else
            MemoryContextSwitchTo(saveMemoryContext);
        ActivePortal = saveActivePortal;
        if (saveResourceOwner == saveTopTransactionResourceOwner)
            CurrentResourceOwner = TopTransactionResourceOwner;
        else
            CurrentResourceOwner = saveResourceOwner;
        PortalContext = savePortalContext;

        PG_RE_THROW();
    }
    PG_END_TRY();

    if (saveMemoryContext == saveTopTransactionContext)
        MemoryContextSwitchTo(TopTransactionContext);
    else
        MemoryContextSwitchTo(saveMemoryContext);
    ActivePortal = saveActivePortal;
    if (saveResourceOwner == saveTopTransactionResourceOwner)
        CurrentResourceOwner = TopTransactionResourceOwner;
    else
        CurrentResourceOwner = saveResourceOwner;
    PortalContext = savePortalContext;

    if (log_executor_stats && portal->strategy != PORTAL_MULTI_QUERY)
        ShowUsage("EXECUTOR STATISTICS");

    TRACE_POSTGRESQL_QUERY_EXECUTE_DONE();

    return result;
}

long PortalRunFetch ( Portal  portal,
FetchDirection  fdirection,
long  count,
DestReceiver dest 
)

Definition at line 1383 of file pquery.c.

References AssertArg, CurrentResourceOwner, DoPortalRunFetch(), elog, ereport, errcode(), errmsg(), ERROR, FillPortalStore(), PortalData::holdStore, MarkPortalFailed(), MemoryContextSwitchTo(), PortalData::name, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PORTAL_ONE_MOD_WITH, PORTAL_ONE_RETURNING, PORTAL_ONE_SELECT, PORTAL_READY, PORTAL_UTIL_SELECT, PortalContext, PortalGetHeapMemory, PortalIsValid, PortalData::resowner, PortalData::status, and PortalData::strategy.

Referenced by _SPI_cursor_operation(), and PerformPortalFetch().

{
    long        result;
    Portal      saveActivePortal;
    ResourceOwner saveResourceOwner;
    MemoryContext savePortalContext;
    MemoryContext oldContext;

    AssertArg(PortalIsValid(portal));

    /*
     * Check for improper portal use, and mark portal active.
     */
    if (portal->status != PORTAL_READY)
        ereport(ERROR,
                (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
                 errmsg("portal \"%s\" cannot be run", portal->name)));
    portal->status = PORTAL_ACTIVE;

    /*
     * Set up global portal context pointers.
     */
    saveActivePortal = ActivePortal;
    saveResourceOwner = CurrentResourceOwner;
    savePortalContext = PortalContext;
    PG_TRY();
    {
        ActivePortal = portal;
        CurrentResourceOwner = portal->resowner;
        PortalContext = PortalGetHeapMemory(portal);

        oldContext = MemoryContextSwitchTo(PortalContext);

        switch (portal->strategy)
        {
            case PORTAL_ONE_SELECT:
                result = DoPortalRunFetch(portal, fdirection, count, dest);
                break;

            case PORTAL_ONE_RETURNING:
            case PORTAL_ONE_MOD_WITH:
            case PORTAL_UTIL_SELECT:

                /*
                 * If we have not yet run the command, do so, storing its
                 * results in the portal's tuplestore.
                 */
                if (!portal->holdStore)
                    FillPortalStore(portal, false /* isTopLevel */ );

                /*
                 * Now fetch desired portion of results.
                 */
                result = DoPortalRunFetch(portal, fdirection, count, dest);
                break;

            default:
                elog(ERROR, "unsupported portal strategy");
                result = 0;     /* keep compiler quiet */
                break;
        }
    }
    PG_CATCH();
    {
        /* Uncaught error while executing portal: mark it dead */
        MarkPortalFailed(portal);

        /* Restore global vars and propagate error */
        ActivePortal = saveActivePortal;
        CurrentResourceOwner = saveResourceOwner;
        PortalContext = savePortalContext;

        PG_RE_THROW();
    }
    PG_END_TRY();

    MemoryContextSwitchTo(oldContext);

    /* Mark portal not active */
    portal->status = PORTAL_READY;

    ActivePortal = saveActivePortal;
    CurrentResourceOwner = saveResourceOwner;
    PortalContext = savePortalContext;

    return result;
}

void PortalSetResultFormat ( Portal  portal,
int  nFormats,
int16 formats 
)

Definition at line 643 of file pquery.c.

References ereport, errcode(), errmsg(), ERROR, PortalData::formats, i, MemoryContextAlloc(), tupleDesc::natts, NULL, PortalGetHeapMemory, and PortalData::tupDesc.

Referenced by exec_bind_message(), and exec_simple_query().

{
    int         natts;
    int         i;

    /* Do nothing if portal won't return tuples */
    if (portal->tupDesc == NULL)
        return;
    natts = portal->tupDesc->natts;
    portal->formats = (int16 *)
        MemoryContextAlloc(PortalGetHeapMemory(portal),
                           natts * sizeof(int16));
    if (nFormats > 1)
    {
        /* format specified for each column */
        if (nFormats != natts)
            ereport(ERROR,
                    (errcode(ERRCODE_PROTOCOL_VIOLATION),
                     errmsg("bind message has %d result formats but query has %d columns",
                            nFormats, natts)));
        memcpy(portal->formats, formats, natts * sizeof(int16));
    }
    else if (nFormats > 0)
    {
        /* single format specified, use for all columns */
        int16       format1 = formats[0];

        for (i = 0; i < natts; i++)
            portal->formats[i] = format1;
    }
    else
    {
        /* use default format for all columns */
        for (i = 0; i < natts; i++)
            portal->formats[i] = 0;
    }
}

void PortalStart ( Portal  portal,
ParamListInfo  params,
int  eflags,
Snapshot  snapshot 
)

Definition at line 459 of file pquery.c.

References Assert, AssertArg, AssertState, PortalData::atEnd, PortalData::atStart, ChoosePortalStrategy(), CreateQueryDesc(), CurrentResourceOwner, CURSOR_OPT_SCROLL, PortalData::cursorOptions, EXEC_FLAG_REWIND, ExecCleanTypeFromTL(), ExecutorStart(), GetActiveSnapshot(), GetTransactionSnapshot(), InvalidSnapshot, IsA, linitial, MarkPortalFailed(), MemoryContextSwitchTo(), None_Receiver, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PlannedStmt::planTree, PopActiveSnapshot(), PORTAL_DEFINED, PORTAL_MULTI_QUERY, PORTAL_ONE_MOD_WITH, PORTAL_ONE_RETURNING, PORTAL_ONE_SELECT, PORTAL_UTIL_SELECT, PortalContext, PortalGetHeapMemory, PortalGetPrimaryStmt, PortalIsValid, PortalData::portalParams, PortalData::portalPos, PortalData::posOverflow, PushActiveSnapshot(), PortalData::queryDesc, PortalData::resowner, PortalData::sourceText, PortalData::status, PortalData::stmts, PortalData::strategy, Plan::targetlist, QueryDesc::tupDesc, PortalData::tupDesc, and UtilityTupleDescriptor().

Referenced by exec_bind_message(), exec_simple_query(), ExecuteQuery(), PerformCursorOpen(), and SPI_cursor_open_internal().

{
    Portal      saveActivePortal;
    ResourceOwner saveResourceOwner;
    MemoryContext savePortalContext;
    MemoryContext oldContext;
    QueryDesc  *queryDesc;
    int         myeflags;

    AssertArg(PortalIsValid(portal));
    AssertState(portal->status == PORTAL_DEFINED);

    /*
     * Set up global portal context pointers.
     */
    saveActivePortal = ActivePortal;
    saveResourceOwner = CurrentResourceOwner;
    savePortalContext = PortalContext;
    PG_TRY();
    {
        ActivePortal = portal;
        CurrentResourceOwner = portal->resowner;
        PortalContext = PortalGetHeapMemory(portal);

        oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));

        /* Must remember portal param list, if any */
        portal->portalParams = params;

        /*
         * Determine the portal execution strategy
         */
        portal->strategy = ChoosePortalStrategy(portal->stmts);

        /*
         * Fire her up according to the strategy
         */
        switch (portal->strategy)
        {
            case PORTAL_ONE_SELECT:

                /* Must set snapshot before starting executor. */
                if (snapshot)
                    PushActiveSnapshot(snapshot);
                else
                    PushActiveSnapshot(GetTransactionSnapshot());

                /*
                 * Create QueryDesc in portal's context; for the moment, set
                 * the destination to DestNone.
                 */
                queryDesc = CreateQueryDesc((PlannedStmt *) linitial(portal->stmts),
                                            portal->sourceText,
                                            GetActiveSnapshot(),
                                            InvalidSnapshot,
                                            None_Receiver,
                                            params,
                                            0);

                /*
                 * If it's a scrollable cursor, executor needs to support
                 * REWIND and backwards scan, as well as whatever the caller
                 * might've asked for.
                 */
                if (portal->cursorOptions & CURSOR_OPT_SCROLL)
                    myeflags = eflags | EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD;
                else
                    myeflags = eflags;

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

                /*
                 * This tells PortalCleanup to shut down the executor
                 */
                portal->queryDesc = queryDesc;

                /*
                 * Remember tuple descriptor (computed by ExecutorStart)
                 */
                portal->tupDesc = queryDesc->tupDesc;

                /*
                 * Reset cursor position data to "start of query"
                 */
                portal->atStart = true;
                portal->atEnd = false;  /* allow fetches */
                portal->portalPos = 0;
                portal->posOverflow = false;

                PopActiveSnapshot();
                break;

            case PORTAL_ONE_RETURNING:
            case PORTAL_ONE_MOD_WITH:

                /*
                 * We don't start the executor until we are told to run the
                 * portal.  We do need to set up the result tupdesc.
                 */
                {
                    PlannedStmt *pstmt;

                    pstmt = (PlannedStmt *) PortalGetPrimaryStmt(portal);
                    Assert(IsA(pstmt, PlannedStmt));
                    portal->tupDesc =
                        ExecCleanTypeFromTL(pstmt->planTree->targetlist,
                                            false);
                }

                /*
                 * Reset cursor position data to "start of query"
                 */
                portal->atStart = true;
                portal->atEnd = false;  /* allow fetches */
                portal->portalPos = 0;
                portal->posOverflow = false;
                break;

            case PORTAL_UTIL_SELECT:

                /*
                 * We don't set snapshot here, because PortalRunUtility will
                 * take care of it if needed.
                 */
                {
                    Node       *ustmt = PortalGetPrimaryStmt(portal);

                    Assert(!IsA(ustmt, PlannedStmt));
                    portal->tupDesc = UtilityTupleDescriptor(ustmt);
                }

                /*
                 * Reset cursor position data to "start of query"
                 */
                portal->atStart = true;
                portal->atEnd = false;  /* allow fetches */
                portal->portalPos = 0;
                portal->posOverflow = false;
                break;

            case PORTAL_MULTI_QUERY:
                /* Need do nothing now */
                portal->tupDesc = NULL;
                break;
        }
    }
    PG_CATCH();
    {
        /* Uncaught error while executing portal: mark it dead */
        MarkPortalFailed(portal);

        /* Restore global vars and propagate error */
        ActivePortal = saveActivePortal;
        CurrentResourceOwner = saveResourceOwner;
        PortalContext = savePortalContext;

        PG_RE_THROW();
    }
    PG_END_TRY();

    MemoryContextSwitchTo(oldContext);

    ActivePortal = saveActivePortal;
    CurrentResourceOwner = saveResourceOwner;
    PortalContext = savePortalContext;

    portal->status = PORTAL_READY;
}


Variable Documentation

PGDLLIMPORT Portal ActivePortal

Definition at line 33 of file pquery.c.

Referenced by function_parse_error_transpose(), and PersistHoldablePortal().