⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 row0ins.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
		update = cascade->update;		update->info_bits = 0;		update->n_fields = foreign->n_fields;				for (i = 0; i < foreign->n_fields; i++) {			(update->fields + i)->field_no				= dict_table_get_nth_col_pos(table,					dict_index_get_nth_col_no(index, i));			(update->fields + i)->exp = NULL;			(update->fields + i)->new_val.len = UNIV_SQL_NULL;			(update->fields + i)->new_val.data = NULL;			(update->fields + i)->extern_storage = FALSE;		}	}	if (!node->is_delete	    && (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)) {		/* Build the appropriate update vector which sets changing		foreign->n_fields first fields in rec to new values */		upd_vec_heap = mem_heap_create(256);		n_to_update = row_ins_cascade_calc_update_vec(node, foreign,							      upd_vec_heap);		if (n_to_update == ULINT_UNDEFINED) {		        err = DB_ROW_IS_REFERENCED;			row_ins_foreign_report_err("Trying a cascaded update where the updated value in the child\n""table would not fit in the length of the column, or the value would\n""be NULL and the column is declared as not NULL in the child table,",			thr, foreign, btr_pcur_get_rec(pcur), entry);		       goto nonstandard_exit_func;		}		if (cascade->update->n_fields == 0) {			/* The update does not change any columns referred			to in this foreign key constraint: no need to do			anything */			err = DB_SUCCESS;					goto nonstandard_exit_func;					}	}		/* Store pcur position and initialize or store the cascade node	pcur stored position */		btr_pcur_store_position(pcur, mtr);		if (index == clust_index) {		btr_pcur_copy_stored_position(cascade->pcur, pcur);	} else {		btr_pcur_store_position(cascade->pcur, mtr);	}			mtr_commit(mtr);	ut_a(cascade->pcur->rel_pos == BTR_PCUR_ON);	cascade->state = UPD_NODE_UPDATE_CLUSTERED;		err = row_update_cascade_for_mysql(thr, cascade,						foreign->foreign_table);	if (foreign->foreign_table->n_foreign_key_checks_running == 0) {		fprintf(stderr,"InnoDB: error: table %s has the counter 0 though there is\n""InnoDB: a FOREIGN KEY check running on it.\n",			foreign->foreign_table->name);	}	/* Release the data dictionary latch for a while, so that we do not	starve other threads from doing CREATE TABLE etc. if we have a huge	cascaded operation running. The counter n_foreign_key_checks_running	will prevent other users from dropping or ALTERing the table when we	release the latch. */	row_mysql_unfreeze_data_dictionary(thr_get_trx(thr));	row_mysql_freeze_data_dictionary(thr_get_trx(thr));	mtr_start(mtr);	/* Restore pcur position */		btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);	if (tmp_heap) {		mem_heap_free(tmp_heap);	}	if (upd_vec_heap) {	        mem_heap_free(upd_vec_heap);	}	return(err);nonstandard_exit_func:	if (tmp_heap) {		mem_heap_free(tmp_heap);	}	if (upd_vec_heap) {	        mem_heap_free(upd_vec_heap);	}	btr_pcur_store_position(pcur, mtr);	mtr_commit(mtr);	mtr_start(mtr);	btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);	return(err);}/*************************************************************************Sets a shared lock on a record. Used in locking possible duplicate keyrecords and also in checking foreign key constraints. */staticulintrow_ins_set_shared_rec_lock(/*========================*/				/* out: DB_SUCCESS or error code */	ulint		type, 	/* in: LOCK_ORDINARY, LOCK_GAP, or				LOCK_REC_NOT_GAP type lock */	rec_t*		rec,	/* in: record */	dict_index_t*	index,	/* in: index */	const ulint*	offsets,/* in: rec_get_offsets(rec, index) */	que_thr_t*	thr)	/* in: query thread */	{	ulint	err;	ut_ad(rec_offs_validate(rec, index, offsets));	if (index->type & DICT_CLUSTERED) {		err = lock_clust_rec_read_check_and_lock(0,				rec, index, offsets, LOCK_S, type, thr);	} else {		err = lock_sec_rec_read_check_and_lock(0,				rec, index, offsets, LOCK_S, type, thr);	}	return(err);}/*************************************************************************Sets a exclusive lock on a record. Used in locking possible duplicate keyrecords */staticulintrow_ins_set_exclusive_rec_lock(/*============================*/				/* out: DB_SUCCESS or error code */	ulint		type, 	/* in: LOCK_ORDINARY, LOCK_GAP, or				LOCK_REC_NOT_GAP type lock */	rec_t*		rec,	/* in: record */	dict_index_t*	index,	/* in: index */	const ulint*	offsets,/* in: rec_get_offsets(rec, index) */	que_thr_t*	thr)	/* in: query thread */	{	ulint	err;	ut_ad(rec_offs_validate(rec, index, offsets));	if (index->type & DICT_CLUSTERED) {		err = lock_clust_rec_read_check_and_lock(0,				rec, index, offsets, LOCK_X, type, thr);	} else {		err = lock_sec_rec_read_check_and_lock(0,				rec, index, offsets, LOCK_X, type, thr);	}	return(err);}	/*******************************************************************Checks if foreign key constraint fails for an index entry. Sets shared lockswhich lock either the success or the failure of the constraint. NOTE thatthe caller must have a shared latch on dict_operation_lock. */ulintrow_ins_check_foreign_constraint(/*=============================*/				/* out: DB_SUCCESS,				DB_NO_REFERENCED_ROW,				or DB_ROW_IS_REFERENCED */	ibool		check_ref,/* in: TRUE if we want to check that				the referenced table is ok, FALSE if we				want to to check the foreign key table */	dict_foreign_t*	foreign,/* in: foreign constraint; NOTE that the				tables mentioned in it must be in the				dictionary cache if they exist at all */	dict_table_t*	table,	/* in: if check_ref is TRUE, then the foreign				table, else the referenced table */	dtuple_t*	entry,	/* in: index entry for index */	que_thr_t*	thr)	/* in: query thread */{  	upd_node_t*  	upd_node;	dict_table_t*	check_table;	dict_index_t*	check_index;	ulint		n_fields_cmp;	rec_t*		rec;	btr_pcur_t	pcur;	ibool		moved;	int		cmp;	ulint		err;	ulint		i;	mtr_t		mtr;	trx_t*		trx		= thr_get_trx(thr);	mem_heap_t*	heap		= NULL;	ulint		offsets_[REC_OFFS_NORMAL_SIZE];	ulint*		offsets		= offsets_;	*offsets_ = (sizeof offsets_) / sizeof *offsets_;run_again:#ifdef UNIV_SYNC_DEBUG	ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_SHARED));#endif /* UNIV_SYNC_DEBUG */	err = DB_SUCCESS;	if (trx->check_foreigns == FALSE) {		/* The user has suppressed foreign key checks currently for		this session */		goto exit_func;	}	/* If any of the foreign key fields in entry is SQL NULL, we	suppress the foreign key check: this is compatible with Oracle,	for example */	for (i = 0; i < foreign->n_fields; i++) {		if (UNIV_SQL_NULL == dfield_get_len(                                         dtuple_get_nth_field(entry, i))) {			goto exit_func;		}	}	if (que_node_get_type(thr->run_node) == QUE_NODE_UPDATE) {	        upd_node = thr->run_node;	        if (!(upd_node->is_delete) && upd_node->foreign == foreign) {		        /* If a cascaded update is done as defined by a 			foreign key constraint, do not check that			constraint for the child row. In ON UPDATE CASCADE			the update of the parent row is only half done when			we come here: if we would check the constraint here			for the child row it would fail.			A QUESTION remains: if in the child table there are			several constraints which refer to the same parent			table, we should merge all updates to the child as			one update? And the updates can be contradictory!			Currently we just perform the update associated			with each foreign key constraint, one after			another, and the user has problems predicting in			which order they are performed. */			goto exit_func;		}	}	if (check_ref) {		check_table = foreign->referenced_table;		check_index = foreign->referenced_index;	} else {		check_table = foreign->foreign_table;		check_index = foreign->foreign_index;	}	if (check_table == NULL || check_table->ibd_file_missing) {		if (check_ref) {			FILE*	ef = dict_foreign_err_file;			row_ins_set_detailed(trx, foreign);						mutex_enter(&dict_foreign_err_mutex);			rewind(ef);			ut_print_timestamp(ef);			fputs(" Transaction:\n", ef);			trx_print(ef, trx, 600);			fputs("Foreign key constraint fails for table ", ef);			ut_print_name(ef, trx, foreign->foreign_table_name);			fputs(":\n", ef);			dict_print_info_on_foreign_key_in_create_format(ef,					trx, foreign, TRUE);			fputs("\nTrying to add to index ", ef);			ut_print_name(ef, trx, foreign->foreign_index->name);			fputs(" tuple:\n", ef);			dtuple_print(ef, entry);			fputs("\nBut the parent table ", ef);			ut_print_name(ef, trx, foreign->referenced_table_name);		fputs("\nor its .ibd file does not currently exist!\n", ef);			mutex_exit(&dict_foreign_err_mutex);			err = DB_NO_REFERENCED_ROW;		}		goto exit_func;	}	ut_a(check_table && check_index);	if (check_table != table) {		/* We already have a LOCK_IX on table, but not necessarily		on check_table */				err = lock_table(0, check_table, LOCK_IS, thr);		if (err != DB_SUCCESS) {			goto do_possible_lock_wait;		}	}	mtr_start(&mtr);	/* Store old value on n_fields_cmp */	n_fields_cmp = dtuple_get_n_fields_cmp(entry);	dtuple_set_n_fields_cmp(entry, foreign->n_fields);	btr_pcur_open(check_index, entry, PAGE_CUR_GE,					BTR_SEARCH_LEAF, &pcur, &mtr);	/* Scan index records and check if there is a matching record */	for (;;) {		page_t*	page;		rec = btr_pcur_get_rec(&pcur);		page = buf_frame_align(rec);		if (rec == page_get_infimum_rec(page)) {			goto next_rec;		}				offsets = rec_get_offsets(rec, check_index,					offsets, ULINT_UNDEFINED, &heap);		if (rec == page_get_supremum_rec(page)) {			err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec,						check_index, offsets, thr);			if (err != DB_SUCCESS) {				break;			}			goto next_rec;		}		cmp = cmp_dtuple_rec(entry, rec, offsets);		if (cmp == 0) {			if (rec_get_deleted_flag(rec,						rec_offs_comp(offsets))) {				err = row_ins_set_shared_rec_lock(						LOCK_ORDINARY, rec,						check_index, offsets, thr);				if (err != DB_SUCCESS) {					break;				}			} else {				/* Found a matching record. Lock only				a record because we can allow inserts				into gaps */								err = row_ins_set_shared_rec_lock(						LOCK_REC_NOT_GAP, rec,						check_index, offsets, thr);				if (err != DB_SUCCESS) {					break;				}				if (check_ref) {								err = DB_SUCCESS;					break;				} else if (foreign->type != 0) {					/* There is an ON UPDATE or ON DELETE					condition: check them in a separate					function */					err =					  row_ins_foreign_check_on_constraint(						thr, foreign, &pcur, entry,									&mtr);					if (err != DB_SUCCESS) {						break;					}				} else {					row_ins_foreign_report_err(						"Trying to delete or update",						thr, foreign, rec, entry);					err = DB_ROW_IS_REFERENCED;					break;				}			}		}		if (cmp < 0) {			err = row_ins_set_shared_rec_lock(LOCK_GAP,					rec, check_index, offsets, thr);			if (err != DB_SUCCESS) {				break;			}			if (check_ref) {							err = DB_NO_REFERENCED_ROW;				row_ins_foreign_report_add_err(					trx, foreign, rec, entry);			} else {				err = DB_SUCCESS;			}			break;		}		ut_a(cmp == 0);next_rec:		moved = btr_pcur_move_to_next(&pcur, &mtr);		if (!moved) {			if (check_ref) {							rec = btr_pcur_get_rec(&pcur);				row_ins_foreign_report_add_err(					trx, foreign, rec, entry);				err = DB_NO_REFERENCED_ROW;			} else {				err = DB_SUCCESS;			}			break;		}	}	btr_pcur_close(&pcur);	mtr_commit(&mtr);	/* Restore old value */	dtuple_set_n_fields_cmp(entry, n_fields_cmp);do_possible_lock_wait:	if (err == DB_LOCK_WAIT) {		trx->error_state = err;		que_thr_stop_for_mysql(thr);		srv_suspend_mysql_thread(thr);			if (trx->error_state == DB_SUCCESS) {		        goto run_again;		}		err = trx->error_state;	}exit_func:	if (UNIV_LIKELY_NULL(heap)) {		mem_heap_free(heap);	}	return(err);}/*******************************************************************Checks if foreign key constraints fail for an index entry. If indexis not mentioned in any constraint, this function does nothing,Otherwise does searches to the indexes of referenced tables andsets shared locks which lock either the success or the failure ofa constraint. */staticulintrow_ins_check_foreign_constraints(/*==============================*/				/* out: DB_SUCCESS or error code */	dict_table_t*	table,	/* in: table */	dict_index_t*	index,	/* in: index */	dtuple_t*	entry,	/* in: index entry for index */	que_thr_t*	thr)	/* in: query thread */{	dict_foreign_t*	foreign;	ulint		err;	trx_t*		trx;	ibool		got_s_lock	= FALSE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -