Before attempting to create a composite type, check whether a type of that
authorPeter Eisentraut <peter_e@gmx.net>
Wed, 20 Jan 2010 05:47:09 +0000 (05:47 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Wed, 20 Jan 2010 05:47:09 +0000 (05:47 +0000)
name already exists, so we'd get an error message about a "type" instead
of about a "relation", because the composite type code shares code with
relation creation.

src/backend/commands/typecmds.c

index 4b38fe957c7ef277ed1fb62df2de890703243e7c..7d5b409f59e9007360462df61526bc2721dcca7a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.145 2010/01/02 16:57:39 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.146 2010/01/20 05:47:09 petere Exp $
  *
  * DESCRIPTION
  *   The "DefineFoo" routines take the parse tree and pick out the
@@ -1509,6 +1509,8 @@ Oid
 DefineCompositeType(const RangeVar *typevar, List *coldeflist)
 {
    CreateStmt *createStmt = makeNode(CreateStmt);
+   Oid         old_type_oid;
+   Oid         typeNamespace;
 
    if (coldeflist == NIL)
        ereport(ERROR,
@@ -1528,7 +1530,26 @@ DefineCompositeType(const RangeVar *typevar, List *coldeflist)
    createStmt->tablespacename = NULL;
 
    /*
-    * finally create the relation...
+    * Check for collision with an existing type name. If there is one
+    * and it's an autogenerated array, we can rename it out of the
+    * way.  This check is here mainly to get a better error message
+    * about a "type" instead of below about a "relation".
+    */
+   typeNamespace = RangeVarGetCreationNamespace(createStmt->relation);
+   old_type_oid = GetSysCacheOid(TYPENAMENSP,
+                                 CStringGetDatum(createStmt->relation->relname),
+                                 ObjectIdGetDatum(typeNamespace),
+                                 0, 0);
+   if (OidIsValid(old_type_oid))
+   {
+       if (!moveArrayTypeName(old_type_oid, createStmt->relation->relname, typeNamespace))
+           ereport(ERROR,
+                   (errcode(ERRCODE_DUPLICATE_OBJECT),
+                    errmsg("type \"%s\" already exists", createStmt->relation->relname)));
+   }
+
+   /*
+    * Finally create the relation.  This also creates the type.
     */
    return DefineRelation(createStmt, RELKIND_COMPOSITE_TYPE);
 }