← Back to team overview

maria-developers team mailing list archive

Please review MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool)

 

Hello Sergei,

Please review a patch for:

MDEV-9653 Assertion `length || !scale' failed in uint
my_decimal_length_to_precision(uint, uint, bool)

Thanks!
diff --git a/mysql-test/r/func_hybrid_type.result b/mysql-test/r/func_hybrid_type.result
index 95a8a82..29f9f46 100644
--- a/mysql-test/r/func_hybrid_type.result
+++ b/mysql-test/r/func_hybrid_type.result
@@ -3396,5 +3396,17 @@ c1
 DROP TABLE t2;
 DROP TABLE t1;
 #
+# MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool)
+#
+SELECT CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END;
+CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END
+NULL
+SELECT CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END;
+CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END
+NULL
+SELECT CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END;
+CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END
+NULL
+#
 # End of 10.1 tests
 #
diff --git a/mysql-test/t/func_hybrid_type.test b/mysql-test/t/func_hybrid_type.test
index 047e5f7..cc5d067 100644
--- a/mysql-test/t/func_hybrid_type.test
+++ b/mysql-test/t/func_hybrid_type.test
@@ -434,5 +434,13 @@ DROP TABLE t1;
 
 
 --echo #
+--echo # MDEV-9653 Assertion `length || !scale' failed in uint my_decimal_length_to_precision(uint, uint, bool)
+--echo #
+SELECT CASE 0 WHEN 1 THEN (CASE 2 WHEN 3 THEN NULL END) WHEN 4 THEN 5 END;
+SELECT CASE 0 WHEN 1 THEN (COALESCE(NULL)) WHEN 4 THEN 5 END;
+SELECT CASE WHEN TRUE THEN COALESCE(NULL) ELSE 4 END;
+
+
+--echo #
 --echo # End of 10.1 tests
 --echo #
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 2783a05..73a47ac 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -3086,10 +3086,28 @@ void Item_func_case::agg_str_lengths(Item* arg)
 
 void Item_func_case::agg_num_lengths(Item *arg)
 {
-  uint len= my_decimal_length_to_precision(arg->max_length, arg->decimals,
-                                           arg->unsigned_flag) - arg->decimals;
-  set_if_bigger(max_length, len); 
-  set_if_bigger(decimals, arg->decimals);
+  /*
+    In a query like this:
+    SELECT CASE WHEN TRUE
+             THEN COALESCE(CAST(NULL AS UNSIGNED))
+             ELSE 40
+           END;
+    "arg" corresponding to Item_func_coalesce has:
+      arg->max_length==0
+      arg->decimals==31 (NOT_FIXED_DEC).
+    my_decimal_length_to_precision() does not expect this kind of input
+    and would crash on DBUG_ASSERT. See MDEV-9653.
+    So let's skip length calculation for explicit NULLs and
+    for expressions derived from explicit NULLs.
+  */
+  if (arg->field_type() != MYSQL_TYPE_NULL)
+  {
+    uint len= my_decimal_length_to_precision(arg->max_length, arg->decimals,
+                                             arg->unsigned_flag) -
+                                             arg->decimals;
+    set_if_bigger(max_length, len);
+    set_if_bigger(decimals, arg->decimals);
+  }
   unsigned_flag= unsigned_flag && arg->unsigned_flag; 
 }
 

Follow ups