Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-20297

Support C++11 range-based for loop for List<T>

Details

    • Task
    • Status: Closed (View Workflow)
    • Major
    • Resolution: Fixed
    • 10.4.11
    • Server
    • None

    Attachments

      Activity

        Adding my prototype: the simplest (and fastest) possible implementation, works with <algorithm> functions.

        diff --git a/sql/sql_list.h b/sql/sql_list.h
        index f5d8ed98b02..f47300d6954 100644
        --- a/sql/sql_list.h
        +++ b/sql/sql_list.h
        @@ -20,6 +20,7 @@
         #endif
         
         #include "sql_alloc.h"
        +#include <iterator>
         
         /**
           Simple intrusive linked list.
        @@ -524,6 +525,45 @@ template <class T> class List :public base_list
             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 std::iterator<std::input_iterator_tag, T>
        +  {
        +  public:
        +    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 2fdfdb1c420..cac6f42ded7 100644
        --- a/sql/sql_table.cc
        +++ b/sql/sql_table.cc
        @@ -54,6 +54,7 @@
         #include "sql_audit.h"
         #include "sql_sequence.h"
         #include "tztime.h"
        +#include <algorithm>
         
         
         #ifdef __WIN__
        @@ -3017,28 +3018,25 @@ 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;
             }
        @@ -3066,21 +3064,17 @@ 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;
        @@ -3091,31 +3085,16 @@ static void check_duplicate_key(THD *thd, Key *key, KEY *key_info,
               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++;
        -      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)
        +    if (std::equal(key->columns.begin(), key->columns.end(), k.columns.begin(),
        +                   [](const Key_part_spec &a, const Key_part_spec &b) {
        +                     return !lex_string_cmp(system_charset_info, &a.field_name,
        +                                            &b.field_name) &&
        +                            a.length == b.length;
        +                   }))
             {
        -      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;
             }
           }
         }
        
        

        kevg Eugene Kosov (Inactive) added a comment - Adding my prototype: the simplest (and fastest) possible implementation, works with <algorithm> functions. diff --git a/sql/sql_list.h b/sql/sql_list.h index f5d8ed98b02..f47300d6954 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -20,6 +20,7 @@ #endif #include "sql_alloc.h" +#include <iterator> /** Simple intrusive linked list. @@ -524,6 +525,45 @@ template <class T> class List :public base_list 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 std::iterator<std::input_iterator_tag, T> + { + public: + 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 2fdfdb1c420..cac6f42ded7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -54,6 +54,7 @@ #include "sql_audit.h" #include "sql_sequence.h" #include "tztime.h" +#include <algorithm> #ifdef __WIN__ @@ -3017,28 +3018,25 @@ 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; } @@ -3066,21 +3064,17 @@ 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; @@ -3091,31 +3085,16 @@ static void check_duplicate_key(THD *thd, Key *key, KEY *key_info, 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++; - 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) + if (std::equal(key->columns.begin(), key->columns.end(), k.columns.begin(), + [](const Key_part_spec &a, const Key_part_spec &b) { + return !lex_string_cmp(system_charset_info, &a.field_name, + &b.field_name) && + a.length == b.length; + })) { - 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; } } }

        People

          kevg Eugene Kosov (Inactive)
          nikitamalyavin Nikita Malyavin
          Votes:
          0 Vote for this issue
          Watchers:
          3 Start watching this issue

          Dates

            Created:
            Updated:
            Resolved:

            Git Integration

              Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.