Commit 91d3299c authored by unknown's avatar unknown

Merge olga.mysql.com:/home/igor/mysql-5.0-opt

into  olga.mysql.com:/home/igor/mysql-5.1-opt


mysql-test/r/distinct.result:
  Auto merged
mysql-test/r/row.result:
  Auto merged
mysql-test/r/select.result:
  Auto merged
mysql-test/r/strict.result:
  Auto merged
mysql-test/t/select.test:
  Auto merged
mysql-test/t/strict.test:
  Auto merged
sql/sql_select.cc:
  Auto merged
sql/sql_table.cc:
  Auto merged
sql/item_cmpfunc.cc:
  Manual merge
parents 37feda25 7c4db88a
...@@ -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
...@@ -69,56 +69,80 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) ...@@ -69,56 +69,80 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
/* /*
Aggregates result types from the array of items. Compare row signature of two expressions
SYNOPSIS SYNOPSIS:
agg_cmp_type() cmp_row_type()
items array of items to aggregate the type from item1 the first expression
nitems number of items in the array item2 the second expression
DESCRIPTION DESCRIPTION
This function aggregates result types from the array of items. Found type The function checks that two expressions have compatible row signatures
supposed to be used later for comparison of values of these items. i.e. that the number of columns they return are the same and that if they
Aggregation itself is performed by the item_cmp_type() function. 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 Item_result agg_cmp_type(Item **items, uint nitems) static int cmp_row_type(Item* item1, Item* item2)
{ {
uint i; uint n= item1->cols();
Item_result type= items[0]->result_type(); if (item2->check_cols(n))
for (i= 1 ; i < nitems ; i++) return 1;
type= item_cmp_type(type, items[i]->result_type()); for (uint i=0; i<n; i++)
return type; {
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;
} }
/* /*
Collects different types for comparison of first item with each other items Aggregates result types from the array of items.
SYNOPSIS SYNOPSIS:
collect_cmp_types() agg_cmp_type()
items Array of items to collect types 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 collects different result types for comparison of the first This function aggregates result types from the array of items. Found type
item in the list with each of the remaining items in the 'items' array. supposed to be used later for comparison of values of these items.
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 RETURN VALUES
Bitmap of collected types 1 type incompatibility has been detected
0 otherwise
*/ */
static uint collect_cmp_types(Item **items, uint nitems) static int agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems)
{ {
uint i; uint i;
uint found_types; type[0]= items[0]->result_type();
Item_result left_result= items[0]->result_type(); for (i= 1 ; i < nitems ; i++)
DBUG_ASSERT(nitems > 1); {
found_types= 0; type[0]= item_cmp_type(type[0], items[i]->result_type());
for (i= 1; i < nitems ; i++) /*
found_types|= 1<< (uint)item_cmp_type(left_result, When aggregating types of two row expressions we have to check
items[i]->result_type()); that they have the same cardinality and that each component
return found_types; 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;
} }
...@@ -1355,7 +1379,8 @@ void Item_func_between::fix_length_and_dec() ...@@ -1355,7 +1379,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;
...@@ -2060,6 +2085,23 @@ void Item_func_case::fix_length_and_dec() ...@@ -2060,6 +2085,23 @@ void Item_func_case::fix_length_and_dec()
return; return;
} }
} }
found_types= collect_cmp_types(agg, nagg);
for (i= 0; i <= (uint)DECIMAL_RESULT; i++)
{
if (found_types & (1 << i) && !cmp_items[i])
{
DBUG_ASSERT((Item_result)i != ROW_RESULT);
if ((Item_result)i == STRING_RESULT &&
agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV, 1))
return;
if (!(cmp_items[i]=
cmp_item::get_comparator((Item_result)i,
cmp_collation.collation)))
return;
}
}
} }
if (else_expr_num == -1 || args[else_expr_num]->maybe_null) if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
......
...@@ -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