Always use the correct column, operator etc

prototype_de_correlate_subqueries
Onder Kalaci 2018-05-20 20:47:46 +03:00
parent cdbd9e079f
commit 8129960405
1 changed files with 85 additions and 39 deletions

View File

@ -232,6 +232,7 @@ static void ExamineSublinks(Node *quals, RecursivePlanningContext *context);
static bool SublinkSafeToDeCorrelate(SubLink *sublink); static bool SublinkSafeToDeCorrelate(SubLink *sublink);
static Expr * ColumnMatchExpressionAtTopLevelConjunction(Node *node, Var *column); static Expr * ColumnMatchExpressionAtTopLevelConjunction(Node *node, Var *column);
static bool SimpleJoinExpression(Expr *clause); static bool SimpleJoinExpression(Expr *clause);
static Node * RemoveMatchExpressionAtTopLevelConjunction(Node *quals, OpExpr *opExpr);
/* /*
* RecursivelyPlanSubqueriesAndCTEs finds subqueries and CTEs that cannot be pushed down to * RecursivelyPlanSubqueriesAndCTEs finds subqueries and CTEs that cannot be pushed down to
@ -325,7 +326,6 @@ ShouldDeCorrelateSubqueries(Query *query, RecursivePlanningContext *context)
{ {
FromExpr *joinTree = query->jointree; FromExpr *joinTree = query->jointree;
Node *queryQuals = NULL; Node *queryQuals = NULL;
List *sublinkList = NIL;
if (!joinTree) if (!joinTree)
{ {
@ -373,46 +373,70 @@ ExamineSublinks(Node *node, RecursivePlanningContext *context)
elog(INFO, "exists sublink found for de corrolation"); elog(INFO, "exists sublink found for de corrolation");
Query *subselect = (Query *) sublink->subselect; Query *subselect = (Query *) sublink->subselect;
List *varList = pull_vars_of_level(subselect->jointree->quals, 1); List *varList = pull_vars_of_level(subselect->jointree->quals, 1);
ListCell *varCell = NULL;
foreach(varCell, varList) if (list_length(varList) != 1)
{ {
Var *v = (Var *) lfirst(varCell); elog(DEBUG2, "skipping since expression condition didn't hold");
Var *secondVar = NULL;
Expr *expr =
ColumnMatchExpressionAtTopLevelConjunction(
subselect->jointree->quals, v);
return;
subselect->jointree->quals = NULL;
sublink->subLinkType = ANY_SUBLINK;
v->varlevelsup -= 1;
Param *p = makeNode(Param);
p = makeNode(Param);
p->paramkind = PARAM_EXEC;
p->paramid = 10000;
p->paramtype = v->vartype;
p->paramtypmod = v->vartypmod;
p->paramcollid = v->varcollid;
p->location = v->location;
if (equal(get_leftop(expr), v))
secondVar = (Var *) get_rightop(expr);
else
secondVar = (Var *) get_leftop(expr);
sublink->testexpr = (Node *) make_opclause(670, 16, false, (Expr *) v,
(Expr *) p, 0, 0);
TargetEntry *tList = makeTargetEntry((Expr *) copyObject(secondVar), 1, "col",
false);
subselect->targetList = list_make1(tList);
RecursivelyPlanSubquery(subselect, context);
} }
Var *v = linitial(varList);
Var *secondVar = NULL;
Expr *expr =
ColumnMatchExpressionAtTopLevelConjunction(
subselect->jointree->quals, v);
if (!IsA(expr, OpExpr))
{
elog(DEBUG2, "skipping since OP EXPRs condition didn't hold");
}
OpExpr *opExpr = (OpExpr *) expr;
if (equal(strip_implicit_coercions(get_leftop(expr)), v))
{
secondVar = (Var *) strip_implicit_coercions(get_rightop(expr));
}
else
{
secondVar = (Var *) strip_implicit_coercions(get_leftop(expr));
}
subselect->jointree->quals =
RemoveMatchExpressionAtTopLevelConjunction(subselect->jointree->quals,
opExpr);
sublink->subLinkType = ANY_SUBLINK;
Param *p = makeNode(Param);
p = makeNode(Param);
p->paramkind = PARAM_EXEC;
p->paramid = 10000;
p->paramtype = v->vartype;
p->paramtypmod = v->vartypmod;
p->paramcollid = v->varcollid;
p->location = v->location;
/* we'll move it to the above level */
v->varlevelsup -= 1;
sublink->testexpr = (Node *) make_opclause(opExpr->opno,
opExpr->opresulttype,
opExpr->opretset, (Expr *) v,
(Expr *) p, opExpr->opcollid,
opExpr->opcollid);
TargetEntry *tList = makeTargetEntry((Expr *) copyObject(secondVar), 1,
"col",
false);
subselect->targetList = list_make1(tList);
RecursivelyPlanSubquery(subselect, context);
} }
} }
} }
@ -469,7 +493,6 @@ ExamineSublinks(Node *node, RecursivePlanningContext *context)
} }
/* /*
* ColumnMatchExpressionAtTopLevelConjunction returns true if the query contains an exact * ColumnMatchExpressionAtTopLevelConjunction returns true if the query contains an exact
* match (equal) expression on the provided column. The function returns true only * match (equal) expression on the provided column. The function returns true only
@ -530,12 +553,35 @@ ColumnMatchExpressionAtTopLevelConjunction(Node *node, Var *column)
} }
/*
* RemoveMatchExpressionAtTopLevelConjunction returns true if the query contains an exact
* match (equal) expression on the provided column. The function returns true only
* if the match expression has an AND relation with the rest of the expression tree.
*/
static Node *
RemoveMatchExpressionAtTopLevelConjunction(Node *quals, OpExpr *opExpr)
{
if (quals == NULL)
{
return NULL;
}
if (IsA(quals, OpExpr) && equal(quals, opExpr))
{
return makeBoolConst(true, false);
}
return expression_tree_mutator(quals,
RemoveMatchExpressionAtTopLevelConjunction,
(void *) opExpr);
}
static bool static bool
SimpleJoinExpression(Expr *clause) SimpleJoinExpression(Expr *clause)
{ {
Node *leftOperand = NULL; Node *leftOperand = NULL;
Node *rightOperand = NULL; Node *rightOperand = NULL;
Const *constantClause = NULL;
if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2) if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
{ {