diff options
author | unknown <monty@mysql.com> | 2004-10-29 19:26:52 +0300 |
---|---|---|
committer | unknown <monty@mysql.com> | 2004-10-29 19:26:52 +0300 |
commit | f095274fe8c3d3394d6c0ce0a68f4bea04311999 (patch) | |
tree | 23bcc9a71fe7237887a111b158e30f5a6bb665d3 /innobase/row/row0sel.c | |
parent | f41bba8c6156a7adf4c67dfa75e16112767a5d3c (diff) | |
parent | 5be6c328f5a9f78f37176bbbd88a538fa3b65fe9 (diff) | |
download | mariadb-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.c | 107 |
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); |