]> granicus.if.org Git - postgresql/commitdiff
Fix failure of "ALTER TABLE t ADD COLUMN c serial" when done by non-owner.
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 18 Aug 2010 18:35:21 +0000 (18:35 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 18 Aug 2010 18:35:21 +0000 (18:35 +0000)
The implicitly created sequence was created as owned by the current user,
who could be different from the table owner, eg if current user is a
superuser or some member of the table's owning role.  This caused sanity
checks in the SEQUENCE OWNED BY code to spit up.  Although possibly we
don't need those sanity checks, the safest fix seems to be to make sure
the implicit sequence is assigned the same owner role as the table has.
(We still do all permissions checks as the current user, however.)
Per report from Josh Berkus.

Back-patch to 9.0.  The bug goes back to the invention of SEQUENCE OWNED BY
in 8.2, but the fix requires an API change for DefineRelation(), which seems
to have potential for breaking third-party code if done in a minor release.
Given the lack of prior complaints, it's probably not worth fixing in the
stable branches.

src/backend/commands/sequence.c
src/backend/commands/tablecmds.c
src/backend/commands/typecmds.c
src/backend/commands/view.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/parser/parse_utilcmd.c
src/backend/tcop/utility.c
src/include/commands/tablecmds.h
src/include/nodes/parsenodes.h

index 6e0930f8d02fb673cf7f3843d777be9087637b41..2c07835b952566c52c131f4f7d269bcb77f62d30 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.170 2010/08/13 20:10:51 rhaas Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.171 2010/08/18 18:35:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -205,7 +205,7 @@ DefineSequence(CreateSeqStmt *seq)
        stmt->tablespacename = NULL;
        stmt->if_not_exists = false;
 
-       seqoid = DefineRelation(stmt, RELKIND_SEQUENCE);
+       seqoid = DefineRelation(stmt, RELKIND_SEQUENCE, seq->ownerId);
        Assert(seqoid != InvalidOid);
 
        rel = heap_open(seqoid, AccessExclusiveLock);
index 703fd7e71b24d70d5be147f8978dc78a1697ace3..2766238f5fce5cf7af2eb8edc2e807d6253fdd26 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.340 2010/08/13 20:10:51 rhaas Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.341 2010/08/18 18:35:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -341,11 +341,21 @@ static const char *storage_name(char c);
  *             DefineRelation
  *                             Creates a new relation.
  *
+ * stmt carries parsetree information from an ordinary CREATE TABLE statement.
+ * The other arguments are used to extend the behavior for other cases:
+ * relkind: relkind to assign to the new relation
+ * ownerId: if not InvalidOid, use this as the new relation's owner.
+ *
+ * Note that permissions checks are done against current user regardless of
+ * ownerId.  A nonzero ownerId is used when someone is creating a relation
+ * "on behalf of" someone else, so we still want to see that the current user
+ * has permissions to do it.
+ *
  * If successful, returns the OID of the new relation.
  * ----------------------------------------------------------------
  */
 Oid
-DefineRelation(CreateStmt *stmt, char relkind)
+DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
 {
        char            relname[NAMEDATALEN];
        Oid                     namespaceId;
@@ -440,6 +450,10 @@ DefineRelation(CreateStmt *stmt, char relkind)
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 errmsg("only shared relations can be placed in pg_global tablespace")));
 
+       /* Identify user ID that will own the table */
+       if (!OidIsValid(ownerId))
+               ownerId = GetUserId();
+
        /*
         * Parse and validate reloptions, if any.
         */
@@ -532,7 +546,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
                                                                                  InvalidOid,
                                                                                  InvalidOid,
                                                                                  ofTypeId,
-                                                                                 GetUserId(),
+                                                                                 ownerId,
                                                                                  descriptor,
                                                                                  list_concat(cookedDefaults,
                                                                                                          old_constraints),
index 19d61a725681834a2da9c36a898f741c6578b70a..7652420c3e5bb8ae145fdd0119824ada507f63ee 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.150 2010/07/28 05:22:24 sriggs Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.151 2010/08/18 18:35:19 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -1548,7 +1548,7 @@ DefineCompositeType(const RangeVar *typevar, List *coldeflist)
        /*
         * Finally create the relation.  This also creates the type.
         */
-       relid = DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE);
+       relid = DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE, InvalidOid);
        Assert(relid != InvalidOid);
        return relid;
 }
index 1acf1b802d729ec907239ba4697c9793e42dff08..e67d377418e87c6a967695d1fc02b9937da0d341 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.121 2010/07/25 23:21:21 rhaas Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.122 2010/08/18 18:35:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -242,7 +242,7 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
                 * existing view, so we don't need more code to complain if "replace"
                 * is false).
                 */
-               relid = DefineRelation(createStmt, RELKIND_VIEW);
+               relid = DefineRelation(createStmt, RELKIND_VIEW, InvalidOid);
                Assert(relid != InvalidOid);
                return relid;
        }
index 70cd56a5921f2096bc267a0e4c49e2a60a80a396..d33b1198017aad5d99b4eb781f4130641ae64e11 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.468 2010/08/18 15:21:54 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.469 2010/08/18 18:35:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3023,6 +3023,7 @@ _copyCreateSeqStmt(CreateSeqStmt *from)
 
        COPY_NODE_FIELD(sequence);
        COPY_NODE_FIELD(options);
+       COPY_SCALAR_FIELD(ownerId);
 
        return newnode;
 }
index 0cb87015b6ec4556f7599bfd48287a990ed8f054..06cdbf5185baa82cca0f0d0f3a03a899d020b89c 100644 (file)
@@ -22,7 +22,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.387 2010/08/07 02:44:06 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.388 2010/08/18 18:35:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1513,6 +1513,7 @@ _equalCreateSeqStmt(CreateSeqStmt *a, CreateSeqStmt *b)
 {
        COMPARE_NODE_FIELD(sequence);
        COMPARE_NODE_FIELD(options);
+       COMPARE_SCALAR_FIELD(ownerId);
 
        return true;
 }
index d9aebb0d7273216becb0d2715c8d4bcac541b00b..74a799f3e84c2363a17db97979b7b31e45b82c46 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.715 2010/08/05 04:21:53 petere Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.716 2010/08/18 18:35:20 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -2827,6 +2827,7 @@ CreateSeqStmt:
                                        $4->istemp = $2;
                                        n->sequence = $4;
                                        n->options = $5;
+                                       n->ownerId = InvalidOid;
                                        $$ = (Node *)n;
                                }
                ;
index b4e0a614c41da28e9dc77ac82f0830f81185796f..bf680a29488f5447c4e807775b86ada7023e6ee7 100644 (file)
@@ -19,7 +19,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.42 2010/08/05 15:25:35 rhaas Exp $
+ *     $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.43 2010/08/18 18:35:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -361,6 +361,18 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
                seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
                seqstmt->options = NIL;
 
+               /*
+                * If this is ALTER ADD COLUMN, make sure the sequence will be owned
+                * by the table's owner.  The current user might be someone else
+                * (perhaps a superuser, or someone who's only a member of the owning
+                * role), but the SEQUENCE OWNED BY mechanisms will bleat unless
+                * table and sequence have exactly the same owning role.
+                */
+               if (cxt->rel)
+                       seqstmt->ownerId = cxt->rel->rd_rel->relowner;
+               else
+                       seqstmt->ownerId = InvalidOid;
+
                cxt->blist = lappend(cxt->blist, seqstmt);
 
                /*
index db5c6e9c0865fb17bcdfbd3f12094e8db9ff7564..d37e9123d9787bca26d3ccb27373b3be8266cfbd 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.336 2010/07/25 23:21:22 rhaas Exp $
+ *       $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.337 2010/08/18 18:35:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -510,7 +510,8 @@ standard_ProcessUtility(Node *parsetree,
 
                                                /* Create the table itself */
                                                relOid = DefineRelation((CreateStmt *) stmt,
-                                                                                               RELKIND_RELATION);
+                                                                                               RELKIND_RELATION,
+                                                                                               InvalidOid);
 
                                                /*
                                                 * If "IF NOT EXISTS" was specified and the relation
index c94a46027ed40da58ac77912d01a390af6f7bbff..9cebb60f514cc0c4a2e620928f137b4c72aa3258 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.47 2010/07/28 05:22:24 sriggs Exp $
+ * $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.48 2010/08/18 18:35:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,7 +19,7 @@
 #include "utils/relcache.h"
 
 
-extern Oid     DefineRelation(CreateStmt *stmt, char relkind);
+extern Oid     DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId);
 
 extern void RemoveRelations(DropStmt *drop);
 
index f02df2aca5bdf5c4ec2a543e7bc8cd4b7d0e9336..6d2128df1120b091707c95667a17a1defc1b7bca 100644 (file)
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.434 2010/08/07 02:44:07 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.435 2010/08/18 18:35:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1700,6 +1700,7 @@ typedef struct CreateSeqStmt
        NodeTag         type;
        RangeVar   *sequence;           /* the sequence to create */
        List       *options;
+       Oid                     ownerId;                /* ID of owner, or InvalidOid for default */
 } CreateSeqStmt;
 
 typedef struct AlterSeqStmt