3939 Upper ,
4040)
4141
42+ from .lookups import is_constant_value
4243from .query_utils import process_lhs
4344
4445MONGO_OPERATORS = {
@@ -84,18 +85,18 @@ def cast(self, compiler, connection, **extra): # noqa: ARG001
8485 return lhs_mql
8586
8687
87- def concat (self , compiler , connection ):
88- return self .get_source_expressions ()[0 ].as_mql (compiler , connection )
88+ def concat (self , compiler , connection , as_path = False ):
89+ return self .get_source_expressions ()[0 ].as_mql (compiler , connection , as_path = as_path )
8990
9091
91- def concat_pair (self , compiler , connection ):
92+ def concat_pair (self , compiler , connection , as_path = False ): # noqa: ARG001
9293 # null on either side results in null for expression, wrap with coalesce.
9394 coalesced = self .coalesce ()
94- return super (ConcatPair , coalesced ).as_mql (compiler , connection )
95+ return super (ConcatPair , coalesced ).as_mql (compiler , connection , as_path = False )
9596
9697
97- def cot (self , compiler , connection ):
98- lhs_mql = process_lhs (self , compiler , connection )
98+ def cot (self , compiler , connection , as_path = False ): # noqa: ARG001
99+ lhs_mql = process_lhs (self , compiler , connection , as_path = False )
99100 return {"$divide" : [1 , {"$tan" : lhs_mql }]}
100101
101102
@@ -117,8 +118,8 @@ def func(self, compiler, connection, **extra): # noqa: ARG001
117118 return {f"${ operator } " : lhs_mql }
118119
119120
120- def left (self , compiler , connection ):
121- return self .get_substr ().as_mql (compiler , connection )
121+ def left (self , compiler , connection , as_path = False ): # noqa: ARG001
122+ return self .get_substr ().as_mql (compiler , connection , as_path = False )
122123
123124
124125def length (self , compiler , connection , as_path = False ): # noqa: ARG001
@@ -127,28 +128,35 @@ def length(self, compiler, connection, as_path=False): # noqa: ARG001
127128 return {"$cond" : {"if" : {"$eq" : [lhs_mql , None ]}, "then" : None , "else" : {"$strLenCP" : lhs_mql }}}
128129
129130
130- def log (self , compiler , connection ):
131+ def log (self , compiler , connection , as_path = False ): # noqa: ARG001
131132 # This function is usually log(base, num) but on MongoDB it's log(num, base).
132133 clone = self .copy ()
133134 clone .set_source_expressions (self .get_source_expressions ()[::- 1 ])
134135 return func (clone , compiler , connection )
135136
136137
137- def now (self , compiler , connection ): # noqa: ARG001
138+ def now (self , compiler , connection , as_path = False ): # noqa: ARG001
138139 return "$$NOW"
139140
140141
141- def null_if (self , compiler , connection ):
142+ def null_if (self , compiler , connection , as_path = False ): # noqa: ARG001
142143 """Return None if expr1==expr2 else expr1."""
143- expr1 , expr2 = (expr .as_mql (compiler , connection ) for expr in self .get_source_expressions ())
144+ expr1 , expr2 = (
145+ expr .as_mql (compiler , connection , as_path = False ) for expr in self .get_source_expressions ()
146+ )
144147 return {"$cond" : {"if" : {"$eq" : [expr1 , expr2 ]}, "then" : None , "else" : expr1 }}
145148
146149
147150def preserve_null (operator ):
148151 # If the argument is null, the function should return null, not
149152 # $toLower/Upper's behavior of returning an empty string.
150- def wrapped (self , compiler , connection ):
151- lhs_mql = process_lhs (self , compiler , connection )
153+ def wrapped (self , compiler , connection , as_path = False ):
154+ if is_constant_value (self .lhs ) and as_path :
155+ if self .lhs is None :
156+ return None
157+ lhs_mql = process_lhs (self , compiler , connection , as_path = True )
158+ return lhs_mql .upper ()
159+ lhs_mql = process_lhs (self , compiler , connection , as_path = False )
152160 return {
153161 "$expr" : {
154162 "$cond" : {
@@ -162,24 +170,29 @@ def wrapped(self, compiler, connection):
162170 return wrapped
163171
164172
165- def replace (self , compiler , connection ):
166- expression , text , replacement = process_lhs (self , compiler , connection )
173+ def replace (self , compiler , connection , as_path = False ):
174+ expression , text , replacement = process_lhs (self , compiler , connection , as_path = as_path )
167175 return {"$replaceAll" : {"input" : expression , "find" : text , "replacement" : replacement }}
168176
169177
170- def round_ (self , compiler , connection ):
178+ def round_ (self , compiler , connection , as_path = False ): # noqa: ARG001
171179 # Round needs its own function because it's a special case that inherits
172180 # from Transform but has two arguments.
173- return {"$round" : [expr .as_mql (compiler , connection ) for expr in self .get_source_expressions ()]}
181+ return {
182+ "$round" : [
183+ expr .as_mql (compiler , connection , as_path = False )
184+ for expr in self .get_source_expressions ()
185+ ]
186+ }
174187
175188
176- def str_index (self , compiler , connection ):
189+ def str_index (self , compiler , connection , as_path = False ): # noqa: ARG001
177190 lhs = process_lhs (self , compiler , connection )
178191 # StrIndex should be 0-indexed (not found) but it's -1-indexed on MongoDB.
179192 return {"$add" : [{"$indexOfCP" : lhs }, 1 ]}
180193
181194
182- def substr (self , compiler , connection , ** extra ): # noqa: ARG001
195+ def substr (self , compiler , connection , as_path = False ): # noqa: ARG001
183196 lhs = process_lhs (self , compiler , connection )
184197 # The starting index is zero-indexed on MongoDB rather than one-indexed.
185198 lhs [1 ] = {"$add" : [lhs [1 ], - 1 ]}
@@ -191,14 +204,14 @@ def substr(self, compiler, connection, **extra): # noqa: ARG001
191204
192205
193206def trim (operator ):
194- def wrapped (self , compiler , connection ):
207+ def wrapped (self , compiler , connection , as_path = False ): # noqa: ARG001
195208 lhs = process_lhs (self , compiler , connection )
196209 return {f"${ operator } " : {"input" : lhs }}
197210
198211 return wrapped
199212
200213
201- def trunc (self , compiler , connection , ** extra ): # noqa: ARG001
214+ def trunc (self , compiler , connection , as_path = False ): # noqa: ARG001
202215 lhs_mql = process_lhs (self , compiler , connection )
203216 lhs_mql = {"date" : lhs_mql , "unit" : self .kind , "startOfWeek" : "mon" }
204217 if timezone := self .get_tzname ():
@@ -257,11 +270,11 @@ def trunc_date(self, compiler, connection, **extra): # noqa: ARG001
257270 }
258271
259272
260- def trunc_time (self , compiler , connection ):
273+ def trunc_time (self , compiler , connection , as_path = False ): # noqa: ARG001
261274 tzname = self .get_tzname ()
262275 if tzname and tzname != "UTC" :
263276 raise NotSupportedError (f"TruncTime with tzinfo ({ tzname } ) isn't supported on MongoDB." )
264- lhs_mql = process_lhs (self , compiler , connection )
277+ lhs_mql = process_lhs (self , compiler , connection , as_path = False )
265278 return {
266279 "$dateFromString" : {
267280 "dateString" : {
0 commit comments