Commit 8da85956 authored by heikki@hundin.mysql.fi's avatar heikki@hundin.mysql.fi
Browse files

Many files:

  Implement ON DELETE CASCADE and facilitate switching off of UNIQUE constraints and foreign keys
parent 6519ed11
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -228,6 +228,7 @@ btr_cur_search_to_nth_level(
	ulint		insert_planned;
	ulint		buf_mode;
	ulint		estimate;
	ulint		ignore_sec_unique;
	ulint		root_height;
#ifdef BTR_CUR_ADAPT
	btr_search_t*	info;
@@ -246,7 +247,9 @@ btr_cur_search_to_nth_level(
#endif	
	insert_planned = latch_mode & BTR_INSERT;
	estimate = latch_mode & BTR_ESTIMATE;
	latch_mode = latch_mode & ~(BTR_INSERT | BTR_ESTIMATE);
	ignore_sec_unique = latch_mode & BTR_IGNORE_SEC_UNIQUE;
	latch_mode = latch_mode & ~(BTR_INSERT | BTR_ESTIMATE
					| BTR_IGNORE_SEC_UNIQUE);

	ut_ad(!insert_planned || (mode == PAGE_CUR_LE));
	
@@ -343,7 +346,8 @@ btr_cur_search_to_nth_level(

			rw_latch = latch_mode;

			if (insert_planned && ibuf_should_try(index)) {
			if (insert_planned && ibuf_should_try(index,
							ignore_sec_unique)) {
				
				/* Try insert to the insert buffer if the
				page is not in the buffer pool */
@@ -356,7 +360,6 @@ btr_cur_search_to_nth_level(
					buf_mode,
					IB__FILE__, __LINE__,
					mtr);

		if (page == NULL) {
			/* This must be a search to perform an insert;
			try insert to the insert buffer */
@@ -365,7 +368,7 @@ btr_cur_search_to_nth_level(
			ut_ad(insert_planned);
			ut_ad(cursor->thr);

			if (ibuf_should_try(index) &&
			if (ibuf_should_try(index, ignore_sec_unique) &&
				ibuf_insert(tuple, index, space, page_no,
							cursor->thr)) {
				/* Insertion to the insert buffer succeeded */
+2 −1
Original line number Diff line number Diff line
@@ -1201,7 +1201,8 @@ dict_create_add_foreigns_to_dictionary(
					ut_dulint_get_low(id),
					table->name,
					foreign->referenced_table_name,
					foreign->n_fields);
					foreign->n_fields
					+ (foreign->type << 24));

	for (i = 0; i < foreign->n_fields; i++) {

+126 −35
Original line number Diff line number Diff line
@@ -1648,7 +1648,7 @@ dict_foreign_find_index(
							->col->name;
				if (ut_strlen(columns[i]) !=
						ut_strlen(col_name)
				    || 0 != ut_memcmp(columns[i],
				    || 0 != ut_cmp_in_lower_case(columns[i],
				    			col_name,
				  			ut_strlen(col_name))) {
				  	break;
@@ -1853,8 +1853,9 @@ dict_scan_col(
	ibool*		success,/* out: TRUE if success */
	dict_table_t*	table,	/* in: table in which the column is */
	dict_col_t**	column,	/* out: pointer to column if success */
	char**		column_name)/* out: pointer to column->name if
	char**		column_name,/* out: pointer to column->name if
				success */
	ulint*		column_name_len)/* out: column name length */
{
	dict_col_t*	col;
	char*		old_ptr;
@@ -1882,6 +1883,13 @@ dict_scan_col(
		ptr++;
	}

	*column_name_len = (ulint)(ptr - old_ptr);
	
	if (table == NULL) {
		*success = TRUE;
		*column = NULL;
		*column_name = old_ptr;
	} else {
	    	for (i = 0; i < dict_table_get_n_cols(table); i++) {

			col = dict_table_get_nth_col(table, i);
@@ -1898,6 +1906,7 @@ dict_scan_col(
		    		break;
			}
		}
	}
	
	if (*ptr == '`') {
		ptr++;
@@ -1914,14 +1923,18 @@ dict_scan_table_name(
/*=================*/
				/* out: scanned to */
	char*		ptr,	/* in: scanned to */
	dict_table_t**	table,	/* out: table object or NULL if error */
	char*		name)	/* in: foreign key table name */
	dict_table_t**	table,	/* out: table object or NULL */
	char*		name,	/* in: foreign key table name */
	ibool*		success,/* out: TRUE if ok name found */
	char*		second_table_name)/* in/out: buffer where to store
				the referenced table name; must be at least
				2500 bytes */
{
	char*	dot_ptr			= NULL;
	char*	old_ptr;
	ulint	i;
	char	second_table_name[10000];
	
	*success = FALSE;
	*table = NULL;

	while (isspace(*ptr)) {
@@ -1947,7 +1960,7 @@ dict_scan_table_name(
		ptr++;
	}

	if (ptr - old_ptr > 9000) {
	if (ptr - old_ptr > 2000) {
		return(old_ptr);
	}
	
@@ -1978,6 +1991,8 @@ dict_scan_table_name(
		second_table_name[ptr - old_ptr] = '\0';
	}

	*success = TRUE;

	*table = dict_table_get_low(second_table_name);

	if (*ptr == '`') {
@@ -2043,8 +2058,11 @@ dict_create_foreign_constraints(
	ibool		success;
	ulint		error;
	ulint		i;
	dict_col_t*	columns[1000];
	char*		column_names[1000];
	ulint		j;
	dict_col_t*	columns[500];
	char*		column_names[500];
	ulint		column_name_lens[500];
	char		referenced_table_name[2500];
	
	ut_ad(mutex_own(&(dict_sys->mutex)));

@@ -2090,7 +2108,7 @@ dict_create_foreign_constraints(
	/* Scan the columns in the first list */
col_loop1:
	ptr = dict_scan_col(ptr, &success, table, columns + i,
							column_names + i);
				column_names + i, column_name_lens + i);
	if (!success) {
		return(DB_CANNOT_ADD_CONSTRAINT);
	}
@@ -2141,9 +2159,13 @@ dict_create_foreign_constraints(
					1 + ut_strlen(columns[i]->name));
	}
	
	ptr = dict_scan_table_name(ptr, &referenced_table, name);
	ptr = dict_scan_table_name(ptr, &referenced_table, name,
					&success, referenced_table_name);

	/* Note that referenced_table can be NULL if the user has suppressed
	checking of foreign key constraints! */

	if (!referenced_table) {
	if (!success || (!referenced_table && trx->check_foreigns)) {
		dict_foreign_free(foreign);

		return(DB_CANNOT_ADD_CONSTRAINT);
@@ -2161,7 +2183,7 @@ dict_create_foreign_constraints(

col_loop2:
	ptr = dict_scan_col(ptr, &success, referenced_table, columns + i,
							column_names + i);
				column_names + i, column_name_lens + i);
	i++;
	
	if (!success) {
@@ -2183,43 +2205,104 @@ dict_create_foreign_constraints(
		return(DB_CANNOT_ADD_CONSTRAINT);
	}

	ptr = dict_accept(ptr, "ON", &success);

	if (!success) {

		goto try_find_index;
	}

	ptr = dict_accept(ptr, "DELETE", &success);

	if (!success) {

		goto try_find_index;
	}

	ptr = dict_accept(ptr, "CASCADE", &success);

	if (success) {

		foreign->type = DICT_FOREIGN_ON_DELETE_CASCADE;

		goto try_find_index;
	}

	ptr = dict_accept(ptr, "SET", &success);

	if (!success) {

		goto try_find_index;
	}

	ptr = dict_accept(ptr, "NULL", &success);

	if (success) {
		for (j = 0; j < foreign->n_fields; j++) {
			if ((dict_index_get_nth_type(
				foreign->foreign_index, j)->prtype)
				& DATA_NOT_NULL) {

				/* It is not sensible to define SET NULL
				if the column is not allowed to be NULL! */

				dict_foreign_free(foreign);
				return(DB_CANNOT_ADD_CONSTRAINT);
			}
		}

		foreign->type = DICT_FOREIGN_ON_DELETE_SET_NULL;

		goto try_find_index;
	}
	
try_find_index:
	/* Try to find an index which contains the columns as the first fields
	and in the right order, and the types are the same as in
	foreign->foreign_index */

	index = dict_foreign_find_index(referenced_table, column_names, i,
	if (referenced_table) {
		index = dict_foreign_find_index(referenced_table,
						column_names, i,
						foreign->foreign_index);

		if (!index) {
			dict_foreign_free(foreign);
			return(DB_CANNOT_ADD_CONSTRAINT);
		}
	} else {
		ut_a(trx->check_foreigns == FALSE);
		index = NULL;
	}

	foreign->referenced_index = index;
	foreign->referenced_table = referenced_table;

	foreign->referenced_table_name = mem_heap_alloc(foreign->heap,
					1 + ut_strlen(referenced_table->name));
					1 + ut_strlen(referenced_table_name));

	ut_memcpy(foreign->referenced_table_name, referenced_table->name,
					1 + ut_strlen(referenced_table->name));
	ut_memcpy(foreign->referenced_table_name, referenced_table_name,
					1 + ut_strlen(referenced_table_name));
					
	foreign->referenced_col_names = mem_heap_alloc(foreign->heap,
							i * sizeof(void*));
	for (i = 0; i < foreign->n_fields; i++) {
		foreign->referenced_col_names[i]
				= mem_heap_alloc(foreign->heap,
					1 + ut_strlen(columns[i]->name));
		ut_memcpy(
			foreign->referenced_col_names[i], columns[i]->name,
					1 + ut_strlen(columns[i]->name));
					1 + column_name_lens[i]);
		ut_memcpy(foreign->referenced_col_names[i], column_names[i],
					column_name_lens[i]);
		(foreign->referenced_col_names[i])[column_name_lens[i]] = '\0';
	}

	/* We found an ok constraint definition: add to the lists */
	
	UT_LIST_ADD_LAST(foreign_list, table->foreign_list, foreign);
	UT_LIST_ADD_LAST(referenced_list, referenced_table->referenced_list,

	if (referenced_table) {
		UT_LIST_ADD_LAST(referenced_list,
					referenced_table->referenced_list,
								foreign);
	}
	goto loop;
}

@@ -3034,6 +3117,14 @@ dict_print_info_on_foreign_keys_in_create_format(

		buf2 += sprintf(buf2, ")");

		if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE) {
			buf2 += sprintf(buf2, " ON DELETE CASCADE");
		}
	
		if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL) {
			buf2 += sprintf(buf2, " ON DELETE SET NULL");
		}

		foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
	}

+5 −0
Original line number Diff line number Diff line
@@ -947,6 +947,11 @@ dict_load_foreign(

	ut_a(len == 4);

	/* We store the type to the bits 24-31 of n_fields */
	
	foreign->type = foreign->n_fields >> 24;
	foreign->n_fields = foreign->n_fields & 0xFFFFFF;
	
	foreign->id = mem_heap_alloc(foreign->heap, ut_strlen(id) + 1);
				
	ut_memcpy(foreign->id, id, ut_strlen(id) + 1);
+3 −1
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ dict_mem_table_create(
	table->mem_fix = 0;

	table->n_mysql_handles_opened = 0;
	table->n_foreign_key_checks_running = 0;
		
	table->cached = FALSE;
	
@@ -235,6 +236,7 @@ dict_mem_foreign_create(void)

	foreign->id = NULL;

	foreign->type = 0;
	foreign->foreign_table_name = NULL;
	foreign->foreign_table = NULL;
	foreign->foreign_col_names = NULL;
Loading