summaryrefslogtreecommitdiff
path: root/innobase/row/row0sel.c
diff options
context:
space:
mode:
authorunknown <monty@mysql.com>2004-10-29 19:26:52 +0300
committerunknown <monty@mysql.com>2004-10-29 19:26:52 +0300
commitf095274fe8c3d3394d6c0ce0a68f4bea04311999 (patch)
tree23bcc9a71fe7237887a111b158e30f5a6bb665d3 /innobase/row/row0sel.c
parentf41bba8c6156a7adf4c67dfa75e16112767a5d3c (diff)
parent5be6c328f5a9f78f37176bbbd88a538fa3b65fe9 (diff)
downloadmariadb-git-f095274fe8c3d3394d6c0ce0a68f4bea04311999.tar.gz
merge with 4.1
BitKeeper/etc/ignore: auto-union BitKeeper/etc/logging_ok: auto-union BitKeeper/triggers/post-commit: Auto merged Docs/Support/texi2html: Auto merged Makefile.am: Auto merged client/Makefile.am: Auto merged client/mysql.cc: Auto merged client/mysqldump.c: Auto merged include/my_base.h: Auto merged include/my_global.h: Auto merged include/my_pthread.h: Auto merged include/my_sys.h: Auto merged include/my_time.h: Auto merged include/mysql.h: Auto merged include/mysql_com.h: Auto merged innobase/buf/buf0buf.c: Auto merged innobase/include/row0mysql.h: Auto merged innobase/row/row0sel.c: Auto merged libmysql/libmysql.c: Auto merged libmysqld/examples/Makefile.am: Auto merged myisam/mi_check.c: Auto merged mysql-test/include/ps_modify.inc: Auto merged mysql-test/install_test_db.sh: Auto merged mysql-test/r/alter_table.result: Auto merged mysql-test/r/auto_increment.result: Auto merged mysql-test/r/bdb.result: Auto merged mysql-test/r/ctype_latin1_de.result: Auto merged mysql-test/r/ctype_recoding.result: Auto merged mysql-test/r/fulltext.result: Auto merged mysql-test/r/func_gconcat.result: Auto merged mysql-test/r/func_group.result: Auto merged mysql-test/r/func_if.result: Auto merged mysql-test/t/derived.test: Auto merged mysql-test/t/insert.test: merge with 4.1 Fixed test case to not use 'if exists' when it shouldn't mysql-test/t/range.test: merge with 4.1 Added missing drop table sql/ha_ndbcluster.cc: merge with 4.1 Simple optimization: use max() instead of ? : sql/item_func.cc: merge with 4.1 (Added back old variable names for easier merges) sql/opt_range.cc: merge with 4.1 Removed argument 'parent_alloc' from QUICK_RANGE_SELECT as this was not used Added assert if using QUICK_GROUP_MIN_MAX_SELECT with parent_alloc as the init() function can't handle this Changed back get_quick_select_for_ref() to use it's own alloc root becasue this function may be called several times for one query sql/sql_handler.cc: merge with 4.1 change variable 'err' to 'error' as same function had a label named 'err' sql/sql_update.cc: Use multi-update code from 5.0 instead of 4.1 We will fix the locking code shortly in 5.0 to be faster than in 4.1
Diffstat (limited to 'innobase/row/row0sel.c')
-rw-r--r--innobase/row/row0sel.c107
1 files changed, 60 insertions, 47 deletions
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index dc6694fc18c..71163bc35b6 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,15 @@ 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;
+ cur_type = dict_col_get_type(
+ dict_field_get_col(ifield));
+
+ clust_len = dtype_get_at_most_n_mbchars(
+ cur_type,
+ ifield->prefix_len,
+ clust_len, clust_field);
}
if (0 != cmp_data_data(dict_col_get_type(col),
@@ -1942,7 +1948,8 @@ row_sel_convert_mysql_key_to_innobase(
ulint buf_len, /* in: buffer length */
dict_index_t* index, /* in: index of the key value */
byte* key_ptr, /* in: MySQL key value */
- ulint key_len) /* in: MySQL key value length */
+ ulint key_len, /* in: MySQL key value length */
+ trx_t* trx) /* in: transaction */
{
byte* original_buf = buf;
byte* original_key_ptr = key_ptr;
@@ -2017,19 +2024,15 @@ row_sel_convert_mysql_key_to_innobase(
/* MySQL stores the actual data length to the first 2
bytes after the optional SQL NULL marker byte. The
- storage format is little-endian. */
-
- /* There are no key fields > 255 bytes currently in
- MySQL */
- if (key_ptr[data_offset + 1] != 0) {
- ut_print_timestamp(stderr);
- fputs(
-" InnoDB: Error: BLOB or TEXT prefix > 255 bytes in query to table ", stderr);
- ut_print_name(stderr, index->table_name);
- putc('\n', stderr);
- }
-
- data_len = key_ptr[data_offset];
+ storage format is little-endian, that is, the most
+ significant byte at a higher address. In UTF-8, MySQL
+ seems to reserve field->prefix_len bytes for
+ storing this field in the key value buffer, even
+ though the actual value only takes data_len bytes
+ from the start. */
+
+ data_len = key_ptr[data_offset]
+ + 256 * key_ptr[data_offset + 1];
data_field_len = data_offset + 2 + field->prefix_len;
data_offset += 2;
@@ -2037,6 +2040,17 @@ row_sel_convert_mysql_key_to_innobase(
store the column value like it would
be a fixed char field */
} else if (field->prefix_len > 0) {
+ /* Looks like MySQL pads unused end bytes in the
+ prefix with space. Therefore, also in UTF-8, it is ok
+ to compare with a prefix containing full prefix_len
+ bytes, and no need to take at most prefix_len / 3
+ UTF-8 characters from the start.
+ If the prefix is used as the upper end of a LIKE
+ 'abc%' query, then MySQL pads the end with chars
+ 0xff. TODO: in that case does it any harm to compare
+ with the full prefix_len bytes. How do characters
+ 0xff in UTF-8 behave? */
+
data_len = field->prefix_len;
data_field_len = data_offset + data_len;
} else {
@@ -2069,11 +2083,13 @@ row_sel_convert_mysql_key_to_innobase(
ut_print_timestamp(stderr);
- fprintf(stderr,
+ fputs(
" InnoDB: Warning: using a partial-field key prefix in search.\n"
- "InnoDB: Table name %s, index name %s. Last data field length %lu bytes,\n"
+ "InnoDB: ", stderr);
+ dict_index_name_print(stderr, trx, index);
+ fprintf(stderr, ". Last data field length %lu bytes,\n"
"InnoDB: key ptr now exceeds key end by %lu bytes.\n"
- "InnoDB: Key value in the MySQL format:\n", index->table_name, index->name,
+ "InnoDB: Key value in the MySQL format:\n",
(ulong) data_field_len,
(ulong) (key_ptr - key_end));
fflush(stderr);
@@ -2116,7 +2132,7 @@ row_sel_store_row_id_to_prebuilt(
if (len != DATA_ROW_ID_LEN) {
fprintf(stderr,
"InnoDB: Error: Row id field is wrong length %lu in ", (ulong) len);
- dict_index_name_print(stderr, index);
+ dict_index_name_print(stderr, prebuilt->trx, index);
fprintf(stderr, "\n"
"InnoDB: Field number %lu, record:\n",
(ulong) dict_index_get_sys_col_pos(index, DATA_ROW_ID));
@@ -2275,7 +2291,11 @@ row_sel_store_mysql_rec(
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Warning: could not allocate %lu + 1000000 bytes to retrieve\n"
-"InnoDB: a big column. Table name %s\n", (ulong) len, prebuilt->table->name);
+"InnoDB: a big column. Table name ", (ulong) len);
+ ut_print_name(stderr,
+ prebuilt->trx,
+ prebuilt->table->name);
+ putc('\n', stderr);
if (extern_field_heap) {
mem_heap_free(
@@ -2407,8 +2427,9 @@ row_sel_get_clust_rec_for_mysql(
trx_t* trx;
*out_rec = NULL;
+ trx = thr_get_trx(thr);
- row_build_row_ref_in_tuple(prebuilt->clust_ref, sec_index, rec);
+ row_build_row_ref_in_tuple(prebuilt->clust_ref, sec_index, rec, trx);
clust_index = dict_table_get_first_index(sec_index->table);
@@ -2441,7 +2462,7 @@ row_sel_get_clust_rec_for_mysql(
fputs(" InnoDB: error clustered record"
" for sec rec not found\n"
"InnoDB: ", stderr);
- dict_index_name_print(stderr, sec_index);
+ dict_index_name_print(stderr, trx, sec_index);
fputs("\n"
"InnoDB: sec index record ", stderr);
rec_print(stderr, rec);
@@ -2449,7 +2470,7 @@ row_sel_get_clust_rec_for_mysql(
"InnoDB: clust index record ", stderr);
rec_print(stderr, clust_rec);
putc('\n', stderr);
- trx_print(stderr, thr_get_trx(thr));
+ trx_print(stderr, trx);
fputs("\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);
@@ -2477,8 +2498,6 @@ row_sel_get_clust_rec_for_mysql(
/* This is a non-locking consistent read: if necessary, fetch
a previous version of the record */
- trx = thr_get_trx(thr);
-
old_vers = NULL;
/* If the isolation level allows reading of uncommitted data,
@@ -2800,7 +2819,7 @@ row_search_for_mysql(
rec_t* index_rec;
rec_t* clust_rec;
rec_t* old_vers;
- ulint err;
+ ulint err = DB_SUCCESS;
ibool moved;
ibool cons_read_requires_clust_rec;
ibool was_lock_wait;
@@ -2828,7 +2847,7 @@ row_search_for_mysql(
"InnoDB: Error: trying to free a corrupt\n"
"InnoDB: table handle. Magic n %lu, table name ",
(ulong) prebuilt->magic_n);
- ut_print_name(stderr, prebuilt->table->name);
+ ut_print_name(stderr, trx, prebuilt->table->name);
putc('\n', stderr);
mem_analyze_corruption((byte*)prebuilt);
@@ -3209,26 +3228,20 @@ rec_loop:
if (prebuilt->select_lock_type != LOCK_NONE
&& set_also_gap_locks) {
- /* Try to place a lock on the index record */
+ /* Try to place a lock on the index record */
- /* If innodb_locks_unsafe_for_binlog option is used,
- we lock only the record, i.e. next-key locking is
- not used.
- */
- if ( srv_locks_unsafe_for_binlog )
- {
- err = sel_set_rec_lock(rec, index,
- prebuilt->select_lock_type,
- LOCK_REC_NOT_GAP, thr);
- }
- else
+ /* If innodb_locks_unsafe_for_binlog option is used,
+ we do not lock gaps. Supremum record is really
+ a gap and therefore we do not set locks there. */
+
+ if ( srv_locks_unsafe_for_binlog == FALSE )
{
- err = sel_set_rec_lock(rec, index,
+ err = sel_set_rec_lock(rec, index,
prebuilt->select_lock_type,
LOCK_ORDINARY, thr);
}
-
- if (err != DB_SUCCESS) {
+
+ if (err != DB_SUCCESS) {
goto lock_wait_or_error;
}
@@ -3262,7 +3275,7 @@ rec_loop:
(ulong) (rec - buf_frame_align(rec)),
(ulong) next_offs,
(ulong) buf_frame_get_page_no(rec));
- dict_index_name_print(stderr, index);
+ dict_index_name_print(stderr, trx, index);
fputs(". Run CHECK TABLE. You may need to\n"
"InnoDB: restore from a backup, or dump + drop + reimport the table.\n",
stderr);
@@ -3280,7 +3293,7 @@ rec_loop:
(ulong) (rec - buf_frame_align(rec)),
(ulong) next_offs,
(ulong) buf_frame_get_page_no(rec));
- dict_index_name_print(stderr, index);
+ dict_index_name_print(stderr, trx, index);
fputs(". We try to skip the rest of the page.\n",
stderr);
@@ -3299,7 +3312,7 @@ rec_loop:
(ulong) (rec - buf_frame_align(rec)),
(ulong) next_offs,
(ulong) buf_frame_get_page_no(rec));
- dict_index_name_print(stderr, index);
+ dict_index_name_print(stderr, trx, index);
fputs(". We try to skip the record.\n",
stderr);