summaryrefslogtreecommitdiff
path: root/innobase/row/row0sel.c
diff options
context:
space:
mode:
authorunknown <heikki@hundin.mysql.fi>2003-10-07 17:28:59 +0300
committerunknown <heikki@hundin.mysql.fi>2003-10-07 17:28:59 +0300
commitd1485aad0eb79559902b1af26502b7cc53f8e95a (patch)
treed53a5cc4e9736e149276ba08d53a7dd09a14b4fd /innobase/row/row0sel.c
parentd1ab51eb947623f45a8314cb9c0b6ddc15f0d148 (diff)
downloadmariadb-git-d1485aad0eb79559902b1af26502b7cc53f8e95a.tar.gz
Many files:
Multiple tablespaces for InnoDB sql_table.cc: Tell explicitly that InnoDB should retrieve all columns in CHECKSUM TABLE sql_update.cc, sql_select.cc, my_base.h: More descriptive flag name HA_EXTRA_RETRIEVE_ALL_COLS include/my_base.h: More descriptive flag name HA_EXTRA_RETRIEVE_ALL_COLS sql/sql_select.cc: More descriptive flag name HA_EXTRA_RETRIEVE_ALL_COLS sql/sql_update.cc: More descriptive flag name HA_EXTRA_RETRIEVE_ALL_COLS sql/sql_table.cc: Tell explicitly that InnoDB should retrieve all columns in CHECKSUM TABLE sql/sql_db.cc: Multiple tablespaces for InnoDB sql/ha_innodb.cc: Multiple tablespaces for InnoDB sql/mysqld.cc: Multiple tablespaces for InnoDB sql/set_var.cc: Multiple tablespaces for InnoDB sql/sql_cache.cc: Multiple tablespaces for InnoDB sql/ha_innodb.h: Multiple tablespaces for InnoDB innobase/include/btr0btr.ic: Multiple tablespaces for InnoDB innobase/include/btr0pcur.ic: Multiple tablespaces for InnoDB innobase/include/data0type.ic: Multiple tablespaces for InnoDB innobase/include/dyn0dyn.ic: Multiple tablespaces for InnoDB innobase/include/fut0lst.ic: Multiple tablespaces for InnoDB innobase/include/log0log.ic: Multiple tablespaces for InnoDB innobase/include/mach0data.ic: Multiple tablespaces for InnoDB innobase/include/mtr0log.ic: Multiple tablespaces for InnoDB innobase/include/rem0rec.ic: Multiple tablespaces for InnoDB innobase/include/ut0byte.ic: Multiple tablespaces for InnoDB innobase/include/ut0ut.ic: Multiple tablespaces for InnoDB innobase/include/buf0buf.h: Multiple tablespaces for InnoDB innobase/include/buf0lru.h: Multiple tablespaces for InnoDB innobase/include/buf0rea.h: Multiple tablespaces for InnoDB innobase/include/data0type.h: Multiple tablespaces for InnoDB innobase/include/db0err.h: Multiple tablespaces for InnoDB innobase/include/dict0boot.h: Multiple tablespaces for InnoDB innobase/include/dict0dict.h: Multiple tablespaces for InnoDB innobase/include/dict0load.h: Multiple tablespaces for InnoDB innobase/include/dict0mem.h: Multiple tablespaces for InnoDB innobase/include/fil0fil.h: Multiple tablespaces for InnoDB innobase/include/fsp0fsp.h: Multiple tablespaces for InnoDB innobase/include/ibuf0ibuf.h: Multiple tablespaces for InnoDB innobase/include/lock0lock.h: Multiple tablespaces for InnoDB innobase/include/log0log.h: Multiple tablespaces for InnoDB innobase/include/log0recv.h: Multiple tablespaces for InnoDB innobase/include/os0file.h: Multiple tablespaces for InnoDB innobase/include/page0page.h: Multiple tablespaces for InnoDB innobase/include/que0types.h: Multiple tablespaces for InnoDB innobase/include/rem0rec.h: Multiple tablespaces for InnoDB innobase/include/srv0srv.h: Multiple tablespaces for InnoDB innobase/include/srv0start.h: Multiple tablespaces for InnoDB innobase/include/sync0sync.h: Multiple tablespaces for InnoDB innobase/include/trx0sys.h: Multiple tablespaces for InnoDB innobase/include/ut0byte.h: Multiple tablespaces for InnoDB innobase/include/univ.i: Multiple tablespaces for InnoDB innobase/btr/btr0cur.c: Multiple tablespaces for InnoDB innobase/btr/btr0sea.c: Multiple tablespaces for InnoDB innobase/buf/buf0buf.c: Multiple tablespaces for InnoDB innobase/buf/buf0flu.c: Multiple tablespaces for InnoDB innobase/buf/buf0lru.c: Multiple tablespaces for InnoDB innobase/buf/buf0rea.c: Multiple tablespaces for InnoDB innobase/data/data0type.c: Multiple tablespaces for InnoDB innobase/dict/dict0boot.c: Multiple tablespaces for InnoDB innobase/dict/dict0crea.c: Multiple tablespaces for InnoDB innobase/dict/dict0dict.c: Multiple tablespaces for InnoDB innobase/dict/dict0load.c: Multiple tablespaces for InnoDB innobase/dict/dict0mem.c: Multiple tablespaces for InnoDB innobase/fil/fil0fil.c: Multiple tablespaces for InnoDB innobase/fsp/fsp0fsp.c: Multiple tablespaces for InnoDB innobase/ha/ha0ha.c: Multiple tablespaces for InnoDB innobase/ibuf/ibuf0ibuf.c: Multiple tablespaces for InnoDB innobase/log/log0log.c: Multiple tablespaces for InnoDB innobase/log/log0recv.c: Multiple tablespaces for InnoDB innobase/mach/mach0data.c: Multiple tablespaces for InnoDB innobase/mem/mem0dbg.c: Multiple tablespaces for InnoDB innobase/mem/mem0pool.c: Multiple tablespaces for InnoDB innobase/mtr/mtr0log.c: Multiple tablespaces for InnoDB innobase/os/os0file.c: Multiple tablespaces for InnoDB innobase/os/os0proc.c: Multiple tablespaces for InnoDB innobase/page/page0cur.c: Multiple tablespaces for InnoDB innobase/que/que0que.c: Multiple tablespaces for InnoDB innobase/row/row0ins.c: Multiple tablespaces for InnoDB innobase/row/row0mysql.c: Multiple tablespaces for InnoDB innobase/row/row0sel.c: Multiple tablespaces for InnoDB innobase/row/row0upd.c: Multiple tablespaces for InnoDB innobase/srv/srv0srv.c: Multiple tablespaces for InnoDB innobase/srv/srv0start.c: Multiple tablespaces for InnoDB innobase/sync/sync0rw.c: Multiple tablespaces for InnoDB innobase/sync/sync0sync.c: Multiple tablespaces for InnoDB innobase/trx/trx0sys.c: Multiple tablespaces for InnoDB innobase/trx/trx0trx.c: Multiple tablespaces for InnoDB innobase/trx/trx0undo.c: Multiple tablespaces for InnoDB innobase/ut/ut0byte.c: Multiple tablespaces for InnoDB innobase/ut/ut0ut.c: Multiple tablespaces for InnoDB
Diffstat (limited to 'innobase/row/row0sel.c')
-rw-r--r--innobase/row/row0sel.c133
1 files changed, 85 insertions, 48 deletions
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index d0f6965f94e..eced7628096 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -1905,6 +1905,7 @@ row_sel_convert_mysql_key_to_innobase(
ulint key_len) /* in: MySQL key value length */
{
byte* original_buf = buf;
+ byte* original_key_ptr = key_ptr;
dict_field_t* field;
dfield_t* dfield;
ulint data_offset;
@@ -2028,7 +2029,16 @@ row_sel_convert_mysql_key_to_innobase(
ut_print_timestamp(stderr);
fprintf(stderr,
- " InnoDB: Warning: using a partial-field key prefix in search\n");
+ " 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: key ptr now exceeds key end by %lu bytes.\n"
+ "InnoDB: Key value in the MySQL format:\n", index->table_name, index->name,
+ data_field_len,
+ (ulint)(key_ptr - key_end));
+ fflush(stderr);
+ ut_print_buf(original_key_ptr, key_len);
+ fflush(stdout);
+ fprintf(stderr, "\n");
if (!is_null) {
dfield->len -= (ulint)(key_ptr - key_end);
@@ -2155,9 +2165,10 @@ static
ibool
row_sel_store_mysql_rec(
/*====================*/
- /* out: TRUE if success, FALSE
- if could not allocate memory for a
- BLOB */
+ /* out: TRUE if success, FALSE if
+ could not allocate memory for a BLOB
+ (though we may also assert in that
+ case) */
byte* mysql_rec, /* out: row in the MySQL format */
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
rec_t* rec) /* in: Innobase record in the index
@@ -2169,8 +2180,9 @@ row_sel_store_mysql_rec(
byte* data;
ulint len;
byte* blob_buf;
+ int pad_char;
ulint i;
-
+
ut_ad(prebuilt->mysql_template);
if (prebuilt->blob_heap != NULL) {
@@ -2178,9 +2190,10 @@ row_sel_store_mysql_rec(
prebuilt->blob_heap = NULL;
}
- /* Mark all columns as SQL NULL */
+ /* MySQL assumes that all columns have the SQL NULL bit set unless it
+ is a nullable column with a non-NULL value */
- memset(mysql_rec, 255, prebuilt->null_bitmap_len);
+ memset(mysql_rec, 0xFF, prebuilt->null_bitmap_len);
for (i = 0; i < prebuilt->n_template; i++) {
@@ -2197,6 +2210,10 @@ row_sel_store_mysql_rec(
extern_field_heap = mem_heap_create(UNIV_PAGE_SIZE);
+ /* NOTE: if we are retrieving a big BLOB, we may
+ already run out of memory in the next call, which
+ causes an assert */
+
data = btr_rec_copy_externally_stored_field(rec,
templ->rec_field_no, &len,
extern_field_heap);
@@ -2209,20 +2226,28 @@ row_sel_store_mysql_rec(
ut_a(prebuilt->templ_contains_blob);
- /* A heuristic test that we can allocate
- the memory for a big BLOB. We have a safety
- margin of 1000000 bytes. Since the test
- takes some CPU time, we do not use for small
- BLOBs. */
+ /* A heuristic test that we can allocate the
+ memory for a big BLOB. We have a safety margin
+ of 1000000 bytes. Since the test takes some
+ CPU time, we do not use it for small BLOBs. */
if (len > 2000000
&& !ut_test_malloc(len + 1000000)) {
+ 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", len, prebuilt->table->name);
+
+ if (extern_field_heap) {
+ mem_heap_free(
+ extern_field_heap);
+ }
return(FALSE);
}
- /* Copy the BLOB data to the BLOB
- heap of prebuilt */
+ /* Copy the BLOB data to the BLOB heap of
+ prebuilt */
if (prebuilt->blob_heap == NULL) {
prebuilt->blob_heap =
@@ -2235,35 +2260,49 @@ row_sel_store_mysql_rec(
data = blob_buf;
}
-
+
row_sel_field_store_in_mysql_format(
mysql_rec + templ->mysql_col_offset,
templ->mysql_col_len, data, len,
templ->type, templ->is_unsigned);
-
+
+ /* Cleanup */
if (extern_field_heap) {
- mem_heap_free(extern_field_heap);
+ mem_heap_free(extern_field_heap);
extern_field_heap = NULL;
- }
-
+ }
+
if (templ->mysql_null_bit_mask) {
+ /* It is a nullable column with a non-NULL
+ value */
mysql_rec[templ->mysql_null_byte_offset] &=
~(byte) (templ->mysql_null_bit_mask);
}
} else {
/* MySQL seems to assume the field for an SQL NULL
- value is set to zero. Not taking this into account
- caused seg faults with NULL BLOB fields, and
+ value is set to zero or space. Not taking this into
+ account caused seg faults with NULL BLOB fields, and
bug number 154 in the MySQL bug database: GROUP BY
and DISTINCT could treat NULL values inequal. */
- memset(mysql_rec + templ->mysql_col_offset,
- ((templ->type == DATA_VARCHAR ||
- templ->type == DATA_VARMYSQL ||
- templ->type == DATA_BINARY) ? ' ' : '\0'),
- templ->mysql_col_len);
+ if (templ->type == DATA_VARCHAR
+ || templ->type == DATA_CHAR
+ || templ->type == DATA_BINARY
+ || templ->type == DATA_FIXBINARY
+ || templ->type == DATA_MYSQL
+ || templ->type == DATA_VARMYSQL) {
+ /* MySQL pads all non-BLOB and non-TEXT
+ string types with space ' ' */
+
+ pad_char = ' ';
+ } else {
+ pad_char = '\0';
+ }
+
+ memset(mysql_rec + templ->mysql_col_offset, pad_char,
+ templ->mysql_col_len);
}
- }
+ }
return(TRUE);
}
@@ -2590,9 +2629,9 @@ row_sel_push_cache_row_for_mysql(
ut_ad(prebuilt->fetch_cache_first == 0);
- row_sel_store_mysql_rec(
+ ut_a(row_sel_store_mysql_rec(
prebuilt->fetch_cache[prebuilt->n_fetch_cached],
- prebuilt, rec);
+ prebuilt, rec));
prebuilt->n_fetch_cached++;
}
@@ -2827,23 +2866,6 @@ row_search_for_mysql(
mode = pcur->search_mode;
}
- if ((direction == ROW_SEL_NEXT || direction == ROW_SEL_PREV)
- && pcur->old_stored != BTR_PCUR_OLD_STORED) {
-
- /* MySQL sometimes seems to do fetch next or fetch prev even
- if the search condition is unique; this can, for example,
- happen with the HANDLER commands; we do not always store the
- pcur position in this case, so we cannot restore cursor
- position, and must return immediately */
-
- /* printf("%s record not found 1\n", index->name); */
-
- trx->op_info = (char *) "";
- return(DB_RECORD_NOT_FOUND);
- }
-
- mtr_start(&mtr);
-
/* In a search where at most one record in the index may match, we
can use a LOCK_REC_NOT_GAP type record lock when locking a non-delete-
marked matching record.
@@ -2858,8 +2880,21 @@ row_search_for_mysql(
&& dtuple_get_n_fields(search_tuple)
== dict_index_get_n_unique(index)) {
unique_search = TRUE;
+
+ /* Even if the condition is unique, MySQL seems to try to
+ retrieve also a second row if a primary key contains more than
+ 1 column. Return immediately if this is not a HANDLER
+ command. */
+
+ if (direction != 0 && !prebuilt->used_in_HANDLER) {
+
+ trx->op_info = (char *) "";
+ return(DB_RECORD_NOT_FOUND);
+ }
}
+ mtr_start(&mtr);
+
/*-------------------------------------------------------------*/
/* PHASE 2: Try fast adaptive hash index search if possible */
@@ -2912,7 +2947,9 @@ row_search_for_mysql(
rec)) {
err = DB_TOO_BIG_RECORD;
- goto lock_wait_or_error;
+ /* We let the main loop to do the
+ error handling */
+ goto shortcut_fails_too_big_rec;
}
mtr_commit(&mtr);
@@ -2960,7 +2997,7 @@ row_search_for_mysql(
return(DB_RECORD_NOT_FOUND);
}
-
+shortcut_fails_too_big_rec:
mtr_commit(&mtr);
mtr_start(&mtr);
}