Commit f21905e0 authored by unknown's avatar unknown

data0type.h, row0sel.c:

  Fix a crash in a simple search with a key: the dtype->len of a true VARCHAR is the payload maximum len in bytes: it does not include the 2 bytes MySQL uses to store the string length
ha_innodb.cc:
  Fix a crash in true VARCHARs in test-innodb: we passed a wrong pointer to the column conversion in an UPDATE
rowid_order_innodb.result, ps_3innodb.result, innodb.result, endspace.result:
  Edit InnoDB test results to reflect the arrival of true VARCHARs


mysql-test/r/endspace.result:
  Edit InnoDB test results to reflect the arrival of true VARCHARs
mysql-test/r/innodb.result:
  Edit InnoDB test results to reflect the arrival of true VARCHARs
mysql-test/r/ps_3innodb.result:
  Edit InnoDB test results to reflect the arrival of true VARCHARs
mysql-test/r/rowid_order_innodb.result:
  Edit InnoDB test results to reflect the arrival of true VARCHARs
sql/ha_innodb.cc:
  Fix a crash in true VARCHARs in test-innodb: we passed a wrong pointer to the column conversion in an UPDATE
innobase/row/row0sel.c:
  Fix a crash in a simple search with a key: the dtype->len of a true VARCHAR is the payload maximum len in bytes: it does not include the 2 bytes MySQL uses to store the string length
innobase/include/data0type.h:
  Fix a crash in a simple search with a key: the dtype->len of a true VARCHAR is the payload maximum len in bytes: it does not include the 2 bytes MySQL uses to store the string length
parent ded3d0cb
...@@ -401,11 +401,20 @@ sym_tab_add_null_lit() */ ...@@ -401,11 +401,20 @@ sym_tab_add_null_lit() */
struct dtype_struct{ struct dtype_struct{
ulint mtype; /* main data type */ ulint mtype; /* main data type */
ulint prtype; /* precise type; MySQL data type */ ulint prtype; /* precise type; MySQL data type, charset code,
flags to indicate nullability, signedness,
whether this is a binary string, whether this
is a true VARCHAR where MySQL uses 2 bytes to
store the length */
/* the remaining fields do not affect alphabetical ordering: */ /* the remaining fields do not affect alphabetical ordering: */
ulint len; /* length */ ulint len; /* length; for MySQL data this is
field->pack_length(), except that for a
>= 5.0.3 type true VARCHAR this is the
maximum byte length of the string data
(in addition to the string, MySQL uses 1 or
2 bytes to store the string length) */
ulint prec; /* precision */ ulint prec; /* precision */
ulint mbminlen; /* minimum length of a character, in bytes */ ulint mbminlen; /* minimum length of a character, in bytes */
......
...@@ -2018,7 +2018,8 @@ Converts a key value stored in MySQL format to an Innobase dtuple. The last ...@@ -2018,7 +2018,8 @@ Converts a key value stored in MySQL format to an Innobase dtuple. The last
field of the key value may be just a prefix of a fixed length field: hence field of the key value may be just a prefix of a fixed length field: hence
the parameter key_len. But currently we do not allow search keys where the the parameter key_len. But currently we do not allow search keys where the
last field is only a prefix of the full key field len and print a warning if last field is only a prefix of the full key field len and print a warning if
such appears. */ such appears. A counterpart of this function is
ha_innobase::store_key_val_for_row() in ha_innodb.cc. */
void void
row_sel_convert_mysql_key_to_innobase( row_sel_convert_mysql_key_to_innobase(
...@@ -2100,12 +2101,9 @@ row_sel_convert_mysql_key_to_innobase( ...@@ -2100,12 +2101,9 @@ row_sel_convert_mysql_key_to_innobase(
/* Calculate data length and data field total length */ /* Calculate data length and data field total length */
if (type == DATA_BLOB || if (type == DATA_BLOB) {
dtype_get_mysql_type(dfield_get_type(dfield)) /* The key field is a column prefix of a BLOB or
== DATA_MYSQL_TRUE_VARCHAR) { TEXT */
/* The key field is a column prefix of a BLOB,
TEXT, OR TRUE VARCHAR type column */
ut_a(field->prefix_len > 0); ut_a(field->prefix_len > 0);
...@@ -2122,11 +2120,9 @@ row_sel_convert_mysql_key_to_innobase( ...@@ -2122,11 +2120,9 @@ row_sel_convert_mysql_key_to_innobase(
+ 256 * key_ptr[data_offset + 1]; + 256 * key_ptr[data_offset + 1];
data_field_len = data_offset + 2 + field->prefix_len; data_field_len = data_offset + 2 + field->prefix_len;
if (type == DATA_BLOB) {
data_offset += 2; data_offset += 2;
}
/* now that we know the length, we store the column /* Now that we know the length, we store the column
value like it would be a fixed char field */ value like it would be a fixed char field */
} else if (field->prefix_len > 0) { } else if (field->prefix_len > 0) {
...@@ -2148,6 +2144,18 @@ row_sel_convert_mysql_key_to_innobase( ...@@ -2148,6 +2144,18 @@ row_sel_convert_mysql_key_to_innobase(
data_field_len = data_offset + data_len; data_field_len = data_offset + data_len;
} }
if (dtype_get_mysql_type(dfield_get_type(dfield))
== DATA_MYSQL_TRUE_VARCHAR) {
/* In a MySQL key value format, a true VARCHAR is
always preceded by 2 bytes of a length field.
dfield_get_type(dfield)->len returns the maximum
'payload' len in bytes. That does not include the
2 bytes that tell the actual data length. */
data_len += 2;
data_field_len += 2;
}
/* Storing may use at most data_len bytes of buf */ /* Storing may use at most data_len bytes of buf */
if (!is_null) { if (!is_null) {
......
...@@ -178,7 +178,7 @@ teststring ...@@ -178,7 +178,7 @@ teststring
teststring teststring
explain select * from t1 order by text1; explain select * from t1 order by text1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL key1 32 NULL 3 Using index 1 SIMPLE t1 index NULL key1 34 NULL 3 Using index
alter table t1 modify text1 char(32) binary not null; alter table t1 modify text1 char(32) binary not null;
select * from t1 order by text1; select * from t1 order by text1;
text1 text1
......
...@@ -1466,13 +1466,13 @@ Error 1146 Table 'test.t4' doesn't exist ...@@ -1466,13 +1466,13 @@ Error 1146 Table 'test.t4' doesn't exist
checksum table t1, t2, t3; checksum table t1, t2, t3;
Table Checksum Table Checksum
test.t1 2948697075 test.t1 2948697075
test.t2 968604391 test.t2 1157260244
test.t3 968604391 test.t3 1157260244
checksum table t1, t2, t3 extended; checksum table t1, t2, t3 extended;
Table Checksum Table Checksum
test.t1 3092701434 test.t1 3092701434
test.t2 968604391 test.t2 1157260244
test.t3 968604391 test.t3 1157260244
drop table t1,t2,t3; drop table t1,t2,t3;
create table t1 (id int, name char(10) not null, name2 char(10) not null) engine=innodb; create table t1 (id int, name char(10) not null, name2 char(10) not null) engine=innodb;
insert into t1 values(1,'first','fff'),(2,'second','sss'),(3,'third','ttt'); insert into t1 values(1,'first','fff'),(2,'second','sss'),(3,'third','ttt');
...@@ -1809,6 +1809,5 @@ show variables like "innodb_thread_sleep_delay"; ...@@ -1809,6 +1809,5 @@ show variables like "innodb_thread_sleep_delay";
Variable_name Value Variable_name Value
innodb_thread_sleep_delay 10000 innodb_thread_sleep_delay 10000
create table t1 (v varchar(16384)) engine=innodb; create table t1 (v varchar(16384)) engine=innodb;
ERROR 42000: Column length too big for column 'v' (max = 255); use BLOB instead
create table t1 (a bit, key(a)) engine=innodb; create table t1 (a bit, key(a)) engine=innodb;
ERROR 42000: The storage engine for the table doesn't support BIT FIELD ERROR 42000: The storage engine for the table doesn't support BIT FIELD
...@@ -70,7 +70,7 @@ def test t9 t9 c18 c18 1 4 1 Y 32768 0 63 ...@@ -70,7 +70,7 @@ def test t9 t9 c18 c18 1 4 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63 def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8 def test t9 t9 c20 c20 254 1 1 Y 0 0 8
def test t9 t9 c21 c21 254 10 10 Y 0 0 8 def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 254 30 30 Y 0 0 8 def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63 def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8 def test t9 t9 c24 c24 252 255 8 Y 16 0 8
def test t9 t9 c25 c25 252 65535 4 Y 144 0 63 def test t9 t9 c25 c25 252 65535 4 Y 144 0 63
......
...@@ -178,9 +178,9 @@ insert into t1 values ('','empt',2,2), ...@@ -178,9 +178,9 @@ insert into t1 values ('','empt',2,2),
('dddd','d--d',2,2); ('dddd','d--d',2,2);
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3; select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
pk1 pk2 key1 key2 pk1 pk2 key1 key2
empt 2 2
a a--a 2 2 a a--a 2 2
bb b--b 2 2 bb b--b 2 2
ccc c--c 2 2 ccc c--c 2 2
dddd d--d 2 2 dddd d--d 2 2
empt 2 2
drop table t1; drop table t1;
...@@ -2920,6 +2920,7 @@ calc_row_difference( ...@@ -2920,6 +2920,7 @@ calc_row_difference(
ulint o_len; ulint o_len;
ulint n_len; ulint n_len;
ulint col_pack_len; ulint col_pack_len;
byte* new_mysql_row_col;
byte* o_ptr; byte* o_ptr;
byte* n_ptr; byte* n_ptr;
byte* buf; byte* buf;
...@@ -2948,10 +2949,17 @@ calc_row_difference( ...@@ -2948,10 +2949,17 @@ calc_row_difference(
o_ptr = (byte*) old_row + get_field_offset(table, field); o_ptr = (byte*) old_row + get_field_offset(table, field);
n_ptr = (byte*) new_row + get_field_offset(table, field); n_ptr = (byte*) new_row + get_field_offset(table, field);
/* Use new_mysql_row_col and col_pack_len save the values */
new_mysql_row_col = n_ptr;
col_pack_len = field->pack_length(); col_pack_len = field->pack_length();
o_len = col_pack_len; o_len = col_pack_len;
n_len = col_pack_len; n_len = col_pack_len;
/* We use o_ptr and n_ptr to dig up the actual data for
comparison. */
field_mysql_type = field->type(); field_mysql_type = field->type();
col_type = get_innobase_type_from_mysql_type(field); col_type = get_innobase_type_from_mysql_type(field);
...@@ -3017,15 +3025,11 @@ calc_row_difference( ...@@ -3017,15 +3025,11 @@ calc_row_difference(
&dfield, &dfield,
(byte*)buf, (byte*)buf,
TRUE, TRUE,
n_ptr, new_mysql_row_col,
col_pack_len, col_pack_len,
prebuilt->table->comp); prebuilt->table->comp);
ufield->new_val.data = ufield->new_val.data = dfield.data;
dfield_get_data_noninline( ufield->new_val.len = dfield.len;
&dfield);
ufield->new_val.len =
dfield_get_len_noninline(
&dfield);
} else { } else {
ufield->new_val.data = NULL; ufield->new_val.data = NULL;
ufield->new_val.len = UNIV_SQL_NULL; ufield->new_val.len = UNIV_SQL_NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment