Commit 03a7cb22 authored by marko's avatar marko

branches/zip: Implement the reporting of duplicate key values to MySQL.

innobase_rec_to_mysql(): New function, for converting an InnoDB clustered
index record to MySQL table->record[0].  TODO: convert integer fields.
Currently, integer fields are in big-endian byte order instead of
host byte order, and signed integer fields are offset by 0x80000000.

innobase_rec_reset(): New function, for resetting table->record[0].

row_merge_build_indexes(): Add the parameter TABLE* table (the MySQL table
handle) for reporting duplicate key values.

dtuple_from_fields(): New function, to convert an array of dfield_t* to
dtuple_t.

dtuple_get_n_ext(): New function, to compute the number of externally stored
fields.

row_merge_dup_t: Structure for counting and reporting duplicate records.

row_merge_dup_report(): Function for counting and reporting duplicate records.

row_merge_tuple_cmp(), row_merge_tuple_sort(): Replace the ulint* n_dup
parameter with row_merge_dup_t* dup.

row_merge_buf_sort(): Add the parameter row_merge_dup_t* dup, which is
NULL when sorting a non-unique index.

row_merge_buf_write(), row_merge_heap_create(), row_merge_read_rec(),
row_merge_cmp(), row_merge_read_clustered_index(), row_merge_blocks(),
row_merge(), row_merge_sort(): Add const qualifiers.

row_merge_read_clustered_index(): Use a common error handling branch err_exit.
Invoke row_merge_buf_sort() differently on unique indexes.

row_merge_blocks(): note TODO: We could invoke innobase_rec_to_mysql()
to report duplicate key values when creating a clustered index.
parent d0631476
...@@ -19,6 +19,80 @@ extern "C" { ...@@ -19,6 +19,80 @@ extern "C" {
#include "handler0alter.h" #include "handler0alter.h"
} }
/*****************************************************************
Copies an InnoDB clustered index record to table->record[0]. */
extern "C"
void
innobase_rec_to_mysql(
/*==================*/
TABLE* table, /* in/out: MySQL table */
const rec_t* rec, /* in: record */
const dict_index_t* index, /* in: clustered index */
const ulint* offsets) /* in: rec_get_offsets(
rec, index, ...) */
{
uint n_fields = table->s->fields;
uint i;
ut_ad(dict_index_is_clust(index));
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(n_fields == dict_table_get_n_user_cols(index->table));
for (i = 0; i < n_fields; i++) {
Field* field = table->field[i];
void* ptr = field->ptr;
uint32 flen = field->pack_length();
ulint ipos;
ulint ilen;
const void* ifield;
ipos = dict_index_get_nth_col_pos(index, i);
ut_ad(ipos != ULINT_UNDEFINED);
if (UNIV_UNLIKELY(ipos == ULINT_UNDEFINED)) {
reset_field:
field->reset();
field->set_null();
continue;
}
ifield = rec_get_nth_field(rec, offsets, ipos, &ilen);
/* Assign the NULL flag */
if (ilen == UNIV_SQL_NULL) {
ut_ad(field->real_maybe_null());
goto reset_field;
} else {
field->set_notnull();
/* Copy the data. */
/* TODO: convert integer fields */
if (ilen >= flen) {
memcpy(ptr, ifield, flen);
} else {
field->reset();
memcpy(ptr, ifield, ilen);
}
}
}
}
/*****************************************************************
Resets table->record[0]. */
extern "C"
void
innobase_rec_reset(
/*===============*/
TABLE* table) /* in/out: MySQL table */
{
uint n_fields = table->s->fields;
uint i;
for (i = 0; i < n_fields; i++) {
table->field[i]->set_default();
}
}
/********************************************************************** /**********************************************************************
Removes the filename encoding of a database and table name. */ Removes the filename encoding of a database and table name. */
static static
...@@ -638,7 +712,7 @@ ha_innobase::add_index( ...@@ -638,7 +712,7 @@ ha_innobase::add_index(
/* Read the clustered index of the table and build indexes /* Read the clustered index of the table and build indexes
based on this information using temporary files and merge sort. */ based on this information using temporary files and merge sort. */
error = row_merge_build_indexes(trx, innodb_table, indexed_table, error = row_merge_build_indexes(trx, innodb_table, indexed_table,
index, num_of_idx); index, num_of_idx, table);
error_handling: error_handling:
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
......
...@@ -213,6 +213,18 @@ dtuple_create( ...@@ -213,6 +213,18 @@ dtuple_create(
is created */ is created */
ulint n_fields); /* in: number of fields */ ulint n_fields); /* in: number of fields */
/**************************************************************
Wrap data fields in a tuple. The default value for number
of fields used in record comparisons for this tuple is n_fields. */
UNIV_INLINE
const dtuple_t*
dtuple_from_fields(
/*===============*/
/* out: data tuple */
dtuple_t* tuple, /* in: storage for data tuple */
const dfield_t* fields, /* in: fields */
ulint n_fields); /* in: number of fields */
/************************************************************************* /*************************************************************************
Creates a dtuple for use in MySQL. */ Creates a dtuple for use in MySQL. */
...@@ -247,6 +259,14 @@ dtuple_get_data_size( ...@@ -247,6 +259,14 @@ dtuple_get_data_size(
/*=================*/ /*=================*/
/* out: sum of data lens */ /* out: sum of data lens */
const dtuple_t* tuple); /* in: typed data tuple */ const dtuple_t* tuple); /* in: typed data tuple */
/*************************************************************************
Computes the number of externally stored fields in a data tuple. */
UNIV_INLINE
ulint
dtuple_get_n_ext(
/*=============*/
/* out: number of fields */
const dtuple_t* tuple); /* in: tuple */
/**************************************************************** /****************************************************************
Compare two data tuples, respecting the collation of character fields. */ Compare two data tuples, respecting the collation of character fields. */
......
...@@ -349,6 +349,26 @@ dtuple_create( ...@@ -349,6 +349,26 @@ dtuple_create(
return(tuple); return(tuple);
} }
/**************************************************************
Wrap data fields in a tuple. The default value for number
of fields used in record comparisons for this tuple is n_fields. */
UNIV_INLINE
const dtuple_t*
dtuple_from_fields(
/*===============*/
/* out: data tuple */
dtuple_t* tuple, /* in: storage for data tuple */
const dfield_t* fields, /* in: fields */
ulint n_fields) /* in: number of fields */
{
tuple->info_bits = 0;
tuple->n_fields = tuple->n_fields_cmp = n_fields;
tuple->fields = (dfield_t*) fields;
ut_d(tuple->magic_n = DATA_TUPLE_MAGIC_N);
return(tuple);
}
/************************************************************** /**************************************************************
The following function returns the sum of data lengths of a tuple. The space The following function returns the sum of data lengths of a tuple. The space
occupied by the field structs or the tuple struct is not counted. Neither occupied by the field structs or the tuple struct is not counted. Neither
...@@ -386,6 +406,30 @@ dtuple_get_data_size( ...@@ -386,6 +406,30 @@ dtuple_get_data_size(
return(sum); return(sum);
} }
/*************************************************************************
Computes the number of externally stored fields in a data tuple. */
UNIV_INLINE
ulint
dtuple_get_n_ext(
/*=============*/
/* out: number of externally stored fields */
const dtuple_t* tuple) /* in: tuple */
{
ulint n_ext = 0;
ulint n_fields = tuple->n_fields;
ulint i;
ut_ad(tuple);
ut_ad(dtuple_check_typed(tuple));
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
for (i = 0; i < n_fields; i++) {
n_ext += dtuple_get_nth_field(tuple, i)->ext;
}
return(n_ext);
}
/*********************************************************************** /***********************************************************************
Sets types of fields binary in a tuple. */ Sets types of fields binary in a tuple. */
UNIV_INLINE UNIV_INLINE
......
...@@ -3,3 +3,23 @@ Smart ALTER TABLE ...@@ -3,3 +3,23 @@ Smart ALTER TABLE
(c) 2005-2007 Innobase Oy (c) 2005-2007 Innobase Oy
*******************************************************/ *******************************************************/
/*****************************************************************
Copies an InnoDB clustered index record to table->record[0]. */
void
innobase_rec_to_mysql(
/*==================*/
TABLE* table, /* in/out: MySQL table */
const rec_t* rec, /* in: record */
const dict_index_t* index, /* in: clustered index */
const ulint* offsets); /* in: rec_get_offsets(
rec, index, ...) */
/*****************************************************************
Resets table->record[0]. */
void
innobase_rec_reset(
/*===============*/
TABLE* table); /* in/out: MySQL table */
...@@ -165,5 +165,8 @@ row_merge_build_indexes( ...@@ -165,5 +165,8 @@ row_merge_build_indexes(
created; identical to old_table created; identical to old_table
unless creating a PRIMARY KEY */ unless creating a PRIMARY KEY */
dict_index_t** indexes, /* in: indexes to be created */ dict_index_t** indexes, /* in: indexes to be created */
ulint n_indexes); /* in: size of indexes[] */ ulint n_indexes, /* in: size of indexes[] */
TABLE* table); /* in/out: MySQL table, for
reporting erroneous key value
if applicable */
#endif /* row0merge.h */ #endif /* row0merge.h */
...@@ -38,4 +38,7 @@ typedef struct row_ext_struct row_ext_t; ...@@ -38,4 +38,7 @@ typedef struct row_ext_struct row_ext_t;
typedef struct row_prebuilt_struct row_prebuilt_t; typedef struct row_prebuilt_struct row_prebuilt_t;
/* MySQL data types */
typedef struct st_table TABLE;
#endif #endif
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment