Commit 543e8336 authored by unknown's avatar unknown

Merge jlindstrom@build.mysql.com:/home/bk/mysql-4.1

into hundin.mysql.fi:/home/jan/mysql-4.1

parents ca65afeb 86489bd0
...@@ -2401,13 +2401,16 @@ btr_index_rec_validate( ...@@ -2401,13 +2401,16 @@ btr_index_rec_validate(
rec_get_nth_field(rec, i, &len); rec_get_nth_field(rec, i, &len);
/* Note that prefix indexes are not fixed size even when
their type is CHAR. */
if ((dict_index_get_nth_field(index, i)->prefix_len == 0 if ((dict_index_get_nth_field(index, i)->prefix_len == 0
&& len != UNIV_SQL_NULL && dtype_is_fixed_size(type) && len != UNIV_SQL_NULL && dtype_is_fixed_size(type)
&& len != dtype_get_fixed_size(type)) && len != dtype_get_fixed_size(type))
|| ||
(dict_index_get_nth_field(index, i)->prefix_len > 0 (dict_index_get_nth_field(index, i)->prefix_len > 0
&& len != UNIV_SQL_NULL && dtype_is_fixed_size(type) && len != UNIV_SQL_NULL
&& len != && len >
dict_index_get_nth_field(index, i)->prefix_len)) { dict_index_get_nth_field(index, i)->prefix_len)) {
btr_index_rec_validate_report(page, rec, index); btr_index_rec_validate_report(page, rec, index);
......
...@@ -756,9 +756,13 @@ lock_rec_has_to_wait( ...@@ -756,9 +756,13 @@ lock_rec_has_to_wait(
ulint type_mode,/* in: precise mode of the new lock to set: ulint type_mode,/* in: precise mode of the new lock to set:
LOCK_S or LOCK_X, possibly ORed to LOCK_S or LOCK_X, possibly ORed to
LOCK_GAP or LOCK_REC_NOT_GAP, LOCK_INSERT_INTENTION */ LOCK_GAP or LOCK_REC_NOT_GAP, LOCK_INSERT_INTENTION */
lock_t* lock2) /* in: another record lock; NOTE that it is assumed lock_t* lock2, /* in: another record lock; NOTE that it is assumed
that this has a lock bit set on the same record as that this has a lock bit set on the same record as
in the new lock we are setting */ in the new lock we are setting */
ibool lock_is_on_supremum) /* in: TRUE if we are setting the lock
on the 'supremum' record of an index
page: we know then that the lock request
is really for a 'gap' type lock */
{ {
ut_ad(trx && lock2); ut_ad(trx && lock2);
ut_ad(lock_get_type(lock2) == LOCK_REC); ut_ad(lock_get_type(lock2) == LOCK_REC);
...@@ -770,10 +774,22 @@ lock_rec_has_to_wait( ...@@ -770,10 +774,22 @@ lock_rec_has_to_wait(
/* We have somewhat complex rules when gap type record locks /* We have somewhat complex rules when gap type record locks
cause waits */ cause waits */
if ((type_mode & LOCK_REC_NOT_GAP) if ((lock_is_on_supremum || (type_mode & LOCK_GAP))
&& !(type_mode & LOCK_INSERT_INTENTION)) {
/* Gap type locks without LOCK_INSERT_INTENTION flag
do not need to wait for anything. This is because
different users can have conflicting lock types
on gaps. */
return(FALSE);
}
if (!(type_mode & LOCK_INSERT_INTENTION)
&& lock_rec_get_gap(lock2)) { && lock_rec_get_gap(lock2)) {
/* Lock on just the record does not need to wait for
a gap type lock */ /* Record lock (LOCK_ORDINARY or LOCK_REC_NOT_GAP
does not need to wait for a gap type lock */
return(FALSE); return(FALSE);
} }
...@@ -830,8 +846,12 @@ lock_has_to_wait( ...@@ -830,8 +846,12 @@ lock_has_to_wait(
if (lock_get_type(lock1) == LOCK_REC) { if (lock_get_type(lock1) == LOCK_REC) {
ut_ad(lock_get_type(lock2) == LOCK_REC); ut_ad(lock_get_type(lock2) == LOCK_REC);
/* If this lock request is for a supremum record
then the second bit on the lock bitmap is set */
return(lock_rec_has_to_wait(lock1->trx, return(lock_rec_has_to_wait(lock1->trx,
lock1->type_mode, lock2)); lock1->type_mode, lock2,
lock_rec_get_nth_bit(lock1,1)));
} }
return(TRUE); return(TRUE);
...@@ -1420,7 +1440,8 @@ lock_rec_other_has_conflicting( ...@@ -1420,7 +1440,8 @@ lock_rec_other_has_conflicting(
lock = lock_rec_get_first(rec); lock = lock_rec_get_first(rec);
while (lock) { while (lock) {
if (lock_rec_has_to_wait(trx, mode, lock)) { if (lock_rec_has_to_wait(trx, mode, lock,
page_rec_is_supremum(rec))) {
return(lock); return(lock);
} }
......
...@@ -541,7 +541,8 @@ cmp_dtuple_rec_with_match( ...@@ -541,7 +541,8 @@ cmp_dtuple_rec_with_match(
&& dtype_get_charset_coll(cur_type->prtype) != && dtype_get_charset_coll(cur_type->prtype) !=
data_mysql_latin1_swedish_charset_coll)) { data_mysql_latin1_swedish_charset_coll)) {
ret = cmp_whole_field(cur_type, ret = cmp_whole_field(
cur_type,
dfield_get_data(dtuple_field), dtuple_f_len, dfield_get_data(dtuple_field), dtuple_f_len,
rec_b_ptr, rec_f_len); rec_b_ptr, rec_f_len);
......
...@@ -1023,6 +1023,33 @@ row_ins_set_shared_rec_lock( ...@@ -1023,6 +1023,33 @@ row_ins_set_shared_rec_lock(
return(err); return(err);
} }
/*************************************************************************
Sets a exclusive lock on a record. Used in locking possible duplicate key
records */
static
ulint
row_ins_set_exclusive_rec_lock(
/*============================*/
/* out: DB_SUCCESS or error code */
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or
LOCK_REC_NOT_GAP type lock */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
que_thr_t* thr) /* in: query thread */
{
ulint err;
if (index->type & DICT_CLUSTERED) {
err = lock_clust_rec_read_check_and_lock(0, rec, index, LOCK_X,
type, thr);
} else {
err = lock_sec_rec_read_check_and_lock(0, rec, index, LOCK_X,
type, thr);
}
return(err);
}
/******************************************************************* /*******************************************************************
Checks if foreign key constraint fails for an index entry. Sets shared locks Checks if foreign key constraint fails for an index entry. Sets shared locks
which lock either the success or the failure of the constraint. NOTE that which lock either the success or the failure of the constraint. NOTE that
...@@ -1451,6 +1478,8 @@ row_ins_scan_sec_index_for_duplicate( ...@@ -1451,6 +1478,8 @@ row_ins_scan_sec_index_for_duplicate(
ulint err = DB_SUCCESS; ulint err = DB_SUCCESS;
ibool moved; ibool moved;
mtr_t mtr; mtr_t mtr;
trx_t *trx;
ibool success;
n_unique = dict_index_get_n_unique(index); n_unique = dict_index_get_n_unique(index);
...@@ -1488,8 +1517,24 @@ row_ins_scan_sec_index_for_duplicate( ...@@ -1488,8 +1517,24 @@ row_ins_scan_sec_index_for_duplicate(
/* Try to place a lock on the index record */ /* Try to place a lock on the index record */
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec, index, trx = thr_get_trx(thr);
thr); ut_ad(trx);
dict_accept(*trx->mysql_query_str, "REPLACE", &success);
if (success) {
/* The manual defines the REPLACE semantics that it
is either an INSERT or DELETE(s) for duplicate key
+ INSERT. Therefore, we should take X-lock for
duplicates */
err = row_ins_set_exclusive_rec_lock(
LOCK_ORDINARY,rec,index,thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_ORDINARY, rec, index,thr);
}
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
...@@ -1556,6 +1601,7 @@ row_ins_duplicate_error_in_clust( ...@@ -1556,6 +1601,7 @@ row_ins_duplicate_error_in_clust(
page_t* page; page_t* page;
ulint n_unique; ulint n_unique;
trx_t* trx = thr_get_trx(thr); trx_t* trx = thr_get_trx(thr);
ibool success;
UT_NOT_USED(mtr); UT_NOT_USED(mtr);
...@@ -1589,8 +1635,26 @@ row_ins_duplicate_error_in_clust( ...@@ -1589,8 +1635,26 @@ row_ins_duplicate_error_in_clust(
sure that in roll-forward we get the same duplicate sure that in roll-forward we get the same duplicate
errors as in original execution */ errors as in original execution */
err = row_ins_set_shared_rec_lock(LOCK_REC_NOT_GAP, dict_accept(*trx->mysql_query_str, "REPLACE",
rec, cursor->index, thr); &success);
if (success) {
/* The manual defines the REPLACE semantics
that it is either an INSERT or DELETE(s)
for duplicate key + INSERT. Therefore, we
should take X-lock for duplicates */
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,rec,cursor->index,
thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,rec, cursor->index,
thr);
}
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(err); return(err);
...@@ -1611,8 +1675,30 @@ row_ins_duplicate_error_in_clust( ...@@ -1611,8 +1675,30 @@ row_ins_duplicate_error_in_clust(
if (rec != page_get_supremum_rec(page)) { if (rec != page_get_supremum_rec(page)) {
err = row_ins_set_shared_rec_lock(LOCK_REC_NOT_GAP,
rec, cursor->index, thr); /* The manual defines the REPLACE semantics that it
is either an INSERT or DELETE(s) for duplicate key
+ INSERT. Therefore, we should take X-lock for
duplicates.
*/
/* Is the first word in MySQL query REPLACE ? */
dict_accept(*trx->mysql_query_str, "REPLACE",
&success);
if (success) {
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,
rec,cursor->index,thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,rec,
cursor->index, thr);
}
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
return(err); return(err);
...@@ -1913,6 +1999,7 @@ row_ins_index_entry_set_vals( ...@@ -1913,6 +1999,7 @@ row_ins_index_entry_set_vals(
dfield_t* row_field; dfield_t* row_field;
ulint n_fields; ulint n_fields;
ulint i; ulint i;
dtype_t* cur_type;
ut_ad(entry && row); ut_ad(entry && row);
...@@ -1926,10 +2013,18 @@ row_ins_index_entry_set_vals( ...@@ -1926,10 +2013,18 @@ row_ins_index_entry_set_vals(
/* Check column prefix indexes */ /* Check column prefix indexes */
if (ind_field->prefix_len > 0 if (ind_field->prefix_len > 0
&& dfield_get_len(row_field) != UNIV_SQL_NULL && dfield_get_len(row_field) != UNIV_SQL_NULL) {
&& dfield_get_len(row_field) > ind_field->prefix_len) {
/* For prefix keys get the storage length
for the prefix_len characters. */
cur_type = dict_col_get_type(
dict_field_get_col(ind_field));
field->len = ind_field->prefix_len; field->len = innobase_get_at_most_n_mbchars(
dtype_get_charset_coll(cur_type->prtype),
ind_field->prefix_len,
dfield_get_len(row_field),row_field->data);
} else { } else {
field->len = row_field->len; field->len = row_field->len;
} }
......
...@@ -113,6 +113,8 @@ row_build_index_entry( ...@@ -113,6 +113,8 @@ row_build_index_entry(
dfield_t* dfield2; dfield_t* dfield2;
dict_col_t* col; dict_col_t* col;
ulint i; ulint i;
ulint storage_len;
dtype_t* cur_type;
ut_ad(row && index && heap); ut_ad(row && index && heap);
ut_ad(dtuple_check_typed(row)); ut_ad(dtuple_check_typed(row));
...@@ -139,10 +141,20 @@ row_build_index_entry( ...@@ -139,10 +141,20 @@ row_build_index_entry(
/* If a column prefix index, take only the prefix */ /* If a column prefix index, take only the prefix */
if (ind_field->prefix_len > 0 if (ind_field->prefix_len > 0
&& dfield_get_len(dfield2) != UNIV_SQL_NULL && dfield_get_len(dfield2) != UNIV_SQL_NULL) {
&& dfield_get_len(dfield2) > ind_field->prefix_len) {
dfield_set_len(dfield, ind_field->prefix_len); /* For prefix keys get the storage length
for the prefix_len characters. */
cur_type = dict_col_get_type(
dict_field_get_col(ind_field));
storage_len = innobase_get_at_most_n_mbchars(
dtype_get_charset_coll(cur_type->prtype),
ind_field->prefix_len,
dfield_get_len(dfield2),dfield2->data);
dfield_set_len(dfield,storage_len);
} }
} }
...@@ -460,6 +472,7 @@ row_build_row_ref_from_row( ...@@ -460,6 +472,7 @@ row_build_row_ref_from_row(
dict_col_t* col; dict_col_t* col;
ulint ref_len; ulint ref_len;
ulint i; ulint i;
dtype_t* cur_type;
ut_ad(ref && table && row); ut_ad(ref && table && row);
...@@ -481,10 +494,18 @@ row_build_row_ref_from_row( ...@@ -481,10 +494,18 @@ row_build_row_ref_from_row(
dfield_copy(dfield, dfield2); dfield_copy(dfield, dfield2);
if (field->prefix_len > 0 if (field->prefix_len > 0
&& dfield->len != UNIV_SQL_NULL && dfield->len != UNIV_SQL_NULL) {
&& dfield->len > field->prefix_len) {
/* For prefix keys get the storage length
for the prefix_len characters. */
cur_type = dict_col_get_type(
dict_field_get_col(field));
dfield->len = field->prefix_len; dfield->len = innobase_get_at_most_n_mbchars(
dtype_get_charset_coll(cur_type->prtype),
field->prefix_len,
dfield->len,dfield->data);
} }
} }
......
...@@ -76,6 +76,7 @@ row_sel_sec_rec_is_for_clust_rec( ...@@ -76,6 +76,7 @@ row_sel_sec_rec_is_for_clust_rec(
ulint clust_len; ulint clust_len;
ulint n; ulint n;
ulint i; ulint i;
dtype_t* cur_type;
UT_NOT_USED(clust_index); UT_NOT_USED(clust_index);
...@@ -91,10 +92,18 @@ row_sel_sec_rec_is_for_clust_rec( ...@@ -91,10 +92,18 @@ row_sel_sec_rec_is_for_clust_rec(
sec_field = rec_get_nth_field(sec_rec, i, &sec_len); sec_field = rec_get_nth_field(sec_rec, i, &sec_len);
if (ifield->prefix_len > 0 if (ifield->prefix_len > 0
&& clust_len != UNIV_SQL_NULL && clust_len != UNIV_SQL_NULL) {
&& clust_len > ifield->prefix_len) {
clust_len = ifield->prefix_len; /* For prefix keys get the storage length
for the prefix_len characters. */
cur_type = dict_col_get_type(
dict_field_get_col(ifield));
clust_len = innobase_get_at_most_n_mbchars(
dtype_get_charset_coll(cur_type->prtype),
ifield->prefix_len,
clust_len,clust_field);
} }
if (0 != cmp_data_data(dict_col_get_type(col), if (0 != cmp_data_data(dict_col_get_type(col),
......
...@@ -842,6 +842,7 @@ row_upd_index_replace_new_col_vals_index_pos( ...@@ -842,6 +842,7 @@ row_upd_index_replace_new_col_vals_index_pos(
dfield_t* new_val; dfield_t* new_val;
ulint j; ulint j;
ulint i; ulint i;
dtype_t* cur_type;
ut_ad(index); ut_ad(index);
...@@ -871,10 +872,19 @@ row_upd_index_replace_new_col_vals_index_pos( ...@@ -871,10 +872,19 @@ row_upd_index_replace_new_col_vals_index_pos(
} }
if (field->prefix_len > 0 if (field->prefix_len > 0
&& new_val->len != UNIV_SQL_NULL && new_val->len != UNIV_SQL_NULL) {
&& new_val->len > field->prefix_len) {
dfield->len = field->prefix_len; /* For prefix keys get the storage length
for the prefix_len characters. */
cur_type = dict_col_get_type(
dict_field_get_col(field));
dfield->len =
innobase_get_at_most_n_mbchars(
dtype_get_charset_coll(cur_type->prtype),
field->prefix_len,
new_val->len,new_val->data);
} }
} }
} }
...@@ -904,6 +914,7 @@ row_upd_index_replace_new_col_vals( ...@@ -904,6 +914,7 @@ row_upd_index_replace_new_col_vals(
dfield_t* new_val; dfield_t* new_val;
ulint j; ulint j;
ulint i; ulint i;
dtype_t* cur_type;
ut_ad(index); ut_ad(index);
...@@ -933,10 +944,19 @@ row_upd_index_replace_new_col_vals( ...@@ -933,10 +944,19 @@ row_upd_index_replace_new_col_vals(
} }
if (field->prefix_len > 0 if (field->prefix_len > 0
&& new_val->len != UNIV_SQL_NULL && new_val->len != UNIV_SQL_NULL) {
&& new_val->len > field->prefix_len) {
/* For prefix keys get the storage length
for the prefix_len characters. */
cur_type = dict_col_get_type(
dict_field_get_col(field));
dfield->len = field->prefix_len; dfield->len =
innobase_get_at_most_n_mbchars(
dtype_get_charset_coll(cur_type->prtype),
field->prefix_len,
new_val->len,new_val->data);
} }
} }
} }
......
...@@ -316,6 +316,39 @@ select c cb20 from t1 where c=repeat('b',20); ...@@ -316,6 +316,39 @@ select c cb20 from t1 where c=repeat('b',20);
cb20 cb20
bbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbb
drop table t1; drop table t1;
create table t1 (c varchar(30) character set utf8, unique(c(10))) engine=innodb;
insert into t1 values ('1'),('2'),('3'),('x'),('y'),('z');
insert into t1 values ('aaaaaaaaaa');
insert into t1 values ('aaaaaaaaaaa');
ERROR 23000: Duplicate entry 'aaaaaaaaaaa' for key 1
insert into t1 values ('aaaaaaaaaaaa');
ERROR 23000: Duplicate entry 'aaaaaaaaaaaa' for key 1
insert into t1 values (repeat('b',20));
select c c1 from t1 where c='1';
c1
1
select c c2 from t1 where c='2';
c2
2
select c c3 from t1 where c='3';
c3
3
select c cx from t1 where c='x';
cx
x
select c cy from t1 where c='y';
cy
y
select c cz from t1 where c='z';
cz
z
select c ca10 from t1 where c='aaaaaaaaaa';
ca10
aaaaaaaaaa
select c cb20 from t1 where c=repeat('b',20);
cb20
bbbbbbbbbbbbbbbbbbbb
drop table t1;
create table t1 (c char(3) character set utf8, unique (c(2))); create table t1 (c char(3) character set utf8, unique (c(2)));
insert into t1 values ('1'),('2'),('3'),('4'),('x'),('y'),('z'); insert into t1 values ('1'),('2'),('3'),('4'),('x'),('y'),('z');
insert into t1 values ('a'); insert into t1 values ('a');
...@@ -339,6 +372,29 @@ insert into t1 values ('ꪪꪪ'); ...@@ -339,6 +372,29 @@ insert into t1 values ('ꪪꪪ');
insert into t1 values ('ꪪꪪꪪ'); insert into t1 values ('ꪪꪪꪪ');
ERROR 23000: Duplicate entry 'ꪪꪪ' for key 1 ERROR 23000: Duplicate entry 'ꪪꪪ' for key 1
drop table t1; drop table t1;
create table t1 (c char(3) character set utf8, unique (c(2))) engine=innodb;
insert into t1 values ('1'),('2'),('3'),('4'),('x'),('y'),('z');
insert into t1 values ('a');
insert into t1 values ('aa');
insert into t1 values ('aaa');
ERROR 23000: Duplicate entry 'aaa' for key 1
insert into t1 values ('b');
insert into t1 values ('bb');
insert into t1 values ('bbb');
ERROR 23000: Duplicate entry 'bbb' for key 1
insert into t1 values ('а');
insert into t1 values ('аа');
insert into t1 values ('ааа');
ERROR 23000: Duplicate entry 'ааа' for key 1
insert into t1 values ('б');
insert into t1 values ('бб');
insert into t1 values ('ббб');
ERROR 23000: Duplicate entry 'ббб' for key 1
insert into t1 values ('ꪪ');
insert into t1 values ('ꪪꪪ');
insert into t1 values ('ꪪꪪꪪ');
ERROR 23000: Duplicate entry 'ꪪꪪ' for key 1
drop table t1;
create table t1 ( create table t1 (
c char(10) character set utf8, c char(10) character set utf8,
unique key a using hash (c(1)) unique key a using hash (c(1))
...@@ -611,6 +667,16 @@ str ...@@ -611,6 +667,16 @@ str
drop table t1; drop table t1;
create table t1 ( create table t1 (
str varchar(255) character set utf8 not null, str varchar(255) character set utf8 not null,
key str (str(2))
) engine=innodb;
INSERT INTO t1 VALUES ('str');
INSERT INTO t1 VALUES ('str2');
select * from t1 where str='str';
str
str
drop table t1;
create table t1 (
str varchar(255) character set utf8 not null,
key str using btree (str(2)) key str using btree (str(2))
) engine=heap; ) engine=heap;
INSERT INTO t1 VALUES ('str'); INSERT INTO t1 VALUES ('str');
......
...@@ -217,6 +217,27 @@ select c ca10 from t1 where c='aaaaaaaaaa'; ...@@ -217,6 +217,27 @@ select c ca10 from t1 where c='aaaaaaaaaa';
select c cb20 from t1 where c=repeat('b',20); select c cb20 from t1 where c=repeat('b',20);
drop table t1; drop table t1;
#
# Bug 4521: unique key prefix interacts poorly with utf8
# InnoDB: keys with prefix compression, case insensitive collation.
#
create table t1 (c varchar(30) character set utf8, unique(c(10))) engine=innodb;
insert into t1 values ('1'),('2'),('3'),('x'),('y'),('z');
insert into t1 values ('aaaaaaaaaa');
--error 1062
insert into t1 values ('aaaaaaaaaaa');
--error 1062
insert into t1 values ('aaaaaaaaaaaa');
insert into t1 values (repeat('b',20));
select c c1 from t1 where c='1';
select c c2 from t1 where c='2';
select c c3 from t1 where c='3';
select c cx from t1 where c='x';
select c cy from t1 where c='y';
select c cz from t1 where c='z';
select c ca10 from t1 where c='aaaaaaaaaa';
select c cb20 from t1 where c=repeat('b',20);
drop table t1;
# #
# Bug 4521: unique key prefix interacts poorly with utf8 # Bug 4521: unique key prefix interacts poorly with utf8
# MYISAM: fixed length keys, case insensitive collation # MYISAM: fixed length keys, case insensitive collation
...@@ -244,7 +265,33 @@ insert into t1 values ('ꪪꪪ'); ...@@ -244,7 +265,33 @@ insert into t1 values ('ꪪꪪ');
--error 1062 --error 1062
insert into t1 values ('ꪪꪪꪪ'); insert into t1 values ('ꪪꪪꪪ');
drop table t1; drop table t1;
#
# Bug 4521: unique key prefix interacts poorly with utf8
# InnoDB: fixed length keys, case insensitive collation
#
create table t1 (c char(3) character set utf8, unique (c(2))) engine=innodb;
insert into t1 values ('1'),('2'),('3'),('4'),('x'),('y'),('z');
insert into t1 values ('a');
insert into t1 values ('aa');
--error 1062
insert into t1 values ('aaa');
insert into t1 values ('b');
insert into t1 values ('bb');
--error 1062
insert into t1 values ('bbb');
insert into t1 values ('а');
insert into t1 values ('аа');
--error 1062
insert into t1 values ('ааа');
insert into t1 values ('б');
insert into t1 values ('бб');
--error 1062
insert into t1 values ('ббб');
insert into t1 values ('ꪪ');
insert into t1 values ('ꪪꪪ');
--error 1062
insert into t1 values ('ꪪꪪꪪ');
drop table t1;
# #
# Bug 4531: unique key prefix interacts poorly with utf8 # Bug 4531: unique key prefix interacts poorly with utf8
# Check HEAP+HASH, case insensitive collation # Check HEAP+HASH, case insensitive collation
...@@ -454,6 +501,18 @@ INSERT INTO t1 VALUES ('str2'); ...@@ -454,6 +501,18 @@ INSERT INTO t1 VALUES ('str2');
select * from t1 where str='str'; select * from t1 where str='str';
drop table t1; drop table t1;
# Bug#4594: column index make = failed for gbk, but like works
# Check InnoDB
#
create table t1 (
str varchar(255) character set utf8 not null,
key str (str(2))
) engine=innodb;
INSERT INTO t1 VALUES ('str');
INSERT INTO t1 VALUES ('str2');
select * from t1 where str='str';
drop table t1;
# the same for HEAP+BTREE # the same for HEAP+BTREE
# #
......
...@@ -41,6 +41,7 @@ have disables the InnoDB inlining in this file. */ ...@@ -41,6 +41,7 @@ have disables the InnoDB inlining in this file. */
#include <hash.h> #include <hash.h>
#include <myisampack.h> #include <myisampack.h>
#include <mysys_err.h> #include <mysys_err.h>
#include <my_sys.h>
#define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1)) #define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1))
...@@ -5270,4 +5271,61 @@ ulonglong ha_innobase::get_mysql_bin_log_pos() ...@@ -5270,4 +5271,61 @@ ulonglong ha_innobase::get_mysql_bin_log_pos()
return trx_sys_mysql_bin_log_pos; return trx_sys_mysql_bin_log_pos;
} }
extern "C" {
/***********************************************************************
This function finds charset information and returns the character
length for multibyte character set. */
ulint innobase_get_charset_mbmaxlen(
ulint charset_id) /* in: charset id */
{
CHARSET_INFO* charset; /* charset used in the field */
charset = get_charset(charset_id,MYF(MY_WME));
ut_ad(charset);
ut_ad(charset->mbmaxlen);
return charset->mbmaxlen;
}
}
extern "C" {
/***********************************************************************
This function finds charset information and returns position the nth
character for multibyte character set.*/
ulint innobase_get_at_most_n_mbchars(
ulint charset_id, /* in: character set id */
ulint nth, /* in: nth character */
ulint data_len, /* in: length of the sting in bytes */
const char *pos) /* in: character string */
{
ulint byte_length; /* storage length, in bytes. */
ulint char_length; /* character length in bytes */
CHARSET_INFO* charset; /* charset used in the field */
ut_ad(pos);
byte_length = data_len;
charset = get_charset(charset_id,MYF(MY_WME));
ut_ad(charset);
ut_ad(charset->mbmaxlen);
char_length= byte_length / charset->mbmaxlen;
nth = nth / charset->mbmaxlen;
if (byte_length > char_length)
{
char_length= my_charpos(charset, pos, pos + byte_length, nth);
set_if_smaller(char_length, byte_length);
}
else
char_length = nth;
return char_length;
}
}
#endif /* HAVE_INNOBASE_DB */ #endif /* HAVE_INNOBASE_DB */
...@@ -229,3 +229,4 @@ my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name, ...@@ -229,3 +229,4 @@ my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name,
void innobase_release_temporary_latches(void* innobase_tid); void innobase_release_temporary_latches(void* innobase_tid);
void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset); void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset);
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