mirror of https://github.com/citusdata/citus.git
WIP
parent
a16f0f0fe1
commit
cdbd9e079f
|
@ -230,6 +230,8 @@ GenerateSubplansForSubqueriesAndCTEs(uint64 planId, Query *originalQuery,
|
||||||
static bool ShouldDeCorrelateSubqueries(Query *query, RecursivePlanningContext *context);
|
static bool ShouldDeCorrelateSubqueries(Query *query, RecursivePlanningContext *context);
|
||||||
static void ExamineSublinks(Node *quals, RecursivePlanningContext *context);
|
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 bool SimpleJoinExpression(Expr *clause);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RecursivelyPlanSubqueriesAndCTEs finds subqueries and CTEs that cannot be pushed down to
|
* RecursivelyPlanSubqueriesAndCTEs finds subqueries and CTEs that cannot be pushed down to
|
||||||
|
@ -371,36 +373,46 @@ 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)
|
||||||
* What we actually need to do is to fetch the necessary
|
{
|
||||||
* expression and operate on that.
|
Var *v = (Var *) lfirst(varCell);
|
||||||
*/
|
Var *secondVar = NULL;
|
||||||
|
Expr *expr =
|
||||||
|
ColumnMatchExpressionAtTopLevelConjunction(
|
||||||
|
subselect->jointree->quals, v);
|
||||||
|
|
||||||
subselect->jointree->quals = NULL;
|
|
||||||
|
|
||||||
sublink->subLinkType = ANY_SUBLINK;
|
subselect->jointree->quals = NULL;
|
||||||
/* sublink->operName = list_make1("="); */
|
|
||||||
Var *v = linitial(varList);
|
|
||||||
|
|
||||||
v->varlevelsup -= 1;
|
sublink->subLinkType = ANY_SUBLINK;
|
||||||
Param *p = makeNode(Param);
|
|
||||||
|
|
||||||
p = makeNode(Param);
|
v->varlevelsup -= 1;
|
||||||
p->paramkind = PARAM_EXEC;
|
Param *p = makeNode(Param);
|
||||||
p->paramid = 10000;
|
|
||||||
p->paramtype = v->vartype;
|
|
||||||
p->paramtypmod = v->vartypmod;
|
|
||||||
p->paramcollid = v->varcollid;
|
|
||||||
p->location = v->location;
|
|
||||||
|
|
||||||
sublink->testexpr = (Node *) make_opclause(670, 16, false, (Expr *) v,
|
p = makeNode(Param);
|
||||||
(Expr *) p, 0, 0);
|
p->paramkind = PARAM_EXEC;
|
||||||
TargetEntry *tList = makeTargetEntry((Expr *) copyObject(v), 1, "col",
|
p->paramid = 10000;
|
||||||
false);
|
p->paramtype = v->vartype;
|
||||||
subselect->targetList = list_make1(tList);
|
p->paramtypmod = v->vartypmod;
|
||||||
|
p->paramcollid = v->varcollid;
|
||||||
|
p->location = v->location;
|
||||||
|
|
||||||
RecursivelyPlanSubquery(subselect, context);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -457,6 +469,97 @@ ExamineSublinks(Node *node, RecursivePlanningContext *context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ColumnMatchExpressionAtTopLevelConjunction 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 Expr *
|
||||||
|
ColumnMatchExpressionAtTopLevelConjunction(Node *node, Var *column)
|
||||||
|
{
|
||||||
|
if (node == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsA(node, OpExpr))
|
||||||
|
{
|
||||||
|
OpExpr *opExpr = (OpExpr *) node;
|
||||||
|
bool simpleExpression = SimpleJoinExpression((Expr *) opExpr);
|
||||||
|
bool columnInExpr = false;
|
||||||
|
|
||||||
|
if (!simpleExpression)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
columnInExpr = OpExpressionContainsColumn(opExpr, column);
|
||||||
|
if (!columnInExpr)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Expr *) opExpr;
|
||||||
|
}
|
||||||
|
else if (IsA(node, BoolExpr))
|
||||||
|
{
|
||||||
|
BoolExpr *boolExpr = (BoolExpr *) node;
|
||||||
|
List *argumentList = boolExpr->args;
|
||||||
|
ListCell *argumentCell = NULL;
|
||||||
|
|
||||||
|
/* handling OR or NOT EXPRs seems hard for now */
|
||||||
|
if (boolExpr->boolop != AND_EXPR)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(argumentCell, argumentList)
|
||||||
|
{
|
||||||
|
Node *argumentNode = (Node *) lfirst(argumentCell);
|
||||||
|
Expr *columnExpr =
|
||||||
|
ColumnMatchExpressionAtTopLevelConjunction(argumentNode, column);
|
||||||
|
if (columnExpr)
|
||||||
|
{
|
||||||
|
return columnExpr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
SimpleJoinExpression(Expr *clause)
|
||||||
|
{
|
||||||
|
Node *leftOperand = NULL;
|
||||||
|
Node *rightOperand = NULL;
|
||||||
|
Const *constantClause = NULL;
|
||||||
|
|
||||||
|
if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
|
||||||
|
{
|
||||||
|
leftOperand = get_leftop(clause);
|
||||||
|
rightOperand = get_rightop(clause);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false; /* not a binary opclause */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* strip coercions before doing check */
|
||||||
|
leftOperand = strip_implicit_coercions(leftOperand);
|
||||||
|
rightOperand = strip_implicit_coercions(rightOperand);
|
||||||
|
|
||||||
|
if (IsA(rightOperand, Var) && IsA(leftOperand, Var))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
SublinkSafeToDeCorrelate(SubLink *sublink)
|
SublinkSafeToDeCorrelate(SubLink *sublink)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue