summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
authorunknown <jan@hundin.mysql.fi>2004-09-16 21:32:05 +0300
committerunknown <jan@hundin.mysql.fi>2004-09-16 21:32:05 +0300
commit86489bd0c4f45dda2874c19a75da50b466b36997 (patch)
treeabe9ef010397f4b41f9d7858c1644b29925b4556 /innobase
parent38628bca1b08b3f5d97d3e4ec2425e022ed0f501 (diff)
parentbfe3df38b7f9313ef19c6ed50ab8b916ecd79e9c (diff)
downloadmariadb-git-86489bd0c4f45dda2874c19a75da50b466b36997.tar.gz
Merge jlindstrom@build.mysql.com:/home/bk/mysql-4.1
into hundin.mysql.fi:/home/jan/mysql-4.1 mysql-test/r/ctype_utf8.result: Auto merged mysql-test/t/ctype_utf8.test: Auto merged sql/ha_innodb.cc: Auto merged sql/ha_innodb.h: Auto merged
Diffstat (limited to 'innobase')
-rw-r--r--innobase/btr/btr0btr.c9
-rw-r--r--innobase/lock/lock0lock.c35
-rw-r--r--innobase/rem/rem0cmp.c5
-rw-r--r--innobase/row/row0ins.c119
-rw-r--r--innobase/row/row0row.c33
-rw-r--r--innobase/row/row0sel.c15
-rw-r--r--innobase/row/row0upd.c32
7 files changed, 209 insertions, 39 deletions
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c
index 27d798f925a..e31aadbbfff 100644
--- a/innobase/btr/btr0btr.c
+++ b/innobase/btr/btr0btr.c
@@ -2400,14 +2400,17 @@ btr_index_rec_validate(
dtype_t* type = dict_index_get_nth_type(index, i);
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
&& len != UNIV_SQL_NULL && dtype_is_fixed_size(type)
&& len != dtype_get_fixed_size(type))
||
(dict_index_get_nth_field(index, i)->prefix_len > 0
- && len != UNIV_SQL_NULL && dtype_is_fixed_size(type)
- && len !=
+ && len != UNIV_SQL_NULL
+ && len >
dict_index_get_nth_field(index, i)->prefix_len)) {
btr_index_rec_validate_report(page, rec, index);
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index c9c0cd109a9..5705c8b0b3e 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -756,9 +756,13 @@ lock_rec_has_to_wait(
ulint type_mode,/* in: precise mode of the new lock to set:
LOCK_S or LOCK_X, possibly ORed to
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
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(lock_get_type(lock2) == LOCK_REC);
@@ -770,10 +774,22 @@ lock_rec_has_to_wait(
/* We have somewhat complex rules when gap type record locks
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 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);
}
@@ -829,9 +845,13 @@ lock_has_to_wait(
lock_get_mode(lock2))) {
if (lock_get_type(lock1) == 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,
- lock1->type_mode, lock2));
+ lock1->type_mode, lock2,
+ lock_rec_get_nth_bit(lock1,1)));
}
return(TRUE);
@@ -1420,7 +1440,8 @@ lock_rec_other_has_conflicting(
lock = lock_rec_get_first(rec);
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);
}
diff --git a/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c
index 6e8f3d82ef3..041fb7914e2 100644
--- a/innobase/rem/rem0cmp.c
+++ b/innobase/rem/rem0cmp.c
@@ -452,7 +452,7 @@ cmp_dtuple_rec_with_match(
ulint cur_bytes; /* number of already matched bytes
in current field */
int ret = 3333; /* return value */
-
+
ut_ad(dtuple && rec && matched_fields && matched_bytes);
ut_ad(dtuple_check_typed(dtuple));
@@ -541,7 +541,8 @@ cmp_dtuple_rec_with_match(
&& dtype_get_charset_coll(cur_type->prtype) !=
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,
rec_b_ptr, rec_f_len);
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 0da749212d2..35641c351a1 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -1022,6 +1022,33 @@ row_ins_set_shared_rec_lock(
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
@@ -1451,6 +1478,8 @@ row_ins_scan_sec_index_for_duplicate(
ulint err = DB_SUCCESS;
ibool moved;
mtr_t mtr;
+ trx_t *trx;
+ ibool success;
n_unique = dict_index_get_n_unique(index);
@@ -1488,8 +1517,24 @@ row_ins_scan_sec_index_for_duplicate(
/* Try to place a lock on the index record */
- err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec, index,
- thr);
+ trx = thr_get_trx(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) {
@@ -1556,6 +1601,7 @@ row_ins_duplicate_error_in_clust(
page_t* page;
ulint n_unique;
trx_t* trx = thr_get_trx(thr);
+ ibool success;
UT_NOT_USED(mtr);
@@ -1588,9 +1634,27 @@ row_ins_duplicate_error_in_clust(
is needed in logical logging of MySQL to make
sure that in roll-forward we get the same duplicate
errors as in original execution */
-
- err = row_ins_set_shared_rec_lock(LOCK_REC_NOT_GAP,
- rec, cursor->index, thr);
+
+ 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_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) {
return(err);
@@ -1611,8 +1675,30 @@ row_ins_duplicate_error_in_clust(
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) {
return(err);
@@ -1913,6 +1999,7 @@ row_ins_index_entry_set_vals(
dfield_t* row_field;
ulint n_fields;
ulint i;
+ dtype_t* cur_type;
ut_ad(entry && row);
@@ -1926,10 +2013,18 @@ row_ins_index_entry_set_vals(
/* Check column prefix indexes */
if (ind_field->prefix_len > 0
- && dfield_get_len(row_field) != UNIV_SQL_NULL
- && dfield_get_len(row_field) > ind_field->prefix_len) {
-
- field->len = ind_field->prefix_len;
+ && dfield_get_len(row_field) != UNIV_SQL_NULL) {
+
+ /* 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 = 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 {
field->len = row_field->len;
}
@@ -2214,4 +2309,4 @@ error_handling:
}
return(thr);
-}
+}
diff --git a/innobase/row/row0row.c b/innobase/row/row0row.c
index 680539764fd..ed6462b7377 100644
--- a/innobase/row/row0row.c
+++ b/innobase/row/row0row.c
@@ -113,6 +113,8 @@ row_build_index_entry(
dfield_t* dfield2;
dict_col_t* col;
ulint i;
+ ulint storage_len;
+ dtype_t* cur_type;
ut_ad(row && index && heap);
ut_ad(dtuple_check_typed(row));
@@ -139,10 +141,20 @@ row_build_index_entry(
/* If a column prefix index, take only the prefix */
if (ind_field->prefix_len > 0
- && dfield_get_len(dfield2) != UNIV_SQL_NULL
- && dfield_get_len(dfield2) > ind_field->prefix_len) {
+ && dfield_get_len(dfield2) != UNIV_SQL_NULL) {
- 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(
dict_col_t* col;
ulint ref_len;
ulint i;
+ dtype_t* cur_type;
ut_ad(ref && table && row);
@@ -481,10 +494,18 @@ row_build_row_ref_from_row(
dfield_copy(dfield, dfield2);
if (field->prefix_len > 0
- && dfield->len != UNIV_SQL_NULL
- && dfield->len > field->prefix_len) {
+ && dfield->len != UNIV_SQL_NULL) {
+
+ /* 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);
}
}
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 2c0092adc6e..d87cc857651 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -76,6 +76,7 @@ row_sel_sec_rec_is_for_clust_rec(
ulint clust_len;
ulint n;
ulint i;
+ dtype_t* cur_type;
UT_NOT_USED(clust_index);
@@ -91,10 +92,18 @@ row_sel_sec_rec_is_for_clust_rec(
sec_field = rec_get_nth_field(sec_rec, i, &sec_len);
if (ifield->prefix_len > 0
- && clust_len != UNIV_SQL_NULL
- && clust_len > ifield->prefix_len) {
+ && clust_len != UNIV_SQL_NULL) {
- 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),
diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c
index d35ae0a3e38..75400e06059 100644
--- a/innobase/row/row0upd.c
+++ b/innobase/row/row0upd.c
@@ -842,6 +842,7 @@ row_upd_index_replace_new_col_vals_index_pos(
dfield_t* new_val;
ulint j;
ulint i;
+ dtype_t* cur_type;
ut_ad(index);
@@ -871,10 +872,19 @@ row_upd_index_replace_new_col_vals_index_pos(
}
if (field->prefix_len > 0
- && new_val->len != UNIV_SQL_NULL
- && new_val->len > field->prefix_len) {
+ && new_val->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 =
+ 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(
dfield_t* new_val;
ulint j;
ulint i;
+ dtype_t* cur_type;
ut_ad(index);
@@ -933,10 +944,19 @@ row_upd_index_replace_new_col_vals(
}
if (field->prefix_len > 0
- && new_val->len != UNIV_SQL_NULL
- && new_val->len > field->prefix_len) {
+ && new_val->len != UNIV_SQL_NULL) {
+
+ /* 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);
}
}
}