Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-41877

INSERT or UPDATE that fails with ERROR 1690 from the partition function still writes the row on MyISAM, debug builds assert

    XMLWordPrintable

Details

    Description

      Likely cause: old code in part_val_int(), not a recent change. MySQL 5.5, 5.6 and 5.7 also keep the row and the new value.

      --source include/have_partition.inc
      CREATE TABLE t1 (a BIGINT) ENGINE=MyISAM PARTITION BY HASH (-a) PARTITIONS 3;
      --error ER_DATA_OUT_OF_RANGE
      INSERT INTO t1 VALUES (-9223372036854775808);
      --let $n= `SELECT COUNT(*) FROM t1`
      if ($n)
      {
        --die The INSERT fails with an out of range error from the partition function, but the row is stored
      }
      INSERT INTO t1 VALUES (5);
      --error ER_DATA_OUT_OF_RANGE
      UPDATE t1 SET a = -9223372036854775808;
      --let $n= `SELECT COUNT(*) FROM t1 WHERE a = 5`
      if (!$n)
      {
        --die The UPDATE fails with an out of range error from the partition function, but the new value is stored
      }
      DROP TABLE t1;

      Leads to:

      CS 13.1.2 87e62ca17270e163a6d41b3fc8d6f4d440f1bb88 (Optimized, Clang 22.1.8-20260622) Build 06/10/2026

      mysqltest: At line 8: The INSERT fails with an out of range error from the partition function, but the row is stored

      The INSERT gives ERROR 1690, but the row is stored. An UPDATE that fails in the same way keeps the new value. On debug builds, the INSERT asserts:

      CS 13.1.2 87e62ca17270e163a6d41b3fc8d6f4d440f1bb88 (Debug, Clang 22.1.8-20260622) Build 06/10/2026

      mariadbd: /tmp/TODO-6010_partition/13.1_dbg/sql/sql_error.cc:357: void Diagnostics_area::set_ok_status(ulonglong, ulonglong, const char *): Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())' failed.

      CS 13.1.2 87e62ca17270e163a6d41b3fc8d6f4d440f1bb88 (Debug, Clang 22.1.8-20260622) Build 06/10/2026

      Core was generated by `/tmp/TODO-6010_partition/MD061026-mariadb-13.1.2-linux-x86_64-dbg/bin/mariadbd'.
      Program terminated with signal SIGABRT, Aborted.
      #0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>)at ./nptl/pthread_kill.c:44
       
      [Current thread is 1 (LWP 127731)]
      (gdb) bt
      #0  __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>)at ./nptl/pthread_kill.c:44
      #1  __pthread_kill_internal (signo=6, threadid=<optimized out>)at ./nptl/pthread_kill.c:78
      #2  __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6)at ./nptl/pthread_kill.c:89
      #3  0x00007c4b6b44527e in __GI_raise (sig=sig@entry=6)at ../sysdeps/posix/raise.c:26
      #4  0x00007c4b6b4288ff in __GI_abort () at ./stdlib/abort.c:79
      #5  0x00007c4b6b42881b in __assert_fail_base (fmt=0x7c4b6b5d1208 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=assertion@entry=0x573e353e4e1e "!is_set() || (m_status == DA_OK_BULK && is_bulk_op())", file=file@entry=0x573e353e4cad "/tmp/TODO-6010_partition/13.1_dbg/sql/sql_error.cc", line=line@entry=357, function=function@entry=0x573e353e4e54 "void Diagnostics_area::set_ok_status(ulonglong, ulonglong, const char *)") at ./assert/assert.c:96
      #6  0x00007c4b6b43b517 in __assert_fail (assertion=0x573e353e4e1e "!is_set() || (m_status == DA_OK_BULK && is_bulk_op())", file=0x573e353e4cad "/tmp/TODO-6010_partition/13.1_dbg/sql/sql_error.cc", line=357, function=0x573e353e4e54 "void Diagnostics_area::set_ok_status(ulonglong, ulonglong, const char *)") at ./assert/assert.c:105
      #7  0x0000573e3436f06b in Diagnostics_area::set_ok_status (this=0x7c4b38007210, affected_rows=1, last_insert_id=0, message=0x0)at /tmp/TODO-6010_partition/13.1_dbg/sql/sql_error.cc:357
      #8  0x0000573e343063cf in my_ok (thd=0x7c4b38000d60, affected_rows_arg=1, id=0, message=0x0)at /tmp/TODO-6010_partition/13.1_dbg/sql/sql_class.h:6640
      #9  0x0000573e3437741f in mysql_insert (thd=0x7c4b38000d60, table_list=0x7c4b38017190, fields=@0x7c4b380062d0: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x573e360f4da0 <end_of_list>, last = 0x7c4b380062d0, elements = 0}, <No data fields>}, values_list=@0x7c4b38006318: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x7c4b38017fa0, last = 0x7c4b38017fa0, elements = 1}, <No data fields>}, update_fields=@0x7c4b38006300: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x573e360f4da0 <end_of_list>, last = 0x7c4b38006300, elements = 0}, <No data fields>}, update_values=@0x7c4b380062e8: {<base_list> = {<Sql_alloc> = {<No data fields>}, first = 0x573e360f4da0 <end_of_list>, last = 0x7c4b380062e8, elements = 0}, <No data fields>}, duplic=DUP_ERROR, ignore=false, result=0x0)at /tmp/TODO-6010_partition/13.1_dbg/sql/sql_insert.cc:1467
      #10 0x0000573e343dda56 in mysql_execute_command (thd=0x7c4b38000d60, is_called_from_prepared_stmt=false)at /tmp/TODO-6010_partition/13.1_dbg/sql/sql_parse.cc:4500
      #11 0x0000573e343d4828 in mysql_parse (thd=0x7c4b38000d60, rawbuf=0x7c4b38017060 "INSERT INTO t1 VALUES (-9223372036854775808)", length=44, parser_state=0x7c4b69d209c0)at /tmp/TODO-6010_partition/13.1_dbg/sql/sql_parse.cc:7955
      #12 0x0000573e343d1fde in dispatch_command (command=COM_QUERY, thd=0x7c4b38000d60, packet=0x7c4b381d3a61 "INSERT INTO t1 VALUES (-9223372036854775808)", packet_length=44, blocking=true)at /tmp/TODO-6010_partition/13.1_dbg/sql/sql_parse.cc:1903
      #13 0x0000573e343d52aa in do_command (thd=0x7c4b38000d60, blocking=true)at /tmp/TODO-6010_partition/13.1_dbg/sql/sql_parse.cc:1437
      #14 0x0000573e345ad3fe in do_handle_one_connection (connect=0x573e604da780, put_in_cache=true)at /tmp/TODO-6010_partition/13.1_dbg/sql/sql_connect.cc:1514
      #15 0x0000573e345ad1e1 in handle_one_connection (arg=0x573e604c6320)at /tmp/TODO-6010_partition/13.1_dbg/sql/sql_connect.cc:1426
      #16 0x00007c4b6b49cb84 in start_thread (arg=<optimized out>)at ./nptl/pthread_create.c:447
      #17 0x00007c4b6b529ecc in clone3 ()at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78

      REPLACE and INSERT IGNORE also keep the row. The same happens with RANGE and LIST partitioning and with subpartitions, for example PARTITION BY RANGE (a - b) on two INT UNSIGNED columns when b > a. InnoDB gives the same error and keeps no row.

      From the code it seems that raise_integer_overflow() (sql/item_func.h) gives the error and returns 0 without setting null_value. part_val_int() (sql/sql_partition.cc) checks thd->is_error() only when null_value is set. So the row goes to the partition for 0, and the statement ends with the error already in the diagnostics area.

      Attachments

        Activity

          People

            ycp Yuchen Pei
            Roel Roel Van de Paar
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Time Tracking

                Estimated:
                Original Estimate - Not Specified
                Not Specified
                Remaining:
                Remaining Estimate - Not Specified
                Not Specified
                Logged:
                Time Spent - 1h
                1h

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.