1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-08-01 06:46:55 +03:00

clang format apply

This commit is contained in:
Leonid Fedorov
2022-02-11 12:24:40 +00:00
parent 509f005be7
commit 7c808317dc
1367 changed files with 394342 additions and 413129 deletions

View File

@ -19,161 +19,161 @@
* $Id$
*/
bool parseAutoincrementTableComment ( std::string comment, uint64_t& startValue, std::string& columnName )
bool parseAutoincrementTableComment(std::string comment, uint64_t& startValue, std::string& columnName)
{
algorithm::to_upper(comment);
regex compat("[[:space:]]*AUTOINCREMENT[[:space:]]*=[[:space:]]*", regex_constants::extended);
bool autoincrement = false;
columnName = "";
boost::match_results<std::string::const_iterator> what;
std::string::const_iterator start, end;
start = comment.begin();
end = comment.end();
boost::match_flag_type flags = boost::match_default;
algorithm::to_upper(comment);
regex compat("[[:space:]]*AUTOINCREMENT[[:space:]]*=[[:space:]]*", regex_constants::extended);
bool autoincrement = false;
columnName = "";
boost::match_results<std::string::const_iterator> what;
std::string::const_iterator start, end;
start = comment.begin();
end = comment.end();
boost::match_flag_type flags = boost::match_default;
if (boost::regex_search(start, end, what, compat, flags))
if (boost::regex_search(start, end, what, compat, flags))
{
if (what[0].matched)
{
if (what[0].matched)
// string params (what[0].first, what[0].second);
string params(&(*(what[0].second)));
unsigned i = params.find_first_of(",");
if (i <= params.length())
{
// check whether there is more autoincrement column
string restComment = params.substr(i + 1, params.length());
start = restComment.begin();
end = restComment.end();
if (boost::regex_search(start, end, what, compat, flags))
{
//string params (what[0].first, what[0].second);
string params (&(*(what[0].second)));
unsigned i = params.find_first_of(",");
if ( i <= params.length() )
{
//check whether there is more autoincrement column
string restComment = params.substr(i + 1, params.length());
start = restComment.begin();
end = restComment.end();
if (boost::regex_search(start, end, what, compat, flags))
{
if (what[0].matched)
throw runtime_error(IDBErrorInfo::instance()->errorMsg(ERR_INVALID_NUMBER_AUTOINCREMENT));
}
columnName = params.substr(0, i);
string startVal = params.substr(i + 1, params.length());
//get rid of possible empty space
i = startVal.find_first_not_of(" ");
if ( i <= startVal.length() )
{
startVal = startVal.substr( i, startVal.length());
//; is the seperator between compression and autoincrement comments.
i = startVal.find_first_of(";");
if ( i <= startVal.length() )
{
startVal = startVal.substr( 0, i);
}
i = startVal.find_last_not_of(" ");
if ( i <= startVal.length() )
{
startVal = startVal.substr( 0, i + 1);
}
errno = 0;
char* ep = NULL;
const char* str = startVal.c_str();
startValue = strtoull(str, &ep, 10);
// (no digits) || (more chars) || (other errors & value = 0)
if ((ep == str) || (*ep != '\0') || (errno != 0))
{
throw runtime_error(IDBErrorInfo::instance()->errorMsg(ERR_INVALID_START_VALUE));
}
}
}
else
{
columnName = params;
}
autoincrement = true;
if (what[0].matched)
throw runtime_error(IDBErrorInfo::instance()->errorMsg(ERR_INVALID_NUMBER_AUTOINCREMENT));
}
}
if (columnName.compare("") != 0)
columnName = params.substr(0, i);
string startVal = params.substr(i + 1, params.length());
// get rid of possible empty space
i = startVal.find_first_not_of(" ");
if (i <= startVal.length())
{
startVal = startVal.substr(i, startVal.length());
//; is the seperator between compression and autoincrement comments.
i = startVal.find_first_of(";");
if (i <= startVal.length())
{
startVal = startVal.substr(0, i);
}
i = startVal.find_last_not_of(" ");
if (i <= startVal.length())
{
startVal = startVal.substr(0, i + 1);
}
errno = 0;
char* ep = NULL;
const char* str = startVal.c_str();
startValue = strtoull(str, &ep, 10);
// (no digits) || (more chars) || (other errors & value = 0)
if ((ep == str) || (*ep != '\0') || (errno != 0))
{
throw runtime_error(IDBErrorInfo::instance()->errorMsg(ERR_INVALID_START_VALUE));
}
}
}
else
{
columnName = params;
}
autoincrement = true;
}
}
if (columnName.compare("") != 0)
{
// get rid of possible empty space
unsigned i = columnName.find_last_not_of(" ");
if (i <= columnName.length())
{
//get rid of possible empty space
unsigned i = columnName.find_last_not_of(" ");
if ( i <= columnName.length() )
{
columnName = columnName.substr( 0, i + 1);
}
columnName = columnName.substr(0, i + 1);
}
}
return autoincrement;
return autoincrement;
}
bool parseAutoincrementColumnComment ( std::string comment, uint64_t& startValue )
bool parseAutoincrementColumnComment(std::string comment, uint64_t& startValue)
{
algorithm::to_upper(comment);
regex compat("[[:space:]]*AUTOINCREMENT[[:space:]]*", regex_constants::extended);
bool autoincrement = false;
boost::match_results<std::string::const_iterator> what;
std::string::const_iterator start, end;
start = comment.begin();
end = comment.end();
boost::match_flag_type flags = boost::match_default;
algorithm::to_upper(comment);
regex compat("[[:space:]]*AUTOINCREMENT[[:space:]]*", regex_constants::extended);
bool autoincrement = false;
boost::match_results<std::string::const_iterator> what;
std::string::const_iterator start, end;
start = comment.begin();
end = comment.end();
boost::match_flag_type flags = boost::match_default;
if (boost::regex_search(start, end, what, compat, flags))
if (boost::regex_search(start, end, what, compat, flags))
{
if (what[0].matched)
{
if (what[0].matched)
string params(&(*(what[0].second)));
unsigned i = params.find_first_of(",");
if (i <= params.length())
{
string startVal = params.substr(i + 1, params.length());
// get rid of possible empty space
i = startVal.find_first_not_of(" ");
if (i <= startVal.length())
{
string params (&(*(what[0].second)));
unsigned i = params.find_first_of(",");
startVal = startVal.substr(i, startVal.length());
//; is the seperator between compression and autoincrement comments.
i = startVal.find_first_of(";");
if ( i <= params.length() )
{
string startVal = params.substr(i + 1, params.length());
//get rid of possible empty space
i = startVal.find_first_not_of(" ");
if (i <= startVal.length())
{
startVal = startVal.substr(0, i);
}
if ( i <= startVal.length() )
{
startVal = startVal.substr( i, startVal.length());
//; is the seperator between compression and autoincrement comments.
i = startVal.find_first_of(";");
i = startVal.find_last_not_of(" ");
if ( i <= startVal.length() )
{
startVal = startVal.substr( 0, i);
}
if (i <= startVal.length())
{
startVal = startVal.substr(0, i + 1);
}
i = startVal.find_last_not_of(" ");
errno = 0;
char* ep = NULL;
const char* str = startVal.c_str();
startValue = strtoll(str, &ep, 10);
if ( i <= startVal.length() )
{
startVal = startVal.substr( 0, i + 1);
}
errno = 0;
char* ep = NULL;
const char* str = startVal.c_str();
startValue = strtoll(str, &ep, 10);
// (no digits) || (more chars) || (other errors & value = 0)
if ((ep == str) || (*ep != '\0') || (errno != 0))
{
throw runtime_error (IDBErrorInfo::instance()->errorMsg(ERR_INVALID_START_VALUE));
}
}
}
else
{
startValue = 1;
}
autoincrement = true;
// (no digits) || (more chars) || (other errors & value = 0)
if ((ep == str) || (*ep != '\0') || (errno != 0))
{
throw runtime_error(IDBErrorInfo::instance()->errorMsg(ERR_INVALID_START_VALUE));
}
}
}
}
else
{
startValue = 1;
}
return autoincrement;
autoincrement = true;
}
}
return autoincrement;
}
// vim:ts=4 sw=4:

View File

@ -17,10 +17,10 @@
MA 02110-1301, USA. */
/***********************************************************************
* $Id: ha_exists_sub.cpp 6426 2010-03-30 18:46:11Z zzhu $
*
*
***********************************************************************/
* $Id: ha_exists_sub.cpp 6426 2010-03-30 18:46:11Z zzhu $
*
*
***********************************************************************/
/** @file */
/** class ExistsSub definition */
@ -47,108 +47,111 @@ extern void makeAntiJoin(const ParseTree* n);
void checkCorrelation(const ParseTree* n, void* obj)
{
ExistsFilter* ef = reinterpret_cast<ExistsFilter*>(obj);
TreeNode* tn = n->data();
SimpleFilter* sf = dynamic_cast<SimpleFilter*>(tn);
ExistsFilter* ef = reinterpret_cast<ExistsFilter*>(obj);
TreeNode* tn = n->data();
SimpleFilter* sf = dynamic_cast<SimpleFilter*>(tn);
if (!sf)
return;
if (!sf)
return;
uint64_t lJoinInfo = sf->lhs()->joinInfo();
uint64_t rJoinInfo = sf->rhs()->joinInfo();
uint64_t lJoinInfo = sf->lhs()->joinInfo();
uint64_t rJoinInfo = sf->rhs()->joinInfo();
if (lJoinInfo & JOIN_CORRELATED)
{
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(sf->rhs());
if (lJoinInfo & JOIN_CORRELATED)
{
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(sf->rhs());
if ((!cc || (cc && sf->op()->op() == OP_EQ)) && !(rJoinInfo & JOIN_CORRELATED))
ef->correlated(true);
}
if ((!cc || (cc && sf->op()->op() == OP_EQ)) && !(rJoinInfo & JOIN_CORRELATED))
ef->correlated(true);
}
if (rJoinInfo & JOIN_CORRELATED)
{
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(sf->lhs());
if (rJoinInfo & JOIN_CORRELATED)
{
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(sf->lhs());
if ((!cc || (cc && sf->op()->op() == OP_EQ)) && !(lJoinInfo & JOIN_CORRELATED))
ef->correlated(true);
}
if ((!cc || (cc && sf->op()->op() == OP_EQ)) && !(lJoinInfo & JOIN_CORRELATED))
ef->correlated(true);
}
}
ExistsSub::ExistsSub(gp_walk_info& gwip) : WhereSubQuery(gwip)
{}
{
}
ExistsSub::ExistsSub(gp_walk_info& gwip, Item_subselect* sub) :
WhereSubQuery(gwip, sub)
{}
ExistsSub::ExistsSub(gp_walk_info& gwip, Item_subselect* sub) : WhereSubQuery(gwip, sub)
{
}
ExistsSub::~ExistsSub()
{}
{
}
execplan::ParseTree* ExistsSub::transform()
{
idbassert(fSub);
idbassert(fSub);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::WHERE);
csep->subType (CalpontSelectExecutionPlan::EXISTS_SUBS);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::WHERE);
csep->subType(CalpontSelectExecutionPlan::EXISTS_SUBS);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// @4827 merge table list to gwi in case there is FROM sub to be referenced
// in the FROM sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
// @4827 merge table list to gwi in case there is FROM sub to be referenced
// in the FROM sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
if (fSub->get_select_lex()->with_sum_func)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_AGG_EXISTS);
return NULL;
}
if (fSub->get_select_lex()->with_sum_func)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_AGG_EXISTS);
return NULL;
}
if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep, false) != 0)
{
fGwip.fatalParseError = true;
if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep, false) != 0)
{
fGwip.fatalParseError = true;
if (gwi.fatalParseError && !gwi.parseErrorText.empty())
fGwip.parseErrorText = gwi.parseErrorText;
else
fGwip.parseErrorText = "Error occured in ExistsSub::transform()";
if (gwi.fatalParseError && !gwi.parseErrorText.empty())
fGwip.parseErrorText = gwi.parseErrorText;
else
fGwip.parseErrorText = "Error occured in ExistsSub::transform()";
return NULL;
}
return NULL;
}
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end());
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end());
CalpontSelectExecutionPlan::SelectList derivedTbList;
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin() + gwi.derivedTbCnt, csep->derivedTableList().end());
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin() + gwi.derivedTbCnt,
csep->derivedTableList().end());
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
ExistsFilter* subFilter = new ExistsFilter();
subFilter->correlated(false);
subFilter->sub(csep);
const ParseTree* pt = csep->filters();
ExistsFilter* subFilter = new ExistsFilter();
subFilter->correlated(false);
subFilter->sub(csep);
const ParseTree* pt = csep->filters();
if (pt)
pt->walk(checkCorrelation, subFilter);
if (pt)
pt->walk(checkCorrelation, subFilter);
fGwip.subselectList.push_back(csep);
return new ParseTree(subFilter);
fGwip.subselectList.push_back(csep);
return new ParseTree(subFilter);
}
/**
@ -158,20 +161,20 @@ execplan::ParseTree* ExistsSub::transform()
*/
void ExistsSub::handleNot()
{
ParseTree* pt = fGwip.ptWorkStack.top();
ExistsFilter* subFilter = dynamic_cast<ExistsFilter*>(pt->data());
idbassert(subFilter);
subFilter->notExists(true);
SCSEP csep = subFilter->sub();
const ParseTree* ptsub = csep->filters();
ParseTree* pt = fGwip.ptWorkStack.top();
ExistsFilter* subFilter = dynamic_cast<ExistsFilter*>(pt->data());
idbassert(subFilter);
subFilter->notExists(true);
SCSEP csep = subFilter->sub();
const ParseTree* ptsub = csep->filters();
if (ptsub)
ptsub->walk(makeAntiJoin);
if (ptsub)
ptsub->walk(makeAntiJoin);
ptsub = csep->having();
ptsub = csep->having();
if (ptsub)
ptsub->walk(makeAntiJoin);
if (ptsub)
ptsub->walk(makeAntiJoin);
}
}
} // namespace cal_impl_if

View File

@ -17,10 +17,10 @@
MA 02110-1301, USA. */
/***********************************************************************
* $Id: ha_from_sub.cpp 6377 2010-03-22 20:18:47Z zzhu $
*
*
***********************************************************************/
* $Id: ha_from_sub.cpp 6377 2010-03-22 20:18:47Z zzhu $
*
*
***********************************************************************/
/** @file */
/** class FromSubSelect definition */
@ -44,409 +44,412 @@ using namespace execplan;
namespace cal_impl_if
{
void derivedTableOptimization(THD* thd, SCSEP& csep)
{
// @bug5634. replace the unused column with ConstantColumn from derived table column list,
// ExeMgr will not project ConstantColumn. Only count for local derived column.
// subquery may carry main query derived table list for column reference, those
// derived tables are not checked for optimization in this scope.
CalpontSelectExecutionPlan::SelectList derivedTbList = csep->derivedTableList();
// @bug5634. replace the unused column with ConstantColumn from derived table column list,
// ExeMgr will not project ConstantColumn. Only count for local derived column.
// subquery may carry main query derived table list for column reference, those
// derived tables are not checked for optimization in this scope.
CalpontSelectExecutionPlan::SelectList derivedTbList = csep->derivedTableList();
// @bug6156. Skip horizontal optimization for no table union.
bool horizontalOptimization = true;
// @bug6156. Skip horizontal optimization for no table union.
bool horizontalOptimization = true;
for (uint i = 0; i < derivedTbList.size(); i++)
for (uint i = 0; i < derivedTbList.size(); i++)
{
CalpontSelectExecutionPlan* plan = reinterpret_cast<CalpontSelectExecutionPlan*>(derivedTbList[i].get());
CalpontSelectExecutionPlan::ReturnedColumnList cols = plan->returnedCols();
vector<CalpontSelectExecutionPlan::ReturnedColumnList> unionColVec;
// only do vertical optimization for union all
// @bug6134. Also skip the vertical optimization for select distinct
// because all columns need to be projected to check the distinctness.
bool verticalOptimization = false;
if (plan->distinctUnionNum() == 0 && !plan->distinct())
{
CalpontSelectExecutionPlan* plan = reinterpret_cast<CalpontSelectExecutionPlan*>(derivedTbList[i].get());
CalpontSelectExecutionPlan::ReturnedColumnList cols = plan->returnedCols();
vector<CalpontSelectExecutionPlan::ReturnedColumnList> unionColVec;
verticalOptimization = true;
// only do vertical optimization for union all
// @bug6134. Also skip the vertical optimization for select distinct
// because all columns need to be projected to check the distinctness.
bool verticalOptimization = false;
for (uint j = 0; j < plan->unionVec().size(); j++)
{
unionColVec.push_back(
reinterpret_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get())->returnedCols());
}
}
if (plan->distinctUnionNum() == 0 && !plan->distinct())
if (plan->tableList().empty())
horizontalOptimization = false;
for (uint j = 0; j < plan->unionVec().size(); j++)
{
if (reinterpret_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get())->tableList().empty())
{
horizontalOptimization = false;
break;
}
}
if (verticalOptimization)
{
int64_t val = 1;
// TODO MCOL-4543 Only project those columns from the subquery
// which are referenced in the outer select. So for example,
// if a table t contains 10 columns c1 ... c10 :
// "select count(c2) from (select * from t) q;"
// with p being the subquery execution plan, p->columnMap()
// and p->returnedCols() should both be of size 1, instead
// of 10, with entries for c2 in each.
//
// We are currently performing a dumb optimization:
// Instead of just referencing c2, we are referencing (c1,c2)
// for the above query. This is due to complexity associated
// with modifying ReturnedColumn::colPosition()
// (from a value of 1 to a value of 0) of the outer query
// which references c2. So essentially, if c2 is replaced by c10
// in the above query, we fallback to projecting all 10 columns
// of the subquery in ExeMgr.
// This will be addressed in future.
CalpontSelectExecutionPlan::ReturnedColumnList nonConstCols;
vector<CalpontSelectExecutionPlan::ReturnedColumnList> nonConstUnionColVec(unionColVec.size());
int64_t lastNonConstIndex = -1;
for (int64_t i = cols.size() - 1; i >= 0; i--)
{
// if (cols[i]->derivedTable().empty())
if (cols[i]->refCount() == 0)
{
verticalOptimization = true;
if (cols[i]->derivedRefCol())
cols[i]->derivedRefCol()->decRefCount();
for (uint j = 0; j < plan->unionVec().size(); j++)
if (lastNonConstIndex == -1)
{
SimpleColumn* sc = dynamic_cast<SimpleColumn*>(cols[i].get());
if (sc && (plan->columnMap().count(sc->columnName()) == 1))
{
unionColVec.push_back(
reinterpret_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get())->returnedCols());
}
}
if (plan->tableList().empty())
horizontalOptimization = false;
for (uint j = 0; j < plan->unionVec().size(); j++)
{
if (reinterpret_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get())->tableList().empty())
{
horizontalOptimization = false;
break;
}
}
if (verticalOptimization)
{
int64_t val = 1;
// TODO MCOL-4543 Only project those columns from the subquery
// which are referenced in the outer select. So for example,
// if a table t contains 10 columns c1 ... c10 :
// "select count(c2) from (select * from t) q;"
// with p being the subquery execution plan, p->columnMap()
// and p->returnedCols() should both be of size 1, instead
// of 10, with entries for c2 in each.
//
// We are currently performing a dumb optimization:
// Instead of just referencing c2, we are referencing (c1,c2)
// for the above query. This is due to complexity associated
// with modifying ReturnedColumn::colPosition()
// (from a value of 1 to a value of 0) of the outer query
// which references c2. So essentially, if c2 is replaced by c10
// in the above query, we fallback to projecting all 10 columns
// of the subquery in ExeMgr.
// This will be addressed in future.
CalpontSelectExecutionPlan::ReturnedColumnList nonConstCols;
vector<CalpontSelectExecutionPlan::ReturnedColumnList> nonConstUnionColVec(unionColVec.size());
int64_t lastNonConstIndex = -1;
for (int64_t i = cols.size() - 1; i >= 0; i--)
{
//if (cols[i]->derivedTable().empty())
if (cols[i]->refCount() == 0)
{
if (cols[i]->derivedRefCol())
cols[i]->derivedRefCol()->decRefCount();
if (lastNonConstIndex == -1)
{
SimpleColumn* sc = dynamic_cast<SimpleColumn*>(cols[i].get());
if (sc && (plan->columnMap().count(sc->columnName()) == 1))
{
plan->columnMap().erase(sc->columnName());
}
}
else
{
cols[i].reset(new ConstantColumn(val));
(reinterpret_cast<ConstantColumn*>(cols[i].get()))->timeZone(thd->variables.time_zone->get_name()->ptr());
}
for (uint j = 0; j < unionColVec.size(); j++)
{
if (lastNonConstIndex == -1)
{
CalpontSelectExecutionPlan* unionSubPlan =
reinterpret_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get());
SimpleColumn* sc = dynamic_cast<SimpleColumn*>(unionSubPlan->returnedCols()[i].get());
if (sc && (unionSubPlan->columnMap().count(sc->columnName()) == 1))
{
unionSubPlan->columnMap().erase(sc->columnName());
}
}
else
{
unionColVec[j][i].reset(new ConstantColumn(val));
(reinterpret_cast<ConstantColumn*>(unionColVec[j][i].get()))->timeZone(thd->variables.time_zone->get_name()->ptr());
}
}
}
else if (lastNonConstIndex == -1)
{
lastNonConstIndex = i;
}
plan->columnMap().erase(sc->columnName());
}
}
else
{
cols[i].reset(new ConstantColumn(val));
(reinterpret_cast<ConstantColumn*>(cols[i].get()))
->timeZone(thd->variables.time_zone->get_name()->ptr());
}
for (uint j = 0; j < unionColVec.size(); j++)
{
if (lastNonConstIndex == -1)
{
// None of the subquery columns are referenced, just use the first one
if (!cols.empty())
{
cols[0].reset(new ConstantColumn(val));
(reinterpret_cast<ConstantColumn*>(cols[0].get()))->timeZone(thd->variables.time_zone->get_name()->ptr());
nonConstCols.push_back(cols[0]);
CalpontSelectExecutionPlan* unionSubPlan =
reinterpret_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get());
for (uint j = 0; j < unionColVec.size(); j++)
{
unionColVec[j][0].reset(new ConstantColumn(val));
(reinterpret_cast<ConstantColumn*>(unionColVec[j][0].get()))->timeZone(thd->variables.time_zone->get_name()->ptr());
nonConstUnionColVec[j].push_back(unionColVec[j][0]);
}
}
SimpleColumn* sc = dynamic_cast<SimpleColumn*>(unionSubPlan->returnedCols()[i].get());
if (sc && (unionSubPlan->columnMap().count(sc->columnName()) == 1))
{
unionSubPlan->columnMap().erase(sc->columnName());
}
}
else
{
nonConstCols.assign(cols.begin(), cols.begin() + lastNonConstIndex + 1);
for (uint j = 0; j < unionColVec.size(); j++)
{
nonConstUnionColVec[j].assign(unionColVec[j].begin(), unionColVec[j].begin() + lastNonConstIndex + 1);
}
}
// set back
plan->returnedCols(nonConstCols);
for (uint j = 0; j < unionColVec.size(); j++)
{
CalpontSelectExecutionPlan* unionSubPlan =
reinterpret_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get());
unionSubPlan->returnedCols(nonConstUnionColVec[j]);
unionColVec[j][i].reset(new ConstantColumn(val));
(reinterpret_cast<ConstantColumn*>(unionColVec[j][i].get()))
->timeZone(thd->variables.time_zone->get_name()->ptr());
}
}
}
}
/*
* @bug5635. Move filters that only belongs to a derived table to inside the derived table.
* 1. parse tree walk to populate derivedTableFilterMap and set null candidate on the tree.
* 2. remove the null filters
* 3. and the filters of derivedTableFilterMap and append to the WHERE filter of the derived table
*
* Note:
* 1. Subquery filters is ignored because derived table can not be in subquery
* 2. While walking tree, whenever a single derive simplefilter is encountered,
* this filter is pushed to the corresponding stack
* 2. Whenever an OR operator is encountered, all the filter stack of
* that OR involving derived table are emptied and null candidate of each
* stacked filter needs to be reset (not null)
*/
ParseTree* pt = csep->filters();
map<string, ParseTree*> derivedTbFilterMap;
if (horizontalOptimization && pt)
{
pt->walk(setDerivedTable);
setDerivedFilter(thd, pt, derivedTbFilterMap, derivedTbList);
csep->filters(pt);
}
// AND the filters of individual stack to the derived table filter tree
// @todo union filters.
// @todo outer join complication
map<string, ParseTree*>::iterator mapIt;
for (uint i = 0; i < derivedTbList.size(); i++)
{
CalpontSelectExecutionPlan* plan = reinterpret_cast<CalpontSelectExecutionPlan*>(derivedTbList[i].get());
CalpontSelectExecutionPlan::ReturnedColumnList derivedColList = plan->returnedCols();
mapIt = derivedTbFilterMap.find(plan->derivedTbAlias());
if (mapIt != derivedTbFilterMap.end())
else if (lastNonConstIndex == -1)
{
// replace all derived column of this filter with real column from
// derived table projection list.
ParseTree* mainFilter = new ParseTree();
mainFilter->copyTree(*(mapIt->second));
replaceRefCol(mainFilter, derivedColList);
ParseTree* derivedFilter = plan->filters();
if (derivedFilter)
{
LogicOperator* op = new LogicOperator("and");
ParseTree* filter = new ParseTree(op);
filter->left(derivedFilter);
filter->right(mainFilter);
plan->filters(filter);
}
else
{
plan->filters(mainFilter);
}
// union filter handling
for (uint j = 0; j < plan->unionVec().size(); j++)
{
CalpontSelectExecutionPlan* unionPlan =
reinterpret_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get());
CalpontSelectExecutionPlan::ReturnedColumnList unionColList = unionPlan->returnedCols();
ParseTree* mainFilterForUnion = new ParseTree();
mainFilterForUnion->copyTree(*(mapIt->second));
replaceRefCol(mainFilterForUnion, unionColList);
ParseTree* unionFilter = unionPlan->filters();
if (unionFilter)
{
LogicOperator* op = new LogicOperator("and");
ParseTree* filter = new ParseTree(op);
filter->left(unionFilter);
filter->right(mainFilterForUnion);
unionPlan->filters(filter);
}
else
{
unionPlan->filters(mainFilterForUnion);
}
}
lastNonConstIndex = i;
}
}
if (lastNonConstIndex == -1)
{
// None of the subquery columns are referenced, just use the first one
if (!cols.empty())
{
cols[0].reset(new ConstantColumn(val));
(reinterpret_cast<ConstantColumn*>(cols[0].get()))
->timeZone(thd->variables.time_zone->get_name()->ptr());
nonConstCols.push_back(cols[0]);
for (uint j = 0; j < unionColVec.size(); j++)
{
unionColVec[j][0].reset(new ConstantColumn(val));
(reinterpret_cast<ConstantColumn*>(unionColVec[j][0].get()))
->timeZone(thd->variables.time_zone->get_name()->ptr());
nonConstUnionColVec[j].push_back(unionColVec[j][0]);
}
}
}
else
{
nonConstCols.assign(cols.begin(), cols.begin() + lastNonConstIndex + 1);
for (uint j = 0; j < unionColVec.size(); j++)
{
nonConstUnionColVec[j].assign(unionColVec[j].begin(),
unionColVec[j].begin() + lastNonConstIndex + 1);
}
}
// set back
plan->returnedCols(nonConstCols);
for (uint j = 0; j < unionColVec.size(); j++)
{
CalpontSelectExecutionPlan* unionSubPlan =
reinterpret_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get());
unionSubPlan->returnedCols(nonConstUnionColVec[j]);
}
}
}
// clean derivedTbFilterMap because all the filters are copied
for ( mapIt = derivedTbFilterMap.begin(); mapIt != derivedTbFilterMap.end(); ++mapIt )
delete (*mapIt).second;
/*
* @bug5635. Move filters that only belongs to a derived table to inside the derived table.
* 1. parse tree walk to populate derivedTableFilterMap and set null candidate on the tree.
* 2. remove the null filters
* 3. and the filters of derivedTableFilterMap and append to the WHERE filter of the derived table
*
* Note:
* 1. Subquery filters is ignored because derived table can not be in subquery
* 2. While walking tree, whenever a single derive simplefilter is encountered,
* this filter is pushed to the corresponding stack
* 2. Whenever an OR operator is encountered, all the filter stack of
* that OR involving derived table are emptied and null candidate of each
* stacked filter needs to be reset (not null)
*/
ParseTree* pt = csep->filters();
map<string, ParseTree*> derivedTbFilterMap;
// recursively process the nested derived table
for (uint i = 0; i < csep->subSelectList().size(); i++)
if (horizontalOptimization && pt)
{
pt->walk(setDerivedTable);
setDerivedFilter(thd, pt, derivedTbFilterMap, derivedTbList);
csep->filters(pt);
}
// AND the filters of individual stack to the derived table filter tree
// @todo union filters.
// @todo outer join complication
map<string, ParseTree*>::iterator mapIt;
for (uint i = 0; i < derivedTbList.size(); i++)
{
CalpontSelectExecutionPlan* plan = reinterpret_cast<CalpontSelectExecutionPlan*>(derivedTbList[i].get());
CalpontSelectExecutionPlan::ReturnedColumnList derivedColList = plan->returnedCols();
mapIt = derivedTbFilterMap.find(plan->derivedTbAlias());
if (mapIt != derivedTbFilterMap.end())
{
SCSEP subselect(boost::dynamic_pointer_cast<CalpontSelectExecutionPlan>(csep->subSelectList()[i]));
derivedTableOptimization(thd, subselect);
// replace all derived column of this filter with real column from
// derived table projection list.
ParseTree* mainFilter = new ParseTree();
mainFilter->copyTree(*(mapIt->second));
replaceRefCol(mainFilter, derivedColList);
ParseTree* derivedFilter = plan->filters();
if (derivedFilter)
{
LogicOperator* op = new LogicOperator("and");
ParseTree* filter = new ParseTree(op);
filter->left(derivedFilter);
filter->right(mainFilter);
plan->filters(filter);
}
else
{
plan->filters(mainFilter);
}
// union filter handling
for (uint j = 0; j < plan->unionVec().size(); j++)
{
CalpontSelectExecutionPlan* unionPlan =
reinterpret_cast<CalpontSelectExecutionPlan*>(plan->unionVec()[j].get());
CalpontSelectExecutionPlan::ReturnedColumnList unionColList = unionPlan->returnedCols();
ParseTree* mainFilterForUnion = new ParseTree();
mainFilterForUnion->copyTree(*(mapIt->second));
replaceRefCol(mainFilterForUnion, unionColList);
ParseTree* unionFilter = unionPlan->filters();
if (unionFilter)
{
LogicOperator* op = new LogicOperator("and");
ParseTree* filter = new ParseTree(op);
filter->left(unionFilter);
filter->right(mainFilterForUnion);
unionPlan->filters(filter);
}
else
{
unionPlan->filters(mainFilterForUnion);
}
}
}
}
// clean derivedTbFilterMap because all the filters are copied
for (mapIt = derivedTbFilterMap.begin(); mapIt != derivedTbFilterMap.end(); ++mapIt)
delete (*mapIt).second;
// recursively process the nested derived table
for (uint i = 0; i < csep->subSelectList().size(); i++)
{
SCSEP subselect(boost::dynamic_pointer_cast<CalpontSelectExecutionPlan>(csep->subSelectList()[i]));
derivedTableOptimization(thd, subselect);
}
}
void setDerivedTable(execplan::ParseTree* n)
{
ParseTree* lhs = n->left();
ParseTree* rhs = n->right();
ParseTree* lhs = n->left();
ParseTree* rhs = n->right();
Operator* op = dynamic_cast<Operator*>(n->data());
Operator* op = dynamic_cast<Operator*>(n->data());
// if logic operator then lhs and rhs can't be both null
if (op)
// if logic operator then lhs and rhs can't be both null
if (op)
{
if (!lhs || lhs->derivedTable() == "*")
{
if (!lhs || lhs->derivedTable() == "*")
{
n->derivedTable(rhs ? rhs->derivedTable() : "*");
}
else if (!rhs || rhs->derivedTable() == "*")
{
n->derivedTable(lhs->derivedTable());
}
else if (lhs->derivedTable() == rhs->derivedTable())
{
n->derivedTable(lhs->derivedTable());
}
else
{
n->derivedTable("");
}
n->derivedTable(rhs ? rhs->derivedTable() : "*");
}
else if (!rhs || rhs->derivedTable() == "*")
{
n->derivedTable(lhs->derivedTable());
}
else if (lhs->derivedTable() == rhs->derivedTable())
{
n->derivedTable(lhs->derivedTable());
}
else
{
n->data()->setDerivedTable();
n->derivedTable(n->data()->derivedTable());
n->derivedTable("");
}
}
else
{
n->data()->setDerivedTable();
n->derivedTable(n->data()->derivedTable());
}
}
ParseTree* setDerivedFilter(THD* thd, ParseTree*& n,
map<string, ParseTree*>& filterMap,
ParseTree* setDerivedFilter(THD* thd, ParseTree*& n, map<string, ParseTree*>& filterMap,
CalpontSelectExecutionPlan::SelectList& derivedTbList)
{
if (!(n->derivedTable().empty()))
if (!(n->derivedTable().empty()))
{
// @todo replace virtual column of n to real column
// all simple columns should belong to the same derived table
CalpontSelectExecutionPlan* csep = NULL;
for (uint i = 0; i < derivedTbList.size(); i++)
{
// @todo replace virtual column of n to real column
// all simple columns should belong to the same derived table
CalpontSelectExecutionPlan* csep = NULL;
CalpontSelectExecutionPlan* plan = dynamic_cast<CalpontSelectExecutionPlan*>(derivedTbList[i].get());
for (uint i = 0; i < derivedTbList.size(); i++)
{
CalpontSelectExecutionPlan* plan = dynamic_cast<CalpontSelectExecutionPlan*>(derivedTbList[i].get());
if (plan->derivedTbAlias() == n->derivedTable())
{
csep = plan;
break;
}
}
if (plan->derivedTbAlias() == n->derivedTable())
{
csep = plan;
break;
}
}
// should never be null; if null then give up optimization.
if (!csep)
return n;
// should never be null; if null then give up optimization.
if (!csep)
return n;
// 2. push the filter to the derived table filter stack, or 'and' with
// the filters in the stack
map<string, ParseTree*>::iterator mapIter = filterMap.find(n->derivedTable());
// 2. push the filter to the derived table filter stack, or 'and' with
// the filters in the stack
map<string, ParseTree*>::iterator mapIter = filterMap.find(n->derivedTable());
if ( mapIter == filterMap.end())
{
filterMap.insert(pair<string, ParseTree*>(n->derivedTable(), n));
}
else
{
ParseTree* pt = new ParseTree(new LogicOperator("and"));
pt->left(mapIter->second);
pt->right(n);
mapIter->second = pt;
}
int64_t val = 1;
n = new ParseTree(new ConstantColumn(val));
(dynamic_cast<ConstantColumn*>(n->data()))->timeZone(thd->variables.time_zone->get_name()->ptr());
if (mapIter == filterMap.end())
{
filterMap.insert(pair<string, ParseTree*>(n->derivedTable(), n));
}
else
{
Operator* op = dynamic_cast<Operator*>(n->data());
if (op && (op->op() == OP_OR || op->op() == OP_XOR))
{
return n;
}
else
{
ParseTree* lhs = n->left();
ParseTree* rhs = n->right();
if (lhs)
n->left(setDerivedFilter(thd, lhs, filterMap, derivedTbList));
if (rhs)
n->right(setDerivedFilter(thd, rhs, filterMap, derivedTbList));
}
ParseTree* pt = new ParseTree(new LogicOperator("and"));
pt->left(mapIter->second);
pt->right(n);
mapIter->second = pt;
}
return n;
int64_t val = 1;
n = new ParseTree(new ConstantColumn(val));
(dynamic_cast<ConstantColumn*>(n->data()))->timeZone(thd->variables.time_zone->get_name()->ptr());
}
else
{
Operator* op = dynamic_cast<Operator*>(n->data());
if (op && (op->op() == OP_OR || op->op() == OP_XOR))
{
return n;
}
else
{
ParseTree* lhs = n->left();
ParseTree* rhs = n->right();
if (lhs)
n->left(setDerivedFilter(thd, lhs, filterMap, derivedTbList));
if (rhs)
n->right(setDerivedFilter(thd, rhs, filterMap, derivedTbList));
}
}
return n;
}
FromSubQuery::FromSubQuery(gp_walk_info& gwip) : SubQuery(gwip)
{}
{
}
FromSubQuery::FromSubQuery(gp_walk_info& gwip,
SELECT_LEX* sub) :
SubQuery(gwip),
fFromSub(sub)
{}
FromSubQuery::FromSubQuery(gp_walk_info& gwip, SELECT_LEX* sub) : SubQuery(gwip), fFromSub(sub)
{
}
FromSubQuery::~FromSubQuery()
{}
{
}
SCSEP FromSubQuery::transform()
{
assert (fFromSub);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::FROM);
csep->subType (CalpontSelectExecutionPlan::FROM_SUBS);
assert(fFromSub);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::FROM);
csep->subType(CalpontSelectExecutionPlan::FROM_SUBS);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
gwi.viewName = fGwip.viewName;
csep->derivedTbAlias(fAlias); // always lower case
csep->derivedTbView(fGwip.viewName.alias, lower_case_table_names);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
gwi.viewName = fGwip.viewName;
csep->derivedTbAlias(fAlias); // always lower case
csep->derivedTbView(fGwip.viewName.alias, lower_case_table_names);
if (getSelectPlan(gwi, *fFromSub, csep, false) != 0)
{
fGwip.fatalParseError = true;
if (getSelectPlan(gwi, *fFromSub, csep, false) != 0)
{
fGwip.fatalParseError = true;
if (!gwi.parseErrorText.empty())
fGwip.parseErrorText = gwi.parseErrorText;
else
fGwip.parseErrorText = "Error occured in FromSubQuery::transform()";
if (!gwi.parseErrorText.empty())
fGwip.parseErrorText = gwi.parseErrorText;
else
fGwip.parseErrorText = "Error occured in FromSubQuery::transform()";
csep.reset();
return csep;
}
fGwip.subselectList.push_back(csep);
csep.reset();
return csep;
}
fGwip.subselectList.push_back(csep);
return csep;
}
}
} // namespace cal_impl_if

View File

@ -17,10 +17,10 @@
MA 02110-1301, USA. */
/***********************************************************************
* $Id: ha_in_sub.cpp 6407 2010-03-26 19:36:56Z zzhu $
*
*
***********************************************************************/
* $Id: ha_in_sub.cpp 6407 2010-03-26 19:36:56Z zzhu $
*
*
***********************************************************************/
/** @file */
/** class InSub definition */
@ -52,66 +52,69 @@ using namespace logging;
namespace cal_impl_if
{
extern void parse_item (Item* item, vector<Item_field*>& field_vec, bool& hasNonSupportItem, uint16& parseInfo);
extern void parse_item(Item* item, vector<Item_field*>& field_vec, bool& hasNonSupportItem,
uint16& parseInfo);
void makeAntiJoin(const ParseTree* n)
{
TreeNode* tn = n->data();
SimpleFilter* sf = dynamic_cast<SimpleFilter*>(tn);
TreeNode* tn = n->data();
SimpleFilter* sf = dynamic_cast<SimpleFilter*>(tn);
if (!sf)
return;
if (!sf)
return;
uint64_t lJoinInfo = sf->lhs()->joinInfo();
uint64_t lJoinInfo = sf->lhs()->joinInfo();
if (lJoinInfo & JOIN_SEMI)
{
lJoinInfo &= ~JOIN_SEMI;
lJoinInfo |= JOIN_ANTI;
if (lJoinInfo & JOIN_SEMI)
{
lJoinInfo &= ~JOIN_SEMI;
lJoinInfo |= JOIN_ANTI;
if (lJoinInfo & JOIN_NULLMATCH_CANDIDATE)
lJoinInfo |= JOIN_NULL_MATCH;
if (lJoinInfo & JOIN_NULLMATCH_CANDIDATE)
lJoinInfo |= JOIN_NULL_MATCH;
sf->lhs()->joinInfo(lJoinInfo);
}
sf->lhs()->joinInfo(lJoinInfo);
}
uint64_t rJoinInfo = sf->rhs()->joinInfo();
uint64_t rJoinInfo = sf->rhs()->joinInfo();
if (rJoinInfo & JOIN_SEMI)
{
rJoinInfo &= ~JOIN_SEMI;
rJoinInfo |= JOIN_ANTI;
if (rJoinInfo & JOIN_SEMI)
{
rJoinInfo &= ~JOIN_SEMI;
rJoinInfo |= JOIN_ANTI;
if (rJoinInfo & JOIN_NULLMATCH_CANDIDATE)
rJoinInfo |= JOIN_NULL_MATCH;
if (rJoinInfo & JOIN_NULLMATCH_CANDIDATE)
rJoinInfo |= JOIN_NULL_MATCH;
sf->rhs()->joinInfo(rJoinInfo);
}
sf->rhs()->joinInfo(rJoinInfo);
}
}
InSub::InSub(gp_walk_info& gwip) : WhereSubQuery(gwip)
{}
{
}
InSub::InSub(gp_walk_info& gwip, Item_func* func) :
WhereSubQuery(gwip, func)
{}
InSub::InSub(gp_walk_info& gwip, Item_func* func) : WhereSubQuery(gwip, func)
{
}
InSub::InSub(const InSub& rhs) :
WhereSubQuery(rhs.gwip(), rhs.fColumn, rhs.fSub, rhs.fFunc)
{}
InSub::InSub(const InSub& rhs) : WhereSubQuery(rhs.gwip(), rhs.fColumn, rhs.fSub, rhs.fFunc)
{
}
InSub::~InSub()
{}
{
}
inline void setCorrelatedFlag(execplan::ReturnedColumn* col, gp_walk_info* gwip)
{
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(col);
ConstantColumn* cc = dynamic_cast<ConstantColumn*>(col);
if (!cc)
{
col->joinInfo(col->joinInfo() | JOIN_CORRELATED | JOIN_NULLMATCH_CANDIDATE);
gwip->subQuery->correlated(true);
}
if (!cc)
{
col->joinInfo(col->joinInfo() | JOIN_CORRELATED | JOIN_NULLMATCH_CANDIDATE);
gwip->subQuery->correlated(true);
}
}
/** MySQL transform (NOT) IN subquery to (NOT) EXIST
@ -119,109 +122,108 @@ inline void setCorrelatedFlag(execplan::ReturnedColumn* col, gp_walk_info* gwip)
*/
execplan::ParseTree* InSub::transform()
{
if (!fFunc)
return NULL;
if (!fFunc)
return NULL;
// @todo need to handle scalar IN and BETWEEN specially
// this blocks handles only one subselect scalar
// arg[0]: column | arg[1]: subselect
//assert (fFunc->argument_count() == 2 && fGwip.rcWorkStack.size() >= 2);
if (fFunc->argument_count() != 2 || fGwip.rcWorkStack.size() < 2)
// @todo need to handle scalar IN and BETWEEN specially
// this blocks handles only one subselect scalar
// arg[0]: column | arg[1]: subselect
// assert (fFunc->argument_count() == 2 && fGwip.rcWorkStack.size() >= 2);
if (fFunc->argument_count() != 2 || fGwip.rcWorkStack.size() < 2)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Unsupported item in IN subquery";
return NULL;
}
ReturnedColumn* rhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
delete rhs;
ReturnedColumn* lhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
fSub = (Item_subselect*)(fFunc->arguments()[1]);
idbassert(fSub);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::WHERE);
csep->subType(CalpontSelectExecutionPlan::IN_SUBS);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// The below 2 fields are used later on in buildInToExistsFilter()
gwi.inSubQueryLHS = lhs;
gwi.inSubQueryLHSItem = fFunc->arguments()[0];
RowColumn* rlhs = dynamic_cast<RowColumn*>(lhs);
if (rlhs)
{
for (auto& col : rlhs->columnVec())
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Unsupported item in IN subquery";
return NULL;
setCorrelatedFlag(col.get(), &gwi);
}
}
else
{
setCorrelatedFlag(lhs, &gwi);
}
ReturnedColumn* rhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
delete rhs;
ReturnedColumn* lhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
// @4827 merge table list to gwi in case there is FROM sub to be referenced
// in the FROM sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
fSub = (Item_subselect*)(fFunc->arguments()[1]);
idbassert(fSub);
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
SCSEP csep (new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::WHERE);
csep->subType (CalpontSelectExecutionPlan::IN_SUBS);
if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep, false) != 0)
{
fGwip.fatalParseError = true;
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// The below 2 fields are used later on in buildInToExistsFilter()
gwi.inSubQueryLHS = lhs;
gwi.inSubQueryLHSItem = fFunc->arguments()[0];
RowColumn* rlhs = dynamic_cast<RowColumn*>(lhs);
if (rlhs)
{
for (auto& col : rlhs->columnVec())
{
setCorrelatedFlag(col.get(), &gwi);
}
}
if (gwi.fatalParseError && !gwi.parseErrorText.empty())
fGwip.parseErrorText = gwi.parseErrorText;
else
{
setCorrelatedFlag(lhs, &gwi);
}
fGwip.parseErrorText = "Error occured in InSub::transform()";
// @4827 merge table list to gwi in case there is FROM sub to be referenced
// in the FROM sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
return NULL;
}
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep, false) != 0)
{
fGwip.fatalParseError = true;
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end());
if (gwi.fatalParseError && !gwi.parseErrorText.empty())
fGwip.parseErrorText = gwi.parseErrorText;
else
fGwip.parseErrorText = "Error occured in InSub::transform()";
CalpontSelectExecutionPlan::SelectList derivedTbList;
return NULL;
}
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin() + gwi.derivedTbCnt,
csep->derivedTableList().end());
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end());
ExistsFilter* subFilter = new ExistsFilter();
subFilter->sub(csep);
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (gwi.subQuery->correlated())
subFilter->correlated(true);
else
subFilter->correlated(false);
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(),
csep->derivedTableList().begin() + gwi.derivedTbCnt,
csep->derivedTableList().end());
if (fGwip.clauseType == HAVING && subFilter->correlated())
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_NON_SUPPORT_HAVING);
}
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
ExistsFilter* subFilter = new ExistsFilter();
subFilter->sub(csep);
if (gwi.subQuery->correlated())
subFilter->correlated(true);
else
subFilter->correlated(false);
if (fGwip.clauseType == HAVING && subFilter->correlated())
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_NON_SUPPORT_HAVING);
}
fGwip.subselectList.push_back(csep);
return new ParseTree(subFilter);
fGwip.subselectList.push_back(csep);
return new ParseTree(subFilter);
}
/**
@ -230,90 +232,89 @@ execplan::ParseTree* InSub::transform()
*/
void InSub::handleFunc(gp_walk_info* gwip, Item_func* func)
{
if (func->functype() == Item_func::TRIG_COND_FUNC || func->functype() == Item_func::COND_OR_FUNC)
if (func->functype() == Item_func::TRIG_COND_FUNC || func->functype() == Item_func::COND_OR_FUNC)
{
// purpose: remove the isnull() function from the parsetree in ptWorkStack.
// IDB handles the null semantics in the join operation
// trigcond(or_cond) is the only form we recognize for now
if (func->argument_count() > 2)
{
// purpose: remove the isnull() function from the parsetree in ptWorkStack.
// IDB handles the null semantics in the join operation
// trigcond(or_cond) is the only form we recognize for now
if (func->argument_count() > 2)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Unsupported item in IN subquery";
return;
}
Item_cond* cond;
if (func->functype() == Item_func::TRIG_COND_FUNC)
{
Item* item;
if (func->arguments()[0]->type() == Item::REF_ITEM)
item = (Item_ref*)(func->arguments()[0])->real_item();
else
item = func->arguments()[0];
cond = (Item_cond*)(item);
}
else
{
cond = (Item_cond*)(func);
}
if (cond->functype() == Item_func::COND_OR_FUNC)
{
// (cache=item) case. do nothing. ignore trigcond()?
if (cond->argument_list()->elements == 1)
return;
if (cond->argument_list()->elements == 2)
{
// don't know how to deal with this. don't think it's a fatal error either.
if (gwip->ptWorkStack.empty())
return;
ParseTree* pt = gwip->ptWorkStack.top();
if (!pt->left() || !pt->right())
return;
SimpleFilter* lsf = dynamic_cast<SimpleFilter*>(pt->left()->data());
SimpleFilter* rsf = dynamic_cast<SimpleFilter*>(pt->right()->data());
if (!lsf || !rsf)
return;
// (a=b or isnull(item))/(a=b or isnotnull(item)) case.
// swap the lhs and rhs operands of the OR operator.
if ((lsf->op()->op() == execplan::OP_ISNULL ||
lsf->op()->op() == execplan::OP_ISNOTNULL) &&
rsf->op()->op() == execplan::OP_EQ)
{
ParseTree* temp = pt->left();
pt->left(pt->right());
pt->right(temp);
}
}
}
else if (cond->functype() == Item_func::EQ_FUNC)
{
// not in (select const ...)
if (gwip->ptWorkStack.empty())
return;
ParseTree* pt = gwip->ptWorkStack.top();
SimpleFilter* sf = dynamic_cast<SimpleFilter*>(pt->data());
if (!sf || sf->op()->op() != execplan::OP_EQ)
return;
if (sf->lhs()->joinInfo() & JOIN_CORRELATED)
sf->lhs()->joinInfo(sf->lhs()->joinInfo() | JOIN_NULLMATCH_CANDIDATE);
if (sf->rhs()->joinInfo() & JOIN_CORRELATED)
sf->rhs()->joinInfo(sf->rhs()->joinInfo() | JOIN_NULLMATCH_CANDIDATE);
}
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Unsupported item in IN subquery";
return;
}
Item_cond* cond;
if (func->functype() == Item_func::TRIG_COND_FUNC)
{
Item* item;
if (func->arguments()[0]->type() == Item::REF_ITEM)
item = (Item_ref*)(func->arguments()[0])->real_item();
else
item = func->arguments()[0];
cond = (Item_cond*)(item);
}
else
{
cond = (Item_cond*)(func);
}
if (cond->functype() == Item_func::COND_OR_FUNC)
{
// (cache=item) case. do nothing. ignore trigcond()?
if (cond->argument_list()->elements == 1)
return;
if (cond->argument_list()->elements == 2)
{
// don't know how to deal with this. don't think it's a fatal error either.
if (gwip->ptWorkStack.empty())
return;
ParseTree* pt = gwip->ptWorkStack.top();
if (!pt->left() || !pt->right())
return;
SimpleFilter* lsf = dynamic_cast<SimpleFilter*>(pt->left()->data());
SimpleFilter* rsf = dynamic_cast<SimpleFilter*>(pt->right()->data());
if (!lsf || !rsf)
return;
// (a=b or isnull(item))/(a=b or isnotnull(item)) case.
// swap the lhs and rhs operands of the OR operator.
if ((lsf->op()->op() == execplan::OP_ISNULL || lsf->op()->op() == execplan::OP_ISNOTNULL) &&
rsf->op()->op() == execplan::OP_EQ)
{
ParseTree* temp = pt->left();
pt->left(pt->right());
pt->right(temp);
}
}
}
else if (cond->functype() == Item_func::EQ_FUNC)
{
// not in (select const ...)
if (gwip->ptWorkStack.empty())
return;
ParseTree* pt = gwip->ptWorkStack.top();
SimpleFilter* sf = dynamic_cast<SimpleFilter*>(pt->data());
if (!sf || sf->op()->op() != execplan::OP_EQ)
return;
if (sf->lhs()->joinInfo() & JOIN_CORRELATED)
sf->lhs()->joinInfo(sf->lhs()->joinInfo() | JOIN_NULLMATCH_CANDIDATE);
if (sf->rhs()->joinInfo() & JOIN_CORRELATED)
sf->rhs()->joinInfo(sf->rhs()->joinInfo() | JOIN_NULLMATCH_CANDIDATE);
}
}
}
/**
@ -323,20 +324,20 @@ void InSub::handleFunc(gp_walk_info* gwip, Item_func* func)
*/
void InSub::handleNot()
{
ParseTree* pt = fGwip.ptWorkStack.top();
ExistsFilter* subFilter = dynamic_cast<ExistsFilter*>(pt->data());
idbassert(subFilter);
subFilter->notExists(true);
SCSEP csep = subFilter->sub();
const ParseTree* ptsub = csep->filters();
ParseTree* pt = fGwip.ptWorkStack.top();
ExistsFilter* subFilter = dynamic_cast<ExistsFilter*>(pt->data());
idbassert(subFilter);
subFilter->notExists(true);
SCSEP csep = subFilter->sub();
const ParseTree* ptsub = csep->filters();
if (ptsub)
ptsub->walk(makeAntiJoin);
if (ptsub)
ptsub->walk(makeAntiJoin);
ptsub = csep->having();
ptsub = csep->having();
if (ptsub)
ptsub->walk(makeAntiJoin);
if (ptsub)
ptsub->walk(makeAntiJoin);
}
}
} // namespace cal_impl_if

File diff suppressed because it is too large Load Diff

View File

@ -32,260 +32,256 @@ extern handlerton* mcs_hton;
*/
typedef struct st_mcs_share
{
char* table_name;
uint32_t table_name_length, use_count;
pthread_mutex_t mutex;
THR_LOCK lock;
char* table_name;
uint32_t table_name_length, use_count;
pthread_mutex_t mutex;
THR_LOCK lock;
} COLUMNSTORE_SHARE;
/** @brief
Class definition for the storage engine
*/
class ha_mcs: public handler
class ha_mcs : public handler
{
THR_LOCK_DATA lock; ///< MySQL lock
COLUMNSTORE_SHARE* share; ///< Shared lock info
ulonglong int_table_flags;
// We are using a vector here to mimick the stack functionality
// using push_back() and pop_back()
// as apparently there is a linker error on the std::stack<COND*>::pop()
// call on Ubuntu18.
std::vector<COND*> condStack;
int m_lock_type;
THR_LOCK_DATA lock; ///< MySQL lock
COLUMNSTORE_SHARE* share; ///< Shared lock info
ulonglong int_table_flags;
// We are using a vector here to mimick the stack functionality
// using push_back() and pop_back()
// as apparently there is a linker error on the std::stack<COND*>::pop()
// call on Ubuntu18.
std::vector<COND*> condStack;
int m_lock_type;
int impl_external_lock(THD* thd, TABLE* table, int lock_type);
int impl_rnd_init(TABLE* table, const std::vector<COND*>& condStack);
int impl_external_lock(THD* thd, TABLE* table, int lock_type);
int impl_rnd_init(TABLE* table, const std::vector<COND*>& condStack);
public:
ha_mcs(handlerton* hton, TABLE_SHARE* table_arg);
virtual ~ha_mcs()
{
}
public:
ha_mcs(handlerton* hton, TABLE_SHARE* table_arg);
virtual ~ha_mcs()
{
}
/** @brief
The name that will be used for display purposes.
*/
const char* table_type() const override
{
return "ColumnStore";
}
/** @brief
The name that will be used for display purposes.
*/
const char* table_type() const override
{
return "ColumnStore";
}
/** @brief
The name of the index type that will be used for display.
Don't implement this method unless you really have indexes.
*/
//const char *index_type(uint32_t inx) { return "HASH"; }
/** @brief
The name of the index type that will be used for display.
Don't implement this method unless you really have indexes.
*/
// const char *index_type(uint32_t inx) { return "HASH"; }
/** @brief
The file extensions.
*/
const char** bas_ext() const;
/** @brief
The file extensions.
*/
const char** bas_ext() const;
/** @brief
This is a list of flags that indicate what functionality the storage engine
implements. The current table flags are documented in handler.h
*/
ulonglong table_flags() const override
{
return int_table_flags;
}
/** @brief
This is a list of flags that indicate what functionality the storage engine
implements. The current table flags are documented in handler.h
*/
ulonglong table_flags() const override
{
return int_table_flags;
}
/** @brief
This is a bitmap of flags that indicates how the storage engine
implements indexes. The current index flags are documented in
handler.h. If you do not implement indexes, just return zero here.
/** @brief
This is a bitmap of flags that indicates how the storage engine
implements indexes. The current index flags are documented in
handler.h. If you do not implement indexes, just return zero here.
@details
part is the key part to check. First key part is 0.
If all_parts is set, MySQL wants to know the flags for the combined
index, up to and including 'part'.
*/
ulong index_flags(uint32_t inx, uint32_t part, bool all_parts) const override
{
return 0;
}
@details
part is the key part to check. First key part is 0.
If all_parts is set, MySQL wants to know the flags for the combined
index, up to and including 'part'.
*/
ulong index_flags(uint32_t inx, uint32_t part, bool all_parts) const override
{
return 0;
}
/** @brief
unireg.cc will call max_supported_record_length(), max_supported_keys(),
max_supported_key_parts(), uint32_t max_supported_key_length()
to make sure that the storage engine can handle the data it is about to
send. Return *real* limits of your storage engine here; MySQL will do
min(your_limits, MySQL_limits) automatically.
*/
uint32_t max_supported_record_length() const override
{
return HA_MAX_REC_LENGTH;
}
/** @brief
unireg.cc will call max_supported_record_length(), max_supported_keys(),
max_supported_key_parts(), uint32_t max_supported_key_length()
to make sure that the storage engine can handle the data it is about to
send. Return *real* limits of your storage engine here; MySQL will do
min(your_limits, MySQL_limits) automatically.
*/
uint32_t max_supported_record_length() const override
{
return HA_MAX_REC_LENGTH;
}
/** @brief
Called in test_quick_select to determine if indexes should be used.
*/
virtual double scan_time() override
{
return (double)(stats.records + stats.deleted) / 20.0 + 10;
}
/** @brief
Called in test_quick_select to determine if indexes should be used.
*/
virtual double scan_time() override
{
return (double) (stats.records + stats.deleted) / 20.0 + 10;
}
/** @brief
Analyze table command.
*/
int analyze(THD* thd, HA_CHECK_OPT* check_opt) override;
/** @brief
Analyze table command.
*/
int analyze(THD* thd, HA_CHECK_OPT* check_opt) override;
/*
Everything below are methods that we implement in ha_example.cc.
/*
Everything below are methods that we implement in ha_example.cc.
Most of these methods are not obligatory, skip them and
MySQL will treat them as not implemented
*/
Most of these methods are not obligatory, skip them and
MySQL will treat them as not implemented
*/
/** @brief
We implement this in ha_example.cc; it's a required method.
*/
int open(const char* name, int mode, uint32_t test_if_locked) override; // required
/** @brief
We implement this in ha_example.cc; it's a required method.
*/
int open(const char* name, int mode, uint32_t test_if_locked) override; // required
// MCOL-4282 This function is called by open_tables in sql_base.cc.
// We mutate the optimizer flags here for prepared statements as this
// handler function is called before JOIN::prepare, and we need to
// disable the default optimizer flags before JOIN::prepare (which is
// called during "PREPARE stmt FROM ..." SQL) is called.
// Sequence of SQL statements that will lead to this execution path
// for prepared statements:
// CREATE TABLE t1 (a int, b int) engine=columnstore;
// INSERT INTO t1 VALUES (1, 2), (2, 4), (3, 1);
// PREPARE stmt1 FROM "SELECT * FROM t1";
// EXECUTE stmt1;
// MCOL-4282 This function is called by open_tables in sql_base.cc.
// We mutate the optimizer flags here for prepared statements as this
// handler function is called before JOIN::prepare, and we need to
// disable the default optimizer flags before JOIN::prepare (which is
// called during "PREPARE stmt FROM ..." SQL) is called.
// Sequence of SQL statements that will lead to this execution path
// for prepared statements:
// CREATE TABLE t1 (a int, b int) engine=columnstore;
// INSERT INTO t1 VALUES (1, 2), (2, 4), (3, 1);
// PREPARE stmt1 FROM "SELECT * FROM t1";
// EXECUTE stmt1;
int discover_check_version() override;
int discover_check_version() override;
/** @brief
We implement this in ha_example.cc; it's a required method.
*/
int close(void) override; // required
/** @brief
We implement this in ha_example.cc; it's a required method.
*/
int close(void) override; // required
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int write_row(const uchar* buf) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int write_row(const uchar* buf) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
void start_bulk_insert(ha_rows rows, uint flags = 0) override;
void start_bulk_insert_from_cache(ha_rows rows, uint flags = 0);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
void start_bulk_insert(ha_rows rows, uint flags = 0) override;
void start_bulk_insert_from_cache(ha_rows rows, uint flags = 0);
/**@bug 2461 - Overloaded end_bulk_insert. MariaDB uses the abort bool, mysql does not. */
int end_bulk_insert() override;
/**@bug 2461 - Overloaded end_bulk_insert. MariaDB uses the abort bool, mysql does not. */
int end_bulk_insert() override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int update_row(const uchar* old_data, const uchar* new_data) override;
int direct_update_rows_init(List<Item>* update_fields) override;
int direct_update_rows(ha_rows* update_rows);
int direct_update_rows(ha_rows* update_rows, ha_rows* found_rows) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int update_row(const uchar* old_data, const uchar* new_data) override;
int direct_update_rows_init(List<Item> *update_fields) override;
int direct_update_rows(ha_rows *update_rows);
int direct_update_rows(ha_rows *update_rows, ha_rows *found_rows) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int delete_row(const uchar* buf) override;
int direct_delete_rows_init() override;
int direct_delete_rows(ha_rows* deleted_rows) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int delete_row(const uchar* buf) override;
int direct_delete_rows_init() override;
int direct_delete_rows(ha_rows *deleted_rows) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_read_map(uchar* buf, const uchar* key, key_part_map keypart_map,
enum ha_rkey_function find_flag) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_read_map(uchar* buf, const uchar* key,
key_part_map keypart_map, enum ha_rkey_function find_flag) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_next(uchar* buf) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_next(uchar* buf) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_prev(uchar* buf) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_prev(uchar* buf) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_first(uchar* buf) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_first(uchar* buf) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_last(uchar* buf) override;
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
int index_last(uchar* buf) override;
/** @brief
Unlike index_init(), rnd_init() can be called two consecutive times
without rnd_end() in between (it only makes sense if scan=1). In this
case, the second call should prepare for the new table scan (e.g if
rnd_init() allocates the cursor, the second call should position the
cursor to the start of the table; no need to deallocate and allocate
it again. This is a required method.
*/
int rnd_init(bool scan) override; // required
int rnd_end() override;
int rnd_next(uchar* buf) override; ///< required
int rnd_pos(uchar* buf, uchar* pos) override; ///< required
int reset() override;
void position(const uchar* record) override; ///< required
int info(uint32_t) override; ///< required
int extra(enum ha_extra_function operation) override;
int external_lock(THD* thd, int lock_type) override; ///< required
int delete_all_rows(void) override;
ha_rows records_in_range(uint32_t inx, const key_range* min_key, const key_range* max_key,
page_range* res) override;
int delete_table(const char* from) override;
int rename_table(const char* from, const char* to) override;
int create(const char* name, TABLE* form,
HA_CREATE_INFO* create_info) override; ///< required
/** @brief
Unlike index_init(), rnd_init() can be called two consecutive times
without rnd_end() in between (it only makes sense if scan=1). In this
case, the second call should prepare for the new table scan (e.g if
rnd_init() allocates the cursor, the second call should position the
cursor to the start of the table; no need to deallocate and allocate
it again. This is a required method.
*/
int rnd_init(bool scan) override; //required
int rnd_end() override;
int rnd_next(uchar* buf) override; ///< required
int rnd_pos(uchar* buf, uchar* pos) override; ///< required
int reset() override;
void position(const uchar* record) override; ///< required
int info(uint32_t) override; ///< required
int extra(enum ha_extra_function operation) override;
int external_lock(THD* thd, int lock_type) override; ///< required
int delete_all_rows(void) override;
ha_rows records_in_range(uint32_t inx, const key_range* min_key,
const key_range* max_key, page_range* res) override;
int delete_table(const char* from) override;
int rename_table(const char* from, const char* to) override;
int create(const char* name, TABLE* form,
HA_CREATE_INFO* create_info) override; ///< required
THR_LOCK_DATA** store_lock(THD* thd, THR_LOCK_DATA** to,
enum thr_lock_type lock_type) override; ///< required
const COND* cond_push(const COND* cond) override;
void cond_pop() override;
uint8 table_cache_type() override
{
return HA_CACHE_TBL_NOCACHE;
}
THR_LOCK_DATA** store_lock(THD* thd, THR_LOCK_DATA** to,
enum thr_lock_type lock_type) override; ///< required
const COND* cond_push(const COND* cond) override;
void cond_pop() override;
uint8 table_cache_type() override
{
return HA_CACHE_TBL_NOCACHE;
}
int repair(THD* thd, HA_CHECK_OPT* check_opt) override;
bool is_crashed() const override;
int repair(THD* thd, HA_CHECK_OPT* check_opt) override;
bool is_crashed() const override;
bool isReadOnly() const
{
return m_lock_type == F_RDLCK;
}
bool isReadOnly() const
{
return m_lock_type == F_RDLCK;
}
};
class ha_mcs_cache_share
{
ha_mcs_cache_share *next; /* Next open share */
const char *name;
ha_mcs_cache_share* next; /* Next open share */
const char* name;
uint open_count;
public:
public:
ulonglong cached_rows;
THR_LOCK org_lock;
friend ha_mcs_cache_share *find_cache_share(const char *name,
ulonglong cached_rows);
friend ha_mcs_cache_share* find_cache_share(const char* name, ulonglong cached_rows);
void close();
};
class ha_mcs_cache :public ha_mcs
class ha_mcs_cache : public ha_mcs
{
typedef ha_mcs parent;
int original_lock_type;
@ -302,16 +298,15 @@ class ha_mcs_cache :public ha_mcs
bool isCacheEnabled() const
{
return (get_cache_inserts(current_thd) && !isSysCatTable &&
!isCacheDisabled);
return (get_cache_inserts(current_thd) && !isSysCatTable && !isCacheDisabled);
}
public:
public:
uint lock_counter;
ha_maria *cache_handler;
ha_mcs_cache_share *share;
ha_maria* cache_handler;
ha_mcs_cache_share* share;
ha_mcs_cache(handlerton *hton, TABLE_SHARE *table_arg, MEM_ROOT *mem_root);
ha_mcs_cache(handlerton* hton, TABLE_SHARE* table_arg, MEM_ROOT* mem_root);
~ha_mcs_cache();
/*
@ -319,27 +314,24 @@ public:
cache handler
*/
int create(const char *name, TABLE *table_arg,
HA_CREATE_INFO *ha_create_info);
int open(const char *name, int mode, uint open_flags);
int delete_table(const char *name);
int rename_table(const char *from, const char *to);
int create(const char* name, TABLE* table_arg, HA_CREATE_INFO* ha_create_info);
int open(const char* name, int mode, uint open_flags);
int delete_table(const char* name);
int rename_table(const char* from, const char* to);
int delete_all_rows(void);
int close(void);
uint lock_count(void) const;
THR_LOCK_DATA **store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
int external_lock(THD *thd, int lock_type);
int repair(THD *thd, HA_CHECK_OPT *check_opt);
THR_LOCK_DATA** store_lock(THD* thd, THR_LOCK_DATA** to, enum thr_lock_type lock_type);
int external_lock(THD* thd, int lock_type);
int repair(THD* thd, HA_CHECK_OPT* check_opt);
bool is_crashed() const;
/*
Write row uses cache_handler, for normal inserts, otherwise derived
handler
*/
int write_row(const uchar *buf);
int write_row(const uchar* buf);
void start_bulk_insert(ha_rows rows, uint flags);
int end_bulk_insert();
@ -347,9 +339,8 @@ public:
void free_locks();
ha_rows num_rows_cached();
int flush_insert_cache();
friend my_bool get_status_and_flush_cache(void *param,
my_bool concurrent_insert);
friend my_bool cache_start_trans(void *param);
friend my_bool get_status_and_flush_cache(void* param, my_bool concurrent_insert);
friend my_bool cache_start_trans(void* param);
};
#endif //HA_MCS_H__
#endif // HA_MCS_H__

File diff suppressed because it is too large Load Diff

View File

@ -24,58 +24,69 @@
MariaDB header files.
*/
namespace datatypes {
class StoreFieldMariaDB: public StoreField
namespace datatypes
{
Field *m_field;
const CalpontSystemCatalog::ColType &m_type;
public:
StoreFieldMariaDB(Field *f, const CalpontSystemCatalog::ColType &type)
:m_field(f), m_type(type)
{ }
class StoreFieldMariaDB : public StoreField
{
Field* m_field;
const CalpontSystemCatalog::ColType& m_type;
const CalpontSystemCatalog::ColType &type() const { return m_type; }
int32_t colWidth() const override { return m_type.colWidth; }
int32_t precision() const override { return m_type.precision; }
int32_t scale() const override { return m_type.scale; }
public:
StoreFieldMariaDB(Field* f, const CalpontSystemCatalog::ColType& type) : m_field(f), m_type(type)
{
}
const CalpontSystemCatalog::ColType& type() const
{
return m_type;
}
int32_t colWidth() const override
{
return m_type.colWidth;
}
int32_t precision() const override
{
return m_type.precision;
}
int32_t scale() const override
{
return m_type.scale;
}
int store_date(int64_t val) override
{
char tmp[256];
DataConvert::dateToString(val, tmp, sizeof(tmp)-1);
DataConvert::dateToString(val, tmp, sizeof(tmp) - 1);
return store_string(tmp, strlen(tmp));
}
int store_datetime(int64_t val) override
{
char tmp[256];
DataConvert::datetimeToString(val, tmp, sizeof(tmp)-1, m_type.precision);
DataConvert::datetimeToString(val, tmp, sizeof(tmp) - 1, m_type.precision);
return store_string(tmp, strlen(tmp));
}
int store_time(int64_t val) override
{
char tmp[256];
DataConvert::timeToString(val, tmp, sizeof(tmp)-1, m_type.precision);
DataConvert::timeToString(val, tmp, sizeof(tmp) - 1, m_type.precision);
return store_string(tmp, strlen(tmp));
}
int store_timestamp(int64_t val) override
{
char tmp[256];
DataConvert::timestampToString(val, tmp, sizeof(tmp),
current_thd->variables.time_zone->get_name()->ptr(),
DataConvert::timestampToString(val, tmp, sizeof(tmp), current_thd->variables.time_zone->get_name()->ptr(),
m_type.precision);
return store_string(tmp, strlen(tmp));
}
int store_string(const char *str, size_t length) override
int store_string(const char* str, size_t length) override
{
return m_field->store(str, length, m_field->charset());
}
int store_varbinary(const char *str, size_t length) override
int store_varbinary(const char* str, size_t length) override
{
if (get_varbin_always_hex(current_thd))
{
@ -134,7 +145,7 @@ public:
m_field->field_length = 310;
if (dl == 0)
{
float8store(m_field->ptr,dl);
float8store(m_field->ptr, dl);
return 0;
}
return m_field->store(dl);
@ -174,44 +185,39 @@ public:
return m_field->store(decAsAStr.c_str(), decAsAStr.length(), m_field->charset());
}
int store_lob(const char *str, size_t length) override
int store_lob(const char* str, size_t length) override
{
idbassert(dynamic_cast<Field_blob*>(m_field));
Field_blob* f2 = static_cast<Field_blob*>(m_field);
f2->set_ptr(length, (uchar*) str);
f2->set_ptr(length, (uchar*)str);
return 0;
}
};
/*******************************************************************************/
class WriteBatchFieldMariaDB: public WriteBatchField
class WriteBatchFieldMariaDB : public WriteBatchField
{
// Maximum number of decimal digits that can be represented in 4 bytes
static const int DIG_PER_DEC = 9;
// See strings/decimal.c
const int dig2bytes[DIG_PER_DEC+1]={0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
const int dig2bytes[DIG_PER_DEC + 1] = {0, 1, 1, 2, 2, 3, 3, 4, 4, 4};
// Returns the number of bytes required to store a given number
// of decimal digits
int numDecimalBytes(int digits)
{
return (((digits/DIG_PER_DEC) * 4) + dig2bytes[digits % DIG_PER_DEC]);
return (((digits / DIG_PER_DEC) * 4) + dig2bytes[digits % DIG_PER_DEC]);
}
public:
Field * m_field;
const CalpontSystemCatalog::ColType & m_type;
public:
Field* m_field;
const CalpontSystemCatalog::ColType& m_type;
uint32_t m_mbmaxlen;
WriteBatchFieldMariaDB(Field *field,
const CalpontSystemCatalog::ColType & type,
uint32_t mbmaxlen)
:m_field(field), m_type(type), m_mbmaxlen(mbmaxlen)
{ }
size_t ColWriteBatchDate(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
WriteBatchFieldMariaDB(Field* field, const CalpontSystemCatalog::ColType& type, uint32_t mbmaxlen)
: m_field(field), m_type(type), m_mbmaxlen(mbmaxlen)
{
}
size_t ColWriteBatchDate(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
// QQ: OLD DATE is not handled
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
@ -229,7 +235,7 @@ public:
}
return 3;
}
size_t ColWriteBatchDatetime(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchDatetime(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
{
@ -250,37 +256,34 @@ public:
if (!ltime.second_part)
{
fprintf(ci.filePtr(), "%04d-%02d-%02d %02d:%02d:%02d%c",
ltime.year, ltime.month, ltime.day,
fprintf(ci.filePtr(), "%04d-%02d-%02d %02d:%02d:%02d%c", ltime.year, ltime.month, ltime.day,
ltime.hour, ltime.minute, ltime.second, ci.delimiter());
}
else
{
fprintf(ci.filePtr(), "%04d-%02d-%02d %02d:%02d:%02d.%ld%c",
ltime.year, ltime.month, ltime.day,
ltime.hour, ltime.minute, ltime.second,
ltime.second_part, ci.delimiter());
fprintf(ci.filePtr(), "%04d-%02d-%02d %02d:%02d:%02d.%ld%c", ltime.year, ltime.month, ltime.day,
ltime.hour, ltime.minute, ltime.second, ltime.second_part, ci.delimiter());
}
return m_field->pack_length();
}
// Old DATETIME
long long value = *((long long*) buf);
long datePart = (long) (value / 1000000ll);
long long value = *((long long*)buf);
long datePart = (long)(value / 1000000ll);
int day = datePart % 100;
int month = (datePart / 100) % 100;
int year = datePart / 10000;
fprintf(ci.filePtr(), "%04d-%02d-%02d ", year, month, day);
long timePart = (long) (value - (long long) datePart * 1000000ll);
long timePart = (long)(value - (long long)datePart * 1000000ll);
int second = timePart % 100;
int min = (timePart / 100) % 100;
int hour = timePart / 10000;
fprintf(ci.filePtr(), "%02d:%02d:%02d%c", hour, min, second, ci.delimiter());
return 8;
}
size_t ColWriteBatchTime(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchTime(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
// QQ: why old TIME is not handled?
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
@ -298,20 +301,18 @@ public:
if (!ltime.second_part)
{
fprintf(ci.filePtr(), "%02d:%02d:%02d%c",
ltime.hour, ltime.minute, ltime.second, ci.delimiter());
fprintf(ci.filePtr(), "%02d:%02d:%02d%c", ltime.hour, ltime.minute, ltime.second, ci.delimiter());
}
else
{
fprintf(ci.filePtr(), "%02d:%02d:%02d.%ld%c",
ltime.hour, ltime.minute, ltime.second,
ltime.second_part, ci.delimiter());
fprintf(ci.filePtr(), "%02d:%02d:%02d.%ld%c", ltime.hour, ltime.minute, ltime.second, ltime.second_part,
ci.delimiter());
}
return m_field->pack_length();
}
size_t ColWriteBatchTimestamp(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchTimestamp(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
// QQ: old TIMESTAMP is not handled
@ -329,30 +330,25 @@ public:
if (!tm.tv_usec)
{
fprintf(ci.filePtr(), "%04d-%02d-%02d %02d:%02d:%02d%c",
time.year, time.month, time.day,
time.hour, time.minute, time.second, ci.delimiter());
fprintf(ci.filePtr(), "%04d-%02d-%02d %02d:%02d:%02d%c", time.year, time.month, time.day, time.hour,
time.minute, time.second, ci.delimiter());
}
else
{
fprintf(ci.filePtr(), "%04d-%02d-%02d %02d:%02d:%02d.%ld%c",
time.year, time.month, time.day,
time.hour, time.minute, time.second,
tm.tv_usec, ci.delimiter());
fprintf(ci.filePtr(), "%04d-%02d-%02d %02d:%02d:%02d.%ld%c", time.year, time.month, time.day, time.hour,
time.minute, time.second, tm.tv_usec, ci.delimiter());
}
return m_field->pack_length();
}
static inline void ColWriteBatchTextStringPrintout(std::string& escape,
const ColBatchWriter &ci)
static inline void ColWriteBatchTextStringPrintout(std::string& escape, const ColBatchWriter& ci)
{
boost::replace_all(escape, "\\", "\\\\");
fprintf(ci.filePtr(), "%c%.*s%c%c", ci.enclosed_by(), (int)escape.length(),
escape.c_str(), ci.enclosed_by(), ci.delimiter());
fprintf(ci.filePtr(), "%c%.*s%c%c", ci.enclosed_by(), (int)escape.length(), escape.c_str(),
ci.enclosed_by(), ci.delimiter());
}
static void ColWriteBatchTextString(const String &value,
const ColBatchWriter &ci,
static void ColWriteBatchTextString(const String& value, const ColBatchWriter& ci,
const size_t colWidthInBytes)
{
std::string escape;
@ -360,8 +356,7 @@ public:
ColWriteBatchTextStringPrintout(escape, ci);
}
static void ColWriteBatchPaddedTextString(const String &value,
const ColBatchWriter &ci,
static void ColWriteBatchPaddedTextString(const String& value, const ColBatchWriter& ci,
const size_t colWidthInBytes)
{
std::string escape;
@ -369,23 +364,19 @@ public:
ColWriteBatchTextStringPrintout(escape, ci);
}
static void ColWriteBatchBlobString(const String &value,
const ColBatchWriter &ci,
static void ColWriteBatchBlobString(const String& value, const ColBatchWriter& ci,
const size_t colWidthInBytes)
{
const char* ptr = value.ptr();
for (uint32_t i = 0; i < value.length(); i++)
{
fprintf(ci.filePtr(), "%02x", *(uint8_t*)(ptr+i));
fprintf(ci.filePtr(), "%02x", *(uint8_t*)(ptr + i));
}
fprintf(ci.filePtr(), "%c", ci.delimiter());
}
size_t ColWriteBatchString(const uchar *buf,
bool nullVal,
ColBatchWriter &ci,
void (*printFuncPtr)(const String&,
const ColBatchWriter &,
size_t ColWriteBatchString(const uchar* buf, bool nullVal, ColBatchWriter& ci,
void (*printFuncPtr)(const String&, const ColBatchWriter&,
const size_t colWidthInBytes)) const
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
@ -403,19 +394,19 @@ public:
return m_field->pack_length();
}
size_t ColWriteBatchChar(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchChar(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
return (current_thd->variables.sql_mode & MODE_PAD_CHAR_TO_FULL_LENGTH) ?
ColWriteBatchString(buf, nullVal, ci, &ColWriteBatchPaddedTextString) :
ColWriteBatchString(buf, nullVal, ci, &ColWriteBatchTextString);
return (current_thd->variables.sql_mode & MODE_PAD_CHAR_TO_FULL_LENGTH)
? ColWriteBatchString(buf, nullVal, ci, &ColWriteBatchPaddedTextString)
: ColWriteBatchString(buf, nullVal, ci, &ColWriteBatchTextString);
}
size_t ColWriteBatchVarchar(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchVarchar(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
return ColWriteBatchString(buf, nullVal, ci, &ColWriteBatchTextString);
}
size_t ColWriteBatchSInt64(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchSInt64(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
fprintf(ci.filePtr(), "%c", ci.delimiter());
@ -424,7 +415,7 @@ public:
return 8;
}
size_t ColWriteBatchUInt64(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchUInt64(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
fprintf(ci.filePtr(), "%c", ci.delimiter());
@ -433,8 +424,7 @@ public:
return 8;
}
size_t ColWriteBatchSInt32(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchSInt32(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
fprintf(ci.filePtr(), "%c", ci.delimiter());
@ -443,7 +433,7 @@ public:
return 4;
}
size_t ColWriteBatchUInt32(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchUInt32(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
fprintf(ci.filePtr(), "%c", ci.delimiter());
@ -452,7 +442,7 @@ public:
return 4;
}
size_t ColWriteBatchSInt16(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchSInt16(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
fprintf(ci.filePtr(), "%c", ci.delimiter());
@ -461,7 +451,7 @@ public:
return 2;
}
size_t ColWriteBatchUInt16(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchUInt16(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
fprintf(ci.filePtr(), "%c", ci.delimiter());
@ -470,7 +460,7 @@ public:
return 2;
}
size_t ColWriteBatchSInt8(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchSInt8(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
fprintf(ci.filePtr(), "%c", ci.delimiter());
@ -479,7 +469,7 @@ public:
return 1;
}
size_t ColWriteBatchUInt8(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchUInt8(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
fprintf(ci.filePtr(), "%c", ci.delimiter());
@ -488,8 +478,7 @@ public:
return 1;
}
size_t ColWriteBatchXFloat(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchXFloat(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
fprintf(ci.filePtr(), "%c", ci.delimiter());
@ -497,7 +486,7 @@ public:
{
float val = *((float*)buf);
if ((fabs(val) > (1.0 / IDB_pow[4])) && (fabs(val) < (float) IDB_pow[6]))
if ((fabs(val) > (1.0 / IDB_pow[4])) && (fabs(val) < (float)IDB_pow[6]))
{
fprintf(ci.filePtr(), "%.7f%c", val, ci.delimiter());
}
@ -506,29 +495,27 @@ public:
fprintf(ci.filePtr(), "%e%c", val, ci.delimiter());
}
//fprintf(ci.filePtr(), "%.7g|", *((float*)buf2));
//printf("%.7f|", *((float*)buf2));
// fprintf(ci.filePtr(), "%.7g|", *((float*)buf2));
// printf("%.7f|", *((float*)buf2));
}
return 4;
}
size_t ColWriteBatchXDouble(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchXDouble(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
fprintf(ci.filePtr(), "%c", ci.delimiter());
else
{
fprintf(ci.filePtr(), "%.15g%c", *((double*)buf), ci.delimiter());
//printf("%.15g|", *((double*)buf));
// printf("%.15g|", *((double*)buf));
}
return 8;
}
size_t ColWriteBatchSLongDouble(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchSLongDouble(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
fprintf(ci.filePtr(), "%c", ci.delimiter());
@ -537,8 +524,7 @@ public:
return sizeof(long double);
}
size_t ColWriteBatchXDecimal(const uchar *buf, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchXDecimal(const uchar* buf, bool nullVal, ColBatchWriter& ci) override
{
uint bytesBefore = numDecimalBytes(m_type.precision - m_type.scale);
uint totalBytes = bytesBefore + numDecimalBytes(m_type.scale);
@ -546,7 +532,7 @@ public:
if (nullVal && (m_type.constraintType != CalpontSystemCatalog::NOTNULL_CONSTRAINT))
{
fprintf(ci.filePtr(), "%c", ci.delimiter());
//printf("|");
// printf("|");
}
else if (m_type.precision > datatypes::INT64MAXPRECISION)
{
@ -564,16 +550,16 @@ public:
}
else
{
uint32_t mask [5] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
uint32_t mask[5] = {0, 0xFF, 0xFFFF, 0xFFFFFF, 0xFFFFFFFF};
char neg = '-';
if (m_type.scale == 0)
{
const uchar* tmpBuf = buf;
//test flag bit for sign
bool posNum = tmpBuf[0] & (0x80);
// test flag bit for sign
bool posNum = tmpBuf[0] & (0x80);
uchar tmpChr = tmpBuf[0];
tmpChr ^= 0x80; //flip the bit
tmpChr ^= 0x80; // flip the bit
int32_t tmp1 = tmpChr;
if (totalBytes > 4)
@ -583,7 +569,7 @@ public:
tmp1 = (tmp1 << 8) + tmpBuf[i];
}
if (( tmp1 != 0 ) && (tmp1 != -1))
if ((tmp1 != 0) && (tmp1 != -1))
{
if (!posNum)
{
@ -592,7 +578,7 @@ public:
if (tmp1 != 0)
{
fprintf(ci.filePtr(), "%c", neg);
//printf("%c", neg);
// printf("%c", neg);
}
}
@ -610,7 +596,7 @@ public:
tmp2 = (tmp2 << 8) + tmpBuf[i];
}
if ( tmp1 != 0 )
if (tmp1 != 0)
{
if (!posNum)
{
@ -632,7 +618,7 @@ public:
else
{
fprintf(ci.filePtr(), "%09u%c", tmp2, ci.delimiter());
//printf("%09u|", tmp2);
// printf("%09u|", tmp2);
}
}
else
@ -641,11 +627,11 @@ public:
{
tmp2 = mask[4] - tmp2;
fprintf(ci.filePtr(), "%c", neg);
//printf("%c", neg);
// printf("%c", neg);
}
fprintf(ci.filePtr(), "%d%c", tmp2, ci.delimiter());
//printf("%d|", tmp2);
// printf("%d|", tmp2);
}
}
else
@ -659,33 +645,33 @@ public:
{
tmp1 = mask[totalBytes] - tmp1;
fprintf(ci.filePtr(), "%c", neg);
//printf("%c", neg);
// printf("%c", neg);
}
fprintf(ci.filePtr(), "%d%c", tmp1, ci.delimiter());
//printf("%d|", tmp1);
// printf("%d|", tmp1);
}
}
else
{
const uchar* tmpBuf = buf;
//test flag bit for sign
bool posNum = tmpBuf[0] & (0x80);
// test flag bit for sign
bool posNum = tmpBuf[0] & (0x80);
uchar tmpChr = tmpBuf[0];
tmpChr ^= 0x80; //flip the bit
tmpChr ^= 0x80; // flip the bit
int32_t tmp1 = tmpChr;
//fetch the digits before decimal point
// fetch the digits before decimal point
if (bytesBefore == 0)
{
if (!posNum)
{
fprintf(ci.filePtr(), "%c", neg);
//printf("%c", neg);
// printf("%c", neg);
}
fprintf(ci.filePtr(), "0.");
//printf("0.");
// printf("0.");
}
else if (bytesBefore > 4)
{
@ -699,23 +685,23 @@ public:
tmp1 = mask[bytesBefore - 4] - tmp1;
}
if (( tmp1 != 0 ) && (tmp1 != -1))
if ((tmp1 != 0) && (tmp1 != -1))
{
if (!posNum)
{
fprintf(ci.filePtr(), "%c", neg);
//printf("%c", neg);
// printf("%c", neg);
}
fprintf(ci.filePtr(), "%d", tmp1);
//printf("%d", tmp1);
// printf("%d", tmp1);
}
tmpBuf += (bytesBefore - 4);
int32_t tmp2 = *((int32_t*)tmpBuf);
tmp2 = ntohl(tmp2);
if ( tmp1 != 0 )
if (tmp1 != 0)
{
if (!posNum)
{
@ -726,13 +712,13 @@ public:
{
fprintf(ci.filePtr(), "%c", neg);
fprintf(ci.filePtr(), "%d.", tmp2);
//printf("%c", neg);
//printf("%d.", tmp2);
// printf("%c", neg);
// printf("%d.", tmp2);
}
else
{
fprintf(ci.filePtr(), "%09u.", tmp2);
//printf("%09u.", tmp2);
// printf("%09u.", tmp2);
}
}
else
@ -741,11 +727,11 @@ public:
{
tmp2 = mask[4] - tmp2;
fprintf(ci.filePtr(), "%c", neg);
//printf("%c", neg);
// printf("%c", neg);
}
fprintf(ci.filePtr(), "%d.", tmp2);
//printf("%d.", tmp2);
// printf("%d.", tmp2);
}
}
else
@ -759,14 +745,14 @@ public:
{
tmp1 = mask[bytesBefore] - tmp1;
fprintf(ci.filePtr(), "%c", neg);
//printf("%c", neg);
// printf("%c", neg);
}
fprintf(ci.filePtr(), "%d.", tmp1);
//printf("%d.", tmp1);
// printf("%d.", tmp1);
}
//fetch the digits after decimal point
// fetch the digits after decimal point
int32_t tmp2 = 0;
if (bytesBefore > 4)
@ -783,9 +769,9 @@ public:
tmp2 = (tmp2 << 8) + tmpBuf[j];
}
int8_t digits = m_type.scale - 9; //9 digits is a 4 bytes chunk
int8_t digits = m_type.scale - 9; // 9 digits is a 4 bytes chunk
if ( digits <= 0 )
if (digits <= 0)
digits = m_type.scale;
if (!posNum)
@ -794,13 +780,13 @@ public:
}
fprintf(ci.filePtr(), "%0*u%c", digits, tmp2, ci.delimiter());
//printf("%0*u|", digits, tmp2);
// printf("%0*u|", digits, tmp2);
}
else
{
for (uint j = 1; j < 4; j++)
{
tmp2 = (tmp2 << 8) + tmpBuf[j];
tmp2 = (tmp2 << 8) + tmpBuf[j];
}
if (!posNum)
@ -809,19 +795,19 @@ public:
}
fprintf(ci.filePtr(), "%09u", tmp2);
//printf("%09u", tmp2);
// printf("%09u", tmp2);
tmpBuf += 4;
int32_t tmp3 = tmpBuf[0];
for (uint j = 1; j < (totalBytes - bytesBefore - 4); j++)
{
tmp3 = (tmp3 << 8) + tmpBuf[j];
tmp3 = (tmp3 << 8) + tmpBuf[j];
}
int8_t digits = m_type.scale - 9; //9 digits is a 4 bytes chunk
int8_t digits = m_type.scale - 9; // 9 digits is a 4 bytes chunk
if ( digits < 0 )
if (digits < 0)
digits = m_type.scale;
if (!posNum)
@ -830,7 +816,7 @@ public:
}
fprintf(ci.filePtr(), "%0*u%c", digits, tmp3, ci.delimiter());
//printf("%0*u|", digits, tmp3);
// printf("%0*u|", digits, tmp3);
}
}
}
@ -838,23 +824,20 @@ public:
return totalBytes;
}
size_t ColWriteBatchVarbinary(const uchar *buf0, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchVarbinary(const uchar* buf0, bool nullVal, ColBatchWriter& ci) override
{
return ColWriteBatchString(buf0, nullVal, ci, &ColWriteBatchBlobString);
}
size_t ColWriteBatchBlob(const uchar *buf0, bool nullVal, ColBatchWriter &ci) override
size_t ColWriteBatchBlob(const uchar* buf0, bool nullVal, ColBatchWriter& ci) override
{
return (UNLIKELY(m_type.colDataType == CalpontSystemCatalog::BLOB)) ?
ColWriteBatchString(buf0, nullVal, ci, &ColWriteBatchBlobString) :
ColWriteBatchString(buf0, nullVal, ci, &ColWriteBatchTextString);
return (UNLIKELY(m_type.colDataType == CalpontSystemCatalog::BLOB))
? ColWriteBatchString(buf0, nullVal, ci, &ColWriteBatchBlobString)
: ColWriteBatchString(buf0, nullVal, ci, &ColWriteBatchTextString);
}
};
} // end of namespace datatypes
} // end of namespace datatypes
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

18005
dbcon/mysql/ha_mcs_execplan.cpp Executable file → Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -36,17 +36,18 @@ extern int ha_mcs_impl_write_row(const uchar* buf, TABLE* table, uint64_t rows_c
extern void ha_mcs_impl_start_bulk_insert(ha_rows rows, TABLE* table, bool is_cache_insert = false);
extern int ha_mcs_impl_end_bulk_insert(bool abort, TABLE* table);
extern int ha_mcs_impl_rename_table(const char* from, const char* to);
extern int ha_mcs_impl_commit (handlerton* hton, THD* thd, bool all);
extern int ha_mcs_impl_rollback (handlerton* hton, THD* thd, bool all);
extern int ha_mcs_impl_close_connection (handlerton* hton, THD* thd);
extern int ha_mcs_impl_commit(handlerton* hton, THD* thd, bool all);
extern int ha_mcs_impl_rollback(handlerton* hton, THD* thd, bool all);
extern int ha_mcs_impl_close_connection(handlerton* hton, THD* thd);
extern COND* ha_mcs_impl_cond_push(COND* cond, TABLE* table, std::vector<COND*>&);
extern int ha_mcs_impl_update_row();
extern int ha_mcs_impl_direct_update_delete_rows(bool execute, ha_rows *affected_rows, const std::vector<COND*>& condStack);
extern int ha_mcs_impl_direct_update_delete_rows(bool execute, ha_rows* affected_rows,
const std::vector<COND*>& condStack);
extern int ha_mcs_impl_delete_row();
extern int ha_mcs_impl_rnd_pos(uchar* buf, uchar* pos);
extern int ha_mcs_impl_pushdown_init(mcs_handler_info* handler_info, TABLE* table);
extern int ha_mcs_impl_select_next(uchar *buf, TABLE *table);
extern int ha_mcs_impl_group_by_init(mcs_handler_info *handler_info, TABLE* table);
extern int ha_mcs_impl_select_next(uchar* buf, TABLE* table);
extern int ha_mcs_impl_group_by_init(mcs_handler_info* handler_info, TABLE* table);
extern int ha_mcs_impl_group_by_next(TABLE* table);
extern int ha_mcs_impl_group_by_end(TABLE* table);
@ -57,22 +58,26 @@ extern int ha_mcs_impl_group_by_end(TABLE* table);
#include "calpontsystemcatalog.h"
#include "ha_mcs.h"
extern int ha_mcs_impl_rename_table_(const char* from, const char* to, cal_impl_if::cal_connection_info& ci);
extern int ha_mcs_impl_write_row_(const uchar* buf, TABLE* table, cal_impl_if::cal_connection_info& ci, ha_rows& rowsInserted);
extern int ha_mcs_impl_write_row_(const uchar* buf, TABLE* table, cal_impl_if::cal_connection_info& ci,
ha_rows& rowsInserted);
extern int ha_mcs_impl_write_batch_row_(const uchar* buf, TABLE* table, cal_impl_if::cal_connection_info& ci);
extern int ha_mcs_impl_write_last_batch(TABLE* table, cal_impl_if::cal_connection_info& ci, bool abort);
extern int ha_mcs_impl_commit_ (handlerton* hton, THD* thd, bool all, cal_impl_if::cal_connection_info& ci);
extern int ha_mcs_impl_rollback_ (handlerton* hton, THD* thd, bool all, cal_impl_if::cal_connection_info& ci);
extern int ha_mcs_impl_close_connection_ (handlerton* hton, THD* thd, cal_impl_if::cal_connection_info& ci);
extern int ha_mcs_impl_commit_(handlerton* hton, THD* thd, bool all, cal_impl_if::cal_connection_info& ci);
extern int ha_mcs_impl_rollback_(handlerton* hton, THD* thd, bool all, cal_impl_if::cal_connection_info& ci);
extern int ha_mcs_impl_close_connection_(handlerton* hton, THD* thd, cal_impl_if::cal_connection_info& ci);
extern int ha_mcs_impl_delete_table_(const char* db, const char* name, cal_impl_if::cal_connection_info& ci);
extern int ha_mcs_impl_create_(const char* name, TABLE* table_arg, HA_CREATE_INFO* create_info,
cal_impl_if::cal_connection_info& ci);
extern std::string ha_mcs_impl_markpartition_ (execplan::CalpontSystemCatalog::TableName tableName, uint32_t partition);
extern std::string ha_mcs_impl_restorepartition_ (execplan::CalpontSystemCatalog::TableName tableName, uint32_t partition);
extern std::string ha_mcs_impl_droppartition_ (execplan::CalpontSystemCatalog::TableName tableName, uint32_t partition);
cal_impl_if::cal_connection_info& ci);
extern std::string ha_mcs_impl_markpartition_(execplan::CalpontSystemCatalog::TableName tableName,
uint32_t partition);
extern std::string ha_mcs_impl_restorepartition_(execplan::CalpontSystemCatalog::TableName tableName,
uint32_t partition);
extern std::string ha_mcs_impl_droppartition_(execplan::CalpontSystemCatalog::TableName tableName,
uint32_t partition);
extern std::string ha_mcs_impl_viewtablelock( cal_impl_if::cal_connection_info& ci, execplan::CalpontSystemCatalog::TableName& tablename);
extern std::string ha_mcs_impl_cleartablelock( cal_impl_if::cal_connection_info& ci, uint64_t tableLockID);
extern std::string ha_mcs_impl_viewtablelock(cal_impl_if::cal_connection_info& ci,
execplan::CalpontSystemCatalog::TableName& tablename);
extern std::string ha_mcs_impl_cleartablelock(cal_impl_if::cal_connection_info& ci, uint64_t tableLockID);
#endif
#endif

View File

@ -49,9 +49,14 @@ class ha_columnstore_derived_handler;
/** Debug macro */
#ifdef INFINIDB_DEBUG
#define IDEBUG(x) {x;}
#define IDEBUG(x) \
{ \
x; \
}
#else
#define IDEBUG(x) {}
#define IDEBUG(x) \
{ \
}
#endif
namespace execplan
@ -65,7 +70,7 @@ class ArithmeticColumn;
class ParseTree;
class ConstantColumn;
class RowColumn;
}
} // namespace execplan
namespace cal_impl_if
{
@ -74,175 +79,185 @@ class View;
struct JoinInfo
{
execplan::CalpontSystemCatalog::TableAliasName tn;
uint32_t joinTimes;
std::vector<uint32_t> IDs;
execplan::CalpontSystemCatalog::TableAliasName tn;
uint32_t joinTimes;
std::vector<uint32_t> IDs;
};
enum ClauseType
{
INIT = 0,
SELECT,
FROM,
WHERE,
HAVING,
GROUP_BY,
ORDER_BY
INIT = 0,
SELECT,
FROM,
WHERE,
HAVING,
GROUP_BY,
ORDER_BY
};
typedef std::vector<JoinInfo> JoinInfoVec;
typedef std::map<execplan::CalpontSystemCatalog::TableAliasName, std::pair<int, TABLE_LIST*> > TableMap;
typedef std::map<execplan::CalpontSystemCatalog::TableAliasName, std::pair<int, TABLE_LIST*>> TableMap;
typedef std::tr1::unordered_map<TABLE_LIST*, std::vector<COND*>> TableOnExprList;
typedef std::tr1::unordered_map<TABLE_LIST*, uint> TableOuterJoinMap;
struct gp_walk_info
{
// MCOL-2178 Marked for removal after 1.4
std::vector <std::string> selectCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList returnedCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList groupByCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList subGroupByCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList orderByCols;
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
// to the end of returnedCols when the processing is finished.
execplan::CalpontSelectExecutionPlan::ReturnedColumnList additionalRetCols;
// the sequence # of the subselect local columns need to be set after
// the additionRetCols are merged to the returnedCols.
std::vector<execplan::ReturnedColumn*> localCols;
std::stack<execplan::ReturnedColumn*> rcWorkStack;
std::stack<execplan::ParseTree*> ptWorkStack;
boost::shared_ptr<execplan::SimpleColumn> scsp;
uint32_t sessionid;
bool fatalParseError;
std::string parseErrorText;
// for outer join walk. the column that is not of the outerTable has the returnAll flag set.
std::set<execplan::CalpontSystemCatalog::TableAliasName> innerTables;
// the followinig members are used for table mode
bool condPush;
bool dropCond;
std::string funcName;
std::vector<execplan::AggregateColumn*> count_asterisk_list;
std::vector<execplan::FunctionColumn*> no_parm_func_list;
std::vector<execplan::ReturnedColumn*> windowFuncList;
TableMap tableMap;
boost::shared_ptr<execplan::CalpontSystemCatalog> csc;
int8_t internalDecimalScale;
THD* thd;
uint64_t subSelectType; // the type of sub select filter that owns the gwi
SubQuery* subQuery;
execplan::CalpontSelectExecutionPlan::SelectList derivedTbList;
execplan::CalpontSelectExecutionPlan::TableList tbList;
std::vector<execplan::CalpontSystemCatalog::TableAliasName> correlatedTbNameVec;
ClauseType clauseType;
execplan::CalpontSystemCatalog::TableAliasName viewName;
bool aggOnSelect;
bool hasWindowFunc;
bool hasSubSelect;
SubQuery* lastSub;
std::vector<View*> viewList;
std::map<std::string, execplan::ParseTree*> derivedTbFilterMap;
uint32_t derivedTbCnt;
std::vector<execplan::SCSEP> subselectList;
// Workaround for duplicate equi-JOIN predicates
// See isDuplicateSF() for more info.
List<execplan::SimpleFilter> equiCondSFList;
// MCOL-2178 Marked for removal after 1.4
std::vector<std::string> selectCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList returnedCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList groupByCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList subGroupByCols;
execplan::CalpontSelectExecutionPlan::ReturnedColumnList orderByCols;
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
// to the end of returnedCols when the processing is finished.
execplan::CalpontSelectExecutionPlan::ReturnedColumnList additionalRetCols;
// the sequence # of the subselect local columns need to be set after
// the additionRetCols are merged to the returnedCols.
std::vector<execplan::ReturnedColumn*> localCols;
std::stack<execplan::ReturnedColumn*> rcWorkStack;
std::stack<execplan::ParseTree*> ptWorkStack;
boost::shared_ptr<execplan::SimpleColumn> scsp;
uint32_t sessionid;
bool fatalParseError;
std::string parseErrorText;
// for outer join walk. the column that is not of the outerTable has the returnAll flag set.
std::set<execplan::CalpontSystemCatalog::TableAliasName> innerTables;
// the followinig members are used for table mode
bool condPush;
bool dropCond;
std::string funcName;
std::vector<execplan::AggregateColumn*> count_asterisk_list;
std::vector<execplan::FunctionColumn*> no_parm_func_list;
std::vector<execplan::ReturnedColumn*> windowFuncList;
TableMap tableMap;
boost::shared_ptr<execplan::CalpontSystemCatalog> csc;
int8_t internalDecimalScale;
THD* thd;
uint64_t subSelectType; // the type of sub select filter that owns the gwi
SubQuery* subQuery;
execplan::CalpontSelectExecutionPlan::SelectList derivedTbList;
execplan::CalpontSelectExecutionPlan::TableList tbList;
std::vector<execplan::CalpontSystemCatalog::TableAliasName> correlatedTbNameVec;
ClauseType clauseType;
execplan::CalpontSystemCatalog::TableAliasName viewName;
bool aggOnSelect;
bool hasWindowFunc;
bool hasSubSelect;
SubQuery* lastSub;
std::vector<View*> viewList;
std::map<std::string, execplan::ParseTree*> derivedTbFilterMap;
uint32_t derivedTbCnt;
std::vector<execplan::SCSEP> subselectList;
// Workaround for duplicate equi-JOIN predicates
// See isDuplicateSF() for more info.
List<execplan::SimpleFilter> equiCondSFList;
// Kludge for Bug 750
int32_t recursionLevel;
int32_t recursionHWM;
std::stack<int32_t> rcBookMarkStack;
// Kludge for Bug 750
int32_t recursionLevel;
int32_t recursionHWM;
std::stack<int32_t> rcBookMarkStack;
// Kludge for MCOL-1472
bool inCaseStmt;
bool cs_vtable_is_update_with_derive;
bool cs_vtable_impossible_where_on_union;
// Kludge for MCOL-1472
bool inCaseStmt;
bool cs_vtable_is_update_with_derive;
bool cs_vtable_impossible_where_on_union;
bool isGroupByHandler;
bool isGroupByHandler;
// MCOL-4617 The below 2 fields are used for in-to-exists
// predicate creation and injection. See usage in InSub::transform()
// and buildInToExistsFilter()
execplan::ReturnedColumn* inSubQueryLHS;
Item* inSubQueryLHSItem;
// MCOL-4617 The below 2 fields are used for in-to-exists
// predicate creation and injection. See usage in InSub::transform()
// and buildInToExistsFilter()
execplan::ReturnedColumn* inSubQueryLHS;
Item* inSubQueryLHSItem;
// The below 2 fields are required for MCOL-4525.
TableOnExprList tableOnExprList;
std::vector<COND*> condList;
// The below 2 fields are required for MCOL-4525.
TableOnExprList tableOnExprList;
std::vector<COND*> condList;
gp_walk_info() : sessionid(0),
fatalParseError(false),
condPush(false),
dropCond(false),
internalDecimalScale(4),
thd(0),
subSelectType(uint64_t(-1)),
subQuery(0),
clauseType(INIT),
aggOnSelect(false),
hasWindowFunc(false),
hasSubSelect(false),
lastSub(0),
derivedTbCnt(0),
recursionLevel(-1),
recursionHWM(0),
inCaseStmt(false),
cs_vtable_is_update_with_derive(false),
cs_vtable_impossible_where_on_union(false),
isGroupByHandler(false),
inSubQueryLHS(nullptr),
inSubQueryLHSItem(nullptr)
{}
gp_walk_info()
: sessionid(0)
, fatalParseError(false)
, condPush(false)
, dropCond(false)
, internalDecimalScale(4)
, thd(0)
, subSelectType(uint64_t(-1))
, subQuery(0)
, clauseType(INIT)
, aggOnSelect(false)
, hasWindowFunc(false)
, hasSubSelect(false)
, lastSub(0)
, derivedTbCnt(0)
, recursionLevel(-1)
, recursionHWM(0)
, inCaseStmt(false)
, cs_vtable_is_update_with_derive(false)
, cs_vtable_impossible_where_on_union(false)
, isGroupByHandler(false)
, inSubQueryLHS(nullptr)
, inSubQueryLHSItem(nullptr)
{
}
~gp_walk_info() {}
~gp_walk_info()
{
}
};
struct cal_table_info
{
enum RowSources { FROM_ENGINE, FROM_FILE };
enum RowSources
{
FROM_ENGINE,
FROM_FILE
};
cal_table_info() : tpl_ctx(0),
c(0),
msTablePtr(0),
conn_hndl(0),
condInfo(0),
moreRows(false)
{ }
~cal_table_info() {}
sm::cpsm_tplh_t* tpl_ctx;
std::stack<sm::cpsm_tplh_t*> tpl_ctx_st;
sm::sp_cpsm_tplsch_t tpl_scan_ctx;
std::stack<sm::sp_cpsm_tplsch_t> tpl_scan_ctx_st;
unsigned c; // for debug purpose
TABLE* msTablePtr; // no ownership
sm::cpsm_conhdl_t* conn_hndl;
gp_walk_info* condInfo;
execplan::SCSEP csep;
bool moreRows; //are there more rows to consume (b/c of limit)
cal_table_info() : tpl_ctx(0), c(0), msTablePtr(0), conn_hndl(0), condInfo(0), moreRows(false)
{
}
~cal_table_info()
{
}
sm::cpsm_tplh_t* tpl_ctx;
std::stack<sm::cpsm_tplh_t*> tpl_ctx_st;
sm::sp_cpsm_tplsch_t tpl_scan_ctx;
std::stack<sm::sp_cpsm_tplsch_t> tpl_scan_ctx_st;
unsigned c; // for debug purpose
TABLE* msTablePtr; // no ownership
sm::cpsm_conhdl_t* conn_hndl;
gp_walk_info* condInfo;
execplan::SCSEP csep;
bool moreRows; // are there more rows to consume (b/c of limit)
};
struct cal_group_info
{
cal_group_info() : groupByFields(0),
groupByTables(0),
groupByWhere(0),
groupByGroup(0),
groupByOrder(0),
groupByHaving(0),
groupByDistinct(false)
{ }
~cal_group_info() { }
cal_group_info()
: groupByFields(0)
, groupByTables(0)
, groupByWhere(0)
, groupByGroup(0)
, groupByOrder(0)
, groupByHaving(0)
, groupByDistinct(false)
{
}
~cal_group_info()
{
}
List<Item>* groupByFields; // MCOL-1052 SELECT
TABLE_LIST* groupByTables; // MCOL-1052 FROM
Item* groupByWhere; // MCOL-1052 WHERE
ORDER* groupByGroup; // MCOL-1052 GROUP BY
ORDER* groupByOrder; // MCOL-1052 ORDER BY
Item* groupByHaving; // MCOL-1052 HAVING
bool groupByDistinct; //MCOL-1052 DISTINCT
std::vector<execplan::ParseTree*> pushedPts;
List<Item>* groupByFields; // MCOL-1052 SELECT
TABLE_LIST* groupByTables; // MCOL-1052 FROM
Item* groupByWhere; // MCOL-1052 WHERE
ORDER* groupByGroup; // MCOL-1052 GROUP BY
ORDER* groupByOrder; // MCOL-1052 ORDER BY
Item* groupByHaving; // MCOL-1052 HAVING
bool groupByDistinct; // MCOL-1052 DISTINCT
std::vector<execplan::ParseTree*> pushedPts;
};
typedef std::tr1::unordered_map<TABLE*, cal_table_info> CalTableMap;
@ -252,131 +267,147 @@ typedef std::map<uint32_t, ColValuesList> TableValuesMap;
typedef std::bitset<4096> NullValuesBitset;
struct cal_connection_info
{
enum AlterTableState { NOT_ALTER, ALTER_SECOND_RENAME, ALTER_FIRST_RENAME };
cal_connection_info() : cal_conn_hndl(0),
queryState(0),
currentTable(0),
traceFlags(0),
alterTableState(NOT_ALTER),
isAlter(false),
bulkInsertRows(0),
singleInsert(true),
isLoaddataInfile(false),
isCacheInsert(false),
dmlProc(0),
rowsHaveInserted(0),
rc(0),
tableOid(0),
localPm(-1),
isSlaveNode(false),
expressionId(0),
mysqld_pid(getpid()),
cpimport_pid(0),
filePtr(0),
headerLength(0),
useXbit(false),
useCpimport(mcs_use_import_for_batchinsert_mode_t::ON),
delimiter('\7'),
affectedRows(0)
{
auto* cf = config::Config::makeConfig();
if (checkQueryStats(cf))
traceFlags |= execplan::CalpontSelectExecutionPlan::TRACE_LOG;
// check if this is a slave mysql daemon
isSlaveNode = checkSlave(cf);
}
enum AlterTableState
{
NOT_ALTER,
ALTER_SECOND_RENAME,
ALTER_FIRST_RENAME
};
cal_connection_info()
: cal_conn_hndl(0)
, queryState(0)
, currentTable(0)
, traceFlags(0)
, alterTableState(NOT_ALTER)
, isAlter(false)
, bulkInsertRows(0)
, singleInsert(true)
, isLoaddataInfile(false)
, isCacheInsert(false)
, dmlProc(0)
, rowsHaveInserted(0)
, rc(0)
, tableOid(0)
, localPm(-1)
, isSlaveNode(false)
, expressionId(0)
, mysqld_pid(getpid())
, cpimport_pid(0)
, filePtr(0)
, headerLength(0)
, useXbit(false)
, useCpimport(mcs_use_import_for_batchinsert_mode_t::ON)
, delimiter('\7')
, affectedRows(0)
{
auto* cf = config::Config::makeConfig();
if (checkQueryStats(cf))
traceFlags |= execplan::CalpontSelectExecutionPlan::TRACE_LOG;
// check if this is a slave mysql daemon
isSlaveNode = checkSlave(cf);
}
bool checkQueryStats(config::Config* cfg)
{
std::string qsVal = cfg->getConfig("QueryStats", "Enabled");
if (qsVal == "Y" || qsVal == "Y")
return true;
bool checkQueryStats(config::Config* cfg)
{
std::string qsVal = cfg->getConfig("QueryStats", "Enabled");
if (qsVal == "Y" || qsVal == "Y")
return true;
return false;
}
return false;
}
static bool checkSlave(config::Config* cf = nullptr)
{
if (!cf)
cf = config::Config::makeConfig();
std::string configVal = cf->getConfig("Installation", "MySQLRep");
bool isMysqlRep = (configVal == "y" || configVal == "Y");
static bool checkSlave(config::Config* cf = nullptr)
{
if (!cf)
cf = config::Config::makeConfig();
std::string configVal = cf->getConfig("Installation", "MySQLRep");
bool isMysqlRep = (configVal == "y" || configVal == "Y");
if (!isMysqlRep) return false;
if (!isMysqlRep)
return false;
configVal = cf->getConfig("SystemConfig", "PrimaryUMModuleName");
std::string module = execplan::ClientRotator::getModule();
configVal = cf->getConfig("SystemConfig", "PrimaryUMModuleName");
std::string module = execplan::ClientRotator::getModule();
if (boost::iequals(configVal, module))
return false;
if (boost::iequals(configVal, module))
return false;
return true;
}
return true;
}
sm::cpsm_conhdl_t* cal_conn_hndl;
std::stack<sm::cpsm_conhdl_t*> cal_conn_hndl_st;
int queryState;
CalTableMap tableMap;
std::set<TABLE*> physTablesList;
sm::tableid_t currentTable;
uint32_t traceFlags;
std::string queryStats;
AlterTableState alterTableState;
bool isAlter;
ha_rows bulkInsertRows;
bool singleInsert;
bool isLoaddataInfile;
bool isCacheInsert;
std::string extendedStats;
std::string miniStats;
messageqcpp::MessageQueueClient* dmlProc;
ha_rows rowsHaveInserted;
ColNameList colNameList;
TableValuesMap tableValuesMap;
NullValuesBitset nullValuesBitset;
int rc;
uint32_t tableOid;
querystats::QueryStats stats;
std::string warningMsg;
int64_t localPm;
bool isSlaveNode;
uint32_t expressionId; // for F&E
pid_t mysqld_pid;
pid_t cpimport_pid;
int fdt[2];
sm::cpsm_conhdl_t* cal_conn_hndl;
std::stack<sm::cpsm_conhdl_t*> cal_conn_hndl_st;
int queryState;
CalTableMap tableMap;
std::set<TABLE*> physTablesList;
sm::tableid_t currentTable;
uint32_t traceFlags;
std::string queryStats;
AlterTableState alterTableState;
bool isAlter;
ha_rows bulkInsertRows;
bool singleInsert;
bool isLoaddataInfile;
bool isCacheInsert;
std::string extendedStats;
std::string miniStats;
messageqcpp::MessageQueueClient* dmlProc;
ha_rows rowsHaveInserted;
ColNameList colNameList;
TableValuesMap tableValuesMap;
NullValuesBitset nullValuesBitset;
int rc;
uint32_t tableOid;
querystats::QueryStats stats;
std::string warningMsg;
int64_t localPm;
bool isSlaveNode;
uint32_t expressionId; // for F&E
pid_t mysqld_pid;
pid_t cpimport_pid;
int fdt[2];
#ifdef _MSC_VER
// Used for launching cpimport for Load Data Infile
HANDLE cpimport_stdin_Rd;
HANDLE cpimport_stdin_Wr;
HANDLE cpimport_stdout_Rd;
HANDLE cpimport_stdout_Wr;
PROCESS_INFORMATION cpimportProcInfo;
// Used for launching cpimport for Load Data Infile
HANDLE cpimport_stdin_Rd;
HANDLE cpimport_stdin_Wr;
HANDLE cpimport_stdout_Rd;
HANDLE cpimport_stdout_Wr;
PROCESS_INFORMATION cpimportProcInfo;
#endif
FILE* filePtr;
uint8_t headerLength;
bool useXbit;
mcs_use_import_for_batchinsert_mode_t useCpimport;
char delimiter;
char enclosed_by;
std::vector <execplan::CalpontSystemCatalog::ColType> columnTypes;
// MCOL-1101 remove compilation unit variable rmParms
std::vector <execplan::RMParam> rmParms;
long long affectedRows;
FILE* filePtr;
uint8_t headerLength;
bool useXbit;
mcs_use_import_for_batchinsert_mode_t useCpimport;
char delimiter;
char enclosed_by;
std::vector<execplan::CalpontSystemCatalog::ColType> columnTypes;
// MCOL-1101 remove compilation unit variable rmParms
std::vector<execplan::RMParam> rmParms;
long long affectedRows;
};
const std::string infinidb_err_msg = "\nThe query includes syntax that is not supported by MariaDB Columnstore. Use 'show warnings;' to get more information. Review the MariaDB Columnstore Syntax guide for additional information on supported distributed syntax or consider changing the MariaDB Columnstore Operating Mode (infinidb_vtable_mode).";
const std::string infinidb_err_msg =
"\nThe query includes syntax that is not supported by MariaDB Columnstore. Use 'show warnings;' to get "
"more information. Review the MariaDB Columnstore Syntax guide for additional information on supported "
"distributed syntax or consider changing the MariaDB Columnstore Operating Mode (infinidb_vtable_mode).";
int cp_get_plan(THD* thd, execplan::SCSEP& csep);
int cp_get_table_plan(THD* thd, execplan::SCSEP& csep, cal_impl_if::cal_table_info& ti);
int cp_get_group_plan(THD* thd, execplan::SCSEP& csep, cal_impl_if::cal_group_info& gi);
int cs_get_derived_plan(ha_columnstore_derived_handler* handler, THD* thd, execplan::SCSEP& csep, gp_walk_info& gwi);
int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* thd, execplan::SCSEP& csep, gp_walk_info& gwi);
int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, execplan::SCSEP& csep, bool isUnion = false, bool isSelectHandlerTop = false, const std::vector<COND*>& condStack = std::vector<COND*>());
int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, execplan::SCSEP& csep, cal_group_info& gi, bool isUnion = false);
int cs_get_derived_plan(ha_columnstore_derived_handler* handler, THD* thd, execplan::SCSEP& csep,
gp_walk_info& gwi);
int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* thd, execplan::SCSEP& csep,
gp_walk_info& gwi);
int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, execplan::SCSEP& csep, bool isUnion = false,
bool isSelectHandlerTop = false,
const std::vector<COND*>& condStack = std::vector<COND*>());
int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, execplan::SCSEP& csep, cal_group_info& gi,
bool isUnion = false);
void setError(THD* thd, uint32_t errcode, const std::string errmsg, gp_walk_info* gwi);
void setError(THD* thd, uint32_t errcode, const std::string errmsg);
void gp_walk(const Item* item, void* arg);
void parse_item (Item* item, std::vector<Item_field*>& field_vec, bool& hasNonSupportItem, uint16& parseInfo, gp_walk_info* gwip = NULL);
void parse_item(Item* item, std::vector<Item_field*>& field_vec, bool& hasNonSupportItem, uint16& parseInfo,
gp_walk_info* gwip = NULL);
const std::string bestTableName(const Item_field* ifp);
bool isMCSTable(TABLE* table_ptr);
bool isForeignTableUpdate(THD* thd);
@ -385,32 +416,39 @@ bool isMCSTableUpdate(THD* thd);
bool isMCSTableDelete(THD* thd);
// execution plan util functions prototypes
execplan::ReturnedColumn* buildReturnedColumn(Item* item, gp_walk_info& gwi, bool& nonSupport, bool isRefItem = false);
execplan::ReturnedColumn* buildFunctionColumn(Item_func* item, gp_walk_info& gwi, bool& nonSupport, bool selectBetweenIn = false);
execplan::ReturnedColumn* buildReturnedColumn(Item* item, gp_walk_info& gwi, bool& nonSupport,
bool isRefItem = false);
execplan::ReturnedColumn* buildFunctionColumn(Item_func* item, gp_walk_info& gwi, bool& nonSupport,
bool selectBetweenIn = false);
execplan::ArithmeticColumn* buildArithmeticColumn(Item_func* item, gp_walk_info& gwi, bool& nonSupport);
execplan::ConstantColumn* buildDecimalColumn(const Item *item, const std::string &str, gp_walk_info& gwi);
execplan::ConstantColumn* buildDecimalColumn(const Item* item, const std::string& str, gp_walk_info& gwi);
execplan::SimpleColumn* buildSimpleColumn(Item_field* item, gp_walk_info& gwi);
execplan::FunctionColumn* buildCaseFunction(Item_func* item, gp_walk_info& gwi, bool& nonSupport);
execplan::ParseTree* buildParseTree(Item_func* item, gp_walk_info& gwi, bool& nonSupport);
execplan::ReturnedColumn* buildAggregateColumn(Item* item, gp_walk_info& gwi);
execplan::ReturnedColumn* buildWindowFunctionColumn(Item* item, gp_walk_info& gwi, bool& nonSupport);
execplan::ReturnedColumn* buildPseudoColumn(Item* item, gp_walk_info& gwi, bool& nonSupport, uint32_t pseudoType);
execplan::ReturnedColumn* buildPseudoColumn(Item* item, gp_walk_info& gwi, bool& nonSupport,
uint32_t pseudoType);
void addIntervalArgs(THD* thd, Item_func* ifp, funcexp::FunctionParm& functionParms);
void castCharArgs(THD* thd, Item_func* ifp, funcexp::FunctionParm& functionParms);
void castDecimalArgs(THD* thd, Item_func* ifp, funcexp::FunctionParm& functionParms);
void castTypeArgs(THD* thd, Item_func* ifp, funcexp::FunctionParm& functionParms);
//void parse_item (Item* item, std::vector<Item_field*>& field_vec, bool& hasNonSupportItem, uint16& parseInfo);
// void parse_item (Item* item, std::vector<Item_field*>& field_vec, bool& hasNonSupportItem, uint16&
// parseInfo);
bool isPredicateFunction(Item* item, gp_walk_info* gwip);
execplan::ParseTree* buildRowPredicate(THD* thd, execplan::RowColumn* lhs, execplan::RowColumn* rhs, std::string predicateOp);
bool buildRowColumnFilter(gp_walk_info* gwip, execplan::RowColumn* rhs, execplan::RowColumn* lhs, Item_func* ifp);
execplan::ParseTree* buildRowPredicate(THD* thd, execplan::RowColumn* lhs, execplan::RowColumn* rhs,
std::string predicateOp);
bool buildRowColumnFilter(gp_walk_info* gwip, execplan::RowColumn* rhs, execplan::RowColumn* lhs,
Item_func* ifp);
bool buildPredicateItem(Item_func* ifp, gp_walk_info* gwip);
void collectAllCols(gp_walk_info& gwi, Item_field* ifp);
void buildSubselectFunc(Item_func* ifp, gp_walk_info* gwip);
uint32_t buildJoin(gp_walk_info& gwi, List<TABLE_LIST>& join_list, std::stack<execplan::ParseTree*>& outerJoinStack);
uint32_t buildJoin(gp_walk_info& gwi, List<TABLE_LIST>& join_list,
std::stack<execplan::ParseTree*>& outerJoinStack);
std::string getViewName(TABLE_LIST* table_ptr);
bool buildConstPredicate(Item_func* ifp, execplan::ReturnedColumn* rhs, gp_walk_info* gwip);
execplan::CalpontSystemCatalog::ColType fieldType_MysqlToIDB (const Field* field);
execplan::CalpontSystemCatalog::ColType colType_MysqlToIDB (const Item* item);
execplan::CalpontSystemCatalog::ColType fieldType_MysqlToIDB(const Field* field);
execplan::CalpontSystemCatalog::ColType colType_MysqlToIDB(const Item* item);
execplan::SPTP getIntervalType(THD* thd, int interval_type);
uint32_t isPseudoColumn(std::string funcName);
void setDerivedTable(execplan::ParseTree* n);
@ -418,45 +456,34 @@ execplan::ParseTree* setDerivedFilter(THD* thd, execplan::ParseTree*& n,
std::map<std::string, execplan::ParseTree*>& obj,
execplan::CalpontSelectExecutionPlan::SelectList& derivedTbList);
void derivedTableOptimization(THD* thd, execplan::SCSEP& csep);
bool buildEqualityPredicate(execplan::ReturnedColumn* lhs,
execplan::ReturnedColumn* rhs,
gp_walk_info* gwip,
boost::shared_ptr<execplan::Operator>& sop,
const Item_func::Functype& funcType,
const std::vector<Item*>& itemList,
bool isInSubs = false);
bool buildEqualityPredicate(execplan::ReturnedColumn* lhs, execplan::ReturnedColumn* rhs, gp_walk_info* gwip,
boost::shared_ptr<execplan::Operator>& sop, const Item_func::Functype& funcType,
const std::vector<Item*>& itemList, bool isInSubs = false);
inline bool isUpdateStatement(const enum_sql_command& command)
{
return ((command == SQLCOM_UPDATE) ||
(command == SQLCOM_UPDATE_MULTI));
return ((command == SQLCOM_UPDATE) || (command == SQLCOM_UPDATE_MULTI));
}
inline bool isDeleteStatement(const enum_sql_command& command)
{
return (command == SQLCOM_DELETE) ||
(command == SQLCOM_DELETE_MULTI);
return (command == SQLCOM_DELETE) || (command == SQLCOM_DELETE_MULTI);
}
inline bool isUpdateOrDeleteStatement(const enum_sql_command& command)
{
return isUpdateStatement(command) ||
isDeleteStatement(command);
return isUpdateStatement(command) || isDeleteStatement(command);
}
inline bool isDMLStatement(const enum_sql_command& command)
{
return (command == SQLCOM_INSERT ||
command == SQLCOM_INSERT_SELECT ||
command == SQLCOM_TRUNCATE ||
command == SQLCOM_LOAD ||
isUpdateOrDeleteStatement(command));
return (command == SQLCOM_INSERT || command == SQLCOM_INSERT_SELECT || command == SQLCOM_TRUNCATE ||
command == SQLCOM_LOAD || isUpdateOrDeleteStatement(command));
}
#ifdef DEBUG_WALK_COND
void debug_walk(const Item* item, void* arg);
#endif
}
} // namespace cal_impl_if
#endif

View File

@ -33,21 +33,20 @@
*/
namespace ha_mcs_impl
{
inline void log_this(THD *thd, const char *message,
logging::LOG_TYPE log_type, unsigned sid)
inline void log_this(THD* thd, const char* message, logging::LOG_TYPE log_type, unsigned sid)
{
// corresponds with dbcon in SubsystemID vector
// in messagelog.cpp
unsigned int subSystemId = 24;
logging::LoggingID logid( subSystemId, sid, 0);
logging::Message::Args args1;
logging::Message msg(1);
args1.add(message);
msg.format( args1 );
logging::Logger logger(logid.fSubsysID);
logger.logMessage(log_type, msg, logid);
// corresponds with dbcon in SubsystemID vector
// in messagelog.cpp
unsigned int subSystemId = 24;
logging::LoggingID logid(subSystemId, sid, 0);
logging::Message::Args args1;
logging::Message msg(1);
args1.add(message);
msg.format(args1);
logging::Logger logger(logid.fSubsysID);
logger.logMessage(log_type, msg, logid);
}
};
}; // namespace ha_mcs_impl
#endif

View File

@ -21,135 +21,130 @@
/*@brief in_subselect_rewrite_walk - Rewrites Item_in_subselect*/
/************************************************************
* DESCRIPTION:
* It traverses filter predicates searching for
* Item_in_subselect and rewrites it adding equi-join predicate
* to finalise IN_2_EXISTS rewrite.
* PARAMETERS:
* item_arg - Item to check.
* arg - bool to early return if predicate injection fails.
* RETURN:
***********************************************************/
* DESCRIPTION:
* It traverses filter predicates searching for
* Item_in_subselect and rewrites it adding equi-join predicate
* to finalise IN_2_EXISTS rewrite.
* PARAMETERS:
* item_arg - Item to check.
* arg - bool to early return if predicate injection fails.
* RETURN:
***********************************************************/
void in_subselect_rewrite_walk(const Item* item_arg, void* arg)
{
bool* result= reinterpret_cast<bool*>(arg);
if (*result) return;
bool* result = reinterpret_cast<bool*>(arg);
if (*result)
return;
Item* item= const_cast<Item*>(item_arg);
Item* item = const_cast<Item*>(item_arg);
JOIN* join= nullptr;
if (typeid(*item) == typeid(Item_in_subselect))
{
Item_in_subselect* sub= reinterpret_cast<Item_in_subselect*>(item);
// MCS 1.4.3 doesn't support IN + subquery with UNION so
// we safe to take this JOIN.
join= sub->unit->first_select()->join;
// Inject equi-JOIN predicates if needed.
*result= sub->create_in_to_exists_cond(join);
*result= (*result) ? *result :
sub->inject_in_to_exists_cond(join);
sub->unit->first_select()->prep_where=
join->conds ? join->conds->copy_andor_structure(current_thd) : 0;
}
else if (typeid(*item) == typeid(Item_singlerow_subselect))
{
Item_singlerow_subselect* sub=
reinterpret_cast<Item_singlerow_subselect*>(item);
// MCS 1.4.3 doesn't support IN + subquery with UNION so
// we safe to take this JOIN.
join= sub->unit->first_select()->join;
}
else
{
// Exit for any but dedicated Items.
return;
}
JOIN* join = nullptr;
if (typeid(*item) == typeid(Item_in_subselect))
{
Item_in_subselect* sub = reinterpret_cast<Item_in_subselect*>(item);
// MCS 1.4.3 doesn't support IN + subquery with UNION so
// we safe to take this JOIN.
join = sub->unit->first_select()->join;
// Inject equi-JOIN predicates if needed.
*result = sub->create_in_to_exists_cond(join);
*result = (*result) ? *result : sub->inject_in_to_exists_cond(join);
sub->unit->first_select()->prep_where = join->conds ? join->conds->copy_andor_structure(current_thd) : 0;
}
else if (typeid(*item) == typeid(Item_singlerow_subselect))
{
Item_singlerow_subselect* sub = reinterpret_cast<Item_singlerow_subselect*>(item);
// MCS 1.4.3 doesn't support IN + subquery with UNION so
// we safe to take this JOIN.
join = sub->unit->first_select()->join;
}
else
{
// Exit for any but dedicated Items.
return;
}
// Walk recursively to process nested IN ops.
if (join->conds)
{
join->conds->traverse_cond(in_subselect_rewrite_walk,
arg, Item::POSTFIX);
}
// Walk recursively to process nested IN ops.
if (join->conds)
{
join->conds->traverse_cond(in_subselect_rewrite_walk, arg, Item::POSTFIX);
}
}
// Sets SELECT_LEX::first_cond_optimization
void first_cond_optimization_flag_set(SELECT_LEX* select_lex)
{
select_lex->first_cond_optimization = true;
select_lex->first_cond_optimization = true;
}
// Unsets SELECT_LEX::first_cond_optimization
void first_cond_optimization_flag_unset(SELECT_LEX* select_lex)
{
select_lex->first_cond_optimization = false;
select_lex->first_cond_optimization = false;
}
/* @brief first_cond_optimization_flag_toggle() - Sets/Unsets first_cond_optimization */
/************************************************************
* DESCRIPTION:
* This function traverses SELECT_LEX::table_list recursively
* to set/unset SELECT_LEX::first_cond_optimization: a marker
* to control optimizations executing PS. If set it allows to
* apply optimizations. If unset, it disables optimizations.
* PARAMETERS:
* select_lex - SELECT_LEX* that describes the query.
* func - Pointer to a function which either sets/unsets
* SELECT_LEX::first_cond_optimization
***********************************************************/
void first_cond_optimization_flag_toggle(SELECT_LEX *select_lex, void (*func)(SELECT_LEX*))
* DESCRIPTION:
* This function traverses SELECT_LEX::table_list recursively
* to set/unset SELECT_LEX::first_cond_optimization: a marker
* to control optimizations executing PS. If set it allows to
* apply optimizations. If unset, it disables optimizations.
* PARAMETERS:
* select_lex - SELECT_LEX* that describes the query.
* func - Pointer to a function which either sets/unsets
* SELECT_LEX::first_cond_optimization
***********************************************************/
void first_cond_optimization_flag_toggle(SELECT_LEX* select_lex, void (*func)(SELECT_LEX*))
{
for (TABLE_LIST *tl= select_lex->get_table_list(); tl; tl= tl->next_local)
for (TABLE_LIST* tl = select_lex->get_table_list(); tl; tl = tl->next_local)
{
if (tl->is_view_or_derived())
{
if (tl->is_view_or_derived())
SELECT_LEX_UNIT* unit = tl->get_unit();
if (unit)
{
for (SELECT_LEX* sl = unit->first_select(); sl; sl = sl->next_select())
{
SELECT_LEX_UNIT *unit= tl->get_unit();
if (unit)
{
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
{
first_cond_optimization_flag_toggle(sl, func);
}
}
first_cond_optimization_flag_toggle(sl, func);
}
}
}
}
(*func)(select_lex);
(*func)(select_lex);
}
/* @brief in_subselect_rewrite - Rewrites Item_in_subselect */
/************************************************************
* DESCRIPTION:
* This function traverses TABLE_LISTs running in_subselect_rewrite_walk
* PARAMETERS:
* select_lex - SELECT_LEX* that describes the query.
* RETURN:
* bool to indicate predicate injection failures.
***********************************************************/
bool in_subselect_rewrite(SELECT_LEX *select_lex)
* DESCRIPTION:
* This function traverses TABLE_LISTs running in_subselect_rewrite_walk
* PARAMETERS:
* select_lex - SELECT_LEX* that describes the query.
* RETURN:
* bool to indicate predicate injection failures.
***********************************************************/
bool in_subselect_rewrite(SELECT_LEX* select_lex)
{
bool result = false;
TABLE_LIST *tbl;
List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
bool result = false;
TABLE_LIST* tbl;
List_iterator_fast<TABLE_LIST> li(select_lex->leaf_tables);
while (!result && (tbl = li++))
while (!result && (tbl = li++))
{
if (tbl->is_view_or_derived())
{
if (tbl->is_view_or_derived())
{
SELECT_LEX_UNIT *unit= tbl->get_unit();
SELECT_LEX_UNIT* unit = tbl->get_unit();
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
result = in_subselect_rewrite(sl);
}
for (SELECT_LEX* sl = unit->first_select(); sl; sl = sl->next_select())
result = in_subselect_rewrite(sl);
}
}
if (select_lex->join && select_lex->join->conds)
{
select_lex->join->conds->traverse_cond(in_subselect_rewrite_walk, &result,
Item::POSTFIX);
}
if (select_lex->join && select_lex->join->conds)
{
select_lex->join->conds->traverse_cond(in_subselect_rewrite_walk, &result, Item::POSTFIX);
}
return result;
return result;
}

View File

@ -20,8 +20,8 @@
#include "idb_mysql.h"
bool in_subselect_rewrite(SELECT_LEX *select_lex);
void first_cond_optimization_flag_toggle(SELECT_LEX *select_lex, void (*func)(SELECT_LEX*));
bool in_subselect_rewrite(SELECT_LEX* select_lex);
void first_cond_optimization_flag_toggle(SELECT_LEX* select_lex, void (*func)(SELECT_LEX*));
void first_cond_optimization_flag_unset(SELECT_LEX*);
void first_cond_optimization_flag_set(SELECT_LEX*);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#ifndef HA_MCS_PUSH
#define HA_MCS_PUSH
@ -27,25 +26,25 @@
#include "ha_mcs_impl_if.h"
#include "ha_mcs_opt_rewrites.h"
void mutate_optimizer_flags(THD *thd_);
void restore_optimizer_flags(THD *thd_);
void mutate_optimizer_flags(THD* thd_);
void restore_optimizer_flags(THD* thd_);
enum mcs_handler_types_t
{
SELECT,
DERIVED,
GROUP_BY,
LEGACY
SELECT,
DERIVED,
GROUP_BY,
LEGACY
};
struct mcs_handler_info
{
mcs_handler_info() : hndl_ptr(NULL), hndl_type(LEGACY) { };
mcs_handler_info(mcs_handler_types_t type) : hndl_ptr(NULL), hndl_type(type) { };
mcs_handler_info(void* ptr, mcs_handler_types_t type) : hndl_ptr(ptr), hndl_type(type) { };
~mcs_handler_info() { };
void* hndl_ptr;
mcs_handler_types_t hndl_type;
mcs_handler_info() : hndl_ptr(NULL), hndl_type(LEGACY){};
mcs_handler_info(mcs_handler_types_t type) : hndl_ptr(NULL), hndl_type(type){};
mcs_handler_info(void* ptr, mcs_handler_types_t type) : hndl_ptr(ptr), hndl_type(type){};
~mcs_handler_info(){};
void* hndl_ptr;
mcs_handler_types_t hndl_type;
};
/*@brief group_by_handler class*/
@ -76,22 +75,22 @@ struct mcs_handler_info
* next_row - get a row back from sm.
* end_scan - finish and clean the things up.
***********************************************************/
class ha_mcs_group_by_handler: public group_by_handler
class ha_mcs_group_by_handler : public group_by_handler
{
public:
ha_mcs_group_by_handler(THD* thd_arg, Query* query);
~ha_mcs_group_by_handler();
int init_scan() override;
int next_row() override;
int end_scan() override;
public:
ha_mcs_group_by_handler(THD* thd_arg, Query* query);
~ha_mcs_group_by_handler();
int init_scan() override;
int next_row() override;
int end_scan() override;
List<Item>* select;
TABLE_LIST* table_list;
bool distinct;
Item* where;
ORDER* group_by;
ORDER* order_by;
Item* having;
List<Item>* select;
TABLE_LIST* table_list;
bool distinct;
Item* where;
ORDER* group_by;
ORDER* order_by;
Item* having;
};
/*@brief derived_handler class*/
@ -107,13 +106,13 @@ public:
* next_row - get a row back from sm.
* end_scan - finish and clean the things up.
***********************************************************/
class ha_columnstore_derived_handler: public derived_handler
class ha_columnstore_derived_handler : public derived_handler
{
private:
COLUMNSTORE_SHARE *share;
private:
COLUMNSTORE_SHARE* share;
public:
ha_columnstore_derived_handler(THD* thd_arg, TABLE_LIST *tbl);
public:
ha_columnstore_derived_handler(THD* thd_arg, TABLE_LIST* tbl);
~ha_columnstore_derived_handler();
int init_scan() override;
int next_row() override;
@ -134,14 +133,14 @@ public:
* next_row - get a row back from sm.
* end_scan - finish and clean the things up.
***********************************************************/
class ha_columnstore_select_handler: public select_handler
class ha_columnstore_select_handler : public select_handler
{
private:
COLUMNSTORE_SHARE *share;
private:
COLUMNSTORE_SHARE* share;
bool prepared;
bool scan_ended;
public:
public:
bool scan_initialized;
int pushdown_init_rc;
// MCOL-4525 Store the original TABLE_LIST::outer_join value in a hash map.

View File

@ -21,692 +21,488 @@
#include "ha_mcs_sysvars.h"
#include "mcsconfig.h"
const char* mcs_compression_type_names[] = {
"SNAPPY", // 0
"SNAPPY", // 1
"SNAPPY", // 2
const char* mcs_compression_type_names[] = {"SNAPPY", // 0
"SNAPPY", // 1
"SNAPPY", // 2
#ifdef HAVE_LZ4
"LZ4", // 3
"LZ4", // 3
#endif
NullS
};
NullS};
static TYPELIB mcs_compression_type_names_lib = {
array_elements(mcs_compression_type_names) - 1,
"mcs_compression_type_names",
mcs_compression_type_names,
NULL
};
static TYPELIB mcs_compression_type_names_lib = {array_elements(mcs_compression_type_names) - 1,
"mcs_compression_type_names", mcs_compression_type_names,
NULL};
// compression type
static MYSQL_THDVAR_ENUM(
compression_type,
PLUGIN_VAR_RQCMDARG,
"Controls compression algorithm for create tables. Possible values are: "
"SNAPPY segment files are Snappy compressed (default);"
static MYSQL_THDVAR_ENUM(compression_type, PLUGIN_VAR_RQCMDARG,
"Controls compression algorithm for create tables. Possible values are: "
"SNAPPY segment files are Snappy compressed (default);"
#ifdef HAVE_LZ4
"LZ4 segment files are LZ4 compressed;",
"LZ4 segment files are LZ4 compressed;",
#endif
NULL, // check
NULL, // update
1, //default
&mcs_compression_type_names_lib); // values lib
NULL, // check
NULL, // update
1, // default
&mcs_compression_type_names_lib); // values lib
// fe_conn_info pointer
static MYSQL_THDVAR_ULONGLONG(
fe_conn_info_ptr,
PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT,
"FrontEnd connection structure pointer. For internal usage.",
NULL,
NULL,
0,
0,
~0U,
1
);
static MYSQL_THDVAR_ULONGLONG(fe_conn_info_ptr, PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT,
"FrontEnd connection structure pointer. For internal usage.", NULL, NULL, 0, 0,
~0U, 1);
// optimizer flags vault
static MYSQL_THDVAR_ULONGLONG(
original_optimizer_flags,
PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT,
"Vault for original optimizer flags. For internal usage.",
NULL,
NULL,
0,
0,
~0U,
1
static MYSQL_THDVAR_ULONGLONG(original_optimizer_flags, PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT,
"Vault for original optimizer flags. For internal usage.", NULL, NULL, 0, 0,
~0U, 1);
static MYSQL_THDVAR_ULONGLONG(original_option_bits, PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT,
"Storage for thd->variables.option_bits. For internal usage.", NULL, NULL, 0, 0,
~0U, 1);
const char* mcs_select_handler_mode_values[] = {"OFF", "ON", "AUTO", NullS};
static TYPELIB mcs_select_handler_mode_values_lib = {array_elements(mcs_select_handler_mode_values) - 1,
"mcs_select_handler_mode_values",
mcs_select_handler_mode_values, NULL};
static MYSQL_THDVAR_ENUM(select_handler, PLUGIN_VAR_RQCMDARG,
"Set the MCS select_handler to Disabled, Enabled, or Automatic",
NULL, // check
NULL, // update
1, // default
&mcs_select_handler_mode_values_lib // values lib
);
static MYSQL_THDVAR_ULONGLONG(
original_option_bits,
PLUGIN_VAR_NOSYSVAR | PLUGIN_VAR_NOCMDOPT,
"Storage for thd->variables.option_bits. For internal usage.",
NULL,
NULL,
0,
0,
~0U,
1
);
static MYSQL_THDVAR_BOOL(derived_handler, PLUGIN_VAR_NOCMDARG, "Enable/Disable the MCS derived_handler", NULL,
NULL, 1);
const char* mcs_select_handler_mode_values[] = {
"OFF",
"ON",
"AUTO",
NullS
};
static MYSQL_THDVAR_BOOL(group_by_handler, PLUGIN_VAR_NOCMDARG, "Enable/Disable the MCS group_by_handler",
NULL, NULL, 1);
static TYPELIB mcs_select_handler_mode_values_lib = {
array_elements(mcs_select_handler_mode_values) - 1,
"mcs_select_handler_mode_values",
mcs_select_handler_mode_values,
NULL
};
static MYSQL_THDVAR_BOOL(select_handler_in_stored_procedures, PLUGIN_VAR_NOCMDARG,
"Enable/Disable the MCS select_handler for Stored Procedures", NULL, NULL, 1);
static MYSQL_THDVAR_ENUM(
select_handler,
PLUGIN_VAR_RQCMDARG,
"Set the MCS select_handler to Disabled, Enabled, or Automatic",
NULL, // check
NULL, // update
1, // default
&mcs_select_handler_mode_values_lib // values lib
);
static MYSQL_THDVAR_BOOL(
derived_handler,
PLUGIN_VAR_NOCMDARG,
"Enable/Disable the MCS derived_handler",
NULL,
NULL,
1
);
static MYSQL_THDVAR_BOOL(
group_by_handler,
PLUGIN_VAR_NOCMDARG,
"Enable/Disable the MCS group_by_handler",
NULL,
NULL,
1
);
static MYSQL_THDVAR_BOOL(
select_handler_in_stored_procedures,
PLUGIN_VAR_NOCMDARG,
"Enable/Disable the MCS select_handler for Stored Procedures",
NULL,
NULL,
1
);
static MYSQL_THDVAR_UINT(
orderby_threads,
PLUGIN_VAR_RQCMDARG,
"Number of parallel threads used by ORDER BY. (default to 16)",
NULL,
NULL,
16,
0,
2048,
1
);
static MYSQL_THDVAR_UINT(orderby_threads, PLUGIN_VAR_RQCMDARG,
"Number of parallel threads used by ORDER BY. (default to 16)", NULL, NULL, 16, 0,
2048, 1);
// legacy system variables
static MYSQL_THDVAR_ULONG(
decimal_scale,
PLUGIN_VAR_RQCMDARG,
"The default decimal precision for calculated column sub-operations ",
NULL,
NULL,
8,
0,
18,
1
);
static MYSQL_THDVAR_ULONG(decimal_scale, PLUGIN_VAR_RQCMDARG,
"The default decimal precision for calculated column sub-operations ", NULL, NULL,
8, 0, 18, 1);
static MYSQL_THDVAR_BOOL(varbin_always_hex, PLUGIN_VAR_NOCMDARG,
"Always display/process varbinary columns as if they have been hexified.", NULL,
NULL, 0);
static MYSQL_THDVAR_BOOL(use_decimal_scale, PLUGIN_VAR_NOCMDARG,
"Enable/disable the MCS decimal scale to be used internally", NULL, NULL, 0);
static MYSQL_THDVAR_BOOL(
varbin_always_hex,
PLUGIN_VAR_NOCMDARG,
"Always display/process varbinary columns as if they have been hexified.",
NULL,
NULL,
0
double_for_decimal_math, PLUGIN_VAR_NOCMDARG,
"Enable/disable for ColumnStore to replace DECIMAL with DOUBLE in arithmetic operation.", NULL, NULL, 0);
static MYSQL_THDVAR_BOOL(decimal_overflow_check, PLUGIN_VAR_NOCMDARG,
"Enable/disable for ColumnStore to check for overflow in arithmetic operation.",
NULL, NULL, 0);
static MYSQL_THDVAR_BOOL(ordered_only, PLUGIN_VAR_NOCMDARG,
"Always use the first table in the from clause as the large side "
"table for joins",
NULL, NULL, 0);
static MYSQL_THDVAR_ULONG(string_scan_threshold, PLUGIN_VAR_RQCMDARG,
"Max number of blocks in a dictionary file to be scanned for filtering", NULL, NULL,
10, 1, ~0U, 1);
static MYSQL_THDVAR_ULONG(stringtable_threshold, PLUGIN_VAR_RQCMDARG,
"The minimum width of a string column to be stored in a string table", NULL, NULL,
20, 9, ~0U, 1);
static MYSQL_THDVAR_ULONG(diskjoin_smallsidelimit, PLUGIN_VAR_RQCMDARG,
"The maximum amount of disk space in MB to use per query for storing "
"'small side' tables for a disk-based join. (0 = unlimited)",
NULL, NULL, 0, 0, ~0U, 1);
static MYSQL_THDVAR_ULONG(diskjoin_largesidelimit, PLUGIN_VAR_RQCMDARG,
"The maximum amount of disk space in MB to use per join for storing "
"'large side' table data for a disk-based join. (0 = unlimited)",
NULL, NULL, 0, 0, ~0U, 1);
static MYSQL_THDVAR_ULONG(diskjoin_bucketsize, PLUGIN_VAR_RQCMDARG,
"The maximum size in MB of each 'small side' table in memory.", NULL, NULL, 100, 1,
~0U, 1);
static MYSQL_THDVAR_ULONG(um_mem_limit, PLUGIN_VAR_RQCMDARG,
"Per user Memory limit(MB). Switch to disk-based JOIN when limit is reached", NULL,
NULL, 0, 0, ~0U, 1);
static MYSQL_THDVAR_ULONG(local_query, PLUGIN_VAR_RQCMDARG,
"Enable/disable the ColumnStore local PM query only feature.", NULL, NULL, 0, 0, 2,
1);
static MYSQL_THDVAR_ULONG(import_for_batchinsert_delimiter, PLUGIN_VAR_RQCMDARG,
"ASCII value of the delimiter used by LDI and INSERT..SELECT",
NULL, // check
NULL, // update
7, // default
0, // min
127, // max
1 // block size
);
static MYSQL_THDVAR_BOOL(
use_decimal_scale,
PLUGIN_VAR_NOCMDARG,
"Enable/disable the MCS decimal scale to be used internally",
NULL,
NULL,
0
static MYSQL_THDVAR_ULONG(import_for_batchinsert_enclosed_by, PLUGIN_VAR_RQCMDARG,
"ASCII value of the quote symbol used by batch data ingestion",
NULL, // check
NULL, // update
17, // default
17, // min
127, // max
1 // block size
);
static MYSQL_THDVAR_BOOL(
double_for_decimal_math,
PLUGIN_VAR_NOCMDARG,
"Enable/disable for ColumnStore to replace DECIMAL with DOUBLE in arithmetic operation.",
NULL,
NULL,
0
);
static MYSQL_THDVAR_BOOL(
decimal_overflow_check,
PLUGIN_VAR_NOCMDARG,
"Enable/disable for ColumnStore to check for overflow in arithmetic operation.",
NULL,
NULL,
0
);
static MYSQL_THDVAR_BOOL(
ordered_only,
PLUGIN_VAR_NOCMDARG,
"Always use the first table in the from clause as the large side "
"table for joins",
NULL,
NULL,
0
);
static MYSQL_THDVAR_ULONG(
string_scan_threshold,
PLUGIN_VAR_RQCMDARG,
"Max number of blocks in a dictionary file to be scanned for filtering",
NULL,
NULL,
10,
1,
~0U,
1
);
static MYSQL_THDVAR_ULONG(
stringtable_threshold,
PLUGIN_VAR_RQCMDARG,
"The minimum width of a string column to be stored in a string table",
NULL,
NULL,
20,
9,
~0U,
1
);
static MYSQL_THDVAR_ULONG(
diskjoin_smallsidelimit,
PLUGIN_VAR_RQCMDARG,
"The maximum amount of disk space in MB to use per query for storing "
"'small side' tables for a disk-based join. (0 = unlimited)",
NULL,
NULL,
0,
0,
~0U,
1
);
static MYSQL_THDVAR_ULONG(
diskjoin_largesidelimit,
PLUGIN_VAR_RQCMDARG,
"The maximum amount of disk space in MB to use per join for storing "
"'large side' table data for a disk-based join. (0 = unlimited)",
NULL,
NULL,
0,
0,
~0U,
1
);
static MYSQL_THDVAR_ULONG(
diskjoin_bucketsize,
PLUGIN_VAR_RQCMDARG,
"The maximum size in MB of each 'small side' table in memory.",
NULL,
NULL,
100,
1,
~0U,
1
);
static MYSQL_THDVAR_ULONG(
um_mem_limit,
PLUGIN_VAR_RQCMDARG,
"Per user Memory limit(MB). Switch to disk-based JOIN when limit is reached",
NULL,
NULL,
0,
0,
~0U,
1
);
static MYSQL_THDVAR_ULONG(
local_query,
PLUGIN_VAR_RQCMDARG,
"Enable/disable the ColumnStore local PM query only feature.",
NULL,
NULL,
0,
0,
2,
1
);
static MYSQL_THDVAR_ULONG(
import_for_batchinsert_delimiter,
PLUGIN_VAR_RQCMDARG,
"ASCII value of the delimiter used by LDI and INSERT..SELECT",
NULL, // check
NULL, // update
7, // default
0, // min
127, // max
1 // block size
);
static MYSQL_THDVAR_ULONG(
import_for_batchinsert_enclosed_by,
PLUGIN_VAR_RQCMDARG,
"ASCII value of the quote symbol used by batch data ingestion",
NULL, // check
NULL, // update
17, // default
17, // min
127, // max
1 // block size
);
const char* mcs_use_import_for_batchinsert_mode_values[] = {
"OFF",
"ON",
"ALWAYS",
NullS
};
const char* mcs_use_import_for_batchinsert_mode_values[] = {"OFF", "ON", "ALWAYS", NullS};
static TYPELIB mcs_use_import_for_batchinsert_mode_values_lib = {
array_elements(mcs_use_import_for_batchinsert_mode_values) - 1,
"mcs_use_import_for_batchinsert_mode_values",
mcs_use_import_for_batchinsert_mode_values,
NULL
};
"mcs_use_import_for_batchinsert_mode_values", mcs_use_import_for_batchinsert_mode_values, NULL};
static MYSQL_THDVAR_ENUM(
use_import_for_batchinsert,
PLUGIN_VAR_RQCMDARG,
"LOAD DATA INFILE and INSERT..SELECT will use cpimport internally",
NULL, // check
NULL, // update
1, // default
&mcs_use_import_for_batchinsert_mode_values_lib // values lib
static MYSQL_THDVAR_ENUM(use_import_for_batchinsert, PLUGIN_VAR_RQCMDARG,
"LOAD DATA INFILE and INSERT..SELECT will use cpimport internally",
NULL, // check
NULL, // update
1, // default
&mcs_use_import_for_batchinsert_mode_values_lib // values lib
);
static MYSQL_THDVAR_BOOL(
replication_slave,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Allow this MariaDB server to apply replication changes to ColumnStore",
NULL,
NULL,
0
);
static MYSQL_THDVAR_BOOL(replication_slave, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Allow this MariaDB server to apply replication changes to ColumnStore", NULL, NULL,
0);
static MYSQL_THDVAR_BOOL(
cache_inserts,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Perform cache-based inserts to ColumnStore",
NULL,
NULL,
0
);
static MYSQL_THDVAR_BOOL(cache_inserts, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Perform cache-based inserts to ColumnStore", NULL, NULL, 0);
static MYSQL_THDVAR_BOOL(
cache_use_import,
PLUGIN_VAR_RQCMDARG,
"Use cpimport for the cache flush into ColumnStore",
NULL,
NULL,
0
);
static MYSQL_THDVAR_BOOL(cache_use_import, PLUGIN_VAR_RQCMDARG,
"Use cpimport for the cache flush into ColumnStore", NULL, NULL, 0);
static MYSQL_THDVAR_ULONGLONG(
cache_flush_threshold,
PLUGIN_VAR_RQCMDARG,
"Threshold on the number of rows in the cache to trigger a flush",
NULL,
NULL,
500000,
1,
1000000000,
1
);
static MYSQL_THDVAR_ULONGLONG(cache_flush_threshold, PLUGIN_VAR_RQCMDARG,
"Threshold on the number of rows in the cache to trigger a flush", NULL, NULL,
500000, 1, 1000000000, 1);
st_mysql_sys_var* mcs_system_variables[] =
{
MYSQL_SYSVAR(compression_type),
MYSQL_SYSVAR(fe_conn_info_ptr),
MYSQL_SYSVAR(original_optimizer_flags),
MYSQL_SYSVAR(original_option_bits),
MYSQL_SYSVAR(select_handler),
MYSQL_SYSVAR(derived_handler),
MYSQL_SYSVAR(group_by_handler),
MYSQL_SYSVAR(select_handler_in_stored_procedures),
MYSQL_SYSVAR(orderby_threads),
MYSQL_SYSVAR(decimal_scale),
MYSQL_SYSVAR(use_decimal_scale),
MYSQL_SYSVAR(ordered_only),
MYSQL_SYSVAR(string_scan_threshold),
MYSQL_SYSVAR(stringtable_threshold),
MYSQL_SYSVAR(diskjoin_smallsidelimit),
MYSQL_SYSVAR(diskjoin_largesidelimit),
MYSQL_SYSVAR(diskjoin_bucketsize),
MYSQL_SYSVAR(um_mem_limit),
MYSQL_SYSVAR(double_for_decimal_math),
MYSQL_SYSVAR(decimal_overflow_check),
MYSQL_SYSVAR(local_query),
MYSQL_SYSVAR(use_import_for_batchinsert),
MYSQL_SYSVAR(import_for_batchinsert_delimiter),
MYSQL_SYSVAR(import_for_batchinsert_enclosed_by),
MYSQL_SYSVAR(varbin_always_hex),
MYSQL_SYSVAR(replication_slave),
MYSQL_SYSVAR(cache_inserts),
MYSQL_SYSVAR(cache_use_import),
MYSQL_SYSVAR(cache_flush_threshold),
NULL
};
st_mysql_sys_var* mcs_system_variables[] = {MYSQL_SYSVAR(compression_type),
MYSQL_SYSVAR(fe_conn_info_ptr),
MYSQL_SYSVAR(original_optimizer_flags),
MYSQL_SYSVAR(original_option_bits),
MYSQL_SYSVAR(select_handler),
MYSQL_SYSVAR(derived_handler),
MYSQL_SYSVAR(group_by_handler),
MYSQL_SYSVAR(select_handler_in_stored_procedures),
MYSQL_SYSVAR(orderby_threads),
MYSQL_SYSVAR(decimal_scale),
MYSQL_SYSVAR(use_decimal_scale),
MYSQL_SYSVAR(ordered_only),
MYSQL_SYSVAR(string_scan_threshold),
MYSQL_SYSVAR(stringtable_threshold),
MYSQL_SYSVAR(diskjoin_smallsidelimit),
MYSQL_SYSVAR(diskjoin_largesidelimit),
MYSQL_SYSVAR(diskjoin_bucketsize),
MYSQL_SYSVAR(um_mem_limit),
MYSQL_SYSVAR(double_for_decimal_math),
MYSQL_SYSVAR(decimal_overflow_check),
MYSQL_SYSVAR(local_query),
MYSQL_SYSVAR(use_import_for_batchinsert),
MYSQL_SYSVAR(import_for_batchinsert_delimiter),
MYSQL_SYSVAR(import_for_batchinsert_enclosed_by),
MYSQL_SYSVAR(varbin_always_hex),
MYSQL_SYSVAR(replication_slave),
MYSQL_SYSVAR(cache_inserts),
MYSQL_SYSVAR(cache_use_import),
MYSQL_SYSVAR(cache_flush_threshold),
NULL};
st_mysql_show_var mcs_status_variables[] =
{
{"columnstore_version", (char*)&cs_version, SHOW_CHAR},
{"columnstore_commit_hash", (char*)&cs_commit_hash, SHOW_CHAR},
{0, 0, (enum_mysql_show_type)0}
};
st_mysql_show_var mcs_status_variables[] = {{"columnstore_version", (char*)&cs_version, SHOW_CHAR},
{"columnstore_commit_hash", (char*)&cs_commit_hash, SHOW_CHAR},
{0, 0, (enum_mysql_show_type)0}};
void* get_fe_conn_info_ptr(THD* thd)
{
return ( current_thd == NULL && thd == NULL ) ? NULL :
(void*)THDVAR(current_thd, fe_conn_info_ptr);
return (current_thd == NULL && thd == NULL) ? NULL : (void*)THDVAR(current_thd, fe_conn_info_ptr);
}
void set_fe_conn_info_ptr(void* ptr, THD* thd)
{
if ( current_thd == NULL && thd == NULL)
{
return;
}
if (current_thd == NULL && thd == NULL)
{
return;
}
THDVAR(current_thd, fe_conn_info_ptr) = (uint64_t)(ptr);
THDVAR(current_thd, fe_conn_info_ptr) = (uint64_t)(ptr);
}
ulonglong get_original_optimizer_flags(THD* thd)
{
return THDVAR(current_thd, original_optimizer_flags);
return THDVAR(current_thd, original_optimizer_flags);
}
void set_original_optimizer_flags(ulonglong ptr, THD* thd)
{
if ( current_thd == NULL && thd == NULL)
{
return;
}
if (current_thd == NULL && thd == NULL)
{
return;
}
THDVAR(current_thd, original_optimizer_flags) = (uint64_t)(ptr);
THDVAR(current_thd, original_optimizer_flags) = (uint64_t)(ptr);
}
ulonglong get_original_option_bits(THD* thd)
{
return (thd == NULL) ? 0 : THDVAR(thd, original_option_bits);
return (thd == NULL) ? 0 : THDVAR(thd, original_option_bits);
}
void set_original_option_bits(ulonglong value, THD* thd)
{
if (thd == NULL)
{
return;
}
if (thd == NULL)
{
return;
}
THDVAR(thd, original_option_bits) = (uint64_t)(value);
THDVAR(thd, original_option_bits) = (uint64_t)(value);
}
mcs_select_handler_mode_t get_select_handler_mode(THD* thd)
{
return ( thd == NULL ) ? mcs_select_handler_mode_t::ON :
(mcs_select_handler_mode_t) THDVAR(thd, select_handler);
return (thd == NULL) ? mcs_select_handler_mode_t::ON
: (mcs_select_handler_mode_t)THDVAR(thd, select_handler);
}
void set_select_handler_mode(THD* thd, ulong value)
{
THDVAR(thd, select_handler) = value;
THDVAR(thd, select_handler) = value;
}
bool get_derived_handler(THD* thd)
{
return ( thd == NULL ) ? false : THDVAR(thd, derived_handler);
return (thd == NULL) ? false : THDVAR(thd, derived_handler);
}
void set_derived_handler(THD* thd, bool value)
{
THDVAR(thd, derived_handler) = value;
THDVAR(thd, derived_handler) = value;
}
bool get_group_by_handler(THD* thd)
{
return ( thd == NULL ) ? false : THDVAR(thd, group_by_handler);
return (thd == NULL) ? false : THDVAR(thd, group_by_handler);
}
void set_group_by_handler(THD* thd, bool value)
{
THDVAR(thd, group_by_handler) = value;
THDVAR(thd, group_by_handler) = value;
}
bool get_select_handler_in_stored_procedures(THD* thd)
{
return ( thd == NULL ) ? true :
THDVAR(thd, select_handler_in_stored_procedures);
return (thd == NULL) ? true : THDVAR(thd, select_handler_in_stored_procedures);
}
void set_select_handler_in_stored_procedures(THD* thd, bool value)
{
THDVAR(thd, select_handler_in_stored_procedures) = value;
THDVAR(thd, select_handler_in_stored_procedures) = value;
}
void set_compression_type(THD* thd, ulong value)
{
THDVAR(thd, compression_type) = value;
THDVAR(thd, compression_type) = value;
}
mcs_compression_type_t get_compression_type(THD* thd) {
return (mcs_compression_type_t) THDVAR(thd, compression_type);
mcs_compression_type_t get_compression_type(THD* thd)
{
return (mcs_compression_type_t)THDVAR(thd, compression_type);
}
uint get_orderby_threads(THD* thd)
{
return ( thd == NULL ) ? 0 : THDVAR(thd, orderby_threads);
return (thd == NULL) ? 0 : THDVAR(thd, orderby_threads);
}
void set_orderby_threads(THD* thd, uint value)
{
THDVAR(thd, orderby_threads) = value;
THDVAR(thd, orderby_threads) = value;
}
bool get_use_decimal_scale(THD* thd)
{
return ( thd == NULL ) ? false : THDVAR(thd, use_decimal_scale);
return (thd == NULL) ? false : THDVAR(thd, use_decimal_scale);
}
void set_use_decimal_scale(THD* thd, bool value)
{
THDVAR(thd, use_decimal_scale) = value;
THDVAR(thd, use_decimal_scale) = value;
}
ulong get_decimal_scale(THD* thd)
{
return ( thd == NULL ) ? 0 : THDVAR(thd, decimal_scale);
return (thd == NULL) ? 0 : THDVAR(thd, decimal_scale);
}
void set_decimal_scale(THD* thd, ulong value)
{
THDVAR(thd, decimal_scale) = value;
THDVAR(thd, decimal_scale) = value;
}
bool get_ordered_only(THD* thd)
{
return ( thd == NULL ) ? false : THDVAR(thd, ordered_only);
return (thd == NULL) ? false : THDVAR(thd, ordered_only);
}
void set_ordered_only(THD* thd, bool value)
{
THDVAR(thd, ordered_only) = value;
THDVAR(thd, ordered_only) = value;
}
ulong get_string_scan_threshold(THD* thd)
{
return ( thd == NULL ) ? 0 : THDVAR(thd, string_scan_threshold);
return (thd == NULL) ? 0 : THDVAR(thd, string_scan_threshold);
}
void set_string_scan_threshold(THD* thd, ulong value)
{
THDVAR(thd, string_scan_threshold) = value;
THDVAR(thd, string_scan_threshold) = value;
}
ulong get_stringtable_threshold(THD* thd)
{
return ( thd == NULL ) ? 0 : THDVAR(thd, stringtable_threshold);
return (thd == NULL) ? 0 : THDVAR(thd, stringtable_threshold);
}
void set_stringtable_threshold(THD* thd, ulong value)
{
THDVAR(thd, stringtable_threshold) = value;
THDVAR(thd, stringtable_threshold) = value;
}
ulong get_diskjoin_smallsidelimit(THD* thd)
{
return ( thd == NULL ) ? 0 : THDVAR(thd, diskjoin_smallsidelimit);
return (thd == NULL) ? 0 : THDVAR(thd, diskjoin_smallsidelimit);
}
void set_diskjoin_smallsidelimit(THD* thd, ulong value)
{
THDVAR(thd, diskjoin_smallsidelimit) = value;
THDVAR(thd, diskjoin_smallsidelimit) = value;
}
ulong get_diskjoin_largesidelimit(THD* thd)
{
return ( thd == NULL ) ? 0 : THDVAR(thd, diskjoin_largesidelimit);
return (thd == NULL) ? 0 : THDVAR(thd, diskjoin_largesidelimit);
}
void set_diskjoin_largesidelimit(THD* thd, ulong value)
{
THDVAR(thd, diskjoin_largesidelimit) = value;
THDVAR(thd, diskjoin_largesidelimit) = value;
}
ulong get_diskjoin_bucketsize(THD* thd)
{
return ( thd == NULL ) ? 0 : THDVAR(thd, diskjoin_bucketsize);
return (thd == NULL) ? 0 : THDVAR(thd, diskjoin_bucketsize);
}
void set_diskjoin_bucketsize(THD* thd, ulong value)
{
THDVAR(thd, diskjoin_bucketsize) = value;
THDVAR(thd, diskjoin_bucketsize) = value;
}
ulong get_um_mem_limit(THD* thd)
{
return ( thd == NULL ) ? 0 : THDVAR(thd, um_mem_limit);
return (thd == NULL) ? 0 : THDVAR(thd, um_mem_limit);
}
void set_um_mem_limit(THD* thd, ulong value)
{
THDVAR(thd, um_mem_limit) = value;
THDVAR(thd, um_mem_limit) = value;
}
bool get_varbin_always_hex(THD* thd)
{
return ( thd == NULL ) ? false : THDVAR(thd, varbin_always_hex);
return (thd == NULL) ? false : THDVAR(thd, varbin_always_hex);
}
void set_varbin_always_hex(THD* thd, bool value)
{
THDVAR(thd, varbin_always_hex) = value;
THDVAR(thd, varbin_always_hex) = value;
}
bool get_double_for_decimal_math(THD* thd)
{
return ( thd == NULL ) ? false : THDVAR(thd, double_for_decimal_math);
return (thd == NULL) ? false : THDVAR(thd, double_for_decimal_math);
}
void set_double_for_decimal_math(THD* thd, bool value)
{
THDVAR(thd, double_for_decimal_math) = value;
THDVAR(thd, double_for_decimal_math) = value;
}
bool get_decimal_overflow_check(THD* thd)
{
return ( thd == NULL ) ? false : THDVAR(thd, decimal_overflow_check);
return (thd == NULL) ? false : THDVAR(thd, decimal_overflow_check);
}
void set_decimal_overflow_check(THD* thd, bool value)
{
THDVAR(thd, decimal_overflow_check) = value;
THDVAR(thd, decimal_overflow_check) = value;
}
ulong get_local_query(THD* thd)
{
return ( thd == NULL ) ? 0 : THDVAR(thd, local_query);
return (thd == NULL) ? 0 : THDVAR(thd, local_query);
}
void set_local_query(THD* thd, ulong value)
{
THDVAR(thd, local_query) = value;
THDVAR(thd, local_query) = value;
}
mcs_use_import_for_batchinsert_mode_t get_use_import_for_batchinsert_mode(THD* thd)
{
return ( thd == NULL ) ? mcs_use_import_for_batchinsert_mode_t::ON :
(mcs_use_import_for_batchinsert_mode_t) THDVAR(thd, use_import_for_batchinsert);
return (thd == NULL) ? mcs_use_import_for_batchinsert_mode_t::ON
: (mcs_use_import_for_batchinsert_mode_t)THDVAR(thd, use_import_for_batchinsert);
}
void set_use_import_for_batchinsert_mode(THD* thd, ulong value)
{
THDVAR(thd, use_import_for_batchinsert) = value;
THDVAR(thd, use_import_for_batchinsert) = value;
}
ulong get_import_for_batchinsert_delimiter(THD* thd)
{
return ( thd == NULL ) ? 0 : THDVAR(thd, import_for_batchinsert_delimiter);
return (thd == NULL) ? 0 : THDVAR(thd, import_for_batchinsert_delimiter);
}
void set_import_for_batchinsert_delimiter(THD* thd, ulong value)
{
THDVAR(thd, import_for_batchinsert_delimiter) = value;
THDVAR(thd, import_for_batchinsert_delimiter) = value;
}
ulong get_import_for_batchinsert_enclosed_by(THD* thd)
{
return ( thd == NULL ) ? 0 : THDVAR(thd, import_for_batchinsert_enclosed_by);
return (thd == NULL) ? 0 : THDVAR(thd, import_for_batchinsert_enclosed_by);
}
void set_import_for_batchinsert_enclosed_by(THD* thd, ulong value)
{
THDVAR(thd, import_for_batchinsert_enclosed_by) = value;
THDVAR(thd, import_for_batchinsert_enclosed_by) = value;
}
bool get_replication_slave(THD* thd)
{
return ( thd == NULL ) ? false : THDVAR(thd, replication_slave);
return (thd == NULL) ? false : THDVAR(thd, replication_slave);
}
void set_replication_slave(THD* thd, bool value)
{
THDVAR(thd, replication_slave) = value;
THDVAR(thd, replication_slave) = value;
}
bool get_cache_inserts(THD* thd)
{
return ( thd == NULL ) ? false : THDVAR(thd, cache_inserts);
return (thd == NULL) ? false : THDVAR(thd, cache_inserts);
}
void set_cache_inserts(THD* thd, bool value)
{
THDVAR(thd, cache_inserts) = value;
THDVAR(thd, cache_inserts) = value;
}
bool get_cache_use_import(THD* thd)
{
return ( thd == NULL ) ? false : THDVAR(thd, cache_use_import);
return (thd == NULL) ? false : THDVAR(thd, cache_use_import);
}
void set_cache_use_import(THD* thd, bool value)
{
THDVAR(thd, cache_use_import) = value;
THDVAR(thd, cache_use_import) = value;
}
ulonglong get_cache_flush_threshold(THD* thd)
{
return ( thd == NULL ) ? 500000 : THDVAR(thd, cache_flush_threshold);
return (thd == NULL) ? 500000 : THDVAR(thd, cache_flush_threshold);
}
void set_cache_flush_threshold(THD* thd, ulonglong value)
{
THDVAR(thd, cache_flush_threshold) = value;
THDVAR(thd, cache_flush_threshold) = value;
}

View File

@ -29,26 +29,29 @@ extern char cs_version[];
extern char cs_commit_hash[];
// compression_type
enum mcs_compression_type_t {
NO_COMPRESSION = 0,
SNAPPY = 2,
enum mcs_compression_type_t
{
NO_COMPRESSION = 0,
SNAPPY = 2,
#ifdef HAVE_LZ4
LZ4 = 3
LZ4 = 3
#endif
};
// use_import_for_batchinsert mode
enum class mcs_use_import_for_batchinsert_mode_t {
OFF = 0,
ON = 1,
ALWAYS = 2
enum class mcs_use_import_for_batchinsert_mode_t
{
OFF = 0,
ON = 1,
ALWAYS = 2
};
// select_handler mode
enum class mcs_select_handler_mode_t {
OFF = 0,
ON = 1,
AUTO = 2
enum class mcs_select_handler_mode_t
{
OFF = 0,
ON = 1,
AUTO = 2
};
// simple setters/getters

View File

@ -34,197 +34,194 @@ using namespace std;
extern "C"
{
// Connector function stub -- CPFUNC1
long long cpfunc1(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
// Connector function stub -- CPFUNC1
long long cpfunc1(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
my_bool cpfunc1_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
return 0;
strcpy(message, "CALFUNC1() requires one COLUMN argument");
return 1;
}
my_bool cpfunc1_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC1() requires one COLUMN argument");
return 1;
}
return 0;
}
return 0;
void cpfunc1_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC2
long long cpfunc2(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc2_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC2() requires one COLUMN argument");
return 1;
}
void cpfunc1_deinit(UDF_INIT* initid)
return 0;
}
void cpfunc2_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC3
long long cpfunc3(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc3_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC3() requires one COLUMN argument");
return 1;
}
// Connector function stub -- CPFUNC2
long long cpfunc2(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
return 0;
}
void cpfunc3_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC4
long long cpfunc4(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc4_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
return 0;
strcpy(message, "CALFUNC4() requires one COLUMN argument");
return 1;
}
my_bool cpfunc2_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC2() requires one COLUMN argument");
return 1;
}
return 0;
}
return 0;
void cpfunc4_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC5
long long cpfunc5(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc5_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC5() requires one COLUMN argument");
return 1;
}
void cpfunc2_deinit(UDF_INIT* initid)
return 0;
}
void cpfunc5_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC6
long long cpfunc6(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc6_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC6() requires one COLUMN argument");
return 1;
}
// Connector function stub -- CPFUNC3
long long cpfunc3(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
return 0;
}
void cpfunc6_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC7
long long cpfunc7(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc7_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
return 0;
strcpy(message, "CALFUNC7() requires one COLUMN argument");
return 1;
}
my_bool cpfunc3_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC3() requires one COLUMN argument");
return 1;
}
return 0;
}
return 0;
void cpfunc7_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC8
long long cpfunc8(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc8_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC8() requires one COLUMN argument");
return 1;
}
void cpfunc3_deinit(UDF_INIT* initid)
return 0;
}
void cpfunc8_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC9
long long cpfunc9(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc9_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC9() requires one COLUMN argument");
return 1;
}
// Connector function stub -- CPFUNC4
long long cpfunc4(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc4_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC4() requires one COLUMN argument");
return 1;
}
return 0;
}
void cpfunc4_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC5
long long cpfunc5(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc5_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC5() requires one COLUMN argument");
return 1;
}
return 0;
}
void cpfunc5_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC6
long long cpfunc6(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc6_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC6() requires one COLUMN argument");
return 1;
}
return 0;
}
void cpfunc6_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC7
long long cpfunc7(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc7_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC7() requires one COLUMN argument");
return 1;
}
return 0;
}
void cpfunc7_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC8
long long cpfunc8(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc8_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC8() requires one COLUMN argument");
return 1;
}
return 0;
}
void cpfunc8_deinit(UDF_INIT* initid)
{
}
// Connector function stub -- CPFUNC9
long long cpfunc9(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
return 0;
}
my_bool cpfunc9_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "CALFUNC9() requires one COLUMN argument");
return 1;
}
return 0;
}
void cpfunc9_deinit(UDF_INIT* initid)
{
}
return 0;
}
void cpfunc9_deinit(UDF_INIT* initid)
{
}
}
// vim:sw=4 ts=4:

View File

@ -26,7 +26,6 @@ using namespace cal_impl_if;
namespace
{
/*******************************************************************************
* Pseudo column connector interface
*
@ -46,548 +45,538 @@ namespace
void bailout(char* error, const string& funcName)
{
string errMsg = IDBErrorInfo::instance()->errorMsg(ERR_PSEUDOCOL_IDB_ONLY, funcName);
current_thd->get_stmt_da()->set_overwrite_status(true);
current_thd->raise_error_printf(ER_INTERNAL_ERROR, errMsg.c_str());
*error = 1;
string errMsg = IDBErrorInfo::instance()->errorMsg(ERR_PSEUDOCOL_IDB_ONLY, funcName);
current_thd->get_stmt_da()->set_overwrite_status(true);
current_thd->raise_error_printf(ER_INTERNAL_ERROR, errMsg.c_str());
*error = 1;
}
int64_t idblocalpm()
{
if (get_fe_conn_info_ptr() == NULL)
set_fe_conn_info_ptr((void*)new cal_connection_info());
if (get_fe_conn_info_ptr() == NULL)
set_fe_conn_info_ptr((void*)new cal_connection_info());
cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
if (ci->localPm == -1)
{
string module = ClientRotator::getModule();
if (ci->localPm == -1)
{
string module = ClientRotator::getModule();
if (module.size() >= 3 && (module[0] == 'p' || module[0] == 'P'))
ci->localPm = atol(module.c_str() + 2);
else
ci->localPm = 0;
}
if (module.size() >= 3 && (module[0] == 'p' || module[0] == 'P'))
ci->localPm = atol(module.c_str() + 2);
else
ci->localPm = 0;
}
return ci->localPm;
return ci->localPm;
}
extern "C"
{
/**
* IDBDBROOT
*/
/**
* IDBDBROOT
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbdbroot_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
my_bool idbdbroot_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
if (args->arg_count != 1)
{
strcpy(message, "idbdbroot() requires one argument");
return 1;
}
return 0;
strcpy(message, "idbdbroot() requires one argument");
return 1;
}
#ifdef _MSC_VER
__declspec(dllexport)
#endif
void idbdbroot_deinit(UDF_INIT* initid)
{
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbdbroot(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbdbroot");
return 0;
}
/**
* IDBPM
*/
void idbdbroot_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbpm_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbpm() requires one argument");
return 1;
}
long long idbdbroot(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbdbroot");
return 0;
}
return 0;
}
/**
* IDBPM
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbpm_deinit(UDF_INIT* initid)
my_bool idbpm_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbpm() requires one argument");
return 1;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbpm(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbpm");
return 0;
}
/**
* IDBEXTENTRELATIVERID
*/
void idbpm_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbextentrelativerid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbextentrelativerid() requires one argument");
return 1;
}
long long idbpm(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbpm");
return 0;
}
return 0;
}
/**
* IDBEXTENTRELATIVERID
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbextentrelativerid_deinit(UDF_INIT* initid)
my_bool idbextentrelativerid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbextentrelativerid() requires one argument");
return 1;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbextentrelativerid(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbextentrelativerid");
return 0;
}
/**
* IDBBLOCKID
*/
void idbextentrelativerid_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbblockid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbblockid() requires one argument");
return 1;
}
long long idbextentrelativerid(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbextentrelativerid");
return 0;
}
return 0;
}
/**
* IDBBLOCKID
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbblockid_deinit(UDF_INIT* initid)
my_bool idbblockid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbblockid() requires one argument");
return 1;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbblockid(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbblockid");
return 0;
}
/**
* IDBEXTENTID
*/
void idbblockid_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbextentid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbextentid() requires one argument");
return 1;
}
long long idbblockid(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbblockid");
return 0;
}
return 0;
}
/**
* IDBEXTENTID
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbextentid_deinit(UDF_INIT* initid)
my_bool idbextentid_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbextentid() requires one argument");
return 1;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbextentid(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbextentid");
return 0;
}
/**
* IDBSEGMENT
*/
void idbextentid_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbsegment_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbsegment() requires one argument");
return 1;
}
long long idbextentid(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbextentid");
return 0;
}
return 0;
}
/**
* IDBSEGMENT
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbsegment_deinit(UDF_INIT* initid)
my_bool idbsegment_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbsegment() requires one argument");
return 1;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbsegment(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbsegment");
return 0;
}
/**
* IDBSEGMENTDIR
*/
void idbsegment_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbsegmentdir_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbsegmentdir() requires one argument");
return 1;
}
long long idbsegment(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbsegment");
return 0;
}
return 0;
}
/**
* IDBSEGMENTDIR
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbsegmentdir_deinit(UDF_INIT* initid)
my_bool idbsegmentdir_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbsegmentdir() requires one argument");
return 1;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idbsegmentdir(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbsegmentdir");
return 0;
}
/**
* IDBPARTITION
*/
void idbsegmentdir_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbpartition_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbpartition() requires one argument");
return 1;
}
long long idbsegmentdir(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
bailout(error, "idbsegmentdir");
return 0;
}
return 0;
}
/**
* IDBPARTITION
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbpartition_deinit(UDF_INIT* initid)
my_bool idbpartition_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbpartition() requires one argument");
return 1;
}
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
const char* idbpartition(UDF_INIT* initid, UDF_ARGS* args,
char* result, unsigned long* length,
char* is_null, char* error)
{
bailout(error, "idbpartition");
return result;
}
/**
* IDBEXTENTMIN
*/
void idbpartition_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbextentmin_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbpm() requires one argument");
return 1;
}
const char* idbpartition(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length,
char* is_null, char* error)
{
bailout(error, "idbpartition");
return result;
}
initid->maybe_null = 1;
return 0;
}
/**
* IDBEXTENTMIN
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbextentmin_deinit(UDF_INIT* initid)
my_bool idbextentmin_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbpm() requires one argument");
return 1;
}
initid->maybe_null = 1;
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
const char* idbextentmin(UDF_INIT* initid, UDF_ARGS* args,
char* result, unsigned long* length,
char* is_null, char* error)
{
bailout(error, "idbextentmin");
return result;
}
/**
* IDBEXTENTMAX
*/
void idbextentmin_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idbextentmax_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbextentmax() requires one argument");
return 1;
}
const char* idbextentmin(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length,
char* is_null, char* error)
{
bailout(error, "idbextentmin");
return result;
}
initid->maybe_null = 1;
return 0;
}
/**
* IDBEXTENTMAX
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idbextentmax_deinit(UDF_INIT* initid)
my_bool idbextentmax_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 1)
{
strcpy(message, "idbextentmax() requires one argument");
return 1;
}
initid->maybe_null = 1;
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
const char* idbextentmax(UDF_INIT* initid, UDF_ARGS* args,
char* result, unsigned long* length,
char* is_null, char* error)
{
bailout(error, "idbextentmax");
return result;
}
/**
* IDBLOCALPM
*/
void idbextentmax_deinit(UDF_INIT* initid)
{
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
my_bool idblocalpm_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 0)
{
strcpy(message, "idblocalpm() should take no argument");
return 1;
}
const char* idbextentmax(UDF_INIT* initid, UDF_ARGS* args, char* result, unsigned long* length,
char* is_null, char* error)
{
bailout(error, "idbextentmax");
return result;
}
initid->maybe_null = 1;
return 0;
}
/**
* IDBLOCALPM
*/
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
void idblocalpm_deinit(UDF_INIT* initid)
my_bool idblocalpm_init(UDF_INIT* initid, UDF_ARGS* args, char* message)
{
if (args->arg_count != 0)
{
strcpy(message, "idblocalpm() should take no argument");
return 1;
}
initid->maybe_null = 1;
return 0;
}
#ifdef _MSC_VER
__declspec(dllexport)
__declspec(dllexport)
#endif
long long idblocalpm(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
longlong localpm = idblocalpm();
void idblocalpm_deinit(UDF_INIT* initid)
{
}
if (localpm == 0)
*is_null = 1;
#ifdef _MSC_VER
__declspec(dllexport)
#endif
long long idblocalpm(UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error)
{
longlong localpm = idblocalpm();
return localpm;
}
if (localpm == 0)
*is_null = 1;
return localpm;
}
}
}
} // namespace
namespace cal_impl_if
{
ReturnedColumn* nullOnError(gp_walk_info& gwi, string& funcName)
{
gwi.fatalParseError = true;
gwi.parseErrorText =
logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_PSEUDOCOL_WRONG_ARG, funcName);
return NULL;
gwi.fatalParseError = true;
gwi.parseErrorText =
logging::IDBErrorInfo::instance()->errorMsg(logging::ERR_PSEUDOCOL_WRONG_ARG, funcName);
return NULL;
}
uint32_t isPseudoColumn(string funcName)
{
return execplan::PseudoColumn::pseudoNameToType(funcName);
return execplan::PseudoColumn::pseudoNameToType(funcName);
}
execplan::ReturnedColumn* buildPseudoColumn(Item* item,
gp_walk_info& gwi,
bool& nonSupport,
uint32_t pseudoType)
execplan::ReturnedColumn* buildPseudoColumn(Item* item, gp_walk_info& gwi, bool& nonSupport,
uint32_t pseudoType)
{
if (get_fe_conn_info_ptr() == NULL)
set_fe_conn_info_ptr((void*)new cal_connection_info());
if (get_fe_conn_info_ptr() == NULL)
set_fe_conn_info_ptr((void*)new cal_connection_info());
cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
cal_connection_info* ci = reinterpret_cast<cal_connection_info*>(get_fe_conn_info_ptr());
Item_func* ifp = (Item_func*)item;
Item_func* ifp = (Item_func*)item;
// idblocalpm is replaced by constant
if (pseudoType == PSEUDO_LOCALPM)
{
int64_t localPm = idblocalpm();
ConstantColumn* cc;
// idblocalpm is replaced by constant
if (pseudoType == PSEUDO_LOCALPM)
{
int64_t localPm = idblocalpm();
ConstantColumn* cc;
if (localPm)
cc = new ConstantColumn(localPm);
else
cc = new ConstantColumn("", ConstantColumn::NULLDATA);
cc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
if (localPm)
cc = new ConstantColumn(localPm);
else
cc = new ConstantColumn("", ConstantColumn::NULLDATA);
cc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
cc->alias(ifp->full_name() ? ifp->full_name() : "");
return cc;
}
cc->alias(ifp->full_name() ? ifp->full_name() : "");
return cc;
}
// convert udf item to pseudocolumn item.
// adjust result type
// put arg col to column map
string funcName = ifp->func_name();
// convert udf item to pseudocolumn item.
// adjust result type
// put arg col to column map
string funcName = ifp->func_name();
if (ifp->argument_count() != 1 ||
!(ifp->arguments()) ||
!(ifp->arguments()[0]) ||
ifp->arguments()[0]->type() != Item::FIELD_ITEM)
return nullOnError(gwi, funcName);
if (ifp->argument_count() != 1 || !(ifp->arguments()) || !(ifp->arguments()[0]) ||
ifp->arguments()[0]->type() != Item::FIELD_ITEM)
return nullOnError(gwi, funcName);
Item_field* field = (Item_field*)(ifp->arguments()[0]);
Item_field* field = (Item_field*)(ifp->arguments()[0]);
// @todo rule out derive table
if (!field->field || !field->db_name.str || strlen(field->db_name.str) == 0)
return nullOnError(gwi, funcName);
// @todo rule out derive table
if (!field->field || !field->db_name.str || strlen(field->db_name.str) == 0)
return nullOnError(gwi, funcName);
SimpleColumn* sc = buildSimpleColumn(field, gwi);
SimpleColumn* sc = buildSimpleColumn(field, gwi);
if (!sc)
return nullOnError(gwi, funcName);
if (!sc)
return nullOnError(gwi, funcName);
if ((pseudoType == PSEUDO_EXTENTMIN || pseudoType == PSEUDO_EXTENTMAX) &&
(sc->colType().colDataType == CalpontSystemCatalog::VARBINARY ||
(sc->colType().colDataType == CalpontSystemCatalog::VARCHAR && sc->colType().colWidth > 7) ||
(sc->colType().colDataType == CalpontSystemCatalog::CHAR && sc->colType().colWidth > 8)))
return nullOnError(gwi, funcName);
if ((pseudoType == PSEUDO_EXTENTMIN || pseudoType == PSEUDO_EXTENTMAX) &&
(sc->colType().colDataType == CalpontSystemCatalog::VARBINARY ||
(sc->colType().colDataType == CalpontSystemCatalog::VARCHAR && sc->colType().colWidth > 7) ||
(sc->colType().colDataType == CalpontSystemCatalog::CHAR && sc->colType().colWidth > 8)))
return nullOnError(gwi, funcName);
// put arg col to column map
if (gwi.clauseType == SELECT || gwi.clauseType == GROUP_BY) // select clause
{
SRCP srcp(sc);
gwi.columnMap.insert(CalpontSelectExecutionPlan::ColumnMap::value_type(sc->columnName(), srcp));
gwi.tableMap[make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias(), sc->isColumnStore())] =
make_pair(1, field->cached_table);
}
else if (!gwi.rcWorkStack.empty())
{
gwi.rcWorkStack.pop();
}
// put arg col to column map
if (gwi.clauseType == SELECT || gwi.clauseType == GROUP_BY) // select clause
{
SRCP srcp(sc);
gwi.columnMap.insert(CalpontSelectExecutionPlan::ColumnMap::value_type(sc->columnName(), srcp));
gwi.tableMap[make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias(), sc->isColumnStore())] =
make_pair(1, field->cached_table);
}
else if (!gwi.rcWorkStack.empty())
{
gwi.rcWorkStack.pop();
}
if (pseudoType == PSEUDO_PARTITION)
{
// parms: psueducolumn dbroot, segmentdir, segment
SPTP sptp;
FunctionColumn* fc = new FunctionColumn(funcName);
funcexp::FunctionParm parms;
PseudoColumn* dbroot = new PseudoColumn(*sc, PSEUDO_DBROOT);
sptp.reset(new ParseTree(dbroot));
parms.push_back(sptp);
PseudoColumn* pp = new PseudoColumn(*sc, PSEUDO_SEGMENTDIR);
sptp.reset(new ParseTree(pp));
parms.push_back(sptp);
PseudoColumn* seg = new PseudoColumn(*sc, PSEUDO_SEGMENT);
sptp.reset(new ParseTree(seg));
parms.push_back(sptp);
fc->functionParms(parms);
fc->expressionId(ci->expressionId++);
fc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
if (pseudoType == PSEUDO_PARTITION)
{
// parms: psueducolumn dbroot, segmentdir, segment
SPTP sptp;
FunctionColumn* fc = new FunctionColumn(funcName);
funcexp::FunctionParm parms;
PseudoColumn* dbroot = new PseudoColumn(*sc, PSEUDO_DBROOT);
sptp.reset(new ParseTree(dbroot));
parms.push_back(sptp);
PseudoColumn* pp = new PseudoColumn(*sc, PSEUDO_SEGMENTDIR);
sptp.reset(new ParseTree(pp));
parms.push_back(sptp);
PseudoColumn* seg = new PseudoColumn(*sc, PSEUDO_SEGMENT);
sptp.reset(new ParseTree(seg));
parms.push_back(sptp);
fc->functionParms(parms);
fc->expressionId(ci->expressionId++);
fc->timeZone(gwi.thd->variables.time_zone->get_name()->ptr());
// string result type
CalpontSystemCatalog::ColType ct;
ct.colDataType = CalpontSystemCatalog::VARCHAR;
ct.colWidth = 256;
fc->resultType(ct);
// string result type
CalpontSystemCatalog::ColType ct;
ct.colDataType = CalpontSystemCatalog::VARCHAR;
ct.colWidth = 256;
fc->resultType(ct);
// operation type integer
funcexp::Func_idbpartition* idbpartition = new funcexp::Func_idbpartition();
fc->operationType(idbpartition->operationType(parms, fc->resultType()));
fc->alias(ifp->full_name() ? ifp->full_name() : "");
return fc;
}
// operation type integer
funcexp::Func_idbpartition* idbpartition = new funcexp::Func_idbpartition();
fc->operationType(idbpartition->operationType(parms, fc->resultType()));
fc->alias(ifp->full_name() ? ifp->full_name() : "");
return fc;
}
PseudoColumn* pc = new PseudoColumn(*sc, pseudoType);
PseudoColumn* pc = new PseudoColumn(*sc, pseudoType);
// @bug5892. set alias for derived table column matching.
pc->alias(ifp->name.length ? ifp->name.str : "");
return pc;
// @bug5892. set alias for derived table column matching.
pc->alias(ifp->name.length ? ifp->name.str : "");
return pc;
}
}
} // namespace cal_impl_if
// vim:ts=4 sw=4:

View File

@ -17,10 +17,10 @@
MA 02110-1301, USA. */
/***********************************************************************
* $Id: ha_scalar_sub.cpp 6418 2010-03-29 21:55:08Z zzhu $
*
*
***********************************************************************/
* $Id: ha_scalar_sub.cpp 6418 2010-03-29 21:55:08Z zzhu $
*
*
***********************************************************************/
/** @file */
/** class ScalarSub definition */
@ -52,290 +52,294 @@ using namespace logging;
namespace cal_impl_if
{
ScalarSub::ScalarSub(gp_walk_info& gwip) : WhereSubQuery(gwip), fReturnedColPos(0)
{}
{
}
ScalarSub::ScalarSub(gp_walk_info& gwip, Item_func* func) :
WhereSubQuery(gwip, func), fReturnedColPos(0)
{}
ScalarSub::ScalarSub(gp_walk_info& gwip, Item_func* func) : WhereSubQuery(gwip, func), fReturnedColPos(0)
{
}
ScalarSub::ScalarSub(gp_walk_info& gwip, const execplan::SRCP& column, Item_subselect* sub, Item_func* func):
WhereSubQuery(gwip, column, sub, func), fReturnedColPos(0)
{}
ScalarSub::ScalarSub(gp_walk_info& gwip, const execplan::SRCP& column, Item_subselect* sub, Item_func* func)
: WhereSubQuery(gwip, column, sub, func), fReturnedColPos(0)
{
}
ScalarSub::ScalarSub(const ScalarSub& rhs) :
WhereSubQuery(rhs.gwip(), rhs.fColumn, rhs.fSub, rhs.fFunc),
fReturnedColPos(rhs.fReturnedColPos)
{}
ScalarSub::ScalarSub(const ScalarSub& rhs)
: WhereSubQuery(rhs.gwip(), rhs.fColumn, rhs.fSub, rhs.fFunc), fReturnedColPos(rhs.fReturnedColPos)
{
}
ScalarSub::~ScalarSub()
{}
{
}
execplan::ParseTree* ScalarSub::transform()
{
if (!fFunc)
return NULL;
if (!fFunc)
return NULL;
// @todo need to handle scalar IN and BETWEEN specially
// this blocks handles only one subselect scalar
// arg[0]: column | arg[1]: subselect
//idbassert(fGwip.rcWorkStack.size() >= 2);
if (fFunc->functype() == Item_func::BETWEEN)
return transform_between();
// @todo need to handle scalar IN and BETWEEN specially
// this blocks handles only one subselect scalar
// arg[0]: column | arg[1]: subselect
// idbassert(fGwip.rcWorkStack.size() >= 2);
if (fFunc->functype() == Item_func::BETWEEN)
return transform_between();
if (fFunc->functype() == Item_func::IN_FUNC)
return transform_in();
if (fFunc->functype() == Item_func::IN_FUNC)
return transform_in();
ReturnedColumn* rhs = NULL;
ReturnedColumn* lhs = NULL;
ReturnedColumn* rhs = NULL;
ReturnedColumn* lhs = NULL;
if (!fGwip.rcWorkStack.empty())
{
rhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
}
if (!fGwip.rcWorkStack.empty())
{
rhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
}
if (!fGwip.rcWorkStack.empty())
{
lhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
}
if (!fGwip.rcWorkStack.empty())
{
lhs = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
}
PredicateOperator* op = new PredicateOperator(fFunc->func_name());
if (!lhs && (fFunc->functype() == Item_func::ISNULL_FUNC ||
fFunc->functype() == Item_func::ISNOTNULL_FUNC))
{
fSub = (Item_subselect*)(fFunc->arguments()[0]);
fColumn.reset(new ConstantColumn("", ConstantColumn::NULLDATA));
(dynamic_cast<ConstantColumn*>(fColumn.get()))->timeZone(fGwip.thd->variables.time_zone->get_name()->ptr());
delete rhs;
return buildParseTree(op);
}
bool reverseOp = false;
SubSelect* sub = dynamic_cast<SubSelect*>(rhs);
if (!sub)
{
reverseOp = true;
delete lhs;
lhs = rhs;
fSub = (Item_subselect*)(fFunc->arguments()[0]);
}
else
{
delete rhs;
fSub = (Item_subselect*)(fFunc->arguments()[1]);
}
fColumn.reset(lhs); // column should be in the stack already. in, between may be different
//PredicateOperator *op = new PredicateOperator(fFunc->func_name());
if (reverseOp)
op->reverseOp();
PredicateOperator* op = new PredicateOperator(fFunc->func_name());
if (!lhs && (fFunc->functype() == Item_func::ISNULL_FUNC || fFunc->functype() == Item_func::ISNOTNULL_FUNC))
{
fSub = (Item_subselect*)(fFunc->arguments()[0]);
fColumn.reset(new ConstantColumn("", ConstantColumn::NULLDATA));
(dynamic_cast<ConstantColumn*>(fColumn.get()))
->timeZone(fGwip.thd->variables.time_zone->get_name()->ptr());
delete rhs;
return buildParseTree(op);
}
bool reverseOp = false;
SubSelect* sub = dynamic_cast<SubSelect*>(rhs);
if (!sub)
{
reverseOp = true;
delete lhs;
lhs = rhs;
fSub = (Item_subselect*)(fFunc->arguments()[0]);
}
else
{
delete rhs;
fSub = (Item_subselect*)(fFunc->arguments()[1]);
}
fColumn.reset(lhs); // column should be in the stack already. in, between may be different
// PredicateOperator *op = new PredicateOperator(fFunc->func_name());
if (reverseOp)
op->reverseOp();
return buildParseTree(op);
}
execplan::ParseTree* ScalarSub::transform_between()
{
//idbassert(fGwip.rcWorkStack.size() >= 3);
if (fGwip.rcWorkStack.size() < 3)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
// idbassert(fGwip.rcWorkStack.size() >= 3);
if (fGwip.rcWorkStack.size() < 3)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
ReturnedColumn* op3 = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
ReturnedColumn* op2 = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
ReturnedColumn* op1 = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
fColumn.reset(op1);
ReturnedColumn* op3 = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
ReturnedColumn* op2 = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
ReturnedColumn* op1 = fGwip.rcWorkStack.top();
fGwip.rcWorkStack.pop();
fColumn.reset(op1);
ParseTree* lhs = NULL;
ParseTree* rhs = NULL;
PredicateOperator* op_LE = new PredicateOperator("<=");
PredicateOperator* op_GE = new PredicateOperator(">=");
ParseTree* lhs = NULL;
ParseTree* rhs = NULL;
PredicateOperator* op_LE = new PredicateOperator("<=");
PredicateOperator* op_GE = new PredicateOperator(">=");
SubSelect* sub2 = dynamic_cast<SubSelect*>(op3);
fSub = (Item_subselect*)(fFunc->arguments()[2]);
SubSelect* sub2 = dynamic_cast<SubSelect*>(op3);
fSub = (Item_subselect*)(fFunc->arguments()[2]);
if (sub2)
{
rhs = buildParseTree(op_LE);
delete sub2;
}
else
{
SOP sop;
sop.reset(op_LE);
rhs = new ParseTree(new SimpleFilter(sop, fColumn.get(), op3));
(dynamic_cast<SimpleFilter*>(rhs->data()))->timeZone(fGwip.thd->variables.time_zone->get_name()->ptr());
}
if (sub2)
{
rhs = buildParseTree(op_LE);
delete sub2;
}
else
{
SOP sop;
sop.reset(op_LE);
rhs = new ParseTree(new SimpleFilter(sop, fColumn.get(), op3));
(dynamic_cast<SimpleFilter*>(rhs->data()))->timeZone(fGwip.thd->variables.time_zone->get_name()->ptr());
}
SubSelect* sub1 = dynamic_cast<SubSelect*>(op2);
fSub = (Item_subselect*)(fFunc->arguments()[1]);
SubSelect* sub1 = dynamic_cast<SubSelect*>(op2);
fSub = (Item_subselect*)(fFunc->arguments()[1]);
if (sub1)
{
lhs = buildParseTree(op_GE);
delete sub1;
}
else
{
SOP sop;
sop.reset(op_GE);
lhs = new ParseTree(new SimpleFilter(sop, fColumn.get(), op2));
(dynamic_cast<SimpleFilter*>(lhs->data()))->timeZone(fGwip.thd->variables.time_zone->get_name()->ptr());
}
if (sub1)
{
lhs = buildParseTree(op_GE);
delete sub1;
}
else
{
SOP sop;
sop.reset(op_GE);
lhs = new ParseTree(new SimpleFilter(sop, fColumn.get(), op2));
(dynamic_cast<SimpleFilter*>(lhs->data()))->timeZone(fGwip.thd->variables.time_zone->get_name()->ptr());
}
if (!rhs || !lhs)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "non-supported scalar subquery";
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
if (!rhs || !lhs)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "non-supported scalar subquery";
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
ParseTree* pt = new ParseTree (new LogicOperator("and"));
pt->left(lhs);
pt->right(rhs);
return pt;
ParseTree* pt = new ParseTree(new LogicOperator("and"));
pt->left(lhs);
pt->right(rhs);
return pt;
}
execplan::ParseTree* ScalarSub::transform_in()
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
execplan::ParseTree* ScalarSub::buildParseTree(PredicateOperator* op)
{
idbassert(fColumn.get() && fSub && fFunc);
idbassert(fColumn.get() && fSub && fFunc);
vector<SRCP> cols;
Filter* filter;
RowColumn* rcol = dynamic_cast<RowColumn*>(fColumn.get());
vector<SRCP> cols;
Filter* filter;
RowColumn* rcol = dynamic_cast<RowColumn*>(fColumn.get());
if (rcol)
if (rcol)
{
// IDB only supports (c1,c2..) =/!= (subquery)
if (fFunc->functype() != Item_func::EQ_FUNC && fFunc->functype() != Item_func::NE_FUNC)
{
// IDB only supports (c1,c2..) =/!= (subquery)
if (fFunc->functype() != Item_func::EQ_FUNC && fFunc->functype() != Item_func::NE_FUNC)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_INVALID_OPERATOR_WITH_LIST);
return NULL;
}
cols = rcol->columnVec();
}
else
cols.push_back(fColumn);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::WHERE);
csep->subType (CalpontSelectExecutionPlan::SINGLEROW_SUBS);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// @4827 merge table list to gwi in case there is FROM sub to be referenced
// in the FROM sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep, false) != 0)
{
//@todo more in error handling
if (!gwi.fatalParseError)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Error occured in ScalarSub::transform()";
}
else
{
fGwip.fatalParseError = gwi.fatalParseError;
fGwip.parseErrorText = gwi.parseErrorText;
}
return NULL;
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_INVALID_OPERATOR_WITH_LIST);
return NULL;
}
fGwip.subselectList.push_back(csep);
cols = rcol->columnVec();
}
else
cols.push_back(fColumn);
// error out non-support case for now: comparison out of semi join tables.
// only check for simplecolumn
if (!gwi.correlatedTbNameVec.empty())
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->location(CalpontSelectExecutionPlan::WHERE);
csep->subType(CalpontSelectExecutionPlan::SINGLEROW_SUBS);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// @4827 merge table list to gwi in case there is FROM sub to be referenced
// in the FROM sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
if (getSelectPlan(gwi, *(fSub->get_select_lex()), csep, false) != 0)
{
//@todo more in error handling
if (!gwi.fatalParseError)
{
for (uint32_t i = 0; i < cols.size(); i++)
{
SimpleColumn* sc = dynamic_cast<SimpleColumn*>(cols[i].get());
if (sc)
{
CalpontSystemCatalog::TableAliasName tan = make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias());
uint32_t j = 0;
for (; j < gwi.correlatedTbNameVec.size(); j++)
if (tan == gwi.correlatedTbNameVec[j])
break;
if (j == gwi.correlatedTbNameVec.size())
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
}
}
}
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end());
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin() + gwi.derivedTbCnt, csep->derivedTableList().end());
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
// if (fSub->is_correlated)
if (fSub->unit->first_select()->master_unit()->uncacheable)
{
SelectFilter* subFilter = new SelectFilter();
subFilter->correlated(true);
subFilter->cols(cols);
subFilter->sub(csep);
subFilter->op(SOP(op));
subFilter->returnedColPos(fReturnedColPos);
filter = subFilter;
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Error occured in ScalarSub::transform()";
}
else
{
SimpleScalarFilter* subFilter = new SimpleScalarFilter();
subFilter->cols(cols);
subFilter->sub(csep);
subFilter->op(SOP(op));
filter = subFilter;
fGwip.fatalParseError = gwi.fatalParseError;
fGwip.parseErrorText = gwi.parseErrorText;
}
return new ParseTree(filter);
return NULL;
}
fGwip.subselectList.push_back(csep);
// error out non-support case for now: comparison out of semi join tables.
// only check for simplecolumn
if (!gwi.correlatedTbNameVec.empty())
{
for (uint32_t i = 0; i < cols.size(); i++)
{
SimpleColumn* sc = dynamic_cast<SimpleColumn*>(cols[i].get());
if (sc)
{
CalpontSystemCatalog::TableAliasName tan =
make_aliastable(sc->schemaName(), sc->tableName(), sc->tableAlias());
uint32_t j = 0;
for (; j < gwi.correlatedTbNameVec.size(); j++)
if (tan == gwi.correlatedTbNameVec[j])
break;
if (j == gwi.correlatedTbNameVec.size())
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = IDBErrorInfo::instance()->errorMsg(ERR_NON_SUPPORT_SCALAR);
return NULL;
}
}
}
}
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end());
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin() + gwi.derivedTbCnt,
csep->derivedTableList().end());
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
// if (fSub->is_correlated)
if (fSub->unit->first_select()->master_unit()->uncacheable)
{
SelectFilter* subFilter = new SelectFilter();
subFilter->correlated(true);
subFilter->cols(cols);
subFilter->sub(csep);
subFilter->op(SOP(op));
subFilter->returnedColPos(fReturnedColPos);
filter = subFilter;
}
else
{
SimpleScalarFilter* subFilter = new SimpleScalarFilter();
subFilter->cols(cols);
subFilter->sub(csep);
subFilter->op(SOP(op));
filter = subFilter;
}
return new ParseTree(filter);
}
}
} // namespace cal_impl_if

View File

@ -17,10 +17,10 @@
MA 02110-1301, USA. */
/***********************************************************************
* $Id: ha_select_sub.cpp 9210 2013-01-21 14:10:42Z rdempsey $
*
*
***********************************************************************/
* $Id: ha_select_sub.cpp 9210 2013-01-21 14:10:42Z rdempsey $
*
*
***********************************************************************/
/** class SelectSubQuery definition */
//#define NDEBUG
@ -47,70 +47,72 @@ using namespace logging;
namespace cal_impl_if
{
SelectSubQuery::SelectSubQuery(gp_walk_info& gwip) : SubQuery(gwip), fSelSub (NULL)
{}
SelectSubQuery::SelectSubQuery(gp_walk_info& gwip) : SubQuery(gwip), fSelSub(NULL)
{
}
SelectSubQuery::SelectSubQuery(gp_walk_info& gwip, Item_subselect* selSub) :
SubQuery(gwip),
fSelSub(selSub)
{}
SelectSubQuery::SelectSubQuery(gp_walk_info& gwip, Item_subselect* selSub) : SubQuery(gwip), fSelSub(selSub)
{
}
SelectSubQuery::~SelectSubQuery()
{}
{
}
SCSEP SelectSubQuery::transform()
{
idbassert(fSelSub);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->subType (CalpontSelectExecutionPlan::SELECT_SUBS);
idbassert(fSelSub);
SCSEP csep(new CalpontSelectExecutionPlan());
csep->sessionID(fGwip.sessionid);
csep->subType(CalpontSelectExecutionPlan::SELECT_SUBS);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fGwip.thd;
gwi.subQuery = this;
// @4632 merge table list to gwi in case there is FROM sub to be referenced
// in the SELECT sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
// @4632 merge table list to gwi in case there is FROM sub to be referenced
// in the SELECT sub
gwi.derivedTbCnt = fGwip.derivedTbList.size();
uint32_t tbCnt = fGwip.tbList.size();
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
gwi.tbList.insert(gwi.tbList.begin(), fGwip.tbList.begin(), fGwip.tbList.end());
gwi.derivedTbList.insert(gwi.derivedTbList.begin(), fGwip.derivedTbList.begin(), fGwip.derivedTbList.end());
if (getSelectPlan(gwi, *(fSelSub->get_select_lex()), csep, false) != 0)
if (getSelectPlan(gwi, *(fSelSub->get_select_lex()), csep, false) != 0)
{
if (!gwi.fatalParseError)
{
if (!gwi.fatalParseError)
{
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Error occured in SelectSubQuery::transform()";
}
else
{
fGwip.fatalParseError = gwi.fatalParseError;
fGwip.parseErrorText = gwi.parseErrorText;
}
csep.reset();
return csep;
fGwip.fatalParseError = true;
fGwip.parseErrorText = "Error occured in SelectSubQuery::transform()";
}
else
{
fGwip.fatalParseError = gwi.fatalParseError;
fGwip.parseErrorText = gwi.parseErrorText;
}
fGwip.subselectList.push_back(csep);
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end());
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin() + gwi.derivedTbCnt, csep->derivedTableList().end());
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
csep.reset();
return csep;
}
fGwip.subselectList.push_back(csep);
// remove outer query tables
CalpontSelectExecutionPlan::TableList tblist;
if (csep->tableList().size() >= tbCnt)
tblist.insert(tblist.begin(), csep->tableList().begin() + tbCnt, csep->tableList().end());
CalpontSelectExecutionPlan::SelectList derivedTbList;
if (csep->derivedTableList().size() >= gwi.derivedTbCnt)
derivedTbList.insert(derivedTbList.begin(), csep->derivedTableList().begin() + gwi.derivedTbCnt,
csep->derivedTableList().end());
csep->tableList(tblist);
csep->derivedTableList(derivedTbList);
return csep;
}
}
} // namespace cal_impl_if

View File

@ -17,10 +17,10 @@
MA 02110-1301, USA. */
/***********************************************************************
* $Id: ha_subquery.h 6418 2010-03-29 21:55:08Z zzhu $
*
*
***********************************************************************/
* $Id: ha_subquery.h 6418 2010-03-29 21:55:08Z zzhu $
*
*
***********************************************************************/
/** @file */
/** class subquery series interface */
@ -39,34 +39,39 @@ class PredicateOperator;
namespace cal_impl_if
{
/** @file */
class SubQuery
{
public:
SubQuery(gp_walk_info& gwip) :
fGwip(gwip),
fCorrelated(false)
{}
virtual ~SubQuery() {}
virtual gp_walk_info& gwip() const
{
return fGwip;
}
bool correlated() const
{
return fCorrelated;
}
void correlated (const bool correlated)
{
fCorrelated = correlated;
}
virtual void handleFunc (gp_walk_info* gwip, Item_func* func) {}
virtual void handleNot () {}
protected:
gp_walk_info& fGwip;
bool fCorrelated;
public:
SubQuery(gp_walk_info& gwip) : fGwip(gwip), fCorrelated(false)
{
}
virtual ~SubQuery()
{
}
virtual gp_walk_info& gwip() const
{
return fGwip;
}
bool correlated() const
{
return fCorrelated;
}
void correlated(const bool correlated)
{
fCorrelated = correlated;
}
virtual void handleFunc(gp_walk_info* gwip, Item_func* func)
{
}
virtual void handleNot()
{
}
protected:
gp_walk_info& fGwip;
bool fCorrelated;
};
/**
@ -74,41 +79,47 @@ protected:
*/
class WhereSubQuery : public SubQuery
{
public:
WhereSubQuery(gp_walk_info& gwip) : SubQuery(gwip),
fSub(NULL),
fFunc(NULL) {}
WhereSubQuery(gp_walk_info& gwip, const execplan::SRCP& column, Item_subselect* sub, Item_func* func) :
SubQuery(gwip),
fColumn(column),
fSub(sub),
fFunc(func) {}
WhereSubQuery(gp_walk_info& gwip, Item_func* func) : SubQuery(gwip), fFunc(func) {}
WhereSubQuery(gp_walk_info& gwip, Item_subselect* sub) : SubQuery(gwip), fSub(sub) {} // for exists
virtual ~WhereSubQuery() {}
public:
WhereSubQuery(gp_walk_info& gwip) : SubQuery(gwip), fSub(NULL), fFunc(NULL)
{
}
WhereSubQuery(gp_walk_info& gwip, const execplan::SRCP& column, Item_subselect* sub, Item_func* func)
: SubQuery(gwip), fColumn(column), fSub(sub), fFunc(func)
{
}
WhereSubQuery(gp_walk_info& gwip, Item_func* func) : SubQuery(gwip), fFunc(func)
{
}
WhereSubQuery(gp_walk_info& gwip, Item_subselect* sub) : SubQuery(gwip), fSub(sub)
{
} // for exists
virtual ~WhereSubQuery()
{
}
/** Accessors and mutators */
virtual Item_subselect* sub() const
{
return fSub;
}
virtual void sub(Item_subselect* sub)
{
fSub = sub;
}
virtual Item_func* func() const
{
return fFunc;
}
virtual void func(Item_func* func)
{
fFunc = func;
}
virtual execplan::ParseTree* transform() = 0;
protected:
execplan::SRCP fColumn;
Item_subselect* fSub;
Item_func* fFunc;
/** Accessors and mutators */
virtual Item_subselect* sub() const
{
return fSub;
}
virtual void sub(Item_subselect* sub)
{
fSub = sub;
}
virtual Item_func* func() const
{
return fFunc;
}
virtual void func(Item_func* func)
{
fFunc = func;
}
virtual execplan::ParseTree* transform() = 0;
protected:
execplan::SRCP fColumn;
Item_subselect* fSub;
Item_func* fFunc;
};
/**
@ -116,27 +127,27 @@ protected:
*/
class ScalarSub : public WhereSubQuery
{
public:
ScalarSub(gp_walk_info& gwip);
ScalarSub(gp_walk_info& gwip, Item_func* func);
ScalarSub(gp_walk_info& gwip, const execplan::SRCP& column, Item_subselect* sub, Item_func* func);
ScalarSub(const ScalarSub& rhs);
~ScalarSub();
execplan::ParseTree* transform();
execplan::ParseTree* transform_between();
execplan::ParseTree* transform_in();
execplan::ParseTree* buildParseTree(execplan::PredicateOperator* op);
uint64_t returnedColPos() const
{
return fReturnedColPos;
}
void returnedColPos(const uint64_t returnedColPos)
{
fReturnedColPos = returnedColPos;
}
public:
ScalarSub(gp_walk_info& gwip);
ScalarSub(gp_walk_info& gwip, Item_func* func);
ScalarSub(gp_walk_info& gwip, const execplan::SRCP& column, Item_subselect* sub, Item_func* func);
ScalarSub(const ScalarSub& rhs);
~ScalarSub();
execplan::ParseTree* transform();
execplan::ParseTree* transform_between();
execplan::ParseTree* transform_in();
execplan::ParseTree* buildParseTree(execplan::PredicateOperator* op);
uint64_t returnedColPos() const
{
return fReturnedColPos;
}
void returnedColPos(const uint64_t returnedColPos)
{
fReturnedColPos = returnedColPos;
}
private:
uint64_t fReturnedColPos;
private:
uint64_t fReturnedColPos;
};
/**
@ -144,14 +155,14 @@ private:
*/
class InSub : public WhereSubQuery
{
public:
InSub(gp_walk_info& gwip);
InSub(gp_walk_info& gwip, Item_func* func);
InSub(const InSub& rhs);
~InSub();
execplan::ParseTree* transform();
void handleFunc(gp_walk_info* gwip, Item_func* func);
void handleNot();
public:
InSub(gp_walk_info& gwip);
InSub(gp_walk_info& gwip, Item_func* func);
InSub(const InSub& rhs);
~InSub();
execplan::ParseTree* transform();
void handleFunc(gp_walk_info* gwip, Item_func* func);
void handleNot();
};
/**
@ -159,12 +170,12 @@ public:
*/
class ExistsSub : public WhereSubQuery
{
public:
ExistsSub(gp_walk_info&); // not complete. just for compile
ExistsSub(gp_walk_info&, Item_subselect* sub);
~ExistsSub();
execplan::ParseTree* transform();
void handleNot();
public:
ExistsSub(gp_walk_info&); // not complete. just for compile
ExistsSub(gp_walk_info&, Item_subselect* sub);
~ExistsSub();
execplan::ParseTree* transform();
void handleNot();
};
/**
@ -179,51 +190,53 @@ class AggregateSub : public WhereSubQuery
*/
class FromSubQuery : public SubQuery
{
public:
FromSubQuery(gp_walk_info&);
FromSubQuery(gp_walk_info&, SELECT_LEX* fromSub);
~FromSubQuery();
const SELECT_LEX* fromSub() const
{
return fFromSub;
}
void fromSub(SELECT_LEX* fromSub)
{
fFromSub = fromSub;
}
const std::string alias () const
{
return fAlias;
}
void alias (const std::string alias)
{
fAlias = alias;
}
execplan::SCSEP transform();
private:
SELECT_LEX* fFromSub;
std::string fAlias;
public:
FromSubQuery(gp_walk_info&);
FromSubQuery(gp_walk_info&, SELECT_LEX* fromSub);
~FromSubQuery();
const SELECT_LEX* fromSub() const
{
return fFromSub;
}
void fromSub(SELECT_LEX* fromSub)
{
fFromSub = fromSub;
}
const std::string alias() const
{
return fAlias;
}
void alias(const std::string alias)
{
fAlias = alias;
}
execplan::SCSEP transform();
private:
SELECT_LEX* fFromSub;
std::string fAlias;
};
class SelectSubQuery : public SubQuery
class SelectSubQuery : public SubQuery
{
public:
SelectSubQuery(gp_walk_info&);
SelectSubQuery(gp_walk_info&, Item_subselect* sel);
~SelectSubQuery();
execplan::SCSEP transform();
Item_subselect* selSub()
{
return fSelSub;
}
void selSub( Item_subselect* selSub )
{
fSelSub = selSub;
}
private:
Item_subselect* fSelSub;
public:
SelectSubQuery(gp_walk_info&);
SelectSubQuery(gp_walk_info&, Item_subselect* sel);
~SelectSubQuery();
execplan::SCSEP transform();
Item_subselect* selSub()
{
return fSelSub;
}
void selSub(Item_subselect* selSub)
{
fSelSub = selSub;
}
private:
Item_subselect* fSelSub;
};
}
} // namespace cal_impl_if
#endif

View File

@ -21,55 +21,49 @@
/* needed for sql_base.h which contains open_system_tables_for_read*/
#ifndef TRUE
#define TRUE (1) /* Logical true */
#define FALSE (0) /* Logical false */
#define TRUE (1) /* Logical true */
#define FALSE (0) /* Logical false */
#endif
#include <sql_base.h>
//static HASH tz_names;
//static HASH offset_tzs;
// static HASH tz_names;
// static HASH offset_tzs;
static MEM_ROOT tz_storage;
static uint tz_leapcnt= 0;
static LS_INFO *tz_lsis= 0;
static bool time_zone_tables_exist= 1;
static uint tz_leapcnt = 0;
static LS_INFO* tz_lsis = 0;
static bool time_zone_tables_exist = 1;
namespace cal_impl_if
{
/*
Names of tables (with their lengths) that are needed
for dynamical loading of time zone descriptions.
*/
static const LEX_CSTRING tz_tables_names[MY_TZ_TABLES_COUNT]=
{
{ STRING_WITH_LEN("time_zone_name")},
{ STRING_WITH_LEN("time_zone")},
{ STRING_WITH_LEN("time_zone_transition_type")},
{ STRING_WITH_LEN("time_zone_transition")}
};
static const LEX_CSTRING tz_tables_names[MY_TZ_TABLES_COUNT] = {
{STRING_WITH_LEN("time_zone_name")},
{STRING_WITH_LEN("time_zone")},
{STRING_WITH_LEN("time_zone_transition_type")},
{STRING_WITH_LEN("time_zone_transition")}};
static void
tz_init_table_list(TABLE_LIST *tz_tabs)
static void tz_init_table_list(TABLE_LIST* tz_tabs)
{
for (int i= 0; i < MY_TZ_TABLES_COUNT; i++)
for (int i = 0; i < MY_TZ_TABLES_COUNT; i++)
{
tz_tabs[i].init_one_table(&MYSQL_SCHEMA_NAME, tz_tables_names + i,
NULL, TL_READ);
tz_tabs[i].init_one_table(&MYSQL_SCHEMA_NAME, tz_tables_names + i, NULL, TL_READ);
if (i != MY_TZ_TABLES_COUNT - 1)
tz_tabs[i].next_global= tz_tabs[i].next_local= &tz_tabs[i+1];
tz_tabs[i].next_global = tz_tabs[i].next_local = &tz_tabs[i + 1];
if (i != 0)
tz_tabs[i].prev_global= &tz_tabs[i-1].next_global;
tz_tabs[i].prev_global = &tz_tabs[i - 1].next_global;
}
}
static my_bool
prepare_tz_info(TIME_ZONE_INFO *sp, MEM_ROOT *storage)
static my_bool prepare_tz_info(TIME_ZONE_INFO* sp, MEM_ROOT* storage)
{
my_time_t cur_t= MY_TIME_T_MIN;
my_time_t cur_t = MY_TIME_T_MIN;
my_time_t cur_l, end_t;
my_time_t end_l = 0;
my_time_t cur_max_seen_l= MY_TIME_T_MIN;
my_time_t cur_max_seen_l = MY_TIME_T_MIN;
long cur_offset, cur_corr, cur_off_and_corr;
uint next_trans_idx, next_leap_idx;
uint i;
@ -87,17 +81,16 @@ prepare_tz_info(TIME_ZONE_INFO *sp, MEM_ROOT *storage)
We will find first non-DST local time type and use it (or use first
local time type if all of them are DST types).
*/
for (i= 0; i < sp->typecnt && sp->ttis[i].tt_isdst; i++)
/* no-op */ ;
for (i = 0; i < sp->typecnt && sp->ttis[i].tt_isdst; i++)
/* no-op */;
if (i == sp->typecnt)
i= 0;
sp->fallback_tti= &(sp->ttis[i]);
i = 0;
sp->fallback_tti = &(sp->ttis[i]);
/*
Let us build shifted my_time_t -> my_time_t map.
*/
sp->revcnt= 0;
sp->revcnt = 0;
/* Let us find initial offset */
if (sp->timecnt == 0 || cur_t < sp->ats[0])
@ -106,105 +99,96 @@ prepare_tz_info(TIME_ZONE_INFO *sp, MEM_ROOT *storage)
If we have not any transitions or t is before first transition we are using
already found fallback time type which index is already in i.
*/
next_trans_idx= 0;
next_trans_idx = 0;
}
else
{
/* cur_t == sp->ats[0] so we found transition */
i= sp->types[0];
next_trans_idx= 1;
i = sp->types[0];
next_trans_idx = 1;
}
cur_offset= sp->ttis[i].tt_gmtoff;
cur_offset = sp->ttis[i].tt_gmtoff;
/* let us find leap correction... unprobable, but... */
for (next_leap_idx= 0; next_leap_idx < sp->leapcnt &&
cur_t >= sp->lsis[next_leap_idx].ls_trans;
++next_leap_idx)
for (next_leap_idx = 0; next_leap_idx < sp->leapcnt && cur_t >= sp->lsis[next_leap_idx].ls_trans;
++next_leap_idx)
continue;
if (next_leap_idx > 0)
cur_corr= sp->lsis[next_leap_idx - 1].ls_corr;
cur_corr = sp->lsis[next_leap_idx - 1].ls_corr;
else
cur_corr= 0;
cur_corr = 0;
/* Iterate trough t space */
while (sp->revcnt < TZ_MAX_REV_RANGES - 1)
{
cur_off_and_corr= cur_offset - cur_corr;
cur_off_and_corr = cur_offset - cur_corr;
/*
We assuming that cur_t could be only overflowed downwards,
we also assume that end_t won't be overflowed in this case.
*/
if (cur_off_and_corr < 0 &&
cur_t < MY_TIME_T_MIN - cur_off_and_corr)
cur_t= MY_TIME_T_MIN - cur_off_and_corr;
if (cur_off_and_corr < 0 && cur_t < MY_TIME_T_MIN - cur_off_and_corr)
cur_t = MY_TIME_T_MIN - cur_off_and_corr;
cur_l= cur_t + cur_off_and_corr;
cur_l = cur_t + cur_off_and_corr;
/*
Let us choose end_t as point before next time type change or leap
second correction.
*/
end_t= MY_MIN((next_trans_idx < sp->timecnt) ? sp->ats[next_trans_idx] - 1:
MY_TIME_T_MAX,
(next_leap_idx < sp->leapcnt) ?
sp->lsis[next_leap_idx].ls_trans - 1: MY_TIME_T_MAX);
end_t = MY_MIN((next_trans_idx < sp->timecnt) ? sp->ats[next_trans_idx] - 1 : MY_TIME_T_MAX,
(next_leap_idx < sp->leapcnt) ? sp->lsis[next_leap_idx].ls_trans - 1 : MY_TIME_T_MAX);
/*
again assuming that end_t can be overlowed only in positive side
we also assume that end_t won't be overflowed in this case.
*/
if (cur_off_and_corr > 0 &&
end_t > MY_TIME_T_MAX - cur_off_and_corr)
end_t= MY_TIME_T_MAX - cur_off_and_corr;
end_l= end_t + cur_off_and_corr;
if (cur_off_and_corr > 0 && end_t > MY_TIME_T_MAX - cur_off_and_corr)
end_t = MY_TIME_T_MAX - cur_off_and_corr;
end_l = end_t + cur_off_and_corr;
if (end_l > cur_max_seen_l)
{
/* We want special handling in the case of first range */
if (cur_max_seen_l == MY_TIME_T_MIN)
{
revts[sp->revcnt]= cur_l;
revtis[sp->revcnt].rt_offset= cur_off_and_corr;
revtis[sp->revcnt].rt_type= 0;
revts[sp->revcnt] = cur_l;
revtis[sp->revcnt].rt_offset = cur_off_and_corr;
revtis[sp->revcnt].rt_type = 0;
sp->revcnt++;
cur_max_seen_l= end_l;
cur_max_seen_l = end_l;
}
else
{
if (cur_l > cur_max_seen_l + 1)
{
/* We have a spring time-gap and we are not at the first range */
revts[sp->revcnt]= cur_max_seen_l + 1;
revtis[sp->revcnt].rt_offset= revtis[sp->revcnt-1].rt_offset;
revtis[sp->revcnt].rt_type= 1;
revts[sp->revcnt] = cur_max_seen_l + 1;
revtis[sp->revcnt].rt_offset = revtis[sp->revcnt - 1].rt_offset;
revtis[sp->revcnt].rt_type = 1;
sp->revcnt++;
if (sp->revcnt == TZ_MAX_TIMES + TZ_MAX_LEAPS + 1)
break; /* That was too much */
cur_max_seen_l= cur_l - 1;
cur_max_seen_l = cur_l - 1;
}
/* Assume here end_l > cur_max_seen_l (because end_l>=cur_l) */
revts[sp->revcnt]= cur_max_seen_l + 1;
revtis[sp->revcnt].rt_offset= cur_off_and_corr;
revtis[sp->revcnt].rt_type= 0;
revts[sp->revcnt] = cur_max_seen_l + 1;
revtis[sp->revcnt].rt_offset = cur_off_and_corr;
revtis[sp->revcnt].rt_type = 0;
sp->revcnt++;
cur_max_seen_l= end_l;
cur_max_seen_l = end_l;
}
}
if (end_t == MY_TIME_T_MAX ||
((cur_off_and_corr > 0) &&
(end_t >= MY_TIME_T_MAX - cur_off_and_corr)))
if (end_t == MY_TIME_T_MAX || ((cur_off_and_corr > 0) && (end_t >= MY_TIME_T_MAX - cur_off_and_corr)))
/* end of t space */
break;
cur_t= end_t + 1;
cur_t = end_t + 1;
/*
Let us find new offset and correction. Because of our choice of end_t
@ -212,19 +196,17 @@ prepare_tz_info(TIME_ZONE_INFO *sp, MEM_ROOT *storage)
correction is performed.
*/
if (sp->timecnt != 0 && cur_t >= sp->ats[0]) /* else reuse old offset */
if (next_trans_idx < sp->timecnt &&
cur_t == sp->ats[next_trans_idx])
if (next_trans_idx < sp->timecnt && cur_t == sp->ats[next_trans_idx])
{
/* We are at offset point */
cur_offset= sp->ttis[sp->types[next_trans_idx]].tt_gmtoff;
cur_offset = sp->ttis[sp->types[next_trans_idx]].tt_gmtoff;
++next_trans_idx;
}
if (next_leap_idx < sp->leapcnt &&
cur_t == sp->lsis[next_leap_idx].ls_trans)
if (next_leap_idx < sp->leapcnt && cur_t == sp->lsis[next_leap_idx].ls_trans)
{
/* we are at leap point */
cur_corr= sp->lsis[next_leap_idx].ls_corr;
cur_corr = sp->lsis[next_leap_idx].ls_corr;
++next_leap_idx;
}
}
@ -234,13 +216,11 @@ prepare_tz_info(TIME_ZONE_INFO *sp, MEM_ROOT *storage)
return 1;
/* set maximum end_l as finisher */
revts[sp->revcnt]= end_l;
revts[sp->revcnt] = end_l;
/* Allocate arrays of proper size in sp and copy result there */
if (!(sp->revts= (my_time_t *)alloc_root(storage,
sizeof(my_time_t) * (sp->revcnt + 1))) ||
!(sp->revtis= (REVT_INFO *)alloc_root(storage,
sizeof(REVT_INFO) * sp->revcnt)))
if (!(sp->revts = (my_time_t*)alloc_root(storage, sizeof(my_time_t) * (sp->revcnt + 1))) ||
!(sp->revtis = (REVT_INFO*)alloc_root(storage, sizeof(REVT_INFO) * sp->revcnt)))
return 1;
memcpy(sp->revts, revts, sizeof(my_time_t) * (sp->revcnt + 1));
@ -249,21 +229,21 @@ prepare_tz_info(TIME_ZONE_INFO *sp, MEM_ROOT *storage)
return 0;
}
static TIME_ZONE_INFO* tz_load_from_open_tables(const String *tz_name, TABLE_LIST *tz_tables)
static TIME_ZONE_INFO* tz_load_from_open_tables(const String* tz_name, TABLE_LIST* tz_tables)
{
TABLE *table= 0;
TIME_ZONE_INFO *tz_info= NULL;
//Tz_names_entry *tmp_tzname;
TIME_ZONE_INFO *return_val= 0;
TABLE* table = 0;
TIME_ZONE_INFO* tz_info = NULL;
// Tz_names_entry *tmp_tzname;
TIME_ZONE_INFO* return_val = 0;
int res;
uint tzid, ttid;
my_time_t ttime;
char buff[MAX_FIELD_WIDTH];
uchar keybuff[32];
Field *field;
Field* field;
String abbr(buff, sizeof(buff), &my_charset_latin1);
char *alloc_buff= NULL;
char *tz_name_buff= NULL;
char* alloc_buff = NULL;
char* tz_name_buff = NULL;
/*
Temporary arrays that are used for loading of data for filling
TIME_ZONE_INFO structure
@ -287,28 +267,25 @@ static TIME_ZONE_INFO* tz_load_from_open_tables(const String *tz_name, TABLE_LIS
Let us find out time zone id by its name (there is only one index
and it is specifically for this purpose).
*/
table= tz_tables->table;
tz_tables= tz_tables->next_local;
table->field[0]->store(tz_name->ptr(), tz_name->length(),
&my_charset_latin1);
table = tz_tables->table;
tz_tables = tz_tables->next_local;
table->field[0]->store(tz_name->ptr(), tz_name->length(), &my_charset_latin1);
if (table->file->ha_index_init(0, 1))
goto end;
if (table->file->ha_index_read_map(table->record[0], table->field[0]->ptr,
HA_WHOLE_KEY, HA_READ_KEY_EXACT))
if (table->file->ha_index_read_map(table->record[0], table->field[0]->ptr, HA_WHOLE_KEY, HA_READ_KEY_EXACT))
{
#ifdef EXTRA_DEBUG
/*
Most probably user has mistyped time zone name, so no need to bark here
unless we need it for debugging.
*/
sql_print_error("Can't find description of time zone '%.*b'",
tz_name->length(), tz_name->ptr());
sql_print_error("Can't find description of time zone '%.*b'", tz_name->length(), tz_name->ptr());
#endif
goto end;
}
tzid= (uint)table->field[1]->val_int();
tzid = (uint)table->field[1]->val_int();
(void)table->file->ha_index_end();
@ -317,19 +294,16 @@ static TIME_ZONE_INFO* tz_load_from_open_tables(const String *tz_name, TABLE_LIS
understand whenever this timezone uses leap seconds (again we are
using the only index in this table).
*/
table= tz_tables->table;
tz_tables= tz_tables->next_local;
field= table->field[0];
field->store((longlong) tzid, true);
table = tz_tables->table;
tz_tables = tz_tables->next_local;
field = table->field[0];
field->store((longlong)tzid, true);
DBUG_ASSERT(field->key_length() <= sizeof(keybuff));
field->get_key_image(keybuff,
MY_MIN(field->key_length(), sizeof(keybuff)),
Field::itRAW);
field->get_key_image(keybuff, MY_MIN(field->key_length(), sizeof(keybuff)), Field::itRAW);
if (table->file->ha_index_init(0, 1))
goto end;
if (table->file->ha_index_read_map(table->record[0], keybuff,
HA_WHOLE_KEY, HA_READ_KEY_EXACT))
if (table->file->ha_index_read_map(table->record[0], keybuff, HA_WHOLE_KEY, HA_READ_KEY_EXACT))
{
sql_print_error("Can't find description of time zone '%u'", tzid);
goto end;
@ -338,8 +312,8 @@ static TIME_ZONE_INFO* tz_load_from_open_tables(const String *tz_name, TABLE_LIS
/* If Uses_leap_seconds == 'Y' */
if (table->field[1]->val_int() == 1)
{
tmp_tz_info.leapcnt= tz_leapcnt;
tmp_tz_info.lsis= tz_lsis;
tmp_tz_info.leapcnt = tz_leapcnt;
tmp_tz_info.lsis = tz_lsis;
}
(void)table->file->ha_index_end();
@ -350,116 +324,118 @@ static TIME_ZONE_INFO* tz_load_from_open_tables(const String *tz_name, TABLE_LIS
only for our time zone guess what are we doing?
Right - using special index.
*/
table= tz_tables->table;
tz_tables= tz_tables->next_local;
field= table->field[0];
field->store((longlong) tzid, true);
table = tz_tables->table;
tz_tables = tz_tables->next_local;
field = table->field[0];
field->store((longlong)tzid, true);
DBUG_ASSERT(field->key_length() <= sizeof(keybuff));
field->get_key_image(keybuff,
MY_MIN(field->key_length(), sizeof(keybuff)),
Field::itRAW);
field->get_key_image(keybuff, MY_MIN(field->key_length(), sizeof(keybuff)), Field::itRAW);
if (table->file->ha_index_init(0, 1))
goto end;
res= table->file->ha_index_read_map(table->record[0], keybuff,
(key_part_map)1, HA_READ_KEY_EXACT);
res = table->file->ha_index_read_map(table->record[0], keybuff, (key_part_map)1, HA_READ_KEY_EXACT);
while (!res)
{
ttid= (uint)table->field[1]->val_int();
ttid = (uint)table->field[1]->val_int();
if (ttid >= TZ_MAX_TYPES)
{
sql_print_error("Error while loading time zone description from "
"mysql.time_zone_transition_type table: too big "
"transition type id");
sql_print_error(
"Error while loading time zone description from "
"mysql.time_zone_transition_type table: too big "
"transition type id");
goto end;
}
ttis[ttid].tt_gmtoff= (long)table->field[2]->val_int();
ttis[ttid].tt_isdst= (table->field[3]->val_int() > 0);
ttis[ttid].tt_gmtoff = (long)table->field[2]->val_int();
ttis[ttid].tt_isdst = (table->field[3]->val_int() > 0);
#ifdef ABBR_ARE_USED
// FIXME should we do something with duplicates here ?
table->field[4]->val_str(&abbr, &abbr);
if (tmp_tz_info.charcnt + abbr.length() + 1 > sizeof(chars))
{
sql_print_error("Error while loading time zone description from "
"mysql.time_zone_transition_type table: not enough "
"room for abbreviations");
sql_print_error(
"Error while loading time zone description from "
"mysql.time_zone_transition_type table: not enough "
"room for abbreviations");
goto end;
}
ttis[ttid].tt_abbrind= tmp_tz_info.charcnt;
ttis[ttid].tt_abbrind = tmp_tz_info.charcnt;
memcpy(chars + tmp_tz_info.charcnt, abbr.ptr(), abbr.length());
tmp_tz_info.charcnt+= abbr.length();
chars[tmp_tz_info.charcnt]= 0;
tmp_tz_info.charcnt += abbr.length();
chars[tmp_tz_info.charcnt] = 0;
tmp_tz_info.charcnt++;
DBUG_PRINT("info",("time_zone_transition_type table: tz_id=%u tt_id=%u tt_gmtoff=%ld "
"abbr='%s' tt_isdst=%u", tzid, ttid, ttis[ttid].tt_gmtoff,
chars + ttis[ttid].tt_abbrind, ttis[ttid].tt_isdst));
DBUG_PRINT("info",
("time_zone_transition_type table: tz_id=%u tt_id=%u tt_gmtoff=%ld "
"abbr='%s' tt_isdst=%u",
tzid, ttid, ttis[ttid].tt_gmtoff, chars + ttis[ttid].tt_abbrind, ttis[ttid].tt_isdst));
#else
DBUG_PRINT("info",("time_zone_transition_type table: tz_id=%u tt_id=%u tt_gmtoff=%ld "
"tt_isdst=%u", tzid, ttid, ttis[ttid].tt_gmtoff, ttis[ttid].tt_isdst));
DBUG_PRINT("info", ("time_zone_transition_type table: tz_id=%u tt_id=%u tt_gmtoff=%ld "
"tt_isdst=%u",
tzid, ttid, ttis[ttid].tt_gmtoff, ttis[ttid].tt_isdst));
#endif
/* ttid is increasing because we are reading using index */
DBUG_ASSERT(ttid >= tmp_tz_info.typecnt);
tmp_tz_info.typecnt= ttid + 1;
tmp_tz_info.typecnt = ttid + 1;
res= table->file->ha_index_next_same(table->record[0], keybuff, 4);
res = table->file->ha_index_next_same(table->record[0], keybuff, 4);
}
if (res != HA_ERR_END_OF_FILE)
{
sql_print_error("Error while loading time zone description from "
"mysql.time_zone_transition_type table");
sql_print_error(
"Error while loading time zone description from "
"mysql.time_zone_transition_type table");
goto end;
}
(void)table->file->ha_index_end();
/*
At last we are doing the same thing for records in
mysql.time_zone_transition table. Here we additionally need records
in ascending order by index scan also satisfies us.
*/
table= tz_tables->table;
table->field[0]->store((longlong) tzid, true);
table = tz_tables->table;
table->field[0]->store((longlong)tzid, true);
if (table->file->ha_index_init(0, 1))
goto end;
res= table->file->ha_index_read_map(table->record[0], keybuff,
(key_part_map)1, HA_READ_KEY_EXACT);
res = table->file->ha_index_read_map(table->record[0], keybuff, (key_part_map)1, HA_READ_KEY_EXACT);
while (!res)
{
ttime= (my_time_t)table->field[1]->val_int();
ttid= (uint)table->field[2]->val_int();
ttime = (my_time_t)table->field[1]->val_int();
ttid = (uint)table->field[2]->val_int();
if (tmp_tz_info.timecnt + 1 > TZ_MAX_TIMES)
{
sql_print_error("Error while loading time zone description from "
"mysql.time_zone_transition table: "
"too much transitions");
sql_print_error(
"Error while loading time zone description from "
"mysql.time_zone_transition table: "
"too much transitions");
goto end;
}
if (ttid + 1 > tmp_tz_info.typecnt)
{
sql_print_error("Error while loading time zone description from "
"mysql.time_zone_transition table: "
"bad transition type id");
sql_print_error(
"Error while loading time zone description from "
"mysql.time_zone_transition table: "
"bad transition type id");
goto end;
}
ats[tmp_tz_info.timecnt]= ttime;
types[tmp_tz_info.timecnt]= ttid;
ats[tmp_tz_info.timecnt] = ttime;
types[tmp_tz_info.timecnt] = ttid;
tmp_tz_info.timecnt++;
DBUG_PRINT("info", ("time_zone_transition table: tz_id: %u tt_time: %lu tt_id: %u",
tzid, (ulong) ttime, ttid));
DBUG_PRINT("info",
("time_zone_transition table: tz_id: %u tt_time: %lu tt_id: %u", tzid, (ulong)ttime, ttid));
res= table->file->ha_index_next_same(table->record[0], keybuff, 4);
res = table->file->ha_index_next_same(table->record[0], keybuff, 4);
}
/*
@ -468,13 +444,14 @@ static TIME_ZONE_INFO* tz_load_from_open_tables(const String *tz_name, TABLE_LIS
*/
if (res != HA_ERR_END_OF_FILE && res != HA_ERR_KEY_NOT_FOUND)
{
sql_print_error("Error while loading time zone description from "
"mysql.time_zone_transition table");
sql_print_error(
"Error while loading time zone description from "
"mysql.time_zone_transition table");
goto end;
}
(void)table->file->ha_index_end();
table= 0;
table = 0;
/*
Let us check how correct our time zone description is. We don't check for
@ -487,16 +464,16 @@ static TIME_ZONE_INFO* tz_load_from_open_tables(const String *tz_name, TABLE_LIS
}
/* Allocate memory for the timezone info and timezone name in tz_storage. */
if (!(alloc_buff= (char*) alloc_root(&tz_storage, sizeof(TIME_ZONE_INFO) + tz_name->length() + 1)))
if (!(alloc_buff = (char*)alloc_root(&tz_storage, sizeof(TIME_ZONE_INFO) + tz_name->length() + 1)))
{
sql_print_error("Out of memory while loading time zone description");
return 0;
}
/* Move the temporary tz_info into the allocated area */
tz_info= (TIME_ZONE_INFO *)alloc_buff;
tz_info = (TIME_ZONE_INFO*)alloc_buff;
memcpy(tz_info, &tmp_tz_info, sizeof(TIME_ZONE_INFO));
tz_name_buff= alloc_buff + sizeof(TIME_ZONE_INFO);
tz_name_buff = alloc_buff + sizeof(TIME_ZONE_INFO);
/*
By writing zero to the end we guarantee that we can call ptr()
instead of c_ptr() for time zone name.
@ -506,32 +483,29 @@ static TIME_ZONE_INFO* tz_load_from_open_tables(const String *tz_name, TABLE_LIS
/*
Now we will allocate memory and init TIME_ZONE_INFO structure.
*/
if (!(alloc_buff= (char*) alloc_root(&tz_storage,
ALIGN_SIZE(sizeof(my_time_t) *
tz_info->timecnt) +
ALIGN_SIZE(tz_info->timecnt) +
if (!(alloc_buff = (char*)alloc_root(&tz_storage, ALIGN_SIZE(sizeof(my_time_t) * tz_info->timecnt) +
ALIGN_SIZE(tz_info->timecnt) +
#ifdef ABBR_ARE_USED
ALIGN_SIZE(tz_info->charcnt) +
ALIGN_SIZE(tz_info->charcnt) +
#endif
sizeof(TRAN_TYPE_INFO) *
tz_info->typecnt)))
sizeof(TRAN_TYPE_INFO) * tz_info->typecnt)))
{
sql_print_error("Out of memory while loading time zone description");
goto end;
}
tz_info->ats= (my_time_t *) alloc_buff;
tz_info->ats = (my_time_t*)alloc_buff;
memcpy(tz_info->ats, ats, tz_info->timecnt * sizeof(my_time_t));
alloc_buff+= ALIGN_SIZE(sizeof(my_time_t) * tz_info->timecnt);
tz_info->types= (uchar *)alloc_buff;
alloc_buff += ALIGN_SIZE(sizeof(my_time_t) * tz_info->timecnt);
tz_info->types = (uchar*)alloc_buff;
memcpy(tz_info->types, types, tz_info->timecnt);
alloc_buff+= ALIGN_SIZE(tz_info->timecnt);
alloc_buff += ALIGN_SIZE(tz_info->timecnt);
#ifdef ABBR_ARE_USED
tz_info->chars= alloc_buff;
tz_info->chars = alloc_buff;
memcpy(tz_info->chars, chars, tz_info->charcnt);
alloc_buff+= ALIGN_SIZE(tz_info->charcnt);
alloc_buff += ALIGN_SIZE(tz_info->charcnt);
#endif
tz_info->ttis= (TRAN_TYPE_INFO *)alloc_buff;
tz_info->ttis = (TRAN_TYPE_INFO*)alloc_buff;
memcpy(tz_info->ttis, ttis, tz_info->typecnt * sizeof(TRAN_TYPE_INFO));
/* Build reversed map. */
@ -544,35 +518,34 @@ static TIME_ZONE_INFO* tz_load_from_open_tables(const String *tz_name, TABLE_LIS
/*
Loading of time zone succeeded
*/
return_val= tz_info;
return_val = tz_info;
end:
if (table && table->file->inited)
(void) table->file->ha_index_end();
(void)table->file->ha_index_end();
DBUG_RETURN(return_val);
}
TIME_ZONE_INFO* my_tzinfo_find(THD *thd, const String *name)
TIME_ZONE_INFO* my_tzinfo_find(THD* thd, const String* name)
{
TIME_ZONE_INFO* result_tzinfo= 0;
TIME_ZONE_INFO* result_tzinfo = 0;
long offset;
DBUG_ENTER("my_tz_find");
DBUG_PRINT("enter", ("time zone name='%s'\n",
name ? ((String *)name)->c_ptr_safe() : "NULL"));
DBUG_PRINT("enter", ("time zone name='%s'\n", name ? ((String*)name)->c_ptr_safe() : "NULL"));
if (!name || name->is_empty())
DBUG_RETURN(0);
if (!timeZoneToOffset(name->ptr(), name->length(), &offset))
{
return NULL;
return NULL;
}
else
{
result_tzinfo= 0;
my_tz_init(thd,NULL, 0);
result_tzinfo = 0;
my_tz_init(thd, NULL, 0);
if (time_zone_tables_exist)
{
TABLE_LIST tz_tables[MY_TZ_TABLES_COUNT];
@ -581,12 +554,12 @@ TIME_ZONE_INFO* my_tzinfo_find(THD *thd, const String *name)
Allocate start_new_trans with malloc as it's > 4000 bytes and this
function can be called deep inside a stored procedure
*/
start_new_trans *new_trans= new start_new_trans(thd);
start_new_trans* new_trans = new start_new_trans(thd);
tz_init_table_list(tz_tables);
init_mdl_requests(tz_tables);
if (!open_system_tables_for_read(thd, tz_tables))
{
result_tzinfo= tz_load_from_open_tables(name, tz_tables);
result_tzinfo = tz_load_from_open_tables(name, tz_tables);
thd->commit_whole_transaction_and_close_tables();
}
new_trans->restore_old_transaction();
@ -597,4 +570,4 @@ TIME_ZONE_INFO* my_tzinfo_find(THD *thd, const String *name)
DBUG_RETURN(result_tzinfo);
}
}
} // namespace cal_impl_if

View File

@ -26,8 +26,7 @@ using namespace dataconvert;
namespace cal_impl_if
{
TIME_ZONE_INFO* my_tzinfo_find(THD *thd, const String *name);
TIME_ZONE_INFO* my_tzinfo_find(THD* thd, const String* name);
}

View File

@ -17,10 +17,10 @@
MA 02110-1301, USA. */
/***********************************************************************
* $Id: ha_view.cpp 9642 2013-06-24 14:57:42Z rdempsey $
*
*
***********************************************************************/
* $Id: ha_view.cpp 9642 2013-06-24 14:57:42Z rdempsey $
*
*
***********************************************************************/
#define PREFER_MY_CONFIG_H
#include <my_config.h>
@ -46,147 +46,156 @@ using namespace execplan;
namespace cal_impl_if
{
extern uint32_t buildJoin(gp_walk_info& gwi, List<TABLE_LIST>& join_list,
std::stack<execplan::ParseTree*>& outerJoinStack);
std::stack<execplan::ParseTree*>& outerJoinStack);
extern string getViewName(TABLE_LIST* table_ptr);
CalpontSystemCatalog::TableAliasName& View::viewName()
{
return fViewName;
return fViewName;
}
void View::viewName(execplan::CalpontSystemCatalog::TableAliasName& viewName)
{
fViewName = viewName;
fViewName = viewName;
}
void View::transform()
{
CalpontSelectExecutionPlan* csep = new CalpontSelectExecutionPlan();
csep->sessionID(fParentGwip->sessionid);
CalpontSelectExecutionPlan* csep = new CalpontSelectExecutionPlan();
csep->sessionID(fParentGwip->sessionid);
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fParentGwip->thd;
// gwi for the sub query
gp_walk_info gwi;
gwi.thd = fParentGwip->thd;
uint32_t sessionID = csep->sessionID();
gwi.sessionid = sessionID;
boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID);
csc->identity(CalpontSystemCatalog::FE);
gwi.csc = csc;
uint32_t sessionID = csep->sessionID();
gwi.sessionid = sessionID;
boost::shared_ptr<CalpontSystemCatalog> csc = CalpontSystemCatalog::makeCalpontSystemCatalog(sessionID);
csc->identity(CalpontSystemCatalog::FE);
gwi.csc = csc;
// traverse the table list of the view
TABLE_LIST* table_ptr = fSelect.get_table_list();
CalpontSelectExecutionPlan::SelectList derivedTbList;
// traverse the table list of the view
TABLE_LIST* table_ptr = fSelect.get_table_list();
CalpontSelectExecutionPlan::SelectList derivedTbList;
// @bug 1796. Remember table order on the FROM list.
gwi.clauseType = FROM;
// @bug 1796. Remember table order on the FROM list.
gwi.clauseType = FROM;
try
try
{
for (; table_ptr; table_ptr = table_ptr->next_local)
{
for (; table_ptr; table_ptr = table_ptr->next_local)
// mysql put vtable here for from sub. we ignore it
if (string(table_ptr->table_name.str).find("$vtable") != string::npos)
continue;
string viewName = getViewName(table_ptr);
if (lower_case_table_names)
{
boost::algorithm::to_lower(viewName);
}
if (table_ptr->derived)
{
SELECT_LEX* select_cursor = table_ptr->derived->first_select();
FromSubQuery* fromSub = new FromSubQuery(gwi, select_cursor);
string alias(table_ptr->alias.str);
if (lower_case_table_names)
{
// mysql put vtable here for from sub. we ignore it
if (string(table_ptr->table_name.str).find("$vtable") != string::npos)
continue;
string viewName = getViewName(table_ptr);
if (lower_case_table_names)
{
boost::algorithm::to_lower(viewName);
}
if (table_ptr->derived)
{
SELECT_LEX* select_cursor = table_ptr->derived->first_select();
FromSubQuery* fromSub = new FromSubQuery(gwi, select_cursor);
string alias(table_ptr->alias.str);
if (lower_case_table_names)
{
boost::algorithm::to_lower(alias);
}
gwi.viewName = make_aliasview("", alias, table_ptr->belong_to_view->alias.str, "", true, lower_case_table_names);
fromSub->alias(alias);
gwi.derivedTbList.push_back(SCSEP(fromSub->transform()));
// set alias to both table name and alias name of the derived table
CalpontSystemCatalog::TableAliasName tn = make_aliasview("", "", alias, viewName);
gwi.tbList.push_back(tn);
gwi.tableMap[tn] = make_pair(0, table_ptr);
// TODO MCOL-2178 isUnion member only assigned, never used
// MIGR::infinidb_vtable.isUnion = true; //by-pass the 2nd pass of rnd_init
}
else if (table_ptr->view)
{
// for nested view, the view name is vout.vin... format
CalpontSystemCatalog::TableAliasName tn = make_aliasview(table_ptr->db.str, table_ptr->table_name.str, table_ptr->alias.str, viewName, true, lower_case_table_names);
gwi.viewName = make_aliastable(table_ptr->db.str, table_ptr->table_name.str, viewName, true, lower_case_table_names);
View* view = new View(*table_ptr->view->first_select_lex(), &gwi);
view->viewName(gwi.viewName);
gwi.viewList.push_back(view);
view->transform();
}
else
{
// check foreign engine tables
bool columnStore = (table_ptr->table ? isMCSTable(table_ptr->table) : true);
// trigger system catalog cache
if (columnStore)
csc->columnRIDs(make_table(table_ptr->db.str, table_ptr->table_name.str, lower_case_table_names), true);
CalpontSystemCatalog::TableAliasName tn = make_aliasview(table_ptr->db.str, table_ptr->table_name.str, table_ptr->alias.str, viewName, columnStore, lower_case_table_names);
gwi.tbList.push_back(tn);
gwi.tableMap[tn] = make_pair(0, table_ptr);
fParentGwip->tableMap[tn] = make_pair(0, table_ptr);
}
boost::algorithm::to_lower(alias);
}
gwi.viewName =
make_aliasview("", alias, table_ptr->belong_to_view->alias.str, "", true, lower_case_table_names);
fromSub->alias(alias);
gwi.derivedTbList.push_back(SCSEP(fromSub->transform()));
// set alias to both table name and alias name of the derived table
CalpontSystemCatalog::TableAliasName tn = make_aliasview("", "", alias, viewName);
gwi.tbList.push_back(tn);
gwi.tableMap[tn] = make_pair(0, table_ptr);
// TODO MCOL-2178 isUnion member only assigned, never used
// MIGR::infinidb_vtable.isUnion = true; //by-pass the 2nd pass of rnd_init
}
else if (table_ptr->view)
{
// for nested view, the view name is vout.vin... format
CalpontSystemCatalog::TableAliasName tn =
make_aliasview(table_ptr->db.str, table_ptr->table_name.str, table_ptr->alias.str, viewName, true,
lower_case_table_names);
gwi.viewName = make_aliastable(table_ptr->db.str, table_ptr->table_name.str, viewName, true,
lower_case_table_names);
View* view = new View(*table_ptr->view->first_select_lex(), &gwi);
view->viewName(gwi.viewName);
gwi.viewList.push_back(view);
view->transform();
}
else
{
// check foreign engine tables
bool columnStore = (table_ptr->table ? isMCSTable(table_ptr->table) : true);
if (gwi.fatalParseError)
{
setError(gwi.thd, ER_INTERNAL_ERROR, gwi.parseErrorText);
return;
}
// trigger system catalog cache
if (columnStore)
csc->columnRIDs(make_table(table_ptr->db.str, table_ptr->table_name.str, lower_case_table_names),
true);
CalpontSystemCatalog::TableAliasName tn =
make_aliasview(table_ptr->db.str, table_ptr->table_name.str, table_ptr->alias.str, viewName,
columnStore, lower_case_table_names);
gwi.tbList.push_back(tn);
gwi.tableMap[tn] = make_pair(0, table_ptr);
fParentGwip->tableMap[tn] = make_pair(0, table_ptr);
}
}
catch (IDBExcept& ie)
if (gwi.fatalParseError)
{
setError(gwi.thd, ER_INTERNAL_ERROR, ie.what());
CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID);
return;
}
catch (...)
{
string emsg = IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR);
setError(gwi.thd, ER_INTERNAL_ERROR, emsg);
CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID);
return;
setError(gwi.thd, ER_INTERNAL_ERROR, gwi.parseErrorText);
return;
}
}
catch (IDBExcept& ie)
{
setError(gwi.thd, ER_INTERNAL_ERROR, ie.what());
CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID);
return;
}
catch (...)
{
string emsg = IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR);
setError(gwi.thd, ER_INTERNAL_ERROR, emsg);
CalpontSystemCatalog::removeCalpontSystemCatalog(sessionID);
return;
}
// merge table list to parent select
fParentGwip->tbList.insert(fParentGwip->tbList.end(), gwi.tbList.begin(), gwi.tbList.end());
fParentGwip->derivedTbList.insert(fParentGwip->derivedTbList.end(), gwi.derivedTbList.begin(), gwi.derivedTbList.end());
fParentGwip->correlatedTbNameVec.insert(fParentGwip->correlatedTbNameVec.end(), gwi.correlatedTbNameVec.begin(), gwi.correlatedTbNameVec.end());
// merge table list to parent select
fParentGwip->tbList.insert(fParentGwip->tbList.end(), gwi.tbList.begin(), gwi.tbList.end());
fParentGwip->derivedTbList.insert(fParentGwip->derivedTbList.end(), gwi.derivedTbList.begin(),
gwi.derivedTbList.end());
fParentGwip->correlatedTbNameVec.insert(fParentGwip->correlatedTbNameVec.end(),
gwi.correlatedTbNameVec.begin(), gwi.correlatedTbNameVec.end());
// merge view list to parent
fParentGwip->viewList.insert(fParentGwip->viewList.end(), gwi.viewList.begin(), gwi.viewList.end());
// merge view list to parent
fParentGwip->viewList.insert(fParentGwip->viewList.end(), gwi.viewList.begin(), gwi.viewList.end());
// merge non-collapsed outer join to parent select
stack<ParseTree*> tmpstack;
// merge non-collapsed outer join to parent select
stack<ParseTree*> tmpstack;
while (!gwi.ptWorkStack.empty())
{
tmpstack.push(gwi.ptWorkStack.top());
gwi.ptWorkStack.pop();
}
while (!gwi.ptWorkStack.empty())
{
tmpstack.push(gwi.ptWorkStack.top());
gwi.ptWorkStack.pop();
}
while (!tmpstack.empty())
{
fParentGwip->ptWorkStack.push(tmpstack.top());
tmpstack.pop();
}
while (!tmpstack.empty())
{
fParentGwip->ptWorkStack.push(tmpstack.top());
tmpstack.pop();
}
}
uint32_t View::processJoin(gp_walk_info& gwi, std::stack<execplan::ParseTree*>& outerJoinStack)
{
return buildJoin(gwi, fSelect.top_join_list, outerJoinStack);
return buildJoin(gwi, fSelect.top_join_list, outerJoinStack);
}
}
} // namespace cal_impl_if

View File

@ -16,10 +16,10 @@
MA 02110-1301, USA. */
/***********************************************************************
* $Id: ha_view.h 9210 2013-01-21 14:10:42Z rdempsey $
*
*
***********************************************************************/
* $Id: ha_view.h 9210 2013-01-21 14:10:42Z rdempsey $
*
*
***********************************************************************/
/** @file */
/** class View interface */
@ -37,30 +37,31 @@ class CalpontSystemCatalog;
namespace cal_impl_if
{
class View
{
public:
View(SELECT_LEX& select, gp_walk_info* parentGwip) :
fSelect(select),
fParentGwip(parentGwip) {}
~View() {}
public:
View(SELECT_LEX& select, gp_walk_info* parentGwip) : fSelect(select), fParentGwip(parentGwip)
{
}
~View()
{
}
execplan::CalpontSystemCatalog::TableAliasName& viewName();
void viewName(execplan::CalpontSystemCatalog::TableAliasName& viewName);
execplan::CalpontSystemCatalog::TableAliasName& viewName();
void viewName(execplan::CalpontSystemCatalog::TableAliasName& viewName);
/** get execution plan for this view. merge the table list and join list to the
parent select.
*/
void transform();
uint32_t processJoin(gp_walk_info& gwi, std::stack<execplan::ParseTree*>&);
/** get execution plan for this view. merge the table list and join list to the
parent select.
*/
void transform();
uint32_t processJoin(gp_walk_info& gwi, std::stack<execplan::ParseTree*>&);
private:
SELECT_LEX fSelect;
gp_walk_info* fParentGwip;
execplan::CalpontSystemCatalog::TableAliasName fViewName;
private:
SELECT_LEX fSelect;
gp_walk_info* fParentGwip;
execplan::CalpontSystemCatalog::TableAliasName fViewName;
};
}
} // namespace cal_impl_if
#endif

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
//One include file to deal with all the MySQL pollution of the
// One include file to deal with all the MySQL pollution of the
// global namespace
//
// Don't include ANY mysql headers anywhere except here!
@ -28,14 +28,15 @@
#ifdef _MSC_VER
#include <stdint.h>
#if _MSC_VER >= 1800
template <class T> bool isnan(T);
template <class T>
bool isnan(T);
#endif
#endif
//#define INFINIDB_DEBUG
//#define DEBUG_WALK_COND
#define MYSQL_SERVER 1 //needed for definition of struct THD in mysql_priv.h
#define MYSQL_SERVER 1 // needed for definition of struct THD in mysql_priv.h
#define USE_CALPONT_REGEX
#undef LOG_INFO
@ -54,7 +55,7 @@ template <class T> bool isnan(T);
#endif
#define DBUG_ON 1
#undef DBUG_OFF
#undef DBUG_OFF
#else
#undef SAFE_MUTEX
#undef SAFEMALLOC
@ -111,12 +112,12 @@ namespace
inline char* idb_mysql_query_str(THD* thd)
{
#if MYSQL_VERSION_ID >= 50172
return thd->query();
return thd->query();
#else
return thd->query;
return thd->query;
#endif
}
}
} // namespace
#endif
// vim:ts=4 sw=4:

View File

@ -22,65 +22,72 @@ int is_columnstore_files_plugin_init(void* p);
int is_columnstore_tables_plugin_init(void* p);
int is_columnstore_columns_plugin_init(void* p);
class InformationSchemaCond
{
StringBuffer<MAX_FIELD_WIDTH> mBufferTableName;
StringBuffer<MAX_FIELD_WIDTH> mBufferTableSchema;
String *mTableName;
String *mTableSchema;
public:
InformationSchemaCond()
:mBufferTableName(system_charset_info),
mBufferTableSchema(system_charset_info),
mTableName(nullptr),
mTableSchema(nullptr)
{ }
const String *tableName() const { return mTableName; }
const String *tableSchema() const { return mTableSchema; }
static bool eqName(const String &a, const std::string &b)
{
return a.length() == b.length() && !memcmp(a.ptr(), b.data(), a.length());
}
static bool eqName(const String *a, const std::string &b)
{
return !a || eqName(*a, b);
}
bool match(const std::string &schema, const std::string &table) const
{
return eqName(mTableName, table) && eqName(mTableSchema, schema);
}
StringBuffer<MAX_FIELD_WIDTH> mBufferTableName;
StringBuffer<MAX_FIELD_WIDTH> mBufferTableSchema;
String* mTableName;
String* mTableSchema;
void getCondItem(Item_field *item_field, Item *item_const)
{
if (strcasecmp(item_field->field_name.str, "table_name") == 0)
{
mTableName = item_const->val_str(&mBufferTableName);
}
else if (strcasecmp(item_field->field_name.str, "table_schema") == 0)
{
mTableSchema = item_const->val_str(&mBufferTableSchema);
}
}
public:
InformationSchemaCond()
: mBufferTableName(system_charset_info)
, mBufferTableSchema(system_charset_info)
, mTableName(nullptr)
, mTableSchema(nullptr)
{
}
const String* tableName() const
{
return mTableName;
}
const String* tableSchema() const
{
return mTableSchema;
}
static bool eqName(const String& a, const std::string& b)
{
return a.length() == b.length() && !memcmp(a.ptr(), b.data(), a.length());
}
static bool eqName(const String* a, const std::string& b)
{
return !a || eqName(*a, b);
}
bool match(const std::string& schema, const std::string& table) const
{
return eqName(mTableName, table) && eqName(mTableSchema, schema);
}
void getCondItemBoolFunc2(Item_bool_func2 *func)
void getCondItem(Item_field* item_field, Item* item_const)
{
if (strcasecmp(item_field->field_name.str, "table_name") == 0)
{
Item_field *field = dynamic_cast<Item_field*>(func->arguments()[0]->real_item());
if (field && func->arguments()[1]->const_item())
getCondItem(field, func->arguments()[1]);
mTableName = item_const->val_str(&mBufferTableName);
}
else if (strcasecmp(item_field->field_name.str, "table_schema") == 0)
{
mTableSchema = item_const->val_str(&mBufferTableSchema);
}
}
void getCondItems(COND* cond)
void getCondItemBoolFunc2(Item_bool_func2* func)
{
Item_field* field = dynamic_cast<Item_field*>(func->arguments()[0]->real_item());
if (field && func->arguments()[1]->const_item())
getCondItem(field, func->arguments()[1]);
}
void getCondItems(COND* cond)
{
if (Item_bool_func2* func = dynamic_cast<Item_bool_func2*>(cond))
{
if (Item_bool_func2 *func = dynamic_cast<Item_bool_func2*>(cond))
{
getCondItemBoolFunc2(func);
}
else if (Item_cond_and *subcond = dynamic_cast<Item_cond_and*>(cond))
{
List_iterator<Item> li(*(subcond)->argument_list());
for (Item *item = li++; item ; item = li++ )
getCondItems(item);
}
getCondItemBoolFunc2(func);
}
else if (Item_cond_and* subcond = dynamic_cast<Item_cond_and*>(cond))
{
List_iterator<Item> li(*(subcond)->argument_list());
for (Item* item = li++; item; item = li++)
getCondItems(item);
}
}
};

View File

@ -32,12 +32,10 @@
#include "is_columnstore.h"
using namespace logging;
// Required declaration as it isn't in a MairaDB include
bool schema_table_store_record(THD* thd, TABLE* table);
ST_FIELD_INFO is_columnstore_columns_fields[] =
{
ST_FIELD_INFO is_columnstore_columns_fields[] = {
Show::Column("TABLE_SCHEMA", Show::Varchar(64), NOT_NULL),
Show::Column("TABLE_NAME", Show::Varchar(64), NOT_NULL),
Show::Column("COLUMN_NAME", Show::Varchar(64), NOT_NULL),
@ -54,159 +52,153 @@ ST_FIELD_INFO is_columnstore_columns_fields[] =
Show::Column("NUMERIC_SCALE", Show::ULong(0), NOT_NULL),
Show::Column("IS_AUTOINCREMENT", Show::STiny(0), NOT_NULL),
Show::Column("COMPRESSION_TYPE", Show::Varchar(64), NOT_NULL),
Show::CEnd()
};
Show::CEnd()};
static int is_columnstore_columns_fill(THD* thd, TABLE_LIST* tables, COND* cond)
{
CHARSET_INFO* cs = system_charset_info;
TABLE* table = tables->table;
InformationSchemaCond isCond;
CHARSET_INFO* cs = system_charset_info;
TABLE* table = tables->table;
InformationSchemaCond isCond;
boost::shared_ptr<execplan::CalpontSystemCatalog> systemCatalogPtr =
execplan::CalpontSystemCatalog::makeCalpontSystemCatalog(execplan::CalpontSystemCatalog::idb_tid2sid(thd->thread_id));
boost::shared_ptr<execplan::CalpontSystemCatalog> systemCatalogPtr =
execplan::CalpontSystemCatalog::makeCalpontSystemCatalog(
execplan::CalpontSystemCatalog::idb_tid2sid(thd->thread_id));
const std::vector< std::pair<execplan::CalpontSystemCatalog::OID, execplan::CalpontSystemCatalog::TableName> > catalog_tables
= systemCatalogPtr->getTables();
const std::vector<
std::pair<execplan::CalpontSystemCatalog::OID, execplan::CalpontSystemCatalog::TableName> >
catalog_tables = systemCatalogPtr->getTables();
systemCatalogPtr->identity(execplan::CalpontSystemCatalog::FE);
systemCatalogPtr->identity(execplan::CalpontSystemCatalog::FE);
if (cond)
if (cond)
{
isCond.getCondItems(cond);
}
for (std::vector<std::pair<execplan::CalpontSystemCatalog::OID,
execplan::CalpontSystemCatalog::TableName> >::const_iterator it =
catalog_tables.begin();
it != catalog_tables.end(); ++it)
{
if (!isCond.match((*it).second.schema, (*it).second.table))
continue;
execplan::CalpontSystemCatalog::RIDList column_rid_list;
// Note a table may get dropped as you iterate over the list of tables.
// So simply ignore the dropped table.
try
{
isCond.getCondItems(cond);
column_rid_list = systemCatalogPtr->columnRIDs((*it).second, true, lower_case_table_names);
}
catch (IDBExcept& ex)
{
if (ex.errorCode() == ERR_TABLE_NOT_IN_CATALOG)
{
continue;
}
else
{
return 1;
}
}
for (std::vector<std::pair<execplan::CalpontSystemCatalog::OID, execplan::CalpontSystemCatalog::TableName> >::const_iterator it = catalog_tables.begin();
it != catalog_tables.end(); ++it)
for (size_t col_num = 0; col_num < column_rid_list.size(); col_num++)
{
if (!isCond.match((*it).second.schema, (*it).second.table))
continue;
execplan::CalpontSystemCatalog::TableColName tcn =
systemCatalogPtr->colName(column_rid_list[col_num].objnum);
execplan::CalpontSystemCatalog::ColType ct = systemCatalogPtr->colType(column_rid_list[col_num].objnum);
execplan::CalpontSystemCatalog::RIDList column_rid_list;
table->field[0]->store(tcn.schema.c_str(), tcn.schema.length(), cs);
table->field[1]->store(tcn.table.c_str(), tcn.table.length(), cs);
table->field[2]->store(tcn.column.c_str(), tcn.column.length(), cs);
table->field[3]->store(column_rid_list[col_num].objnum);
// Note a table may get dropped as you iterate over the list of tables.
// So simply ignore the dropped table.
try
{
column_rid_list = systemCatalogPtr->columnRIDs((*it).second, true, lower_case_table_names);
}
catch (IDBExcept& ex)
{
if (ex.errorCode() == ERR_TABLE_NOT_IN_CATALOG)
{
continue;
}
else
{
return 1;
}
}
if (ct.ddn.dictOID == std::numeric_limits<int32_t>::min())
{
table->field[4]->set_null();
}
else
{
table->field[4]->set_notnull();
table->field[4]->store(ct.ddn.dictOID);
}
for (size_t col_num = 0; col_num < column_rid_list.size(); col_num++)
{
execplan::CalpontSystemCatalog::TableColName tcn = systemCatalogPtr->colName(column_rid_list[col_num].objnum);
execplan::CalpontSystemCatalog::ColType ct = systemCatalogPtr->colType(column_rid_list[col_num].objnum);
if (ct.ddn.listOID == std::numeric_limits<int32_t>::min())
{
table->field[5]->set_null();
}
else
{
table->field[5]->set_notnull();
table->field[5]->store(ct.ddn.listOID);
}
table->field[0]->store(tcn.schema.c_str(), tcn.schema.length(), cs);
table->field[1]->store(tcn.table.c_str(), tcn.table.length(), cs);
table->field[2]->store(tcn.column.c_str(), tcn.column.length(), cs);
table->field[3]->store(column_rid_list[col_num].objnum);
if (ct.ddn.treeOID == std::numeric_limits<int32_t>::min())
{
table->field[6]->set_null();
}
else
{
table->field[6]->set_notnull();
table->field[6]->store(ct.ddn.treeOID);
}
if (ct.ddn.dictOID == std::numeric_limits<int32_t>::min())
{
table->field[4]->set_null();
}
else
{
table->field[4]->set_notnull();
table->field[4]->store(ct.ddn.dictOID);
}
std::string data_type = execplan::colDataTypeToString(ct.colDataType);
table->field[7]->store(data_type.c_str(), data_type.length(), cs);
table->field[8]->store(ct.colWidth);
table->field[9]->store(ct.colPosition);
if (ct.ddn.listOID == std::numeric_limits<int32_t>::min())
{
table->field[5]->set_null();
}
else
{
table->field[5]->set_notnull();
table->field[5]->store(ct.ddn.listOID);
}
if (ct.defaultValue.empty())
{
table->field[10]->set_null();
}
else
{
table->field[10]->set_notnull();
table->field[10]->store(ct.defaultValue.c_str(), ct.defaultValue.length(), cs);
}
if (ct.ddn.treeOID == std::numeric_limits<int32_t>::min())
{
table->field[6]->set_null();
}
else
{
table->field[6]->set_notnull();
table->field[6]->store(ct.ddn.treeOID);
}
table->field[11]->store(ct.autoincrement);
table->field[12]->store(ct.precision);
table->field[13]->store(ct.scale);
std::string data_type = execplan::colDataTypeToString(ct.colDataType);
table->field[7]->store(data_type.c_str(), data_type.length(), cs);
table->field[8]->store(ct.colWidth);
table->field[9]->store(ct.colPosition);
if (ct.constraintType != execplan::CalpontSystemCatalog::NOTNULL_CONSTRAINT)
{
table->field[14]->store(true);
}
else
{
table->field[14]->store(false);
}
if (ct.defaultValue.empty())
{
table->field[10]->set_null();
}
else
{
table->field[10]->set_notnull();
table->field[10]->store(ct.defaultValue.c_str(), ct.defaultValue.length(), cs);
}
std::string compression_type;
table->field[11]->store(ct.autoincrement);
table->field[12]->store(ct.precision);
table->field[13]->store(ct.scale);
switch (ct.compressionType)
{
case 0: compression_type = "None"; break;
if (ct.constraintType != execplan::CalpontSystemCatalog::NOTNULL_CONSTRAINT)
{
table->field[14]->store(true);
}
else
{
table->field[14]->store(false);
}
case 2: compression_type = "Snappy"; break;
std::string compression_type;
case 3: compression_type = "LZ4"; break;
switch (ct.compressionType)
{
case 0:
compression_type = "None";
break;
default: compression_type = "Unknown"; break;
}
case 2:
compression_type = "Snappy";
break;
table->field[15]->store(compression_type.c_str(), compression_type.length(), cs);
case 3:
compression_type = "LZ4";
break;
default:
compression_type = "Unknown";
break;
}
table->field[15]->store(compression_type.c_str(), compression_type.length(), cs);
if (schema_table_store_record(thd, table))
return 1;
}
if (schema_table_store_record(thd, table))
return 1;
}
}
return 0;
return 0;
}
int is_columnstore_columns_plugin_init(void* p)
{
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = is_columnstore_columns_fields;
schema->fill_table = is_columnstore_columns_fill;
return 0;
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*)p;
schema->fields_info = is_columnstore_columns_fields;
schema->fill_table = is_columnstore_columns_fill;
return 0;
}

View File

@ -34,292 +34,269 @@
// Required declaration as it isn't in a MairaDB include
bool schema_table_store_record(THD* thd, TABLE* table);
ST_FIELD_INFO is_columnstore_extents_fields[] =
{
Show::Column("OBJECT_ID", Show::ULong(0), NOT_NULL), // 0
Show::Column("OBJECT_TYPE", Show::Varchar(64), NOT_NULL), // 1
Show::Column("LOGICAL_BLOCK_START", Show::SLonglong(0), NOT_NULL), // 2
Show::Column("LOGICAL_BLOCK_END", Show::SLonglong(0), NOT_NULL), // 3
ST_FIELD_INFO is_columnstore_extents_fields[] = {
Show::Column("OBJECT_ID", Show::ULong(0), NOT_NULL), // 0
Show::Column("OBJECT_TYPE", Show::Varchar(64), NOT_NULL), // 1
Show::Column("LOGICAL_BLOCK_START", Show::SLonglong(0), NOT_NULL), // 2
Show::Column("LOGICAL_BLOCK_END", Show::SLonglong(0), NOT_NULL), // 3
// length=3800 here because sql/sql_i_s.h sets
// decimal_precision() as (length / 100) % 100). Not sure why.
Show::Column("MIN_VALUE", Show::Decimal(3800), NULLABLE), // 4
Show::Column("MAX_VALUE", Show::Decimal(3800), NULLABLE), // 5
Show::Column("WIDTH", Show::ULong(0), NOT_NULL), // 6
Show::Column("DBROOT", Show::ULong(0), NOT_NULL), // 7
Show::Column("PARTITION_ID", Show::ULong(0), NOT_NULL), // 8
Show::Column("SEGMENT_ID", Show::ULong(0), NOT_NULL), // 9
Show::Column("BLOCK_OFFSET", Show::ULong(0), NOT_NULL), // 10
Show::Column("MAX_BLOCKS", Show::ULong(0), NOT_NULL), // 11
Show::Column("HIGH_WATER_MARK", Show::ULong(0), NOT_NULL), // 12
Show::Column("STATE", Show::Varchar(64), NOT_NULL), // 13
Show::Column("STATUS", Show::Varchar(64), NOT_NULL), // 14
Show::Column("DATA_SIZE", Show::ULonglong(0), NOT_NULL), // 15
Show::CEnd()
};
Show::Column("MIN_VALUE", Show::Decimal(3800), NULLABLE), // 4
Show::Column("MAX_VALUE", Show::Decimal(3800), NULLABLE), // 5
Show::Column("WIDTH", Show::ULong(0), NOT_NULL), // 6
Show::Column("DBROOT", Show::ULong(0), NOT_NULL), // 7
Show::Column("PARTITION_ID", Show::ULong(0), NOT_NULL), // 8
Show::Column("SEGMENT_ID", Show::ULong(0), NOT_NULL), // 9
Show::Column("BLOCK_OFFSET", Show::ULong(0), NOT_NULL), // 10
Show::Column("MAX_BLOCKS", Show::ULong(0), NOT_NULL), // 11
Show::Column("HIGH_WATER_MARK", Show::ULong(0), NOT_NULL), // 12
Show::Column("STATE", Show::Varchar(64), NOT_NULL), // 13
Show::Column("STATUS", Show::Varchar(64), NOT_NULL), // 14
Show::Column("DATA_SIZE", Show::ULonglong(0), NOT_NULL), // 15
Show::CEnd()};
static int generate_result(BRM::OID_t oid, BRM::DBRM* emp, TABLE* table, THD* thd)
{
CHARSET_INFO* cs = system_charset_info;
std::vector<struct BRM::EMEntry> entries;
std::vector<struct BRM::EMEntry>::iterator iter;
std::vector<struct BRM::EMEntry>::iterator end;
CHARSET_INFO* cs = system_charset_info;
std::vector<struct BRM::EMEntry> entries;
std::vector<struct BRM::EMEntry>::iterator iter;
std::vector<struct BRM::EMEntry>::iterator end;
emp->getExtents(oid, entries, false, false, true);
emp->getExtents(oid, entries, false, false, true);
if (entries.size() == 0)
return 0;
if (entries.size() == 0)
return 0;
iter = entries.begin();
end = entries.end();
iter = entries.begin();
end = entries.end();
while (iter != end)
while (iter != end)
{
table->field[0]->store(oid);
if (iter->colWid > 0)
{
table->field[0]->store(oid);
table->field[1]->store("Column", strlen("Column"), cs);
if (iter->colWid > 0)
if (iter->colWid != datatypes::MAXDECIMALWIDTH)
{
if (iter->partition.cprange.loVal == std::numeric_limits<int64_t>::max() ||
iter->partition.cprange.loVal <= (std::numeric_limits<int64_t>::min() + 1))
{
table->field[1]->store("Column", strlen("Column"), cs);
if (iter->colWid != datatypes::MAXDECIMALWIDTH)
{
if (iter->partition.cprange.loVal == std::numeric_limits<int64_t>::max() ||
iter->partition.cprange.loVal <= (std::numeric_limits<int64_t>::min() + 1))
{
table->field[4]->set_null();
}
else
{
table->field[4]->set_notnull();
table->field[4]->store((longlong) iter->partition.cprange.loVal, false);
}
if (iter->partition.cprange.hiVal <= (std::numeric_limits<int64_t>::min() + 1))
{
table->field[5]->set_null();
}
else
{
table->field[5]->set_notnull();
table->field[5]->store((longlong) iter->partition.cprange.hiVal, false);
}
}
else
{
if (iter->partition.cprange.bigLoVal == utils::maxInt128 ||
iter->partition.cprange.bigLoVal <= (utils::minInt128 + 1))
{
table->field[4]->set_null();
}
else
{
table->field[4]->set_notnull();
std::string decAsAStr = datatypes::TSInt128(iter->partition.cprange.bigLoVal)
.toString();
table->field[4]->store(decAsAStr.c_str(),
decAsAStr.length(),
table->field[4]->charset());
}
if (iter->partition.cprange.bigHiVal <= (utils::minInt128 + 1))
{
table->field[5]->set_null();
}
else
{
table->field[5]->set_notnull();
std::string decAsAStr = datatypes::TSInt128(iter->partition.cprange.bigHiVal)
.toString();
table->field[5]->store(decAsAStr.c_str(),
decAsAStr.length(),
table->field[5]->charset());
}
}
table->field[6]->store(iter->colWid);
table->field[4]->set_null();
}
else
{
table->field[1]->store("Dictionary", strlen("Dictionary"), cs);
table->field[4]->set_null();
table->field[5]->set_null();
table->field[6]->store(8192);
table->field[4]->set_notnull();
table->field[4]->store((longlong)iter->partition.cprange.loVal, false);
}
table->field[2]->store(iter->range.start);
table->field[3]->store(iter->range.start + (iter->range.size * 1024) - 1);
table->field[7]->store(iter->dbRoot);
table->field[8]->store(iter->partitionNum);
table->field[9]->store(iter->segmentNum);
table->field[10]->store(iter->blockOffset);
table->field[11]->store(iter->range.size * 1024);
table->field[12]->store(iter->HWM);
switch (iter->partition.cprange.isValid)
if (iter->partition.cprange.hiVal <= (std::numeric_limits<int64_t>::min() + 1))
{
case 0:
table->field[13]->store("Invalid", strlen("Invalid"), cs);
break;
case 1:
table->field[13]->store("Updating", strlen("Updating"), cs);
break;
case 2:
table->field[13]->store("Valid", strlen("Valid"), cs);
break;
default:
table->field[13]->store("Unknown", strlen("Unknown"), cs);
break;
}
switch (iter->status)
{
case BRM::EXTENTAVAILABLE:
table->field[14]->store("Available", strlen("Available"), cs);
break;
case BRM::EXTENTUNAVAILABLE:
table->field[14]->store("Unavailable", strlen("Unavailable"), cs);
break;
case BRM::EXTENTOUTOFSERVICE:
table->field[14]->store("Out of service", strlen("Out of service"), cs);
break;
default:
table->field[14]->store("Unknown", strlen("Unknown"), cs);
}
// MCOL-1016: on multiple segments HWM is set to 0 on the lower
// segments, we don't want these to show as 8KB. The down side is
// if the column has less than 1 block it will show as 0 bytes.
// We have no lookahead without it getting messy so this is the
// best compromise.
if (iter->HWM == 0)
{
table->field[15]->store(0);
table->field[5]->set_null();
}
else
{
table->field[15]->store((iter->HWM + 1) * 8192);
table->field[5]->set_notnull();
table->field[5]->store((longlong)iter->partition.cprange.hiVal, false);
}
if (schema_table_store_record(thd, table))
}
else
{
if (iter->partition.cprange.bigLoVal == utils::maxInt128 ||
iter->partition.cprange.bigLoVal <= (utils::minInt128 + 1))
{
delete emp;
return 1;
table->field[4]->set_null();
}
else
{
table->field[4]->set_notnull();
std::string decAsAStr = datatypes::TSInt128(iter->partition.cprange.bigLoVal).toString();
table->field[4]->store(decAsAStr.c_str(), decAsAStr.length(), table->field[4]->charset());
}
iter++;
if (iter->partition.cprange.bigHiVal <= (utils::minInt128 + 1))
{
table->field[5]->set_null();
}
else
{
table->field[5]->set_notnull();
std::string decAsAStr = datatypes::TSInt128(iter->partition.cprange.bigHiVal).toString();
table->field[5]->store(decAsAStr.c_str(), decAsAStr.length(), table->field[5]->charset());
}
}
table->field[6]->store(iter->colWid);
}
else
{
table->field[1]->store("Dictionary", strlen("Dictionary"), cs);
table->field[4]->set_null();
table->field[5]->set_null();
table->field[6]->store(8192);
}
return 0;
table->field[2]->store(iter->range.start);
table->field[3]->store(iter->range.start + (iter->range.size * 1024) - 1);
table->field[7]->store(iter->dbRoot);
table->field[8]->store(iter->partitionNum);
table->field[9]->store(iter->segmentNum);
table->field[10]->store(iter->blockOffset);
table->field[11]->store(iter->range.size * 1024);
table->field[12]->store(iter->HWM);
switch (iter->partition.cprange.isValid)
{
case 0: table->field[13]->store("Invalid", strlen("Invalid"), cs); break;
case 1: table->field[13]->store("Updating", strlen("Updating"), cs); break;
case 2: table->field[13]->store("Valid", strlen("Valid"), cs); break;
default: table->field[13]->store("Unknown", strlen("Unknown"), cs); break;
}
switch (iter->status)
{
case BRM::EXTENTAVAILABLE: table->field[14]->store("Available", strlen("Available"), cs); break;
case BRM::EXTENTUNAVAILABLE: table->field[14]->store("Unavailable", strlen("Unavailable"), cs); break;
case BRM::EXTENTOUTOFSERVICE:
table->field[14]->store("Out of service", strlen("Out of service"), cs);
break;
default: table->field[14]->store("Unknown", strlen("Unknown"), cs);
}
// MCOL-1016: on multiple segments HWM is set to 0 on the lower
// segments, we don't want these to show as 8KB. The down side is
// if the column has less than 1 block it will show as 0 bytes.
// We have no lookahead without it getting messy so this is the
// best compromise.
if (iter->HWM == 0)
{
table->field[15]->store(0);
}
else
{
table->field[15]->store((iter->HWM + 1) * 8192);
}
if (schema_table_store_record(thd, table))
{
delete emp;
return 1;
}
iter++;
}
return 0;
}
static int is_columnstore_extents_fill(THD* thd, TABLE_LIST* tables, COND* cond)
{
BRM::OID_t cond_oid = 0;
TABLE* table = tables->table;
BRM::OID_t cond_oid = 0;
TABLE* table = tables->table;
BRM::DBRM::refreshShm();
BRM::DBRM* emp = new BRM::DBRM();
BRM::DBRM::refreshShm();
BRM::DBRM* emp = new BRM::DBRM();
if (!emp || !emp->isDBRMReady())
if (!emp || !emp->isDBRMReady())
{
return 1;
}
if (cond && cond->type() == Item::FUNC_ITEM)
{
Item_func* fitem = (Item_func*)cond;
if ((fitem->functype() == Item_func::EQ_FUNC) && (fitem->argument_count() == 2))
{
return 1;
if (fitem->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
fitem->arguments()[1]->const_item())
{
// WHERE object_id = value
Item_field* item_field = (Item_field*)fitem->arguments()[0]->real_item();
if (strcasecmp(item_field->field_name.str, "object_id") == 0)
{
cond_oid = fitem->arguments()[1]->val_int();
return generate_result(cond_oid, emp, table, thd);
}
}
else if (fitem->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
fitem->arguments()[0]->const_item())
{
// WHERE value = object_id
Item_field* item_field = (Item_field*)fitem->arguments()[1]->real_item();
if (strcasecmp(item_field->field_name.str, "object_id") == 0)
{
cond_oid = fitem->arguments()[0]->val_int();
return generate_result(cond_oid, emp, table, thd);
}
}
}
if (cond && cond->type() == Item::FUNC_ITEM)
else if (fitem->functype() == Item_func::IN_FUNC)
{
Item_func* fitem = (Item_func*) cond;
// WHERE object_id in (value1, value2)
Item_field* item_field = (Item_field*)fitem->arguments()[0]->real_item();
if ((fitem->functype() == Item_func::EQ_FUNC) && (fitem->argument_count() == 2))
if (strcasecmp(item_field->field_name.str, "object_id") == 0)
{
for (unsigned int i = 1; i < fitem->argument_count(); i++)
{
if (fitem->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
fitem->arguments()[1]->const_item())
{
// WHERE object_id = value
Item_field* item_field = (Item_field*) fitem->arguments()[0]->real_item();
cond_oid = fitem->arguments()[i]->val_int();
int result = generate_result(cond_oid, emp, table, thd);
if (strcasecmp(item_field->field_name.str, "object_id") == 0)
{
cond_oid = fitem->arguments()[1]->val_int();
return generate_result(cond_oid, emp, table, thd);
}
}
else if (fitem->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
fitem->arguments()[0]->const_item())
{
// WHERE value = object_id
Item_field* item_field = (Item_field*) fitem->arguments()[1]->real_item();
if (strcasecmp(item_field->field_name.str, "object_id") == 0)
{
cond_oid = fitem->arguments()[0]->val_int();
return generate_result(cond_oid, emp, table, thd);
}
}
}
else if (fitem->functype() == Item_func::IN_FUNC)
{
// WHERE object_id in (value1, value2)
Item_field* item_field = (Item_field*) fitem->arguments()[0]->real_item();
if (strcasecmp(item_field->field_name.str, "object_id") == 0)
{
for (unsigned int i = 1; i < fitem->argument_count(); i++)
{
cond_oid = fitem->arguments()[i]->val_int();
int result = generate_result(cond_oid, emp, table, thd);
if (result)
return 1;
}
}
}
else if (fitem->functype() == Item_func::UNKNOWN_FUNC &&
strcasecmp(fitem->func_name(), "find_in_set") == 0)
{
// WHERE FIND_IN_SET(object_id, values)
String* tmp_var = fitem->arguments()[1]->val_str();
std::stringstream ss(tmp_var->ptr());
while (ss >> cond_oid)
{
int ret = generate_result(cond_oid, emp, table, thd);
if (ret)
return 1;
if (ss.peek() == ',')
ss.ignore();
}
}
}
execplan::ObjectIDManager oidm;
BRM::OID_t MaxOID = oidm.size();
for (BRM::OID_t oid = 3000; oid <= MaxOID; oid++)
{
int result = generate_result(oid, emp, table, thd);
if (result)
if (result)
return 1;
}
}
}
else if (fitem->functype() == Item_func::UNKNOWN_FUNC &&
strcasecmp(fitem->func_name(), "find_in_set") == 0)
{
// WHERE FIND_IN_SET(object_id, values)
String* tmp_var = fitem->arguments()[1]->val_str();
std::stringstream ss(tmp_var->ptr());
delete emp;
return 0;
while (ss >> cond_oid)
{
int ret = generate_result(cond_oid, emp, table, thd);
if (ret)
return 1;
if (ss.peek() == ',')
ss.ignore();
}
}
}
execplan::ObjectIDManager oidm;
BRM::OID_t MaxOID = oidm.size();
for (BRM::OID_t oid = 3000; oid <= MaxOID; oid++)
{
int result = generate_result(oid, emp, table, thd);
if (result)
return 1;
}
delete emp;
return 0;
}
int is_columnstore_extents_plugin_init(void* p)
{
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = is_columnstore_extents_fields;
schema->fill_table = is_columnstore_extents_fill;
return 0;
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*)p;
schema->fields_info = is_columnstore_extents_fields;
schema->fill_table = is_columnstore_extents_fill;
return 0;
}

View File

@ -42,281 +42,279 @@
// Required declaration as it isn't in a MairaDB include
bool schema_table_store_record(THD* thd, TABLE* table);
ST_FIELD_INFO is_columnstore_files_fields[] =
{
ST_FIELD_INFO is_columnstore_files_fields[] = {
Show::Column("OBJECT_ID", Show::ULong(0), NOT_NULL),
Show::Column("SEGMENT_ID", Show::ULong(0), NOT_NULL),
Show::Column("PARTITION_ID", Show::ULong(0), NOT_NULL),
Show::Column("FILENAME", Show::Varchar(1024), NOT_NULL),
Show::Column("FILE_SIZE", Show::ULonglong(0), NULLABLE),
Show::Column("COMPRESSED_DATA_SIZE", Show::ULonglong(0), NULLABLE),
Show::CEnd()
};
Show::CEnd()};
static bool get_file_sizes(THD* thd, messageqcpp::MessageQueueClient* msgQueueClient, const char* fileName, off_t* fileSize, off_t* compressedFileSize)
static bool get_file_sizes(THD* thd, messageqcpp::MessageQueueClient* msgQueueClient, const char* fileName,
off_t* fileSize, off_t* compressedFileSize)
{
messageqcpp::ByteStream bs;
messageqcpp::ByteStream::byte rc;
std::string errMsg;
messageqcpp::ByteStream bs;
messageqcpp::ByteStream::byte rc;
std::string errMsg;
try
try
{
bs << (messageqcpp::ByteStream::byte)WriteEngine::WE_SVR_GET_FILESIZE;
// header??
bs << fileName;
msgQueueClient->write(bs);
// namespace??
messageqcpp::SBS sbs;
sbs = msgQueueClient->read();
if (sbs->length() == 0)
{
bs << (messageqcpp::ByteStream::byte) WriteEngine::WE_SVR_GET_FILESIZE;
// header??
bs << fileName;
msgQueueClient->write(bs);
// namespace??
messageqcpp::SBS sbs;
sbs = msgQueueClient->read();
if (sbs->length() == 0)
{
delete msgQueueClient;
return false;
}
*sbs >> rc;
*sbs >> errMsg;
if (rc)
{
ha_mcs_impl::log_this(thd,
"I_S::COLUMNSTORE_FILE::get_file_sizes(): WriteEngineServer returns an error().",
logging::LOG_TYPE_ERROR, thd->thread_id);
return false;
}
*sbs >> *fileSize;
*sbs >> *compressedFileSize;
return true;
delete msgQueueClient;
return false;
}
catch (...)
*sbs >> rc;
*sbs >> errMsg;
if (rc)
{
return false;
ha_mcs_impl::log_this(thd,
"I_S::COLUMNSTORE_FILE::get_file_sizes(): WriteEngineServer returns an error().",
logging::LOG_TYPE_ERROR, thd->thread_id);
return false;
}
*sbs >> *fileSize;
*sbs >> *compressedFileSize;
return true;
}
catch (...)
{
return false;
}
}
static int generate_result(BRM::OID_t oid, BRM::DBRM* emp, TABLE* table, THD* thd)
{
std::vector<struct BRM::EMEntry> entries;
CHARSET_INFO* cs = system_charset_info;
std::vector<struct BRM::EMEntry> entries;
CHARSET_INFO* cs = system_charset_info;
char oidDirName[WriteEngine::FILE_NAME_SIZE];
char fullFileName[WriteEngine::FILE_NAME_SIZE];
char dbDir[WriteEngine::MAX_DB_DIR_LEVEL][WriteEngine::MAX_DB_DIR_NAME_SIZE];
char oidDirName[WriteEngine::FILE_NAME_SIZE];
char fullFileName[WriteEngine::FILE_NAME_SIZE];
char dbDir[WriteEngine::MAX_DB_DIR_LEVEL][WriteEngine::MAX_DB_DIR_NAME_SIZE];
config::Config* config;
config::Config* config;
try
{
config = config::Config::makeConfig();
}
catch (std::runtime_error& e)
{
thd->raise_error_printf(ER_INTERNAL_ERROR, e.what());
return ER_INTERNAL_ERROR;
}
WriteEngine::Config we_config;
off_t fileSize = 0;
off_t compressedFileSize = 0;
we_config.initConfigCache();
messageqcpp::MessageQueueClient* msgQueueClient;
oam::Oam oam_instance;
int pmId = 0;
int rc;
emp->getExtents(oid, entries, false, false, true);
if (entries.size() == 0)
return 0;
std::vector<struct BRM::EMEntry>::const_iterator iter = entries.begin();
while (iter != entries.end()) // organize extents into files
{
// Don't include files more than once at different block offsets
if (iter->blockOffset > 0)
{
iter++;
continue;
}
try
{
config = config::Config::makeConfig();
oam_instance.getDbrootPmConfig(iter->dbRoot, pmId);
}
catch (std::runtime_error& e)
catch (std::runtime_error&)
{
thd->raise_error_printf(ER_INTERNAL_ERROR, e.what());
return ER_INTERNAL_ERROR;
// MCOL-1116: If we are here a DBRoot is offline/missing
iter++;
return 0;
}
WriteEngine::Config we_config;
off_t fileSize = 0;
off_t compressedFileSize = 0;
we_config.initConfigCache();
messageqcpp::MessageQueueClient* msgQueueClient;
oam::Oam oam_instance;
int pmId = 0;
int rc;
table->field[0]->store(oid);
table->field[1]->store(iter->segmentNum);
table->field[2]->store(iter->partitionNum);
emp->getExtents(oid, entries, false, false, true);
WriteEngine::Convertor::oid2FileName(oid, oidDirName, dbDir, iter->partitionNum, iter->segmentNum);
std::stringstream DbRootName;
DbRootName << "DBRoot" << iter->dbRoot;
std::string DbRootPath = config->getConfig("SystemConfig", DbRootName.str());
fileSize = compressedFileSize = 0;
rc = snprintf(fullFileName, WriteEngine::FILE_NAME_SIZE, "%s/%s", DbRootPath.c_str(), oidDirName);
if (entries.size() == 0)
return 0;
std::ostringstream oss;
oss << "pm" << pmId << "_WriteEngineServer";
std::string client = oss.str();
msgQueueClient = messageqcpp::MessageQueueClientPool::getInstance(oss.str());
std::vector<struct BRM::EMEntry>::const_iterator iter = entries.begin();
while ( iter != entries.end() ) //organize extents into files
// snprintf output truncation check
if (rc == WriteEngine::FILE_NAME_SIZE ||
!get_file_sizes(thd, msgQueueClient, fullFileName, &fileSize, &compressedFileSize))
{
// Don't include files more than once at different block offsets
if (iter->blockOffset > 0)
{
iter++;
continue;
}
try
{
oam_instance.getDbrootPmConfig(iter->dbRoot, pmId);
}
catch (std::runtime_error&)
{
// MCOL-1116: If we are here a DBRoot is offline/missing
iter++;
return 0;
}
table->field[0]->store(oid);
table->field[1]->store(iter->segmentNum);
table->field[2]->store(iter->partitionNum);
WriteEngine::Convertor::oid2FileName(oid, oidDirName, dbDir, iter->partitionNum, iter->segmentNum);
std::stringstream DbRootName;
DbRootName << "DBRoot" << iter->dbRoot;
std::string DbRootPath = config->getConfig("SystemConfig", DbRootName.str());
fileSize = compressedFileSize = 0;
rc = snprintf(fullFileName, WriteEngine::FILE_NAME_SIZE, "%s/%s", DbRootPath.c_str(), oidDirName);
std::ostringstream oss;
oss << "pm" << pmId << "_WriteEngineServer";
std::string client = oss.str();
msgQueueClient = messageqcpp::MessageQueueClientPool::getInstance(oss.str());
// snprintf output truncation check
if (rc == WriteEngine::FILE_NAME_SIZE ||
!get_file_sizes(thd, msgQueueClient, fullFileName, &fileSize, &compressedFileSize))
{
messageqcpp::MessageQueueClientPool::releaseInstance(msgQueueClient);
delete emp;
return 1;
}
table->field[3]->store(fullFileName, strlen(fullFileName), cs);
if (fileSize > 0)
{
table->field[4]->set_notnull();
table->field[4]->store(fileSize);
if (compressedFileSize > 0)
{
table->field[5]->set_notnull();
table->field[5]->store(compressedFileSize);
}
else
{
table->field[5]->set_null();
}
}
else
{
table->field[4]->set_null();
table->field[5]->set_null();
}
if (schema_table_store_record(thd, table))
{
messageqcpp::MessageQueueClientPool::releaseInstance(msgQueueClient);
delete emp;
return 1;
}
iter++;
messageqcpp::MessageQueueClientPool::releaseInstance(msgQueueClient);
msgQueueClient = NULL;
messageqcpp::MessageQueueClientPool::releaseInstance(msgQueueClient);
delete emp;
return 1;
}
return 0;
table->field[3]->store(fullFileName, strlen(fullFileName), cs);
if (fileSize > 0)
{
table->field[4]->set_notnull();
table->field[4]->store(fileSize);
if (compressedFileSize > 0)
{
table->field[5]->set_notnull();
table->field[5]->store(compressedFileSize);
}
else
{
table->field[5]->set_null();
}
}
else
{
table->field[4]->set_null();
table->field[5]->set_null();
}
if (schema_table_store_record(thd, table))
{
messageqcpp::MessageQueueClientPool::releaseInstance(msgQueueClient);
delete emp;
return 1;
}
iter++;
messageqcpp::MessageQueueClientPool::releaseInstance(msgQueueClient);
msgQueueClient = NULL;
}
return 0;
}
static int is_columnstore_files_fill(THD* thd, TABLE_LIST* tables, COND* cond)
{
BRM::DBRM::refreshShm();
BRM::DBRM* emp = new BRM::DBRM();
BRM::OID_t cond_oid = 0;
TABLE* table = tables->table;
BRM::DBRM::refreshShm();
BRM::DBRM* emp = new BRM::DBRM();
BRM::OID_t cond_oid = 0;
TABLE* table = tables->table;
if (!emp || !emp->isDBRMReady())
if (!emp || !emp->isDBRMReady())
{
return 1;
}
if (cond && cond->type() == Item::FUNC_ITEM)
{
Item_func* fitem = (Item_func*)cond;
if ((fitem->functype() == Item_func::EQ_FUNC) && (fitem->argument_count() == 2))
{
if (fitem->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
fitem->arguments()[1]->const_item())
{
// WHERE object_id = value
Item_field* item_field = (Item_field*)fitem->arguments()[0]->real_item();
if (strcasecmp(item_field->field_name.str, "object_id") == 0)
{
cond_oid = fitem->arguments()[1]->val_int();
return generate_result(cond_oid, emp, table, thd);
}
}
else if (fitem->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
fitem->arguments()[0]->const_item())
{
// WHERE value = object_id
Item_field* item_field = (Item_field*)fitem->arguments()[1]->real_item();
if (strcasecmp(item_field->field_name.str, "object_id") == 0)
{
cond_oid = fitem->arguments()[0]->val_int();
return generate_result(cond_oid, emp, table, thd);
}
}
}
else if (fitem->functype() == Item_func::IN_FUNC)
{
// WHERE object_id in (value1, value2)
Item_field* item_field = (Item_field*)fitem->arguments()[0]->real_item();
if (strcasecmp(item_field->field_name.str, "object_id") == 0)
{
for (unsigned int i = 1; i < fitem->argument_count(); i++)
{
cond_oid = fitem->arguments()[i]->val_int();
int result = generate_result(cond_oid, emp, table, thd);
if (result)
return 1;
}
}
}
else if (fitem->functype() == Item_func::UNKNOWN_FUNC &&
strcasecmp(fitem->func_name(), "find_in_set") == 0)
{
// WHERE FIND_IN_SET(object_id, values)
String* tmp_var = fitem->arguments()[1]->val_str();
std::stringstream ss(tmp_var->ptr());
while (ss >> cond_oid)
{
int ret = generate_result(cond_oid, emp, table, thd);
if (ret)
return 1;
if (ss.peek() == ',')
ss.ignore();
}
}
}
execplan::ObjectIDManager oidm;
BRM::OID_t MaxOID = oidm.size();
if (!cond_oid)
{
for (BRM::OID_t oid = 3000; oid <= MaxOID; oid++)
{
int result = generate_result(oid, emp, table, thd);
if (result)
return 1;
}
}
if (cond && cond->type() == Item::FUNC_ITEM)
{
Item_func* fitem = (Item_func*) cond;
if ((fitem->functype() == Item_func::EQ_FUNC) && (fitem->argument_count() == 2))
{
if (fitem->arguments()[0]->real_item()->type() == Item::FIELD_ITEM &&
fitem->arguments()[1]->const_item())
{
// WHERE object_id = value
Item_field* item_field = (Item_field*) fitem->arguments()[0]->real_item();
if (strcasecmp(item_field->field_name.str, "object_id") == 0)
{
cond_oid = fitem->arguments()[1]->val_int();
return generate_result(cond_oid, emp, table, thd);
}
}
else if (fitem->arguments()[1]->real_item()->type() == Item::FIELD_ITEM &&
fitem->arguments()[0]->const_item())
{
// WHERE value = object_id
Item_field* item_field = (Item_field*) fitem->arguments()[1]->real_item();
if (strcasecmp(item_field->field_name.str, "object_id") == 0)
{
cond_oid = fitem->arguments()[0]->val_int();
return generate_result(cond_oid, emp, table, thd);
}
}
}
else if (fitem->functype() == Item_func::IN_FUNC)
{
// WHERE object_id in (value1, value2)
Item_field* item_field = (Item_field*) fitem->arguments()[0]->real_item();
if (strcasecmp(item_field->field_name.str, "object_id") == 0)
{
for (unsigned int i = 1; i < fitem->argument_count(); i++)
{
cond_oid = fitem->arguments()[i]->val_int();
int result = generate_result(cond_oid, emp, table, thd);
if (result)
return 1;
}
}
}
else if (fitem->functype() == Item_func::UNKNOWN_FUNC &&
strcasecmp(fitem->func_name(), "find_in_set") == 0)
{
// WHERE FIND_IN_SET(object_id, values)
String* tmp_var = fitem->arguments()[1]->val_str();
std::stringstream ss(tmp_var->ptr());
while (ss >> cond_oid)
{
int ret = generate_result(cond_oid, emp, table, thd);
if (ret)
return 1;
if (ss.peek() == ',')
ss.ignore();
}
}
}
execplan::ObjectIDManager oidm;
BRM::OID_t MaxOID = oidm.size();
if (!cond_oid)
{
for (BRM::OID_t oid = 3000; oid <= MaxOID; oid++)
{
int result = generate_result(oid, emp, table, thd);
if (result)
return 1;
}
}
delete emp;
return 0;
delete emp;
return 0;
}
int is_columnstore_files_plugin_init(void* p)
{
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = is_columnstore_files_fields;
schema->fill_table = is_columnstore_files_fill;
return 0;
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*)p;
schema->fields_info = is_columnstore_files_fields;
schema->fill_table = is_columnstore_files_fill;
return 0;
}

View File

@ -32,82 +32,82 @@
// Required declaration as it isn't in a MairaDB include
bool schema_table_store_record(THD* thd, TABLE* table);
ST_FIELD_INFO is_columnstore_tables_fields[] =
{
ST_FIELD_INFO is_columnstore_tables_fields[] = {
Show::Column("TABLE_SCHEMA", Show::Varchar(64), NOT_NULL),
Show::Column("TABLE_NAME", Show::Varchar(64), NOT_NULL),
Show::Column("OBJECT_ID", Show::SLong(0), NOT_NULL),
Show::Column("CREATION_DATE", Show::Datetime(0), NOT_NULL), // TODO: Make a date if possible
Show::Column("CREATION_DATE", Show::Datetime(0), NOT_NULL), // TODO: Make a date if possible
Show::Column("COLUMN_COUNT", Show::SLong(0), NOT_NULL),
Show::Column("AUTOINCREMENT", Show::SLong(0), NULLABLE),
Show::CEnd()
};
Show::CEnd()};
static int is_columnstore_tables_fill(THD* thd, TABLE_LIST* tables, COND* cond)
{
CHARSET_INFO* cs = system_charset_info;
TABLE* table = tables->table;
InformationSchemaCond isCond;
CHARSET_INFO* cs = system_charset_info;
TABLE* table = tables->table;
InformationSchemaCond isCond;
boost::shared_ptr<execplan::CalpontSystemCatalog> systemCatalogPtr =
execplan::CalpontSystemCatalog::makeCalpontSystemCatalog(execplan::CalpontSystemCatalog::idb_tid2sid(thd->thread_id));
boost::shared_ptr<execplan::CalpontSystemCatalog> systemCatalogPtr =
execplan::CalpontSystemCatalog::makeCalpontSystemCatalog(
execplan::CalpontSystemCatalog::idb_tid2sid(thd->thread_id));
systemCatalogPtr->identity(execplan::CalpontSystemCatalog::FE);
systemCatalogPtr->identity(execplan::CalpontSystemCatalog::FE);
if (cond)
if (cond)
{
isCond.getCondItems(cond);
}
const std::vector<
std::pair<execplan::CalpontSystemCatalog::OID, execplan::CalpontSystemCatalog::TableName> >
catalog_tables = systemCatalogPtr->getTables();
for (std::vector<std::pair<execplan::CalpontSystemCatalog::OID,
execplan::CalpontSystemCatalog::TableName> >::const_iterator it =
catalog_tables.begin();
it != catalog_tables.end(); ++it)
{
if (!isCond.match((*it).second.schema, (*it).second.table))
continue;
try
{
isCond.getCondItems(cond);
execplan::CalpontSystemCatalog::TableInfo tb_info = systemCatalogPtr->tableInfo((*it).second);
std::string create_date = dataconvert::DataConvert::dateToString((*it).second.create_date);
table->field[0]->store((*it).second.schema.c_str(), (*it).second.schema.length(), cs);
table->field[1]->store((*it).second.table.c_str(), (*it).second.table.length(), cs);
table->field[2]->store((*it).first);
table->field[3]->store(create_date.c_str(), create_date.length(), cs);
table->field[4]->store(tb_info.numOfCols);
if (tb_info.tablewithautoincr)
{
table->field[5]->set_notnull();
table->field[5]->store(systemCatalogPtr->nextAutoIncrValue((*it).second));
}
else
{
table->field[5]->set_null();
}
table->field[5]->store(tb_info.tablewithautoincr);
if (schema_table_store_record(thd, table))
return 1;
}
const std::vector< std::pair<execplan::CalpontSystemCatalog::OID, execplan::CalpontSystemCatalog::TableName> > catalog_tables
= systemCatalogPtr->getTables();
for (std::vector<std::pair<execplan::CalpontSystemCatalog::OID, execplan::CalpontSystemCatalog::TableName> >::const_iterator it = catalog_tables.begin();
it != catalog_tables.end(); ++it)
catch (std::runtime_error& e)
{
if (!isCond.match((*it).second.schema, (*it).second.table))
continue;
try
{
execplan::CalpontSystemCatalog::TableInfo tb_info = systemCatalogPtr->tableInfo((*it).second);
std::string create_date = dataconvert::DataConvert::dateToString((*it).second.create_date);
table->field[0]->store((*it).second.schema.c_str(), (*it).second.schema.length(), cs);
table->field[1]->store((*it).second.table.c_str(), (*it).second.table.length(), cs);
table->field[2]->store((*it).first);
table->field[3]->store(create_date.c_str(), create_date.length(), cs);
table->field[4]->store(tb_info.numOfCols);
if (tb_info.tablewithautoincr)
{
table->field[5]->set_notnull();
table->field[5]->store(systemCatalogPtr->nextAutoIncrValue((*it).second));
}
else
{
table->field[5]->set_null();
}
table->field[5]->store(tb_info.tablewithautoincr);
if (schema_table_store_record(thd, table))
return 1;
}
catch (std::runtime_error& e)
{
std::cerr << e.what() << std::endl;
}
std::cerr << e.what() << std::endl;
}
}
return 0;
return 0;
}
int is_columnstore_tables_plugin_init(void* p)
{
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
schema->fields_info = is_columnstore_tables_fields;
schema->fill_table = is_columnstore_tables_fill;
return 0;
ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*)p;
schema->fields_info = is_columnstore_tables_fields;
schema->fill_table = is_columnstore_tables_fill;
return 0;
}

View File

@ -20,7 +20,6 @@
*
***********************************************************************/
#define PREFER_MY_CONFIG_H
#include <mariadb.h>
#include <mysql.h>
@ -65,214 +64,217 @@ using namespace sm;
// @bug 159 fix. clean up routine when error happened
void cleanup(cpsm_conhdl_t* hndl)
{
// remove system catalog instance for this statement.
CalpontSystemCatalog::removeCalpontSystemCatalog(hndl->sessionID);
hndl->queryState = NO_QUERY;
hndl->resultSet.erase(hndl->resultSet.begin(), hndl->resultSet.end());
// remove system catalog instance for this statement.
CalpontSystemCatalog::removeCalpontSystemCatalog(hndl->sessionID);
hndl->queryState = NO_QUERY;
hndl->resultSet.erase(hndl->resultSet.begin(), hndl->resultSet.end());
}
status_t tpl_scan_fetch_getband(cpsm_conhdl_t* hndl, sp_cpsm_tplsch_t& ntplsch, int* killed)
{
// @bug 649 check keybandmap first
map<int, int>::iterator keyBandMapIter = hndl->keyBandMap.find(ntplsch->key);
// @bug 649 check keybandmap first
map<int, int>::iterator keyBandMapIter = hndl->keyBandMap.find(ntplsch->key);
try
try
{
if (keyBandMapIter != hndl->keyBandMap.end())
{
if (keyBandMapIter != hndl->keyBandMap.end())
{
ByteStream bs;
ostringstream oss;
oss << DEFAULT_SAVE_PATH << '/' << hndl->sessionID << '/' << ntplsch->key << '_' << ntplsch->bandID << ".band";
ifstream bandFile (oss.str().c_str(), ios::in);
bandFile >> bs;
unlink (oss.str().c_str());
ByteStream bs;
ostringstream oss;
oss << DEFAULT_SAVE_PATH << '/' << hndl->sessionID << '/' << ntplsch->key << '_' << ntplsch->bandID
<< ".band";
ifstream bandFile(oss.str().c_str(), ios::in);
bandFile >> bs;
unlink(oss.str().c_str());
// not possible for vtable
ntplsch->deserializeTable(bs);
ntplsch->bandID++;
// not possible for vtable
ntplsch->deserializeTable(bs);
ntplsch->bandID++;
// end of result set
if (ntplsch->bandID == keyBandMapIter->second)
{
hndl->keyBandMap.erase(keyBandMapIter);
return SQL_NOT_FOUND;
}
}
else
{
ByteStream bs;
// @bug 626. check saveFlag. If SAVING, read band from socket and save to disk
if (ntplsch->saveFlag == SAVING)
{
ByteStream bs;
// @bug 2244. Bypass ClientRotator::read() because if I/O error occurs, it tries
// to reestablish a connection with ExeMgr which ends up causing mysql
// session to hang.
bs = hndl->exeMgr->read();
ostringstream oss;
oss << DEFAULT_SAVE_PATH << '/' << hndl->sessionID << '/' << ntplsch->tableid << '_' << ntplsch->bandsReturned << ".band";
ofstream saveFile (oss.str().c_str(), ios::out);
saveFile << bs;
saveFile.close();
ntplsch->bandsReturned++;
// not possible for vtable
ntplsch->deserializeTable(bs);
}
// if SAVED, read from saved file. not possible for vtable
else if (ntplsch->saveFlag == SAVED)
{
ostringstream oss;
oss << DEFAULT_SAVE_PATH << '/' << hndl->sessionID << '/' << ntplsch->tableid << '_' << ntplsch->bandsReturned << ".band";
ifstream saveFile (oss.str().c_str(), ios::in);
saveFile >> bs;
saveFile.close();
ntplsch->bandsReturned++;
ntplsch->deserializeTable(bs);
}
// most normal path. also the path for vtable
else
{
ntplsch->bs.restart();
// @bug 2244. Bypass ClientRotator::read() because if I/O error occurs, it tries
// to reestablish a connection with ExeMgr which ends up causing mysql
// session to hang.
// @bug 3386. need to abort the query when user does ctrl+c
timespec t;
t.tv_sec = 5L;
t.tv_nsec = 0L;
if (killed && *killed)
return SQL_KILLED;
ntplsch->bs = hndl->exeMgr->read();
if (ntplsch->bs.length() != 0)
{
ntplsch->deserializeTable(ntplsch->bs);
if (ntplsch->rowGroup && ntplsch->rowGroup->getRGData() == NULL)
{
ntplsch->bs.restart();
// @bug 2244. Bypass ClientRotator::read() because if I/O error occurs, it tries
// to reestablish a connection with ExeMgr which ends up causing mysql
// session to hang.
bool timeout = true;
while (timeout)
{
timeout = false;
ntplsch->bs = hndl->exeMgr->getClient()->read(&t, &timeout);
if (killed && *killed)
return SQL_KILLED;
}
if (ntplsch->bs.length() == 0)
{
hndl->curFetchTb = 0;
return logging::ERR_LOST_CONN_EXEMGR;
}
ntplsch->deserializeTable(ntplsch->bs);
}
uint16_t error = ntplsch->getStatus();
if (0 != error)
{
ntplsch->setErrMsg();
return error;
}
}
else // @todo error handling
{
hndl->curFetchTb = 0;
if (ntplsch->saveFlag == NO_SAVE)
hndl->tidScanMap[ntplsch->tableid] = ntplsch;
ntplsch->errMsg = IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR);
return logging::ERR_LOST_CONN_EXEMGR;
}
}
// All done with this table. reset curFetchTb when finish SOCKET reading
if (ntplsch->getRowCount() == 0)
{
hndl->curFetchTb = 0;
if (ntplsch->saveFlag == NO_SAVE)
hndl->tidScanMap[ntplsch->tableid] = ntplsch;
return SQL_NOT_FOUND;
}
}
// end of result set
if (ntplsch->bandID == keyBandMapIter->second)
{
hndl->keyBandMap.erase(keyBandMapIter);
return SQL_NOT_FOUND;
}
}
catch (std::exception& e)
else
{
ByteStream bs;
// @bug 626. check saveFlag. If SAVING, read band from socket and save to disk
if (ntplsch->saveFlag == SAVING)
{
ByteStream bs;
// @bug 2244. Bypass ClientRotator::read() because if I/O error occurs, it tries
// to reestablish a connection with ExeMgr which ends up causing mysql
// session to hang.
bs = hndl->exeMgr->read();
ostringstream oss;
oss << DEFAULT_SAVE_PATH << '/' << hndl->sessionID << '/' << ntplsch->tableid << '_'
<< ntplsch->bandsReturned << ".band";
ofstream saveFile(oss.str().c_str(), ios::out);
saveFile << bs;
saveFile.close();
ntplsch->bandsReturned++;
// not possible for vtable
ntplsch->deserializeTable(bs);
}
// if SAVED, read from saved file. not possible for vtable
else if (ntplsch->saveFlag == SAVED)
{
ostringstream oss;
oss << DEFAULT_SAVE_PATH << '/' << hndl->sessionID << '/' << ntplsch->tableid << '_'
<< ntplsch->bandsReturned << ".band";
ifstream saveFile(oss.str().c_str(), ios::in);
saveFile >> bs;
saveFile.close();
ntplsch->bandsReturned++;
ntplsch->deserializeTable(bs);
}
// most normal path. also the path for vtable
else
{
ntplsch->bs.restart();
// @bug 2244. Bypass ClientRotator::read() because if I/O error occurs, it tries
// to reestablish a connection with ExeMgr which ends up causing mysql
// session to hang.
// @bug 3386. need to abort the query when user does ctrl+c
timespec t;
t.tv_sec = 5L;
t.tv_nsec = 0L;
if (killed && *killed)
return SQL_KILLED;
ntplsch->bs = hndl->exeMgr->read();
if (ntplsch->bs.length() != 0)
{
ntplsch->deserializeTable(ntplsch->bs);
if (ntplsch->rowGroup && ntplsch->rowGroup->getRGData() == NULL)
{
ntplsch->bs.restart();
// @bug 2244. Bypass ClientRotator::read() because if I/O error occurs, it tries
// to reestablish a connection with ExeMgr which ends up causing mysql
// session to hang.
bool timeout = true;
while (timeout)
{
timeout = false;
ntplsch->bs = hndl->exeMgr->getClient()->read(&t, &timeout);
if (killed && *killed)
return SQL_KILLED;
}
if (ntplsch->bs.length() == 0)
{
hndl->curFetchTb = 0;
return logging::ERR_LOST_CONN_EXEMGR;
}
ntplsch->deserializeTable(ntplsch->bs);
}
uint16_t error = ntplsch->getStatus();
if (0 != error)
{
ntplsch->setErrMsg();
return error;
}
}
else // @todo error handling
{
hndl->curFetchTb = 0;
if (ntplsch->saveFlag == NO_SAVE)
hndl->tidScanMap[ntplsch->tableid] = ntplsch;
ntplsch->errMsg = IDBErrorInfo::instance()->errorMsg(ERR_LOST_CONN_EXEMGR);
return logging::ERR_LOST_CONN_EXEMGR;
}
}
// All done with this table. reset curFetchTb when finish SOCKET reading
if (ntplsch->getRowCount() == 0)
{
hndl->curFetchTb = 0;
if (ntplsch->saveFlag == NO_SAVE)
hndl->tidScanMap[ntplsch->tableid] = ntplsch;
hndl->tidScanMap[ntplsch->tableid] = ntplsch;
ntplsch->errMsg = e.what();
return logging::ERR_LOST_CONN_EXEMGR;
return SQL_NOT_FOUND;
}
}
}
catch (std::exception& e)
{
hndl->curFetchTb = 0;
ntplsch->rowsreturned = 0;
return STATUS_OK;
if (ntplsch->saveFlag == NO_SAVE)
hndl->tidScanMap[ntplsch->tableid] = ntplsch;
ntplsch->errMsg = e.what();
return logging::ERR_LOST_CONN_EXEMGR;
}
ntplsch->rowsreturned = 0;
return STATUS_OK;
}
void end_query(cpsm_conhdl_t* hndl)
{
// remove system catalog instance for this statement.
// @bug 695. turn on system catalog session cache for FE
// CalpontSystemCatalog::removeCalpontSystemCatalog(hndl->sessionID);
hndl->queryState = NO_QUERY;
// reset at the end of query
hndl->curFetchTb = 0;
// @bug 626 clear up
hndl->tidMap.clear();
hndl->tidScanMap.clear();
hndl->keyBandMap.clear();
// remove system catalog instance for this statement.
// @bug 695. turn on system catalog session cache for FE
// CalpontSystemCatalog::removeCalpontSystemCatalog(hndl->sessionID);
hndl->queryState = NO_QUERY;
// reset at the end of query
hndl->curFetchTb = 0;
// @bug 626 clear up
hndl->tidMap.clear();
hndl->tidScanMap.clear();
hndl->keyBandMap.clear();
// Tell ExeMgr we are done with this query
try
{
ByteStream bs;
ByteStream::quadbyte qb = 0;
bs << qb;
hndl->write(bs);
}
catch (...)
{
throw;
}
// Tell ExeMgr we are done with this query
try
{
ByteStream bs;
ByteStream::quadbyte qb = 0;
bs << qb;
hndl->write(bs);
}
catch (...)
{
throw;
}
}
// @bug 1054, 863 - SIGPIPE handler
bool sigFlag = false;
void sighandler(int sig_num)
{
FILE* p;
char buf[1024];
FILE* p;
char buf[1024];
string tmpDir = startup::StartUp::tmpDir() + "/f1.dat";
const char *cstr = tmpDir.c_str();
if ((p = fopen(cstr, "a")) != NULL)
{
snprintf(buf, 1024, "sighandler() hit with %d\n", sig_num);
fwrite(buf, 1, strlen(buf), p);
fclose(p);
}
string tmpDir = startup::StartUp::tmpDir() + "/f1.dat";
const char* cstr = tmpDir.c_str();
sigFlag = true;
throw runtime_error("zerror");
if ((p = fopen(cstr, "a")) != NULL)
{
snprintf(buf, 1024, "sighandler() hit with %d\n", sig_num);
fwrite(buf, 1, strlen(buf), p);
fclose(p);
}
sigFlag = true;
throw runtime_error("zerror");
}
}
} // namespace
namespace sm
{
@ -282,246 +284,229 @@ const std::string DEFAULT_SAVE_PATH = "C:\\Calpont\\tmp";
const std::string DEFAULT_SAVE_PATH = "/var/tmp";
#endif
status_t
tpl_open ( tableid_t tableid,
cpsm_tplh_t* ntplh,
cpsm_conhdl_t* conn_hdl)
status_t tpl_open(tableid_t tableid, cpsm_tplh_t* ntplh, cpsm_conhdl_t* conn_hdl)
{
SMDEBUGLOG << "tpl_open: ntplh: " << ntplh << " conn_hdl: " << conn_hdl << " tableid: " << tableid << endl;
SMDEBUGLOG << "tpl_open: ntplh: " << ntplh << " conn_hdl: " << conn_hdl << " tableid: " << tableid << endl;
// if first time enter this function for a statement, set
// queryState to QUERY_IN_PROCESS and get execution plan.
if (conn_hdl->queryState == NO_QUERY)
// if first time enter this function for a statement, set
// queryState to QUERY_IN_PROCESS and get execution plan.
if (conn_hdl->queryState == NO_QUERY)
{
conn_hdl->queryState = QUERY_IN_PROCESS;
}
try
{
// @bug 626. check saveFlag, if SAVED, do not project
if (ntplh->saveFlag != SAVED)
{
conn_hdl->queryState = QUERY_IN_PROCESS;
// Request ExeMgr to start projecting table tableid
CalpontSystemCatalog::OID tableOID = static_cast<CalpontSystemCatalog::OID>(tableid);
ByteStream::quadbyte qb = static_cast<ByteStream::quadbyte>(tableOID);
ByteStream bs;
bs << qb;
conn_hdl->write(bs);
}
}
catch (std::exception& ex)
{
SMDEBUGLOG << "Exception caught in tpl_open: " << ex.what() << endl;
cleanup(conn_hdl);
return CALPONT_INTERNAL_ERROR;
}
ntplh->tableid = tableid;
return STATUS_OK;
}
status_t tpl_scan_open(tableid_t tableid, sp_cpsm_tplsch_t& ntplsch, cpsm_conhdl_t* conn_hdl)
{
#if IDB_SM_DEBUG
SMDEBUGLOG << "tpl_scan_open: " << conn_hdl << " tableid: " << tableid << endl;
#endif
// @bug 649. No initialization here. take passed in reference
ntplsch->tableid = tableid;
ntplsch->rowsreturned = 0;
return STATUS_OK;
}
status_t tpl_scan_fetch(sp_cpsm_tplsch_t& ntplsch, cpsm_conhdl_t* conn_hdl, int* killed)
{
// @770. force end of result set when this is not the first table to be fetched.
if (ntplsch->traceFlags & CalpontSelectExecutionPlan::TRACE_NO_ROWS2)
if (conn_hdl->tidScanMap.size() >= 1)
return SQL_NOT_FOUND;
// need another band
status_t status = STATUS_OK;
if (ntplsch->rowsreturned == ntplsch->getRowCount())
status = tpl_scan_fetch_getband(conn_hdl, ntplsch, killed);
return status;
}
status_t tpl_scan_close(sp_cpsm_tplsch_t& ntplsch)
{
#if IDB_SM_DEBUG
SMDEBUGLOG << "tpl_scan_close: ";
if (ntplsch)
SMDEBUGLOG << "tpl_scan_close: ntplsch " << ntplsch;
SMDEBUGLOG << "tpl_scan_close: tableid: " << ntplsch->tableid << endl;
#endif
ntplsch.reset();
return STATUS_OK;
}
status_t tpl_close(cpsm_tplh_t* ntplh, cpsm_conhdl_t** conn_hdl, QueryStats& stats, bool ask_4_stats,
bool clear_scan_ctx)
{
cpsm_conhdl_t* hndl = *conn_hdl;
SMDEBUGLOG << "tpl_close: hndl" << hndl << " ntplh " << ntplh;
if (ntplh)
SMDEBUGLOG << " tableid: " << ntplh->tableid;
SMDEBUGLOG << endl;
delete ntplh;
// determine end of result set and end of statement execution
if (hndl->queryState == QUERY_IN_PROCESS)
{
// Get the query stats
ByteStream bs;
// Ask for a stats only if a user explicitly asks
if (ask_4_stats)
{
ByteStream::quadbyte qb = 3;
bs << qb;
hndl->write(bs);
}
// MCOL-1601 Dispose of unused empty RowGroup
if (clear_scan_ctx)
{
SMDEBUGLOG << "tpl_close() clear_scan_ctx read" << std::endl;
bs = hndl->exeMgr->read();
}
try
SMDEBUGLOG << "tpl_close hndl->exeMgr: " << hndl->exeMgr << endl;
// keep reading until we get a string
// Ask for a stats only if a user explicitly asks
if (ask_4_stats)
{
// @bug 626. check saveFlag, if SAVED, do not project
if (ntplh->saveFlag != SAVED)
for (int tries = 0; tries < 10; tries++)
{
bs = hndl->exeMgr->read();
if (bs.length() == 0)
break;
try
{
// Request ExeMgr to start projecting table tableid
CalpontSystemCatalog::OID tableOID = static_cast<CalpontSystemCatalog::OID>(tableid);
ByteStream::quadbyte qb = static_cast<ByteStream::quadbyte>(tableOID);
ByteStream bs;
bs << qb;
conn_hdl->write(bs);
bs >> hndl->queryStats;
bs >> hndl->extendedStats;
bs >> hndl->miniStats;
stats.unserialize(bs);
stats.setEndTime();
stats.insert();
break;
}
}
catch (std::exception& ex)
{
SMDEBUGLOG << "Exception caught in tpl_open: " << ex.what() << endl;
cleanup(conn_hdl);
return CALPONT_INTERNAL_ERROR;
}
ntplh->tableid = tableid;
return STATUS_OK;
}
status_t
tpl_scan_open ( tableid_t tableid,
sp_cpsm_tplsch_t& ntplsch,
cpsm_conhdl_t* conn_hdl )
{
#if IDB_SM_DEBUG
SMDEBUGLOG << "tpl_scan_open: " << conn_hdl << " tableid: " << tableid << endl;
#endif
// @bug 649. No initialization here. take passed in reference
ntplsch->tableid = tableid;
ntplsch->rowsreturned = 0;
return STATUS_OK;
}
status_t
tpl_scan_fetch ( sp_cpsm_tplsch_t& ntplsch,
cpsm_conhdl_t* conn_hdl,
int* killed )
{
// @770. force end of result set when this is not the first table to be fetched.
if (ntplsch->traceFlags & CalpontSelectExecutionPlan::TRACE_NO_ROWS2)
if (conn_hdl->tidScanMap.size() >= 1)
return SQL_NOT_FOUND;
// need another band
status_t status = STATUS_OK;
if (ntplsch->rowsreturned == ntplsch->getRowCount())
status = tpl_scan_fetch_getband(conn_hdl, ntplsch, killed);
return status;
}
status_t
tpl_scan_close ( sp_cpsm_tplsch_t& ntplsch )
{
#if IDB_SM_DEBUG
SMDEBUGLOG << "tpl_scan_close: ";
if (ntplsch)
SMDEBUGLOG << "tpl_scan_close: ntplsch " << ntplsch;
SMDEBUGLOG << "tpl_scan_close: tableid: " << ntplsch->tableid << endl;
#endif
ntplsch.reset();
return STATUS_OK;
}
status_t
tpl_close ( cpsm_tplh_t* ntplh,
cpsm_conhdl_t** conn_hdl,
QueryStats& stats,
bool ask_4_stats,
bool clear_scan_ctx)
{
cpsm_conhdl_t* hndl = *conn_hdl;
SMDEBUGLOG << "tpl_close: hndl" << hndl << " ntplh " << ntplh;
if (ntplh)
SMDEBUGLOG << " tableid: " << ntplh->tableid;
SMDEBUGLOG << endl;
delete ntplh;
// determine end of result set and end of statement execution
if (hndl->queryState == QUERY_IN_PROCESS)
{
// Get the query stats
ByteStream bs;
// Ask for a stats only if a user explicitly asks
if(ask_4_stats)
catch (IDBExcept&)
{
ByteStream::quadbyte qb = 3;
bs << qb;
hndl->write(bs);
// @bug4732
end_query(hndl);
throw;
}
// MCOL-1601 Dispose of unused empty RowGroup
if (clear_scan_ctx)
catch (...)
{
SMDEBUGLOG << "tpl_close() clear_scan_ctx read" << std::endl;
bs = hndl->exeMgr->read();
// querystats messed up. close connection.
// no need to throw for querystats protocol error, like for tablemode.
SMDEBUGLOG << "tpl_close() exception whilst getting stats" << endl;
end_query(hndl);
sm_cleanup(hndl);
*conn_hdl = 0;
return STATUS_OK;
// throw runtime_error(string("tbl_close catch exception: ") + e.what());
}
}
} // stats
SMDEBUGLOG << "tpl_close hndl->exeMgr: " << hndl->exeMgr << endl;
//keep reading until we get a string
// Ask for a stats only if a user explicitly asks
if(ask_4_stats)
{
for (int tries = 0; tries < 10; tries++)
{
bs = hndl->exeMgr->read();
end_query(hndl);
}
if (bs.length() == 0) break;
try
{
bs >> hndl->queryStats;
bs >> hndl->extendedStats;
bs >> hndl->miniStats;
stats.unserialize(bs);
stats.setEndTime();
stats.insert();
break;
}
catch (IDBExcept&)
{
// @bug4732
end_query(hndl);
throw;
}
catch (...)
{
// querystats messed up. close connection.
// no need to throw for querystats protocol error, like for tablemode.
SMDEBUGLOG << "tpl_close() exception whilst getting stats" << endl;
end_query(hndl);
sm_cleanup(hndl);
*conn_hdl = 0;
return STATUS_OK;
//throw runtime_error(string("tbl_close catch exception: ") + e.what());
}
}
} //stats
end_query(hndl);
}
return STATUS_OK;
return STATUS_OK;
}
status_t
sm_init ( uint32_t sid,
cpsm_conhdl_t** conn_hdl,
uint32_t columnstore_local_query)
status_t sm_init(uint32_t sid, cpsm_conhdl_t** conn_hdl, uint32_t columnstore_local_query)
{
// clear file content
// clear file content
#if IDB_SM_DEBUG
//smlog.close();
//smlog.open("/tmp/sm.log");
SMDEBUGLOG << "sm_init: " << endl;
// smlog.close();
// smlog.open("/tmp/sm.log");
SMDEBUGLOG << "sm_init: " << endl;
#endif
// @bug5660 Connection changes related to the local pm setting
/**
* when local PM is detected, or columnstore_local_query is set:
* 1. SELECT query connect to local ExeMgr 127.0.0.1:8601;
* 2. DML/DDL is disallowed.
* once local connection is determined, no need to check
* again because it will not switch back.
**/
if (*conn_hdl)
{
// existing connection is local, ok.
if ((*conn_hdl)->exeMgr->localQuery() || ! columnstore_local_query)
return STATUS_OK;
// if session variable changes to local, re-establish the connection to loopback.
else
sm_cleanup(*conn_hdl);
}
// @bug5660 Connection changes related to the local pm setting
/**
* when local PM is detected, or columnstore_local_query is set:
* 1. SELECT query connect to local ExeMgr 127.0.0.1:8601;
* 2. DML/DDL is disallowed.
* once local connection is determined, no need to check
* again because it will not switch back.
**/
if (*conn_hdl)
{
// existing connection is local, ok.
if ((*conn_hdl)->exeMgr->localQuery() || !columnstore_local_query)
return STATUS_OK;
// if session variable changes to local, re-establish the connection to loopback.
else
sm_cleanup(*conn_hdl);
}
cpsm_conhdl_t* hndl = new cpsm_conhdl_t(time(0), sid, columnstore_local_query);
*conn_hdl = hndl;
hndl->sessionID = sid;
cpsm_conhdl_t* hndl = new cpsm_conhdl_t(time(0), sid, columnstore_local_query);
*conn_hdl = hndl;
hndl->sessionID = sid;
// profiling statistics
GET_PF_TIME(hndl->pf.login);
// profiling statistics
GET_PF_TIME(hndl->pf.login);
return STATUS_OK;
return STATUS_OK;
}
status_t
sm_cleanup ( cpsm_conhdl_t* conn_hdl )
status_t sm_cleanup(cpsm_conhdl_t* conn_hdl)
{
#if IDB_SM_DEBUG
SMDEBUGLOG << "sm_cleanup: " << conn_hdl << endl;
SMDEBUGLOG << "sm_cleanup: " << conn_hdl << endl;
#endif
delete conn_hdl;
delete conn_hdl;
return STATUS_OK;
return STATUS_OK;
}
void cpsm_conhdl_t::write(ByteStream bs)
{
#ifdef _MSC_VER
exeMgr->write(bs);
exeMgr->write(bs);
#else
sighandler_t old_handler = signal(SIGPIPE, sighandler);
sigFlag = false;
exeMgr->write(bs);
signal(SIGPIPE, old_handler);
sighandler_t old_handler = signal(SIGPIPE, sighandler);
sigFlag = false;
exeMgr->write(bs);
signal(SIGPIPE, old_handler);
if (sigFlag)
throw runtime_error("Broken Pipe Error");
if (sigFlag)
throw runtime_error("Broken Pipe Error");
#endif
}
}
} // namespace sm
/**
* The following functions exist because QueryStats is used by sm.
@ -533,59 +518,57 @@ void cpsm_conhdl_t::write(ByteStream bs)
* these functions aren't needed.
*/
unsigned long mysql_real_escape_string(MYSQL* mysql,
char* to, const char* from,
unsigned long length)
unsigned long mysql_real_escape_string(MYSQL* mysql, char* to, const char* from, unsigned long length)
{
my_bool overflow;
return escape_string_for_mysql(mysql->charset, to, length * 2 + 1, from, length, &overflow);
my_bool overflow;
return escape_string_for_mysql(mysql->charset, to, length * 2 + 1, from, length, &overflow);
}
// Clone of sql-common/client.c cli_use_result
MYSQL_RES* mysql_use_result(MYSQL* mysql)
{
MYSQL_RES* result;
DBUG_ENTER("mysql_use_result (clone)");
MYSQL_RES* result;
DBUG_ENTER("mysql_use_result (clone)");
if (!mysql->fields)
DBUG_RETURN(0);
if (!mysql->fields)
DBUG_RETURN(0);
if (mysql->status != MYSQL_STATUS_GET_RESULT)
{
set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(0);
}
if (mysql->status != MYSQL_STATUS_GET_RESULT)
{
set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(0);
}
if (!(result = (MYSQL_RES*) my_malloc(PSI_NOT_INSTRUMENTED, sizeof(*result) +
sizeof(ulong) * mysql->field_count,
MYF(MY_WME | MY_ZEROFILL))))
DBUG_RETURN(0);
if (!(result =
(MYSQL_RES*)my_malloc(PSI_NOT_INSTRUMENTED, sizeof(*result) + sizeof(ulong) * mysql->field_count,
MYF(MY_WME | MY_ZEROFILL))))
DBUG_RETURN(0);
result->lengths = (ulong*) (result + 1);
result->methods = mysql->methods;
result->lengths = (ulong*)(result + 1);
result->methods = mysql->methods;
if (!(result->row = (MYSQL_ROW)
my_malloc(PSI_NOT_INSTRUMENTED, sizeof(result->row[0]) * (mysql->field_count + 1), MYF(MY_WME))))
{
/* Ptrs: to one row */
my_free(result);
DBUG_RETURN(0);
}
if (!(result->row = (MYSQL_ROW)my_malloc(PSI_NOT_INSTRUMENTED,
sizeof(result->row[0]) * (mysql->field_count + 1), MYF(MY_WME))))
{
/* Ptrs: to one row */
my_free(result);
DBUG_RETURN(0);
}
result->fields = mysql->fields;
result->field_alloc = mysql->field_alloc;
result->field_count = mysql->field_count;
result->current_field = 0;
result->handle = mysql;
result->current_row = 0;
mysql->fields = 0; /* fields is now in result */
clear_alloc_root(&mysql->field_alloc);
mysql->status = MYSQL_STATUS_USE_RESULT;
mysql->unbuffered_fetch_owner = &result->unbuffered_fetch_cancelled;
DBUG_RETURN(result); /* Data is read to be fetched */
result->fields = mysql->fields;
result->field_alloc = mysql->field_alloc;
result->field_count = mysql->field_count;
result->current_field = 0;
result->handle = mysql;
result->current_row = 0;
mysql->fields = 0; /* fields is now in result */
clear_alloc_root(&mysql->field_alloc);
mysql->status = MYSQL_STATUS_USE_RESULT;
mysql->unbuffered_fetch_owner = &result->unbuffered_fetch_cancelled;
DBUG_RETURN(result); /* Data is read to be fetched */
}
MYSQL_FIELD* mysql_fetch_fields(MYSQL_RES* res)
{
return res->fields;
return res->fields;
}

View File

@ -48,9 +48,14 @@
#if IDB_SM_PROFILE
#include <sys/time.h>
#define GET_PF_TIME(n) {gettimeofday(&n, NULL);}
#define GET_PF_TIME(n) \
{ \
gettimeofday(&n, NULL); \
}
#else
#define GET_PF_TIME(n) {}
#define GET_PF_TIME(n) \
{ \
}
#endif
namespace sm
@ -61,10 +66,12 @@ const int SQL_KILLED = -1001;
const int CALPONT_INTERNAL_ERROR = -1007;
//#if IDB_SM_DEBUG
//extern std::ofstream smlog;
// extern std::ofstream smlog;
//#define SMDEBUGLOG smlog
//#else
#define SMDEBUGLOG if (false) std::cout
#define SMDEBUGLOG \
if (false) \
std::cout
//#endif
extern const std::string DEFAULT_SAVE_PATH;
@ -73,206 +80,219 @@ typedef int32_t status_t;
enum QueryState
{
NO_QUERY = 0,
QUERY_IN_PROCESS
NO_QUERY = 0,
QUERY_IN_PROCESS
};
typedef struct Column
{
Column(): tableID(-1) {}
~Column() {}
int tableID;
int colPos;
int dataType;
std::vector <std::string> data;
Column() : tableID(-1)
{
}
~Column()
{
}
int tableID;
int colPos;
int dataType;
std::vector<std::string> data;
} Column;
typedef std::map <int, Column*> ResultMap;
typedef std::map<int, Column*> ResultMap;
struct Profiler
{
struct timeval login;
struct timeval beforePlan;
struct timeval afterPlan;
struct timeval resultArrival;
struct timeval resultReady;
struct timeval endProcess;
long prePlan()
{
return (beforePlan.tv_sec - login.tv_sec) * 1000 +
(beforePlan.tv_usec - login.tv_usec) / 1000;
}
long buildPlan()
{
return (afterPlan.tv_sec - beforePlan.tv_sec) * 1000 +
(afterPlan.tv_usec - beforePlan.tv_usec) / 1000;
}
long jobProcess()
{
return (resultArrival.tv_sec - afterPlan.tv_sec) * 1000 +
(resultArrival.tv_usec - afterPlan.tv_usec) / 1000;
}
long buildResult()
{
return (resultReady.tv_sec - resultArrival.tv_sec) * 1000 +
(resultReady.tv_usec - resultArrival.tv_usec) / 1000;
}
long tableFetch ()
{
return (endProcess.tv_sec - resultReady.tv_sec) * 1000 +
(endProcess.tv_usec - resultReady.tv_usec) / 1000;
}
struct timeval login;
struct timeval beforePlan;
struct timeval afterPlan;
struct timeval resultArrival;
struct timeval resultReady;
struct timeval endProcess;
long prePlan()
{
return (beforePlan.tv_sec - login.tv_sec) * 1000 + (beforePlan.tv_usec - login.tv_usec) / 1000;
}
long buildPlan()
{
return (afterPlan.tv_sec - beforePlan.tv_sec) * 1000 + (afterPlan.tv_usec - beforePlan.tv_usec) / 1000;
}
long jobProcess()
{
return (resultArrival.tv_sec - afterPlan.tv_sec) * 1000 +
(resultArrival.tv_usec - afterPlan.tv_usec) / 1000;
}
long buildResult()
{
return (resultReady.tv_sec - resultArrival.tv_sec) * 1000 +
(resultReady.tv_usec - resultArrival.tv_usec) / 1000;
}
long tableFetch()
{
return (endProcess.tv_sec - resultReady.tv_sec) * 1000 +
(endProcess.tv_usec - resultReady.tv_usec) / 1000;
}
};
/** @brief Calpont table scan handle */
struct cpsm_tplsch_t
{
cpsm_tplsch_t() : tableid(0), rowsreturned(0), rowGroup(0), traceFlags(0), bandID(0), saveFlag(0), bandsReturned(0),
ctp(0) {}
~cpsm_tplsch_t()
{
delete rowGroup;
}
cpsm_tplsch_t()
: tableid(0), rowsreturned(0), rowGroup(0), traceFlags(0), bandID(0), saveFlag(0), bandsReturned(0), ctp(0)
{
}
~cpsm_tplsch_t()
{
delete rowGroup;
}
tableid_t tableid;
uint64_t rowsreturned;
rowgroup::RowGroup* rowGroup;
messageqcpp::ByteStream bs; // rowgroup bytestream. need to stay with the life span of rowgroup
uint32_t traceFlags;
// @bug 649
int bandID; // the band that being read from the disk
int key; // unique key for the table's scan context
// @bug 626
uint16_t saveFlag;
uint32_t bandsReturned;
std::vector<execplan::CalpontSystemCatalog::ColType> ctp;
std::string errMsg;
rowgroup::RGData rgData;
void deserializeTable(messageqcpp::ByteStream& bs)
tableid_t tableid;
uint64_t rowsreturned;
rowgroup::RowGroup* rowGroup;
messageqcpp::ByteStream bs; // rowgroup bytestream. need to stay with the life span of rowgroup
uint32_t traceFlags;
// @bug 649
int bandID; // the band that being read from the disk
int key; // unique key for the table's scan context
// @bug 626
uint16_t saveFlag;
uint32_t bandsReturned;
std::vector<execplan::CalpontSystemCatalog::ColType> ctp;
std::string errMsg;
rowgroup::RGData rgData;
void deserializeTable(messageqcpp::ByteStream& bs)
{
if (!rowGroup)
{
if (!rowGroup)
{
rowGroup = new rowgroup::RowGroup();
rowGroup->deserialize(bs);
}
else
{
// XXXST: the 'true' is to ease the transition to RGDatas. Take it out when the
// transition is done.
rgData.deserialize(bs, true);
rowGroup->setData(&rgData);
//rowGroup->setData(const_cast<uint8_t*>(bs.buf()));
}
rowGroup = new rowgroup::RowGroup();
rowGroup->deserialize(bs);
}
else
{
// XXXST: the 'true' is to ease the transition to RGDatas. Take it out when the
// transition is done.
rgData.deserialize(bs, true);
rowGroup->setData(&rgData);
// rowGroup->setData(const_cast<uint8_t*>(bs.buf()));
}
}
uint16_t getStatus()
{
idbassert(rowGroup != 0);
return rowGroup->getStatus();
}
uint16_t getStatus()
{
idbassert(rowGroup != 0);
return rowGroup->getStatus();
}
uint64_t getRowCount()
{
if (rowGroup)
return rowGroup->getRowCount();
else
return 0;
}
uint64_t getRowCount()
{
if (rowGroup)
return rowGroup->getRowCount();
else
return 0;
}
void setErrMsg()
void setErrMsg()
{
if (rowGroup && getStatus())
{
if (rowGroup && getStatus())
{
//bs.advance(rowGroup->getDataSize());
bs >> errMsg;
}
else
{
errMsg = "NOERROR";
}
// bs.advance(rowGroup->getDataSize());
bs >> errMsg;
}
else
{
errMsg = "NOERROR";
}
}
};
typedef boost::shared_ptr<cpsm_tplsch_t> sp_cpsm_tplsch_t;
/** @brief Calpont connection handle structure */
class cpsm_conhdl_t
{
public:
cpsm_conhdl_t(time_t v, const uint32_t sid, bool columnstore_local_query) :
value(v), sessionID(sid), queryState (NO_QUERY),
exeMgr( new execplan::ClientRotator(sid, "ExeMgr", columnstore_local_query)),
tblinfo_idx(0), idxinfo_idx(0), curFetchTb (0)
{ }
public:
cpsm_conhdl_t(time_t v, const uint32_t sid, bool columnstore_local_query)
: value(v)
, sessionID(sid)
, queryState(NO_QUERY)
, exeMgr(new execplan::ClientRotator(sid, "ExeMgr", columnstore_local_query))
, tblinfo_idx(0)
, idxinfo_idx(0)
, curFetchTb(0)
{
}
/** @brief connnect ExeMgr
*
* Try connecting to ExeMgr. If no connection, try ExeMgr1,
* ExeMgr2... until timeout lapses. Then throw exception.
*/
void connect(double timeout = 0.005)
{
exeMgr->connect(timeout);
}
EXPORT void write(messageqcpp::ByteStream bs);
/** @brief connnect ExeMgr
*
* Try connecting to ExeMgr. If no connection, try ExeMgr1,
* ExeMgr2... until timeout lapses. Then throw exception.
*/
void connect(double timeout = 0.005)
{
exeMgr->connect(timeout);
}
EXPORT void write(messageqcpp::ByteStream bs);
~cpsm_conhdl_t()
{
delete exeMgr;
}
EXPORT const std::string toString() const;
time_t value;
uint32_t sessionID;
short queryState; // 0 -- NO_QUERY; 1 -- QUERY_IN_PROCESS
execplan::ClientRotator* exeMgr;
ResultMap resultSet;
Profiler pf;
int tblinfo_idx;
int idxinfo_idx;
std::string schemaname;
std::string tablename;
int tboid;
short requestType; // 0 -- ID2NAME; 1 -- NAME2ID
boost::shared_ptr<execplan::CalpontSystemCatalog> csc;
// @bug 649; @bug 626
std::map<int, int> tidMap; // tableid-tableStartCount map
std::map<int, sp_cpsm_tplsch_t> tidScanMap;
std::map<int, int> keyBandMap; // key-savedBandCount map
int curFetchTb; // current fetching table key
std::string queryStats;
std::string extendedStats;
std::string miniStats;
~cpsm_conhdl_t()
{
delete exeMgr;
}
EXPORT const std::string toString() const;
time_t value;
uint32_t sessionID;
short queryState; // 0 -- NO_QUERY; 1 -- QUERY_IN_PROCESS
execplan::ClientRotator* exeMgr;
ResultMap resultSet;
Profiler pf;
int tblinfo_idx;
int idxinfo_idx;
std::string schemaname;
std::string tablename;
int tboid;
short requestType; // 0 -- ID2NAME; 1 -- NAME2ID
boost::shared_ptr<execplan::CalpontSystemCatalog> csc;
// @bug 649; @bug 626
std::map <int, int> tidMap; // tableid-tableStartCount map
std::map <int, sp_cpsm_tplsch_t> tidScanMap;
std::map <int, int> keyBandMap; // key-savedBandCount map
int curFetchTb; // current fetching table key
std::string queryStats;
std::string extendedStats;
std::string miniStats;
private:
private:
};
std::ostream& operator<<(std::ostream& output, const cpsm_conhdl_t& rhs);
// @bug 626 save table bands to avoid sending plan too many times
enum SavingFlag
{
NO_SAVE = 0,
SAVING,
SAVED
NO_SAVE = 0,
SAVING,
SAVED
};
/** @brief Calpont table handle */
struct cpsm_tplh_t
{
cpsm_tplh_t() : tableid(0), rowsintable(0), bandID(0), saveFlag(NO_SAVE), bandsInTable(0) {}
tableid_t tableid;
int rowsintable;
// @bug 649
int bandID; // the band that being read from the disk
int key; // unique key for the table's scan context
// @bug 626
uint16_t saveFlag;
int bandsInTable;
cpsm_tplh_t() : tableid(0), rowsintable(0), bandID(0), saveFlag(NO_SAVE), bandsInTable(0)
{
}
tableid_t tableid;
int rowsintable;
// @bug 649
int bandID; // the band that being read from the disk
int key; // unique key for the table's scan context
// @bug 626
uint16_t saveFlag;
int bandsInTable;
};
struct cpsm_tid_t
{
cpsm_tid_t() : valid(false), value(0) {}
bool valid;
int value;
cpsm_tid_t() : valid(false), value(0)
{
}
bool valid;
int value;
};
extern status_t sm_init(uint32_t, cpsm_conhdl_t**, uint32_t columnstore_local_query = false);
@ -282,11 +302,11 @@ extern status_t tpl_open(tableid_t, cpsm_tplh_t*, cpsm_conhdl_t*);
extern status_t tpl_scan_open(tableid_t, sp_cpsm_tplsch_t&, cpsm_conhdl_t*);
extern status_t tpl_scan_fetch(sp_cpsm_tplsch_t&, cpsm_conhdl_t*, int* k = 0);
extern status_t tpl_scan_close(sp_cpsm_tplsch_t&);
extern status_t tpl_close(cpsm_tplh_t*, cpsm_conhdl_t**, querystats::QueryStats& stats, bool ask_4_stats, bool clear_scan_ctx = false);
extern status_t tpl_close(cpsm_tplh_t*, cpsm_conhdl_t**, querystats::QueryStats& stats, bool ask_4_stats,
bool clear_scan_ctx = false);
}
} // namespace sm
#undef EXPORT
#endif

View File

@ -29,85 +29,84 @@ typedef int64_t longlong;
string toString(int64_t t1, unsigned scale)
{
longlong int_val = (longlong)t1;
// MySQL seems to round off values unless we use the string store method. Groan.
// Taken from tablefuncs.cpp
longlong int_val = (longlong)t1;
// MySQL seems to round off values unless we use the string store method. Groan.
// Taken from tablefuncs.cpp
//biggest Calpont supports is DECIMAL(18,x), or 18 total digits+dp+sign
const int ctmp_size = 18 + 1 + 1 + 1;
char ctmp[ctmp_size];
snprintf(ctmp, ctmp_size,
// biggest Calpont supports is DECIMAL(18,x), or 18 total digits+dp+sign
const int ctmp_size = 18 + 1 + 1 + 1;
char ctmp[ctmp_size];
snprintf(ctmp, ctmp_size,
#if __WORDSIZE <= 32
"%lld",
"%lld",
#else
"%ld",
"%ld",
#endif
int_val);
//we want to move the last dt_scale chars right by one spot to insert the dp
//we want to move the trailing null as well, so it's really dt_scale+1 chars
size_t l1 = strlen(ctmp);
//need to make sure we have enough leading zeros for this to work...
//at this point scale is always > 0
char* ptr = &ctmp[0];
int_val);
// we want to move the last dt_scale chars right by one spot to insert the dp
// we want to move the trailing null as well, so it's really dt_scale+1 chars
size_t l1 = strlen(ctmp);
// need to make sure we have enough leading zeros for this to work...
// at this point scale is always > 0
char* ptr = &ctmp[0];
if (int_val < 0)
{
ptr++;
idbassert(l1 >= 2);
l1--;
}
if (int_val < 0)
{
ptr++;
idbassert(l1 >= 2);
l1--;
}
if (scale > l1)
{
const char* zeros = "000000000000000000"; //18 0's
size_t diff = scale - l1; //this will always be > 0
memmove((ptr + diff), ptr, l1 + 1); //also move null
memcpy(ptr, zeros, diff);
l1 = 0;
}
else
l1 -= scale;
if (scale > l1)
{
const char* zeros = "000000000000000000"; // 18 0's
size_t diff = scale - l1; // this will always be > 0
memmove((ptr + diff), ptr, l1 + 1); // also move null
memcpy(ptr, zeros, diff);
l1 = 0;
}
else
l1 -= scale;
memmove((ptr + l1 + 1), (ptr + l1), scale + 1); //also move null
*(ptr + l1) = '.';
memmove((ptr + l1 + 1), (ptr + l1), scale + 1); // also move null
*(ptr + l1) = '.';
return string(ctmp);
}
return string(ctmp);
}
} // namespace
int main(int argc, char** argv)
{
int64_t x;
string xstr;
int64_t x;
string xstr;
x = 10001LL;
xstr = toString(x, 2);
idbassert(xstr == "100.01");
x = 10001LL;
xstr = toString(x, 2);
idbassert(xstr == "100.01");
x = -10001LL;
xstr = toString(x, 2);
idbassert(xstr == "-100.01");
x = -10001LL;
xstr = toString(x, 2);
idbassert(xstr == "-100.01");
x = 999999999999999999LL;
xstr = toString(x, 2);
idbassert(xstr == "9999999999999999.99");
x = 999999999999999999LL;
xstr = toString(x, 2);
idbassert(xstr == "9999999999999999.99");
x = -999999999999999999LL;
xstr = toString(x, 2);
idbassert(xstr == "-9999999999999999.99");
x = -999999999999999999LL;
xstr = toString(x, 2);
idbassert(xstr == "-9999999999999999.99");
x = 1LL;
xstr = toString(x, 5);
idbassert(xstr == ".00001");
x = 1LL;
xstr = toString(x, 5);
idbassert(xstr == ".00001");
x = -1LL;
xstr = toString(x, 5);
idbassert(xstr == "-.00001");
x = -1LL;
xstr = toString(x, 5);
idbassert(xstr == "-.00001");
x = -1LL;
xstr = toString(x, 16);
idbassert(xstr == "-.0000000000000001");
x = -1LL;
xstr = toString(x, 16);
idbassert(xstr == "-.0000000000000001");
return 0;
return 0;
}

View File

@ -5,4 +5,3 @@
const std::string idb_version("1.0.2");
const std::string idb_release("1");
#endif