# Buggy code
def _add_select(self, table_set):
    to_select = []
    for expr in self.select_set:
        if isinstance(expr, ir.ValueExpr):
            arg = self._translate(expr, named=True)
        elif isinstance(expr, ir.TableExpr):
            if expr.equals(self.table_set):
                cached_table = self.context.get_table(expr)
                if cached_table is None:
                    # the select * case from materialized join
                    arg = "*"
                else:
                    arg = table_set
            else:
                arg = self.context.get_table(expr)
                if arg is None:
                    raise ValueError(expr)

        to_select.append(arg)

    if self.exists:
        clause = sa.exists(to_select)
    else:
        clause = sa.select(to_select)

    if self.distinct:
        clause = clause.distinct()

    if table_set is not None:
        return clause.select_from(table_set)
    else:
        return clause


# Traceback (NotImplementedError)
---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
<ipython-input-1-7f46bd388b37> in <module>()
----> 1 t1.join(t2, t1.id1 == t2.id2).materialize().val2.compile()

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/expr/types.pyc in compile(self, limit)
148         """
149         from ibis.client import compile
--> 150         return compile(self, limit=limit)
151
152     def verify(self):

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/client.pyc in compile(expr, limit)
317 def compile(expr, limit=None):
318     backend = find_backend(expr)
--> 319     return backend.compile(expr, limit=limit)
320
321

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/client.pyc in compile(self, expr, params, limit)
242         output : single query or list of queries
243         """
--> 244         ast = self._build_ast_ensure_limit(expr, limit)
245         queries = [query.compile() for query in ast.queries]
246         return queries[0] if len(queries) == 1 else queries

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/client.pyc in _build_ast_ensure_limit(self, expr, limit)
247
248     def _build_ast_ensure_limit(self, expr, limit):
--> 249         ast = self._build_ast(expr)
250         # note: limit can still be None at this point, if the global
251         # default_limit is None

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/sql/alchemy.pyc in _build_ast(self, expr)
544
545     def _build_ast(self, expr):
--> 546         return build_ast(expr, dialect=self.dialect)
547
548     def _get_sqla_table(self, name):

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/sql/alchemy.pyc in build_ast(expr, context, dialect)
449 def build_ast(expr, context=None, dialect=None):
450     builder = AlchemyQueryBuilder(expr, context=context, dialect=dialect)
--> 451     return builder.get_result()
452
453

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/sql/compiler.pyc in get_result(self)
926             query = self._make_union()
927         else:
--> 928             query = self._make_select()
929
930         return QueryAST(self.context, [query])

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/sql/compiler.pyc in _make_select(self)
938     def _make_select(self):
939         builder = self.select_builder(self.expr, self.context)
--> 940         return builder.get_result()
941
942

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/sql/compiler.pyc in get_result(self)
84         teardown_queries = self._generate_teardown_queries()
85
---> 86         select_query = self._build_result_query()
87
88         self.queries.extend(setup_queries)

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/sql/compiler.pyc in _build_result_query(self)
103         self._analyze_select_exprs()
104         self._analyze_filter_exprs()
--> 105         self._analyze_subqueries()
106         self._populate_context()
107

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/sql/compiler.pyc in _analyze_subqueries(self)
543
544         # Find the subqueries, and record them in the passed query context.
--> 545         subqueries = _extract_subqueries(self)
546         self.subqueries = []
547         for expr in subqueries:

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/sql/compiler.pyc in _extract_subqueries(select_stmt)
590 def _extract_subqueries(select_stmt):
591     helper = _ExtractSubqueries(select_stmt)
--> 592     return helper.get_result()
593
594

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/sql/compiler.pyc in get_result(self)
612     def get_result(self):
613         if self.query.table_set is not None:
--> 614             self.visit(self.query.table_set)
615
616         for clause in self.query.filters:

/Users/jakedust/.ibis-postgres-env/lib/python2.7/site-packages/ibis_framework-0.6.0+11.ga278aea-py2.7.egg/ibis/sql/compiler.pyc in visit(self, expr)
659                 self.visit(arg)
660         else:
--> 661             raise NotImplementedError(type(node))
662
663     def _visit_join(self, expr):

NotImplementedError: <class 'ibis.expr.operations.MaterializedJoin'>

# Fixed code
def _add_select(self, table_set):
    to_select = []

    has_select_star = False
    for expr in self.select_set:
        if isinstance(expr, ir.ValueExpr):
            arg = self._translate(expr, named=True)
        elif isinstance(expr, ir.TableExpr):
            if expr.equals(self.table_set):
                cached_table = self.context.get_table(expr)
                if cached_table is None:
                    # the select * case from materialized join
                    has_select_star = True
                    continue
                else:
                    arg = table_set
            else:
                arg = self.context.get_table(expr)
                if arg is None:
                    raise ValueError(expr)

        to_select.append(arg)

    if has_select_star:
        if table_set is None:
            raise ValueError("table_set cannot be None here")

        clauses = [table_set] + to_select
    else:
        clauses = to_select

    if self.exists:
        result = sa.exists(clauses)
    else:
        result = sa.select(clauses)

    if self.distinct:
        result = result.distinct()

    if not has_select_star:
        if table_set is not None:
            return result.select_from(table_set)
        else:
            return result
    else:
        return result