-- | Implements a Right Outer Join operation between two RTables (any type of join predicate is allowed),
-- i.e., the rows of the right RTable will be preserved.
-- A Right Join :
-- @ 
-- tabLeft RIGHT JOIN tabRight ON joinPred
-- @ 
-- where tabRight is the preserving table can be defined as:
-- the Union between the following two RTables:
--  A. The result of the inner join: tabLeft INNER JOIN tabRight ON joinPred
--  B. The rows from the preserving table (tabRight) that DONT satisfy the join condition, enhanced with the columns
--     of tabLeft returning Null values.
--  The common columns will appear from both tables but only the right table column's will retain their original name. 
runRightJoin ::
    RJoinPredicate
    -> RTable
    -> RTable
    -> RTable
runRightJoin jpred tab preservingTab =
    if isRTabEmpty preservingTab
        then 
            emptyRTable
        else
            if isRTabEmpty tab
                then
                    preservingTab        
                else     
                    -- we know that both the preservingTab and tab are non empty 
                    let 
                        unionFstPart =                             
                            iJ (flip jpred) preservingTab tab --tab    -- we used the preserving table as the left table in the inner join, 
                                                                    -- in order to retain the original column names for the common columns 
                        -- debug
                        -- !dummy1 = trace ("unionFstPart:\n" ++ show unionFstPart) True

                        -- project only the preserving tab's columns
                        fstPartProj = 
                            p (getColumnNamesfromRTab preservingTab) unionFstPart

                        -- the second part are the rows from the preserving table that dont join
                        -- we will use the Difference operations for this
                        unionSndPart = 
                            let 
                                difftab = 
                                    d preservingTab   fstPartProj -- unionFstPart 
                                -- now enhance the result with the columns of the left table
                            in iJ (\t1 t2 -> True) difftab (createSingletonRTable $ createNullRTuple $ (getColumnNamesfromRTab tab))
                        -- debug
                        -- !dummy2 = trace ("unionSndPart :\n" ++ show unionSndPart) True
                        -- !dummy3 = trace ("u unionFstPart unionSndPart :\n" ++ (show $ u unionFstPart unionSndPart)) True
                    in u unionFstPart unionSndPart
runRightJoin ::
    RJoinPredicate
    -> RTable
    -> RTable
    -> RTable
runRightJoin jpred tab preservingTab =
    if isRTabEmpty preservingTab
        then 
            emptyRTable
        else
            if isRTabEmpty tab
                then
                    preservingTab        
                else     
                    -- we know that both the preservingTab and tab are non empty 
                    let 
                        unionFstPart =                             
                            iJ (flip jpred) preservingTab tab --tab    -- we used the preserving table as the left table in the inner join, 
                                                                    -- in order to retain the original column names for the common columns 
                        -- debug
                        -- !dummy1 = trace ("unionFstPart:\n" ++ show unionFstPart) True

                        -- project only the preserving tab's columns
                        fstPartProj = 
                            p (getColumnNamesfromRTab preservingTab) unionFstPart

                        -- the second part are the rows from the preserving table that dont join
                        -- we will use the Difference operations for this
                        unionSndPart = 
                            let 
                                difftab = 
                                    d preservingTab   fstPartProj -- unionFstPart 
                                -- now enhance the result with the columns of the left table
                            in iJ (\t1 t2 -> True) difftab (createSingletonRTable $ createNullRTuple $ (getColumnNamesfromRTab tab))
                        -- debug
                        -- !dummy2 = trace ("unionSndPart :\n" ++ show unionSndPart) True
                        -- !dummy3 = trace ("u unionFstPart unionSndPart :\n" ++ (show $ u unionFstPart unionSndPart)) True
                    in u unionFstPart unionSndPart
runRightJoin jpred tab preservingTab =
    if isRTabEmpty preservingTab
        then 
            emptyRTable
        else
            if isRTabEmpty tab
                then
                    preservingTab        
                else     
                    -- we know that both the preservingTab and tab are non empty 
                    let 
                        unionFstPart =                             
                            iJ (flip jpred) preservingTab tab --tab    -- we used the preserving table as the left table in the inner join, 
                                                                    -- in order to retain the original column names for the common columns 
                        -- debug
                        -- !dummy1 = trace ("unionFstPart:\n" ++ show unionFstPart) True

                        -- project only the preserving tab's columns
                        fstPartProj = 
                            p (getColumnNamesfromRTab preservingTab) unionFstPart

                        -- the second part are the rows from the preserving table that dont join
                        -- we will use the Difference operations for this
                        unionSndPart = 
                            let 
                                difftab = 
                                    d preservingTab   fstPartProj -- unionFstPart 
                                -- now enhance the result with the columns of the left table
                            in iJ (\t1 t2 -> True) difftab (createSingletonRTable $ createNullRTuple $ (getColumnNamesfromRTab tab))
                        -- debug
                        -- !dummy2 = trace ("unionSndPart :\n" ++ show unionSndPart) True
                        -- !dummy3 = trace ("u unionFstPart unionSndPart :\n" ++ (show $ u unionFstPart unionSndPart)) True
                    in u unionFstPart unionSndPart