#ifdef UNIV_DEBUG /** Dummy variable to catch access to uninitialized fields. In the debugversion,dtuple_create()willmakeallfieldsofdtuple_tpoint
to data_error. */
ut_d(byte data_error); #endif/* UNIV_DEBUG */
/** Trim the tail of an index tuple before insert or update. AfterinstantADDCOLUMN,ifthelastfieldsofaclusteredindextuple matchthedefaultvaluesthatwereexplicitlyspecifiedorimpliedduring ADDCOLUMN,therewillbenoneedtostorethem. NOTE:Apagelatchintheindexmustbeheld,sothattheindex maynotlose'instantness'beforethetrimmedtuplehasbeen insertedorupdated.
@param[in] index index possibly with instantly added columns */ void dtuple_t::trim(const dict_index_t& index)
{
ut_ad(n_fields >= index.n_core_fields);
ut_ad(n_fields <= index.n_fields);
ut_ad(index.is_instant());
ulint i = n_fields; for (; i > index.n_core_fields; i--) { const dfield_t* dfield = dtuple_get_nth_field(this, i - 1); const dict_col_t* col = dict_index_get_nth_col(&index, i - 1);
if (col->is_dropped()) { continue;
}
ut_ad(col->is_added());
ulint len = dfield_get_len(dfield); if (len != col->def_val.len) { break;
}
if (len != 0 && len != UNIV_SQL_NULL
&& dfield->data != col->def_val.data
&& memcmp(dfield->data, col->def_val.data, len)) { break;
}
}
n_fields = uint16_t(i);
}
/**********************************************************//**
Checks that a data field is typed.
@returnTRUEif ok */ static
ibool
dfield_check_typed_no_assert( /*=========================*/ const dfield_t* field) /*!< in: data field */
{ if (dfield_get_type(field)->mtype > DATA_MTYPE_CURRENT_MAX
|| dfield_get_type(field)->mtype < DATA_MTYPE_CURRENT_MIN) {
ib::error() << "Data field type "
<< dfield_get_type(field)->mtype
<< ", len " << dfield_get_len(field);
return(FALSE);
}
return(TRUE);
}
/**********************************************************//**
Checks that a data tuple is typed.
@returnTRUEif ok */ static
ibool
dtuple_check_typed_no_assert( /*=========================*/ const dtuple_t* tuple) /*!< in: tuple */
{ const dfield_t* field;
ulint i;
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
field = dtuple_get_nth_field(tuple, i);
if (!dfield_check_typed_no_assert(field)) { goto dump;
}
}
return(TRUE);
}
#ifdef UNIV_DEBUG /**********************************************************//**
Checks that a data field is typed. Asserts an error ifnot.
@returnTRUEif ok */
ibool
dfield_check_typed( /*===============*/ const dfield_t* field) /*!< in: data field */
{ if (dfield_get_type(field)->mtype > DATA_MTYPE_CURRENT_MAX
|| dfield_get_type(field)->mtype < DATA_MTYPE_CURRENT_MIN) {
ib::fatal() << "Data field type "
<< dfield_get_type(field)->mtype
<< ", len " << dfield_get_len(field);
}
return(TRUE);
}
/**********************************************************//**
Checks that a data tuple is typed. Asserts an error ifnot.
@returnTRUEif ok */
ibool
dtuple_check_typed( /*===============*/ const dtuple_t* tuple) /*!< in: tuple */
{ const dfield_t* field;
ulint i;
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
field = dtuple_get_nth_field(tuple, i);
ut_a(dfield_check_typed(field));
}
return(TRUE);
}
/**********************************************************//**
Validates the consistency of a tuple which must be complete, i.e,
all fields must have been set.
@returnTRUEif ok */
ibool
dtuple_validate( /*============*/ const dtuple_t* tuple) /*!< in: tuple */
{
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); #ifdef HAVE_valgrind const ulint n_fields = dtuple_get_n_fields(tuple);
for (ulint i = 0; i < n_fields; i++) { const dfield_t* field = dtuple_get_nth_field(tuple, i);
/*************************************************************//**
Pretty prints a dfield value according to its data type. */ void
dfield_print( /*=========*/ const dfield_t* dfield) /*!< in: dfield */
{ const byte* data;
ulint len;
ulint i;
len = dfield_get_len(dfield);
data = static_cast<const byte*>(dfield_get_data(dfield));
if (dfield_is_null(dfield)) {
fputs("NULL", stderr);
return;
}
switch (dtype_get_mtype(dfield_get_type(dfield))) { case DATA_CHAR: case DATA_VARCHAR: for (i = 0; i < len; i++) { int c = *data++;
putc(isprint(c) ? c : ' ', stderr);
}
if (dfield_is_ext(dfield)) {
fputs("(external)", stderr);
} break; case DATA_INT:
ut_a(len == 4); /* only works for 32-bit integers */
fprintf(stderr, "%d", (int) mach_read_from_4(data)); break; default:
ut_error;
}
}
/*************************************************************//**
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 */
{ const byte* data;
ulint len;
ulint prtype;
ulint i;
ibool print_also_hex;
len = dfield_get_len(dfield);
data = static_cast<const byte*>(dfield_get_data(dfield));
if (dfield_is_null(dfield)) {
fputs("NULL", stderr);
/**********************************************************//**
The following function prints the contents of a tuple. */ void
dtuple_print( /*=========*/
FILE* f, /*!< in: output stream */ const dtuple_t* tuple) /*!< in: tuple */
{
ulint n_fields;
ulint i;
/** Print the contents of a tuple. @param[out]ooutputstream @param[in]fieldarrayofdatafields
@param[in] n number of data fields */ void
dfield_print(
std::ostream& o, const dfield_t* field,
ulint n)
{ for (ulint i = 0; i < n; i++, field++) { constvoid* data = dfield_get_data(field); const ulint len = dfield_get_len(field);
if (i) {
o << ',';
}
if (dfield_is_null(field)) {
o << "NULL";
} elseif (dfield_is_ext(field)) {
ulint local_len = len - BTR_EXTERN_FIELD_REF_SIZE;
ut_ad(len >= BTR_EXTERN_FIELD_REF_SIZE);
/** Print the contents of a tuple. @param[out]ooutputstream
@param[in] tuple data tuple */ void
dtuple_print(
std::ostream& o, const dtuple_t* tuple)
{ const ulint n = dtuple_get_n_fields(tuple);
o << "TUPLE (info_bits=" << dtuple_get_info_bits(tuple)
<< ", " << n << " fields): {";
dfield_print(o, tuple->fields, n);
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 */
{
mem_heap_t* heap;
big_rec_t* vector;
dfield_t* dfield;
ulint size;
ulint local_prefix_len;
if (!dict_index_is_clust(index)) { return(NULL);
}
if (!dict_table_has_atomic_blobs(index->table)) { /* up to MySQL 5.1: store a 768-byte prefix locally */
local_len = BTR_EXTERN_FIELD_REF_SIZE
+ DICT_ANTELOPE_MAX_INDEX_COL_LEN;
} else { /* new-format table: do not store any BLOB prefix locally */
local_len = BTR_EXTERN_FIELD_REF_SIZE;
}
while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry,
*n_ext),
index->table->not_redundant(),
dict_index_get_n_fields(index),
zip_size)) {
longest_i = 0;
longest = 0; for (uint16_t i = index->first_user_field();
i < entry->n_fields - mblob; i++) {
ulint savings;
dfield = dtuple_get_nth_field(entry, i + mblob);
/* Check that there would be savings */ if (longest >= savings) { goto skip_field;
}
/* In DYNAMIC and COMPRESSED format, store locallyanynon-BLOBcolumnswhosemaximum lengthdoesnotexceed256bytes.Thisis becausethereisnoroomforthe"external storage"flagwhenthemaximumlengthis255 bytesorless.Thisrestrictiontrivially holdsinREDUNDANTandCOMPACTformat,because therewealwaysstorelocallycolumnswhose lengthisuptolocal_len==788bytes.
@see rec_init_offsets_comp_ordinary */ if (!DATA_BIG_COL(ifield->col)) { goto skip_field;
}
/**************************************************************//**
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 MY_ATTRIBUTE((unused)), /*!< in: index */
dtuple_t* entry, /*!< in/out: entry whose data was put to vector */
big_rec_t* vector) /*!< in, own: big rec vector; it is
freed in this function */
{
big_rec_field_t* b = vector->fields; const big_rec_field_t* const end = b + vector->n_fields;
for (; b < end; b++) {
dfield_t* dfield;
ulint local_len;
/* Only in REDUNDANT and COMPACT format, we store uptoDICT_ANTELOPE_MAX_INDEX_COL_LEN(768)bytes
locally */
ut_ad(local_len <= DICT_ANTELOPE_MAX_INDEX_COL_LEN);
/** Allocate a big_rec_t object in the given memory heap, and for storing n_fldnumberoffields. @param[in]heapmemoryheapinwhichthisobjectisallocated @param[in]n_fldmaximumnumberoffieldsthatcanbestoredin thisobject
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.