mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-03 20:36:16 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			850 lines
		
	
	
	
		
			31 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			850 lines
		
	
	
	
		
			31 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*****************************************************************************
 | 
						|
 | 
						|
Copyright (c) 2000, 2017, 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/row0mysql.h
 | 
						|
Interface between Innobase row operations and MySQL.
 | 
						|
Contains also create table and other data dictionary operations.
 | 
						|
 | 
						|
Created 9/17/2000 Heikki Tuuri
 | 
						|
*******************************************************/
 | 
						|
 | 
						|
#ifndef row0mysql_h
 | 
						|
#define row0mysql_h
 | 
						|
 | 
						|
#include "que0types.h"
 | 
						|
#include "trx0types.h"
 | 
						|
#include "row0types.h"
 | 
						|
#include "btr0types.h"
 | 
						|
#include "lock0types.h"
 | 
						|
#include "fil0fil.h"
 | 
						|
#include "fts0fts.h"
 | 
						|
#include "gis0type.h"
 | 
						|
 | 
						|
struct row_prebuilt_t;
 | 
						|
class ha_innobase;
 | 
						|
class ha_handler_stats;
 | 
						|
 | 
						|
/*******************************************************************//**
 | 
						|
Frees the blob heap in prebuilt when no longer needed. */
 | 
						|
void
 | 
						|
row_mysql_prebuilt_free_blob_heap(
 | 
						|
/*==============================*/
 | 
						|
	row_prebuilt_t*	prebuilt);	/*!< in: prebuilt struct of a
 | 
						|
					ha_innobase:: table handle */
 | 
						|
/*******************************************************************//**
 | 
						|
Stores a >= 5.0.3 format true VARCHAR length to dest, in the MySQL row
 | 
						|
format.
 | 
						|
@return pointer to the data, we skip the 1 or 2 bytes at the start
 | 
						|
that are used to store the len */
 | 
						|
byte*
 | 
						|
row_mysql_store_true_var_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 */
 | 
						|
/*******************************************************************//**
 | 
						|
Reads a >= 5.0.3 format true VARCHAR length, in the MySQL row format, and
 | 
						|
returns a pointer to the data.
 | 
						|
@return pointer to the data, we skip the 1 or 2 bytes at the start
 | 
						|
that are used to store the len */
 | 
						|
const byte*
 | 
						|
row_mysql_read_true_varchar(
 | 
						|
/*========================*/
 | 
						|
	ulint*		len,	/*!< out: variable-length field length */
 | 
						|
	const byte*	field,	/*!< in: field in the MySQL format */
 | 
						|
	ulint		lenlen);/*!< in: storage length of len: either 1
 | 
						|
				or 2 bytes */
 | 
						|
/*******************************************************************//**
 | 
						|
Stores a reference to a BLOB in the MySQL format. */
 | 
						|
void
 | 
						|
row_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 */
 | 
						|
	const void*	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! */
 | 
						|
/*******************************************************************//**
 | 
						|
Reads a reference to a BLOB in the MySQL format.
 | 
						|
@return pointer to BLOB data */
 | 
						|
const byte*
 | 
						|
row_mysql_read_blob_ref(
 | 
						|
/*====================*/
 | 
						|
	ulint*		len,		/*!< out: BLOB length */
 | 
						|
	const byte*	ref,		/*!< in: BLOB reference in the
 | 
						|
					MySQL format */
 | 
						|
	ulint		col_len);	/*!< in: BLOB reference length
 | 
						|
					(not BLOB length) */
 | 
						|
/*******************************************************************//**
 | 
						|
Converts InnoDB geometry data format to MySQL data format. */
 | 
						|
void
 | 
						|
row_mysql_store_geometry(
 | 
						|
/*=====================*/
 | 
						|
	byte*		dest,		/*!< in/out: where to store */
 | 
						|
	ulint		dest_len,	/*!< in: dest buffer size: determines into
 | 
						|
					how many bytes the geometry length is stored,
 | 
						|
					the space for the length may vary from 1
 | 
						|
					to 4 bytes */
 | 
						|
	const byte*	src,		/*!< in: geometry data; if the value to store
 | 
						|
					is SQL NULL this should be NULL pointer */
 | 
						|
	ulint		src_len);	/*!< in: geometry 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! */
 | 
						|
/**************************************************************//**
 | 
						|
Pad a column with spaces. */
 | 
						|
void
 | 
						|
row_mysql_pad_col(
 | 
						|
/*==============*/
 | 
						|
	ulint	mbminlen,	/*!< in: minimum size of a character,
 | 
						|
				in bytes */
 | 
						|
	byte*	pad,		/*!< out: padded buffer */
 | 
						|
	ulint	len);		/*!< in: number of bytes to pad */
 | 
						|
 | 
						|
/**************************************************************//**
 | 
						|
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() in
 | 
						|
row0sel.cc.
 | 
						|
@return up to which byte we used buf in the conversion */
 | 
						|
byte*
 | 
						|
row_mysql_store_col_in_innobase_format(
 | 
						|
/*===================================*/
 | 
						|
	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! NOTE that dfield
 | 
						|
					may also get a pointer to 'buf',
 | 
						|
					therefore do not discard this as long
 | 
						|
					as dfield is used! */
 | 
						|
	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! */
 | 
						|
	const 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 */
 | 
						|
/****************************************************************//**
 | 
						|
Handles user errors and lock waits detected by the database engine.
 | 
						|
@return true if it was a lock wait and we should continue running the
 | 
						|
query thread */
 | 
						|
bool
 | 
						|
row_mysql_handle_errors(
 | 
						|
/*====================*/
 | 
						|
	dberr_t*	new_err,/*!< out: possible new error encountered in
 | 
						|
				rollback, or the old error which was
 | 
						|
				during the function entry */
 | 
						|
	trx_t*		trx,	/*!< in: transaction */
 | 
						|
	que_thr_t*	thr,	/*!< in: query thread, or NULL */
 | 
						|
	const undo_no_t*savept)	/*!< in: pointer to savepoint, or nullptr */
 | 
						|
	MY_ATTRIBUTE((nonnull(1,2)));
 | 
						|
/********************************************************************//**
 | 
						|
Create a prebuilt struct for a MySQL table handle.
 | 
						|
@return own: a prebuilt struct */
 | 
						|
row_prebuilt_t*
 | 
						|
row_create_prebuilt(
 | 
						|
/*================*/
 | 
						|
	dict_table_t*	table,		/*!< in: Innobase table handle */
 | 
						|
	ulint		mysql_row_len);	/*!< in: length in bytes of a row in
 | 
						|
					the MySQL format */
 | 
						|
/** Free a prebuilt struct for a TABLE handle. */
 | 
						|
void row_prebuilt_free(row_prebuilt_t *prebuilt);
 | 
						|
/*********************************************************************//**
 | 
						|
Updates the transaction pointers in query graphs stored in the prebuilt
 | 
						|
struct. */
 | 
						|
void
 | 
						|
row_update_prebuilt_trx(
 | 
						|
/*====================*/
 | 
						|
	row_prebuilt_t*	prebuilt,	/*!< in/out: prebuilt struct
 | 
						|
					in MySQL handle */
 | 
						|
	trx_t*		trx);		/*!< in: transaction handle */
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Sets an AUTO_INC type lock on the table mentioned in prebuilt. The
 | 
						|
AUTO_INC lock gives exclusive access to the auto-inc counter of the
 | 
						|
table. The lock is reserved only for the duration of an SQL statement.
 | 
						|
It is not compatible with another AUTO_INC or exclusive lock on the
 | 
						|
table.
 | 
						|
@return error code or DB_SUCCESS */
 | 
						|
dberr_t
 | 
						|
row_lock_table_autoinc_for_mysql(
 | 
						|
/*=============================*/
 | 
						|
	row_prebuilt_t*	prebuilt)	/*!< in: prebuilt struct in the MySQL
 | 
						|
					table handle */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
 | 
						|
/** Lock a table.
 | 
						|
@param[in,out]	prebuilt	table handle
 | 
						|
@return error code or DB_SUCCESS */
 | 
						|
dberr_t
 | 
						|
row_lock_table(row_prebuilt_t* prebuilt);
 | 
						|
 | 
						|
/** System Versioning: row_insert_for_mysql() modes */
 | 
						|
enum ins_mode_t {
 | 
						|
	/* plain row (without versioning) */
 | 
						|
	ROW_INS_NORMAL = 0,
 | 
						|
	/* row_start = TRX_ID, row_end = MAX */
 | 
						|
	ROW_INS_VERSIONED,
 | 
						|
	/* row_end = TRX_ID */
 | 
						|
	ROW_INS_HISTORICAL
 | 
						|
};
 | 
						|
 | 
						|
/** Does an insert for MySQL.
 | 
						|
@param[in]	mysql_rec	row in the MySQL format
 | 
						|
@param[in,out]	prebuilt	prebuilt struct in MySQL handle
 | 
						|
@param[in]	ins_mode	what row type we're inserting
 | 
						|
@return error code or DB_SUCCESS*/
 | 
						|
dberr_t
 | 
						|
row_insert_for_mysql(
 | 
						|
	const byte*		mysql_rec,
 | 
						|
	row_prebuilt_t*		prebuilt,
 | 
						|
	ins_mode_t		ins_mode)
 | 
						|
	MY_ATTRIBUTE((warn_unused_result));
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Builds a dummy query graph used in selects. */
 | 
						|
void
 | 
						|
row_prebuild_sel_graph(
 | 
						|
/*===================*/
 | 
						|
	row_prebuilt_t*	prebuilt);	/*!< in: prebuilt struct in MySQL
 | 
						|
					handle */
 | 
						|
/*********************************************************************//**
 | 
						|
Gets pointer to a prebuilt update vector used in updates. If the update
 | 
						|
graph has not yet been built in the prebuilt struct, then this function
 | 
						|
first builds it.
 | 
						|
@return prebuilt update vector */
 | 
						|
upd_t*
 | 
						|
row_get_prebuilt_update_vector(
 | 
						|
/*===========================*/
 | 
						|
	row_prebuilt_t*	prebuilt);	/*!< in: prebuilt struct in MySQL
 | 
						|
					handle */
 | 
						|
/** Does an update or delete of a row for MySQL.
 | 
						|
@param[in,out]	prebuilt	prebuilt struct in MySQL handle
 | 
						|
@return error code or DB_SUCCESS */
 | 
						|
dberr_t
 | 
						|
row_update_for_mysql(
 | 
						|
	row_prebuilt_t*		prebuilt)
 | 
						|
	MY_ATTRIBUTE((warn_unused_result));
 | 
						|
 | 
						|
/** This can only be used when the current transaction is at
 | 
						|
READ COMMITTED or READ UNCOMMITTED isolation level.
 | 
						|
Before calling this function row_search_mvcc() must have
 | 
						|
initialized prebuilt->new_rec_locks to store the information which new
 | 
						|
record locks really were set. This function removes a newly set
 | 
						|
clustered index record lock under prebuilt->pcur or
 | 
						|
prebuilt->clust_pcur.  Thus, this implements a 'mini-rollback' that
 | 
						|
releases the latest clustered index record lock we set.
 | 
						|
@param[in,out]	prebuilt		prebuilt struct in MySQL handle
 | 
						|
@param[in]	has_latches_on_recs	TRUE if called so that we have the
 | 
						|
					latches on the records under pcur
 | 
						|
					and clust_pcur, and we do not need
 | 
						|
					to reposition the cursors. */
 | 
						|
void
 | 
						|
row_unlock_for_mysql(
 | 
						|
	row_prebuilt_t*	prebuilt,
 | 
						|
	ibool		has_latches_on_recs);
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Creates an query graph node of 'update' type to be used in the MySQL
 | 
						|
interface.
 | 
						|
@return own: update node */
 | 
						|
upd_node_t*
 | 
						|
row_create_update_node_for_mysql(
 | 
						|
/*=============================*/
 | 
						|
	dict_table_t*	table,	/*!< in: table to update */
 | 
						|
	mem_heap_t*	heap);	/*!< in: mem heap from which allocated */
 | 
						|
 | 
						|
/**********************************************************************//**
 | 
						|
Does a cascaded delete or set null in a foreign key operation.
 | 
						|
@return error code or DB_SUCCESS */
 | 
						|
dberr_t
 | 
						|
row_update_cascade_for_mysql(
 | 
						|
/*=========================*/
 | 
						|
        que_thr_t*      thr,    /*!< in: query thread */
 | 
						|
        upd_node_t*     node,   /*!< in: update node used in the cascade
 | 
						|
                                or set null operation */
 | 
						|
        dict_table_t*   table)  /*!< in: table where we do the operation */
 | 
						|
        MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
 | 
						|
/** Lock the data dictionary cache exclusively. */
 | 
						|
#define row_mysql_lock_data_dictionary(trx)			\
 | 
						|
	do {							\
 | 
						|
		ut_ad(!trx->dict_operation_lock_mode);		\
 | 
						|
		dict_sys.lock(SRW_LOCK_CALL);			\
 | 
						|
		trx->dict_operation_lock_mode = true;		\
 | 
						|
	} while (0)
 | 
						|
 | 
						|
/** Unlock the data dictionary. */
 | 
						|
#define row_mysql_unlock_data_dictionary(trx)			\
 | 
						|
	do {							\
 | 
						|
		ut_ad(!lock_trx_has_sys_table_locks(trx));	\
 | 
						|
		ut_ad(trx->dict_operation_lock_mode);		\
 | 
						|
		trx->dict_operation_lock_mode = false;		\
 | 
						|
		dict_sys.unlock();				\
 | 
						|
	} while (0)
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Creates a table for MySQL. On failure the transaction will be rolled back
 | 
						|
and the 'table' object will be freed.
 | 
						|
@return error code or DB_SUCCESS */
 | 
						|
dberr_t
 | 
						|
row_create_table_for_mysql(
 | 
						|
/*=======================*/
 | 
						|
	dict_table_t*	table,	/*!< in, own: table definition
 | 
						|
				(will be freed, or on DB_SUCCESS
 | 
						|
				added to the data dictionary cache) */
 | 
						|
	trx_t*		trx)	/*!< in/out: transaction */
 | 
						|
	MY_ATTRIBUTE((warn_unused_result));
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Create an index when creating a table.
 | 
						|
On failure, the caller must drop the table!
 | 
						|
@return error number or DB_SUCCESS */
 | 
						|
dberr_t
 | 
						|
row_create_index_for_mysql(
 | 
						|
/*=======================*/
 | 
						|
	dict_index_t*	index,		/*!< in, own: index definition
 | 
						|
					(will be freed) */
 | 
						|
	trx_t*		trx,		/*!< in: transaction handle */
 | 
						|
	const ulint*	field_lengths,	/*!< in: if not NULL, must contain
 | 
						|
					dict_index_get_n_fields(index)
 | 
						|
					actual field lengths for the
 | 
						|
					index columns, which are
 | 
						|
					then checked for not being too
 | 
						|
					large. */
 | 
						|
	fil_encryption_t mode,	/*!< in: encryption mode */
 | 
						|
	uint32_t	key_id)	/*!< in: encryption key_id */
 | 
						|
	MY_ATTRIBUTE((warn_unused_result));
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Discards the tablespace of a table which stored in an .ibd file. Discarding
 | 
						|
means that this function deletes the .ibd file and assigns a new table id for
 | 
						|
the table. Also the file_unreadable flag is set.
 | 
						|
@return error code or DB_SUCCESS */
 | 
						|
dberr_t row_discard_tablespace_for_mysql(dict_table_t *table, trx_t *trx)
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
/*****************************************************************//**
 | 
						|
Imports a tablespace. The space id in the .ibd file must match the space id
 | 
						|
of the table in the data dictionary.
 | 
						|
@return error code or DB_SUCCESS */
 | 
						|
dberr_t
 | 
						|
row_import_tablespace_for_mysql(
 | 
						|
/*============================*/
 | 
						|
	dict_table_t*	table,		/*!< in/out: table */
 | 
						|
	row_prebuilt_t*	prebuilt)	/*!< in: prebuilt struct in MySQL */
 | 
						|
        MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
 | 
						|
enum rename_fk {
 | 
						|
  /** ignore FOREIGN KEY constraints */
 | 
						|
  RENAME_IGNORE_FK= 0,
 | 
						|
  /** Rename a table as part of a native table-rebuilding DDL operation */
 | 
						|
  RENAME_REBUILD,
 | 
						|
  /** Rename as part of ALTER TABLE...ALGORITHM=COPY */
 | 
						|
  RENAME_ALTER_COPY
 | 
						|
};
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Renames a table for MySQL.
 | 
						|
@return error code or DB_SUCCESS */
 | 
						|
dberr_t
 | 
						|
row_rename_table_for_mysql(
 | 
						|
/*=======================*/
 | 
						|
	const char*	old_name,	/*!< in: old table name */
 | 
						|
	const char*	new_name,	/*!< in: new table name */
 | 
						|
	trx_t*		trx,		/*!< in/out: transaction */
 | 
						|
	rename_fk	fk)		/*!< in: how to handle
 | 
						|
					FOREIGN KEY constraints */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
 | 
						|
/* A struct describing a place for an individual column in the MySQL
 | 
						|
row format which is presented to the table handler in ha_innobase.
 | 
						|
This template struct is used to speed up row transformations between
 | 
						|
Innobase and MySQL. */
 | 
						|
 | 
						|
struct mysql_row_templ_t {
 | 
						|
	ulint	col_no;			/*!< column number of the column */
 | 
						|
	ulint	rec_field_no;		/*!< field number of the column in an
 | 
						|
					Innobase record in the current index;
 | 
						|
					not defined if template_type is
 | 
						|
					ROW_MYSQL_WHOLE_ROW */
 | 
						|
	ibool	rec_field_is_prefix;	/* is this field in a prefix index? */
 | 
						|
	ulint	rec_prefix_field_no;	/* record field, even if just a
 | 
						|
					prefix; same as rec_field_no when not a
 | 
						|
					prefix, otherwise rec_field_no is
 | 
						|
					ULINT_UNDEFINED but this is the true
 | 
						|
					field number*/
 | 
						|
	ulint	clust_rec_field_no;	/*!< field number of the column in an
 | 
						|
					Innobase record in the clustered index;
 | 
						|
					not defined if template_type is
 | 
						|
					ROW_MYSQL_WHOLE_ROW */
 | 
						|
	ulint	icp_rec_field_no;	/*!< field number of the column in an
 | 
						|
					Innobase record in the current index;
 | 
						|
					not defined unless
 | 
						|
					index condition pushdown is used */
 | 
						|
	ulint	mysql_col_offset;	/*!< offset of the column in the MySQL
 | 
						|
					row format */
 | 
						|
	ulint	mysql_col_len;		/*!< length of the column in the MySQL
 | 
						|
					row format */
 | 
						|
	ulint	mysql_null_byte_offset;	/*!< MySQL NULL bit byte offset in a
 | 
						|
					MySQL record */
 | 
						|
	ulint	mysql_null_bit_mask;	/*!< bit mask to get the NULL bit,
 | 
						|
					zero if column cannot be NULL */
 | 
						|
	ulint	type;			/*!< column type in Innobase mtype
 | 
						|
					numbers DATA_CHAR... */
 | 
						|
	ulint	mysql_type;		/*!< MySQL type code; this is always
 | 
						|
					< 256 */
 | 
						|
	ulint	mysql_length_bytes;	/*!< if mysql_type
 | 
						|
					== DATA_MYSQL_TRUE_VARCHAR, this tells
 | 
						|
					whether we should use 1 or 2 bytes to
 | 
						|
					store the MySQL true VARCHAR data
 | 
						|
					length at the start of row in the MySQL
 | 
						|
					format (NOTE that the MySQL key value
 | 
						|
					format always uses 2 bytes for the data
 | 
						|
					len) */
 | 
						|
	ulint	charset;		/*!< MySQL charset-collation code
 | 
						|
					of the column, or zero */
 | 
						|
	ulint	mbminlen;		/*!< minimum length of a char, in bytes,
 | 
						|
					or zero if not a char type */
 | 
						|
	ulint	mbmaxlen;		/*!< maximum length of a char, in bytes,
 | 
						|
					or zero if not a char type */
 | 
						|
	ulint	is_unsigned;		/*!< if a column type is an integer
 | 
						|
					type and this field is != 0, then
 | 
						|
					it is an unsigned integer type */
 | 
						|
	ulint	is_virtual;		/*!< if a column is a virtual column */
 | 
						|
};
 | 
						|
 | 
						|
#define MYSQL_FETCH_CACHE_SIZE		8
 | 
						|
/* After fetching this many rows, we start caching them in fetch_cache */
 | 
						|
#define MYSQL_FETCH_CACHE_THRESHOLD	4
 | 
						|
 | 
						|
#define ROW_PREBUILT_ALLOCATED	78540783
 | 
						|
#define ROW_PREBUILT_FREED	26423527
 | 
						|
 | 
						|
/** A struct for (sometimes lazily) prebuilt structures in an Innobase table
 | 
						|
handle used within MySQL; these are used to save CPU time. */
 | 
						|
 | 
						|
struct row_prebuilt_t {
 | 
						|
	ulint		magic_n;	/*!< this magic number is set to
 | 
						|
					ROW_PREBUILT_ALLOCATED when created,
 | 
						|
					or ROW_PREBUILT_FREED when the
 | 
						|
					struct has been freed */
 | 
						|
	dict_table_t*	table;		/*!< Innobase table handle */
 | 
						|
	dict_index_t*	index;		/*!< current index for a search, if
 | 
						|
					any */
 | 
						|
	trx_t*		trx;		/*!< current transaction handle */
 | 
						|
	unsigned	sql_stat_start:1;/*!< TRUE when we start processing of
 | 
						|
					an SQL statement: we may have to set
 | 
						|
					an intention lock on the table,
 | 
						|
					create a consistent read view etc. */
 | 
						|
	unsigned	clust_index_was_generated:1;
 | 
						|
					/*!< if the user did not define a
 | 
						|
					primary key in MySQL, then Innobase
 | 
						|
					automatically generated a clustered
 | 
						|
					index where the ordering column is
 | 
						|
					the row id: in this case this flag
 | 
						|
					is set to TRUE */
 | 
						|
	unsigned	index_usable:1;	/*!< caches the value of
 | 
						|
					row_merge_is_index_usable(trx,index) */
 | 
						|
	unsigned	read_just_key:1;/*!< set to 1 when MySQL calls
 | 
						|
					ha_innobase::extra with the
 | 
						|
					argument HA_EXTRA_KEYREAD; it is enough
 | 
						|
					to read just columns defined in
 | 
						|
					the index (i.e., no read of the
 | 
						|
					clustered index record necessary) */
 | 
						|
	unsigned	used_in_HANDLER:1;/*!< TRUE if we have been using this
 | 
						|
					handle in a MySQL HANDLER low level
 | 
						|
					index cursor command: then we must
 | 
						|
					store the pcur position even in a
 | 
						|
					unique search from a clustered index,
 | 
						|
					because HANDLER allows NEXT and PREV
 | 
						|
					in such a situation */
 | 
						|
	unsigned	template_type:2;/*!< ROW_MYSQL_WHOLE_ROW,
 | 
						|
					ROW_MYSQL_REC_FIELDS,
 | 
						|
					ROW_MYSQL_DUMMY_TEMPLATE, or
 | 
						|
					ROW_MYSQL_NO_TEMPLATE */
 | 
						|
	unsigned	n_template:10;	/*!< number of elements in the
 | 
						|
					template */
 | 
						|
	unsigned	null_bitmap_len:10;/*!< number of bytes in the SQL NULL
 | 
						|
					bitmap at the start of a row in the
 | 
						|
					MySQL format */
 | 
						|
	unsigned	need_to_access_clustered:1; /*!< if we are fetching
 | 
						|
					columns through a secondary index
 | 
						|
					and at least one column is not in
 | 
						|
					the secondary index, then this is
 | 
						|
					set to TRUE; note that sometimes this
 | 
						|
					is set but we later optimize out the
 | 
						|
					clustered index lookup */
 | 
						|
	unsigned	templ_contains_blob:1;/*!< TRUE if the template contains
 | 
						|
					a column with DATA_LARGE_MTYPE(
 | 
						|
					get_innobase_type_from_mysql_type())
 | 
						|
					is TRUE;
 | 
						|
					not to be confused with InnoDB
 | 
						|
					externally stored columns
 | 
						|
					(VARCHAR can be off-page too) */
 | 
						|
	unsigned	versioned_write:1;/*!< whether this is
 | 
						|
					a versioned write */
 | 
						|
	mysql_row_templ_t* mysql_template;/*!< template used to transform
 | 
						|
					rows fast between MySQL and Innobase
 | 
						|
					formats; memory for this template
 | 
						|
					is not allocated from 'heap' */
 | 
						|
	mem_heap_t*	heap;		/*!< memory heap from which
 | 
						|
					these auxiliary structures are
 | 
						|
					allocated when needed */
 | 
						|
	ins_node_t*	ins_node;	/*!< Innobase SQL insert node
 | 
						|
					used to perform inserts
 | 
						|
					to the table */
 | 
						|
	byte*		ins_upd_rec_buff;/*!< buffer for storing data converted
 | 
						|
					to the Innobase format from the MySQL
 | 
						|
					format */
 | 
						|
	const byte*	default_rec;	/*!< the default values of all columns
 | 
						|
					(a "default row") in MySQL format */
 | 
						|
	ulint		hint_need_to_fetch_extra_cols;
 | 
						|
					/*!< normally this is set to 0; if this
 | 
						|
					is set to ROW_RETRIEVE_PRIMARY_KEY,
 | 
						|
					then we should at least retrieve all
 | 
						|
					columns in the primary key; if this
 | 
						|
					is set to ROW_RETRIEVE_ALL_COLS, then
 | 
						|
					we must retrieve all columns in the
 | 
						|
					key (if read_just_key == 1), or all
 | 
						|
					columns in the table */
 | 
						|
	upd_node_t*	upd_node;	/*!< Innobase SQL update node used
 | 
						|
					to perform updates and deletes */
 | 
						|
	trx_id_t	trx_id;		/*!< The table->def_trx_id when
 | 
						|
					ins_graph was built */
 | 
						|
	que_fork_t*	ins_graph;	/*!< Innobase SQL query graph used
 | 
						|
					in inserts. Will be rebuilt on
 | 
						|
					trx_id or n_indexes mismatch. */
 | 
						|
	que_fork_t*	upd_graph;	/*!< Innobase SQL query graph used
 | 
						|
					in updates or deletes */
 | 
						|
	btr_pcur_t*	pcur;		/*!< persistent cursor used in selects
 | 
						|
					and updates */
 | 
						|
	btr_pcur_t*	clust_pcur;	/*!< persistent cursor used in
 | 
						|
					some selects and updates */
 | 
						|
	que_fork_t*	sel_graph;	/*!< dummy query graph used in
 | 
						|
					selects */
 | 
						|
	dtuple_t*	search_tuple;	/*!< prebuilt dtuple used in selects */
 | 
						|
	byte		row_id[DATA_ROW_ID_LEN];
 | 
						|
					/*!< if the clustered index was
 | 
						|
					generated, the row id of the
 | 
						|
					last row fetched is stored
 | 
						|
					here */
 | 
						|
	doc_id_t	fts_doc_id;	/* if the table has an FTS index on
 | 
						|
					it then we fetch the doc_id.
 | 
						|
					FTS-FIXME: Currently we fetch it always
 | 
						|
					but in the future we must only fetch
 | 
						|
					it when FTS columns are being
 | 
						|
					updated */
 | 
						|
	dtuple_t*	clust_ref;	/*!< prebuilt dtuple used in
 | 
						|
					sel/upd/del */
 | 
						|
	lock_mode	select_lock_type;/*!< LOCK_NONE, LOCK_S, or LOCK_X */
 | 
						|
	bool		skip_locked;	/*!< TL_{READ,WRITE}_SKIP_LOCKED */
 | 
						|
	lock_mode	stored_select_lock_type;/*!< this field is used to
 | 
						|
					remember the original select_lock_type
 | 
						|
					that was decided in ha_innodb.cc,
 | 
						|
					::store_lock(), ::external_lock(),
 | 
						|
					etc. */
 | 
						|
	ulint		row_read_type;	/*!< ROW_READ_WITH_LOCKS if row locks
 | 
						|
					should be the obtained for records
 | 
						|
					under an UPDATE or DELETE cursor.
 | 
						|
					At READ UNCOMMITTED or
 | 
						|
					READ COMMITTED isolation level,
 | 
						|
					this can be set to
 | 
						|
					ROW_READ_TRY_SEMI_CONSISTENT, so that
 | 
						|
					if the row under an UPDATE or DELETE
 | 
						|
					cursor was locked by another
 | 
						|
					transaction, InnoDB will resort
 | 
						|
					to reading the last committed value
 | 
						|
					('semi-consistent read').  Then,
 | 
						|
					this field will be set to
 | 
						|
					ROW_READ_DID_SEMI_CONSISTENT to
 | 
						|
					indicate that.	If the row does not
 | 
						|
					match the WHERE condition, MySQL will
 | 
						|
					invoke handler::unlock_row() to
 | 
						|
					clear the flag back to
 | 
						|
					ROW_READ_TRY_SEMI_CONSISTENT and
 | 
						|
					to simply skip the row.	 If
 | 
						|
					the row matches, the next call to
 | 
						|
					row_search_mvcc() will lock
 | 
						|
					the row.
 | 
						|
					This eliminates lock waits in some
 | 
						|
					cases; note that this breaks
 | 
						|
					serializability. */
 | 
						|
	ulint		new_rec_locks;	/*!< normally 0; if
 | 
						|
					the session is using READ
 | 
						|
					COMMITTED or READ UNCOMMITTED
 | 
						|
					isolation level, set in
 | 
						|
					row_search_mvcc() if we set a new
 | 
						|
					record lock on the secondary
 | 
						|
					or clustered index; this is
 | 
						|
					used in row_unlock_for_mysql()
 | 
						|
					when releasing the lock under
 | 
						|
					the cursor if we determine
 | 
						|
					after retrieving the row that
 | 
						|
					it does not need to be locked
 | 
						|
					('mini-rollback') */
 | 
						|
	ulint		mysql_prefix_len;/*!< byte offset of the end of
 | 
						|
					the last requested column */
 | 
						|
	ulint		mysql_row_len;	/*!< length in bytes of a row in the
 | 
						|
					MySQL format */
 | 
						|
	ulint		n_rows_fetched;	/*!< number of rows fetched after
 | 
						|
					positioning the current cursor */
 | 
						|
	ulint		fetch_direction;/*!< ROW_SEL_NEXT or ROW_SEL_PREV */
 | 
						|
	byte*		fetch_cache[MYSQL_FETCH_CACHE_SIZE];
 | 
						|
					/*!< a cache for fetched rows if we
 | 
						|
					fetch many rows from the same cursor:
 | 
						|
					it saves CPU time to fetch them in a
 | 
						|
					batch; we reserve mysql_row_len
 | 
						|
					bytes for each such row; these
 | 
						|
					pointers point 4 bytes past the
 | 
						|
					allocated mem buf start, because
 | 
						|
					there is a 4 byte magic number at the
 | 
						|
					start and at the end */
 | 
						|
	bool		keep_other_fields_on_keyread; /*!< when using fetch
 | 
						|
					cache with HA_EXTRA_KEYREAD, don't
 | 
						|
					overwrite other fields in mysql row
 | 
						|
					row buffer.*/
 | 
						|
	ulint		fetch_cache_first;/*!< position of the first not yet
 | 
						|
					fetched row in fetch_cache */
 | 
						|
	ulint		n_fetch_cached;	/*!< number of not yet fetched rows
 | 
						|
					in fetch_cache */
 | 
						|
	mem_heap_t*	blob_heap;	/*!< in SELECTS BLOB fields are copied
 | 
						|
					to this heap */
 | 
						|
	mem_heap_t*	old_vers_heap;	/*!< memory heap where a previous
 | 
						|
					version is built in consistent read */
 | 
						|
	bool		in_fts_query;	/*!< Whether we are in a FTS query */
 | 
						|
	bool		fts_doc_id_in_read_set; /*!< true if table has externally
 | 
						|
					defined FTS_DOC_ID column. */
 | 
						|
	/*----------------------*/
 | 
						|
	ulonglong	autoinc_last_value;
 | 
						|
					/*!< last value of AUTO-INC interval */
 | 
						|
	ulonglong	autoinc_increment;/*!< The increment step of the auto
 | 
						|
					increment column. Value must be
 | 
						|
					greater than or equal to 1. Required to
 | 
						|
					calculate the next value */
 | 
						|
	ulonglong	autoinc_offset; /*!< The offset passed to
 | 
						|
					get_auto_increment() by MySQL. Required
 | 
						|
					to calculate the next value */
 | 
						|
	dberr_t		autoinc_error;	/*!< The actual error code encountered
 | 
						|
					while trying to init or read the
 | 
						|
					autoinc value from the table. We
 | 
						|
					store it here so that we can return
 | 
						|
					it to MySQL */
 | 
						|
	/*----------------------*/
 | 
						|
 | 
						|
	/** Argument of handler_rowid_filter_check(),
 | 
						|
	or NULL if no PRIMARY KEY filter is pushed */
 | 
						|
	ha_innobase*	pk_filter;
 | 
						|
 | 
						|
	/** Argument to handler_index_cond_check(),
 | 
						|
	or NULL if no index condition pushdown (ICP) is used. */
 | 
						|
	ha_innobase*	idx_cond;
 | 
						|
	ulint		idx_cond_n_cols;/*!< Number of fields in idx_cond_cols.
 | 
						|
					0 if and only if idx_cond == NULL. */
 | 
						|
	/*----------------------*/
 | 
						|
 | 
						|
	/*----------------------*/
 | 
						|
	rtr_info_t*	rtr_info;	/*!< R-tree Search Info */
 | 
						|
	/*----------------------*/
 | 
						|
 | 
						|
	ulint		magic_n2;	/*!< this should be the same as
 | 
						|
					magic_n */
 | 
						|
 | 
						|
	byte*		srch_key_val1;  /*!< buffer used in converting
 | 
						|
					search key values from MySQL format
 | 
						|
					to InnoDB format.*/
 | 
						|
	byte*		srch_key_val2;  /*!< buffer used in converting
 | 
						|
					search key values from MySQL format
 | 
						|
					to InnoDB format.*/
 | 
						|
	uint		srch_key_val_len; /*!< Size of search key */
 | 
						|
	/** The MySQL table object */
 | 
						|
	TABLE*		m_mysql_table;
 | 
						|
 | 
						|
	/** Get template by dict_table_t::cols[] number */
 | 
						|
	const mysql_row_templ_t* get_template_by_col(ulint col) const
 | 
						|
	{
 | 
						|
		ut_ad(col < n_template);
 | 
						|
		ut_ad(mysql_template);
 | 
						|
		for (ulint i = col; i < n_template; ++i) {
 | 
						|
			const mysql_row_templ_t* templ = &mysql_template[i];
 | 
						|
			if (!templ->is_virtual && templ->col_no == col) {
 | 
						|
				return templ;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
/** Callback for row_mysql_sys_index_iterate() */
 | 
						|
struct SysIndexCallback {
 | 
						|
	virtual ~SysIndexCallback() = default;
 | 
						|
 | 
						|
	/** Callback method
 | 
						|
	@param mtr current mini transaction
 | 
						|
	@param pcur persistent cursor. */
 | 
						|
	virtual void operator()(mtr_t* mtr, btr_pcur_t* pcur) throw() = 0;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/** Storage for calculating virtual columns */
 | 
						|
 | 
						|
class String;
 | 
						|
struct VCOL_STORAGE
 | 
						|
{
 | 
						|
	TABLE *maria_table;
 | 
						|
	byte *innobase_record;
 | 
						|
	byte *maria_record;
 | 
						|
	String *blob_value_storage;
 | 
						|
	VCOL_STORAGE(): maria_table(NULL), innobase_record(NULL),
 | 
						|
		maria_record(NULL),  blob_value_storage(NULL) {}
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
   Allocate a heap and record for calculating virtual fields
 | 
						|
   Used mainly for virtual fields in indexes
 | 
						|
 | 
						|
@param[in]	thd		MariaDB THD
 | 
						|
@param[in]	index		Index in use
 | 
						|
@param[out]	heap		Heap that holds temporary row
 | 
						|
@param[in,out]	mysql_table	MariaDB table
 | 
						|
@param[out]	rec		Pointer to allocated MariaDB record
 | 
						|
@param[out]	storage		Internal storage for blobs etc
 | 
						|
 | 
						|
@return		FALSE ok
 | 
						|
@return		TRUE  malloc failure
 | 
						|
*/
 | 
						|
 | 
						|
bool innobase_allocate_row_for_vcol(THD *thd,
 | 
						|
				    const dict_index_t* index,
 | 
						|
				    mem_heap_t**  heap,
 | 
						|
				    TABLE**	  table,
 | 
						|
				    VCOL_STORAGE* storage);
 | 
						|
 | 
						|
/** Free memory allocated by innobase_allocate_row_for_vcol() */
 | 
						|
void innobase_free_row_for_vcol(VCOL_STORAGE *storage);
 | 
						|
 | 
						|
class ib_vcol_row
 | 
						|
{
 | 
						|
  VCOL_STORAGE storage;
 | 
						|
public:
 | 
						|
  mem_heap_t *heap;
 | 
						|
 | 
						|
  ib_vcol_row(mem_heap_t *heap) : heap(heap) {}
 | 
						|
 | 
						|
  byte *record(THD *thd, const dict_index_t *index, TABLE **table)
 | 
						|
  {
 | 
						|
    if (!storage.innobase_record &&
 | 
						|
        !innobase_allocate_row_for_vcol(thd, index, &heap, table, &storage))
 | 
						|
      return nullptr;
 | 
						|
    return storage.innobase_record;
 | 
						|
  }
 | 
						|
 | 
						|
  ~ib_vcol_row()
 | 
						|
  {
 | 
						|
    if (heap)
 | 
						|
    {
 | 
						|
      if (storage.innobase_record)
 | 
						|
        innobase_free_row_for_vcol(&storage);
 | 
						|
      mem_heap_free(heap);
 | 
						|
    }
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
/** Report virtual value computation failure in ib::error
 | 
						|
@param[in]    row    the data row
 | 
						|
*/
 | 
						|
ATTRIBUTE_COLD
 | 
						|
void innobase_report_computed_value_failed(dtuple_t *row);
 | 
						|
 | 
						|
/** Get the computed value by supplying the base column values.
 | 
						|
@param[in,out]	row		the data row
 | 
						|
@param[in]	col		virtual column
 | 
						|
@param[in]	index		index on the virtual column
 | 
						|
@param[in,out]	local_heap	heap memory for processing large data etc.
 | 
						|
@param[in,out]	heap		memory heap that copies the actual index row
 | 
						|
@param[in]	ifield		index field
 | 
						|
@param[in]	thd		connection handle
 | 
						|
@param[in,out]	mysql_table	MariaDB table handle
 | 
						|
@param[in,out]	mysql_rec	MariaDB record buffer
 | 
						|
@param[in]	old_table	during ALTER TABLE, this is the old table
 | 
						|
				or NULL.
 | 
						|
@param[in]	update	update vector for the parent row
 | 
						|
@param[in]	ignore_warnings	ignore warnings during calculation. Usually
 | 
						|
				means that a calculation is internal and
 | 
						|
				should have no side effects.
 | 
						|
@return the field filled with computed value */
 | 
						|
dfield_t*
 | 
						|
innobase_get_computed_value(
 | 
						|
	dtuple_t*		row,
 | 
						|
	const dict_v_col_t*	col,
 | 
						|
	const dict_index_t*	index,
 | 
						|
	mem_heap_t**		local_heap,
 | 
						|
	mem_heap_t*		heap,
 | 
						|
	const dict_field_t*	ifield,
 | 
						|
	THD*			thd,
 | 
						|
	TABLE*			mysql_table,
 | 
						|
	byte*			mysql_rec,
 | 
						|
	const dict_table_t*	old_table=NULL,
 | 
						|
	const upd_t*		update=NULL,
 | 
						|
	bool			ignore_warnings=false);
 | 
						|
 | 
						|
/** Change dbname and table name in table->vc_templ.
 | 
						|
@param[in,out]	table	the table whose virtual column template
 | 
						|
dbname and tbname to be renamed. */
 | 
						|
void
 | 
						|
innobase_rename_vc_templ(
 | 
						|
	dict_table_t*	table);
 | 
						|
 | 
						|
#define ROW_PREBUILT_FETCH_MAGIC_N	465765687
 | 
						|
 | 
						|
#define ROW_MYSQL_WHOLE_ROW	0
 | 
						|
#define ROW_MYSQL_REC_FIELDS	1
 | 
						|
#define ROW_MYSQL_NO_TEMPLATE	2
 | 
						|
#define ROW_MYSQL_DUMMY_TEMPLATE 3	/* dummy template used in
 | 
						|
					row_check_index() */
 | 
						|
 | 
						|
/* Values for hint_need_to_fetch_extra_cols */
 | 
						|
#define ROW_RETRIEVE_PRIMARY_KEY	1
 | 
						|
#define ROW_RETRIEVE_ALL_COLS		2
 | 
						|
 | 
						|
/* Values for row_read_type */
 | 
						|
#define ROW_READ_WITH_LOCKS		0
 | 
						|
#define ROW_READ_TRY_SEMI_CONSISTENT	1
 | 
						|
#define ROW_READ_DID_SEMI_CONSISTENT	2
 | 
						|
 | 
						|
#endif /* row0mysql.h */
 |