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
32
- from django_mongodb_backend .query_utils import is_direct_value , process_lhs
29
+ from django_mongodb_backend .query_utils import process_lhs
33
30
34
31
35
- def case (self , compiler , connection , as_path = False ):
32
+ def case (self , compiler , connection ):
36
33
case_parts = []
37
34
for case in self .cases :
38
35
case_mql = {}
@@ -49,16 +46,12 @@ def case(self, compiler, connection, as_path=False):
49
46
default_mql = self .default .as_mql (compiler , connection )
50
47
if not case_parts :
51
48
return default_mql
52
- expr = {
49
+ return {
53
50
"$switch" : {
54
51
"branches" : case_parts ,
55
52
"default" : default_mql ,
56
53
}
57
54
}
58
- if as_path :
59
- return {"$expr" : expr }
60
-
61
- return expr
62
55
63
56
64
57
def col (self , compiler , connection , as_path = False ): # noqa: ARG001
@@ -99,12 +92,12 @@ def combined_expression(self, compiler, connection, as_path=False):
99
92
return connection .ops .combine_expression (self .connector , expressions )
100
93
101
94
102
- def expression_wrapper (self , compiler , connection , as_path = False ):
103
- 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 )
104
97
105
98
106
- def negated_expression (self , compiler , connection , as_path = False ):
107
- 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 )}
108
101
109
102
110
103
def order_by (self , compiler , connection ):
@@ -177,32 +170,26 @@ def ref(self, compiler, connection, as_path=False): # noqa: ARG001
177
170
return f"{ prefix } { refs } "
178
171
179
172
180
- 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
181
179
return {"$literal" : True }
182
180
183
181
184
- def subquery (self , compiler , connection , get_wrapping_pipeline = None , as_path = False ):
185
- expr = self .query .as_mql (
182
+ def subquery (self , compiler , connection , get_wrapping_pipeline = None ):
183
+ return self .query .as_mql (
186
184
compiler , connection , get_wrapping_pipeline = get_wrapping_pipeline , as_path = False
187
185
)
188
- if as_path :
189
- return {"$expr" : expr }
190
- return expr
191
186
192
187
193
- def exists (self , compiler , connection , get_wrapping_pipeline = None , as_path = False ):
188
+ def exists (self , compiler , connection , get_wrapping_pipeline = None ):
194
189
try :
195
- lhs_mql = subquery (
196
- self ,
197
- compiler ,
198
- connection ,
199
- get_wrapping_pipeline = get_wrapping_pipeline ,
200
- as_path = as_path ,
201
- )
190
+ lhs_mql = subquery (self , compiler , connection , get_wrapping_pipeline = get_wrapping_pipeline )
202
191
except EmptyResultSet :
203
192
return Value (False ).as_mql (compiler , connection )
204
- if as_path :
205
- return {"$expr" : connection .mongo_operators_match ["isnull" ](lhs_mql , False )}
206
193
return connection .mongo_operators_expr ["isnull" ](lhs_mql , False )
207
194
208
195
@@ -234,54 +221,37 @@ def value(self, compiler, connection, as_path=False): # noqa: ARG001
234
221
return value
235
222
236
223
237
- @staticmethod
238
- def _is_constant_value (value ):
239
- if isinstance (value , list | Array ):
240
- iterable = value .get_source_expressions () if isinstance (value , Array ) else value
241
- return all (_is_constant_value (e ) for e in iterable )
242
- if is_direct_value (value ):
243
- return True
244
- return isinstance (value , Func | Value ) and not (
245
- value .contains_aggregate
246
- or value .contains_over_clause
247
- or value .contains_column_references
248
- or value .contains_subquery
249
- )
250
-
251
-
252
- @staticmethod
253
- def _is_simple_column (lhs ):
254
- while isinstance (lhs , KeyTransform ):
255
- if "." in getattr (lhs , "key_name" , "" ):
256
- return False
257
- lhs = lhs .lhs
258
- col = lhs .source if isinstance (lhs , Ref ) else lhs
259
- # Foreign columns from parent cannot be addressed as single match
260
- return isinstance (col , Col ) and col .alias is not None
261
-
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 )
262
231
263
- def _is_simple_expression ( self ):
264
- 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
265
234
266
235
267
236
def register_expressions ():
268
- Case .as_mql = case
237
+ BaseExpression .as_mql = base_expression
238
+ BaseExpression .is_simple_column = False
239
+ Case .as_mql_expr = case
269
240
Col .as_mql = col
241
+ Col .is_simple_column = True
270
242
ColPairs .as_mql = col_pairs
271
- CombinedExpression .as_mql = combined_expression
272
- Exists .as_mql = exists
243
+ CombinedExpression .as_mql_expr = combined_expression
244
+ Exists .as_mql_expr = exists
273
245
ExpressionList .as_mql = process_lhs
274
- ExpressionWrapper .as_mql = expression_wrapper
275
- NegatedExpression .as_mql = negated_expression
276
- 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
277
249
Query .as_mql = query
278
250
RawSQL .as_mql = raw_sql
279
251
Ref .as_mql = ref
252
+ Ref .is_simple_column = ref_is_simple_column
280
253
ResolvedOuterRef .as_mql = ResolvedOuterRef .as_sql
281
254
Star .as_mql = star
282
- Subquery .as_mql = subquery
255
+ Subquery .as_mql_expr = subquery
283
256
When .as_mql = when
284
257
Value .as_mql = value
285
- BaseExpression .is_simple_expression = _is_simple_expression
286
- BaseExpression .is_simple_column = _is_simple_column
287
- BaseExpression .is_constant_value = _is_constant_value
0 commit comments