Обсуждение: ERROR: PlaceHolderVar found where not expected
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
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
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
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
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
we would match the 'clause_expr' to StatisticExtInfo expressions with
equal(). +1 to remove it.
Thanks
Richard
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