gStore/Query/QueryTree.cpp

699 lines
23 KiB
C++

/*=============================================================================
# Filename: QueryTree.cpp
# Author: Jiaqi, Chen
# Mail: chenjiaqi93@163.com
# Last Modified: 2017-03-13
# Description: implement functions in QueryTree.h
=============================================================================*/
#include "QueryTree.h"
using namespace std;
void QueryTree::GroupPattern::FilterTree::FilterTreeNode::getVarset(Varset &varset)
{
for (int i = 0; i < (int)this->child.size(); i++)
{
if (this->child[i].node_type == FilterTreeChild::String_type && this->child[i].str[0] == '?')
varset.addVar(this->child[i].str);
if (this->child[i].node_type == FilterTreeChild::Tree_type)
this->child[i].node.getVarset(varset);
}
}
void QueryTree::GroupPattern::FilterTree::FilterTreeNode::mapVarPos2Varset(Varset &varset, Varset &entity_literal_varset)
{
if (this->oper_type == Not_type)
{
this->child[0].node.mapVarPos2Varset(varset, entity_literal_varset);
}
else if (this->oper_type == Or_type || this->oper_type == And_type)
{
this->child[0].node.mapVarPos2Varset(varset, entity_literal_varset);
this->child[1].node.mapVarPos2Varset(varset, entity_literal_varset);
}
else if (Equal_type <= this->oper_type && this->oper_type <= GreaterOrEqual_type)
{
if (this->child[0].node_type == FilterTreeChild::Tree_type)
this->child[0].node.mapVarPos2Varset(varset, entity_literal_varset);
else if (this->child[0].node_type == FilterTreeChild::String_type && this->child[0].str[0] == '?')
{
this->child[0].pos = Varset(this->child[0].str).mapTo(varset)[0];
this->child[0].isel = entity_literal_varset.findVar(this->child[0].str);
}
if (this->child[1].node_type == FilterTreeChild::Tree_type)
this->child[1].node.mapVarPos2Varset(varset, entity_literal_varset);
else if (this->child[1].node_type == FilterTreeChild::String_type && this->child[1].str[0] == '?')
{
this->child[1].pos = Varset(this->child[1].str).mapTo(varset)[0];
this->child[1].isel = entity_literal_varset.findVar(this->child[1].str);
}
}
else if (this->oper_type == Builtin_regex_type ||
this->oper_type == Builtin_str_type ||
this->oper_type == Builtin_isiri_type ||
this->oper_type == Builtin_isuri_type ||
this->oper_type == Builtin_isliteral_type ||
this->oper_type == Builtin_isnumeric_type ||
this->oper_type == Builtin_lang_type ||
this->oper_type == Builtin_langmatches_type ||
this->oper_type == Builtin_bound_type ||
this->oper_type == Builtin_in_type)
{
if (this->child[0].node_type == FilterTreeChild::Tree_type)
this->child[0].node.mapVarPos2Varset(varset, entity_literal_varset);
else if (this->child[0].node_type == FilterTreeChild::String_type && this->child[0].str[0] == '?')
{
this->child[0].pos = Varset(this->child[0].str).mapTo(varset)[0];
this->child[0].isel = entity_literal_varset.findVar(this->child[0].str);
}
}
}
void QueryTree::GroupPattern::FilterTree::FilterTreeNode::print(int dep)
{
if (this->oper_type == Not_type) printf("!");
if (this->oper_type == Builtin_regex_type) printf("REGEX");
if (this->oper_type == Builtin_str_type) printf("STR");
if (this->oper_type == Builtin_isiri_type) printf("ISIRI");
if (this->oper_type == Builtin_isuri_type) printf("ISURI");
if (this->oper_type == Builtin_isliteral_type) printf("ISLITERAL");
if (this->oper_type == Builtin_isnumeric_type) printf("ISNUMERIC");
if (this->oper_type == Builtin_lang_type) printf("LANG");
if (this->oper_type == Builtin_langmatches_type) printf("LANGMATCHES");
if (this->oper_type == Builtin_bound_type) printf("BOUND");
if (this->oper_type == Builtin_in_type)
{
printf("(");
if (this->child[0].node_type == FilterTreeChild::String_type) printf("%s", this->child[0].str.c_str());
if (this->child[0].node_type == FilterTreeChild::Tree_type) this->child[0].node.print(dep);
printf(" IN (");
for (int i = 1; i < (int)this->child.size(); i++)
{
if (i != 1) printf(", ");
if (this->child[i].node_type == FilterTreeChild::String_type) printf("%s", this->child[i].str.c_str());
if (this->child[i].node_type == FilterTreeChild::Tree_type) this->child[i].node.print(dep);
}
printf("))");
return;
}
printf("(");
if ((int)this->child.size() >= 1)
{
if (this->child[0].node_type == FilterTreeChild::String_type) printf("%s", this->child[0].str.c_str());
if (this->child[0].node_type == FilterTreeChild::Tree_type) this->child[0].node.print(dep);
}
if (this->oper_type == Or_type) printf(" || ");
if (this->oper_type == And_type) printf(" && ");
if (this->oper_type == Equal_type) printf(" = ");
if (this->oper_type == NotEqual_type) printf(" != ");
if (this->oper_type == Less_type) printf(" < ");
if (this->oper_type == LessOrEqual_type) printf(" <= ");
if (this->oper_type == Greater_type) printf(" > ");
if (this->oper_type == GreaterOrEqual_type) printf(" >= ");
if (this->oper_type == Builtin_regex_type || this->oper_type == Builtin_langmatches_type) printf(", ");
if ((int)this->child.size() >= 2)
{
if (this->child[1].node_type == FilterTreeChild::String_type) printf("%s", this->child[1].str.c_str());
if (this->child[1].node_type == FilterTreeChild::Tree_type) this->child[1].node.print(dep);
}
if ((int)this->child.size() >= 3)
{
if (this->oper_type == FilterTreeNode::Builtin_regex_type && this->child[2].node_type == FilterTreeChild::String_type)
printf(", %s", this->child[2].str.c_str());
}
printf(")");
}
//----------------------------------------------------------------------------------------------------------------------------------------------------
void QueryTree::GroupPattern::addOnePattern(Pattern _pattern)
{
this->sub_grouppattern.push_back(SubGroupPattern(SubGroupPattern::Pattern_type));
this->sub_grouppattern.back().pattern = _pattern;
}
void QueryTree::GroupPattern::addOneGroupUnion()
{
this->sub_grouppattern.push_back(SubGroupPattern(SubGroupPattern::Union_type));
}
void QueryTree::GroupPattern::addOneUnion()
{
if (this->sub_grouppattern.back().type != SubGroupPattern::Union_type)
throw "QueryTree::GroupPattern::addOneUnion failed";
this->sub_grouppattern.back().unions.push_back(GroupPattern());
}
QueryTree::GroupPattern& QueryTree::GroupPattern::getLastUnion()
{
if (this->sub_grouppattern.back().type != SubGroupPattern::Union_type || this->sub_grouppattern.back().unions.empty())
throw "QueryTree::GroupPattern::getLastUnion failed";
return this->sub_grouppattern.back().unions.back();
}
void QueryTree::GroupPattern::addOneOptional(int _type)
{
SubGroupPattern::SubGroupPatternType type = (SubGroupPattern::SubGroupPatternType)_type;
if (type != SubGroupPattern::Optional_type && type != SubGroupPattern::Minus_type)
throw "QueryTree::GroupPattern::addOneOptional failed";
this->sub_grouppattern.push_back(SubGroupPattern(type));
}
QueryTree::GroupPattern& QueryTree::GroupPattern::getLastOptional()
{
if (this->sub_grouppattern.back().type != SubGroupPattern::Optional_type && this->sub_grouppattern.back().type != SubGroupPattern::Minus_type)
throw "QueryTree::GroupPattern::getLastOptional failed";
return this->sub_grouppattern.back().optional;
}
void QueryTree::GroupPattern::addOneFilter()
{
this->sub_grouppattern.push_back(SubGroupPattern(SubGroupPattern::Filter_type));
}
QueryTree::GroupPattern::FilterTree& QueryTree::GroupPattern::getLastFilter()
{
if (this->sub_grouppattern.back().type != SubGroupPattern::Filter_type)
throw "QueryTree::GroupPattern::getLastFilter failed";
return this->sub_grouppattern.back().filter;
}
void QueryTree::GroupPattern::addOneBind()
{
this->sub_grouppattern.push_back(SubGroupPattern(SubGroupPattern::Bind_type));
}
QueryTree::GroupPattern::Bind& QueryTree::GroupPattern::getLastBind()
{
if (this->sub_grouppattern.back().type != SubGroupPattern::Bind_type)
throw "QueryTree::GroupPattern::getLastBind failed";
return this->sub_grouppattern.back().bind;
}
void QueryTree::GroupPattern::getVarset()
{
for (int i = 0; i < (int)this->sub_grouppattern.size(); i++)
if (this->sub_grouppattern[i].type == SubGroupPattern::Pattern_type)
{
if (this->sub_grouppattern[i].pattern.subject.value[0] == '?')
{
this->sub_grouppattern[i].pattern.varset.addVar(this->sub_grouppattern[i].pattern.subject.value);
this->sub_grouppattern[i].pattern.subject_object_varset.addVar(this->sub_grouppattern[i].pattern.subject.value);
this->grouppattern_subject_object_maximal_varset.addVar(this->sub_grouppattern[i].pattern.subject.value);
}
if (this->sub_grouppattern[i].pattern.predicate.value[0] == '?')
{
this->sub_grouppattern[i].pattern.varset.addVar(this->sub_grouppattern[i].pattern.predicate.value);
this->grouppattern_predicate_maximal_varset.addVar(this->sub_grouppattern[i].pattern.predicate.value);
}
if (this->sub_grouppattern[i].pattern.object.value[0] == '?')
{
this->sub_grouppattern[i].pattern.varset.addVar(this->sub_grouppattern[i].pattern.object.value);
this->sub_grouppattern[i].pattern.subject_object_varset.addVar(this->sub_grouppattern[i].pattern.object.value);
this->grouppattern_subject_object_maximal_varset.addVar(this->sub_grouppattern[i].pattern.object.value);
}
this->grouppattern_resultset_minimal_varset += this->sub_grouppattern[i].pattern.varset;
this->grouppattern_resultset_maximal_varset += this->sub_grouppattern[i].pattern.varset;
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Union_type)
{
Varset minimal_varset;
for (int j = 0; j < (int)this->sub_grouppattern[i].unions.size(); j++)
{
this->sub_grouppattern[i].unions[j].getVarset();
if (j == 0)
minimal_varset = this->sub_grouppattern[i].unions[j].grouppattern_resultset_minimal_varset;
else
minimal_varset = minimal_varset * this->sub_grouppattern[i].unions[j].grouppattern_resultset_minimal_varset;
this->grouppattern_resultset_maximal_varset += this->sub_grouppattern[i].unions[j].grouppattern_resultset_maximal_varset;
this->grouppattern_subject_object_maximal_varset += this->sub_grouppattern[i].unions[j].grouppattern_subject_object_maximal_varset;
this->grouppattern_predicate_maximal_varset += this->sub_grouppattern[i].unions[j].grouppattern_predicate_maximal_varset;
}
this->grouppattern_resultset_minimal_varset += minimal_varset;
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Optional_type)
{
this->sub_grouppattern[i].optional.getVarset();
this->grouppattern_resultset_maximal_varset += this->sub_grouppattern[i].optional.grouppattern_resultset_maximal_varset;
this->grouppattern_subject_object_maximal_varset += this->sub_grouppattern[i].optional.grouppattern_subject_object_maximal_varset;
this->grouppattern_predicate_maximal_varset += this->sub_grouppattern[i].optional.grouppattern_predicate_maximal_varset;
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Minus_type)
{
this->sub_grouppattern[i].optional.getVarset();
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Filter_type)
{
this->sub_grouppattern[i].filter.root.getVarset(this->sub_grouppattern[i].filter.varset);
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Bind_type)
{
this->sub_grouppattern[i].bind.varset = Varset(this->sub_grouppattern[i].bind.var);
this->grouppattern_resultset_minimal_varset += this->sub_grouppattern[i].bind.varset;
this->grouppattern_resultset_maximal_varset += this->sub_grouppattern[i].bind.varset;
}
}
pair<Varset, Varset> QueryTree::GroupPattern::checkNoMinusAndOptionalVarAndSafeFilter(Varset occur_varset, Varset ban_varset, bool &check_condition)
//return occur varset and ban varset
{
if (!check_condition) return make_pair(Varset(), Varset());
Varset new_ban_varset;
for (int i = 0; i < (int)this->sub_grouppattern.size(); i++)
if (!check_condition) break;
else if (this->sub_grouppattern[i].type == SubGroupPattern::Pattern_type)
{
if (this->sub_grouppattern[i].pattern.varset.hasCommonVar(ban_varset))
check_condition = false;
occur_varset += this->sub_grouppattern[i].pattern.varset;
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Union_type)
{
Varset sub_occur_varset, sub_ban_varset;
for (int j = 0; j < (int)this->sub_grouppattern[i].unions.size(); j++)
{
pair<Varset, Varset> sub_return_varset =
this->sub_grouppattern[i].unions[j].checkNoMinusAndOptionalVarAndSafeFilter(occur_varset, ban_varset, check_condition);
if (j == 0)
sub_occur_varset = sub_return_varset.first;
else
sub_occur_varset = sub_occur_varset * sub_return_varset.first;
sub_ban_varset += sub_return_varset.second;
}
new_ban_varset += sub_ban_varset;
occur_varset += sub_occur_varset;
ban_varset += new_ban_varset;
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Optional_type)
{
pair<Varset, Varset> sub_return_varset =
this->sub_grouppattern[i].optional.checkNoMinusAndOptionalVarAndSafeFilter(Varset(), ban_varset, check_condition);
//occur before
if (occur_varset.hasCommonVar(sub_return_varset.second))
check_condition = false;
new_ban_varset += sub_return_varset.second;
new_ban_varset += this->sub_grouppattern[i].optional.grouppattern_resultset_maximal_varset - occur_varset;
occur_varset += sub_return_varset.first;
ban_varset += new_ban_varset;
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Minus_type)
{
check_condition = false;
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Filter_type)
{
if (!this->sub_grouppattern[i].filter.varset.belongTo(occur_varset))
check_condition = false;
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Bind_type)
{
if (this->sub_grouppattern[i].bind.varset.hasCommonVar(ban_varset))
check_condition = false;
occur_varset += this->sub_grouppattern[i].bind.varset;
}
return make_pair(occur_varset, new_ban_varset);
}
void QueryTree::GroupPattern::initPatternBlockid()
{
for (int i = 0; i < (int)this->sub_grouppattern.size(); i++)
if (this->sub_grouppattern[i].type == SubGroupPattern::Pattern_type)
this->sub_grouppattern[i].pattern.blockid = i;
}
int QueryTree::GroupPattern::getRootPatternBlockID(int x)
{
if (this->sub_grouppattern[x].type != SubGroupPattern::Pattern_type)
throw "QueryTree::GroupPattern::getRootPatternBlockID failed";
if (this->sub_grouppattern[x].pattern.blockid == x)
return x;
this->sub_grouppattern[x].pattern.blockid = this->getRootPatternBlockID(this->sub_grouppattern[x].pattern.blockid);
return this->sub_grouppattern[x].pattern.blockid;
}
void QueryTree::GroupPattern::mergePatternBlockID(int x, int y)
{
int px = this->getRootPatternBlockID(x);
int py = this->getRootPatternBlockID(y);
this->sub_grouppattern[px].pattern.blockid = py;
}
void QueryTree::GroupPattern::print(int dep)
{
for (int t = 0; t < dep; t++) printf("\t"); printf("{\n");
for (int i = 0; i < (int)this->sub_grouppattern.size(); i++)
if (this->sub_grouppattern[i].type == SubGroupPattern::Pattern_type)
{
for (int t = 0; t <= dep; t++) printf("\t");
printf("%s\t%s\t%s.\n", this->sub_grouppattern[i].pattern.subject.value.c_str(),
this->sub_grouppattern[i].pattern.predicate.value.c_str(),
this->sub_grouppattern[i].pattern.object.value.c_str());
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Union_type)
{
for (int j = 0; j < (int)this->sub_grouppattern[i].unions.size(); j++)
{
if (j != 0)
{
for (int t = 0; t <= dep; t++) printf("\t"); printf("UNION\n");
}
this->sub_grouppattern[i].unions[j].print(dep + 1);
}
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Optional_type || this->sub_grouppattern[i].type == SubGroupPattern::Minus_type)
{
for (int t = 0; t <= dep; t++) printf("\t");
if (this->sub_grouppattern[i].type == SubGroupPattern::Optional_type) printf("OPTIONAL\n");
if (this->sub_grouppattern[i].type == SubGroupPattern::Minus_type) printf("MINUS\n");
this->sub_grouppattern[i].optional.print(dep + 1);
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Filter_type)
{
for (int t = 0; t <= dep; t++) printf("\t"); printf("FILTER\t");
this->sub_grouppattern[i].filter.root.print(dep + 1);
printf("\n");
}
else if (this->sub_grouppattern[i].type == SubGroupPattern::Bind_type)
{
for (int t = 0; t <= dep; t++) printf("\t");
printf("BIND(%s\tAS\t%s)", this->sub_grouppattern[i].bind.str.c_str(), this->sub_grouppattern[i].bind.var.c_str());
printf("\n");
}
for (int t = 0; t < dep; t++) printf("\t"); printf("}\n");
}
//----------------------------------------------------------------------------------------------------------------------------------------------------
void QueryTree::setQueryForm(QueryForm _queryform)
{
this->query_form = _queryform;
}
QueryTree::QueryForm QueryTree::getQueryForm()
{
return this->query_form;
}
void QueryTree::setProjectionModifier(ProjectionModifier _projection_modifier)
{
this->projection_modifier = _projection_modifier;
}
QueryTree::ProjectionModifier QueryTree::getProjectionModifier()
{
return this->projection_modifier;
}
void QueryTree::addProjectionVar()
{
this->projection.push_back(ProjectionVar());
}
QueryTree::ProjectionVar& QueryTree::getLastProjectionVar()
{
return this->projection.back();
}
vector<QueryTree::ProjectionVar>& QueryTree::getProjection()
{
return this->projection;
}
Varset QueryTree::getProjectionVarset()
{
Varset varset;
for (int i = 0; i < (int)this->projection.size(); i++)
varset.addVar(this->projection[i].var);
return varset;
}
Varset QueryTree::getResultProjectionVarset()
{
Varset varset;
for (int i = 0; i < (int)this->projection.size(); i++)
if (this->projection[i].aggregate_type == ProjectionVar::None_type)
varset.addVar(this->projection[i].var);
else if (this->projection[i].aggregate_var != "*")
varset.addVar(this->projection[i].aggregate_var);
return varset;
}
void QueryTree::setProjectionAsterisk()
{
this->projection_asterisk = true;
}
bool QueryTree::checkProjectionAsterisk()
{
return this->projection_asterisk;
}
void QueryTree::addGroupByVar(string &_var)
{
this->group_by.addVar(_var);
}
Varset& QueryTree::getGroupByVarset()
{
return this->group_by;
}
void QueryTree::addOrderVar(string &_var, bool _descending)
{
this->order_by.push_back(Order(_var, _descending));
}
vector<QueryTree::Order>& QueryTree::getOrderVarVector()
{
return this->order_by;
}
Varset QueryTree::getOrderByVarset()
{
Varset varset;
for (int i = 0; i < (int)this->order_by.size(); i++)
varset.addVar(this->order_by[i].var);
return varset;
}
void QueryTree::setOffset(int _offset)
{
this->offset = _offset;
}
int QueryTree::getOffset()
{
return this->offset;
}
void QueryTree::setLimit(int _limit)
{
this->limit = _limit;
}
int QueryTree::getLimit()
{
return this->limit;
}
QueryTree::GroupPattern& QueryTree::getGroupPattern()
{
return this->grouppattern;
}
void QueryTree::setUpdateType(UpdateType _updatetype)
{
this->update_type = _updatetype;
}
QueryTree::UpdateType QueryTree::getUpdateType()
{
return this->update_type;
}
QueryTree::GroupPattern& QueryTree::getInsertPatterns()
{
return this->insert_patterns;
}
QueryTree::GroupPattern& QueryTree::getDeletePatterns()
{
return this->delete_patterns;
}
bool QueryTree::checkWellDesigned()
{
bool check_condition = true;
this->grouppattern.checkNoMinusAndOptionalVarAndSafeFilter(Varset(), Varset(), check_condition);
return check_condition;
}
bool QueryTree::checkAtLeastOneAggregateFunction()
{
for (int i = 0; i < (int)this->projection.size(); i++)
if (this->projection[i].aggregate_type != ProjectionVar::None_type)
return true;
return false;
}
bool QueryTree::checkSelectAggregateFunctionGroupByValid()
{
if (this->checkAtLeastOneAggregateFunction() && this->group_by.empty())
{
for (int i = 0; i < (int)this->projection.size(); i++)
if (this->projection[i].aggregate_type == ProjectionVar::None_type)
return false;
}
if (!this->group_by.empty())
{
for (int i = 0; i < (int)this->projection.size(); i++)
if (this->projection[i].aggregate_type == ProjectionVar::None_type && !this->group_by.findVar(this->projection[i].var))
return false;
}
return true;
}
void QueryTree::print()
{
for (int j = 0; j < 80; j++) printf("="); printf("\n");
if (this->update_type == Not_Update)
{
if (this->query_form == Select_Query)
{
printf("SELECT");
if (this->projection_modifier == Modifier_Distinct)
printf(" DISTINCT");
printf("\n");
printf("Var: \t");
for (int i = 0; i < (int)this->projection.size(); i++)
{
if (this->projection[i].aggregate_type == QueryTree::ProjectionVar::None_type)
printf("%s\t", this->projection[i].var.c_str());
else
{
printf("(");
if (this->projection[i].aggregate_type == QueryTree::ProjectionVar::Count_type)
printf("COUNT(");
if (this->projection[i].aggregate_type == QueryTree::ProjectionVar::Sum_type)
printf("SUM(");
if (this->projection[i].aggregate_type == QueryTree::ProjectionVar::Min_type)
printf("MIN(");
if (this->projection[i].aggregate_type == QueryTree::ProjectionVar::Max_type)
printf("MAX(");
if (this->projection[i].aggregate_type == QueryTree::ProjectionVar::Avg_type)
printf("AVG(");
if (this->projection[i].distinct)
printf("DISTINCT ");
printf("%s) AS %s)\t", this->projection[i].aggregate_var.c_str(), this->projection[i].var.c_str());
}
}
if (this->projection_asterisk && !this->checkAtLeastOneAggregateFunction())
printf("*");
printf("\n");
}
else printf("ASK\n");
printf("GroupPattern:\n");
this->grouppattern.print(0);
if (this->query_form == Select_Query)
{
if (!this->group_by.empty())
{
printf("GROUP BY\t");
for (int i = 0; i < (int)this->group_by.vars.size(); i++)
printf("%s\t", this->group_by.vars[i].c_str());
printf("\n");
}
if (!this->order_by.empty())
{
printf("ORDER BY\t");
for (int i = 0; i < (int)this->order_by.size(); i++)
{
if (!this->order_by[i].descending) printf("ASC(");
else printf("DESC(");
printf("%s)\t", this->order_by[i].var.c_str());
}
printf("\n");
}
if (this->offset != 0)
printf("OFFSET\t%d\n", this->offset);
if (this->limit != -1)
printf("LIMIT\t%d\n", this->limit);
}
}
else
{
printf("UPDATE\n");
if (this->update_type == Delete_Data || this->update_type == Delete_Where ||
this->update_type == Delete_Clause || this->update_type == Modify_Clause)
{
printf("Delete:\n");
this->delete_patterns.print(0);
}
if (this->update_type == Insert_Data || this->update_type == Insert_Clause || this->update_type == Modify_Clause)
{
printf("Insert:\n");
this->insert_patterns.print(0);
}
if (this->update_type == Delete_Where || this->update_type == Insert_Clause ||
this->update_type == Delete_Clause || this->update_type == Modify_Clause)
{
printf("GroupPattern:\n");
this->grouppattern.print(0);
}
}
for (int j = 0; j < 80; j++) printf("="); printf("\n");
}