* Routines to support inter-object dependencies.
*
*
- * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.77 2008/08/02 21:31:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.88 2009/06/04 18:33:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "catalog/pg_conversion_fn.h"
#include "catalog/pg_database.h"
#include "catalog/pg_depend.h"
+#include "catalog/pg_foreign_data_wrapper.h"
+#include "catalog/pg_foreign_server.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_ts_parser.h"
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
+#include "catalog/pg_user_mapping.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/tablespace.h"
#include "commands/trigger.h"
#include "commands/typecmds.h"
+#include "foreign/foreign.h"
#include "miscadmin.h"
-#include "optimizer/clauses.h"
+#include "nodes/nodeFuncs.h"
#include "parser/parsetree.h"
#include "rewrite/rewriteRemove.h"
#include "storage/lmgr.h"
}
if (numNotReportedClient > 0)
- appendStringInfo(&clientdetail, _("\nand %d other objects "
- "(see server log for list)"),
+ appendStringInfo(&clientdetail, ngettext("\nand %d other object "
+ "(see server log for list)",
+ "\nand %d other objects "
+ "(see server log for list)",
+ numNotReportedClient),
numNotReportedClient);
if (!ok)
{
ereport(msglevel,
/* translator: %d always has a value larger than 1 */
- (errmsg("drop cascades to %d other objects",
- numReportedClient + numNotReportedClient),
+ (errmsg_plural("drop cascades to %d other object",
+ "drop cascades to %d other objects",
+ numReportedClient + numNotReportedClient,
+ numReportedClient + numNotReportedClient),
errdetail("%s", clientdetail.data),
errdetail_log("%s", logdetail.data)));
}
systable_endscan(scan);
+ /*
+ * Delete shared dependency references related to this object. Again,
+ * if subId = 0, remove records for sub-objects too.
+ */
+ deleteSharedDependencyRecordsFor(object->classId, object->objectId,
+ object->objectSubId);
+
/*
* Now delete the object itself, in an object-type-dependent way.
*/
*/
DeleteComments(object->objectId, object->classId, object->objectSubId);
- /*
- * Delete shared dependency references related to this object. Sub-objects
- * (columns) don't have dependencies on global objects, so skip them.
- */
- if (object->objectSubId == 0)
- deleteSharedDependencyRecordsFor(object->classId, object->objectId);
-
/*
* CommandCounterIncrement here to ensure that preceding changes are all
* visible to the next deletion step.
RemoveTSConfigurationById(object->objectId);
break;
+ case OCLASS_USER_MAPPING:
+ RemoveUserMappingById(object->objectId);
+ break;
+
+ case OCLASS_FOREIGN_SERVER:
+ RemoveForeignServerById(object->objectId);
+ break;
+
+ case OCLASS_FDW:
+ RemoveForeignDataWrapperById(object->objectId);
+ break;
+
/* OCLASS_ROLE, OCLASS_DATABASE, OCLASS_TBLSPACE not handled */
default:
context->addrs);
/* fall through to examine arguments */
}
- else if (is_subplan(node))
+ else if (IsA(node, WindowFunc))
+ {
+ WindowFunc *wfunc = (WindowFunc *) node;
+
+ add_object_address(OCLASS_PROC, wfunc->winfnoid, 0,
+ context->addrs);
+ /* fall through to examine arguments */
+ }
+ else if (IsA(node, SubPlan))
{
/* Extra work needed here if we ever need this case */
elog(ERROR, "already-planned subqueries not supported");
* Add whole-relation refs for each plain relation mentioned in the
* subquery's rtable, as well as datatype refs for any datatypes used
* as a RECORD function's output. (Note: query_tree_walker takes care
- * of recursing into RTE_FUNCTION and RTE_SUBQUERY RTEs, so no need to
+ * of recursing into RTE_FUNCTION RTEs, subqueries, etc, so no need to
* do that here. But keep it from looking at join alias lists.)
*/
foreach(rtable, query->rtable)
/* query_tree_walker ignores ORDER BY etc, but we need those opers */
find_expr_references_walker((Node *) query->sortClause, context);
find_expr_references_walker((Node *) query->groupClause, context);
+ find_expr_references_walker((Node *) query->windowClause, context);
find_expr_references_walker((Node *) query->distinctClause, context);
/* Examine substructure of query */
context->rtables = list_delete_first(context->rtables);
return result;
}
+ else if (IsA(node, SetOperationStmt))
+ {
+ SetOperationStmt *setop = (SetOperationStmt *) node;
+
+ /* we need to look at the groupClauses for operator references */
+ find_expr_references_walker((Node *) setop->groupClauses, context);
+ /* fall through to examine child nodes */
+ }
+
return expression_tree_walker(node, find_expr_references_walker,
(void *) context);
}
case TableSpaceRelationId:
Assert(object->objectSubId == 0);
return OCLASS_TBLSPACE;
+
+ case ForeignDataWrapperRelationId:
+ Assert(object->objectSubId == 0);
+ return OCLASS_FDW;
+
+ case ForeignServerRelationId:
+ Assert(object->objectSubId == 0);
+ return OCLASS_FOREIGN_SERVER;
+
+ case UserMappingRelationId:
+ Assert(object->objectSubId == 0);
+ return OCLASS_USER_MAPPING;
}
/* shouldn't get here */
if (OidIsValid(con->conrelid))
{
- appendStringInfo(&buffer, _("constraint %s on "),
- NameStr(con->conname));
- getRelationDescription(&buffer, con->conrelid);
+ StringInfoData rel;
+
+ initStringInfo(&rel);
+ getRelationDescription(&rel, con->conrelid);
+ appendStringInfo(&buffer, _("constraint %s on %s"),
+ NameStr(con->conname), rel.data);
+ pfree(rel.data);
}
else
{
break;
}
+ case OCLASS_FDW:
+ {
+ ForeignDataWrapper *fdw;
+
+ fdw = GetForeignDataWrapper(object->objectId);
+ appendStringInfo(&buffer, _("foreign-data wrapper %s"), fdw->fdwname);
+ break;
+ }
+
+ case OCLASS_FOREIGN_SERVER:
+ {
+ ForeignServer *srv;
+
+ srv = GetForeignServer(object->objectId);
+ appendStringInfo(&buffer, _("server %s"), srv->servername);
+ break;
+ }
+
+ case OCLASS_USER_MAPPING:
+ {
+ HeapTuple tup;
+ Oid useid;
+ char *usename;
+
+ tup = SearchSysCache(USERMAPPINGOID,
+ ObjectIdGetDatum(object->objectId),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for user mapping %u",
+ object->objectId);
+
+ useid = ((Form_pg_user_mapping) GETSTRUCT(tup))->umuser;
+
+ ReleaseSysCache(tup);
+
+ if (OidIsValid(useid))
+ usename = GetUserNameFromId(useid);
+ else
+ usename = "public";
+
+ appendStringInfo(&buffer, _("user mapping for %s"), usename);
+ break;
+ }
+
default:
appendStringInfo(&buffer, "unrecognized object %u %u %d",
object->classId,