I was actually thinking about going the other direction - similar to the
pullexec approach:
refactor NLIJ::p_execute, IndexScan::p_execute, Projection::p_execute to be
able to call each other instead of current cut-and-paste implementation.
This way NLIJ doesn't need to be aware of the index node projection.
The NLJ is fine even now simply because it doesn't have an inline scan
node. The projection logic is hidden within the SeqScan::p_execute call

I guess, the both approaches are complimentary, what do you think?

On Mon, Mar 4, 2013 at 12:40 PM, Paul A Martel <notifications@github.com>wrote:

> In src/ee/executors/nestloopexecutor.cpp:
>
> > @@ -241,6 +251,13 @@ bool NestLoopExecutor::p_execute(const NValueArray &params) {
> >                  output_table->insertTupleNonVirtual(joined);
> >              }
> >          }
> > +        //
> > +        // Left Outer Join
> > +        //
> > +        if (!match && join_type == JOIN_TYPE_LEFT) {
> > +            joined.setNValues(null_tuple.getTuple(), outer_cols, joined.sizeInValues());
> > +            output_table->insertTupleNonVirtual(joined);
> > +        }
>
> This sounds like another case of a shortfall in the planner being
> compensated for in the EE -- I am in the process -- though I am out sick
> today -- of trying to get the planner to generate more complete plans
> containing correct column indexes and inner/outer tuple designations. As
> far as I can tell, the end result will not require evals in the nest loop
> code. But I have yet to prove this.
> … <#13d367d2f709c9be_>
> On Sun, Mar 3, 2013 at 9:31 PM, Michael Alexeev <notifications@github.com>wrote:
> In src/ee/executors/nestloopexecutor.cpp: > @@ -241,6 +251,13 @@ bool
> NestLoopExecutor::p_execute(const NValueArray &params) { >
> output_table->insertTupleNonVirtual(joined); > } > } > + // > + // Left
> Outer Join > + // > + if (!match && join_type == JOIN_TYPE_LEFT) { > +
> joined.setNValues(null_tuple.getTuple(), outer_cols,
> joined.sizeInValues()); > + output_table->insertTupleNonVirtual(joined); >
> + } There is actually the reason for evals calls (for matched inner tuple
> only) - inline projection! Found it the hard way. The inner table in case
> of NLIJ is the inner node target table and not the output one. The outer
> table tuple and non-matched inner one can be set by using getNValue method
> directly. The non-matched inner tuple should have the schema of the inner
> node output table and not the target one though. I created
> ExpressionUtil::evalExpressions method to hide the eval loop. The other
> approach could be to properly initialize the projection node, factor-out
> ProjectionExecutor::p_execute while loop inner logic into a separate
> method, and call it from NLIJ loop as well. — Reply to this email directly
> or view it on GitHub<
> https://github.com/alexeevm/voltdb/pull/4/files#r3219386> .
>
> —
> Reply to this email directly or view it on GitHub<https://github.com/alexeevm/voltdb/pull/4/files#r3228156>
> .
>