ERROR: PlaceHolderVar found where not expected

Started by Richard Guoabout 3 years ago5 messagesbugs
Jump to latest
#1Richard Guo
guofenglinux@gmail.com

I came across an ERROR as $subject with query below.

create table t (a int, b int);
create statistics if not exists t_s0 (dependencies, ndistinct) on a, b from
t;
insert into t values(1,1);
analyze t;

SELECT * FROM t LEFT JOIN (select true as c0) s0 ON true INNER JOIN (select
true as c0) s1 ON s0.c0 INNER JOIN (select true as c0) s2 ON s0.c0;

This is due to that we use 0 flags for pull_var_clause in
dependency_is_compatible_expression, assuming that the 'clause_expr'
cannot contain Aggrefs, WindowFuncs or PlaceHolderVars. This should be
an oversight as we can see that it's possible to find PHVs here. We can
fix it by

--- a/src/backend/statistics/dependencies.c
+++ b/src/backend/statistics/dependencies.c
@@ -1316,7 +1316,7 @@ dependency_is_compatible_expression(Node *clause,
Index relid, List *statlist, N
    if (IsA(clause_expr, RelabelType))
        clause_expr = (Node *) ((RelabelType *) clause_expr)->arg;
-   vars = pull_var_clause(clause_expr, 0);
+   vars = pull_var_clause(clause_expr, PVC_RECURSE_PLACEHOLDERS);

But I'm not sure if Aggrefs and WindowFuncs are possible to be found
here.

This issue can be seen on 14, 15 and master.

Thanks
Richard

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Richard Guo (#1)
Re: ERROR: PlaceHolderVar found where not expected

Richard Guo <guofenglinux@gmail.com> writes:

I came across an ERROR as $subject with query below.
...
This is due to that we use 0 flags for pull_var_clause in
dependency_is_compatible_expression, assuming that the 'clause_expr'
cannot contain Aggrefs, WindowFuncs or PlaceHolderVars. This should be
an oversight as we can see that it's possible to find PHVs here.

Nice catch.

But I'm not sure if Aggrefs and WindowFuncs are possible to be found
here.

WindowFuncs should be disallowed in qual clauses, so I think it's okay
to leave those flags out. An Aggref could occur in a HAVING qual though.
I'm not sure if this code could get applied to HAVING ... but it's
not immediately clear that it can't. I'd be inclined to add
PVC_RECURSE_AGGREGATES, as that seems more likely to be okay than not.

regards, tom lane

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Tom Lane (#2)
Re: ERROR: PlaceHolderVar found where not expected

I wrote:

WindowFuncs should be disallowed in qual clauses, so I think it's okay
to leave those flags out. An Aggref could occur in a HAVING qual though.
I'm not sure if this code could get applied to HAVING ... but it's
not immediately clear that it can't. I'd be inclined to add
PVC_RECURSE_AGGREGATES, as that seems more likely to be okay than not.

Actually, on closer look: why don't we just nuke that pull_var_clause
call entirely, along with the following loop inspecting its result?

The subsequent loop that looks for a matching StatisticExtInfo
expression will do just fine at rejecting any expression that
contains Vars of the wrong relation. Maybe there is some performance
argument why the pull_var_clause precheck is worth the trouble,
but I'm inclined to bet that it's actually a net loss.

regards, tom lane

#4Richard Guo
guofenglinux@gmail.com
In reply to: Tom Lane (#3)
Re: ERROR: PlaceHolderVar found where not expected

On Tue, Mar 14, 2023 at 11:39 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Actually, on closer look: why don't we just nuke that pull_var_clause
call entirely, along with the following loop inspecting its result?

The subsequent loop that looks for a matching StatisticExtInfo
expression will do just fine at rejecting any expression that
contains Vars of the wrong relation. Maybe there is some performance
argument why the pull_var_clause precheck is worth the trouble,
but I'm inclined to bet that it's actually a net loss.

Yes agreed. The pull_var_clause precheck is not necessary considering
we would match the 'clause_expr' to StatisticExtInfo expressions with
equal(). +1 to remove it.

Thanks
Richard

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Richard Guo (#4)
Re: ERROR: PlaceHolderVar found where not expected

Richard Guo <guofenglinux@gmail.com> writes:

Yes agreed. The pull_var_clause precheck is not necessary considering
we would match the 'clause_expr' to StatisticExtInfo expressions with
equal(). +1 to remove it.

Done that way.

regards, tom lane