Pantek Library
Hosting Provided By
CybrHost
High Speed Hosting

Re: [Fwd: How to report duplicate key values in handler::add_index()?]

From: Ingo Strüwing <ingo(at)mysql.com>
Date: Mon Aug 27 2007 - 06:24:41 EDT


Hi Martin,

Martin Skold, 17.08.2007 16:40:
> Hi Ingo!
>
> Any ideas how we can add support for this?
...
> ------------------------------------------------------------------------
>
> Betreff:
> How to report duplicate key values in handler::add_index()?
> Von:
> Marko Mäkelä <marko.makela@oracle.com>
> Datum:
> Wed, 15 Aug 2007 13:03:27 +0300
> An:
> internals@lists.mysql.com

...
> I have a problem with reporting duplicate key errors in CREATE UNIQUE
> INDEX. How can the storage engine return a duplicate key value in
> handler::add_index()?
>
> As far as I understand, the key value that MySQL reports to the client
> is read from the TABLE::key_info array by key_unpack(), in sql/key.cc.
> But it is not obvious to me how this information could be updated.
> Perhaps something like restore_record() followed by something that
> copies table->record[0] to table->key_info[]?

table->record[0] contains the row data.

table->key_info[] contains index information for the existing indexes. table->s->keys tells the array size. key_info does not contain row data or key data. It just points into table->record[0] so that the keys can be constructed from it.

handler::add_index() takes a key_info array[0 .. number of indexes to add - 1] and the number of indexes to add.

You need to copy the record (with the duplicate key) into table->record[0], and report the array slot number of the add_index() key_info array as the "errkey" in handler::info().

ALTER TABLE, after the call to add_index(), temporarily exchanges the original table->key_info array by the array sent to add_index(). So the duplicate key message should be constructed from the correct key_info.

For example a table has 2 indexes. So we have table->key_info[0..1]. These are the original indexes. We want to add four new indexes. add_index() has key_info[0..3]. If the third is a duplicate key and provokes a duplicate key error, copy the offending record into table->record[0]. On handler::info(HA_STATUS_ERRKEY) return errkey=2 (which is the third key from the add_index() key_info array). ALTER TABLE will then exchange the key_info array and table->file->print_error() will construct the duplicate key message from the right key_info slot.

Do you need help?X

At least this was my intention when implementing it. If it does not work this way, please report it as a bug.

> Furthermore, is there any better documentation for TABLE than this
> in table.h:
>
> struct st_table {
> ...
> uchar *record[2]; /* Pointer to records */
> uchar *write_row_record; /* Used as optimisation in
> THD::write_row */
> ...
> uint status; /* What's in record[0] */
> ...
> };
>
> I don't see any method THD::write_row(). Is the comment supposed to
> refer to THD::binlog_write_row()? What are the possible values of
> "status"? What can there be in record[1]?

Unfortunately I don't know about better documentation.

I agree with you that write_row_record should be used in THD::binlog_*_row() only.

In structs.h we have:

	/* Bits in form->status */
#define STATUS_NO_RECORD	(1+2)	/* Record isn't usably */
#define STATUS_GARBAGE		1
#define STATUS_NOT_FOUND	2	/* No record in database when needed */
#define STATUS_NO_PARENT	4	/* Parent record wasn't found */
#define STATUS_NOT_READ		8	/* Record isn't read */
#define STATUS_UPDATED		16	/* Record is updated by formula */
#define STATUS_NULL_ROW		32	/* table->null_row is set */
#define STATUS_DELETED		64

record[1] is used for UPDATE. It contains the old row, while record[0] contains the new row. Tables that cannot be updated may not have record[1]. For safety reasons record[1] would point to the same location as record[0] then.

Regards
Ingo

-- 
Ingo Strüwing, Senior Software Developer
MySQL GmbH, Dachauer Str. 37, D-80335 München
Geschäftsführer: Kaj Arnö - HRB München 162140

-- 
MySQL Internals Mailing List
For list archives: 
http://lists.mysql.com/internals
To unsubscribe:    
http://lists.mysql.com/internals?unsub=lists@pantek.com
Received on Mon Aug 27 06:25:53 2007

This archive was generated by hypermail 2.1.8 : Sun Oct 07 2007 - 07:59:14 EDT

Do you need more help?X

Contact Us  Legal Notices  Order Services Online 
Pantek Home  Privacy Policy  IT news  Site Map  Pantek Library