You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-29 08:21:15 +03:00
Merge pull request #2741 from mariadb-corporation/MDEV-25080-CS-dev
MDEV-25080 Allow pushdown of queries involving UNIONs in outer select to ColumnStore
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
local events = ['pull_request', 'cron'];
|
||||
|
||||
local servers = {
|
||||
develop: ['10.6-enterprise'],
|
||||
'develop-22.08': ['10.6-enterprise'],
|
||||
develop: ['10.6-MENT-1667'],
|
||||
'develop-22.08': ['10.6-MENT-1667'],
|
||||
};
|
||||
|
||||
local platforms = {
|
||||
@ -108,7 +108,7 @@ local testPreparation(platform) =
|
||||
platform_map[platform];
|
||||
|
||||
|
||||
local Pipeline(branch, platform, event, arch='amd64', server='10.6-enterprise') = {
|
||||
local Pipeline(branch, platform, event, arch='amd64', server='10.6-MENT-1667') = {
|
||||
local pkg_format = if (std.split(platform, ':')[0] == 'centos' || std.split(platform, ':')[0] == 'rockylinux') then 'rpm' else 'deb',
|
||||
local init = if (pkg_format == 'rpm') then '/usr/lib/systemd/systemd' else 'systemd',
|
||||
local mtr_path = if (pkg_format == 'rpm') then '/usr/share/mysql-test' else '/usr/share/mysql/mysql-test',
|
||||
@ -125,7 +125,7 @@ local Pipeline(branch, platform, event, arch='amd64', server='10.6-enterprise')
|
||||
local container_tags = if (event == 'cron') then [brancht + std.strReplace(event, '_', '-') + '${DRONE_BUILD_NUMBER}', brancht] else [brancht + std.strReplace(event, '_', '-') + '${DRONE_BUILD_NUMBER}'],
|
||||
local container_version = branchp + event + '/${DRONE_BUILD_NUMBER}/' + server + '/' + arch,
|
||||
|
||||
local server_remote = if (std.endsWith(server, 'enterprise')) then 'https://github.com/mariadb-corporation/MariaDBEnterprise' else 'https://github.com/MariaDB/server',
|
||||
local server_remote = if (std.endsWith(server, 'enterprise') || std.endsWith(server, '10.6-MENT-1667')) then 'https://github.com/mariadb-corporation/MariaDBEnterprise' else 'https://github.com/MariaDB/server',
|
||||
|
||||
local sccache_arch = if (arch == 'amd64') then 'x86_64' else 'aarch64',
|
||||
local get_sccache = 'curl -L -o sccache.tar.gz https://github.com/mozilla/sccache/releases/download/v0.3.0/sccache-v0.3.0-' + sccache_arch + '-unknown-linux-musl.tar.gz ' +
|
||||
@ -693,8 +693,8 @@ local FinalPipeline(branch, event) = {
|
||||
'failure',
|
||||
],
|
||||
} + (if event == 'cron' then { cron: ['nightly-' + std.strReplace(branch, '.', '-')] } else {}),
|
||||
depends_on: std.map(function(p) std.join(' ', [branch, p, event, 'amd64', '10.6-enterprise']), platforms.develop) +
|
||||
std.map(function(p) std.join(' ', [branch, p, event, 'arm64', '10.6-enterprise']), platforms_arm.develop),
|
||||
depends_on: std.map(function(p) std.join(' ', [branch, p, event, 'amd64', '10.6-MENT-1667']), platforms.develop) +
|
||||
std.map(function(p) std.join(' ', [branch, p, event, 'arm64', '10.6-MENT-1667']), platforms_arm.develop),
|
||||
};
|
||||
|
||||
|
||||
@ -719,10 +719,10 @@ local FinalPipeline(branch, event) = {
|
||||
] +
|
||||
|
||||
[
|
||||
Pipeline(any_branch, p, 'custom', 'amd64', '10.6-enterprise')
|
||||
Pipeline(any_branch, p, 'custom', 'amd64', '10.6-MENT-1667')
|
||||
for p in platforms_custom
|
||||
] +
|
||||
[
|
||||
Pipeline(any_branch, p, 'custom', 'arm64', '10.6-enterprise')
|
||||
Pipeline(any_branch, p, 'custom', 'arm64', '10.6-MENT-1667')
|
||||
for p in platforms_arm_custom
|
||||
]
|
||||
|
@ -6393,12 +6393,13 @@ boost::any CalpontSystemCatalog::ColType::convertColumnData(const std::string& d
|
||||
}
|
||||
|
||||
CalpontSystemCatalog::ColType CalpontSystemCatalog::ColType::convertUnionColType(
|
||||
vector<CalpontSystemCatalog::ColType>& types)
|
||||
vector<CalpontSystemCatalog::ColType>& types,
|
||||
unsigned int& rc)
|
||||
{
|
||||
idbassert(types.size());
|
||||
CalpontSystemCatalog::ColType unionedType = types[0];
|
||||
for (uint64_t i = 1; i < types.size(); i++)
|
||||
dataconvert::DataConvert::joinColTypeForUnion(unionedType, types[i]);
|
||||
dataconvert::DataConvert::joinColTypeForUnion(unionedType, types[i], rc);
|
||||
return unionedType;
|
||||
}
|
||||
|
||||
|
@ -306,7 +306,7 @@ class CalpontSystemCatalog : public datatypes::SystemCatalog
|
||||
return !(*this == t);
|
||||
}
|
||||
|
||||
static ColType convertUnionColType(std::vector<ColType>&);
|
||||
static ColType convertUnionColType(std::vector<ColType>&, unsigned int&);
|
||||
};
|
||||
|
||||
/** the structure of a table infomation
|
||||
|
@ -5102,11 +5102,18 @@ SJSTEP unionQueries(JobStepVector& queries, uint64_t distinctUnionNum, JobInfo&
|
||||
unionStep->inputAssociation(jsaToUnion);
|
||||
unionStep->outputAssociation(jsa);
|
||||
|
||||
// This return code in the call to convertUnionColType() below would
|
||||
// always be 0. This is because convertUnionColType() is also called
|
||||
// in the connector code in getSelectPlan()/getGroupPlan() which handle
|
||||
// the non-zero return code scenarios from this function call and error
|
||||
// out, in which case, the execution does not even get to ExeMgr.
|
||||
unsigned int dummyUnionedTypeRc = 0;
|
||||
|
||||
// get unioned column types
|
||||
for (uint64_t j = 0; j < colCount; ++j)
|
||||
{
|
||||
CalpontSystemCatalog::ColType colType =
|
||||
CalpontSystemCatalog::ColType::convertUnionColType(queryColTypes[j]);
|
||||
CalpontSystemCatalog::ColType::convertUnionColType(queryColTypes[j], dummyUnionedTypeRc);
|
||||
types.push_back(colType.colDataType);
|
||||
csNums.push_back(colType.charsetNumber);
|
||||
scale.push_back(colType.scale);
|
||||
|
@ -1766,12 +1766,14 @@ void TupleUnion::writeNull(Row* out, uint32_t col)
|
||||
{
|
||||
case 1: out->setUintField<1>(joblist::TINYINTNULL, col); break;
|
||||
|
||||
case 2: out->setUintField<1>(joblist::SMALLINTNULL, col); break;
|
||||
case 2: out->setUintField<2>(joblist::SMALLINTNULL, col); break;
|
||||
|
||||
case 4: out->setUintField<4>(joblist::INTNULL, col); break;
|
||||
|
||||
case 8: out->setUintField<8>(joblist::BIGINTNULL, col); break;
|
||||
|
||||
case 16: out->setInt128Field(datatypes::Decimal128Null, col); break;
|
||||
|
||||
default:
|
||||
{
|
||||
}
|
||||
|
@ -45,7 +45,8 @@ group_by_handler* create_columnstore_group_by_handler(THD* thd, Query* query);
|
||||
|
||||
derived_handler* create_columnstore_derived_handler(THD* thd, TABLE_LIST* derived);
|
||||
|
||||
select_handler* create_columnstore_select_handler(THD* thd, SELECT_LEX* sel);
|
||||
select_handler* create_columnstore_select_handler(THD* thd, SELECT_LEX* sel_lex, SELECT_LEX_UNIT* sel_unit);
|
||||
select_handler* create_columnstore_unit_handler(THD* thd, SELECT_LEX_UNIT* sel_unit);
|
||||
|
||||
/* Variables for example share methods */
|
||||
|
||||
@ -1835,6 +1836,7 @@ static int columnstore_init_func(void* p)
|
||||
mcs_hton->create_group_by = create_columnstore_group_by_handler;
|
||||
mcs_hton->create_derived = create_columnstore_derived_handler;
|
||||
mcs_hton->create_select = create_columnstore_select_handler;
|
||||
mcs_hton->create_unit = create_columnstore_unit_handler;
|
||||
mcs_hton->db_type = DB_TYPE_AUTOASSIGN;
|
||||
|
||||
#ifdef HAVE_PSI_INTERFACE
|
||||
|
@ -6682,7 +6682,8 @@ void setExecutionParams(gp_walk_info& gwi, SCSEP& csep)
|
||||
* RETURNS
|
||||
* error id as an int
|
||||
***********************************************************/
|
||||
int processFrom(bool& isUnion, SELECT_LEX& select_lex, gp_walk_info& gwi, SCSEP& csep)
|
||||
int processFrom(bool& isUnion, SELECT_LEX& select_lex, gp_walk_info& gwi, SCSEP& csep,
|
||||
bool isSelectHandlerTop, bool isSelectLexUnit)
|
||||
{
|
||||
// populate table map and trigger syscolumn cache for all the tables (@bug 1637).
|
||||
// all tables on FROM list must have at least one col in colmap
|
||||
@ -6819,9 +6820,9 @@ int processFrom(bool& isUnion, SELECT_LEX& select_lex, gp_walk_info& gwi, SCSEP&
|
||||
bool unionSel = false;
|
||||
// UNION master unit check
|
||||
// Existed pushdown handlers won't get in this scope
|
||||
// except UNION pushdown that is to come.
|
||||
// MDEV-25080 Union pushdown would enter this scope
|
||||
// is_unit_op() give a segv for derived_handler's SELECT_LEX
|
||||
if (!isUnion && select_lex.master_unit()->is_unit_op())
|
||||
if (!isUnion && (!isSelectHandlerTop || isSelectLexUnit) && select_lex.master_unit()->is_unit_op())
|
||||
{
|
||||
// MCOL-2178 isUnion member only assigned, never used
|
||||
// MIGR::infinidb_vtable.isUnion = true;
|
||||
@ -7383,7 +7384,8 @@ void buildInToExistsFilter(gp_walk_info& gwi, SELECT_LEX& select_lex)
|
||||
* error id as an int
|
||||
***********************************************************/
|
||||
int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool isUnion,
|
||||
bool isSelectHandlerTop, const std::vector<COND*>& condStack)
|
||||
bool isSelectHandlerTop, bool isSelectLexUnit,
|
||||
const std::vector<COND*>& condStack)
|
||||
{
|
||||
#ifdef DEBUG_WALK_COND
|
||||
cerr << "getSelectPlan()" << endl;
|
||||
@ -7411,13 +7413,12 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
CalpontSelectExecutionPlan::SelectList derivedTbList;
|
||||
// @bug 1796. Remember table order on the FROM list.
|
||||
gwi.clauseType = FROM;
|
||||
if ((rc = processFrom(isUnion, select_lex, gwi, csep)))
|
||||
if ((rc = processFrom(isUnion, select_lex, gwi, csep, isSelectHandlerTop,
|
||||
isSelectLexUnit)))
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool unionSel = (!isUnion && select_lex.master_unit()->is_unit_op()) ? true : false;
|
||||
|
||||
gwi.clauseType = WHERE;
|
||||
if ((rc = processWhere(select_lex, gwi, csep, condStack)))
|
||||
{
|
||||
@ -7860,25 +7861,32 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
// @bug4388 normalize the project coltypes for union main select list
|
||||
if (!csep->unionVec().empty())
|
||||
{
|
||||
unsigned int unionedTypeRc = 0;
|
||||
|
||||
for (uint32_t i = 0; i < gwi.returnedCols.size(); i++)
|
||||
{
|
||||
vector<CalpontSystemCatalog::ColType> coltypes;
|
||||
|
||||
for (uint32_t j = 0; j < csep->unionVec().size(); j++)
|
||||
{
|
||||
coltypes.push_back(dynamic_cast<CalpontSelectExecutionPlan*>(csep->unionVec()[j].get())
|
||||
->returnedCols()[i]
|
||||
->resultType());
|
||||
CalpontSelectExecutionPlan* unionCsep =
|
||||
dynamic_cast<CalpontSelectExecutionPlan*>(csep->unionVec()[j].get());
|
||||
coltypes.push_back(unionCsep->returnedCols()[i]->resultType());
|
||||
|
||||
// @bug5976. set hasAggregate true for the main column if
|
||||
// one corresponding union column has aggregate
|
||||
if (dynamic_cast<CalpontSelectExecutionPlan*>(csep->unionVec()[j].get())
|
||||
->returnedCols()[i]
|
||||
->hasAggregate())
|
||||
if (unionCsep->returnedCols()[i]->hasAggregate())
|
||||
gwi.returnedCols[i]->hasAggregate(true);
|
||||
}
|
||||
|
||||
gwi.returnedCols[i]->resultType(CalpontSystemCatalog::ColType::convertUnionColType(coltypes));
|
||||
gwi.returnedCols[i]->resultType(CalpontSystemCatalog::ColType::convertUnionColType(coltypes, unionedTypeRc));
|
||||
|
||||
if (unionedTypeRc != 0)
|
||||
{
|
||||
gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(unionedTypeRc);
|
||||
setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi);
|
||||
return ER_CHECK_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8047,6 +8055,8 @@ int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, bool i
|
||||
|
||||
SRCP minSc; // min width projected column. for count(*) use
|
||||
|
||||
bool unionSel = (!isUnion && select_lex.master_unit()->is_unit_op()) ? true : false;
|
||||
|
||||
// Group by list. not valid for union main query
|
||||
if (!unionSel)
|
||||
{
|
||||
@ -8805,9 +8815,10 @@ int cs_get_derived_plan(ha_columnstore_derived_handler* handler, THD* thd, SCSEP
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* thd, SCSEP& csep, gp_walk_info& gwi)
|
||||
int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* thd, SCSEP& csep, gp_walk_info& gwi,
|
||||
bool isSelectLexUnit)
|
||||
{
|
||||
SELECT_LEX& select_lex = *handler->select;
|
||||
SELECT_LEX& select_lex = handler->select_lex ? *handler->select_lex : *handler->lex_unit->first_select();
|
||||
|
||||
if (select_lex.where)
|
||||
{
|
||||
@ -8819,7 +8830,7 @@ int cs_get_select_plan(ha_columnstore_select_handler* handler, THD* thd, SCSEP&
|
||||
convertOuterJoinToInnerJoin(&select_lex.top_join_list, gwi.tableOnExprList, gwi.condList,
|
||||
handler->tableOuterJoinMap);
|
||||
|
||||
int status = getSelectPlan(gwi, select_lex, csep, false, true);
|
||||
int status = getSelectPlan(gwi, select_lex, csep, false, true, isSelectLexUnit);
|
||||
|
||||
if (status > 0)
|
||||
return ER_INTERNAL_ERROR;
|
||||
@ -9683,25 +9694,32 @@ int getGroupPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, SCSEP& csep, cal_gro
|
||||
// @bug4388 normalize the project coltypes for union main select list
|
||||
if (!csep->unionVec().empty())
|
||||
{
|
||||
unsigned int unionedTypeRc = 0;
|
||||
|
||||
for (uint32_t i = 0; i < gwi.returnedCols.size(); i++)
|
||||
{
|
||||
vector<CalpontSystemCatalog::ColType> coltypes;
|
||||
|
||||
for (uint32_t j = 0; j < csep->unionVec().size(); j++)
|
||||
{
|
||||
coltypes.push_back(dynamic_cast<CalpontSelectExecutionPlan*>(csep->unionVec()[j].get())
|
||||
->returnedCols()[i]
|
||||
->resultType());
|
||||
CalpontSelectExecutionPlan* unionCsep =
|
||||
dynamic_cast<CalpontSelectExecutionPlan*>(csep->unionVec()[j].get());
|
||||
coltypes.push_back(unionCsep->returnedCols()[i]->resultType());
|
||||
|
||||
// @bug5976. set hasAggregate true for the main column if
|
||||
// one corresponding union column has aggregate
|
||||
if (dynamic_cast<CalpontSelectExecutionPlan*>(csep->unionVec()[j].get())
|
||||
->returnedCols()[i]
|
||||
->hasAggregate())
|
||||
if (unionCsep->returnedCols()[i]->hasAggregate())
|
||||
gwi.returnedCols[i]->hasAggregate(true);
|
||||
}
|
||||
|
||||
gwi.returnedCols[i]->resultType(CalpontSystemCatalog::ColType::convertUnionColType(coltypes));
|
||||
gwi.returnedCols[i]->resultType(CalpontSystemCatalog::ColType::convertUnionColType(coltypes, unionedTypeRc));
|
||||
|
||||
if (unionedTypeRc != 0)
|
||||
{
|
||||
gwi.parseErrorText = IDBErrorInfo::instance()->errorMsg(unionedTypeRc);
|
||||
setError(gwi.thd, ER_CHECK_NOT_IMPLEMENTED, gwi.parseErrorText, gwi);
|
||||
return ER_CHECK_NOT_IMPLEMENTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1392,7 +1392,7 @@ uint32_t doUpdateDelete(THD* thd, gp_walk_info& gwi, const std::vector<COND*>& c
|
||||
|
||||
gwi.clauseType = WHERE;
|
||||
|
||||
if (getSelectPlan(gwi, select_lex, updateCP, false, false, condStack) !=
|
||||
if (getSelectPlan(gwi, select_lex, updateCP, false, false, false, condStack) !=
|
||||
0) //@Bug 3030 Modify the error message for unsupported functions
|
||||
{
|
||||
if (gwi.cs_vtable_is_update_with_derive)
|
||||
@ -4886,7 +4886,7 @@ int ha_mcs_impl_group_by_end(TABLE* table)
|
||||
* RETURN:
|
||||
* rc as int
|
||||
***********************************************************/
|
||||
int ha_mcs_impl_pushdown_init(mcs_handler_info* handler_info, TABLE* table)
|
||||
int ha_mcs_impl_pushdown_init(mcs_handler_info* handler_info, TABLE* table, bool isSelectLexUnit)
|
||||
{
|
||||
IDEBUG(cout << "pushdown_init for table " << endl);
|
||||
THD* thd = current_thd;
|
||||
@ -5076,7 +5076,7 @@ int ha_mcs_impl_pushdown_init(mcs_handler_info* handler_info, TABLE* table)
|
||||
if (handler_info->hndl_type == mcs_handler_types_t::SELECT)
|
||||
{
|
||||
sh = reinterpret_cast<ha_columnstore_select_handler*>(handler_info->hndl_ptr);
|
||||
status = cs_get_select_plan(sh, thd, csep, gwi);
|
||||
status = cs_get_select_plan(sh, thd, csep, gwi, isSelectLexUnit);
|
||||
}
|
||||
else if (handler_info->hndl_type == DERIVED)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ extern int ha_mcs_impl_direct_update_delete_rows(bool execute, ha_rows* affected
|
||||
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_pushdown_init(mcs_handler_info* handler_info, TABLE* table, bool isSelectLexUnit = false);
|
||||
extern int ha_mcs_impl_select_next(uchar* buf, TABLE* table, long timeZone);
|
||||
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, long timeZone);
|
||||
|
@ -397,9 +397,9 @@ int cp_get_group_plan(THD* thd, execplan::SCSEP& csep, cal_impl_if::cal_group_in
|
||||
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);
|
||||
gp_walk_info& gwi, bool isSelectLexUnit);
|
||||
int getSelectPlan(gp_walk_info& gwi, SELECT_LEX& select_lex, execplan::SCSEP& csep, bool isUnion = false,
|
||||
bool isSelectHandlerTop = false,
|
||||
bool isSelectHandlerTop = false, bool isSelectLexUnit = 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);
|
||||
|
@ -728,20 +728,21 @@ int ha_mcs_group_by_handler::end_scan()
|
||||
DBUG_RETURN(rc);
|
||||
}
|
||||
|
||||
/*@brief create_columnstore_select_handler- Creates handler*/
|
||||
/************************************************************
|
||||
/*@brief create_columnstore_select_handler_- Creates handler
|
||||
************************************************************
|
||||
* DESCRIPTION:
|
||||
* Creates a select handler if there is no non-equi JOIN, e.g
|
||||
* t1.c1 > t2.c2 and logical OR in the filter predicates.
|
||||
* More details in server/sql/select_handler.h
|
||||
* PARAMETERS:
|
||||
* thd - THD pointer.
|
||||
* select_lex - SELECT_LEX* that describes the query.
|
||||
* sel_lex - SELECT_LEX* that describes the query.
|
||||
* sel_unit - SELECT_LEX_UNIT* that describes the query.
|
||||
* RETURN:
|
||||
* select_handler if possible
|
||||
* NULL in other case
|
||||
***********************************************************/
|
||||
select_handler* create_columnstore_select_handler(THD* thd, SELECT_LEX* select_lex)
|
||||
select_handler* create_columnstore_select_handler_(THD* thd, SELECT_LEX* sel_lex, SELECT_LEX_UNIT* sel_unit)
|
||||
{
|
||||
mcs_select_handler_mode_t select_handler_mode = get_select_handler_mode(thd);
|
||||
|
||||
@ -778,60 +779,105 @@ select_handler* create_columnstore_select_handler(THD* thd, SELECT_LEX* select_l
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Iterate and traverse through the item list and the JOIN cond
|
||||
// and do not create SH if the unsupported (set_user_var)
|
||||
// function is present.
|
||||
TABLE_LIST* table_ptr = select_lex->get_table_list();
|
||||
for (; table_ptr; table_ptr = table_ptr->next_global)
|
||||
// MCOL-5432 Disable partial pushdown of the UNION operation if the query
|
||||
// involves an order by or a limit clause.
|
||||
if (sel_lex && sel_unit &&
|
||||
(sel_unit->global_parameters()->limit_params.explicit_limit == true ||
|
||||
sel_unit->global_parameters()->order_list.elements != 0))
|
||||
{
|
||||
if (check_user_var(table_ptr->select_lex))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<SELECT_LEX*> select_lex_vec;
|
||||
|
||||
if (sel_unit && !sel_lex)
|
||||
{
|
||||
for (SELECT_LEX* sl = sel_unit->first_select(); sl; sl = sl->next_select())
|
||||
{
|
||||
return nullptr;
|
||||
select_lex_vec.push_back(sl);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
select_lex_vec.push_back(sel_lex);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < select_lex_vec.size(); i++)
|
||||
{
|
||||
SELECT_LEX* select_lex = select_lex_vec[i];
|
||||
|
||||
// Iterate and traverse through the item list and the JOIN cond
|
||||
// and do not create SH if the unsupported (set_user_var)
|
||||
// function is present.
|
||||
TABLE_LIST* table_ptr = select_lex->get_table_list();
|
||||
for (; table_ptr; table_ptr = table_ptr->next_global)
|
||||
{
|
||||
if (check_user_var(table_ptr->select_lex))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We apply dedicated rewrites from MDB here so MDB's data structures
|
||||
// becomes dirty and CS has to raise an error in case of any problem
|
||||
// or unsupported feature.
|
||||
ha_columnstore_select_handler* handler = new ha_columnstore_select_handler(thd, select_lex);
|
||||
ha_columnstore_select_handler* handler;
|
||||
|
||||
JOIN* join = select_lex->join;
|
||||
|
||||
if (select_lex->first_cond_optimization && select_lex->handle_derived(thd->lex, DT_MERGE))
|
||||
if (sel_unit && sel_lex) // partial pushdown of the SELECT_LEX_UNIT
|
||||
{
|
||||
if (!thd->is_error())
|
||||
{
|
||||
my_printf_error(ER_INTERNAL_ERROR, "%s", MYF(0), "Error occured in select_lex::handle_derived()");
|
||||
}
|
||||
|
||||
return handler;
|
||||
handler = new ha_columnstore_select_handler(thd, sel_lex, sel_unit);
|
||||
}
|
||||
else if (sel_unit) // complete pushdown of the SELECT_LEX_UNIT
|
||||
{
|
||||
handler = new ha_columnstore_select_handler(thd, sel_unit);
|
||||
}
|
||||
else // Query only has a SELECT_LEX, no SELECT_LEX_UNIT
|
||||
{
|
||||
handler = new ha_columnstore_select_handler(thd, sel_lex);
|
||||
}
|
||||
|
||||
// This is partially taken from JOIN::optimize_inner() in sql/sql_select.cc
|
||||
if (select_lex->first_cond_optimization)
|
||||
for (size_t i = 0; i < select_lex_vec.size(); i++)
|
||||
{
|
||||
create_explain_query_if_not_exists(thd->lex, thd->mem_root);
|
||||
Query_arena *arena, backup;
|
||||
arena = thd->activate_stmt_arena_if_needed(&backup);
|
||||
COND* conds = join->conds;
|
||||
select_lex->where = conds;
|
||||
SELECT_LEX* select_lex = select_lex_vec[i];
|
||||
JOIN* join = select_lex->join;
|
||||
|
||||
if (isPS)
|
||||
if (select_lex->first_cond_optimization && select_lex->handle_derived(thd->lex, DT_MERGE))
|
||||
{
|
||||
select_lex->prep_where = conds ? conds->copy_andor_structure(thd) : 0;
|
||||
if (!thd->is_error())
|
||||
{
|
||||
my_printf_error(ER_INTERNAL_ERROR, "%s", MYF(0), "Error occured in select_lex::handle_derived()");
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
select_lex->update_used_tables();
|
||||
// This is partially taken from JOIN::optimize_inner() in sql/sql_select.cc
|
||||
if (select_lex->first_cond_optimization)
|
||||
{
|
||||
create_explain_query_if_not_exists(thd->lex, thd->mem_root);
|
||||
Query_arena *arena, backup;
|
||||
arena = thd->activate_stmt_arena_if_needed(&backup);
|
||||
COND* conds = join->conds;
|
||||
select_lex->where = conds;
|
||||
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
if (isPS)
|
||||
{
|
||||
select_lex->prep_where = conds ? conds->copy_andor_structure(thd) : 0;
|
||||
}
|
||||
|
||||
select_lex->update_used_tables();
|
||||
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
|
||||
#ifdef DEBUG_WALK_COND
|
||||
if (conds)
|
||||
{
|
||||
conds->traverse_cond(cal_impl_if::debug_walk, NULL, Item::POSTFIX);
|
||||
}
|
||||
if (conds)
|
||||
{
|
||||
conds->traverse_cond(cal_impl_if::debug_walk, NULL, Item::POSTFIX);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to execute the query using the select handler.
|
||||
@ -840,69 +886,45 @@ select_handler* create_columnstore_select_handler(THD* thd, SELECT_LEX* select_l
|
||||
// Skip execution for EXPLAIN queries
|
||||
if (!thd->lex->describe)
|
||||
{
|
||||
// This is taken from JOIN::optimize()
|
||||
join->fields = &select_lex->item_list;
|
||||
|
||||
// Instantiate handler::table, which is the place for the result set.
|
||||
if (handler->prepare())
|
||||
for (size_t i = 0; i < select_lex_vec.size(); i++)
|
||||
{
|
||||
// check fallback
|
||||
if (select_handler_mode == mcs_select_handler_mode_t::AUTO) // columnstore_select_handler=AUTO
|
||||
SELECT_LEX* select_lex = select_lex_vec[i];
|
||||
JOIN* join = select_lex->join;
|
||||
|
||||
// This is taken from JOIN::optimize()
|
||||
join->fields = &select_lex->item_list;
|
||||
|
||||
// Instantiate handler::table, which is the place for the result set.
|
||||
if ((i == 0) && handler->prepare())
|
||||
{
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999,
|
||||
"MCS select_handler execution failed. Falling back to server execution");
|
||||
restore_query_state(handler);
|
||||
delete handler;
|
||||
return nullptr;
|
||||
// check fallback
|
||||
if (select_handler_mode == mcs_select_handler_mode_t::AUTO) // columnstore_select_handler=AUTO
|
||||
{
|
||||
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 9999,
|
||||
"MCS select_handler execution failed. Falling back to server execution");
|
||||
restore_query_state(handler);
|
||||
delete handler;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// error out
|
||||
if (!thd->is_error())
|
||||
{
|
||||
my_printf_error(ER_INTERNAL_ERROR, "%s", MYF(0), "Error occured in handler->prepare()");
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
// error out
|
||||
if (!thd->is_error())
|
||||
{
|
||||
my_printf_error(ER_INTERNAL_ERROR, "%s", MYF(0), "Error occured in handler->prepare()");
|
||||
}
|
||||
// Prepare query execution
|
||||
// This is taken from JOIN::exec_inner()
|
||||
if (!select_lex->outer_select() && // (1)
|
||||
select_lex != select_lex->master_unit()->fake_select_lex) // (2)
|
||||
thd->lex->set_limit_rows_examined();
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
// Prepare query execution
|
||||
// This is taken from JOIN::exec_inner()
|
||||
if (!select_lex->outer_select() && // (1)
|
||||
select_lex != select_lex->master_unit()->fake_select_lex) // (2)
|
||||
thd->lex->set_limit_rows_examined();
|
||||
|
||||
if (!join->tables_list && (join->table_count || !select_lex->with_sum_func) &&
|
||||
!select_lex->have_window_funcs())
|
||||
{
|
||||
if (!thd->is_error())
|
||||
{
|
||||
restore_query_state(handler);
|
||||
delete handler;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
if (!join->zero_result_cause && join->exec_const_cond && !join->exec_const_cond->val_int())
|
||||
join->zero_result_cause = "Impossible WHERE noticed after reading const tables";
|
||||
|
||||
// We've called exec_const_cond->val_int(). This may have caused an error.
|
||||
if (unlikely(thd->is_error()))
|
||||
{
|
||||
// error out
|
||||
handler->pushdown_init_rc = 1;
|
||||
return handler;
|
||||
}
|
||||
|
||||
if (join->zero_result_cause)
|
||||
{
|
||||
if (join->select_lex->have_window_funcs() && join->send_row_on_empty_set())
|
||||
{
|
||||
join->const_tables = join->table_count;
|
||||
join->first_select = sub_select_postjoin_aggr;
|
||||
}
|
||||
else
|
||||
if ((!sel_unit || sel_lex) && !join->tables_list &&
|
||||
(join->table_count || !select_lex->with_sum_func) &&
|
||||
!select_lex->have_window_funcs())
|
||||
{
|
||||
if (!thd->is_error())
|
||||
{
|
||||
@ -913,23 +935,56 @@ select_handler* create_columnstore_select_handler(THD* thd, SELECT_LEX* select_l
|
||||
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
||||
if ((join->select_lex->options & OPTION_SCHEMA_TABLE) &&
|
||||
get_schema_tables_result(join, PROCESSED_BY_JOIN_EXEC))
|
||||
{
|
||||
if (!thd->is_error())
|
||||
if (!join->zero_result_cause && join->exec_const_cond && !join->exec_const_cond->val_int())
|
||||
join->zero_result_cause = "Impossible WHERE noticed after reading const tables";
|
||||
|
||||
// We've called exec_const_cond->val_int(). This may have caused an error.
|
||||
if (unlikely(thd->is_error()))
|
||||
{
|
||||
my_printf_error(ER_INTERNAL_ERROR, "%s", MYF(0), "Error occured in get_schema_tables_result()");
|
||||
// error out
|
||||
handler->pushdown_init_rc = 1;
|
||||
return handler;
|
||||
}
|
||||
|
||||
return handler;
|
||||
if (join->zero_result_cause)
|
||||
{
|
||||
if (join->select_lex->have_window_funcs() && join->send_row_on_empty_set())
|
||||
{
|
||||
join->const_tables = join->table_count;
|
||||
join->first_select = sub_select_postjoin_aggr;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!thd->is_error())
|
||||
{
|
||||
restore_query_state(handler);
|
||||
delete handler;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
||||
if ((join->select_lex->options & OPTION_SCHEMA_TABLE) &&
|
||||
get_schema_tables_result(join, PROCESSED_BY_JOIN_EXEC))
|
||||
{
|
||||
if (!thd->is_error())
|
||||
{
|
||||
my_printf_error(ER_INTERNAL_ERROR, "%s", MYF(0), "Error occured in get_schema_tables_result()");
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
||||
handler->scan_initialized = true;
|
||||
mcs_handler_info mhi(reinterpret_cast<void*>(handler), SELECT);
|
||||
|
||||
if ((handler->pushdown_init_rc = ha_mcs_impl_pushdown_init(&mhi, handler->table)))
|
||||
bool isSelectLexUnit = (sel_unit && !sel_lex) ? true : false;
|
||||
|
||||
if ((handler->pushdown_init_rc = ha_mcs_impl_pushdown_init(&mhi, handler->table, isSelectLexUnit)))
|
||||
{
|
||||
// check fallback
|
||||
if (select_handler_mode == mcs_select_handler_mode_t::AUTO)
|
||||
@ -967,31 +1022,101 @@ select_handler* create_columnstore_select_handler(THD* thd, SELECT_LEX* select_l
|
||||
return handler;
|
||||
}
|
||||
|
||||
// Unset select_lex::first_cond_optimization
|
||||
if (select_lex->first_cond_optimization)
|
||||
for (size_t i = 0; i < select_lex_vec.size(); i++)
|
||||
{
|
||||
first_cond_optimization_flag_toggle(select_lex, &first_cond_optimization_flag_unset);
|
||||
SELECT_LEX* select_lex = select_lex_vec[i];
|
||||
|
||||
// Unset select_lex::first_cond_optimization
|
||||
if (select_lex->first_cond_optimization)
|
||||
{
|
||||
first_cond_optimization_flag_toggle(select_lex, &first_cond_optimization_flag_unset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
select_handler* create_columnstore_select_handler(THD* thd, SELECT_LEX* select_lex, SELECT_LEX_UNIT* sel_unit)
|
||||
{
|
||||
return create_columnstore_select_handler_(thd, select_lex, sel_unit);
|
||||
}
|
||||
|
||||
select_handler* create_columnstore_unit_handler(THD* thd, SELECT_LEX_UNIT* sel_unit)
|
||||
{
|
||||
if (thd->lex->sql_command == SQLCOM_CREATE_VIEW)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (thd->stmt_arena && thd->stmt_arena->is_stmt_prepare())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// MCOL-5432 Disable UNION pushdown if the query involves an order by
|
||||
// or a limit clause.
|
||||
if (sel_unit->global_parameters()->limit_params.explicit_limit == true ||
|
||||
sel_unit->global_parameters()->order_list.elements != 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return create_columnstore_select_handler_(thd, 0, sel_unit);
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* DESCRIPTION:
|
||||
* select_handler constructor
|
||||
* PARAMETERS:
|
||||
* thd - THD pointer.
|
||||
* select_lex - sematic tree for the query.
|
||||
* sel_lex - semantic tree for the query.
|
||||
***********************************************************/
|
||||
ha_columnstore_select_handler::ha_columnstore_select_handler(THD* thd, SELECT_LEX* select_lex)
|
||||
: select_handler(thd, mcs_hton)
|
||||
ha_columnstore_select_handler::ha_columnstore_select_handler(THD* thd, SELECT_LEX* sel_lex)
|
||||
: select_handler(thd, mcs_hton, sel_lex)
|
||||
, prepared(false)
|
||||
, scan_ended(false)
|
||||
, scan_initialized(false)
|
||||
, pushdown_init_rc(0)
|
||||
{
|
||||
const char* timeZone = thd->variables.time_zone->get_name()->ptr();
|
||||
dataconvert::timeZoneToOffset(timeZone, strlen(timeZone), &time_zone);
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* DESCRIPTION:
|
||||
* select_handler constructor
|
||||
* PARAMETERS:
|
||||
* thd - THD pointer.
|
||||
* sel_unit - semantic tree for the query.
|
||||
***********************************************************/
|
||||
ha_columnstore_select_handler::ha_columnstore_select_handler(THD* thd, SELECT_LEX_UNIT* sel_unit)
|
||||
: select_handler(thd, mcs_hton, sel_unit)
|
||||
, prepared(false)
|
||||
, scan_ended(false)
|
||||
, scan_initialized(false)
|
||||
, pushdown_init_rc(0)
|
||||
{
|
||||
const char* timeZone = thd->variables.time_zone->get_name()->ptr();
|
||||
dataconvert::timeZoneToOffset(timeZone, strlen(timeZone), &time_zone);
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* DESCRIPTION:
|
||||
* select_handler constructor
|
||||
* PARAMETERS:
|
||||
* thd - THD pointer.
|
||||
* sel_lex - semantic tree for the query.
|
||||
* sel_unit - unit containing SELECT_LEX's
|
||||
***********************************************************/
|
||||
ha_columnstore_select_handler::ha_columnstore_select_handler(THD* thd, SELECT_LEX* sel_lex,
|
||||
SELECT_LEX_UNIT* sel_unit)
|
||||
: select_handler(thd, mcs_hton, sel_lex, sel_unit)
|
||||
, prepared(false)
|
||||
, scan_ended(false)
|
||||
, scan_initialized(false)
|
||||
, pushdown_init_rc(0)
|
||||
{
|
||||
select = select_lex;
|
||||
const char* timeZone = thd->variables.time_zone->get_name()->ptr();
|
||||
dataconvert::timeZoneToOffset(timeZone, strlen(timeZone), &time_zone);
|
||||
}
|
||||
@ -1074,7 +1199,7 @@ bool ha_columnstore_select_handler::prepare()
|
||||
|
||||
prepared = true;
|
||||
|
||||
if ((!table && !(table = create_tmp_table(thd, select))) || table->fill_item_list(&result_columns))
|
||||
if ((!table && !(table = create_tmp_table(thd))) || table->fill_item_list(&result_columns))
|
||||
{
|
||||
pushdown_init_rc = 1;
|
||||
DBUG_RETURN(true);
|
||||
|
@ -151,7 +151,9 @@ class ha_columnstore_select_handler : public select_handler
|
||||
// This will be used to restore to the original state later in case
|
||||
// query execution fails using the select_handler.
|
||||
cal_impl_if::TableOuterJoinMap tableOuterJoinMap;
|
||||
ha_columnstore_select_handler(THD* thd_arg, SELECT_LEX* sel);
|
||||
ha_columnstore_select_handler(THD* thd_arg, SELECT_LEX* sel_lex);
|
||||
ha_columnstore_select_handler(THD* thd_arg, SELECT_LEX_UNIT* sel_unit);
|
||||
ha_columnstore_select_handler(THD* thd_arg, SELECT_LEX* sel_lex, SELECT_LEX_UNIT* sel_unit);
|
||||
~ha_columnstore_select_handler();
|
||||
int init_scan() override;
|
||||
int next_row() override;
|
||||
|
@ -1,3 +1,5 @@
|
||||
# MCOL-641 Union Test Cases
|
||||
# Once MCOL-5417 is supported, the errored out queries below should be fixed.
|
||||
DROP DATABASE IF EXISTS mcol641_union_db;
|
||||
CREATE DATABASE mcol641_union_db;
|
||||
USE mcol641_union_db;
|
||||
@ -11,63 +13,52 @@ INSERT INTO cs1 values (99999999999999999999999999999999999999, 9999999999999999
|
||||
INSERT INTO cs1 values (-99999999999999999999999999999999999998, -9999999999999999999999999999.9999999998, -0.99999999999999999999999999999999999998);
|
||||
INSERT INTO cs1 values (-99999999999999999999999999999999999999, -9999999999999999999999999999.9999999999, -0.99999999999999999999999999999999999999);
|
||||
SELECT d1, d1, d2 FROM cs1 UNION SELECT d2, d3, d3 FROM cs1;
|
||||
d1 d1 d2
|
||||
125.0000000000 125.00000000000000000000000000000000000000 1.25000000000000000000000000000000000000
|
||||
-125.0000000000 -125.00000000000000000000000000000000000000 -1.25000000000000000000000000000000000000
|
||||
99999999999999999999999999999999999998.0000000000 999999999999999999999999999.99999999999999999999999999999999999999 999999999999999999999999999.99999999999999999999999999999999999999
|
||||
99999999999999999999999999999999999999.0000000000 999999999999999999999999999.99999999999999999999999999999999999999 999999999999999999999999999.99999999999999999999999999999999999999
|
||||
-99999999999999999999999999999999999998.0000000000 -999999999999999999999999999.99999999999999999999999999999999999999 -999999999999999999999999999.99999999999999999999999999999999999999
|
||||
-99999999999999999999999999999999999999.0000000000 -999999999999999999999999999.99999999999999999999999999999999999999 -999999999999999999999999999.99999999999999999999999999999999999999
|
||||
1.2500000000 0.12500000000000000000000000000000000000 0.12500000000000000000000000000000000000
|
||||
-1.2500000000 -0.12500000000000000000000000000000000000 -0.12500000000000000000000000000000000000
|
||||
9999999999999999999999999999.9999999998 0.99999999999999999999999999999999999998 0.99999999999999999999999999999999999998
|
||||
9999999999999999999999999999.9999999999 0.99999999999999999999999999999999999999 0.99999999999999999999999999999999999999
|
||||
-9999999999999999999999999999.9999999998 -0.99999999999999999999999999999999999998 -0.99999999999999999999999999999999999998
|
||||
-9999999999999999999999999999.9999999999 -0.99999999999999999999999999999999999999 -0.99999999999999999999999999999999999999
|
||||
ERROR 42000: The storage engine for the table doesn't support MCS-2060: Union operation exceeds maximum DECIMAL precision of 38.
|
||||
SELECT d2, d3, d3 FROM cs1 UNION SELECT d1, d1, d2 FROM cs1;
|
||||
d2 d3 d3
|
||||
1.2500000000 0.12500000000000000000000000000000000000 0.12500000000000000000000000000000000000
|
||||
-1.2500000000 -0.12500000000000000000000000000000000000 -0.12500000000000000000000000000000000000
|
||||
9999999999999999999999999999.9999999998 0.99999999999999999999999999999999999998 0.99999999999999999999999999999999999998
|
||||
9999999999999999999999999999.9999999999 0.99999999999999999999999999999999999999 0.99999999999999999999999999999999999999
|
||||
-9999999999999999999999999999.9999999998 -0.99999999999999999999999999999999999998 -0.99999999999999999999999999999999999998
|
||||
-9999999999999999999999999999.9999999999 -0.99999999999999999999999999999999999999 -0.99999999999999999999999999999999999999
|
||||
125.0000000000 125.00000000000000000000000000000000000000 1.25000000000000000000000000000000000000
|
||||
-125.0000000000 -125.00000000000000000000000000000000000000 -1.25000000000000000000000000000000000000
|
||||
99999999999999999999999999999999999998.0000000000 999999999999999999999999999.99999999999999999999999999999999999999 999999999999999999999999999.99999999999999999999999999999999999999
|
||||
99999999999999999999999999999999999999.0000000000 999999999999999999999999999.99999999999999999999999999999999999999 999999999999999999999999999.99999999999999999999999999999999999999
|
||||
-99999999999999999999999999999999999998.0000000000 -999999999999999999999999999.99999999999999999999999999999999999999 -999999999999999999999999999.99999999999999999999999999999999999999
|
||||
-99999999999999999999999999999999999999.0000000000 -999999999999999999999999999.99999999999999999999999999999999999999 -999999999999999999999999999.99999999999999999999999999999999999999
|
||||
ERROR 42000: The storage engine for the table doesn't support MCS-2060: Union operation exceeds maximum DECIMAL precision of 38.
|
||||
SELECT d1, d2, d3 FROM cs1 UNION SELECT d1, d2, d3 FROM cs1;
|
||||
d1 d2 d3
|
||||
125 1.2500000000 0.12500000000000000000000000000000000000
|
||||
-125 -1.2500000000 -0.12500000000000000000000000000000000000
|
||||
99999999999999999999999999999999999998 9999999999999999999999999999.9999999998 0.99999999999999999999999999999999999998
|
||||
99999999999999999999999999999999999999 9999999999999999999999999999.9999999999 0.99999999999999999999999999999999999999
|
||||
-99999999999999999999999999999999999998 -9999999999999999999999999999.9999999998 -0.99999999999999999999999999999999999998
|
||||
-99999999999999999999999999999999999999 -9999999999999999999999999999.9999999999 -0.99999999999999999999999999999999999999
|
||||
125 1.2500000000 0.12500000000000000000000000000000000000
|
||||
99999999999999999999999999999999999998 9999999999999999999999999999.9999999998 0.99999999999999999999999999999999999998
|
||||
99999999999999999999999999999999999999 9999999999999999999999999999.9999999999 0.99999999999999999999999999999999999999
|
||||
INSERT INTO cs2 VALUES (125, 1.25, 0.125);
|
||||
INSERT INTO cs2 values (99999999999999999999999999999999999998, 9999999999999999999999999999.9999999998, 0.99999999999999999999999999999999999998);
|
||||
INSERT INTO cs2 values (99999999999999999999999999999999999999, 9999999999999999999999999999.9999999999, 0.99999999999999999999999999999999999999);
|
||||
SELECT d1, d1, d2 FROM cs2 UNION SELECT d2, d3, d3 FROM cs2;
|
||||
d1 d1 d2
|
||||
125.0000000000 125.00000000000000000000000000000000000000 1.25000000000000000000000000000000000000
|
||||
99999999999999999999999999999999999998.0000000000 999999999999999999999999999.99999999999999999999999999999999999999 999999999999999999999999999.99999999999999999999999999999999999999
|
||||
99999999999999999999999999999999999999.0000000000 999999999999999999999999999.99999999999999999999999999999999999999 999999999999999999999999999.99999999999999999999999999999999999999
|
||||
1.2500000000 0.12500000000000000000000000000000000000 0.12500000000000000000000000000000000000
|
||||
9999999999999999999999999999.9999999998 0.99999999999999999999999999999999999998 0.99999999999999999999999999999999999998
|
||||
9999999999999999999999999999.9999999999 0.99999999999999999999999999999999999999 0.99999999999999999999999999999999999999
|
||||
ERROR 42000: The storage engine for the table doesn't support MCS-2060: Union operation exceeds maximum DECIMAL precision of 38.
|
||||
SELECT d2, d3, d3 FROM cs2 UNION SELECT d1, d1, d2 FROM cs2;
|
||||
d2 d3 d3
|
||||
1.2500000000 0.12500000000000000000000000000000000000 0.12500000000000000000000000000000000000
|
||||
9999999999999999999999999999.9999999998 0.99999999999999999999999999999999999998 0.99999999999999999999999999999999999998
|
||||
9999999999999999999999999999.9999999999 0.99999999999999999999999999999999999999 0.99999999999999999999999999999999999999
|
||||
125.0000000000 125.00000000000000000000000000000000000000 1.25000000000000000000000000000000000000
|
||||
99999999999999999999999999999999999998.0000000000 999999999999999999999999999.99999999999999999999999999999999999999 999999999999999999999999999.99999999999999999999999999999999999999
|
||||
99999999999999999999999999999999999999.0000000000 999999999999999999999999999.99999999999999999999999999999999999999 999999999999999999999999999.99999999999999999999999999999999999999
|
||||
ERROR 42000: The storage engine for the table doesn't support MCS-2060: Union operation exceeds maximum DECIMAL precision of 38.
|
||||
SELECT d1, d2, d3 FROM cs2 UNION SELECT d1, d2, d3 FROM cs2;
|
||||
d1 d2 d3
|
||||
125 1.2500000000 0.12500000000000000000000000000000000000
|
||||
99999999999999999999999999999999999998 9999999999999999999999999999.9999999998 0.99999999999999999999999999999999999998
|
||||
99999999999999999999999999999999999999 9999999999999999999999999999.9999999999 0.99999999999999999999999999999999999999
|
||||
DROP TABLE cs1, cs2;
|
||||
CREATE TABLE cs1 (d1 DECIMAL(20, 0), d2 DECIMAL(20, 18), d3 DECIMAL(18, 18)) ENGINE=columnstore;
|
||||
CREATE TABLE cs2 (d1 DECIMAL(20, 0) UNSIGNED, d2 DECIMAL(20, 18) UNSIGNED, d3 DECIMAL(18, 18) UNSIGNED) ENGINE=columnstore;
|
||||
INSERT INTO cs1 VALUES (12345678901234567890, 12.345678901234567891, 0.123456789012345678);
|
||||
INSERT INTO cs1 VALUES (-12345678901234567890, -12.345678901234567891, -0.123456789012345678);
|
||||
INSERT INTO cs1 VALUES (99999999999999999999, 99.999999999999999999, 0.999999999999999999);
|
||||
INSERT INTO cs1 VALUES (-99999999999999999999, -99.999999999999999999, -0.999999999999999999);
|
||||
INSERT INTO cs2 VALUES (12345678901234567890, 12.345678901234567891, 0.123456789012345678);
|
||||
INSERT INTO cs2 VALUES (99999999999999999999, 99.999999999999999999, 0.999999999999999999);
|
||||
SELECT d1, d1, d2 FROM cs1 UNION SELECT d2, d3, d3 FROM cs1;
|
||||
d1 d1 d2
|
||||
-12.345678901234567891 -0.123456789012345678 -0.123456789012345678
|
||||
-12345678901234567890.000000000000000000 -12345678901234567890.000000000000000000 -12.345678901234567891
|
||||
-99.999999999999999999 -0.999999999999999999 -0.999999999999999999
|
||||
-99999999999999999999.000000000000000000 -99999999999999999999.000000000000000000 -99.999999999999999999
|
||||
12.345678901234567891 0.123456789012345678 0.123456789012345678
|
||||
12345678901234567890.000000000000000000 12345678901234567890.000000000000000000 12.345678901234567891
|
||||
99.999999999999999999 0.999999999999999999 0.999999999999999999
|
||||
99999999999999999999.000000000000000000 99999999999999999999.000000000000000000 99.999999999999999999
|
||||
SELECT d1, d1, d2 FROM cs2 UNION SELECT d2, d3, d3 FROM cs2;
|
||||
d1 d1 d2
|
||||
12.345678901234567891 0.123456789012345678 0.123456789012345678
|
||||
12345678901234567890.000000000000000000 12345678901234567890.000000000000000000 12.345678901234567891
|
||||
99.999999999999999999 0.999999999999999999 0.999999999999999999
|
||||
99999999999999999999.000000000000000000 99999999999999999999.000000000000000000 99.999999999999999999
|
||||
DROP DATABASE mcol641_union_db;
|
||||
|
313
mysql-test/columnstore/basic/r/mdev-25080.result
Normal file
313
mysql-test/columnstore/basic/r/mdev-25080.result
Normal file
@ -0,0 +1,313 @@
|
||||
#
|
||||
# MDEV-25080: Allow pushdown of queries involving UNIONs
|
||||
# in outer select to foreign engines
|
||||
#
|
||||
# Remove the sorted_result MTR qualifier and add ORDER BY
|
||||
# clause after MCOL-5222 is fixed
|
||||
#
|
||||
CREATE USER IF NOT EXISTS'cejuser'@'localhost' IDENTIFIED BY 'Vagrant1|0000001';
|
||||
GRANT ALL PRIVILEGES ON *.* TO 'cejuser'@'localhost';
|
||||
FLUSH PRIVILEGES;
|
||||
DROP DATABASE IF EXISTS mdev25080;
|
||||
CREATE DATABASE mdev25080;
|
||||
USE mdev25080;
|
||||
CREATE TABLE t1 (a varchar(30)) ENGINE=ColumnStore;
|
||||
CREATE TABLE t2 (a varchar(30)) ENGINE=ColumnStore;
|
||||
CREATE TABLE t3 (a varchar(30)) ENGINE=MyISAM;
|
||||
CREATE TABLE t4 (a varchar(30)) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES ('abc'), ('bcd'), ('cde');
|
||||
INSERT INTO t2 VALUES ('bcd'), ('cde'), ('def'), ('efg');
|
||||
INSERT INTO t3 VALUES ('t3_myisam1'), ('t3_myisam2'), ('t3_myisam3');
|
||||
INSERT INTO t4 VALUES ('t4_myisam1'), ('t4_myisam2'), ('t4_myisam3');
|
||||
# Pushdown of the whole UNION
|
||||
SELECT * FROM t1 UNION SELECT * FROM t2;
|
||||
a
|
||||
abc
|
||||
bcd
|
||||
cde
|
||||
def
|
||||
efg
|
||||
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2;
|
||||
a
|
||||
abc
|
||||
bcd
|
||||
bcd
|
||||
cde
|
||||
cde
|
||||
def
|
||||
efg
|
||||
EXPLAIN SELECT * FROM t1 UNION ALL SELECT * FROM t2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
# UNION with a foreign engine
|
||||
SELECT * FROM t1 UNION SELECT * FROM t3;
|
||||
a
|
||||
abc
|
||||
bcd
|
||||
cde
|
||||
t3_myisam1
|
||||
t3_myisam2
|
||||
t3_myisam3
|
||||
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t3;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
# More than two SELECTs in a UNIT:
|
||||
SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2 UNION ALL
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
abc
|
||||
abc
|
||||
bcd
|
||||
bcd
|
||||
cde
|
||||
cde
|
||||
def
|
||||
efg
|
||||
EXPLAIN SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2 UNION ALL
|
||||
SELECT * FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
(SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2) UNION ALL
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
abc
|
||||
abc
|
||||
bcd
|
||||
bcd
|
||||
cde
|
||||
cde
|
||||
def
|
||||
efg
|
||||
EXPLAIN (SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2) UNION ALL
|
||||
SELECT * FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2 UNION ALL
|
||||
SELECT * FROM t3 UNION
|
||||
SELECT * FROM t4;
|
||||
a
|
||||
abc
|
||||
bcd
|
||||
cde
|
||||
def
|
||||
efg
|
||||
t3_myisam1
|
||||
t3_myisam2
|
||||
t3_myisam3
|
||||
t4_myisam1
|
||||
t4_myisam2
|
||||
t4_myisam3
|
||||
EXPLAIN SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2 UNION ALL
|
||||
SELECT * FROM t3 UNION
|
||||
SELECT * FROM t4;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
(SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2) UNION ALL
|
||||
(SELECT * FROM t3 UNION
|
||||
SELECT * FROM t4);
|
||||
a
|
||||
abc
|
||||
bcd
|
||||
cde
|
||||
def
|
||||
efg
|
||||
t3_myisam1
|
||||
t3_myisam2
|
||||
t3_myisam3
|
||||
t4_myisam1
|
||||
t4_myisam2
|
||||
t4_myisam3
|
||||
EXPLAIN (SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2) UNION ALL
|
||||
(SELECT * FROM t3 UNION
|
||||
SELECT * FROM t4);
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
SELECT count(*) FROM t1 UNION
|
||||
SELECT count(*) FROM t2 UNION ALL
|
||||
SELECT count(*)+20 FROM t2 UNION
|
||||
SELECT count(*)+5 FROM t1;
|
||||
count(*)
|
||||
24
|
||||
3
|
||||
4
|
||||
8
|
||||
EXPLAIN
|
||||
SELECT count(*) FROM t1 UNION
|
||||
SELECT count(*) FROM t2 UNION ALL
|
||||
SELECT count(*)+20 FROM t2 UNION
|
||||
SELECT count(*)+5 FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
# UNION inside a derived table: the whole derived table must be pushed
|
||||
SELECT a FROM
|
||||
(SELECT a FROM t1 UNION ALL SELECT a FROM t2) q ORDER BY a;
|
||||
a
|
||||
abc
|
||||
bcd
|
||||
bcd
|
||||
cde
|
||||
cde
|
||||
def
|
||||
efg
|
||||
EXPLAIN
|
||||
SELECT a FROM
|
||||
(SELECT a FROM t1 UNION ALL SELECT a FROM t2) q ORDER BY a;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
SELECT a FROM
|
||||
(SELECT a FROM t1 UNION ALL SELECT a FROM t3) q ORDER BY a;
|
||||
a
|
||||
abc
|
||||
bcd
|
||||
cde
|
||||
t3_myisam1
|
||||
t3_myisam2
|
||||
t3_myisam3
|
||||
EXPLAIN
|
||||
SELECT a FROM
|
||||
(SELECT a FROM t1 UNION ALL SELECT a FROM t3) q ORDER BY a;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PUSHED SELECT NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
# Prepared statements
|
||||
PREPARE stmt FROM "SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2";
|
||||
EXECUTE stmt;
|
||||
a
|
||||
abc
|
||||
bcd
|
||||
cde
|
||||
def
|
||||
efg
|
||||
EXECUTE stmt;
|
||||
a
|
||||
abc
|
||||
bcd
|
||||
cde
|
||||
def
|
||||
efg
|
||||
EXECUTE stmt;
|
||||
a
|
||||
abc
|
||||
bcd
|
||||
cde
|
||||
def
|
||||
efg
|
||||
PREPARE stmt FROM "EXPLAIN SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2";
|
||||
EXECUTE stmt;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
EXECUTE stmt;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
PREPARE stmt FROM "(SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2) UNION ALL
|
||||
(SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2)";
|
||||
EXECUTE stmt;
|
||||
a
|
||||
abc
|
||||
abc
|
||||
bcd
|
||||
bcd
|
||||
cde
|
||||
cde
|
||||
def
|
||||
def
|
||||
efg
|
||||
efg
|
||||
EXECUTE stmt;
|
||||
a
|
||||
abc
|
||||
abc
|
||||
bcd
|
||||
bcd
|
||||
cde
|
||||
cde
|
||||
def
|
||||
def
|
||||
efg
|
||||
efg
|
||||
EXECUTE stmt;
|
||||
a
|
||||
abc
|
||||
abc
|
||||
bcd
|
||||
bcd
|
||||
cde
|
||||
cde
|
||||
def
|
||||
def
|
||||
efg
|
||||
efg
|
||||
PREPARE stmt FROM "EXPLAIN (SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2) UNION ALL
|
||||
(SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2)";
|
||||
EXECUTE stmt;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
EXECUTE stmt;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
# MCOL-5432 Disable UNION pushdown if an ORDER BY or a LIMIT
|
||||
# clause is involved, until MCOL-5222 is fixed.
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY a;
|
||||
a
|
||||
abc
|
||||
bcd
|
||||
bcd
|
||||
cde
|
||||
cde
|
||||
def
|
||||
efg
|
||||
EXPLAIN SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY a;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 2000
|
||||
2 UNION t2 ALL NULL NULL NULL NULL 2000
|
||||
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL Using filesort
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2 LIMIT 3;
|
||||
a
|
||||
abc
|
||||
bcd
|
||||
cde
|
||||
EXPLAIN SELECT * FROM t1 UNION ALL SELECT * FROM t2 LIMIT 3;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 2000
|
||||
2 UNION t2 ALL NULL NULL NULL NULL 2000
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY a DESC LIMIT 5;
|
||||
a
|
||||
efg
|
||||
def
|
||||
cde
|
||||
cde
|
||||
bcd
|
||||
EXPLAIN SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY a DESC LIMIT 5;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 2000
|
||||
2 UNION t2 ALL NULL NULL NULL NULL 2000
|
||||
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL Using filesort
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY a LIMIT 3 OFFSET 2;
|
||||
a
|
||||
bcd
|
||||
cde
|
||||
cde
|
||||
EXPLAIN SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY a LIMIT 3 OFFSET 2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t1 ALL NULL NULL NULL NULL 2000
|
||||
2 UNION t2 ALL NULL NULL NULL NULL 2000
|
||||
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL Using filesort
|
||||
DROP USER 'cejuser'@'localhost';
|
||||
DROP TABLE t1, t2, t3, t4;
|
||||
DROP DATABASE mdev25080;
|
@ -5,6 +5,9 @@ USE mcs_union;
|
||||
#
|
||||
# MCOL-4700 Wrong result of a UNION for INT and INT UNSIGNED
|
||||
#
|
||||
# Move the UNIONs from the subqueries to outer selects and add
|
||||
# ORDER BY clause after MCOL-5222 is fixed
|
||||
#
|
||||
CREATE TABLE t1 (a INT, b INT UNSIGNED);
|
||||
INSERT INTO t1 VALUES (-1, 1), (-1, 1), (-2, 2);
|
||||
SELECT * FROM (SELECT * FROM t1 UNION SELECT * FROM t1) tu ORDER BY b;
|
||||
@ -862,4 +865,58 @@ a
|
||||
16777213
|
||||
9223372036854775807
|
||||
DROP TABLE t1,t2;
|
||||
#
|
||||
# Union of tables containing different string data types
|
||||
#
|
||||
# Remove the sorted_result MTR qualifier and add ORDER BY clause
|
||||
# after MCOL-5222 is fixed
|
||||
#
|
||||
CREATE TABLE t1 (a CHAR(6));
|
||||
INSERT INTO t1 VALUES ('t13abc'), ('t13xx'), ('common');
|
||||
CREATE TABLE t2 (a VARCHAR(8));
|
||||
INSERT INTO t2 VALUES ('t14abcde'), ('t14xyzzz'), ('common');
|
||||
SELECT * FROM t1 UNION SELECT * FROM t2;
|
||||
a
|
||||
common
|
||||
t13abc
|
||||
t13xx
|
||||
t14abcde
|
||||
t14xyzzz
|
||||
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
SELECT * FROM t2 UNION ALL SELECT * FROM t1;
|
||||
a
|
||||
common
|
||||
common
|
||||
t13abc
|
||||
t13xx
|
||||
t14abcde
|
||||
t14xyzzz
|
||||
EXPLAIN SELECT * FROM t2 UNION ALL SELECT * FROM t1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
SELECT * FROM t1 UNION SELECT * FROM t2 UNION SELECT '123456789000';
|
||||
a
|
||||
123456789000
|
||||
common
|
||||
t13abc
|
||||
t13xx
|
||||
t14abcde
|
||||
t14xyzzz
|
||||
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2 UNION SELECT '123456789000';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
SELECT * FROM t1 UNION SELECT '123456789000' UNION SELECT * FROM t2;
|
||||
a
|
||||
123456789000
|
||||
common
|
||||
t13abc
|
||||
t13xx
|
||||
t14abcde
|
||||
t14xyzzz
|
||||
EXPLAIN SELECT * FROM t1 UNION SELECT '123456789000' UNION SELECT * FROM t2;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
NULL PUSHED UNION NULL NULL NULL NULL NULL NULL NULL NULL
|
||||
DROP TABLE t1,t2;
|
||||
DROP DATABASE mcs_union;
|
||||
|
@ -1,5 +1,8 @@
|
||||
-- source ../include/have_columnstore.inc
|
||||
|
||||
--echo # MCOL-641 Union Test Cases
|
||||
--echo # Once MCOL-5417 is supported, the errored out queries below should be fixed.
|
||||
|
||||
--disable_warnings
|
||||
DROP DATABASE IF EXISTS mcol641_union_db;
|
||||
--enable_warnings
|
||||
@ -19,17 +22,38 @@ INSERT INTO cs1 values (99999999999999999999999999999999999999, 9999999999999999
|
||||
INSERT INTO cs1 values (-99999999999999999999999999999999999998, -9999999999999999999999999999.9999999998, -0.99999999999999999999999999999999999998);
|
||||
INSERT INTO cs1 values (-99999999999999999999999999999999999999, -9999999999999999999999999999.9999999999, -0.99999999999999999999999999999999999999);
|
||||
|
||||
--error ER_CHECK_NOT_IMPLEMENTED
|
||||
SELECT d1, d1, d2 FROM cs1 UNION SELECT d2, d3, d3 FROM cs1;
|
||||
--error ER_CHECK_NOT_IMPLEMENTED
|
||||
SELECT d2, d3, d3 FROM cs1 UNION SELECT d1, d1, d2 FROM cs1;
|
||||
--sorted_result
|
||||
SELECT d1, d2, d3 FROM cs1 UNION SELECT d1, d2, d3 FROM cs1;
|
||||
|
||||
INSERT INTO cs2 VALUES (125, 1.25, 0.125);
|
||||
INSERT INTO cs2 values (99999999999999999999999999999999999998, 9999999999999999999999999999.9999999998, 0.99999999999999999999999999999999999998);
|
||||
INSERT INTO cs2 values (99999999999999999999999999999999999999, 9999999999999999999999999999.9999999999, 0.99999999999999999999999999999999999999);
|
||||
|
||||
--error ER_CHECK_NOT_IMPLEMENTED
|
||||
SELECT d1, d1, d2 FROM cs2 UNION SELECT d2, d3, d3 FROM cs2;
|
||||
--error ER_CHECK_NOT_IMPLEMENTED
|
||||
SELECT d2, d3, d3 FROM cs2 UNION SELECT d1, d1, d2 FROM cs2;
|
||||
--sorted_result
|
||||
SELECT d1, d2, d3 FROM cs2 UNION SELECT d1, d2, d3 FROM cs2;
|
||||
|
||||
DROP TABLE cs1, cs2;
|
||||
CREATE TABLE cs1 (d1 DECIMAL(20, 0), d2 DECIMAL(20, 18), d3 DECIMAL(18, 18)) ENGINE=columnstore;
|
||||
CREATE TABLE cs2 (d1 DECIMAL(20, 0) UNSIGNED, d2 DECIMAL(20, 18) UNSIGNED, d3 DECIMAL(18, 18) UNSIGNED) ENGINE=columnstore;
|
||||
INSERT INTO cs1 VALUES (12345678901234567890, 12.345678901234567891, 0.123456789012345678);
|
||||
INSERT INTO cs1 VALUES (-12345678901234567890, -12.345678901234567891, -0.123456789012345678);
|
||||
INSERT INTO cs1 VALUES (99999999999999999999, 99.999999999999999999, 0.999999999999999999);
|
||||
INSERT INTO cs1 VALUES (-99999999999999999999, -99.999999999999999999, -0.999999999999999999);
|
||||
INSERT INTO cs2 VALUES (12345678901234567890, 12.345678901234567891, 0.123456789012345678);
|
||||
INSERT INTO cs2 VALUES (99999999999999999999, 99.999999999999999999, 0.999999999999999999);
|
||||
|
||||
--sorted_result
|
||||
SELECT d1, d1, d2 FROM cs1 UNION SELECT d2, d3, d3 FROM cs1;
|
||||
--sorted_result
|
||||
SELECT d1, d1, d2 FROM cs2 UNION SELECT d2, d3, d3 FROM cs2;
|
||||
|
||||
# Clean UP
|
||||
DROP DATABASE mcol641_union_db;
|
||||
|
185
mysql-test/columnstore/basic/t/mdev-25080.test
Normal file
185
mysql-test/columnstore/basic/t/mdev-25080.test
Normal file
@ -0,0 +1,185 @@
|
||||
--echo #
|
||||
--echo # MDEV-25080: Allow pushdown of queries involving UNIONs
|
||||
--echo # in outer select to foreign engines
|
||||
--echo #
|
||||
--echo # Remove the sorted_result MTR qualifier and add ORDER BY
|
||||
--echo # clause after MCOL-5222 is fixed
|
||||
--echo #
|
||||
|
||||
--source ../include/have_columnstore.inc
|
||||
|
||||
if (!$MASTER_MYPORT)
|
||||
{
|
||||
# Running with --extern
|
||||
let $MASTER_MYPORT=`SELECT @@port`;
|
||||
}
|
||||
|
||||
#
|
||||
# Enable cross engine join
|
||||
# Configure user and password in Columnstore.xml file
|
||||
#
|
||||
--exec $MCS_MCSSETCONFIG CrossEngineSupport User 'cejuser'
|
||||
--exec $MCS_MCSSETCONFIG CrossEngineSupport Password 'Vagrant1|0000001'
|
||||
--exec $MCS_MCSSETCONFIG CrossEngineSupport Port $MASTER_MYPORT
|
||||
|
||||
#
|
||||
# Create corresponding in the server
|
||||
#
|
||||
--disable_warnings
|
||||
CREATE USER IF NOT EXISTS'cejuser'@'localhost' IDENTIFIED BY 'Vagrant1|0000001';
|
||||
--enable_warnings
|
||||
GRANT ALL PRIVILEGES ON *.* TO 'cejuser'@'localhost';
|
||||
FLUSH PRIVILEGES;
|
||||
|
||||
--disable_warnings
|
||||
DROP DATABASE IF EXISTS mdev25080;
|
||||
--enable_warnings
|
||||
|
||||
CREATE DATABASE mdev25080;
|
||||
|
||||
USE mdev25080;
|
||||
|
||||
CREATE TABLE t1 (a varchar(30)) ENGINE=ColumnStore;
|
||||
CREATE TABLE t2 (a varchar(30)) ENGINE=ColumnStore;
|
||||
CREATE TABLE t3 (a varchar(30)) ENGINE=MyISAM;
|
||||
CREATE TABLE t4 (a varchar(30)) ENGINE=MyISAM;
|
||||
|
||||
INSERT INTO t1 VALUES ('abc'), ('bcd'), ('cde');
|
||||
INSERT INTO t2 VALUES ('bcd'), ('cde'), ('def'), ('efg');
|
||||
|
||||
INSERT INTO t3 VALUES ('t3_myisam1'), ('t3_myisam2'), ('t3_myisam3');
|
||||
INSERT INTO t4 VALUES ('t4_myisam1'), ('t4_myisam2'), ('t4_myisam3');
|
||||
|
||||
--echo # Pushdown of the whole UNION
|
||||
--sorted_result
|
||||
SELECT * FROM t1 UNION SELECT * FROM t2;
|
||||
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2;
|
||||
|
||||
--sorted_result
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2;
|
||||
EXPLAIN SELECT * FROM t1 UNION ALL SELECT * FROM t2;
|
||||
|
||||
--echo # UNION with a foreign engine
|
||||
--sorted_result
|
||||
SELECT * FROM t1 UNION SELECT * FROM t3;
|
||||
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t3;
|
||||
|
||||
--echo # More than two SELECTs in a UNIT:
|
||||
--sorted_result
|
||||
SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2 UNION ALL
|
||||
SELECT * FROM t1;
|
||||
|
||||
EXPLAIN SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2 UNION ALL
|
||||
SELECT * FROM t1;
|
||||
|
||||
--sorted_result
|
||||
(SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2) UNION ALL
|
||||
SELECT * FROM t1;
|
||||
|
||||
EXPLAIN (SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2) UNION ALL
|
||||
SELECT * FROM t1;
|
||||
|
||||
--sorted_result
|
||||
SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2 UNION ALL
|
||||
SELECT * FROM t3 UNION
|
||||
SELECT * FROM t4;
|
||||
|
||||
EXPLAIN SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2 UNION ALL
|
||||
SELECT * FROM t3 UNION
|
||||
SELECT * FROM t4;
|
||||
|
||||
--sorted_result
|
||||
(SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2) UNION ALL
|
||||
(SELECT * FROM t3 UNION
|
||||
SELECT * FROM t4);
|
||||
|
||||
EXPLAIN (SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2) UNION ALL
|
||||
(SELECT * FROM t3 UNION
|
||||
SELECT * FROM t4);
|
||||
|
||||
--sorted_result
|
||||
SELECT count(*) FROM t1 UNION
|
||||
SELECT count(*) FROM t2 UNION ALL
|
||||
SELECT count(*)+20 FROM t2 UNION
|
||||
SELECT count(*)+5 FROM t1;
|
||||
|
||||
EXPLAIN
|
||||
SELECT count(*) FROM t1 UNION
|
||||
SELECT count(*) FROM t2 UNION ALL
|
||||
SELECT count(*)+20 FROM t2 UNION
|
||||
SELECT count(*)+5 FROM t1;
|
||||
|
||||
--echo # UNION inside a derived table: the whole derived table must be pushed
|
||||
SELECT a FROM
|
||||
(SELECT a FROM t1 UNION ALL SELECT a FROM t2) q ORDER BY a;
|
||||
|
||||
EXPLAIN
|
||||
SELECT a FROM
|
||||
(SELECT a FROM t1 UNION ALL SELECT a FROM t2) q ORDER BY a;
|
||||
|
||||
SELECT a FROM
|
||||
(SELECT a FROM t1 UNION ALL SELECT a FROM t3) q ORDER BY a;
|
||||
|
||||
EXPLAIN
|
||||
SELECT a FROM
|
||||
(SELECT a FROM t1 UNION ALL SELECT a FROM t3) q ORDER BY a;
|
||||
|
||||
--echo # Prepared statements
|
||||
PREPARE stmt FROM "SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2";
|
||||
|
||||
--sorted_result
|
||||
EXECUTE stmt;
|
||||
--sorted_result
|
||||
EXECUTE stmt;
|
||||
--sorted_result
|
||||
EXECUTE stmt;
|
||||
|
||||
PREPARE stmt FROM "EXPLAIN SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2";
|
||||
|
||||
EXECUTE stmt;
|
||||
EXECUTE stmt;
|
||||
|
||||
PREPARE stmt FROM "(SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2) UNION ALL
|
||||
(SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2)";
|
||||
|
||||
--sorted_result
|
||||
EXECUTE stmt;
|
||||
--sorted_result
|
||||
EXECUTE stmt;
|
||||
--sorted_result
|
||||
EXECUTE stmt;
|
||||
|
||||
PREPARE stmt FROM "EXPLAIN (SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2) UNION ALL
|
||||
(SELECT * FROM t1 UNION
|
||||
SELECT * FROM t2)";
|
||||
|
||||
EXECUTE stmt;
|
||||
EXECUTE stmt;
|
||||
|
||||
--echo # MCOL-5432 Disable UNION pushdown if an ORDER BY or a LIMIT
|
||||
--echo # clause is involved, until MCOL-5222 is fixed.
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY a;
|
||||
EXPLAIN SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY a;
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2 LIMIT 3;
|
||||
EXPLAIN SELECT * FROM t1 UNION ALL SELECT * FROM t2 LIMIT 3;
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY a DESC LIMIT 5;
|
||||
EXPLAIN SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY a DESC LIMIT 5;
|
||||
SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY a LIMIT 3 OFFSET 2;
|
||||
EXPLAIN SELECT * FROM t1 UNION ALL SELECT * FROM t2 ORDER BY a LIMIT 3 OFFSET 2;
|
||||
|
||||
DROP USER 'cejuser'@'localhost';
|
||||
DROP TABLE t1, t2, t3, t4;
|
||||
DROP DATABASE mdev25080;
|
@ -12,6 +12,9 @@ USE mcs_union;
|
||||
--echo #
|
||||
--echo # MCOL-4700 Wrong result of a UNION for INT and INT UNSIGNED
|
||||
--echo #
|
||||
--echo # Move the UNIONs from the subqueries to outer selects and add
|
||||
--echo # ORDER BY clause after MCOL-5222 is fixed
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a INT, b INT UNSIGNED);
|
||||
INSERT INTO t1 VALUES (-1, 1), (-1, 1), (-2, 2);
|
||||
@ -273,4 +276,29 @@ SELECT * FROM (SELECT a FROM t1 UNION ALL SELECT a FROM t2) tu ORDER BY a;
|
||||
SELECT * FROM (SELECT a FROM t2 UNION ALL SELECT a FROM t1) tu ORDER BY a;
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
--echo #
|
||||
--echo # Union of tables containing different string data types
|
||||
--echo #
|
||||
--echo # Remove the sorted_result MTR qualifier and add ORDER BY clause
|
||||
--echo # after MCOL-5222 is fixed
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a CHAR(6));
|
||||
INSERT INTO t1 VALUES ('t13abc'), ('t13xx'), ('common');
|
||||
CREATE TABLE t2 (a VARCHAR(8));
|
||||
INSERT INTO t2 VALUES ('t14abcde'), ('t14xyzzz'), ('common');
|
||||
--sorted_result
|
||||
SELECT * FROM t1 UNION SELECT * FROM t2;
|
||||
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2;
|
||||
--sorted_result
|
||||
SELECT * FROM t2 UNION ALL SELECT * FROM t1;
|
||||
EXPLAIN SELECT * FROM t2 UNION ALL SELECT * FROM t1;
|
||||
--sorted_result
|
||||
SELECT * FROM t1 UNION SELECT * FROM t2 UNION SELECT '123456789000';
|
||||
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2 UNION SELECT '123456789000';
|
||||
--sorted_result
|
||||
SELECT * FROM t1 UNION SELECT '123456789000' UNION SELECT * FROM t2;
|
||||
EXPLAIN SELECT * FROM t1 UNION SELECT '123456789000' UNION SELECT * FROM t2;
|
||||
DROP TABLE t1,t2;
|
||||
|
||||
DROP DATABASE mcs_union;
|
||||
|
@ -2934,7 +2934,8 @@ int64_t DataConvert::stringToTime(const string& data)
|
||||
}
|
||||
|
||||
void DataConvert::joinColTypeForUnion(datatypes::SystemCatalog::TypeHolderStd& unionedType,
|
||||
const datatypes::SystemCatalog::TypeHolderStd& type)
|
||||
const datatypes::SystemCatalog::TypeHolderStd& type,
|
||||
unsigned int& rc)
|
||||
{
|
||||
// limited support for VARBINARY, no implicit conversion.
|
||||
if (type.colDataType == datatypes::SystemCatalog::VARBINARY ||
|
||||
@ -2974,7 +2975,31 @@ void DataConvert::joinColTypeForUnion(datatypes::SystemCatalog::TypeHolderStd& u
|
||||
case datatypes::SystemCatalog::UBIGINT:
|
||||
case datatypes::SystemCatalog::UDECIMAL:
|
||||
|
||||
unionedType.precision = std::max(type.precision, unionedType.precision);
|
||||
if (type.scale != 0 && (unionedType.scale != 0 || isDecimal(unionedType.colDataType)))
|
||||
{
|
||||
const unsigned int digitsBeforeDecimal = type.precision - type.scale;
|
||||
const unsigned int digitsBeforeDecimalUnion = unionedType.precision - unionedType.scale;
|
||||
|
||||
if ((std::max(digitsBeforeDecimal, digitsBeforeDecimalUnion) +
|
||||
std::max(type.scale, unionedType.scale)) > datatypes::INT128MAXPRECISION)
|
||||
{
|
||||
rc = logging::ERR_UNION_DECIMAL_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the scenario where the upstream code assigns special values of 9999
|
||||
// and -1 as the precision of the unionedType.
|
||||
if ((unionedType.precision == 9999 || unionedType.precision == -1) &&
|
||||
(type.precision != 9999 && type.precision != -1))
|
||||
{
|
||||
unionedType.precision = type.precision;
|
||||
}
|
||||
else
|
||||
{
|
||||
unionedType.precision = std::max(type.precision, unionedType.precision);
|
||||
}
|
||||
|
||||
unionedType.scale = std::max(type.scale, unionedType.scale);
|
||||
|
||||
if (datatypes::Decimal::isWideDecimalTypeByPrecision(unionedType.precision))
|
||||
@ -3042,6 +3067,10 @@ void DataConvert::joinColTypeForUnion(datatypes::SystemCatalog::TypeHolderStd& u
|
||||
case datatypes::SystemCatalog::UFLOAT:
|
||||
case datatypes::SystemCatalog::UDOUBLE:
|
||||
case datatypes::SystemCatalog::LONGDOUBLE:
|
||||
if (datatypes::isWideDecimalType(type.colDataType, type.colWidth))
|
||||
unionedType = type;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -1290,7 +1290,8 @@ class DataConvert
|
||||
EXPORT static int64_t stringToTime(const std::string& data);
|
||||
// bug4388, union type conversion
|
||||
EXPORT static void joinColTypeForUnion(datatypes::SystemCatalog::TypeHolderStd& unionedType,
|
||||
const datatypes::SystemCatalog::TypeHolderStd& type);
|
||||
const datatypes::SystemCatalog::TypeHolderStd& type,
|
||||
unsigned int& rc);
|
||||
|
||||
static boost::any StringToBit(const datatypes::SystemCatalog::TypeAttributesStd& colType,
|
||||
const datatypes::ConvertFromStringParam& prm, const std::string& dataOrig,
|
||||
|
@ -106,6 +106,8 @@
|
||||
2058 ERR_DISKAGG_OVERFLOW1 The hash function used produces a lot of hash collisions (1).
|
||||
2059 ERR_DISKAGG_OVERFLOW2 The hash function used produces a lot of hash collisions (2).
|
||||
|
||||
2060 ERR_UNION_DECIMAL_OVERFLOW Union operation exceeds maximum DECIMAL precision of 38.
|
||||
|
||||
# Sub-query errors
|
||||
3001 ERR_NON_SUPPORT_SUB_QUERY_TYPE This subquery type is not supported yet.
|
||||
3002 ERR_MORE_THAN_1_ROW Subquery returns more than 1 row.
|
||||
|
Reference in New Issue
Block a user