]> granicus.if.org Git - postgresql/blobdiff - src/backend/catalog/dependency.c
Improve the recently-added support for properly pluralized error messages
[postgresql] / src / backend / catalog / dependency.c
index d58b9d4a2fe061290fe8617e9964e9b5a114cdd2..377ae8b712b451c507436e4884b854abc0fb8b10 100644 (file)
@@ -4,11 +4,11 @@
  *       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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,6 +33,8 @@
 #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"
@@ -47,6 +49,7 @@
 #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"
@@ -55,8 +58,9 @@
 #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"
@@ -881,8 +885,11 @@ reportDependentObjects(const ObjectAddresses *targetObjects,
        }
 
        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)
@@ -907,8 +914,10 @@ reportDependentObjects(const ObjectAddresses *targetObjects,
        {
                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)));
        }
@@ -972,6 +981,13 @@ deleteOneObject(const ObjectAddress *object, Relation depRel)
 
        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.
         */
@@ -983,13 +999,6 @@ deleteOneObject(const ObjectAddress *object, Relation depRel)
         */
        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.
@@ -1105,6 +1114,18 @@ doDeletion(const ObjectAddress *object)
                        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:
@@ -1464,7 +1485,15 @@ find_expr_references_walker(Node *node,
                                                   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");
@@ -1557,7 +1586,7 @@ find_expr_references_walker(Node *node,
                 * 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)
@@ -1586,6 +1615,7 @@ find_expr_references_walker(Node *node,
                /* 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 */
@@ -1597,6 +1627,15 @@ find_expr_references_walker(Node *node,
                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);
 }
@@ -1996,6 +2035,18 @@ getObjectClass(const ObjectAddress *object)
                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 */
@@ -2085,9 +2136,13 @@ getObjectDescription(const ObjectAddress *object)
 
                                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
                                {
@@ -2488,6 +2543,50 @@ getObjectDescription(const ObjectAddress *object)
                                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,