Below is the list of changes that have just been committed into a local
5.0 repository of ram. When ram does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-11-23 16:14:29+04:00, ramil@stripped +3 -0
Fix for bug #32560: crash with interval function and count(*)
Problem: INTERVAL function implementation doesn't handle NULL range values.
Fix: skip NULL ranges looking for a proper one.
mysql-test/r/func_set.result@stripped, 2007-11-23 16:14:28+04:00, ramil@stripped +30 -0
Fix for bug #32560: crash with interval function and count(*)
- test result.
mysql-test/t/func_set.test@stripped, 2007-11-23 16:14:28+04:00, ramil@stripped +18 -1
Fix for bug #32560: crash with interval function and count(*)
- test case.
sql/item_cmpfunc.cc@stripped, 2007-11-23 16:14:28+04:00, ramil@stripped +26 -13
Fix for bug #32560: crash with interval function and count(*)
- skip NULL ranges calculating INTERVAL(...).
diff -Nrup a/mysql-test/r/func_set.result b/mysql-test/r/func_set.result
--- a/mysql-test/r/func_set.result 2005-02-19 20:58:20 +04:00
+++ b/mysql-test/r/func_set.result 2007-11-23 16:14:28 +04:00
@@ -73,3 +73,33 @@ find_in_set(binary 'a', 'A,B,C')
select find_in_set('1','3,1,');
find_in_set('1','3,1,')
2
+End of 4.1 tests
+SELECT INTERVAL(0.0, NULL);
+INTERVAL(0.0, NULL)
+1
+SELECT INTERVAL(0.0, CAST(NULL AS DECIMAL));
+INTERVAL(0.0, CAST(NULL AS DECIMAL))
+1
+SELECT INTERVAL(0.0, CAST(DATE(NULL) AS DECIMAL));
+INTERVAL(0.0, CAST(DATE(NULL) AS DECIMAL))
+1
+SELECT INTERVAL(0.0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+INTERVAL(0.0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)
+8
+SELECT INTERVAL(0.0, CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL),
+CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL),
+CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL));
+INTERVAL(0.0, CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL),
+CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL),
+CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL))
+8
+SELECT INTERVAL(0.0, CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL),
+CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL),
+CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL),
+CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL));
+INTERVAL(0.0, CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL),
+CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL),
+CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL),
+CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL))
+8
+End of 5.0 tests
diff -Nrup a/mysql-test/t/func_set.test b/mysql-test/t/func_set.test
--- a/mysql-test/t/func_set.test 2005-07-28 18:12:33 +05:00
+++ b/mysql-test/t/func_set.test 2007-11-23 16:14:28 +04:00
@@ -54,4 +54,21 @@ select find_in_set(binary 'a', 'A,B,C');
#
select find_in_set('1','3,1,');
-# End of 4.1 tests
+--echo End of 4.1 tests
+
+#
+# Bug #32560: crash with interval function and count(*)
+#
+SELECT INTERVAL(0.0, NULL);
+SELECT INTERVAL(0.0, CAST(NULL AS DECIMAL));
+SELECT INTERVAL(0.0, CAST(DATE(NULL) AS DECIMAL));
+SELECT INTERVAL(0.0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+SELECT INTERVAL(0.0, CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL),
+ CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL),
+ CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL), CAST(NULL AS DECIMAL));
+SELECT INTERVAL(0.0, CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL),
+ CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL),
+ CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL),
+ CAST(DATE(NULL) AS DECIMAL), CAST(DATE(NULL) AS DECIMAL));
+
+--echo End of 5.0 tests
diff -Nrup a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
--- a/sql/item_cmpfunc.cc 2007-11-10 23:58:21 +04:00
+++ b/sql/item_cmpfunc.cc 2007-11-23 16:14:28 +04:00
@@ -1638,24 +1638,27 @@ bool Item_func_opt_neg::eq(const Item *i
void Item_func_interval::fix_length_and_dec()
{
+ uint rows= row->cols();
+
use_decimal_comparison= (row->element_index(0)->result_type() == DECIMAL_RESULT) ||
(row->element_index(0)->result_type() == INT_RESULT);
- if (row->cols() > 8)
+ if (rows > 8)
{
- bool consts=1;
+ bool not_null_consts= TRUE;
- for (uint i=1 ; consts && i < row->cols() ; i++)
+ for (uint i= 1; not_null_consts && i < rows; i++)
{
- consts&= row->element_index(i)->const_item();
+ Item *el= row->element_index(i);
+ not_null_consts&= el->const_item() & !el->is_null();
}
- if (consts &&
+ if (not_null_consts &&
(intervals=
- (interval_range*) sql_alloc(sizeof(interval_range)*(row->cols()-1))))
+ (interval_range*) sql_alloc(sizeof(interval_range) * (rows - 1))))
{
if (use_decimal_comparison)
{
- for (uint i=1 ; i < row->cols(); i++)
+ for (uint i= 1; i < rows; i++)
{
Item *el= row->element_index(i);
interval_range *range= intervals + (i-1);
@@ -1680,7 +1683,7 @@ void Item_func_interval::fix_length_and_
}
else
{
- for (uint i=1 ; i < row->cols(); i++)
+ for (uint i= 1; i < rows; i++)
{
intervals[i-1].dbl= row->element_index(i)->val_real();
}
@@ -1771,12 +1774,22 @@ longlong Item_func_interval::val_int()
((el->result_type() == DECIMAL_RESULT) ||
(el->result_type() == INT_RESULT)))
{
- my_decimal e_dec_buf, *e_dec= row->element_index(i)->val_decimal(&e_dec_buf);
- if (my_decimal_cmp(e_dec, dec) > 0)
- return i-1;
+ my_decimal e_dec_buf, *e_dec= el->val_decimal(&e_dec_buf);
+ /* Skip NULL ranges. */
+ if (el->null_value)
+ continue;
+ else if (my_decimal_cmp(e_dec, dec) > 0)
+ return i - 1;
+ }
+ else
+ {
+ double val= el->val_real();
+ /* Skip NULL ranges. */
+ if (el->null_value)
+ continue;
+ else if (val > value)
+ return i - 1;
}
- else if (row->element_index(i)->val_real() > value)
- return i-1;
}
return i-1;
}
| Thread |
|---|
| • bk commit into 5.0 tree (ramil:1.2578) BUG#32560 | ramil | 23 Nov |