Skip to content

Commit

Permalink
[AQUMV] Expose the function adjust view query and varno fix.
Browse files Browse the repository at this point in the history
Add new function aqumv_adjust_simple_query.
Make it external for other codes may use the same logic.
It has two main functions:
Adjust view query, remove 'old' and 'new' rte for refresh, make
it to be a valid query tree.
Fix varno after that rewrite.

Fix varnosyn, keep it with varno as we don't have syntactic one.

Authored-by: Zhang Mingli avamingli@gmail.com
  • Loading branch information
avamingli authored and my-ship-it committed Jun 25, 2024
1 parent 357c6aa commit b446160
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 101 deletions.
210 changes: 109 additions & 101 deletions src/backend/optimizer/plan/aqumv.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "catalog/pg_inherits.h"
#include "catalog/pg_rewrite.h"
#include "cdb/cdbllize.h"
#include "optimizer/aqumv.h"
#include "optimizer/optimizer.h"
#include "optimizer/planmain.h"
#include "optimizer/planner.h"
Expand Down Expand Up @@ -50,6 +51,7 @@ typedef struct
int varno;
} aqumv_adjust_varno_context;

extern void aqumv_adjust_simple_query(Query *viewQuery);
static bool aqumv_process_from_quals(Node *query_quals, Node *mv_quals, List** post_quals);
static void aqumv_adjust_varno(Query *parse, int delta);
static Node *aqumv_adjust_varno_mutator(Node *node, aqumv_adjust_varno_context *context);
Expand Down Expand Up @@ -92,7 +94,6 @@ answer_query_using_materialized_views(PlannerInfo *root,
Query *parse = root->parse; /* Query of origin SQL. */
Query *viewQuery; /* Query of view. */
RelOptInfo *mv_final_rel = current_rel; /* Final rel after rewritten. */
ListCell *lc;
Node *jtnode;
Node *mvjtnode;
int varno;
Expand Down Expand Up @@ -271,35 +272,8 @@ answer_query_using_materialized_views(PlannerInfo *root,
subroot->tuple_fraction = root->tuple_fraction;
subroot->limit_tuples = root->limit_tuples;

/*
* AQUMV
* We have to rewrite now before we do the real Equivalent
* Transformation 'rewrite'.
* Because actions sotored in rule is not a normal query tree,
* it can't be used directly, ex: new/old realtions used to
* refresh mv.
* Earse unused relatoins, keep the right one.
*/
foreach(lc, viewQuery->rtable)
{
RangeTblEntry* rtetmp = lfirst(lc);
if ((rtetmp->relkind == RELKIND_MATVIEW) &&
(rtetmp->alias != NULL) &&
(strcmp(rtetmp->alias->aliasname, "new") == 0 ||
strcmp(rtetmp->alias->aliasname,"old") == 0))
{
foreach_delete_current(viewQuery->rtable, lc);
}
}

/*
* Now we have the right relation, adjust
* varnos in its query tree.
* AQUMV_FIXME_MVP: Only one single relation
* is supported now, we could assign varno
* to 1 opportunistically.
*/
aqumv_adjust_varno(viewQuery, 1);
/* Adjust to valid query tree and fix varno after rewrite.*/
aqumv_adjust_simple_query(viewQuery);

/*
* AQUMV_FIXME_MVP
Expand Down Expand Up @@ -505,77 +479,6 @@ aqumv_init_context(List *view_tlist, TupleDesc mv_tupledesc)
return context;
}

/*
* Process varno after we eliminate mv's actions("old" and "new" relation)
* Correct rindex and all varnos with a delta.
*
* MV's actions query tree:
* [rtable]
* RangeTblEntry [rtekind=RTE_RELATION]
* [alias] Alias [aliasname="old"]
* RangeTblEntry [rtekind=RTE_RELATION]
* [alias] Alias [aliasname="new"]
* RangeTblEntry [rtekind=RTE_RELATION]
* [jointree]
* FromExpr []
* [fromlist]
* RangeTblRef [rtindex=3]
* [targetList]
* TargetEntry [resno=1 resname="c1"]
* Var [varno=3 varattno=1]
* TargetEntry [resno=2 resname="c2"]
* Var [varno=3 varattno=2]
*------------------------------------------------------------------------------------------
* MV's query tree after rewrite:
* [rtable]
* RangeTblEntry [rtekind=RTE_RELATION]
* [jointree]
* FromExpr []
* [fromlist]
* RangeTblRef [rtindex=3]
* [targetList]
* TargetEntry [resno=1 resname="c1"]
* Var [varno=3 varattno=1]
* TargetEntry [resno=2 resname="c2"]
* Var [varno=3 varattno=2]
*------------------------------------------------------------------------------------------
* MV's query tree after varno adjust:
* [rtable]
* RangeTblEntry [rtekind=RTE_RELATION]
* [jointree]
* FromExpr []
* [fromlist]
* RangeTblRef [rtindex=1]
* [targetList]
* TargetEntry [resno=1 resname="c1"]
* Var [varno=1 varattno=1]
* TargetEntry [resno=2 resname="c2"]
* Var [varno=1 varattno=2]
*
*/
static void
aqumv_adjust_varno(Query* parse, int varno)
{
aqumv_adjust_varno_context context;
context.varno = varno;
parse = query_tree_mutator(parse, aqumv_adjust_varno_mutator, &context, QTW_DONT_COPY_QUERY);
}

/*
* Adjust varno and rindex with delta.
*/
static Node *aqumv_adjust_varno_mutator(Node *node, aqumv_adjust_varno_context *context)
{
if (node == NULL)
return NULL;
if (IsA(node, Var))
((Var *)node)->varno = context->varno;
else if (IsA(node, RangeTblRef))
/* AQUMV_FIXME_MVP: currently we have only one relation */
((RangeTblRef*) node)->rtindex = context->varno;
return expression_tree_mutator(node, aqumv_adjust_varno_mutator, context);
}

/*
* Compute a node complexity recursively.
* Complexity of a node is the total times we enter walker function after all
Expand Down Expand Up @@ -811,3 +714,108 @@ aqumv_process_targetlist(aqumv_equivalent_transformation_context *context, List

return !context->has_unmatched;
}

void aqumv_adjust_simple_query(Query *viewQuery)
{
ListCell *lc;
/*
* AQUMV
* We have to rewrite now before we do the real Equivalent
* Transformation 'rewrite'.
* Because actions sotored in rule is not a normal query tree,
* it can't be used directly, ex: new/old realtions used to
* refresh mv.
* Earse unused relatoins, keep the right one.
*/
foreach (lc, viewQuery->rtable)
{
RangeTblEntry *rtetmp = lfirst(lc);
if ((rtetmp->relkind == RELKIND_MATVIEW) &&
(rtetmp->alias != NULL) &&
(strcmp(rtetmp->alias->aliasname, "new") == 0 ||
strcmp(rtetmp->alias->aliasname, "old") == 0))
{
foreach_delete_current(viewQuery->rtable, lc);
}
}

/*
* Now we have the right relation, adjust
* varnos in its query tree.
* AQUMV_FIXME_MVP: Only one single relation
* is supported now, we could assign varno
* to 1 opportunistically.
*/
aqumv_adjust_varno(viewQuery, 1);
}

/*
* Process varno after we eliminate mv's actions("old" and "new" relation)
* Correct rindex and all varnos with a delta.
*
* MV's actions query tree:
* [rtable]
* RangeTblEntry [rtekind=RTE_RELATION]
* [alias] Alias [aliasname="old"]
* RangeTblEntry [rtekind=RTE_RELATION]
* [alias] Alias [aliasname="new"]
* RangeTblEntry [rtekind=RTE_RELATION]
* [jointree]
* FromExpr []
* [fromlist]
* RangeTblRef [rtindex=3]
* [targetList]
* TargetEntry [resno=1 resname="c1"]
* Var [varno=3 varattno=1]
* TargetEntry [resno=2 resname="c2"]
* Var [varno=3 varattno=2]
*------------------------------------------------------------------------------------------
* MV's query tree after rewrite:
* [rtable]
* RangeTblEntry [rtekind=RTE_RELATION]
* [jointree]
* FromExpr []
* [fromlist]
* RangeTblRef [rtindex=3]
* [targetList]
* TargetEntry [resno=1 resname="c1"]
* Var [varno=3 varattno=1]
* TargetEntry [resno=2 resname="c2"]
* Var [varno=3 varattno=2]
*------------------------------------------------------------------------------------------
* MV's query tree after varno adjust:
* [rtable]
* RangeTblEntry [rtekind=RTE_RELATION]
* [jointree]
* FromExpr []
* [fromlist]
* RangeTblRef [rtindex=1]
* [targetList]
* TargetEntry [resno=1 resname="c1"]
* Var [varno=1 varattno=1]
* TargetEntry [resno=2 resname="c2"]
* Var [varno=1 varattno=2]
*
*/
static void
aqumv_adjust_varno(Query* parse, int varno)
{
aqumv_adjust_varno_context context;
context.varno = varno;
parse = query_tree_mutator(parse, aqumv_adjust_varno_mutator, &context, QTW_DONT_COPY_QUERY);
}

static Node *aqumv_adjust_varno_mutator(Node *node, aqumv_adjust_varno_context *context)
{
if (node == NULL)
return NULL;
if (IsA(node, Var))
{
((Var *)node)->varno = context->varno;
((Var *)node)->varnosyn = context->varno; /* Keep syntactic with varno. */
}
else if (IsA(node, RangeTblRef))
/* AQUMV_FIXME_MVP: currently we have only one relation */
((RangeTblRef*) node)->rtindex = context->varno;
return expression_tree_mutator(node, aqumv_adjust_varno_mutator, context);
}
26 changes: 26 additions & 0 deletions src/include/optimizer/aqumv.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*-------------------------------------------------------------------------
*
* aqumv.h
* prototypes for optimizer/plan/aqumv.c.
*
* Portions Copyright (c) 2024, HashData Technology Limited.
*
* Author: Zhang Mingli <avamingli@gmail.com>
*
* src/include/optimizer/aqumv.h
*
*-------------------------------------------------------------------------
*/
#ifndef AQUMV_H
#define AQUMV_H

#include "nodes/parsenodes.h"

/*
* Adjust parse tree storaged in view's actions.
* Query should be a simple query, ex:
* select from a single table.
*/
extern void aqumv_adjust_simple_query(Query *viewQuery);

#endif /* AQUMV_H */

0 comments on commit b446160

Please sign in to comment.