runInnerJoinO ::
    RJoinPredicate
    -> RTable
    -> RTable
    -> RTable
runInnerJoinO jpred tabDriver tabProbed =  
    if isRTabEmpty tabDriver || isRTabEmpty tabProbed
        then
            emptyRTable
        else 
            do 
                rtupDrv <- tabDriver
                -- this is the equivalent of a nested loop with tabDriver playing the role of the driving table and tabProbed the probed table
                V.foldr' (\t accum -> 
                            if (jpred rtupDrv t) 
                                then 
                                    -- insert joined tuple to result table (i.e. the accumulator)
                                    insertAppendRTab (joinRTuples rtupDrv t) accum
                                else 
                                    -- keep the accumulator unchanged
                                    accum
                        ) emptyRTable tabProbed 


-- | Joins two RTuples into one. 
-- In this join we follow Oracle DB's convention when joining two tuples with some common column names.
-- When we have two tuples t1 and t2 with a common column name (lets say "Common"), then the resulitng 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.
runInnerJoinO ::
    RJoinPredicate
    -> RTable
    -> RTable
    -> RTable
runInnerJoinO jpred tabDriver tabProbed =  
    if isRTabEmpty tabDriver || isRTabEmpty tabProbed
        then
            emptyRTable
        else 
            do 
                rtupDrv <- tabDriver
                -- this is the equivalent of a nested loop with tabDriver playing the role of the driving table and tabProbed the probed table
                V.foldr' (\t accum -> 
                            if (jpred rtupDrv t) 
                                then 
                                    -- insert joined tuple to result table (i.e. the accumulator)
                                    insertAppendRTab (joinRTuples rtupDrv t) accum
                                else 
                                    -- keep the accumulator unchanged
                                    accum
                        ) emptyRTable tabProbed 


-- | Joins two RTuples into one. 
-- In this join we follow Oracle DB's convention when joining two tuples with some common column names.
-- When we have two tuples t1 and t2 with a common column name (lets say "Common"), then the resulitng 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.
runInnerJoinO jpred tabDriver tabProbed =  
    if isRTabEmpty tabDriver || isRTabEmpty tabProbed
        then
            emptyRTable
        else 
            do 
                rtupDrv <- tabDriver
                -- this is the equivalent of a nested loop with tabDriver playing the role of the driving table and tabProbed the probed table
                V.foldr' (\t accum -> 
                            if (jpred rtupDrv t) 
                                then 
                                    -- insert joined tuple to result table (i.e. the accumulator)
                                    insertAppendRTab (joinRTuples rtupDrv t) accum
                                else 
                                    -- keep the accumulator unchanged
                                    accum
                        ) emptyRTable tabProbed 


-- | Joins two RTuples into one. 
-- In this join we follow Oracle DB's convention when joining two tuples with some common column names.
-- When we have two tuples t1 and t2 with a common column name (lets say "Common"), then the resulitng 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.