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

PPC64: Unexpected error with a negative value into auto-increment columns in HEAP, MyISAM, ARIA

    Details

      Description

      DROP TABLE IF EXISTS t1;
      CREATE TABLE t1 (
        id TINYINT NOT NULL AUTO_INCREMENT,
        name CHAR(30) NOT NULL,
        PRIMARY KEY (id)
      ) ENGINE=InnoDB;
      INSERT INTO t1 (name) VALUES ('dog');
      UPDATE t1 SET id=-1 WHERE id=1;
      INSERT INTO t1 (name) VALUES ('cat');
      SELECT * FROM t1;
      DROP TABLE t1;
      

      +----+------+
      | id | name |
      +----+------+
      | -1 | dog  |
      |  2 | cat  |
      +----+------+
      

      If I now change ENGINE to HEAP, MyISAM or ARIA:

      DROP TABLE IF EXISTS t1;
      CREATE TABLE t1 (
        id TINYINT NOT NULL AUTO_INCREMENT,
        name CHAR(30) NOT NULL,
        PRIMARY KEY (id)
      ) ENGINE=MyISAM;
      INSERT INTO t1 (name) VALUES ('dog');
      UPDATE t1 SET id=-1 WHERE id=1;
      INSERT INTO t1 (name) VALUES ('cat');
      SELECT * FROM t1;
      DROP TABLE t1;
      

      the script fails in the last INSERT with this error:

      ERROR 167 (22003): Out of range value for column 'id' at row 1
      

      Looks wrong. All engines should insert two rows without errors, like InnoDB does.

      Note, if I run the same scripts on other platforms (e.g. x86-64), all engines work as expected, like InnoDB.

      The problem resides in these code fragments in HEAP, MyISAM and ARIA implementations respectively:

      void heap_update_auto_increment(HP_INFO *info, const uchar *record)
      {
      ..
        case HA_KEYTYPE_INT8:
          s_value= (longlong) *(char*)key;
          break;
      ..
      }
      

      ulonglong retrieve_auto_increment(MI_INFO *info,const uchar *record)
      {
      ..
        case HA_KEYTYPE_INT8:
          s_value= (longlong) *(char*)key;
          break;
      ..
      }
      

      ulonglong ma_retrieve_auto_increment(const uchar *key, uint8 key_type)
      {
      ..
        case HA_KEYTYPE_INT8:
          s_value= (longlong) *(const char*)key;
          break;
       
      ..
      }
      

      "char" is unsigned by default on PPC64.
      The cast operators should include the "signed" keyword, i.e:

        case HA_KEYTYPE_INT8:
          s_value= (longlong) *(const signed char*)key;
          break;
      

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                bar Alexander Barkov
                Reporter:
                bar Alexander Barkov
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: