Commit 7c62023b authored by unknown's avatar unknown

Merge mskold@bk-internal.mysql.com:/home/bk/mysql-5.0

into mysql.com:/usr/local/home/marty/MySQL/mysql-5.0


sql/sql_select.cc:
  Auto merged
parents 4360dd16 fec4347f
...@@ -87,6 +87,7 @@ hf@deer.mysql.r18.ru ...@@ -87,6 +87,7 @@ hf@deer.mysql.r18.ru
hf@genie.(none) hf@genie.(none)
holyfoot@mysql.com holyfoot@mysql.com
igor@hundin.mysql.fi igor@hundin.mysql.fi
igor@igor-inspiron.creware.com
igor@linux.local igor@linux.local
igor@rurik.mysql.com igor@rurik.mysql.com
ingo@mysql.com ingo@mysql.com
...@@ -236,6 +237,7 @@ rburnett@bk-internal.mysql.com ...@@ -236,6 +237,7 @@ rburnett@bk-internal.mysql.com
rburnett@build.mysql.com rburnett@build.mysql.com
reggie@bob.(none) reggie@bob.(none)
reggie@mdk10.(none) reggie@mdk10.(none)
reggie@monster.
root@home.(none) root@home.(none)
root@mc04.(none) root@mc04.(none)
root@x3.internalnet root@x3.internalnet
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#include "handshake.hpp" #include "handshake.hpp"
#include "yassl_int.hpp" #include "yassl_int.hpp"
#include <stdio.h> #include <stdio.h>
#include "runtime.hpp"
namespace yaSSL { namespace yaSSL {
......
...@@ -74,7 +74,7 @@ extern char *mysql_unix_port; ...@@ -74,7 +74,7 @@ extern char *mysql_unix_port;
#define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG) #define IS_PRI_KEY(n) ((n) & PRI_KEY_FLAG)
#define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG) #define IS_NOT_NULL(n) ((n) & NOT_NULL_FLAG)
#define IS_BLOB(n) ((n) & BLOB_FLAG) #define IS_BLOB(n) ((n) & BLOB_FLAG)
#define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR) #define IS_NUM(t) ((t) <= FIELD_TYPE_INT24 || (t) == FIELD_TYPE_YEAR || (t) == FIELD_TYPE_NEWDECIMAL)
#define IS_NUM_FIELD(f) ((f)->flags & NUM_FLAG) #define IS_NUM_FIELD(f) ((f)->flags & NUM_FLAG)
#define INTERNAL_NUM_FIELD(f) (((f)->type <= FIELD_TYPE_INT24 && ((f)->type != FIELD_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == FIELD_TYPE_YEAR) #define INTERNAL_NUM_FIELD(f) (((f)->type <= FIELD_TYPE_INT24 && ((f)->type != FIELD_TYPE_TIMESTAMP || (f)->length == 14 || (f)->length == 8)) || (f)->type == FIELD_TYPE_YEAR)
......
...@@ -160,3 +160,20 @@ t1 CREATE TABLE `t1` ( ...@@ -160,3 +160,20 @@ t1 CREATE TABLE `t1` (
`COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default '' `COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (EMPNUM INT);
INSERT INTO t1 VALUES (0), (2);
CREATE TABLE t2 (EMPNUM DECIMAL (4, 2));
INSERT INTO t2 VALUES (0.0), (9.0);
SELECT COALESCE(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM,
t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2
FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM;
CEMPNUM EMPMUM1 EMPNUM2
0.00 0 0.00
2.00 2 NULL
SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM,
t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2
FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM;
CEMPNUM EMPMUM1 EMPNUM2
0.00 0 0.00
2.00 2 NULL
DROP TABLE t1,t2;
...@@ -110,3 +110,22 @@ explain extended SELECT ...@@ -110,3 +110,22 @@ explain extended SELECT
COALESCE('a' COLLATE latin1_bin,'b'); COALESCE('a' COLLATE latin1_bin,'b');
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
DROP TABLE t1; DROP TABLE t1;
#
# Tests for bug #9939: conversion of the arguments for COALESCE and IFNULL
#
CREATE TABLE t1 (EMPNUM INT);
INSERT INTO t1 VALUES (0), (2);
CREATE TABLE t2 (EMPNUM DECIMAL (4, 2));
INSERT INTO t2 VALUES (0.0), (9.0);
SELECT COALESCE(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM,
t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2
FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM;
SELECT IFNULL(t2.EMPNUM,t1.EMPNUM) AS CEMPNUM,
t1.EMPNUM AS EMPMUM1, t2.EMPNUM AS EMPNUM2
FROM t1 LEFT JOIN t2 ON t1.EMPNUM=t2.EMPNUM;
DROP TABLE t1,t2;
...@@ -44,7 +44,7 @@ int my_access(const char *path, int amode) ...@@ -44,7 +44,7 @@ int my_access(const char *path, int amode)
result= GetFileAttributesEx(path, GetFileExInfoStandard, &fileinfo); result= GetFileAttributesEx(path, GetFileExInfoStandard, &fileinfo);
if (! result || if (! result ||
(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (amode & W_OK)) (fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) && (amode & F_OK))
{ {
my_errno= errno= EACCES; my_errno= errno= EACCES;
return -1; return -1;
......
...@@ -5963,11 +5963,14 @@ ha_innobase::external_lock( ...@@ -5963,11 +5963,14 @@ ha_innobase::external_lock(
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
an InnoDB table lock if it is released immediately at the end an InnoDB table lock if it is released immediately at the end
of LOCK TABLES, and InnoDB's table locks in that case cause of LOCK TABLES, and InnoDB's table locks in that case cause
VERY easily deadlocks. */ VERY easily deadlocks. We do not set InnoDB table locks when
MySQL sets them at the start of a stored procedure call
(MySQL does have thd->in_lock_tables TRUE there). */
if (prebuilt->select_lock_type != LOCK_NONE) { if (prebuilt->select_lock_type != LOCK_NONE) {
if (thd->in_lock_tables && if (thd->in_lock_tables &&
thd->lex->sql_command != SQLCOM_CALL &&
thd->variables.innodb_table_locks && thd->variables.innodb_table_locks &&
(thd->options & OPTION_NOT_AUTOCOMMIT)) { (thd->options & OPTION_NOT_AUTOCOMMIT)) {
...@@ -6478,11 +6481,21 @@ ha_innobase::store_lock( ...@@ -6478,11 +6481,21 @@ ha_innobase::store_lock(
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
/* Starting from 5.0.7, we weaken also the table locks
set at the start of a MySQL stored procedure call, just like
we weaken the locks set at the start of an SQL statement.
MySQL does set thd->in_lock_tables TRUE there, but in reality
we do not need table locks to make the execution of a
single transaction stored procedure call deterministic
(if it does not use a consistent read). */
/* If we are not doing a LOCK TABLE or DISCARD/IMPORT /* If we are not doing a LOCK TABLE or DISCARD/IMPORT
TABLESPACE or TRUNCATE TABLE, then allow multiple writers */ TABLESPACE or TRUNCATE TABLE, then allow multiple writers */
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
lock_type <= TL_WRITE) && !thd->in_lock_tables lock_type <= TL_WRITE)
&& (!thd->in_lock_tables
|| thd->lex->sql_command == SQLCOM_CALL)
&& !thd->tablespace_op && !thd->tablespace_op
&& thd->lex->sql_command != SQLCOM_TRUNCATE && thd->lex->sql_command != SQLCOM_TRUNCATE
&& thd->lex->sql_command != SQLCOM_CREATE_TABLE) { && thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
...@@ -6496,7 +6509,10 @@ ha_innobase::store_lock( ...@@ -6496,7 +6509,10 @@ ha_innobase::store_lock(
to t2. Convert the lock to a normal read lock to allow to t2. Convert the lock to a normal read lock to allow
concurrent inserts to t2. */ concurrent inserts to t2. */
if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) { if (lock_type == TL_READ_NO_INSERT
&& (!thd->in_lock_tables
|| thd->lex->sql_command == SQLCOM_CALL)) {
lock_type = TL_READ; lock_type = TL_READ;
} }
......
...@@ -1116,8 +1116,8 @@ Item_func_ifnull::fix_length_and_dec() ...@@ -1116,8 +1116,8 @@ Item_func_ifnull::fix_length_and_dec()
max_length= (max(args[0]->max_length - args[0]->decimals, max_length= (max(args[0]->max_length - args[0]->decimals,
args[1]->max_length - args[1]->decimals) + args[1]->max_length - args[1]->decimals) +
decimals); decimals);
agg_result_type(&cached_result_type, args, 2); agg_result_type(&hybrid_type, args, 2);
switch (cached_result_type) { switch (hybrid_type) {
case STRING_RESULT: case STRING_RESULT:
agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV); agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
break; break;
...@@ -1155,7 +1155,7 @@ Field *Item_func_ifnull::tmp_table_field(TABLE *table) ...@@ -1155,7 +1155,7 @@ Field *Item_func_ifnull::tmp_table_field(TABLE *table)
} }
double double
Item_func_ifnull::val_real() Item_func_ifnull::real_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
double value= args[0]->val_real(); double value= args[0]->val_real();
...@@ -1171,7 +1171,7 @@ Item_func_ifnull::val_real() ...@@ -1171,7 +1171,7 @@ Item_func_ifnull::val_real()
} }
longlong longlong
Item_func_ifnull::val_int() Item_func_ifnull::int_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
longlong value=args[0]->val_int(); longlong value=args[0]->val_int();
...@@ -1187,7 +1187,7 @@ Item_func_ifnull::val_int() ...@@ -1187,7 +1187,7 @@ Item_func_ifnull::val_int()
} }
my_decimal *Item_func_ifnull::val_decimal(my_decimal *decimal_value) my_decimal *Item_func_ifnull::decimal_op(my_decimal *decimal_value)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
my_decimal *value= args[0]->val_decimal(decimal_value); my_decimal *value= args[0]->val_decimal(decimal_value);
...@@ -1204,7 +1204,7 @@ my_decimal *Item_func_ifnull::val_decimal(my_decimal *decimal_value) ...@@ -1204,7 +1204,7 @@ my_decimal *Item_func_ifnull::val_decimal(my_decimal *decimal_value)
String * String *
Item_func_ifnull::val_str(String *str) Item_func_ifnull::str_op(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
String *res =args[0]->val_str(str); String *res =args[0]->val_str(str);
...@@ -1685,7 +1685,7 @@ void Item_func_case::print(String *str) ...@@ -1685,7 +1685,7 @@ void Item_func_case::print(String *str)
Coalesce - return first not NULL argument. Coalesce - return first not NULL argument.
*/ */
String *Item_func_coalesce::val_str(String *str) String *Item_func_coalesce::str_op(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
null_value=0; null_value=0;
...@@ -1699,7 +1699,7 @@ String *Item_func_coalesce::val_str(String *str) ...@@ -1699,7 +1699,7 @@ String *Item_func_coalesce::val_str(String *str)
return 0; return 0;
} }
longlong Item_func_coalesce::val_int() longlong Item_func_coalesce::int_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
null_value=0; null_value=0;
...@@ -1713,7 +1713,7 @@ longlong Item_func_coalesce::val_int() ...@@ -1713,7 +1713,7 @@ longlong Item_func_coalesce::val_int()
return 0; return 0;
} }
double Item_func_coalesce::val_real() double Item_func_coalesce::real_op()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
null_value=0; null_value=0;
...@@ -1728,7 +1728,7 @@ double Item_func_coalesce::val_real() ...@@ -1728,7 +1728,7 @@ double Item_func_coalesce::val_real()
} }
my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value) my_decimal *Item_func_coalesce::decimal_op(my_decimal *decimal_value)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
null_value= 0; null_value= 0;
...@@ -1745,8 +1745,8 @@ my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value) ...@@ -1745,8 +1745,8 @@ my_decimal *Item_func_coalesce::val_decimal(my_decimal *decimal_value)
void Item_func_coalesce::fix_length_and_dec() void Item_func_coalesce::fix_length_and_dec()
{ {
agg_result_type(&cached_result_type, args, arg_count); agg_result_type(&hybrid_type, args, arg_count);
switch (cached_result_type) { switch (hybrid_type) {
case STRING_RESULT: case STRING_RESULT:
count_only_length(); count_only_length();
decimals= NOT_FIXED_DEC; decimals= NOT_FIXED_DEC;
......
...@@ -453,23 +453,19 @@ class Item_func_interval :public Item_int_func ...@@ -453,23 +453,19 @@ class Item_func_interval :public Item_int_func
}; };
class Item_func_coalesce :public Item_func class Item_func_coalesce :public Item_func_numhybrid
{ {
protected: protected:
enum Item_result cached_result_type; Item_func_coalesce(Item *a, Item *b) :Item_func_numhybrid(a, b) {}
Item_func_coalesce(Item *a, Item *b)
:Item_func(a, b), cached_result_type(INT_RESULT)
{}
public: public:
Item_func_coalesce(List<Item> &list) Item_func_coalesce(List<Item> &list) :Item_func_numhybrid(list) {}
:Item_func(list),cached_result_type(INT_RESULT) double real_op();
{} longlong int_op();
double val_real(); String *str_op(String *);
longlong val_int(); my_decimal *decimal_op(my_decimal *);
String *val_str(String *);
my_decimal *val_decimal(my_decimal *);
void fix_length_and_dec(); void fix_length_and_dec();
enum Item_result result_type () const { return cached_result_type; } void find_num_type() {}
enum Item_result result_type () const { return hybrid_type; }
const char *func_name() const { return "coalesce"; } const char *func_name() const { return "coalesce"; }
table_map not_null_tables() const { return 0; } table_map not_null_tables() const { return 0; }
}; };
...@@ -482,10 +478,10 @@ class Item_func_ifnull :public Item_func_coalesce ...@@ -482,10 +478,10 @@ class Item_func_ifnull :public Item_func_coalesce
bool field_type_defined; bool field_type_defined;
public: public:
Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {} Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {}
double val_real(); double real_op();
longlong val_int(); longlong int_op();
String *val_str(String *str); String *str_op(String *str);
my_decimal *val_decimal(my_decimal *); my_decimal *decimal_op(my_decimal *);
enum_field_types field_type() const; enum_field_types field_type() const;
void fix_length_and_dec(); void fix_length_and_dec();
const char *func_name() const { return "ifnull"; } const char *func_name() const { return "ifnull"; }
......
...@@ -817,6 +817,8 @@ String *Item_func_numhybrid::val_str(String *str) ...@@ -817,6 +817,8 @@ String *Item_func_numhybrid::val_str(String *str)
str->set(nr,decimals,&my_charset_bin); str->set(nr,decimals,&my_charset_bin);
break; break;
} }
case STRING_RESULT:
return str_op(&str_value);
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
...@@ -841,6 +843,14 @@ double Item_func_numhybrid::val_real() ...@@ -841,6 +843,14 @@ double Item_func_numhybrid::val_real()
return (double)int_op(); return (double)int_op();
case REAL_RESULT: case REAL_RESULT:
return real_op(); return real_op();
case STRING_RESULT:
{
char *end_not_used;
int err_not_used;
String *res= str_op(&str_value);
return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
&end_not_used, &err_not_used) : 0.0);
}
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
...@@ -865,6 +875,15 @@ longlong Item_func_numhybrid::val_int() ...@@ -865,6 +875,15 @@ longlong Item_func_numhybrid::val_int()
return int_op(); return int_op();
case REAL_RESULT: case REAL_RESULT:
return (longlong)real_op(); return (longlong)real_op();
case STRING_RESULT:
{
char *end_not_used;
int err_not_used;
String *res= str_op(&str_value);
CHARSET_INFO *cs= str_value.charset();
return (res ? (*(cs->cset->strtoll10))(cs, res->ptr(), &end_not_used,
&err_not_used) : 0);
}
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
...@@ -893,6 +912,12 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value) ...@@ -893,6 +912,12 @@ my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
break; break;
} }
case STRING_RESULT: case STRING_RESULT:
{
String *res= str_op(&str_value);
str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
res->length(), res->charset(), decimal_value);
break;
}
case ROW_RESULT: case ROW_RESULT:
default: default:
DBUG_ASSERT(0); DBUG_ASSERT(0);
...@@ -2325,9 +2350,6 @@ longlong Item_func_field::val_int() ...@@ -2325,9 +2350,6 @@ longlong Item_func_field::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (args[0]->is_null())
return 0;
if (cmp_type == STRING_RESULT) if (cmp_type == STRING_RESULT)
{ {
String *field; String *field;
...@@ -2343,6 +2365,8 @@ longlong Item_func_field::val_int() ...@@ -2343,6 +2365,8 @@ longlong Item_func_field::val_int()
else if (cmp_type == INT_RESULT) else if (cmp_type == INT_RESULT)
{ {
longlong val= args[0]->val_int(); longlong val= args[0]->val_int();
if (args[0]->null_value)
return 0;
for (uint i=1; i < arg_count ; i++) for (uint i=1; i < arg_count ; i++)
{ {
if (!args[i]->is_null() && val == args[i]->val_int()) if (!args[i]->is_null() && val == args[i]->val_int())
...@@ -2353,6 +2377,8 @@ longlong Item_func_field::val_int() ...@@ -2353,6 +2377,8 @@ longlong Item_func_field::val_int()
{ {
my_decimal dec_arg_buf, *dec_arg, my_decimal dec_arg_buf, *dec_arg,
dec_buf, *dec= args[0]->val_decimal(&dec_buf); dec_buf, *dec= args[0]->val_decimal(&dec_buf);
if (args[0]->null_value)
return 0;
for (uint i=1; i < arg_count; i++) for (uint i=1; i < arg_count; i++)
{ {
dec_arg= args[i]->val_decimal(&dec_arg_buf); dec_arg= args[i]->val_decimal(&dec_arg_buf);
...@@ -2363,6 +2389,8 @@ longlong Item_func_field::val_int() ...@@ -2363,6 +2389,8 @@ longlong Item_func_field::val_int()
else else
{ {
double val= args[0]->val_real(); double val= args[0]->val_real();
if (args[0]->null_value)
return 0;
for (uint i=1; i < arg_count ; i++) for (uint i=1; i < arg_count ; i++)
{ {
if (!args[i]->is_null() && val == args[i]->val_real()) if (!args[i]->is_null() && val == args[i]->val_real())
......
...@@ -189,10 +189,13 @@ class Item_func_numhybrid: public Item_func ...@@ -189,10 +189,13 @@ class Item_func_numhybrid: public Item_func
protected: protected:
Item_result hybrid_type; Item_result hybrid_type;
public: public:
Item_func_numhybrid(Item *a) :Item_func(a),hybrid_type(REAL_RESULT) Item_func_numhybrid(Item *a) :Item_func(a), hybrid_type(REAL_RESULT)
{} {}
Item_func_numhybrid(Item *a,Item *b) Item_func_numhybrid(Item *a,Item *b)
:Item_func(a,b),hybrid_type(REAL_RESULT) :Item_func(a,b), hybrid_type(REAL_RESULT)
{}
Item_func_numhybrid(List<Item> &list)
:Item_func(list), hybrid_type(REAL_RESULT)
{} {}
enum Item_result result_type () const { return hybrid_type; } enum Item_result result_type () const { return hybrid_type; }
...@@ -208,6 +211,7 @@ class Item_func_numhybrid: public Item_func ...@@ -208,6 +211,7 @@ class Item_func_numhybrid: public Item_func
virtual longlong int_op()= 0; virtual longlong int_op()= 0;
virtual double real_op()= 0; virtual double real_op()= 0;
virtual my_decimal *decimal_op(my_decimal *)= 0; virtual my_decimal *decimal_op(my_decimal *)= 0;
virtual String *str_op(String *)= 0;
bool is_null() { (void) val_real(); return null_value; } bool is_null() { (void) val_real(); return null_value; }
}; };
...@@ -220,6 +224,7 @@ class Item_func_num1: public Item_func_numhybrid ...@@ -220,6 +224,7 @@ class Item_func_num1: public Item_func_numhybrid
void fix_num_length_and_dec(); void fix_num_length_and_dec();
void find_num_type(); void find_num_type();
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
}; };
...@@ -231,6 +236,7 @@ class Item_num_op :public Item_func_numhybrid ...@@ -231,6 +236,7 @@ class Item_num_op :public Item_func_numhybrid
virtual void result_precision()= 0; virtual void result_precision()= 0;
void print(String *str) { print_op(str); } void print(String *str) { print_op(str); }
void find_num_type(); void find_num_type();
String *str_op(String *str) { DBUG_ASSERT(0); return 0; }
}; };
......
...@@ -28,7 +28,7 @@ template <uint default_width> class Bitmap ...@@ -28,7 +28,7 @@ template <uint default_width> class Bitmap
uchar buffer[(default_width+7)/8]; uchar buffer[(default_width+7)/8];
public: public:
Bitmap() { init(); } Bitmap() { init(); }
Bitmap(Bitmap& from) { *this=from; } Bitmap(const Bitmap& from) { *this=from; }
explicit Bitmap(uint prefix_to_set) { init(prefix_to_set); } explicit Bitmap(uint prefix_to_set) { init(prefix_to_set); }
void init() { bitmap_init(&map, buffer, default_width, 0); } void init() { bitmap_init(&map, buffer, default_width, 0); }
void init(uint prefix_to_set) { init(); set_prefix(prefix_to_set); } void init(uint prefix_to_set) { init(); set_prefix(prefix_to_set); }
...@@ -61,18 +61,17 @@ template <uint default_width> class Bitmap ...@@ -61,18 +61,17 @@ template <uint default_width> class Bitmap
my_bool operator==(const Bitmap& map2) const { return bitmap_cmp(&map, &map2.map); } my_bool operator==(const Bitmap& map2) const { return bitmap_cmp(&map, &map2.map); }
char *print(char *buf) const char *print(char *buf) const
{ {
char *s=buf; int i; char *s=buf;
for (i=sizeof(buffer)-1; i>=0 ; i--) const uchar *e=buffer, *b=e+sizeof(buffer)-1;
while (!*b && b>e)
b--;
if ((*s=_dig_vec_upper[*b >> 4]) != '0')
s++;
*s++=_dig_vec_upper[*b & 15];
while (--b>=e)
{ {
if ((*s=_dig_vec_upper[buffer[i] >> 4]) != '0') *s++=_dig_vec_upper[*b >> 4];
break; *s++=_dig_vec_upper[*b & 15];
if ((*s=_dig_vec_upper[buffer[i] & 15]) != '0')
break;
}
for (s++, i-- ; i>=0 ; i--)
{
*s++=_dig_vec_upper[buffer[i] >> 4];
*s++=_dig_vec_upper[buffer[i] & 15];
} }
*s=0; *s=0;
return buf; return buf;
......
...@@ -5799,6 +5799,7 @@ make_join_readinfo(JOIN *join, uint options) ...@@ -5799,6 +5799,7 @@ make_join_readinfo(JOIN *join, uint options)
if (!table->no_keyread) if (!table->no_keyread)
{ {
if (tab->select && tab->select->quick && if (tab->select && tab->select->quick &&
tab->select->quick->index != MAX_KEY && //not index_merge
table->used_keys.is_set(tab->select->quick->index)) table->used_keys.is_set(tab->select->quick->index))
{ {
table->key_read=1; table->key_read=1;
......
...@@ -7455,12 +7455,16 @@ static void test_explain_bug() ...@@ -7455,12 +7455,16 @@ static void test_explain_bug()
verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING, verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN, 0); "", "", "", NAME_LEN, 0);
verify_prepare_field(result, 6, "key_len", "", if (mysql_get_server_version(mysql) <= 50000)
(mysql_get_server_version(mysql) <= 50000 ? {
MYSQL_TYPE_LONGLONG : MYSQL_TYPE_VAR_STRING), verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_LONGLONG, "",
"", "", "", "", "", 3, 0);
(mysql_get_server_version(mysql) <= 50000 ? 3 : 4096), }
0); else
{
verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING, "",
"", "", NAME_LEN*MAX_KEY, 0);
}
verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING, verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN*16, 0); "", "", "", NAME_LEN*16, 0);
......
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