Commit df323421 authored by Igor Babaev's avatar Igor Babaev

Fixed LP bug #668290.

Prohibited to use hash join algorithm BNLH if join attributes
need non-binary collations. It has to be done because BNLH does
not support join for such attributes yet.
Later this limitations will be lifted.

Changed default collations for the schemes of some test cases
to preserve the old execution plans.
parent 0b72fd88
......@@ -6,7 +6,7 @@ CREATE TABLE Country (
Capital int(11) default NULL,
PRIMARY KEY (Code),
UNIQUE INDEX (Name)
);
) COLLATE latin1_bin;
CREATE TABLE City (
ID int(11) NOT NULL auto_increment,
Name char(35) NOT NULL default '',
......@@ -15,11 +15,11 @@ CREATE TABLE City (
PRIMARY KEY (ID),
INDEX (Population),
INDEX (Country)
);
) COLLATE latin1_bin;
CREATE TABLE CountryLanguage (
Country char(3) NOT NULL default '',
Language char(30) NOT NULL default '',
Percentage float(3,1) NOT NULL default '0.0',
PRIMARY KEY (Country, Language),
INDEX (Percentage)
);
) COLLATE latin1_bin;
......@@ -4,15 +4,15 @@ CREATE TABLE Country (
SurfaceArea float(10,2) NOT NULL default '0.00',
Population int(11) NOT NULL default '0',
Capital int(11) default NULL
);
) COLLATE latin1_bin;
CREATE TABLE City (
ID int(11) NOT NULL,
Name char(35) NOT NULL default '',
Country char(3) NOT NULL default '',
Population int(11) NOT NULL default '0'
);
) COLLATE latin1_bin;
CREATE TABLE CountryLanguage (
Country char(3) NOT NULL default '',
Language char(30) NOT NULL default '',
Percentage float(3,1) NOT NULL default '0.0'
);
) COLLATE latin1_bin;
......@@ -12,18 +12,18 @@ Name char(52) NOT NULL default '',
SurfaceArea float(10,2) NOT NULL default '0.00',
Population int(11) NOT NULL default '0',
Capital int(11) default NULL
);
) COLLATE latin1_bin;
CREATE TABLE City (
ID int(11) NOT NULL,
Name char(35) NOT NULL default '',
Country char(3) NOT NULL default '',
Population int(11) NOT NULL default '0'
);
) COLLATE latin1_bin;
CREATE TABLE CountryLanguage (
Country char(3) NOT NULL default '',
Language char(30) NOT NULL default '',
Percentage float(3,1) NOT NULL default '0.0'
);
) COLLATE latin1_bin;
SELECT COUNT(*) FROM Country;
COUNT(*)
239
......@@ -810,7 +810,7 @@ Population int(11) NOT NULL default '0',
Capital int(11) default NULL,
PRIMARY KEY (Code),
UNIQUE INDEX (Name)
);
) COLLATE latin1_bin;
CREATE TABLE City (
ID int(11) NOT NULL auto_increment,
Name char(35) NOT NULL default '',
......@@ -819,14 +819,14 @@ Population int(11) NOT NULL default '0',
PRIMARY KEY (ID),
INDEX (Population),
INDEX (Country)
);
) COLLATE latin1_bin;
CREATE TABLE CountryLanguage (
Country char(3) NOT NULL default '',
Language char(30) NOT NULL default '',
Percentage float(3,1) NOT NULL default '0.0',
PRIMARY KEY (Country, Language),
INDEX (Percentage)
);
) COLLATE latin1_bin;
show variables like 'join_buffer_size';
Variable_name Value
join_buffer_size 131072
......@@ -5469,7 +5469,7 @@ SET SESSION join_buffer_size=DEFAULT;
CREATE TABLE t1 (
pk int NOT NULL, i int NOT NULL, v varchar(1) NOT NULL,
PRIMARY KEY (pk), INDEX idx1(i), INDEX idx2 (v,i)
);
) COLLATE latin1_bin;
INSERT INTO t1 VALUES
(10,8,'v'), (11,8,'f'), (12,5,'v'), (13,8,'s'), (14,8,'a'),
(15,6,'p'), (16,7,'z'), (17,2,'a'), (18,5,'h'), (19,7,'h'),
......@@ -5477,16 +5477,16 @@ INSERT INTO t1 VALUES
CREATE TABLE t2 (
pk int NOT NULL, i int NOT NULL, v varchar(1) NOT NULL,
PRIMARY KEY (pk), INDEX idx1(i), INDEX idx2(v,i)
);
) COLLATE latin1_bin;
INSERT INTO t2 VALUES
(10,8,'v'), (11,8,'f'), (12,5,'v'), (13,8,'s'), (14,8,'a'),
(15,6,'p'), (16,7,'z'), (17,2,'a'), (18,5,'h'), (19,7,'h'),
(20,2,'v'), (21,9,'v'), (22,142,'b'), (23,3,'y'), (24,0,'v'),
(25,3,'m'), (26,5,'z'), (27,9,'n'), (28,1,'d'), (29,107,'a');
CREATE TABLE t3 (
pk int NOT NULL, i int(11) NOT NULL, v varchar(1) NOT NULL,
pk int NOT NULL, i int NOT NULL, v varchar(1) NOT NULL,
PRIMARY KEY (pk), INDEX idx1(i), INDEX idx2(v,i)
);
) COLLATE latin1_bin;
INSERT INTO t3 VALUES
(1,9,'x'), (2,5,'g'), (3,1,'o'), (4,0,'g'), (5,1,'v'),
(6,190,'m'), (7,6,'x'), (8,3,'c'), (9,4,'z'), (10,3,'i'),
......@@ -5542,4 +5542,51 @@ v
p
DROP TABLE t1,t2,t3;
SET SESSION join_cache_level=DEFAULT;
#
# Bug #668290: hash join with non-binary collations
#
CREATE TABLE t1 (
i int DEFAULT NULL,
cl varchar(10) CHARACTER SET latin1 DEFAULT NULL,
cu varchar(10) CHARACTER SET utf8 DEFAULT NULL,
INDEX cl (cl),
INDEX cu (cu)
);
INSERT INTO t1 VALUES
(650903552,'cmxffkpsel','z'), (535298048,'tvtjrcmxff','y'),
(1626865664,'when','for'), (39649280,'rcvljitvtj','ercvljitvt'),
(792068096,'ttercvljit','jttercvlji');
INSERT INTO t1 SELECT * FROM t1;
CREATE TABLE t2 (
cu varchar(10) CHARACTER SET utf8 DEFAULT NULL,
i int DEFAULT NULL,
cl varchar(10) CHARACTER SET latin1 DEFAULT NULL,
INDEX cu (cu),
INDEX cl (cl)
);
INSERT INTO t2 VALUES
('g',7,'like'), ('fujttercvl',6,'y'),
('s',2,'e'), ('didn\'t',0,'v'),
('gvdrodpedk',8,'chogvdrodp'), ('jichogvdro',7,'will');
EXPLAIN
SELECT t2.i FROM t1,t2 WHERE t1.cu = t2.cl ;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 6
1 SIMPLE t1 ref cu cu 33 func 2 Using where; Using index
SELECT t2.i FROM t1,t2 WHERE t1.cu = t2.cl ;
i
6
6
SET SESSION join_cache_level = 4;
EXPLAIN
SELECT t2.i FROM t1,t2 WHERE t1.cu = t2.cl ;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 6
1 SIMPLE t1 ref cu cu 33 func 2 Using where; Using index
SELECT t2.i FROM t1,t2 WHERE t1.cu = t2.cl ;
i
6
6
SET SESSION join_cache_level = DEFAULT;
DROP TABLE t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
......@@ -2192,7 +2192,7 @@ SET SESSION join_buffer_size=DEFAULT;
CREATE TABLE t1 (
pk int NOT NULL, i int NOT NULL, v varchar(1) NOT NULL,
PRIMARY KEY (pk), INDEX idx1(i), INDEX idx2 (v,i)
);
) COLLATE latin1_bin;
INSERT INTO t1 VALUES
(10,8,'v'), (11,8,'f'), (12,5,'v'), (13,8,'s'), (14,8,'a'),
(15,6,'p'), (16,7,'z'), (17,2,'a'), (18,5,'h'), (19,7,'h'),
......@@ -2201,7 +2201,7 @@ INSERT INTO t1 VALUES
CREATE TABLE t2 (
pk int NOT NULL, i int NOT NULL, v varchar(1) NOT NULL,
PRIMARY KEY (pk), INDEX idx1(i), INDEX idx2(v,i)
);
) COLLATE latin1_bin;
INSERT INTO t2 VALUES
(10,8,'v'), (11,8,'f'), (12,5,'v'), (13,8,'s'), (14,8,'a'),
(15,6,'p'), (16,7,'z'), (17,2,'a'), (18,5,'h'), (19,7,'h'),
......@@ -2209,9 +2209,9 @@ INSERT INTO t2 VALUES
(25,3,'m'), (26,5,'z'), (27,9,'n'), (28,1,'d'), (29,107,'a');
CREATE TABLE t3 (
pk int NOT NULL, i int(11) NOT NULL, v varchar(1) NOT NULL,
pk int NOT NULL, i int NOT NULL, v varchar(1) NOT NULL,
PRIMARY KEY (pk), INDEX idx1(i), INDEX idx2(v,i)
);
) COLLATE latin1_bin;
INSERT INTO t3 VALUES
(1,9,'x'), (2,5,'g'), (3,1,'o'), (4,0,'g'), (5,1,'v'),
(6,190,'m'), (7,6,'x'), (8,3,'c'), (9,4,'z'), (10,3,'i'),
......@@ -2243,5 +2243,48 @@ DROP TABLE t1,t2,t3;
SET SESSION join_cache_level=DEFAULT;
--echo #
--echo # Bug #668290: hash join with non-binary collations
--echo #
CREATE TABLE t1 (
i int DEFAULT NULL,
cl varchar(10) CHARACTER SET latin1 DEFAULT NULL,
cu varchar(10) CHARACTER SET utf8 DEFAULT NULL,
INDEX cl (cl),
INDEX cu (cu)
);
INSERT INTO t1 VALUES
(650903552,'cmxffkpsel','z'), (535298048,'tvtjrcmxff','y'),
(1626865664,'when','for'), (39649280,'rcvljitvtj','ercvljitvt'),
(792068096,'ttercvljit','jttercvlji');
INSERT INTO t1 SELECT * FROM t1;
CREATE TABLE t2 (
cu varchar(10) CHARACTER SET utf8 DEFAULT NULL,
i int DEFAULT NULL,
cl varchar(10) CHARACTER SET latin1 DEFAULT NULL,
INDEX cu (cu),
INDEX cl (cl)
);
INSERT INTO t2 VALUES
('g',7,'like'), ('fujttercvl',6,'y'),
('s',2,'e'), ('didn\'t',0,'v'),
('gvdrodpedk',8,'chogvdrodp'), ('jichogvdro',7,'will');
EXPLAIN
SELECT t2.i FROM t1,t2 WHERE t1.cu = t2.cl ;
SELECT t2.i FROM t1,t2 WHERE t1.cu = t2.cl ;
SET SESSION join_cache_level = 4;
EXPLAIN
SELECT t2.i FROM t1,t2 WHERE t1.cu = t2.cl ;
SELECT t2.i FROM t1,t2 WHERE t1.cu = t2.cl ;
SET SESSION join_cache_level = DEFAULT;
DROP TABLE t1,t2;
# this must be the last command in the file
set @@optimizer_switch=@save_optimizer_switch;
......@@ -585,6 +585,10 @@ public:
}
/* Hash value */
virtual void hash(ulong *nr, ulong *nr2);
/* Check whether the field can be used as a join attribute in hash join */
virtual bool hash_join_is_possible() { return TRUE; }
friend bool reopen_table(THD *,struct st_table *,bool);
friend int cre_myisam(char * name, register TABLE *form, uint options,
ulonglong auto_increment_value);
......@@ -760,6 +764,12 @@ public:
my_decimal *val_decimal(my_decimal *);
virtual bool str_needs_quotes() { return TRUE; }
uint is_equal(Create_field *new_field);
bool hash_join_is_possible()
{
/* TODO: support hash joins for non-binary collations */
return (flags & BINARY_FLAG);
}
};
......@@ -1904,6 +1914,7 @@ public:
uint size_of() const { return sizeof(*this); }
int reset(void) { return !maybe_null() || Field_blob::reset(); }
geometry_type get_geometry_type() { return geom_type; };
bool hash_join_is_possible() { return FALSE; }
};
#endif /*HAVE_SPATIAL*/
......
......@@ -5946,6 +5946,39 @@ void JOIN_TAB::calc_used_field_length(bool max_fl)
}
/**
@brief
Check whether hash join algorithm can be used to join this table
@details
This function finds out whether the ref items that have been chosen
by the planner to access this table can be used for hash join algorithms.
The answer depends on a certain property of the the fields of the
joined tables on which the hash join key is built. If hash join is
allowed for all these fields the answer is positive.
@note
The function is supposed to be called now only after the function
get_best_combination has been called.
@retval TRUE it's possible to use hash join to join this table
@retval FALSE otherwise
*/
bool JOIN_TAB::hash_join_is_possible()
{
if (type != JT_REF && type != JT_EQ_REF)
return FALSE;
KEY *keyinfo= &table->key_info[ref.key];
for (uint i= 0; i < ref.key_parts; i++)
{
if (!keyinfo->key_part[i].field->hash_join_is_possible())
return FALSE;
}
return TRUE;
}
static uint
cache_record_length(JOIN *join,uint idx)
{
......@@ -7649,8 +7682,10 @@ uint check_join_cache_usage(JOIN_TAB *tab,
&bufsz, &flags, &cost);
if ((cache_level <=4 && !no_hashed_cache) || no_bka_cache ||
(flags & HA_MRR_NO_ASSOCIATION) && cache_level <=6)
((flags & HA_MRR_NO_ASSOCIATION) && cache_level <=6))
{
if (!tab->hash_join_is_possible())
goto no_join_cache;
if (cache_level == 3)
prev_cache= 0;
if ((tab->cache= new JOIN_CACHE_BNLH(join, tab, prev_cache)) &&
......
......@@ -391,6 +391,7 @@ typedef struct st_join_table {
return max_used_fieldlength;
}
double get_partial_join_cardinality() { return partial_join_cardinality; }
bool hash_join_is_possible();
} JOIN_TAB;
......
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