summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Kosov <claprix@yandex.ru>2021-03-22 22:12:50 +0300
committerEugene Kosov <claprix@yandex.ru>2021-03-24 11:23:12 +0300
commit8094640809804f74f9d51c9c50a368ecad4f7cb1 (patch)
tree393c348a07310174598bfb6b0811367e2579d4aa
parentcb545f11169d2425316d96feafc78ac841950e43 (diff)
downloadmariadb-git-bb-10.6-MDEV-20453.tar.gz
MDEV-20453 add class similar to std::string_view (non owning string reference)bb-10.6-MDEV-20453
Also use string_view in some places.
-rw-r--r--include/string_view.h417
-rw-r--r--sql/CMakeLists.txt1
-rw-r--r--sql/string_view.cc25
-rw-r--r--storage/innobase/dict/dict0mem.cc41
-rw-r--r--storage/innobase/fil/fil0fil.cc47
-rw-r--r--storage/innobase/fsp/fsp0file.cc26
-rw-r--r--storage/innobase/handler/handler0alter.cc28
-rw-r--r--storage/innobase/include/fil0fil.h7
-rw-r--r--storage/innobase/include/log0log.h2
9 files changed, 502 insertions, 92 deletions
diff --git a/include/string_view.h b/include/string_view.h
new file mode 100644
index 00000000000..88ec70fcd74
--- /dev/null
+++ b/include/string_view.h
@@ -0,0 +1,417 @@
+/*****************************************************************************
+Copyright (c) 2021 MariaDB Corporation.
+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 the Free Software
+Foundation; version 2 of the License.
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
+*****************************************************************************/
+
+#ifndef STRING_VIEW_H
+#define STRING_VIEW_H
+
+#include <cassert>
+#include <cstddef>
+
+#include <algorithm>
+#include <iosfwd>
+#include <iterator>
+#include <limits>
+#include <memory>
+#include <stdexcept>
+#include <string>
+
+#include "my_attribute.h"
+
+class string_view
+{
+public:
+ using traits_type= std::char_traits<char>;
+ using value_type= char;
+ using pointer= char *;
+ using const_pointer= const char *;
+ using reference= char &;
+ using const_reference= const char &;
+ using const_iterator= const char *;
+ using iterator= const_iterator;
+ using const_reverse_iterator= std::reverse_iterator<const_iterator>;
+ using reverse_iterator= const_reverse_iterator;
+ using size_type= std::size_t;
+ using difference_type= std::ptrdiff_t;
+
+ static constexpr size_type npos= size_type(-1);
+
+ constexpr string_view() noexcept : str_(nullptr), size_(0) {}
+ constexpr string_view(const string_view &rhs) noexcept= default;
+ constexpr string_view(const char *s, size_type count) : str_(s), size_(count)
+ {
+ }
+ string_view(const char *s) : str_(s), size_(traits_type::length(s)) {}
+ // In C++20 it's different.
+ template <class It>
+ constexpr string_view(It first, It last) : str_(&*first), size_(last - first)
+ {
+ }
+ // Add such ctor because we can't add string_view operator to std::string
+ string_view(const std::string &s) noexcept : str_(s.data()), size_(s.size())
+ {
+ }
+
+ string_view &operator=(const string_view &rhs)
+ {
+ str_= rhs.str_;
+ size_= rhs.size_;
+ return *this;
+ }
+
+ constexpr const_iterator begin() const noexcept { return str_; }
+ constexpr const_iterator cbegin() const noexcept { return str_; }
+
+ constexpr const_iterator end() const noexcept { return str_ + size_; }
+ constexpr const_iterator cend() const noexcept { return str_ + size_; }
+
+ const_reverse_iterator rbegin() const noexcept
+ {
+ return const_reverse_iterator(end());
+ }
+ const_reverse_iterator crbegin() const noexcept
+ {
+ return const_reverse_iterator(end());
+ }
+
+ const_reverse_iterator rend() const noexcept
+ {
+ return const_reverse_iterator(begin());
+ }
+ const_reverse_iterator crend() const noexcept
+ {
+ return const_reverse_iterator(begin());
+ }
+
+ constexpr const_reference operator[](size_type pos) const noexcept
+ {
+ return str_[pos];
+ }
+
+ const_reference at(size_type pos) const
+ {
+ if (pos >= size())
+ throw std::out_of_range("string_view::at()");
+
+ return str_[pos];
+ }
+
+ constexpr const_reference front() const noexcept { return operator[](0); }
+ constexpr const_reference back() const noexcept
+ {
+ return operator[](size() - 1);
+ }
+
+ constexpr const_pointer data() const noexcept { return str_; }
+
+ constexpr size_type size() const noexcept { return size_; }
+ constexpr size_type length() const noexcept { return size_; }
+
+ constexpr size_type max_size() const noexcept
+ {
+ return std::numeric_limits<size_type>::max();
+ }
+
+ constexpr __attribute__((warn_unused_result)) bool empty() const noexcept
+ {
+ return size() == 0;
+ }
+
+ void remove_prefix(size_type n)
+ {
+ assert(n <= size());
+ str_+= n;
+ size_-= n;
+ }
+
+ void remove_suffix(size_type n)
+ {
+ assert(n <= size());
+ size_-= n;
+ }
+
+ void swap(string_view &rhs) noexcept
+ {
+ std::swap(str_, rhs.str_);
+ std::swap(size_, rhs.size_);
+ }
+
+ size_type copy(char *dest, size_type count, size_type pos= 0) const
+ {
+ if (pos > size())
+ throw std::out_of_range("string_view::copy()");
+
+ auto rcount= std::min(size() - pos, count);
+ traits_type::copy(dest, data() + pos, rcount);
+ return rcount;
+ }
+
+ string_view substr(size_type pos= 0, size_type count= npos) const
+ {
+ if (pos > size())
+ throw std::out_of_range("string_view::substr()");
+
+ auto rcount= std::min(size() - pos, count);
+ return {data() + pos, pos + rcount};
+ }
+
+ int compare(string_view v) const noexcept
+ {
+ auto rlen= std::min(size(), v.size());
+ return traits_type::compare(data(), v.data(), rlen);
+ }
+ int compare(size_type pos1, size_type count1, string_view v) const
+ {
+ return substr(pos1, count1).compare(v);
+ }
+ int compare(size_type pos1, size_type count1, string_view v, size_type pos2,
+ size_type count2) const
+ {
+ return substr(pos1, count1).compare(v.substr(pos2, count2));
+ }
+ int compare(const char *s) const { return compare(string_view(s)); }
+ int compare(size_type pos1, size_type count1, const char *s) const
+ {
+ return substr(pos1, count1).compare(string_view(s));
+ }
+ int compare(size_type pos1, size_type count1, const char *s,
+ size_type count2) const
+ {
+ return substr(pos1, count1).compare(string_view(s, count2));
+ }
+
+ bool starts_with(string_view sv) const noexcept
+ {
+ return substr(0, sv.size()) == sv;
+ }
+ constexpr bool starts_with(char c) const noexcept
+ {
+ return !empty() && traits_type::eq(front(), c);
+ }
+ bool starts_with(const char *s) const { return starts_with(string_view(s)); }
+
+ bool ends_with(string_view sv) const noexcept
+ {
+ return size() >= sv.size() && compare(size() - sv.size(), npos, sv) == 0;
+ }
+ constexpr bool ends_with(char c) const noexcept
+ {
+ return !empty() && traits_type::eq(back(), c);
+ }
+ bool ends_with(const char *s) const { return ends_with(string_view(s)); }
+
+ bool contains(string_view sv) const noexcept { return find(sv) != npos; }
+ bool contains(char c) const noexcept { return find(c) != npos; }
+ bool contains(const char *s) const { return find(s) != npos; }
+
+ size_type find(string_view v, size_type pos= 0) const noexcept
+ {
+ // TODO: optimize with std::strstr()
+ auto it= std::search(begin() + pos, end(), v.begin(), v.end());
+ if (it == end())
+ return npos;
+ return it - begin();
+ }
+ size_type find(char ch, size_type pos= 0) const noexcept
+ {
+ return find(string_view(std::addressof(ch), 1));
+ }
+ size_type find(const char *s, size_type pos, size_type count) const
+ {
+ return find(string_view(s, count), pos);
+ }
+ size_type find(const char *s, size_type pos= 0) const
+ {
+ return find(string_view(s), pos);
+ }
+
+ size_type rfind(string_view v, size_type pos= npos) const noexcept
+ {
+ assert(!v.empty());
+
+ if (empty())
+ return npos;
+
+ pos= std::min(size() - 1, pos);
+
+ if (v.size() > pos + 1)
+ return npos;
+
+ pos-= v.size();
+
+ for (;; --pos)
+ {
+ string_view tmp(str_ + pos, v.size());
+ if (tmp == v)
+ return pos;
+
+ if (pos == 0)
+ break;
+ }
+
+ return npos;
+ }
+ size_type rfind(char c, size_type pos= npos) const noexcept
+ {
+ return rfind(string_view(std::addressof(c), 1), pos);
+ }
+ size_type rfind(const char *s, size_type pos, size_type count) const
+ {
+ return rfind(string_view(s, count), pos);
+ }
+ size_type rfind(const char *s, size_type pos= npos) const
+ {
+ return rfind(string_view(s), pos);
+ }
+
+ size_type find_first_of(string_view v, size_type pos= 0) const noexcept
+ {
+ // TODO: optimize with a lookup table.
+ auto it= std::find_if(begin() + pos, end(),
+ [v](char c) { return v.find(c) != npos; });
+ if (it == end())
+ return npos;
+ return it - begin();
+ }
+ size_type find_first_of(char c, size_type pos= 0) const noexcept
+ {
+ return find_first_of(string_view(std::addressof(c), 1), pos);
+ }
+ size_type find_first_of(const char *s, size_type pos, size_type count) const
+ {
+ return find_first_of(string_view(s, count), pos);
+ }
+ size_type find_first_of(const char *s, size_type pos= 0) const
+ {
+ return find_first_of(string_view(s), pos);
+ }
+
+ size_type find_last_of(string_view v, size_type pos= npos) const noexcept
+ {
+ // TODO: optimize with a lookup table.
+ auto it= std::find_if(reverse_iterator(begin() + pos), rend(),
+ [v](char c) { return v.find(c) != npos; });
+ if (it == rend())
+ return npos;
+ return it.base() - begin();
+ }
+ size_type find_last_of(char c, size_type pos= npos) const noexcept
+ {
+ return find_last_of(string_view(std::addressof(c), 1), pos);
+ }
+ size_type find_last_of(const char *s, size_type pos, size_type count) const
+ {
+ return find_last_of(string_view(s, count), pos);
+ }
+ size_type find_last_of(const char *s, size_type pos= npos) const
+ {
+ return find_last_of(string_view(s), pos);
+ }
+
+ size_type find_first_not_of(string_view v, size_type pos= 0) const noexcept
+ {
+ // TODO: optimize with a lookup table.
+ auto it= std::find_if(begin() + pos, end(),
+ [v](char c) { return v.find(c) == npos; });
+ if (it == end())
+ return npos;
+ return it - begin();
+ }
+ size_type find_first_not_of(char c, size_type pos= 0) const noexcept
+ {
+ return find_first_not_of(string_view(std::addressof(c), 1), pos);
+ }
+ size_type find_first_not_of(const char *s, size_type pos,
+ size_type count) const
+ {
+ return find_first_not_of(string_view(s, count), pos);
+ }
+ size_type find_first_not_of(const char *s, size_type pos= 0) const
+ {
+ return find_first_not_of(string_view(s), pos);
+ }
+
+ size_type find_last_not_of(string_view v, size_type pos= npos) const noexcept
+ {
+ // TODO: optimize with a lookup table.
+ auto it= std::find_if(reverse_iterator(begin() + pos), rend(),
+ [v](char c) { return v.find(c) == npos; });
+ if (it == rend())
+ return npos;
+ return it.base() - begin();
+ }
+ size_type find_last_not_of(char c, size_type pos= npos) const noexcept
+ {
+ return find_last_not_of(string_view(std::addressof(c), 1), pos);
+ }
+ size_type find_last_not_of(const char *s, size_type pos,
+ size_type count) const
+ {
+ return find_last_not_of(string_view(s, count), pos);
+ }
+ size_type find_last_not_of(const char *s, size_type pos= npos) const
+ {
+ return find_last_not_of(string_view(s), pos);
+ }
+
+ friend bool operator==(string_view lhs, string_view rhs) noexcept
+ {
+ return lhs.compare(rhs) == 0;
+ }
+ friend bool operator!=(string_view lhs, string_view rhs) noexcept
+ {
+ return lhs.compare(rhs) != 0;
+ }
+ friend bool operator<(string_view lhs, string_view rhs) noexcept
+ {
+ return lhs.compare(rhs) < 0;
+ }
+ friend bool operator<=(string_view lhs, string_view rhs) noexcept
+ {
+ return lhs.compare(rhs) <= 0;
+ }
+ friend bool operator>(string_view lhs, string_view rhs) noexcept
+ {
+ return lhs.compare(rhs) > 0;
+ }
+ friend bool operator>=(string_view lhs, string_view rhs) noexcept
+ {
+ return lhs.compare(rhs) >= 0;
+ }
+
+private:
+ const_pointer str_= nullptr;
+ size_type size_= 0;
+};
+
+std::basic_ostream<char> &operator<<(std::basic_ostream<char> &os,
+ string_view v);
+
+namespace std
+{
+
+template <> struct hash<string_view>
+{
+ size_t operator()(string_view v)
+ {
+ uint32_t hash= 0;
+
+ for (char c : v)
+ hash= (hash * 2166136261u) ^ static_cast<uint32_t>(c);
+
+ return static_cast<size_t>(hash);
+ }
+};
+
+} // namespace std
+
+#endif
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 9f44eee1f96..6185b74aac5 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -165,6 +165,7 @@ SET (SQL_SOURCE
opt_trace.cc
table_cache.cc encryption.cc temporary_tables.cc
proxy_protocol.cc backup.cc xa.cc
+ string_view.cc
${CMAKE_CURRENT_BINARY_DIR}/lex_hash.h
${CMAKE_CURRENT_BINARY_DIR}/lex_token.h
${GEN_SOURCES}
diff --git a/sql/string_view.cc b/sql/string_view.cc
new file mode 100644
index 00000000000..6b3b101c131
--- /dev/null
+++ b/sql/string_view.cc
@@ -0,0 +1,25 @@
+/*****************************************************************************
+Copyright (c) 2021 MariaDB Corporation.
+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 the Free Software
+Foundation; version 2 of the License.
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
+*****************************************************************************/
+
+#include "string_view.h"
+
+#include <ostream>
+
+std::basic_ostream<char> &operator<<(std::basic_ostream<char> &os,
+ string_view v)
+{
+ // TODO standard requires a much more complicated code here.
+ auto size= static_cast<std::streamsize>(v.size());
+ os.write(v.data(), size);
+ return os;
+}
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
index f4a56faaf28..667ec29f6c8 100644
--- a/storage/innobase/dict/dict0mem.cc
+++ b/storage/innobase/dict/dict0mem.cc
@@ -37,40 +37,37 @@ Created 1/8/1996 Heikki Tuuri
#include "lock0lock.h"
#include "row0row.h"
#include "sql_string.h"
+#include "string_view.h"
#include <iostream>
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
creating a table or index object */
/** System databases */
-static const char* innobase_system_databases[] = {
- "mysql/",
- "information_schema/",
- "performance_schema/",
- NullS
+static const string_view innobase_system_databases[]= {
+ "mysql/",
+ "information_schema/",
+ "performance_schema/",
};
/** Determine if a table belongs to innobase_system_databases[]
@param[in] name database_name/table_name
@return whether the database_name is in innobase_system_databases[] */
-static bool dict_mem_table_is_system(const char *name)
+static bool dict_mem_table_is_system(string_view name)
{
- /* table has the following format: database/table
- and some system table are of the form SYS_* */
- if (!strchr(name, '/')) {
- return true;
- }
- size_t table_len = strlen(name);
- const char *system_db;
- int i = 0;
- while ((system_db = innobase_system_databases[i++])
- && (system_db != NullS)) {
- size_t len = strlen(system_db);
- if (table_len > len && !strncmp(name, system_db, len)) {
- return true;
- }
- }
- return false;
+ /* table has the following format: database/table
+ and some system table are of the form SYS_* */
+ if (!name.contains('/'))
+ return true;
+ for (auto system_db : innobase_system_databases)
+ {
+ if (name.size() > system_db.size() &&
+ system_db == name.substr(0, system_db.size()))
+ {
+ return true;
+ }
+ }
+ return false;
}
/** The start of the table basename suffix for partitioned tables */
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 7eb3abfbf21..f036b728e00 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -2692,53 +2692,6 @@ fil_space_read_name_and_filepath(
return(success);
}
-/** Convert a file name to a tablespace name.
-@param[in] filename directory/databasename/tablename.ibd
-@return database/tablename string, to be freed with ut_free() */
-char*
-fil_path_to_space_name(
- const char* filename)
-{
- /* Strip the file name prefix and suffix, leaving
- only databasename/tablename. */
- ulint filename_len = strlen(filename);
- const char* end = filename + filename_len;
-#ifdef HAVE_MEMRCHR
- const char* tablename = 1 + static_cast<const char*>(
- memrchr(filename, OS_PATH_SEPARATOR,
- filename_len));
- const char* dbname = 1 + static_cast<const char*>(
- memrchr(filename, OS_PATH_SEPARATOR,
- tablename - filename - 1));
-#else /* HAVE_MEMRCHR */
- const char* tablename = filename;
- const char* dbname = NULL;
-
- while (const char* t = static_cast<const char*>(
- memchr(tablename, OS_PATH_SEPARATOR,
- ulint(end - tablename)))) {
- dbname = tablename;
- tablename = t + 1;
- }
-#endif /* HAVE_MEMRCHR */
-
- ut_ad(dbname != NULL);
- ut_ad(tablename > dbname);
- ut_ad(tablename < end);
- ut_ad(end - tablename > 4);
- ut_ad(memcmp(end - 4, DOT_IBD, 4) == 0);
-
- char* name = mem_strdupl(dbname, ulint(end - dbname) - 4);
-
- ut_ad(name[tablename - dbname - 1] == OS_PATH_SEPARATOR);
-#if OS_PATH_SEPARATOR != '/'
- /* space->name uses '/', not OS_PATH_SEPARATOR. */
- name[tablename - dbname - 1] = '/';
-#endif
-
- return(name);
-}
-
/** Discover the correct IBD file to open given a remote or missing
filepath from the REDO log. Administrators can move a crashed
database to another location on the same machine and try to recover it.
diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc
index 57164113647..69ffae15543 100644
--- a/storage/innobase/fsp/fsp0file.cc
+++ b/storage/innobase/fsp/fsp0file.cc
@@ -30,6 +30,8 @@ Created 2013-7-26 by Kevin Lewis
#include "page0page.h"
#include "srv0start.h"
+#include "string_view.h"
+
/** Initialize the name, size and order of this datafile
@param[in] name tablespace name, will be copied
@param[in] flags tablespace flags */
@@ -258,6 +260,28 @@ Datafile::same_as(
#endif /* WIN32 */
}
+/** Convert a file name to a tablespace name.
+@param[in] filename directory/databasename/tablename.ibd
+@return database/tablename string, to be freed with ut_free() */
+static char *fsp_path_to_space_name(string_view filename)
+{
+ auto last_slash= filename.rfind(OS_PATH_SEPARATOR);
+ auto prev_last_slash=
+ filename.substr(0, last_slash).rfind(OS_PATH_SEPARATOR);
+ filename.remove_prefix(prev_last_slash + 1);
+ ut_ad(filename.ends_with(DOT_IBD));
+ filename.remove_suffix(strlen(DOT_IBD));
+
+ char *name= mem_strdupl(filename.data(), filename.size());
+
+#if OS_PATH_SEPARATOR != '/'
+ /* space->name uses '/', not OS_PATH_SEPARATOR. */
+ name[last_slash - prev_last_slash - 1]= '/';
+#endif
+
+ return name;
+}
+
/** Allocate and set the datafile or tablespace name in m_name.
If a name is provided, use it; else extract a file-per-table
tablespace name from m_filepath. The value of m_name
@@ -271,7 +295,7 @@ Datafile::set_name(const char* name)
if (name != NULL) {
m_name = mem_strdup(name);
} else {
- m_name = fil_path_to_space_name(m_filepath);
+ m_name = fsp_path_to_space_name(m_filepath);
}
}
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 58e17cd3ead..359a3aa49c2 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -30,6 +30,7 @@ Smart ALTER TABLE
#include <sql_class.h>
#include <sql_table.h>
#include <mysql/plugin.h>
+#include "string_view.h"
/* Include necessary InnoDB headers */
#include "btr0sea.h"
@@ -7367,27 +7368,26 @@ Rename a given index in the InnoDB data dictionary cache.
@param[in,out] index index to rename
@param new_name new index name
*/
-static
-void
-innobase_rename_index_cache(dict_index_t* index, const char* new_name)
+static void innobase_rename_index_cache(dict_index_t *index,
+ string_view new_name)
{
- DBUG_ENTER("innobase_rename_index_cache");
- ut_d(dict_sys.assert_locked());
+ DBUG_ENTER("innobase_rename_index_cache");
+ ut_d(dict_sys.assert_locked());
- size_t old_name_len = strlen(index->name);
- size_t new_name_len = strlen(new_name);
+ size_t old_name_len= strlen(index->name);
- if (old_name_len < new_name_len) {
- index->name = static_cast<char*>(
- mem_heap_alloc(index->heap, new_name_len + 1));
- }
+ if (old_name_len < new_name.size())
+ {
+ index->name=
+ static_cast<char *>(mem_heap_alloc(index->heap, new_name.size() + 1));
+ }
- memcpy(const_cast<char*>(index->name()), new_name, new_name_len + 1);
+ memcpy(const_cast<char *>(index->name()), new_name.data(),
+ new_name.size() + 1);
- DBUG_VOID_RETURN;
+ DBUG_VOID_RETURN;
}
-
/** Rename the index name in cache.
@param[in] ctx alter context
@param[in] ha_alter_info Data used during inplace alter. */
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 70cbedc3a94..1d91d759d9d 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -1765,13 +1765,6 @@ fil_space_read_name_and_filepath(
char** name,
char** filepath);
-/** Convert a file name to a tablespace name.
-@param[in] filename directory/databasename/tablename.ibd
-@return database/tablename string, to be freed with ut_free() */
-char*
-fil_path_to_space_name(
- const char* filename);
-
/*******************************************************************//**
Returns the table space by a given id, NULL if not found. */
fil_space_t*
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index a3085f0f2dd..a28f4195ee4 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/include/log0log.h
@@ -525,7 +525,7 @@ public:
/** writes header */
void write_header_durable(lsn_t lsn);
/** opens log file which must be closed prior this call */
- dberr_t rename(std::string path) { return fd.rename(path); }
+ dberr_t rename(std::string path) { return fd.rename(std::move(path)); }
/** reads buffer from log file
@param[in] offset offset in log file
@param[in] buf buffer where to read */