Commits

Andrew Dunstan  committed 70eecd5

initial working version of add enum value if not exists

  • Participants
  • Parent commits c246eb5
  • Branches add_enum_ine

Comments (0)

Files changed (7)

File src/backend/catalog/pg_enum.c

 AddEnumLabel(Oid enumTypeOid,
 			 const char *newVal,
 			 const char *neighbor,
-			 bool newValIsAfter)
+			 bool newValIsAfter,
+	         bool skipIfExists)
 {
 	Relation	pg_enum;
 	Oid			newOid;
 				 errdetail("Labels must be %d characters or less.",
 						   NAMEDATALEN - 1)));
 
+	/* Do the "IF NOT EXISTS" test if specified */
+	if (skipIfExists)
+	{
+		HeapTuple tup;
+
+		tup = SearchSysCache2(ENUMTYPOIDNAME,
+							  ObjectIdGetDatum(enumTypeOid),
+							  CStringGetDatum(newVal));
+		if (HeapTupleIsValid(tup))
+		{
+			ReleaseSysCache(tup);
+			return;
+		}
+	}
+
 	/*
 	 * Acquire a lock on the enum type, which we won't release until commit.
 	 * This ensures that two backends aren't concurrently modifying the same

File src/backend/commands/typecmds.c

 
 	/* Add the new label */
 	AddEnumLabel(enum_type_oid, stmt->newVal,
-				 stmt->newValNeighbor, stmt->newValIsAfter);
+				 stmt->newValNeighbor, stmt->newValIsAfter, 
+				 stmt->skipIfExists);
 
 	ReleaseSysCache(tup);
 }

File src/backend/nodes/copyfuncs.c

 	COPY_STRING_FIELD(newVal);
 	COPY_STRING_FIELD(newValNeighbor);
 	COPY_SCALAR_FIELD(newValIsAfter);
+	COPY_SCALAR_FIELD(skipIfExists);
 
 	return newnode;
 }

File src/backend/nodes/equalfuncs.c

 	COMPARE_STRING_FIELD(newVal);
 	COMPARE_STRING_FIELD(newValNeighbor);
 	COMPARE_SCALAR_FIELD(newValIsAfter);
+	COMPARE_SCALAR_FIELD(skipIfExists);
 
 	return true;
 }

File src/backend/parser/gram.y

 %type <windef>	window_definition over_clause window_specification
 				opt_frame_clause frame_extent frame_bound
 %type <str>		opt_existing_window_name
-
+%type <boolean> IfNotExists
 
 /*
  * Non-keyword token types.  These are hard-wired into the "flex" lexer.
  *****************************************************************************/
 
 AlterEnumStmt:
-		ALTER TYPE_P any_name ADD_P VALUE_P Sconst
+		ALTER TYPE_P any_name ADD_P VALUE_P IfNotExists Sconst
 			{
 				AlterEnumStmt *n = makeNode(AlterEnumStmt);
 				n->typeName = $3;
-				n->newVal = $6;
+				n->newVal = $7;
 				n->newValNeighbor = NULL;
 				n->newValIsAfter = true;
+				n->skipIfExists = $6;
 				$$ = (Node *) n;
 			}
-		 | ALTER TYPE_P any_name ADD_P VALUE_P Sconst BEFORE Sconst
+		 | ALTER TYPE_P any_name ADD_P VALUE_P IfNotExists Sconst BEFORE Sconst
 			{
 				AlterEnumStmt *n = makeNode(AlterEnumStmt);
 				n->typeName = $3;
-				n->newVal = $6;
-				n->newValNeighbor = $8;
+				n->newVal = $7;
+				n->newValNeighbor = $9;
 				n->newValIsAfter = false;
+				n->skipIfExists = $6;
 				$$ = (Node *) n;
 			}
-		 | ALTER TYPE_P any_name ADD_P VALUE_P Sconst AFTER Sconst
+		 | ALTER TYPE_P any_name ADD_P VALUE_P IfNotExists Sconst AFTER Sconst
 			{
 				AlterEnumStmt *n = makeNode(AlterEnumStmt);
 				n->typeName = $3;
-				n->newVal = $6;
-				n->newValNeighbor = $8;
+				n->newVal = $7;
+				n->newValNeighbor = $9;
 				n->newValIsAfter = true;
+				n->skipIfExists = $6;
 				$$ = (Node *) n;
 			}
 		 ;
 
+IfNotExists: IF_P NOT EXISTS { $$ = true; }
+           | /* empty */ { $$ = false; }
+           ;
+
 
 /*****************************************************************************
  *

File src/include/catalog/pg_enum.h

 extern void EnumValuesCreate(Oid enumTypeOid, List *vals);
 extern void EnumValuesDelete(Oid enumTypeOid);
 extern void AddEnumLabel(Oid enumTypeOid, const char *newVal,
-			 const char *neighbor, bool newValIsAfter);
+						 const char *neighbor, bool newValIsAfter, 
+						 bool skipIfExists);
 
 #endif   /* PG_ENUM_H */

File src/include/nodes/parsenodes.h

 	char	   *newVal;			/* new enum value's name */
 	char	   *newValNeighbor; /* neighboring enum value, if specified */
 	bool		newValIsAfter;	/* place new enum value after neighbor? */
+	bool        skipIfExists;   /* ignore statement if label already exists */
 } AlterEnumStmt;
 
 /* ----------------------