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

📄 row0sel.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
					to index! */	byte*		buf,		/* in: buffer to use in field					conversions */	ulint		buf_len,	/* in: buffer length */	dict_index_t*	index,		/* in: index of the key value */	byte*		key_ptr,	/* in: MySQL key value */	ulint		key_len,	/* in: MySQL key value length */	trx_t*		trx)		/* in: transaction */{	byte*		original_buf	= buf;	byte*		original_key_ptr = key_ptr;	dict_field_t*	field;	dfield_t*	dfield;	ulint		data_offset;	ulint		data_len;	ulint		data_field_len;	ibool		is_null;	byte*		key_end;	ulint		n_fields = 0;	ulint		type;		/* For documentation of the key value storage format in MySQL, see	ha_innobase::store_key_val_for_row() in ha_innodb.cc. */	key_end = key_ptr + key_len;	/* Permit us to access any field in the tuple (ULINT_MAX): */		dtuple_set_n_fields(tuple, ULINT_MAX);	dfield = dtuple_get_nth_field(tuple, 0);	field = dict_index_get_nth_field(index, 0);	if (dfield_get_type(dfield)->mtype == DATA_SYS) {		/* A special case: we are looking for a position in the		generated clustered index which InnoDB automatically added		to a table with no primary key: the first and the only		ordering column is ROW_ID which InnoDB stored to the key_ptr		buffer. */		ut_a(key_len == DATA_ROW_ID_LEN);		dfield_set_data(dfield, key_ptr, DATA_ROW_ID_LEN);							dtuple_set_n_fields(tuple, 1);		return;	}	while (key_ptr < key_end) {		ut_a(dict_col_get_type(field->col)->mtype		     == dfield_get_type(dfield)->mtype);		data_offset = 0;		is_null = FALSE;    		if (!(dfield_get_type(dfield)->prtype & DATA_NOT_NULL)) {    			/* The first byte in the field tells if this is    			an SQL NULL value */    						data_offset = 1; 			if (*key_ptr != 0) {      				dfield_set_data(dfield, NULL, UNIV_SQL_NULL);				is_null = TRUE;      			}      		}		type = dfield_get_type(dfield)->mtype;		/* Calculate data length and data field total length */				if (type == DATA_BLOB) {			/* The key field is a column prefix of a BLOB or			TEXT */			ut_a(field->prefix_len > 0);			/* MySQL stores the actual data length to the first 2			bytes after the optional SQL NULL marker byte. The			storage format is little-endian, that is, the most			significant byte at a higher address. In UTF-8, MySQL			seems to reserve field->prefix_len bytes for			storing this field in the key value buffer, even			though the actual value only takes data_len bytes			from the start. */			data_len = key_ptr[data_offset]				   + 256 * key_ptr[data_offset + 1];			data_field_len = data_offset + 2 + field->prefix_len;			data_offset += 2;			/* Now that we know the length, we store the column			value like it would be a fixed char field */		} else if (field->prefix_len > 0) {			/* Looks like MySQL pads unused end bytes in the			prefix with space. Therefore, also in UTF-8, it is ok			to compare with a prefix containing full prefix_len			bytes, and no need to take at most prefix_len / 3			UTF-8 characters from the start.			If the prefix is used as the upper end of a LIKE			'abc%' query, then MySQL pads the end with chars			0xff. TODO: in that case does it any harm to compare			with the full prefix_len bytes. How do characters			0xff in UTF-8 behave? */		        data_len = field->prefix_len;			data_field_len = data_offset + data_len;		} else {			data_len = dfield_get_type(dfield)->len;			data_field_len = data_offset + data_len;		} 		if (dtype_get_mysql_type(dfield_get_type(dfield))					== DATA_MYSQL_TRUE_VARCHAR		    && dfield_get_type(dfield)->mtype != DATA_INT) {			/* In a MySQL key value format, a true VARCHAR is			always preceded by 2 bytes of a length field.			dfield_get_type(dfield)->len returns the maximum			'payload' len in bytes. That does not include the			2 bytes that tell the actual data length.			We added the check != DATA_INT to make sure we do			not treat MySQL ENUM or SET as a true VARCHAR! */			data_len += 2;			data_field_len += 2;		}		/* Storing may use at most data_len bytes of buf */				if (!is_null) {		        row_mysql_store_col_in_innobase_format(					dfield,					buf,					FALSE, /* MySQL key value format col */					key_ptr + data_offset,					data_len,					index->table->comp);			buf += data_len;		}    		key_ptr += data_field_len;		if (key_ptr > key_end) {			/* The last field in key was not a complete key field			but a prefix of it.		        Print a warning about this! HA_READ_PREFIX_LAST does			not currently work in InnoDB with partial-field key			value prefixes. Since MySQL currently uses a padding			trick to calculate LIKE 'abc%' type queries there			should never be partial-field prefixes in searches. */		        ut_print_timestamp(stderr);						fputs(  "  InnoDB: Warning: using a partial-field key prefix in search.\n"  "InnoDB: ", stderr);			dict_index_name_print(stderr, trx, index);			fprintf(stderr, ". Last data field length %lu bytes,\n"  "InnoDB: key ptr now exceeds key end by %lu bytes.\n"  "InnoDB: Key value in the MySQL format:\n",					  (ulong) data_field_len,					  (ulong) (key_ptr - key_end));			fflush(stderr);			ut_print_buf(stderr, original_key_ptr, key_len);			fprintf(stderr, "\n");			if (!is_null) {			        dfield->len -= (ulint)(key_ptr - key_end);			}		}		n_fields++;    		    		field++;		dfield++;  	}	ut_a(buf <= original_buf + buf_len); 	/* We set the length of tuple to n_fields: we assume that the memory	area allocated for it is big enough (usually bigger than n_fields). */ 	 	dtuple_set_n_fields(tuple, n_fields);}/******************************************************************Stores the row id to the prebuilt struct. */staticvoidrow_sel_store_row_id_to_prebuilt(/*=============================*/	row_prebuilt_t*	prebuilt,	/* in: prebuilt */	rec_t*		index_rec,	/* in: record */	dict_index_t*	index,		/* in: index of the record */	const ulint*	offsets)	/* in: rec_get_offsets					(index_rec, index) */{	byte*	data;	ulint	len;	ut_ad(rec_offs_validate(index_rec, index, offsets));	data = rec_get_nth_field(index_rec, offsets,			dict_index_get_sys_col_pos(index, DATA_ROW_ID), &len);	if (len != DATA_ROW_ID_LEN) {	        fprintf(stderr,"InnoDB: Error: Row id field is wrong length %lu in ", (ulong) len);		dict_index_name_print(stderr, prebuilt->trx, index);		fprintf(stderr, "\n""InnoDB: Field number %lu, record:\n",		    (ulong) dict_index_get_sys_col_pos(index, DATA_ROW_ID));		rec_print_new(stderr, index_rec, offsets);		putc('\n', stderr);		ut_error;	}	ut_memcpy(prebuilt->row_id, data, len);}/******************************************************************Stores a non-SQL-NULL field in the MySQL format. The counterpart of thisfunction is row_mysql_store_col_in_innobase_format() in row0mysql.c. */staticvoidrow_sel_field_store_in_mysql_format(/*================================*/	byte*	dest,	/* in/out: buffer where to store; NOTE that BLOBs			are not in themselves stored here: the caller must			allocate and copy the BLOB into buffer before, and pass			the pointer to the BLOB in 'data' */	const mysql_row_templ_t* templ,	/* in: MySQL column template.			Its following fields are referenced:			type, is_unsigned, mysql_col_len, mbminlen, mbmaxlen */	byte*	data,	/* in: data to store */	ulint	len)	/* in: length of the data */{	byte*	ptr;	byte*	field_end;	byte*	pad_ptr;	ut_ad(len != UNIV_SQL_NULL);	if (templ->type == DATA_INT) {		/* Convert integer data from Innobase to a little-endian		format, sign bit restored to normal */		ptr = dest + len;		for (;;) {			ptr--;			*ptr = *data;			if (ptr == dest) {				break;			}			data++;		}		if (!templ->is_unsigned) {			dest[len - 1] = (byte) (dest[len - 1] ^ 128);		}		ut_ad(templ->mysql_col_len == len);	} else if (templ->type == DATA_VARCHAR	           || templ->type == DATA_VARMYSQL		   || templ->type == DATA_BINARY) {		field_end = dest + templ->mysql_col_len;		if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {			/* This is a >= 5.0.3 type true VARCHAR. Store the			length of the data to the first byte or the first			two bytes of dest. */					dest = row_mysql_store_true_var_len(dest, len,						templ->mysql_length_bytes);		}		/* Copy the actual data */		ut_memcpy(dest, data, len);				/* Pad with trailing spaces. We pad with spaces also the		unused end of a >= 5.0.3 true VARCHAR column, just in case		MySQL expects its contents to be deterministic. */					pad_ptr = dest + len;		ut_ad(templ->mbminlen <= templ->mbmaxlen);		/* We handle UCS2 charset strings differently. */		if (templ->mbminlen == 2) {			/* A space char is two bytes, 0x0020 in UCS2 */			if (len & 1) {				/* A 0x20 has been stripped from the column.				Pad it back. */								if (pad_ptr < field_end) {					*pad_ptr = 0x20;					pad_ptr++;				}			}						/* Pad the rest of the string with 0x0020 */			while (pad_ptr < field_end) {				*pad_ptr = 0x00;				pad_ptr++;				*pad_ptr = 0x20;				pad_ptr++;			}		} else {			ut_ad(templ->mbminlen == 1);			/* space=0x20 */			memset(pad_ptr, 0x20, field_end - pad_ptr);		}	} else if (templ->type == DATA_BLOB) {		/* Store a pointer to the BLOB buffer to dest: the BLOB was		already copied to the buffer in row_sel_store_mysql_rec */		row_mysql_store_blob_ref(dest, templ->mysql_col_len, data,									len);	} else if (templ->type == DATA_MYSQL) {		memcpy(dest, data, len);		ut_ad(templ->mysql_col_len >= len);		ut_ad(templ->mbmaxlen >= templ->mbminlen);		ut_ad(templ->mbmaxlen > templ->mbminlen			|| templ->mysql_col_len == len);		/* The following assertion would fail for old tables		containing UTF-8 ENUM columns due to Bug #9526. */		ut_ad(!templ->mbmaxlen			|| !(templ->mysql_col_len % templ->mbmaxlen));		ut_ad(len * templ->mbmaxlen >= templ->mysql_col_len);		if (templ->mbminlen != templ->mbmaxlen) {			/* Pad with spaces. This undoes the stripping			done in row0mysql.ic, function			row_mysql_store_col_in_innobase_format(). */			memset(dest + len, 0x20, templ->mysql_col_len - len);		}	} else {		ut_ad(templ->type == DATA_CHAR			|| templ->type == DATA_FIXBINARY			/*|| templ->type == DATA_SYS_CHILD			|| templ->type == DATA_SYS*/			|| templ->type == DATA_FLOAT			|| templ->type == DATA_DOUBLE			|| templ->type == DATA_DECIMAL);		ut_ad(templ->mysql_col_len == len);		memcpy(dest, data, len);	}}/******************************************************************Convert a row in the Innobase format to a row in the MySQL format.Note that the template in prebuilt may advise us to copy only a fewcolumns to mysql_rec, other columns are left blank. All columns may notbe needed in the query. */staticiboolrow_sel_store_mysql_rec(/*====================*/					/* out: TRUE if success, FALSE if					could not allocate memory for a BLOB					(though we may also assert in that					case) */	byte*		mysql_rec,	/* out: row in the MySQL format */	row_prebuilt_t*	prebuilt,	/* in: prebuilt struct */	rec_t*		rec,		/* in: Innobase record in the index					which was described in prebuilt's					template */	const ulint*	offsets)	/* in: array returned by					rec_get_offsets() */{	mysql_row_templ_t*	templ;	mem_heap_t*		extern_field_heap	= NULL;	byte*			data;	ulint			len;	ulint			i;		ut_ad(prebuilt->mysql_template);	ut_ad(rec_offs_validate(rec, NULL, offsets));	if (UNIV_LIKELY_NULL(prebuilt->blob_heap)) {		mem_heap_free(prebuilt->blob_heap);		prebuilt->blob_heap = NULL;	}	for (i = 0; i < prebuilt->n_template; i++) {		templ = prebuilt->mysql_template + i;		data = rec_get_nth_field(rec, offsets,					templ->rec_field_no, &len);		if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,						templ->rec_field_no))) {			/* Copy an externally stored field to the temporary			heap */			ut_a(!prebuilt->trx->has_search_latch);			extern_field_heap = mem_heap_create(UNIV_PAGE_SIZE);			/* NOTE: if we are retrieving a big BLOB, we may			already run out of memory in the next call, which			causes an assert */			data = btr_rec_copy_externally_stored_field(rec,					offsets, templ->rec_field_no, &len,					extern_field_heap);			ut_a(len != UNIV_SQL_NULL);		}		if (len != UNIV_SQL_NULL) {			if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) {				ut_a(prebuilt->templ_contains_blob);				/* A heuristic test that we can allocate the				memory for a big BLOB. We have a safety margin				of 1000000 bytes. Since the test takes some				CPU time, we do not use it for small BLOBs. */				if (UNIV_UNLIKELY(len > 2000000)				    && UNIV_UNLIKELY(!ut_test_malloc(							len + 1000000))) {					ut_print_timestamp(stderr);					fprintf(stderr,"  InnoDB: Warning: could not allocate %lu + 1000000 bytes to retrieve\n""InnoDB: a big column. Table name ", (ulong) len);					ut_print_name(stderr,						prebuilt->trx,						prebuilt->table->name);					putc('\n', stderr);					if (extern_field_heap) {						mem_heap_free(							extern_field_heap);					}					return(FALSE);				}				/* Copy the BLOB data to the BLOB heap of				prebuilt */				if (prebuilt->blob_heap == NULL) {					prebuilt->blob_heap =						mem_heap_create(len);				}				data = memcpy(mem_heap_alloc(						prebuilt->blob_heap, len),						data, len);			}					row_sel_field_store_in_mysql_format(				mysql_rec + templ->mysql_col_offset,				templ, data, len);			/* Cleanup */			if (extern_field_heap) { 				mem_heap_free(extern_field_heap);				extern_field_heap = NULL; 			}						if (templ->mysql_null_bit_mask) {				/* It is a nullable column with a non-NULL				value */				mysql_rec[templ->mysql_null_byte_offset] &=					~(byte) (templ->mysql_null_bit_mask);			}		} else {		        /* MySQL seems to assume the field for an SQL NULL		        value is set to zero or space. Not taking this into			account caused seg faults with NULL BLOB fields, and		        bug number 154 in the MySQL bug database: GROUP BY		        and DISTINCT could treat NULL values inequal. */			int	pad_char;			mysql_rec[templ->mysql_null_byte_offset] |=					(byte) (templ->mysql_null_bit_mask);			switch (templ->type) {			case DATA_VARCHAR:			case DATA_BINARY:			case DATA_VARMYSQL:				if (templ->mysql_type				    == DATA_MYSQL_TRUE_VARCHAR) {					/* This is a >= 5.0.3 type					true VARCHAR.  Zero the field. */					pad_char = 0x00;					

⌨️ 快捷键说明

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