v23-0003-Solve-conflict-with-self-join-removal.patch

application/octet-stream

Filename: v23-0003-Solve-conflict-with-self-join-removal.patch
Type: application/octet-stream
Part: 3
Message: Re: [PoC] Reducing planning time when tables have many partitions

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: format-patch
Series: patch v23-0003
Subject: Solve conflict with self join removal
File+
src/backend/optimizer/plan/analyzejoins.c 35 14
From c7525241e4d3c1adac3328420a61ada5aa799107 Mon Sep 17 00:00:00 2001
From: Yuya Watari <watari.yuya@gmail.com>
Date: Mon, 11 Dec 2023 12:19:55 +0900
Subject: [PATCH v23 3/6] Solve conflict with self join removal

Written by Alena Rybakina <lena.ribackina@yandex.ru> [1] with
modifications by me.

[1] https://www.postgresql.org/message-id/72d292a1-06ff-432a-a803-af5053786444%40yandex.ru
---
 src/backend/optimizer/plan/analyzejoins.c | 49 ++++++++++++++++-------
 1 file changed, 35 insertions(+), 14 deletions(-)

diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c
index 38328d945a..49f3c17057 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -1589,10 +1589,12 @@ replace_relid(Relids relids, int oldId, int newId)
  * delete them.
  */
 static void
-update_eclasses(EquivalenceClass *ec, int from, int to)
+update_eclasses(PlannerInfo *root, EquivalenceClass *ec, int from, int to)
 {
 	List	   *new_members = NIL;
-	List	   *new_sources = NIL;
+	Bitmapset  *new_source_indexes = NULL;
+	int			i;
+	int			j;
 	ListCell   *lc;
 	ListCell   *lc1;
 
@@ -1634,18 +1636,28 @@ update_eclasses(EquivalenceClass *ec, int from, int to)
 	list_free(ec->ec_members);
 	ec->ec_members = new_members;
 
-	list_free(ec->ec_derives);
-	ec->ec_derives = NULL;
+	i = -1;
+	while ((i = bms_next_member(ec->ec_derive_indexes, i)) >= 0)
+	{
+		/*
+		 * Can't delete the element because we would need to rebuild all
+		 * the eq_derives indexes. But set a nuke to detect potential problems.
+		 */
+		list_nth_cell(root->eq_derives, i)->ptr_value = NULL;
+	}
+	bms_free(ec->ec_derive_indexes);
+	ec->ec_derive_indexes = NULL;
 
 	/* Update EC source expressions */
-	foreach(lc, ec->ec_sources)
+	i = -1;
+	while ((i = bms_next_member(ec->ec_source_indexes, i)) >= 0)
 	{
-		RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
+		RestrictInfo *rinfo = list_nth_node(RestrictInfo, root->eq_sources, i);
 		bool		is_redundant = false;
 
 		if (!bms_is_member(from, rinfo->required_relids))
 		{
-			new_sources = lappend(new_sources, rinfo);
+			new_source_indexes = bms_add_member(new_source_indexes, i);
 			continue;
 		}
 
@@ -1656,9 +1668,10 @@ update_eclasses(EquivalenceClass *ec, int from, int to)
 		 * redundancy with existing ones. We don't have to check for
 		 * redundancy with derived clauses, because we've just deleted them.
 		 */
-		foreach(lc1, new_sources)
+		j = -1;
+		while ((j = bms_next_member(new_source_indexes, j)) >= 0)
 		{
-			RestrictInfo *other = lfirst_node(RestrictInfo, lc1);
+			RestrictInfo *other = list_nth_node(RestrictInfo, root->eq_sources, j);
 
 			if (!equal(rinfo->clause_relids, other->clause_relids))
 				continue;
@@ -1670,12 +1683,20 @@ update_eclasses(EquivalenceClass *ec, int from, int to)
 			}
 		}
 
-		if (!is_redundant)
-			new_sources = lappend(new_sources, rinfo);
+		if (is_redundant)
+		{
+			/*
+			 * Can't delete the element because we would need to rebuild all
+			 * the eq_sources indexes. But set a nuke to detect potential problems.
+			 */
+			list_nth_cell(root->eq_sources, i)->ptr_value = NULL;
+		}
+		else
+			new_source_indexes = bms_add_member(new_source_indexes, i);
 	}
 
-	list_free(ec->ec_sources);
-	ec->ec_sources = new_sources;
+	bms_free(ec->ec_source_indexes);
+	ec->ec_source_indexes = new_source_indexes;
 	ec->ec_relids = replace_relid(ec->ec_relids, from, to);
 }
 
@@ -1855,7 +1876,7 @@ remove_self_join_rel(PlannerInfo *root, PlanRowMark *kmark, PlanRowMark *rmark,
 	{
 		EquivalenceClass *ec = (EquivalenceClass *) list_nth(root->eq_classes, i);
 
-		update_eclasses(ec, toRemove->relid, toKeep->relid);
+		update_eclasses(root, ec, toRemove->relid, toKeep->relid);
 		toKeep->eclass_indexes = bms_add_member(toKeep->eclass_indexes, i);
 	}
 
-- 
2.42.0.windows.2