/*---------------------------------------------------------------------
  * DefineVirtualRelation
  *
- * Create the "view" relation. `DefineRelation' does all the work,
- * we just provide the correct arguments ... at least when we're
- * creating a view.  If we're updating an existing view, we have to
- * work harder.
+ * Create a view relation and use the rules system to store the query
+ * for the view.
  *---------------------------------------------------------------------
  */
 static ObjectAddress
 DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
-                     List *options)
+                     List *options, Query *viewParse)
 {
    Oid         viewOid;
    LOCKMODE    lockmode;
        descriptor = BuildDescForRelation(attrList);
        checkViewTupleDesc(descriptor, rel->rd_att);
 
-       /*
-        * The new options list replaces the existing options list, even if
-        * it's empty.
-        */
-       atcmd = makeNode(AlterTableCmd);
-       atcmd->subtype = AT_ReplaceRelOptions;
-       atcmd->def = (Node *) options;
-       atcmds = lappend(atcmds, atcmd);
-
        /*
         * If new attributes have been added, we must add pg_attribute entries
         * for them.  It is convenient (although overkill) to use the ALTER
         * TABLE ADD COLUMN infrastructure for this.
+        *
+        * Note that we must do this before updating the query for the view,
+        * since the rules system requires that the correct view columns be in
+        * place when defining the new rules.
         */
        if (list_length(attrList) > rel->rd_att->natts)
        {
                atcmd->def = (Node *) lfirst(c);
                atcmds = lappend(atcmds, atcmd);
            }
+
+           AlterTableInternal(viewOid, atcmds, true);
+
+           /* Make the new view columns visible */
+           CommandCounterIncrement();
        }
 
-       /* OK, let's do it. */
+       /*
+        * Update the query for the view.
+        *
+        * Note that we must do this before updating the view options, because
+        * the new options may not be compatible with the old view query (for
+        * example if we attempt to add the WITH CHECK OPTION, we require that
+        * the new view be automatically updatable, but the old view may not
+        * have been).
+        */
+       StoreViewQuery(viewOid, viewParse, replace);
+
+       /* Make the new view query visible */
+       CommandCounterIncrement();
+
+       /*
+        * Finally update the view options.
+        *
+        * The new options list replaces the existing options list, even if
+        * it's empty.
+        */
+       atcmd = makeNode(AlterTableCmd);
+       atcmd->subtype = AT_ReplaceRelOptions;
+       atcmd->def = (Node *) options;
+       atcmds = list_make1(atcmd);
+
        AlterTableInternal(viewOid, atcmds, true);
 
        ObjectAddressSet(address, RelationRelationId, viewOid);
        ObjectAddress address;
 
        /*
-        * now set the parameters for keys/inheritance etc. All of these are
+        * Set the parameters for keys/inheritance etc. All of these are
         * uninteresting for views...
         */
        createStmt->relation = relation;
        createStmt->if_not_exists = false;
 
        /*
-        * finally create the relation (this will error out if there's an
-        * existing view, so we don't need more code to complain if "replace"
-        * is false).
+        * Create the relation (this will error out if there's an existing
+        * view, so we don't need more code to complain if "replace" is
+        * false).
         */
        address = DefineRelation(createStmt, RELKIND_VIEW, InvalidOid, NULL,
                                 NULL);
        Assert(address.objectId != InvalidOid);
+
+       /* Make the new view relation visible */
+       CommandCounterIncrement();
+
+       /* Store the query for the view */
+       StoreViewQuery(address.objectId, viewParse, replace);
+
        return address;
    }
 }
     * aborted.
     */
    address = 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(address.objectId, viewParse, stmt->replace);
+                                   stmt->replace, stmt->options, viewParse);
 
    return address;
 }