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

📄 row0ins.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************Insert into a table(c) 1996 Innobase OyCreated 4/20/1996 Heikki Tuuri*******************************************************/#include "row0ins.h"#ifdef UNIV_NONINL#include "row0ins.ic"#endif#include "dict0dict.h"#include "dict0boot.h"#include "trx0undo.h"#include "btr0btr.h"#include "btr0cur.h"#include "mach0data.h"#include "que0que.h"#include "row0upd.h"#include "row0sel.h"#include "row0row.h"#include "rem0cmp.h"#include "lock0lock.h"#include "log0log.h"#include "eval0eval.h"#include "data0data.h"#include "usr0sess.h"#include "buf0lru.h"#define	ROW_INS_PREV	1#define	ROW_INS_NEXT	2/*********************************************************************This prototype is copied from /mysql/sql/ha_innodb.cc.Invalidates the MySQL query cache for the table.NOTE that the exact prototype of this function has to be in/innobase/row/row0ins.c! */externvoidinnobase_invalidate_query_cache(/*============================*/	trx_t*	trx,		/* in: transaction which modifies the table */	char*	full_name,	/* in: concatenation of database name, null				char '\0', table name, null char'\0';				NOTE that in Windows this is always				in LOWER CASE! */	ulint	full_name_len);	/* in: full name length where also the null				chars count *//**********************************************************************This function returns true if 1) SQL-query in the current threadis either REPLACE or LOAD DATA INFILE REPLACE. 2) SQL-query in the current threadis INSERT ON DUPLICATE KEY UPDATE.NOTE that /mysql/innobase/row/row0ins.c must contain the prototype for this function ! */iboolinnobase_query_is_update(void);/*************************************************************************Creates an insert node struct. */ins_node_t*ins_node_create(/*============*/					/* out, own: insert node struct */	ulint		ins_type,	/* in: INS_VALUES, ... */	dict_table_t*	table, 		/* in: table where to insert */	mem_heap_t*	heap)		/* in: mem heap where created */{	ins_node_t*	node;	node = mem_heap_alloc(heap, sizeof(ins_node_t));	node->common.type = QUE_NODE_INSERT;	node->ins_type = ins_type;	node->state = INS_NODE_SET_IX_LOCK;	node->table = table;	node->index = NULL;	node->entry = NULL;	node->select = NULL;		node->trx_id = ut_dulint_zero;		node->entry_sys_heap = mem_heap_create(128);	node->magic_n = INS_NODE_MAGIC_N;			return(node);}/***************************************************************Creates an entry template for each index of a table. */staticvoidins_node_create_entry_list(/*=======================*/	ins_node_t*	node)	/* in: row insert node */{	dict_index_t*	index;	dtuple_t*	entry;	ut_ad(node->entry_sys_heap);	UT_LIST_INIT(node->entry_list);	index = dict_table_get_first_index(node->table);		while (index != NULL) {		entry = row_build_index_entry(node->row, index,							node->entry_sys_heap);		UT_LIST_ADD_LAST(tuple_list, node->entry_list, entry);		index = dict_table_get_next_index(index);	}}/*********************************************************************Adds system field buffers to a row. */staticvoidrow_ins_alloc_sys_fields(/*=====================*/	ins_node_t*	node)	/* in: insert node */{	dtuple_t*	row;	dict_table_t*	table;	mem_heap_t*	heap;	dict_col_t*	col;	dfield_t*	dfield;	ulint		len;	byte*		ptr;	row = node->row;	table = node->table;	heap = node->entry_sys_heap;	ut_ad(row && table && heap);	ut_ad(dtuple_get_n_fields(row) == dict_table_get_n_cols(table));	/* 1. Allocate buffer for row id */	col = dict_table_get_sys_col(table, DATA_ROW_ID);		dfield = dtuple_get_nth_field(row, dict_col_get_no(col));	ptr = mem_heap_alloc(heap, DATA_ROW_ID_LEN);					dfield_set_data(dfield, ptr, DATA_ROW_ID_LEN);	node->row_id_buf = ptr;	if (table->type == DICT_TABLE_CLUSTER_MEMBER) {		/* 2. Fill in the dfield for mix id */		col = dict_table_get_sys_col(table, DATA_MIX_ID);			dfield = dtuple_get_nth_field(row, dict_col_get_no(col));		len = mach_dulint_get_compressed_size(table->mix_id);		ptr = mem_heap_alloc(heap, DATA_MIX_ID_LEN);						mach_dulint_write_compressed(ptr, table->mix_id);		dfield_set_data(dfield, ptr, len);	}	/* 3. Allocate buffer for trx id */	col = dict_table_get_sys_col(table, DATA_TRX_ID);		dfield = dtuple_get_nth_field(row, dict_col_get_no(col));	ptr = mem_heap_alloc(heap, DATA_TRX_ID_LEN);					dfield_set_data(dfield, ptr, DATA_TRX_ID_LEN);	node->trx_id_buf = ptr;	/* 4. Allocate buffer for roll ptr */	col = dict_table_get_sys_col(table, DATA_ROLL_PTR);		dfield = dtuple_get_nth_field(row, dict_col_get_no(col));	ptr = mem_heap_alloc(heap, DATA_ROLL_PTR_LEN);					dfield_set_data(dfield, ptr, DATA_ROLL_PTR_LEN);}/*************************************************************************Sets a new row to insert for an INS_DIRECT node. This function is only usedif we have constructed the row separately, which is a rare case; thisfunction is quite slow. */voidins_node_set_new_row(/*=================*/	ins_node_t*	node,	/* in: insert node */	dtuple_t*	row)	/* in: new row (or first row) for the node */{	node->state = INS_NODE_SET_IX_LOCK;	node->index = NULL;	node->entry = NULL;	node->row = row;	mem_heap_empty(node->entry_sys_heap);	/* Create templates for index entries */				ins_node_create_entry_list(node);	/* Allocate from entry_sys_heap buffers for sys fields */	row_ins_alloc_sys_fields(node);	/* As we allocated a new trx id buf, the trx id should be written	there again: */	node->trx_id = ut_dulint_zero;}/***********************************************************************Does an insert operation by updating a delete-marked existing recordin the index. This situation can occur if the delete-marked record iskept in the index for consistent reads. */staticulintrow_ins_sec_index_entry_by_modify(/*==============================*/				/* out: DB_SUCCESS or error code */	ulint		mode,	/* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,				depending on whether mtr holds just a leaf				latch or also a tree latch */	btr_cur_t*	cursor,	/* in: B-tree cursor */	dtuple_t*	entry,	/* in: index entry to insert */	que_thr_t*	thr,	/* in: query thread */	mtr_t*		mtr)	/* in: mtr */{	big_rec_t*	dummy_big_rec;	mem_heap_t*	heap;	upd_t*		update;	rec_t*		rec;	ulint		err;		rec = btr_cur_get_rec(cursor);		ut_ad((cursor->index->type & DICT_CLUSTERED) == 0);	ut_ad(rec_get_deleted_flag(rec, cursor->index->table->comp));		/* We know that in the alphabetical ordering, entry and rec are	identified. But in their binary form there may be differences if	there are char fields in them. Therefore we have to calculate the	difference. */		heap = mem_heap_create(1024);		update = row_upd_build_sec_rec_difference_binary(cursor->index,				entry, rec, thr_get_trx(thr), heap);	if (mode == BTR_MODIFY_LEAF) {		/* Try an optimistic updating of the record, keeping changes		within the page */		err = btr_cur_optimistic_update(BTR_KEEP_SYS_FLAG, cursor,						update, 0, thr, mtr);		if (err == DB_OVERFLOW || err == DB_UNDERFLOW) {			err = DB_FAIL;		}	} else  {		ut_a(mode == BTR_MODIFY_TREE);		if (buf_LRU_buf_pool_running_out()) {				err = DB_LOCK_TABLE_FULL;					goto func_exit;		}		err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG, cursor,					&dummy_big_rec, update, 0, thr, mtr);	}func_exit:	mem_heap_free(heap);	return(err);}/***********************************************************************Does an insert operation by delete unmarking and updating a delete markedexisting record in the index. This situation can occur if the delete markedrecord is kept in the index for consistent reads. */staticulintrow_ins_clust_index_entry_by_modify(/*================================*/				/* out: DB_SUCCESS, DB_FAIL, or error code */	ulint		mode,	/* in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE,				depending on whether mtr holds just a leaf				latch or also a tree latch */	btr_cur_t*	cursor,	/* in: B-tree cursor */	big_rec_t**	big_rec,/* out: possible big rec vector of fields				which have to be stored externally by the				caller */	dtuple_t*	entry,	/* in: index entry to insert */	ulint*		ext_vec,/* in: array containing field numbers of				externally stored fields in entry, or NULL */	ulint		n_ext_vec,/* in: number of fields in ext_vec */	que_thr_t*	thr,	/* in: query thread */	mtr_t*		mtr)	/* in: mtr */{	mem_heap_t*	heap;	rec_t*		rec;	upd_t*		update;	ulint		err;		ut_ad(cursor->index->type & DICT_CLUSTERED);		*big_rec = NULL;	rec = btr_cur_get_rec(cursor);	ut_ad(rec_get_deleted_flag(rec, cursor->index->table->comp));	heap = mem_heap_create(1024);		/* Build an update vector containing all the fields to be modified;	NOTE that this vector may NOT contain system columns trx_id or	roll_ptr */		update = row_upd_build_difference_binary(cursor->index, entry, ext_vec,			n_ext_vec, rec, thr_get_trx(thr), heap);	if (mode == BTR_MODIFY_LEAF) {		/* Try optimistic updating of the record, keeping changes		within the page */		err = btr_cur_optimistic_update(0, cursor, update, 0, thr,								   mtr);		if (err == DB_OVERFLOW || err == DB_UNDERFLOW) {			err = DB_FAIL;		}	} else  {		ut_a(mode == BTR_MODIFY_TREE);		if (buf_LRU_buf_pool_running_out()) {				err = DB_LOCK_TABLE_FULL;			goto func_exit;		}		err = btr_cur_pessimistic_update(0, cursor, big_rec, update,								0, thr, mtr);	}func_exit:		mem_heap_free(heap);	return(err);}/*************************************************************************Returns TRUE if in a cascaded update/delete an ancestor node of nodeupdates (not DELETE, but UPDATE) table. */staticiboolrow_ins_cascade_ancestor_updates_table(/*===================================*/				/* out: TRUE if an ancestor updates table */	que_node_t*	node,	/* in: node in a query graph */	dict_table_t*	table)	/* in: table */{	que_node_t*	parent;	upd_node_t*	upd_node;	parent = que_node_get_parent(node);		while (que_node_get_type(parent) == QUE_NODE_UPDATE) {		upd_node = parent;		if (upd_node->table == table && upd_node->is_delete == FALSE) {			return(TRUE);		}		parent = que_node_get_parent(parent);		ut_a(parent);	}	return(FALSE);}	/*************************************************************************Returns the number of ancestor UPDATE or DELETE nodes of acascaded update/delete node. */staticulintrow_ins_cascade_n_ancestors(/*========================*/				/* out: number of ancestors */	que_node_t*	node)	/* in: node in a query graph */{	que_node_t*	parent;	ulint		n_ancestors = 0;	parent = que_node_get_parent(node);		while (que_node_get_type(parent) == QUE_NODE_UPDATE) {		n_ancestors++;		parent = que_node_get_parent(parent);		ut_a(parent);	}	return(n_ancestors);}	/**********************************************************************Calculates the update vector node->cascade->update for a child table ina cascaded update. */staticulintrow_ins_cascade_calc_update_vec(/*============================*/					/* out: number of fields in the					calculated update vector; the value					can also be 0 if no foreign key					fields changed; the returned value					is ULINT_UNDEFINED if the column					type in the child table is too short					to fit the new value in the parent					table: that means the update fails */	upd_node_t*	node,		/* in: update node of the parent					table */	dict_foreign_t*	foreign,	/* in: foreign key constraint whose					type is != 0 */	mem_heap_t*	heap)		/* in: memory heap to use as					temporary storage */{	upd_node_t*	cascade		= node->cascade_node;	dict_table_t*	table		= foreign->foreign_table;	dict_index_t*	index		= foreign->foreign_index;	upd_t*		update;	upd_field_t*	ufield;	dict_table_t*	parent_table;	dict_index_t*	parent_index;	upd_t*		parent_update;	upd_field_t*	parent_ufield;	ulint		n_fields_updated;	ulint           parent_field_no;	dtype_t*	type;	ulint		i;	ulint		j;	    		ut_a(node && foreign && cascade && table && index);	/* Calculate the appropriate update vector which will set the fields	in the child index record to the same value (possibly padded with 	spaces if the column is a fixed length CHAR or FIXBINARY column) as	the referenced index record will get in the update. */	parent_table = node->table;	ut_a(parent_table == foreign->referenced_table);	parent_index = foreign->referenced_index;	parent_update = node->update;			update = cascade->update;	update->info_bits = 0;	update->n_fields = foreign->n_fields;			n_fields_updated = 0;	for (i = 0; i < foreign->n_fields; i++) {		parent_field_no = dict_table_get_nth_col_pos(					parent_table,					dict_index_get_nth_col_no(							parent_index, i));		for (j = 0; j < parent_update->n_fields; j++) {			parent_ufield = parent_update->fields + j;					if (parent_ufield->field_no == parent_field_no) {				ulint	min_size;				/* A field in the parent index record is				updated. Let us make the update vector				field for the child table. */ 				ufield = update->fields + n_fields_updated;

⌨️ 快捷键说明

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