Prevent dropping distribution keys for MODULO
authorTomas Vondra <[email protected]>
Fri, 16 Jun 2017 20:59:48 +0000 (22:59 +0200)
committerTomas Vondra <[email protected]>
Sat, 17 Jun 2017 21:28:11 +0000 (23:28 +0200)
Due to a coding issue in IsDistColumnForRelId() it was possible to drop
columns that were used as modulo distribution keys. A simple example
demonstrates the behavior:

    CREATE TABLE t (a INT, b INT, c INT) DISTRIBUTE BY MODULO (a);
    ALTER TABLE t DROP COLUMN a;

    test=# \d+ t
                              Table "public.t"
     Column |  Type   | Modifiers | Storage | Stats target | Description
    --------+---------+-----------+---------+--------------+-------------
     b      | integer |           | plain   |              |
     c      | integer |           | plain   |              |
    Distribute By: MODULO(........pg.dropped.1........)
    Location Nodes: ALL DATANODES

With this commit, the ALTER TABLE command fails as expected:

    ERROR:  Distribution column cannot be dropped

The commit simplifies the coding a bit, and removes several functions
that were not needed anymore (and unused outside locator.c).

src/backend/pgxc/locator/locator.c
src/include/pgxc/locator.h
src/test/regress/expected/xl_alter_table.out
src/test/regress/sql/xl_alter_table.sql

index 2ecffe45ac80631761ac0c77c59654a666e20bc7..2c8aa676aea857fbd04f802a0943b263c0e91b7a 100644 (file)
@@ -260,38 +260,6 @@ GetRelationHashColumn(RelationLocInfo * rel_loc_info)
        return column_str;
 }
 
-/*
- * IsHashColumn - return whether or not column for relation is hashed.
- *
- */
-bool
-IsHashColumn(RelationLocInfo *rel_loc_info, char *part_col_name)
-{
-       bool            ret_value = false;
-
-       if (!rel_loc_info || !part_col_name)
-               ret_value = false;
-       else if (rel_loc_info->locatorType != LOCATOR_TYPE_HASH)
-               ret_value = false;
-       else
-               ret_value = !strcmp(part_col_name, rel_loc_info->partAttrName);
-
-       return ret_value;
-}
-
-
-/*
- * IsHashColumnForRelId - return whether or not column for relation is hashed.
- *
- */
-bool
-IsHashColumnForRelId(Oid relid, char *part_col_name)
-{
-       RelationLocInfo *rel_loc_info = GetRelationLocInfo(relid);
-
-       return IsHashColumn(rel_loc_info, part_col_name);
-}
-
 /*
  * IsDistColumnForRelId - return whether or not column for relation is used for hash or modulo distribution
  *
@@ -299,16 +267,22 @@ IsHashColumnForRelId(Oid relid, char *part_col_name)
 bool
 IsDistColumnForRelId(Oid relid, char *part_col_name)
 {
-       bool bRet;
        RelationLocInfo *rel_loc_info;
 
-       rel_loc_info = GetRelationLocInfo(relid);
-       bRet = false;
+       /* if no column is specified, we're done */
+       if (!part_col_name)
+               return false;
+
+       /* if no locator, we're done too */
+       if (!(rel_loc_info = GetRelationLocInfo(relid)))
+               return false;
+
+       /* is the table distributed by column value */
+       if (!IsRelationDistributedByValue(rel_loc_info))
+               return false;
 
-       bRet = IsHashColumn(rel_loc_info, part_col_name);
-       if (bRet == false)
-               IsModuloColumn(rel_loc_info, part_col_name);
-       return bRet;
+       /* does the column name match the distribution column */
+       return !strcmp(part_col_name, rel_loc_info->partAttrName);
 }
 
 
@@ -347,37 +321,6 @@ GetRelationModuloColumn(RelationLocInfo * rel_loc_info)
        return column_str;
 }
 
-/*
- * IsModuloColumn - return whether or not column for relation is used for modulo distribution.
- *
- */
-bool
-IsModuloColumn(RelationLocInfo *rel_loc_info, char *part_col_name)
-{
-       bool            ret_value = false;
-
-       if (!rel_loc_info || !part_col_name)
-               ret_value = false;
-       else if (rel_loc_info->locatorType != LOCATOR_TYPE_MODULO)
-               ret_value = false;
-       else
-               ret_value = !strcmp(part_col_name, rel_loc_info->partAttrName);
-
-       return ret_value;
-}
-
-
-/*
- * IsModuloColumnForRelId - return whether or not column for relation is used for modulo distribution.
- */
-bool
-IsModuloColumnForRelId(Oid relid, char *part_col_name)
-{
-       RelationLocInfo *rel_loc_info = GetRelationLocInfo(relid);
-
-       return IsModuloColumn(rel_loc_info, part_col_name);
-}
-
 /*
  * Update the round robin node for the relation
  *
index 5062cebe8311760e839bbb41fdae7b52749d0621..21c7e3fe1d6f58e836b099f6f18349bc8257269d 100644 (file)
@@ -162,8 +162,6 @@ extern RelationLocInfo *CopyRelationLocInfo(RelationLocInfo *src_info);
 extern char GetRelationLocType(Oid relid);
 extern bool IsTableDistOnPrimary(RelationLocInfo *rel_loc_info);
 extern bool IsLocatorInfoEqual(RelationLocInfo *rel_loc_info1, RelationLocInfo *rel_loc_info2);
-extern bool IsHashColumn(RelationLocInfo *rel_loc_info, char *part_col_name);
-extern bool IsHashColumnForRelId(Oid relid, char *part_col_name);
 extern int     GetRoundRobinNode(Oid relid);
 extern ExecNodes *GetRelationNodes(RelationLocInfo *rel_loc_info,
                                                                   Datum valueForDistCol,
@@ -184,8 +182,6 @@ extern void FreeRelationLocInfo(RelationLocInfo *relationLocInfo);
 
 extern bool IsTypeModuloDistributable(Oid col_type);
 extern char *GetRelationModuloColumn(RelationLocInfo *rel_loc_info);
-extern bool IsModuloColumn(RelationLocInfo *rel_loc_info, char *part_col_name);
-extern bool IsModuloColumnForRelId(Oid relid, char *part_col_name);
 extern char *GetRelationDistColumn(RelationLocInfo *rel_loc_info);
 extern bool IsDistColumnForRelId(Oid relid, char *part_col_name);
 extern void FreeExecNodes(ExecNodes **exec_nodes);
index 6d578b898ab19bf51b7be25cab35197473926d6d..edfe8b6d13be57f672d5608a0b1c5e571450d4e3 100755 (executable)
@@ -82,6 +82,8 @@ CREATE TABLE xl_at2m (
     product_no INT8,
     product_id INT2
 ) DISTRIBUTE BY MODULO (product_id); 
+ALTER TABLE xl_at2m DROP COLUMN product_id;--fail - distribution column cannot be dropped. 
+ERROR:  Distribution column cannot be dropped
 ALTER TABLE xl_at2m DISTRIBUTE BY HASH(product_id);
 ALTER TABLE xl_at2m DISTRIBUTE BY MODULO(product_id);
 ALTER TABLE xl_at2m DROP COLUMN product_no;
index 1f1c112b2b10c976c5bb85729a4b5b4e8446a322..5e2477cc5e25c672648e001263ffcd35e9bb52d7 100755 (executable)
@@ -137,6 +137,8 @@ CREATE TABLE xl_at2m (
     product_id INT2
 ) DISTRIBUTE BY MODULO (product_id); 
 
+ALTER TABLE xl_at2m DROP COLUMN product_id;--fail - distribution column cannot be dropped. 
+
 ALTER TABLE xl_at2m DISTRIBUTE BY HASH(product_id);
 
 ALTER TABLE xl_at2m DISTRIBUTE BY MODULO(product_id);