Split out CreateCast into src/backend/catalog/pg_cast.c
authorAlvaro Herrera
Tue, 10 Mar 2020 14:28:23 +0000 (11:28 -0300)
committerAlvaro Herrera
Tue, 10 Mar 2020 14:28:23 +0000 (11:28 -0300)
This catalog-handling code was previously together with the rest of
CastCreate() in src/backend/commands/functioncmds.c.  A future patch
will need a way to add casts internally, so this will be useful to have
separate.

Also, move the nearby get_cast_oid() function from functioncmds.c to
lsyscache.c, which seems a more natural place for it.

Author: Paul Jungwirth, minor edits by Álvaro
Discussion: https://postgr.es/m/20200309210003[email protected]

src/backend/catalog/Makefile
src/backend/catalog/pg_cast.c [new file with mode: 0644]
src/backend/commands/functioncmds.c
src/backend/commands/typecmds.c
src/backend/utils/cache/lsyscache.c
src/include/catalog/pg_cast.h
src/include/commands/defrem.h
src/include/utils/lsyscache.h

index f8f0b4841c3fe105dec7e6d36dcb096e7a90a7a7..9499bb33e566e56a5178458ec4a886c0abefcd2d 100644 (file)
@@ -25,6 +25,7 @@ OBJS = \
    objectaddress.o \
    partition.o \
    pg_aggregate.o \
+   pg_cast.o \
    pg_collation.o \
    pg_constraint.o \
    pg_conversion.o \
diff --git a/src/backend/catalog/pg_cast.c b/src/backend/catalog/pg_cast.c
new file mode 100644 (file)
index 0000000..3854455
--- /dev/null
@@ -0,0 +1,123 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_cast.c
+ *   routines to support manipulation of the pg_cast relation
+ *
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *   src/backend/catalog/pg_cast.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup_details.h"
+#include "access/table.h"
+#include "catalog/catalog.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_cast.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
+#include "utils/builtins.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+/*
+ * ----------------------------------------------------------------
+ *     CastCreate
+ *
+ * Forms and inserts catalog tuples for a new cast being created.
+ * Caller must have already checked privileges, and done consistency
+ * checks on the given datatypes and cast function (if applicable).
+ *
+ * 'behavior' indicates the types of the dependencies that the new
+ * cast will have on its input and output types and the cast function.
+ * ----------------------------------------------------------------
+ */
+ObjectAddress
+CastCreate(Oid sourcetypeid, Oid targettypeid, Oid funcid, char castcontext,
+          char castmethod, DependencyType behavior)
+{
+   Relation        relation;
+   HeapTuple       tuple;
+   Oid             castid;
+   Datum           values[Natts_pg_cast];
+   bool            nulls[Natts_pg_cast];
+   ObjectAddress   myself,
+                   referenced;
+
+   relation = table_open(CastRelationId, RowExclusiveLock);
+
+   /*
+    * Check for duplicate.  This is just to give a friendly error message,
+    * the unique index would catch it anyway (so no need to sweat about race
+    * conditions).
+    */
+   tuple = SearchSysCache2(CASTSOURCETARGET,
+                           ObjectIdGetDatum(sourcetypeid),
+                           ObjectIdGetDatum(targettypeid));
+   if (HeapTupleIsValid(tuple))
+       ereport(ERROR,
+               (errcode(ERRCODE_DUPLICATE_OBJECT),
+                errmsg("cast from type %s to type %s already exists",
+                       format_type_be(sourcetypeid),
+                       format_type_be(targettypeid))));
+
+   /* ready to go */
+   castid = GetNewOidWithIndex(relation, CastOidIndexId, Anum_pg_cast_oid);
+   values[Anum_pg_cast_oid - 1] = ObjectIdGetDatum(castid);
+   values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
+   values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
+   values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
+   values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
+   values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
+
+   MemSet(nulls, false, sizeof(nulls));
+
+   tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
+
+   CatalogTupleInsert(relation, tuple);
+
+   /* make dependency entries */
+   myself.classId = CastRelationId;
+   myself.objectId = castid;
+   myself.objectSubId = 0;
+
+   /* dependency on source type */
+   referenced.classId = TypeRelationId;
+   referenced.objectId = sourcetypeid;
+   referenced.objectSubId = 0;
+   recordDependencyOn(&myself, &referenced, behavior);
+
+   /* dependency on target type */
+   referenced.classId = TypeRelationId;
+   referenced.objectId = targettypeid;
+   referenced.objectSubId = 0;
+   recordDependencyOn(&myself, &referenced, behavior);
+
+   /* dependency on function */
+   if (OidIsValid(funcid))
+   {
+       referenced.classId = ProcedureRelationId;
+       referenced.objectId = funcid;
+       referenced.objectSubId = 0;
+       recordDependencyOn(&myself, &referenced, behavior);
+   }
+
+   /* dependency on extension */
+   recordDependencyOnCurrentExtension(&myself, false);
+
+   /* Post creation hook for new cast */
+   InvokeObjectPostCreateHook(CastRelationId, castid, 0);
+
+   heap_freetuple(tuple);
+
+   table_close(relation, RowExclusiveLock);
+
+   return myself;
+}
index 43a23c69af30e42a9636720eb988c3cacdb09f8e..5eac55aaca196ebefe05b24d3006bbaa8314e16d 100644 (file)
@@ -1411,17 +1411,12 @@ CreateCast(CreateCastStmt *stmt)
    char        sourcetyptype;
    char        targettyptype;
    Oid         funcid;
-   Oid         castid;
    int         nargs;
    char        castcontext;
    char        castmethod;
-   Relation    relation;
    HeapTuple   tuple;
-   Datum       values[Natts_pg_cast];
-   bool        nulls[Natts_pg_cast];
-   ObjectAddress myself,
-               referenced;
    AclResult   aclresult;
+   ObjectAddress   myself;
 
    sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
    targettypeid = typenameTypeId(NULL, stmt->targettype);
@@ -1645,100 +1640,11 @@ CreateCast(CreateCastStmt *stmt)
            break;
    }
 
-   relation = table_open(CastRelationId, RowExclusiveLock);
-
-   /*
-    * Check for duplicate.  This is just to give a friendly error message,
-    * the unique index would catch it anyway (so no need to sweat about race
-    * conditions).
-    */
-   tuple = SearchSysCache2(CASTSOURCETARGET,
-                           ObjectIdGetDatum(sourcetypeid),
-                           ObjectIdGetDatum(targettypeid));
-   if (HeapTupleIsValid(tuple))
-       ereport(ERROR,
-               (errcode(ERRCODE_DUPLICATE_OBJECT),
-                errmsg("cast from type %s to type %s already exists",
-                       format_type_be(sourcetypeid),
-                       format_type_be(targettypeid))));
-
-   /* ready to go */
-   castid = GetNewOidWithIndex(relation, CastOidIndexId, Anum_pg_cast_oid);
-   values[Anum_pg_cast_oid - 1] = ObjectIdGetDatum(castid);
-   values[Anum_pg_cast_castsource - 1] = ObjectIdGetDatum(sourcetypeid);
-   values[Anum_pg_cast_casttarget - 1] = ObjectIdGetDatum(targettypeid);
-   values[Anum_pg_cast_castfunc - 1] = ObjectIdGetDatum(funcid);
-   values[Anum_pg_cast_castcontext - 1] = CharGetDatum(castcontext);
-   values[Anum_pg_cast_castmethod - 1] = CharGetDatum(castmethod);
-
-   MemSet(nulls, false, sizeof(nulls));
-
-   tuple = heap_form_tuple(RelationGetDescr(relation), values, nulls);
-
-   CatalogTupleInsert(relation, tuple);
-
-   /* make dependency entries */
-   myself.classId = CastRelationId;
-   myself.objectId = castid;
-   myself.objectSubId = 0;
-
-   /* dependency on source type */
-   referenced.classId = TypeRelationId;
-   referenced.objectId = sourcetypeid;
-   referenced.objectSubId = 0;
-   recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
-
-   /* dependency on target type */
-   referenced.classId = TypeRelationId;
-   referenced.objectId = targettypeid;
-   referenced.objectSubId = 0;
-   recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
-
-   /* dependency on function */
-   if (OidIsValid(funcid))
-   {
-       referenced.classId = ProcedureRelationId;
-       referenced.objectId = funcid;
-       referenced.objectSubId = 0;
-       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
-   }
-
-   /* dependency on extension */
-   recordDependencyOnCurrentExtension(&myself, false);
-
-   /* Post creation hook for new cast */
-   InvokeObjectPostCreateHook(CastRelationId, castid, 0);
-
-   heap_freetuple(tuple);
-
-   table_close(relation, RowExclusiveLock);
-
+   myself = CastCreate(sourcetypeid, targettypeid, funcid, castcontext,
+                       castmethod, DEPENDENCY_NORMAL);
    return myself;
 }
 
-/*
- * get_cast_oid - given two type OIDs, look up a cast OID
- *
- * If missing_ok is false, throw an error if the cast is not found.  If
- * true, just return InvalidOid.
- */
-Oid
-get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
-{
-   Oid         oid;
-
-   oid = GetSysCacheOid2(CASTSOURCETARGET, Anum_pg_cast_oid,
-                         ObjectIdGetDatum(sourcetypeid),
-                         ObjectIdGetDatum(targettypeid));
-   if (!OidIsValid(oid) && !missing_ok)
-       ereport(ERROR,
-               (errcode(ERRCODE_UNDEFINED_OBJECT),
-                errmsg("cast from type %s to type %s does not exist",
-                       format_type_be(sourcetypeid),
-                       format_type_be(targettypeid))));
-   return oid;
-}
-
 void
 DropCastById(Oid castOid)
 {
index b088ca848d38c0988aca9d9cb43a6c8e68f73a76..8891b1d56458ff2173c2abebb236de9e4a0547b4 100644 (file)
@@ -42,6 +42,7 @@
 #include "catalog/objectaccess.h"
 #include "catalog/pg_am.h"
 #include "catalog/pg_authid.h"
+#include "catalog/pg_cast.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_depend.h"
index 400e7689fe27916cc6ac4715746b1443644b1ed9..6b24369de8ff9b02740ad13dd5a4927c3c1f8ba3 100644 (file)
@@ -23,6 +23,7 @@
 #include "catalog/pg_am.h"
 #include "catalog/pg_amop.h"
 #include "catalog/pg_amproc.h"
+#include "catalog/pg_cast.h"
 #include "catalog/pg_collation.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_language.h"
@@ -908,6 +909,31 @@ get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
    ReleaseSysCache(tp);
 }
 
+/*             ---------- PG_CAST CACHE ----------                  */
+
+/*
+ * get_cast_oid - given two type OIDs, look up a cast OID
+ *
+ * If missing_ok is false, throw an error if the cast is not found.  If
+ * true, just return InvalidOid.
+ */
+Oid
+get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok)
+{
+   Oid         oid;
+
+   oid = GetSysCacheOid2(CASTSOURCETARGET, Anum_pg_cast_oid,
+                         ObjectIdGetDatum(sourcetypeid),
+                         ObjectIdGetDatum(targettypeid));
+   if (!OidIsValid(oid) && !missing_ok)
+       ereport(ERROR,
+               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                errmsg("cast from type %s to type %s does not exist",
+                       format_type_be(sourcetypeid),
+                       format_type_be(targettypeid))));
+   return oid;
+}
+
 /*             ---------- COLLATION CACHE ----------                    */
 
 /*
index 1b81b52df6b54fa854d2b6bd6be75831b9bdcd8c..2620ff40f05cbf7a75403a890233935a1809db0b 100644 (file)
@@ -20,6 +20,7 @@
 #ifndef PG_CAST_H
 #define PG_CAST_H
 
+#include "catalog/dependency.h"
 #include "catalog/genbki.h"
 #include "catalog/pg_cast_d.h"
 
@@ -87,4 +88,12 @@ typedef enum CoercionMethod
 
 #endif                         /* EXPOSE_TO_CLIENT_CODE */
 
+
+extern ObjectAddress CastCreate(Oid sourcetypeid,
+                               Oid targettypeid,
+                               Oid funcid,
+                               char castcontext,
+                               char castmethod,
+                               DependencyType behavior);
+
 #endif                         /* PG_CAST_H */
index 08ca6ac31e8d328db1d7f04e31bae9b25b074b60..c77c9a6ed5aea648e092a6ada88edcc0b0c208bb 100644 (file)
@@ -64,7 +64,6 @@ extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
 extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
 extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
 extern TupleDesc CallStmtResultDesc(CallStmt *stmt);
-extern Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok);
 extern Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
 extern void interpret_function_parameter_list(ParseState *pstate,
                                              List *parameters,
index 131d10eab07698b499eb18f972ef15b97791979f..6e93590befcd044aaf9d0b698ff93947c839d055 100644 (file)
@@ -90,6 +90,7 @@ extern char get_attgenerated(Oid relid, AttrNumber attnum);
 extern Oid get_atttype(Oid relid, AttrNumber attnum);
 extern void get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
                                  Oid *typid, int32 *typmod, Oid *collid);
+extern Oid get_cast_oid(Oid sourcetypeid, Oid targettypeid, bool missing_ok);
 extern char *get_collation_name(Oid colloid);
 extern bool get_collation_isdeterministic(Oid colloid);
 extern char *get_constraint_name(Oid conoid);