mirror of
https://github.com/postgres/postgres.git
synced 2025-06-08 22:02:03 +03:00
Split out CreateCast into src/backend/catalog/pg_cast.c
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.GA19992@alvherre.pgsql
This commit is contained in:
parent
0a42a2e9ce
commit
40b3e2c201
@ -25,6 +25,7 @@ OBJS = \
|
|||||||
objectaddress.o \
|
objectaddress.o \
|
||||||
partition.o \
|
partition.o \
|
||||||
pg_aggregate.o \
|
pg_aggregate.o \
|
||||||
|
pg_cast.o \
|
||||||
pg_collation.o \
|
pg_collation.o \
|
||||||
pg_constraint.o \
|
pg_constraint.o \
|
||||||
pg_conversion.o \
|
pg_conversion.o \
|
||||||
|
123
src/backend/catalog/pg_cast.c
Normal file
123
src/backend/catalog/pg_cast.c
Normal file
@ -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;
|
||||||
|
}
|
@ -1411,17 +1411,12 @@ CreateCast(CreateCastStmt *stmt)
|
|||||||
char sourcetyptype;
|
char sourcetyptype;
|
||||||
char targettyptype;
|
char targettyptype;
|
||||||
Oid funcid;
|
Oid funcid;
|
||||||
Oid castid;
|
|
||||||
int nargs;
|
int nargs;
|
||||||
char castcontext;
|
char castcontext;
|
||||||
char castmethod;
|
char castmethod;
|
||||||
Relation relation;
|
|
||||||
HeapTuple tuple;
|
HeapTuple tuple;
|
||||||
Datum values[Natts_pg_cast];
|
|
||||||
bool nulls[Natts_pg_cast];
|
|
||||||
ObjectAddress myself,
|
|
||||||
referenced;
|
|
||||||
AclResult aclresult;
|
AclResult aclresult;
|
||||||
|
ObjectAddress myself;
|
||||||
|
|
||||||
sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
|
sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
|
||||||
targettypeid = typenameTypeId(NULL, stmt->targettype);
|
targettypeid = typenameTypeId(NULL, stmt->targettype);
|
||||||
@ -1645,100 +1640,11 @@ CreateCast(CreateCastStmt *stmt)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
relation = table_open(CastRelationId, RowExclusiveLock);
|
myself = CastCreate(sourcetypeid, targettypeid, funcid, castcontext,
|
||||||
|
castmethod, DEPENDENCY_NORMAL);
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
return myself;
|
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
|
void
|
||||||
DropCastById(Oid castOid)
|
DropCastById(Oid castOid)
|
||||||
{
|
{
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "catalog/objectaccess.h"
|
#include "catalog/objectaccess.h"
|
||||||
#include "catalog/pg_am.h"
|
#include "catalog/pg_am.h"
|
||||||
#include "catalog/pg_authid.h"
|
#include "catalog/pg_authid.h"
|
||||||
|
#include "catalog/pg_cast.h"
|
||||||
#include "catalog/pg_collation.h"
|
#include "catalog/pg_collation.h"
|
||||||
#include "catalog/pg_constraint.h"
|
#include "catalog/pg_constraint.h"
|
||||||
#include "catalog/pg_depend.h"
|
#include "catalog/pg_depend.h"
|
||||||
|
26
src/backend/utils/cache/lsyscache.c
vendored
26
src/backend/utils/cache/lsyscache.c
vendored
@ -23,6 +23,7 @@
|
|||||||
#include "catalog/pg_am.h"
|
#include "catalog/pg_am.h"
|
||||||
#include "catalog/pg_amop.h"
|
#include "catalog/pg_amop.h"
|
||||||
#include "catalog/pg_amproc.h"
|
#include "catalog/pg_amproc.h"
|
||||||
|
#include "catalog/pg_cast.h"
|
||||||
#include "catalog/pg_collation.h"
|
#include "catalog/pg_collation.h"
|
||||||
#include "catalog/pg_constraint.h"
|
#include "catalog/pg_constraint.h"
|
||||||
#include "catalog/pg_language.h"
|
#include "catalog/pg_language.h"
|
||||||
@ -908,6 +909,31 @@ get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
|
|||||||
ReleaseSysCache(tp);
|
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 ---------- */
|
/* ---------- COLLATION CACHE ---------- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#ifndef PG_CAST_H
|
#ifndef PG_CAST_H
|
||||||
#define PG_CAST_H
|
#define PG_CAST_H
|
||||||
|
|
||||||
|
#include "catalog/dependency.h"
|
||||||
#include "catalog/genbki.h"
|
#include "catalog/genbki.h"
|
||||||
#include "catalog/pg_cast_d.h"
|
#include "catalog/pg_cast_d.h"
|
||||||
|
|
||||||
@ -87,4 +88,12 @@ typedef enum CoercionMethod
|
|||||||
|
|
||||||
#endif /* EXPOSE_TO_CLIENT_CODE */
|
#endif /* EXPOSE_TO_CLIENT_CODE */
|
||||||
|
|
||||||
|
|
||||||
|
extern ObjectAddress CastCreate(Oid sourcetypeid,
|
||||||
|
Oid targettypeid,
|
||||||
|
Oid funcid,
|
||||||
|
char castcontext,
|
||||||
|
char castmethod,
|
||||||
|
DependencyType behavior);
|
||||||
|
|
||||||
#endif /* PG_CAST_H */
|
#endif /* PG_CAST_H */
|
||||||
|
@ -64,7 +64,6 @@ extern void IsThereFunctionInNamespace(const char *proname, int pronargs,
|
|||||||
extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
|
extern void ExecuteDoStmt(DoStmt *stmt, bool atomic);
|
||||||
extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
|
extern void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest);
|
||||||
extern TupleDesc CallStmtResultDesc(CallStmt *stmt);
|
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 Oid get_transform_oid(Oid type_id, Oid lang_id, bool missing_ok);
|
||||||
extern void interpret_function_parameter_list(ParseState *pstate,
|
extern void interpret_function_parameter_list(ParseState *pstate,
|
||||||
List *parameters,
|
List *parameters,
|
||||||
|
@ -90,6 +90,7 @@ extern char get_attgenerated(Oid relid, AttrNumber attnum);
|
|||||||
extern Oid get_atttype(Oid relid, AttrNumber attnum);
|
extern Oid get_atttype(Oid relid, AttrNumber attnum);
|
||||||
extern void get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
|
extern void get_atttypetypmodcoll(Oid relid, AttrNumber attnum,
|
||||||
Oid *typid, int32 *typmod, Oid *collid);
|
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 char *get_collation_name(Oid colloid);
|
||||||
extern bool get_collation_isdeterministic(Oid colloid);
|
extern bool get_collation_isdeterministic(Oid colloid);
|
||||||
extern char *get_constraint_name(Oid conoid);
|
extern char *get_constraint_name(Oid conoid);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user