Fix for #10: Hybrid Hash Join for iterations

With this change, ozone's hash join implementation is able to be reopened multiple times with different probe side inputs.

In-memory build-site contents are spilled to disk once the build phase has finished. Spilled build partitions are kept until hybrid hash join's final close() call, so that subsequent probe phases can re-use the build side.
Upon a reopen() call, hybrid hash join will reinitialize itself to the same state as after a regular open() call, but without re-pulling the build side iterator.

If the build side fits completely in-memory, no spilling will happen.

I'm very happy about feedback and comments on my code!