2005-10-27 09:29:40 +02:00
|
|
|
/******************************************************
|
|
|
|
General row routines
|
|
|
|
|
|
|
|
(c) 1996 Innobase Oy
|
|
|
|
|
|
|
|
Created 4/20/1996 Heikki Tuuri
|
|
|
|
*******************************************************/
|
|
|
|
|
|
|
|
#ifndef row0row_h
|
|
|
|
#define row0row_h
|
|
|
|
|
|
|
|
#include "univ.i"
|
|
|
|
#include "data0data.h"
|
|
|
|
#include "dict0types.h"
|
|
|
|
#include "trx0types.h"
|
|
|
|
#include "que0types.h"
|
2006-02-23 20:25:29 +01:00
|
|
|
#include "mtr0mtr.h"
|
2005-10-27 09:29:40 +02:00
|
|
|
#include "rem0types.h"
|
|
|
|
#include "read0types.h"
|
2006-09-26 13:50:54 +02:00
|
|
|
#include "row0types.h"
|
2005-10-27 09:29:40 +02:00
|
|
|
#include "btr0types.h"
|
|
|
|
|
2006-02-10 16:06:17 +01:00
|
|
|
/*************************************************************************
|
|
|
|
Gets the offset of the trx id field, in bytes relative to the origin of
|
|
|
|
a clustered index record. */
|
2008-02-18 19:38:33 +01:00
|
|
|
UNIV_INTERN
|
2006-02-10 16:06:17 +01:00
|
|
|
ulint
|
|
|
|
row_get_trx_id_offset(
|
|
|
|
/*==================*/
|
|
|
|
/* out: offset of DATA_TRX_ID */
|
2006-10-20 15:50:40 +02:00
|
|
|
const rec_t* rec, /* in: record */
|
2006-02-10 16:06:17 +01:00
|
|
|
dict_index_t* index, /* in: clustered index */
|
|
|
|
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
|
2005-10-27 09:29:40 +02:00
|
|
|
/*************************************************************************
|
|
|
|
Reads the trx id field from a clustered index record. */
|
|
|
|
UNIV_INLINE
|
|
|
|
dulint
|
|
|
|
row_get_rec_trx_id(
|
|
|
|
/*===============*/
|
|
|
|
/* out: value of the field */
|
2006-10-20 15:50:40 +02:00
|
|
|
const rec_t* rec, /* in: record */
|
2005-10-27 09:29:40 +02:00
|
|
|
dict_index_t* index, /* in: clustered index */
|
|
|
|
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
|
|
|
|
/*************************************************************************
|
|
|
|
Reads the roll pointer field from a clustered index record. */
|
|
|
|
UNIV_INLINE
|
|
|
|
dulint
|
|
|
|
row_get_rec_roll_ptr(
|
|
|
|
/*=================*/
|
|
|
|
/* out: value of the field */
|
2006-10-20 15:50:40 +02:00
|
|
|
const rec_t* rec, /* in: record */
|
2005-10-27 09:29:40 +02:00
|
|
|
dict_index_t* index, /* in: clustered index */
|
|
|
|
const ulint* offsets);/* in: rec_get_offsets(rec, index) */
|
|
|
|
/*********************************************************************
|
2007-04-04 13:05:33 +02:00
|
|
|
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. */
|
2008-02-18 19:38:33 +01:00
|
|
|
UNIV_INTERN
|
2005-10-27 09:29:40 +02:00
|
|
|
dtuple_t*
|
|
|
|
row_build_index_entry(
|
|
|
|
/*==================*/
|
2007-04-04 13:05:33 +02:00
|
|
|
/* out: index entry which should be
|
2007-11-27 10:11:45 +01:00
|
|
|
inserted or purged, or NULL if the
|
|
|
|
externally stored columns in the
|
|
|
|
clustered index record are unavailable
|
|
|
|
and ext != NULL */
|
2007-04-04 13:05:33 +02:00
|
|
|
const dtuple_t* row, /* in: row which should be
|
|
|
|
inserted or purged */
|
2006-09-26 13:50:54 +02:00
|
|
|
row_ext_t* ext, /* in: externally stored column prefixes,
|
|
|
|
or NULL */
|
2006-02-23 20:25:29 +01:00
|
|
|
dict_index_t* index, /* in: index on the table */
|
2005-10-27 09:29:40 +02:00
|
|
|
mem_heap_t* heap); /* in: memory heap from which the memory for
|
|
|
|
the index entry is allocated */
|
|
|
|
/***********************************************************************
|
2007-06-08 09:37:07 +02:00
|
|
|
An inverse function to row_build_index_entry. Builds a row from a
|
2005-10-27 09:29:40 +02:00
|
|
|
record in a clustered index. */
|
2008-02-18 19:38:33 +01:00
|
|
|
UNIV_INTERN
|
2005-10-27 09:29:40 +02:00
|
|
|
dtuple_t*
|
|
|
|
row_build(
|
|
|
|
/*======*/
|
2007-12-03 13:16:07 +01:00
|
|
|
/* out, own: row built;
|
|
|
|
see the NOTE below! */
|
|
|
|
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 ulint* 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 */
|
|
|
|
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 */
|
2005-10-27 09:29:40 +02:00
|
|
|
/***********************************************************************
|
|
|
|
Converts an index record to a typed data tuple. */
|
2008-02-18 19:38:33 +01:00
|
|
|
UNIV_INTERN
|
2007-06-08 09:37:07 +02:00
|
|
|
dtuple_t*
|
|
|
|
row_rec_to_index_entry_low(
|
|
|
|
/*=======================*/
|
2007-10-17 14:13:29 +02:00
|
|
|
/* out: index entry built; does not
|
|
|
|
set info_bits, and the data fields in
|
|
|
|
the entry will point directly to rec */
|
|
|
|
const rec_t* rec, /* in: record in the index */
|
|
|
|
const dict_index_t* index, /* in: index */
|
|
|
|
const ulint* offsets,/* in: rec_get_offsets(rec, index) */
|
|
|
|
ulint* n_ext, /* out: number of externally
|
|
|
|
stored columns */
|
|
|
|
mem_heap_t* heap); /* in: memory heap from which
|
|
|
|
the memory needed is allocated */
|
2007-06-08 09:37:07 +02:00
|
|
|
/***********************************************************************
|
|
|
|
Converts an index record to a typed data tuple. NOTE that externally
|
|
|
|
stored (often big) fields are NOT copied to heap. */
|
2008-02-18 19:38:33 +01:00
|
|
|
UNIV_INTERN
|
2005-10-27 09:29:40 +02:00
|
|
|
dtuple_t*
|
|
|
|
row_rec_to_index_entry(
|
|
|
|
/*===================*/
|
2007-10-17 14:13:29 +02:00
|
|
|
/* out, own: index entry
|
|
|
|
built; see the NOTE below! */
|
|
|
|
ulint type, /* in: ROW_COPY_DATA, or
|
|
|
|
ROW_COPY_POINTERS: the former
|
|
|
|
copies also the data fields to
|
|
|
|
heap as the latter only places
|
|
|
|
pointers to data fields on the
|
|
|
|
index page */
|
|
|
|
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 dtuple is used! */
|
|
|
|
const dict_index_t* index, /* in: index */
|
|
|
|
ulint* offsets,/* in/out: rec_get_offsets(rec) */
|
|
|
|
ulint* n_ext, /* out: number of externally
|
|
|
|
stored columns */
|
|
|
|
mem_heap_t* heap); /* in: memory heap from which
|
|
|
|
the memory needed is allocated */
|
2005-10-27 09:29:40 +02:00
|
|
|
/***********************************************************************
|
|
|
|
Builds from a secondary index record a row reference with which we can
|
|
|
|
search the clustered index record. */
|
2008-02-18 19:38:33 +01:00
|
|
|
UNIV_INTERN
|
2005-10-27 09:29:40 +02:00
|
|
|
dtuple_t*
|
|
|
|
row_build_row_ref(
|
|
|
|
/*==============*/
|
|
|
|
/* out, own: row reference built; see the
|
|
|
|
NOTE below! */
|
|
|
|
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 */
|
2007-10-17 14:13:29 +02:00
|
|
|
dict_index_t* index, /* in: secondary index */
|
2006-10-20 15:50:40 +02:00
|
|
|
const rec_t* rec, /* in: record in the index;
|
2005-10-27 09:29:40 +02:00
|
|
|
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 */
|
|
|
|
/***********************************************************************
|
|
|
|
Builds from a secondary index record a row reference with which we can
|
|
|
|
search the clustered index record. */
|
2008-02-18 19:38:33 +01:00
|
|
|
UNIV_INTERN
|
2005-10-27 09:29:40 +02:00
|
|
|
void
|
|
|
|
row_build_row_ref_in_tuple(
|
|
|
|
/*=======================*/
|
2007-09-25 09:20:56 +02:00
|
|
|
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 */
|
|
|
|
ulint* offsets,/* in: rec_get_offsets(rec, index)
|
|
|
|
or NULL */
|
|
|
|
trx_t* trx); /* in: transaction */
|
2005-10-27 09:29:40 +02:00
|
|
|
/***********************************************************************
|
|
|
|
From a row build a row reference with which we can search the clustered
|
|
|
|
index record. */
|
2008-02-18 19:38:33 +01:00
|
|
|
UNIV_INTERN
|
2005-10-27 09:29:40 +02:00
|
|
|
void
|
|
|
|
row_build_row_ref_from_row(
|
|
|
|
/*=======================*/
|
2007-09-26 09:45:08 +02:00
|
|
|
dtuple_t* ref, /* in/out: row reference built;
|
|
|
|
see the NOTE below!
|
|
|
|
ref must have the right number
|
|
|
|
of fields! */
|
|
|
|
const dict_table_t* table, /* in: table */
|
|
|
|
const dtuple_t* row); /* in: row
|
|
|
|
NOTE: the data fields in ref will point
|
|
|
|
directly into data of this row */
|
2005-10-27 09:29:40 +02:00
|
|
|
/***********************************************************************
|
|
|
|
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(
|
|
|
|
/*===================*/
|
2007-09-26 09:45:08 +02:00
|
|
|
dtuple_t* ref, /* in/out: typed data tuple where the
|
2005-10-27 09:29:40 +02:00
|
|
|
reference is built */
|
|
|
|
const ulint* map, /* in: array of field numbers in rec
|
|
|
|
telling how ref should be built from
|
|
|
|
the fields of rec */
|
2006-10-20 15:50:40 +02:00
|
|
|
const rec_t* rec, /* in: record in the index; must be
|
2005-10-27 09:29:40 +02:00
|
|
|
preserved while ref is used, as we do
|
|
|
|
not copy field values to heap */
|
|
|
|
const ulint* offsets);/* in: array returned by rec_get_offsets() */
|
|
|
|
/*******************************************************************
|
|
|
|
Searches the clustered index record for a row, if we have the row
|
|
|
|
reference. */
|
2008-02-18 19:38:33 +01:00
|
|
|
UNIV_INTERN
|
2005-10-27 09:29:40 +02:00
|
|
|
ibool
|
|
|
|
row_search_on_row_ref(
|
|
|
|
/*==================*/
|
2007-09-26 11:12:23 +02:00
|
|
|
/* out: TRUE if found */
|
|
|
|
btr_pcur_t* pcur, /* out: persistent cursor, which must
|
|
|
|
be closed by the caller */
|
|
|
|
ulint 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 */
|
2005-10-27 09:29:40 +02:00
|
|
|
/*************************************************************************
|
|
|
|
Fetches the clustered index record for a secondary index record. The latches
|
|
|
|
on the secondary index record are preserved. */
|
2008-02-18 19:38:33 +01:00
|
|
|
UNIV_INTERN
|
2005-10-27 09:29:40 +02:00
|
|
|
rec_t*
|
|
|
|
row_get_clust_rec(
|
|
|
|
/*==============*/
|
|
|
|
/* out: record or NULL, if no record found */
|
|
|
|
ulint mode, /* in: BTR_MODIFY_LEAF, ... */
|
2006-10-20 15:50:40 +02:00
|
|
|
const rec_t* rec, /* in: record in a secondary index */
|
2005-10-27 09:29:40 +02:00
|
|
|
dict_index_t* index, /* in: secondary index */
|
|
|
|
dict_index_t** clust_index,/* out: clustered index */
|
|
|
|
mtr_t* mtr); /* in: mtr */
|
2008-09-30 20:06:38 +02:00
|
|
|
|
|
|
|
/* Result of row_search_index_entry */
|
|
|
|
enum row_search_result {
|
|
|
|
ROW_FOUND = 0, /* the record was found */
|
|
|
|
ROW_NOT_FOUND, /* record not found */
|
|
|
|
ROW_BUFFERED, /* one of BTR_INSERT, BTR_DELETE, or
|
|
|
|
BTR_DELETE_MARK was specified, the
|
|
|
|
secondary index leaf page was not in
|
|
|
|
the buffer pool, and the operation was
|
|
|
|
enqueued in the insert/delete buffer */
|
branches/innodb+: Clean up the buffering of purges. Instead of
traversing the index B-tree twice (first in BTR_WATCH_LEAF mode and
then in BTR_DELETE mode), let BTR_DELETE take care of checking that
the record can be purged, and either buffering or performing the
purge.
row_purge_poss_sec(): New function, to check if it is possible to
purge a secondary index record. Refactored from
row_purge_remove_sec_if_poss_low().
row_purge_remove_sec_if_poss_nonbuffered(): Rename to
row_purge_remove_sec_if_poss_tree(). Remove the parameter mode
(always use BTR_MODIFY_TREE). Use row_purge_poss_sec().
row_purge_remove_sec_if_poss_low(): Rename to
row_purge_remove_sec_if_poss_leaf(). Remove the parameter mode
(always use BTR_MODIFY_LEAF). Let row_search_index_entry() do all the
hard work.
btr_cur_t: Add purge_node, which will be needed by
btr_cur_search_to_nth_level() for BTR_DELETE. Replace the flag value
BTR_CUR_ABORTED with BTR_CUR_DELETE_REF and BTR_CUR_DELETE_FAILED.
enum row_search_result, row_search_index_entry(): Replace
ROW_NOT_IN_POOL with ROW_NOT_DELETED_REF and ROW_NOT_DELETED.
btr_cur_search_to_nth_level(): Remove BTR_WATCH_LEAF. As a side
effect, the adaptive hash index can be used in purge as well. If
BTR_DELETE cannot be buffered, attempt btr_cur_optimistic_delete().
Either way, check row_purge_poss_sec(). Move the code to set
cursor->ibuf_count to get rid of another if (height == 0)
check. Eliminate the label loop_end. Do not call ibuf_should_try()
twice.
ibuf_should_try(): Now that the successful calls to this function will
be halved, halve the magic constant that ibuf_flush_count will be
compared to, accordingly.
The changes regarding ibuf_should_try() were merged from branches/zip
r3515.
rb://60 approved by Heikki over IM
2008-12-12 13:59:48 +01:00
|
|
|
ROW_NOT_DELETED_REF, /* BTR_DELETE was specified, and
|
|
|
|
row_purge_poss_sec() failed */
|
|
|
|
ROW_NOT_DELETED, /* BTR_DELETE was specified, and the
|
|
|
|
optimistic delete failed */
|
2008-09-30 20:06:38 +02:00
|
|
|
};
|
|
|
|
|
2005-10-27 09:29:40 +02:00
|
|
|
/*******************************************************************
|
|
|
|
Searches an index record. */
|
2008-02-18 19:38:33 +01:00
|
|
|
UNIV_INTERN
|
2008-09-30 20:06:38 +02:00
|
|
|
enum row_search_result
|
2005-10-27 09:29:40 +02:00
|
|
|
row_search_index_entry(
|
|
|
|
/*===================*/
|
2008-09-30 20:06:38 +02:00
|
|
|
/* out: whether the record was found
|
|
|
|
or buffered */
|
2005-10-27 09:29:40 +02:00
|
|
|
dict_index_t* index, /* in: index */
|
2006-10-20 15:50:40 +02:00
|
|
|
const dtuple_t* entry, /* in: index entry */
|
2005-10-27 09:29:40 +02:00
|
|
|
ulint 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 */
|
|
|
|
|
2006-02-23 20:25:29 +01:00
|
|
|
|
2005-10-27 09:29:40 +02:00
|
|
|
#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.
|
|
|
|
|
|
|
|
No new latches may be obtained while the kernel mutex is reserved.
|
|
|
|
However, the kernel mutex can be reserved while latches are owned. */
|
|
|
|
|
2007-10-29 14:03:53 +01:00
|
|
|
/***********************************************************************
|
|
|
|
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 '\0'-terminated (provided buf_size > 0) and the
|
|
|
|
number of bytes that were written to "buf" is returned (including the
|
|
|
|
terminating '\0'). */
|
2008-02-18 19:38:33 +01:00
|
|
|
UNIV_INTERN
|
2007-10-29 14:03:53 +01:00
|
|
|
ulint
|
|
|
|
row_raw_format(
|
|
|
|
/*===========*/
|
|
|
|
/* out: number of bytes
|
|
|
|
that were written */
|
|
|
|
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 */
|
|
|
|
|
2005-10-27 09:29:40 +02:00
|
|
|
#ifndef UNIV_NONINL
|
|
|
|
#include "row0row.ic"
|
|
|
|
#endif
|
|
|
|
|
2006-02-23 20:25:29 +01:00
|
|
|
#endif
|