Commit 640246e6 authored by marko's avatar marko

Fix a severe bug that was introduced in r1422 when fixing Bug #21101.

When creating an index containing a too long record, InnoDB would
dereference a NULL pointer when trying to determine the maximum row length.

innodb_check_for_record_too_big_error(): Replace the dict_table_t*
parameter with a Boolean flag.  There is not always a dict_table_t object
when this function is called.

page_get_free_space_of_empty_noninline(): Move the definition and
declaration from row0mysql (!) to page0page.  Make the signature
identical with page_get_free_space_of_empty().

create_clustered_index_when_no_primary(): Add the parameter "comp".
Remove unnecessary casts.
parent 5ce26f77
......@@ -4510,17 +4510,17 @@ ha_innobase::position(
/*********************************************************************
If it's a DB_TOO_BIG_RECORD error then set a suitable message to
return to the client.*/
static
inline
void
innodb_check_for_record_too_big_error(
/*==================================*/
dict_table_t* table, /* in: table to check */
int error) /* in: error code to check */
ulint comp, /* in: ROW_FORMAT: nonzero=COMPACT, 0=REDUNDANT */
int error) /* in: error code to check */
{
if (error == (int)DB_TOO_BIG_RECORD) {
ulint max_row_size;
max_row_size = page_get_free_space_of_empty_noninline(table);
max_row_size = page_get_free_space_of_empty_noninline(comp);
my_error(ER_TOO_BIG_ROWSIZE, MYF(0), max_row_size);
}
......@@ -4634,9 +4634,8 @@ create_table_def(
error = row_create_table_for_mysql(table, trx);
/* We need access to the table and so we do the error checking
and set the error message here, before the error translation.*/
innodb_check_for_record_too_big_error(table, error);
innodb_check_for_record_too_big_error(dict_table_is_comp(table),
error);
error = convert_error_code_to_mysql(error, NULL);
......@@ -4760,9 +4759,8 @@ create_index(
sure we don't create too long indexes. */
error = row_create_index_for_mysql(index, trx, field_lengths);
/* We need access to the table and so we do the error checking
and set the error message here, before the error translation.*/
innodb_check_for_record_too_big_error(index->table, error);
innodb_check_for_record_too_big_error(form->s->row_type
!= ROW_TYPE_REDUNDANT, error);
error = convert_error_code_to_mysql(error, NULL);
......@@ -4779,6 +4777,8 @@ int
create_clustered_index_when_no_primary(
/*===================================*/
trx_t* trx, /* in: InnoDB transaction handle */
ulint comp, /* in: ROW_FORMAT:
nonzero=COMPACT, 0=REDUNDANT */
const char* table_name) /* in: table name */
{
dict_index_t* index;
......@@ -4787,13 +4787,11 @@ create_clustered_index_when_no_primary(
/* We pass 0 as the space id, and determine at a lower level the space
id where to store the table */
index = dict_mem_index_create((char*) table_name,
(char*) "GEN_CLUST_INDEX", 0, DICT_CLUSTERED, 0);
index = dict_mem_index_create(table_name, "GEN_CLUST_INDEX",
0, DICT_CLUSTERED, 0);
error = row_create_index_for_mysql(index, trx, NULL);
/* We need access to the table and so we do the error checking
and set the error message here, before the error translation.*/
innodb_check_for_record_too_big_error(index->table, error);
innodb_check_for_record_too_big_error(comp, error);
error = convert_error_code_to_mysql(error, NULL);
......@@ -4924,8 +4922,9 @@ ha_innobase::create(
order the rows by their row id which is internally generated
by InnoDB */
error = create_clustered_index_when_no_primary(trx,
norm_name);
error = create_clustered_index_when_no_primary(
trx, form->s->row_type != ROW_TYPE_REDUNDANT,
norm_name);
if (error) {
goto cleanup;
}
......
......@@ -531,6 +531,15 @@ page_get_free_space_of_empty(
/* out: free space */
ulint comp) /* in: nonzero=compact page format */
__attribute__((const));
/*****************************************************************
Calculates free space if a page is emptied. */
ulint
page_get_free_space_of_empty_noninline(
/*===================================*/
/* out: free space */
ulint comp) /* in: nonzero=compact page format */
__attribute__((const));
/****************************************************************
Returns the sum of the sizes of the records in the record list
excluding the infimum and supremum records. */
......
......@@ -460,19 +460,6 @@ row_check_table_for_mysql(
/* out: DB_ERROR or DB_SUCCESS */
row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL
handle */
/*************************************************************************
Get the min of the maximum possible row sizes. */
ulint
page_get_free_space_of_empty_noninline(
/*===================================*/
/* out: The (approx) maximum size
of a row, this is a conservative
estimate, since the size can be
slightly larger depending upon
the ROW_FORMAT setting.*/
dict_table_t* table); /* in: table for which max record
size required.*/
/* A struct describing a place for an individual column in the MySQL
row format which is presented to the table handler in ha_innobase.
......
......@@ -209,6 +209,18 @@ page_set_max_trx_id(
}
}
/*****************************************************************
Calculates free space if a page is emptied. */
ulint
page_get_free_space_of_empty_noninline(
/*===================================*/
/* out: free space */
ulint comp) /* in: nonzero=compact page format */
{
return(page_get_free_space_of_empty(comp));
}
/****************************************************************
Allocates a block of memory from an index page. */
......
......@@ -4059,25 +4059,3 @@ row_check_table_for_mysql(
return(ret);
}
/*************************************************************************
Get the maximum row size. */
ulint
page_get_free_space_of_empty_noninline(
/*===================================*/
/* out: The (approx) maximum size
of a row, this is a conservative
estimate, since the size can be
slightly larger depending upon
the ROW_FORMAT setting.*/
dict_table_t* table) /* in: table for which max record
size is required.*/
{
ibool compact;
compact = dict_table_is_comp(table);
return(page_get_free_space_of_empty(compact) / 2);
}
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