1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

WL 1682: After review fixes + update bitvector class + bitvector test

cases + bug fixes
This commit is contained in:
mronstrom@mysql.com
2005-05-02 15:45:33 +02:00
parent 21347433cf
commit f7cd6b8aa1
19 changed files with 772 additions and 209 deletions

View File

@@ -102,14 +102,6 @@ void bitmap_free(MY_BITMAP *map)
void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit) void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit)
{ {
if (map->bitmap)
{
DBUG_PRINT("info", ("Bitmap not defined"));
}
if (bitmap_bit >= map->bitmap_size*8)
{
DBUG_PRINT("info", ("bit %d size in bytes %d", bitmap_bit, map->bitmap_size));
}
DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8); DBUG_ASSERT(map->bitmap && bitmap_bit < map->bitmap_size*8);
bitmap_lock(map); bitmap_lock(map);
bitmap_fast_set_bit(map, bitmap_bit); bitmap_fast_set_bit(map, bitmap_bit);

320
sql/bitvector.cc Normal file
View File

@@ -0,0 +1,320 @@
/* -*- Mode: C++ -*-
Copyright (C) 2005 MySQL AB
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; either version 2 of the License, or
(at your option) any later version.
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 */
#include <bitvector.h>
void bitvector::create_last_word_mask()
{
/* Get the number of used bits (1..8) in the last byte */
unsigned int const used= 1U + ((size()-1U) & 0x7U);
/*
* Create a mask with the upper 'unused' bits set and the lower 'used'
* bits clear. The bits within each byte is stored in big-endian order.
*/
unsigned char const mask= (~((1 << used) - 1)) & 255;
last_word_ptr= (uint32*)(m_data+((bytes()-1U)>>2));
/*
The first bytes are to be set to zero since they represent real bits
in the bitvector. The last bytes are set to 0xFF since they represent
bytes not used by the bitvector. Finally the last byte contains bits
as set by the mask above.
*/
unsigned char *ptr= (unsigned char*)&last_word_mask;
switch (bytes()&3)
{
case 1:
last_word_mask= ~0U;
ptr[0]= mask;
return;
case 2:
last_word_mask= ~0U;
ptr[0]= 0;
ptr[1]= mask;
return;
case 3:
last_word_mask= 0U;
ptr[2]= mask;
ptr[3]= 0xFFU;
return;
case 0:
last_word_mask= 0U;
ptr[3]= mask;
return;
}
}
int bitvector::init(size_t size)
{
DBUG_ASSERT(size < MYSQL_NO_BIT_FOUND);
m_size= size;
m_data= (uchar*)my_malloc(byte_size_word_aligned(size), MYF(0));
if (m_data)
{
create_last_word_mask();
clear_all();
return FALSE;
}
return TRUE;
}
uint bitvector::no_bits_set()
{
uint no_bytes= bytes(), res=0, i;
uchar *ptr= m_data;
*last_word_ptr^=last_word_mask; //Reset last bits to zero
for (i=0; i< no_bytes; i++, ptr++)
res+=my_count_bits_ushort(*ptr);
*last_word_ptr^=last_word_mask; //Set last bits to one again
return res;
}
uint bitvector::get_first_bit_set()
{
uchar *byte_ptr;
uint32 *data_ptr= (uint32*)data(), bit_found,i,j,k;
for (i=0; data_ptr <= last_word_ptr; data_ptr++, i++)
{
if (*data_ptr)
{
byte_ptr= (uchar*)data_ptr;
for (j=0; j < 4; j++, byte_ptr++)
{
if (*byte_ptr)
{
for (k=0; k < 8; k++)
{
if (*byte_ptr & (1 << k))
{
bit_found= (i << 5) + (j << 3) + k;
if (bit_found == m_size)
return MYSQL_NO_BIT_FOUND;
else
return bit_found;
}
}
DBUG_ASSERT(1);
}
}
DBUG_ASSERT(1);
}
}
return MYSQL_NO_BIT_FOUND;
}
uint bitvector::get_first_bit_unset()
{
uchar *byte_ptr;
uint32 *data_ptr= (uint32*)data(), bit_found,i,j,k;
for (i=0; data_ptr <= last_word_ptr; data_ptr++, i++)
{
if (*data_ptr != 0xFFFFFFFF)
{
byte_ptr= (uchar*)data_ptr;
for (j=0; j < 4; j++, byte_ptr++)
{
if (*byte_ptr != 0xFF)
{
for (k=0; k < 8; k++)
{
if (!(*byte_ptr & (1 << k)))
{
bit_found= (i << 5) + (j << 3) + k;
if (bit_found == m_size)
return MYSQL_NO_BIT_FOUND;
else
return bit_found;
}
}
DBUG_ASSERT(1);
}
}
DBUG_ASSERT(1);
}
}
return MYSQL_NO_BIT_FOUND;
}
#ifdef TEST_BITVECTOR
int main()
{
int i;
for (i= 0; i < 4096; i++)
if (do_test(i))
return -1;
return 0;
}
bool do_test(uint bitsize)
{
bitvector *bv;
bv = new bitvector;
bv->init(bitsize);
if (test_set_get_clear_bit(bv,bitsize))
return TRUE;
if (test_flip_bit(bv,bitsize))
return TRUE;
if (test_operators(bv,bitsize))
return TRUE;
if (test_get_all_bits(bvbitsize))
return TRUE;
if (test_compare_operators(bv,bitsize))
return TRUE;
if (test_count_bits_set(bv,bitsize))
return TRUE;
if (test_get_first_bit(bv,bitsize))
return TRUE;
if (test_get_next_bit(bv,bitsize))
return TRUE;
printf("OK");
return FALSE;
}
uint get_rand_bit(uint bitsize)
{
return (rand() % bitsize);
}
bool test_set_get_clear_bit(bitvector *bv, uint bitsize)
{
uint i, test_bit;
uint no_loops= bitsize > 128 ? 128 : bitsize;
for (i=0; i < no_loops; i++)
{
test_bit= get_rand_bit(bitsize);
bv->set_bit(test_bit)
if (!bv->get_bit(test_bit))
goto error1;
bv->clear_bit(test_bit);
if (bv->get_bit(test_bit))
goto error2;
}
return FALSE;
error1:
printf("Error in set bit, bit %u, bitsize = %u", test_bit, bitsize);
return TRUE;
error2:
printf("Error in clear bit, bit %u, bitsize = %u", test_bit, bitsize);
return TRUE;
}
bool test_flip_bit(bitvector *bv, uint bitsize)
{
uint i test_bit;
uint no_loops= bitsize > 128 ? 128 : bitsize;
for (i=0; i < no_loops; i++)
{
test_bit= get_rand_bit(bitsize);
bv->flip_bit(test_bit)
if (!bv->get_bit(test_bit))
goto error1;
bv->flip_bit(test_bit);
if (bv->get_bit(test_bit))
goto error2;
}
return FALSE;
error1:
printf("Error in flip bit 1, bit %u, bitsize = %u", test_bit, bitsize);
return TRUE;
error2:
printf("Error in flip bit 2, bit %u, bitsize = %u", test_bit, bitsize);
return TRUE;
}
bool test_operators(bitvector *bv, uint bitsize)
{
return FALSE;
}
bool test_get_all_bits(bitvector *bv, uint bitsize)
{
uint i;
bv->set_all();
if (!bv->get_all_bits_set())
goto error1;
bv->clear_all();
if (!bv->get_all_bits_clear())
goto error2;
for (i=0; i<bitsize;i++)
bv->set_bit(i);
if (!bv->get_all_bits_set())
goto error3;
for (i=0; i<bitsize;i++)
bv->clear_bit(i);
if (!bv->get_all_bits_clear())
goto error4;
return FALSE;
error1:
printf("Error in set_all, bitsize = %u", bitsize);
return TRUE;
error2:
printf("Error in clear_all, bitsize = %u", bitsize);
return TRUE;
error3:
printf("Error in bitwise set all, bitsize = %u", bitsize);
return TRUE;
error4:
printf("Error in bitwise clear all, bitsize = %u", bitsize);
return TRUE;
}
bool test_compare_operators(bitvector *bv, uint bitsize)
{
return FALSE;
}
bool test_count_bits_set(bitvector *bv, uint bitsize)
{
uint i, bit_count=0;
uint no_loops= bitsize > 128 ? 128 : bitsize;
for (i=0; i < no_loops; i++)
{
test_bit=get_rand_bit(bitsize);
if (!bv->get_bit(test_bit))
{
bv->set_bit(test_bit);
bit_count++;
}
}
if (bit_count==0 && bitsize > 0)
error1;
if (bv->no_bits_set() != bit_count)
error2;
return FALSE;
error1:
printf("No bits set bitsize = %u", bitsize);
return TRUE;
error2:
printf("Wrong count of bits set, bitsize = %u", bitsize);
return TRUE;
}
bool test_get_first_bit(bitvector *bv, uint bitsize)
{
return FALSE;
}
bool test_get_next_bit(bitvector *bv, uint bitsize)
{
return FALSE;
}
#endif

View File

@@ -68,64 +68,70 @@ namespace
inlining code. inlining code.
*/ */
/* Number returned when no bit found */
#define MYSQL_NO_BIT_FOUND 1 << 20
class bitvector class bitvector
{ {
private: private:
/* Helper classes */
struct flip_bit_op
{
void operator()(byte* p, byte m) { *p^= m; }
};
struct set_bit_op
{
void operator()(byte* p, byte m) { *p|= m; }
};
struct clear_bit_op
{
void operator()(byte* p, byte m) { *p&= ~m; }
};
struct test_bit_op
{
bool operator()(byte* p, byte m) { return *p & m; }
};
/* Compute the number of bytes required to store 'bits' bits in an array. */ /* Compute the number of bytes required to store 'bits' bits in an array. */
static inline size_t byte_size(size_t bits) static inline size_t byte_size(size_t bits)
{ {
int const byte_bits = sizeof(byte) * CHAR_BIT; uint const byte_bits = sizeof(byte) * CHAR_BIT;
return (bits + (byte_bits-1)) / byte_bits; return (bits + (byte_bits-1)) / byte_bits;
} }
/* Tidy the last byte (by clearing the unused bits) of the bitvector to make static inline size_t byte_size_word_aligned(size_t bits)
* comparison easy. This code is assuming that we're working with 8-bit {
* bytes. return ((bits + 31) >> 5) << 2;
*/ }
void tidy_last_byte()
void create_last_word_mask()
{ {
byte* const last_byte= m_data + bytes() - 1;
/* Get the number of used bits (1..8) in the last byte */ /* Get the number of used bits (1..8) in the last byte */
unsigned int const used= 1U + ((size()-1U) & 0x7U); unsigned int const used= 1U + ((size()-1U) & 0x7U);
/* Create a mask with the upper 'unused' bits clear and the lower 'used' /*
* bits set. The bits within each byte is stored in big-endian order. * Create a mask with the upper 'unused' bits set and the lower 'used'
* bits clear. The bits within each byte is stored in big-endian order.
*/ */
unsigned int const mask= ((1 << used) - 1); unsigned char const mask= (~((1 << used) - 1)) & 255;
last_word_ptr= (uint32*)(m_data+((bytes()-1U)>>2));
/* Mask the last byte */ /*
*last_byte&= mask; The first bytes are to be set to zero since they represent real bits
in the bitvector. The last bytes are set to 0xFF since they represent
bytes not used by the bitvector. Finally the last byte contains bits
as set by the mask above.
*/
unsigned char *ptr= (unsigned char*)&last_word_mask;
switch (bytes()&3)
{
case 1:
last_word_mask= ~0U;
ptr[0]= mask;
return;
case 2:
last_word_mask= ~0U;
ptr[0]= 0;
ptr[1]= mask;
return;
case 3:
last_word_mask= 0U;
ptr[2]= mask;
ptr[3]= 0xFFU;
return;
case 0:
last_word_mask= 0U;
ptr[3]= mask;
return;
}
} }
template <class ReturnType, class Func> inline void tidy_last_word()
inline ReturnType apply_to_byte(size_t const pos, Func op) const
{ {
/* Here I'm assuming that we're working with 8-bit bytes. */ *last_word_ptr|= last_word_mask;
ptrdiff_t const byte_pos= pos >> 3;
byte const mask= (1 << (pos & 0x7U));
return op(&m_data[byte_pos], mask);
} }
public: public:
@@ -135,8 +141,11 @@ public:
} }
explicit bitvector(size_t size, bool value= false) explicit bitvector(size_t size, bool value= false)
: m_size(size), m_data(my_malloc(byte_size(size), MYF(0))) : m_size(size),
m_data((uchar*)my_malloc(byte_size_word_aligned(size), MYF(0)))
{ {
DBUG_ASSERT(size < MYSQL_NO_BIT_FOUND);
create_last_word_mask();
if (value) if (value)
set_all(); set_all();
else else
@@ -147,32 +156,43 @@ public:
* number of *bits* in the bitvector. * number of *bits* in the bitvector.
*/ */
explicit bitvector(byte const* data, size_t size) explicit bitvector(byte const* data, size_t size)
: m_size(size), m_data(my_malloc(byte_size(size), MYF(0))) : m_size(size),
m_data((uchar*)my_malloc(byte_size_word_aligned(size), MYF(0)))
{ {
/* std::copy(data, data + byte_size(size), m_data); */ DBUG_ASSERT(size < MYSQL_NO_BIT_FOUND);
create_last_word_mask();
memcpy(m_data, data, byte_size(size)); memcpy(m_data, data, byte_size(size));
tidy_last_byte(); tidy_last_word();
} }
bitvector(bitvector const& other) bitvector(bitvector const& other)
: m_size(other.size()), m_data(my_malloc(other.bytes(), MYF(0))) : m_size(other.size()),
m_data((uchar*)my_malloc(other.bytes(), MYF(0)))
{ {
/* std::copy(other.m_data, other.m_data + other.bytes(), m_data); */ DBUG_ASSERT(m_size < MYSQL_NO_BIT_FOUND);
create_last_word_mask();
memcpy(m_data, other.data(), other.bytes()); memcpy(m_data, other.data(), other.bytes());
tidy_last_byte(); /* Just a precaution */ tidy_last_word();
}
/* Assignment operator */
bitvector& operator=(bitvector other)
{
swap(other);
return *this;
} }
~bitvector() ~bitvector()
{ {
if (m_data) if (m_data)
my_free(m_data, MYF(0)); my_free((char*)m_data, MYF(0));
}
int init(size_t size)
{
DBUG_ASSERT(size < MYSQL_NO_BIT_FOUND);
m_size= size;
m_data= (uchar*)my_malloc(byte_size_word_aligned(size), MYF(0));
if (m_data)
{
create_last_word_mask();
clear_all();
return FALSE;
}
return TRUE;
} }
/* Swap the guts of this instance with another instance. */ /* Swap the guts of this instance with another instance. */
@@ -182,8 +202,35 @@ public:
my_swap(m_data, other.m_data); my_swap(m_data, other.m_data);
} }
bitvector &operator=(const bitvector &rhs)
{
DBUG_ASSERT(rhs.size() == size());
memcpy(m_data, rhs.data(), byte_size_word_aligned(m_size));
return *this;
}
bool get_all_bits_set()
{
uint32 *data_ptr= (uint32*)&m_data[0];
for (; data_ptr <= last_word_ptr; data_ptr++)
if (*data_ptr != 0xFFFFFFFF)
return FALSE;
return TRUE;
}
bool get_all_bits_clear()
{
uint32 *data_ptr= (uint32*)&m_data[0];
if (*last_word_ptr ^ last_word_mask)
return FALSE;
for (; data_ptr < last_word_ptr; data_ptr++)
if (*data_ptr)
return FALSE;
return TRUE;
}
/* A pointer to the bytes representing the bits */ /* A pointer to the bytes representing the bits */
byte const *data() const { return m_data; } uchar const *data() const { return m_data; }
/* The size of the data in *bytes* */ /* The size of the data in *bytes* */
size_t bytes() const { return byte_size(m_size); } size_t bytes() const { return byte_size(m_size); }
@@ -194,47 +241,44 @@ public:
/* Set all bits in the vector */ /* Set all bits in the vector */
void set_all() void set_all()
{ {
/* std::fill_n(m_data, bytes(), 255); */ memset(m_data, 255, byte_size_word_aligned(m_size));
memset(m_data, 255, bytes());
tidy_last_byte();
} }
/* Set a bit to a value */ /* Set a bit to a value */
void set_bit(size_t pos) void set_bit(size_t pos)
{ {
apply_to_byte<void>(pos, set_bit_op()); *(uchar*)(m_data + (pos >> 3)) |= (uchar)(1 << (pos & 0x7U));
} }
/* Reset (clear) all bits in the vector */ /* Reset (clear) all bits in the vector */
void clear_all() void clear_all()
{ {
/* std::fill_n(m_data, bytes(), 0); */
memset(m_data, 0, bytes()); memset(m_data, 0, bytes());
tidy_last_byte(); tidy_last_word();
} }
/* Reset one bit in the vector */ /* Reset one bit in the vector */
void clear_bit(size_t pos) void clear_bit(size_t pos)
{ {
apply_to_byte<void>(pos, clear_bit_op()); *(u_char*)(m_data + (pos >> 3)) &= (u_char)(~(1 << (pos & 0x7U)));
} }
void flip_bit(size_t pos) void flip_bit(size_t pos)
{ {
apply_to_byte<void>(pos, flip_bit_op()); *(uchar*)(m_data + (pos >> 3)) ^= (uchar)(1 << (pos & 0x7U));
} }
bool get_bit(size_t pos) const bool get_bit(size_t pos) const
{ {
return apply_to_byte<bool>(pos, test_bit_op()); (bool)(*(uchar*)(m_data + (pos >> 3))) & (uchar)(1 << (pos & 0x7U));
}; };
bool operator==(bitvector const& rhs) const bool operator==(bitvector const& rhs) const
{ {
if (size() != rhs.size()) if (size() != rhs.size())
return false; return false;
/* This works since I have ensured that the last byte of the array contain /* This works since I have ensured that the last byte of the array
* sensible data. * contain sensible data.
*/ */
if (memcmp(data(), rhs.data(), bytes()) != 0) if (memcmp(data(), rhs.data(), bytes()) != 0)
return false; return false;
@@ -246,9 +290,130 @@ public:
return !(*this == rhs); return !(*this == rhs);
} }
bitvector &operator&=(bitvector const& rhs)
{
DBUG_ASSERT(size() == rhs.size());
uint32 *data_ptr=(uint32*)data(), *rhs_data_ptr=(uint32*)rhs.data();
uint32 *last_ptr= last_word_ptr;
for (; data_ptr <= last_ptr; data_ptr++, rhs_data_ptr++)
*data_ptr&=*rhs_data_ptr;
return *this;
}
bitvector &operator|=(bitvector const& rhs)
{
DBUG_ASSERT(size() == rhs.size());
uint32 *data_ptr=(uint32*)data(), *rhs_data_ptr=(uint32*)rhs.data();
uint32 *last_ptr= last_word_ptr;
for (; data_ptr <= last_ptr; data_ptr++, rhs_data_ptr++)
*data_ptr|=*rhs_data_ptr;
return *this;
}
bitvector &operator^=(bitvector const& rhs)
{
DBUG_ASSERT(size() == rhs.size());
uint32 *data_ptr=(uint32*)data(), *rhs_data_ptr=(uint32*)rhs.data();
uint32 *last_ptr= last_word_ptr;
for (; data_ptr <= last_ptr; data_ptr++, rhs_data_ptr++)
*data_ptr^=*rhs_data_ptr;
tidy_last_word();
return *this;
}
bitvector &operator~()
{
uint32 *data_ptr= (uint32*)data();
uint32 *last_ptr= last_word_ptr;
for (; data_ptr <= last_ptr; data_ptr++)
*data_ptr^=0xFFFFFFFF;
tidy_last_word();
return *this;
}
uint no_bits_set()
{
uint no_bytes= bytes(), res=0, i;
uchar *ptr= m_data;
*last_word_ptr^=last_word_mask; //Reset last bits to zero
for (i=0; i< no_bytes; i++, ptr++)
res+=my_count_bits_ushort(*ptr);
*last_word_ptr^=last_word_mask; //Set last bits to one again
return res;
}
uint get_first_bit_set()
{
uchar *byte_ptr;
uint32 *data_ptr= (uint32*)data(), bit_found,i,j,k;
for (i=0; data_ptr <= last_word_ptr; data_ptr++, i++)
{
if (*data_ptr)
{
byte_ptr= (uchar*)data_ptr;
for (j=0; j < 4; j++, byte_ptr++)
{
if (*byte_ptr)
{
for (k=0; k < 8; k++)
{
if (*byte_ptr & (1 << k))
{
bit_found= (i << 5) + (j << 3) + k;
if (bit_found == m_size)
return MYSQL_NO_BIT_FOUND;
else
return bit_found;
}
}
DBUG_ASSERT(1);
}
}
DBUG_ASSERT(1);
}
}
return MYSQL_NO_BIT_FOUND;
}
uint get_first_bit_unset()
{
uchar *byte_ptr;
uint32 *data_ptr= (uint32*)data(), bit_found,i,j,k;
for (i=0; data_ptr <= last_word_ptr; data_ptr++, i++)
{
if (*data_ptr != 0xFFFFFFFF)
{
byte_ptr= (uchar*)data_ptr;
for (j=0; j < 4; j++, byte_ptr++)
{
if (*byte_ptr != 0xFF)
{
for (k=0; k < 8; k++)
{
if (!(*byte_ptr & (1 << k)))
{
bit_found= (i << 5) + (j << 3) + k;
if (bit_found == m_size)
return MYSQL_NO_BIT_FOUND;
else
return bit_found;
}
}
DBUG_ASSERT(1);
}
}
DBUG_ASSERT(1);
}
}
return MYSQL_NO_BIT_FOUND;
}
private: private:
size_t m_size; size_t m_size;
byte *m_data; uint32 last_word_mask;
uchar *m_data;
uint32 *last_word_ptr;
}; };
#endif /* BITVECTOR_H */ #endif /* BITVECTOR_H */

View File

@@ -86,7 +86,10 @@ public:
utype unireg_check; utype unireg_check;
uint32 field_length; // Length of field uint32 field_length; // Length of field
uint16 flags; uint16 flags;
uint16 fieldnr; // Field number /* fieldnr is the id of the field (first field = 1) as is also
used in key_part.
*/
uint16 fieldnr;
uchar null_bit; // Bit used to test null bit uchar null_bit; // Bit used to test null bit
Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uchar null_bit_arg, Field(char *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,uchar null_bit_arg,

View File

@@ -1113,7 +1113,7 @@ int ha_federated::write_row(byte *buf)
loop through the field pointer array, add any fields to both the values loop through the field pointer array, add any fields to both the values
list and the fields list that is part of the write set list and the fields list that is part of the write set
*/ */
for (x=0, num_fields= 0, field= table->field; *field; field++, x++) for (num_fields= 0, field= table->field; *field; field++)
{ {
/* if there is a query id and if it's equal to the current query id */ /* if there is a query id and if it's equal to the current query id */
if (ha_get_bit_in_write_set((*field)->fieldnr)) if (ha_get_bit_in_write_set((*field)->fieldnr))
@@ -1122,15 +1122,16 @@ int ha_federated::write_row(byte *buf)
if ((*field)->is_null()) if ((*field)->is_null())
{ {
DBUG_PRINT("info", ("column %d field is_null", x)); DBUG_PRINT("info", ("column %d field is_null", num_fields-1));
insert_field_value_string.append("NULL"); insert_field_value_string.append("NULL");
} }
else else
{ {
DBUG_PRINT("info", ("column %d field is not null", x)); DBUG_PRINT("info", ("column %d field is not null", num_fields-1));
(*field)->val_str(&insert_field_value_string); (*field)->val_str(&insert_field_value_string);
/* quote these fields if they require it */ /* quote these fields if they require it */
(*field)->quote_data(&insert_field_value_string); } (*field)->quote_data(&insert_field_value_string);
}
/* append the field name */ /* append the field name */
insert_string.append((*field)->field_name); insert_string.append((*field)->field_name);

View File

@@ -2684,8 +2684,8 @@ build_template(
(!(fetch_all_in_key && index_contains_field) && (!(fetch_all_in_key && index_contains_field) &&
!(fetch_primary_key_cols && !(fetch_primary_key_cols &&
dict_table_col_in_clustered_key(index->table, i)) && dict_table_col_in_clustered_key(index->table, i)) &&
!(ha_get_bit_in_read_set(i+1) || (!(table->file->ha_get_bit_in_read_set(i+1) ||
ha_get_bit_in_write_set(i+1))))) { table->file->ha_get_bit_in_write_set(i+1)))))) {
/* This field is not needed in the query, skip it */ /* This field is not needed in the query, skip it */

View File

@@ -165,6 +165,16 @@ class ha_innobase: public handler
int transactional_table_lock(THD *thd, int lock_type); int transactional_table_lock(THD *thd, int lock_type);
int start_stmt(THD *thd); int start_stmt(THD *thd);
int ha_retrieve_all_cols()
{
ha_set_all_bits_in_read_set();
return extra(HA_EXTRA_RETRIEVE_ALL_COLS);
}
int ha_retrieve_all_pk()
{
ha_set_primary_key_in_read_set();
return extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
}
void position(byte *record); void position(byte *record);
ha_rows records_in_range(uint inx, key_range *min_key, key_range ha_rows records_in_range(uint inx, key_range *min_key, key_range
*max_key); *max_key);

View File

@@ -1921,10 +1921,7 @@ int ha_ndbcluster::write_row(byte *record)
statistic_increment(thd->status_var.ha_write_count, &LOCK_status); statistic_increment(thd->status_var.ha_write_count, &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
{
table->timestamp_field->set_time(); table->timestamp_field->set_time();
ha_set_bit_in_write_set(table->timestamp_field->fieldnr);
}
has_auto_increment= (table->next_number_field && record == table->record[0]); has_auto_increment= (table->next_number_field && record == table->record[0]);
if (!(op= trans->getNdbOperation((const NDBTAB *) m_table))) if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)))
@@ -1977,7 +1974,6 @@ int ha_ndbcluster::write_row(byte *record)
{ {
Field *field= table->field[i]; Field *field= table->field[i];
if (!(field->flags & PRI_KEY_FLAG) && if (!(field->flags & PRI_KEY_FLAG) &&
(ha_get_bit_in_write_set(i+1)) &&
set_ndb_value(op, field, i, &set_blob_value)) set_ndb_value(op, field, i, &set_blob_value))
{ {
m_skip_auto_increment= TRUE; m_skip_auto_increment= TRUE;

View File

@@ -271,10 +271,10 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
} }
if (file) if (file)
{ {
if (table && file->ha_allocate_read_write_set(table->s->fields)) if (file->ha_initialise())
{ {
delete file; delete file;
file= 0; file=0;
} }
} }
return file; return file;
@@ -1343,38 +1343,154 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
DBUG_RETURN(error); DBUG_RETURN(error);
} }
int handler::ha_initialise()
{
if (table && table->s->fields &&
ha_allocate_read_write_set(table->s->fields))
{
return TRUE;
}
return FALSE;
}
int handler::ha_allocate_read_write_set(ulong no_fields) int handler::ha_allocate_read_write_set(ulong no_fields)
{ {
DBUG_ENTER("ha_allocate_read_write_set"); DBUG_ENTER("ha_allocate_read_write_set");
uint map_size= ((no_fields + 8)/8)*8; DBUG_PRINT("info", ("no_fields = %d", no_fields));
if (rw_set_allocated) read_set= new bitvector;
ha_deallocate_read_write_set(); write_set= new bitvector;
DBUG_PRINT("info", ("no_fields = %d, map_size = %d", no_fields, map_size)); if (!read_set || !write_set)
if (bitmap_init(&read_set, NULL, map_size, FALSE))
{ {
ha_deallocate_read_write_set();
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
if (bitmap_init(&write_set, NULL, map_size, FALSE)) if (read_set->init(no_fields+1) || write_set->init(no_fields+1))
{ {
bitmap_free(&read_set); ha_deallocate_read_write_set();
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
ha_clear_all_set(); ha_clear_all_set();
rw_set_allocated= TRUE;
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
void handler::ha_deallocate_read_write_set() void handler::ha_deallocate_read_write_set()
{ {
if (!rw_set_allocated) delete read_set;
return; delete write_set;
bitmap_free(&read_set); read_set=write_set=0;
bitmap_free(&write_set); }
void handler::ha_clear_all_set()
{
DBUG_ENTER("ha_clear_all_set");
read_set->clear_all();
write_set->clear_all();
read_set->set_bit((uint)0);
write_set->set_bit((uint)0);
DBUG_VOID_RETURN;
}
void handler::ha_set_all_bits_in_read_set()
{
DBUG_ENTER("handler::ha_set_all_bits_in_read_set");
read_set->set_all();
DBUG_VOID_RETURN;
}
void handler::ha_set_all_bits_in_write_set()
{
DBUG_ENTER("handler::ha_set_all_bits_in_write_set");
write_set->set_all();
DBUG_VOID_RETURN;
}
void handler::ha_set_bit_in_read_set(uint fieldnr)
{
DBUG_ENTER("handler::ha_set_bit_in_read_set");
DBUG_PRINT("info", ("fieldnr = %d", fieldnr));
read_set->set_bit((size_t)fieldnr);
DBUG_VOID_RETURN;
}
void handler::ha_clear_bit_in_read_set(uint fieldnr)
{
DBUG_ENTER("handler::ha_clear_bit_in_read_set");
DBUG_PRINT("info", ("fieldnr = %d", fieldnr));
read_set->clear_bit((size_t)fieldnr);
DBUG_VOID_RETURN;
}
void handler::ha_set_bit_in_write_set(uint fieldnr)
{
DBUG_ENTER("handler::ha_set_bit_in_write_set");
DBUG_PRINT("info", ("fieldnr = %d", fieldnr));
write_set->set_bit((size_t)fieldnr);
DBUG_VOID_RETURN;
}
void handler::ha_clear_bit_in_write_set(uint fieldnr)
{
DBUG_ENTER("handler::ha_clear_bit_in_write_set");
DBUG_PRINT("info", ("fieldnr = %d", fieldnr));
write_set->clear_bit((size_t)fieldnr);
DBUG_VOID_RETURN;
}
void handler::ha_set_bit_in_rw_set(uint fieldnr, bool write_op)
{
if (!write_op)
read_set->set_bit((size_t)fieldnr);
else
write_set->set_bit((size_t)fieldnr);
}
bool handler::ha_get_bit_in_read_set(uint fieldnr)
{
read_set->get_bit((size_t)fieldnr);
}
bool handler::ha_get_bit_in_write_set(uint fieldnr)
{
write_set->get_bit((size_t)fieldnr);
}
bool handler::ha_get_all_bit_in_read_set()
{
return read_set->get_all_bits_set();
}
bool handler::ha_get_all_bit_in_read_clear()
{
return read_set->get_all_bits_clear();
}
bool handler::ha_get_all_bit_in_write_set()
{
return write_set->get_all_bits_set();
}
bool handler::ha_get_all_bit_in_write_clear()
{
return write_set->get_all_bits_clear();
}
int handler::ha_retrieve_all_cols()
{
read_set->set_all();
return 0;
}
int handler::ha_retrieve_all_pk()
{
ha_set_primary_key_in_read_set();
return 0;
} }
void handler::ha_set_primary_key_in_read_set() void handler::ha_set_primary_key_in_read_set()
{ {
ulong prim_key= table->s->primary_key; ulong prim_key= table->s->primary_key;
DBUG_ENTER("handler::ha_set_primary_key_in_read_set");
DBUG_PRINT("info", ("Primary key = %d", prim_key));
if (prim_key != MAX_KEY) if (prim_key != MAX_KEY)
{ {
KEY_PART_INFO *key_part= table->key_info[prim_key].key_part; KEY_PART_INFO *key_part= table->key_info[prim_key].key_part;
@@ -1383,6 +1499,7 @@ void handler::ha_set_primary_key_in_read_set()
for (;key_part != key_part_end; ++key_part) for (;key_part != key_part_end; ++key_part)
ha_set_bit_in_read_set(key_part->fieldnr); ha_set_bit_in_read_set(key_part->fieldnr);
} }
DBUG_VOID_RETURN;
} }
/* /*
Read first row (only) from a table Read first row (only) from a table

View File

@@ -23,6 +23,7 @@
#include <ft_global.h> #include <ft_global.h>
#include <keycache.h> #include <keycache.h>
#include <bitvector.h>
#ifndef NO_HASH #ifndef NO_HASH
#define NO_HASH /* Not yet implemented */ #define NO_HASH /* Not yet implemented */
@@ -483,9 +484,8 @@ public:
bool auto_increment_column_changed; bool auto_increment_column_changed;
bool implicit_emptied; /* Can be !=0 only if HEAP */ bool implicit_emptied; /* Can be !=0 only if HEAP */
const COND *pushed_cond; const COND *pushed_cond;
MY_BITMAP read_set; bitvector *read_set;
MY_BITMAP write_set; bitvector *write_set;
bool rw_set_allocated;
handler(TABLE *table_arg) :table(table_arg), handler(TABLE *table_arg) :table(table_arg),
ref(0), data_file_length(0), max_data_file_length(0), index_file_length(0), ref(0), data_file_length(0), max_data_file_length(0), index_file_length(0),
@@ -495,13 +495,14 @@ public:
key_used_on_scan(MAX_KEY), active_index(MAX_KEY), key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
ref_length(sizeof(my_off_t)), block_size(0), ref_length(sizeof(my_off_t)), block_size(0),
raid_type(0), ft_handler(0), inited(NONE), implicit_emptied(0), raid_type(0), ft_handler(0), inited(NONE), implicit_emptied(0),
pushed_cond(NULL), rw_set_allocated(0) pushed_cond(NULL), read_set(0), write_set(0)
{} {}
virtual ~handler(void) virtual ~handler(void)
{ {
ha_deallocate_read_write_set(); ha_deallocate_read_write_set();
/* TODO: DBUG_ASSERT(inited == NONE); */ /* TODO: DBUG_ASSERT(inited == NONE); */
} }
virtual int ha_initialise();
int ha_open(const char *name, int mode, int test_if_locked); int ha_open(const char *name, int mode, int test_if_locked);
void update_auto_increment(); void update_auto_increment();
virtual void print_error(int error, myf errflag); virtual void print_error(int error, myf errflag);
@@ -578,64 +579,32 @@ public:
The routines are all part of the general handler and are not possible The routines are all part of the general handler and are not possible
to override by a handler. A handler can however set/reset bits by to override by a handler. A handler can however set/reset bits by
calling these routines. calling these routines.
The methods ha_retrieve_all_cols and ha_retrieve_all_pk are made
virtual to handle InnoDB specifics. If InnoDB doesn't need the
extra parameters HA_EXTRA_RETRIEVE_ALL_COLS and
HA_EXTRA_RETRIEVE_PRIMARY_KEY anymore then these methods need not be
virtual anymore.
*/ */
void ha_set_all_bits_in_read_set() virtual int ha_retrieve_all_cols();
{ virtual int ha_retrieve_all_pk();
bitmap_set_all(&read_set); void ha_set_all_bits_in_read_set();
} void ha_set_all_bits_in_write_set();
void ha_set_all_bits_in_write_set() void ha_set_bit_in_read_set(uint fieldnr);
{ void ha_clear_bit_in_read_set(uint fieldnr);
bitmap_set_all(&write_set); void ha_set_bit_in_write_set(uint fieldnr);
} void ha_clear_bit_in_write_set(uint fieldnr);
void ha_set_bit_in_read_set(uint fieldnr) void ha_set_bit_in_rw_set(uint fieldnr, bool write_set);
{ bool ha_get_bit_in_read_set(uint fieldnr);
bitmap_set_bit(&read_set, fieldnr); bool ha_get_bit_in_write_set(uint fieldnr);
} bool ha_get_all_bit_in_read_set();
void ha_clear_bit_in_read_set(uint fieldnr) bool ha_get_all_bit_in_read_clear();
{ bool ha_get_all_bit_in_write_set();
bitmap_clear_bit(&read_set, fieldnr); bool ha_get_all_bit_in_write_clear();
}
void ha_set_bit_in_write_set(uint fieldnr)
{
bitmap_set_bit(&write_set, fieldnr);
}
void ha_clear_bit_in_write_set(uint fieldnr)
{
bitmap_clear_bit(&write_set, fieldnr);
}
void ha_set_bit_in_rw_set(uint fieldnr, bool write_set)
{
if (!write_set)
ha_set_bit_in_read_set(fieldnr);
else
ha_set_bit_in_write_set(fieldnr);
}
my_bool ha_get_bit_in_read_set(uint fieldnr)
{
return bitmap_is_set(&read_set, fieldnr);
}
my_bool ha_get_all_bit_in_read_set()
{
return bitmap_is_set_all(&read_set);
}
my_bool ha_get_all_bit_in_write_set()
{
return bitmap_is_set_all(&write_set);
}
my_bool ha_get_bit_in_write_set(uint fieldnr)
{
return bitmap_is_set(&write_set, fieldnr);
}
void ha_clear_all_set()
{
bitmap_clear_all(&read_set);
bitmap_clear_all(&write_set);
bitmap_set_bit(&read_set,0);
bitmap_set_bit(&write_set,0);
}
void ha_set_primary_key_in_read_set(); void ha_set_primary_key_in_read_set();
int ha_allocate_read_write_set(ulong no_fields); int ha_allocate_read_write_set(ulong no_fields);
void ha_deallocate_read_write_set(); void ha_deallocate_read_write_set();
void ha_clear_all_set();
uint get_index(void) const { return active_index; } uint get_index(void) const { return active_index; }
virtual int open(const char *name, int mode, uint test_if_locked)=0; virtual int open(const char *name, int mode, uint test_if_locked)=0;

View File

@@ -916,12 +916,11 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
{ {
DBUG_PRINT("info", ("Reusing handler %p", file)); DBUG_PRINT("info", ("Reusing handler %p", file));
if (file->extra(HA_EXTRA_KEYREAD) || if (file->extra(HA_EXTRA_KEYREAD) ||
file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) || file->ha_retrieve_all_pk() ||
init() || reset()) init() || reset())
{ {
DBUG_RETURN(1); DBUG_RETURN(1);
} }
file->ha_set_primary_key_in_read_set();
DBUG_RETURN(0); DBUG_RETURN(0);
} }
@@ -945,14 +944,13 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
goto failure; goto failure;
if (file->extra(HA_EXTRA_KEYREAD) || if (file->extra(HA_EXTRA_KEYREAD) ||
file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) || file->ha_retrieve_all_pk() ||
init() || reset()) init() || reset())
{ {
file->external_lock(thd, F_UNLCK); file->external_lock(thd, F_UNLCK);
file->close(); file->close();
goto failure; goto failure;
} }
file->ha_set_primary_key_in_read_set();
free_file= TRUE; free_file= TRUE;
last_rowid= file->ref; last_rowid= file->ref;
DBUG_RETURN(0); DBUG_RETURN(0);
@@ -5627,9 +5625,8 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
(This also creates a deficiency - it is possible that we will retrieve (This also creates a deficiency - it is possible that we will retrieve
parts of key that are not used by current query at all.) parts of key that are not used by current query at all.)
*/ */
if (head->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY)) if (head->file->ha_retrieve_all_pk())
DBUG_RETURN(1); DBUG_RETURN(1);
head->file->ha_set_primary_key_in_read_set();
cur_quick_it.rewind(); cur_quick_it.rewind();
cur_quick= cur_quick_it++; cur_quick= cur_quick_it++;

View File

@@ -1526,8 +1526,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
key_copy((byte *) user_key, table->record[0], table->key_info, key_copy((byte *) user_key, table->record[0], table->key_info,
table->key_info->key_length); table->key_info->key_length);
table->file->ha_set_all_bits_in_read_set(); table->file->ha_retrieve_all_cols();
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (table->file->index_read_idx(table->record[0], 0, if (table->file->index_read_idx(table->record[0], 0,
(byte *) user_key, table->key_info->key_length, (byte *) user_key, table->key_info->key_length,
HA_READ_KEY_EXACT)) HA_READ_KEY_EXACT))
@@ -1620,8 +1619,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
key_copy(user_key, table->record[0], table->key_info, key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length); table->key_info->key_length);
table->file->ha_set_all_bits_in_read_set(); table->file->ha_retrieve_all_cols();
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (table->file->index_read_idx(table->record[0], 0, if (table->file->index_read_idx(table->record[0], 0,
user_key, table->key_info->key_length, user_key, table->key_info->key_length,
HA_READ_KEY_EXACT)) HA_READ_KEY_EXACT))
@@ -1754,8 +1752,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
We should NEVER delete from the user table, as a uses can still We should NEVER delete from the user table, as a uses can still
use mysqld even if he doesn't have any privileges in the user table! use mysqld even if he doesn't have any privileges in the user table!
*/ */
table->file->ha_set_all_bits_in_read_set(); table->file->ha_retrieve_all_cols();
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (cmp_record(table,record[1]) && if (cmp_record(table,record[1]) &&
(error=table->file->update_row(table->record[1],table->record[0]))) (error=table->file->update_row(table->record[1],table->record[0])))
{ // This should never happen { // This should never happen
@@ -1837,8 +1834,7 @@ static int replace_db_table(TABLE *table, const char *db,
key_copy(user_key, table->record[0], table->key_info, key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length); table->key_info->key_length);
table->file->ha_set_all_bits_in_read_set(); table->file->ha_retrieve_all_cols();
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (table->file->index_read_idx(table->record[0],0, if (table->file->index_read_idx(table->record[0],0,
user_key, table->key_info->key_length, user_key, table->key_info->key_length,
HA_READ_KEY_EXACT)) HA_READ_KEY_EXACT))
@@ -1874,8 +1870,7 @@ static int replace_db_table(TABLE *table, const char *db,
/* update old existing row */ /* update old existing row */
if (rights) if (rights)
{ {
table->file->ha_set_all_bits_in_read_set(); table->file->ha_retrieve_all_cols();
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if ((error=table->file->update_row(table->record[1],table->record[0]))) if ((error=table->file->update_row(table->record[1],table->record[0])))
goto table_error; /* purecov: deadcode */ goto table_error; /* purecov: deadcode */
} }
@@ -2208,8 +2203,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
key_copy(user_key, table->record[0], table->key_info, key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length); table->key_info->key_length);
table->file->ha_set_all_bits_in_read_set(); table->file->ha_retrieve_all_cols();
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (table->file->index_read(table->record[0], user_key, if (table->file->index_read(table->record[0], user_key,
table->key_info->key_length, table->key_info->key_length,
HA_READ_KEY_EXACT)) HA_READ_KEY_EXACT))
@@ -2286,8 +2280,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
key_copy(user_key, table->record[0], table->key_info, key_copy(user_key, table->record[0], table->key_info,
key_prefix_length); key_prefix_length);
table->file->ha_set_all_bits_in_read_set(); table->file->ha_retrieve_all_cols();
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (table->file->index_read(table->record[0], user_key, if (table->file->index_read(table->record[0], user_key,
key_prefix_length, key_prefix_length,
HA_READ_KEY_EXACT)) HA_READ_KEY_EXACT))
@@ -2385,8 +2378,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
key_copy(user_key, table->record[0], table->key_info, key_copy(user_key, table->record[0], table->key_info,
table->key_info->key_length); table->key_info->key_length);
table->file->ha_set_all_bits_in_read_set(); table->file->ha_retrieve_all_cols();
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (table->file->index_read_idx(table->record[0], 0, if (table->file->index_read_idx(table->record[0], 0,
user_key, table->key_info->key_length, user_key, table->key_info->key_length,
HA_READ_KEY_EXACT)) HA_READ_KEY_EXACT))

View File

@@ -3705,12 +3705,14 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
goto err; goto err;
/* Mark field used for table cache */ /* Mark field used for table cache */
t2_field->query_id= thd->query_id; t2_field->query_id= thd->query_id;
t2->file->ha_set_bit_in_read_set(t2_field->fieldnr);
t2->used_keys.intersect(t2_field->part_of_key); t2->used_keys.intersect(t2_field->part_of_key);
} }
if ((t1_field= iterator->field())) if ((t1_field= iterator->field()))
{ {
/* Mark field used for table cache */ /* Mark field used for table cache */
t1_field->query_id= thd->query_id; t1_field->query_id= thd->query_id;
t1->file->ha_set_bit_in_read_set(t1_field->fieldnr);
t1->used_keys.intersect(t1_field->part_of_key); t1->used_keys.intersect(t1_field->part_of_key);
} }
Item_func_eq *tmp= new Item_func_eq(iterator->item(thd), Item_func_eq *tmp= new Item_func_eq(iterator->item(thd),

View File

@@ -231,7 +231,10 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list,
clear_timestamp_auto_bits(table->timestamp_field_type, clear_timestamp_auto_bits(table->timestamp_field_type,
TIMESTAMP_AUTO_SET_ON_UPDATE); TIMESTAMP_AUTO_SET_ON_UPDATE);
else else
{
table->timestamp_field->query_id= timestamp_query_id; table->timestamp_field->query_id= timestamp_query_id;
table->file->ha_set_bit_in_write_set(table->timestamp_field->fieldnr);
}
} }
return 0; return 0;
@@ -798,10 +801,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
if (duplic == DUP_UPDATE || duplic == DUP_REPLACE) if (duplic == DUP_UPDATE || duplic == DUP_REPLACE)
{ table->file->ha_retrieve_all_pk();
table->file->ha_set_primary_key_in_read_set();
table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
}
thd->lex->select_lex.first_execution= 0; thd->lex->select_lex.first_execution= 0;
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }

View File

@@ -163,7 +163,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
The main thing to fix to remove this restriction is to ensure that the The main thing to fix to remove this restriction is to ensure that the
table is marked to be 'used for insert' in which case we should never table is marked to be 'used for insert' in which case we should never
mark this table as as 'const table' (ie, one that has only one row). mark this table as 'const table' (ie, one that has only one row).
*/ */
if (unique_table(table_list, table_list->next_global)) if (unique_table(table_list, table_list->next_global))
{ {
@@ -180,7 +180,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
for (field=table->field; *field ; field++) for (field=table->field; *field ; field++)
fields_vars.push_back(new Item_field(*field)); fields_vars.push_back(new Item_field(*field));
/* /*
Since all fields is be set we set all bits in the write set Since all fields are set we set all bits in the write set
*/ */
table->file->ha_set_all_bits_in_write_set(); table->file->ha_set_all_bits_in_write_set();
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
@@ -197,8 +197,11 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
/* TODO: use this conds for 'WITH CHECK OPTIONS' */ /* TODO: use this conds for 'WITH CHECK OPTIONS' */
/* /*
Indicate that both variables in field list and fields in update_list Indicate that both variables in field list and fields in update_list
is to be included in write set of table is to be included in write set of table. We do however set all bits
in write set anyways since it is not allowed to specify NULLs in
LOAD DATA
*/ */
table->file->ha_set_all_bits_in_write_set();
if (setup_fields(thd, 0, table_list, fields_vars, 2, 0, 0) || if (setup_fields(thd, 0, table_list, fields_vars, 2, 0, 0) ||
setup_fields(thd, 0, table_list, set_fields, 2, 0, 0) || setup_fields(thd, 0, table_list, set_fields, 2, 0, 0) ||
check_that_all_fields_are_given_values(thd, table)) check_that_all_fields_are_given_values(thd, table))

View File

@@ -922,24 +922,19 @@ JOIN::optimize()
} }
/* /*
Need to tell Innobase that to play it safe, it should fetch all Need to tell handlers that to play it safe, it should fetch all
columns of the tables: this is because MySQL may build row columns of the primary key of the tables: this is because MySQL may
pointers for the rows, and for all columns of the primary key the build row pointers for the rows, and for all columns of the primary key
field->query_id has not necessarily been set to thd->query_id by the read set has not necessarily been set by the server code.
MySQL.
*/ */
#ifdef HAVE_INNOBASE_DB
if (need_tmp || select_distinct || group_list || order) if (need_tmp || select_distinct || group_list || order)
{ {
for (uint i_h = const_tables; i_h < tables; i_h++) for (uint i_h = const_tables; i_h < tables; i_h++)
{ {
TABLE* table_h = join_tab[i_h].table; TABLE* table_h = join_tab[i_h].table;
table_h->file->set_primary_key_in_read_set(); table_h->file->ha_retrieve_all_pk();
table_h->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
} }
} }
#endif
DBUG_EXECUTE("info",TEST_join(this);); DBUG_EXECUTE("info",TEST_join(this););
/* /*
@@ -8090,6 +8085,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
table->s->tmp_table= TMP_TABLE; table->s->tmp_table= TMP_TABLE;
table->s->db_low_byte_first=1; // True for HEAP and MyISAM table->s->db_low_byte_first=1; // True for HEAP and MyISAM
table->s->table_charset= param->table_charset; table->s->table_charset= param->table_charset;
table->s->primary_key= MAX_KEY; //Indicate no primary key
table->s->keys_for_keyread.init(); table->s->keys_for_keyread.init();
table->s->keys_in_use.init(); table->s->keys_in_use.init();
/* For easier error reporting */ /* For easier error reporting */

View File

@@ -3826,8 +3826,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
current query id current query id
*/ */
to->file->ha_set_all_bits_in_write_set(); to->file->ha_set_all_bits_in_write_set();
from->file->ha_set_all_bits_in_read_set(); from->file->ha_retrieve_all_cols();
from->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); //To be removed RONM
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1); init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
if (ignore || if (ignore ||
handle_duplicates == DUP_REPLACE) handle_duplicates == DUP_REPLACE)
@@ -3990,11 +3989,11 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
/* calculating table's checksum */ /* calculating table's checksum */
ha_checksum crc= 0; ha_checksum crc= 0;
/* InnoDB must be told explicitly to retrieve all columns, because /*
this function does not set field->query_id in the columns to the Set all bits in read set and inform InnoDB that we are reading all
current query id */ fields
t->file->ha_set_all_bits_in_read_set(); */
t->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); t->file->ha_retrieve_all_cols();
if (t->file->ha_rnd_init(1)) if (t->file->ha_rnd_init(1))
protocol->store_null(); protocol->store_null();

View File

@@ -526,8 +526,7 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
if (!(table = open_ltable(thd,&tables,TL_WRITE))) if (!(table = open_ltable(thd,&tables,TL_WRITE)))
goto err; goto err;
table->field[0]->store(udf_name->str, udf_name->length, system_charset_info); table->field[0]->store(udf_name->str, udf_name->length, system_charset_info);
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); table->file->ha_retrieve_all_cols();
table->file->ha_set_all_bits_in_read_set();
if (!table->file->index_read_idx(table->record[0], 0, if (!table->file->index_read_idx(table->record[0], 0,
(byte*) table->field[0]->ptr, (byte*) table->field[0]->ptr,
table->key_info[0].key_length, table->key_info[0].key_length,

View File

@@ -212,7 +212,10 @@ int mysql_update(THD *thd,
if (table->timestamp_field->query_id == thd->query_id) if (table->timestamp_field->query_id == thd->query_id)
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
else else
{
table->timestamp_field->query_id=timestamp_query_id; table->timestamp_field->query_id=timestamp_query_id;
table->file->ha_set_bit_in_write_set(table->timestamp_field->fieldnr);
}
} }
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -272,8 +275,7 @@ int mysql_update(THD *thd,
We can't update table directly; We must first search after all We can't update table directly; We must first search after all
matching rows before updating the table! matching rows before updating the table!
*/ */
table->file->ha_set_all_bits_in_read_set(); table->file->ha_retrieve_all_cols();
table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (used_index < MAX_KEY && old_used_keys.is_set(used_index)) if (used_index < MAX_KEY && old_used_keys.is_set(used_index))
{ {
table->key_read=1; table->key_read=1;