Commit bcbcacb8 authored by svoj@mysql.com/april.(none)'s avatar svoj@mysql.com/april.(none)
Browse files

BUG#24342 - Incorrect results with query over MERGE table

MERGE engine may return incorrect values when several representations
of equal keys are present in the index. For example "groß" and "gross"
or "gross" and "gross " (trailing space), which are considered equal,
but have different lengths.

The problem was that key length was not recalculated after key lookup.

Only MERGE engine is affected.
parent db45dc5f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
    key_buff=info->lastkey+info->s->base.max_key_length;
    pack_key_length= key_len;
    bmove(key_buff,key,key_len);
    last_used_keyseg= 0;
    last_used_keyseg= info->s->keyinfo[inx].seg + info->last_used_keyseg;
  }
  else
  {
@@ -62,6 +62,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
				 key_len, &last_used_keyseg);
    /* Save packed_key_length for use by the MERGE engine. */
    info->pack_key_length= pack_key_length;
    info->last_used_keyseg= last_used_keyseg - info->s->keyinfo[inx].seg;
    DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE, keyinfo->seg,
				     key_buff, pack_key_length););
  }
+1 −0
Original line number Diff line number Diff line
@@ -263,6 +263,7 @@ struct st_myisam_info {
  enum ha_rkey_function last_key_func;  /* CONTAIN, OVERLAP, etc */
  uint  save_lastkey_length;
  uint  pack_key_length;                /* For MYISAMMRG */
  uint16 last_used_keyseg;              /* For MyISAMMRG */
  int	errkey;				/* Got last error on this key */
  int   lock_type;			/* How database was locked */
  int   tmp_lock_type;			/* When locked by readinfo */
+4 −0
Original line number Diff line number Diff line
@@ -41,12 +41,14 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
{
  byte *key_buff;
  uint pack_key_length;
  uint16 last_used_keyseg;
  MYRG_TABLE *table;
  MI_INFO *mi;
  int err;
  DBUG_ENTER("myrg_rkey");
  LINT_INIT(key_buff);
  LINT_INIT(pack_key_length);
  LINT_INIT(last_used_keyseg);

  if (_myrg_init_queue(info,inx,search_flag))
    DBUG_RETURN(my_errno);
@@ -61,10 +63,12 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key,
      /* Get the saved packed key and packed key length. */
      key_buff=(byte*) mi->lastkey+mi->s->base.max_key_length;
      pack_key_length=mi->pack_key_length;
      last_used_keyseg= mi->last_used_keyseg;
    }
    else
    {
      mi->once_flags|= USE_PACKED_KEYS;
      mi->last_used_keyseg= last_used_keyseg;
      err=mi_rkey(mi,0,inx,key_buff,pack_key_length,search_flag);
    }
    info->last_used_table=table+1;
+11 −0
Original line number Diff line number Diff line
@@ -819,3 +819,14 @@ ALTER TABLE m1 ENGINE=MERGE UNION=(t1);
SELECT * FROM m1;
c1	c2	c3	c4	c5	c6	c7	c8	c9
DROP TABLE t1, m1;
CREATE TABLE t1 (a VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_german2_ci,
b INT, INDEX(a,b));
CREATE TABLE t2 LIKE t1;
CREATE TABLE t3 LIKE t1;
ALTER TABLE t3 ENGINE=MERGE UNION=(t1,t2);
INSERT INTO t1 VALUES ('ss',1);
INSERT INTO t2 VALUES ('ss',2),(0xDF,2);
SELECT COUNT(*) FROM t3 WHERE a=0xDF AND b=2;
COUNT(*)
2
DROP TABLE t1,t2,t3;
+13 −0
Original line number Diff line number Diff line
@@ -454,4 +454,17 @@ ALTER TABLE m1 ENGINE=MERGE UNION=(t1);
SELECT * FROM m1;
DROP TABLE t1, m1;

#
# BUG#24342 - Incorrect results with query over MERGE table
#
CREATE TABLE t1 (a VARCHAR(255) CHARACTER SET latin1 COLLATE latin1_german2_ci,
                 b INT, INDEX(a,b));
CREATE TABLE t2 LIKE t1;
CREATE TABLE t3 LIKE t1;
ALTER TABLE t3 ENGINE=MERGE UNION=(t1,t2);
INSERT INTO t1 VALUES ('ss',1);
INSERT INTO t2 VALUES ('ss',2),(0xDF,2);
SELECT COUNT(*) FROM t3 WHERE a=0xDF AND b=2;
DROP TABLE t1,t2,t3;

# End of 4.1 tests