pgsql-at-rework-exec.2.patch
text/x-patch
Filename: pgsql-at-rework-exec.2.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| src/backend/commands/tablecmds.c | 180 | 0 |
*** a/src/backend/commands/tablecmds.c
--- b/src/backend/commands/tablecmds.c
***************
*** 262,269 **** static void ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
static void ATRewriteTables(List **wqueue);
static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap);
static AlteredTableInfo *ATGetQueueEntry(List **wqueue, Relation rel);
! static void ATSimplePermissions(Relation rel, bool allowView);
! static void ATSimplePermissionsRelationOrIndex(Relation rel);
static void ATSimpleRecursion(List **wqueue, Relation rel,
AlterTableCmd *cmd, bool recurse);
static void ATOneLevelRecursion(List **wqueue, Relation rel,
--- 262,270 ----
static void ATRewriteTables(List **wqueue);
static void ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap);
static AlteredTableInfo *ATGetQueueEntry(List **wqueue, Relation rel);
! static void ATCheckRelkind(Relation rel, bool viewOK, bool indexOK);
! static void ATCheckOwnership(Relation rel);
! static void ATCheckNoCatalog(Relation rel);
static void ATSimpleRecursion(List **wqueue, Relation rel,
AlterTableCmd *cmd, bool recurse);
static void ATOneLevelRecursion(List **wqueue, Relation rel,
***************
*** 280,291 **** static void ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
const char *colName);
static void ATExecColumnDefault(Relation rel, const char *colName,
Node *newDefault);
- static void ATPrepSetStatistics(Relation rel, const char *colName,
- Node *newValue);
static void ATExecSetStatistics(Relation rel, const char *colName,
Node *newValue);
- static void ATPrepSetDistinct(Relation rel, const char *colName,
- Node *newValue);
static void ATExecSetDistinct(Relation rel, const char *colName,
Node *newValue);
static void ATExecSetStorage(Relation rel, const char *colName,
--- 281,288 ----
***************
*** 1929,1942 **** renameatt(Oid myrelid,
*
* normally, only the owner of a class can change its schema.
*/
! if (!pg_class_ownercheck(myrelid, GetUserId()))
! aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
! RelationGetRelationName(targetrelation));
! if (!allowSystemTableMods && IsSystemRelation(targetrelation))
! ereport(ERROR,
! (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
! errmsg("permission denied: \"%s\" is a system catalog",
! RelationGetRelationName(targetrelation))));
/*
* if the 'recurse' flag is set then we are supposed to rename this
--- 1926,1934 ----
*
* normally, only the owner of a class can change its schema.
*/
! ATCheckOwnership(targetrelation);
!
! ATCheckNoCatalog(targetrelation);
/*
* if the 'recurse' flag is set then we are supposed to rename this
***************
*** 2048,2053 **** RenameRelation(Oid myrelid, const char *newrelname, ObjectType reltype)
--- 2040,2046 ----
Relation targetrelation;
Oid namespaceId;
char relkind;
+ AclResult aclresult;
/*
* Grab an exclusive lock on the target table, index, sequence or view,
***************
*** 2075,2080 **** RenameRelation(Oid myrelid, const char *newrelname, ObjectType reltype)
--- 2068,2086 ----
RelationGetRelationName(targetrelation))));
/*
+ * Permission checks
+ * XXX - CheckRelationOwnership() should be removed from alter.c
+ */
+ ATCheckOwnership(targetrelation);
+
+ ATCheckNoCatalog(targetrelation);
+
+ aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
+ get_namespace_name(namespaceId));
+
+ /*
* Don't allow ALTER TABLE on composite types. We want people to use ALTER
* TYPE for that.
*/
***************
*** 2382,2395 **** ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
switch (cmd->subtype)
{
case AT_AddColumn: /* ADD COLUMN */
! ATSimplePermissions(rel, false);
/* Performs own recursion */
ATPrepAddColumn(wqueue, rel, recurse, cmd);
pass = AT_PASS_ADD_COL;
break;
case AT_AddColumnToView: /* add column via CREATE OR REPLACE
* VIEW */
! ATSimplePermissions(rel, true);
/* Performs own recursion */
ATPrepAddColumn(wqueue, rel, recurse, cmd);
pass = AT_PASS_ADD_COL;
--- 2388,2403 ----
switch (cmd->subtype)
{
case AT_AddColumn: /* ADD COLUMN */
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
/* Performs own recursion */
ATPrepAddColumn(wqueue, rel, recurse, cmd);
pass = AT_PASS_ADD_COL;
break;
case AT_AddColumnToView: /* add column via CREATE OR REPLACE
* VIEW */
! ATCheckRelkind(rel, true, false);
! ATCheckNoCatalog(rel);
/* Performs own recursion */
ATPrepAddColumn(wqueue, rel, recurse, cmd);
pass = AT_PASS_ADD_COL;
***************
*** 2402,2444 **** ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
* substitutes default values into INSERTs before it expands
* rules.
*/
! ATSimplePermissions(rel, true);
ATSimpleRecursion(wqueue, rel, cmd, recurse);
/* No command-specific prep needed */
pass = cmd->def ? AT_PASS_ADD_CONSTR : AT_PASS_DROP;
break;
case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */
! ATSimplePermissions(rel, false);
ATSimpleRecursion(wqueue, rel, cmd, recurse);
/* No command-specific prep needed */
pass = AT_PASS_DROP;
break;
case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */
! ATSimplePermissions(rel, false);
ATSimpleRecursion(wqueue, rel, cmd, recurse);
/* No command-specific prep needed */
pass = AT_PASS_ADD_CONSTR;
break;
case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */
ATSimpleRecursion(wqueue, rel, cmd, recurse);
! /* Performs own permission checks */
! ATPrepSetStatistics(rel, cmd->name, cmd->def);
pass = AT_PASS_COL_ATTRS;
break;
case AT_SetDistinct: /* ALTER COLUMN SET STATISTICS DISTINCT */
ATSimpleRecursion(wqueue, rel, cmd, recurse);
! /* Performs own permission checks */
! ATPrepSetDistinct(rel, cmd->name, cmd->def);
pass = AT_PASS_COL_ATTRS;
break;
case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
! ATSimplePermissions(rel, false);
ATSimpleRecursion(wqueue, rel, cmd, recurse);
/* No command-specific prep needed */
pass = AT_PASS_COL_ATTRS;
break;
case AT_DropColumn: /* DROP COLUMN */
! ATSimplePermissions(rel, false);
/* Recursion occurs during execution phase */
/* No command-specific prep needed except saving recurse flag */
if (recurse)
--- 2410,2455 ----
* substitutes default values into INSERTs before it expands
* rules.
*/
! ATCheckRelkind(rel, true, false);
! ATCheckNoCatalog(rel);
ATSimpleRecursion(wqueue, rel, cmd, recurse);
/* No command-specific prep needed */
pass = cmd->def ? AT_PASS_ADD_CONSTR : AT_PASS_DROP;
break;
case AT_DropNotNull: /* ALTER COLUMN DROP NOT NULL */
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
ATSimpleRecursion(wqueue, rel, cmd, recurse);
/* No command-specific prep needed */
pass = AT_PASS_DROP;
break;
case AT_SetNotNull: /* ALTER COLUMN SET NOT NULL */
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
ATSimpleRecursion(wqueue, rel, cmd, recurse);
/* No command-specific prep needed */
pass = AT_PASS_ADD_CONSTR;
break;
case AT_SetStatistics: /* ALTER COLUMN SET STATISTICS */
ATSimpleRecursion(wqueue, rel, cmd, recurse);
! ATCheckRelkind(rel, false, true);
pass = AT_PASS_COL_ATTRS;
break;
case AT_SetDistinct: /* ALTER COLUMN SET STATISTICS DISTINCT */
ATSimpleRecursion(wqueue, rel, cmd, recurse);
! ATCheckRelkind(rel, false, true);
pass = AT_PASS_COL_ATTRS;
break;
case AT_SetStorage: /* ALTER COLUMN SET STORAGE */
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
ATSimpleRecursion(wqueue, rel, cmd, recurse);
/* No command-specific prep needed */
pass = AT_PASS_COL_ATTRS;
break;
case AT_DropColumn: /* DROP COLUMN */
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
/* Recursion occurs during execution phase */
/* No command-specific prep needed except saving recurse flag */
if (recurse)
***************
*** 2446,2458 **** ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
pass = AT_PASS_DROP;
break;
case AT_AddIndex: /* ADD INDEX */
! ATSimplePermissions(rel, false);
/* This command never recurses */
/* No command-specific prep needed */
pass = AT_PASS_ADD_INDEX;
break;
case AT_AddConstraint: /* ADD CONSTRAINT */
! ATSimplePermissions(rel, false);
/* Recursion occurs during execution phase */
/* No command-specific prep needed except saving recurse flag */
if (recurse)
--- 2457,2471 ----
pass = AT_PASS_DROP;
break;
case AT_AddIndex: /* ADD INDEX */
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
/* This command never recurses */
/* No command-specific prep needed */
pass = AT_PASS_ADD_INDEX;
break;
case AT_AddConstraint: /* ADD CONSTRAINT */
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
/* Recursion occurs during execution phase */
/* No command-specific prep needed except saving recurse flag */
if (recurse)
***************
*** 2460,2466 **** ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
pass = AT_PASS_ADD_CONSTR;
break;
case AT_DropConstraint: /* DROP CONSTRAINT */
! ATSimplePermissions(rel, false);
/* Recursion occurs during execution phase */
/* No command-specific prep needed except saving recurse flag */
if (recurse)
--- 2473,2480 ----
pass = AT_PASS_ADD_CONSTR;
break;
case AT_DropConstraint: /* DROP CONSTRAINT */
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
/* Recursion occurs during execution phase */
/* No command-specific prep needed except saving recurse flag */
if (recurse)
***************
*** 2468,2474 **** ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
pass = AT_PASS_DROP;
break;
case AT_AlterColumnType: /* ALTER COLUMN TYPE */
! ATSimplePermissions(rel, false);
/* Performs own recursion */
ATPrepAlterColumnType(wqueue, tab, rel, recurse, recursing, cmd);
pass = AT_PASS_ALTER_TYPE;
--- 2482,2489 ----
pass = AT_PASS_DROP;
break;
case AT_AlterColumnType: /* ALTER COLUMN TYPE */
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
/* Performs own recursion */
ATPrepAlterColumnType(wqueue, tab, rel, recurse, recursing, cmd);
pass = AT_PASS_ALTER_TYPE;
***************
*** 2480,2499 **** ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
break;
case AT_ClusterOn: /* CLUSTER ON */
case AT_DropCluster: /* SET WITHOUT CLUSTER */
! ATSimplePermissions(rel, false);
/* These commands never recurse */
/* No command-specific prep needed */
pass = AT_PASS_MISC;
break;
case AT_AddOids: /* SET WITH OIDS */
! ATSimplePermissions(rel, false);
/* Performs own recursion */
if (!rel->rd_rel->relhasoids || recursing)
ATPrepAddOids(wqueue, rel, recurse, cmd);
pass = AT_PASS_ADD_COL;
break;
case AT_DropOids: /* SET WITHOUT OIDS */
! ATSimplePermissions(rel, false);
/* Performs own recursion */
if (rel->rd_rel->relhasoids)
{
--- 2495,2517 ----
break;
case AT_ClusterOn: /* CLUSTER ON */
case AT_DropCluster: /* SET WITHOUT CLUSTER */
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
/* These commands never recurse */
/* No command-specific prep needed */
pass = AT_PASS_MISC;
break;
case AT_AddOids: /* SET WITH OIDS */
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
/* Performs own recursion */
if (!rel->rd_rel->relhasoids || recursing)
ATPrepAddOids(wqueue, rel, recurse, cmd);
pass = AT_PASS_ADD_COL;
break;
case AT_DropOids: /* SET WITHOUT OIDS */
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
/* Performs own recursion */
if (rel->rd_rel->relhasoids)
{
***************
*** 2507,2520 **** ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
pass = AT_PASS_DROP;
break;
case AT_SetTableSpace: /* SET TABLESPACE */
! ATSimplePermissionsRelationOrIndex(rel);
/* This command never recurses */
ATPrepSetTableSpace(tab, rel, cmd->name);
pass = AT_PASS_MISC; /* doesn't actually matter */
break;
case AT_SetRelOptions: /* SET (...) */
case AT_ResetRelOptions: /* RESET (...) */
! ATSimplePermissionsRelationOrIndex(rel);
/* This command never recurses */
/* No command-specific prep needed */
pass = AT_PASS_MISC;
--- 2525,2540 ----
pass = AT_PASS_DROP;
break;
case AT_SetTableSpace: /* SET TABLESPACE */
! ATCheckRelkind(rel, false, true);
! ATCheckNoCatalog(rel);
/* This command never recurses */
ATPrepSetTableSpace(tab, rel, cmd->name);
pass = AT_PASS_MISC; /* doesn't actually matter */
break;
case AT_SetRelOptions: /* SET (...) */
case AT_ResetRelOptions: /* RESET (...) */
! ATCheckRelkind(rel, false, true);
! ATCheckNoCatalog(rel);
/* This command never recurses */
/* No command-specific prep needed */
pass = AT_PASS_MISC;
***************
*** 2533,2539 **** ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
case AT_DisableRule:
case AT_AddInherit: /* INHERIT / NO INHERIT */
case AT_DropInherit:
! ATSimplePermissions(rel, false);
/* These commands never recurse */
/* No command-specific prep needed */
pass = AT_PASS_MISC;
--- 2553,2560 ----
case AT_DisableRule:
case AT_AddInherit: /* INHERIT / NO INHERIT */
case AT_DropInherit:
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
/* These commands never recurse */
/* No command-specific prep needed */
pass = AT_PASS_MISC;
***************
*** 2709,2715 **** ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
--- 2730,2746 ----
*/
break;
case AT_SetTableSpace: /* SET TABLESPACE */
+ {
+ Oid tablespaceId = tab->newTableSpace;
+ AclResult aclresult;
+ ATCheckOwnership(rel);
+ aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(),
+ ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
+ get_tablespace_name(tablespaceId));
+ }
/*
* Nothing to do here; Phase 3 does the work
*/
***************
*** 3278,3343 **** ATGetQueueEntry(List **wqueue, Relation rel)
}
/*
! * ATSimplePermissions
*
! * - Ensure that it is a relation (or possibly a view)
! * - Ensure this user is the owner
! * - Ensure that it is not a system table
*/
static void
! ATSimplePermissions(Relation rel, bool allowView)
{
! if (rel->rd_rel->relkind != RELKIND_RELATION)
! {
! if (allowView)
! {
! if (rel->rd_rel->relkind != RELKIND_VIEW)
! ereport(ERROR,
! (errcode(ERRCODE_WRONG_OBJECT_TYPE),
! errmsg("\"%s\" is not a table or view",
! RelationGetRelationName(rel))));
! }
! else
! ereport(ERROR,
! (errcode(ERRCODE_WRONG_OBJECT_TYPE),
! errmsg("\"%s\" is not a table",
! RelationGetRelationName(rel))));
! }
! /* Permissions checks */
! if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
! aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
! RelationGetRelationName(rel));
!
! if (!allowSystemTableMods && IsSystemRelation(rel))
ereport(ERROR,
! (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
! errmsg("permission denied: \"%s\" is a system catalog",
! RelationGetRelationName(rel))));
}
- /*
- * ATSimplePermissionsRelationOrIndex
- *
- * - Ensure that it is a relation or an index
- * - Ensure this user is the owner
- * - Ensure that it is not a system table
- */
static void
! ATSimplePermissionsRelationOrIndex(Relation rel)
{
- if (rel->rd_rel->relkind != RELKIND_RELATION &&
- rel->rd_rel->relkind != RELKIND_INDEX)
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a table or index",
- RelationGetRelationName(rel))));
-
- /* Permissions checks */
if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
RelationGetRelationName(rel));
if (!allowSystemTableMods && IsSystemRelation(rel))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
--- 3309,3347 ----
}
/*
! * ATCheckRelkind
! * ATCheckOwnership
! * ATCheckOwnership
*
! * These are originally checked in ATSimplePermissions
*/
static void
! ATCheckRelkind(Relation rel, bool viewOK, bool indexOK)
{
! char relkind = rel->rd_rel->relkind;
! if (relkind != RELKIND_RELATION &&
! (!viewOK || relkind != RELKIND_VIEW) &&
! (!indexOK || relkind != RELKIND_INDEX))
ereport(ERROR,
! (errcode(ERRCODE_WRONG_OBJECT_TYPE),
! errmsg("\"%s\" is not a table%s%s",
! RelationGetRelationName(rel),
! !viewOK ? "" : " or view",
! !indexOK ? "" : " or index")));
}
static void
! ATCheckOwnership(Relation rel)
{
if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
RelationGetRelationName(rel));
+ }
+ static void
+ ATCheckNoCatalog(Relation rel)
+ {
if (!allowSystemTableMods && IsSystemRelation(rel))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
***************
*** 3584,3589 **** ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
--- 3588,3596 ----
Form_pg_type tform;
Expr *defval;
+ /* permission check to add a new column */
+ ATCheckOwnership(rel);
+
attrdesc = heap_open(AttributeRelationId, RowExclusiveLock);
/*
***************
*** 3884,3889 **** ATExecDropNotNull(Relation rel, const char *colName)
--- 3891,3899 ----
List *indexoidlist;
ListCell *indexoidscan;
+ /* permission check */
+ ATCheckOwnership(rel);
+
/*
* lookup the attribute
*/
***************
*** 3976,3981 **** ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
--- 3986,3994 ----
AttrNumber attnum;
Relation attr_rel;
+ /* permission check */
+ ATCheckOwnership(rel);
+
/*
* lookup the attribute
*/
***************
*** 4026,4031 **** ATExecColumnDefault(Relation rel, const char *colName,
--- 4039,4047 ----
{
AttrNumber attnum;
+ /* permission check */
+ ATCheckOwnership(rel);
+
/*
* get the number of the attribute
*/
***************
*** 4071,4098 **** ATExecColumnDefault(Relation rel, const char *colName,
* ALTER TABLE ALTER COLUMN SET STATISTICS
*/
static void
- ATPrepSetStatistics(Relation rel, const char *colName, Node *newValue)
- {
- /*
- * We do our own permission checking because (a) we want to allow SET
- * STATISTICS on indexes (for expressional index columns), and (b) we want
- * to allow SET STATISTICS on system catalogs without requiring
- * allowSystemTableMods to be turned on.
- */
- if (rel->rd_rel->relkind != RELKIND_RELATION &&
- rel->rd_rel->relkind != RELKIND_INDEX)
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a table or index",
- RelationGetRelationName(rel))));
-
- /* Permissions checks */
- if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
- RelationGetRelationName(rel));
- }
-
- static void
ATExecSetStatistics(Relation rel, const char *colName, Node *newValue)
{
int newtarget;
--- 4087,4092 ----
***************
*** 4100,4105 **** ATExecSetStatistics(Relation rel, const char *colName, Node *newValue)
--- 4094,4102 ----
HeapTuple tuple;
Form_pg_attribute attrtuple;
+ /* permission check */
+ ATCheckOwnership(rel);
+
Assert(IsA(newValue, Integer));
newtarget = intVal(newValue);
***************
*** 4155,4182 **** ATExecSetStatistics(Relation rel, const char *colName, Node *newValue)
* ALTER TABLE ALTER COLUMN SET STATISTICS DISTINCT
*/
static void
- ATPrepSetDistinct(Relation rel, const char *colName, Node *newValue)
- {
- /*
- * We do our own permission checking because (a) we want to allow SET
- * DISTINCT on indexes (for expressional index columns), and (b) we want
- * to allow SET DISTINCT on system catalogs without requiring
- * allowSystemTableMods to be turned on.
- */
- if (rel->rd_rel->relkind != RELKIND_RELATION &&
- rel->rd_rel->relkind != RELKIND_INDEX)
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is not a table or index",
- RelationGetRelationName(rel))));
-
- /* Permissions checks */
- if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
- RelationGetRelationName(rel));
- }
-
- static void
ATExecSetDistinct(Relation rel, const char *colName, Node *newValue)
{
float4 newdistinct;
--- 4152,4157 ----
***************
*** 4184,4189 **** ATExecSetDistinct(Relation rel, const char *colName, Node *newValue)
--- 4159,4167 ----
HeapTuple tuple;
Form_pg_attribute attrtuple;
+ /* permission check */
+ ATCheckOwnership(rel);
+
switch (nodeTag(newValue))
{
case T_Integer:
***************
*** 4251,4256 **** ATExecSetStorage(Relation rel, const char *colName, Node *newValue)
--- 4229,4237 ----
HeapTuple tuple;
Form_pg_attribute attrtuple;
+ /* permission check */
+ ATCheckOwnership(rel);
+
Assert(IsA(newValue, String));
storagemode = strVal(newValue);
***************
*** 4332,4340 **** ATExecDropColumn(List **wqueue, Relation rel, const char *colName,
List *children;
ObjectAddress object;
! /* At top level, permission check was done in ATPrepCmd, else do it */
if (recursing)
! ATSimplePermissions(rel, false);
/*
* get the number of the attribute
--- 4313,4327 ----
List *children;
ObjectAddress object;
! /* At top level, sanity check was done in ATPrepCmd, else do it */
if (recursing)
! {
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
! }
!
! /* permission check */
! ATCheckOwnership(rel);
/*
* get the number of the attribute
***************
*** 4525,4530 **** ATExecAddIndex(AlteredTableInfo *tab, Relation rel,
--- 4512,4528 ----
Assert(IsA(stmt, IndexStmt));
+ /*
+ * XXX - IMO, we should apply all the permission checks in DefineIndex()
+ * when it is invoked with check_rights == true.
+ * Here are only two code paths. The one is ATExecAddIndex() by AT_AddIndex,
+ * the other is standard_ProcessUtility() by T_IndexStmt which also calls
+ * CheckRelationOwnership() on the relation to be indexed just before
+ * DefineIndex() invocation.
+ */
+ ATCheckOwnership(rel);
+ /* XXX - ACL_CREATE on pg_namespace should be checked here? */
+
/* suppress schema rights check when rebuilding existing index */
check_rights = !is_rebuild;
/* skip index build if phase 3 will have to rewrite table anyway */
***************
*** 4634,4642 **** ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
List *children;
ListCell *child;
! /* At top level, permission check was done in ATPrepCmd, else do it */
if (recursing)
! ATSimplePermissions(rel, false);
/*
* Call AddRelationNewConstraints to do the work, making sure it works on
--- 4632,4645 ----
List *children;
ListCell *child;
! /* At top level, sanity check was done in ATPrepCmd, else do it */
if (recursing)
! {
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
! }
! /* Permission check */
! ATCheckOwnership(rel);
/*
* Call AddRelationNewConstraints to do the work, making sure it works on
***************
*** 4754,4770 **** ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
* Validity checks (permission checks wait till we have the column
* numbers)
*/
! if (pkrel->rd_rel->relkind != RELKIND_RELATION)
! ereport(ERROR,
! (errcode(ERRCODE_WRONG_OBJECT_TYPE),
! errmsg("referenced relation \"%s\" is not a table",
! RelationGetRelationName(pkrel))));
!
! if (!allowSystemTableMods && IsSystemRelation(pkrel))
! ereport(ERROR,
! (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
! errmsg("permission denied: \"%s\" is a system catalog",
! RelationGetRelationName(pkrel))));
/*
* Disallow reference from permanent table to temp table or vice versa.
--- 4757,4764 ----
* Validity checks (permission checks wait till we have the column
* numbers)
*/
! ATCheckRelkind(pkrel, false, false);
! ATCheckNoCatalog(pkrel);
/*
* Disallow reference from permanent table to temp table or vice versa.
***************
*** 4832,4837 **** ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
--- 4826,4832 ----
/*
* Now we can check permissions.
*/
+ ATCheckOwnership(rel);
checkFkeyPermissions(pkrel, pkattnum, numpks);
checkFkeyPermissions(rel, fkattnum, numfks);
***************
*** 5582,5590 **** ATExecDropConstraint(Relation rel, const char *constrName,
bool found = false;
bool is_check_constraint = false;
! /* At top level, permission check was done in ATPrepCmd, else do it */
if (recursing)
! ATSimplePermissions(rel, false);
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
--- 5577,5590 ----
bool found = false;
bool is_check_constraint = false;
! /* At top level, sanity check was done in ATPrepCmd, else do it */
if (recursing)
! {
! ATCheckRelkind(rel, false, false);
! ATCheckNoCatalog(rel);
! }
! /* Permission checks */
! ATCheckOwnership(rel);
conrel = heap_open(ConstraintRelationId, RowExclusiveLock);
***************
*** 5915,5920 **** ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
--- 5915,5923 ----
SysScanDesc scan;
HeapTuple depTup;
+ /* Permission checks */
+ ATCheckOwnership(rel);
+
attrelation = heap_open(AttributeRelationId, RowExclusiveLock);
/* Look up the target column */
***************
*** 6695,6700 **** ATExecClusterOn(Relation rel, const char *indexName)
--- 6698,6706 ----
{
Oid indexOid;
+ /* Permission checks */
+ ATCheckOwnership(rel);
+
indexOid = get_relname_relid(indexName, rel->rd_rel->relnamespace);
if (!OidIsValid(indexOid))
***************
*** 6719,6724 **** ATExecClusterOn(Relation rel, const char *indexName)
--- 6725,6733 ----
static void
ATExecDropCluster(Relation rel)
{
+ /* Permission checks */
+ ATCheckOwnership(rel);
+
mark_index_clustered(rel, InvalidOid);
}
***************
*** 6729,6735 **** static void
ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, char *tablespacename)
{
Oid tablespaceId;
- AclResult aclresult;
/* Check that the tablespace exists */
tablespaceId = get_tablespace_oid(tablespacename);
--- 6738,6743 ----
***************
*** 6738,6748 **** ATPrepSetTableSpace(AlteredTableInfo *tab, Relation rel, char *tablespacename)
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("tablespace \"%s\" does not exist", tablespacename)));
- /* Check its permissions */
- aclresult = pg_tablespace_aclcheck(tablespaceId, GetUserId(), ACL_CREATE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_TABLESPACE, tablespacename);
-
/* Save info for Phase 3 to do the real work */
if (OidIsValid(tab->newTableSpace))
ereport(ERROR,
--- 6746,6751 ----
***************
*** 6769,6774 **** ATExecSetRelOptions(Relation rel, List *defList, bool isReset)
--- 6772,6780 ----
bool repl_repl[Natts_pg_class];
static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
+ /* Permission checks */
+ ATCheckOwnership(rel);
+
if (defList == NIL)
return; /* nothing to do */
***************
*** 7091,7096 **** static void
--- 7097,7105 ----
ATExecEnableDisableTrigger(Relation rel, char *trigname,
char fires_when, bool skip_system)
{
+ /* Permission checks */
+ ATCheckOwnership(rel);
+
EnableDisableTrigger(rel, trigname, fires_when, skip_system);
}
***************
*** 7103,7108 **** static void
--- 7112,7123 ----
ATExecEnableDisableRule(Relation rel, char *trigname,
char fires_when)
{
+ /*
+ * Permission checks
+ * XXX - pg_class_ownercheck() in EnableDisableRule() should be removed
+ */
+ ATCheckOwnership(rel);
+
EnableDisableRule(rel, trigname, fires_when);
}
***************
*** 7131,7140 **** ATExecAddInherit(Relation child_rel, RangeVar *parent)
parent_rel = heap_openrv(parent, AccessShareLock);
/*
! * Must be owner of both parent and child -- child was checked by
! * ATSimplePermissions call in ATPrepCmd
*/
! ATSimplePermissions(parent_rel, false);
/* Permanent rels cannot inherit from temporary ones */
if (parent_rel->rd_istemp && !child_rel->rd_istemp)
--- 7146,7161 ----
parent_rel = heap_openrv(parent, AccessShareLock);
/*
! * Sanity check
*/
! ATCheckRelkind(parent_rel, false, false);
! ATCheckNoCatalog(parent_rel);
!
! /*
! * Must be owner of both parent and child
! */
! ATCheckOwnership(child_rel);
! ATCheckOwnership(parent_rel);
/* Permanent rels cannot inherit from temporary ones */
if (parent_rel->rd_istemp && !child_rel->rd_istemp)
***************
*** 7782,7787 **** AlterTableNamespace(RangeVar *relation, const char *newschema,
--- 7803,7816 ----
RelationGetRelationName(rel))));
}
+ /*
+ * Permission checks
+ * XXX - CheckRelationOwnership() should be removed from alter.c
+ */
+ ATCheckOwnership(rel);
+
+ ATCheckNoCatalog(rel);
+
/* get schema OID and check its permissions */
nspOid = LookupCreationNamespace(newschema);