A Cartesian product is an inner join by definition :). The current cartesian product operator does not support outer joins, so we use the only operator that does: BroadcastNestedLoopJoinExec. This is far from great, and it does have the potential to OOM, there are some safety nets in the driver that should start complaining before you actually OOM though.
An outer non-equi join is pretty hard to do in a distributed setting. This is caused by two things:
There is no way to partition the data in such a way that you can exploit some locality (know that all the same keys are in one partition), unless you use only one partition or use some clever index.
You need to keep track of records that do not match the join condition if you are doing a full join or a join in which the stream side does not match the join side. This is the number one source of complexity in the current join implementations. If you can partition your data then you can track and emit unmatched rows as part of processing the partition. If you cannot (and you have more than 1 partition) then you need to send the unmatched rows (in some form) back to the driver and figure out which records actually have not been matched (see BroadcastNestedLoopJoinExec for example).
It is definitely doable to implement a such a join, however I have not seen many JIRA's or user requests for this.