Re: Warning: using a partial-field key prefix in search.
"Heikki Tuuri" <[email protected]>
| Newsgroups | gmane.comp.db.mysql.bugs |
|---|---|
| Message-ID | <118501c40539$f8dc5300$155110ac@hebis> |
Hi! I am able to repeat the warning with a relatively recent build of 4.1.2 with just an empty table. The 'hack' function below apparently copies some list of ranges from QUICK_SELECT to QUICK_SELECT_DESC. Then, in QUICK_SELECT_DESC::get_next(), 'range' is nonsensical. It is on a 4-byte integer column, but the key value in the range is only 2 bytes! People have reported this warning in the .err log also before. " ----- Original Message ----- From: ""Mechain Marc"" <[email protected]> Newsgroups: mailing.database.mysql Sent: Tuesday, August 19, 2003 5:09 PM Subject: What's the meaning of: "InnoDB: Warning: using a partial-field key prefix in search" " Unfortunately, Marc never told what MySQL version he was using. Regards, Heikki /sql/opt_range.cc: /* This is a hack: we inherit from QUICK_SELECT so that we can use the get_next() interface, but we have to hold a pointer to the original QUICK_SELECT because its data are used all over the place. What should be done is to factor out the data that is needed into a base class (QUICK_SELECT), and then have two subclasses (_ASC and _DESC) which handle the ranges and implement the get_next() function. But for now, this seems to work right at least. */ QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_SELECT *q, uint used_key_parts) : QUICK_SELECT(*q), rev_it(rev_ranges) { bool not_read_after_key = file->table_flags() & HA_NOT_READ_AFTER_KEY; QUICK_RANGE *r; it.rewind(); for (r = it++; r; r = it++) { rev_ranges.push_front(r); if (not_read_after_key && range_reads_after_key(r)) { it.rewind(); // Reset range error = HA_ERR_UNSUPPORTED; dont_free=1; // Don't free memory from 'q' return; } } /* Remove EQ_RANGE flag for keys that are not using the full key */ for (r = rev_it++; r; r = rev_it++) { if ((r->flag & EQ_RANGE) && head->key_info[index].key_length != r->max_length) r->flag&= ~EQ_RANGE; } rev_it.rewind(); q->dont_free=1; // Don't free shared mem delete q; } int QUICK_SELECT_DESC::get_next() { DBUG_ENTER("QUICK_SELECT_DESC::get_next"); /* The max key is handled as follows: * - if there is NO_MAX_RANGE, start at the end and move backwards * - if it is an EQ_RANGE, which means that max key covers the entire * key, go directly to the key and read through it (sorting backwards is * same as sorting forwards) * - if it is NEAR_MAX, go to the key or next, step back once, and * move backwards * - otherwise (not NEAR_MAX == include the key), go after the key, * step back once, and move backwards */ for (;;) { int result; if (range) { // Already read through key result = ((range->flag & EQ_RANGE) ? file->index_next_same(record, (byte*) range->min_key, range->min_length) : file->index_prev(record)); if (!result) { if (cmp_prev(*rev_it.ref()) == 0) DBUG_RETURN(0); } else if (result != HA_ERR_END_OF_FILE) DBUG_RETURN(result); } if (!(range=rev_it++)) DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used if (range->flag & NO_MAX_RANGE) // Read last record { int local_error; if ((local_error=file->index_last(record))) DBUG_RETURN(local_error); // Empty table if (cmp_prev(range) == 0) DBUG_RETURN(0); range=0; // No matching records; go to next range continue; } if (range->flag & EQ_RANGE) { result = file->index_read(record, (byte*) range->max_key, range->max_length, HA_READ_KEY_EXACT); } else { DBUG_ASSERT(range->flag & NEAR_MAX || range_reads_after_key(range)); #ifndef NOT_IMPLEMENTED_YET result=file->index_read(record, (byte*) range->max_key, range->max_length, ((range->flag & NEAR_MAX) ? HA_READ_BEFORE_KEY : HA_READ_PREFIX_LAST_OR_PREV\ )); #else /* Heikki changed Sept 11, 2002: since InnoDB does not store the cursor position if READ_KEY_EXACT is used to a primary key with all key columns specified, we must use below HA_READ_KEY_OR_NEXT, so that InnoDB stores the cursor position and is able to move the cursor one step backward after the search. */ /* Note: even if max_key is only a prefix, HA_READ_AFTER_KEY will do the right thing - go past all keys which match the prefix */ result=file->index_read(record, (byte*) range->max_key, range->max_length, ((range->flag & NEAR_MAX) ? HA_READ_KEY_OR_NEXT : HA_READ_AFTER_KEY)); result = file->index_prev(record); #endi -- MySQL Bugs Mailing List For list archives: http://lists.mysql.com/bugs To unsubscribe: http://lists.mysql.com/[email protected]