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

📄 row0ins.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
				ufield->field_no =					dict_table_get_nth_col_pos(table,					dict_index_get_nth_col_no(index, i));				ufield->exp = NULL;				ufield->new_val = parent_ufield->new_val;				type = dict_index_get_nth_type(index, i);				/* Do not allow a NOT NULL column to be				updated as NULL */				if (ufield->new_val.len == UNIV_SQL_NULL				    && (type->prtype & DATA_NOT_NULL)) {				        return(ULINT_UNDEFINED);				}				/* If the new value would not fit in the				column, do not allow the update */				if (ufield->new_val.len != UNIV_SQL_NULL				    && dtype_get_at_most_n_mbchars(						type, dtype_get_len(type),						ufield->new_val.len,						ufield->new_val.data)				    < ufield->new_val.len) {					return(ULINT_UNDEFINED);				}				/* If the parent column type has a different				length than the child column type, we may				need to pad with spaces the new value of the				child column */				min_size = dtype_get_min_size(type);				if (min_size				    && ufield->new_val.len != UNIV_SQL_NULL				    && ufield->new_val.len < min_size) {					char*		pad_start;					const char*	pad_end;				        ufield->new_val.data =						mem_heap_alloc(heap,								min_size);					pad_start =						((char*) ufield->new_val.data)						+ ufield->new_val.len;					pad_end =						((char*) ufield->new_val.data)						+ min_size;					ufield->new_val.len = min_size;					ut_memcpy(ufield->new_val.data,						parent_ufield->new_val.data,						parent_ufield->new_val.len);					switch (UNIV_EXPECT(						dtype_get_mbminlen(type), 1)) {					default:						ut_error;					case 1:						if (UNIV_UNLIKELY(							dtype_get_charset_coll(							dtype_get_prtype(type))					== DATA_MYSQL_BINARY_CHARSET_COLL)) {						    /* Do not pad BINARY						    columns. */						    return(ULINT_UNDEFINED);						}						/* space=0x20 */						memset(pad_start, 0x20,							pad_end - pad_start);						break;					case 2:						/* space=0x0020 */						ut_a(!(ufield->new_val.len									% 2));						ut_a(!(min_size % 2));						do {							*pad_start++ = 0x00;							*pad_start++ = 0x20;						} while (pad_start < pad_end);						break;					}				}				ufield->extern_storage = FALSE;				n_fields_updated++;			}		}	}	update->n_fields = n_fields_updated;	return(n_fields_updated);}/*************************************************************************Set detailed error message associated with foreign key errors forthe given transaction. */staticvoidrow_ins_set_detailed(/*=================*/	trx_t*		trx,		/* in: transaction */	dict_foreign_t*	foreign)	/* in: foreign key constraint */{	mutex_enter(&srv_misc_tmpfile_mutex);	rewind(srv_misc_tmpfile);	if (os_file_set_eof(srv_misc_tmpfile)) {		ut_print_name(srv_misc_tmpfile, trx,				foreign->foreign_table_name);		dict_print_info_on_foreign_key_in_create_format(				srv_misc_tmpfile,				trx, foreign, FALSE);		trx_set_detailed_error_from_file(trx, srv_misc_tmpfile);	} else {		trx_set_detailed_error(trx, "temp file operation failed");	}	mutex_exit(&srv_misc_tmpfile_mutex);}/*************************************************************************Reports a foreign key error associated with an update or a delete of aparent table index entry. */staticvoidrow_ins_foreign_report_err(/*=======================*/	const char*	errstr,		/* in: error string from the viewpoint					of the parent table */	que_thr_t*	thr,		/* in: query thread whose run_node					is an update node */	dict_foreign_t*	foreign,	/* in: foreign key constraint */	rec_t*		rec,		/* in: a matching index record in the					child table */	dtuple_t*	entry)		/* in: index entry in the parent					table */{	FILE*	ef	= dict_foreign_err_file;	trx_t*	trx	= thr_get_trx(thr);	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);	putc('\n', ef);	fputs(errstr, ef);	fputs(" in parent table, in index ", ef);	ut_print_name(ef, trx, foreign->referenced_index->name);	if (entry) {		fputs(" tuple:\n", ef);		dtuple_print(ef, entry);	}	fputs("\nBut in child table ", ef);	ut_print_name(ef, trx, foreign->foreign_table_name);	fputs(", in index ", ef);	ut_print_name(ef, trx, foreign->foreign_index->name);	if (rec) {		fputs(", there is a record:\n", ef);		rec_print(ef, rec, foreign->foreign_index);	} else {		fputs(", the record is not available\n", ef);	}	putc('\n', ef);	mutex_exit(&dict_foreign_err_mutex);}/*************************************************************************Reports a foreign key error to dict_foreign_err_buf when we are tryingto add an index entry to a child table. Note that the adding may be the resultof an update, too. */staticvoidrow_ins_foreign_report_add_err(/*===========================*/	trx_t*		trx,		/* in: transaction */	dict_foreign_t*	foreign,	/* in: foreign key constraint */	rec_t*		rec,		/* in: a record in the parent table:					it does not match entry because we					have an error! */	dtuple_t*	entry)		/* in: index entry to insert in the					child table */{	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 in child table, in index ", ef);	ut_print_name(ef, trx, foreign->foreign_index->name);	if (entry) {		fputs(" tuple:\n", ef);		dtuple_print(ef, entry);	}	fputs("\nBut in parent table ", ef);	ut_print_name(ef, trx, foreign->referenced_table_name);	fputs(", in index ", ef);	ut_print_name(ef, trx, foreign->referenced_index->name);	fputs(",\nthe closest match we can find is record:\n", ef);	if (rec && page_rec_is_supremum(rec)) {		/* If the cursor ended on a supremum record, it is better		to report the previous record in the error message, so that		the user gets a more descriptive error message. */		rec = page_rec_get_prev(rec);	}	if (rec) {		rec_print(ef, rec, foreign->referenced_index);	}	putc('\n', ef);	mutex_exit(&dict_foreign_err_mutex);}/*************************************************************************Invalidate the query cache for the given table. */staticvoidrow_ins_invalidate_query_cache(/*===========================*/	que_thr_t*	thr,		/* in: query thread whose run_node					is an update node */	const char*	name)		/* in: table name prefixed with					database name and a '/' character */{	char*	buf;	char*	ptr;	ulint	len = strlen(name) + 1;	buf = mem_strdupl(name, len);	ptr = strchr(buf, '/');	ut_a(ptr);	*ptr = '\0';	/* We call a function in ha_innodb.cc */#ifndef UNIV_HOTBACKUP	innobase_invalidate_query_cache(thr_get_trx(thr), buf, len);#endif	mem_free(buf);}/*************************************************************************Perform referential actions or checks when a parent row is deleted or updatedand the constraint had an ON DELETE or ON UPDATE condition which was notRESTRICT. */staticulintrow_ins_foreign_check_on_constraint(/*================================*/					/* out: DB_SUCCESS, DB_LOCK_WAIT,					or error code */	que_thr_t*	thr,		/* in: query thread whose run_node					is an update node */	dict_foreign_t*	foreign,	/* in: foreign key constraint whose					type is != 0 */	btr_pcur_t*	pcur,		/* in: cursor placed on a matching					index record in the child table */	dtuple_t*	entry,		/* in: index entry in the parent					table */	mtr_t*		mtr)		/* in: mtr holding the latch of pcur					page */{	upd_node_t*	node;	upd_node_t*	cascade;	dict_table_t*	table		= foreign->foreign_table;	dict_index_t*	index;	dict_index_t*	clust_index;	dtuple_t*	ref;	mem_heap_t*	upd_vec_heap	= NULL;	rec_t*		rec;	rec_t*		clust_rec;	upd_t*		update;	ulint		n_to_update;	ulint		err;	ulint		i;	trx_t*		trx;	mem_heap_t*	tmp_heap	= NULL;	ut_a(thr && foreign && pcur && mtr);	trx = thr_get_trx(thr);	/* Since we are going to delete or update a row, we have to invalidate	the MySQL query cache for table. A deadlock of threads is not possible	here because the caller of this function does not hold any latches with	the sync0sync.h rank above the kernel mutex. The query cache mutex has	a rank just above the kernel mutex. */	row_ins_invalidate_query_cache(thr, table->name);	node = thr->run_node;	if (node->is_delete && 0 == (foreign->type &			(DICT_FOREIGN_ON_DELETE_CASCADE			 | DICT_FOREIGN_ON_DELETE_SET_NULL))) {		row_ins_foreign_report_err("Trying to delete",					thr, foreign,					btr_pcur_get_rec(pcur), entry);	        return(DB_ROW_IS_REFERENCED);	}	if (!node->is_delete && 0 == (foreign->type &			(DICT_FOREIGN_ON_UPDATE_CASCADE			 | DICT_FOREIGN_ON_UPDATE_SET_NULL))) {		/* This is an UPDATE */			 		row_ins_foreign_report_err("Trying to update",					thr, foreign,					btr_pcur_get_rec(pcur), entry);	        return(DB_ROW_IS_REFERENCED);	}	if (node->cascade_node == NULL) {		/* Extend our query graph by creating a child to current		update node. The child is used in the cascade or set null		operation. */		node->cascade_heap = mem_heap_create(128);		node->cascade_node = row_create_update_node_for_mysql(						table, node->cascade_heap);		que_node_set_parent(node->cascade_node, node);	}	/* Initialize cascade_node to do the operation we want. Note that we	use the SAME cascade node to do all foreign key operations of the	SQL DELETE: the table of the cascade node may change if there are	several child tables to the table where the delete is done! */	cascade = node->cascade_node;		cascade->table = table;	cascade->foreign = foreign;		if (node->is_delete	    && (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)) {		cascade->is_delete = TRUE;	} else {		cascade->is_delete = FALSE;		if (foreign->n_fields > cascade->update_n_fields) {			/* We have to make the update vector longer */			cascade->update = upd_create(foreign->n_fields,							node->cascade_heap);			cascade->update_n_fields = foreign->n_fields;		}	}	/* We do not allow cyclic cascaded updating (DELETE is allowed,	but not UPDATE) of the same table, as this can lead to an infinite	cycle. Check that we are not updating the same table which is	already being modified in this cascade chain. We have to check	this also because the modification of the indexes of a 'parent'	table may still be incomplete, and we must avoid seeing the indexes	of the parent table in an inconsistent state! */	if (!cascade->is_delete	    && row_ins_cascade_ancestor_updates_table(cascade, table)) {	        /* We do not know if this would break foreign key	        constraints, but play safe and return an error */	        err = DB_ROW_IS_REFERENCED;		row_ins_foreign_report_err("Trying an update, possibly causing a cyclic cascaded update\n""in the child table,", thr, foreign, btr_pcur_get_rec(pcur), entry);		goto nonstandard_exit_func;	}	if (row_ins_cascade_n_ancestors(cascade) >= 15) {		err = DB_ROW_IS_REFERENCED;		row_ins_foreign_report_err("Trying a too deep cascaded delete or update\n",			thr, foreign, btr_pcur_get_rec(pcur), entry);		goto nonstandard_exit_func;	}	index = btr_pcur_get_btr_cur(pcur)->index;	ut_a(index == foreign->foreign_index);		rec = btr_pcur_get_rec(pcur);	if (index->type & DICT_CLUSTERED) {		/* pcur is already positioned in the clustered index of		the child table */			clust_index = index;		clust_rec = rec;	} else {		/* We have to look for the record in the clustered index		in the child table */		clust_index = dict_table_get_first_index(table);		tmp_heap = mem_heap_create(256);				ref = row_build_row_ref(ROW_COPY_POINTERS, index, rec,								tmp_heap);		btr_pcur_open_with_no_init(clust_index, ref,			PAGE_CUR_LE, BTR_SEARCH_LEAF,			cascade->pcur, 0, mtr);		clust_rec = btr_pcur_get_rec(cascade->pcur);		if (!page_rec_is_user_rec(clust_rec)		    || btr_pcur_get_low_match(cascade->pcur)		       < dict_index_get_n_unique(clust_index)) {			fputs(			"InnoDB: error in cascade of a foreign key op\n"			"InnoDB: ", stderr);			dict_index_name_print(stderr, trx, index);			fputs("\n"				"InnoDB: record ", stderr);			rec_print(stderr, rec, index);			fputs("\n"				"InnoDB: clustered record ", stderr);			rec_print(stderr, clust_rec, clust_index);			fputs("\n""InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);			err = DB_SUCCESS;			goto nonstandard_exit_func;		}	}	/* Set an X-lock on the row to delete or update in the child table */	err = lock_table(0, table, LOCK_IX, thr);	if (err == DB_SUCCESS) {		/* Here it suffices to use a LOCK_REC_NOT_GAP type lock;		we already have a normal shared lock on the appropriate		gap if the search criterion was not unique */		err = lock_clust_rec_read_check_and_lock_alt(0, clust_rec,			clust_index, LOCK_X, LOCK_REC_NOT_GAP, thr);	}		if (err != DB_SUCCESS) {		goto nonstandard_exit_func;	}	if (rec_get_deleted_flag(clust_rec, table->comp)) {		/* This can happen if there is a circular reference of		rows such that cascading delete comes to delete a row		already in the process of being delete marked */		err = DB_SUCCESS;				goto nonstandard_exit_func;	}	if ((node->is_delete	    && (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL))	   || (!node->is_delete	    && (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL))) {	    			/* Build the appropriate update vector which sets		foreign->n_fields first fields in rec to SQL NULL */

⌨️ 快捷键说明

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