1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge 10.3 into 10.4

This commit is contained in:
Marko Mäkelä
2020-05-26 11:54:55 +03:00
47 changed files with 1104 additions and 347 deletions

View File

@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2017, Oracle and/or its affiliates.
Copyright (c) 2008, 2019, MariaDB
Copyright (c) 2008, 2020, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -96,8 +96,11 @@ static std::atomic<ulong> last_table_id;
/* Functions defined in this file */
static void fix_type_pointers(const char ***array, TYPELIB *point_to_type,
uint types, char **names);
static bool fix_type_pointers(const char ***typelib_value_names,
uint **typelib_value_lengths,
TYPELIB *point_to_type, uint types,
char *names, size_t names_length);
static uint find_field(Field **fields, uchar *record, uint start, uint length);
inline bool is_system_table_name(const char *name, size_t length);
@@ -723,7 +726,8 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end,
uint keys, KEY *keyinfo,
uint new_frm_ver, uint *ext_key_parts,
TABLE_SHARE *share, uint len,
KEY *first_keyinfo, char** keynames)
KEY *first_keyinfo,
LEX_STRING *keynames)
{
uint i, j, n_length;
KEY_PART_INFO *key_part= NULL;
@@ -875,10 +879,13 @@ static bool create_key_infos(const uchar *strpos, const uchar *frm_image_end,
share->ext_key_parts++;
share->ext_key_parts+= keyinfo->ext_key_parts;
}
*keynames=(char*) key_part;
strpos+= strnmov(*keynames, (char *) strpos, frm_image_end - strpos) - *keynames;
keynames->str= (char*) key_part;
keynames->length= strnmov(keynames->str, (char *) strpos,
frm_image_end - strpos) - keynames->str;
strpos+= keynames->length;
if (*strpos++) // key names are \0-terminated
return 1;
keynames->length++; // Include '\0', to make fix_type_pointers() happy.
//reading index comments
for (keyinfo= share->key_info, i=0; i < keys; i++, keyinfo++)
@@ -1571,11 +1578,13 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
TABLE_SHARE *share= this;
uint new_frm_ver, field_pack_length, new_field_pack_flag;
uint interval_count, interval_parts, read_length, int_length;
uint total_typelib_value_count;
uint db_create_options, keys, key_parts, n_length;
uint com_length, null_bit_pos, UNINIT_VAR(mysql57_vcol_null_bit_pos), bitmap_count;
uint i, hash_fields= 0;
bool use_hash, mysql57_null_bits= 0;
char *keynames, *names, *comment_pos;
LEX_STRING keynames= {NULL, 0};
char *names, *comment_pos;
const uchar *forminfo;
const uchar *frm_image_end = frm_image + frm_length;
uchar *record, *null_flags, *null_pos, *UNINIT_VAR(mysql57_vcol_null_pos);
@@ -1587,6 +1596,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
KEY_PART_INFO *key_part= NULL;
Field **field_ptr, *reg_field;
const char **interval_array;
uint *typelib_value_lengths= NULL;
enum legacy_db_type legacy_db_type;
my_bitmap_map *bitmaps;
bool null_bits_are_used;
@@ -1986,11 +1996,34 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d vcol_screen_length: %d", interval_count,interval_parts, keys,n_length,int_length, com_length, vcol_screen_length));
/*
We load the following things into TYPELIBs:
- One TYPELIB for field names
- interval_count TYPELIBs for ENUM/SET values
- One TYPELIB for key names
Every TYPELIB requires one extra value with a NULL pointer and zero length,
which is the end-of-values marker.
TODO-10.5+:
Note, we should eventually reuse this total_typelib_value_count
to allocate interval_array. The below code reserves less space
than total_typelib_value_count pointers. So it seems `interval_array`
and `names` overlap in the memory. Too dangerous to fix in 10.1.
*/
total_typelib_value_count=
(share->fields + 1/*end-of-values marker*/) +
(interval_parts + interval_count/*end-of-values markers*/) +
(keys + 1/*end-of-values marker*/);
if (!multi_alloc_root(&share->mem_root,
&share->field, (uint)(share->fields+1)*sizeof(Field*),
&share->intervals, (uint)interval_count*sizeof(TYPELIB),
&share->check_constraints, (uint) share->table_check_constraints * sizeof(Virtual_column_info*),
/*
This looks wrong: shouldn't it be (+2+interval_count)
instread of (+3) ?
*/
&interval_array, (uint) (share->fields+interval_parts+ keys+3)*sizeof(char *),
&typelib_value_lengths, total_typelib_value_count * sizeof(uint *),
&names, (uint) (n_length+int_length),
&comment_pos, (uint) com_length,
&vcol_screen_pos, vcol_screen_length,
@@ -2017,33 +2050,21 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
memcpy(vcol_screen_pos, disk_buff+read_length-vcol_screen_length,
vcol_screen_length);
fix_type_pointers(&interval_array, &share->fieldnames, 1, &names);
if (share->fieldnames.count != share->fields)
if (fix_type_pointers(&interval_array, &typelib_value_lengths,
&share->fieldnames, 1, names, n_length) ||
share->fieldnames.count != share->fields)
goto err;
fix_type_pointers(&interval_array, share->intervals, interval_count, &names);
{
/* Set ENUM and SET lengths */
TYPELIB *interval;
for (interval= share->intervals;
interval < share->intervals + interval_count;
interval++)
{
uint count= (uint) (interval->count + 1) * sizeof(uint);
if (!(interval->type_lengths= (uint *) alloc_root(&share->mem_root,
count)))
goto err;
for (count= 0; count < interval->count; count++)
{
char *val= (char*) interval->type_names[count];
interval->type_lengths[count]= (uint)strlen(val);
}
interval->type_lengths[count]= 0;
}
}
if (fix_type_pointers(&interval_array, &typelib_value_lengths,
share->intervals, interval_count,
names + n_length, int_length))
goto err;
if (keynames)
fix_type_pointers(&interval_array, &share->keynames, 1, &keynames);
if (keynames.length &&
(fix_type_pointers(&interval_array, &typelib_value_lengths,
&share->keynames, 1, keynames.str, keynames.length) ||
share->keynames.count != keys))
goto err;
/* Allocate handler */
if (!(handler_file= get_new_handler(share, thd->mem_root,
@@ -4185,37 +4206,81 @@ void open_table_error(TABLE_SHARE *share, enum open_frm_error error,
** with a '\0'
*/
static void
fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types,
char **names)
static bool
fix_type_pointers(const char ***typelib_value_names,
uint **typelib_value_lengths,
TYPELIB *point_to_type, uint types,
char *ptr, size_t length)
{
char *type_name, *ptr;
char chr;
const char *end= ptr + length;
ptr= *names;
while (types--)
{
char sep;
point_to_type->name=0;
point_to_type->type_names= *array;
point_to_type->type_names= *typelib_value_names;
point_to_type->type_lengths= *typelib_value_lengths;
if ((chr= *ptr)) /* Test if empty type */
/*
Typelib can be encoded as:
1) 0x00 - empty typelib
2) 0xFF 0x00 - empty typelib (index names)
3) sep (value sep)... 0x00 - non-empty typelib (where sep is a separator)
*/
if (length == 2 && ptr[0] == (char) 0xFF && ptr[1] == '\0')
{
while ((type_name=strchr(ptr+1,chr)) != NullS)
{
*((*array)++) = ptr+1;
*type_name= '\0'; /* End string */
ptr=type_name;
}
ptr+=2; /* Skip end mark and last 0 */
/*
This is a special case #2.
If there are no indexes at all, index names can be encoded
as a two byte sequence: 0xFF 0x00
TODO: Check if it's a bug in the FRM packing routine.
It should probably write just 0x00 instead of 0xFF00.
*/
ptr+= 2;
}
else
ptr++;
point_to_type->count= (uint) (*array - point_to_type->type_names);
else if ((sep= *ptr++)) // A non-empty typelib
{
for ( ; ptr < end; )
{
// Now scan the next value+sep pair
char *vend= (char*) memchr(ptr, sep, end - ptr);
if (!vend)
return true; // Bad format
*((*typelib_value_names)++)= ptr;
*((*typelib_value_lengths)++)= (uint) (vend - ptr);
*vend= '\0'; // Change sep to '\0'
ptr= vend + 1; // Shift from sep to the next byte
/*
Now we can have either:
- the end-of-typelib marker (0x00)
- more value+sep pairs
*/
if (!*ptr)
{
/*
We have an ambiguity here. 0x00 can be an end-of-typelib marker,
but it can also be a part of the next value:
CREATE TABLE t1 (a ENUM(0x61, 0x0062) CHARACTER SET BINARY);
If this is the last ENUM/SET in the table and there is still more
packed data left after 0x00, then we know for sure that 0x00
is a part of the next value.
TODO-10.5+: we should eventually introduce a new unambiguous
typelib encoding for FRM.
*/
if (!types && ptr + 1 < end)
continue; // A binary value starting with 0x00
ptr++; // Consume the end-of-typelib marker
break; // End of the current typelib
}
}
}
point_to_type->count= (uint) (*typelib_value_names -
point_to_type->type_names);
point_to_type++;
*((*array)++)= NullS; /* End of type */
*((*typelib_value_names)++)= NullS; /* End of type */
*((*typelib_value_lengths)++)= 0; /* End of type */
}
*names=ptr; /* Update end */
return;
return ptr != end;
} /* fix_type_pointers */
@@ -9640,3 +9705,14 @@ void TABLE::initialize_quick_structures()
bzero(quick_costs, sizeof(quick_costs));
bzero(quick_n_ranges, sizeof(quick_n_ranges));
}
/*
Mark table to be reopened after query
*/
void TABLE::mark_table_for_reopen()
{
THD *thd= in_use;
DBUG_ASSERT(thd);
thd->locked_tables_list.mark_table_for_reopen(thd, this);
}