mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01:00
68a002071b
The direct aggregate mechanism sems to be only intended to work when otherwise a full table scan query will be executed from the spider node and the aggregation done at the spider node too. Typically this happens in sub_select(). In the test spider.direct_aggregate_part direct aggregate allows to send COUNT statements directly to the data nodes and adds up the results at the spider node, instead of iterating over the rows one by one at the spider node. By contrast, the group by handler (GBH) typically sends aggregated queries directly to data nodes, in which case DA does not improve the situation here. That is why we should fix it by disabling DA when GBH is used. There are other reasons supporting this change. First, the creation of GBH results in a call to change_to_use_tmp_fields() (as opposed to setup_copy_fields()) which causes the spider DA function spider_db_fetch_for_item_sum_funcs() to work on wrong items. Second, the spider DA function only calls direct_add() on the items, and the follow-up add() needs to be called by the sql layer code. In do_select(), after executing the query with the GBH, it seems that the required add() would not necessarily be called. Disabling DA when GBH is used does fix the bug. There are a few other things included in this commit to improve the situation with spider DA: 1. Add a session variable that allows user to disable DA completely, this will help as a temporary measure if/when further bugs with DA emerge. 2. Move the increment of direct_aggregate_count to the spider DA function. Currently this is done in rather bizarre and random locations. 3. Fix the spider_db_mbase_row creation so that the last of its row field (sentinel) is NULL. The code is already doing a null check, but somehow the sentinel field is on an invalid address, causing the segfaults. With a correct implementation of the row creation, we can avoid such segfaults.
2132 lines
66 KiB
C++
2132 lines
66 KiB
C++
/* Copyright (C) 2008-2019 Kentoku Shiba
|
|
Copyright (C) 2019 MariaDB corp
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
#define MYSQL_SERVER 1
|
|
#include <my_global.h>
|
|
#include "mysql_version.h"
|
|
#include "spd_environ.h"
|
|
#if MYSQL_VERSION_ID < 50500
|
|
#include "mysql_priv.h"
|
|
#include <mysql/plugin.h>
|
|
#else
|
|
#include "sql_priv.h"
|
|
#include "probes_mysql.h"
|
|
#include "sql_class.h"
|
|
#include "sql_partition.h"
|
|
#include "ha_partition.h"
|
|
#endif
|
|
#include "sql_common.h"
|
|
#include <errmsg.h>
|
|
#include "spd_err.h"
|
|
#include "spd_param.h"
|
|
#include "spd_db_include.h"
|
|
#include "spd_include.h"
|
|
#include "ha_spider.h"
|
|
#include "spd_conn.h"
|
|
#include "spd_db_conn.h"
|
|
#include "spd_malloc.h"
|
|
#include "spd_table.h"
|
|
#include "spd_ping_table.h"
|
|
#include "spd_group_by_handler.h"
|
|
|
|
extern handlerton *spider_hton_ptr;
|
|
extern SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE];
|
|
|
|
spider_fields::spider_fields() :
|
|
dbton_count(0), current_dbton_num(0),
|
|
table_count(0), current_table_num(0), table_holder(NULL),
|
|
first_link_idx_chain(NULL), last_link_idx_chain(NULL), current_link_idx_chain(NULL),
|
|
first_conn_holder(NULL), last_conn_holder(NULL), current_conn_holder(NULL),
|
|
first_field_holder(NULL), last_field_holder(NULL), current_field_holder(NULL),
|
|
first_field_chain(NULL), last_field_chain(NULL), current_field_chain(NULL)
|
|
{
|
|
DBUG_ENTER("spider_fields::spider_fields");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
spider_fields::~spider_fields()
|
|
{
|
|
DBUG_ENTER("spider_fields::~spider_fields");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
if (first_link_idx_chain)
|
|
{
|
|
while ((current_link_idx_chain = first_link_idx_chain))
|
|
{
|
|
first_link_idx_chain = current_link_idx_chain->next;
|
|
spider_free(spider_current_trx, current_link_idx_chain, MYF(0));
|
|
}
|
|
}
|
|
if (first_field_chain)
|
|
{
|
|
while ((current_field_chain = first_field_chain))
|
|
{
|
|
first_field_chain = current_field_chain->next;
|
|
spider_free(spider_current_trx, current_field_chain, MYF(0));
|
|
}
|
|
}
|
|
if (first_field_holder)
|
|
{
|
|
while ((current_field_holder = first_field_holder))
|
|
{
|
|
first_field_holder = current_field_holder->next;
|
|
spider_free(spider_current_trx, current_field_holder, MYF(0));
|
|
}
|
|
}
|
|
if (table_holder)
|
|
spider_free(spider_current_trx, table_holder, MYF(0));
|
|
if (first_conn_holder)
|
|
{
|
|
while ((current_conn_holder = first_conn_holder))
|
|
{
|
|
first_conn_holder = current_conn_holder->next;
|
|
free_conn_holder(current_conn_holder);
|
|
}
|
|
}
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
void spider_fields::add_dbton_id(
|
|
uint dbton_id_arg
|
|
) {
|
|
uint roop_count;
|
|
DBUG_ENTER("spider_fields::add_dbton_id");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
for (roop_count = 0; roop_count < dbton_count; ++roop_count)
|
|
{
|
|
if (dbton_ids[roop_count] == dbton_id_arg)
|
|
{
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
}
|
|
dbton_ids[roop_count] = dbton_id_arg;
|
|
++dbton_count;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
void spider_fields::set_pos_to_first_dbton_id(
|
|
) {
|
|
DBUG_ENTER("spider_fields::set_pos_to_first_dbton_id");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
current_dbton_num = 0;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
uint spider_fields::get_next_dbton_id(
|
|
) {
|
|
uint return_dbton_id;
|
|
DBUG_ENTER("spider_fields::get_next_dbton_id");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
if (current_dbton_num >= dbton_count)
|
|
DBUG_RETURN(SPIDER_DBTON_SIZE);
|
|
return_dbton_id = dbton_ids[current_dbton_num];
|
|
++current_dbton_num;
|
|
DBUG_RETURN(return_dbton_id);
|
|
}
|
|
|
|
int spider_fields::make_link_idx_chain(
|
|
int link_status
|
|
) {
|
|
uint roop_count, roop_count2;
|
|
SPIDER_CONN *conn;
|
|
SPIDER_CONN_HOLDER *conn_holder;
|
|
SPIDER_TABLE_LINK_IDX_HOLDER *table_link_idx_holder;
|
|
SPIDER_LINK_IDX_HOLDER *link_idx_holder, *add_link_idx_holder,
|
|
*dup_link_idx_holder, *current_link_idx_holder;
|
|
ha_spider *spider;
|
|
SPIDER_LINK_IDX_CHAIN *link_idx_chain;
|
|
SPIDER_SHARE *share;
|
|
DBUG_ENTER("spider_fields::make_link_idx_chain");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
conn_holder = first_conn_holder;
|
|
bool has_remain, skip;
|
|
do {
|
|
for (roop_count2 = 0; roop_count2 < table_count; ++roop_count2)
|
|
{
|
|
table_link_idx_holder = &conn_holder->table_link_idx_holder[roop_count2];
|
|
link_idx_holder = table_link_idx_holder->first_link_idx_holder;
|
|
dup_link_idx_holder = NULL;
|
|
for (roop_count = 0;
|
|
roop_count < conn_holder->link_idx_holder_count_max - 1; ++roop_count)
|
|
{
|
|
if (!link_idx_holder->next)
|
|
{
|
|
DBUG_PRINT("info",("spider fill link_idx_holder for %u",
|
|
roop_count2));
|
|
if (!(add_link_idx_holder = create_link_idx_holder()))
|
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
|
dup_link_idx_holder = get_dup_link_idx_holder(
|
|
table_link_idx_holder, dup_link_idx_holder);
|
|
add_link_idx_holder->table_link_idx_holder =
|
|
dup_link_idx_holder->table_link_idx_holder;
|
|
add_link_idx_holder->link_idx = dup_link_idx_holder->link_idx;
|
|
add_link_idx_holder->link_status = dup_link_idx_holder->link_status;
|
|
link_idx_holder->next = add_link_idx_holder;
|
|
}
|
|
link_idx_holder = link_idx_holder->next;
|
|
}
|
|
}
|
|
|
|
for (roop_count2 = 0; roop_count2 < table_count; ++roop_count2)
|
|
{
|
|
table_link_idx_holder = &conn_holder->table_link_idx_holder[roop_count2];
|
|
table_link_idx_holder->current_link_idx_holder =
|
|
table_link_idx_holder->first_link_idx_holder;
|
|
}
|
|
for (roop_count = 0;
|
|
roop_count < conn_holder->link_idx_holder_count_max; ++roop_count)
|
|
{
|
|
link_idx_holder = NULL;
|
|
for (roop_count2 = 0; roop_count2 < table_count; ++roop_count2)
|
|
{
|
|
table_link_idx_holder =
|
|
&conn_holder->table_link_idx_holder[roop_count2];
|
|
if (link_idx_holder)
|
|
{
|
|
link_idx_holder->next_table =
|
|
table_link_idx_holder->current_link_idx_holder;
|
|
}
|
|
link_idx_holder = table_link_idx_holder->current_link_idx_holder;
|
|
table_link_idx_holder->current_link_idx_holder = link_idx_holder->next;
|
|
}
|
|
}
|
|
} while ((conn_holder = conn_holder->next));
|
|
|
|
current_conn_holder = first_conn_holder;
|
|
do {
|
|
table_link_idx_holder =
|
|
¤t_conn_holder->table_link_idx_holder[0];
|
|
table_link_idx_holder->current_link_idx_holder =
|
|
table_link_idx_holder->first_link_idx_holder;
|
|
} while ((current_conn_holder = current_conn_holder->next));
|
|
|
|
spider = table_holder[0].spider;
|
|
share = spider->share;
|
|
DBUG_PRINT("info",("spider create link_idx_chain sorted by 0"));
|
|
for (
|
|
roop_count = spider_conn_link_idx_next(share->link_statuses,
|
|
spider->conn_link_idx, -1, share->link_count,
|
|
link_status);
|
|
roop_count < share->link_count;
|
|
roop_count = spider_conn_link_idx_next(share->link_statuses,
|
|
spider->conn_link_idx, roop_count, share->link_count,
|
|
link_status)
|
|
) {
|
|
conn = spider->conns[roop_count];
|
|
if (!conn->conn_holder_for_direct_join)
|
|
{
|
|
continue;
|
|
}
|
|
table_link_idx_holder =
|
|
&conn->conn_holder_for_direct_join->table_link_idx_holder[0];
|
|
link_idx_holder = table_link_idx_holder->current_link_idx_holder;
|
|
table_link_idx_holder->current_link_idx_holder = link_idx_holder->next;
|
|
DBUG_ASSERT(link_idx_holder->link_idx == (int) roop_count);
|
|
if (!(link_idx_chain = create_link_idx_chain()))
|
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
|
if (!first_link_idx_chain)
|
|
{
|
|
first_link_idx_chain = link_idx_chain;
|
|
} else {
|
|
last_link_idx_chain->next = link_idx_chain;
|
|
}
|
|
last_link_idx_chain = link_idx_chain;
|
|
link_idx_chain->conn = conn;
|
|
link_idx_chain->link_idx_holder = link_idx_holder;
|
|
do {
|
|
if (link_idx_chain->link_status < link_idx_holder->link_status)
|
|
{
|
|
link_idx_chain->link_status = link_idx_holder->link_status;
|
|
}
|
|
} while ((link_idx_holder = link_idx_holder->next_table));
|
|
}
|
|
|
|
do {
|
|
has_remain = FALSE;
|
|
current_conn_holder = first_conn_holder;
|
|
do {
|
|
table_link_idx_holder =
|
|
¤t_conn_holder->table_link_idx_holder[0];
|
|
link_idx_holder = table_link_idx_holder->current_link_idx_holder;
|
|
if (link_idx_holder)
|
|
{
|
|
has_remain = TRUE;
|
|
for (roop_count2 = 1; roop_count2 < table_count; ++roop_count2)
|
|
{
|
|
if (table_link_idx_holder[roop_count2].link_idx_holder_count ==
|
|
current_conn_holder->link_idx_holder_count_max)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
} while ((current_conn_holder = current_conn_holder->next));
|
|
|
|
if (has_remain)
|
|
{
|
|
current_conn_holder = first_conn_holder;
|
|
do {
|
|
table_link_idx_holder =
|
|
¤t_conn_holder->table_link_idx_holder[0];
|
|
link_idx_holder = table_link_idx_holder->current_link_idx_holder;
|
|
if (link_idx_holder)
|
|
{
|
|
for (roop_count = 1; roop_count <= roop_count2; ++roop_count)
|
|
{
|
|
link_idx_holder = link_idx_holder->next_table;
|
|
}
|
|
table_link_idx_holder[roop_count2].current_link_idx_holder =
|
|
link_idx_holder;
|
|
} else {
|
|
table_link_idx_holder[roop_count2].current_link_idx_holder = NULL;
|
|
}
|
|
} while ((current_conn_holder = current_conn_holder->next));
|
|
|
|
spider = table_holder[roop_count2].spider;
|
|
share = spider->share;
|
|
DBUG_PRINT("info",("spider create link_idx_chain sorted by %d",
|
|
roop_count2));
|
|
for (
|
|
roop_count = spider_conn_link_idx_next(share->link_statuses,
|
|
spider->conn_link_idx, -1, share->link_count,
|
|
link_status);
|
|
roop_count < share->link_count;
|
|
roop_count = spider_conn_link_idx_next(share->link_statuses,
|
|
spider->conn_link_idx, roop_count, share->link_count,
|
|
link_status)
|
|
) {
|
|
conn = spider->conns[roop_count];
|
|
if (!conn->conn_holder_for_direct_join)
|
|
{
|
|
continue;
|
|
}
|
|
table_link_idx_holder =
|
|
&conn->conn_holder_for_direct_join->table_link_idx_holder[0];
|
|
link_idx_holder =
|
|
table_link_idx_holder[roop_count2].current_link_idx_holder;
|
|
skip = FALSE;
|
|
if (link_idx_holder)
|
|
{
|
|
current_link_idx_holder = table_link_idx_holder->first_link_idx_holder;
|
|
while (current_link_idx_holder != link_idx_holder)
|
|
{
|
|
if (current_link_idx_holder->link_idx ==
|
|
link_idx_holder->link_idx)
|
|
{
|
|
skip = TRUE;
|
|
break;
|
|
}
|
|
current_link_idx_holder = current_link_idx_holder->next;
|
|
}
|
|
}
|
|
if (skip)
|
|
{
|
|
continue;
|
|
}
|
|
DBUG_PRINT("info",("spider create link_idx_chain for %d",
|
|
roop_count2));
|
|
table_link_idx_holder[roop_count2].current_link_idx_holder =
|
|
link_idx_holder->next;
|
|
link_idx_holder =
|
|
table_link_idx_holder->current_link_idx_holder;
|
|
table_link_idx_holder->current_link_idx_holder =
|
|
link_idx_holder->next;
|
|
if (!(link_idx_chain = create_link_idx_chain()))
|
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
|
DBUG_ASSERT(first_link_idx_chain);
|
|
last_link_idx_chain->next = link_idx_chain;
|
|
last_link_idx_chain = link_idx_chain;
|
|
link_idx_chain->conn = conn;
|
|
link_idx_chain->link_idx_holder = link_idx_holder;
|
|
do {
|
|
if (link_idx_chain->link_status < link_idx_holder->link_status)
|
|
{
|
|
link_idx_chain->link_status = link_idx_holder->link_status;
|
|
}
|
|
} while ((link_idx_holder = link_idx_holder->next_table));
|
|
}
|
|
}
|
|
} while (has_remain);
|
|
DBUG_RETURN(0);
|
|
}
|
|
|
|
SPIDER_LINK_IDX_CHAIN *spider_fields::create_link_idx_chain(
|
|
) {
|
|
DBUG_ENTER("spider_fields::create_link_idx_chain");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
DBUG_RETURN((SPIDER_LINK_IDX_CHAIN *)
|
|
spider_malloc(spider_current_trx, 254, sizeof(SPIDER_LINK_IDX_CHAIN),
|
|
MYF(MY_WME | MY_ZEROFILL)));
|
|
}
|
|
|
|
void spider_fields::set_pos_to_first_link_idx_chain(
|
|
) {
|
|
DBUG_ENTER("spider_fields::set_pos_to_first_link_idx_chain");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
current_link_idx_chain = first_link_idx_chain;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
SPIDER_LINK_IDX_CHAIN *spider_fields::get_next_link_idx_chain(
|
|
) {
|
|
SPIDER_LINK_IDX_CHAIN *return_link_idx_chain = current_link_idx_chain;
|
|
DBUG_ENTER("spider_fields::get_next_link_idx_chain");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
if (current_link_idx_chain)
|
|
current_link_idx_chain = current_link_idx_chain->next;
|
|
DBUG_RETURN(return_link_idx_chain);
|
|
}
|
|
|
|
SPIDER_LINK_IDX_HOLDER *spider_fields::get_dup_link_idx_holder(
|
|
SPIDER_TABLE_LINK_IDX_HOLDER *table_link_idx_holder,
|
|
SPIDER_LINK_IDX_HOLDER *current
|
|
) {
|
|
SPIDER_LINK_IDX_HOLDER *return_link_idx_holder;
|
|
DBUG_ENTER("spider_fields::get_dup_link_idx_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
if (!current)
|
|
{
|
|
return_link_idx_holder = table_link_idx_holder->first_link_idx_holder;
|
|
do {
|
|
if (return_link_idx_holder->link_status == SPIDER_LINK_STATUS_OK)
|
|
break;
|
|
} while ((return_link_idx_holder = return_link_idx_holder->next));
|
|
if (!return_link_idx_holder)
|
|
{
|
|
return_link_idx_holder = table_link_idx_holder->first_link_idx_holder;
|
|
}
|
|
} else {
|
|
if (current->link_status == SPIDER_LINK_STATUS_OK)
|
|
{
|
|
return_link_idx_holder = current;
|
|
while ((return_link_idx_holder = return_link_idx_holder->next))
|
|
{
|
|
if (return_link_idx_holder->link_status == SPIDER_LINK_STATUS_OK)
|
|
break;
|
|
}
|
|
if (!return_link_idx_holder)
|
|
{
|
|
return_link_idx_holder = table_link_idx_holder->first_link_idx_holder;
|
|
do {
|
|
if (
|
|
return_link_idx_holder->link_status == SPIDER_LINK_STATUS_OK
|
|
)
|
|
break;
|
|
DBUG_ASSERT(return_link_idx_holder != current);
|
|
} while ((return_link_idx_holder = return_link_idx_holder->next));
|
|
}
|
|
} else {
|
|
if (!current->next)
|
|
{
|
|
return_link_idx_holder = table_link_idx_holder->first_link_idx_holder;
|
|
} else {
|
|
return_link_idx_holder = current->next;
|
|
}
|
|
}
|
|
}
|
|
DBUG_RETURN(return_link_idx_holder);
|
|
}
|
|
|
|
bool spider_fields::check_link_ok_chain(
|
|
) {
|
|
DBUG_ENTER("spider_fields::check_link_ok_chain");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
for (current_link_idx_chain = first_link_idx_chain; current_link_idx_chain;
|
|
current_link_idx_chain = current_link_idx_chain->next)
|
|
{
|
|
DBUG_PRINT("info",("spider current_link_idx_chain=%p", current_link_idx_chain));
|
|
DBUG_PRINT("info",("spider current_link_idx_chain->link_status=%d", current_link_idx_chain->link_status));
|
|
if (current_link_idx_chain->link_status == SPIDER_LINK_STATUS_OK)
|
|
{
|
|
first_ok_link_idx_chain = current_link_idx_chain;
|
|
DBUG_RETURN(FALSE);
|
|
}
|
|
}
|
|
DBUG_RETURN(TRUE);
|
|
}
|
|
|
|
bool spider_fields::is_first_link_ok_chain(
|
|
SPIDER_LINK_IDX_CHAIN *link_idx_chain_arg
|
|
) {
|
|
DBUG_ENTER("spider_fields::is_first_link_ok_chain");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
DBUG_RETURN(first_ok_link_idx_chain == link_idx_chain_arg);
|
|
}
|
|
|
|
int spider_fields::get_ok_link_idx(
|
|
) {
|
|
DBUG_ENTER("spider_fields::get_ok_link_idx");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
DBUG_RETURN(first_ok_link_idx_chain->link_idx_holder->link_idx);
|
|
}
|
|
|
|
void spider_fields::set_first_link_idx(
|
|
) {
|
|
SPIDER_TABLE_HOLDER *table_holder;
|
|
SPIDER_LINK_IDX_HOLDER *link_idx_holder;
|
|
SPIDER_LINK_IDX_CHAIN *link_idx_chain;
|
|
uint dbton_id;
|
|
ha_spider *spider;
|
|
spider_db_handler *dbton_hdl;
|
|
DBUG_ENTER("spider_fields::set_first_link_idx");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
set_pos_to_first_dbton_id();
|
|
while ((dbton_id = get_next_dbton_id()) < SPIDER_DBTON_SIZE)
|
|
{
|
|
set_pos_to_first_link_idx_chain();
|
|
while ((link_idx_chain = get_next_link_idx_chain()))
|
|
{
|
|
if (link_idx_chain->conn->dbton_id == dbton_id)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
DBUG_ASSERT(link_idx_chain);
|
|
set_pos_to_first_table_on_link_idx_chain(link_idx_chain);
|
|
|
|
set_pos_to_first_table_holder();
|
|
while ((table_holder = get_next_table_holder()))
|
|
{
|
|
link_idx_holder = get_next_table_on_link_idx_chain(link_idx_chain);
|
|
spider = table_holder->spider;
|
|
dbton_hdl = spider->dbton_handler[dbton_id];
|
|
dbton_hdl->first_link_idx = link_idx_holder->link_idx;
|
|
}
|
|
}
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
int spider_fields::add_link_idx(
|
|
SPIDER_CONN_HOLDER *conn_holder_arg,
|
|
ha_spider *spider_arg,
|
|
int link_idx
|
|
) {
|
|
SPIDER_TABLE_LINK_IDX_HOLDER *table_link_idx_holder;
|
|
SPIDER_LINK_IDX_HOLDER *link_idx_holder;
|
|
DBUG_ENTER("spider_fields::add_link_idx");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
table_link_idx_holder =
|
|
&conn_holder_arg->table_link_idx_holder[spider_arg->idx_for_direct_join];
|
|
if (!table_link_idx_holder->first_link_idx_holder)
|
|
{
|
|
link_idx_holder = create_link_idx_holder();
|
|
DBUG_PRINT("info",("spider link_idx_holder=%p", link_idx_holder));
|
|
if (!link_idx_holder)
|
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
|
table_link_idx_holder->first_link_idx_holder = link_idx_holder;
|
|
table_link_idx_holder->last_link_idx_holder = link_idx_holder;
|
|
table_link_idx_holder->table_holder =
|
|
&table_holder[spider_arg->idx_for_direct_join];
|
|
} else {
|
|
link_idx_holder = create_link_idx_holder();
|
|
DBUG_PRINT("info",("spider link_idx_holder=%p", link_idx_holder));
|
|
if (!link_idx_holder)
|
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
|
table_link_idx_holder->last_link_idx_holder->next = link_idx_holder;
|
|
table_link_idx_holder->last_link_idx_holder = link_idx_holder;
|
|
}
|
|
link_idx_holder->table_link_idx_holder = table_link_idx_holder;
|
|
link_idx_holder->link_idx = link_idx;
|
|
link_idx_holder->link_status = spider_conn_get_link_status(
|
|
spider_arg->share->link_statuses, spider_arg->conn_link_idx,
|
|
link_idx);
|
|
++table_link_idx_holder->link_idx_holder_count;
|
|
if (conn_holder_arg->link_idx_holder_count_max <
|
|
table_link_idx_holder->link_idx_holder_count)
|
|
{
|
|
conn_holder_arg->link_idx_holder_count_max =
|
|
table_link_idx_holder->link_idx_holder_count;
|
|
}
|
|
DBUG_RETURN(0);
|
|
}
|
|
|
|
SPIDER_LINK_IDX_HOLDER *spider_fields::create_link_idx_holder(
|
|
) {
|
|
DBUG_ENTER("spider_fields::create_link_idx_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
DBUG_RETURN((SPIDER_LINK_IDX_HOLDER *)
|
|
spider_malloc(spider_current_trx, 253, sizeof(SPIDER_LINK_IDX_HOLDER),
|
|
MYF(MY_WME | MY_ZEROFILL)));
|
|
}
|
|
|
|
void spider_fields::set_pos_to_first_table_on_link_idx_chain(
|
|
SPIDER_LINK_IDX_CHAIN *link_idx_chain_arg
|
|
) {
|
|
DBUG_ENTER("spider_fields::set_pos_to_first_table_on_link_idx_chain");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
link_idx_chain_arg->current_link_idx_holder =
|
|
link_idx_chain_arg->link_idx_holder;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
SPIDER_LINK_IDX_HOLDER *spider_fields::get_next_table_on_link_idx_chain(
|
|
SPIDER_LINK_IDX_CHAIN *link_idx_chain_arg
|
|
) {
|
|
SPIDER_LINK_IDX_HOLDER *return_link_idx_holder;
|
|
DBUG_ENTER("spider_fields::get_next_table_on_link_idx_chain");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
if (!link_idx_chain_arg->current_link_idx_holder)
|
|
DBUG_RETURN(NULL);
|
|
return_link_idx_holder = link_idx_chain_arg->current_link_idx_holder;
|
|
link_idx_chain_arg->current_link_idx_holder =
|
|
link_idx_chain_arg->current_link_idx_holder->next_table;
|
|
DBUG_RETURN(return_link_idx_holder);
|
|
}
|
|
|
|
SPIDER_CONN_HOLDER *spider_fields::add_conn(
|
|
SPIDER_CONN *conn_arg,
|
|
long access_balance
|
|
) {
|
|
SPIDER_CONN_HOLDER *conn_holder;
|
|
DBUG_ENTER("spider_fields::add_conn");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
if (!first_conn_holder)
|
|
{
|
|
conn_holder = create_conn_holder();
|
|
DBUG_PRINT("info",("spider conn_holder=%p", conn_holder));
|
|
if (!conn_holder)
|
|
DBUG_RETURN(NULL);
|
|
conn_holder->conn = conn_arg;
|
|
conn_holder->access_balance = access_balance;
|
|
first_conn_holder = conn_holder;
|
|
last_conn_holder = conn_holder;
|
|
conn_arg->conn_holder_for_direct_join = conn_holder;
|
|
add_dbton_id(conn_arg->dbton_id);
|
|
} else {
|
|
conn_holder = first_conn_holder;
|
|
do {
|
|
if (conn_holder->conn == conn_arg)
|
|
break;
|
|
} while ((conn_holder = conn_holder->next));
|
|
if (!conn_holder)
|
|
{
|
|
conn_holder = create_conn_holder();
|
|
DBUG_PRINT("info",("spider conn_holder=%p", conn_holder));
|
|
if (!conn_holder)
|
|
DBUG_RETURN(NULL);
|
|
conn_holder->conn = conn_arg;
|
|
conn_holder->access_balance = access_balance;
|
|
conn_holder->prev = last_conn_holder;
|
|
last_conn_holder->next = conn_holder;
|
|
last_conn_holder = conn_holder;
|
|
conn_arg->conn_holder_for_direct_join = conn_holder;
|
|
add_dbton_id(conn_arg->dbton_id);
|
|
}
|
|
}
|
|
DBUG_RETURN(conn_holder);
|
|
}
|
|
|
|
SPIDER_CONN_HOLDER *spider_fields::create_conn_holder(
|
|
) {
|
|
SPIDER_CONN_HOLDER *return_conn_holder;
|
|
SPIDER_TABLE_LINK_IDX_HOLDER *table_link_idx_holder;
|
|
DBUG_ENTER("spider_fields::create_conn_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
return_conn_holder = (SPIDER_CONN_HOLDER *)
|
|
spider_bulk_malloc(spider_current_trx, 252, MYF(MY_WME | MY_ZEROFILL),
|
|
&return_conn_holder, (uint) (sizeof(SPIDER_CONN_HOLDER)),
|
|
&table_link_idx_holder,
|
|
(uint) (table_count * sizeof(SPIDER_TABLE_LINK_IDX_HOLDER)),
|
|
NullS
|
|
);
|
|
if (!return_conn_holder)
|
|
DBUG_RETURN(NULL);
|
|
DBUG_PRINT("info",("spider table_count=%u", table_count));
|
|
DBUG_PRINT("info",("spider table_link_idx_holder=%p", table_link_idx_holder));
|
|
return_conn_holder->table_link_idx_holder = table_link_idx_holder;
|
|
DBUG_RETURN(return_conn_holder);
|
|
}
|
|
|
|
void spider_fields::set_pos_to_first_conn_holder(
|
|
) {
|
|
DBUG_ENTER("spider_fields::set_pos_to_first_conn_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
current_conn_holder = first_conn_holder;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
SPIDER_CONN_HOLDER *spider_fields::get_next_conn_holder(
|
|
) {
|
|
SPIDER_CONN_HOLDER *return_conn_holder = current_conn_holder;
|
|
DBUG_ENTER("spider_fields::get_next_conn_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
if (current_conn_holder)
|
|
current_conn_holder = current_conn_holder->next;
|
|
DBUG_RETURN(return_conn_holder);
|
|
}
|
|
|
|
bool spider_fields::has_conn_holder(
|
|
) {
|
|
DBUG_ENTER("spider_fields::has_conn_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
DBUG_RETURN(first_conn_holder);
|
|
}
|
|
|
|
void spider_fields::clear_conn_holder_from_conn(
|
|
) {
|
|
DBUG_ENTER("spider_fields::clear_conn_checked_for_same_conn");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
for (current_conn_holder = first_conn_holder; current_conn_holder;
|
|
current_conn_holder = current_conn_holder->next)
|
|
{
|
|
current_conn_holder->checked_for_same_conn = FALSE;
|
|
}
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
bool spider_fields::check_conn_same_conn(
|
|
SPIDER_CONN *conn_arg
|
|
) {
|
|
DBUG_ENTER("spider_fields::check_conn_same_conn");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
for (current_conn_holder = first_conn_holder; current_conn_holder;
|
|
current_conn_holder = current_conn_holder->next)
|
|
{
|
|
if (current_conn_holder->conn == conn_arg)
|
|
{
|
|
current_conn_holder->checked_for_same_conn = TRUE;
|
|
DBUG_RETURN(TRUE);
|
|
}
|
|
}
|
|
DBUG_RETURN(FALSE);
|
|
}
|
|
|
|
bool spider_fields::remove_conn_if_not_checked(
|
|
) {
|
|
SPIDER_CONN_HOLDER *conn_holder;
|
|
bool removed = FALSE;
|
|
DBUG_ENTER("spider_fields::remove_conn_if_not_checked");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
current_conn_holder = first_conn_holder;
|
|
while (current_conn_holder)
|
|
{
|
|
if (!current_conn_holder->checked_for_same_conn)
|
|
{
|
|
removed = TRUE;
|
|
DBUG_PRINT("info",("spider remove connection %p",
|
|
current_conn_holder->conn));
|
|
if (!current_conn_holder->prev)
|
|
{
|
|
first_conn_holder = current_conn_holder->next;
|
|
if (current_conn_holder->next)
|
|
{
|
|
current_conn_holder->next->prev = NULL;
|
|
} else {
|
|
last_conn_holder = NULL;
|
|
}
|
|
} else {
|
|
current_conn_holder->prev->next = current_conn_holder->next;
|
|
if (current_conn_holder->next)
|
|
{
|
|
current_conn_holder->next->prev = current_conn_holder->prev;
|
|
} else {
|
|
last_conn_holder = current_conn_holder->prev;
|
|
last_conn_holder->next = NULL;
|
|
}
|
|
}
|
|
conn_holder = current_conn_holder->next;
|
|
free_conn_holder(current_conn_holder);
|
|
current_conn_holder = conn_holder;
|
|
} else {
|
|
current_conn_holder = current_conn_holder->next;
|
|
}
|
|
}
|
|
DBUG_RETURN(removed);
|
|
}
|
|
|
|
void spider_fields::check_support_dbton(
|
|
uchar *dbton_bitmap
|
|
) {
|
|
SPIDER_CONN_HOLDER *conn_holder;
|
|
DBUG_ENTER("spider_fields::check_support_dbton");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
current_conn_holder = first_conn_holder;
|
|
while (current_conn_holder)
|
|
{
|
|
if (!spider_bit_is_set(dbton_bitmap, current_conn_holder->conn->dbton_id))
|
|
{
|
|
DBUG_PRINT("info",("spider remove connection %p",
|
|
current_conn_holder->conn));
|
|
if (!current_conn_holder->prev)
|
|
{
|
|
first_conn_holder = current_conn_holder->next;
|
|
if (current_conn_holder->next)
|
|
{
|
|
current_conn_holder->next->prev = NULL;
|
|
} else {
|
|
last_conn_holder = NULL;
|
|
}
|
|
} else {
|
|
current_conn_holder->prev->next = current_conn_holder->next;
|
|
if (current_conn_holder->next)
|
|
{
|
|
current_conn_holder->next->prev = current_conn_holder->prev;
|
|
} else {
|
|
last_conn_holder = current_conn_holder->prev;
|
|
last_conn_holder->next = NULL;
|
|
}
|
|
}
|
|
conn_holder = current_conn_holder->next;
|
|
free_conn_holder(current_conn_holder);
|
|
current_conn_holder = conn_holder;
|
|
} else {
|
|
current_conn_holder = current_conn_holder->next;
|
|
}
|
|
}
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
void spider_fields::choose_a_conn(
|
|
) {
|
|
SPIDER_CONN_HOLDER *conn_holder;
|
|
longlong balance_total = 0, balance_val;
|
|
double rand_val;
|
|
THD *thd = table_holder[0].spider->wide_handler->trx->thd;
|
|
DBUG_ENTER("spider_fields::choose_a_conn");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
for (current_conn_holder = first_conn_holder; current_conn_holder;
|
|
current_conn_holder = current_conn_holder->next)
|
|
{
|
|
balance_total += current_conn_holder->access_balance;
|
|
}
|
|
|
|
rand_val = spider_rand(thd->variables.server_id + thd_get_thread_id(thd));
|
|
balance_val = (longlong) (rand_val * balance_total);
|
|
|
|
current_conn_holder = first_conn_holder;
|
|
while (current_conn_holder)
|
|
{
|
|
if (balance_val < current_conn_holder->access_balance)
|
|
break;
|
|
balance_val -= current_conn_holder->access_balance;
|
|
|
|
DBUG_PRINT("info",("spider remove connection %p",
|
|
current_conn_holder->conn));
|
|
first_conn_holder = current_conn_holder->next;
|
|
DBUG_ASSERT(current_conn_holder->next);
|
|
first_conn_holder->prev = NULL;
|
|
free_conn_holder(current_conn_holder);
|
|
current_conn_holder = first_conn_holder;
|
|
}
|
|
|
|
DBUG_PRINT("info",("spider chosen connection is %p",
|
|
current_conn_holder->conn));
|
|
last_conn_holder = current_conn_holder;
|
|
current_conn_holder = current_conn_holder->next;
|
|
last_conn_holder->next = NULL;
|
|
|
|
while (current_conn_holder)
|
|
{
|
|
DBUG_PRINT("info",("spider remove connection %p",
|
|
current_conn_holder->conn));
|
|
conn_holder = current_conn_holder->next;
|
|
free_conn_holder(current_conn_holder);
|
|
current_conn_holder = conn_holder;
|
|
}
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
void spider_fields::free_conn_holder(
|
|
SPIDER_CONN_HOLDER *conn_holder_arg
|
|
) {
|
|
uint roop_count;
|
|
DBUG_ENTER("spider_fields::free_conn_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
for (roop_count = 0; roop_count < table_count; ++roop_count)
|
|
{
|
|
if (conn_holder_arg->table_link_idx_holder[roop_count].first_link_idx_holder)
|
|
{
|
|
SPIDER_LINK_IDX_HOLDER *first_link_idx_holder, *current_link_idx_holder;
|
|
first_link_idx_holder =
|
|
conn_holder_arg->table_link_idx_holder[roop_count].first_link_idx_holder;
|
|
while ((current_link_idx_holder = first_link_idx_holder))
|
|
{
|
|
first_link_idx_holder = current_link_idx_holder->next;
|
|
spider_free(spider_current_trx, current_link_idx_holder, MYF(0));
|
|
}
|
|
}
|
|
}
|
|
conn_holder_arg->conn->conn_holder_for_direct_join = NULL;
|
|
DBUG_PRINT("info",("spider free conn_holder=%p", conn_holder_arg));
|
|
spider_free(spider_current_trx, conn_holder_arg, MYF(0));
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
SPIDER_TABLE_HOLDER *spider_fields::add_table(
|
|
ha_spider *spider_arg
|
|
) {
|
|
spider_string *str;
|
|
uint length;
|
|
char tmp_buf[SPIDER_SQL_INT_LEN + 2];
|
|
SPIDER_TABLE_HOLDER *return_table_holder;
|
|
SPIDER_FIELD_HOLDER *field_holder;
|
|
TABLE *table = spider_arg->get_table();
|
|
Field *field;
|
|
DBUG_ENTER("spider_fields::add_table");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
DBUG_PRINT("info",("spider table_count=%u", table_count));
|
|
DBUG_PRINT("info",("spider idx_for_direct_join=%u",
|
|
spider_arg->idx_for_direct_join));
|
|
length = my_sprintf(tmp_buf, (tmp_buf, "t%u",
|
|
spider_arg->idx_for_direct_join));
|
|
str = &spider_arg->result_list.tmp_sqls[0];
|
|
str->length(0);
|
|
if (str->reserve(length + SPIDER_SQL_DOT_LEN))
|
|
{
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
str->q_append(tmp_buf, length);
|
|
str->q_append(SPIDER_SQL_DOT_STR, SPIDER_SQL_DOT_LEN);
|
|
|
|
return_table_holder = &table_holder[spider_arg->idx_for_direct_join];
|
|
return_table_holder->table = spider_arg->get_table();
|
|
return_table_holder->spider = spider_arg;
|
|
return_table_holder->alias = str;
|
|
|
|
set_pos_to_first_field_holder();
|
|
while ((field_holder = get_next_field_holder()))
|
|
{
|
|
if (!field_holder->spider)
|
|
{
|
|
field = field_holder->field;
|
|
if (
|
|
field->field_index < table->s->fields &&
|
|
field == table->field[field->field_index]
|
|
) {
|
|
field_holder->spider = spider_arg;
|
|
field_holder->alias = str;
|
|
}
|
|
}
|
|
}
|
|
DBUG_RETURN(return_table_holder);
|
|
}
|
|
|
|
/**
|
|
Verify that all fields in the query are members of tables that are in the
|
|
query.
|
|
|
|
@return TRUE All fields in the query are members of tables
|
|
that are in the query.
|
|
FALSE At least one field in the query is not a
|
|
member of a table that is in the query.
|
|
*/
|
|
|
|
bool spider_fields::all_query_fields_are_query_table_members()
|
|
{
|
|
SPIDER_FIELD_HOLDER *field_holder;
|
|
DBUG_ENTER("spider_fields::all_query_fields_are_query_table_members");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
|
|
set_pos_to_first_field_holder();
|
|
while ((field_holder = get_next_field_holder()))
|
|
{
|
|
if (!field_holder->spider)
|
|
{
|
|
DBUG_PRINT("info", ("spider field is not a member of a query table"));
|
|
DBUG_RETURN(FALSE);
|
|
}
|
|
}
|
|
|
|
DBUG_RETURN(TRUE);
|
|
}
|
|
|
|
int spider_fields::create_table_holder(
|
|
uint table_count_arg
|
|
) {
|
|
DBUG_ENTER("spider_fields::create_table_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
DBUG_ASSERT(!table_holder);
|
|
table_holder = (SPIDER_TABLE_HOLDER *)
|
|
spider_malloc(spider_current_trx, 249,
|
|
table_count_arg * sizeof(SPIDER_TABLE_HOLDER),
|
|
MYF(MY_WME | MY_ZEROFILL));
|
|
if (!table_holder)
|
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
|
table_count = table_count_arg;
|
|
current_table_num = 0;
|
|
DBUG_RETURN(0);
|
|
}
|
|
|
|
void spider_fields::set_pos_to_first_table_holder(
|
|
) {
|
|
DBUG_ENTER("spider_fields::set_pos_to_first_table_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
current_table_num = 0;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
SPIDER_TABLE_HOLDER *spider_fields::get_next_table_holder(
|
|
) {
|
|
SPIDER_TABLE_HOLDER *return_table_holder;
|
|
DBUG_ENTER("spider_fields::get_next_table_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
if (current_table_num >= table_count)
|
|
DBUG_RETURN(NULL);
|
|
return_table_holder = &table_holder[current_table_num];
|
|
++current_table_num;
|
|
DBUG_RETURN(return_table_holder);
|
|
}
|
|
|
|
SPIDER_TABLE_HOLDER *spider_fields::get_table_holder(TABLE *table)
|
|
{
|
|
uint table_num;
|
|
DBUG_ENTER("spider_fields::get_table_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
for (table_num = 0; table_num < table_count; ++table_num)
|
|
{
|
|
if (table_holder[table_num].table == table)
|
|
DBUG_RETURN(&table_holder[table_num]);
|
|
}
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
|
|
uint spider_fields::get_table_count()
|
|
{
|
|
DBUG_ENTER("spider_fields::get_table_count");
|
|
DBUG_RETURN(table_count);
|
|
}
|
|
|
|
int spider_fields::add_field(
|
|
Field *field_arg
|
|
) {
|
|
SPIDER_FIELD_HOLDER *field_holder;
|
|
SPIDER_FIELD_CHAIN *field_chain;
|
|
DBUG_ENTER("spider_fields::add_field");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
DBUG_PRINT("info",("spider field=%p", field_arg));
|
|
if (!first_field_holder)
|
|
{
|
|
field_holder = create_field_holder();
|
|
DBUG_PRINT("info",("spider field_holder=%p", field_holder));
|
|
if (!field_holder)
|
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
|
field_holder->field = field_arg;
|
|
first_field_holder = field_holder;
|
|
last_field_holder = field_holder;
|
|
} else {
|
|
field_holder = first_field_holder;
|
|
do {
|
|
if (field_holder->field == field_arg)
|
|
break;
|
|
} while ((field_holder = field_holder->next));
|
|
if (!field_holder)
|
|
{
|
|
field_holder = create_field_holder();
|
|
DBUG_PRINT("info",("spider field_holder=%p", field_holder));
|
|
if (!field_holder)
|
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
|
field_holder->field = field_arg;
|
|
last_field_holder->next = field_holder;
|
|
last_field_holder = field_holder;
|
|
}
|
|
}
|
|
field_chain = create_field_chain();
|
|
DBUG_PRINT("info",("spider field_chain=%p", field_chain));
|
|
if (!field_chain)
|
|
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
|
field_chain->field_holder = field_holder;
|
|
if (!first_field_chain)
|
|
{
|
|
first_field_chain = field_chain;
|
|
last_field_chain = field_chain;
|
|
} else {
|
|
last_field_chain->next = field_chain;
|
|
last_field_chain = field_chain;
|
|
}
|
|
DBUG_RETURN(0);
|
|
}
|
|
|
|
SPIDER_FIELD_HOLDER *spider_fields::create_field_holder(
|
|
) {
|
|
DBUG_ENTER("spider_fields::create_field_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
DBUG_RETURN((SPIDER_FIELD_HOLDER *)
|
|
spider_malloc(spider_current_trx, 250, sizeof(SPIDER_FIELD_HOLDER),
|
|
MYF(MY_WME | MY_ZEROFILL)));
|
|
}
|
|
|
|
void spider_fields::set_pos_to_first_field_holder(
|
|
) {
|
|
DBUG_ENTER("spider_fields::set_pos_to_first_field_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
current_field_holder = first_field_holder;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
SPIDER_FIELD_HOLDER *spider_fields::get_next_field_holder(
|
|
) {
|
|
SPIDER_FIELD_HOLDER *return_field_holder = current_field_holder;
|
|
DBUG_ENTER("spider_fields::get_next_field_holder");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
if (current_field_holder)
|
|
current_field_holder = current_field_holder->next;
|
|
DBUG_RETURN(return_field_holder);
|
|
}
|
|
|
|
SPIDER_FIELD_CHAIN *spider_fields::create_field_chain(
|
|
) {
|
|
DBUG_ENTER("spider_fields::create_field_chain");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
DBUG_RETURN((SPIDER_FIELD_CHAIN *)
|
|
spider_malloc(spider_current_trx, 251, sizeof(SPIDER_FIELD_CHAIN),
|
|
MYF(MY_WME | MY_ZEROFILL)));
|
|
}
|
|
|
|
void spider_fields::set_pos_to_first_field_chain(
|
|
) {
|
|
DBUG_ENTER("spider_fields::set_pos_to_first_field_chain");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
current_field_chain = first_field_chain;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
SPIDER_FIELD_CHAIN *spider_fields::get_next_field_chain(
|
|
) {
|
|
SPIDER_FIELD_CHAIN *return_field_chain = current_field_chain;
|
|
DBUG_ENTER("spider_fields::get_next_field_chain");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
if (current_field_chain)
|
|
current_field_chain = current_field_chain->next;
|
|
DBUG_RETURN(return_field_chain);
|
|
}
|
|
|
|
void spider_fields::set_field_ptr(
|
|
Field **field_arg
|
|
) {
|
|
DBUG_ENTER("spider_fields::set_field_ptr");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
DBUG_PRINT("info",("spider field_ptr=%p", field_arg));
|
|
first_field_ptr = field_arg;
|
|
current_field_ptr = field_arg;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
Field **spider_fields::get_next_field_ptr(
|
|
) {
|
|
Field **return_field_ptr = current_field_ptr;
|
|
DBUG_ENTER("spider_fields::get_next_field_ptr");
|
|
DBUG_PRINT("info",("spider this=%p", this));
|
|
if (*current_field_ptr)
|
|
current_field_ptr++;
|
|
DBUG_PRINT("info",("spider field_ptr=%p", return_field_ptr));
|
|
DBUG_RETURN(return_field_ptr);
|
|
}
|
|
|
|
int spider_fields::ping_table_mon_from_table(
|
|
SPIDER_LINK_IDX_CHAIN *link_idx_chain
|
|
) {
|
|
int error_num = 0, error_num_buf;
|
|
ha_spider *tmp_spider;
|
|
SPIDER_SHARE *tmp_share;
|
|
int tmp_link_idx;
|
|
SPIDER_TABLE_HOLDER *table_holder;
|
|
SPIDER_LINK_IDX_HOLDER *link_idx_holder;
|
|
DBUG_ENTER("spider_fields::ping_table_mon_from_table");
|
|
set_pos_to_first_table_on_link_idx_chain(link_idx_chain);
|
|
set_pos_to_first_table_holder();
|
|
while ((table_holder = get_next_table_holder()))
|
|
{
|
|
link_idx_holder = get_next_table_on_link_idx_chain(link_idx_chain);
|
|
tmp_spider = table_holder->spider;
|
|
tmp_link_idx = link_idx_holder->link_idx;
|
|
tmp_share = tmp_spider->share;
|
|
if (tmp_share->monitoring_kind[tmp_link_idx])
|
|
{
|
|
error_num_buf = spider_ping_table_mon_from_table(
|
|
tmp_spider->wide_handler->trx,
|
|
tmp_spider->wide_handler->trx->thd,
|
|
tmp_share,
|
|
tmp_link_idx,
|
|
(uint32) tmp_share->monitoring_sid[tmp_link_idx],
|
|
tmp_share->table_name,
|
|
tmp_share->table_name_length,
|
|
tmp_spider->conn_link_idx[tmp_link_idx],
|
|
NULL,
|
|
0,
|
|
tmp_share->monitoring_kind[tmp_link_idx],
|
|
tmp_share->monitoring_limit[tmp_link_idx],
|
|
tmp_share->monitoring_flag[tmp_link_idx],
|
|
TRUE
|
|
);
|
|
if (!error_num)
|
|
error_num = error_num_buf;
|
|
}
|
|
}
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
|
|
#ifdef SPIDER_HAS_GROUP_BY_HANDLER
|
|
spider_group_by_handler::spider_group_by_handler(
|
|
THD *thd_arg,
|
|
Query *query_arg,
|
|
spider_fields *fields_arg
|
|
) : group_by_handler(thd_arg, spider_hton_ptr),
|
|
query(*query_arg), fields(fields_arg)
|
|
{
|
|
DBUG_ENTER("spider_group_by_handler::spider_group_by_handler");
|
|
fields->set_pos_to_first_table_holder();
|
|
SPIDER_TABLE_HOLDER *table_holder = fields->get_next_table_holder();
|
|
spider = table_holder->spider;
|
|
trx = spider->wide_handler->trx;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
spider_group_by_handler::~spider_group_by_handler()
|
|
{
|
|
DBUG_ENTER("spider_group_by_handler::~spider_group_by_handler");
|
|
delete fields;
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
int spider_group_by_handler::init_scan()
|
|
{
|
|
int error_num, link_idx;
|
|
uint dbton_id;
|
|
spider_db_handler *dbton_hdl;
|
|
st_select_lex *select_lex;
|
|
longlong select_limit;
|
|
longlong direct_order_limit;
|
|
SPIDER_SHARE *share = spider->share;
|
|
SPIDER_CONN *conn;
|
|
SPIDER_RESULT_LIST *result_list = &spider->result_list;
|
|
SPIDER_LINK_IDX_CHAIN *link_idx_chain;
|
|
SPIDER_LINK_IDX_HOLDER *link_idx_holder;
|
|
DBUG_ENTER("spider_group_by_handler::init_scan");
|
|
store_error = 0;
|
|
#ifndef DBUG_OFF
|
|
Field **field;
|
|
for (
|
|
field = table->field;
|
|
*field;
|
|
field++
|
|
) {
|
|
DBUG_PRINT("info",("spider field_name=%s",
|
|
SPIDER_field_name_str(*field)));
|
|
}
|
|
#endif
|
|
|
|
if (trx->thd->killed)
|
|
{
|
|
my_error(ER_QUERY_INTERRUPTED, MYF(0));
|
|
DBUG_RETURN(ER_QUERY_INTERRUPTED);
|
|
}
|
|
|
|
spider->use_fields = TRUE;
|
|
spider->fields = fields;
|
|
|
|
spider->check_pre_call(TRUE);
|
|
|
|
spider->pushed_pos = NULL;
|
|
result_list->sorted = (query.group_by || query.order_by);
|
|
spider_set_result_list_param(spider);
|
|
spider->mrr_with_cnt = FALSE;
|
|
spider->init_index_handler = FALSE;
|
|
spider->use_spatial_index = FALSE;
|
|
result_list->check_direct_order_limit = FALSE;
|
|
/* Disable direct aggregate when GBH is on (MDEV-29502). */
|
|
result_list->direct_aggregate = FALSE;
|
|
spider->select_column_mode = 0;
|
|
spider->search_link_idx = fields->get_ok_link_idx();
|
|
spider->result_link_idx = spider->search_link_idx;
|
|
|
|
spider_db_free_one_result_for_start_next(spider);
|
|
|
|
spider->sql_kinds = SPIDER_SQL_KIND_SQL;
|
|
for (link_idx = 0; link_idx < (int) share->link_count; ++link_idx)
|
|
spider->sql_kind[link_idx] = SPIDER_SQL_KIND_SQL;
|
|
|
|
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS
|
|
spider->do_direct_update = FALSE;
|
|
spider->direct_update_kinds = 0;
|
|
#endif
|
|
spider_get_select_limit(spider, &select_lex, &select_limit, &offset_limit);
|
|
direct_order_limit = spider_param_direct_order_limit(thd,
|
|
share->direct_order_limit);
|
|
if (
|
|
direct_order_limit &&
|
|
select_lex->explicit_limit &&
|
|
!(select_lex->options & OPTION_FOUND_ROWS) &&
|
|
select_limit < direct_order_limit /* - offset_limit */
|
|
) {
|
|
result_list->internal_limit = select_limit /* + offset_limit */;
|
|
result_list->split_read = select_limit /* + offset_limit */;
|
|
#ifndef WITHOUT_SPIDER_BG_SEARCH
|
|
result_list->bgs_split_read = select_limit /* + offset_limit */;
|
|
#endif
|
|
|
|
result_list->split_read_base = 9223372036854775807LL;
|
|
result_list->semi_split_read = 0;
|
|
result_list->semi_split_read_limit = 9223372036854775807LL;
|
|
result_list->first_read = 9223372036854775807LL;
|
|
result_list->second_read = 9223372036854775807LL;
|
|
trx->direct_order_limit_count++;
|
|
}
|
|
result_list->semi_split_read_base = 0;
|
|
result_list->set_split_read = TRUE;
|
|
#ifndef WITHOUT_SPIDER_BG_SEARCH
|
|
if ((error_num = spider_set_conn_bg_param(spider)))
|
|
DBUG_RETURN(error_num);
|
|
#endif
|
|
DBUG_PRINT("info",("spider result_list.finish_flg = FALSE"));
|
|
result_list->finish_flg = FALSE;
|
|
result_list->record_num = 0;
|
|
result_list->keyread = FALSE;
|
|
result_list->desc_flg = FALSE;
|
|
result_list->sorted = FALSE;
|
|
result_list->key_info = NULL;
|
|
result_list->key_order = 0;
|
|
result_list->limit_num =
|
|
result_list->internal_limit >= result_list->split_read ?
|
|
result_list->split_read : result_list->internal_limit;
|
|
|
|
if (select_lex->explicit_limit)
|
|
{
|
|
result_list->internal_offset += offset_limit;
|
|
} else {
|
|
offset_limit = 0;
|
|
}
|
|
|
|
/* making a query */
|
|
fields->set_pos_to_first_dbton_id();
|
|
while ((dbton_id = fields->get_next_dbton_id()) < SPIDER_DBTON_SIZE)
|
|
{
|
|
dbton_hdl = spider->dbton_handler[dbton_id];
|
|
result_list->direct_distinct = query.distinct;
|
|
fields->set_pos_to_first_field_chain();
|
|
if ((error_num = dbton_hdl->reset_sql(SPIDER_SQL_TYPE_SELECT_SQL)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
if ((error_num = dbton_hdl->append_select_part(SPIDER_SQL_TYPE_SELECT_SQL)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
fields->set_field_ptr(table->field);
|
|
if ((error_num = dbton_hdl->append_list_item_select_part(
|
|
query.select, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
if ((error_num = dbton_hdl->append_from_and_tables_part(
|
|
fields, SPIDER_SQL_TYPE_SELECT_SQL)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
if (query.where)
|
|
{
|
|
if ((error_num =
|
|
dbton_hdl->append_where_part(SPIDER_SQL_TYPE_SELECT_SQL)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
if ((error_num = dbton_hdl->append_item_type_part(
|
|
query.where, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
}
|
|
if (query.group_by)
|
|
{
|
|
if ((error_num = dbton_hdl->append_group_by_part(
|
|
query.group_by, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
}
|
|
if (query.having)
|
|
{
|
|
if ((error_num =
|
|
dbton_hdl->append_having_part(SPIDER_SQL_TYPE_SELECT_SQL)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
if ((error_num = dbton_hdl->append_item_type_part(
|
|
query.having, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
}
|
|
if (query.order_by)
|
|
{
|
|
if ((error_num = dbton_hdl->append_order_by_part(
|
|
query.order_by, NULL, 0, TRUE, fields, SPIDER_SQL_TYPE_SELECT_SQL)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
}
|
|
if ((error_num = dbton_hdl->append_limit_part(result_list->internal_offset,
|
|
result_list->limit_num, SPIDER_SQL_TYPE_SELECT_SQL)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
if ((error_num = dbton_hdl->append_select_lock_part(
|
|
SPIDER_SQL_TYPE_SELECT_SQL)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
}
|
|
|
|
fields->set_pos_to_first_link_idx_chain();
|
|
while ((link_idx_chain = fields->get_next_link_idx_chain()))
|
|
{
|
|
conn = link_idx_chain->conn;
|
|
link_idx_holder = link_idx_chain->link_idx_holder;
|
|
link_idx = link_idx_holder->link_idx;
|
|
dbton_hdl = spider->dbton_handler[conn->dbton_id];
|
|
spider->link_idx_chain = link_idx_chain;
|
|
#ifndef WITHOUT_SPIDER_BG_SEARCH
|
|
if (result_list->bgs_phase > 0)
|
|
{
|
|
if ((error_num = spider_check_and_init_casual_read(trx->thd, spider,
|
|
link_idx)))
|
|
DBUG_RETURN(error_num);
|
|
if ((error_num = spider_bg_conn_search(spider, link_idx,
|
|
dbton_hdl->first_link_idx, TRUE, FALSE,
|
|
!fields->is_first_link_ok_chain(link_idx_chain))))
|
|
{
|
|
if (
|
|
error_num != HA_ERR_END_OF_FILE &&
|
|
spider->need_mons[link_idx]
|
|
) {
|
|
error_num = fields->ping_table_mon_from_table(link_idx_chain);
|
|
}
|
|
if ((error_num = spider->check_error_mode_eof(error_num)) == HA_ERR_END_OF_FILE)
|
|
{
|
|
store_error = HA_ERR_END_OF_FILE;
|
|
error_num = 0;
|
|
}
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
} else {
|
|
#endif
|
|
pthread_mutex_assert_not_owner(&conn->mta_conn_mutex);
|
|
if ((error_num =
|
|
dbton_hdl->set_sql_for_exec(SPIDER_SQL_TYPE_SELECT_SQL, link_idx,
|
|
link_idx_chain)))
|
|
{
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
pthread_mutex_lock(&conn->mta_conn_mutex);
|
|
SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos);
|
|
conn->need_mon = &spider->need_mons[link_idx];
|
|
DBUG_ASSERT(!conn->mta_conn_mutex_lock_already);
|
|
DBUG_ASSERT(!conn->mta_conn_mutex_unlock_later);
|
|
conn->mta_conn_mutex_lock_already = TRUE;
|
|
conn->mta_conn_mutex_unlock_later = TRUE;
|
|
if ((error_num = spider_db_set_names(spider, conn,
|
|
link_idx)))
|
|
{
|
|
DBUG_ASSERT(conn->mta_conn_mutex_lock_already);
|
|
DBUG_ASSERT(conn->mta_conn_mutex_unlock_later);
|
|
conn->mta_conn_mutex_lock_already = FALSE;
|
|
conn->mta_conn_mutex_unlock_later = FALSE;
|
|
SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos);
|
|
pthread_mutex_unlock(&conn->mta_conn_mutex);
|
|
if (
|
|
spider->need_mons[link_idx]
|
|
) {
|
|
error_num = fields->ping_table_mon_from_table(link_idx_chain);
|
|
}
|
|
if ((error_num = spider->check_error_mode_eof(error_num)) == HA_ERR_END_OF_FILE)
|
|
{
|
|
store_error = HA_ERR_END_OF_FILE;
|
|
error_num = 0;
|
|
}
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
spider_conn_set_timeout_from_share(conn, link_idx,
|
|
trx->thd, share);
|
|
if (dbton_hdl->execute_sql(
|
|
SPIDER_SQL_TYPE_SELECT_SQL,
|
|
conn,
|
|
spider->result_list.quick_mode,
|
|
&spider->need_mons[link_idx])
|
|
) {
|
|
DBUG_ASSERT(conn->mta_conn_mutex_lock_already);
|
|
DBUG_ASSERT(conn->mta_conn_mutex_unlock_later);
|
|
conn->mta_conn_mutex_lock_already = FALSE;
|
|
conn->mta_conn_mutex_unlock_later = FALSE;
|
|
error_num = spider_db_errorno(conn);
|
|
if (
|
|
spider->need_mons[link_idx]
|
|
) {
|
|
error_num = fields->ping_table_mon_from_table(link_idx_chain);
|
|
}
|
|
if ((error_num = spider->check_error_mode_eof(error_num)) == HA_ERR_END_OF_FILE)
|
|
{
|
|
store_error = HA_ERR_END_OF_FILE;
|
|
error_num = 0;
|
|
}
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
spider->connection_ids[link_idx] = conn->connection_id;
|
|
DBUG_ASSERT(conn->mta_conn_mutex_lock_already);
|
|
DBUG_ASSERT(conn->mta_conn_mutex_unlock_later);
|
|
conn->mta_conn_mutex_lock_already = FALSE;
|
|
conn->mta_conn_mutex_unlock_later = FALSE;
|
|
if (fields->is_first_link_ok_chain(link_idx_chain))
|
|
{
|
|
if ((error_num = spider_db_store_result(spider, link_idx, table)))
|
|
{
|
|
if (
|
|
error_num != HA_ERR_END_OF_FILE &&
|
|
spider->need_mons[link_idx]
|
|
) {
|
|
error_num = fields->ping_table_mon_from_table(link_idx_chain);
|
|
}
|
|
if ((error_num = spider->check_error_mode_eof(error_num)) == HA_ERR_END_OF_FILE)
|
|
{
|
|
store_error = HA_ERR_END_OF_FILE;
|
|
error_num = 0;
|
|
}
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
spider->result_link_idx = link_idx;
|
|
spider->result_link_idx_chain = link_idx_chain;
|
|
} else {
|
|
spider_db_discard_result(spider, link_idx, conn);
|
|
SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos);
|
|
pthread_mutex_unlock(&conn->mta_conn_mutex);
|
|
}
|
|
#ifndef WITHOUT_SPIDER_BG_SEARCH
|
|
}
|
|
#endif
|
|
}
|
|
|
|
first = TRUE;
|
|
DBUG_RETURN(0);
|
|
}
|
|
|
|
int spider_group_by_handler::next_row()
|
|
{
|
|
int error_num, link_idx;
|
|
spider_db_handler *dbton_hdl;
|
|
SPIDER_CONN *conn;
|
|
SPIDER_LINK_IDX_CHAIN *link_idx_chain;
|
|
SPIDER_LINK_IDX_HOLDER *link_idx_holder;
|
|
DBUG_ENTER("spider_group_by_handler::next_row");
|
|
if (trx->thd->killed)
|
|
{
|
|
my_error(ER_QUERY_INTERRUPTED, MYF(0));
|
|
DBUG_RETURN(ER_QUERY_INTERRUPTED);
|
|
}
|
|
if (store_error)
|
|
{
|
|
if (store_error == HA_ERR_END_OF_FILE)
|
|
{
|
|
table->status = STATUS_NOT_FOUND;
|
|
}
|
|
DBUG_RETURN(store_error);
|
|
}
|
|
if (first)
|
|
{
|
|
first = FALSE;
|
|
if (spider->use_pre_call)
|
|
{
|
|
if (spider->store_error_num)
|
|
{
|
|
if (spider->store_error_num == HA_ERR_END_OF_FILE)
|
|
table->status = STATUS_NOT_FOUND;
|
|
DBUG_RETURN(spider->store_error_num);
|
|
}
|
|
#ifndef WITHOUT_SPIDER_BG_SEARCH
|
|
if (spider->result_list.bgs_phase > 0)
|
|
{
|
|
fields->set_pos_to_first_link_idx_chain();
|
|
while ((link_idx_chain = fields->get_next_link_idx_chain()))
|
|
{
|
|
conn = link_idx_chain->conn;
|
|
link_idx_holder = link_idx_chain->link_idx_holder;
|
|
link_idx = link_idx_holder->link_idx;
|
|
dbton_hdl = spider->dbton_handler[conn->dbton_id];
|
|
spider->link_idx_chain = link_idx_chain;
|
|
if ((error_num = spider_bg_conn_search(spider, link_idx,
|
|
dbton_hdl->first_link_idx, TRUE, TRUE,
|
|
!fields->is_first_link_ok_chain(link_idx_chain))))
|
|
{
|
|
if (
|
|
error_num != HA_ERR_END_OF_FILE &&
|
|
spider->need_mons[link_idx]
|
|
) {
|
|
error_num = fields->ping_table_mon_from_table(link_idx_chain);
|
|
}
|
|
if ((error_num = spider->check_error_mode_eof(error_num)) == HA_ERR_END_OF_FILE)
|
|
{
|
|
table->status = STATUS_NOT_FOUND;
|
|
}
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
spider->use_pre_call = FALSE;
|
|
}
|
|
} else if (offset_limit)
|
|
{
|
|
--offset_limit;
|
|
DBUG_RETURN(0);
|
|
}
|
|
if ((error_num = spider_db_seek_next(table->record[0], spider,
|
|
spider->search_link_idx, table)))
|
|
{
|
|
if ((error_num = spider->check_error_mode_eof(error_num)) == HA_ERR_END_OF_FILE)
|
|
{
|
|
table->status = STATUS_NOT_FOUND;
|
|
}
|
|
DBUG_RETURN(error_num);
|
|
}
|
|
DBUG_RETURN(0);
|
|
}
|
|
|
|
int spider_group_by_handler::end_scan()
|
|
{
|
|
DBUG_ENTER("spider_group_by_handler::end_scan");
|
|
DBUG_RETURN(0);
|
|
}
|
|
|
|
group_by_handler *spider_create_group_by_handler(
|
|
THD *thd,
|
|
Query *query
|
|
) {
|
|
spider_group_by_handler *group_by_handler;
|
|
Item *item;
|
|
TABLE_LIST *from;
|
|
SPIDER_CONN *conn;
|
|
ha_spider *spider;
|
|
SPIDER_SHARE *share;
|
|
int roop_count, lock_mode;
|
|
List_iterator_fast<Item> it(*query->select);
|
|
uchar dbton_bitmap[spider_bitmap_size(SPIDER_DBTON_SIZE)];
|
|
uchar dbton_bitmap_tmp[spider_bitmap_size(SPIDER_DBTON_SIZE)];
|
|
ORDER *order;
|
|
bool keep_going;
|
|
bool find_dbton = FALSE;
|
|
spider_fields *fields = NULL, *fields_arg = NULL;
|
|
uint table_idx, dbton_id;
|
|
long tgt_link_status;
|
|
DBUG_ENTER("spider_create_group_by_handler");
|
|
|
|
switch (thd_sql_command(thd))
|
|
{
|
|
case SQLCOM_UPDATE:
|
|
case SQLCOM_UPDATE_MULTI:
|
|
case SQLCOM_DELETE:
|
|
case SQLCOM_DELETE_MULTI:
|
|
DBUG_PRINT("info",("spider update and delete does not support this feature"));
|
|
DBUG_RETURN(NULL);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
|
from = query->from;
|
|
do {
|
|
DBUG_PRINT("info",("spider from=%p", from));
|
|
if (from->table->const_table)
|
|
continue;
|
|
if (from->table->part_info)
|
|
{
|
|
DBUG_PRINT("info",("spider partition handler"));
|
|
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
|
|
partition_info *part_info = from->table->part_info;
|
|
uint bits = bitmap_bits_set(&part_info->read_partitions);
|
|
DBUG_PRINT("info",("spider bits=%u", bits));
|
|
if (bits != 1)
|
|
{
|
|
DBUG_PRINT("info",("spider using multiple partitions is not supported by this feature yet"));
|
|
#else
|
|
DBUG_PRINT("info",("spider partition is not supported by this feature yet"));
|
|
#endif
|
|
DBUG_RETURN(NULL);
|
|
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
|
|
}
|
|
#endif
|
|
}
|
|
} while ((from = from->next_local));
|
|
#endif
|
|
|
|
table_idx = 0;
|
|
from = query->from;
|
|
while (from && from->table->const_table)
|
|
{
|
|
from = from->next_local;
|
|
}
|
|
if (!from)
|
|
{
|
|
/* all tables are const_table */
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
|
|
if (from->table->part_info)
|
|
{
|
|
partition_info *part_info = from->table->part_info;
|
|
uint part = bitmap_get_first_set(&part_info->read_partitions);
|
|
ha_partition *partition = (ha_partition *) from->table->file;
|
|
handler **handlers = partition->get_child_handlers();
|
|
spider = (ha_spider *) handlers[part];
|
|
} else {
|
|
#endif
|
|
spider = (ha_spider *) from->table->file;
|
|
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
|
|
}
|
|
#endif
|
|
share = spider->share;
|
|
spider->idx_for_direct_join = table_idx;
|
|
++table_idx;
|
|
memset(dbton_bitmap, 0, spider_bitmap_size(SPIDER_DBTON_SIZE));
|
|
for (roop_count = 0; roop_count < (int) share->use_dbton_count; ++roop_count)
|
|
{
|
|
dbton_id = share->use_sql_dbton_ids[roop_count];
|
|
if (
|
|
spider_dbton[dbton_id].support_direct_join &&
|
|
spider_dbton[dbton_id].support_direct_join()
|
|
) {
|
|
spider_set_bit(dbton_bitmap, dbton_id);
|
|
}
|
|
}
|
|
while ((from = from->next_local))
|
|
{
|
|
if (from->table->const_table)
|
|
continue;
|
|
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
|
|
if (from->table->part_info)
|
|
{
|
|
partition_info *part_info = from->table->part_info;
|
|
uint part = bitmap_get_first_set(&part_info->read_partitions);
|
|
ha_partition *partition = (ha_partition *) from->table->file;
|
|
handler **handlers = partition->get_child_handlers();
|
|
spider = (ha_spider *) handlers[part];
|
|
} else {
|
|
#endif
|
|
spider = (ha_spider *) from->table->file;
|
|
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
|
|
}
|
|
#endif
|
|
share = spider->share;
|
|
spider->idx_for_direct_join = table_idx;
|
|
++table_idx;
|
|
memset(dbton_bitmap_tmp, 0, spider_bitmap_size(SPIDER_DBTON_SIZE));
|
|
for (roop_count = 0; roop_count < (int) share->use_dbton_count; ++roop_count)
|
|
{
|
|
dbton_id = share->use_sql_dbton_ids[roop_count];
|
|
if (
|
|
spider_dbton[dbton_id].support_direct_join &&
|
|
spider_dbton[dbton_id].support_direct_join()
|
|
) {
|
|
spider_set_bit(dbton_bitmap_tmp, dbton_id);
|
|
}
|
|
}
|
|
for (roop_count = 0;
|
|
roop_count < spider_bitmap_size(SPIDER_DBTON_SIZE); ++roop_count)
|
|
{
|
|
dbton_bitmap[roop_count] &= dbton_bitmap_tmp[roop_count];
|
|
}
|
|
}
|
|
|
|
from = query->from;
|
|
do {
|
|
if (from->table->const_table)
|
|
continue;
|
|
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
|
|
if (from->table->part_info)
|
|
{
|
|
partition_info *part_info = from->table->part_info;
|
|
uint part = bitmap_get_first_set(&part_info->read_partitions);
|
|
ha_partition *partition = (ha_partition *) from->table->file;
|
|
handler **handlers = partition->get_child_handlers();
|
|
spider = (ha_spider *) handlers[part];
|
|
} else {
|
|
#endif
|
|
spider = (ha_spider *) from->table->file;
|
|
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
|
|
}
|
|
#endif
|
|
share = spider->share;
|
|
if (spider_param_skip_default_condition(thd,
|
|
share->skip_default_condition))
|
|
{
|
|
/* find skip_default_condition = 1 */
|
|
break;
|
|
}
|
|
} while ((from = from->next_local));
|
|
|
|
for (roop_count = 0; roop_count < SPIDER_DBTON_SIZE; ++roop_count)
|
|
{
|
|
if (spider_bit_is_set(dbton_bitmap, roop_count))
|
|
{
|
|
if (!fields)
|
|
{
|
|
fields_arg = new spider_fields();
|
|
if (!fields_arg)
|
|
{
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
}
|
|
keep_going = TRUE;
|
|
it.init(*query->select);
|
|
while ((item = it++))
|
|
{
|
|
DBUG_PRINT("info",("spider select item=%p", item));
|
|
if (item->const_item())
|
|
{
|
|
DBUG_PRINT("info",("spider const item"));
|
|
continue;
|
|
}
|
|
if (spider_db_print_item_type(item, NULL, spider, NULL, NULL, 0,
|
|
roop_count, TRUE, fields_arg))
|
|
{
|
|
DBUG_PRINT("info",("spider dbton_id=%d can't create select", roop_count));
|
|
spider_clear_bit(dbton_bitmap, roop_count);
|
|
keep_going = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (keep_going)
|
|
{
|
|
if (spider_dbton[roop_count].db_util->append_from_and_tables(
|
|
spider, fields_arg, NULL, query->from, table_idx))
|
|
{
|
|
DBUG_PRINT("info",("spider dbton_id=%d can't create from", roop_count));
|
|
spider_clear_bit(dbton_bitmap, roop_count);
|
|
keep_going = FALSE;
|
|
}
|
|
}
|
|
if (keep_going)
|
|
{
|
|
DBUG_PRINT("info",("spider query->where=%p", query->where));
|
|
if (query->where)
|
|
{
|
|
if (spider_db_print_item_type(query->where, NULL, spider, NULL, NULL, 0,
|
|
roop_count, TRUE, fields_arg))
|
|
{
|
|
DBUG_PRINT("info",("spider dbton_id=%d can't create where", roop_count));
|
|
spider_clear_bit(dbton_bitmap, roop_count);
|
|
keep_going = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if (keep_going)
|
|
{
|
|
DBUG_PRINT("info",("spider query->group_by=%p", query->group_by));
|
|
if (query->group_by)
|
|
{
|
|
for (order = query->group_by; order; order = order->next)
|
|
{
|
|
if (spider_db_print_item_type((*order->item), NULL, spider, NULL, NULL, 0,
|
|
roop_count, TRUE, fields_arg))
|
|
{
|
|
DBUG_PRINT("info",("spider dbton_id=%d can't create group by", roop_count));
|
|
spider_clear_bit(dbton_bitmap, roop_count);
|
|
keep_going = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (keep_going)
|
|
{
|
|
DBUG_PRINT("info",("spider query->order_by=%p", query->order_by));
|
|
if (query->order_by)
|
|
{
|
|
for (order = query->order_by; order; order = order->next)
|
|
{
|
|
if ((*order->item)->type() == Item::SUM_FUNC_ITEM)
|
|
continue;
|
|
if (spider_db_print_item_type((*order->item), NULL, spider, NULL, NULL, 0,
|
|
roop_count, TRUE, fields_arg))
|
|
{
|
|
DBUG_PRINT("info",("spider dbton_id=%d can't create order by", roop_count));
|
|
spider_clear_bit(dbton_bitmap, roop_count);
|
|
keep_going = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (keep_going)
|
|
{
|
|
DBUG_PRINT("info",("spider query->having=%p", query->having));
|
|
if (query->having)
|
|
{
|
|
if (spider_db_print_item_type(query->having, NULL, spider, NULL, NULL, 0,
|
|
roop_count, TRUE, fields_arg))
|
|
{
|
|
DBUG_PRINT("info",("spider dbton_id=%d can't create having", roop_count));
|
|
spider_clear_bit(dbton_bitmap, roop_count);
|
|
keep_going = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if (keep_going)
|
|
{
|
|
find_dbton = TRUE;
|
|
fields = fields_arg;
|
|
fields_arg = NULL;
|
|
} else {
|
|
delete fields_arg;
|
|
}
|
|
}
|
|
}
|
|
if (!find_dbton)
|
|
{
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
|
|
if (fields->create_table_holder(table_idx))
|
|
{
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
|
|
from = query->from;
|
|
while (from->table->const_table)
|
|
{
|
|
from = from->next_local;
|
|
}
|
|
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
|
|
if (from->table->part_info)
|
|
{
|
|
partition_info *part_info = from->table->part_info;
|
|
uint part = bitmap_get_first_set(&part_info->read_partitions);
|
|
ha_partition *partition = (ha_partition *) from->table->file;
|
|
handler **handlers = partition->get_child_handlers();
|
|
spider = (ha_spider *) handlers[part];
|
|
} else {
|
|
#endif
|
|
spider = (ha_spider *) from->table->file;
|
|
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
|
|
}
|
|
#endif
|
|
share = spider->share;
|
|
lock_mode = spider_conn_lock_mode(spider);
|
|
if (lock_mode)
|
|
{
|
|
tgt_link_status = SPIDER_LINK_STATUS_RECOVERY;
|
|
} else {
|
|
tgt_link_status = SPIDER_LINK_STATUS_OK;
|
|
}
|
|
DBUG_PRINT("info",("spider s->db=%s", from->table->s->db.str));
|
|
DBUG_PRINT("info",("spider s->table_name=%s", from->table->s->table_name.str));
|
|
if (!fields->add_table(spider))
|
|
{
|
|
DBUG_PRINT("info",("spider can not add a table"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
if (spider->dml_init())
|
|
{
|
|
DBUG_PRINT("info",("spider can not init for dml"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
for (
|
|
roop_count = spider_conn_link_idx_next(share->link_statuses,
|
|
spider->conn_link_idx, -1, share->link_count,
|
|
tgt_link_status);
|
|
roop_count < (int) share->link_count;
|
|
roop_count = spider_conn_link_idx_next(share->link_statuses,
|
|
spider->conn_link_idx, roop_count, share->link_count,
|
|
tgt_link_status)
|
|
) {
|
|
if (spider_param_use_handler(thd, share->use_handlers[roop_count]))
|
|
{
|
|
DBUG_PRINT("info",("spider direct_join does not support use_handler"));
|
|
if (lock_mode)
|
|
{
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
continue;
|
|
}
|
|
conn = spider->conns[roop_count];
|
|
DBUG_PRINT("info",("spider roop_count=%d", roop_count));
|
|
DBUG_PRINT("info",("spider conn=%p", conn));
|
|
DBUG_ASSERT(conn);
|
|
if (conn->table_lock)
|
|
{
|
|
DBUG_PRINT("info",("spider direct_join does not support with lock tables yet"));
|
|
if (lock_mode)
|
|
{
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
continue;
|
|
}
|
|
if (!fields->add_conn(conn,
|
|
share->access_balances[spider->conn_link_idx[roop_count]]))
|
|
{
|
|
DBUG_PRINT("info",("spider can not create conn_holder"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
if (fields->add_link_idx(conn->conn_holder_for_direct_join, spider, roop_count))
|
|
{
|
|
DBUG_PRINT("info",("spider can not create link_idx_holder"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
}
|
|
if (!fields->has_conn_holder())
|
|
{
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
|
|
while ((from = from->next_local))
|
|
{
|
|
if (from->table->const_table)
|
|
continue;
|
|
fields->clear_conn_holder_from_conn();
|
|
|
|
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
|
|
if (from->table->part_info)
|
|
{
|
|
partition_info *part_info = from->table->part_info;
|
|
uint part = bitmap_get_first_set(&part_info->read_partitions);
|
|
ha_partition *partition = (ha_partition *) from->table->file;
|
|
handler **handlers = partition->get_child_handlers();
|
|
spider = (ha_spider *) handlers[part];
|
|
} else {
|
|
#endif
|
|
spider = (ha_spider *) from->table->file;
|
|
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
|
|
}
|
|
#endif
|
|
share = spider->share;
|
|
if (!fields->add_table(spider))
|
|
{
|
|
DBUG_PRINT("info",("spider can not add a table"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
DBUG_PRINT("info",("spider s->db=%s", from->table->s->db.str));
|
|
DBUG_PRINT("info",("spider s->table_name=%s", from->table->s->table_name.str));
|
|
if (spider->dml_init())
|
|
{
|
|
DBUG_PRINT("info",("spider can not init for dml"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
for (
|
|
roop_count = spider_conn_link_idx_next(share->link_statuses,
|
|
spider->conn_link_idx, -1, share->link_count,
|
|
tgt_link_status);
|
|
roop_count < (int) share->link_count;
|
|
roop_count = spider_conn_link_idx_next(share->link_statuses,
|
|
spider->conn_link_idx, roop_count, share->link_count,
|
|
tgt_link_status)
|
|
) {
|
|
DBUG_PRINT("info",("spider roop_count=%d", roop_count));
|
|
if (spider_param_use_handler(thd, share->use_handlers[roop_count]))
|
|
{
|
|
DBUG_PRINT("info",("spider direct_join does not support use_handler"));
|
|
if (lock_mode)
|
|
{
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
continue;
|
|
}
|
|
conn = spider->conns[roop_count];
|
|
DBUG_PRINT("info",("spider conn=%p", conn));
|
|
if (!fields->check_conn_same_conn(conn))
|
|
{
|
|
DBUG_PRINT("info",("spider connection %p can not be used for this query with locking",
|
|
conn));
|
|
if (lock_mode)
|
|
{
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
continue;
|
|
}
|
|
if (fields->add_link_idx(conn->conn_holder_for_direct_join, spider, roop_count))
|
|
{
|
|
DBUG_PRINT("info",("spider can not create link_idx_holder"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
}
|
|
|
|
if (fields->remove_conn_if_not_checked())
|
|
{
|
|
if (lock_mode)
|
|
{
|
|
DBUG_PRINT("info",("spider some connections can not be used for this query with locking"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
}
|
|
if (!fields->has_conn_holder())
|
|
{
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
}
|
|
|
|
if (!fields->all_query_fields_are_query_table_members())
|
|
{
|
|
DBUG_PRINT("info", ("spider found a query field that is not a query table member"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
|
|
fields->check_support_dbton(dbton_bitmap);
|
|
if (!fields->has_conn_holder())
|
|
{
|
|
DBUG_PRINT("info",("spider all chosen connections can't match dbton_id"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
|
|
/* choose a connection */
|
|
if (!lock_mode)
|
|
{
|
|
fields->choose_a_conn();
|
|
}
|
|
|
|
if (fields->make_link_idx_chain(tgt_link_status))
|
|
{
|
|
DBUG_PRINT("info",("spider can not create link_idx_chain"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
|
|
/* choose link_id */
|
|
if (fields->check_link_ok_chain())
|
|
{
|
|
DBUG_PRINT("info",("spider do not have link ok status"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
|
|
fields->set_first_link_idx();
|
|
|
|
if (!(group_by_handler = new spider_group_by_handler(thd, query, fields)))
|
|
{
|
|
DBUG_PRINT("info",("spider can't create group_by_handler"));
|
|
delete fields;
|
|
DBUG_RETURN(NULL);
|
|
}
|
|
query->distinct = FALSE;
|
|
query->where = NULL;
|
|
query->group_by = NULL;
|
|
query->having = NULL;
|
|
query->order_by = NULL;
|
|
DBUG_RETURN(group_by_handler);
|
|
}
|
|
#endif
|