Commit 5c3c4d37 authored by heikki@hundin.mysql.fi's avatar heikki@hundin.mysql.fi
Browse files

row0mysql.c, dict0dict.c, db0err.h, ha_innobase.cc:

  Heikki will merge to 4.0: Prevent listing the same column twice in an InnoDB index: that will cause index corruption when that col is UPDATEd
parent 7b58a93a
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -1033,6 +1033,7 @@ dict_index_add_to_cache(
	ulint		n_ord;
	ibool		success;
	ulint		i;
	ulint		j;
	
	ut_ad(index);
	ut_ad(mutex_own(&(dict_sys->mutex)));
@@ -1063,6 +1064,26 @@ dict_index_add_to_cache(
		return(FALSE);
	}

	/* Check that the same column does not appear twice in the index.
	   InnoDB assumes this in its algorithms, e.g., update of an index
	   entry */

	for (i = 0; i < dict_index_get_n_fields(index); i++) {

	  for (j = 0; j < i; j++) {
	    if (dict_index_get_nth_field(index, j)->col
		== dict_index_get_nth_field(index, i)->col) {

	      fprintf(stderr,
"InnoDB: Error: column %s appears twice in index %s of table %s\n"
"InnoDB: This is not allowed in InnoDB.\n"
"InnoDB: UPDATE can cause such an index to become corrupt in InnoDB.\n",
		      dict_index_get_nth_field(index, i)->col->name,
		      index->name, table->name);
	    }
	  }
	}
	
	/* Build the cache internal representation of the index,
	containing also the added system fields */

+2 −0
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ Created 5/24/1996 Heikki Tuuri
#define DB_CANNOT_ADD_CONSTRAINT 38	/* adding a foreign key constraint
					to a table failed */

#define DB_COL_APPEARS_TWICE_IN_INDEX 40

/* The following are partial failure codes */
#define DB_FAIL 		1000
#define DB_OVERFLOW 		1001
+33 −7
Original line number Diff line number Diff line
@@ -1393,7 +1393,7 @@ int
row_create_index_for_mysql(
/*=======================*/
					/* out: error number or DB_SUCCESS */
	dict_index_t*	index,		/* in: index defintion */
	dict_index_t*	index,		/* in: index definition */
	trx_t*		trx)		/* in: transaction handle */
{
	ind_node_t*	node;
@@ -1402,11 +1402,14 @@ row_create_index_for_mysql(
	ulint		namelen;
	ulint		keywordlen;
	ulint		err;
	ulint		i;
	ulint		j;
	
	ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
	ut_ad(mutex_own(&(dict_sys->mutex)));
	ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
	
	trx->op_info = "creating index";
	trx->op_info = (char *) "creating index";

	trx_start_if_not_started(trx);

@@ -1422,6 +1425,29 @@ row_create_index_for_mysql(
		return(DB_SUCCESS);
	}

	/* Check that the same column does not appear twice in the index.
	InnoDB assumes this in its algorithms, e.g., update of an index
	entry */

	for (i = 0; i < dict_index_get_n_fields(index); i++) {
		for (j = 0; j < i; j++) {
			if (0 == ut_strcmp(
				dict_index_get_nth_field(index, j)->name,
				dict_index_get_nth_field(index, i)->name)) {

				fprintf(stderr,
"InnoDB: Error: column %s appears twice in index %s\n"
"InnoDB: This is not allowed in InnoDB.\n",
				dict_index_get_nth_field(index, i)->name,
				index->name);

				err = DB_COL_APPEARS_TWICE_IN_INDEX;

				goto error_handling;
			}
		}
	}

	heap = mem_heap_create(512);

	trx->dict_operation = TRUE;
@@ -1436,9 +1462,11 @@ row_create_index_for_mysql(

 	err = trx->error_state;

	que_graph_free((que_t*) que_node_get_parent(thr));

error_handling:
	if (err != DB_SUCCESS) {
		/* We have special error handling here */
		ut_a(err == DB_OUT_OF_FILE_SPACE);
		
		trx->error_state = DB_SUCCESS;

@@ -1449,9 +1477,7 @@ row_create_index_for_mysql(
		trx->error_state = DB_SUCCESS;
	}
	
	que_graph_free((que_t*) que_node_get_parent(thr));
	
	trx->op_info = "";
	trx->op_info = (char *) "";

	return((int) err);
}
+5 −1
Original line number Diff line number Diff line
@@ -237,6 +237,10 @@ convert_error_code_to_mysql(

    		return(HA_ERR_CANNOT_ADD_FOREIGN);

        } else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {

    		return(HA_ERR_WRONG_TABLE_DEF);

 	} else if (error == (int) DB_OUT_OF_FILE_SPACE) {

    		return(HA_ERR_RECORD_FILE_FULL);