@@ -1988,14 +1988,26 @@ def mutate(
19881988 │ Adelie │ 2007 │ -7.22193 │
19891989 └─────────┴───────┴────────────────┘
19901990 """
1991+
1992+ # the implementation of `mutate` should be kept in sync with that of `select`
1993+ # with the exception that mutate does not call bind on the fields already in this table (node.fields)
1994+ from ibis .expr .rewrites import rewrite_project_input
1995+
19911996 # string and integer inputs are going to be coerced to literals instead
19921997 # of interpreted as column references like in select
19931998 node = self .op ()
1994- values = self .bind (* exprs , ** mutations )
1999+ values = self .bind (* exprs , ** mutations ) # bind new expressions/mutations
19952000 values = unwrap_aliases (values )
1996- # allow overriding of fields, hence the mutation behavior
1997- values = {** node .fields , ** values }
1998- return self .select (** values )
2001+
2002+ # we need to detect reductions which are either turned into window functions
2003+ # or scalar subqueries depending on whether they are originating from self
2004+ values = {
2005+ k : rewrite_project_input (v , relation = self .op ()) for k , v in values .items ()
2006+ }
2007+
2008+ # note that existing fields in node.fields will skip bind&dereferencing to improve performance
2009+ # (unless overridden by mutations in **values)
2010+ return ops .Project (self , {** node .fields , ** values }).to_expr ()
19992011
20002012 def select (
20012013 self ,
@@ -2174,6 +2186,8 @@ def select(
21742186 │ 43.92193 │ 17.15117 │ 200.915205 │ 4201.754386 │
21752187 └────────────────┴───────────────┴───────────────────┴─────────────┘
21762188 """
2189+ # note that if changes are made to implementation of select,
2190+ # corresponding changes may be needed in `.mutate()`
21772191 from ibis .expr .rewrites import rewrite_project_input
21782192
21792193 values = self .bind (* exprs , ** named_exprs )
0 commit comments