Skip to content

Commit

Permalink
MCOL-2121 New derived_handler(MDEV-17096) infrastructure.
Browse files Browse the repository at this point in the history
    Renamed isInfiniDB() into isMCSTable

    Changed getSelectPlan() to reuse it with derived and
        other handler types.

    Separate pushdown handlers methods and functions.

    Removed vcxproj files from the source.

    Added fix for MCOL-2166.

    Merged with MCOL-2121
  • Loading branch information
drrtuy authored and tntnatbry committed Aug 1, 2019
1 parent d30745d commit 2071716
Show file tree
Hide file tree
Showing 11 changed files with 1,643 additions and 340 deletions.
2 changes: 2 additions & 0 deletions dbcon/mysql/CMakeLists.txt
Expand Up @@ -22,6 +22,8 @@ SET ( libcalmysql_SRCS
ha_pseudocolumn.cpp)

add_definitions(-DMYSQL_DYNAMIC_PLUGIN)
add_definitions(-DEBUG_WALK_COND)
add_definitions(-DINFINIDB_DEBUG)

set_source_files_properties(ha_calpont.cpp PROPERTIES COMPILE_FLAGS "-fno-rtti -fno-implicit-templates")

Expand Down
266 changes: 16 additions & 250 deletions dbcon/mysql/ha_calpont.cpp
Expand Up @@ -21,6 +21,7 @@

#define NEED_CALPONT_EXTERNS
#include "ha_calpont_impl.h"
#include "ha_mcs_pushdown.h"

static handler* calpont_create_handler(handlerton* hton,
TABLE_SHARE* table,
Expand All @@ -32,9 +33,17 @@ static int calpont_rollback(handlerton* hton, THD* thd, bool all);
static int calpont_close_connection ( handlerton* hton, THD* thd );
handlerton* calpont_hton;

// handlers creation function for hton.
// Look into ha_mcs_pushdown.* for more details.
static group_by_handler*
create_calpont_group_by_handler(THD* thd, Query* query);

static derived_handler*
create_columnstore_derived_handler(THD* thd, TABLE_LIST *derived);

static select_handler*
create_columnstore_select_handler(THD* thd, SELECT_LEX* sel);

/* Variables for example share methods */

/*
Expand Down Expand Up @@ -131,6 +140,8 @@ static int columnstore_init_func(void* p)
calpont_hton->rollback = calpont_rollback;
calpont_hton->close_connection = calpont_close_connection;
calpont_hton->create_group_by = create_calpont_group_by_handler;
calpont_hton->create_derived = create_columnstore_derived_handler;
calpont_hton->create_select = create_columnstore_select_handler;
DBUG_RETURN(0);
}

Expand Down Expand Up @@ -159,6 +170,10 @@ static int infinidb_init_func(void* p)
calpont_hton->commit = calpont_commit;
calpont_hton->rollback = calpont_rollback;
calpont_hton->close_connection = calpont_close_connection;
calpont_hton->create_group_by = create_calpont_group_by_handler;
calpont_hton->create_derived = create_columnstore_derived_handler;
calpont_hton->create_select = create_columnstore_select_handler;

DBUG_RETURN(0);
}

Expand Down Expand Up @@ -929,256 +944,7 @@ struct st_mysql_storage_engine columnstore_storage_engine =
struct st_mysql_storage_engine infinidb_storage_engine =
{ MYSQL_HANDLERTON_INTERFACE_VERSION };

/*@brief check_walk - It traverses filter conditions*/
/************************************************************
* DESCRIPTION:
* It traverses filter predicates looking for unsupported
* JOIN types: non-equi JOIN, e.g t1.c1 > t2.c2;
* logical OR.
* PARAMETERS:
* thd - THD pointer.
* derived - TABLE_LIST* to work with.
* RETURN:
* derived_handler if possible
* NULL in other case
***********************************************************/
void check_walk(const Item* item, void* arg)
{
bool* unsupported_feature = static_cast<bool*>(arg);
if ( *unsupported_feature )
return;
switch (item->type())
{
case Item::FUNC_ITEM:
{
const Item_func* ifp = static_cast<const Item_func*>(item);

if ( ifp->functype() != Item_func::EQ_FUNC ) // NON-equi JOIN
{
if ( ifp->argument_count() == 2 &&
ifp->arguments()[0]->type() == Item::FIELD_ITEM &&
ifp->arguments()[1]->type() == Item::FIELD_ITEM )
{
Item_field* left= static_cast<Item_field*>(ifp->arguments()[0]);
Item_field* right= static_cast<Item_field*>(ifp->arguments()[1]);

if ( left->field->table != right->field->table )
{
*unsupported_feature = true;
return;
}
}
else // IN + correlated subquery
{
if ( ifp->functype() == Item_func::NOT_FUNC
&& ifp->arguments()[0]->type() == Item::EXPR_CACHE_ITEM )
{
check_walk(ifp->arguments()[0], arg);
}
}
}
break;
}

case Item::EXPR_CACHE_ITEM: // IN + correlated subquery
{
const Item_cache_wrapper* icw = static_cast<const Item_cache_wrapper*>(item);
if ( icw->get_orig_item()->type() == Item::FUNC_ITEM )
{
const Item_func *ifp = static_cast<const Item_func*>(icw->get_orig_item());
if ( ifp->argument_count() == 2 &&
( ifp->arguments()[0]->type() == Item::Item::SUBSELECT_ITEM
|| ifp->arguments()[1]->type() == Item::Item::SUBSELECT_ITEM ))
{
*unsupported_feature = true;
return;
}
}
break;
}

case Item::COND_ITEM: // OR in cods is unsupported yet
{
Item_cond* icp = (Item_cond*)item;
if ( is_cond_or(icp) )
{
*unsupported_feature = true;
}
break;
}
default:
{
break;
}
}
}

/*@brief create_calpont_group_by_handler- Creates handler*/
/***********************************************************
* DESCRIPTION:
* Creates a group_by pushdown handler if there is no:
* non-equi JOIN, e.g * t1.c1 > t2.c2
* logical OR in the filter predicates
* Impossible WHERE
* Impossible HAVING
* and there is either GROUP BY or aggregation function
* exists at the top level.
* Valid queries with the last two crashes the server if
* processed.
* Details are in server/sql/group_by_handler.h
* PARAMETERS:
* thd - THD pointer
* query - Query structure LFM in group_by_handler.h
* RETURN:
* group_by_handler if success
* NULL in other case
***********************************************************/
static group_by_handler*
create_calpont_group_by_handler(THD* thd, Query* query)
{
ha_calpont_group_by_handler* handler = NULL;
// same as thd->lex->current_select
SELECT_LEX *select_lex = query->from->select_lex;

// Create a handler if query is valid. See comments for details.
if ( thd->infinidb_vtable.vtable_state == THD::INFINIDB_DISABLE_VTABLE
&& ( thd->variables.infinidb_vtable_mode == 0
|| thd->variables.infinidb_vtable_mode == 2 )
&& ( query->group_by || select_lex->with_sum_func ) )
{
bool unsupported_feature = false;
// revisit SELECT_LEX for all units
for(TABLE_LIST* tl = query->from; !unsupported_feature && tl; tl = tl->next_global)
{
select_lex = tl->select_lex;
// Correlation subquery. Comming soon so fail on this yet.
unsupported_feature = select_lex->is_correlated;

// Impossible HAVING or WHERE
if ( ( !unsupported_feature && query->having && select_lex->having_value == Item::COND_FALSE )
|| ( select_lex->cond_count > 0
&& select_lex->cond_value == Item::COND_FALSE ) )
{
unsupported_feature = true;
}

// Unsupported JOIN conditions
if ( !unsupported_feature )
{
JOIN *join = select_lex->join;
Item_cond *icp = 0;

if (join != 0)
icp = reinterpret_cast<Item_cond*>(join->conds);

if ( unsupported_feature == false
&& icp )
{
icp->traverse_cond(check_walk, &unsupported_feature, Item::POSTFIX);
}

// Optimizer could move some join conditions into where
if (select_lex->where != 0)
icp = reinterpret_cast<Item_cond*>(select_lex->where);

if ( unsupported_feature == false
&& icp )
{
icp->traverse_cond(check_walk, &unsupported_feature, Item::POSTFIX);
}

}
} // unsupported features check ends here

if ( !unsupported_feature )
{
handler = new ha_calpont_group_by_handler(thd, query);

// Notify the server, that CS handles GROUP BY, ORDER BY and HAVING clauses.
query->group_by = NULL;
query->order_by = NULL;
query->having = NULL;
}
}

return handler;
}

/***********************************************************
* DESCRIPTION:
* GROUP BY handler constructor
* PARAMETERS:
* thd - THD pointer.
* query - Query describing structure
***********************************************************/
ha_calpont_group_by_handler::ha_calpont_group_by_handler(THD* thd_arg, Query* query)
: group_by_handler(thd_arg, calpont_hton),
select(query->select),
table_list(query->from),
distinct(query->distinct),
where(query->where),
group_by(query->group_by),
order_by(query->order_by),
having(query->having)
{
}

/***********************************************************
* DESCRIPTION:
* GROUP BY destructor
***********************************************************/
ha_calpont_group_by_handler::~ha_calpont_group_by_handler()
{
}

/***********************************************************
* DESCRIPTION:
* Makes the plan and prepares the data
* RETURN:
* int rc
***********************************************************/
int ha_calpont_group_by_handler::init_scan()
{
DBUG_ENTER("ha_calpont_group_by_handler::init_scan");

// Save vtable_state to restore the after we inited.
THD::infinidb_state oldState = thd->infinidb_vtable.vtable_state;
// MCOL-1052 Should be removed after cleaning the code up.
thd->infinidb_vtable.vtable_state = THD::INFINIDB_CREATE_VTABLE;
int rc = ha_calpont_impl_group_by_init(this, table);
thd->infinidb_vtable.vtable_state = oldState;

DBUG_RETURN(rc);
}

/***********************************************************
* DESCRIPTION:
* Fetches a row and saves it to a temporary table.
* RETURN:
* int rc
***********************************************************/
int ha_calpont_group_by_handler::next_row()
{
DBUG_ENTER("ha_calpont_group_by_handler::next_row");
int rc = ha_calpont_impl_group_by_next(this, table);

DBUG_RETURN(rc);
}

/***********************************************************
* DESCRIPTION:
* Shuts the scan down.
* RETURN:
* int rc
***********************************************************/
int ha_calpont_group_by_handler::end_scan()
{
DBUG_ENTER("ha_calpont_group_by_handler::end_scan");

int rc = ha_calpont_impl_group_by_end(this, table);

DBUG_RETURN(rc);
}
#include "ha_mcs_pushdown.cpp"

mysql_declare_plugin(columnstore)
{
Expand Down
49 changes: 1 addition & 48 deletions dbcon/mysql/ha_calpont.h
Expand Up @@ -24,7 +24,7 @@
extern handlerton* calpont_hton;

/** @brief
This structure will be shared among all open handlers.
INFINIDB_SHARE is a structure that will be shared among all open handlers.
This example implements the minimum of what you will probably need.
*/
typedef struct st_calpont_share
Expand Down Expand Up @@ -228,51 +228,4 @@ class ha_calpont: public handler
}

};

/*@brief group_by_handler class*/
/***********************************************************
* DESCRIPTION:
* Provides server with group_by_handler API methods.
* One should read comments in server/sql/group_by_handler.h
* Attributes:
* select - attribute contains all GROUP BY, HAVING, ORDER items and calls it
* an extended SELECT list according to comments in
* server/sql/group_handler.cc.
* So the temporary table for
* select count(*) from b group by a having a > 3 order by a
* will have 4 columns not 1.
* However server ignores all NULLs used in
* GROUP BY, HAVING, ORDER.
* select_list_descr - contains Item description returned by Item->print()
* that is used in lookup for corresponding columns in
* extended SELECT list.
* table_list - contains all tables involved. Must be CS tables only.
* distinct - looks like a useless thing for now. Couldn't get it set by server.
* where - where items.
* group_by - group by ORDER items.
* order_by - order by ORDER items.
* having - having Item.
* Methods:
* init_scan - get plan and send it to ExeMgr. Get the execution result.
* next_row - get a row back from sm.
* end_scan - finish and clean the things up.
***********************************************************/
class ha_calpont_group_by_handler: public group_by_handler
{
public:
ha_calpont_group_by_handler(THD* thd_arg, Query* query);
~ha_calpont_group_by_handler();
int init_scan();
int next_row();
int end_scan();

List<Item>* select;
TABLE_LIST* table_list;
bool distinct;
Item* where;
ORDER* group_by;
ORDER* order_by;
Item* having;
};
#endif //HA_CALPONT_H__

0 comments on commit 2071716

Please sign in to comment.