summaryrefslogtreecommitdiff
path: root/src/backend/commands/functioncmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/functioncmds.c')
-rw-r--r--src/backend/commands/functioncmds.c147
1 files changed, 88 insertions, 59 deletions
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index c8e4c65386..647385b207 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -5,12 +5,12 @@
* Routines for CREATE and DROP FUNCTION commands and CREATE and DROP
* CAST commands.
*
- * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.118 2010/02/26 02:00:39 momjian Exp $
+ * src/backend/commands/functioncmds.c
*
* DESCRIPTION
* These routines take the parse tree and pick out the
@@ -37,6 +37,7 @@
#include "access/sysattr.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_cast.h"
#include "catalog/pg_language.h"
@@ -50,6 +51,7 @@
#include "miscadmin.h"
#include "optimizer/var.h"
#include "parser/parse_coerce.h"
+#include "parser/parse_collate.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
#include "parser/parse_type.h"
@@ -333,6 +335,7 @@ examine_parameter_list(List *parameters, Oid languageOid,
def = transformExpr(pstate, fp->defexpr);
def = coerce_to_specific_type(pstate, def, toid, "DEFAULT");
+ assign_expr_collations(pstate, def);
/*
* Make sure no variables are referred to.
@@ -1507,8 +1510,8 @@ CreateCast(CreateCastStmt *stmt)
ObjectAddress myself,
referenced;
- sourcetypeid = typenameTypeId(NULL, stmt->sourcetype, NULL);
- targettypeid = typenameTypeId(NULL, stmt->targettype, NULL);
+ sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
+ targettypeid = typenameTypeId(NULL, stmt->targettype);
sourcetyptype = get_typtype(sourcetypeid);
targettyptype = get_typtype(targettypeid);
@@ -1668,6 +1671,23 @@ CreateCast(CreateCastStmt *stmt)
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("array data types are not binary-compatible")));
+
+ /*
+ * We also disallow creating binary-compatibility casts involving
+ * domains. Casting from a domain to its base type is already
+ * allowed, and casting the other way ought to go through domain
+ * coercion to permit constraint checking. Again, if you're intent on
+ * having your own semantics for that, create a no-op cast function.
+ *
+ * NOTE: if we were to relax this, the above checks for composites
+ * etc. would have to be modified to look through domains to their
+ * base types.
+ */
+ if (sourcetyptype == TYPTYPE_DOMAIN ||
+ targettyptype == TYPTYPE_DOMAIN)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+ errmsg("domain data types must not be marked binary-compatible")));
}
/*
@@ -1755,6 +1775,13 @@ CreateCast(CreateCastStmt *stmt)
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
+ /* dependency on extension */
+ recordDependencyOnCurrentExtension(&myself);
+
+ /* Post creation hook for new cast */
+ InvokeObjectAccessHook(OAT_POST_CREATE,
+ CastRelationId, myself.objectId, 0);
+
heap_freetuple(tuple);
heap_close(relation, RowExclusiveLock);
@@ -1770,30 +1797,23 @@ DropCast(DropCastStmt *stmt)
{
Oid sourcetypeid;
Oid targettypeid;
- HeapTuple tuple;
ObjectAddress object;
/* when dropping a cast, the types must exist even if you use IF EXISTS */
- sourcetypeid = typenameTypeId(NULL, stmt->sourcetype, NULL);
- targettypeid = typenameTypeId(NULL, stmt->targettype, NULL);
+ sourcetypeid = typenameTypeId(NULL, stmt->sourcetype);
+ targettypeid = typenameTypeId(NULL, stmt->targettype);
- tuple = SearchSysCache2(CASTSOURCETARGET,
- ObjectIdGetDatum(sourcetypeid),
- ObjectIdGetDatum(targettypeid));
- if (!HeapTupleIsValid(tuple))
+ object.classId = CastRelationId;
+ object.objectId = get_cast_oid(sourcetypeid, targettypeid,
+ stmt->missing_ok);
+ object.objectSubId = 0;
+
+ if (!OidIsValid(object.objectId))
{
- if (!stmt->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))));
- else
- ereport(NOTICE,
+ ereport(NOTICE,
(errmsg("cast from type %s to type %s does not exist, skipping",
format_type_be(sourcetypeid),
format_type_be(targettypeid))));
-
return;
}
@@ -1809,15 +1829,31 @@ DropCast(DropCastStmt *stmt)
/*
* Do the deletion
*/
- object.classId = CastRelationId;
- object.objectId = HeapTupleGetOid(tuple);
- object.objectSubId = 0;
-
- ReleaseSysCache(tuple);
-
performDeletion(&object, stmt->behavior);
}
+/*
+ * 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,
+ 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)
@@ -1855,13 +1891,7 @@ AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
const char *newschema)
{
Oid procOid;
- Oid oldNspOid;
Oid nspOid;
- HeapTuple tup;
- Relation procRel;
- Form_pg_proc proc;
-
- procRel = heap_open(ProcedureRelationId, RowExclusiveLock);
/* get function OID */
if (isagg)
@@ -1869,39 +1899,36 @@ AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
else
procOid = LookupFuncNameTypeNames(name, argtypes, false);
- /* check permissions on function */
- if (!pg_proc_ownercheck(procOid, GetUserId()))
- aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
- NameListToString(name));
+ /* get schema OID and check its permissions */
+ nspOid = LookupCreationNamespace(newschema);
+
+ AlterFunctionNamespace_oid(procOid, nspOid);
+}
+
+Oid
+AlterFunctionNamespace_oid(Oid procOid, Oid nspOid)
+{
+ Oid oldNspOid;
+ HeapTuple tup;
+ Relation procRel;
+ Form_pg_proc proc;
+
+ procRel = heap_open(ProcedureRelationId, RowExclusiveLock);
tup = SearchSysCacheCopy1(PROCOID, ObjectIdGetDatum(procOid));
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for function %u", procOid);
proc = (Form_pg_proc) GETSTRUCT(tup);
- oldNspOid = proc->pronamespace;
-
- /* get schema OID and check its permissions */
- nspOid = LookupCreationNamespace(newschema);
-
- if (oldNspOid == nspOid)
- ereport(ERROR,
- (errcode(ERRCODE_DUPLICATE_FUNCTION),
- errmsg("function \"%s\" is already in schema \"%s\"",
- NameListToString(name),
- newschema)));
+ /* check permissions on function */
+ if (!pg_proc_ownercheck(procOid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
+ NameStr(proc->proname));
- /* disallow renaming into or out of temp schemas */
- if (isAnyTempNamespace(nspOid) || isAnyTempNamespace(oldNspOid))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("cannot move objects into or out of temporary schemas")));
+ oldNspOid = proc->pronamespace;
- /* same for TOAST schema */
- if (nspOid == PG_TOAST_NAMESPACE || oldNspOid == PG_TOAST_NAMESPACE)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("cannot move objects into or out of TOAST schema")));
+ /* common checks on switching namespaces */
+ CheckSetNamespace(oldNspOid, nspOid, ProcedureRelationId, procOid);
/* check for duplicate name (more friendly than unique-index failure) */
if (SearchSysCacheExists3(PROCNAMEARGSNSP,
@@ -1912,7 +1939,7 @@ AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
(errcode(ERRCODE_DUPLICATE_FUNCTION),
errmsg("function \"%s\" already exists in schema \"%s\"",
NameStr(proc->proname),
- newschema)));
+ get_namespace_name(nspOid))));
/* OK, modify the pg_proc row */
@@ -1926,11 +1953,13 @@ AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
if (changeDependencyFor(ProcedureRelationId, procOid,
NamespaceRelationId, oldNspOid, nspOid) != 1)
elog(ERROR, "failed to change schema dependency for function \"%s\"",
- NameListToString(name));
+ NameStr(proc->proname));
heap_freetuple(tup);
heap_close(procRel, RowExclusiveLock);
+
+ return oldNspOid;
}