from different trees of the context forest (there are some examples
 in the next section).
 
-For convenience we will also want operations like "reset/delete all
-children of a given context, but don't reset or delete that context
-itself".
+Actually, it turns out that resetting a given context should almost
+always imply deleting (not just resetting) any child contexts it has.
+So MemoryContextReset() means that, and if you really do want a tree of
+empty contexts you need to call MemoryContextResetOnly() plus
+MemoryContextResetChildren().
+
+For convenience we also provide operations like "reset/delete all children
+of a given context, but don't reset or delete that context itself".
 
 
 Globally Known Contexts
 
 
 /*
  * MemoryContextReset
- *     Release all space allocated within a context and its descendants,
- *     but don't delete the contexts themselves.
- *
- * The type-specific reset routine handles the context itself, but we
- * have to do the recursion for the children.
+ *     Release all space allocated within a context and delete all its
+ *     descendant contexts (but not the named context itself).
  */
 void
 MemoryContextReset(MemoryContext context)
 
    /* save a function call in common case where there are no children */
    if (context->firstchild != NULL)
-       MemoryContextResetChildren(context);
+       MemoryContextDeleteChildren(context);
+
+   /* save a function call if no pallocs since startup or last reset */
+   if (!context->isReset)
+       MemoryContextResetOnly(context);
+}
+
+/*
+ * MemoryContextResetOnly
+ *     Release all space allocated within a context.
+ *     Nothing is done to the context's descendant contexts.
+ */
+void
+MemoryContextResetOnly(MemoryContext context)
+{
+   AssertArg(MemoryContextIsValid(context));
 
    /* Nothing to do if no pallocs since startup or last reset */
    if (!context->isReset)
    AssertArg(MemoryContextIsValid(context));
 
    for (child = context->firstchild; child != NULL; child = child->nextchild)
-       MemoryContextReset(child);
+   {
+       MemoryContextResetChildren(child);
+       MemoryContextResetOnly(child);
+   }
 }
 
 /*
        MemoryContextDelete(context->firstchild);
 }
 
-/*
- * MemoryContextResetAndDeleteChildren
- *     Release all space allocated within a context and delete all
- *     its descendants.
- *
- * This is a common combination case where we want to preserve the
- * specific context but get rid of absolutely everything under it.
- */
-void
-MemoryContextResetAndDeleteChildren(MemoryContext context)
-{
-   AssertArg(MemoryContextIsValid(context));
-
-   MemoryContextDeleteChildren(context);
-   MemoryContextReset(context);
-}
-
 /*
  * MemoryContextRegisterResetCallback
  *     Register a function to be called before next context reset/delete.
 
 /* This is a transient link to the active portal's memory context: */
 extern PGDLLIMPORT MemoryContext PortalContext;
 
+/* Backwards compatibility macro */
+#define MemoryContextResetAndDeleteChildren(ctx) MemoryContextReset(ctx)
+
 
 /*
  * Memory-context-type-independent functions in mcxt.c
 extern void MemoryContextInit(void);
 extern void MemoryContextReset(MemoryContext context);
 extern void MemoryContextDelete(MemoryContext context);
+extern void MemoryContextResetOnly(MemoryContext context);
 extern void MemoryContextResetChildren(MemoryContext context);
 extern void MemoryContextDeleteChildren(MemoryContext context);
-extern void MemoryContextResetAndDeleteChildren(MemoryContext context);
 extern void MemoryContextRegisterResetCallback(MemoryContext context,
                                   MemoryContextCallback *cb);
 extern void MemoryContextSetParent(MemoryContext context,