14
14
Exists ,
15
15
ExpressionList ,
16
16
ExpressionWrapper ,
17
- Func ,
18
17
NegatedExpression ,
19
18
OrderBy ,
20
19
RawSQL ,
25
24
Value ,
26
25
When ,
27
26
)
28
- from django .db .models .fields .json import KeyTransform
29
27
from django .db .models .sql import Query
30
28
31
- from django_mongodb_backend . fields . array import Array
29
+ from .. query_utils import process_lhs
32
30
33
- from ..query_utils import is_direct_value , process_lhs
34
31
35
-
36
- def case (self , compiler , connection , as_path = False ):
32
+ def case (self , compiler , connection ):
37
33
case_parts = []
38
34
for case in self .cases :
39
35
case_mql = {}
@@ -50,16 +46,12 @@ def case(self, compiler, connection, as_path=False):
50
46
default_mql = self .default .as_mql (compiler , connection )
51
47
if not case_parts :
52
48
return default_mql
53
- expr = {
49
+ return {
54
50
"$switch" : {
55
51
"branches" : case_parts ,
56
52
"default" : default_mql ,
57
53
}
58
54
}
59
- if as_path :
60
- return {"$expr" : expr }
61
-
62
- return expr
63
55
64
56
65
57
def col (self , compiler , connection , as_path = False ): # noqa: ARG001
@@ -100,12 +92,12 @@ def combined_expression(self, compiler, connection, as_path=False):
100
92
return connection .ops .combine_expression (self .connector , expressions )
101
93
102
94
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 )
105
97
106
98
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 )}
109
101
110
102
111
103
def order_by (self , compiler , connection ):
@@ -178,32 +170,26 @@ def ref(self, compiler, connection, as_path=False): # noqa: ARG001
178
170
return f"{ prefix } { refs } "
179
171
180
172
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
182
179
return {"$literal" : True }
183
180
184
181
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 (
187
184
compiler , connection , get_wrapping_pipeline = get_wrapping_pipeline , as_path = False
188
185
)
189
- if as_path :
190
- return {"$expr" : expr }
191
- return expr
192
186
193
187
194
- def exists (self , compiler , connection , get_wrapping_pipeline = None , as_path = False ):
188
+ def exists (self , compiler , connection , get_wrapping_pipeline = None ):
195
189
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 )
203
191
except EmptyResultSet :
204
192
return Value (False ).as_mql (compiler , connection )
205
- if as_path :
206
- return {"$expr" : connection .mongo_operators_match ["isnull" ](lhs_mql , False )}
207
193
return connection .mongo_operators_expr ["isnull" ](lhs_mql , False )
208
194
209
195
@@ -235,54 +221,37 @@ def value(self, compiler, connection, as_path=False): # noqa: ARG001
235
221
return value
236
222
237
223
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 )
263
231
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
266
234
267
235
268
236
def 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
270
240
Col .as_mql = col
241
+ Col .is_simple_column = True
271
242
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
274
245
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
278
249
Query .as_mql = query
279
250
RawSQL .as_mql = raw_sql
280
251
Ref .as_mql = ref
252
+ Ref .is_simple_column = ref_is_simple_column
281
253
ResolvedOuterRef .as_mql = ResolvedOuterRef .as_sql
282
254
Star .as_mql = star
283
- Subquery .as_mql = subquery
255
+ Subquery .as_mql_expr = subquery
284
256
When .as_mql = when
285
257
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