diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c
index 750ee5a7e5..17d96a9291 100644
--- a/src/backend/nodes/list.c
+++ b/src/backend/nodes/list.c
@@ -349,6 +349,37 @@ lappend(List *list, void *datum)
 	return list;
 }
 
+/*
+ * Append a pointer to the new list (copy).
+ * A pointer to the modified list is returned.
+ * Note that this function may or may not destructively
+ * modify the list; callers should always use this function's return
+ * value, rather than continuing to use the pointer passed as the
+ * first argument.
+ */
+List *
+lappend_copy(List *list, void *datum)
+{
+	Assert(IsPointerList(list));
+
+	if (list == NIL)
+		list = new_list(T_List, 1);
+	else
+	{
+		List *newlist;
+
+		newlist = new_list(list->type, list->length + 1);
+		memcpy(newlist->elements, list->elements,
+		   list->length * sizeof(ListCell));
+
+		list = newlist;
+	}
+
+	llast(list) = datum;
+	check_list_invariants(list);
+	return list;
+}
+
 /*
  * Append an integer to the specified list. See lappend()
  */
@@ -541,6 +572,78 @@ lcons_oid(Oid datum, List *list)
 	return list;
 }
 
+/*
+ * Prepend a new element to the new list (copy).
+ * A pointer to the modified list is returned.
+ * Note that this function may or may not destructively
+ * modify the list; callers should always use this function's return
+ * value, rather than continuing to use the pointer passed as the
+ * second argument.
+ *
+ * Note that this takes time proportional to the length of the list,
+ * since the existing entries must be moved.
+ *
+ * Caution: before Postgres 8.0, the original List was unmodified and
+ * could be considered to retain its separate identity.  This is no longer
+ * the case.
+ */
+List *
+lcons_copy(void *datum, List *list)
+{
+	Assert(IsPointerList(list));
+
+	if (list == NIL)
+		list = new_list(T_List, 1);
+	else
+	{
+		List *newlist;
+
+		newlist = new_list(list->type, list->length + 1);
+		memcpy(newlist->elements + 1, list->elements,
+		   list->length * sizeof(ListCell));
+
+		list = newlist;
+	}
+
+	linitial(list) = datum;
+	check_list_invariants(list);
+	return list;
+}
+
+/*
+ * Prepend a new element to the new list (copy) and
+ * delete the n'th cell (counting from 0) in new list (copy).
+ *
+ * The List is pfree'd if this was the last member.
+ *
+ * Note that this takes time proportional to the distance to the end of the
+ * list, since the following entries must be moved.
+ */
+
+List *
+lcons_copy_delete(void *datum, List *list, int n)
+{
+	check_list_invariants(list);
+	Assert(IsPointerList(list));
+
+	if (list == NIL)
+		list = new_list(T_List, 1);
+	else if (n > 1 && list->length > n)
+	{
+		List *newlist;
+
+		newlist = new_list(list->type, list->length - 1 - n);
+		memcpy(&newlist->elements[n], &list->elements[n + 1],
+		   (list->length - 1 - n) * sizeof(ListCell));
+
+		list = newlist;
+	}
+
+	linitial(list) = datum;
+	check_list_invariants(list);
+	return list;
+}
+
 /*
  * Concatenate list2 to the end of list1, and return list1.
  *
diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h
index 529a382d28..78376158dc 100644
--- a/src/include/nodes/pg_list.h
+++ b/src/include/nodes/pg_list.h
@@ -324,6 +324,17 @@ list_nth_oid(const List *list, int n)
 	return lfirst_oid(list_nth_cell(list, n));
 }
 
+/*
+ * Return the TransactionId value contained in the n'th element of the specified
+ * list.
+ */
+static inline TransactionId
+list_nth_xid(const List *list, int n)
+{
+	Assert(IsA(list, TransactionList));
+	return lfirst_xid(list_nth_cell(list, n));
+}
+
 #define list_nth_node(type,list,n)	castNode(type, list_nth(list, n))
 
 /*
@@ -569,6 +580,8 @@ extern pg_nodiscard List *list_insert_nth_oid(List *list, int pos, Oid datum);
 extern pg_nodiscard List *lcons(void *datum, List *list);
 extern pg_nodiscard List *lcons_int(int datum, List *list);
 extern pg_nodiscard List *lcons_oid(Oid datum, List *list);
+extern pg_nodiscard List *lcons_copy(void *datum, List *list);
+extern pg_nodiscard List *lcons_copy_delete(void *datum, List *list, int n);
 
 extern pg_nodiscard List *list_concat(List *list1, const List *list2);
 extern pg_nodiscard List *list_concat_copy(const List *list1, const List *list2);