/********************************************************************* Creates the tuple with which the index entry is searched for writing the index tree root page number, if such a tree is created. */ static dtuple_t* dict_create_search_tuple( /*=====================*/ /* out: the tuple for search */ dtuple_t* tuple, /* in: the tuple inserted in the SYS_INDEXES table */ mem_heap_t* heap) /* in: memory heap from which the memory for the built tuple is allocated */ { dtuple_t* search_tuple; dfield_t* field1; dfield_t* field2; ut_ad(tuple && heap); search_tuple = dtuple_create(heap, 2); field1 = dtuple_get_nth_field(tuple, 0); field2 = dtuple_get_nth_field(search_tuple, 0); dfield_copy(field2, field1); field1 = dtuple_get_nth_field(tuple, 1); field2 = dtuple_get_nth_field(search_tuple, 1); dfield_copy(field2, field1); ut_ad(dtuple_validate(search_tuple)); return(search_tuple); }
dtuple_t* row_build_index_entry( /*==================*/ /* out: index entry which should be inserted */ dtuple_t* row, /* in: row which should be inserted to the table */ dict_index_t* index, /* in: index on the table */ mem_heap_t* heap) /* in: memory heap from which the memory for the index entry is allocated */ { dtuple_t* entry; ulint entry_len; dict_field_t* ind_field; dfield_t* dfield; dfield_t* dfield2; dict_col_t* col; ulint i; ut_ad(row && index && heap); ut_ad(dtuple_check_typed(row)); entry_len = dict_index_get_n_fields(index); entry = dtuple_create(heap, entry_len); if (index->type & DICT_UNIVERSAL) { dtuple_set_n_fields_cmp(entry, entry_len); } else { dtuple_set_n_fields_cmp(entry, dict_index_get_n_unique_in_tree(index)); } for (i = 0; i < entry_len; i++) { ind_field = dict_index_get_nth_field(index, i); col = ind_field->col; dfield = dtuple_get_nth_field(entry, i); dfield2 = dtuple_get_nth_field(row, dict_col_get_no(col)); dfield_copy(dfield, dfield2); /* If a column prefix index, take only the prefix */ if (ind_field->prefix_len > 0 && dfield_get_len(dfield2) != UNIV_SQL_NULL && dfield_get_len(dfield2) > ind_field->prefix_len) { dfield_set_len(dfield, ind_field->prefix_len); } } ut_ad(dtuple_check_typed(entry)); return(entry); }
void row_build_row_ref_from_row( /*=======================*/ dtuple_t* ref, /* in/out: row reference built; see the NOTE below! ref must have the right number of fields! */ dict_table_t* table, /* in: table */ dtuple_t* row) /* in: row NOTE: the data fields in ref will point directly into data of this row */ { dict_index_t* clust_index; dict_field_t* field; dfield_t* dfield; dfield_t* dfield2; dict_col_t* col; ulint ref_len; ulint i; ut_ad(ref && table && row); clust_index = dict_table_get_first_index(table); ref_len = dict_index_get_n_unique(clust_index); ut_ad(ref_len == dtuple_get_n_fields(ref)); for (i = 0; i < ref_len; i++) { dfield = dtuple_get_nth_field(ref, i); field = dict_index_get_nth_field(clust_index, i); col = dict_field_get_col(field); dfield2 = dtuple_get_nth_field(row, dict_col_get_no(col)); dfield_copy(dfield, dfield2); if (field->prefix_len > 0 && dfield->len != UNIV_SQL_NULL && dfield->len > field->prefix_len) { dfield->len = field->prefix_len; } } ut_ad(dtuple_check_typed(ref)); }
ibool dtuple_check_typed_no_assert( /*=========================*/ /* out: TRUE if ok */ dtuple_t* tuple) /* in: tuple */ { dfield_t* field; ulint i; if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) { fprintf(stderr, "InnoDB: Error: index entry has %lu fields\n", (ulong) dtuple_get_n_fields(tuple)); dump: fputs("InnoDB: Tuple contents: ", stderr); dtuple_print(stderr, tuple); putc('\n', stderr); return(FALSE); } 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); }
void row_upd_clust_index_replace_new_col_vals( /*=====================================*/ dtuple_t* entry, /* in/out: index entry where replaced */ upd_t* update) /* in: update vector */ { upd_field_t* upd_field; dfield_t* dfield; dfield_t* new_val; ulint field_no; ulint i; dtuple_set_info_bits(entry, update->info_bits); for (i = 0; i < upd_get_n_fields(update); i++) { upd_field = upd_get_nth_field(update, i); field_no = upd_field->field_no; dfield = dtuple_get_nth_field(entry, field_no); new_val = &(upd_field->new_val); dfield_set_data(dfield, new_val->data, new_val->len); } }
void dtuple_print( /*=========*/ FILE* f, /* in: output stream */ dtuple_t* tuple) /* in: tuple */ { dfield_t* field; ulint n_fields; ulint i; n_fields = dtuple_get_n_fields(tuple); fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields); for (i = 0; i < n_fields; i++) { fprintf(f, " %lu:", (ulong) i); field = dtuple_get_nth_field(tuple, i); if (field->len != UNIV_SQL_NULL) { ut_print_buf(f, field->data, field->len); } else { fputs(" SQL NULL", f); } putc(';', f); } putc('\n', f); ut_ad(dtuple_validate(tuple)); }
void row_upd_index_entry_sys_field( /*==========================*/ dtuple_t* entry, /* in: index entry, where the memory buffers for sys fields are already allocated: the function just copies the new values to them */ dict_index_t* index, /* in: clustered index */ ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */ dulint val) /* in: value to write */ { dfield_t* dfield; byte* field; ulint pos; ut_ad(index->type & DICT_CLUSTERED); pos = dict_index_get_sys_col_pos(index, type); dfield = dtuple_get_nth_field(entry, pos); field = dfield_get_data(dfield); if (type == DATA_TRX_ID) { trx_write_trx_id(field, val); } else { ut_ad(type == DATA_ROLL_PTR); trx_write_roll_ptr(field, val); } }
/**************************************************************//** Checks if a dtuple is a prefix of a record. The last field in dtuple is allowed to be a prefix of the corresponding field in the record. @return TRUE if prefix */ UNIV_INTERN ibool cmp_dtuple_is_prefix_of_rec( /*========================*/ const dtuple_t* dtuple, /*!< in: data tuple */ const rec_t* rec, /*!< in: physical record */ const ulint* offsets)/*!< in: array returned by rec_get_offsets() */ { ulint n_fields; ulint matched_fields = 0; ulint matched_bytes = 0; ut_ad(rec_offs_validate(rec, NULL, offsets)); n_fields = dtuple_get_n_fields(dtuple); if (n_fields > rec_offs_n_fields(offsets)) { return(FALSE); } cmp_dtuple_rec_with_match(dtuple, rec, offsets, &matched_fields, &matched_bytes); if (matched_fields == n_fields) { return(TRUE); } if (matched_fields == n_fields - 1 && matched_bytes == dfield_get_len( dtuple_get_nth_field(dtuple, n_fields - 1))) { return(TRUE); } return(FALSE); }
byte* trx_undo_rec_get_partial_row( /*=========================*/ /* out: pointer to remaining part of undo record */ byte* ptr, /* in: remaining part in update undo log record of a suitable type, at the start of the stored index columns; NOTE that this copy of the undo log record must be preserved as long as the partial row is used, as we do NOT copy the data in the record! */ dict_index_t* index, /* in: clustered index */ dtuple_t** row, /* out, own: partial row */ mem_heap_t* heap) /* in: memory heap from which the memory needed is allocated */ { dfield_t* dfield; byte* field; ulint len; ulint field_no; ulint col_no; ulint row_len; ulint total_len; byte* start_ptr; ulint i; ut_ad(index && ptr && row && heap); row_len = dict_table_get_n_cols(index->table); *row = dtuple_create(heap, row_len); dict_table_copy_types(*row, index->table); start_ptr = ptr; total_len = mach_read_from_2(ptr); ptr += 2; for (i = 0;; i++) { if (ptr == start_ptr + total_len) { break; } ptr = trx_undo_update_rec_get_field_no(ptr, &field_no); col_no = dict_index_get_nth_col_no(index, field_no); ptr = trx_undo_rec_get_col_val(ptr, &field, &len); dfield = dtuple_get_nth_field(*row, col_no); dfield_set_data(dfield, field, len); } return(ptr); }
/**********************************************************//** The following function prints the contents of a tuple. */ UNIV_INTERN void dtuple_print( /*=========*/ FILE* f, /*!< in: output stream */ const dtuple_t* tuple) /*!< in: tuple */ { ulint n_fields; ulint i; n_fields = dtuple_get_n_fields(tuple); fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields); for (i = 0; i < n_fields; i++) { fprintf(f, " %lu:", (ulong) i); dfield_print_raw(f, dtuple_get_nth_field(tuple, i)); putc(';', f); putc('\n', f); } ut_ad(dtuple_validate(tuple)); }
dtuple_t* row_rec_to_index_entry( /*===================*/ /* 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 */ dict_index_t* index, /* in: index */ 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! */ mem_heap_t* heap) /* in: memory heap from which the memory needed is allocated */ { dtuple_t* entry; dfield_t* dfield; ulint i; byte* field; ulint len; ulint rec_len; byte* buf; ut_ad(rec && heap && index); if (type == ROW_COPY_DATA) { /* Take a copy of rec to heap */ buf = mem_heap_alloc(heap, rec_get_size(rec)); rec = rec_copy(buf, rec); } rec_len = rec_get_n_fields(rec); entry = dtuple_create(heap, rec_len); dtuple_set_n_fields_cmp(entry, dict_index_get_n_unique_in_tree(index)); ut_ad(rec_len == dict_index_get_n_fields(index)); dict_index_copy_types(entry, index, rec_len); dtuple_set_info_bits(entry, rec_get_info_bits(rec)); for (i = 0; i < rec_len; i++) { dfield = dtuple_get_nth_field(entry, i); field = rec_get_nth_field(rec, i, &len); dfield_set_data(dfield, field, len); } ut_ad(dtuple_check_typed(entry)); return(entry); }
dfield_t* dtuple_get_nth_field_noninline( dtuple_t* tuple, /* in: tuple */ ulint n) /* in: index of field */ { return(dtuple_get_nth_field(tuple, n)); }
void rec_copy_prefix_to_dtuple( /*======================*/ dtuple_t* tuple, /* in: data tuple */ rec_t* rec, /* in: physical record */ ulint n_fields, /* in: number of fields to copy */ mem_heap_t* heap) /* in: memory heap */ { dfield_t* field; byte* data; ulint len; byte* buf = NULL; ulint i; ut_ad(rec_validate(rec)); ut_ad(dtuple_check_typed(tuple)); dtuple_set_info_bits(tuple, rec_get_info_bits(rec)); for (i = 0; i < n_fields; i++) { field = dtuple_get_nth_field(tuple, i); data = rec_get_nth_field(rec, i, &len); if (len != UNIV_SQL_NULL) { buf = mem_heap_alloc(heap, len); ut_memcpy(buf, data, len); } dfield_set_data(field, buf, len); } }
void dtuple_print( /*=========*/ dtuple_t* tuple) /* in: tuple */ { dfield_t* field; ulint n_fields; ulint i; n_fields = dtuple_get_n_fields(tuple); printf("DATA TUPLE: %lu fields;\n", n_fields); for (i = 0; i < n_fields; i++) { printf(" %lu:", i); field = dtuple_get_nth_field(tuple, i); if (field->len != UNIV_SQL_NULL) { ut_print_buf(field->data, field->len); } else { printf(" SQL NULL"); } printf(";"); } printf("\n"); dtuple_validate(tuple); }
upd_t* row_upd_build_sec_rec_difference_binary( /*====================================*/ /* out, own: update vector of differing fields */ dict_index_t* index, /* in: index */ dtuple_t* entry, /* in: entry to insert */ rec_t* rec, /* in: secondary index record */ mem_heap_t* heap) /* in: memory heap from which allocated */ { upd_field_t* upd_field; dfield_t* dfield; byte* data; ulint len; upd_t* update; ulint n_diff; ulint i; /* This function is used only for a secondary index */ ut_ad(0 == (index->type & DICT_CLUSTERED)); update = upd_create(dtuple_get_n_fields(entry), heap); n_diff = 0; for (i = 0; i < dtuple_get_n_fields(entry); i++) { data = rec_get_nth_field(rec, i, &len); dfield = dtuple_get_nth_field(entry, i); ut_a(len == dfield_get_len(dfield)); /* NOTE: we compare the fields as binary strings! (No collation) */ if (!dfield_data_is_binary_equal(dfield, len, data)) { upd_field = upd_get_nth_field(update, n_diff); dfield_copy(&(upd_field->new_val), dfield); upd_field_set_field_no(upd_field, i, index); upd_field->extern_storage = FALSE; n_diff++; } } update->n_fields = n_diff; return(update); }
ibool dtuple_datas_are_ordering_equal( /*============================*/ /* out: TRUE if length and fieds are equal when compared with cmp_data_data: NOTE: in character type fields some letters are identified with others! (collation) */ dtuple_t* tuple1, /* in: tuple 1 */ dtuple_t* tuple2) /* in: tuple 2 */ { dfield_t* field1; dfield_t* field2; ulint n_fields; ulint i; ut_ad(tuple1 && tuple2); ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N); ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N); ut_ad(dtuple_check_typed(tuple1)); ut_ad(dtuple_check_typed(tuple2)); n_fields = dtuple_get_n_fields(tuple1); if (n_fields != dtuple_get_n_fields(tuple2)) { return(FALSE); } for (i = 0; i < n_fields; i++) { field1 = dtuple_get_nth_field(tuple1, i); field2 = dtuple_get_nth_field(tuple2, i); if (0 != cmp_dfield_dfield(field1, field2)) { return(FALSE); } } return(TRUE); }
/*******************************************************************//** 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 */ UNIV_INTERN 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 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 */ { dtuple_t* entry; dfield_t* dfield; ulint i; const byte* field; ulint len; ulint rec_len; ut_ad(rec && heap && index); /* Because this function may be invoked by row0merge.c on a record whose header is in different format, the check rec_offs_validate(rec, index, offsets) must be avoided here. */ ut_ad(n_ext); *n_ext = 0; rec_len = rec_offs_n_fields(offsets); entry = dtuple_create(heap, rec_len); dtuple_set_n_fields_cmp(entry, dict_index_get_n_unique_in_tree(index)); ut_ad(rec_len == dict_index_get_n_fields(index)); dict_index_copy_types(entry, index, rec_len); for (i = 0; i < rec_len; i++) { dfield = dtuple_get_nth_field(entry, i); field = rec_get_nth_field(rec, offsets, i, &len); dfield_set_data(dfield, field, len); if (rec_offs_nth_extern(offsets, i)) { dfield_set_ext(dfield); (*n_ext)++; } } ut_ad(dtuple_check_typed(entry)); return(entry); }
ibool row_upd_changes_ord_field_binary( /*=============================*/ /* out: TRUE if update vector changes an ordering field in the index record; NOTE: the fields are compared as binary strings */ dtuple_t* row, /* in: old value of row, or NULL if the row and the data values in update are not known when this function is called, e.g., at compile time */ dict_index_t* index, /* in: index of the record */ upd_t* update) /* in: update vector for the row */ { upd_field_t* upd_field; dict_field_t* ind_field; dict_col_t* col; ulint n_unique; ulint n_upd_fields; ulint col_pos; ulint col_no; ulint i, j; ut_ad(update && index); n_unique = dict_index_get_n_unique(index); n_upd_fields = upd_get_n_fields(update); for (i = 0; i < n_unique; i++) { ind_field = dict_index_get_nth_field(index, i); col = dict_field_get_col(ind_field); col_pos = dict_col_get_clust_pos(col); col_no = dict_col_get_no(col); for (j = 0; j < n_upd_fields; j++) { upd_field = upd_get_nth_field(update, j); if (col_pos == upd_field->field_no && (row == NULL || !dfield_datas_are_binary_equal( dtuple_get_nth_field(row, col_no), &(upd_field->new_val)))) { return(TRUE); } } } return(FALSE); }
/************************************************************//** Compare two data tuples, respecting the collation of character fields. @return 1, 0 , -1 if tuple1 is greater, equal, less, respectively, than tuple2 */ UNIV_INTERN int dtuple_coll_cmp( /*============*/ const dtuple_t* tuple1, /*!< in: tuple 1 */ const dtuple_t* tuple2) /*!< in: tuple 2 */ { ulint n_fields; ulint i; ut_ad(tuple1 && tuple2); ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N); ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N); ut_ad(dtuple_check_typed(tuple1)); ut_ad(dtuple_check_typed(tuple2)); n_fields = dtuple_get_n_fields(tuple1); if (n_fields != dtuple_get_n_fields(tuple2)) { return(n_fields < dtuple_get_n_fields(tuple2) ? -1 : 1); } for (i = 0; i < n_fields; i++) { int cmp; const dfield_t* field1 = dtuple_get_nth_field(tuple1, i); const dfield_t* field2 = dtuple_get_nth_field(tuple2, i); cmp = cmp_dfield_dfield(field1, field2); if (cmp) { return(cmp); } } return(0); }
void row_build_to_tuple( /*===============*/ dtuple_t* row, /* in/out: row built; see the NOTE below! */ dict_index_t* index, /* in: clustered index */ rec_t* rec) /* in: record in the clustered index; NOTE: 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! NOTE 2: does not work with externally stored fields! */ { dict_table_t* table; ulint n_fields; ulint i; dfield_t* dfield; byte* field; ulint len; ulint row_len; dict_col_t* col; ut_ad(index && rec); ut_ad(index->type & DICT_CLUSTERED); table = index->table; row_len = dict_table_get_n_cols(table); dtuple_set_info_bits(row, rec_get_info_bits(rec)); n_fields = dict_index_get_n_fields(index); ut_ad(n_fields == rec_get_n_fields(rec)); dict_table_copy_types(row, table); for (i = 0; i < n_fields; i++) { col = dict_field_get_col(dict_index_get_nth_field(index, i)); dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); field = rec_get_nth_field(rec, i, &len); dfield_set_data(dfield, field, len); } ut_ad(dtuple_check_typed(row)); }
/********************************************************************//** Creates a cache of column prefixes of externally stored columns. @return own: column prefix cache */ UNIV_INTERN row_ext_t* row_ext_create( /*===========*/ ulint n_ext, /*!< in: number of externally stored columns */ const ulint* ext, /*!< in: col_no's of externally stored columns in the InnoDB table object, as reported by dict_col_get_no(); NOT relative to the records in the clustered index */ ulint flags, /*!< in: table->flags */ const dtuple_t* tuple, /*!< in: data tuple containing the field references of the externally stored columns; must be indexed by col_no; the clustered index record must be covered by a lock or a page latch to prevent deletion (rollback or purge). */ mem_heap_t* heap) /*!< in: heap where created */ { ulint i; ulint zip_size = dict_table_flags_to_zip_size(flags); row_ext_t* ret = mem_heap_alloc(heap, (sizeof *ret) + (n_ext - 1) * sizeof ret->len); ut_ad(ut_is_2pow(zip_size)); ut_ad(zip_size <= UNIV_PAGE_SIZE); ret->n_ext = n_ext; ret->ext = ext; ret->max_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags); ret->buf = mem_heap_alloc(heap, n_ext * ret->max_len); #ifdef UNIV_DEBUG memset(ret->buf, 0xaa, n_ext * ret->max_len); UNIV_MEM_ALLOC(ret->buf, n_ext * ret->max_len); #endif /* Fetch the BLOB prefixes */ for (i = 0; i < n_ext; i++) { const dfield_t* dfield; dfield = dtuple_get_nth_field(tuple, ext[i]); row_ext_cache_fill(ret, i, zip_size, dfield); } return(ret); }
/**********************************************************//** Validates the consistency of a tuple which must be complete, i.e, all fields must have been set. @return TRUE if ok */ UNIV_INTERN ibool dtuple_validate( /*============*/ const dtuple_t* tuple) /*!< in: tuple */ { const dfield_t* field; ulint n_fields; ulint len; ulint i; ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); n_fields = dtuple_get_n_fields(tuple); /* We dereference all the data of each field to test for memory traps */ for (i = 0; i < n_fields; i++) { field = dtuple_get_nth_field(tuple, i); len = dfield_get_len(field); if (!dfield_is_null(field)) { const byte* data = dfield_get_data(field); #ifndef UNIV_DEBUG_VALGRIND ulint j; for (j = 0; j < len; j++) { data_dummy += *data; /* fool the compiler not to optimize out this code */ data++; } #endif /* !UNIV_DEBUG_VALGRIND */ UNIV_MEM_ASSERT_RW(data, len); } } ut_a(dtuple_check_typed(tuple)); return(TRUE); }
ibool dtuple_check_typed( /*===============*/ /* out: TRUE if ok */ dtuple_t* tuple) /* in: tuple */ { 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); }
/**********************************************************//** Checks that a data tuple is typed. Asserts an error if not. @return TRUE if ok */ UNIV_INTERN 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); }
ulint dtuple_sprintf( /*===========*/ /* out: printed length in bytes */ char* buf, /* in: print buffer */ ulint buf_len,/* in: buf length in bytes */ dtuple_t* tuple) /* in: tuple */ { dfield_t* field; ulint n_fields; ulint len; ulint i; len = 0; n_fields = dtuple_get_n_fields(tuple); for (i = 0; i < n_fields; i++) { if (len + 30 > buf_len) { return(len); } len += sprintf(buf + len, " %lu:", i); field = dtuple_get_nth_field(tuple, i); if (field->len != UNIV_SQL_NULL) { if (5 * field->len + len + 30 > buf_len) { return(len); } len += ut_sprintf_buf(buf + len, field->data, field->len); } else { len += sprintf(buf + len, " SQL NULL"); } len += sprintf(buf + len, ";"); } return(len); }
ibool dtuple_validate( /*============*/ /* out: TRUE if ok */ dtuple_t* tuple) /* in: tuple */ { dfield_t* field; byte* data; ulint n_fields; ulint len; ulint i; ulint j; ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N); n_fields = dtuple_get_n_fields(tuple); /* We dereference all the data of each field to test for memory traps */ for (i = 0; i < n_fields; i++) { field = dtuple_get_nth_field(tuple, i); len = dfield_get_len(field); if (len != UNIV_SQL_NULL) { data = field->data; for (j = 0; j < len; j++) { data_dummy += *data; /* fool the compiler not to optimize out this code */ data++; } } } ut_a(dtuple_check_typed(tuple)); return(TRUE); }
/*******************************************************************//** Builds a row reference from an undo log record. @return pointer to remaining part of undo record */ UNIV_INTERN byte* trx_undo_rec_get_row_ref( /*=====================*/ byte* ptr, /*!< in: remaining part of a copy of an undo log record, at the start of the row reference; NOTE that this copy of the undo log record must be preserved as long as the row reference is used, as we do NOT copy the data in the record! */ dict_index_t* index, /*!< in: clustered index */ dtuple_t** ref, /*!< out, own: row reference */ mem_heap_t* heap) /*!< in: memory heap from which the memory needed is allocated */ { ulint ref_len; ulint i; ut_ad(index && ptr && ref && heap); ut_a(dict_index_is_clust(index)); ref_len = dict_index_get_n_unique(index); *ref = dtuple_create(heap, ref_len); dict_index_copy_types(*ref, index, ref_len); for (i = 0; i < ref_len; i++) { dfield_t* dfield; byte* field; ulint len; ulint orig_len; dfield = dtuple_get_nth_field(*ref, i); ptr = trx_undo_rec_get_col_val(ptr, &field, &len, &orig_len); dfield_set_data(dfield, field, len); } return(ptr); }
ibool dtuple_check_typed_no_assert( /*=========================*/ /* out: TRUE if ok */ dtuple_t* tuple) /* in: tuple */ { dfield_t* field; ulint i; char err_buf[1000]; if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) { fprintf(stderr, "InnoDB: Error: index entry has %lu fields\n", dtuple_get_n_fields(tuple)); dtuple_sprintf(err_buf, 900, tuple); fprintf(stderr, "InnoDB: Tuple contents: %s\n", err_buf); return(FALSE); } for (i = 0; i < dtuple_get_n_fields(tuple); i++) { field = dtuple_get_nth_field(tuple, i); if (!dfield_check_typed_no_assert(field)) { dtuple_sprintf(err_buf, 900, tuple); fprintf(stderr, "InnoDB: Tuple contents: %s\n", err_buf); return(FALSE); } } return(TRUE); }
void row_upd_index_replace_new_col_vals( /*===============================*/ dtuple_t* entry, /* in/out: index entry where replaced */ dict_index_t* index, /* in: index; NOTE that may also be a non-clustered index */ upd_t* update) /* in: update vector */ { upd_field_t* upd_field; dfield_t* dfield; dfield_t* new_val; ulint field_no; dict_index_t* clust_index; ulint i; ut_ad(index); clust_index = dict_table_get_first_index(index->table); dtuple_set_info_bits(entry, update->info_bits); for (i = 0; i < upd_get_n_fields(update); i++) { upd_field = upd_get_nth_field(update, i); field_no = dict_index_get_nth_col_pos(index, dict_index_get_nth_col_no(clust_index, upd_field->field_no)); if (field_no != ULINT_UNDEFINED) { dfield = dtuple_get_nth_field(entry, field_no); new_val = &(upd_field->new_val); dfield_set_data(dfield, new_val->data, new_val->len); } } }
/********************************************************************* Based on an index object, this function builds the entry to be inserted in the SYS_FIELDS system table. */ static dtuple_t* dict_create_sys_fields_tuple( /*=========================*/ /* out: the tuple which should be inserted */ dict_index_t* index, /* in: index */ ulint i, /* in: field number */ mem_heap_t* heap) /* in: memory heap from which the memory for the built tuple is allocated */ { dict_table_t* sys_fields; dtuple_t* entry; dict_field_t* field; dfield_t* dfield; byte* ptr; ibool index_contains_column_prefix_field = FALSE; ulint j; ut_ad(index && heap); for (j = 0; j < index->n_fields; j++) { if (dict_index_get_nth_field(index, j)->prefix_len > 0) { index_contains_column_prefix_field = TRUE; } } field = dict_index_get_nth_field(index, i); sys_fields = dict_sys->sys_fields; entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS); /* 0: INDEX_ID -----------------------*/ dfield = dtuple_get_nth_field(entry, 0); ptr = mem_heap_alloc(heap, 8); mach_write_to_8(ptr, index->id); dfield_set_data(dfield, ptr, 8); /* 1: POS + PREFIX LENGTH ----------------------------*/ dfield = dtuple_get_nth_field(entry, 1); ptr = mem_heap_alloc(heap, 4); if (index_contains_column_prefix_field) { /* If there are column prefix fields in the index, then we store the number of the field to the 2 HIGH bytes and the prefix length to the 2 low bytes, */ mach_write_to_4(ptr, (i << 16) + field->prefix_len); } else { /* Else we store the number of the field to the 2 LOW bytes. This is to keep the storage format compatible with InnoDB versions < 4.0.14. */ mach_write_to_4(ptr, i); } dfield_set_data(dfield, ptr, 4); /* 4: COL_NAME -------------------------*/ dfield = dtuple_get_nth_field(entry, 2); dfield_set_data(dfield, field->name, ut_strlen(field->name)); /*---------------------------------*/ dict_table_copy_types(entry, sys_fields); return(entry); }