aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/catalog/Makefile1
-rw-r--r--src/backend/catalog/pg_cast.c123
-rw-r--r--src/backend/commands/functioncmds.c100
-rw-r--r--src/backend/commands/typecmds.c1
-rw-r--r--src/backend/utils/cache/lsyscache.c26
-rw-r--r--src/include/catalog/pg_cast.h9
-rw-r--r--src/include/commands/defrem.h1
-rw-r--r--src/include/utils/lsyscache.h1
8 files changed, 164 insertions, 98 deletions
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index f8f0b4841c3..9499bb33e56 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -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
index 00000000000..38544556371
--- /dev/null
+++ b/src/backend/catalog/pg_cast.c
@@ -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;
+}
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 43a23c69af3..5eac55aaca1 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -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)
{
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index b088ca848d3..8891b1d5645 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -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"
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index 400e7689fe2..6b24369de8f 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -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 ---------- */
/*
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
index 1b81b52df6b..2620ff40f05 100644
--- a/src/include/catalog/pg_cast.h
+++ b/src/include/catalog/pg_cast.h
@@ -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 */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 08ca6ac31e8..c77c9a6ed5a 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -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,
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index 131d10eab07..6e93590befc 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -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);