1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-07-04 04:42:30 +03:00

MCOL-4957 Fix performance slowdown for processing TIMESTAMP columns.

Part 1:
 As part of MCOL-3776 to address synchronization issue while accessing
 the fTimeZone member of the Func class, mutex locks were added to the
 accessor and mutator methods. However, this slows down processing
 of TIMESTAMP columns in PrimProc significantly as all threads across
 all concurrently running queries would serialize on the mutex. This
 is because PrimProc only has a single global object for the functor
 class (class derived from Func in utils/funcexp/functor.h) for a given
 function name. To fix this problem:

   (1) We remove the fTimeZone as a member of the Func derived classes
   (hence removing the mutexes) and instead use the fOperationType
   member of the FunctionColumn class to propagate the timezone values
   down to the individual functor processing functions such as
   FunctionColumn::getStrVal(), FunctionColumn::getIntVal(), etc.

   (2) To achieve (1), a timezone member is added to the
   execplan::CalpontSystemCatalog::ColType class.

Part 2:
 Several functors in the Funcexp code call dataconvert::gmtSecToMySQLTime()
 and dataconvert::mySQLTimeToGmtSec() functions for conversion between seconds
 since unix epoch and broken-down representation. These functions in turn call
 the C library function localtime_r() which currently has a known bug of holding
 a global lock via a call to __tz_convert. This significantly reduces performance
 in multi-threaded applications where multiple threads concurrently call
 localtime_r(). More details on the bug:
   https://sourceware.org/bugzilla/show_bug.cgi?id=16145

 This bug in localtime_r() caused processing of the Functors in PrimProc to
 slowdown significantly since a query execution causes Functors code to be
 processed in a multi-threaded manner.

 As a fix, we remove the calls to localtime_r() from gmtSecToMySQLTime()
 and mySQLTimeToGmtSec() by performing the timezone-to-offset conversion
 (done in dataconvert::timeZoneToOffset()) during the execution plan
 creation in the plugin. Note that localtime_r() is only called when the
 time_zone system variable is set to "SYSTEM".

 This fix also required changing the timezone type from a std::string to
 a long across the system.
This commit is contained in:
Gagan Goel
2022-02-09 19:03:00 -05:00
parent f67a37bcae
commit 973e5024d8
120 changed files with 1022 additions and 695 deletions

View File

@ -1509,7 +1509,7 @@ uint32_t buildJoin(gp_walk_info& gwi, List<TABLE_LIST>& join_list,
return 0;
}
ParseTree* buildRowPredicate(THD* thd, RowColumn* lhs, RowColumn* rhs, string predicateOp)
ParseTree* buildRowPredicate(gp_walk_info* gwip, RowColumn* lhs, RowColumn* rhs, string predicateOp)
{
PredicateOperator* po = new PredicateOperator(predicateOp);
boost::shared_ptr<Operator> sop(po);
@ -1523,7 +1523,7 @@ ParseTree* buildRowPredicate(THD* thd, RowColumn* lhs, RowColumn* rhs, string pr
ParseTree* pt = new ParseTree(lo);
sop->setOpType(lhs->columnVec()[0]->resultType(), rhs->columnVec()[0]->resultType());
SimpleFilter* sf = new SimpleFilter(sop, lhs->columnVec()[0].get(), rhs->columnVec()[0].get());
sf->timeZone(thd->variables.time_zone->get_name()->ptr());
sf->timeZone(gwip->timeZone);
pt->left(new ParseTree(sf));
for (uint32_t i = 1; i < lhs->columnVec().size(); i++)
@ -1531,7 +1531,7 @@ ParseTree* buildRowPredicate(THD* thd, RowColumn* lhs, RowColumn* rhs, string pr
sop.reset(po->clone());
sop->setOpType(lhs->columnVec()[i]->resultType(), rhs->columnVec()[i]->resultType());
SimpleFilter* sf = new SimpleFilter(sop, lhs->columnVec()[i].get(), rhs->columnVec()[i].get());
sf->timeZone(thd->variables.time_zone->get_name()->ptr());
sf->timeZone(gwip->timeZone);
pt->right(new ParseTree(sf));
if (i + 1 < lhs->columnVec().size())
@ -1551,7 +1551,7 @@ bool buildRowColumnFilter(gp_walk_info* gwip, RowColumn* rhs, RowColumn* lhs, It
{
// (c1,c2,..) = (v1,v2,...) transform to: c1=v1 and c2=v2 and ...
assert(!lhs->columnVec().empty() && lhs->columnVec().size() == rhs->columnVec().size());
gwip->ptWorkStack.push(buildRowPredicate(gwip->thd, rhs, lhs, ifp->func_name()));
gwip->ptWorkStack.push(buildRowPredicate(gwip, rhs, lhs, ifp->func_name()));
}
else if (ifp->functype() == Item_func::IN_FUNC)
{
@ -1595,7 +1595,7 @@ bool buildRowColumnFilter(gp_walk_info* gwip, RowColumn* rhs, RowColumn* lhs, It
RowColumn* vals = dynamic_cast<RowColumn*>(tmpStack.top());
valVec.push_back(vals);
tmpStack.pop();
ParseTree* pt = buildRowPredicate(gwip->thd, columns, vals, predicateOp);
ParseTree* pt = buildRowPredicate(gwip, columns, vals, predicateOp);
while (!tmpStack.empty())
{
@ -1604,7 +1604,7 @@ bool buildRowColumnFilter(gp_walk_info* gwip, RowColumn* rhs, RowColumn* lhs, It
vals = dynamic_cast<RowColumn*>(tmpStack.top());
valVec.push_back(vals);
tmpStack.pop();
pt1->right(buildRowPredicate(gwip->thd, columns->clone(), vals, predicateOp));
pt1->right(buildRowPredicate(gwip, columns->clone(), vals, predicateOp));
pt = pt1;
}
@ -1646,8 +1646,8 @@ bool buildRowColumnFilter(gp_walk_info* gwip, RowColumn* rhs, RowColumn* lhs, It
break;
sop->setOpType(sc->resultType(), valVec[j]->columnVec()[i]->resultType());
cf->pushFilter(new SimpleFilter(sop, sc->clone(), valVec[j]->columnVec()[i]->clone(),
gwip->thd->variables.time_zone->get_name()->ptr()));
cf->pushFilter(
new SimpleFilter(sop, sc->clone(), valVec[j]->columnVec()[i]->clone(), gwip->timeZone));
}
if (j < valVec.size())
@ -1792,7 +1792,7 @@ bool buildEqualityPredicate(execplan::ReturnedColumn* lhs, execplan::ReturnedCol
}
SimpleFilter* sf = new SimpleFilter();
sf->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
sf->timeZone(gwip->timeZone);
//@bug 2101 for when there are only constants in a delete or update where clause (eg "where 5 < 6").
// There will be no field column and it will get here only if the comparison is true.
@ -1906,11 +1906,11 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
sop.reset(new PredicateOperator(">"));
sop->setOpType(filterCol->resultType(), rhs->resultType());
sfr = new SimpleFilter(sop, filterCol, rhs);
sfr->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
sfr->timeZone(gwip->timeZone);
sop.reset(new PredicateOperator("<"));
sop->setOpType(filterCol->resultType(), lhs->resultType());
sfl = new SimpleFilter(sop, filterCol->clone(), lhs);
sfl->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
sfl->timeZone(gwip->timeZone);
ParseTree* ptp = new ParseTree(new LogicOperator("or"));
ptp->left(sfr);
ptp->right(sfl);
@ -1921,11 +1921,11 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
sop.reset(new PredicateOperator("<="));
sop->setOpType(filterCol->resultType(), rhs->resultType());
sfr = new SimpleFilter(sop, filterCol, rhs);
sfr->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
sfr->timeZone(gwip->timeZone);
sop.reset(new PredicateOperator(">="));
sop->setOpType(filterCol->resultType(), lhs->resultType());
sfl = new SimpleFilter(sop, filterCol->clone(), lhs);
sfl->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
sfl->timeZone(gwip->timeZone);
ParseTree* ptp = new ParseTree(new LogicOperator("and"));
ptp->left(sfr);
ptp->right(sfl);
@ -1985,8 +1985,7 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
cf->op(sop);
sop.reset(new PredicateOperator(eqop));
sop->setOpType(gwip->scsp->resultType(), lhs->resultType());
cf->pushFilter(
new SimpleFilter(sop, gwip->scsp->clone(), lhs, gwip->thd->variables.time_zone->get_name()->ptr()));
cf->pushFilter(new SimpleFilter(sop, gwip->scsp->clone(), lhs, gwip->timeZone));
while (!gwip->rcWorkStack.empty())
{
@ -1998,8 +1997,7 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
gwip->rcWorkStack.pop();
sop.reset(new PredicateOperator(eqop));
sop->setOpType(gwip->scsp->resultType(), lhs->resultType());
cf->pushFilter(
new SimpleFilter(sop, gwip->scsp->clone(), lhs, gwip->thd->variables.time_zone->get_name()->ptr()));
cf->pushFilter(new SimpleFilter(sop, gwip->scsp->clone(), lhs, gwip->timeZone));
}
if (!gwip->rcWorkStack.empty())
@ -2065,8 +2063,7 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
{
gwip->rcWorkStack.push(new ConstantColumn((int64_t)udf->val_int()));
}
(dynamic_cast<ConstantColumn*>(gwip->rcWorkStack.top()))
->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(gwip->rcWorkStack.top()))->timeZone(gwip->timeZone);
}
else
{
@ -2088,8 +2085,7 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
{
gwip->rcWorkStack.push(new ConstantColumn(buf.ptr(), ConstantColumn::NUM));
}
(dynamic_cast<ConstantColumn*>(gwip->rcWorkStack.top()))
->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(gwip->rcWorkStack.top()))->timeZone(gwip->timeZone);
return false;
}
@ -2265,19 +2261,19 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
SimpleFilter* sfo = 0;
// b IS NULL
ConstantColumn* nlhs1 = new ConstantColumn("", ConstantColumn::NULLDATA);
nlhs1->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
nlhs1->timeZone(gwip->timeZone);
sop.reset(new PredicateOperator("isnull"));
sop->setOpType(lhs->resultType(), rhs->resultType());
sfn1 = new SimpleFilter(sop, rhs, nlhs1);
sfn1->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
sfn1->timeZone(gwip->timeZone);
ParseTree* ptpl = new ParseTree(sfn1);
// a IS NULL
ConstantColumn* nlhs2 = new ConstantColumn("", ConstantColumn::NULLDATA);
nlhs2->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
nlhs2->timeZone(gwip->timeZone);
sop.reset(new PredicateOperator("isnull"));
sop->setOpType(lhs->resultType(), rhs->resultType());
sfn2 = new SimpleFilter(sop, lhs, nlhs2);
sfn2->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
sfn2->timeZone(gwip->timeZone);
ParseTree* ptpr = new ParseTree(sfn2);
// AND them both
ParseTree* ptpn = new ParseTree(new LogicOperator("and"));
@ -2287,7 +2283,7 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
sop.reset(new PredicateOperator("="));
sop->setOpType(lhs->resultType(), rhs->resultType());
sfo = new SimpleFilter(sop, lhs->clone(), rhs->clone());
sfo->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
sfo->timeZone(gwip->timeZone);
// OR with the NULL comparison tree
ParseTree* ptp = new ParseTree(new LogicOperator("or"));
ptp->left(sfo);
@ -2337,7 +2333,7 @@ bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip)
bool buildConstPredicate(Item_func* ifp, ReturnedColumn* rhs, gp_walk_info* gwip)
{
SimpleFilter* sf = new SimpleFilter();
sf->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
sf->timeZone(gwip->timeZone);
boost::shared_ptr<Operator> sop(new PredicateOperator(ifp->func_name()));
ConstantColumn* lhs = 0;
@ -2356,7 +2352,7 @@ bool buildConstPredicate(Item_func* ifp, ReturnedColumn* rhs, gp_walk_info* gwip
lhs = new ConstantColumn((int64_t)0, ConstantColumn::NUM);
sop.reset(new PredicateOperator("="));
}
lhs->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
lhs->timeZone(gwip->timeZone);
CalpontSystemCatalog::ColType opType = rhs->resultType();
@ -2431,7 +2427,7 @@ SimpleColumn* buildSimpleColFromDerivedTable(gp_walk_info& gwi, Item_field* ifp)
sc->tableAlias(gwi.tbList[i].alias);
sc->viewName(viewName, lower_case_table_names);
sc->resultType(ct);
sc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
sc->timeZone(gwi.timeZone);
break;
}
}
@ -2490,7 +2486,7 @@ SimpleColumn* buildSimpleColFromDerivedTable(gp_walk_info& gwi, Item_field* ifp)
sc->tableName(csep->derivedTbAlias());
sc->colPosition(j);
sc->tableAlias(csep->derivedTbAlias());
sc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
sc->timeZone(gwi.timeZone);
if (!viewName.empty())
{
sc->viewName(viewName, lower_case_table_names);
@ -2613,7 +2609,7 @@ void collectAllCols(gp_walk_info& gwi, Item_field* ifp)
sc->tableAlias(csep->derivedTbAlias());
sc->viewName(gwi.tbList[i].view);
sc->resultType(cols[j]->resultType());
sc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
sc->timeZone(gwi.timeZone);
// @bug5634 derived table optimization
cols[j]->incRefCount();
@ -2661,7 +2657,7 @@ void collectAllCols(gp_walk_info& gwi, Item_field* ifp)
sc->resultType(ct);
sc->tableAlias(gwi.tbList[i].alias, lower_case_table_names);
sc->viewName(viewName, lower_case_table_names);
sc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
sc->timeZone(gwi.timeZone);
srcp.reset(sc);
gwi.returnedCols.push_back(srcp);
gwi.columnMap.insert(CalpontSelectExecutionPlan::ColumnMap::value_type(sc->columnName(), srcp));
@ -2994,7 +2990,7 @@ SimpleColumn* getSmallestColumn(boost::shared_ptr<CalpontSystemCatalog> csc,
sc->columnName(rc->alias());
sc->sequence(0);
sc->tableAlias(tan.alias);
sc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
sc->timeZone(gwi.timeZone);
sc->derivedTable(csep->derivedTbAlias());
sc->derivedRefCol(rc);
return sc;
@ -3013,7 +3009,7 @@ SimpleColumn* getSmallestColumn(boost::shared_ptr<CalpontSystemCatalog> csc,
tan.fisColumnStore, gwi.sessionid, lower_case_table_names);
sc->tableAlias(table->alias.ptr(), lower_case_table_names);
sc->isColumnStore(false);
sc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
sc->timeZone(gwi.timeZone);
sc->resultType(fieldType_MysqlToIDB(field));
sc->oid(field->field_index + 1);
return sc;
@ -3043,7 +3039,7 @@ SimpleColumn* getSmallestColumn(boost::shared_ptr<CalpontSystemCatalog> csc,
SimpleColumn* sc = new SimpleColumn(tcn.schema, tcn.table, tcn.column, csc->sessionID());
sc->tableAlias(tan.alias);
sc->viewName(tan.view);
sc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
sc->timeZone(gwi.timeZone);
sc->resultType(csc->colType(oidlist[minWidthColOffset].objnum));
sc->charsetNumber(table->field[minWidthColOffset]->charset()->number);
return sc;
@ -3209,7 +3205,7 @@ ReturnedColumn* buildReturnedColumnNull(gp_walk_info& gwi)
return new SimpleColumn("noop");
ConstantColumn* rc = new ConstantColumnNull();
if (rc)
rc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
rc->timeZone(gwi.timeZone);
return rc;
}
@ -3346,7 +3342,7 @@ static ConstantColumn* buildConstantColumnMaybeNullFromValStr(const Item* item,
{
ConstantColumn* rc = newConstantColumnMaybeNullFromValStrNoTz(item, valStr, gwi);
if (rc)
rc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
rc->timeZone(gwi.timeZone);
return rc;
}
@ -3365,7 +3361,7 @@ static ConstantColumn* buildConstantColumnNotNullUsingValNative(Item* item, gp_w
{
ConstantColumn* rc = newConstantColumnNotNullUsingValNativeNoTz(item, gwi);
if (rc)
rc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
rc->timeZone(gwi.timeZone);
return rc;
}
@ -3565,7 +3561,7 @@ ArithmeticColumn* buildArithmeticColumn(Item_func* item, gp_walk_info& gwi, bool
ArithmeticColumn* ac = new ArithmeticColumn();
Item** sfitempp = item->arguments();
ArithmeticOperator* aop = new ArithmeticOperator(item->func_name());
aop->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
aop->timeZone(gwi.timeZone);
aop->setOverflowCheck(get_decimal_overflow_check(gwi.thd));
ParseTree* pt = new ParseTree(aop);
// ReturnedColumn *lhs = 0, *rhs = 0;
@ -3692,7 +3688,7 @@ ArithmeticColumn* buildArithmeticColumn(Item_func* item, gp_walk_info& gwi, bool
else
{
ConstantColumn* cc = new ConstantColumn(string("0"), (int64_t)0);
cc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
cc->timeZone(gwi.timeZone);
if (gwi.clauseType == SELECT || gwi.clauseType == HAVING || gwi.clauseType == GROUP_BY) // select clause
{
@ -4065,15 +4061,14 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
THD* thd = current_thd;
sptp.reset(
new ParseTree(new ConstantColumn(static_cast<uint64_t>(thd->variables.default_week_format))));
(dynamic_cast<ConstantColumn*>(sptp->data()))
->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwi.timeZone);
funcParms.push_back(sptp);
}
// add the keyword unit argument for interval function
if (funcName == "date_add_interval" || funcName == "extract" || funcName == "timestampdiff")
{
addIntervalArgs(gwi.thd, ifp, funcParms);
addIntervalArgs(&gwi, ifp, funcParms);
}
// check for unsupported arguments add the keyword unit argument for extract functions
@ -4123,19 +4118,19 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
// add the keyword unit argument and char length for cast functions
if (funcName == "cast_as_char")
{
castCharArgs(gwi.thd, ifp, funcParms);
castCharArgs(&gwi, ifp, funcParms);
}
// add the length and scale arguments
if (funcName == "decimal_typecast")
{
castDecimalArgs(gwi.thd, ifp, funcParms);
castDecimalArgs(&gwi, ifp, funcParms);
}
// add the type argument
if (funcName == "get_format")
{
castTypeArgs(gwi.thd, ifp, funcParms);
castTypeArgs(&gwi, ifp, funcParms);
}
// add my_time_zone
@ -4150,8 +4145,7 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
// FIXME: Get GMT offset (in seconds east of GMT) in Windows...
sptp.reset(new ParseTree(new ConstantColumn(static_cast<int64_t>(0), ConstantColumn::NUM)));
#endif
(dynamic_cast<ConstantColumn*>(sptp->data()))
->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwi.timeZone);
funcParms.push_back(sptp);
}
@ -4161,12 +4155,10 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
if (funcParms.size() == 0)
{
sptp.reset(new ParseTree(new ConstantColumn((int64_t)gwi.thd->rand.seed1, ConstantColumn::NUM)));
(dynamic_cast<ConstantColumn*>(sptp->data()))
->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwi.timeZone);
funcParms.push_back(sptp);
sptp.reset(new ParseTree(new ConstantColumn((int64_t)gwi.thd->rand.seed2, ConstantColumn::NUM)));
(dynamic_cast<ConstantColumn*>(sptp->data()))
->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwi.timeZone);
funcParms.push_back(sptp);
gwi.no_parm_func_list.push_back(fc);
}
@ -4220,8 +4212,7 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
tzinfo = string((char*)buf, length);
}
sptp.reset(new ParseTree(new ConstantColumn(tzinfo)));
(dynamic_cast<ConstantColumn*>(sptp->data()))
->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwi.timeZone);
funcParms.push_back(sptp);
tzinfo.clear();
if (to_tzinfo)
@ -4233,8 +4224,7 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
tzinfo = string((char*)buf, length);
}
sptp.reset(new ParseTree(new ConstantColumn(tzinfo)));
(dynamic_cast<ConstantColumn*>(sptp->data()))
->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwi.timeZone);
funcParms.push_back(sptp);
tzinfo.clear();
}
@ -4253,8 +4243,7 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
sign = -1;
}
sptp.reset(new ParseTree(new ConstantColumn(sign)));
(dynamic_cast<ConstantColumn*>(sptp->data()))
->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwi.timeZone);
funcParms.push_back(sptp);
}
@ -4327,16 +4316,23 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
#endif
fc->operationType(functor->operationType(funcParms, fc->resultType()));
// For some reason, MDB has MYSQL_TYPE_DATETIME2 for functions on a TIMESTAMP
if (fc->operationType().colDataType == CalpontSystemCatalog::TIMESTAMP)
execplan::CalpontSystemCatalog::ColType& resultType = fc->resultType();
resultType.setTimeZone(gwi.timeZone);
fc->operationType(functor->operationType(funcParms, resultType));
// For floor/ceiling/truncate/round functions applied on TIMESTAMP columns, set the
// function result type to TIMESTAMP
if ((funcName == "floor" || funcName == "ceiling" || funcName == "truncate" || funcName == "round") &&
fc->operationType().colDataType == CalpontSystemCatalog::TIMESTAMP)
{
CalpontSystemCatalog::ColType ct = fc->resultType();
ct.colDataType = CalpontSystemCatalog::TIMESTAMP;
ct.colWidth = 8;
fc->resultType(ct);
}
fc->expressionId(ci->expressionId++);
// A few functions use a different collation than that found in
// the base ifp class
if (funcName == "locate" || funcName == "find_in_set" || funcName == "strcmp")
@ -4409,7 +4405,7 @@ ReturnedColumn* buildFunctionColumn(Item_func* ifp, gp_walk_info& gwi, bool& non
}
}
fc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
fc->timeZone(gwi.timeZone);
return fc;
}
@ -4549,11 +4545,13 @@ FunctionColumn* buildCaseFunction(Item_func* item, gp_walk_info& gwi, bool& nonS
Func* functor = funcexp->getFunctor(funcName);
fc->resultType(colType_MysqlToIDB(item));
fc->operationType(functor->operationType(funcParms, fc->resultType()));
execplan::CalpontSystemCatalog::ColType& resultType = fc->resultType();
resultType.setTimeZone(gwi.timeZone);
fc->operationType(functor->operationType(funcParms, resultType));
fc->functionName(funcName);
fc->functionParms(funcParms);
fc->expressionId(ci->expressionId++);
fc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
fc->timeZone(gwi.timeZone);
// For function join. If any argument has non-zero joininfo, set it to the function.
fc->setSimpleColumnList();
@ -4695,7 +4693,7 @@ SimpleColumn* buildSimpleColumn(Item_field* ifp, gp_walk_info& gwi)
sc->alias(ifp->name.str);
sc->isColumnStore(prm.columnStore());
sc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
sc->timeZone(gwi.timeZone);
if (!prm.columnStore() && ifp->field)
sc->oid(ifp->field->field_index + 1); // ExeMgr requires offset started from 1
@ -4803,7 +4801,7 @@ static void processAggregateColumnConstArg(gp_walk_info& gwi, SRCP& parm, Aggreg
{
// Explicit NULL or a const function that evaluated to NULL
cc = new ConstantColumnNull();
cc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
cc->timeZone(gwi.timeZone);
parm.reset(cc);
ac->constCol(SRCP(rt));
return;
@ -4878,7 +4876,7 @@ ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi)
ac = new AggregateColumn(gwi.sessionid);
}
ac->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
ac->timeZone(gwi.timeZone);
if (isp->name.length)
ac->alias(isp->name.str);
@ -5397,7 +5395,7 @@ because it has multiple arguments.";
return ac;
}
void addIntervalArgs(THD* thd, Item_func* ifp, FunctionParm& functionParms)
void addIntervalArgs(gp_walk_info* gwip, Item_func* ifp, FunctionParm& functionParms)
{
string funcName = ifp->func_name();
int interval_type = -1;
@ -5409,7 +5407,7 @@ void addIntervalArgs(THD* thd, Item_func* ifp, FunctionParm& functionParms)
else if (funcName == "extract")
interval_type = ((Item_extract*)ifp)->int_type;
functionParms.push_back(getIntervalType(thd, interval_type));
functionParms.push_back(getIntervalType(gwip, interval_type));
SPTP sptp;
if (funcName == "date_add_interval")
@ -5417,42 +5415,42 @@ void addIntervalArgs(THD* thd, Item_func* ifp, FunctionParm& functionParms)
if (((Item_date_add_interval*)ifp)->date_sub_interval)
{
sptp.reset(new ParseTree(new ConstantColumn((int64_t)OP_SUB)));
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwip->timeZone);
functionParms.push_back(sptp);
}
else
{
sptp.reset(new ParseTree(new ConstantColumn((int64_t)OP_ADD)));
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwip->timeZone);
functionParms.push_back(sptp);
}
}
}
SPTP getIntervalType(THD* thd, int interval_type)
SPTP getIntervalType(gp_walk_info* gwip, int interval_type)
{
SPTP sptp;
sptp.reset(new ParseTree(new ConstantColumn((int64_t)interval_type)));
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwip->timeZone);
return sptp;
}
void castCharArgs(THD* thd, Item_func* ifp, FunctionParm& functionParms)
void castCharArgs(gp_walk_info* gwip, Item_func* ifp, FunctionParm& functionParms)
{
Item_char_typecast* idai = (Item_char_typecast*)ifp;
SPTP sptp;
sptp.reset(new ParseTree(new ConstantColumn((int64_t)idai->get_cast_length())));
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwip->timeZone);
functionParms.push_back(sptp);
}
void castDecimalArgs(THD* thd, Item_func* ifp, FunctionParm& functionParms)
void castDecimalArgs(gp_walk_info* gwip, Item_func* ifp, FunctionParm& functionParms)
{
Item_decimal_typecast* idai = (Item_decimal_typecast*)ifp;
SPTP sptp;
sptp.reset(new ParseTree(new ConstantColumn((int64_t)idai->decimals)));
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwip->timeZone);
functionParms.push_back(sptp);
// max length including sign and/or decimal points
@ -5460,12 +5458,12 @@ void castDecimalArgs(THD* thd, Item_func* ifp, FunctionParm& functionParms)
sptp.reset(new ParseTree(new ConstantColumn((int64_t)idai->max_length - 1)));
else
sptp.reset(new ParseTree(new ConstantColumn((int64_t)idai->max_length - 2)));
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwip->timeZone);
functionParms.push_back(sptp);
}
void castTypeArgs(THD* thd, Item_func* ifp, FunctionParm& functionParms)
void castTypeArgs(gp_walk_info* gwip, Item_func* ifp, FunctionParm& functionParms)
{
Item_func_get_format* get_format = (Item_func_get_format*)ifp;
SPTP sptp;
@ -5474,7 +5472,7 @@ void castTypeArgs(THD* thd, Item_func* ifp, FunctionParm& functionParms)
sptp.reset(new ParseTree(new ConstantColumn("DATE")));
else
sptp.reset(new ParseTree(new ConstantColumn("DATETIME")));
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(sptp->data()))->timeZone(gwip->timeZone);
functionParms.push_back(sptp);
}
@ -5575,7 +5573,7 @@ void gp_walk(const Item* item, void* arg)
Item_hex_hybrid* hip = reinterpret_cast<Item_hex_hybrid*>(const_cast<Item*>(item));
gwip->rcWorkStack.push(new ConstantColumn((int64_t)hip->val_int(), ConstantColumn::NUM));
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(gwip->rcWorkStack.top());
cc->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
cc->timeZone(gwip->timeZone);
break;
}
@ -5594,8 +5592,7 @@ void gp_walk(const Item* item, void* arg)
}
gwip->rcWorkStack.push(new ConstantColumn(cval));
(dynamic_cast<ConstantColumn*>(gwip->rcWorkStack.top()))
->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(gwip->rcWorkStack.top()))->timeZone(gwip->timeZone);
break;
}
@ -5630,7 +5627,7 @@ void gp_walk(const Item* item, void* arg)
{
// push noop for unhandled item
SimpleColumn* rc = new SimpleColumn("noop");
rc->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
rc->timeZone(gwip->timeZone);
gwip->rcWorkStack.push(rc);
break;
}
@ -5650,14 +5647,13 @@ void gp_walk(const Item* item, void* arg)
{
// push noop for unhandled item
SimpleColumn* rc = new SimpleColumn("noop");
rc->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
rc->timeZone(gwip->timeZone);
gwip->rcWorkStack.push(rc);
break;
}
gwip->rcWorkStack.push(new ConstantColumn("", ConstantColumn::NULLDATA));
(dynamic_cast<ConstantColumn*>(gwip->rcWorkStack.top()))
->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(gwip->rcWorkStack.top()))->timeZone(gwip->timeZone);
break;
}
@ -6175,7 +6171,7 @@ void gp_walk(const Item* item, void* arg)
{
// push noop for unhandled item
SimpleColumn* rc = new SimpleColumn("noop");
rc->timeZone(gwip->thd->variables.time_zone->get_name()->ptr());
rc->timeZone(gwip->timeZone);
gwip->rcWorkStack.push(rc);
break;
}
@ -6664,7 +6660,7 @@ int processFrom(bool& isUnion, SELECT_LEX& select_lex, gp_walk_info& gwi, SCSEP&
plan->data(csep->data());
// gwi for the union unit
gp_walk_info union_gwi;
gp_walk_info union_gwi(gwi.timeZone);
union_gwi.thd = gwi.thd;
uint32_t err = 0;
@ -6777,8 +6773,7 @@ int processWhere(SELECT_LEX& select_lex, gp_walk_info& gwi, SCSEP& csep, const s
else if (join && join->zero_result_cause)
{
gwi.rcWorkStack.push(new ConstantColumn((int64_t)0, ConstantColumn::NUM));
(dynamic_cast<ConstantColumn*>(gwi.rcWorkStack.top()))
->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(gwi.rcWorkStack.top()))->timeZone(gwi.timeZone);
}
for (Item* item : gwi.condList)
@ -7226,7 +7221,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
gwi.sessionid = sessionID;
boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID);
csc->identity(CalpontSystemCatalog::FE);
csep->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
csep->timeZone(gwi.timeZone);
gwi.csc = csc;
CalpontSelectExecutionPlan::SelectList derivedTbList;
@ -7607,7 +7602,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
selectSubList.push_back(ssub);
SimpleColumn* rc = new SimpleColumn();
rc->colSource(rc->colSource() | SELECT_SUB);
rc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
rc->timeZone(gwi.timeZone);
if (sub->get_select_lex()->get_table_list())
{
@ -8414,7 +8409,7 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
sc1->tableAlias(sc->tableAlias());
sc1->viewName(sc->viewName());
sc1->colPosition(0);
sc1->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
sc1->timeZone(gwi.timeZone);
minSc.reset(sc1);
}
}
@ -8473,12 +8468,12 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
return 0;
}
int cp_get_table_plan(THD* thd, SCSEP& csep, cal_table_info& ti)
int cp_get_table_plan(THD* thd, SCSEP& csep, cal_table_info& ti, long timeZone)
{
gp_walk_info* gwi = ti.condInfo;
if (!gwi)
gwi = new gp_walk_info();
gwi = new gp_walk_info(timeZone);
gwi->thd = thd;
LEX* lex = thd->lex;
@ -8506,7 +8501,7 @@ int cp_get_table_plan(THD* thd, SCSEP& csep, cal_table_info& ti)
boost::algorithm::to_lower(alias);
}
sc->tableAlias(alias);
sc->timeZone(gwi->thd->variables.time_zone->get_name()->ptr());
sc->timeZone(gwi->timeZone);
assert(sc);
boost::shared_ptr<SimpleColumn> spsc(sc);
gwi->returnedCols.push_back(spsc);
@ -8581,7 +8576,10 @@ int cp_get_table_plan(THD* thd, SCSEP& csep, cal_table_info& ti)
int cp_get_group_plan(THD* thd, SCSEP& csep, cal_impl_if::cal_group_info& gi)
{
SELECT_LEX* select_lex = gi.groupByTables->select_lex;
gp_walk_info gwi;
const char* timeZone = thd->variables.time_zone->get_name()->ptr();
long timeZoneOffset;
dataconvert::timeZoneToOffset(timeZone, strlen(timeZone), &timeZoneOffset);
gp_walk_info gwi(timeZoneOffset);
gwi.thd = thd;
gwi.isGroupByHandler = true;
int status = getGroupPlan(gwi, *select_lex, csep, gi);
@ -8597,7 +8595,7 @@ int cp_get_group_plan(THD* thd, SCSEP& csep, cal_impl_if::cal_group_info& gi)
else if (status < 0)
return status;
// Derived table projection and filter optimization.
derivedTableOptimization(thd, csep);
derivedTableOptimization(&gwi, csep);
return 0;
}
@ -8618,7 +8616,7 @@ int cs_get_derived_plan(ha_columnstore_derived_handler* handler, THD* thd, SCSEP
cerr << "-------------- EXECUTION PLAN END --------------\n" << endl;
#endif
// Derived table projection and filter optimization.
derivedTableOptimization(thd, csep);
derivedTableOptimization(&gwi, csep);
return 0;
}
@ -8649,7 +8647,7 @@ int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* thd, SCSEP&
cerr << "-------------- EXECUTION PLAN END --------------\n" << endl;
#endif
// Derived table projection and filter optimization.
derivedTableOptimization(thd, csep);
derivedTableOptimization(&gwi, csep);
return 0;
}
@ -8954,8 +8952,7 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro
else if (join && join->zero_result_cause)
{
gwi.rcWorkStack.push(new ConstantColumn((int64_t)0, ConstantColumn::NUM));
(dynamic_cast<ConstantColumn*>(gwi.rcWorkStack.top()))
->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
(dynamic_cast<ConstantColumn*>(gwi.rcWorkStack.top()))->timeZone(gwi.timeZone);
}
SELECT_LEX tmp_select_lex;
@ -9443,7 +9440,7 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro
selectSubList.push_back(ssub);
SimpleColumn* rc = new SimpleColumn();
rc->colSource(rc->colSource() | SELECT_SUB);
rc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
rc->timeZone(gwi.timeZone);
if (sub->get_select_lex()->get_table_list())
{
@ -10401,7 +10398,7 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro
sc1->tableName(sc->tableName());
sc1->tableAlias(sc->tableAlias());
sc1->viewName(sc->viewName());
sc1->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
sc1->timeZone(gwi.timeZone);
sc1->colPosition(0);
minSc.reset(sc1);
}