ibool row_upd_changes_field_size( /*=======================*/ /* out: TRUE if the update changes the size of some field in index */ rec_t* rec, /* in: record in clustered index */ dict_index_t* index, /* in: clustered index */ upd_t* update) /* in: update vector */ { upd_field_t* upd_field; dfield_t* new_val; ulint old_len; ulint new_len; ulint n_fields; ulint i; ut_ad(index->type & DICT_CLUSTERED); n_fields = upd_get_n_fields(update); for (i = 0; i < n_fields; i++) { upd_field = upd_get_nth_field(update, i); new_val = &(upd_field->new_val); new_len = new_val->len; if (new_len == UNIV_SQL_NULL) { new_len = dtype_get_sql_null_size( dict_index_get_nth_type(index, i)); } old_len = rec_get_nth_field_size(rec, upd_field->field_no); if (old_len != new_len) { return(TRUE); } if (rec_get_nth_field_extern_bit(rec, upd_field->field_no)) { return(TRUE); } if (upd_field->extern_storage) { return(TRUE); } } return(FALSE); }
big_rec_t* dtuple_convert_big_rec( /*===================*/ /* out, own: created big record vector, NULL if we are not able to shorten the entry enough, i.e., if there are too many short fields in entry */ dict_index_t* index, /* in: index */ dtuple_t* entry, /* in: index entry */ ulint* ext_vec,/* in: array of externally stored fields, or NULL: if a field already is externally stored, then we cannot move it to the vector this function returns */ ulint n_ext_vec)/* in: number of elements is ext_vec */ { mem_heap_t* heap; big_rec_t* vector; dfield_t* dfield; ulint size; ulint n_fields; ulint longest; ulint longest_i = ULINT_MAX; ibool is_externally_stored; ulint i; ulint j; char err_buf[1000]; ut_a(dtuple_check_typed_no_assert(entry)); size = rec_get_converted_size(entry); if (size > 1000000000) { fprintf(stderr, "InnoDB: Warning: tuple size very big: %lu\n", size); dtuple_sprintf(err_buf, 900, entry); fprintf(stderr, "InnoDB: Tuple contents: %s\n", err_buf); } heap = mem_heap_create(size + dtuple_get_n_fields(entry) * sizeof(big_rec_field_t) + 1000); vector = mem_heap_alloc(heap, sizeof(big_rec_t)); vector->heap = heap; vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry) * sizeof(big_rec_field_t)); /* Decide which fields to shorten: the algorithm is to look for the longest field whose type is DATA_BLOB */ n_fields = 0; while ((rec_get_converted_size(entry) >= page_get_free_space_of_empty() / 2) || rec_get_converted_size(entry) >= REC_MAX_DATA_SIZE) { longest = 0; for (i = dict_index_get_n_unique_in_tree(index); i < dtuple_get_n_fields(entry); i++) { /* Skip over fields which already are externally stored */ is_externally_stored = FALSE; if (ext_vec) { for (j = 0; j < n_ext_vec; j++) { if (ext_vec[j] == i) { is_externally_stored = TRUE; } } } if (!is_externally_stored && dict_index_get_nth_type(index, i)->mtype == DATA_BLOB) { dfield = dtuple_get_nth_field(entry, i); if (dfield->len != UNIV_SQL_NULL && dfield->len > longest) { longest = dfield->len; longest_i = i; } } } /* We do not store externally fields which are smaller than DICT_MAX_COL_PREFIX_LEN */ ut_a(DICT_MAX_COL_PREFIX_LEN > REC_1BYTE_OFFS_LIMIT); if (longest < BTR_EXTERN_FIELD_REF_SIZE + 10 + DICT_MAX_COL_PREFIX_LEN) { /* Cannot shorten more */ mem_heap_free(heap); return(NULL); } /* Move data from field longest_i to big rec vector; we do not let data size of the remaining entry drop below 128 which is the limit for the 2-byte offset storage format in a physical record. This we accomplish by storing 128 bytes of data in entry itself, and only the remaining part to big rec vec. We store the first bytes locally to the record. Then we can calculate all ordering fields in all indexes from locally stored data. */ dfield = dtuple_get_nth_field(entry, longest_i); vector->fields[n_fields].field_no = longest_i; ut_a(dfield->len > DICT_MAX_COL_PREFIX_LEN); vector->fields[n_fields].len = dfield->len - DICT_MAX_COL_PREFIX_LEN; vector->fields[n_fields].data = mem_heap_alloc(heap, vector->fields[n_fields].len); /* Copy data (from the end of field) to big rec vector */ ut_memcpy(vector->fields[n_fields].data, ((byte*)dfield->data) + dfield->len - vector->fields[n_fields].len, vector->fields[n_fields].len); dfield->len = dfield->len - vector->fields[n_fields].len + BTR_EXTERN_FIELD_REF_SIZE; /* Set the extern field reference in dfield to zero */ memset(((byte*)dfield->data) + dfield->len - BTR_EXTERN_FIELD_REF_SIZE, 0, BTR_EXTERN_FIELD_REF_SIZE); n_fields++; } vector->n_fields = n_fields; return(vector); }