1414 Exists ,
1515 ExpressionList ,
1616 ExpressionWrapper ,
17- Func ,
1817 NegatedExpression ,
1918 OrderBy ,
2019 RawSQL ,
2524 Value ,
2625 When ,
2726)
28- from django .db .models .fields .json import KeyTransform
2927from django .db .models .sql import Query
3028
31- from django_mongodb_backend . fields . array import Array
29+ from .. query_utils import process_lhs
3230
33- from ..query_utils import is_direct_value , process_lhs
3431
35-
36- def case (self , compiler , connection , as_path = False ):
32+ def case (self , compiler , connection ):
3733 case_parts = []
3834 for case in self .cases :
3935 case_mql = {}
@@ -50,16 +46,12 @@ def case(self, compiler, connection, as_path=False):
5046 default_mql = self .default .as_mql (compiler , connection )
5147 if not case_parts :
5248 return default_mql
53- expr = {
49+ return {
5450 "$switch" : {
5551 "branches" : case_parts ,
5652 "default" : default_mql ,
5753 }
5854 }
59- if as_path :
60- return {"$expr" : expr }
61-
62- return expr
6355
6456
6557def col (self , compiler , connection , as_path = False ): # noqa: ARG001
@@ -100,12 +92,12 @@ def combined_expression(self, compiler, connection, as_path=False):
10092 return connection .ops .combine_expression (self .connector , expressions )
10193
10294
103- def expression_wrapper (self , compiler , connection , as_path = False ):
104- return self .expression .as_mql (compiler , connection , as_path = as_path )
95+ def expression_wrapper_expr (self , compiler , connection ):
96+ return self .expression .as_mql (compiler , connection , as_path = False )
10597
10698
107- def negated_expression (self , compiler , connection , as_path = False ):
108- return {"$not" : expression_wrapper (self , compiler , connection , as_path = as_path )}
99+ def negated_expression_expr (self , compiler , connection ):
100+ return {"$not" : expression_wrapper_expr (self , compiler , connection )}
109101
110102
111103def order_by (self , compiler , connection ):
@@ -178,32 +170,26 @@ def ref(self, compiler, connection, as_path=False): # noqa: ARG001
178170 return f"{ prefix } { refs } "
179171
180172
181- def star (self , compiler , connection , ** extra ): # noqa: ARG001
173+ @property
174+ def ref_is_simple_column (self ):
175+ return isinstance (self .source , Col ) and self .source .alias is not None
176+
177+
178+ def star (self , compiler , connection , as_path = False ): # noqa: ARG001
182179 return {"$literal" : True }
183180
184181
185- def subquery (self , compiler , connection , get_wrapping_pipeline = None , as_path = False ):
186- expr = self .query .as_mql (
182+ def subquery (self , compiler , connection , get_wrapping_pipeline = None ):
183+ return self .query .as_mql (
187184 compiler , connection , get_wrapping_pipeline = get_wrapping_pipeline , as_path = False
188185 )
189- if as_path :
190- return {"$expr" : expr }
191- return expr
192186
193187
194- def exists (self , compiler , connection , get_wrapping_pipeline = None , as_path = False ):
188+ def exists (self , compiler , connection , get_wrapping_pipeline = None ):
195189 try :
196- lhs_mql = subquery (
197- self ,
198- compiler ,
199- connection ,
200- get_wrapping_pipeline = get_wrapping_pipeline ,
201- as_path = as_path ,
202- )
190+ lhs_mql = subquery (self , compiler , connection , get_wrapping_pipeline = get_wrapping_pipeline )
203191 except EmptyResultSet :
204192 return Value (False ).as_mql (compiler , connection )
205- if as_path :
206- return {"$expr" : connection .mongo_operators_match ["isnull" ](lhs_mql , False )}
207193 return connection .mongo_operators_expr ["isnull" ](lhs_mql , False )
208194
209195
@@ -235,54 +221,37 @@ def value(self, compiler, connection, as_path=False): # noqa: ARG001
235221 return value
236222
237223
238- @staticmethod
239- def _is_constant_value (value ):
240- if isinstance (value , list | Array ):
241- iterable = value .get_source_expressions () if isinstance (value , Array ) else value
242- return all (_is_constant_value (e ) for e in iterable )
243- if is_direct_value (value ):
244- return True
245- return isinstance (value , Func | Value ) and not (
246- value .contains_aggregate
247- or value .contains_over_clause
248- or value .contains_column_references
249- or value .contains_subquery
250- )
251-
252-
253- @staticmethod
254- def _is_simple_column (lhs ):
255- while isinstance (lhs , KeyTransform ):
256- if "." in getattr (lhs , "key_name" , "" ):
257- return False
258- lhs = lhs .lhs
259- col = lhs .source if isinstance (lhs , Ref ) else lhs
260- # Foreign columns from parent cannot be addressed as single match
261- return isinstance (col , Col ) and col .alias is not None
262-
224+ def base_expression (self , compiler , connection , as_path = False , ** extra ):
225+ if (
226+ as_path
227+ and hasattr (self , "as_mql_path" )
228+ and getattr (self , "is_simple_expression" , lambda : False )()
229+ ):
230+ return self .as_mql_path (compiler , connection , ** extra )
263231
264- def _is_simple_expression ( self ):
265- return self . is_simple_column ( self . lhs ) and self . is_constant_value ( self . rhs )
232+ expr = self . as_mql_expr ( compiler , connection , ** extra )
233+ return { "$expr" : expr } if as_path else expr
266234
267235
268236def register_expressions ():
269- Case .as_mql = case
237+ BaseExpression .as_mql = base_expression
238+ BaseExpression .is_simple_column = False
239+ Case .as_mql_expr = case
270240 Col .as_mql = col
241+ Col .is_simple_column = True
271242 ColPairs .as_mql = col_pairs
272- CombinedExpression .as_mql = combined_expression
273- Exists .as_mql = exists
243+ CombinedExpression .as_mql_expr = combined_expression
244+ Exists .as_mql_expr = exists
274245 ExpressionList .as_mql = process_lhs
275- ExpressionWrapper .as_mql = expression_wrapper
276- NegatedExpression .as_mql = negated_expression
277- OrderBy .as_mql = order_by
246+ ExpressionWrapper .as_mql_expr = expression_wrapper_expr
247+ NegatedExpression .as_mql_expr = negated_expression_expr
248+ OrderBy .as_mql_expr = order_by
278249 Query .as_mql = query
279250 RawSQL .as_mql = raw_sql
280251 Ref .as_mql = ref
252+ Ref .is_simple_column = ref_is_simple_column
281253 ResolvedOuterRef .as_mql = ResolvedOuterRef .as_sql
282254 Star .as_mql = star
283- Subquery .as_mql = subquery
255+ Subquery .as_mql_expr = subquery
284256 When .as_mql = when
285257 Value .as_mql = value
286- BaseExpression .is_simple_expression = _is_simple_expression
287- BaseExpression .is_simple_column = _is_simple_column
288- BaseExpression .is_constant_value = _is_constant_value
0 commit comments