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); }
/*************************************************************** Stores to the heap the row on which the node->pcur is positioned. */ static void row_upd_store_row( /*==============*/ upd_node_t* node) /* in: row update node */ { dict_index_t* clust_index; upd_t* update; rec_t* rec; ut_ad(node->pcur->latch_mode != BTR_NO_LATCHES); if (node->row != NULL) { mem_heap_empty(node->heap); node->row = NULL; } clust_index = dict_table_get_first_index(node->table); rec = btr_pcur_get_rec(node->pcur); node->row = row_build(ROW_COPY_DATA, clust_index, rec, node->heap); node->ext_vec = mem_heap_alloc(node->heap, sizeof(ulint) * rec_get_n_fields(rec)); if (node->is_delete) { update = NULL; } else { update = node->update; } node->n_ext_vec = btr_push_update_extern_fields(node->ext_vec, rec, update); }
void rec_set_nth_field_extern_bit( /*=========================*/ rec_t* rec, /* in: record */ ulint i, /* in: ith field */ ibool val, /* in: value to set */ mtr_t* mtr) /* in: mtr holding an X-latch to the page where rec is, or NULL; in the NULL case we do not write to log about the change */ { ulint info; ut_a(!rec_get_1byte_offs_flag(rec)); ut_a(i < rec_get_n_fields(rec)); info = rec_2_get_field_end_info(rec, i); if (val) { info = info | REC_2BYTE_EXTERN_MASK; } else { info = info & ~REC_2BYTE_EXTERN_MASK; } if (mtr) { mlog_write_ulint(rec - REC_N_EXTRA_BYTES - 2 * (i + 1), info, MLOG_2BYTES, mtr); } else { rec_2_set_field_end_info(rec, i, info); } }
byte* rec_get_nth_field( /*==============*/ /* out: pointer to the field */ rec_t* rec, /* in: record */ ulint n, /* in: index of the field */ ulint* len) /* out: length of the field; UNIV_SQL_NULL if SQL null */ { ulint os; ulint next_os; ut_ad(rec && len); ut_ad(n < rec_get_n_fields(rec)); if (n > 1024) { fprintf(stderr, "Error: trying to access field %lu in rec\n", n); ut_a(0); } if (rec == NULL) { fprintf(stderr, "Error: rec is NULL pointer\n"); ut_a(0); } if (rec_get_1byte_offs_flag(rec)) { os = rec_1_get_field_start_offs(rec, n); next_os = rec_1_get_field_end_info(rec, n); if (next_os & REC_1BYTE_SQL_NULL_MASK) { *len = UNIV_SQL_NULL; return(rec + os); } next_os = next_os & ~REC_1BYTE_SQL_NULL_MASK; } else { os = rec_2_get_field_start_offs(rec, n); next_os = rec_2_get_field_end_info(rec, n); if (next_os & REC_2BYTE_SQL_NULL_MASK) { *len = UNIV_SQL_NULL; return(rec + os); } next_os = next_os & ~(REC_2BYTE_SQL_NULL_MASK | REC_2BYTE_EXTERN_MASK); } *len = next_os - os; ut_ad(*len < UNIV_PAGE_SIZE); return(rec + os); }
ibool rec_validate( /*=========*/ /* out: TRUE if ok */ rec_t* rec) /* in: physical record */ { byte* data; ulint len; ulint n_fields; ulint len_sum = 0; ulint sum = 0; ulint i; ut_a(rec); n_fields = rec_get_n_fields(rec); if ((n_fields == 0) || (n_fields > REC_MAX_N_FIELDS)) { fprintf(stderr, "InnoDB: Error: record has %lu fields\n", n_fields); return(FALSE); } for (i = 0; i < n_fields; i++) { data = rec_get_nth_field(rec, i, &len); if (!((len < UNIV_PAGE_SIZE) || (len == UNIV_SQL_NULL))) { fprintf(stderr, "InnoDB: Error: record field %lu len %lu\n", i, len); return(FALSE); } if (len != UNIV_SQL_NULL) { len_sum += len; sum += *(data + len -1); /* dereference the end of the field to cause a memory trap if possible */ } else { len_sum += rec_get_nth_field_size(rec, i); } } if (len_sum != (ulint)(rec_get_end(rec) - rec)) { fprintf(stderr, "InnoDB: Error: record len should be %lu, len %lu\n", len_sum, (ulint)(rec_get_end(rec) - rec)); return(FALSE); } rec_dummy = sum; /* This is here only to fool the compiler */ return(TRUE); }
ulint rec_sprintf( /*========*/ /* out: printed length in bytes */ char* buf, /* in: buffer to print to */ ulint buf_len,/* in: buffer length */ rec_t* rec) /* in: physical record */ { byte* data; ulint len; ulint k; ulint n; ulint i; ut_ad(rec); n = rec_get_n_fields(rec); k = 0; if (k + 30 > buf_len) { return(k); } k += sprintf(buf + k, "RECORD: info bits %lu", rec_get_info_bits(rec)); for (i = 0; i < n; i++) { if (k + 30 > buf_len) { return(k); } data = rec_get_nth_field(rec, i, &len); k += sprintf(buf + k, " %lu:", i); if (len != UNIV_SQL_NULL) { if (k + 30 + 5 * len > buf_len) { return(k); } k += ut_sprintf_buf(buf + k, data, len); } else { k += sprintf(buf + k, " SQL NULL"); } k += sprintf(buf + k, ";"); } return(k); }
void rec_print( /*======*/ rec_t* rec) /* in: physical record */ { byte* data; ulint len; char* offs; ulint n; ulint i; ut_ad(rec); if (rec_get_1byte_offs_flag(rec)) { offs = "TRUE"; } else { offs = "FALSE"; } n = rec_get_n_fields(rec); printf( "PHYSICAL RECORD: n_fields %lu; 1-byte offs %s; info bits %lu\n", n, offs, rec_get_info_bits(rec)); for (i = 0; i < n; i++) { data = rec_get_nth_field(rec, i, &len); printf(" %lu:", i); if (len != UNIV_SQL_NULL) { if (len <= 30) { ut_print_buf(data, len); } else { ut_print_buf(data, 30); printf("...(truncated)"); } } else { printf(" SQL NULL, size %lu ", rec_get_nth_field_size(rec, i)); } printf(";"); } printf("\n"); rec_validate(rec); }
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)); }
dtuple_t* row_build( /*======*/ /* out, own: row built; see the NOTE below! */ ulint type, /* in: ROW_COPY_POINTERS, ROW_COPY_DATA, or ROW_COPY_ALSO_EXTERNALS, the two last copy also the data fields to heap as the first only places pointers to data fields on the index page, and thus is more efficient */ dict_index_t* index, /* in: clustered index */ 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! */ mem_heap_t* heap) /* in: memory heap from which the memory needed is allocated */ { dtuple_t* row; dict_table_t* table; dict_field_t* ind_field; dict_col_t* col; dfield_t* dfield; ulint n_fields; byte* field; ulint len; ulint row_len; byte* buf; ulint i; ut_ad(index && rec && heap); ut_ad(index->type & DICT_CLUSTERED); if (type != ROW_COPY_POINTERS) { /* Take a copy of rec to heap */ buf = mem_heap_alloc(heap, rec_get_size(rec)); rec = rec_copy(buf, rec); } table = index->table; row_len = dict_table_get_n_cols(table); row = dtuple_create(heap, row_len); 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++) { ind_field = dict_index_get_nth_field(index, i); if (ind_field->prefix_len == 0) { col = dict_field_get_col(ind_field); dfield = dtuple_get_nth_field(row, dict_col_get_no(col)); field = rec_get_nth_field(rec, i, &len); if (type == ROW_COPY_ALSO_EXTERNALS && rec_get_nth_field_extern_bit(rec, i)) { field = btr_rec_copy_externally_stored_field( rec, i, &len, heap); } dfield_set_data(dfield, field, len); } } ut_ad(dtuple_check_typed(row)); return(row); }