# Example Factories

### Complex Factories

The factory scheme can be used to model a volcano-style query processor. Each node in the query tree is an iterator that calls upon the operands to produce a chunk, which are combined into a new chunk for consumption of the parent. The prototypical join(R,S) query illustrates it. The plan does not test for all boundary conditions, it merely implements a nested loop. The end of a sequence is identified by a NIL chunk.

```     factory query();
Left:= sql.bind("relationA");
Right:= sql.bind("relationB");
rc:= sql.joinStep(Left,Right);
barrier rc!= nil;
io.print(rc);
rc:= sql.joinStep(Left,Right);
redo rc!= nil;
exit rc;
end query;

#nested loop join
factory sql.joinStep(Left:bat[:any,:any],Right:bat[:any,:any]):bat[:any,:any];
lc:= bat.chunkStep(Left);
barrier outer:= lc != nil;
rc:= bat.chunkStep(Right);
barrier inner:= rc != nil;
chunk:= algebra.join(lc,rc);
yield chunk;
rc:= bat.chunkStep(Right);
redo inner:= rc != nil;
exit inner;
lc:= bat.chunkStep(Left);
redo outer:= lc != nil;
exit outer;
# we have seen everything
return nil;
end joinStep;

#factory for left branch
factory chunkStepL(L:bat[:any,:any]):bat[:any,:any];
i:= 0;
j:= 20;
cnt:= algebra.count(L);
barrier outer:= j<cnt;
chunk:= algebra.slice(L,i,j);
i:= j;
j:= i+ 20;
yield chunk;
redo loop:= j<cnt;
exit outer;
# send last portion
chunk:= algebra.slice(L,i,cnt);
yielD chunk;
return nil;
end chunkStep;

#factory for right leg
factory chunkStepR(L:bat[:any,:any]):bat[:any,:any];
```

So far we haven't re-used the pattern that both legs are identical. This could be modeled by a generic chunk factory. Choosing a new factory for each query steps reduces the administrative overhead.

### Materialized Views

An area where factories might be useful are support for materialized views, i.e. the result of a query is retained for ease of access. A simple strategy is to prepare the result once and return it on each successive call. Provided the arguments have not been changed. For example:

```     factory view1(l:int, h:int):bat[:oid,:str];
a:bat[:oid,:int]:= bbp.bind("emp","age");
b:bat[:oid,:str]:= bbp.bind("emp","name");
barrier always := true;
lOld := l;
hOld := h;
c := algebra.select(a,l,h);
d := algebra.semijoin(b,c);
barrier available := true;
yield d;
leave available := calc.!=(lOld,l);
leave available := calc.!=(hOld,h);
redo available := true;
exit available;
redo always;
exit always;
end view1;
```

The code should be extended to also check validity of the BATs. It requires a check against the last transaction identifier known.

The Factory concept is still rather experimental and many questions should be considered, e.g. What is the lifetime of a factory? Does it persists after all clients has disappeared? What additional control do you need? Can you throw an exception to a Factory?