-- | Implements RTable projection operation.
-- If a column name does not exist, then an empty RTable is returned.
runProjection :: 
    [ColumnName]  -- ^ list of column names to be included in the final result RTable
    -> RTable
    -> RTable
runProjection colNamList irtab = 
    if isRTabEmpty irtab
        then
            emptyRTable
        else
            do -- RTable is a Monad
                srcRtuple <- irtab
                let
                    -- 1. get original column value (in this case it is a list of values :: Maybe RDataType)
                    srcValueL = Data.List.map (\colName -> rtupLookup colName srcRtuple) colNamList

                -- if there is at least one Nothing value then an non-existing column name has been asked. 
                if Data.List.elem Nothing srcValueL 
                    then -- return an empty RTable
                        emptyRTable
                    else
                        let 
                            -- 2. create the new RTuple                        
                            valList = Data.List.map (\(Just v) -> v) srcValueL -- get rid of Maybe
                            targetRtuple = rtupleFromList (Data.List.zip colNamList valList) -- HM.fromList
                        in return targetRtuple                        


-- | Implements RTable projection operation.
-- If a column name does not exist, then the returned RTable includes this column with a Null
-- value. This projection implementation allows missed hits.
runProjection :: 
    [ColumnName]  -- ^ list of column names to be included in the final result RTable
    -> RTable
    -> RTable
runProjection colNamList irtab = 
    if isRTabEmpty irtab
        then
            emptyRTable
        else
            do -- RTable is a Monad
                srcRtuple <- irtab
                let
                    -- 1. get original column value (in this case it is a list of values :: Maybe RDataType)
                    srcValueL = Data.List.map (\colName -> rtupLookup colName srcRtuple) colNamList

                -- if there is at least one Nothing value then an non-existing column name has been asked. 
                if Data.List.elem Nothing srcValueL 
                    then -- return an empty RTable
                        emptyRTable
                    else
                        let 
                            -- 2. create the new RTuple                        
                            valList = Data.List.map (\(Just v) -> v) srcValueL -- get rid of Maybe
                            targetRtuple = rtupleFromList (Data.List.zip colNamList valList) -- HM.fromList
                        in return targetRtuple                        


-- | Implements RTable projection operation.
-- If a column name does not exist, then the returned RTable includes this column with a Null
-- value. This projection implementation allows missed hits.
runProjection colNamList irtab = 
    if isRTabEmpty irtab
        then
            emptyRTable
        else
            do -- RTable is a Monad
                srcRtuple <- irtab
                let
                    -- 1. get original column value (in this case it is a list of values :: Maybe RDataType)
                    srcValueL = Data.List.map (\colName -> rtupLookup colName srcRtuple) colNamList

                -- if there is at least one Nothing value then an non-existing column name has been asked. 
                if Data.List.elem Nothing srcValueL 
                    then -- return an empty RTable
                        emptyRTable
                    else
                        let 
                            -- 2. create the new RTuple                        
                            valList = Data.List.map (\(Just v) -> v) srcValueL -- get rid of Maybe
                            targetRtuple = rtupleFromList (Data.List.zip colNamList valList) -- HM.fromList
                        in return targetRtuple                        


-- | Implements RTable projection operation.
-- If a column name does not exist, then the returned RTable includes this column with a Null
-- value. This projection implementation allows missed hits.