Commit 7ec65585 authored by Nirbhay Choubey's avatar Nirbhay Choubey

MDEV-9021: MYSQLD SEGFAULTS WHEN BUILT USING --WITH-MAX-INDEXES=128

The bitmap implementation defines two template Bitmap classes. One
optimized for 64-bit (default) wide bitmaps while the other is used for
all other widths.

In order to optimize the computations, Bitmap<64> class has defined its
own member functions for bitmap operations, the other one, however,
relies on mysys' bitmap implementation (mysys/my_bitmap.c).

Issue 1:
In case of non 64-bit Bitmap class, intersect() wrongly reset the
received bitmap while initialising a new local bitmap structure
(bitmap_init() clears the bitmap buffer) thus, the received bitmap was
getting cleared.

Fixed by initializing the local bitmap structure by using a temporary
buffer and later copying the received bitmap to the initialised bitmap
structure.

Issue 2:
The non 64-bit Bitmap class had the Iterator missing which caused
compilation failure.

Also added a cmake variable to hold the MAX_INDEXES value when supplied
from the command prompt. (eg. cmake .. -DMAX_INDEXES=128U). Checks have
been put in place to trigger build failure if MAX_INDEXES value is
greater than 128.

Test modifications:
* Introduced include/have_max_indexes_[64|128].inc to facilitate
skipping of tests for which the output differs with different
MAX_INDEXES.

* Introduced include/max_indexes.inc which would get modified by cmake
to reflect the MAX_INDEXES value used to build the server. This file
simply sets an mtr variable '$max_indexes' to show the MAX_INDEXES
value, which will then be consumed by the above introduced include file.

* Some tests (portions), dependent on MAX_INDEXES value, have been moved
to separate test files.
parent d6b430c9
......@@ -56,6 +56,16 @@ ENDIF()
SET(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel")
# MAX_INDEXES - Set the maximum number of indexes per table, default 64U
IF (NOT MAX_INDEXES)
SET(MAX_INDEXES 64U)
ENDIF(NOT MAX_INDEXES)
IF (${MAX_INDEXES} GREATER 128)
MESSAGE(FATAL_ERROR "MAX_INDEXES values greater than 128 is not supported!")
ENDIF()
MESSAGE(STATUS "Configuring with MAX_INDEXES = ${MAX_INDEXES}")
IF(UNIX AND NOT APPLE)
# Note, that generally one should not change settings depending
# on CMAKE_BUILD_TYPE, because VS and Xcode configure once (with
......
......@@ -232,6 +232,11 @@ foreach my $option (@ARGV)
$cmakeargs = $cmakeargs." -DENABLE_GCOV=ON";
next;
}
if ($option =~ /with-max-indexes=/)
{
$cmakeargs = $cmakeargs." -DMAX_INDEXES=".substr($option, 17);
next;
}
if ($option =~ /verbose/)
{
$cmakeargs = $cmakeargs." -DCMAKE_VERBOSE_MAKEFILE=1";
......
......@@ -404,7 +404,7 @@
#cmakedefine HAVE_MBSTATE_T 1
#define MAX_INDEXES 64
#cmakedefine MAX_INDEXES @MAX_INDEXES@
#cmakedefine QSORT_TYPE_IS_VOID 1
#cmakedefine RETQSORTTYPE @RETQSORTTYPE@
......
......@@ -139,3 +139,19 @@ ENDMACRO()
# FILE(APPEND ${colldone} "${collin}\n")
# ENDIF()
#ENDFOREACH()
# With different MAX_INDEXES values, server might behave differently in
# certain cases. 'max_indexes.inc' file should be updated accordingly to
# reflect the current MAX_INDEXES value. This file helps MTR to decide on
# which tests should be skipped.
# NOTE: While committing a patch please make sure that the file is unmodified
# and should show the default MAX_INDEXES (i.e. 64U).
IF (MAX_INDEXES)
IF(NOT (${MAX_INDEXES} EQUAL 64U))
FILE(WRITE include/max_indexes.inc
"# Warning: This is an auto-generated file. Please do not modify it.
--let $max_indexes = ${MAX_INDEXES}\n")
MESSAGE(STATUS "mysql-test/include/max_indexes.inc adjusted")
ENDIF()
ENDIF()
--source include/max_indexes.inc
if (`SELECT "$max_indexes" NOT REGEXP "^128U?\$"`) {
--skip Test needs mysqld built with --with-max-indexes=128
}
--source include/max_indexes.inc
if (`SELECT "$max_indexes" NOT REGEXP "^64U?\$"`) {
--skip Test needs mysqld built with --with-max-indexes=64U
}
# Warning: This is an auto-generated file. Please do not modify it.
--let $max_indexes = 64U
......@@ -767,6 +767,7 @@ select '------ explain select tests ------' as test_sequence ;
# table with many column types
prepare stmt1 from ' explain select * from t9 ' ;
--enable_metadata
--replace_result 4096 4_OR_8_K 8192 4_OR_8_K
execute stmt1;
--disable_metadata
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
......@@ -447,9 +447,9 @@ def id 8 3 1 Y 32928 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def possible_keys 253 4_OR_8_K 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 253 4096 0 Y 0 31 8
def key_len 253 4_OR_8_K 0 Y 0 31 8
def ref 253 2048 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 14 N 1 31 8
......@@ -463,9 +463,9 @@ def id 8 3 1 Y 32928 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 5 Y 0 31 8
def possible_keys 253 4096 7 Y 0 31 8
def possible_keys 253 4_OR_8_K 7 Y 0 31 8
def key 253 64 7 Y 0 31 8
def key_len 253 4096 1 Y 0 31 8
def key_len 253 4_OR_8_K 1 Y 0 31 8
def ref 253 2048 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 37 N 1 31 8
......
......@@ -1157,9 +1157,9 @@ def id 8 3 1 Y 32928 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def possible_keys 253 4_OR_8_K 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 253 4096 0 Y 0 31 8
def key_len 253 4_OR_8_K 0 Y 0 31 8
def ref 253 2048 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
......
......@@ -1157,9 +1157,9 @@ def id 8 3 1 Y 32928 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def possible_keys 253 4_OR_8_K 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 253 4096 0 Y 0 31 8
def key_len 253 4_OR_8_K 0 Y 0 31 8
def ref 253 2048 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
......
......@@ -1158,9 +1158,9 @@ def id 8 3 1 Y 32928 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def possible_keys 253 4_OR_8_K 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 253 4096 0 Y 0 31 8
def key_len 253 4_OR_8_K 0 Y 0 31 8
def ref 253 2048 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
......
......@@ -1201,9 +1201,9 @@ def id 8 3 1 Y 32928 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def possible_keys 253 4_OR_8_K 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 253 4096 0 Y 0 31 8
def key_len 253 4_OR_8_K 0 Y 0 31 8
def ref 253 2048 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
......@@ -4555,9 +4555,9 @@ def id 8 3 1 Y 32928 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def possible_keys 253 4_OR_8_K 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 253 4096 0 Y 0 31 8
def key_len 253 4_OR_8_K 0 Y 0 31 8
def ref 253 2048 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
......
......@@ -1157,9 +1157,9 @@ def id 8 3 1 Y 32928 0 63
def select_type 253 19 6 N 1 31 8
def table 253 64 2 Y 0 31 8
def type 253 10 3 Y 0 31 8
def possible_keys 253 4096 0 Y 0 31 8
def possible_keys 253 4_OR_8_K 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
def key_len 253 4096 0 Y 0 31 8
def key_len 253 4_OR_8_K 0 Y 0 31 8
def ref 253 2048 0 Y 0 31 8
def rows 8 10 1 Y 32928 0 63
def Extra 253 255 0 N 1 31 8
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -497,11 +497,13 @@ prepare stmt1 from ' explain select a from t1 order by b ';
# PS protocol gives slightly different metadata
--disable_ps_protocol
--enable_metadata
--replace_result 4096 4_OR_8_K 8192 4_OR_8_K
execute stmt1;
--disable_metadata
SET @arg00=1 ;
prepare stmt1 from ' explain select a from t1 where a > ? order by b ';
--enable_metadata
--replace_result 4096 4_OR_8_K 8192 4_OR_8_K
execute stmt1 using @arg00;
--disable_metadata
--enable_ps_protocol
......
......@@ -306,6 +306,12 @@ uint bitmap_set_next(MY_BITMAP *map)
}
/**
Set the specified number of bits in the bitmap buffer.
@param map [IN] Bitmap
@param prefix_size [IN] Number of bits to be set
*/
void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size)
{
uint prefix_bytes, prefix_bits, d;
......@@ -319,11 +325,12 @@ void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size)
m+= prefix_bytes;
if ((prefix_bits= prefix_size & 7))
{
*m++= (1 << prefix_bits)-1;
prefix_bytes++;
*(m++)= (1 << prefix_bits)-1;
// As the prefix bits are set, lets count this byte too as a prefix byte.
prefix_bytes ++;
}
if ((d= no_bytes_in_map(map)-prefix_bytes))
bzero(m, d);
memset(m, 0, d);
}
......@@ -373,6 +380,7 @@ my_bool bitmap_is_clear_all(const MY_BITMAP *map)
my_bitmap_map *data_ptr= map->bitmap;
my_bitmap_map *end= map->last_word_ptr;
DBUG_ASSERT(map->n_bits > 0);
for (; data_ptr < end; data_ptr++)
if (*data_ptr)
return FALSE;
......
......@@ -41,10 +41,6 @@
#include <keycache.h>
#include <mysql/psi/mysql_table.h>
#if MAX_KEY > 128
#error MAX_KEY is too large. Values up to 128 are supported.
#endif
class Alter_info;
// the following is for checking tables
......
......@@ -39,6 +39,8 @@ typedef struct st_mysql_show_var SHOW_VAR;
#if MAX_INDEXES <= 64
typedef Bitmap<64> key_map; /* Used for finding keys */
#elif MAX_INDEXES > 128
#error "MAX_INDEXES values greater than 128 is not supported."
#else
typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */
#endif
......
......@@ -5214,6 +5214,7 @@ bool prepare_search_best_index_intersect(PARAM *param,
return 1;
bzero(init, sizeof(*init));
init->filtered_scans.init();
init->common_info= common;
init->cost= cutoff_cost;
......
......@@ -51,8 +51,27 @@ public:
void intersect(Bitmap& map2) { bitmap_intersect(&map, &map2.map); }
void intersect(ulonglong map2buff)
{
// Use a spearate temporary buffer, as bitmap_init() clears all the bits.
ulonglong buf2;
MY_BITMAP map2;
my_bitmap_init(&map2, (uint32 *)&map2buff, sizeof(ulonglong)*8, 0);
my_bitmap_init(&map2, (uint32 *) &buf2, sizeof(ulonglong) * 8, 0);
// Store the original bits.
if (sizeof(ulonglong) >= 8)
{
int8store(const_cast<uchar *>(static_cast<uchar *>
(static_cast<void *>(&buf2))),
map2buff);
}
else
{
DBUG_ASSERT(sizeof(buffer) >= 4);
int4store(const_cast<uchar *>(static_cast<uchar *>
(static_cast<void *>(&buf2))),
static_cast<uint32>(map2buff));
}
bitmap_intersect(&map, &map2);
}
/* Use highest bit for all bits above sizeof(ulonglong)*8. */
......@@ -93,14 +112,33 @@ public:
ulonglong to_ulonglong() const
{
if (sizeof(buffer) >= 8)
return uint8korr(buffer);
return uint8korr(static_cast<const uchar *>
(static_cast<const void *>(buffer)));
DBUG_ASSERT(sizeof(buffer) >= 4);
return (ulonglong) uint4korr(buffer);
return (ulonglong)
uint4korr(static_cast<const uchar *>
(static_cast<const void *>(buffer)));
}
uint bits_set()
{
return bitmap_bits_set(&map);
}
class Iterator
{
Bitmap &map;
uint no;
public:
Iterator(Bitmap<default_width> &map2): map(map2), no(0) {}
int operator++(int) {
if (no == default_width) return BITMAP_END;
while (!map.is_set(no))
{
if ((++no) == default_width) return BITMAP_END;
}
return no ++;
}
enum { BITMAP_END= default_width };
};
};
/* An iterator to quickly walk over bits in unlonglong bitmap. */
......
......@@ -60,6 +60,19 @@
#include <hash.h>
#include <ft_global.h>
/*
A key part number that means we're using a fulltext scan.
In order not to confuse it with regular equalities, we need to pick
a number that's greater than MAX_REF_PARTS.
Hash Join code stores field->field_index in KEYUSE::keypart, so the
number needs to be bigger than MAX_FIELDS, also.
CAUTION: sql_test.cc has its own definition of FT_KEYPART.
*/
#define FT_KEYPART (MAX_FIELDS+10)
const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
"MAYBE_REF","ALL","range","index","fulltext",
"ref_or_null","unique_subquery","index_subquery",
......@@ -3877,7 +3890,9 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
has_expensive_keyparts= false;
do
{
if (keyuse->val->type() != Item::NULL_ITEM && !keyuse->optimize)
if (keyuse->val->type() != Item::NULL_ITEM &&
!keyuse->optimize &&
keyuse->keypart != FT_KEYPART)
{
if (!((~found_const_table_map) & keyuse->used_tables))
{
......@@ -5113,19 +5128,6 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array, KEY_FIELD *key_field)
}
/*
A key part number that means we're using a fulltext scan.
In order not to confuse it with regular equalities, we need to pick
a number that's greater than MAX_REF_PARTS.
Hash Join code stores field->field_index in KEYUSE::keypart, so the
number needs to be bigger than MAX_FIELDS, also.
CAUTION: sql_test.cc has its own definition of FT_KEYPART.
*/
#define FT_KEYPART (MAX_FIELDS+10)
static bool
add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
JOIN_TAB *stat,COND *cond,table_map usable_tables)
......@@ -9705,7 +9707,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
if (tab->type == JT_REF && tab->quick &&
(((uint) tab->ref.key == tab->quick->index &&
tab->ref.key_length < tab->quick->max_used_key_length) ||
tab->table->intersect_keys.is_set(tab->ref.key)))
(!is_hash_join_key_no(tab->ref.key) &&
tab->table->intersect_keys.is_set(tab->ref.key))))
{
/* Range uses longer key; Use this instead of ref on key */
tab->type=JT_ALL;
......@@ -20770,7 +20773,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
quick_type == QUICK_SELECT_I::QS_TYPE_INDEX_INTERSECT ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_UNION ||
quick_type == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT)
ref_key= MAX_KEY;
ref_key= -1;
else
{
ref_key= select->quick->index;
......@@ -25462,6 +25465,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
uint *saved_best_key_parts)
{
DBUG_ENTER("test_if_cheaper_ordering");
DBUG_ASSERT(ref_key < int(MAX_KEY));
/*
Check whether there is an index compatible with the given order
usage of which is cheaper than usage of the ref_key index (ref_key>=0)
......@@ -25526,7 +25530,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
Calculate the selectivity of the ref_key for REF_ACCESS. For
RANGE_ACCESS we use table->quick_condition_rows.
*/
if (ref_key >= 0 && tab->type == JT_REF)
if (ref_key >= 0 && !is_hash_join_key_no(ref_key) && tab->type == JT_REF)
{
if (table->quick_keys.is_set(ref_key))
refkey_rows_estimate= table->quick_rows[ref_key];
......@@ -25693,6 +25697,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table,
{
ha_rows quick_records= table_records;
ha_rows refkey_select_limit= (ref_key >= 0 &&
!is_hash_join_key_no(ref_key) &&
table->covering_keys.is_set(ref_key)) ?
refkey_rows_estimate :
HA_POS_ERROR;
......
......@@ -2617,6 +2617,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
outparam->quick_keys.init();
outparam->covering_keys.init();
outparam->merge_keys.init();
outparam->intersect_keys.init();
outparam->keys_in_use_for_query.init();
/* Allocate handler */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment