1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-08-07 03:22:57 +03:00

Merge branch 'develop' into MCOL-521-b

This commit is contained in:
David Hall
2018-09-10 13:55:52 -05:00
62 changed files with 1922 additions and 878 deletions

View File

@@ -1187,18 +1187,6 @@ ha_calpont_group_by_handler::ha_calpont_group_by_handler(THD* thd_arg, Query* qu
order_by(query->order_by),
having(query->having)
{
List_iterator_fast<Item> item_iter(*select);
Item* item;
char* str = NULL;
while((item = item_iter++))
{
String descr;
item->print(&descr, QT_ORDINARY);
str = new char[descr.length()+1];
strncpy(str, descr.ptr(), descr.length());
str[descr.length()] = '\0';
select_list_descr.push_back(str);
}
}
/***********************************************************
@@ -1207,7 +1195,6 @@ ha_calpont_group_by_handler::ha_calpont_group_by_handler(THD* thd_arg, Query* qu
***********************************************************/
ha_calpont_group_by_handler::~ha_calpont_group_by_handler()
{
select_list_descr.delete_elements();
}
/***********************************************************

View File

@@ -286,7 +286,6 @@ public:
int end_scan();
List<Item>* select;
List<char> select_list_descr;
TABLE_LIST* table_list;
bool distinct;
Item* where;

View File

@@ -1912,6 +1912,79 @@ pair<string, string> parseTableName(const string& tn)
}
//
// get_field_default_value: Returns the default value as a string value
// NOTE: This is duplicated code copied from show.cc and a MDEV-17006 has
// been created.
//
static bool get_field_default_value(THD *thd, Field *field, String *def_value,
bool quoted)
{
bool has_default;
enum enum_field_types field_type= field->type();
has_default= (field->default_value ||
(!(field->flags & NO_DEFAULT_VALUE_FLAG) &&
field->unireg_check != Field::NEXT_NUMBER));
def_value->length(0);
if (has_default)
{
StringBuffer<MAX_FIELD_WIDTH> str(field->charset());
if (field->default_value)
{
field->default_value->print(&str);
if (field->default_value->expr->need_parentheses_in_default())
{
def_value->set_charset(&my_charset_utf8mb4_general_ci);
def_value->append('(');
def_value->append(str);
def_value->append(')');
}
else
def_value->append(str);
}
else if (!field->is_null())
{ // Not null by default
if (field_type == MYSQL_TYPE_BIT)
{
str.qs_append('b');
str.qs_append('\'');
str.qs_append(field->val_int(), 2);
str.qs_append('\'');
quoted= 0;
}
else
{
field->val_str(&str);
if (!field->str_needs_quotes())
quoted= 0;
}
if (str.length())
{
StringBuffer<MAX_FIELD_WIDTH> def_val;
uint dummy_errors;
/* convert to system_charset_info == utf8 */
def_val.copy(str.ptr(), str.length(), field->charset(),
system_charset_info, &dummy_errors);
if (quoted)
append_unescaped(def_value, def_val.ptr(), def_val.length());
else
def_value->append(def_val);
}
else if (quoted)
def_value->set(STRING_WITH_LEN("''"), system_charset_info);
}
else if (field->maybe_null() && quoted)
def_value->set(STRING_WITH_LEN("NULL"), system_charset_info); // Null as default
else
return 0;
}
return has_default;
}
int ha_calpont_impl_create_(const char* name, TABLE* table_arg, HA_CREATE_INFO* create_info, cal_connection_info& ci)
{
#ifdef INFINIDB_DEBUG
@@ -2096,6 +2169,97 @@ int ha_calpont_impl_create_(const char* name, TABLE* table_arg, HA_CREATE_INFO*
return 1;
}
//
// Check if this is a "CREATE TABLE ... LIKE " statement.
// If so generate a full create table statement using the properties of
// the source table. Note that source table has to be a columnstore table and
// we only check for currently supported options.
//
if (thd->lex->create_info.like())
{
TABLE_SHARE *share = table_arg->s;
my_bitmap_map *old_map; // To save the read_set
char datatype_buf[MAX_FIELD_WIDTH], def_value_buf[MAX_FIELD_WIDTH];
String datatype, def_value;
ostringstream oss;
string tbl_name (name+2);
std::replace(tbl_name.begin(), tbl_name.end(), '/', '.');
// Save the current read_set map and mark it for read
old_map= tmp_use_all_columns(table_arg, table_arg->read_set);
oss << "CREATE TABLE " << tbl_name << " (";
restore_record(table_arg, s->default_values);
for (Field **field= table_arg->field; *field; field++)
{
uint flags = (*field)->flags;
datatype.set(datatype_buf, sizeof(datatype_buf), system_charset_info);
(*field)->sql_type(datatype);
if (field != table_arg->field)
oss << ", ";
oss << (*field)->field_name.str << " " << datatype.ptr();
if (flags & NOT_NULL_FLAG)
oss << " NOT NULL";
def_value.set(def_value_buf, sizeof(def_value_buf), system_charset_info);
if (get_field_default_value(thd, *field, &def_value, true)) {
oss << " DEFAULT " << def_value.c_ptr();
}
if ((*field)->comment.length)
{
String comment;
append_unescaped(&comment, (*field)->comment.str, (*field)->comment.length);
oss << " COMMENT ";
oss << comment.c_ptr();
}
}
// End the list of columns
oss<< ") ENGINE=columnstore ";
// Process table level options
if (create_info->auto_increment_value > 1)
{
oss << " AUTO_INCREMENT=" << create_info->auto_increment_value;
}
if (share->table_charset)
{
oss << " DEFAULT CHARSET=" << share->table_charset->csname;
}
// Process table level options such as MIN_ROWS, MAX_ROWS, COMMENT
if (share->min_rows)
{
char buff[80];
longlong10_to_str(share->min_rows, buff, 10);
oss << " MIN_ROWS=" << buff;
}
if (share->max_rows) {
char buff[80];
longlong10_to_str(share->max_rows, buff, 10);
oss << " MAX_ROWS=" << buff;
}
if (share->comment.length) {
String comment;
append_unescaped(&comment, share->comment.str, share->comment.length);
oss << " COMMENT ";
oss << comment.c_ptr();
}
oss << ";";
stmt = oss.str();
tmp_restore_column_map(table_arg->read_set, old_map);
}
rc = ProcessDDLStatement(stmt, db, tbl, tid2sid(thd->thread_id), emsg, compressiontype, isAnyAutoincreCol, startValue, columnName);
if (rc != 0)

View File

@@ -1820,8 +1820,11 @@ int ha_calpont_impl_write_batch_row_(uchar* buf, TABLE* table, cal_impl_if::cal_
}
else if (ci.columnTypes[colpos].colWidth < 16777216)
{
dataLength = *(uint32_t*) buf;
buf = buf + 3 ;
dataLength = *(uint16_t*) buf;
buf = buf + 2 ;
if (*(uint8_t*)buf)
dataLength += 256*256*(*(uint8_t*)buf) ;
buf++;
}
else
{

View File

@@ -190,21 +190,57 @@ bool nonConstFunc(Item_func* ifp)
return false;
}
ReturnedColumn* findCorrespTempField(Item_ref* item, gp_walk_info& gwi, bool clone = true)
/*@brief buildAggFrmTempField- build aggr func from extSELECT list item*/
/***********************************************************
* DESCRIPTION:
* Server adds additional aggregation items to extended SELECT list and
* references them in projection and HAVING. This f() finds
* corresponding item in extSelAggColsItems and builds
* ReturnedColumn using the item.
* PARAMETERS:
* item Item* used to build aggregation
* gwi main structure
* RETURNS
* ReturnedColumn* if corresponding Item has been found
* NULL otherwise
***********************************************************/
ReturnedColumn* buildAggFrmTempField(Item* item, gp_walk_info& gwi)
{
ReturnedColumn* result = NULL;
uint32_t i;
for (i = 0; i < gwi.returnedCols.size(); i++)
Item_field* ifip = NULL;
Item_ref* irip;
Item_func_or_sum* isfp;
switch ( item->type() )
{
if (item->ref[0] && item->ref[0]->name.length &&
gwi.returnedCols[i]->alias().c_str() &&
!strcasecmp(item->ref[0]->name.str, gwi.returnedCols[i]->alias().c_str()))
{
if (clone)
result = gwi.returnedCols[i]->clone();
else
result = gwi.returnedCols[i].get();
case Item::FIELD_ITEM:
ifip = reinterpret_cast<Item_field*>(item);
break;
default:
irip = reinterpret_cast<Item_ref*>(item);
if ( irip )
ifip = reinterpret_cast<Item_field*>(irip->ref[0]);
break;
}
if (ifip && ifip->field)
{
std::vector<Item*>::iterator iter = gwi.extSelAggColsItems.begin();
for ( ; iter != gwi.extSelAggColsItems.end(); iter++ )
{
//Item* temp_isfp = *iter;
isfp = reinterpret_cast<Item_func_or_sum*>(*iter);
if ( isfp->type() == Item::SUM_FUNC_ITEM &&
isfp->result_field == ifip->field )
{
ReturnedColumn* rc = buildAggregateColumn(isfp, gwi);
if (rc)
result = rc;
break;
}
}
}
@@ -1548,8 +1584,7 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
ifp->functype() == Item_func::ISNOTNULL_FUNC)
{
ReturnedColumn* rhs = NULL;
if (!gwip->rcWorkStack.empty())
if (!gwip->rcWorkStack.empty() && !gwip->inCaseStmt)
{
rhs = gwip->rcWorkStack.top();
gwip->rcWorkStack.pop();
@@ -1650,8 +1685,49 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
idbassert(ifp->argument_count() == 1);
ParseTree* ptp = 0;
if (((Item_func*)(ifp->arguments()[0]))->functype() == Item_func::EQUAL_FUNC)
{
// negate it in place
// Note that an EQUAL_FUNC ( a <=> b) was converted to
// ( a = b OR ( a is null AND b is null) )
// NOT of the above expression is: ( a != b AND (a is not null OR b is not null )
if (isPredicateFunction(ifp->arguments()[0], gwip) || ifp->arguments()[0]->type() == Item::COND_ITEM)
if (!gwip->ptWorkStack.empty())
ptp = gwip->ptWorkStack.top();
if (ptp)
{
ParseTree* or_ptp = ptp;
ParseTree* and_ptp = or_ptp->right();
ParseTree* equal_ptp = or_ptp->left();
ParseTree* nullck_left_ptp = and_ptp->left();
ParseTree* nullck_right_ptp = and_ptp->right();
SimpleFilter *sf_left_nullck = dynamic_cast<SimpleFilter*>(nullck_left_ptp->data());
SimpleFilter *sf_right_nullck = dynamic_cast<SimpleFilter*>(nullck_right_ptp->data());
SimpleFilter *sf_equal = dynamic_cast<SimpleFilter*>(equal_ptp->data());
if (sf_left_nullck && sf_right_nullck && sf_equal) {
// Negate the null checks
sf_left_nullck->op()->reverseOp();
sf_right_nullck->op()->reverseOp();
sf_equal->op()->reverseOp();
// Rehook the nodes
ptp = and_ptp;
ptp->left(equal_ptp);
ptp->right(or_ptp);
or_ptp->left(nullck_left_ptp);
or_ptp->right(nullck_right_ptp);
gwip->ptWorkStack.pop();
gwip->ptWorkStack.push(ptp);
}
else {
gwip->fatalParseError = true;
gwip->parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_ASSERTION_FAILURE);
return false;
}
}
}
else if (isPredicateFunction(ifp->arguments()[0], gwip) || ifp->arguments()[0]->type() == Item::COND_ITEM)
{
// negate it in place
if (!gwip->ptWorkStack.empty())
@@ -1725,7 +1801,7 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
}
else if (ifp->functype() == Item_func::EQUAL_FUNC)
{
// a = b OR (a IS NULL AND b IS NULL)
// Convert "a <=> b" to (a = b OR (a IS NULL AND b IS NULL))"
idbassert (gwip->rcWorkStack.size() >= 2);
ReturnedColumn* rhs = gwip->rcWorkStack.top();
gwip->rcWorkStack.pop();
@@ -1737,7 +1813,7 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
// b IS NULL
ConstantColumn* nlhs1 = new ConstantColumn("", ConstantColumn::NULLDATA);
sop.reset(new PredicateOperator("isnull"));
sop->setOpType(lhs->resultType(), rhs->resultType());
sop->setOpType(lhs->resultType(), rhs->resultType());
sfn1 = new SimpleFilter(sop, rhs, nlhs1);
ParseTree* ptpl = new ParseTree(sfn1);
// a IS NULL
@@ -1752,7 +1828,7 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
ptpn->right(ptpr);
// a = b
sop.reset(new PredicateOperator("="));
sop->setOpType(lhs->resultType(), lhs->resultType());
sop->setOpType(lhs->resultType(), rhs->resultType());
sfo = new SimpleFilter(sop, lhs->clone(), rhs->clone());
// OR with the NULL comparison tree
ParseTree* ptp = new ParseTree(new LogicOperator("or"));
@@ -3061,7 +3137,10 @@ ArithmeticColumn* buildArithmeticColumn(
{
// There must be an aggregation column in extended SELECT
// list so find the corresponding column.
ReturnedColumn* rc = findCorrespTempField(static_cast<Item_ref*>(sfitempp[0]), gwi);
// Could have it set if there are aggregation funcs as this function arguments.
gwi.fatalParseError = false;
ReturnedColumn* rc = buildAggFrmTempField(sfitempp[0], gwi);
if(rc)
lhs = new ParseTree(rc);
}
@@ -3077,7 +3156,10 @@ ArithmeticColumn* buildArithmeticColumn(
{
// There must be an aggregation column in extended SELECT
// list so find the corresponding column.
ReturnedColumn* rc = findCorrespTempField(static_cast<Item_ref*>(sfitempp[1]), gwi);
// Could have it set if there are aggregation funcs as this function arguments.
gwi.fatalParseError = false;
ReturnedColumn* rc = buildAggFrmTempField(sfitempp[1], gwi);
if(rc)
rhs = new ParseTree(rc);
}
@@ -3416,10 +3498,11 @@ ReturnedColumn* buildFunctionColumn(
ReturnedColumn* rc = buildReturnedColumn(ifp->arguments()[i], gwi, nonSupport, pushdownHand);
// MCOL-1510 It must be a temp table field, so find the corresponding column.
if (pushdownHand
if (!rc && pushdownHand
&& ifp->arguments()[i]->type() == Item::REF_ITEM)
{
rc = findCorrespTempField(static_cast<Item_ref*>(ifp->arguments()[i]), gwi);
gwi.fatalParseError = false;
rc = buildAggFrmTempField(ifp->arguments()[i], gwi);
}
if (!rc || nonSupport)
@@ -3772,8 +3855,12 @@ FunctionColumn* buildCaseFunction(Item_func* item, gp_walk_info& gwi, bool& nonS
if (funcName == "case_searched" &&
(i < arg_offset))
{
// MCOL-1472 Nested CASE with an ISNULL predicate. We don't want the predicate
// to pull off of rcWorkStack, so we set this inCaseStmt flag to tell it
// not to.
gwi.inCaseStmt = true;
sptp.reset(buildParseTree((Item_func*)(item->arguments()[i]), gwi, nonSupport));
gwi.inCaseStmt = false;
if (!gwi.ptWorkStack.empty() && *gwi.ptWorkStack.top()->data() == sptp->data())
{
gwi.ptWorkStack.pop();
@@ -4101,7 +4188,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
// MCOL-1201 For UDAnF multiple parameters
vector<SRCP> selCols;
vector<SRCP> orderCols;
bool bIsConst = false;
if (!(gwi.thd->infinidb_vtable.cal_conn_info))
gwi.thd->infinidb_vtable.cal_conn_info = (void*)(new cal_connection_info());
@@ -4280,6 +4367,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
parm.reset(buildReturnedColumn(sfitemp, gwi, gwi.fatalParseError));
ac->constCol(parm);
bIsConst = true;
break;
}
@@ -4396,7 +4484,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
// Get result type
// Modified for MCOL-1201 multi-argument aggregate
if (ac->aggParms().size() > 0)
if (!bIsConst && ac->aggParms().size() > 0)
{
// These are all one parm functions, so we can safely
// use the first parm for result type.
@@ -5299,26 +5387,9 @@ void gp_walk(const Item* item, void* arg)
}
else if (col->type() == Item::FIELD_ITEM && gwip->clauseType == HAVING)
{
Item_field* ifip = static_cast<Item_field*>(col);
std::vector<Item*>::iterator iter = gwip->havingAggColsItems.begin();
Item_func_or_sum* isfp = NULL;
for ( ; iter != gwip->havingAggColsItems.end(); iter++ )
{
Item* temp_isfp = *iter;
isfp = reinterpret_cast<Item_func_or_sum*>(temp_isfp);
if ( isfp->type() == Item::SUM_FUNC_ITEM &&
isfp->result_field == ifip->field )
{
ReturnedColumn* rc = buildAggregateColumn(isfp, *gwip);
if (rc)
gwip->rcWorkStack.push(rc);
break;
}
}
ReturnedColumn* rc = buildAggFrmTempField(const_cast<Item*>(item), *gwip);
if (rc)
gwip->rcWorkStack.push(rc);
break;
}
@@ -5583,7 +5654,7 @@ void parse_item (Item* item, vector<Item_field*>& field_vec,
// and set hasNonSupportItem if it is so.
ReturnedColumn* rc = NULL;
if (gwi)
rc = findCorrespTempField(ref, *gwi, false);
rc = buildAggFrmTempField(ref, *gwi);
if (!rc)
{
@@ -8193,12 +8264,13 @@ int cp_get_group_plan(THD* thd, SCSEP& csep, cal_impl_if::cal_group_info& gi)
SELECT_LEX select_lex = lex->select_lex;
gp_walk_info gwi;
gwi.thd = thd;
gwi.groupByAuxDescr = gi.groupByAuxDescr;
int status = getGroupPlan(gwi, select_lex, csep, gi);
#ifdef DEBUG_WALK_COND
cerr << "---------------- cp_get_group_plan EXECUTION PLAN ----------------" << endl;
cerr << *csep << endl ;
cerr << "-------------- EXECUTION PLAN END --------------\n" << endl;
#endif
if (status > 0)
return ER_INTERNAL_ERROR;
@@ -8575,8 +8647,6 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro
string sel_cols_in_create;
string sel_cols_in_select;
bool redo = false;
List_iterator_fast<char> itDescr(*gi.groupByAuxDescr);
char* fieldDescr;
// empty rcWorkStack and ptWorkStack. They should all be empty by now.
clearStacks(gwi);
@@ -8595,14 +8665,12 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro
while ((item = it++))
{
// Given the size of gi.groupByAuxDescr is equal to gi.groupByFields
fieldDescr = itDescr++;
string itemAlias;
if(item->name.length)
itemAlias = (item->name.str);
else
{
itemAlias = (fieldDescr ? fieldDescr: "<NULL>");
itemAlias = "<NULL>";
}
// @bug 5916. Need to keep checking until getting concret item in case
@@ -8709,18 +8777,11 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro
return ER_CHECK_NOT_IMPLEMENTED;
}
if(!ac->alias().length())
ac->alias(fieldDescr);
// add this agg col to returnedColumnList
boost::shared_ptr<ReturnedColumn> spac(ac);
gwi.returnedCols.push_back(spac);
// This item will be used in HAVING later.
Item_func_or_sum* isfp = reinterpret_cast<Item_func_or_sum*>(item);
if ( ! isfp->name.length )
{
gwi.havingAggColsItems.push_back(item);
}
// This item could be used in projection or HAVING later.
gwi.extSelAggColsItems.push_back(item);
gwi.selectCols.push_back('`' + escapeBackTick(spac->alias().c_str()) + '`');
String str(256);
@@ -10103,20 +10164,28 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro
}
}
if (ord_cols.length() > 0) // has order by
if ( gwi.orderByCols.size() ) // has order by
{
gwi.thd->infinidb_vtable.has_order_by = true;
csep->hasOrderBy(true);
ord_cols = " order by " + ord_cols;
select_query += ord_cols;
csep->specHandlerProcessed(true);
}
}
// LIMIT and OFFSET are extracted from TABLE_LIST elements.
// All of JOIN-ed tables contain relevant limit and offset.
if (gi.groupByTables->select_lex->select_limit)
uint64_t limit = (uint64_t)-1;
if (gi.groupByTables->select_lex->select_limit &&
( limit = static_cast<Item_int*>(gi.groupByTables->select_lex->select_limit)->val_int() ) &&
limit != (uint64_t)-1 )
{
csep->limitNum(((Item_int*)gi.groupByTables->select_lex->select_limit)->val_int());
csep->limitNum(limit);
}
else if (csep->hasOrderBy())
{
// We use LimitedOrderBy so set the limit to
// go through the check in addOrderByAndLimit
csep->limitNum((uint64_t) - 2);
}
if (gi.groupByTables->select_lex->offset_limit)
@@ -10228,3 +10297,4 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro
}
// vim:ts=4 sw=4:

View File

@@ -1964,7 +1964,7 @@ uint32_t doUpdateDelete(THD* thd)
}
else
{
thd->set_row_count_func(dmlRowCount);
thd->set_row_count_func(dmlRowCount+thd->get_row_count_func());
}
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, errorMsg.c_str());
@@ -1972,7 +1972,7 @@ uint32_t doUpdateDelete(THD* thd)
else
{
// if (dmlRowCount != 0) //Bug 5117. Handling self join.
thd->set_row_count_func(dmlRowCount);
thd->set_row_count_func(dmlRowCount+thd->get_row_count_func());
//cout << " error status " << ci->rc << " and rowcount = " << dmlRowCount << endl;
@@ -5265,7 +5265,6 @@ int ha_calpont_impl_group_by_init(ha_calpont_group_by_handler* group_hand, TABLE
// MCOL-1052 Send Items lists down to the optimizer.
gi.groupByTables = group_hand->table_list;
gi.groupByFields = group_hand->select;
gi.groupByAuxDescr = &group_hand->select_list_descr;
gi.groupByWhere = group_hand->where;
gi.groupByGroup = group_hand->group_by;
gi.groupByOrder = group_hand->order_by;

View File

@@ -99,7 +99,7 @@ struct gp_walk_info
execplan::CalpontSelectExecutionPlan::ReturnedColumnList groupByCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList subGroupByCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList orderByCols;
std::vector <Item*> havingAggColsItems;
std::vector <Item*> extSelAggColsItems;
execplan::CalpontSelectExecutionPlan::ColumnMap columnMap;
// This vector temporarily hold the projection columns to be added
// to the returnedCols vector for subquery processing. It will be appended
@@ -142,13 +142,15 @@ struct gp_walk_info
std::map<std::string, execplan::ParseTree*> derivedTbFilterMap;
uint32_t derivedTbCnt;
std::vector<execplan::SCSEP> subselectList;
List<char>* groupByAuxDescr;
// Kludge for Bug 750
int32_t recursionLevel;
int32_t recursionHWM;
std::stack<int32_t> rcBookMarkStack;
// Kludge for MCOL-1472
bool inCaseStmt;
gp_walk_info() : sessionid(0),
fatalParseError(false),
condPush(false),
@@ -164,7 +166,8 @@ struct gp_walk_info
lastSub(0),
derivedTbCnt(0),
recursionLevel(-1),
recursionHWM(0)
recursionHWM(0),
inCaseStmt(false)
{}
~gp_walk_info() {}
@@ -196,7 +199,6 @@ struct cal_table_info
struct cal_group_info
{
cal_group_info() : groupByFields(0),
groupByAuxDescr(0),
groupByTables(0),
groupByWhere(0),
groupByGroup(0),
@@ -207,7 +209,6 @@ struct cal_group_info
~cal_group_info() { }
List<Item>* groupByFields; // MCOL-1052 SELECT
List<char>* groupByAuxDescr; //MCOL-1052 Auxilary column descriptions
TABLE_LIST* groupByTables; // MCOL-1052 FROM
Item* groupByWhere; // MCOL-1052 WHERE
ORDER* groupByGroup; // MCOL-1052 GROUP BY