mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-04 12:56:14 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			688 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			688 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*****************************************************************************
 | 
						|
 | 
						|
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
 | 
						|
Copyright (c) 2017, 2022, MariaDB Corporation.
 | 
						|
 | 
						|
This program is free software; you can redistribute it and/or modify it under
 | 
						|
the terms of the GNU General Public License as published by the Free Software
 | 
						|
Foundation; version 2 of the License.
 | 
						|
 | 
						|
This program is distributed in the hope that it will be useful, but WITHOUT
 | 
						|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
						|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License along with
 | 
						|
this program; if not, write to the Free Software Foundation, Inc.,
 | 
						|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
 | 
						|
 | 
						|
*****************************************************************************/
 | 
						|
 | 
						|
/********************************************************************//**
 | 
						|
@file include/data0data.h
 | 
						|
SQL data field and tuple
 | 
						|
 | 
						|
Created 5/30/1994 Heikki Tuuri
 | 
						|
*************************************************************************/
 | 
						|
 | 
						|
#ifndef data0data_h
 | 
						|
#define data0data_h
 | 
						|
 | 
						|
#include "data0types.h"
 | 
						|
#include "data0type.h"
 | 
						|
#include "mem0mem.h"
 | 
						|
#include "dict0types.h"
 | 
						|
#include "btr0types.h"
 | 
						|
#include <vector>
 | 
						|
 | 
						|
#include <ostream>
 | 
						|
 | 
						|
/** Storage for overflow data in a big record, that is, a clustered
 | 
						|
index record which needs external storage of data fields */
 | 
						|
struct big_rec_t;
 | 
						|
struct upd_t;
 | 
						|
 | 
						|
/** Dummy variable to catch access to uninitialized fields.  In the
 | 
						|
debug version, dtuple_create() will make all fields of dtuple_t point
 | 
						|
to data_error. */
 | 
						|
ut_d(extern byte data_error);
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Sets the type struct of SQL data field. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dfield_set_type(
 | 
						|
/*============*/
 | 
						|
	dfield_t*	field,	/*!< in: SQL data field */
 | 
						|
	const dtype_t*	type);	/*!< in: pointer to data type struct */
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Sets length in a field. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dfield_set_len(
 | 
						|
/*===========*/
 | 
						|
	dfield_t*	field,	/*!< in: field */
 | 
						|
	ulint		len)	/*!< in: length or UNIV_SQL_NULL */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
 | 
						|
/** Gets spatial status for "external storage"
 | 
						|
@param[in,out]	field		field */
 | 
						|
UNIV_INLINE
 | 
						|
spatial_status_t
 | 
						|
dfield_get_spatial_status(
 | 
						|
	const dfield_t*	field);
 | 
						|
 | 
						|
/** Sets spatial status for "external storage"
 | 
						|
@param[in,out]	field		field
 | 
						|
@param[in]	spatial_status	spatial status */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dfield_set_spatial_status(
 | 
						|
	dfield_t*		field,
 | 
						|
	spatial_status_t	spatial_status);
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Sets pointer to the data and length in a field. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dfield_set_data(
 | 
						|
/*============*/
 | 
						|
	dfield_t*	field,	/*!< in: field */
 | 
						|
	const void*	data,	/*!< in: data */
 | 
						|
	ulint		len)	/*!< in: length or UNIV_SQL_NULL */
 | 
						|
	MY_ATTRIBUTE((nonnull(1)));
 | 
						|
/*********************************************************************//**
 | 
						|
Sets pointer to the data and length in a field. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dfield_write_mbr(
 | 
						|
/*=============*/
 | 
						|
	dfield_t*	field,	/*!< in: field */
 | 
						|
	const double*	mbr)	/*!< in: data */
 | 
						|
	MY_ATTRIBUTE((nonnull(1)));
 | 
						|
/*********************************************************************//**
 | 
						|
Sets a data field to SQL NULL. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dfield_set_null(
 | 
						|
/*============*/
 | 
						|
	dfield_t*	field)	/*!< in/out: field */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
/**********************************************************************//**
 | 
						|
Writes an SQL null field full of zeros. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
data_write_sql_null(
 | 
						|
/*================*/
 | 
						|
	byte*	data,	/*!< in: pointer to a buffer of size len */
 | 
						|
	ulint	len)	/*!< in: SQL null size in bytes */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
/*********************************************************************//**
 | 
						|
Copies the data and len fields. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dfield_copy_data(
 | 
						|
/*=============*/
 | 
						|
	dfield_t*	field1,		/*!< out: field to copy to */
 | 
						|
	const dfield_t*	field2);	/*!< in: field to copy from */
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Copies a data field to another. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dfield_copy(
 | 
						|
/*========*/
 | 
						|
	dfield_t*	field1,	/*!< out: field to copy to */
 | 
						|
	const dfield_t*	field2)	/*!< in: field to copy from */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
/*********************************************************************//**
 | 
						|
Copies the data pointed to by a data field. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dfield_dup(
 | 
						|
/*=======*/
 | 
						|
	dfield_t*	field,	/*!< in/out: data field */
 | 
						|
	mem_heap_t*	heap)	/*!< in: memory heap where allocated */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Tests if two data fields are equal.
 | 
						|
If len==0, tests the data length and content for equality.
 | 
						|
If len>0, tests the first len bytes of the content for equality.
 | 
						|
@return TRUE if both fields are NULL or if they are equal */
 | 
						|
UNIV_INLINE
 | 
						|
ibool
 | 
						|
dfield_datas_are_binary_equal(
 | 
						|
/*==========================*/
 | 
						|
	const dfield_t*	field1,	/*!< in: field */
 | 
						|
	const dfield_t*	field2,	/*!< in: field */
 | 
						|
	ulint		len)	/*!< in: maximum prefix to compare,
 | 
						|
				or 0 to compare the whole field length */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
/*********************************************************************//**
 | 
						|
Tests if dfield data length and content is equal to the given.
 | 
						|
@return TRUE if equal */
 | 
						|
UNIV_INLINE
 | 
						|
ibool
 | 
						|
dfield_data_is_binary_equal(
 | 
						|
/*========================*/
 | 
						|
	const dfield_t*	field,	/*!< in: field */
 | 
						|
	ulint		len,	/*!< in: data length or UNIV_SQL_NULL */
 | 
						|
	const byte*	data)	/*!< in: data */
 | 
						|
	MY_ATTRIBUTE((nonnull(1), warn_unused_result));
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Gets info bits in a data tuple.
 | 
						|
@return info bits */
 | 
						|
UNIV_INLINE
 | 
						|
ulint
 | 
						|
dtuple_get_info_bits(
 | 
						|
/*=================*/
 | 
						|
	const dtuple_t*	tuple)	/*!< in: tuple */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
/*********************************************************************//**
 | 
						|
Sets info bits in a data tuple. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dtuple_set_info_bits(
 | 
						|
/*=================*/
 | 
						|
	dtuple_t*	tuple,		/*!< in: tuple */
 | 
						|
	ulint		info_bits)	/*!< in: info bits */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
/*********************************************************************//**
 | 
						|
Gets number of fields used in record comparisons.
 | 
						|
@return number of fields used in comparisons in rem0cmp.* */
 | 
						|
UNIV_INLINE
 | 
						|
uint16_t
 | 
						|
dtuple_get_n_fields_cmp(
 | 
						|
/*====================*/
 | 
						|
	const dtuple_t*	tuple)	/*!< in: tuple */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
/*********************************************************************//**
 | 
						|
Gets number of fields used in record comparisons. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dtuple_set_n_fields_cmp(
 | 
						|
/*====================*/
 | 
						|
	dtuple_t*	tuple,		/*!< in: tuple */
 | 
						|
	ulint		n_fields_cmp)	/*!< in: number of fields used in
 | 
						|
					comparisons in rem0cmp.* */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
 | 
						|
/* Estimate the number of bytes that are going to be allocated when
 | 
						|
creating a new dtuple_t object */
 | 
						|
#define DTUPLE_EST_ALLOC(n_fields)	\
 | 
						|
	(sizeof(dtuple_t) + (n_fields) * sizeof(dfield_t))
 | 
						|
 | 
						|
/** Creates a data tuple from an already allocated chunk of memory.
 | 
						|
The size of the chunk must be at least DTUPLE_EST_ALLOC(n_fields).
 | 
						|
The default value for number of fields used in record comparisons
 | 
						|
for this tuple is n_fields.
 | 
						|
@param[in,out]	buf		buffer to use
 | 
						|
@param[in]	buf_size	buffer size
 | 
						|
@param[in]	n_fields	number of field
 | 
						|
@param[in]	n_v_fields	number of fields on virtual columns
 | 
						|
@return created tuple (inside buf) */
 | 
						|
UNIV_INLINE
 | 
						|
dtuple_t*
 | 
						|
dtuple_create_from_mem(
 | 
						|
	void*	buf,
 | 
						|
	ulint	buf_size,
 | 
						|
	ulint	n_fields,
 | 
						|
	ulint	n_v_fields)
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
 | 
						|
/**********************************************************//**
 | 
						|
Creates a data tuple to a memory heap. The default value for number
 | 
						|
of fields used in record comparisons for this tuple is n_fields.
 | 
						|
@return own: created tuple */
 | 
						|
UNIV_INLINE
 | 
						|
dtuple_t*
 | 
						|
dtuple_create(
 | 
						|
/*==========*/
 | 
						|
	mem_heap_t*	heap,	/*!< in: memory heap where the tuple
 | 
						|
				is created, DTUPLE_EST_ALLOC(n_fields)
 | 
						|
				bytes will be allocated from this heap */
 | 
						|
	ulint		n_fields)/*!< in: number of fields */
 | 
						|
	MY_ATTRIBUTE((nonnull, malloc));
 | 
						|
 | 
						|
/** Initialize the virtual field data in a dtuple_t
 | 
						|
@param[in,out]		vrow	dtuple contains the virtual fields */
 | 
						|
UNIV_INLINE void dtuple_init_v_fld(dtuple_t* vrow);
 | 
						|
 | 
						|
/** Duplicate the virtual field data in a dtuple_t
 | 
						|
@param[in,out]		vrow	dtuple contains the virtual fields
 | 
						|
@param[in]		heap	heap memory to use */
 | 
						|
UNIV_INLINE void dtuple_dup_v_fld(dtuple_t* vrow, mem_heap_t* heap);
 | 
						|
 | 
						|
/** Creates a data tuple with possible virtual columns to a memory heap.
 | 
						|
@param[in]	heap		memory heap where the tuple is created
 | 
						|
@param[in]	n_fields	number of fields
 | 
						|
@param[in]	n_v_fields	number of fields on virtual col
 | 
						|
@return own: created tuple */
 | 
						|
UNIV_INLINE
 | 
						|
dtuple_t*
 | 
						|
dtuple_create_with_vcol(
 | 
						|
	mem_heap_t*	heap,
 | 
						|
	ulint		n_fields,
 | 
						|
	ulint		n_v_fields);
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Sets number of fields used in a tuple. Normally this is set in
 | 
						|
dtuple_create, but if you want later to set it smaller, you can use this. */
 | 
						|
inline
 | 
						|
void
 | 
						|
dtuple_set_n_fields(
 | 
						|
/*================*/
 | 
						|
	dtuple_t*	tuple,		/*!< in: tuple */
 | 
						|
	ulint		n_fields)	/*!< in: number of fields */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
/** Copies a data tuple's virtual fields to another. This is a shallow copy;
 | 
						|
@param[in,out]	d_tuple		destination tuple
 | 
						|
@param[in]	s_tuple		source tuple */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dtuple_copy_v_fields(
 | 
						|
	dtuple_t*	d_tuple,
 | 
						|
	const dtuple_t*	s_tuple);
 | 
						|
/*********************************************************************//**
 | 
						|
Copies a data tuple to another.  This is a shallow copy; if a deep copy
 | 
						|
is desired, dfield_dup() will have to be invoked on each field.
 | 
						|
@return own: copy of tuple */
 | 
						|
UNIV_INLINE
 | 
						|
dtuple_t*
 | 
						|
dtuple_copy(
 | 
						|
/*========*/
 | 
						|
	const dtuple_t*	tuple,	/*!< in: tuple to copy from */
 | 
						|
	mem_heap_t*	heap)	/*!< in: memory heap
 | 
						|
				where the tuple is created */
 | 
						|
	MY_ATTRIBUTE((nonnull, malloc));
 | 
						|
/**********************************************************//**
 | 
						|
The following function returns the sum of data lengths of a tuple. The space
 | 
						|
occupied by the field structs or the tuple struct is not counted.
 | 
						|
@return sum of data lens */
 | 
						|
UNIV_INLINE
 | 
						|
ulint
 | 
						|
dtuple_get_data_size(
 | 
						|
/*=================*/
 | 
						|
	const dtuple_t*	tuple,	/*!< in: typed data tuple */
 | 
						|
	ulint		comp)	/*!< in: nonzero=ROW_FORMAT=COMPACT  */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
/*********************************************************************//**
 | 
						|
Computes the number of externally stored fields in a data tuple.
 | 
						|
@return number of fields */
 | 
						|
UNIV_INLINE
 | 
						|
ulint
 | 
						|
dtuple_get_n_ext(
 | 
						|
/*=============*/
 | 
						|
	const dtuple_t*	tuple)	/*!< in: tuple */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
/*******************************************************************//**
 | 
						|
Sets types of fields binary in a tuple. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dtuple_set_types_binary(
 | 
						|
/*====================*/
 | 
						|
	dtuple_t*	tuple,	/*!< in: data tuple */
 | 
						|
	ulint		n)	/*!< in: number of fields to set */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
/** Checks if a dtuple contains an SQL null value.
 | 
						|
@param tuple tuple
 | 
						|
@param fields_number number of fields in the tuple to check
 | 
						|
@return true if some field is SQL null */
 | 
						|
UNIV_INLINE
 | 
						|
bool dtuple_contains_null(const dtuple_t *tuple, ulint fields_number = 0);
 | 
						|
/**********************************************************//**
 | 
						|
Checks that a data field is typed. Asserts an error if not.
 | 
						|
@return TRUE if ok */
 | 
						|
ibool
 | 
						|
dfield_check_typed(
 | 
						|
/*===============*/
 | 
						|
	const dfield_t*	field)	/*!< in: data field */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
/**********************************************************//**
 | 
						|
Checks that a data tuple is typed. Asserts an error if not.
 | 
						|
@return TRUE if ok */
 | 
						|
ibool
 | 
						|
dtuple_check_typed(
 | 
						|
/*===============*/
 | 
						|
	const dtuple_t*	tuple)	/*!< in: tuple */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
#ifdef UNIV_DEBUG
 | 
						|
/**********************************************************//**
 | 
						|
Validates the consistency of a tuple which must be complete, i.e,
 | 
						|
all fields must have been set.
 | 
						|
@return TRUE if ok */
 | 
						|
ibool
 | 
						|
dtuple_validate(
 | 
						|
/*============*/
 | 
						|
	const dtuple_t*	tuple)	/*!< in: tuple */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
#endif /* UNIV_DEBUG */
 | 
						|
/*************************************************************//**
 | 
						|
Pretty prints a dfield value according to its data type. */
 | 
						|
void
 | 
						|
dfield_print(
 | 
						|
/*=========*/
 | 
						|
	const dfield_t*	dfield)	/*!< in: dfield */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
/*************************************************************//**
 | 
						|
Pretty prints a dfield value according to its data type. Also the hex string
 | 
						|
is printed if a string contains non-printable characters. */
 | 
						|
void
 | 
						|
dfield_print_also_hex(
 | 
						|
/*==================*/
 | 
						|
	const dfield_t*	dfield)	 /*!< in: dfield */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
/**********************************************************//**
 | 
						|
The following function prints the contents of a tuple. */
 | 
						|
void
 | 
						|
dtuple_print(
 | 
						|
/*=========*/
 | 
						|
	FILE*		f,	/*!< in: output stream */
 | 
						|
	const dtuple_t*	tuple)	/*!< in: tuple */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
 | 
						|
/** Print the contents of a tuple.
 | 
						|
@param[out]	o	output stream
 | 
						|
@param[in]	field	array of data fields
 | 
						|
@param[in]	n	number of data fields */
 | 
						|
void
 | 
						|
dfield_print(
 | 
						|
	std::ostream&	o,
 | 
						|
	const dfield_t*	field,
 | 
						|
	ulint		n);
 | 
						|
/** Print the contents of a tuple.
 | 
						|
@param[out]	o	output stream
 | 
						|
@param[in]	tuple	data tuple */
 | 
						|
void
 | 
						|
dtuple_print(
 | 
						|
	std::ostream&	o,
 | 
						|
	const dtuple_t*	tuple);
 | 
						|
 | 
						|
/** Print the contents of a tuple.
 | 
						|
@param[out]	o	output stream
 | 
						|
@param[in]	tuple	data tuple */
 | 
						|
inline
 | 
						|
std::ostream&
 | 
						|
operator<<(std::ostream& o, const dtuple_t& tuple)
 | 
						|
{
 | 
						|
	dtuple_print(o, &tuple);
 | 
						|
	return(o);
 | 
						|
}
 | 
						|
 | 
						|
/**************************************************************//**
 | 
						|
Moves parts of long fields in entry to the big record vector so that
 | 
						|
the size of tuple drops below the maximum record size allowed in the
 | 
						|
database. Moves data only from those fields which are not necessary
 | 
						|
to determine uniquely the insertion place of the tuple in the index.
 | 
						|
@return own: created big record vector, NULL if we are not able to
 | 
						|
shorten the entry enough, i.e., if there are too many fixed-length or
 | 
						|
short fields in entry or the index is clustered */
 | 
						|
big_rec_t*
 | 
						|
dtuple_convert_big_rec(
 | 
						|
/*===================*/
 | 
						|
	dict_index_t*	index,	/*!< in: index */
 | 
						|
	upd_t*		upd,	/*!< in/out: update vector */
 | 
						|
	dtuple_t*	entry,	/*!< in/out: index entry */
 | 
						|
	ulint*		n_ext)	/*!< in/out: number of
 | 
						|
				externally stored columns */
 | 
						|
	MY_ATTRIBUTE((malloc, warn_unused_result));
 | 
						|
/**************************************************************//**
 | 
						|
Puts back to entry the data stored in vector. Note that to ensure the
 | 
						|
fields in entry can accommodate the data, vector must have been created
 | 
						|
from entry with dtuple_convert_big_rec. */
 | 
						|
void
 | 
						|
dtuple_convert_back_big_rec(
 | 
						|
/*========================*/
 | 
						|
	dict_index_t*	index,	/*!< in: index */
 | 
						|
	dtuple_t*	entry,	/*!< in: entry whose data was put to vector */
 | 
						|
	big_rec_t*	vector)	/*!< in, own: big rec vector; it is
 | 
						|
				freed in this function */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
/**************************************************************//**
 | 
						|
Frees the memory in a big rec vector. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
dtuple_big_rec_free(
 | 
						|
/*================*/
 | 
						|
	big_rec_t*	vector)	/*!< in, own: big rec vector; it is
 | 
						|
				freed in this function */
 | 
						|
	MY_ATTRIBUTE((nonnull));
 | 
						|
 | 
						|
/*######################################################################*/
 | 
						|
 | 
						|
/** Structure for an SQL data field */
 | 
						|
struct dfield_t{
 | 
						|
	void*		data;	/*!< pointer to data */
 | 
						|
	unsigned	ext:1;	/*!< TRUE=externally stored, FALSE=local */
 | 
						|
	unsigned	spatial_status:2;
 | 
						|
				/*!< spatial status of externally stored field
 | 
						|
				in undo log for purge */
 | 
						|
	unsigned	len;	/*!< data length; UNIV_SQL_NULL if SQL null */
 | 
						|
	dtype_t		type;	/*!< type of data */
 | 
						|
 | 
						|
	/** Create a deep copy of this object.
 | 
						|
	@param[in,out]	heap	memory heap in which the clone will be created
 | 
						|
	@return	the cloned object */
 | 
						|
	dfield_t* clone(mem_heap_t* heap) const;
 | 
						|
 | 
						|
	/** @return system field indicates history row */
 | 
						|
	bool vers_history_row() const
 | 
						|
	{
 | 
						|
		ut_ad(type.vers_sys_end());
 | 
						|
		if (type.mtype == DATA_FIXBINARY) {
 | 
						|
			ut_ad(len == sizeof timestamp_max_bytes);
 | 
						|
			return !IS_MAX_TIMESTAMP(data);
 | 
						|
		} else {
 | 
						|
			ut_ad(type.mtype == DATA_INT);
 | 
						|
			ut_ad(len == sizeof trx_id_max_bytes);
 | 
						|
			return 0 != memcmp(data, trx_id_max_bytes, len);
 | 
						|
		}
 | 
						|
		ut_ad(0);
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
/** Structure for an SQL data tuple of fields (logical record) */
 | 
						|
struct dtuple_t {
 | 
						|
	byte		info_bits;	/*!< info bits of an index record:
 | 
						|
					the default is 0; this field is used
 | 
						|
					if an index record is built from
 | 
						|
					a data tuple */
 | 
						|
	uint16_t	n_fields;	/*!< number of fields in dtuple */
 | 
						|
	uint16_t	n_fields_cmp;	/*!< number of fields which should
 | 
						|
					be used in comparison services
 | 
						|
					of rem0cmp.*; the index search
 | 
						|
					is performed by comparing only these
 | 
						|
					fields, others are ignored; the
 | 
						|
					default value in dtuple creation is
 | 
						|
					the same value as n_fields */
 | 
						|
	uint16_t	n_v_fields;	/*!< number of virtual fields */
 | 
						|
	dfield_t*	fields;		/*!< fields */
 | 
						|
	dfield_t*	v_fields;	/*!< fields on virtual column */
 | 
						|
#ifdef UNIV_DEBUG
 | 
						|
	ulint		magic_n;	/*!< magic number, used in
 | 
						|
					debug assertions */
 | 
						|
/** Value of dtuple_t::magic_n */
 | 
						|
# define		DATA_TUPLE_MAGIC_N	65478679
 | 
						|
#endif /* UNIV_DEBUG */
 | 
						|
 | 
						|
	/** Trim the tail of an index tuple before insert or update.
 | 
						|
	After instant ADD COLUMN, if the last fields of a clustered index tuple
 | 
						|
	match the default values that were explicitly specified or implied
 | 
						|
	during ADD COLUMN, there will be no need to store them.
 | 
						|
	NOTE: A page latch in the index must be held, so that the index
 | 
						|
	may not lose 'instantness' before the trimmed tuple has been
 | 
						|
	inserted or updated.
 | 
						|
	@param[in]	index	index possibly with instantly added columns */
 | 
						|
	void trim(const dict_index_t& index);
 | 
						|
 | 
						|
	bool vers_history_row() const
 | 
						|
	{
 | 
						|
		for (ulint i = 0; i < n_fields; i++) {
 | 
						|
			const dfield_t* field = &fields[i];
 | 
						|
			if (field->type.vers_sys_end()) {
 | 
						|
				return field->vers_history_row();
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return false;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	@param info_bits	the info_bits of a data tuple
 | 
						|
	@return whether this is a hidden metadata record
 | 
						|
	for instant ADD COLUMN or ALTER TABLE */
 | 
						|
	static bool is_alter_metadata(ulint info_bits)
 | 
						|
	{
 | 
						|
		return UNIV_UNLIKELY(info_bits == REC_INFO_METADATA_ALTER);
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	@param info_bits	the info_bits of a data tuple
 | 
						|
	@return whether this is a hidden metadata record
 | 
						|
	for instant ADD COLUMN or ALTER TABLE */
 | 
						|
	static bool is_metadata(ulint info_bits)
 | 
						|
	{
 | 
						|
		return UNIV_UNLIKELY((info_bits & ~REC_INFO_DELETED_FLAG)
 | 
						|
				     == REC_INFO_METADATA_ADD);
 | 
						|
	}
 | 
						|
 | 
						|
	/** @return whether this is a hidden metadata record
 | 
						|
	for instant ALTER TABLE (not only ADD COLUMN) */
 | 
						|
	bool is_alter_metadata() const { return is_alter_metadata(info_bits); }
 | 
						|
 | 
						|
	/** @return whether this is a hidden metadata record
 | 
						|
	for instant ADD COLUMN or ALTER TABLE */
 | 
						|
	bool is_metadata() const { return is_metadata(info_bits); }
 | 
						|
 | 
						|
	/** Copy type information from index fields.
 | 
						|
	@param index	index field to be copied */
 | 
						|
	inline void copy_field_types(const dict_index_t &index);
 | 
						|
};
 | 
						|
 | 
						|
inline uint16_t dtuple_get_n_fields(const dtuple_t* tuple)
 | 
						|
{ return tuple->n_fields; }
 | 
						|
inline dtype_t* dfield_get_type(dfield_t* field) { return &field->type; }
 | 
						|
inline const dtype_t* dfield_get_type(const dfield_t* field)
 | 
						|
{ return &field->type; }
 | 
						|
inline void* dfield_get_data(dfield_t* field)
 | 
						|
{
 | 
						|
	ut_ad(field->len == UNIV_SQL_NULL || field->data != &data_error);
 | 
						|
	return field->data;
 | 
						|
}
 | 
						|
inline const void* dfield_get_data(const dfield_t* field)
 | 
						|
{
 | 
						|
	ut_ad(field->len == UNIV_SQL_NULL || field->data != &data_error);
 | 
						|
	return field->data;
 | 
						|
}
 | 
						|
inline ulint dfield_get_len(const dfield_t* field) {
 | 
						|
	ut_ad(field->len == UNIV_SQL_NULL || field->data != &data_error);
 | 
						|
	ut_ad(field->len != UNIV_SQL_DEFAULT);
 | 
						|
	return field->len;
 | 
						|
}
 | 
						|
inline bool dfield_is_null(const dfield_t* field)
 | 
						|
{ return field->len == UNIV_SQL_NULL; }
 | 
						|
/** @return whether a column is to be stored off-page */
 | 
						|
inline bool dfield_is_ext(const dfield_t* field)
 | 
						|
{
 | 
						|
	ut_ad(!field->ext || field->len >= BTR_EXTERN_FIELD_REF_SIZE);
 | 
						|
	return static_cast<bool>(field->ext);
 | 
						|
}
 | 
						|
/** Set the "external storage" flag */
 | 
						|
inline void dfield_set_ext(dfield_t* field) { field->ext = 1; }
 | 
						|
 | 
						|
/** Gets number of virtual fields in a data tuple.
 | 
						|
@param[in]	tuple	dtuple to check
 | 
						|
@return number of fields */
 | 
						|
inline uint16_t
 | 
						|
dtuple_get_n_v_fields(const dtuple_t* tuple) { return tuple->n_v_fields; }
 | 
						|
 | 
						|
inline const dfield_t* dtuple_get_nth_field(const dtuple_t* tuple, ulint n)
 | 
						|
{
 | 
						|
	ut_ad(n < tuple->n_fields);
 | 
						|
	return &tuple->fields[n];
 | 
						|
}
 | 
						|
inline dfield_t* dtuple_get_nth_field(dtuple_t* tuple, ulint n)
 | 
						|
{
 | 
						|
	ut_ad(n < tuple->n_fields);
 | 
						|
	return &tuple->fields[n];
 | 
						|
}
 | 
						|
 | 
						|
/** Get a virtual column in a table row or an extended clustered index record.
 | 
						|
@param[in]	tuple	tuple
 | 
						|
@oaran[in]	n	the nth virtual field to get
 | 
						|
@return nth virtual field */
 | 
						|
inline const dfield_t* dtuple_get_nth_v_field(const dtuple_t* tuple, ulint n)
 | 
						|
{
 | 
						|
	ut_ad(n < tuple->n_v_fields);
 | 
						|
	return &tuple->v_fields[n];
 | 
						|
}
 | 
						|
/** Get a virtual column in a table row or an extended clustered index record.
 | 
						|
@param[in]	tuple	tuple
 | 
						|
@oaran[in]	n	the nth virtual field to get
 | 
						|
@return nth virtual field */
 | 
						|
inline dfield_t* dtuple_get_nth_v_field(dtuple_t* tuple, ulint n)
 | 
						|
{
 | 
						|
	ut_ad(n < tuple->n_v_fields);
 | 
						|
	return &tuple->v_fields[n];
 | 
						|
}
 | 
						|
 | 
						|
/** A slot for a field in a big rec vector */
 | 
						|
struct big_rec_field_t {
 | 
						|
 | 
						|
	/** Constructor.
 | 
						|
	@param[in]	field_no_	the field number
 | 
						|
	@param[in]	len_		the data length
 | 
						|
	@param[in]	data_		the data */
 | 
						|
	big_rec_field_t(ulint field_no_, ulint len_, const void* data_)
 | 
						|
		: field_no(field_no_),
 | 
						|
		  len(len_),
 | 
						|
		  data(data_)
 | 
						|
	{}
 | 
						|
 | 
						|
	ulint		field_no;	/*!< field number in record */
 | 
						|
	ulint		len;		/*!< stored data length, in bytes */
 | 
						|
	const void*	data;		/*!< stored data */
 | 
						|
};
 | 
						|
 | 
						|
/** Storage format for overflow data in a big record, that is, a
 | 
						|
clustered index record which needs external storage of data fields */
 | 
						|
struct big_rec_t {
 | 
						|
	mem_heap_t*	heap;		/*!< memory heap from which
 | 
						|
					allocated */
 | 
						|
	const ulint	capacity;	/*!< fields array size */
 | 
						|
	ulint		n_fields;	/*!< number of stored fields */
 | 
						|
	big_rec_field_t*fields;		/*!< stored fields */
 | 
						|
 | 
						|
	/** Constructor.
 | 
						|
	@param[in]	max	the capacity of the array of fields. */
 | 
						|
	explicit big_rec_t(const ulint max)
 | 
						|
		: heap(0),
 | 
						|
		  capacity(max),
 | 
						|
		  n_fields(0),
 | 
						|
		  fields(0)
 | 
						|
	{}
 | 
						|
 | 
						|
	/** Append one big_rec_field_t object to the end of array of fields */
 | 
						|
	void append(const big_rec_field_t& field)
 | 
						|
	{
 | 
						|
		ut_ad(n_fields < capacity);
 | 
						|
		fields[n_fields] = field;
 | 
						|
		n_fields++;
 | 
						|
	}
 | 
						|
 | 
						|
	/** Allocate a big_rec_t object in the given memory heap, and for
 | 
						|
	storing n_fld number of fields.
 | 
						|
	@param[in]	heap	memory heap in which this object is allocated
 | 
						|
	@param[in]	n_fld	maximum number of fields that can be stored in
 | 
						|
			this object
 | 
						|
	@return the allocated object */
 | 
						|
	static big_rec_t* alloc(
 | 
						|
		mem_heap_t*	heap,
 | 
						|
		ulint		n_fld);
 | 
						|
};
 | 
						|
 | 
						|
#include "data0data.inl"
 | 
						|
 | 
						|
#endif
 |