mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-04 12:56:14 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			402 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			402 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*****************************************************************************
 | 
						|
 | 
						|
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
 | 
						|
Copyright (c) 2016, 2023, 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/row0row.h
 | 
						|
General row routines
 | 
						|
 | 
						|
Created 4/20/1996 Heikki Tuuri
 | 
						|
*******************************************************/
 | 
						|
 | 
						|
#ifndef row0row_h
 | 
						|
#define row0row_h
 | 
						|
 | 
						|
#include "que0types.h"
 | 
						|
#include "trx0types.h"
 | 
						|
#include "mtr0mtr.h"
 | 
						|
#include "rem0types.h"
 | 
						|
#include "row0types.h"
 | 
						|
#include "btr0types.h"
 | 
						|
 | 
						|
/*********************************************************************//**
 | 
						|
Gets the offset of the DB_TRX_ID field, in bytes relative to the origin of
 | 
						|
a clustered index record.
 | 
						|
@return offset of DATA_TRX_ID */
 | 
						|
UNIV_INLINE
 | 
						|
ulint
 | 
						|
row_get_trx_id_offset(
 | 
						|
/*==================*/
 | 
						|
	const dict_index_t*	index,	/*!< in: clustered index */
 | 
						|
	const rec_offs*		offsets)/*!< in: record offsets */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
/*********************************************************************//**
 | 
						|
Reads the trx id field from a clustered index record.
 | 
						|
@return value of the field */
 | 
						|
UNIV_INLINE
 | 
						|
trx_id_t
 | 
						|
row_get_rec_trx_id(
 | 
						|
/*===============*/
 | 
						|
	const rec_t*		rec,	/*!< in: record */
 | 
						|
	const dict_index_t*	index,	/*!< in: clustered index */
 | 
						|
	const rec_offs*		offsets)/*!< in: rec_get_offsets(rec, index) */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
/*********************************************************************//**
 | 
						|
Reads the roll pointer field from a clustered index record.
 | 
						|
@return value of the field */
 | 
						|
UNIV_INLINE
 | 
						|
roll_ptr_t
 | 
						|
row_get_rec_roll_ptr(
 | 
						|
/*=================*/
 | 
						|
	const rec_t*		rec,	/*!< in: record */
 | 
						|
	const dict_index_t*	index,	/*!< in: clustered index */
 | 
						|
	const rec_offs*		offsets)/*!< in: rec_get_offsets(rec, index) */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
 | 
						|
/* Flags for row build type. */
 | 
						|
#define ROW_BUILD_NORMAL	0	/*!< build index row */
 | 
						|
#define ROW_BUILD_FOR_PURGE	1	/*!< build row for purge. */
 | 
						|
#define ROW_BUILD_FOR_UNDO	2	/*!< build row for undo. */
 | 
						|
#define ROW_BUILD_FOR_INSERT	3	/*!< build row for insert. */
 | 
						|
 | 
						|
/*****************************************************************//**
 | 
						|
When an insert or purge to a table is performed, this function builds
 | 
						|
the entry to be inserted into or purged from an index on the table.
 | 
						|
@return index entry which should be inserted or purged
 | 
						|
@retval NULL if the externally stored columns in the clustered index record
 | 
						|
are unavailable and ext != NULL, or row is missing some needed columns. */
 | 
						|
dtuple_t*
 | 
						|
row_build_index_entry_low(
 | 
						|
/*======================*/
 | 
						|
	const dtuple_t*		row,	/*!< in: row which should be
 | 
						|
					inserted or purged */
 | 
						|
	const row_ext_t*	ext,	/*!< in: externally stored column
 | 
						|
					prefixes, or NULL */
 | 
						|
	const dict_index_t*	index,	/*!< in: index on the table */
 | 
						|
	mem_heap_t*		heap,	/*!< in,out: memory heap from which
 | 
						|
					the memory for the index entry
 | 
						|
					is allocated */
 | 
						|
	ulint			flag)	/*!< in: ROW_BUILD_NORMAL,
 | 
						|
					ROW_BUILD_FOR_PURGE
 | 
						|
                                        or ROW_BUILD_FOR_UNDO */
 | 
						|
	MY_ATTRIBUTE((warn_unused_result, nonnull(1,3,4)));
 | 
						|
/*****************************************************************//**
 | 
						|
When an insert or purge to a table is performed, this function builds
 | 
						|
the entry to be inserted into or purged from an index on the table.
 | 
						|
@return index entry which should be inserted or purged, or NULL if the
 | 
						|
externally stored columns in the clustered index record are
 | 
						|
unavailable and ext != NULL */
 | 
						|
UNIV_INLINE
 | 
						|
dtuple_t*
 | 
						|
row_build_index_entry(
 | 
						|
/*==================*/
 | 
						|
	const dtuple_t*		row,	/*!< in: row which should be
 | 
						|
					inserted or purged */
 | 
						|
	const row_ext_t*	ext,	/*!< in: externally stored column
 | 
						|
					prefixes, or NULL */
 | 
						|
	const dict_index_t*	index,	/*!< in: index on the table */
 | 
						|
	mem_heap_t*		heap)	/*!< in,out: memory heap from which
 | 
						|
					the memory for the index entry
 | 
						|
					is allocated */
 | 
						|
	MY_ATTRIBUTE((warn_unused_result, nonnull(1,3,4)));
 | 
						|
/*******************************************************************//**
 | 
						|
An inverse function to row_build_index_entry. Builds a row from a
 | 
						|
record in a clustered index.
 | 
						|
@return own: row built; see the NOTE below! */
 | 
						|
dtuple_t*
 | 
						|
row_build(
 | 
						|
/*======*/
 | 
						|
	ulint			type,	/*!< in: ROW_COPY_POINTERS or
 | 
						|
					ROW_COPY_DATA; the latter
 | 
						|
					copies also the data fields to
 | 
						|
					heap while the first only
 | 
						|
					places pointers to data fields
 | 
						|
					on the index page, and thus is
 | 
						|
					more efficient */
 | 
						|
	const dict_index_t*	index,	/*!< in: clustered index */
 | 
						|
	const rec_t*		rec,	/*!< in: record in the clustered
 | 
						|
					index; NOTE: in the case
 | 
						|
					ROW_COPY_POINTERS the data
 | 
						|
					fields in the row will point
 | 
						|
					directly into this record,
 | 
						|
					therefore, the buffer page of
 | 
						|
					this record must be at least
 | 
						|
					s-latched and the latch held
 | 
						|
					as long as the row dtuple is used! */
 | 
						|
	const rec_offs*		offsets,/*!< in: rec_get_offsets(rec,index)
 | 
						|
					or NULL, in which case this function
 | 
						|
					will invoke rec_get_offsets() */
 | 
						|
	const dict_table_t*	col_table,
 | 
						|
					/*!< in: table, to check which
 | 
						|
					externally stored columns
 | 
						|
					occur in the ordering columns
 | 
						|
					of an index, or NULL if
 | 
						|
					index->table should be
 | 
						|
					consulted instead; the user
 | 
						|
					columns in this table should be
 | 
						|
					the same columns as in index->table */
 | 
						|
	const dtuple_t*		defaults,
 | 
						|
					/*!< in: default values of
 | 
						|
					added, changed columns, or NULL */
 | 
						|
	const ulint*		col_map,/*!< in: mapping of old column
 | 
						|
					numbers to new ones, or NULL */
 | 
						|
	row_ext_t**		ext,	/*!< out, own: cache of
 | 
						|
					externally stored column
 | 
						|
					prefixes, or NULL */
 | 
						|
	mem_heap_t*		heap);	/*!< in: memory heap from which
 | 
						|
					the memory needed is allocated */
 | 
						|
 | 
						|
/** An inverse function to row_build_index_entry. Builds a row from a
 | 
						|
record in a clustered index, with possible indexing on ongoing
 | 
						|
addition of new virtual columns.
 | 
						|
@param[in]	type		ROW_COPY_POINTERS or ROW_COPY_DATA;
 | 
						|
@param[in]	index		clustered index
 | 
						|
@param[in]	rec		record in the clustered index
 | 
						|
@param[in]	offsets		rec_get_offsets(rec,index) or NULL
 | 
						|
@param[in]	col_table	table, to check which
 | 
						|
				externally stored columns
 | 
						|
				occur in the ordering columns
 | 
						|
				of an index, or NULL if
 | 
						|
				index->table should be
 | 
						|
				consulted instead
 | 
						|
@param[in]	defaults	default values of added, changed columns, or NULL
 | 
						|
@param[in]	add_v		new virtual columns added
 | 
						|
				along with new indexes
 | 
						|
@param[in]	col_map		mapping of old column
 | 
						|
				numbers to new ones, or NULL
 | 
						|
@param[in]	ext		cache of externally stored column
 | 
						|
				prefixes, or NULL
 | 
						|
@param[in]	heap		memory heap from which
 | 
						|
				the memory needed is allocated
 | 
						|
@return own: row built */
 | 
						|
dtuple_t*
 | 
						|
row_build_w_add_vcol(
 | 
						|
	ulint			type,
 | 
						|
	const dict_index_t*	index,
 | 
						|
	const rec_t*		rec,
 | 
						|
	const rec_offs*		offsets,
 | 
						|
	const dict_table_t*	col_table,
 | 
						|
	const dtuple_t*		defaults,
 | 
						|
	const dict_add_v_col_t*	add_v,
 | 
						|
	const ulint*		col_map,
 | 
						|
	row_ext_t**		ext,
 | 
						|
	mem_heap_t*		heap);
 | 
						|
 | 
						|
/*******************************************************************//**
 | 
						|
Converts an index record to a typed data tuple.
 | 
						|
@return index entry built; does not set info_bits, and the data fields
 | 
						|
in the entry will point directly to rec */
 | 
						|
dtuple_t*
 | 
						|
row_rec_to_index_entry_low(
 | 
						|
/*=======================*/
 | 
						|
	const rec_t*		rec,	/*!< in: record in the index */
 | 
						|
	const dict_index_t*	index,	/*!< in: index */
 | 
						|
	const rec_offs*		offsets,/*!< in: rec_get_offsets(rec, index) */
 | 
						|
	mem_heap_t*		heap)	/*!< in: memory heap from which
 | 
						|
					the memory needed is allocated */
 | 
						|
	MY_ATTRIBUTE((warn_unused_result));
 | 
						|
/*******************************************************************//**
 | 
						|
Converts an index record to a typed data tuple. NOTE that externally
 | 
						|
stored (often big) fields are NOT copied to heap.
 | 
						|
@return own: index entry built */
 | 
						|
dtuple_t*
 | 
						|
row_rec_to_index_entry(
 | 
						|
/*===================*/
 | 
						|
	const rec_t*		rec,	/*!< in: record in the index */
 | 
						|
	const dict_index_t*	index,	/*!< in: index */
 | 
						|
	const rec_offs*		offsets,/*!< in/out: rec_get_offsets(rec) */
 | 
						|
	mem_heap_t*		heap)	/*!< in: memory heap from which
 | 
						|
					the memory needed is allocated */
 | 
						|
	MY_ATTRIBUTE((warn_unused_result));
 | 
						|
 | 
						|
/** Convert a metadata record to a data tuple.
 | 
						|
@param[in]	rec		metadata record
 | 
						|
@param[in]	index		clustered index after instant ALTER TABLE
 | 
						|
@param[in]	offsets		rec_get_offsets(rec)
 | 
						|
@param[in,out]	heap		memory heap for allocations
 | 
						|
@param[in]	info_bits	the info_bits after an update
 | 
						|
@param[in]	pad		whether to pad to index->n_fields */
 | 
						|
dtuple_t*
 | 
						|
row_metadata_to_tuple(
 | 
						|
	const rec_t*		rec,
 | 
						|
	const dict_index_t*	index,
 | 
						|
	const rec_offs*		offsets,
 | 
						|
	mem_heap_t*		heap,
 | 
						|
	ulint			info_bits,
 | 
						|
	bool			pad)
 | 
						|
	MY_ATTRIBUTE((nonnull,warn_unused_result));
 | 
						|
 | 
						|
/*******************************************************************//**
 | 
						|
Builds from a secondary index record a row reference with which we can
 | 
						|
search the clustered index record.
 | 
						|
@return own: row reference built; see the NOTE below! */
 | 
						|
dtuple_t*
 | 
						|
row_build_row_ref(
 | 
						|
/*==============*/
 | 
						|
	ulint		type,	/*!< in: ROW_COPY_DATA, or ROW_COPY_POINTERS:
 | 
						|
				the former copies also the data fields to
 | 
						|
				heap, whereas the latter only places pointers
 | 
						|
				to data fields on the index page */
 | 
						|
	dict_index_t*	index,	/*!< in: secondary index */
 | 
						|
	const rec_t*	rec,	/*!< in: record in the index;
 | 
						|
				NOTE: in the case ROW_COPY_POINTERS
 | 
						|
				the data fields in the row will point
 | 
						|
				directly into this record, therefore,
 | 
						|
				the buffer page of this record must be
 | 
						|
				at least s-latched and the latch held
 | 
						|
				as long as the row reference is used! */
 | 
						|
	mem_heap_t*	heap)	/*!< in: memory heap from which the memory
 | 
						|
				needed is allocated */
 | 
						|
	MY_ATTRIBUTE((warn_unused_result));
 | 
						|
/*******************************************************************//**
 | 
						|
Builds from a secondary index record a row reference with which we can
 | 
						|
search the clustered index record. */
 | 
						|
void
 | 
						|
row_build_row_ref_in_tuple(
 | 
						|
/*=======================*/
 | 
						|
	dtuple_t*		ref,	/*!< in/out: row reference built;
 | 
						|
					see the NOTE below! */
 | 
						|
	const rec_t*		rec,	/*!< in: record in the index;
 | 
						|
					NOTE: the data fields in ref
 | 
						|
					will point directly into this
 | 
						|
					record, therefore, the buffer
 | 
						|
					page of this record must be at
 | 
						|
					least s-latched and the latch
 | 
						|
					held as long as the row
 | 
						|
					reference is used! */
 | 
						|
	const dict_index_t*	index,	/*!< in: secondary index */
 | 
						|
	rec_offs*		offsets)/*!< in: rec_get_offsets(rec, index)
 | 
						|
					or NULL */
 | 
						|
	MY_ATTRIBUTE((nonnull(1,2,3)));
 | 
						|
/*******************************************************************//**
 | 
						|
Builds from a secondary index record a row reference with which we can
 | 
						|
search the clustered index record. */
 | 
						|
UNIV_INLINE
 | 
						|
void
 | 
						|
row_build_row_ref_fast(
 | 
						|
/*===================*/
 | 
						|
	dtuple_t*	ref,	/*!< in/out: typed data tuple where the
 | 
						|
				reference is built */
 | 
						|
	const ulint*	map,	/*!< in: array of field numbers in rec
 | 
						|
				telling how ref should be built from
 | 
						|
				the fields of rec */
 | 
						|
	const rec_t*	rec,	/*!< in: secondary index record;
 | 
						|
				must be preserved while ref is used, as we do
 | 
						|
				not copy field values to heap */
 | 
						|
	const rec_offs*	offsets);/*!< in: array returned by rec_get_offsets() */
 | 
						|
/***************************************************************//**
 | 
						|
Searches the clustered index record for a row, if we have the row
 | 
						|
reference.
 | 
						|
@return true if found */
 | 
						|
bool
 | 
						|
row_search_on_row_ref(
 | 
						|
/*==================*/
 | 
						|
	btr_pcur_t*		pcur,	/*!< out: persistent cursor, which must
 | 
						|
					be closed by the caller */
 | 
						|
	btr_latch_mode		mode,	/*!< in: BTR_MODIFY_LEAF, ... */
 | 
						|
	const dict_table_t*	table,	/*!< in: table */
 | 
						|
	const dtuple_t*		ref,	/*!< in: row reference */
 | 
						|
	mtr_t*			mtr)	/*!< in/out: mtr */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
/*********************************************************************//**
 | 
						|
Fetches the clustered index record for a secondary index record. The latches
 | 
						|
on the secondary index record are preserved.
 | 
						|
@return record or NULL, if no record found */
 | 
						|
rec_t*
 | 
						|
row_get_clust_rec(
 | 
						|
/*==============*/
 | 
						|
	btr_latch_mode	mode,	/*!< in: BTR_MODIFY_LEAF, ... */
 | 
						|
	const rec_t*	rec,	/*!< in: record in a secondary index */
 | 
						|
	dict_index_t*	index,	/*!< in: secondary index */
 | 
						|
	dict_index_t**	clust_index,/*!< out: clustered index */
 | 
						|
	mtr_t*		mtr)	/*!< in: mtr */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
 | 
						|
/***************************************************************//**
 | 
						|
Searches an index record.
 | 
						|
@return whether the record was found */
 | 
						|
bool
 | 
						|
row_search_index_entry(
 | 
						|
/*===================*/
 | 
						|
	const dtuple_t*	entry,	/*!< in: index entry */
 | 
						|
	btr_latch_mode	mode,	/*!< in: BTR_MODIFY_LEAF, ... */
 | 
						|
	btr_pcur_t*	pcur,	/*!< in/out: persistent cursor, which must
 | 
						|
				be closed by the caller */
 | 
						|
	mtr_t*		mtr)	/*!< in: mtr */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
 | 
						|
/** Get the byte offset of the DB_TRX_ID column
 | 
						|
@param[in]	rec	clustered index record
 | 
						|
@param[in]	index	clustered index
 | 
						|
@return	the byte offset of DB_TRX_ID, from the start of rec */
 | 
						|
ulint row_trx_id_offset(const rec_t* rec, const dict_index_t* index);
 | 
						|
 | 
						|
#define ROW_COPY_DATA		1
 | 
						|
#define ROW_COPY_POINTERS	2
 | 
						|
 | 
						|
/* The allowed latching order of index records is the following:
 | 
						|
(1) a secondary index record ->
 | 
						|
(2) the clustered index record ->
 | 
						|
(3) rollback segment data for the clustered index record. */
 | 
						|
 | 
						|
/*******************************************************************//**
 | 
						|
Formats the raw data in "data" (in InnoDB on-disk format) using
 | 
						|
"dict_field" and writes the result to "buf".
 | 
						|
Not more than "buf_size" bytes are written to "buf".
 | 
						|
The result is always NUL-terminated (provided buf_size is positive) and the
 | 
						|
number of bytes that were written to "buf" is returned (including the
 | 
						|
terminating NUL).
 | 
						|
@return number of bytes that were written */
 | 
						|
ulint
 | 
						|
row_raw_format(
 | 
						|
/*===========*/
 | 
						|
	const char*		data,		/*!< in: raw data */
 | 
						|
	ulint			data_len,	/*!< in: raw data length
 | 
						|
						in bytes */
 | 
						|
	const dict_field_t*	dict_field,	/*!< in: index field */
 | 
						|
	char*			buf,		/*!< out: output buffer */
 | 
						|
	ulint			buf_size)	/*!< in: output buffer size
 | 
						|
						in bytes */
 | 
						|
	MY_ATTRIBUTE((nonnull, warn_unused_result));
 | 
						|
 | 
						|
#include "dict0mem.h"
 | 
						|
 | 
						|
/** Prepare to start a mini-transaction to modify an index.
 | 
						|
@param[in,out]	mtr		mini-transaction
 | 
						|
@param[in,out]	index		possibly secondary index */
 | 
						|
inline void row_mtr_start(mtr_t* mtr, dict_index_t* index)
 | 
						|
{
 | 
						|
	mtr->start();
 | 
						|
 | 
						|
	switch (index->table->space_id) {
 | 
						|
	case 0:
 | 
						|
		break;
 | 
						|
	case SRV_TMP_SPACE_ID:
 | 
						|
		mtr->set_log_mode(MTR_LOG_NO_REDO);
 | 
						|
		break;
 | 
						|
	default:
 | 
						|
		index->set_modified(*mtr);
 | 
						|
		break;
 | 
						|
	}
 | 
						|
 | 
						|
	log_free_check();
 | 
						|
}
 | 
						|
 | 
						|
#include "row0row.inl"
 | 
						|
 | 
						|
#endif
 |