Better implementation of joins in ORM

Use an internal hash table of join information to prevent multiple joins
over the same path. Also use table aliases in order to support self joins or
otherwise multiple joins to the same table using different paths.