Commit ba607308 authored by tomas@whalegate.ndb.mysql.com's avatar tomas@whalegate.ndb.mysql.com

Merge whalegate.ndb.mysql.com:/home/tomas/mysql-5.1-single-user

into  whalegate.ndb.mysql.com:/home/tomas/mysql-5.1-opt
parents bdd0e454 9de1bbfb
...@@ -668,3 +668,17 @@ NULL ...@@ -668,3 +668,17 @@ NULL
3 3
4 4
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (a INT, b INT);
INSERT INTO t1 VALUES(1,1),(1,2),(1,3);
SELECT DISTINCT a, b FROM t1;
a b
1 1
1 2
1 3
SELECT DISTINCT a, a, b FROM t1;
a a b
1 1 1
1 1 2
1 1 3
DROP TABLE t1;
End of 5.0 tests
...@@ -175,6 +175,24 @@ ROW(2,10) <=> ROW(3,4) ...@@ -175,6 +175,24 @@ ROW(2,10) <=> ROW(3,4)
SELECT ROW(NULL,10) <=> ROW(3,NULL); SELECT ROW(NULL,10) <=> ROW(3,NULL);
ROW(NULL,10) <=> ROW(3,NULL) ROW(NULL,10) <=> ROW(3,NULL)
0 0
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1));
ERROR 21000: Operand should contain 2 column(s)
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1),ROW(1,ROW(2,3)));
ERROR 21000: Operand should contain 2 column(s)
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,ROW(2,2,2)));
ERROR 21000: Operand should contain 2 column(s)
SELECT ROW(1,ROW(2,3,4)) IN (ROW(1,ROW(2,3,4)),ROW(1,ROW(2,2)));
ERROR 21000: Operand should contain 3 column(s)
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1));
ERROR 21000: Operand should contain 2 column(s)
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1),ROW(1,ROW(2,4)));
ERROR 21000: Operand should contain 2 column(s)
SELECT ROW(1,ROW(2,3)) IN ((SELECT 1,1),ROW(1,ROW(2,3)));
ERROR 21000: Operand should contain 2 column(s)
SELECT ROW(2,1) IN (ROW(21,2),ROW(ROW(1,1,3),0));
ERROR 21000: Operand should contain 1 column(s)
SELECT ROW(2,1) IN (ROW(ROW(1,1,3),0),ROW(21,2));
ERROR 21000: Operand should contain 1 column(s)
SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ; SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ;
1 0 0 0 null 1 0 0 0 null
1 0 0 0 NULL 1 0 0 0 NULL
......
...@@ -3971,4 +3971,13 @@ t2.access_id IN (1,4) AND t.access_id IS NULL AND t2.faq_id in (265); ...@@ -3971,4 +3971,13 @@ t2.access_id IN (1,4) AND t.access_id IS NULL AND t2.faq_id in (265);
faq_id faq_id
265 265
DROP TABLE t1,t2; DROP TABLE t1,t2;
CREATE TABLE t1 (a INT, b INT, KEY inx (b,a));
INSERT INTO t1 VALUES (1,1), (1,2), (1,3), (1,4), (1,5), (1, 6), (1,7);
EXPLAIN SELECT COUNT(*) FROM t1 f1 INNER JOIN t1 f2
ON ( f1.b=f2.b AND f1.a<f2.a )
WHERE 1 AND f1.b NOT IN (100,2232,3343,51111);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE f1 index inx inx 10 NULL 7 Using where; Using index
1 SIMPLE f2 ref inx inx 5 test.f1.b 1 Using where; Using index
DROP TABLE t1;
End of 5.0 tests End of 5.0 tests
...@@ -1386,4 +1386,9 @@ ERROR 01000: Data truncated for column 'a' at row 1 ...@@ -1386,4 +1386,9 @@ ERROR 01000: Data truncated for column 'a' at row 1
insert into t1 values ('2E3x'); insert into t1 values ('2E3x');
ERROR 01000: Data truncated for column 'a' at row 1 ERROR 01000: Data truncated for column 'a' at row 1
drop table t1; drop table t1;
set sql_mode='traditional';
create table t1 (f1 set('a','a'));
ERROR HY000: Column 'f1' has duplicated value 'a' in SET
create table t1 (f1 enum('a','a'));
ERROR HY000: Column 'f1' has duplicated value 'a' in ENUM
End of 5.0 tests End of 5.0 tests
...@@ -540,3 +540,16 @@ EXPLAIN SELECT a FROM t1 GROUP BY a; ...@@ -540,3 +540,16 @@ EXPLAIN SELECT a FROM t1 GROUP BY a;
SELECT a FROM t1 GROUP BY a; SELECT a FROM t1 GROUP BY a;
DROP TABLE t1; DROP TABLE t1;
#
#Bug #27659: SELECT DISTINCT returns incorrect result set when field is
#repeated
#
#
CREATE TABLE t1 (a INT, b INT);
INSERT INTO t1 VALUES(1,1),(1,2),(1,3);
SELECT DISTINCT a, b FROM t1;
SELECT DISTINCT a, a, b FROM t1;
DROP TABLE t1;
--echo End of 5.0 tests
...@@ -85,6 +85,31 @@ drop table t1; ...@@ -85,6 +85,31 @@ drop table t1;
SELECT ROW(2,10) <=> ROW(3,4); SELECT ROW(2,10) <=> ROW(3,4);
SELECT ROW(NULL,10) <=> ROW(3,NULL); SELECT ROW(NULL,10) <=> ROW(3,NULL);
#
# Bug #27484: nested row expressions in IN predicate
#
--error 1241
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1));
--error 1241
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1),ROW(1,ROW(2,3)));
--error 1241
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,ROW(2,2,2)));
--error 1241
SELECT ROW(1,ROW(2,3,4)) IN (ROW(1,ROW(2,3,4)),ROW(1,ROW(2,2)));
--error 1241
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1));
--error 1241
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1),ROW(1,ROW(2,4)));
--error 1241
SELECT ROW(1,ROW(2,3)) IN ((SELECT 1,1),ROW(1,ROW(2,3)));
--error 1241
SELECT ROW(2,1) IN (ROW(21,2),ROW(ROW(1,1,3),0));
--error 1241
SELECT ROW(2,1) IN (ROW(ROW(1,1,3),0),ROW(21,2));
# End of 4.1 tests # End of 4.1 tests
# #
......
...@@ -3346,4 +3346,17 @@ SELECT t2.faq_id ...@@ -3346,4 +3346,17 @@ SELECT t2.faq_id
DROP TABLE t1,t2; DROP TABLE t1,t2;
#
# Bug #19372: Optimizer does not use index anymore when WHERE index NOT IN
# () is added
#
CREATE TABLE t1 (a INT, b INT, KEY inx (b,a));
INSERT INTO t1 VALUES (1,1), (1,2), (1,3), (1,4), (1,5), (1, 6), (1,7);
EXPLAIN SELECT COUNT(*) FROM t1 f1 INNER JOIN t1 f2
ON ( f1.b=f2.b AND f1.a<f2.a )
WHERE 1 AND f1.b NOT IN (100,2232,3343,51111);
DROP TABLE t1;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -1249,4 +1249,13 @@ insert into t1 values ('2000a'); ...@@ -1249,4 +1249,13 @@ insert into t1 values ('2000a');
insert into t1 values ('2E3x'); insert into t1 values ('2E3x');
drop table t1; drop table t1;
#
# Bug#27069 set with identical elements are created
#
set sql_mode='traditional';
--error 1291
create table t1 (f1 set('a','a'));
--error 1291
create table t1 (f1 enum('a','a'));
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -68,27 +68,81 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) ...@@ -68,27 +68,81 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
} }
/*
Compare row signature of two expressions
SYNOPSIS:
cmp_row_type()
item1 the first expression
item2 the second expression
DESCRIPTION
The function checks that two expressions have compatible row signatures
i.e. that the number of columns they return are the same and that if they
are both row expressions then each component from the first expression has
a row signature compatible with the signature of the corresponding component
of the second expression.
RETURN VALUES
1 type incompatibility has been detected
0 otherwise
*/
static int cmp_row_type(Item* item1, Item* item2)
{
uint n= item1->cols();
if (item2->check_cols(n))
return 1;
for (uint i=0; i<n; i++)
{
if (item2->element_index(i)->check_cols(item1->element_index(i)->cols()) ||
(item1->element_index(i)->result_type() == ROW_RESULT &&
cmp_row_type(item1->element_index(i), item2->element_index(i))))
return 1;
}
return 0;
}
/* /*
Aggregates result types from the array of items. Aggregates result types from the array of items.
SYNOPSIS SYNOPSIS:
agg_cmp_type() agg_cmp_type()
items array of items to aggregate the type from type [out] the aggregated type
nitems number of items in the array items array of items to aggregate the type from
nitems number of items in the array
DESCRIPTION DESCRIPTION
This function aggregates result types from the array of items. Found type This function aggregates result types from the array of items. Found type
supposed to be used later for comparison of values of these items. supposed to be used later for comparison of values of these items.
Aggregation itself is performed by the item_cmp_type() function. Aggregation itself is performed by the item_cmp_type() function.
The function also checks compatibility of row signatures for the
submitted items (see the spec for the cmp_row_type function).
RETURN VALUES
1 type incompatibility has been detected
0 otherwise
*/ */
static Item_result agg_cmp_type(Item **items, uint nitems) static int agg_cmp_type(Item_result *type, Item **items, uint nitems)
{ {
uint i; uint i;
Item_result type= items[0]->result_type(); type[0]= items[0]->result_type();
for (i= 1 ; i < nitems ; i++) for (i= 1 ; i < nitems ; i++)
type= item_cmp_type(type, items[i]->result_type()); {
return type; type[0]= item_cmp_type(type[0], items[i]->result_type());
/*
When aggregating types of two row expressions we have to check
that they have the same cardinality and that each component
of the first row expression has a compatible row signature with
the signature of the corresponding component of the second row
expression.
*/
if (type[0] == ROW_RESULT && cmp_row_type(items[0], items[i]))
return 1; // error found: invalid usage of rows
}
return 0;
} }
...@@ -105,7 +159,8 @@ static Item_result agg_cmp_type(Item **items, uint nitems) ...@@ -105,7 +159,8 @@ static Item_result agg_cmp_type(Item **items, uint nitems)
item in the list with each of the remaining items in the 'items' array. item in the list with each of the remaining items in the 'items' array.
RETURN RETURN
Bitmap of collected types 0 - if row type incompatibility has been detected (see cmp_row_type)
Bitmap of collected types - otherwise
*/ */
static uint collect_cmp_types(Item **items, uint nitems) static uint collect_cmp_types(Item **items, uint nitems)
...@@ -116,12 +171,17 @@ static uint collect_cmp_types(Item **items, uint nitems) ...@@ -116,12 +171,17 @@ static uint collect_cmp_types(Item **items, uint nitems)
DBUG_ASSERT(nitems > 1); DBUG_ASSERT(nitems > 1);
found_types= 0; found_types= 0;
for (i= 1; i < nitems ; i++) for (i= 1; i < nitems ; i++)
{
if ((left_result == ROW_RESULT ||
items[i]->result_type() == ROW_RESULT) &&
cmp_row_type(items[0], items[i]))
return 0;
found_types|= 1<< (uint)item_cmp_type(left_result, found_types|= 1<< (uint)item_cmp_type(left_result,
items[i]->result_type()); items[i]->result_type());
}
return found_types; return found_types;
} }
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
const char *fname) const char *fname)
{ {
...@@ -1355,7 +1415,8 @@ void Item_func_between::fix_length_and_dec() ...@@ -1355,7 +1415,8 @@ void Item_func_between::fix_length_and_dec()
*/ */
if (!args[0] || !args[1] || !args[2]) if (!args[0] || !args[1] || !args[2])
return; return;
cmp_type= agg_cmp_type(args, 3); if ( agg_cmp_type(&cmp_type, args, 3))
return;
if (cmp_type == STRING_RESULT && if (cmp_type == STRING_RESULT &&
agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1)) agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV, 1))
return; return;
...@@ -2044,7 +2105,8 @@ void Item_func_case::fix_length_and_dec() ...@@ -2044,7 +2105,8 @@ void Item_func_case::fix_length_and_dec()
for (nagg= 0; nagg < ncases/2 ; nagg++) for (nagg= 0; nagg < ncases/2 ; nagg++)
agg[nagg+1]= args[nagg*2]; agg[nagg+1]= args[nagg*2];
nagg++; nagg++;
found_types= collect_cmp_types(agg, nagg); if (!(found_types= collect_cmp_types(agg, nagg)))
return;
for (i= 0; i <= (uint)DECIMAL_RESULT; i++) for (i= 0; i <= (uint)DECIMAL_RESULT; i++)
{ {
...@@ -2748,7 +2810,8 @@ void Item_func_in::fix_length_and_dec() ...@@ -2748,7 +2810,8 @@ void Item_func_in::fix_length_and_dec()
uint type_cnt= 0, i; uint type_cnt= 0, i;
Item_result cmp_type= STRING_RESULT; Item_result cmp_type= STRING_RESULT;
left_result_type= args[0]->result_type(); left_result_type= args[0]->result_type();
found_types= collect_cmp_types(args, arg_count); if (!(found_types= collect_cmp_types(args, arg_count)))
return;
for (arg= args + 1, arg_end= args + arg_count; arg != arg_end ; arg++) for (arg= args + 1, arg_end= args + arg_count; arg != arg_end ; arg++)
{ {
......
...@@ -13799,9 +13799,7 @@ create_distinct_group(THD *thd, Item **ref_pointer_array, ...@@ -13799,9 +13799,7 @@ create_distinct_group(THD *thd, Item **ref_pointer_array,
ORDER *ord_iter; ORDER *ord_iter;
for (ord_iter= group; ord_iter; ord_iter= ord_iter->next) for (ord_iter= group; ord_iter; ord_iter= ord_iter->next)
if ((*ord_iter->item)->eq(item, 1)) if ((*ord_iter->item)->eq(item, 1))
break; goto next_item;
if (ord_iter)
continue;
ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER)); ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER));
if (!ord) if (!ord)
...@@ -13816,6 +13814,7 @@ create_distinct_group(THD *thd, Item **ref_pointer_array, ...@@ -13816,6 +13814,7 @@ create_distinct_group(THD *thd, Item **ref_pointer_array,
*prev=ord; *prev=ord;
prev= &ord->next; prev= &ord->next;
} }
next_item:
ref_pointer_array++; ref_pointer_array++;
} }
*prev=0; *prev=0;
......
...@@ -1929,10 +1929,11 @@ static int sort_keys(KEY *a, KEY *b) ...@@ -1929,10 +1929,11 @@ static int sort_keys(KEY *a, KEY *b)
which has some duplicates on its right which has some duplicates on its right
RETURN VALUES RETURN VALUES
void 0 ok
1 Error
*/ */
void check_duplicates_in_interval(const char *set_or_name, bool check_duplicates_in_interval(const char *set_or_name,
const char *name, TYPELIB *typelib, const char *name, TYPELIB *typelib,
CHARSET_INFO *cs, unsigned int *dup_val_count) CHARSET_INFO *cs, unsigned int *dup_val_count)
{ {
...@@ -1948,6 +1949,13 @@ void check_duplicates_in_interval(const char *set_or_name, ...@@ -1948,6 +1949,13 @@ void check_duplicates_in_interval(const char *set_or_name,
tmp.count--; tmp.count--;
if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs)) if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
{ {
if ((current_thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
{
my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
name,*cur_value,set_or_name);
return 1;
}
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE, push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_DUPLICATED_VALUE_IN_TYPE, ER_DUPLICATED_VALUE_IN_TYPE,
ER(ER_DUPLICATED_VALUE_IN_TYPE), ER(ER_DUPLICATED_VALUE_IN_TYPE),
...@@ -1955,6 +1963,7 @@ void check_duplicates_in_interval(const char *set_or_name, ...@@ -1955,6 +1963,7 @@ void check_duplicates_in_interval(const char *set_or_name,
(*dup_val_count)++; (*dup_val_count)++;
} }
} }
return 0;
} }
...@@ -2090,9 +2099,10 @@ int prepare_create_field(create_field *sql_field, ...@@ -2090,9 +2099,10 @@ int prepare_create_field(create_field *sql_field,
if (sql_field->charset->state & MY_CS_BINSORT) if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY; sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::INTERVAL_FIELD; sql_field->unireg_check=Field::INTERVAL_FIELD;
check_duplicates_in_interval("ENUM",sql_field->field_name, if (check_duplicates_in_interval("ENUM",sql_field->field_name,
sql_field->interval, sql_field->interval,
sql_field->charset, &dup_val_count); sql_field->charset, &dup_val_count))
DBUG_RETURN(1);
break; break;
case MYSQL_TYPE_SET: case MYSQL_TYPE_SET:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) | sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
...@@ -2100,9 +2110,10 @@ int prepare_create_field(create_field *sql_field, ...@@ -2100,9 +2110,10 @@ int prepare_create_field(create_field *sql_field,
if (sql_field->charset->state & MY_CS_BINSORT) if (sql_field->charset->state & MY_CS_BINSORT)
sql_field->pack_flag|=FIELDFLAG_BINARY; sql_field->pack_flag|=FIELDFLAG_BINARY;
sql_field->unireg_check=Field::BIT_FIELD; sql_field->unireg_check=Field::BIT_FIELD;
check_duplicates_in_interval("SET",sql_field->field_name, if (check_duplicates_in_interval("SET",sql_field->field_name,
sql_field->interval, sql_field->interval,
sql_field->charset, &dup_val_count); sql_field->charset, &dup_val_count))
DBUG_RETURN(1);
/* Check that count of unique members is not more then 64 */ /* Check that count of unique members is not more then 64 */
if (sql_field->interval->count - dup_val_count > sizeof(longlong)*8) if (sql_field->interval->count - dup_val_count > sizeof(longlong)*8)
{ {
......
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