Bug #53352 Decimal(65,0) is incorrectly truncated to decimal(64,) on cluster
Submitted: 2 May 2010 6:49 Modified: 6 May 2010 12:35
Reporter: Shane Bester (Platinum Quality Contributor) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Cluster: Cluster (NDB) storage engine Severity:S1 (Critical)
Version:mysql-5.1-telco-6.2 OS:Any (MS Windows, Linux)
Assigned to: Jonas Oreland CPU Architecture:Any

[2 May 2010 6:49] Shane Bester
Description:
when dabbling in ndb i found cluster crashes with unique decimal indexes.

Version: '5.1.44-ndb-7.1.3-cluster-gpl-debug'  socket: ''  port: 3306  MySQL Cluster Server - Debug (GPL)
100502  8:40:04 [Note] NDB Binlog: CREATE TABLE Event: REPL$test/t1
Assertion failed: 0, file ..\..\sql\ha_ndbcluster.cc, line 12145

mysqld-debug.exe!my_sigabrt_handler()[mysqld.cc:2092]
mysqld-debug.exe!raise()[winsig.c:597]
mysqld-debug.exe!abort()[abort.c:78]
mysqld-debug.exe!_wassert()[assert.c:212]
mysqld-debug.exe!ha_ndbcluster::calculate_key_hash_value[ha_ndbcluster.cc:12145
mysqld-debug.exe!get_part_id_key()[sql_partition.cc:2445]
mysqld-debug.exe!get_partition_id_key_nosub()[sql_partition.cc:3052]
mysqld-debug.exe!find_used_partitions()[opt_range.cc:3198]
mysqld-debug.exe!prune_partitions()[opt_range.cc:2740]
mysqld-debug.exe!mysql_update()[sql_update.cc:325]
mysqld-debug.exe!mysql_execute_command()[sql_parse.cc:3073]
mysqld-debug.exe!mysql_parse()[sql_parse.cc:5981]
mysqld-debug.exe!dispatch_command()[sql_parse.cc:1238]
mysqld-debug.exe!do_command()[sql_parse.cc:877]
mysqld-debug.exe!handle_one_connection()[sql_connect.cc:1133]
mysqld-debug.exe!pstart()[my_winthread.c:105]
mysqld-debug.exe!detached_pstart()[my_winthread.c:94]
mysqld-debug.exe!_callthreadstart()[thread.c:295]
mysqld-debug.exe!_threadstart()[thread.c:277]
kernel32.dll!BaseThreadStart()
ariables.
 invalid and cause the dump to abort...
00030312F8=update `t1` set `a`=2 where `a` = 1

debug binary asserts.
release binary aborts()

How to repeat:
#i setup a single node cluster, then:

drop table if exists `t1`;
create table `t1` (`a` decimal(65,4) not null,
primary key (`a`)) engine=ndbcluster;
update `t1` set `a`=2 where `a` = 1;
[2 May 2010 14:15] Sveta Smirnova
Thank you for the report.

Verified as described.
[3 May 2010 9:22] Hartmut Holzgraefe
ndb-7.0.14 backtrace

Program terminated with signal 6, Aborted.
#0  0x00aa9422 in __kernel_vsyscall ()
(gdb) bt
#0  0x00aa9422 in __kernel_vsyscall ()
#1  0x00f32e93 in __pthread_kill (threadid=3052280688, signo=6)
    at ../nptl/sysdeps/unix/sysv/linux/pthread_kill.c:64
#2  0x0867b6f3 in my_write_core (sig=6) at stacktrace.c:332
#3  0x082bacf9 in handle_segfault (sig=6) at mysqld.cc:2614
#4  <signal handler called>
#5  0x00aa9422 in __kernel_vsyscall ()
#6  0x001bf4d1 in *__GI_raise (sig=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#7  0x001c2932 in *__GI_abort () at abort.c:92
#8  0x001b8648 in *__GI___assert_fail (assertion=0x8852ee3 "(0)", 
    file=0x8852a74 "ha_ndbcluster.cc", line=12145, 
    function=0x8857e80 "virtual uint32 ha_ndbcluster::calculate_key_hash_value(Field**)") at assert.c:81
#9  0x0850d71a in ha_ndbcluster::calculate_key_hash_value (this=0x9a024d0, 
    field_array=0x9a03bb4) at ha_ndbcluster.cc:12145
#10 0x081e5778 in get_part_id_key (file=0x9a024d0, field_array=0x9a03bb0, 
    no_parts=2, func_value=0xb5edfc38) at sql_partition.cc:2445
#11 0x081e6c11 in get_partition_id_key_nosub (part_info=0x9a03970, 
    part_id=0xb5edfc44, func_value=0xb5edfc38) at sql_partition.cc:3052
#12 0x083de3f1 in find_used_partitions (ppar=0xb5edfcb4, key_tree=0x99f2870)
    at opt_range.cc:3197
#13 0x083dd8da in prune_partitions (thd=0x9a07068, table=0x99e87b0, 
---Type <return> to continue, or q <return> to quit---
    pprune_cond=0x9a044c8) at opt_range.cc:2739
#14 0x0837a05d in mysql_update (thd=0x9a07068, table_list=0x9a040c0, 
    fields=..., values=..., conds=0x9a044c8, order_num=0, order=0x0, 
    limit=18446744073709551615, handle_duplicates=DUP_ERROR, ignore=false)
    at sql_update.cc:325
#15 0x082cfb8c in mysql_execute_command (thd=0x9a07068) at sql_parse.cc:3073
#16 0x082d8dbe in mysql_parse (thd=0x9a07068, 
    inBuf=0x9a04000 "update `t1` set `a`=2 where `a` = 1", length=35, 
    found_semicolon=0xb5ee1058) at sql_parse.cc:5977
#17 0x082cad2b in dispatch_command (command=COM_QUERY, thd=0x9a07068, 
    packet=0x9a27971 "update `t1` set `a`=2 where `a` = 1", packet_length=35)
    at sql_parse.cc:1236
#18 0x082c9e1f in do_command (thd=0x9a07068) at sql_parse.cc:877
#19 0x082c81c6 in handle_one_connection (arg=0x9a07068) at sql_connect.cc:1133
#20 0x00f2d80e in start_thread (arg=0xb5ee1b70) at pthread_create.c:300
#21 0x002618de in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:130
[3 May 2010 10:03] Hartmut Holzgraefe
crash is due to an abort() call after receiving unexpected 
non-zero result from Ndb::computeHash():

  if ((ret_val= ndb->computeHash(&hash_value, m_table,
                                 key_data_ptr, buf, sizeof(tmp))))
  {
    DBUG_PRINT("info", ("ret_val = %d", ret_val));
    DBUG_ASSERT(FALSE);
    abort();
  }

actual problem in Ndb.cpp is on the last statement in the snippet below
with keyData[i].len being 30 and maxlen being 29 (or vice versa, closed
debugger too soon) so that "emalformedkey" error handling is triggered

 369   for (Uint32 i = 0; i<parts; i++)
 370   {
 371     Uint32 lb, len;
 372     if (unlikely(!NdbSqlUtil::get_var_length(partcols[i]->m_type,
 373                                              keyData[i].ptr,
 374                                              keyData[i].len,
 375                                              lb, len)))
 376       goto emalformedkey;
 377 
 378     if (unlikely(keyData[i].len < (lb + len)))
 379       goto elentosmall;
 380 
 381     Uint32 maxlen = (partcols[i]->m_attrSize * partcols[i]->m_arraySize);
 382 
 383     if (unlikely(lb == 0 && keyData[i].len != maxlen))
 384       goto emalformedkey;
[6 May 2010 10:08] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/107616

3097 Jonas Oreland	2010-05-06
      ndb - bug#53352, ndb did incorrect truncate max length of decimal to 64. Change to server defined 65, and change so that instead of truncating, return an error (if server changes in the future)
[6 May 2010 10:14] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/107618

3097 Jonas Oreland	2010-05-06
      ndb - bug#53352, ndb did incorrect truncate max length of decimal to 64. Change to server defined 65, and change so that instead of truncating, return an error (if server changes in the future)
[6 May 2010 11:22] Jonas Oreland
Problem was that decimal(65,0) is incorrectly truncated to decimal(64,) on cluster, this lead/could lead to various problems in mysqld integration.

The patch changes so that
1) truncation never happens, instead an error is thrown
2) ndb correctly accepts decimal(65,)

pushed to 6.2.19, 6.3.34, 7.0.15, 7.1.4
[6 May 2010 12:32] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/107639

3595 Martin Skold	2010-05-06 [merge]
      Merge
      modified:
        storage/ndb/include/kernel/signaldata/DictTabInfo.hpp
[6 May 2010 12:35] Jon Stephens
Documented bugfix in the NDB-6.2.19, 6.3.34, 7.0.15, and 7.1.4 changelogs, as follows:

      NDB truncated a column declared as DECIMAL(65,0) to a length of 64. 
      Now such a column is accepted and handled correctly. In cases where 
      the maximum length (65) is exceeded, NDB now raises an error instead 
      of truncating.

Closed.
[6 May 2010 12:38] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/107645

3526 Martin Skold	2010-05-06 [merge]
      Merge
      modified:
        storage/ndb/include/kernel/signaldata/DictTabInfo.hpp
        storage/ndb/tools/restore/consumer_restore.cpp
[6 May 2010 12:40] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/107648

3194 Martin Skold	2010-05-06 [merge]
      Merge
      modified:
        storage/ndb/include/kernel/signaldata/DictTabInfo.hpp