Removing hard-coding in ORDER BY statement
authorTomasz Iwanek <t.iwanek@samsung.com>
Thu, 17 Jan 2013 09:40:10 +0000 (10:40 +0100)
committerGerrit Code Review <gerrit2@kim11>
Tue, 22 Jan 2013 10:10:39 +0000 (19:10 +0900)
[Issue#]       N/A
[Bug]          Need of hard coding order by statement
[Cause]        N/A
[Problem]      N/A
[Solution]     N/A
[Verification] Build repository with --define="WITH_TESTS ON"
Run:
dpl-tests-db --output=text --regexp='ORM_SelectOrderByMultipleColumns'
dpl-tests-db --output=text --regexp='ORM_Delete'
Tests should pass

Change-Id: I272bc01cf1ed0a60d00a57f7a41d10b61a173544

modules/db/include/dpl/db/orm.h
tests/dpl/db/test_orm.cpp

index c404fba..652e8e1 100644 (file)
@@ -86,6 +86,38 @@ public:
 
 typedef std::shared_ptr<Expression> ExpressionPtr;
 
+namespace OrderingUtils {
+
+template<typename CompoundType> inline std::string OrderByInternal()
+{
+    std::string order = OrderByInternal<typename CompoundType::Tail>();
+    if(!order.empty()) return CompoundType::Head::GetString() + ", " + order;
+    else return CompoundType::Head::GetString();
+}
+
+template<> inline std::string OrderByInternal<TypeListGuard>()
+{
+    return std::string();
+}
+
+}
+
+template<typename ColumnType>
+class __attribute__ ((visibility("hidden"))) OrderingExpression {
+protected:
+    static std::string GetSchemaAndName()
+    {
+        std::string statement;
+        statement += ColumnType::GetTableName();
+        statement += ".";
+        statement += ColumnType::GetColumnName();
+        statement += " ";
+        return statement;
+    }
+public:
+    virtual ~OrderingExpression() {}
+};
+
 template<const char* Operator, typename LeftExpression, typename RightExpression>
 class __attribute__ ((visibility("hidden"))) BinaryExpression : public Expression {
 protected:
@@ -187,6 +219,22 @@ public:
 ORM_DEFINE_COMPARE_EXPRESSION(Equals, Equal)
 ORM_DEFINE_COMPARE_EXPRESSION(Is, Is)
 
+#define ORM_DEFINE_ORDERING_EXPRESSION(name, value)                                     \
+    template<typename ColumnType>                                                       \
+    class __attribute__ ((visibility("hidden"))) name                                   \
+        : OrderingExpression<ColumnType> {                                              \
+    public:                                                                             \
+        static std::string GetString()                                                  \
+        {                                                                               \
+            std::string statement = OrderingExpression<ColumnType>::GetSchemaAndName(); \
+            statement += value;                                                         \
+            return statement;                                                           \
+        }                                                                               \
+    };
+
+ORM_DEFINE_ORDERING_EXPRESSION(OrderingAscending, "ASC")
+ORM_DEFINE_ORDERING_EXPRESSION(OrderingDescending, "DESC")
+
 template<typename ColumnData1, typename ColumnData2>
 class __attribute__ ((visibility("hidden"))) CompareBinaryColumn {
 private:
@@ -844,11 +892,22 @@ public:
         m_distinctResults = true;
     }
 
-    void OrderBy(const std::string& orderBy)
+    template<typename CompoundType>
+    void OrderBy(const CompoundType&)
+    {
+        m_orderBy = OrderingUtils::OrderByInternal<typename CompoundType::Type>();
+    }
+
+    void OrderBy(const std::string & orderBy) //backward compatibility
     {
         m_orderBy = orderBy;
     }
 
+    void OrderBy(const char * orderBy) //backward compatibility
+    {
+        m_orderBy = std::string(orderBy);
+    }
+
     template<typename ColumnList, typename Expression>
     void Join(const Expression& expression) {
         std::string usedTableNames = TableDefinition::GetName();
index 9295ed2..d2e224f 100644 (file)
@@ -412,7 +412,7 @@ RUNNER_TEST(ORM_Delete)
     using namespace DPL::DB::ORM;
     using namespace DPL::DB::ORM::dpl_orm_test;
     TestTableDelete::Select selectStart(interface.get());
-    selectStart.OrderBy("ColumnInt2 ASC");
+    selectStart.OrderBy(DPL::TypeListDecl<OrderingAscending<TestTableDelete::ColumnInt2> >());
     std::list<TestTableDelete::Row> list = selectStart.GetRowList();
     std::list<TestTableDelete::Row> originalList = list;
 
@@ -849,3 +849,55 @@ RUNNER_TEST(ORM_Join)
         oss.str(std::string());
     }
 }
+
+RUNNER_TEST(ORM_SelectOrderByMultipleColumns)
+{
+    SmartAttach interface;
+    using namespace DPL::DB::ORM;
+    using namespace DPL::DB::ORM::dpl_orm_test;
+    {
+        TestTableJoin3::Select select(interface.get());
+
+        // testing: " ORDER BY Value3 ASC, TestID DESC, TestID ASC"
+        select.OrderBy(DPL::TypeListDecl<OrderingAscending<TestTableJoin3::Value3>,
+                                OrderingDescending<TestTableJoin3::TestText33>,
+                                OrderingAscending<TestTableJoin3::TestID> >());
+
+        std::list<TestTableJoin3::Row> result = select.GetRowList();
+        std::list<TestTableJoin3::Row>::const_iterator iter = result.begin();
+        { //1 row
+            RUNNER_ASSERT_MSG(*iter->Get_TestText33() == DPL::FromASCIIString("test 6"), "Wrong row 1 order");
+            RUNNER_ASSERT_MSG(iter->Get_TestID() == 10, "Wrong row 1 order");
+            iter++;
+        }
+        { //2 row
+            RUNNER_ASSERT_MSG(*iter->Get_TestText33() == DPL::FromASCIIString("test 5"), "Wrong row 2 order");
+            RUNNER_ASSERT_MSG(iter->Get_TestID() == 7, "Wrong row 2 order");
+            iter++;
+        }
+        { //3 row
+            RUNNER_ASSERT_MSG(iter->Get_Value3() == 111, "Wrong row 3 order");
+            RUNNER_ASSERT_MSG(*iter->Get_TestText33() == DPL::FromASCIIString("test 2"), "Wrong row 3 order");
+            RUNNER_ASSERT_MSG(iter->Get_TestID() == 2, "Wrong row 3 order");
+            iter++;
+        }
+        { //4 row
+            RUNNER_ASSERT_MSG(iter->Get_Value3() == 111, "Wrong row 4 order");
+            RUNNER_ASSERT_MSG(*iter->Get_TestText33() == DPL::FromASCIIString("test 1"), "Wrong row 4 order");
+            RUNNER_ASSERT_MSG(iter->Get_TestID() == 1, "Wrong row 4 order");
+            iter++;
+        }
+        { //5 row
+            RUNNER_ASSERT_MSG(iter->Get_Value3() == 222, "Wrong row 5 order");
+            RUNNER_ASSERT_MSG(*iter->Get_TestText33() == DPL::FromASCIIString("test 4"), "Wrong row 5 order");
+            RUNNER_ASSERT_MSG(iter->Get_TestID() == 6, "Wrong row 5 order");
+            iter++;
+        }
+        { //6 row
+            RUNNER_ASSERT_MSG(iter->Get_Value3() == 222, "Wrong row 6 order");
+            RUNNER_ASSERT_MSG(*iter->Get_TestText33() == DPL::FromASCIIString("test 3"), "Wrong row 6 order");
+            RUNNER_ASSERT_MSG(iter->Get_TestID() == 3, "Wrong row 6 order");
+            iter++;
+        }
+    }
+}