Skip to content

Commit

Permalink
[#22923] YSQL: In EXPLAIN command, fix relids of prefix keys when und…
Browse files Browse the repository at this point in the history
…er a subquery distinct index scan.

Summary:
### Issue

Schema

```
create table demo(k int, x int, v int, a int, d date, primary key(k,x,v,d));
```

Query

```
explain select v from (select distinct on (v) v from demo where k=1 and x=1) foo;
```

returns an error

```
ERROR:  invalid attnum 2 for relation "foo"
```

### Root Cause

The relation index in index target list (var->varno) is relative to the subquery. That is, var->varno indexes into PlannerInfo's RangeTable.

In explain, we require a global index across all RangeTableEntries. That is, we need an index into PlannerGlobal's RangeTable instead.

### Fix

We can access the index into PlannerGlobal's RangeTable by looking at scanrelid of the IndexScan. In this revision, we adjust the varno's of the index expressions to this scanrelid.
Jira: DB-11842

Test Plan:
Jenkins

Added a test case to yb_distinct_pushdown_base.sql to guard against regression for the above scenario.

```
./yb_build.sh --java-test TestPgRegressDistinctPushdown
```

Backport-through: 2.20

Reviewers: tnayak, smishra

Reviewed By: tnayak

Subscribers: yql

Differential Revision: https://phorge.dev.yugabyte.com/D36181
  • Loading branch information
pao214 committed Jul 12, 2024
1 parent 968e831 commit de8c392
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
34 changes: 32 additions & 2 deletions src/postgres/src/backend/commands/explain.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ static void YbExplainDistinctPrefixLen(
ExplainState *es, List *ancestors);
static void show_ybtidbitmap_info(YbBitmapTableScanState *planstate,
ExplainState *es);
static Node* yb_fix_indexpr_mutator(Node *node, int *newvarno);

typedef enum YbStatLabel
{
Expand Down Expand Up @@ -5091,6 +5092,7 @@ YbExplainDistinctPrefixLen(PlanState *planstate, List *indextlist,
bool useprefix;
int keyno;
ListCell *tlelc;
Index scanrelid;

initStringInfo(&distinct_prefix_key_buf);

Expand All @@ -5099,21 +5101,25 @@ YbExplainDistinctPrefixLen(PlanState *planstate, List *indextlist,
(Node *) planstate,
ancestors);
useprefix = (list_length(es->rtable) > 1 || es->verbose);
scanrelid = ((Scan *) planstate->plan)->scanrelid;

keyno = 0;
foreach(tlelc, indextlist)
{
TargetEntry *indextle;
Node *indexpr;
char *exprstr;

if (keyno >= yb_distinct_prefixlen)
break;

indextle = (TargetEntry *) lfirst(tlelc);

/* Fix the varno of prefix to scanrelid after making a copy. */
indexpr = yb_fix_indexpr_mutator(
(Node *) indextle->expr, (void *) &scanrelid);
/* Deparse the expression, showing any top-level cast */
exprstr = deparse_expression((Node *) indextle->expr, context,
useprefix, true);
exprstr = deparse_expression(indexpr, context, useprefix, true);
resetStringInfo(&distinct_prefix_key_buf);
appendStringInfoString(&distinct_prefix_key_buf, exprstr);
/* Emit one property-list item per key */
Expand All @@ -5125,3 +5131,27 @@ YbExplainDistinctPrefixLen(PlanState *planstate, List *indextlist,
ExplainPropertyList("Distinct Keys", result, es);
}
}

static Node *
yb_fix_indexpr_mutator(Node *node, int *newvarno)
{
if (node == NULL)
return NULL;

if (nodeTag(node) == T_Var)
{
Var *var = palloc(sizeof(Var));

/* Copy old var into a new one and adjust varno */
*var = *((Var *) node);
if (!IS_SPECIAL_VARNO(var->varno))
var->varno = *newvarno;
if (var->varnoold > 0)
var->varnoold = *newvarno;

return (Node *) var;
}

return expression_tree_mutator(
node, yb_fix_indexpr_mutator, (void *) newvarno);
}
Original file line number Diff line number Diff line change
Expand Up @@ -382,3 +382,15 @@ SELECT DISTINCT k, v1, v2 FROM kv ORDER BY k;
(10 rows)

DROP TABLE kv;
-- Test #22923
CREATE TABLE demo(k INT, x INT, v INT, a INT, d DATE, PRIMARY KEY(k,x,v,d));
EXPLAIN (COSTS OFF, TIMING OFF, SUMMARY OFF)
SELECT v FROM (SELECT DISTINCT v FROM demo WHERE k=1 AND x=1) foo;
QUERY PLAN
---------------------------------------------
Distinct Index Scan using demo_pkey on demo
Index Cond: ((k = 1) AND (x = 1))
Distinct Keys: demo.k, demo.x, demo.v
(3 rows)

DROP TABLE demo;
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,10 @@ SELECT DISTINCT k, v1, v2 FROM kv;
SELECT DISTINCT k, v1, v2 FROM kv ORDER BY k;

DROP TABLE kv;
-- Test #22923
CREATE TABLE demo(k INT, x INT, v INT, a INT, d DATE, PRIMARY KEY(k,x,v,d));

EXPLAIN (COSTS OFF, TIMING OFF, SUMMARY OFF)
SELECT v FROM (SELECT DISTINCT v FROM demo WHERE k=1 AND x=1) foo;

DROP TABLE demo;

0 comments on commit de8c392

Please sign in to comment.