diff options
Diffstat (limited to 'storage/innobase/data/data0data.c')
-rw-r--r-- | storage/innobase/data/data0data.c | 681 |
1 files changed, 0 insertions, 681 deletions
diff --git a/storage/innobase/data/data0data.c b/storage/innobase/data/data0data.c deleted file mode 100644 index 0f03de4ca9d..00000000000 --- a/storage/innobase/data/data0data.c +++ /dev/null @@ -1,681 +0,0 @@ -/************************************************************************ -SQL data field and tuple - -(c) 1994-1996 Innobase Oy - -Created 5/30/1994 Heikki Tuuri -*************************************************************************/ - -#include "data0data.h" - -#ifdef UNIV_NONINL -#include "data0data.ic" -#endif - -#include "rem0rec.h" -#include "rem0cmp.h" -#include "page0page.h" -#include "dict0dict.h" -#include "btr0cur.h" - -#include <ctype.h> - -#ifdef UNIV_DEBUG -byte data_error; /* data pointers of tuple fields are initialized - to point here for error checking */ - -ulint data_dummy; /* this is used to fool the compiler in - dtuple_validate */ -#endif /* UNIV_DEBUG */ - -/* Some non-inlined functions used in the MySQL interface: */ -void -dfield_set_data_noninline( - dfield_t* field, /* in: field */ - void* data, /* in: data */ - ulint len) /* in: length or UNIV_SQL_NULL */ -{ - dfield_set_data(field, data, len); -} -void* -dfield_get_data_noninline( - dfield_t* field) /* in: field */ -{ - return(dfield_get_data(field)); -} -ulint -dfield_get_len_noninline( - dfield_t* field) /* in: field */ -{ - return(dfield_get_len(field)); -} -ulint -dtuple_get_n_fields_noninline( - dtuple_t* tuple) /* in: tuple */ -{ - return(dtuple_get_n_fields(tuple)); -} -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)); -} - -/************************************************************************* -Tests if dfield data length and content is equal to the given. */ - -ibool -dfield_data_is_binary_equal( -/*========================*/ - /* out: TRUE if equal */ - dfield_t* field, /* in: field */ - ulint len, /* in: data length or UNIV_SQL_NULL */ - byte* data) /* in: data */ -{ - if (len != field->len) { - - return(FALSE); - } - - if (len == UNIV_SQL_NULL) { - - return(TRUE); - } - - if (0 != ut_memcmp(field->data, data, len)) { - - return(FALSE); - } - - return(TRUE); -} - -/**************************************************************** -Returns TRUE if lengths of two dtuples are equal and respective data fields -in them are equal when compared with collation in char fields (not as binary -strings). */ - -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); -} - -/************************************************************************* -Creates a dtuple for use in MySQL. */ - -dtuple_t* -dtuple_create_for_mysql( -/*====================*/ - /* out, own created dtuple */ - void** heap, /* out: created memory heap */ - ulint n_fields) /* in: number of fields */ -{ - *heap = (void*)mem_heap_create(500); - - return(dtuple_create(*((mem_heap_t**)heap), n_fields)); -} - -/************************************************************************* -Frees a dtuple used in MySQL. */ - -void -dtuple_free_for_mysql( -/*==================*/ - void* heap) /* in: memory heap where tuple was created */ -{ - mem_heap_free((mem_heap_t*)heap); -} - -/************************************************************************* -Sets number of fields used in a tuple. Normally this is set in -dtuple_create, but if you want later to set it smaller, you can use this. */ - -void -dtuple_set_n_fields( -/*================*/ - dtuple_t* tuple, /* in: tuple */ - ulint n_fields) /* in: number of fields */ -{ - ut_ad(tuple); - - tuple->n_fields = n_fields; - tuple->n_fields_cmp = n_fields; -} - -/************************************************************** -Checks that a data field is typed. */ -static -ibool -dfield_check_typed_no_assert( -/*=========================*/ - /* out: TRUE if ok */ - dfield_t* field) /* in: data field */ -{ - if (dfield_get_type(field)->mtype > DATA_MYSQL - || dfield_get_type(field)->mtype < DATA_VARCHAR) { - - fprintf(stderr, - "InnoDB: Error: data field type %lu, len %lu\n", - (ulong) dfield_get_type(field)->mtype, - (ulong) dfield_get_len(field)); - return(FALSE); - } - - return(TRUE); -} - -/************************************************************** -Checks that a data tuple is typed. */ - -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); -} - -/************************************************************** -Checks that a data field is typed. Asserts an error if not. */ - -ibool -dfield_check_typed( -/*===============*/ - /* out: TRUE if ok */ - dfield_t* field) /* in: data field */ -{ - if (dfield_get_type(field)->mtype > DATA_MYSQL - || dfield_get_type(field)->mtype < DATA_VARCHAR) { - - fprintf(stderr, - "InnoDB: Error: data field type %lu, len %lu\n", - (ulong) dfield_get_type(field)->mtype, - (ulong) dfield_get_len(field)); - - ut_error; - } - - return(TRUE); -} - -/************************************************************** -Checks that a data tuple is typed. Asserts an error if not. */ - -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); -} - -#ifdef UNIV_DEBUG -/************************************************************** -Validates the consistency of a tuple which must be complete, i.e, -all fields must have been set. */ - -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); -} -#endif /* UNIV_DEBUG */ - -/***************************************************************** -Pretty prints a dfield value according to its data type. */ - -void -dfield_print( -/*=========*/ - dfield_t* dfield) /* in: dfield */ -{ - byte* data; - ulint len; - ulint mtype; - ulint i; - - len = dfield_get_len(dfield); - data = dfield_get_data(dfield); - - if (len == UNIV_SQL_NULL) { - fputs("NULL", stderr); - - return; - } - - mtype = dtype_get_mtype(dfield_get_type(dfield)); - - if ((mtype == DATA_CHAR) || (mtype == DATA_VARCHAR)) { - - for (i = 0; i < len; i++) { - int c = *data++; - putc(isprint(c) ? c : ' ', stderr); - } - } else if (mtype == DATA_INT) { - ut_a(len == 4); /* only works for 32-bit integers */ - fprintf(stderr, "%d", (int)mach_read_from_4(data)); - } else { - 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( -/*==================*/ - dfield_t* dfield) /* in: dfield */ -{ - byte* data; - ulint len; - ulint mtype; - ulint i; - ibool print_also_hex; - - len = dfield_get_len(dfield); - data = dfield_get_data(dfield); - - if (len == UNIV_SQL_NULL) { - fputs("NULL", stderr); - - return; - } - - mtype = dtype_get_mtype(dfield_get_type(dfield)); - - if ((mtype == DATA_CHAR) || (mtype == DATA_VARCHAR)) { - - print_also_hex = FALSE; - - for (i = 0; i < len; i++) { - int c = *data++; - if (!isprint(c)) { - print_also_hex = TRUE; - c = ' '; - } - putc(c, stderr); - } - - if (!print_also_hex) { - - return; - } - - fputs(" Hex: ", stderr); - - data = dfield_get_data(dfield); - - for (i = 0; i < len; i++) { - fprintf(stderr, "%02lx", (ulint)*data); - - data++; - } - } else if (mtype == DATA_INT) { - ut_a(len == 4); /* only works for 32-bit integers */ - fprintf(stderr, "%d", (int)mach_read_from_4(data)); - } else { - ut_error; - } -} - -/***************************************************************** -Print a dfield value using ut_print_buf. */ -static -void -dfield_print_raw( -/*=============*/ - FILE* f, /* in: output stream */ - dfield_t* dfield) /* in: dfield */ -{ - ulint len = dfield->len; - if (len != UNIV_SQL_NULL) { - ulint print_len = ut_min(len, 1000); - ut_print_buf(f, dfield->data, print_len); - if (len != print_len) { - fprintf(f, "(total %lu bytes)", (ulong) len); - } - } else { - fputs(" SQL NULL", f); - } -} - -/************************************************************** -The following function prints the contents of a tuple. */ - -void -dtuple_print( -/*=========*/ - FILE* f, /* in: output stream */ - 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)); -} - -/****************************************************************** -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. */ - -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; - - ut_a(dtuple_check_typed_no_assert(entry)); - - size = rec_get_converted_size(index, entry); - - if (UNIV_UNLIKELY(size > 1000000000)) { - fprintf(stderr, - "InnoDB: Warning: tuple size very big: %lu\n", - (ulong) size); - fputs("InnoDB: Tuple contents: ", stderr); - dtuple_print(stderr, entry); - putc('\n', stderr); - } - - 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(index, entry) - >= ut_min(page_get_free_space_of_empty( - dict_table_is_comp(index->table)) / 2, - 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) { - - 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_INDEX_COL_LEN */ - -#if DICT_MAX_INDEX_COL_LEN <= REC_1BYTE_OFFS_LIMIT -# error "DICT_MAX_INDEX_COL_LEN <= REC_1BYTE_OFFS_LIMIT" -#endif - - if (longest < BTR_EXTERN_FIELD_REF_SIZE + 10 - + DICT_MAX_INDEX_COL_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_INDEX_COL_LEN); - - vector->fields[n_fields].len = dfield->len - - DICT_MAX_INDEX_COL_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); -} - -/****************************************************************** -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 __attribute__((unused)), /* in: index */ - dtuple_t* entry, /* in: entry whose data was put to vector */ - big_rec_t* vector) /* in, own: big rec vector; it is - freed in this function */ -{ - dfield_t* dfield; - ulint i; - - for (i = 0; i < vector->n_fields; i++) { - - dfield = dtuple_get_nth_field(entry, - vector->fields[i].field_no); - /* Copy data from big rec vector */ - - ut_memcpy(((byte*)dfield->data) - + dfield->len - BTR_EXTERN_FIELD_REF_SIZE, - vector->fields[i].data, - vector->fields[i].len); - dfield->len = dfield->len + vector->fields[i].len - - BTR_EXTERN_FIELD_REF_SIZE; - } - - mem_heap_free(vector->heap); -} - -/****************************************************************** -Frees the memory in a big rec vector. */ - -void -dtuple_big_rec_free( -/*================*/ - big_rec_t* vector) /* in, own: big rec vector; it is - freed in this function */ -{ - mem_heap_free(vector->heap); -} |