Header And Logo

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

Functions

view.h File Reference

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

Go to the source code of this file.

Functions

Oid DefineView (ViewStmt *stmt, const char *queryString)
void StoreViewQuery (Oid viewOid, Query *viewParse, bool replace)

Function Documentation

Oid DefineView ( ViewStmt stmt,
const char *  queryString 
)

Definition at line 372 of file view.c.

References ViewStmt::aliases, Assert, CMD_SELECT, CommandCounterIncrement(), Query::commandType, copyObject(), DefineVirtualRelation(), elog, ereport, errcode(), errmsg(), ERROR, Query::hasModifyingCTE, IsA, isQueryUsingTempRelation(), lfirst, list_head(), lnext, NIL, NOTICE, NULL, ViewStmt::options, parse_analyze(), pstrdup(), ViewStmt::query, RangeVar::relname, RangeVar::relpersistence, RELPERSISTENCE_PERMANENT, RELPERSISTENCE_UNLOGGED, ViewStmt::replace, TargetEntry::resjunk, TargetEntry::resname, StoreViewQuery(), strVal, Query::targetList, Query::utilityStmt, and ViewStmt::view.

Referenced by ProcessUtilitySlow().

{
    Query      *viewParse;
    Oid         viewOid;
    RangeVar   *view;

    /*
     * Run parse analysis to convert the raw parse tree to a Query.  Note this
     * also acquires sufficient locks on the source table(s).
     *
     * Since parse analysis scribbles on its input, copy the raw parse tree;
     * this ensures we don't corrupt a prepared statement, for example.
     */
    viewParse = parse_analyze((Node *) copyObject(stmt->query),
                              queryString, NULL, 0);

    /*
     * The grammar should ensure that the result is a single SELECT Query.
     * However, it doesn't forbid SELECT INTO, so we have to check for that.
     */
    if (!IsA(viewParse, Query))
        elog(ERROR, "unexpected parse analysis result");
    if (viewParse->utilityStmt != NULL &&
        IsA(viewParse->utilityStmt, CreateTableAsStmt))
        ereport(ERROR,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("views must not contain SELECT INTO")));
    if (viewParse->commandType != CMD_SELECT ||
        viewParse->utilityStmt != NULL)
        elog(ERROR, "unexpected parse analysis result");

    /*
     * Check for unsupported cases.  These tests are redundant with ones in
     * DefineQueryRewrite(), but that function will complain about a bogus ON
     * SELECT rule, and we'd rather the message complain about a view.
     */
    if (viewParse->hasModifyingCTE)
        ereport(ERROR,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
        errmsg("views must not contain data-modifying statements in WITH")));

    /*
     * If a list of column names was given, run through and insert these into
     * the actual query tree. - thomas 2000-03-08
     */
    if (stmt->aliases != NIL)
    {
        ListCell   *alist_item = list_head(stmt->aliases);
        ListCell   *targetList;

        foreach(targetList, viewParse->targetList)
        {
            TargetEntry *te = (TargetEntry *) lfirst(targetList);

            Assert(IsA(te, TargetEntry));
            /* junk columns don't get aliases */
            if (te->resjunk)
                continue;
            te->resname = pstrdup(strVal(lfirst(alist_item)));
            alist_item = lnext(alist_item);
            if (alist_item == NULL)
                break;          /* done assigning aliases */
        }

        if (alist_item != NULL)
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("CREATE VIEW specifies more column "
                            "names than columns")));
    }

    /* Unlogged views are not sensible. */
    if (stmt->view->relpersistence == RELPERSISTENCE_UNLOGGED)
        ereport(ERROR,
                (errcode(ERRCODE_SYNTAX_ERROR),
        errmsg("views cannot be unlogged because they do not have storage")));

    /*
     * If the user didn't explicitly ask for a temporary view, check whether
     * we need one implicitly.  We allow TEMP to be inserted automatically as
     * long as the CREATE command is consistent with that --- no explicit
     * schema name.
     */
    view = copyObject(stmt->view);      /* don't corrupt original command */
    if (view->relpersistence == RELPERSISTENCE_PERMANENT
        && isQueryUsingTempRelation(viewParse))
    {
        view->relpersistence = RELPERSISTENCE_TEMP;
        ereport(NOTICE,
                (errmsg("view \"%s\" will be a temporary view",
                        view->relname)));
    }

    /*
     * Create the view relation
     *
     * NOTE: if it already exists and replace is false, the xact will be
     * aborted.
     */
    viewOid = DefineVirtualRelation(view, viewParse->targetList,
                                    stmt->replace, stmt->options);

    /*
     * The relation we have just created is not visible to any other commands
     * running with the same transaction & command id. So, increment the
     * command id counter (but do NOT pfree any memory!!!!)
     */
    CommandCounterIncrement();

    StoreViewQuery(viewOid, viewParse, stmt->replace);

    return viewOid;
}

void StoreViewQuery ( Oid  viewOid,
Query viewParse,
bool  replace 
)

Definition at line 490 of file view.c.

References DefineViewRules(), and UpdateRangeTableOfViewParse().

Referenced by DefineView(), and intorel_startup().

{
    /*
     * The range table of 'viewParse' does not contain entries for the "OLD"
     * and "NEW" relations. So... add them!
     */
    viewParse = UpdateRangeTableOfViewParse(viewOid, viewParse);

    /*
     * Now create the rules associated with the view.
     */
    DefineViewRules(viewOid, viewParse, replace);
}