bdr: fix command filter to check on the transformed ALTER TABLE statements
authorChristian Kruse <[email protected]>
Mon, 5 May 2014 15:32:18 +0000 (17:32 +0200)
committerAndres Freund <[email protected]>
Thu, 3 Jul 2014 15:55:30 +0000 (17:55 +0200)
contrib/bdr/bdr_commandfilter.c

index cccdedcf77d3ce1e98578f275f5997561a2fa293..cb17b4d1f8976f04111447639f9c6e388008863d 100644 (file)
@@ -26,6 +26,8 @@
 #include "commands/extension.h"
 #include "commands/tablecmds.h"
 
+#include "parser/parse_utilcmd.h"
+
 #include "tcop/utility.h"
 
 #include "utils/guc.h"
@@ -120,105 +122,130 @@ filter_CreateStmt(Node *parsetree,
 
 static void
 filter_AlterTableStmt(Node *parsetree,
-                  char *completionTag)
+                     char *completionTag,
+                     const char *queryString)
 {
    AlterTableStmt *astmt;
-   ListCell   *cell;
+   ListCell   *cell,
+              *cell1;
    bool        hasInvalid;
+   List       *stmts;
+   Oid         relid;
+   LOCKMODE    lockmode;
 
    astmt = (AlterTableStmt *) parsetree;
    hasInvalid = false;
 
-   foreach(cell, astmt->cmds)
+   lockmode = AlterTableGetLockLevel(astmt->cmds);
+   relid = AlterTableLookupRelation(astmt, lockmode);
+
+   stmts = transformAlterTableStmt(relid, astmt, queryString);
+
+   foreach(cell, stmts)
    {
-       AlterTableCmd *stmt;
+       Node       *node = (Node *) lfirst(cell);
+       AlterTableStmt *at_stmt;
+
+       /*
+        * we ignore all nodes which are not AlterTableCmd statements since
+        * the standard utility hook will recurse and thus call our handler
+        * again
+        */
+       if (!IsA(node, AlterTableStmt))
+           continue;
 
-       Assert(IsA(lfirst(cell), AlterTableCmd));
-       stmt = (AlterTableCmd *) lfirst(cell);
+       at_stmt = (AlterTableStmt *) node;
 
-       switch (stmt->subtype)
+       foreach(cell1, at_stmt->cmds)
        {
-           /*
-            * allowed for now:
-            */
-           case AT_AddColumn:
-               {
-                   ColumnDef *def = (ColumnDef *) stmt->def;
-                   ListCell   *cell;
+           AlterTableCmd *stmt = (AlterTableCmd *) lfirst(cell1);
 
+           switch (stmt->subtype)
+           {
                    /*
-                    * Error out if there's a default for the new
-                    * column, that requires a table rewrite which
-                    * might be nondeterministic.
+                    * allowed for now:
                     */
-                   if (def->raw_default != NULL ||
-                       def->cooked_default != NULL)
+               case AT_AddColumn:
                    {
-                       error_on_persistent_rv(
-                           astmt->relation,
-                           "ALTER TABLE ... ADD COLUMN ... DEFAULT",
-                           AlterTableGetLockLevel(astmt->cmds),
-                           astmt->missing_ok);
+                       ColumnDef  *def = (ColumnDef *) stmt->def;
+                       ListCell   *cell;
+
+                       /*
+                        * Error out if there's a default for the new column,
+                        * that requires a table rewrite which might be
+                        * nondeterministic.
+                        */
+                       if (def->raw_default != NULL ||
+                           def->cooked_default != NULL)
+                       {
+                           error_on_persistent_rv(
+                                                  astmt->relation,
+                                   "ALTER TABLE ... ADD COLUMN ... DEFAULT",
+                                        AlterTableGetLockLevel(astmt->cmds),
+                                                  astmt->missing_ok);
+                       }
+
+                       /*
+                        * Column defaults can also be represented as
+                        * constraints.
+                        */
+                       foreach(cell, def->constraints)
+                       {
+                           Constraint *con;
+
+                           Assert(IsA(lfirst(cell), Constraint));
+                           con = (Constraint *) lfirst(cell);
+
+                           if (con->contype == CONSTR_DEFAULT)
+                               error_on_persistent_rv(
+                                                      astmt->relation,
+                                   "ALTER TABLE ... ADD COLUMN ... DEFAULT",
+                                        AlterTableGetLockLevel(astmt->cmds),
+                                                      astmt->missing_ok);
+                       }
                    }
+               case AT_AddIndex: /* produced by for example ALTER TABLE … ADD
+                                  * CONSTRAINT … PRIMARY KEY */
+               case AT_DropColumn:
+               case AT_DropNotNull:
+               case AT_SetNotNull:
+               case AT_ColumnDefault:  /* ALTER COLUMN DEFAULT */
+
+               case AT_ClusterOn:      /* CLUSTER ON */
+               case AT_DropCluster:    /* SET WITHOUT CLUSTER */
+
+               case AT_SetRelOptions:  /* SET (...) */
+               case AT_ResetRelOptions:        /* RESET (...) */
+               case AT_ReplaceRelOptions:      /* replace reloption list */
+               case AT_ReplicaIdentity:
+               case AT_ChangeOwner:
+               case AT_SetStorage:
+                   break;
 
-                   /*
-                    * Column defaults can also be represented as
-                    * constraints.
-                    */
-                   foreach(cell, def->constraints)
-                   {
-                       Constraint *con;
+               case AT_DropConstraint:
+                   break;
 
-                       Assert(IsA(lfirst(cell), Constraint));
-                       con = (Constraint *) lfirst(cell);
+               case AT_SetTableSpace:
+                   break;
 
-                       if (con->contype == CONSTR_DEFAULT)
-                           error_on_persistent_rv(
-                               astmt->relation,
-                               "ALTER TABLE ... ADD COLUMN ... DEFAULT",
-                               AlterTableGetLockLevel(astmt->cmds),
-                               astmt->missing_ok);
+               case AT_AddConstraint:
+               case AT_ProcessedConstraint:
+                   if (IsA(stmt->def, Constraint))
+                   {
+                       Constraint *con = (Constraint *) stmt->def;
+
+                       if (con->contype == CONSTR_EXCLUSION)
+                           error_on_persistent_rv(astmt->relation,
+                               "ALTER TABLE ... ADD CONSTRAINT ... EXCLUDE",
+                                        AlterTableGetLockLevel(astmt->cmds),
+                                                  astmt->missing_ok);
                    }
-               }
-           case AT_DropColumn:
-           case AT_DropNotNull:
-           case AT_SetNotNull:
-           case AT_ColumnDefault:      /* ALTER COLUMN DEFAULT */
-
-           case AT_ClusterOn:          /* CLUSTER ON */
-           case AT_DropCluster:        /* SET WITHOUT CLUSTER */
-
-           case AT_SetRelOptions:      /* SET (...) */
-           case AT_ResetRelOptions:    /* RESET (...) */
-           case AT_ReplaceRelOptions:  /* replace reloption list */
-           case AT_ReplicaIdentity:
-           case AT_ChangeOwner:
-           case AT_SetStorage:
-               break;
-
-           case AT_DropConstraint:
-               break;
-
-           case AT_SetTableSpace:
-               break;
-
-           case AT_AddConstraint:
-           case AT_ProcessedConstraint:
-               if (IsA(stmt->def, Constraint))
-               {
-                   Constraint *con = (Constraint *) stmt->def;
-
-                   if (con->contype == CONSTR_EXCLUSION)
-                       error_on_persistent_rv(astmt->relation,
-                                              "ALTER TABLE ... ADD CONSTRAINT ... EXCLUDE",
-                                              AlterTableGetLockLevel(astmt->cmds),
-                                              astmt->missing_ok);
-               }
-               break;
-
-           default:
-               hasInvalid = true;
-               break;
+                   break;
+
+               default:
+                   hasInvalid = true;
+                   break;
+           }
        }
    }
 
@@ -347,7 +374,7 @@ bdr_commandfilter(Node *parsetree,
            break;
 
        case T_AlterTableStmt:
-           filter_AlterTableStmt(parsetree, completionTag);
+           filter_AlterTableStmt(parsetree, completionTag, queryString);
            break;
 
        case T_AlterDomainStmt: