aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/catalog/Makefile4
-rw-r--r--src/backend/catalog/dependency.c17
-rw-r--r--src/backend/catalog/indexing.c4
-rw-r--r--src/backend/catalog/pg_aggregate.c3
-rw-r--r--src/backend/catalog/pg_proc.c5
-rw-r--r--src/backend/commands/functioncmds.c252
-rw-r--r--src/backend/parser/gram.y138
-rw-r--r--src/backend/parser/keywords.c3
-rw-r--r--src/backend/parser/parse_coerce.c96
-rw-r--r--src/backend/tcop/postgres.c12
-rw-r--r--src/backend/tcop/utility.c10
-rw-r--r--src/backend/utils/adt/ruleutils.c45
-rw-r--r--src/backend/utils/adt/sets.c3
-rw-r--r--src/backend/utils/cache/syscache.c14
-rw-r--r--src/bin/initdb/initdb.sh3
-rw-r--r--src/bin/pg_dump/common.c26
-rw-r--r--src/bin/pg_dump/pg_dump.c113
-rw-r--r--src/bin/pg_dump/pg_dump.h5
-rw-r--r--src/include/catalog/catname.h3
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/catalog/indexing.h6
-rw-r--r--src/include/catalog/pg_cast.h225
-rw-r--r--src/include/catalog/pg_proc.h5
-rw-r--r--src/include/commands/defrem.h5
-rw-r--r--src/include/nodes/nodes.h4
-rw-r--r--src/include/nodes/parsenodes.h28
-rw-r--r--src/include/utils/syscache.h49
-rw-r--r--src/test/regress/expected/opr_sanity.out59
-rw-r--r--src/test/regress/expected/sanity_check.out3
-rw-r--r--src/test/regress/sql/opr_sanity.sql50
30 files changed, 925 insertions, 269 deletions
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 22e033524ee..37681565ecf 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -2,7 +2,7 @@
#
# Makefile for backend/catalog
#
-# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.41 2002/07/12 18:43:13 tgl Exp $
+# $Header: /cvsroot/pgsql/src/backend/catalog/Makefile,v 1.42 2002/07/18 23:11:27 petere Exp $
#
#-------------------------------------------------------------------------
@@ -30,7 +30,7 @@ POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
pg_attrdef.h pg_constraint.h pg_inherits.h pg_index.h \
pg_operator.h pg_opclass.h pg_am.h pg_amop.h pg_amproc.h \
pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \
- pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h \
+ pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h pg_cast.h \
pg_namespace.h pg_conversion.h pg_database.h pg_shadow.h pg_group.h \
pg_depend.h indexing.h \
)
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index d2dc8b3795a..638843c3e07 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.4 2002/07/18 16:47:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.5 2002/07/18 23:11:27 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -47,6 +47,7 @@
/* This enum covers all system catalogs whose OIDs can appear in classid. */
typedef enum ObjectClasses
{
+ OCLASS_CAST, /* pg_cast */
OCLASS_CLASS, /* pg_class */
OCLASS_PROC, /* pg_proc */
OCLASS_TYPE, /* pg_type */
@@ -604,6 +605,10 @@ doDeletion(const ObjectAddress *object)
RemoveSchemaById(object->objectId);
break;
+ case OCLASS_CAST:
+ DropCastById(object->objectId);
+ break;
+
default:
elog(ERROR, "doDeletion: Unsupported object class %u",
object->classId);
@@ -979,6 +984,7 @@ term_object_addresses(ObjectAddresses *addrs)
static void
init_object_classes(void)
{
+ object_classes[OCLASS_CAST] = get_system_catalog_relid(CastRelationName);
object_classes[OCLASS_CLASS] = RelOid_pg_class;
object_classes[OCLASS_PROC] = RelOid_pg_proc;
object_classes[OCLASS_TYPE] = RelOid_pg_type;
@@ -1023,6 +1029,11 @@ getObjectClass(const ObjectAddress *object)
if (!object_classes_initialized)
init_object_classes();
+ if (object->classId == object_classes[OCLASS_CAST])
+ {
+ Assert(object->objectSubId == 0);
+ return OCLASS_CAST;
+ }
if (object->classId == object_classes[OCLASS_CONSTRAINT])
{
Assert(object->objectSubId == 0);
@@ -1078,6 +1089,10 @@ getObjectDescription(const ObjectAddress *object)
switch (getObjectClass(object))
{
+ case OCLASS_CAST:
+ appendStringInfo(&buffer, "cast");
+ break;
+
case OCLASS_CLASS:
getRelationDescription(&buffer, object->objectId);
if (object->objectSubId != 0)
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 9f16b4d4cc1..80e3a15cf57 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.97 2002/07/15 16:33:31 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.98 2002/07/18 23:11:27 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -43,6 +43,8 @@ char *Name_pg_attr_indices[Num_pg_attr_indices] =
{AttributeRelidNameIndex, AttributeRelidNumIndex};
char *Name_pg_attrdef_indices[Num_pg_attrdef_indices] =
{AttrDefaultIndex, AttrDefaultOidIndex};
+char *Name_pg_cast_indices[Num_pg_cast_indices] =
+{CastSourceTargetIndex};
char *Name_pg_class_indices[Num_pg_class_indices] =
{ClassNameNspIndex, ClassOidIndex};
char *Name_pg_constraint_indices[Num_pg_constraint_indices] =
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index 28d7e83f575..189db5d77da 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.50 2002/07/16 22:12:18 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.51 2002/07/18 23:11:27 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -144,7 +144,6 @@ AggregateCreate(const char *aggName,
"-", /* probin */
true, /* isAgg */
false, /* security invoker (currently not definable for agg) */
- false, /* isImplicit */
false, /* isStrict (not needed for agg) */
PROVOLATILE_IMMUTABLE, /* volatility (not needed for agg) */
BYTE_PCT, /* default cost values */
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index f8693fa7fec..29cfbb9b46e 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.78 2002/07/18 16:47:23 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.79 2002/07/18 23:11:27 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -55,7 +55,6 @@ ProcedureCreate(const char *procedureName,
const char *probin,
bool isAgg,
bool security_definer,
- bool isImplicit,
bool isStrict,
char volatility,
int32 byte_pct,
@@ -163,7 +162,7 @@ ProcedureCreate(const char *procedureName,
values[i++] = ObjectIdGetDatum(languageObjectId); /* prolang */
values[i++] = BoolGetDatum(isAgg); /* proisagg */
values[i++] = BoolGetDatum(security_definer); /* prosecdef */
- values[i++] = BoolGetDatum(isImplicit); /* proimplicit */
+ values[i++] = BoolGetDatum(false); /* proimplicit */
values[i++] = BoolGetDatum(isStrict); /* proisstrict */
values[i++] = BoolGetDatum(returnsSet); /* proretset */
values[i++] = CharGetDatum(volatility); /* provolatile */
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 9a33810b073..2ed9581b665 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.8 2002/07/12 18:43:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.9 2002/07/18 23:11:27 petere Exp $
*
* DESCRIPTION
* These routines take the parse tree and pick out the
@@ -34,7 +34,9 @@
#include "access/heapam.h"
#include "catalog/catname.h"
#include "catalog/dependency.h"
+#include "catalog/indexing.h"
#include "catalog/namespace.h"
+#include "catalog/pg_cast.h"
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
@@ -44,6 +46,7 @@
#include "parser/parse_func.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
+#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
@@ -171,8 +174,7 @@ compute_attributes_sql_style(const List *options,
char **language,
char *volatility_p,
bool *strict_p,
- bool *security_definer,
- bool *implicit_cast)
+ bool *security_definer)
{
const List *option;
DefElem *as_item = NULL;
@@ -180,7 +182,6 @@ compute_attributes_sql_style(const List *options,
DefElem *volatility_item = NULL;
DefElem *strict_item = NULL;
DefElem *security_item = NULL;
- DefElem *implicit_item = NULL;
foreach(option, options)
{
@@ -216,12 +217,6 @@ compute_attributes_sql_style(const List *options,
elog(ERROR, "conflicting or redundant options");
security_item = defel;
}
- else if (strcmp(defel->defname, "implicit")==0)
- {
- if (implicit_item)
- elog(ERROR, "conflicting or redundant options");
- implicit_item = defel;
- }
else
elog(ERROR, "invalid CREATE FUNCTION option");
}
@@ -252,8 +247,6 @@ compute_attributes_sql_style(const List *options,
*strict_p = intVal(strict_item->arg);
if (security_item)
*security_definer = intVal(security_item->arg);
- if (implicit_item)
- *implicit_cast = intVal(implicit_item->arg);
}
@@ -264,10 +257,7 @@ compute_attributes_sql_style(const List *options,
* These parameters supply optional information about a function.
* All have defaults if not specified.
*
- * Note: currently, only three of these parameters actually do anything:
- *
- * * isImplicit means the function may be used as an implicit type
- * coercion.
+ * Note: currently, only two of these parameters actually do anything:
*
* * isStrict means the function should not be called when any NULL
* inputs are present; instead a NULL result value should be assumed.
@@ -284,7 +274,7 @@ static void
compute_attributes_with_style(List *parameters,
int32 *byte_pct_p, int32 *perbyte_cpu_p,
int32 *percall_cpu_p, int32 *outin_ratio_p,
- bool *isImplicit_p, bool *isStrict_p,
+ bool *isStrict_p,
char *volatility_p)
{
List *pl;
@@ -293,9 +283,7 @@ compute_attributes_with_style(List *parameters,
{
DefElem *param = (DefElem *) lfirst(pl);
- if (strcasecmp(param->defname, "implicitcoercion") == 0)
- *isImplicit_p = true;
- else if (strcasecmp(param->defname, "isstrict") == 0)
+ if (strcasecmp(param->defname, "isstrict") == 0)
*isStrict_p = true;
else if (strcasecmp(param->defname, "isimmutable") == 0)
*volatility_p = PROVOLATILE_IMMUTABLE;
@@ -398,8 +386,7 @@ CreateFunction(CreateFunctionStmt *stmt)
perbyte_cpu,
percall_cpu,
outin_ratio;
- bool isImplicit,
- isStrict,
+ bool isStrict,
security;
char volatility;
HeapTuple languageTuple;
@@ -420,14 +407,13 @@ CreateFunction(CreateFunctionStmt *stmt)
perbyte_cpu = PERBYTE_CPU;
percall_cpu = PERCALL_CPU;
outin_ratio = OUTIN_RATIO;
- isImplicit = false;
isStrict = false;
security = false;
volatility = PROVOLATILE_VOLATILE;
/* override attributes from explicit list */
compute_attributes_sql_style(stmt->options,
- &as_clause, &language, &volatility, &isStrict, &security, &isImplicit);
+ &as_clause, &language, &volatility, &isStrict, &security);
/* Convert language name to canonical case */
case_translate_language_name(language, languageName);
@@ -474,8 +460,7 @@ CreateFunction(CreateFunctionStmt *stmt)
compute_attributes_with_style(stmt->withClause,
&byte_pct, &perbyte_cpu, &percall_cpu,
- &outin_ratio, &isImplicit, &isStrict,
- &volatility);
+ &outin_ratio, &isStrict, &volatility);
interpret_AS_clause(languageOid, languageName, as_clause,
&prosrc_str, &probin_str);
@@ -517,7 +502,6 @@ CreateFunction(CreateFunctionStmt *stmt)
probin_str, /* converted to text later */
false, /* not an aggregate */
security,
- isImplicit,
isStrict,
volatility,
byte_pct,
@@ -639,3 +623,217 @@ RemoveFunctionById(Oid funcOid)
heap_close(relation, RowExclusiveLock);
}
}
+
+
+
+/*
+ * CREATE CAST
+ */
+void
+CreateCast(CreateCastStmt *stmt)
+{
+ Oid sourcetypeid;
+ Oid targettypeid;
+ Oid funcid;
+ HeapTuple tuple;
+ Relation relation;
+ Form_pg_proc procstruct;
+
+ Datum values[Natts_pg_proc];
+ char nulls[Natts_pg_proc];
+ int i;
+
+ ObjectAddress myself,
+ referenced;
+
+ sourcetypeid = LookupTypeName(stmt->sourcetype);
+ if (!OidIsValid(sourcetypeid))
+ elog(ERROR, "source data type %s does not exist",
+ TypeNameToString(stmt->sourcetype));
+
+ targettypeid = LookupTypeName(stmt->targettype);
+ if (!OidIsValid(targettypeid))
+ elog(ERROR, "target data type %s does not exist",
+ TypeNameToString(stmt->targettype));
+
+ if (sourcetypeid == targettypeid)
+ elog(ERROR, "source data type and target data type are the same");
+
+ relation = heap_openr(CastRelationName, RowExclusiveLock);
+
+ tuple = SearchSysCache(CASTSOURCETARGET,
+ ObjectIdGetDatum(sourcetypeid),
+ ObjectIdGetDatum(targettypeid),
+ 0, 0);
+ if (HeapTupleIsValid(tuple))
+ elog(ERROR, "cast from data type %s to data type %s already exists",
+ TypeNameToString(stmt->sourcetype),
+ TypeNameToString(stmt->targettype));
+
+ if (stmt->func != NULL)
+ {
+ funcid = LookupFuncNameTypeNames(stmt->func->funcname, stmt->func->funcargs, false, "CreateCast");
+
+ if(!pg_proc_ownercheck(funcid, GetUserId()))
+ elog(ERROR, "permission denied");
+
+ tuple = SearchSysCache(PROCOID, ObjectIdGetDatum(funcid), 0, 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cache lookup of function %u failed", funcid);
+
+ procstruct = (Form_pg_proc) GETSTRUCT(tuple);
+ if (procstruct->pronargs != 1)
+ elog(ERROR, "cast function must take 1 argument");
+ if (procstruct->proargtypes[0] != sourcetypeid)
+ elog(ERROR, "argument of cast function must match source data type");
+ if (procstruct->prorettype != targettypeid)
+ elog(ERROR, "return data type of cast function must match target data type");
+ if (procstruct->provolatile != PROVOLATILE_IMMUTABLE)
+ elog(ERROR, "cast function must be immutable");
+ if (procstruct->proisagg)
+ elog(ERROR, "cast function must not be an aggregate function");
+ if (procstruct->proretset)
+ elog(ERROR, "cast function must be not return a set");
+
+ ReleaseSysCache(tuple);
+ }
+ else
+ {
+ /* indicates binary compatibility */
+ if (!pg_type_ownercheck(sourcetypeid, GetUserId())
+ || !pg_type_ownercheck(targettypeid, GetUserId()))
+ elog(ERROR, "permission denied");
+ funcid = 0;
+ }
+
+ /* ready to go */
+ 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_castimplicit-1] = BoolGetDatum(stmt->implicit);
+
+ for (i = 0; i < Natts_pg_cast; ++i)
+ nulls[i] = ' ';
+
+ tuple = heap_formtuple(RelationGetDescr(relation), values, nulls);
+ simple_heap_insert(relation, tuple);
+
+ if (RelationGetForm(relation)->relhasindex)
+ {
+ Relation idescs[Num_pg_cast_indices];
+
+ CatalogOpenIndices(Num_pg_cast_indices, Name_pg_cast_indices, idescs);
+ CatalogIndexInsert(idescs, Num_pg_cast_indices, relation, tuple);
+ CatalogCloseIndices(Num_pg_cast_indices, idescs);
+ }
+
+ myself.classId = get_system_catalog_relid(CastRelationName);
+ myself.objectId = tuple->t_data->t_oid;
+ myself.objectSubId = 0;
+
+ /* dependency on source type */
+ referenced.classId = RelOid_pg_type;
+ referenced.objectId = sourcetypeid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* dependency on target type */
+ referenced.classId = RelOid_pg_type;
+ referenced.objectId = targettypeid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+ /* dependency on function */
+ if (OidIsValid(funcid))
+ {
+ referenced.classId = RelOid_pg_proc;
+ referenced.objectId = funcid;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ heap_freetuple(tuple);
+ heap_close(relation, RowExclusiveLock);
+}
+
+
+
+/*
+ * DROP CAST
+ */
+void
+DropCast(DropCastStmt *stmt)
+{
+ Oid sourcetypeid;
+ Oid targettypeid;
+ HeapTuple tuple;
+ Form_pg_cast caststruct;
+ ObjectAddress object;
+
+ sourcetypeid = LookupTypeName(stmt->sourcetype);
+ if (!OidIsValid(sourcetypeid))
+ elog(ERROR, "source data type %s does not exist",
+ TypeNameToString(stmt->sourcetype));
+
+ targettypeid = LookupTypeName(stmt->targettype);
+ if (!OidIsValid(targettypeid))
+ elog(ERROR, "target data type %s does not exist",
+ TypeNameToString(stmt->targettype));
+
+ tuple = SearchSysCache(CASTSOURCETARGET,
+ ObjectIdGetDatum(sourcetypeid),
+ ObjectIdGetDatum(targettypeid),
+ 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "cast from type %s to type %s does not exist",
+ TypeNameToString(stmt->sourcetype),
+ TypeNameToString(stmt->targettype));
+
+ /* Permission check */
+ caststruct = (Form_pg_cast) GETSTRUCT(tuple);
+ if (caststruct->castfunc != InvalidOid)
+ {
+ if(!pg_proc_ownercheck(caststruct->castfunc, GetUserId()))
+ elog(ERROR, "permission denied");
+ }
+ else
+ {
+ if (!pg_type_ownercheck(sourcetypeid, GetUserId())
+ || !pg_type_ownercheck(targettypeid, GetUserId()))
+ elog(ERROR, "permission denied");
+ }
+
+ ReleaseSysCache(tuple);
+
+ /*
+ * Do the deletion
+ */
+ object.classId = get_system_catalog_relid(CastRelationName);
+ object.objectId = tuple->t_data->t_oid;
+ object.objectSubId = 0;
+
+ performDeletion(&object, stmt->behavior);
+}
+
+
+void
+DropCastById(Oid castOid)
+{
+ Relation relation;
+ ScanKeyData scankey;
+ HeapScanDesc scan;
+ HeapTuple tuple;
+
+ relation = heap_openr(CastRelationName, RowExclusiveLock);
+ ScanKeyEntryInitialize(&scankey, 0x0,
+ ObjectIdAttributeNumber, F_OIDEQ,
+ ObjectIdGetDatum(castOid));
+ scan = heap_beginscan(relation, SnapshotNow, 1, &scankey);
+ tuple = heap_getnext(scan, ForwardScanDirection);
+ if (HeapTupleIsValid(tuple))
+ simple_heap_delete(relation, &tuple->t_self);
+ else
+ elog(ERROR, "could not find tuple for cast %u", castOid);
+ heap_endscan(scan);
+ heap_close(relation, RowExclusiveLock);
+}
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index bece9e0f184..4bc561f96ab 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.346 2002/07/18 17:14:19 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.347 2002/07/18 23:11:27 petere Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -135,13 +135,13 @@ static void doNegateFloat(Value *v);
AlterDatabaseSetStmt, AlterGroupStmt,
AlterTableStmt, AlterUserStmt, AlterUserSetStmt,
AnalyzeStmt, ClosePortalStmt, ClusterStmt, CommentStmt,
- ConstraintsSetStmt, CopyStmt, CreateAsStmt,
+ ConstraintsSetStmt, CopyStmt, CreateAsStmt, CreateCastStmt,
CreateDomainStmt, CreateGroupStmt, CreatePLangStmt,
CreateSchemaStmt, CreateSeqStmt, CreateStmt,
CreateAssertStmt, CreateTrigStmt, CreateUserStmt,
CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
DropGroupStmt, DropPLangStmt, DropStmt,
- DropAssertStmt, DropTrigStmt, DropRuleStmt,
+ DropAssertStmt, DropTrigStmt, DropRuleStmt, DropCastStmt,
DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt,
LockStmt, NotifyStmt, OptimizableStmt,
@@ -165,7 +165,7 @@ static void doNegateFloat(Value *v);
%type <defelt> createdb_opt_item, copy_opt_item
%type <ival> opt_lock, lock_type
-%type <boolean> opt_force, opt_or_replace
+%type <boolean> opt_force, opt_or_replace, opt_assignment
%type <list> user_list
@@ -346,7 +346,7 @@ static void doNegateFloat(Value *v);
HANDLER, HAVING, HOUR_P,
- ILIKE, IMMEDIATE, IMMUTABLE, IMPLICIT, IN_P, INCREMENT,
+ ILIKE, IMMEDIATE, IMMUTABLE, IN_P, INCREMENT,
INDEX, INHERITS, INITIALLY, INNER_P, INOUT, INPUT,
INSENSITIVE, INSERT, INSTEAD, INT, INTEGER, INTERSECT,
INTERVAL, INTO, INVOKER, IS, ISNULL, ISOLATION,
@@ -475,6 +475,7 @@ stmt :
| CopyStmt
| CreateStmt
| CreateAsStmt
+ | CreateCastStmt
| CreateDomainStmt
| CreateFunctionStmt
| CreateSchemaStmt
@@ -489,6 +490,7 @@ stmt :
| DropStmt
| TruncateStmt
| CommentStmt
+ | DropCastStmt
| DropGroupStmt
| DropPLangStmt
| DropAssertStmt
@@ -2886,15 +2888,6 @@ RecipeStmt: EXECUTE RECIPE recipe_name
* as <filename or code in language as appropriate>
* language <lang> [with parameters]
*
- * CAST() form allowing all options from the CREATE FUNCTION form:
- * create [or replace] cast (<type> as <type>)
- * as <filename or code in language as appropriate>
- * language <lang> [with parameters]
- *
- * SQL99 CAST() form (requires a function to be previously defined):
- * create [or replace] cast (<type> as <type>)
- * with function fname (<type>) [as assignment]
- *
*****************************************************************************/
CreateFunctionStmt:
@@ -2910,63 +2903,6 @@ CreateFunctionStmt:
n->withClause = $9;
$$ = (Node *)n;
}
- /* CREATE CAST SQL99 standard form */
- | CREATE opt_or_replace CAST '(' func_type AS func_type ')'
- WITH FUNCTION func_name func_args opt_assignment opt_definition
- {
- CreateFunctionStmt *n;
- char buf[256];
- n = makeNode(CreateFunctionStmt);
- n->replace = $2;
- n->funcname = $7->names;
- n->argTypes = makeList1($5);
- n->returnType = $7;
- /* expand this into a string of SQL language */
- strcpy(buf, "select ");
- strcat(buf, ((Value *)lfirst($11))->val.str);
- strcat(buf, "($1)");
- n->options = lappend($14, makeDefElem("as", (Node *)makeList1(makeString(pstrdup(buf)))));
- /* make sure that this will allow implicit casting */
- n->options = lappend(n->options,
- makeDefElem("implicit", (Node *)makeInteger(TRUE)));
- /* and mention that this is SQL language */
- n->options = lappend(n->options,
- makeDefElem("language", (Node *)makeString(pstrdup("sql"))));
- $$ = (Node *)n;
- }
- /* CREATE CAST SQL99 minimally variant form */
- | CREATE opt_or_replace CAST '(' func_type AS func_type ')'
- WITH FUNCTION func_name func_args AS Sconst opt_definition
- {
- CreateFunctionStmt *n;
- n = makeNode(CreateFunctionStmt);
- n->replace = $2;
- n->funcname = $7->names;
- n->argTypes = makeList1($5);
- n->returnType = $7;
- n->options = lappend($15, makeDefElem("as", (Node *)lcons(makeList1(makeString($14)), $11)));
- /* make sure that this will allow implicit casting */
- n->options = lappend(n->options,
- makeDefElem("implicit", (Node *)makeInteger(TRUE)));
- n->options = lappend(n->options,
- makeDefElem("language", (Node *)makeString(pstrdup("c"))));
- $$ = (Node *)n;
- }
- /* CREATE CAST with mostly CREATE FUNCTION clauses */
- | CREATE opt_or_replace CAST '(' func_type AS func_type ')'
- createfunc_opt_list opt_definition
- {
- CreateFunctionStmt *n;
- n = makeNode(CreateFunctionStmt);
- n->replace = $2;
- n->funcname = $7->names;
- n->argTypes = makeList1($5);
- n->returnType = $7;
- /* make sure that this will allow implicit casting */
- n->options = lappend($9, makeDefElem("implicit", (Node *)makeInteger(TRUE)));
- n->withClause = $10;
- $$ = (Node *)n;
- }
;
opt_or_replace:
@@ -3090,10 +3026,6 @@ createfunc_opt_item:
{
$$ = makeDefElem("security", (Node *)makeInteger(FALSE));
}
- | IMPLICIT CAST
- {
- $$ = makeDefElem("implicit", (Node *)makeInteger(TRUE));
- }
;
func_as: Sconst { $$ = makeList1(makeString($1)); }
@@ -3108,10 +3040,6 @@ opt_definition:
| /*EMPTY*/ { $$ = NIL; }
;
-opt_assignment: AS ASSIGNMENT {}
- | /*EMPTY*/ {}
- ;
-
/*****************************************************************************
*
@@ -3132,14 +3060,6 @@ RemoveFuncStmt:
n->behavior = $5;
$$ = (Node *)n;
}
- | DROP CAST '(' func_type AS func_type ')' opt_drop_behavior
- {
- RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
- n->funcname = $6->names;
- n->args = makeList1($4);
- n->behavior = $8;
- $$ = (Node *)n;
- }
;
RemoveAggrStmt:
@@ -3192,6 +3112,49 @@ any_operator:
/*****************************************************************************
*
+ * CREATE CAST / DROP CAST
+ *
+ *****************************************************************************/
+
+CreateCastStmt: CREATE CAST '(' ConstTypename AS ConstTypename ')'
+ WITH FUNCTION function_with_argtypes opt_assignment
+ {
+ CreateCastStmt *n = makeNode(CreateCastStmt);
+ n->sourcetype = $4;
+ n->targettype = $6;
+ n->func = (FuncWithArgs *) $10;
+ n->implicit = $11;
+ $$ = (Node *)n;
+ }
+ | CREATE CAST '(' ConstTypename AS ConstTypename ')'
+ WITHOUT FUNCTION opt_assignment
+ {
+ CreateCastStmt *n = makeNode(CreateCastStmt);
+ n->sourcetype = $4;
+ n->targettype = $6;
+ n->func = NULL;
+ n->implicit = $10;
+ $$ = (Node *)n;
+ }
+
+opt_assignment: AS ASSIGNMENT { $$ = TRUE; }
+ | /*EMPTY*/ { $$ = FALSE; }
+ ;
+
+
+DropCastStmt: DROP CAST '(' ConstTypename AS ConstTypename ')' opt_drop_behavior
+ {
+ DropCastStmt *n = makeNode(DropCastStmt);
+ n->sourcetype = $4;
+ n->targettype = $6;
+ n->behavior = $8;
+ $$ = (Node *)n;
+ }
+
+
+
+/*****************************************************************************
+ *
* QUERY:
*
* REINDEX type <typename> [FORCE] [ALL]
@@ -6701,7 +6664,6 @@ unreserved_keyword:
| HOUR_P
| IMMEDIATE
| IMMUTABLE
- | IMPLICIT
| INCREMENT
| INDEX
| INHERITS
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index f007092f668..02c9fcdda93 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.121 2002/07/18 17:14:19 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.122 2002/07/18 23:11:28 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -142,7 +142,6 @@ static const ScanKeyword ScanKeywords[] = {
{"ilike", ILIKE},
{"immediate", IMMEDIATE},
{"immutable", IMMUTABLE},
- {"implicit", IMPLICIT},
{"in", IN_P},
{"increment", INCREMENT},
{"index", INDEX},
diff --git a/src/backend/parser/parse_coerce.c b/src/backend/parser/parse_coerce.c
index fda9100d67d..15896a37d78 100644
--- a/src/backend/parser/parse_coerce.c
+++ b/src/backend/parser/parse_coerce.c
@@ -8,12 +8,13 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.77 2002/07/09 13:52:14 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_coerce.c,v 2.78 2002/07/18 23:11:28 petere Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "catalog/pg_cast.h"
#include "catalog/pg_proc.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
@@ -31,8 +32,9 @@ Oid PromoteTypeToNext(Oid inType);
static Oid PreferredType(CATEGORY category, Oid type);
static Node *build_func_call(Oid funcid, Oid rettype, List *args);
-static Oid find_coercion_function(Oid targetTypeId, Oid inputTypeId,
- Oid secondArgType, bool isExplicit);
+static Oid find_coercion_function(Oid targetTypeId, Oid sourceTypeId,
+ bool isExplicit);
+static Oid find_typmod_coercion_function(Oid typeId);
static Node *TypeConstraints(Node *arg, Oid typeId);
/* coerce_type()
@@ -142,7 +144,6 @@ coerce_type(ParseState *pstate, Node *node, Oid inputTypeId,
funcId = find_coercion_function(baseTypeId,
getBaseType(inputTypeId),
- InvalidOid,
isExplicit);
if (!OidIsValid(funcId))
elog(ERROR, "coerce_type: no conversion function from '%s' to '%s'",
@@ -258,7 +259,6 @@ can_coerce_type(int nargs, Oid *input_typeids, Oid *func_typeids,
*/
funcId = find_coercion_function(getBaseType(targetTypeId),
getBaseType(inputTypeId),
- InvalidOid,
isExplicit);
if (!OidIsValid(funcId))
return false;
@@ -312,8 +312,7 @@ coerce_type_typmod(ParseState *pstate, Node *node,
if (atttypmod < 0 || atttypmod == exprTypmod(node))
return node;
- /* Note this is always implicit coercion */
- funcId = find_coercion_function(baseTypeId, baseTypeId, INT4OID, false);
+ funcId = find_typmod_coercion_function(baseTypeId);
if (OidIsValid(funcId))
{
Const *cons;
@@ -621,21 +620,25 @@ TypeCategory(Oid inType)
static bool
DirectlyBinaryCompatible(Oid type1, Oid type2)
{
+ HeapTuple tuple;
+ bool result;
+
if (type1 == type2)
return true;
- if (TypeIsTextGroup(type1) && TypeIsTextGroup(type2))
- return true;
- if (TypeIsInt4GroupA(type1) && TypeIsInt4GroupA(type2))
- return true;
- if (TypeIsInt4GroupB(type1) && TypeIsInt4GroupB(type2))
- return true;
- if (TypeIsInt4GroupC(type1) && TypeIsInt4GroupC(type2))
- return true;
- if (TypeIsInetGroup(type1) && TypeIsInetGroup(type2))
- return true;
- if (TypeIsBitGroup(type1) && TypeIsBitGroup(type2))
- return true;
- return false;
+
+ tuple = SearchSysCache(CASTSOURCETARGET, type1, type2, 0, 0);
+ if (HeapTupleIsValid(tuple))
+ {
+ Form_pg_cast caststruct;
+
+ caststruct = (Form_pg_cast) GETSTRUCT(tuple);
+ result = caststruct->castfunc == InvalidOid && caststruct->castimplicit;
+ ReleaseSysCache(tuple);
+ }
+ else
+ result = false;
+
+ return result;
}
@@ -750,34 +753,51 @@ PreferredType(CATEGORY category, Oid type)
* If a function is found, return its pg_proc OID; else return InvalidOid.
*/
static Oid
-find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType,
- bool isExplicit)
+find_coercion_function(Oid targetTypeId, Oid sourceTypeId, bool isExplicit)
+{
+ Oid funcid = InvalidOid;
+ HeapTuple tuple;
+
+ tuple = SearchSysCache(CASTSOURCETARGET,
+ ObjectIdGetDatum(sourceTypeId),
+ ObjectIdGetDatum(targetTypeId),
+ 0, 0);
+
+ if (HeapTupleIsValid(tuple))
+ {
+ Form_pg_cast cform = (Form_pg_cast) GETSTRUCT(tuple);
+
+ if (isExplicit || cform->castimplicit)
+ funcid = cform->castfunc;
+
+ ReleaseSysCache(tuple);
+ }
+
+ return funcid;
+}
+
+
+static Oid
+find_typmod_coercion_function(Oid typeId)
{
Oid funcid = InvalidOid;
Type targetType;
char *typname;
Oid typnamespace;
Oid oid_array[FUNC_MAX_ARGS];
- int nargs;
HeapTuple ftup;
- targetType = typeidType(targetTypeId);
+ targetType = typeidType(typeId);
typname = NameStr(((Form_pg_type) GETSTRUCT(targetType))->typname);
typnamespace = ((Form_pg_type) GETSTRUCT(targetType))->typnamespace;
MemSet(oid_array, 0, FUNC_MAX_ARGS * sizeof(Oid));
- oid_array[0] = inputTypeId;
- if (OidIsValid(secondArgType))
- {
- oid_array[1] = secondArgType;
- nargs = 2;
- }
- else
- nargs = 1;
+ oid_array[0] = typeId;
+ oid_array[1] = INT4OID;
ftup = SearchSysCache(PROCNAMENSP,
CStringGetDatum(typname),
- Int16GetDatum(nargs),
+ Int16GetDatum(2),
PointerGetDatum(oid_array),
ObjectIdGetDatum(typnamespace));
if (HeapTupleIsValid(ftup))
@@ -785,15 +805,11 @@ find_coercion_function(Oid targetTypeId, Oid inputTypeId, Oid secondArgType,
Form_pg_proc pform = (Form_pg_proc) GETSTRUCT(ftup);
/* Make sure the function's result type is as expected */
- if (pform->prorettype == targetTypeId && !pform->proretset &&
+ if (pform->prorettype == typeId && !pform->proretset &&
!pform->proisagg)
{
- /* If needed, make sure it can be invoked implicitly */
- if (isExplicit || pform->proimplicit)
- {
- /* Okay to use it */
- funcid = ftup->t_data->t_oid;
- }
+ /* Okay to use it */
+ funcid = ftup->t_data->t_oid;
}
ReleaseSysCache(ftup);
}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 862faf34cae..d9137368335 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.271 2002/07/18 16:47:25 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.272 2002/07/18 23:11:28 petere Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@@ -1693,7 +1693,7 @@ PostgresMain(int argc, char *argv[], const char *username)
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
- puts("$Revision: 1.271 $ $Date: 2002/07/18 16:47:25 $\n");
+ puts("$Revision: 1.272 $ $Date: 2002/07/18 23:11:28 $\n");
}
/*
@@ -2444,6 +2444,14 @@ CreateCommandTag(Node *parsetree)
tag = "CREATE CONVERSION";
break;
+ case T_CreateCastStmt:
+ tag = "CREATE CAST";
+ break;
+
+ case T_DropCastStmt:
+ tag = "DROP CAST";
+ break;
+
default:
elog(LOG, "CreateCommandTag: unknown parse node type %d",
nodeTag(parsetree));
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 8ba7466ee28..54eeab77cd1 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.163 2002/07/18 16:47:25 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.164 2002/07/18 23:11:28 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -829,6 +829,14 @@ ProcessUtility(Node *parsetree,
}
break;
+ case T_CreateCastStmt:
+ CreateCast((CreateCastStmt *) parsetree);
+ break;
+
+ case T_DropCastStmt:
+ DropCast((DropCastStmt *) parsetree);
+ break;
+
default:
elog(ERROR, "ProcessUtility: command #%d unsupported",
nodeTag(parsetree));
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 2772b668738..5999ad96285 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.111 2002/07/18 17:14:20 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.112 2002/07/18 23:11:28 petere Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -43,6 +43,7 @@
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/namespace.h"
+#include "catalog/pg_cast.h"
#include "catalog/pg_index.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_operator.h"
@@ -2048,9 +2049,9 @@ get_agg_expr(Aggref *aggref, deparse_context *context)
* Strip any type coercions at the top of the given expression tree,
* as long as they are coercions to the given datatype.
*
- * A RelabelType node is always a type coercion. A function call is also
- * considered a type coercion if it has one argument and the function name
- * is the same as the (internal) name of its result type.
+ * A RelabelType node is always a type coercion. A function call is
+ * also considered a type coercion if it has one argument and there is
+ * a cast declared that uses it.
*
* XXX It'd be better if the parsetree retained some explicit indication
* of the coercion, so we didn't need these heuristics.
@@ -2069,9 +2070,9 @@ strip_type_coercion(Node *expr, Oid resultType)
{
Func *func;
HeapTuple procTuple;
- HeapTuple typeTuple;
+ HeapTuple castTuple;
Form_pg_proc procStruct;
- Form_pg_type typeStruct;
+ Form_pg_cast castStruct;
func = (Func *) (((Expr *) expr)->oper);
Assert(IsA(func, Func));
@@ -2085,33 +2086,33 @@ strip_type_coercion(Node *expr, Oid resultType)
elog(ERROR, "cache lookup for proc %u failed", func->funcid);
procStruct = (Form_pg_proc) GETSTRUCT(procTuple);
/* Double-check func has one arg and correct result type */
- /* Also, it must be an implicit coercion function */
if (procStruct->pronargs != 1 ||
- procStruct->prorettype != resultType ||
- !procStruct->proimplicit)
+ procStruct->prorettype != resultType)
{
ReleaseSysCache(procTuple);
return expr;
}
- /* See if function has same name/namespace as its result type */
- typeTuple = SearchSysCache(TYPEOID,
- ObjectIdGetDatum(procStruct->prorettype),
- 0, 0, 0);
- if (!HeapTupleIsValid(typeTuple))
- elog(ERROR, "cache lookup for type %u failed",
- procStruct->prorettype);
- typeStruct = (Form_pg_type) GETSTRUCT(typeTuple);
- if (strcmp(NameStr(procStruct->proname),
- NameStr(typeStruct->typname)) != 0 ||
- procStruct->pronamespace != typeStruct->typnamespace)
+ /* See if function has is actually declared as a cast */
+ castTuple = SearchSysCache(CASTSOURCETARGET,
+ ObjectIdGetDatum(procStruct->proargtypes[0]),
+ ObjectIdGetDatum(procStruct->prorettype),
+ 0, 0);
+ if (!HeapTupleIsValid(castTuple))
+ {
+ ReleaseSysCache(procTuple);
+ return expr;
+ }
+ /* It must also be an implicit cast. */
+ castStruct = (Form_pg_cast) GETSTRUCT(castTuple);
+ if (!castStruct->castimplicit)
{
ReleaseSysCache(procTuple);
- ReleaseSysCache(typeTuple);
+ ReleaseSysCache(castTuple);
return expr;
}
/* Okay, it is indeed a type-coercion function */
ReleaseSysCache(procTuple);
- ReleaseSysCache(typeTuple);
+ ReleaseSysCache(castTuple);
return strip_type_coercion(lfirst(((Expr *) expr)->args), resultType);
}
diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c
index 52763d29e43..d03fd88e4df 100644
--- a/src/backend/utils/adt/sets.c
+++ b/src/backend/utils/adt/sets.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.46 2002/06/20 20:29:38 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.47 2002/07/18 23:11:29 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -63,7 +63,6 @@ SetDefine(char *querystr, Oid elemType)
fileName, /* probin */
false, /* not aggregate */
false, /* security invoker */
- false, /* not implicit coercion */
false, /* isStrict (irrelevant, no args) */
PROVOLATILE_VOLATILE, /* assume unsafe */
100, /* byte_pct */
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index a724a0874ee..5f0be16b75a 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.81 2002/07/11 07:39:27 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.82 2002/07/18 23:11:29 petere Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
@@ -28,6 +28,7 @@
#include "catalog/pg_aggregate.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h"
+#include "catalog/pg_cast.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_group.h"
#include "catalog/pg_index.h"
@@ -174,6 +175,17 @@ static const struct cachedesc cacheinfo[] = {
0,
0
}},
+ {
+ CastRelationName, /* CASTSOURCETARGET */
+ CastSourceTargetIndex,
+ 0,
+ 2,
+ {
+ Anum_pg_cast_castsource,
+ Anum_pg_cast_casttarget,
+ 0,
+ 0
+ }},
{OperatorClassRelationName, /* CLAAMNAMENSP */
OpclassAmNameNspIndex,
0,
diff --git a/src/bin/initdb/initdb.sh b/src/bin/initdb/initdb.sh
index 9902a24fc4f..f582da72c39 100644
--- a/src/bin/initdb/initdb.sh
+++ b/src/bin/initdb/initdb.sh
@@ -27,7 +27,7 @@
# Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
-# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.160 2002/07/18 16:47:25 tgl Exp $
+# $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.161 2002/07/18 23:11:29 petere Exp $
#
#-------------------------------------------------------------------------
@@ -708,6 +708,7 @@ $ECHO_N "initializing pg_depend... "$ECHO_C
-- First delete any already-made entries; PINs override all else, and must
-- be the only entries for their objects.
DELETE FROM pg_depend;
+INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_cast;
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_class;
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_proc;
INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' FROM pg_type;
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 827459b4db4..123ef3df056 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.65 2002/06/20 20:29:41 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.66 2002/07/18 23:11:29 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -170,6 +170,13 @@ dumpSchema(Archive *fout,
dumpOprs(fout, oprinfo, numOperators);
}
+ if (!dataOnly)
+ {
+ if (g_verbose)
+ write_msg(NULL, "dumping out user-defined casts\n");
+ dumpCasts(fout, finfo, numFuncs, tinfo, numTypes);
+ }
+
*numTablesPtr = numTables;
return tblinfo;
}
@@ -387,6 +394,23 @@ findFuncByOid(FuncInfo *finfo, int numFuncs, const char *oid)
}
/*
+ * Finds the index (in tinfo) of the type with the given OID. Returns
+ * -1 if not found.
+ */
+int
+findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid)
+{
+ int i;
+
+ for (i = 0; i < numTypes; i++)
+ {
+ if (strcmp(tinfo[i].oid, oid) == 0)
+ return i;
+ }
+ return -1;
+}
+
+/*
* findOprByOid
* given the oid of an operator, return the name of the operator
*
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 1aefb9801aa..a173839b4d4 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -22,7 +22,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.273 2002/07/18 04:50:51 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.274 2002/07/18 23:11:29 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -3398,7 +3398,6 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
char *prosrc;
char *probin;
char *provolatile;
- char *proimplicit;
char *proisstrict;
char *prosecdef;
char *lanname;
@@ -3417,7 +3416,7 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
{
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
- "provolatile, proimplicit, proisstrict, prosecdef, "
+ "provolatile, proisstrict, prosecdef, "
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
"FROM pg_catalog.pg_proc "
"WHERE oid = '%s'::pg_catalog.oid",
@@ -3428,7 +3427,6 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
"case when proiscachable then 'i' else 'v' end as provolatile, "
- "'f'::boolean as proimplicit, "
"proisstrict, "
"'f'::boolean as prosecdef, "
"(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
@@ -3441,7 +3439,6 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
appendPQExpBuffer(query,
"SELECT proretset, prosrc, probin, "
"case when proiscachable then 'i' else 'v' end as provolatile, "
- "'f'::boolean as proimplicit, "
"'f'::boolean as proisstrict, "
"'f'::boolean as prosecdef, "
"(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
@@ -3472,7 +3469,6 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
prosrc = PQgetvalue(res, 0, PQfnumber(res, "prosrc"));
probin = PQgetvalue(res, 0, PQfnumber(res, "probin"));
provolatile = PQgetvalue(res, 0, PQfnumber(res, "provolatile"));
- proimplicit = PQgetvalue(res, 0, PQfnumber(res, "proimplicit"));
proisstrict = PQgetvalue(res, 0, PQfnumber(res, "proisstrict"));
prosecdef = PQgetvalue(res, 0, PQfnumber(res, "prosecdef"));
lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
@@ -3533,9 +3529,6 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo)
}
}
- if (proimplicit[0] == 't')
- appendPQExpBuffer(q, " IMPLICIT CAST");
-
if (proisstrict[0] == 't')
appendPQExpBuffer(q, " STRICT");
@@ -3569,6 +3562,108 @@ done:
free(funcsig_tag);
}
+
+/*
+ * Dump all casts
+ */
+void
+dumpCasts(Archive *fout,
+ FuncInfo *finfo, int numFuncs,
+ TypeInfo *tinfo, int numTypes)
+{
+ PGresult *res;
+ PQExpBuffer query = createPQExpBuffer();
+ PQExpBuffer defqry = createPQExpBuffer();
+ PQExpBuffer delqry = createPQExpBuffer();
+ int ntups;
+ int i;
+
+ /* Make sure we are in proper schema */
+ selectSourceSchema("pg_catalog");
+
+ if (fout->remoteVersion >= 70300)
+ appendPQExpBuffer(query, "SELECT oid, castsource, casttarget, castfunc, castimplicit FROM pg_cast ORDER BY 1,2,3;");
+ else
+ appendPQExpBuffer(query, "SELECT p.oid, t1.oid, t2.oid, p.oid, true FROM pg_type t1, pg_type t2, pg_proc p WHERE p.pronargs = 1 AND p.proargtypes[0] = t1.oid AND p.prorettype = t2.oid AND p.proname = t2.typname ORDER BY 1,2,3;");
+
+ res = PQexec(g_conn, query->data);
+ if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
+ {
+ write_msg(NULL, "query to obtain list of casts failed: %s",
+ PQerrorMessage(g_conn));
+ exit_nicely();
+ }
+ ntups = PQntuples(res);
+
+ for (i = 0; i < ntups; i++)
+ {
+ char * castoid = PQgetvalue(res, i, 0);
+ char * castsource = PQgetvalue(res, i, 1);
+ char * casttarget = PQgetvalue(res, i, 2);
+ char * castfunc = PQgetvalue(res, i, 3);
+ char * castimplicit = PQgetvalue(res, i, 4);
+ int fidx = -1;
+ const char *((*deps)[]);
+
+ if (strcmp(castfunc, "0") != 0)
+ fidx = findFuncByOid(finfo, numFuncs, castfunc);
+
+ /*
+ * We treat the cast as being in the namespace of the
+ * underlying function. This doesn't handle binary compatible
+ * casts. Where should those go?
+ */
+ if (fidx < 0 || !finfo[fidx].pronamespace->dump)
+ continue;
+
+ /* Make a dependency to ensure function is dumped first */
+ if (fidx >= 0)
+ {
+ deps = malloc(sizeof(char *) * 2);
+
+ (*deps)[0] = strdup(castfunc);
+ (*deps)[1] = NULL; /* End of List */
+ }
+ else
+ deps = NULL;
+
+ resetPQExpBuffer(defqry);
+ resetPQExpBuffer(delqry);
+
+ appendPQExpBuffer(delqry, "DROP CAST (%s AS %s);\n",
+ getFormattedTypeName(castsource, zeroAsNone),
+ getFormattedTypeName(casttarget, zeroAsNone));
+
+ appendPQExpBuffer(defqry, "CREATE CAST (%s AS %s) ",
+ getFormattedTypeName(castsource, zeroAsNone),
+ getFormattedTypeName(casttarget, zeroAsNone));
+
+ if (strcmp(castfunc, "0")==0)
+ appendPQExpBuffer(defqry, "WITHOUT FUNCTION");
+ else
+ appendPQExpBuffer(defqry, "WITH FUNCTION %s",
+ format_function_signature(&finfo[fidx], true));
+
+ if (strcmp(castimplicit, "t")==0)
+ appendPQExpBuffer(defqry, " AS ASSIGNMENT");
+ appendPQExpBuffer(defqry, ";\n");
+
+ ArchiveEntry(fout, castoid,
+ format_function_signature(&finfo[fidx], false),
+ finfo[fidx].pronamespace->nspname, "",
+ "CAST", deps,
+ defqry->data, delqry->data,
+ NULL, NULL, NULL);
+ }
+
+ PQclear(res);
+
+ destroyPQExpBuffer(query);
+ destroyPQExpBuffer(defqry);
+ destroyPQExpBuffer(delqry);
+}
+
+
/*
* dumpOprs
* writes out to fout the queries to recreate all the user-defined operators
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 17491b027e5..732fdfb74e4 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_dump.h,v 1.90 2002/07/06 20:12:30 momjian Exp $
+ * $Id: pg_dump.h,v 1.91 2002/07/18 23:11:29 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -177,6 +177,7 @@ typedef enum _OidOptions
extern int findTableByOid(TableInfo *tbinfo, int numTables, const char *oid);
extern char *findOprByOid(OprInfo *oprinfo, int numOprs, const char *oid);
extern int findFuncByOid(FuncInfo *finfo, int numFuncs, const char *oid);
+extern int findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid);
extern void check_conn_and_db(void);
extern void exit_nicely(void);
@@ -202,6 +203,8 @@ extern void dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
TypeInfo *tinfo, int numTypes);
extern void dumpProcLangs(Archive *fout, FuncInfo finfo[], int numFuncs);
extern void dumpFuncs(Archive *fout, FuncInfo finfo[], int numFuncs);
+extern void dumpCasts(Archive *fout, FuncInfo *finfo, int numFuncs,
+ TypeInfo *tinfo, int numTypes);
extern void dumpAggs(Archive *fout, AggInfo agginfo[], int numAggregates);
extern void dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators);
extern void dumpTables(Archive *fout, TableInfo tblinfo[], int numTables,
diff --git a/src/include/catalog/catname.h b/src/include/catalog/catname.h
index 0e452a9ca3e..dc1fedae9e1 100644
--- a/src/include/catalog/catname.h
+++ b/src/include/catalog/catname.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: catname.h,v 1.28 2002/07/12 18:43:19 tgl Exp $
+ * $Id: catname.h,v 1.29 2002/07/18 23:11:30 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,6 +20,7 @@
#define AccessMethodOperatorRelationName "pg_amop"
#define AccessMethodProcedureRelationName "pg_amproc"
#define AttributeRelationName "pg_attribute"
+#define CastRelationName "pg_cast"
#define ConstraintRelationName "pg_constraint"
#define ConversionRelationName "pg_conversion"
#define DatabaseRelationName "pg_database"
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 5fd581b2548..077da864a41 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: catversion.h,v 1.140 2002/07/15 16:33:31 tgl Exp $
+ * $Id: catversion.h,v 1.141 2002/07/18 23:11:30 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200207141
+#define CATALOG_VERSION_NO 200207191
#endif
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index 91e35934470..777a4031dd7 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: indexing.h,v 1.70 2002/07/15 16:33:31 tgl Exp $
+ * $Id: indexing.h,v 1.71 2002/07/18 23:11:30 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -26,6 +26,7 @@
#define Num_pg_amproc_indices 1
#define Num_pg_attr_indices 2
#define Num_pg_attrdef_indices 2
+#define Num_pg_cast_indices 1
#define Num_pg_class_indices 2
#define Num_pg_constraint_indices 3
#define Num_pg_conversion_indices 3
@@ -60,6 +61,7 @@
#define AttrDefaultOidIndex "pg_attrdef_oid_index"
#define AttributeRelidNameIndex "pg_attribute_relid_attnam_index"
#define AttributeRelidNumIndex "pg_attribute_relid_attnum_index"
+#define CastSourceTargetIndex "pg_cast_source_target_index"
#define ClassNameNspIndex "pg_class_relname_nsp_index"
#define ClassOidIndex "pg_class_oid_index"
#define ConstraintNameNspIndex "pg_constraint_conname_nsp_index"
@@ -108,6 +110,7 @@ extern char *Name_pg_amop_indices[];
extern char *Name_pg_amproc_indices[];
extern char *Name_pg_attr_indices[];
extern char *Name_pg_attrdef_indices[];
+extern char *Name_pg_cast_indices[];
extern char *Name_pg_class_indices[];
extern char *Name_pg_constraint_indices[];
extern char *Name_pg_conversion_indices[];
@@ -166,6 +169,7 @@ DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index on pg_attrdef using btree(ad
DECLARE_UNIQUE_INDEX(pg_attrdef_oid_index on pg_attrdef using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index on pg_attribute using btree(attrelid oid_ops, attname name_ops));
DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnum_index on pg_attribute using btree(attrelid oid_ops, attnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_cast_source_target_index on pg_cast using btree(castsource oid_ops, casttarget oid_ops));
DECLARE_UNIQUE_INDEX(pg_class_oid_index on pg_class using btree(oid oid_ops));
DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index on pg_class using btree(relname name_ops, relnamespace oid_ops));
/* This following index is not used for a cache and is not unique */
diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h
new file mode 100644
index 00000000000..4e042a396e9
--- /dev/null
+++ b/src/include/catalog/pg_cast.h
@@ -0,0 +1,225 @@
+/*-------------------------------------------------------------------------
+ *
+ * $Header: /cvsroot/pgsql/src/include/catalog/pg_cast.h,v 1.1 2002/07/18 23:11:30 petere Exp $
+ *
+ * Copyright (c) 2002, PostgreSQL Global Development Group
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CAST_H
+#define PG_CAST_H
+
+CATALOG(pg_cast)
+{
+ Oid castsource;
+ Oid casttarget;
+ Oid castfunc; /* 0 = binary compatible */
+ bool castimplicit;
+} FormData_pg_cast;
+
+typedef FormData_pg_cast *Form_pg_cast;
+
+#define Natts_pg_cast 4
+#define Anum_pg_cast_castsource 1
+#define Anum_pg_cast_casttarget 2
+#define Anum_pg_cast_castfunc 3
+#define Anum_pg_cast_castimplicit 4
+
+/* ----------------
+ * initial contents of pg_cast
+ * ----------------
+ */
+
+/*
+ * binary compatible casts
+ */
+DATA(insert ( 25 1042 0 t ));
+DATA(insert ( 25 1043 0 t ));
+DATA(insert ( 1042 25 0 t ));
+DATA(insert ( 1042 1043 0 t ));
+DATA(insert ( 1043 25 0 t ));
+DATA(insert ( 1043 1042 0 t ));
+
+DATA(insert ( 23 24 0 t ));
+DATA(insert ( 23 26 0 t ));
+DATA(insert ( 23 2202 0 t ));
+DATA(insert ( 23 2203 0 t ));
+DATA(insert ( 23 2204 0 t ));
+DATA(insert ( 23 2205 0 t ));
+DATA(insert ( 23 2206 0 t ));
+DATA(insert ( 24 23 0 t ));
+DATA(insert ( 24 26 0 t ));
+DATA(insert ( 24 2202 0 t ));
+DATA(insert ( 24 2203 0 t ));
+DATA(insert ( 24 2204 0 t ));
+DATA(insert ( 24 2205 0 t ));
+DATA(insert ( 24 2206 0 t ));
+DATA(insert ( 26 23 0 t ));
+DATA(insert ( 26 24 0 t ));
+DATA(insert ( 26 2202 0 t ));
+DATA(insert ( 26 2203 0 t ));
+DATA(insert ( 26 2204 0 t ));
+DATA(insert ( 26 2205 0 t ));
+DATA(insert ( 26 2206 0 t ));
+DATA(insert ( 2202 23 0 t ));
+DATA(insert ( 2202 24 0 t ));
+DATA(insert ( 2202 26 0 t ));
+DATA(insert ( 2202 2203 0 t ));
+DATA(insert ( 2202 2204 0 t ));
+DATA(insert ( 2202 2205 0 t ));
+DATA(insert ( 2202 2206 0 t ));
+DATA(insert ( 2203 23 0 t ));
+DATA(insert ( 2203 24 0 t ));
+DATA(insert ( 2203 26 0 t ));
+DATA(insert ( 2203 2202 0 t ));
+DATA(insert ( 2203 2204 0 t ));
+DATA(insert ( 2203 2205 0 t ));
+DATA(insert ( 2203 2206 0 t ));
+DATA(insert ( 2204 23 0 t ));
+DATA(insert ( 2204 24 0 t ));
+DATA(insert ( 2204 26 0 t ));
+DATA(insert ( 2204 2202 0 t ));
+DATA(insert ( 2204 2203 0 t ));
+DATA(insert ( 2204 2205 0 t ));
+DATA(insert ( 2204 2206 0 t ));
+DATA(insert ( 2205 23 0 t ));
+DATA(insert ( 2205 24 0 t ));
+DATA(insert ( 2205 26 0 t ));
+DATA(insert ( 2205 2202 0 t ));
+DATA(insert ( 2205 2203 0 t ));
+DATA(insert ( 2205 2204 0 t ));
+DATA(insert ( 2205 2206 0 t ));
+DATA(insert ( 2206 23 0 t ));
+DATA(insert ( 2206 24 0 t ));
+DATA(insert ( 2206 26 0 t ));
+DATA(insert ( 2206 2202 0 t ));
+DATA(insert ( 2206 2203 0 t ));
+DATA(insert ( 2206 2204 0 t ));
+DATA(insert ( 2206 2205 0 t ));
+
+DATA(insert ( 23 702 0 t ));
+DATA(insert ( 702 23 0 t ));
+
+DATA(insert ( 23 703 0 t ));
+DATA(insert ( 703 23 0 t ));
+
+DATA(insert ( 650 869 0 t ));
+DATA(insert ( 869 650 0 t ));
+
+DATA(insert ( 1560 1562 0 t ));
+DATA(insert ( 1562 1560 0 t ));
+
+/*
+ * regular casts through a function
+ *
+ * This list can be obtained from the following query as long as the
+ * naming convention of the cast functions remains the same:
+ *
+ * select p.proargtypes[0] as source, p.prorettype as target, p.oid as func, p.proimplicit as implicit from pg_proc p, pg_type t where p.pronargs=1 and p.proname = t.typname and p.prorettype = t.oid order by 1, 2;
+ */
+DATA(insert ( 18 25 946 t ));
+DATA(insert ( 18 1042 860 t ));
+DATA(insert ( 19 25 406 t ));
+DATA(insert ( 19 1042 408 t ));
+DATA(insert ( 19 1043 1401 t ));
+DATA(insert ( 20 21 714 t ));
+DATA(insert ( 20 23 480 t ));
+DATA(insert ( 20 25 1288 t ));
+DATA(insert ( 20 701 482 t ));
+DATA(insert ( 20 1043 1623 f ));
+DATA(insert ( 20 1700 1781 t ));
+DATA(insert ( 21 20 754 t ));
+DATA(insert ( 21 23 313 t ));
+DATA(insert ( 21 25 113 t ));
+DATA(insert ( 21 700 236 t ));
+DATA(insert ( 21 701 235 t ));
+DATA(insert ( 21 1700 1782 t ));
+DATA(insert ( 23 20 481 t ));
+DATA(insert ( 23 21 314 t ));
+DATA(insert ( 23 25 112 t ));
+DATA(insert ( 23 700 318 t ));
+DATA(insert ( 23 701 316 t ));
+/*xDATA(insert ( 23 703 1200 f ));*/
+DATA(insert ( 23 1043 1619 f ));
+DATA(insert ( 23 1700 1740 t ));
+DATA(insert ( 25 18 944 t ));
+DATA(insert ( 25 19 407 t ));
+DATA(insert ( 25 20 1289 f ));
+DATA(insert ( 25 21 818 f ));
+DATA(insert ( 25 23 819 f ));
+DATA(insert ( 25 26 817 f ));
+DATA(insert ( 25 650 1714 f ));
+DATA(insert ( 25 700 839 f ));
+DATA(insert ( 25 701 838 f ));
+DATA(insert ( 25 829 767 f ));
+DATA(insert ( 25 869 1713 f ));
+DATA(insert ( 25 1082 748 f ));
+DATA(insert ( 25 1083 837 f ));
+DATA(insert ( 25 1114 2022 f ));
+DATA(insert ( 25 1184 1191 f ));
+DATA(insert ( 25 1186 1263 f ));
+DATA(insert ( 25 1266 938 f ));
+DATA(insert ( 26 25 114 f ));
+DATA(insert ( 601 600 1532 f ));
+DATA(insert ( 602 600 1533 f ));
+DATA(insert ( 602 604 1449 f ));
+DATA(insert ( 603 600 1534 f ));
+DATA(insert ( 603 601 1541 f ));
+DATA(insert ( 603 604 1448 f ));
+DATA(insert ( 603 718 1479 f ));
+DATA(insert ( 604 600 1540 f ));
+DATA(insert ( 604 602 1447 f ));
+DATA(insert ( 604 603 1446 f ));
+DATA(insert ( 604 718 1474 f ));
+DATA(insert ( 700 21 238 f ));
+DATA(insert ( 700 23 319 f ));
+DATA(insert ( 700 25 841 t ));
+DATA(insert ( 700 701 311 t ));
+DATA(insert ( 700 1700 1742 t ));
+DATA(insert ( 701 20 483 f ));
+DATA(insert ( 701 21 237 f ));
+DATA(insert ( 701 23 317 f ));
+DATA(insert ( 701 25 840 t ));
+DATA(insert ( 701 700 312 t ));
+DATA(insert ( 701 1700 1743 t ));
+DATA(insert ( 702 1082 1179 f ));
+DATA(insert ( 702 1083 1364 f ));
+DATA(insert ( 702 1114 2023 t ));
+DATA(insert ( 702 1184 1173 t ));
+DATA(insert ( 703 1186 1177 t ));
+DATA(insert ( 718 600 1416 f ));
+DATA(insert ( 718 603 1480 f ));
+DATA(insert ( 718 604 1544 f ));
+DATA(insert ( 829 25 752 f ));
+DATA(insert ( 869 25 730 f ));
+DATA(insert ( 1042 19 409 t ));
+DATA(insert ( 1043 19 1400 t ));
+DATA(insert ( 1082 25 749 t ));
+DATA(insert ( 1082 1114 2024 t ));
+DATA(insert ( 1082 1184 1174 t ));
+DATA(insert ( 1083 25 948 t ));
+DATA(insert ( 1083 1186 1370 t ));
+DATA(insert ( 1083 1266 2047 t ));
+DATA(insert ( 1114 25 2034 t ));
+DATA(insert ( 1114 702 2030 f ));
+DATA(insert ( 1114 1082 2029 f ));
+DATA(insert ( 1114 1083 1316 f ));
+DATA(insert ( 1114 1184 2028 t ));
+DATA(insert ( 1184 25 1192 t ));
+DATA(insert ( 1184 702 1180 f ));
+DATA(insert ( 1184 1082 1178 f ));
+DATA(insert ( 1184 1083 2019 f ));
+DATA(insert ( 1184 1114 2027 t ));
+DATA(insert ( 1184 1266 1388 f ));
+DATA(insert ( 1186 25 1193 t ));
+DATA(insert ( 1186 703 1194 f ));
+DATA(insert ( 1186 1083 1419 f ));
+DATA(insert ( 1266 25 939 t ));
+DATA(insert ( 1266 1083 2046 t ));
+DATA(insert ( 1700 20 1779 f ));
+DATA(insert ( 1700 21 1783 f ));
+DATA(insert ( 1700 23 1744 f ));
+DATA(insert ( 1700 700 1745 f ));
+DATA(insert ( 1700 701 1746 f ));
+
+#endif /* PG_CAST_H */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 0bb719a55ab..c84ac13a959 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_proc.h,v 1.243 2002/06/20 20:29:44 momjian Exp $
+ * $Id: pg_proc.h,v 1.244 2002/07/18 23:11:30 petere Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@@ -45,7 +45,7 @@ CATALOG(pg_proc) BOOTSTRAP
Oid prolang; /* OID of pg_language entry */
bool proisagg; /* is it an aggregate? */
bool prosecdef; /* security definer */
- bool proimplicit; /* can be invoked as implicit coercion? */
+ bool proimplicit; /* unused */
bool proisstrict; /* strict with respect to NULLs? */
bool proretset; /* returns a set? */
char provolatile; /* see PROVOLATILE_ categories below */
@@ -3007,7 +3007,6 @@ extern Oid ProcedureCreate(const char *procedureName,
const char *probin,
bool isAgg,
bool security_definer,
- bool isImplicit,
bool isStrict,
char volatility,
int32 byte_pct,
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index 169ec3f3dff..707ba1d1b81 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: defrem.h,v 1.41 2002/07/12 18:43:19 tgl Exp $
+ * $Id: defrem.h,v 1.42 2002/07/18 23:11:32 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -42,6 +42,9 @@ extern void ReindexDatabase(const char *databaseName, bool force, bool all);
extern void CreateFunction(CreateFunctionStmt *stmt);
extern void RemoveFunction(RemoveFuncStmt *stmt);
extern void RemoveFunctionById(Oid funcOid);
+extern void CreateCast(CreateCastStmt *stmt);
+extern void DropCast(DropCastStmt *stmt);
+extern void DropCastById(Oid castOid);
extern void DefineOperator(List *names, List *parameters);
extern void RemoveOperator(RemoveOperStmt *stmt);
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 308bf95877d..3583315a274 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: nodes.h,v 1.112 2002/07/18 17:14:20 momjian Exp $
+ * $Id: nodes.h,v 1.113 2002/07/18 23:11:32 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -199,6 +199,8 @@ typedef enum NodeTag
T_AlterDatabaseSetStmt,
T_AlterUserSetStmt,
T_CreateConversionStmt,
+ T_CreateCastStmt,
+ T_DropCastStmt,
T_A_Expr = 700,
T_ColumnRef,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index b2e42ab7164..e4c6b625d11 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parsenodes.h,v 1.192 2002/07/18 17:14:20 momjian Exp $
+ * $Id: parsenodes.h,v 1.193 2002/07/18 23:11:32 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1555,4 +1555,30 @@ typedef struct CreateConversionStmt
bool def; /* is this a default conversion? */
} CreateConversionStmt;
+/* ----------------------
+ * CREATE CAST Statement
+ * ----------------------
+ */
+typedef struct CreateCastStmt
+{
+ NodeTag type;
+ TypeName *sourcetype;
+ TypeName *targettype;
+ FuncWithArgs *func;
+ bool implicit;
+} CreateCastStmt;
+
+/* ----------------------
+ * DROP CAST Statement
+ * ----------------------
+ */
+typedef struct DropCastStmt
+{
+ NodeTag type;
+ TypeName *sourcetype;
+ TypeName *targettype;
+ DropBehavior behavior;
+} DropCastStmt;
+
+
#endif /* PARSENODES_H */
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index f40471d7948..5d964bb5668 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: syscache.h,v 1.49 2002/07/11 07:39:28 ishii Exp $
+ * $Id: syscache.h,v 1.50 2002/07/18 23:11:32 petere Exp $
*
*-------------------------------------------------------------------------
*/
@@ -36,29 +36,30 @@
#define AMPROCNUM 5
#define ATTNAME 6
#define ATTNUM 7
-#define CLAAMNAMENSP 8
-#define CLAOID 9
-#define CONNAMESP 10
-#define GRONAME 11
-#define GROSYSID 12
-#define INDEXRELID 13
-#define INHRELID 14
-#define LANGNAME 15
-#define LANGOID 16
-#define NAMESPACENAME 17
-#define NAMESPACEOID 18
-#define OPERNAMENSP 19
-#define OPEROID 20
-#define PROCNAMENSP 21
-#define PROCOID 22
-#define RELNAMENSP 23
-#define RELOID 24
-#define RULERELNAME 25
-#define SHADOWNAME 26
-#define SHADOWSYSID 27
-#define STATRELATT 28
-#define TYPENAMENSP 29
-#define TYPEOID 30
+#define CASTSOURCETARGET 8
+#define CLAAMNAMENSP 9
+#define CLAOID 10
+#define CONNAMESP 11
+#define GRONAME 12
+#define GROSYSID 13
+#define INDEXRELID 14
+#define INHRELID 15
+#define LANGNAME 16
+#define LANGOID 17
+#define NAMESPACENAME 18
+#define NAMESPACEOID 19
+#define OPERNAMENSP 20
+#define OPEROID 21
+#define PROCNAMENSP 22
+#define PROCOID 23
+#define RELNAMENSP 24
+#define RELOID 25
+#define RULERELNAME 26
+#define SHADOWNAME 27
+#define SHADOWSYSID 28
+#define STATRELATT 29
+#define TYPENAMENSP 30
+#define TYPEOID 31
extern void InitCatalogCache(void);
extern void InitCatalogCachePhase2(void);
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index 98ac26c0c20..cb1193b0407 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -1,7 +1,7 @@
--
-- OPR_SANITY
-- Sanity checks for common errors in making operator/procedure system tables:
--- pg_operator, pg_proc, pg_aggregate, pg_am, pg_amop, pg_amproc, pg_opclass.
+-- pg_operator, pg_proc, pg_cast, pg_aggregate, pg_am, pg_amop, pg_amproc, pg_opclass.
--
-- None of the SELECTs here should ever find any matching entries,
-- so the expected output is easy to maintain ;-).
@@ -180,20 +180,49 @@ WHERE p1.oid != p2.oid AND
-------------+-------------
(0 rows)
--- If a proc is marked as an implicit cast, then it should be something that
--- the system might actually use as a cast function: name same as the name
--- of its output type, and either one arg that's a different type, or two
--- args where the first is the same as the output type and the second is int4.
-SELECT p1.oid, p1.proname
-FROM pg_proc as p1
-WHERE p1.proimplicit AND
- (NOT EXISTS (SELECT 1 FROM pg_type t WHERE t.oid = p1.prorettype AND
- t.typname = p1.proname) OR
- NOT ((p1.pronargs = 1 AND p1.proargtypes[0] != prorettype) OR
- (p1.pronargs = 2 AND p1.proargtypes[0] = prorettype AND
- p1.proargtypes[1] = 'int4'::regtype)));
- oid | proname
------+---------
+-- **************** pg_cast ****************
+-- Look for casts from and to the same type. This is not harmful, but
+-- useless.
+SELECT *
+FROM pg_cast c
+WHERE c.castsource = c.casttarget;
+ castsource | casttarget | castfunc | castimplicit
+------------+------------+----------+--------------
+(0 rows)
+
+-- Look for cast functions with incorrect number or type of argument
+-- or return value.
+SELECT c.*
+FROM pg_cast c, pg_proc p
+WHERE c.castfunc = p.oid AND
+ (p.pronargs <> 1 OR
+ p.proargtypes[0] <> c.castsource OR
+ p.prorettype <> c.casttarget);
+ castsource | casttarget | castfunc | castimplicit
+------------+------------+----------+--------------
+(0 rows)
+
+-- Look for binary compatible casts that are not implicit. This is
+-- legal, but probably not intended.
+SELECT *
+FROM pg_cast c
+WHERE c.castfunc = 0 AND NOT c.castimplicit;
+ castsource | casttarget | castfunc | castimplicit
+------------+------------+----------+--------------
+(0 rows)
+
+-- Look for binary compatible casts that do not have the reverse
+-- direction registered as well, or where the reverse direction is not
+-- also binary compatible. This is legal, but probably not intended.
+SELECT *
+FROM pg_cast c
+WHERE c.castfunc = 0 AND
+ NOT EXISTS (SELECT * FROM pg_cast k
+ WHERE k.castfunc = 0 AND
+ k.castsource = c.casttarget AND
+ k.casttarget = c.castsource);
+ castsource | casttarget | castfunc | castimplicit
+------------+------------+----------+--------------
(0 rows)
-- **************** pg_operator ****************
diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out
index 2e0cf3a0330..25e7b091c22 100644
--- a/src/test/regress/expected/sanity_check.out
+++ b/src/test/regress/expected/sanity_check.out
@@ -37,6 +37,7 @@ SELECT relname, relhasindex
pg_amproc | t
pg_attrdef | t
pg_attribute | t
+ pg_cast | t
pg_class | t
pg_constraint | t
pg_conversion | t
@@ -62,5 +63,5 @@ SELECT relname, relhasindex
shighway | t
tenk1 | t
tenk2 | t
-(52 rows)
+(53 rows)
diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql
index 270c275b87a..9d08dbd5bb3 100644
--- a/src/test/regress/sql/opr_sanity.sql
+++ b/src/test/regress/sql/opr_sanity.sql
@@ -1,7 +1,7 @@
--
-- OPR_SANITY
-- Sanity checks for common errors in making operator/procedure system tables:
--- pg_operator, pg_proc, pg_aggregate, pg_am, pg_amop, pg_amproc, pg_opclass.
+-- pg_operator, pg_proc, pg_cast, pg_aggregate, pg_am, pg_amop, pg_amproc, pg_opclass.
--
-- None of the SELECTs here should ever find any matching entries,
-- so the expected output is easy to maintain ;-).
@@ -141,19 +141,43 @@ WHERE p1.oid != p2.oid AND
NOT p1.proisagg AND NOT p2.proisagg AND
(p1.proargtypes[7] < p2.proargtypes[7]);
--- If a proc is marked as an implicit cast, then it should be something that
--- the system might actually use as a cast function: name same as the name
--- of its output type, and either one arg that's a different type, or two
--- args where the first is the same as the output type and the second is int4.
+-- **************** pg_cast ****************
-SELECT p1.oid, p1.proname
-FROM pg_proc as p1
-WHERE p1.proimplicit AND
- (NOT EXISTS (SELECT 1 FROM pg_type t WHERE t.oid = p1.prorettype AND
- t.typname = p1.proname) OR
- NOT ((p1.pronargs = 1 AND p1.proargtypes[0] != prorettype) OR
- (p1.pronargs = 2 AND p1.proargtypes[0] = prorettype AND
- p1.proargtypes[1] = 'int4'::regtype)));
+-- Look for casts from and to the same type. This is not harmful, but
+-- useless.
+
+SELECT *
+FROM pg_cast c
+WHERE c.castsource = c.casttarget;
+
+-- Look for cast functions with incorrect number or type of argument
+-- or return value.
+
+SELECT c.*
+FROM pg_cast c, pg_proc p
+WHERE c.castfunc = p.oid AND
+ (p.pronargs <> 1 OR
+ p.proargtypes[0] <> c.castsource OR
+ p.prorettype <> c.casttarget);
+
+-- Look for binary compatible casts that are not implicit. This is
+-- legal, but probably not intended.
+
+SELECT *
+FROM pg_cast c
+WHERE c.castfunc = 0 AND NOT c.castimplicit;
+
+-- Look for binary compatible casts that do not have the reverse
+-- direction registered as well, or where the reverse direction is not
+-- also binary compatible. This is legal, but probably not intended.
+
+SELECT *
+FROM pg_cast c
+WHERE c.castfunc = 0 AND
+ NOT EXISTS (SELECT * FROM pg_cast k
+ WHERE k.castfunc = 0 AND
+ k.castsource = c.casttarget AND
+ k.casttarget = c.castsource);
-- **************** pg_operator ****************