-- | Implements an Inner Join operation between two RTables (any type of join predicate is allowed)
-- Note that this operation is implemented as a 'Data.HashMap.Strict' union, which means "the first 
-- Map (i.e., the left RTuple) will be prefered when dublicate keys encountered with different values. That is, in the context of 
-- joining two RTuples the value of the first (i.e., left) RTuple on the common key will be prefered.
runInnerJoin ::
    RJoinPredicate
    -> RTable
    -> RTable
    -> RTable
runInnerJoin jpred irtab1 irtab2 =  
    if (isRTabEmpty irtab1) || (isRTabEmpty irtab2)
        then
            emptyRTable
        else 
            do 
                rtup1 <- irtab1
                rtup2 <- irtab2
                let targetRtuple = 
                        if (jpred rtup1 rtup2)
                        then HM.union rtup1 rtup2                 
                        else HM.empty
                removeEmptyRTuples (return targetRtuple)
                    where removeEmptyRTuples = f (not.isRTupEmpty) 

-- Inner Join with Oracle DB's convention for common column names.
-- When we have two tuples t1 and t2 with a common column name (lets say "Common"), then the resulting tuple after a join
-- will be "Common", "Common_1", so a "_1" suffix is appended. The tuple from the left table by convention retains the original column name.
-- So "Column_1" is the column from the right table. If "Column_1" already exists, then "Column_2" is used.
runInnerJoin ::
    RJoinPredicate
    -> RTable
    -> RTable
    -> RTable
runInnerJoin jpred irtab1 irtab2 =  
    if (isRTabEmpty irtab1) || (isRTabEmpty irtab2)
        then
            emptyRTable
        else 
            do 
                rtup1 <- irtab1
                rtup2 <- irtab2
                let targetRtuple = 
                        if (jpred rtup1 rtup2)
                        then HM.union rtup1 rtup2                 
                        else HM.empty
                removeEmptyRTuples (return targetRtuple)
                    where removeEmptyRTuples = f (not.isRTupEmpty) 

-- Inner Join with Oracle DB's convention for common column names.
-- When we have two tuples t1 and t2 with a common column name (lets say "Common"), then the resulting tuple after a join
-- will be "Common", "Common_1", so a "_1" suffix is appended. The tuple from the left table by convention retains the original column name.
-- So "Column_1" is the column from the right table. If "Column_1" already exists, then "Column_2" is used.
runInnerJoin jpred irtab1 irtab2 =  
    if (isRTabEmpty irtab1) || (isRTabEmpty irtab2)
        then
            emptyRTable
        else 
            do 
                rtup1 <- irtab1
                rtup2 <- irtab2
                let targetRtuple = 
                        if (jpred rtup1 rtup2)
                        then HM.union rtup1 rtup2                 
                        else HM.empty
                removeEmptyRTuples (return targetRtuple)
                    where removeEmptyRTuples = f (not.isRTupEmpty) 

-- Inner Join with Oracle DB's convention for common column names.
-- When we have two tuples t1 and t2 with a common column name (lets say "Common"), then the resulting tuple after a join
-- will be "Common", "Common_1", so a "_1" suffix is appended. The tuple from the left table by convention retains the original column name.
-- So "Column_1" is the column from the right table. If "Column_1" already exists, then "Column_2" is used.