Repository: incubator-hawq
Updated Branches:
  refs/heads/master 5ce139a25 -> e2ddb6ac0


HAWQ-322. Refixed DROP TABLESPACE doesnot check sub-object(database/relation) 
in some cases


Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/e2ddb6ac
Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/e2ddb6ac
Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/e2ddb6ac

Branch: refs/heads/master
Commit: e2ddb6ac0ddb4d069caa7428c306facaf2f42194
Parents: 5ce139a
Author: Ming LI <m...@pivotal.io>
Authored: Thu Jan 14 19:31:39 2016 +0800
Committer: Ming LI <m...@pivotal.io>
Committed: Thu Jan 14 19:31:39 2016 +0800

----------------------------------------------------------------------
 src/backend/commands/tablespace.c | 136 ++++++++++++++++++++++-----------
 1 file changed, 90 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e2ddb6ac/src/backend/commands/tablespace.c
----------------------------------------------------------------------
diff --git a/src/backend/commands/tablespace.c 
b/src/backend/commands/tablespace.c
index 3b4c6f7..3f1fa9c 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -60,6 +60,7 @@
 #include "catalog/indexing.h"
 #include "catalog/pg_filespace.h"
 #include "catalog/pg_tablespace.h"
+#include "catalog/pg_database.h"
 #include "catalog/pg_type.h"
 #include "cdb/cdbmirroredflatfile.h"
 #include "commands/comment.h"
@@ -89,7 +90,7 @@
 char      *default_tablespace = NULL;
 
 
-static bool remove_tablespace_directories(Oid tablespaceoid, bool redo, 
+static bool remove_tablespace_directories(Oid tablespaceoid, bool redo,
                                                                                
  char *location);
 /*
  * Create a table space
@@ -128,7 +129,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
                ownerId = get_roleid_checked(stmt->owner);
        else
                ownerId = GetUserId();
-               
+
        /*
         * Disallow creation of tablespaces named "pg_xxx"; we reserve this
         * namespace for system purposes.
@@ -144,7 +145,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
        }
 
        /*
-        * Check the specified filespace 
+        * Check the specified filespace
         */
        filespaceRel = heap_open(FileSpaceRelationId, RowShareLock);
        filespaceoid = get_filespace_oid(filespaceRel, stmt->filespacename);
@@ -154,20 +155,20 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
                                (errcode(ERRCODE_UNDEFINED_OBJECT),
                                 errmsg("filespace \"%s\" does not exist",
                                                stmt->filespacename)));
-       
-       /* 
+
+       /*
         * Filespace pg_system is reserved for system use:
         *   - Used for pg_global and pg_default tablespaces only
-        * 
+        *
         * Directory layout is slightly different for the system filespace.
         * Instead of having subdirectories for individual tablespaces instead
         * the two system tablespaces have specific locations within it:
         *         pg_global  : $PG_SYSTEM/global/relfilenode
         *         pg_default : $PG_SYSTEM/base/dboid/relfilenode
         *
-        * In other words PG_SYSTEM points to the segments "datadir", or in 
+        * In other words PG_SYSTEM points to the segments "datadir", or in
         * postgres vocabulary $PGDATA.
-        * 
+        *
         */
        if (filespaceoid == SYSTEMFILESPACE_OID && !IsBootstrapProcessingMode())
                ereport(ERROR,
@@ -239,13 +240,13 @@ CreateTableSpace(CreateTableSpaceStmt *stmt)
                                                                                
&persistentSerialNum);
 
        /*
-        * Record dependency on owner 
+        * Record dependency on owner
         *
         * We do not record the dependency on pg_filespace because we do not 
track
-        * dependencies between shared objects.  Additionally the pg_tablespace 
+        * dependencies between shared objects.  Additionally the pg_tablespace
         * table itself contains the foreign key back to pg_filespace and can be
-        * used to fulfill the same purpose that an entry in pg_shdepend would. 
-        */      
+        * used to fulfill the same purpose that an entry in pg_shdepend would.
+        */
        recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId);
 
        /*
@@ -275,24 +276,24 @@ void
 RemoveTableSpace(List *names, DropBehavior behavior, bool missing_ok)
 {
        char        *tablespacename;
-       Relation         rel;
-       HeapTuple        tuple;
-       cqContext                                        cqc;
-       cqContext                                       *pcqCtx;
+       Relation         rel, rel1;
+       HeapTuple        tuple, tuple1;
+       cqContext                                        cqc, cqc1;
+       cqContext                                       *pcqCtx, *pcqCtx1;
        Oid                      tablespaceoid;
        int32        count,
                                 count2;
-       RelFileNode  relfilenode;       
+       RelFileNode  relfilenode;
        DbDirNode        dbDirNode;
        PersistentFileSysState persistentState;
        ItemPointerData persistentTid;
        int64            persistentSerialNum;
-       
+
 
        /* don't call this in a transaction block */
        // PreventTransactionChain((void *) stmt, "DROP TABLESPACE");
 
-       /* 
+       /*
         * General DROP (object) syntax allows fully qualified names, but
         * tablespaces are global objects that do not live in schemas, so
         * it is a syntax error if a fully qualified name was given.
@@ -314,13 +315,13 @@ RemoveTableSpace(List *names, DropBehavior behavior, bool 
missing_ok)
         */
        rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
 
-       pcqCtx = caql_addrel(cqclr(&cqc), rel); 
+       pcqCtx = caql_addrel(cqclr(&cqc), rel);
 
        tuple = caql_getfirst(
                        pcqCtx,
                        cql("SELECT * FROM pg_tablespace "
                                 " WHERE spcname = :1 "
-                                " FOR UPDATE ", 
+                                " FOR UPDATE ",
                                CStringGetDatum(tablespacename)));
 
        if (!HeapTupleIsValid(tuple))
@@ -357,13 +358,56 @@ RemoveTableSpace(List *names, DropBehavior behavior, bool 
missing_ok)
                aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE,
                                           tablespacename);
 
-       /* 
-        * Check for any databases or relations defined in this tablespace, 
this 
-        * is logically the same as checkSharedDependencies, however we don't 
-        * actually track these in pg_shdepend, instead we lookup this 
information 
+       /*
+        * Check for any databases or relations defined in this tablespace, this
+        * is logically the same as checkSharedDependencies, however we don't
+        * actually track these in pg_shdepend, instead we lookup this 
information
         * in the gp_persistent_database/relation_node tables.
         */
-       /* ... */
+
+       /*
+        * Check for any databases defined in this tablespace
+        */
+       rel1 = heap_open(DatabaseRelationId, AccessShareLock);
+
+       pcqCtx1 = caql_addrel(cqclr(&cqc1), rel1);
+
+       tuple1 = caql_getfirst(
+                       pcqCtx1,
+                       cql("SELECT * FROM pg_database "
+                                " WHERE dat2tablespace = :1 ",
+                               ObjectIdGetDatum(tablespaceoid)));
+
+       if (HeapTupleIsValid(tuple1))
+       {
+               ereport(ERROR,
+                               
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+                                errmsg("tablespace \"%s\" is not empty: 
existing database.", tablespacename)));
+
+       }
+    heap_close(rel1, AccessShareLock);
+
+       /*
+        * Check for any databases defined in this tablespace
+        */
+       rel1 = heap_open(RelationRelationId, AccessShareLock);
+
+       pcqCtx1 = caql_addrel(cqclr(&cqc1), rel1);
+
+       tuple1 = caql_getfirst(
+                       pcqCtx1,
+                       cql("SELECT * FROM pg_class "
+                                " WHERE reltablespace = :1 ",
+                               ObjectIdGetDatum(tablespaceoid)));
+
+       if (HeapTupleIsValid(tuple1))
+       {
+               ereport(ERROR,
+                               
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+                                errmsg("tablespace \"%s\" is not empty: 
existing table.", tablespacename)));
+
+       }
+    heap_close(rel1, AccessShareLock);
 
        /*
         * Remove the pg_tablespace tuple (this will roll back if we fail below)
@@ -384,16 +428,16 @@ RemoveTableSpace(List *names, DropBehavior behavior, bool 
missing_ok)
        deleteSharedDependencyRecordsFor(TableSpaceRelationId, tablespaceoid);
 
        /* MPP-6929: metadata tracking */
-       MetaTrackDropObject(TableSpaceRelationId, 
+       MetaTrackDropObject(TableSpaceRelationId,
                                                tablespaceoid);
 
        /*
-        * Acquire TablespaceCreateLock to ensure that no 
+        * Acquire TablespaceCreateLock to ensure that no
         * MirroredFileSysObj_JustInTimeDbDirCreate is running concurrently.
         */
        LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE);
 
-       /* 
+       /*
         * Check for any relations still defined in the tablespace.
         */
        PersistentRelation_CheckTablespace(tablespaceoid, &count, &relfilenode);
@@ -407,9 +451,9 @@ RemoveTableSpace(List *names, DropBehavior behavior, bool 
missing_ok)
 
        /*
         * Schedule the removal the physical infrastructure.
-        * 
+        *
         * Note: This only schedules the delete, the delete won't actually occur
-        * until after the transaction has comitted.  This should however do 
+        * until after the transaction has comitted.  This should however do
         * everything it can to assure that the delete will occur sucessfully,
         * e.g. check permissions etc.
         */
@@ -435,7 +479,7 @@ RemoveTableSpace(List *names, DropBehavior behavior, bool 
missing_ok)
                 */
         if (persistentState != PersistentFileSysState_Created)
             continue;
-    
+
         MirroredFileSysObj_ScheduleDropDbDir(
                                         &dbDirNode,
                                         &persistentTid,
@@ -488,16 +532,16 @@ remove_tablespace_directories(Oid tablespaceoid, bool 
redo, char *phys)
        location = (char *) palloc(10 + 10 + 1);
        sprintf(location, "pg_tblspc/%u", tablespaceoid);
 
-       /* 
+       /*
         * If the tablespace location has been removed previously, then we are 
done.
-        * 
+        *
         */
        if (stat(location, &st) < 0)
        {
                ereport(WARNING,
                                (errmsg("directory linked to \"%s\" does not 
exist", location)
                                 ));
-                               
+
                return true;
        }
 
@@ -608,13 +652,13 @@ remove_tablespace_directories(Oid tablespaceoid, bool 
redo, char *phys)
        tempstr = palloc(MAXPGPATH);
 
        sprintf(tempstr,"%s",phys);
-       
+
        if (rmdir(tempstr) < 0)
                ereport(ERROR,
                                (errcode_for_file_access(),
                                 errmsg("could not remove subdirectory \"%s\": 
%m",
                                                tempstr)));
-       
+
        pfree(tempstr);
 
        return true;
@@ -698,7 +742,7 @@ set_short_version(const char *path, DbDirNode *dbDirNode, 
bool mirror)
                                        (errcode_for_file_access(),
                                         errmsg("could not write to file 
\"%s\": %m",
                                                        fullname)));
-                       
+
                FileClose(version_file);
 
                pfree(fullname);
@@ -758,7 +802,7 @@ RenameTableSpace(const char *oldname, const char *newname)
                        pcqCtx,
                        cql("SELECT * FROM pg_tablespace "
                                " WHERE spcname = :1 "
-                               " FOR UPDATE ", 
+                               " FOR UPDATE ",
                                CStringGetDatum(oldname)));
 
        if (!HeapTupleIsValid(newtuple))
@@ -833,7 +877,7 @@ AlterTableSpaceOwner(const char *name, Oid newOwnerId)
                        pcqCtx,
                        cql("SELECT * FROM pg_tablespace "
                                " WHERE spcname = :1 "
-                               " FOR UPDATE ", 
+                               " FOR UPDATE ",
                                CStringGetDatum(name)));
 
        if (!HeapTupleIsValid(tup))
@@ -1018,7 +1062,7 @@ get_tablespace_oid(const char *tablespacename)
        else
                tsoid = InvalidOid;
 
-       /* 
+       /*
         * Anything that needs to lookup a tablespace name must need a lock
         * on the tablespace for the duration of its transaction, otherwise
         * there is nothing preventing it from being dropped.
@@ -1031,7 +1075,7 @@ get_tablespace_oid(const char *tablespacename)
                TransactionId   update_xmax;
 
                /*
-                * Unfortunately locking of objects other than relations 
doesn't 
+                * Unfortunately locking of objects other than relations doesn't
                 * really work, the work around is to lock the tuple in 
pg_tablespace
                 * to prevent drops from getting the exclusive lock they need.
                 */
@@ -1052,7 +1096,7 @@ get_tablespace_oid(const char *tablespacename)
                        case HeapTupleBeingUpdated:
                                Assert(false);  /* Not possible with 
LockTupleWait */
                                /* fallthrough */
-                  
+
                        case HeapTupleUpdated:
                                ereport(ERROR,
                                                
(errcode(ERRCODE_T_R_SERIALIZATION_FAILURE),
@@ -1229,13 +1273,13 @@ tblspc_redo(XLogRecPtr beginLoc, XLogRecPtr lsn, 
XLogRecord *record)
                sublocation = palloc(MAXPGPATH);
 
                sprintf(sublocation,"%s",location);
-       
+
                if (mkdir(sublocation, 0700) != 0)
                        ereport(ERROR,
                                        (errcode_for_file_access(),
                                         errmsg("could not create subdirectory 
\"%s\": %m",
                                                        sublocation)));
-       
+
                /* Create or re-create the PG_VERSION file in the target 
directory */
                set_short_version(sublocation, NULL, false);
 
@@ -1306,7 +1350,7 @@ RejectAccessTablespace(Oid reltablespace, char *msg)
        if (!OidIsValid(reltablespace))
                return;
 
-       if (is_tablespace_shared_master(reltablespace))         
+       if (is_tablespace_shared_master(reltablespace))
                ereport(ERROR,
                                (errcode(ERRCODE_GP_FEATURE_NOT_SUPPORTED),
                                 errmsg(msg, 
get_tablespace_name(reltablespace)),

Reply via email to