This query should give us two NL index joins because of the hints.
select count (1) from R join S on
R.u1K /*+ indexnl */ = tobigint(S.u1K)
join T on tobigint(S.u4K) /*+ indexnl */ = T.u4K ;
Here is the logical plan that is given to the CBO optimizer.
The problem happens because of these two lines
join (eq($$79, $$80)) – |PARTITIONED|
assign [$$79] <- [to-bigint($$85)] – |PARTITIONED| <<<<<< THIS ASSIGN!!
The CBO code used the assign in the "internal edge" to modify the join predicate as follows:
This fails to pass the ifApplicable test to see if a nl index join is possible.
Consequently, we get a hash join between S and T followed by an index NL join with R.
Some of these queries produced an internal edge with an assign statement such as $$25 <-- tobigint ($$20)
The assign statement is then used to modify the next join predicate eq($$25, $$30) to
It turns out that NL index join code only accepts the original join predicate.
The fix will be to push down the assigns from the internal edge to the corresponding leaf node.