[messaging] Refactor commonly used functions 36/199336/10
authorPawel Wasowski <p.wasowski2@samsung.com>
Sat, 9 Feb 2019 09:01:20 +0000 (10:01 +0100)
committerPawel Wasowski <p.wasowski2@samsung.com>
Wed, 6 Mar 2019 12:09:28 +0000 (12:09 +0000)
Functions for sorting and filtering are now more general.
Dedicated function for making SQL clause, comprising
only offset and limit was made to replace addFilters usage.

[Verification] tct-messaging-email-tests pass rate did not
change after the change was applied

Change-Id: Id73331631ff2e8cd17723cb7acd882c19f0be5be
Signed-off-by: Pawel Wasowski <p.wasowski2@samsung.com>
src/messaging/messaging_database_manager.cc

index dbdf03e43a9db3ec2e76557cd6ff1820ba8116c3..25a6bba1ff6b2e7ba815f301c83b43d514c2771d 100644 (file)
@@ -721,6 +721,68 @@ PlatformResult MessagingDatabaseManager::addFilters(AbstractFilterPtr filter, So
   return PlatformResult(ErrorCode::NO_ERROR);
 }
 
+namespace {
+
+template <typename T>
+using SharedPtrVector = std::vector<std::shared_ptr<T>>;
+
+template <typename T>
+void filterVector(const AbstractFilter& filter, SharedPtrVector<T>* vec) {
+  ScopeLogger();
+
+  auto toBeFilteredOut = [&filter](const std::shared_ptr<T>& object_ptr) {
+    return !filter.isMatching(object_ptr.get());
+  };
+
+  vec->erase(std::remove_if(vec->begin(), vec->end(), toBeFilteredOut), vec->end());
+}
+
+template <typename T>
+void sortVector(const SortMode& sortMode, SharedPtrVector<T>* vec) {
+  ScopeLogger();
+
+  const std::string attribute = sortMode.getAttributeName();
+  auto comparator = T::getComparator(attribute);
+
+  if (SortModeOrder::ASC == sortMode.getOrder()) {
+    std::sort(vec->begin(), vec->end(), comparator);
+  } else {
+    std::sort(vec->rbegin(), vec->rend(), comparator);
+  }
+}
+
+std::string makeSQLLimitAndOffsetClause(long limit, long offset) {
+  ScopeLogger();
+
+  std::string limitAndOffsetClause;
+  limitAndOffsetClause.reserve(64);
+
+  if (limit) {
+    limitAndOffsetClause += "LIMIT " + std::to_string(limit) + " ";
+  }
+
+  if (offset) {
+    if (!limit) {
+      // Ugly fix proposed by mySQL team:
+      // http://dev.mysql.com/doc/refman/5.0/en/select.html
+      // To retrieve all rows from a certain offset up to the end of the result set,
+      // you can use some large number for the second parameter.
+      //
+      // Reason: to use OFFSET you need to have LIMIT statement
+      // 18446744073709551615 is 2^64-1 - max value of big int
+      // However we will use -1 since it will work fine for various int sizes (this
+      // trick have been used in old implementation).
+
+      limitAndOffsetClause += "LIMIT -1 ";
+    }
+    limitAndOffsetClause += "OFFSET " + std::to_string(offset) + " ";
+  }
+
+  return limitAndOffsetClause;
+}
+
+}  // namespace
+
 PlatformResult MessagingDatabaseManager::findShortMessages(FindMsgCallbackUserData* callback,
                                                            std::vector<int>* result) {
   ScopeLogger();
@@ -883,32 +945,6 @@ void convertToMessageConversations(const email_mail_data_t* mailData, int mailDa
   }
 }
 
-void filterMessageConversations(const AbstractFilter& filter,
-                                ConversationPtrVector* conversations) {
-  ScopeLogger();
-
-  auto toBeFilteredOut = [&filter](const ConversationPtr& conversation) {
-    return !filter.isMatching(conversation.get());
-  };
-
-  conversations->erase(
-      std::remove_if(std::begin(*conversations), std::end(*conversations), toBeFilteredOut),
-      std::end(*conversations));
-}
-
-void sortConversations(const SortMode& sortMode, ConversationPtrVector* conversations) {
-  ScopeLogger();
-
-  const std::string attribute = sortMode.getAttributeName();
-  auto comparator = MessageConversation::getComparator(attribute);
-
-  if (SortModeOrder::ASC == sortMode.getOrder()) {
-    std::sort(std::begin(*conversations), std::end(*conversations), comparator);
-  } else {
-    std::sort(std::rbegin(*conversations), std::rend(*conversations), comparator);
-  }
-}
-
 }  // namespace
 
 PlatformResult MessagingDatabaseManager::retrieveEmailThreadsFromDatabase(
@@ -916,25 +952,8 @@ PlatformResult MessagingDatabaseManager::retrieveEmailThreadsFromDatabase(
     ConversationPtrVector* conversations) {
   ScopeLogger();
 
-  std::string limitAndOffset;
-  PlatformResult result = PlatformResult{ErrorCode::UNKNOWN_ERR};
-  AttributeInfoMap emptyAttributeMap;
-  /*
-   * Sorting and filtering is done programmatically, after data retrieval from the database,
-   * because some parameters cannot be used in ORDER BY/WHERE or both clauses,
-   * passed to the email_query_mails() - e.g. there is no "unreadMessages" column in the.
-   *
-   * For that reason both filter and sort mode arguments of addFilters are null pointers.
-   */
-  result = addFilters(AbstractFilterPtr{nullptr}, SortModePtr{nullptr},
-                      findEmailConversationsData.getLimit(), findEmailConversationsData.getOffset(),
-                      emptyAttributeMap, findEmailConversationsData.getMessageServiceType(),
-                      &limitAndOffset);
-
-  if (result.IsError()) {
-    LoggerE("addFilters failed (%s)", result.message().c_str());
-    return result;
-  }
+  std::string limitAndOffset = makeSQLLimitAndOffsetClause(findEmailConversationsData.getLimit(),
+                                                           findEmailConversationsData.getOffset());
 
   // clang-format off
   const std::string isLastMessageInThread =
@@ -987,10 +1006,10 @@ PlatformResult MessagingDatabaseManager::findEmailConversations(
     return result;
   }
 
-  filterMessageConversations(*findEmailConversationsData.getFilter(), conversations);
+  filterVector(*findEmailConversationsData.getFilter(), conversations);
 
   if (findEmailConversationsData.getSortMode()) {
-    sortConversations(*findEmailConversationsData.getSortMode(), conversations);
+    sortVector(*findEmailConversationsData.getSortMode(), conversations);
   }
 
   return PlatformResult(ErrorCode::NO_ERROR);