[MDEV-20297] Support C++11 range-based for loop for List<T> Created: 2019-08-08  Updated: 2019-11-12  Resolved: 2019-11-12

Status: Closed
Project: MariaDB Server
Component/s: Server
Fix Version/s: 10.4.11

Type: Task Priority: Major
Reporter: Nikita Malyavin Assignee: Eugene Kosov (Inactive)
Resolution: Fixed Votes: 0
Labels: None


 Comments   
Comment by Eugene Kosov (Inactive) [ 2019-08-08 ]

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;
     }
   }
 }

Generated at Thu Feb 08 08:58:23 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.