From a202bda485e653deeb41feb9d0ae0821e8a2d153 Mon Sep 17 00:00:00 2001 From: David Hall Date: Thu, 22 Jul 2021 13:56:21 -0500 Subject: [PATCH] MCOL-4719 iterate into subquery looking for windowfunctions When an outer query filter accesses an subquery column that contains an aggregate or a window function, certain optimizations can't be performed. We had been looking at the surface of the returned column. We now iterate into any functions or operations looking for aggregates and window functions. --- dbcon/execplan/simplecolumn.cpp | 19 +++++++++++-------- dbcon/execplan/windowfunctioncolumn.cpp | 12 ++++++++++-- .../columnstore/bugfixes/mcol_4719.result | 17 +++++++++++++++++ .../columnstore/bugfixes/mcol_4719.test | 17 +++++++++++++++++ 4 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 mysql-test/columnstore/bugfixes/mcol_4719.result create mode 100644 mysql-test/columnstore/bugfixes/mcol_4719.test diff --git a/dbcon/execplan/simplecolumn.cpp b/dbcon/execplan/simplecolumn.cpp index 71ee8f3a8..56a926108 100644 --- a/dbcon/execplan/simplecolumn.cpp +++ b/dbcon/execplan/simplecolumn.cpp @@ -471,22 +471,25 @@ bool SimpleColumn::sameColumn(const ReturnedColumn* rc) const void SimpleColumn::setDerivedTable() { - if (hasAggregate()) + if (hasAggregate() || hasWindowFunc()) { fDerivedTable = ""; return; } + ReturnedColumn* rc = dynamic_cast(fDerivedRefCol); + // @todo make aggregate filter to having clause. not optimize it for now + if (rc) + { + if (rc->hasAggregate() || rc->hasWindowFunc()) + { + fDerivedTable = ""; + return; + } + } // fDerivedTable is set at the parsing phase if (!fSchemaName.empty()) fDerivedTable = ""; - - // @todo make aggregate filter to having clause. not optimize it for now - if (fDerivedRefCol && - // TODO replace with typeid() - (dynamic_cast(fDerivedRefCol) || - dynamic_cast(fDerivedRefCol))) - fDerivedTable = ""; } bool SimpleColumn::singleTable(CalpontSystemCatalog::TableAliasName& tan) diff --git a/dbcon/execplan/windowfunctioncolumn.cpp b/dbcon/execplan/windowfunctioncolumn.cpp index 57a32a95a..d370c1a93 100644 --- a/dbcon/execplan/windowfunctioncolumn.cpp +++ b/dbcon/execplan/windowfunctioncolumn.cpp @@ -71,11 +71,19 @@ void getWindowFunctionCols(execplan::ParseTree* n, void* obj) if (afc) list->push_back(afc); else if (ac) - list->insert(list->end(), ac->windowfunctionColumnList().begin(), ac->windowfunctionColumnList().end()); + { + if (ac->hasWindowFunc()) // adds window functions to list + list->insert(list->end(), ac->windowfunctionColumnList().begin(), ac->windowfunctionColumnList().end()); + } else if (fc) - list->insert(list->end(), fc->windowfunctionColumnList().begin(), fc->windowfunctionColumnList().end()); + { + if (fc->hasWindowFunc()) + list->insert(list->end(), fc->windowfunctionColumnList().begin(), fc->windowfunctionColumnList().end()); + } else if (sf) + { list->insert(list->end(), sf->windowfunctionColumnList().begin(), sf->windowfunctionColumnList().end()); + } } /** diff --git a/mysql-test/columnstore/bugfixes/mcol_4719.result b/mysql-test/columnstore/bugfixes/mcol_4719.result new file mode 100644 index 000000000..baf568944 --- /dev/null +++ b/mysql-test/columnstore/bugfixes/mcol_4719.result @@ -0,0 +1,17 @@ +DROP DATABASE IF EXISTS mcol_4719; +CREATE DATABASE mcol_4719; +USE mcol_4719; +CREATE TABLE test_table (category CHAR(1), count INTEGER(1))ENGINE=COLUMNSTORE; +INSERT INTO test_table (category, count) VALUES ('A', 1); +INSERT INTO test_table (category, count) VALUES ('A', 2); +INSERT INTO test_table (category, count) VALUES ('B', 3); +INSERT INTO test_table (category, count) VALUES ('B', 4); +select * FROM (SELECT count / SUM(count) OVER (PARTITION BY category) AS ratio FROM test_table) a where ratio > .5; +ratio +0.6667 +0.5714 +select * FROM (SELECT round(0+SUM(count) OVER (PARTITION BY category),3) AS x FROM test_table ) a where x>3; +x +7.000 +7.000 +DROP DATABASE mcol_4719; diff --git a/mysql-test/columnstore/bugfixes/mcol_4719.test b/mysql-test/columnstore/bugfixes/mcol_4719.test new file mode 100644 index 000000000..b46948365 --- /dev/null +++ b/mysql-test/columnstore/bugfixes/mcol_4719.test @@ -0,0 +1,17 @@ +--source ../include/have_columnstore.inc +--disable_warnings +DROP DATABASE IF EXISTS mcol_4719; +--enable_warnings +CREATE DATABASE mcol_4719; +USE mcol_4719; +CREATE TABLE test_table (category CHAR(1), count INTEGER(1))ENGINE=COLUMNSTORE; +INSERT INTO test_table (category, count) VALUES ('A', 1); +INSERT INTO test_table (category, count) VALUES ('A', 2); +INSERT INTO test_table (category, count) VALUES ('B', 3); +INSERT INTO test_table (category, count) VALUES ('B', 4); + +# a subselect with an arithmetic operator on a window function +select * FROM (SELECT count / SUM(count) OVER (PARTITION BY category) AS ratio FROM test_table) a where ratio > .5; +# a subselect with a function containing an arithmetic operator on a window function +select * FROM (SELECT round(0+SUM(count) OVER (PARTITION BY category),3) AS x FROM test_table ) a where x>3; +DROP DATABASE mcol_4719;