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

📄 row0mysql.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
/******************************************************Interface between Innobase row operations and MySQL.Contains also create table and other data dictionary operations.(c) 2000 Innobase OyCreated 9/17/2000 Heikki Tuuri*******************************************************/#include "row0mysql.h"#ifdef UNIV_NONINL#include "row0mysql.ic"#endif#include "row0ins.h"#include "row0sel.h"#include "row0upd.h"#include "row0row.h"#include "que0que.h"#include "pars0pars.h"#include "dict0dict.h"#include "dict0crea.h"#include "dict0load.h"#include "dict0boot.h"#include "trx0roll.h"#include "trx0purge.h"#include "lock0lock.h"#include "rem0cmp.h"#include "log0log.h"#include "btr0sea.h"#include "fil0fil.h"#include "ibuf0ibuf.h"/* A dummy variable used to fool the compiler */ibool	row_mysql_identically_false	= FALSE;/* List of tables we should drop in background. ALTER TABLE in MySQL requiresthat the table handler can drop the table in background when there are noqueries to it any more. Protected by the kernel mutex. */typedef struct row_mysql_drop_struct	row_mysql_drop_t;struct row_mysql_drop_struct{	char*				table_name;	UT_LIST_NODE_T(row_mysql_drop_t) row_mysql_drop_list;};UT_LIST_BASE_NODE_T(row_mysql_drop_t)	row_mysql_drop_list;ibool	row_mysql_drop_list_inited 	= FALSE;/* Magic table names for invoking various monitor threads */static const char S_innodb_monitor[] = "innodb_monitor";static const char S_innodb_lock_monitor[] = "innodb_lock_monitor";static const char S_innodb_tablespace_monitor[] = "innodb_tablespace_monitor";static const char S_innodb_table_monitor[] = "innodb_table_monitor";static const char S_innodb_mem_validate[] = "innodb_mem_validate";/* Name suffix for recovered orphaned temporary tables */static const char S_recover_innodb_tmp_table[] = "_recover_innodb_tmp_table";/***********************************************************************Determine if the given name ends in the suffix reserved for recoveredorphaned temporary tables. */staticiboolrow_mysql_is_recovered_tmp_table(/*=============================*/				 /* out: TRUE if table name ends in				 the reserved suffix */	const char*	name){	ulint	namelen	= strlen(name) + 1;	return(namelen >= sizeof S_recover_innodb_tmp_table		&& !memcmp(name + namelen -			sizeof S_recover_innodb_tmp_table,			S_recover_innodb_tmp_table,			sizeof S_recover_innodb_tmp_table));}/***********************************************************************Determine if the given name is a name reserved for MySQL system tables. */staticiboolrow_mysql_is_system_table(/*======================*/				 /* out: TRUE if name is a MySQL				 system table name */	const char*	name){	if (memcmp(name, "mysql/", 6)) {		return(FALSE);	}	return(0 == strcmp(name + 6, "host")	    || 0 == strcmp(name + 6, "user")	    || 0 == strcmp(name + 6, "db"));}/***********************************************************************Delays an INSERT, DELETE or UPDATE operation if the purge is lagging. */staticvoidrow_mysql_delay_if_needed(void)/*===========================*/{	if (srv_dml_needed_delay) {		os_thread_sleep(srv_dml_needed_delay);	}}/***********************************************************************Frees the blob heap in prebuilt when no longer needed. */voidrow_mysql_prebuilt_free_blob_heap(/*==============================*/	row_prebuilt_t*	prebuilt)	/* in: prebuilt struct of a					ha_innobase:: table handle */{	mem_heap_free(prebuilt->blob_heap);	prebuilt->blob_heap = NULL;}/***********************************************************************Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL rowformat. */byte*row_mysql_store_true_var_len(/*=========================*/			/* out: pointer to the data, we skip the 1 or 2 bytes			at the start that are used to store the len */	byte*	dest,	/* in: where to store */	ulint	len,	/* in: length, must fit in two bytes */	ulint	lenlen)	/* in: storage length of len: either 1 or 2 bytes */{	if (lenlen == 2) {		ut_a(len < 256 * 256);		mach_write_to_2_little_endian(dest, len);		return(dest + 2);	}	ut_a(lenlen == 1);	ut_a(len < 256);	mach_write_to_1(dest, len);	return(dest + 1);}/***********************************************************************Reads a >= 5.0.3 format true VARCHAR length, in the MySQL row format, andreturns a pointer to the data. */byte*row_mysql_read_true_varchar(/*========================*/			/* out: pointer to the data, we skip the 1 or 2 bytes			at the start that are used to store the len */	ulint*	len,	/* out: variable-length field length */	byte*	field,	/* in: field in the MySQL format */	ulint	lenlen)	/* in: storage length of len: either 1 or 2 bytes */{	if (lenlen == 2) {		*len = mach_read_from_2_little_endian(field);		return(field + 2);	}	ut_a(lenlen == 1);	*len = mach_read_from_1(field);	return(field + 1);}/***********************************************************************Stores a reference to a BLOB in the MySQL format. */voidrow_mysql_store_blob_ref(/*=====================*/	byte*	dest,		/* in: where to store */	ulint	col_len,	/* in: dest buffer size: determines into				how many bytes the BLOB length is stored,				the space for the length may vary from 1				to 4 bytes */	byte*	data,		/* in: BLOB data; if the value to store				is SQL NULL this should be NULL pointer */	ulint	len)		/* in: BLOB length; if the value to store				is SQL NULL this should be 0; remember				also to set the NULL bit in the MySQL record				header! */{	/* MySQL might assume the field is set to zero except the length and	the pointer fields */	memset(dest, '\0', col_len);	/* In dest there are 1 - 4 bytes reserved for the BLOB length,	and after that 8 bytes reserved for the pointer to the data.	In 32-bit architectures we only use the first 4 bytes of the pointer	slot. */	ut_a(col_len - 8 > 1 || len < 256);	ut_a(col_len - 8 > 2 || len < 256 * 256);	ut_a(col_len - 8 > 3 || len < 256 * 256 * 256);	mach_write_to_n_little_endian(dest, col_len - 8, len);	ut_memcpy(dest + col_len - 8, (byte*)&data, sizeof(byte*));	}/***********************************************************************Reads a reference to a BLOB in the MySQL format. */byte*row_mysql_read_blob_ref(/*====================*/				/* out: pointer to BLOB data */	ulint*	len,		/* out: BLOB length */	byte*	ref,		/* in: BLOB reference in the MySQL format */	ulint	col_len)	/* in: BLOB reference length (not BLOB				length) */{	byte*	data;	*len = mach_read_from_n_little_endian(ref, col_len - 8);	ut_memcpy((byte*)&data, ref + col_len - 8, sizeof(byte*));	return(data);}/******************************************************************Stores a non-SQL-NULL field given in the MySQL format in the InnoDB format.The counterpart of this function is row_sel_field_store_in_mysql_format() inrow0sel.c. */byte*row_mysql_store_col_in_innobase_format(/*===================================*/					/* out: up to which byte we used					buf in the conversion */	dfield_t*	dfield,		/* in/out: dfield where dtype					information must be already set when					this function is called! */	byte*		buf,		/* in/out: buffer for a converted					integer value; this must be at least					col_len long then! */	ibool		row_format_col,	/* TRUE if the mysql_data is from					a MySQL row, FALSE if from a MySQL					key value;					in MySQL, a true VARCHAR storage					format differs in a row and in a					key value: in a key value the length					is always stored in 2 bytes! */	byte*		mysql_data,	/* in: MySQL column value, not					SQL NULL; NOTE that dfield may also					get a pointer to mysql_data,					therefore do not discard this as long					as dfield is used! */	ulint		col_len,	/* in: MySQL column length; NOTE that					this is the storage length of the					column in the MySQL format row, not					necessarily the length of the actual					payload data; if the column is a true					VARCHAR then this is irrelevant */	ulint		comp)		/* in: nonzero=compact format */{	byte*		ptr 	= mysql_data;	dtype_t*	dtype;	ulint		type;	ulint		lenlen;	dtype = dfield_get_type(dfield);	type = dtype->mtype;	if (type == DATA_INT) {		/* Store integer data in Innobase in a big-endian format,		sign bit negated if the data is a signed integer. In MySQL,		integers are stored in a little-endian format. */		ptr = buf + col_len;		for (;;) {			ptr--;			*ptr = *mysql_data;			if (ptr == buf) {				break;			}			mysql_data++;		}		if (!(dtype->prtype & DATA_UNSIGNED)) {			*ptr = (byte) (*ptr ^ 128);		}		buf += col_len;	} else if ((type == DATA_VARCHAR		    || type == DATA_VARMYSQL		    || type == DATA_BINARY)) {		if (dtype_get_mysql_type(dtype) == DATA_MYSQL_TRUE_VARCHAR) {			/* The length of the actual data is stored to 1 or 2			bytes at the start of the field */						if (row_format_col) {				if (dtype->prtype & DATA_LONG_TRUE_VARCHAR) {					lenlen = 2;				} else {					lenlen = 1;				}			} else {				/* In a MySQL key value, lenlen is always 2 */				lenlen = 2;			}			ptr = row_mysql_read_true_varchar(&col_len, mysql_data,								      lenlen);		} else {			/* Remove trailing spaces from old style VARCHAR			columns. */			/* Handle UCS2 strings differently. */			ulint	mbminlen	= dtype_get_mbminlen(dtype);			ptr = mysql_data;			if (mbminlen == 2) {				/* space=0x0020 */				/* Trim "half-chars", just in case. */				col_len &= ~1;				while (col_len >= 2 && ptr[col_len - 2] == 0x00						&& ptr[col_len - 1] == 0x20) {					col_len -= 2;				}			} else {				ut_a(mbminlen == 1);				/* space=0x20 */				while (col_len > 0						&& ptr[col_len - 1] == 0x20) {					col_len--;				}			}		}	} else if (comp && type == DATA_MYSQL			&& dtype_get_mbminlen(dtype) == 1			&& dtype_get_mbmaxlen(dtype) > 1) {		/* In some cases we strip trailing spaces from UTF-8 and other		multibyte charsets, from FIXED-length CHAR columns, to save		space. UTF-8 would otherwise normally use 3 * the string length		bytes to store a latin1 string! */		/* We assume that this CHAR field is encoded in a		variable-length character set where spaces have		1:1 correspondence to 0x20 bytes, such as UTF-8.		Consider a CHAR(n) field, a field of n characters.		It will contain between n * mbminlen and n * mbmaxlen bytes.		We will try to truncate it to n bytes by stripping		space padding.  If the field contains single-byte		characters only, it will be truncated to n characters.		Consider a CHAR(5) field containing the string ".a   "		where "." denotes a 3-byte character represented by		the bytes "$%&".  After our stripping, the string will		be stored as "$%&a " (5 bytes).  The string ".abc "		will be stored as "$%&abc" (6 bytes).		The space padding will be restored in row0sel.c, function		row_sel_field_store_in_mysql_format(). */		ulint		n_chars;		ut_a(!(dtype_get_len(dtype) % dtype_get_mbmaxlen(dtype)));		n_chars = dtype_get_len(dtype) / dtype_get_mbmaxlen(dtype);		/* Strip space padding. */		while (col_len > n_chars && ptr[col_len - 1] == 0x20) {			col_len--;		}	} else if (type == DATA_BLOB && row_format_col) {		ptr = row_mysql_read_blob_ref(&col_len, mysql_data, col_len);	}	dfield_set_data(dfield, ptr, col_len);	return(buf);}/******************************************************************Convert a row in the MySQL format to a row in the Innobase format. Note thatthe function to convert a MySQL format key value to an InnoDB dtuple isrow_sel_convert_mysql_key_to_innobase() in row0sel.c. */staticvoidrow_mysql_convert_row_to_innobase(/*==============================*/	dtuple_t*	row,		/* in/out: Innobase row where the					field type information is already					copied there! */	row_prebuilt_t*	prebuilt,	/* in: prebuilt struct where template					must be of type ROW_MYSQL_WHOLE_ROW */	byte*		mysql_rec)	/* in: row in the MySQL format;					NOTE: do not discard as long as					row is used, as row may contain					pointers to this record! */{	mysql_row_templ_t*	templ;		dfield_t*		dfield;	ulint			i;		ut_ad(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);	ut_ad(prebuilt->mysql_template);	for (i = 0; i < prebuilt->n_template; i++) {		templ = prebuilt->mysql_template + i;		dfield = dtuple_get_nth_field(row, i);		if (templ->mysql_null_bit_mask != 0) {			/* Column may be SQL NULL */			if (mysql_rec[templ->mysql_null_byte_offset] & 					(byte) (templ->mysql_null_bit_mask)) {				/* It is SQL NULL */				dfield_set_data(dfield, NULL, UNIV_SQL_NULL);				goto next_column;			}		}							row_mysql_store_col_in_innobase_format(dfield,					prebuilt->ins_upd_rec_buff						+ templ->mysql_col_offset,					TRUE, /* MySQL row format data */					mysql_rec + templ->mysql_col_offset,					templ->mysql_col_len,					prebuilt->table->comp);next_column:		;	} }/********************************************************************Handles user errors and lock waits detected by the database engine. */iboolrow_mysql_handle_errors(/*====================*/				/* out: TRUE if it was a lock wait and				we should continue running the query thread */	ulint*		new_err,/* out: possible new error encountered in				lock wait, or if no new error, the value				of trx->error_state at the entry of this				function */	trx_t*		trx,	/* in: transaction */	que_thr_t*	thr,	/* in: query thread */	trx_savept_t*	savept)	/* in: savepoint or NULL */{#ifndef UNIV_HOTBACKUP	ulint	err;handle_new_error:	err = trx->error_state;		ut_a(err != DB_SUCCESS);		trx->error_state = DB_SUCCESS;	if (err == DB_DUPLICATE_KEY) {           	if (savept) {			/* Roll back the latest, possibly incomplete			insertion or update */			trx_general_rollback_for_mysql(trx, TRUE, savept);		}	} else if (err == DB_TOO_BIG_RECORD) {           	if (savept) {			/* Roll back the latest, possibly incomplete			insertion or update */			trx_general_rollback_for_mysql(trx, TRUE, savept);		}

⌨️ 快捷键说明

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