diff options
author | Eugene Kosov <claprix@yandex.ru> | 2019-10-30 13:55:52 +0300 |
---|---|---|
committer | Eugene Kosov <claprix@yandex.ru> | 2019-11-12 17:48:14 +0700 |
commit | e5f99a0c0ccbb6cbf4a816fed552af9c20cc32e9 (patch) | |
tree | 7165ad5607e6f2c7f77074bc7b935254aa245b94 | |
parent | 0308de94ee806c21b6776ecab73396da75282596 (diff) | |
download | mariadb-git-e5f99a0c0ccbb6cbf4a816fed552af9c20cc32e9.tar.gz |
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
-rw-r--r-- | sql/sql_list.h | 46 | ||||
-rw-r--r-- | sql/sql_table.cc | 89 |
2 files changed, 78 insertions, 57 deletions
diff --git a/sql/sql_list.h b/sql/sql_list.h index 3585adbd714..35aaaf49c50 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -21,6 +21,7 @@ #endif #include "sql_alloc.h" +#include <iterator> /** Simple intrusive linked list. @@ -532,6 +533,51 @@ public: List<T> *res= new (mem_root) List<T>; 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}; + }; }; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 334834b2603..3430762fa49 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -54,7 +54,7 @@ #include "sql_audit.h" #include "sql_sequence.h" #include "tztime.h" - +#include <algorithm> #ifdef __WIN__ #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) { - List_iterator_fast<Create_field> it(*column_definitions); - Create_field *column_definition; - - while ((column_definition= it++) != NULL) + for (Create_field &column_definition : *column_definitions) { - if (column_definition->is_timestamp_type() || // TIMESTAMP - column_definition->unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy + if (column_definition.is_timestamp_type() || // TIMESTAMP + column_definition.unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy { - DBUG_PRINT("info", ("field-ptr:%p", column_definition->field)); - if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL, - column_definition->default_value == NULL && // no constant default, - column_definition->unireg_check == Field::NONE && // no function default - column_definition->vcol_info == NULL && - column_definition->period == NULL && - !(column_definition->flags & VERS_SYSTEM_FIELD)) // column isn't generated + DBUG_PRINT("info", ("field-ptr:%p", column_definition.field)); + if ((column_definition.flags & NOT_NULL_FLAG) != 0 && // NOT NULL, + column_definition.default_value == NULL && // no constant default, + column_definition.unireg_check == Field::NONE && // no function default + column_definition.vcol_info == NULL && + column_definition.period == NULL && + !(column_definition.flags & VERS_SYSTEM_FIELD)) // column isn't generated { DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to " "DEFAULT CURRENT_TIMESTAMP ON UPDATE " "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; } } } +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. @@ -3058,8 +3061,8 @@ void promote_first_timestamp_column(List<Create_field> *column_definitions) @param key_info Key meta-data info. @param key_list List of existing keys. */ -static void check_duplicate_key(THD *thd, Key *key, KEY *key_info, - List<Key> *key_list) +static void check_duplicate_key(THD *thd, const Key *key, const KEY *key_info, + const List<Key> *key_list) { /* 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) return; - List_iterator_fast<Key> key_list_iterator(*key_list); - List_iterator_fast<Key_part_spec> key_column_iterator(key->columns); - Key *k; - - while ((k= key_list_iterator++)) + for (const Key &k : *key_list) { // Looking for a similar key... - if (k == key) + if (&k == key) break; - if (k->generated || - (key->type != k->type) || - (key->key_create_info.algorithm != k->key_create_info.algorithm) || - (key->columns.elements != k->columns.elements)) + if (k.generated || + (key->type != k.type) || + (key->key_create_info.algorithm != k.key_create_info.algorithm) || + (key->columns.elements != k.columns.elements)) { // Keys are different. continue; } - /* - Keys 'key' and 'k' might be identical. - 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) + if (std::equal(key->columns.begin(), key->columns.end(), k.columns.begin(), + key_cmp)) { - Key_part_spec *c1= key_column_iterator++; - Key_part_spec *c2= k_column_iterator++; - - 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; + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_DUP_INDEX, + ER_THD(thd, ER_DUP_INDEX), key_info->name.str); + return; } } } |