Add some sanity checks to CREATE CAST ... WITHOUT FUNCTION. Disallow
authorHeikki Linnakangas <heikki@enterprisedb.com>
Wed, 4 Mar 2009 11:53:53 +0000 (11:53 +0000)
committerHeikki Linnakangas <heikki@enterprisedb.com>
Wed, 4 Mar 2009 11:53:53 +0000 (11:53 +0000)
composite, enum and array types, as those are surely not binary-compatible
with anything else because of the embedded OIDs.

Inspired by bug report by Oleg Serov.

src/backend/commands/functioncmds.c

index d8a9dae90bb85d9a61f0e723536460e1d5e79448..7ed97a37a263c6ba83eb9959d3b066bb72f4c73d 100644 (file)
@@ -1470,6 +1470,8 @@ CreateCast(CreateCastStmt *stmt)
 {
        Oid                     sourcetypeid;
        Oid                     targettypeid;
+       char            sourcetyptype;
+       char            targettyptype;
        Oid                     funcid;
        int                     nargs;
        char            castcontext;
@@ -1483,15 +1485,17 @@ CreateCast(CreateCastStmt *stmt)
 
        sourcetypeid = typenameTypeId(NULL, stmt->sourcetype, NULL);
        targettypeid = typenameTypeId(NULL, stmt->targettype, NULL);
+       sourcetyptype = get_typtype(sourcetypeid);
+       targettyptype = get_typtype(targettypeid);
 
        /* No pseudo-types allowed */
-       if (get_typtype(sourcetypeid) == TYPTYPE_PSEUDO)
+       if (sourcetyptype == TYPTYPE_PSEUDO)
                ereport(ERROR,
                                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                 errmsg("source data type %s is a pseudo-type",
                                                TypeNameToString(stmt->sourcetype))));
 
-       if (get_typtype(targettypeid) == TYPTYPE_PSEUDO)
+       if (targettyptype == TYPTYPE_PSEUDO)
                ereport(ERROR,
                                (errcode(ERRCODE_WRONG_OBJECT_TYPE),
                                 errmsg("target data type %s is a pseudo-type",
@@ -1615,6 +1619,33 @@ CreateCast(CreateCastStmt *stmt)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
                                         errmsg("source and target data types are not physically compatible")));
+
+               /*
+                * We know that composite, enum and array types are never binary-
+                * compatible with each other.  They all have OIDs embedded in them.
+                *
+                * Theoretically you could build a user-defined base type that is
+                * binary-compatible with a composite, enum, or array type.  But we
+                * disallow that too, as in practice such a cast is surely a mistake.
+                * You can always work around that by writing a cast function.
+                */
+               if (sourcetyptype == TYPTYPE_COMPOSITE ||
+                       targettyptype == TYPTYPE_COMPOSITE)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                        errmsg("composite data types are not binary-compatible")));
+
+               if (sourcetyptype == TYPTYPE_ENUM ||
+                       targettyptype == TYPTYPE_ENUM)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                        errmsg("enum data types are not binary-compatible")));
+
+               if (OidIsValid(get_element_type(sourcetypeid)) ||
+                       OidIsValid(get_element_type(targettypeid)))
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+                                        errmsg("array data types are not binary-compatible")));
        }
 
        /*