mariadb/storage/spider/spd_group_by_handler.cc
Jacob Mathew f6694b6244 MDEV-16889: Spider Crash mysqld got exception 0xc0000005
The SELECT with the INNER JOIN is executed with one of the two tables being
optimized as a constant table, which is pre-read.  Spider nevertheless attempts
to push down the join to the data node.  The crash occurs because the constant
table is excluded from the optimized query that Spider attempts to push down.

In order for Spider to be able to push down a join, the following conditions
need to be met:
- All of the tables involved in the join need to be included in the optimized
  query that Spider pushes down.  When any of the tables involved in the join
  is a constant table, it is excluded from the optimized query that Spider
  attempts to push down.
- All fields involved in the query need to be members of tables included in the
  optimized query.

I fixed the problem by preventing Spider from pushing down queries that include
a field that is not a member of a table included in the optimized query.  This
solution fixes the reported problem and also fixes other potential problems.

Author:
  Jacob Mathew.

Reviewer:
  Kentoku Shiba.

Cherry-Picked:
  Commit 4885baf on branch bb-10.3-MDEV-16889
2018-08-29 20:00:50 -07:00

2080 lines
65 KiB
C++

/* Copyright (C) 2008-2017 Kentoku Shiba
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;
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 =
&current_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 =
&current_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 =
&current_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)
{
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, sizeof(SPIDER_CONN_HOLDER),
&table_link_idx_holder,
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->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 choosed 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_fields_are_query_table_fields");
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);
}
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->trx,
tmp_spider->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->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", (*field)->field_name.str));
}
#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;
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
if (dbton_hdl->need_lock_before_set_sql_for_exec(
SPIDER_SQL_TYPE_SELECT_SQL))
{
pthread_mutex_lock(&conn->mta_conn_mutex);
SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos);
}
if ((error_num =
dbton_hdl->set_sql_for_exec(SPIDER_SQL_TYPE_SELECT_SQL, link_idx,
link_idx_chain)))
{
DBUG_RETURN(error_num);
}
if (!dbton_hdl->need_lock_before_set_sql_for_exec(
SPIDER_SQL_TYPE_SELECT_SQL))
{
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];
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)))
{
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])
) {
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;
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) && defined(PARTITION_HAS_GET_PART_SPEC)
ha_partition *partition = (ha_partition *) from->table->file;
part_id_range *part_spec = partition->get_part_spec();
DBUG_PRINT("info",("spider part_spec->start_part=%u", part_spec->start_part));
DBUG_PRINT("info",("spider part_spec->end_part=%u", part_spec->end_part));
if (
part_spec->start_part == partition->get_no_current_part_id() ||
part_spec->start_part != part_spec->end_part
) {
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) && defined(PARTITION_HAS_GET_PART_SPEC)
}
#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) && defined(PARTITION_HAS_GET_PART_SPEC)
if (from->table->part_info)
{
ha_partition *partition = (ha_partition *) from->table->file;
part_id_range *part_spec = partition->get_part_spec();
handler **handlers = partition->get_child_handlers();
spider = (ha_spider *) handlers[part_spec->start_part];
} else {
#endif
spider = (ha_spider *) from->table->file;
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
}
#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) && defined(PARTITION_HAS_GET_PART_SPEC)
if (from->table->part_info)
{
ha_partition *partition = (ha_partition *) from->table->file;
part_id_range *part_spec = partition->get_part_spec();
handler **handlers = partition->get_child_handlers();
spider = (ha_spider *) handlers[part_spec->start_part];
} else {
#endif
spider = (ha_spider *) from->table->file;
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
}
#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) && defined(PARTITION_HAS_GET_PART_SPEC)
if (from->table->part_info)
{
ha_partition *partition = (ha_partition *) from->table->file;
part_id_range *part_spec = partition->get_part_spec();
handler **handlers = partition->get_child_handlers();
spider = (ha_spider *) handlers[part_spec->start_part];
} else {
#endif
spider = (ha_spider *) from->table->file;
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
}
#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 (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)
{
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 (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) && defined(PARTITION_HAS_GET_PART_SPEC)
if (from->table->part_info)
{
ha_partition *partition = (ha_partition *) from->table->file;
part_id_range *part_spec = partition->get_part_spec();
handler **handlers = partition->get_child_handlers();
spider = (ha_spider *) handlers[part_spec->start_part];
} else {
#endif
spider = (ha_spider *) from->table->file;
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
}
#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);
}
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) && defined(PARTITION_HAS_GET_PART_SPEC)
if (from->table->part_info)
{
ha_partition *partition = (ha_partition *) from->table->file;
part_id_range *part_spec = partition->get_part_spec();
handler **handlers = partition->get_child_handlers();
spider = (ha_spider *) handlers[part_spec->start_part];
} else {
#endif
spider = (ha_spider *) from->table->file;
#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
}
#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));
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 choosed 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