From: Alvaro Herrera <alvherre@2ndquadrant.com>
To: Pg Hackers <pgsql-hackers@lists.postgresql.org>
Subject: time for catalog/pg_cast.c?
Date: Mon, 9 Mar 2020 18:00:03 -0300
Message-ID: <20200309210003.GA19992@alvherre.pgsql> (raw)
I extracted from the latest multirange patch a bit that creates a new
routine CastCreate() in src/backend/catalog/pg_cast.c. It contains the
catalog-accessing bits to create a new cast. It seems harmless, so I
thought I'd apply it to get rid of a couple of hunks in the large patch.
(I also threw in a move of get_cast_oid from functioncmds.c to
lsyscache.c, which seems its natural place; at first I thought to put it
in catalog/pg_cast.c but really it's not a great place IMO. This
function was invented out of whole cloth in commit fd1843ff8979. I also
contemplated the move of CreateCast and DropCastById from functioncmds.c
to some new place, but creating a new commands/castcmds.c seemed a bit
excessive, so I left them in their current locations.)
--
Álvaro Herrera 39°49'30"S 73°17'W
"The problem with the future is that it keeps turning into the present"
(Hobbes)
Attachments:
[text/x-diff] pg_cast.patch (11.8K, ../20200309210003.GA19992@alvherre.pgsql/2-pg_cast.patch)
download | inline diff:
commit 928aa3fa75a2f244dfb3ac08c4b4d166e426f9cf
Author: Alvaro Herrera <alvherre@alvh.no-ip.org>
AuthorDate: Mon Mar 9 17:19:50 2020 -0300
CommitDate: Mon Mar 9 17:59:30 2020 -0300
add pg_cast.c for CastCreate()
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefileindex f8f0b4841c..9499bb33e5 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.cnew file mode 100644index 0000000000..19f410337d--- /dev/null+++ b/src/backend/catalog/pg_cast.c@@ -0,0 +1,116 @@+/*-------------------------------------------------------------------------+ *+ * 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+ * ----------------------------------------------------------------+ */+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.cindex 43a23c69af..5eac55aaca 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.cindex b088ca848d..8891b1d564 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.cindex 3da90cb72a..1955b846c2 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.hindex 1b81b52df6..2620ff40f0 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.hindex 5cd6975a22..cdb752243f 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.hindex f132d39458..52d4c77260 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);
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: alvherre@2ndquadrant.com, pgsql-hackers@lists.postgresql.org
Subject: Re: time for catalog/pg_cast.c?
In-Reply-To: <20200309210003.GA19992@alvherre.pgsql>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox