summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--myisam/mi_check.c14
-rw-r--r--mysql-test/r/ctype_ucs.result21
-rw-r--r--mysql-test/r/ps.result47
-rw-r--r--mysql-test/r/subselect.result36
-rw-r--r--mysql-test/t/ctype_ucs.test21
-rw-r--r--mysql-test/t/ps.test52
-rw-r--r--mysql-test/t/subselect.test37
-rw-r--r--mysys/my_chsize.c4
-rw-r--r--sql/field.h2
-rw-r--r--sql/item.cc1
-rw-r--r--sql/sql_select.cc5
-rw-r--r--sql/unireg.cc39
12 files changed, 265 insertions, 14 deletions
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 1e62e5e641d..301becf9c62 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -1153,9 +1153,12 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
/* We don't need to lock the key tree here as we don't allow
concurrent threads when running myisamchk
*/
- int search_result= (keyinfo->flag & HA_SPATIAL) ?
+ int search_result=
+#ifdef HAVE_RTREE_KEYS
+ (keyinfo->flag & HA_SPATIAL) ?
rtree_find_first(info, key, info->lastkey, key_length,
MBR_EQUAL | MBR_DATA) :
+#endif
_mi_search(info,keyinfo,info->lastkey,key_length,
SEARCH_SAME, info->s->state.key_root[key]);
if (search_result)
@@ -1366,7 +1369,8 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
param->temp_filename);
goto err;
}
- if (filecopy(param,new_file,info->dfile,0L,new_header_length,
+ if (new_header_length &&
+ filecopy(param,new_file,info->dfile,0L,new_header_length,
"datafile-header"))
goto err;
info->s->state.dellink= HA_OFFSET_ERROR;
@@ -2063,7 +2067,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
param->temp_filename);
goto err;
}
- if (filecopy(param, new_file,info->dfile,0L,new_header_length,
+ if (new_header_length &&
+ filecopy(param, new_file,info->dfile,0L,new_header_length,
"datafile-header"))
goto err;
if (param->testflag & T_UNPACK)
@@ -2431,7 +2436,8 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
param->temp_filename);
goto err;
}
- if (filecopy(param, new_file,info->dfile,0L,new_header_length,
+ if (new_header_length &&
+ filecopy(param, new_file,info->dfile,0L,new_header_length,
"datafile-header"))
goto err;
if (param->testflag & T_UNPACK)
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index 24a4ca9a85f..642a0fc13b5 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -747,6 +747,27 @@ select export_set(5, name, upper(name), ",", 5) from bug20536;
export_set(5, name, upper(name), ",", 5)
test1,TEST1,test1,TEST1,TEST1
'test\_2','TEST\_2','test\_2','TEST\_2','TEST\_2'
+CREATE TABLE t1 (
+status enum('active','passive') collate latin1_general_ci
+NOT NULL default 'passive'
+);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `status` enum('active','passive') character set latin1 collate latin1_general_ci NOT NULL default 'passive'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t1 ADD a int NOT NULL AFTER status;
+CREATE TABLE t2 (
+status enum('active','passive') collate ucs2_turkish_ci
+NOT NULL default 'passive'
+);
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `status` enum('active','passive') character set ucs2 collate ucs2_turkish_ci NOT NULL default 'passive'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t2 ADD a int NOT NULL AFTER status;
+DROP TABLE t1,t2;
select password(name) from bug20536;
password(name)
????????????????????
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 01aa4ddf859..78752622db7 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -889,3 +889,50 @@ create temporary table if not exists t1 (a1 int);
execute stmt;
drop temporary table t1;
deallocate prepare stmt;
+CREATE TABLE t1(
+ID int(10) unsigned NOT NULL auto_increment,
+Member_ID varchar(15) NOT NULL default '',
+Action varchar(12) NOT NULL,
+Action_Date datetime NOT NULL,
+Track varchar(15) default NULL,
+User varchar(12) default NULL,
+Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update
+CURRENT_TIMESTAMP,
+PRIMARY KEY (ID),
+KEY Action (Action),
+KEY Action_Date (Action_Date)
+);
+INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES
+('111111', 'Disenrolled', '2006-03-01', 'CAD' ),
+('111111', 'Enrolled', '2006-03-01', 'CAD' ),
+('111111', 'Disenrolled', '2006-07-03', 'CAD' ),
+('222222', 'Enrolled', '2006-03-07', 'CAD' ),
+('222222', 'Enrolled', '2006-03-07', 'CHF' ),
+('222222', 'Disenrolled', '2006-08-02', 'CHF' ),
+('333333', 'Enrolled', '2006-03-01', 'CAD' ),
+('333333', 'Disenrolled', '2006-03-01', 'CAD' ),
+('444444', 'Enrolled', '2006-03-01', 'CAD' ),
+('555555', 'Disenrolled', '2006-03-01', 'CAD' ),
+('555555', 'Enrolled', '2006-07-21', 'CAD' ),
+('555555', 'Disenrolled', '2006-03-01', 'CHF' ),
+('666666', 'Enrolled', '2006-02-09', 'CAD' ),
+('666666', 'Enrolled', '2006-05-12', 'CHF' ),
+('666666', 'Disenrolled', '2006-06-01', 'CAD' );
+PREPARE STMT FROM
+"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1
+ WHERE Member_ID=? AND Action='Enrolled' AND
+ (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1
+ WHERE Member_ID=?
+ GROUP BY Track
+ HAVING Track>='CAD' AND
+ MAX(Action_Date)>'2006-03-01')";
+SET @id='111111';
+EXECUTE STMT USING @id,@id;
+GROUP_CONCAT(Track SEPARATOR ', ')
+NULL
+SET @id='222222';
+EXECUTE STMT USING @id,@id;
+GROUP_CONCAT(Track SEPARATOR ', ')
+CAD
+DEALLOCATE PREPARE STMT;
+DROP TABLE t1;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index ba4de7f6406..ad847b5f156 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -2946,3 +2946,39 @@ ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10;
a a b
10 1 359
drop table t1,t2;
+CREATE TABLE t1 (
+field1 int NOT NULL,
+field2 int NOT NULL,
+field3 int NOT NULL,
+PRIMARY KEY (field1,field2,field3)
+);
+CREATE TABLE t2 (
+fieldA int NOT NULL,
+fieldB int NOT NULL,
+PRIMARY KEY (fieldA,fieldB)
+);
+INSERT INTO t1 VALUES
+(1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,1);
+INSERT INTO t2 VALUES (1,1), (1,2), (1,3);
+SELECT field1, field2, COUNT(*)
+FROM t1 GROUP BY field1, field2;
+field1 field2 COUNT(*)
+1 1 2
+1 2 3
+1 3 1
+SELECT field1, field2
+FROM t1
+GROUP BY field1, field2
+HAVING COUNT(*) >= ALL (SELECT fieldB
+FROM t2 WHERE fieldA = field1);
+field1 field2
+1 2
+SELECT field1, field2
+FROM t1
+GROUP BY field1, field2
+HAVING COUNT(*) < ANY (SELECT fieldB
+FROM t2 WHERE fieldA = field1);
+field1 field2
+1 1
+1 3
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index d96b9938f1b..641080f48ab 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -482,6 +482,27 @@ select make_set(3, name, upper(name)) from bug20536;
select export_set(5, name, upper(name)) from bug20536;
select export_set(5, name, upper(name), ",", 5) from bug20536;
+#
+# Bug #20108: corrupted default enum value for a ucs2 field
+#
+
+CREATE TABLE t1 (
+ status enum('active','passive') collate latin1_general_ci
+ NOT NULL default 'passive'
+);
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 ADD a int NOT NULL AFTER status;
+
+CREATE TABLE t2 (
+ status enum('active','passive') collate ucs2_turkish_ci
+ NOT NULL default 'passive'
+);
+SHOW CREATE TABLE t2;
+ALTER TABLE t2 ADD a int NOT NULL AFTER status;
+
+DROP TABLE t1,t2;
+
+
# Some broken functions: add these tests just to document current behavior.
# PASSWORD and OLD_PASSWORD don't work with UCS2 strings, but to fix it would
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 0ca293eb1ba..7c2a42404ad 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -951,4 +951,56 @@ execute stmt;
drop temporary table t1;
deallocate prepare stmt;
+#
+# BUG#22085: Crash on the execution of a prepared statement that
+# uses an IN subquery with aggregate functions in HAVING
+#
+
+CREATE TABLE t1(
+ ID int(10) unsigned NOT NULL auto_increment,
+ Member_ID varchar(15) NOT NULL default '',
+ Action varchar(12) NOT NULL,
+ Action_Date datetime NOT NULL,
+ Track varchar(15) default NULL,
+ User varchar(12) default NULL,
+ Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update
+ CURRENT_TIMESTAMP,
+ PRIMARY KEY (ID),
+ KEY Action (Action),
+ KEY Action_Date (Action_Date)
+);
+
+INSERT INTO t1(Member_ID, Action, Action_Date, Track) VALUES
+ ('111111', 'Disenrolled', '2006-03-01', 'CAD' ),
+ ('111111', 'Enrolled', '2006-03-01', 'CAD' ),
+ ('111111', 'Disenrolled', '2006-07-03', 'CAD' ),
+ ('222222', 'Enrolled', '2006-03-07', 'CAD' ),
+ ('222222', 'Enrolled', '2006-03-07', 'CHF' ),
+ ('222222', 'Disenrolled', '2006-08-02', 'CHF' ),
+ ('333333', 'Enrolled', '2006-03-01', 'CAD' ),
+ ('333333', 'Disenrolled', '2006-03-01', 'CAD' ),
+ ('444444', 'Enrolled', '2006-03-01', 'CAD' ),
+ ('555555', 'Disenrolled', '2006-03-01', 'CAD' ),
+ ('555555', 'Enrolled', '2006-07-21', 'CAD' ),
+ ('555555', 'Disenrolled', '2006-03-01', 'CHF' ),
+ ('666666', 'Enrolled', '2006-02-09', 'CAD' ),
+ ('666666', 'Enrolled', '2006-05-12', 'CHF' ),
+ ('666666', 'Disenrolled', '2006-06-01', 'CAD' );
+
+PREPARE STMT FROM
+"SELECT GROUP_CONCAT(Track SEPARATOR ', ') FROM t1
+ WHERE Member_ID=? AND Action='Enrolled' AND
+ (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t1
+ WHERE Member_ID=?
+ GROUP BY Track
+ HAVING Track>='CAD' AND
+ MAX(Action_Date)>'2006-03-01')";
+SET @id='111111';
+EXECUTE STMT USING @id,@id;
+SET @id='222222';
+EXECUTE STMT USING @id,@id;
+
+DEALLOCATE PREPARE STMT;
+DROP TABLE t1;
+
# End of 4.1 tests
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 1018b5de005..6defa8b16a5 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1911,4 +1911,41 @@ SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r
drop table t1,t2;
+#
+# Bug #21853: assert failure for a grouping query with
+# an ALL/ANY quantified subquery in HAVING
+#
+
+CREATE TABLE t1 (
+ field1 int NOT NULL,
+ field2 int NOT NULL,
+ field3 int NOT NULL,
+ PRIMARY KEY (field1,field2,field3)
+);
+CREATE TABLE t2 (
+ fieldA int NOT NULL,
+ fieldB int NOT NULL,
+ PRIMARY KEY (fieldA,fieldB)
+);
+
+INSERT INTO t1 VALUES
+ (1,1,1), (1,1,2), (1,2,1), (1,2,2), (1,2,3), (1,3,1);
+INSERT INTO t2 VALUES (1,1), (1,2), (1,3);
+
+SELECT field1, field2, COUNT(*)
+ FROM t1 GROUP BY field1, field2;
+
+SELECT field1, field2
+ FROM t1
+ GROUP BY field1, field2
+ HAVING COUNT(*) >= ALL (SELECT fieldB
+ FROM t2 WHERE fieldA = field1);
+SELECT field1, field2
+ FROM t1
+ GROUP BY field1, field2
+ HAVING COUNT(*) < ANY (SELECT fieldB
+ FROM t2 WHERE fieldA = field1);
+
+DROP TABLE t1, t2;
+
# End of 4.1 tests
diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c
index cf26428d65f..efc19927183 100644
--- a/mysys/my_chsize.c
+++ b/mysys/my_chsize.c
@@ -44,7 +44,9 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
DBUG_PRINT("my",("fd: %d length: %lu MyFlags: %d",fd,(ulong) newlength,
MyFlags));
- oldsize = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
+ if ((oldsize = my_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE))) == newlength)
+ DBUG_RETURN(0);
+
DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize));
if (oldsize > newlength)
diff --git a/sql/field.h b/sql/field.h
index a33cb0a93aa..79fb7ff76d1 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1192,6 +1192,8 @@ public:
uint decimals,flags,pack_length;
Field::utype unireg_check;
TYPELIB *interval; // Which interval to use
+ TYPELIB *save_interval; // Temporary copy for the above
+ // Used only for UCS2 intervals
List<String> interval_list;
CHARSET_INFO *charset;
Field::geometry_type geom_type;
diff --git a/sql/item.cc b/sql/item.cc
index 7c9f6ec77fb..94f0a24fcc3 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -387,6 +387,7 @@ void Item::split_sum_func2(THD *thd, Item **ref_pointer_array,
}
else if ((type() == SUM_FUNC_ITEM ||
(used_tables() & ~PARAM_TABLE_BIT)) &&
+ type() != SUBSELECT_ITEM &&
type() != REF_ITEM)
{
/*
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 02ec7ae08ed..74a9fc573c4 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -290,8 +290,6 @@ JOIN::prepare(Item ***rref_pointer_array,
select_lex->having_fix_field= 0;
if (having_fix_rc || thd->net.report_error)
DBUG_RETURN(-1); /* purecov: inspected */
- if (having->with_sum_func)
- having->split_sum_func2(thd, ref_pointer_array, all_fields, &having);
}
// Is it subselect
@@ -306,6 +304,9 @@ JOIN::prepare(Item ***rref_pointer_array,
}
}
+ if (having && having->with_sum_func)
+ having->split_sum_func2(thd, ref_pointer_array, all_fields, &having);
+
if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
DBUG_RETURN(-1);
diff --git a/sql/unireg.cc b/sql/unireg.cc
index e3bf763f700..e4fdc77912c 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -190,13 +190,19 @@ bool mysql_create_frm(THD *thd, my_string file_name,
goto err3;
{
- /* Unescape all UCS2 intervals: were escaped in pack_headers */
+ /*
+ Restore all UCS2 intervals.
+ HEX representation of them is not needed anymore.
+ */
List_iterator<create_field> it(create_fields);
create_field *field;
while ((field=it++))
{
- if (field->interval && field->charset->mbminlen > 1)
- unhex_type2(field->interval);
+ if (field->save_interval)
+ {
+ field->interval= field->save_interval;
+ field->save_interval= 0;
+ }
}
}
DBUG_RETURN(0);
@@ -452,18 +458,36 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
reclength=(uint) (field->offset+ data_offset + length);
n_length+= (ulong) strlen(field->field_name)+1;
field->interval_id=0;
+ field->save_interval= 0;
if (field->interval)
{
uint old_int_count=int_count;
if (field->charset->mbminlen > 1)
{
- /* Escape UCS2 intervals using HEX notation */
+ /*
+ Escape UCS2 intervals using HEX notation to avoid
+ problems with delimiters between enum elements.
+ As the original representation is still needed in
+ the function make_empty_rec to create a record of
+ filled with default values it is saved in save_interval
+ The HEX representation is created from this copy.
+ */
+ field->save_interval= field->interval;
+ field->interval= (TYPELIB*) sql_alloc(sizeof(TYPELIB));
+ *field->interval= *field->save_interval;
+ field->interval->type_names=
+ (const char **) sql_alloc(sizeof(char*) *
+ (field->interval->count+1));
+ field->interval->type_names[field->interval->count]= 0;
+ field->interval->type_lengths=
+ (uint *) sql_alloc(sizeof(uint) * field->interval->count);
+
for (uint pos= 0; pos < field->interval->count; pos++)
{
char *dst;
- uint length= field->interval->type_lengths[pos], hex_length;
- const char *src= field->interval->type_names[pos];
+ uint length= field->save_interval->type_lengths[pos], hex_length;
+ const char *src= field->save_interval->type_names[pos];
const char *srcend= src + length;
hex_length= length * 2;
field->interval->type_lengths[pos]= hex_length;
@@ -715,7 +739,8 @@ static bool make_empty_rec(File file,enum db_type table_type,
field->charset,
field->geom_type,
field->unireg_check,
- field->interval,
+ field->save_interval ? field->save_interval :
+ field->interval,
field->field_name,
&table);