From 7654eb8e59e8fe5e918e517aa64ebeb5767da87c Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@2ndquadrant.com>
Date: Mon, 17 Jun 2024 16:48:30 +0200
Subject: [PATCH v20240617 43/56] Fix error "unexpected system attribute" when
 join with system attr

We can't just change 'elog(ERROR, "unexpected system attribute");' to
'continue' in extract_relation_info since after we extract the
StatisticExtInfo, and stat is not NULL, we grantee the expression in
JoinPairInfo.clause has a matched expression with mcv_match_expression,
however this is not true for system attribute. so fix it at the first
place when populate the clause into JoinPairInfo.clauses which is the
statext_is_supported_join_clause function. Expression contains a system
attribute is OK since due to the implementation of mcv_match_expression
so only Var need to be handled there.
---
 src/backend/statistics/extended_stats.c | 27 ++++++++++++++++++++-----
 src/test/regress/sql/stats_ext.sql      |  6 ++++++
 2 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c
index 08998f219e1..d6f1c70ae64 100644
--- a/src/backend/statistics/extended_stats.c
+++ b/src/backend/statistics/extended_stats.c
@@ -2846,11 +2846,11 @@ statext_determine_join_restrictions(PlannerInfo *root, RelOptInfo *rel,
 static bool
 statext_is_supported_join_clause(PlannerInfo *root, Node *clause)
 {
-	Oid			oprsel;
-	RestrictInfo *rinfo;
-	OpExpr	   *opclause;
-	int			left_relid,
-				right_relid;
+	Oid	oprsel;
+	RestrictInfo   *rinfo;
+	OpExpr		   *opclause;
+	int				left_relid, right_relid;
+	Var			   *var;
 
 	/* XXX Can we rely on always getting RestrictInfo here? */
 	if (!IsA(clause, RestrictInfo))
@@ -2908,6 +2908,14 @@ statext_is_supported_join_clause(PlannerInfo *root, Node *clause)
 	if (left_relid == right_relid)
 		return false;
 
+	var = (Var *) linitial(opclause->args);
+	if (IsA(var, Var) && var->varattno < 0)
+		return false;
+
+	var = (Var *) lsecond(opclause->args);
+	if (IsA(var, Var) && var->varattno < 0)
+		return false;
+
 	return true;
 }
 
@@ -3195,6 +3203,15 @@ extract_relation_info(PlannerInfo *root, JoinPairInfo *info, int index,
 		}
 	}
 
+	/*
+	 * Find a stat which covers *all* the attnums and exprs for simplification.
+	 *
+	 * To overcome above limitation, statext_find_matching_mcv has to smart enough to
+	 * decide which expression to discard as the first step. and later the other
+	 * side of join has to use a stats which match or superset of expression here.
+	 * at last mcv_combine_extended should be improved to handle the not-exactly-same
+	 * mcv.
+	 */
 	*stat = statext_find_matching_mcv(root, rel, attnums, exprs, base_conditions);
 
 	return rel;
diff --git a/src/test/regress/sql/stats_ext.sql b/src/test/regress/sql/stats_ext.sql
index e372fffebfb..798ee78265e 100644
--- a/src/test/regress/sql/stats_ext.sql
+++ b/src/test/regress/sql/stats_ext.sql
@@ -1595,6 +1595,12 @@ SELECT * FROM check_estimated_rows('select * from join_test_1 j1 join join_test_
 SELECT * FROM check_estimated_rows('select * from join_test_1 j1 join join_test_2 j2 on (j1.a + 1 = j2.a) where j1.c < 5');
 SELECT * FROM check_estimated_rows('select * from join_test_1 j1 join join_test_2 j2 on (j1.a + 1 = j2.a + 1) where j1.c < 5');
 
+-- test join with system column var, but the ext statistics can't be built in system attribute AND extended statistics
+-- must covers all the join columns, so the following 2 statements can use extended statistics for join.
+SELECT * FROM check_estimated_rows('select * from join_test_1 j1 join join_test_2 j2 on ((j1.a + 1 = j2.a + 1) and (j1.b = j2.b)) and j1.cmin = j2.cmin');
+-- Join with system column expression.
+SELECT * FROM check_estimated_rows('select * from join_test_1 j1 join join_test_2 j2 on ((j1.a + 1 = j2.a + 1) and (j1.b = j2.b)) and j1.cmin::text::int4 = j2.cmin::text::int4');
+
 -- try combining with single-column (and single-expression) statistics
 DROP STATISTICS join_stats_2;
 
-- 
2.45.2

