mirror of
https://github.com/MariaDB/server.git
synced 2025-07-17 12:02:09 +03:00
MDEV-20297 Support C++11 range-based for loop for List<T>
New iterator has the fastest possible implementation: just moves one pointer. It's faster that List_iterator and List_iterator_fast: both do more on increment. Overall patch brings: 1) work compile times 2) possibly(!) worse debug build performance 3) definitely better optimized build performance 4) ability to write less code 5) ability to write less bug-prone code
This commit is contained in:
@ -21,6 +21,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "sql_alloc.h"
|
#include "sql_alloc.h"
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Simple intrusive linked list.
|
Simple intrusive linked list.
|
||||||
@ -532,6 +533,51 @@ public:
|
|||||||
List<T> *res= new (mem_root) List<T>;
|
List<T> *res= new (mem_root) List<T>;
|
||||||
return res == NULL || res->push_back(first, mem_root) ? NULL : res;
|
return res == NULL || res->push_back(first, mem_root) ? NULL : res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Iterator;
|
||||||
|
using value_type= T;
|
||||||
|
using iterator= Iterator;
|
||||||
|
using const_iterator= const Iterator;
|
||||||
|
|
||||||
|
Iterator begin() const { return Iterator(first); }
|
||||||
|
Iterator end() const { return Iterator(); }
|
||||||
|
|
||||||
|
class Iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using iterator_category= std::forward_iterator_tag;
|
||||||
|
using value_type= T;
|
||||||
|
using difference_type= std::ptrdiff_t;
|
||||||
|
using pointer= T *;
|
||||||
|
using reference= T &;
|
||||||
|
|
||||||
|
Iterator(list_node *p= &end_of_list) : node{p} {}
|
||||||
|
|
||||||
|
Iterator &operator++()
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(node != &end_of_list);
|
||||||
|
|
||||||
|
node= node->next;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator++(int)
|
||||||
|
{
|
||||||
|
Iterator tmp(*this);
|
||||||
|
operator++();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
T &operator*() { return *static_cast<T *>(node->info); }
|
||||||
|
|
||||||
|
bool operator!=(const typename List<T>::iterator &rhs)
|
||||||
|
{
|
||||||
|
return node != rhs.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
list_node *node{&end_of_list};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
#include "sql_audit.h"
|
#include "sql_audit.h"
|
||||||
#include "sql_sequence.h"
|
#include "sql_sequence.h"
|
||||||
#include "tztime.h"
|
#include "tztime.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
@ -3022,34 +3022,37 @@ CHARSET_INFO* get_sql_field_charset(Column_definition *sql_field,
|
|||||||
|
|
||||||
void promote_first_timestamp_column(List<Create_field> *column_definitions)
|
void promote_first_timestamp_column(List<Create_field> *column_definitions)
|
||||||
{
|
{
|
||||||
List_iterator_fast<Create_field> it(*column_definitions);
|
for (Create_field &column_definition : *column_definitions)
|
||||||
Create_field *column_definition;
|
|
||||||
|
|
||||||
while ((column_definition= it++) != NULL)
|
|
||||||
{
|
{
|
||||||
if (column_definition->is_timestamp_type() || // TIMESTAMP
|
if (column_definition.is_timestamp_type() || // TIMESTAMP
|
||||||
column_definition->unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy
|
column_definition.unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("field-ptr:%p", column_definition->field));
|
DBUG_PRINT("info", ("field-ptr:%p", column_definition.field));
|
||||||
if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
|
if ((column_definition.flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
|
||||||
column_definition->default_value == NULL && // no constant default,
|
column_definition.default_value == NULL && // no constant default,
|
||||||
column_definition->unireg_check == Field::NONE && // no function default
|
column_definition.unireg_check == Field::NONE && // no function default
|
||||||
column_definition->vcol_info == NULL &&
|
column_definition.vcol_info == NULL &&
|
||||||
column_definition->period == NULL &&
|
column_definition.period == NULL &&
|
||||||
!(column_definition->flags & VERS_SYSTEM_FIELD)) // column isn't generated
|
!(column_definition.flags & VERS_SYSTEM_FIELD)) // column isn't generated
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to "
|
DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to "
|
||||||
"DEFAULT CURRENT_TIMESTAMP ON UPDATE "
|
"DEFAULT CURRENT_TIMESTAMP ON UPDATE "
|
||||||
"CURRENT_TIMESTAMP",
|
"CURRENT_TIMESTAMP",
|
||||||
column_definition->field_name.str
|
column_definition.field_name.str
|
||||||
));
|
));
|
||||||
column_definition->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
|
column_definition.unireg_check= Field::TIMESTAMP_DNUN_FIELD;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool key_cmp(const Key_part_spec &a, const Key_part_spec &b)
|
||||||
|
{
|
||||||
|
return a.length == b.length &&
|
||||||
|
!lex_string_cmp(system_charset_info, &a.field_name, &b.field_name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Check if there is a duplicate key. Report a warning for every duplicate key.
|
Check if there is a duplicate key. Report a warning for every duplicate key.
|
||||||
|
|
||||||
@ -3058,8 +3061,8 @@ void promote_first_timestamp_column(List<Create_field> *column_definitions)
|
|||||||
@param key_info Key meta-data info.
|
@param key_info Key meta-data info.
|
||||||
@param key_list List of existing keys.
|
@param key_list List of existing keys.
|
||||||
*/
|
*/
|
||||||
static void check_duplicate_key(THD *thd, Key *key, KEY *key_info,
|
static void check_duplicate_key(THD *thd, const Key *key, const KEY *key_info,
|
||||||
List<Key> *key_list)
|
const List<Key> *key_list)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We only check for duplicate indexes if it is requested and the
|
We only check for duplicate indexes if it is requested and the
|
||||||
@ -3071,56 +3074,28 @@ static void check_duplicate_key(THD *thd, Key *key, KEY *key_info,
|
|||||||
if (!key->key_create_info.check_for_duplicate_indexes || key->generated)
|
if (!key->key_create_info.check_for_duplicate_indexes || key->generated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
List_iterator_fast<Key> key_list_iterator(*key_list);
|
for (const Key &k : *key_list)
|
||||||
List_iterator_fast<Key_part_spec> key_column_iterator(key->columns);
|
|
||||||
Key *k;
|
|
||||||
|
|
||||||
while ((k= key_list_iterator++))
|
|
||||||
{
|
{
|
||||||
// Looking for a similar key...
|
// Looking for a similar key...
|
||||||
|
|
||||||
if (k == key)
|
if (&k == key)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (k->generated ||
|
if (k.generated ||
|
||||||
(key->type != k->type) ||
|
(key->type != k.type) ||
|
||||||
(key->key_create_info.algorithm != k->key_create_info.algorithm) ||
|
(key->key_create_info.algorithm != k.key_create_info.algorithm) ||
|
||||||
(key->columns.elements != k->columns.elements))
|
(key->columns.elements != k.columns.elements))
|
||||||
{
|
{
|
||||||
// Keys are different.
|
// Keys are different.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (std::equal(key->columns.begin(), key->columns.end(), k.columns.begin(),
|
||||||
Keys 'key' and 'k' might be identical.
|
key_cmp))
|
||||||
Check that the keys have identical columns in the same order.
|
|
||||||
*/
|
|
||||||
|
|
||||||
List_iterator_fast<Key_part_spec> k_column_iterator(k->columns);
|
|
||||||
uint i;
|
|
||||||
key_column_iterator.rewind();
|
|
||||||
|
|
||||||
for (i= 0; i < key->columns.elements; ++i)
|
|
||||||
{
|
{
|
||||||
Key_part_spec *c1= key_column_iterator++;
|
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_DUP_INDEX,
|
||||||
Key_part_spec *c2= k_column_iterator++;
|
ER_THD(thd, ER_DUP_INDEX), key_info->name.str);
|
||||||
|
return;
|
||||||
DBUG_ASSERT(c1 && c2);
|
|
||||||
|
|
||||||
if (lex_string_cmp(system_charset_info,
|
|
||||||
&c1->field_name, &c2->field_name) ||
|
|
||||||
(c1->length != c2->length))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report a warning if we have two identical keys.
|
|
||||||
|
|
||||||
if (i == key->columns.elements)
|
|
||||||
{
|
|
||||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
|
||||||
ER_DUP_INDEX, ER_THD(thd, ER_DUP_INDEX),
|
|
||||||
key_info->name.str);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user