Issue #20 - Hash join implementations

The main impact on interfaces in the current master:

1. QueryCompiler: the original logic of compile() now goes into compileSingleQuery(), and the call compile() is now used as entry for both single select statements and join statements. Join statement compilation might go through recursive calls of compileSingleQuery() and compileJoinQuery().

2. ServerCacheClient: the original interface takes a TableRef in the constructor, while the parameter has now been moved to addServerCache(), for the reason that we might want to reuse ServerCacheClient for multiple calls in completing a query, and the parameter "cacheUsingTableRef" could be different among these multiple calls.