Commit d0eeb5cc authored by Roman Nozdrin's avatar Roman Nozdrin Committed by Sergei Petrunia

CLX-7 Introduce derived handler support.

        Renamed select handler control knob.

        Updated test suite.
parent 8f3d1f60
......@@ -15,5 +15,24 @@ DROP TABLE cx1;
--error ER_NO_SUCH_TABLE
SHOW CREATE TABLE cx1;
DROP TABLE IF EXISTS intandtext;
CREATE TABLE intandtext(i bigint, t text)ENGINE=clustrixdb;
INSERT INTO intandtext VALUES(10, 'someqwqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq');
SELECT i,t FROM intandtext;
EXPLAIN SELECT i,t FROM intandtext;
SET clustrixdb_select_handler=OFF;
SELECT i,t FROM (SELECT i,t FROM intandtext) t;
EXPLAIN SELECT i,t FROM (SELECT i,t FROM intandtext) t;
SET clustrixdb_select_handler=OFF;
SELECT i,t FROM intandtext;
SELECT i,t FROM (SELECT i,t FROM intandtext) t;
EXPLAIN SELECT i,t FROM (SELECT i,t FROM intandtext) t;
DROP TABLE intandtext;
USE test;
DROP DATABASE clx;
......@@ -91,7 +91,16 @@ static MYSQL_SYSVAR_STR
// Per thread select handler knob
static MYSQL_THDVAR_BOOL(
enable_sh,
select_handler,
PLUGIN_VAR_NOCMDARG,
"",
NULL,
NULL,
1
);
// Per thread derived handler knob
static MYSQL_THDVAR_BOOL(
derived_handler,
PLUGIN_VAR_NOCMDARG,
"",
NULL,
......@@ -99,12 +108,15 @@ static MYSQL_THDVAR_BOOL(
1
);
bool get_enable_sh(THD* thd)
bool select_handler_setting(THD* thd)
{
return ( thd == NULL ) ? false : THDVAR(thd, enable_sh);
return ( thd == NULL ) ? false : THDVAR(thd, select_handler);
}
bool derived_handler_setting(THD* thd)
{
return ( thd == NULL ) ? false : THDVAR(thd, derived_handler);
}
/****************************************************************************
** Class ha_clustrixdb_trx
......@@ -1084,6 +1096,7 @@ static int clustrixdb_init(void *p)
clustrixdb_hton->discover_table_names = clustrixdb_discover_table_names;
clustrixdb_hton->discover_table = clustrixdb_discover_table;
clustrixdb_hton->create_select = create_clustrixdb_select_handler;
clustrixdb_hton->create_derived = create_clustrixdb_derived_handler;
return 0;
}
......@@ -1103,7 +1116,8 @@ static struct st_mysql_sys_var* clustrixdb_system_variables[] =
MYSQL_SYSVAR(password),
MYSQL_SYSVAR(port),
MYSQL_SYSVAR(socket),
MYSQL_SYSVAR(enable_sh),
MYSQL_SYSVAR(select_handler),
MYSQL_SYSVAR(derived_handler),
NULL
};
......
......@@ -89,7 +89,7 @@ static select_handler*
create_clustrixdb_select_handler(THD* thd, SELECT_LEX* select_lex)
{
ha_clustrixdb_select_handler *sh = NULL;
if (!get_enable_sh(thd)) {
if (!select_handler_setting(thd)) {
return sh;
}
......@@ -151,8 +151,10 @@ ha_clustrixdb_select_handler::ha_clustrixdb_select_handler(
THD *thd,
SELECT_LEX* select_lex,
ulonglong scan_refid_)
: select_handler(thd, clustrixdb_hton), scan_refid(scan_refid_)
: select_handler(thd, clustrixdb_hton)
{
thd__ = thd;
scan_refid = scan_refid_;
select = select_lex;
rli = NULL;
rgi = NULL;
......@@ -169,12 +171,14 @@ ha_clustrixdb_select_handler::~ha_clustrixdb_select_handler()
int error_code;
st_clustrixdb_trx *trx = get_trx(thd, &error_code);
if (!trx) {
// WIP BANG
// TBD Log this
}
if (scan_refid)
if (trx && scan_refid)
trx->clustrix_net->scan_end(scan_refid);
my_bitmap_free(&scan_fields);
// If the ::init_scan has been executed
if (table__)
my_bitmap_free(&scan_fields);
remove_current_table_from_rpl_table_list();
}
......@@ -189,7 +193,9 @@ ha_clustrixdb_select_handler::~ha_clustrixdb_select_handler()
* rc as int
* ********************************************************/
int ha_clustrixdb_select_handler::init_scan()
{
{
// Save this into the base handler class attribute
table__ = table;
// need this bitmap future in next_row()
if (my_bitmap_init(&scan_fields, NULL, table->read_set->n_bits, false))
return ER_OUTOFMEMORY;
......@@ -249,8 +255,189 @@ int ha_clustrixdb_select_handler::end_scan()
return 0;
}
void ha_clustrixdb_select_handler::print_error(int, unsigned long)
/*@brief create_clustrixdb_derived_handler- Creates handler*/
/************************************************************
* DESCRIPTION:
* Creates a derived handler
* More details in server/sql/derived_handler.h
* PARAMETERS:
* thd - THD pointer.
* derived - TABLE_LIST* that describes the tables involved
* RETURN:
* derived_handler if possible
* NULL otherwise
************************************************************/
static derived_handler*
create_clustrixdb_derived_handler(THD* thd, TABLE_LIST *derived)
{
ha_clustrixdb_derived_handler *dh = NULL;
if (!derived_handler_setting(thd)) {
return dh;
}
SELECT_LEX_UNIT *unit= derived->derived;
// *DRRTUY Check for potential UNIONS in derived
SELECT_LEX *select_lex = unit->first_select();
String query;
// Print the query into a string provided
select_lex->print(thd, &query, QT_ORDINARY);
int error_code = 0;
int field_metadata_size = 0;
ulonglong scan_refid = 0;
st_clustrixdb_trx *trx = 0;
// We presume this number is equal to types.elements in get_field_types
uint items_number = select_lex->get_item_list()->elements;
uint num_null_bytes = (items_number + 7) / 8;
uchar *fieldtype = NULL;
uchar *null_bits = NULL;
uchar *field_metadata = NULL;
uchar *meta_memory= (uchar *)my_multi_malloc(MYF(MY_WME), &fieldtype, items_number,
&null_bits, num_null_bytes, &field_metadata, (items_number * 2), NULL);
if (!meta_memory) {
// The only way to say something here is to raise warning
// b/c we will fallback to other access methods: derived handler or rowstore.
goto err;
}
if((field_metadata_size =
get_field_types(thd, select_lex, fieldtype, field_metadata, null_bits, num_null_bytes)) < 0) {
goto err;
}
trx = get_trx(thd, &error_code);
if (!trx)
goto err;
if ((error_code = trx->clustrix_net->scan_query_init(query, fieldtype, items_number,
null_bits, num_null_bytes, field_metadata, field_metadata_size, &scan_refid))) {
goto err;
}
dh = new ha_clustrixdb_derived_handler(thd, select_lex, scan_refid);
err:
// deallocate buffers
if (meta_memory)
my_free(meta_memory);
return dh;
}
/***********************************************************
* DESCRIPTION:
* derived_handler constructor
* PARAMETERS:
* thd - THD pointer.
* select_lex - sematic tree for the query.
**********************************************************/
ha_clustrixdb_derived_handler::ha_clustrixdb_derived_handler(
THD *thd,
SELECT_LEX* select_lex,
ulonglong scan_refid_)
: derived_handler(thd, clustrixdb_hton)
{
thd__ = thd;
scan_refid = scan_refid_;
select = select_lex;
rli = NULL;
rgi = NULL;
}
/***********************************************************
* DESCRIPTION:
* derived_handler constructor
* This frees dynamic memory allocated for bitmap
* and disables replication to SH temp table.
**********************************************************/
ha_clustrixdb_derived_handler::~ha_clustrixdb_derived_handler()
{
int error_code;
st_clustrixdb_trx *trx = get_trx(thd, &error_code);
if (!trx) {
// TBD Log this.
}
if (trx && scan_refid)
trx->clustrix_net->scan_end(scan_refid);
// If the ::init_scan has been executed
if (table__)
my_bitmap_free(&scan_fields);
remove_current_table_from_rpl_table_list();
}
/*@brief Initiate the query for derived_handler */
/***********************************************************
* DESCRIPTION:
* Initializes dynamic structures and sets SH temp table
* as RBR replication destination to unpack rows.
* * PARAMETERS:
* RETURN:
* rc as int
* ********************************************************/
int ha_clustrixdb_derived_handler::init_scan()
{
// Save this into the base handler class attribute
table__ = table;
// need this bitmap future in next_row()
if (my_bitmap_init(&scan_fields, NULL, table->read_set->n_bits, false))
return ER_OUTOFMEMORY;
bitmap_set_all(&scan_fields);
add_current_table_to_rpl_table_list();
return 0;
}
/*@brief Fetch next row for derived_handler */
/***********************************************************
* DESCRIPTION:
* Fetch next row for derived_handler.
* PARAMETERS:
* RETURN:
* rc as int
* ********************************************************/
int ha_clustrixdb_derived_handler::next_row()
{
int error_code = 0;
st_clustrixdb_trx *trx = get_trx(thd, &error_code);
if (!trx)
return error_code;
assert(scan_refid);
uchar *rowdata;
ulong rowdata_length;
if ((error_code = trx->clustrix_net->scan_next(scan_refid, &rowdata,
&rowdata_length)))
return error_code;
uchar const *current_row_end;
ulong master_reclength;
error_code = unpack_row(rgi, table, table->s->fields, rowdata,
&scan_fields, &current_row_end,
&master_reclength, rowdata + rowdata_length);
if (error_code)
return error_code;
return 0;
}
/*@brief Finishes the scan and clean it up */
/***********************************************************
* DESCRIPTION:
* Finishes the scan for derived handler
* PARAMETERS:
* RETURN:
* rc as int
***********************************************************/
int ha_clustrixdb_derived_handler::end_scan()
{
return 0;
}
/*@brief clone of ha_clustrixdb method */
......@@ -261,16 +448,16 @@ void ha_clustrixdb_select_handler::print_error(int, unsigned long)
* RETURN:
* rc as int
***********************************************************/
void ha_clustrixdb_select_handler::add_current_table_to_rpl_table_list()
void ha_clustrixdb_base_handler::add_current_table_to_rpl_table_list()
{
if (rli)
return;
rli = new Relay_log_info(FALSE);
rli->sql_driver_thd = thd;
rli->sql_driver_thd = thd__;
rgi = new rpl_group_info(rli);
rgi->thd = thd;
rgi->thd = thd__;
rgi->tables_to_lock_count = 0;
rgi->tables_to_lock = NULL;
if (rgi->tables_to_lock_count)
......@@ -278,20 +465,20 @@ void ha_clustrixdb_select_handler::add_current_table_to_rpl_table_list()
rgi->tables_to_lock = (RPL_TABLE_LIST *)my_malloc(sizeof(RPL_TABLE_LIST),
MYF(MY_WME));
rgi->tables_to_lock->init_one_table(&table->s->db, &table->s->table_name, 0,
rgi->tables_to_lock->init_one_table(&table__->s->db, &table__->s->table_name, 0,
TL_READ);
rgi->tables_to_lock->table = table;
rgi->tables_to_lock->table_id = table->tablenr;
rgi->tables_to_lock->table = table__;
rgi->tables_to_lock->table_id = table__->tablenr;
rgi->tables_to_lock->m_conv_table = NULL;
rgi->tables_to_lock->master_had_triggers = FALSE;
rgi->tables_to_lock->m_tabledef_valid = TRUE;
// We need one byte per column to save a column's binlog type.
uchar *col_type = (uchar*) my_alloca(table->s->fields);
for (uint i = 0 ; i < table->s->fields ; ++i)
col_type[i] = table->field[i]->binlog_type();
uchar *col_type = (uchar*) my_alloca(table__->s->fields);
for (uint i = 0 ; i < table__->s->fields ; ++i)
col_type[i] = table__->field[i]->binlog_type();
table_def *tabledef = &rgi->tables_to_lock->m_tabledef;
new (tabledef) table_def(col_type, table->s->fields, NULL, 0, NULL, 0);
new (tabledef) table_def(col_type, table__->s->fields, NULL, 0, NULL, 0);
rgi->tables_to_lock_count++;
if (col_type)
my_afree(col_type);
......@@ -306,7 +493,7 @@ void ha_clustrixdb_select_handler::add_current_table_to_rpl_table_list()
* RETURN:
* rc as int
***********************************************************/
void ha_clustrixdb_select_handler::remove_current_table_from_rpl_table_list()
void ha_clustrixdb_base_handler::remove_current_table_from_rpl_table_list()
{
// the 2nd cond might be unnecessary
if (!rgi || !rgi->tables_to_lock)
......@@ -320,6 +507,3 @@ void ha_clustrixdb_select_handler::remove_current_table_from_rpl_table_list()
delete rli;
delete rgi;
}
......@@ -5,8 +5,38 @@ Copyright (c) 2019, MariaDB Corporation.
#define _ha_clustrixdb_pushdown_h
#include "select_handler.h"
#include "derived_handler.h"
#include "sql_select.h"
/*@brief base_handler class*/
/***********************************************************
* DESCRIPTION:
* To be described
************************************************************/
class ha_clustrixdb_base_handler
{
// To simulate abstract class
protected:
ha_clustrixdb_base_handler(): thd__(0),table__(0) {}
~ha_clustrixdb_base_handler() {}
// Copies of pushdown handlers attributes
// to use them in shared methods.
THD *thd__;
TABLE *table__;
// The bitmap used to sent
MY_BITMAP scan_fields;
// Structures to unpack RBR rows from CLX BE
rpl_group_info *rgi;
Relay_log_info *rli;
RPL_TABLE_LIST *rpl_table_list;
// CLX BE scan operation reference
ulonglong scan_refid;
// To unpack rows from CLX BE
void add_current_table_to_rpl_table_list();
void remove_current_table_from_rpl_table_list();
};
/*@brief select_handler class*/
/***********************************************************
* DESCRIPTION:
......@@ -15,7 +45,9 @@ Copyright (c) 2019, MariaDB Corporation.
* More details in server/sql/select_handler.h
* sel semantic tree for the query in SELECT_LEX.
************************************************************/
class ha_clustrixdb_select_handler: public select_handler
class ha_clustrixdb_select_handler:
private ha_clustrixdb_base_handler,
public select_handler
{
public:
ha_clustrixdb_select_handler(THD* thd_arg, SELECT_LEX* sel,
......@@ -25,20 +57,32 @@ class ha_clustrixdb_select_handler: public select_handler
int init_scan();
int next_row();
int end_scan();
void print_error(int, unsigned long);
void print_error(int, unsigned long) {}
};
private:
// The bitmap used to sent
MY_BITMAP scan_fields;
// Structures to unpack RBR rows from CLX BE
rpl_group_info *rgi;
Relay_log_info *rli;
RPL_TABLE_LIST *rpl_table_list;
// CLX BE scan operation reference
ulonglong scan_refid;
// To unpack rows from CLX BE
void add_current_table_to_rpl_table_list();
void remove_current_table_from_rpl_table_list();
/*@brief derived_handler class*/
/***********************************************************
* DESCRIPTION:
* derived_handler API methods. Could be used by the server
* tp pushdown the whole query described by SELECT_LEX.
* More details in server/sql/derived_handler.h
* sel semantic tree for the query in SELECT_LEX.
************************************************************/
class ha_clustrixdb_derived_handler:
private ha_clustrixdb_base_handler,
public derived_handler
{
public:
ha_clustrixdb_derived_handler(THD* thd_arg, SELECT_LEX* sel,
ulonglong scan_refid);
~ha_clustrixdb_derived_handler();
int init_scan();
int next_row();
int end_scan();
void print_error(int, unsigned long) {}
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment