Header And Logo

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

Functions

createas.h File Reference

#include "nodes/params.h"
#include "nodes/parsenodes.h"
#include "tcop/dest.h"
Include dependency graph for createas.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void ExecCreateTableAs (CreateTableAsStmt *stmt, const char *queryString, ParamListInfo params, char *completionTag)
int GetIntoRelEFlags (IntoClause *intoClause)
DestReceiverCreateIntoRelDestReceiver (IntoClause *intoClause)

Function Documentation

DestReceiver* CreateIntoRelDestReceiver ( IntoClause intoClause  ) 

Definition at line 205 of file createas.c.

References palloc0().

Referenced by CreateDestReceiver(), ExecCreateTableAs(), and ExplainOnePlan().

{
    DR_intorel *self = (DR_intorel *) palloc0(sizeof(DR_intorel));

    self->pub.receiveSlot = intorel_receive;
    self->pub.rStartup = intorel_startup;
    self->pub.rShutdown = intorel_shutdown;
    self->pub.rDestroy = intorel_destroy;
    self->pub.mydest = DestIntoRel;
    self->into = intoClause;
    /* other private fields will be set during intorel_startup */

    return (DestReceiver *) self;
}

void ExecCreateTableAs ( CreateTableAsStmt stmt,
const char *  queryString,
ParamListInfo  params,
char *  completionTag 
)

Definition at line 67 of file createas.c.

References Assert, CMD_SELECT, CMD_UTILITY, Query::commandType, COMPLETION_TAG_BUFSIZE, copyObject(), CreateIntoRelDestReceiver(), CreateQueryDesc(), elog, ERROR, ExecuteQuery(), ExecutorEnd(), ExecutorFinish(), ExecutorRun(), ExecutorStart(), FreeQueryDesc(), GetActiveSnapshot(), GetIntoRelEFlags(), CreateTableAsStmt::into, InvalidSnapshot, IsA, linitial, list_length(), pg_plan_query(), PopActiveSnapshot(), PushCopiedSnapshot(), CreateTableAsStmt::query, QueryRewrite(), snprintf(), UpdateActiveSnapshotCommandId(), and Query::utilityStmt.

Referenced by ProcessUtilitySlow().

{
    Query      *query = (Query *) stmt->query;
    IntoClause *into = stmt->into;
    DestReceiver *dest;
    List       *rewritten;
    PlannedStmt *plan;
    QueryDesc  *queryDesc;
    ScanDirection dir;

    /*
     * Create the tuple receiver object and insert info it will need
     */
    dest = CreateIntoRelDestReceiver(into);

    /*
     * The contained Query could be a SELECT, or an EXECUTE utility command.
     * If the latter, we just pass it off to ExecuteQuery.
     */
    Assert(IsA(query, Query));
    if (query->commandType == CMD_UTILITY &&
        IsA(query->utilityStmt, ExecuteStmt))
    {
        ExecuteStmt *estmt = (ExecuteStmt *) query->utilityStmt;

        ExecuteQuery(estmt, into, queryString, params, dest, completionTag);

        return;
    }
    Assert(query->commandType == CMD_SELECT);

    /*
     * Parse analysis was done already, but we still have to run the rule
     * rewriter.  We do not do AcquireRewriteLocks: we assume the query either
     * came straight from the parser, or suitable locks were acquired by
     * plancache.c.
     *
     * Because the rewriter and planner tend to scribble on the input, we make
     * a preliminary copy of the source querytree.  This prevents problems in
     * the case that CTAS is in a portal or plpgsql function and is executed
     * repeatedly.  (See also the same hack in EXPLAIN and PREPARE.)
     */
    rewritten = QueryRewrite((Query *) copyObject(query));

    /* SELECT should never rewrite to more or less than one SELECT query */
    if (list_length(rewritten) != 1)
        elog(ERROR, "unexpected rewrite result for CREATE TABLE AS SELECT");
    query = (Query *) linitial(rewritten);
    Assert(query->commandType == CMD_SELECT);

    /* plan the query */
    plan = pg_plan_query(query, 0, params);

    /*
     * Use a snapshot with an updated command ID to ensure this query sees
     * results of any previously executed queries.  (This could only matter if
     * the planner executed an allegedly-stable function that changed the
     * database contents, but let's do it anyway to be parallel to the EXPLAIN
     * code path.)
     */
    PushCopiedSnapshot(GetActiveSnapshot());
    UpdateActiveSnapshotCommandId();

    /* Create a QueryDesc, redirecting output to our tuple receiver */
    queryDesc = CreateQueryDesc(plan, queryString,
                                GetActiveSnapshot(), InvalidSnapshot,
                                dest, params, 0);

    /* call ExecutorStart to prepare the plan for execution */
    ExecutorStart(queryDesc, GetIntoRelEFlags(into));

    /*
     * Normally, we run the plan to completion; but if skipData is specified,
     * just do tuple receiver startup and shutdown.
     */
    if (into->skipData)
        dir = NoMovementScanDirection;
    else
        dir = ForwardScanDirection;

    /* run the plan */
    ExecutorRun(queryDesc, dir, 0L);

    /* save the rowcount if we're given a completionTag to fill */
    if (completionTag)
        snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
                 "SELECT %u", queryDesc->estate->es_processed);

    /* and clean up */
    ExecutorFinish(queryDesc);
    ExecutorEnd(queryDesc);

    FreeQueryDesc(queryDesc);

    PopActiveSnapshot();
}

int GetIntoRelEFlags ( IntoClause intoClause  ) 

Definition at line 174 of file createas.c.

References interpretOidsOption(), NULL, IntoClause::options, IntoClause::skipData, and IntoClause::viewQuery.

Referenced by ExecCreateTableAs(), ExecuteQuery(), and ExplainOnePlan().

{
    int     flags;

    /*
     * We need to tell the executor whether it has to produce OIDs or not,
     * because it doesn't have enough information to do so itself (since we
     * can't build the target relation until after ExecutorStart).
     *
     * Disallow the OIDS option for materialized views.
     */
    if (interpretOidsOption(intoClause->options,
                            (intoClause->viewQuery == NULL)))
        flags = EXEC_FLAG_WITH_OIDS;
    else
        flags = EXEC_FLAG_WITHOUT_OIDS;

    if (intoClause->skipData)
        flags |= EXEC_FLAG_WITH_NO_DATA;

    return flags;
}