runOrderBy ::
        [(ColumnName, OrderingSpec)]  -- ^ Input ordering specification
    ->  RTable -- ^ Input RTable
    ->  RTable -- ^ Output RTable
runOrderBy ordSpec rtab = 
    if isRTabEmpty rtab
        then emptyRTable
    else 
        let unsortedRTupList = rtableToList rtab
            sortedRTupList = Data.List.sortBy (\t1 t2 -> compareTuples ordSpec t1 t2) unsortedRTupList
        in rtableFromList sortedRTupList
        where 
            compareTuples :: [(ColumnName, OrderingSpec)] -> RTuple -> RTuple -> Ordering
            compareTuples [] t1 t2 = EQ
            compareTuples ((col, colordspec) : rest) t1 t2 = 
                -- if they are equal or both Null on the column in question, then go to the next column
                if nvl (t1 <!> col) (RText "I am Null baby!") == nvl (t2 <!> col) (RText "I am Null baby!")
                    then compareTuples rest t1 t2
                    else -- Either one of the two is Null or are Not Equal
                         -- so we need to compare t1 versus t2
                         -- the GT, LT below refer to t1 wrt to t2
                         -- In the following we treat Null as the maximum value (anything compared to Null is smaller).
                         -- This way Nulls are send at the end (i.e., the default is "Nulls Last" in SQL parlance)
                        if isNull (t1 <!> col)
                            then 
                                case colordspec of
                                    Asc ->  GT -- t1 is GT than t2 (Nulls go to the end)
                                    Desc -> LT
                            else 
                                if isNull (t2 <!> col)
                                    then 
                                        case colordspec of
                                            Asc ->  LT -- t1 is LT than t2 (Nulls go to the end)
                                            Desc -> GT
                                else
                                    -- here we cant have Nulls
                                    case compare (t1 <!> col) (t2 <!> col) of
                                        GT -> if colordspec == Asc 
                                                then GT else LT
                                        LT -> if colordspec == Asc 
                                                then LT else GT
runOrderBy ::
        [(ColumnName, OrderingSpec)]  -- ^ Input ordering specification
    ->  RTable -- ^ Input RTable
    ->  RTable
runOrderBy ordSpec rtab = 
    if isRTabEmpty rtab
        then emptyRTable
    else 
        let unsortedRTupList = rtableToList rtab
            sortedRTupList = Data.List.sortBy (\t1 t2 -> compareTuples ordSpec t1 t2) unsortedRTupList
        in rtableFromList sortedRTupList
        where 
            compareTuples :: [(ColumnName, OrderingSpec)] -> RTuple -> RTuple -> Ordering
            compareTuples [] t1 t2 = EQ
            compareTuples ((col, colordspec) : rest) t1 t2 = 
                -- if they are equal or both Null on the column in question, then go to the next column
                if nvl (t1 <!> col) (RText "I am Null baby!") == nvl (t2 <!> col) (RText "I am Null baby!")
                    then compareTuples rest t1 t2
                    else -- Either one of the two is Null or are Not Equal
                         -- so we need to compare t1 versus t2
                         -- the GT, LT below refer to t1 wrt to t2
                         -- In the following we treat Null as the maximum value (anything compared to Null is smaller).
                         -- This way Nulls are send at the end (i.e., the default is "Nulls Last" in SQL parlance)
                        if isNull (t1 <!> col)
                            then 
                                case colordspec of
                                    Asc ->  GT -- t1 is GT than t2 (Nulls go to the end)
                                    Desc -> LT
                            else 
                                if isNull (t2 <!> col)
                                    then 
                                        case colordspec of
                                            Asc ->  LT -- t1 is LT than t2 (Nulls go to the end)
                                            Desc -> GT
                                else
                                    -- here we cant have Nulls
                                    case compare (t1 <!> col) (t2 <!> col) of
                                        GT -> if colordspec == Asc 
                                                then GT else LT
                                        LT -> if colordspec == Asc 
                                                then LT else GT
runOrderBy ordSpec rtab = 
    if isRTabEmpty rtab
        then emptyRTable
    else 
        let unsortedRTupList = rtableToList rtab
            sortedRTupList = Data.List.sortBy (\t1 t2 -> compareTuples ordSpec t1 t2) unsortedRTupList
        in rtableFromList sortedRTupList
        where 
            compareTuples :: [(ColumnName, OrderingSpec)] -> RTuple -> RTuple -> Ordering
            compareTuples [] t1 t2 = EQ
            compareTuples ((col, colordspec) : rest) t1 t2 = 
                -- if they are equal or both Null on the column in question, then go to the next column
                if nvl (t1 <!> col) (RText "I am Null baby!") == nvl (t2 <!> col) (RText "I am Null baby!")
                    then compareTuples rest t1 t2
                    else -- Either one of the two is Null or are Not Equal
                         -- so we need to compare t1 versus t2
                         -- the GT, LT below refer to t1 wrt to t2
                         -- In the following we treat Null as the maximum value (anything compared to Null is smaller).
                         -- This way Nulls are send at the end (i.e., the default is "Nulls Last" in SQL parlance)
                        if isNull (t1 <!> col)
                            then 
                                case colordspec of
                                    Asc ->  GT -- t1 is GT than t2 (Nulls go to the end)
                                    Desc -> LT
                            else 
                                if isNull (t2 <!> col)
                                    then 
                                        case colordspec of
                                            Asc ->  LT -- t1 is LT than t2 (Nulls go to the end)
                                            Desc -> GT
                                else
                                    -- here we cant have Nulls
                                    case compare (t1 <!> col) (t2 <!> col) of
                                        GT -> if colordspec == Asc 
                                                then GT else LT
                                        LT -> if colordspec == Asc 
                                                then LT else GT