@@ -177,14 +177,96 @@ def _(op: ops.base_ops.UnaryOp, expr: TypedExpr) -> sge.Expression:
177177 )
178178
179179
180+ @UNARY_OP_REGISTRATION .register (ops .StrContainsOp )
181+ def _ (op : ops .StrContainsOp , expr : TypedExpr ) -> sge .Expression :
182+ return sge .Like (this = expr .expr , expression = sge .convert (f"%{ op .pat } %" ))
183+
184+
180185@UNARY_OP_REGISTRATION .register (ops .StrContainsRegexOp )
181186def _ (op : ops .StrContainsRegexOp , expr : TypedExpr ) -> sge .Expression :
182187 return sge .RegexpLike (this = expr .expr , expression = sge .convert (op .pat ))
183188
184189
185- @UNARY_OP_REGISTRATION .register (ops .StrContainsOp )
186- def _ (op : ops .StrContainsOp , expr : TypedExpr ) -> sge .Expression :
187- return sge .Like (this = expr .expr , expression = sge .convert (f"%{ op .pat } %" ))
190+ @UNARY_OP_REGISTRATION .register (ops .StrExtractOp )
191+ def _ (op : ops .StrExtractOp , expr : TypedExpr ) -> sge .Expression :
192+ return sge .RegexpExtract (
193+ this = expr .expr , expression = sge .convert (op .pat ), group = sge .convert (op .n )
194+ )
195+
196+
197+ @UNARY_OP_REGISTRATION .register (ops .StrFindOp )
198+ def _ (op : ops .StrFindOp , expr : TypedExpr ) -> sge .Expression :
199+ # INSTR is 1-based, so we need to adjust the start position.
200+ start = sge .convert (op .start + 1 ) if op .start is not None else sge .convert (1 )
201+ if op .end is not None :
202+ # BigQuery's INSTR doesn't support `end`, so we need to use SUBSTR.
203+ return sge .func (
204+ "INSTR" ,
205+ sge .Substring (
206+ this = expr .expr ,
207+ start = start ,
208+ length = sge .convert (op .end - (op .start or 0 )),
209+ ),
210+ sge .convert (op .substr ),
211+ ) - sge .convert (1 )
212+ else :
213+ return sge .func (
214+ "INSTR" ,
215+ expr .expr ,
216+ sge .convert (op .substr ),
217+ start ,
218+ ) - sge .convert (1 )
219+
220+
221+ @UNARY_OP_REGISTRATION .register (ops .StrLstripOp )
222+ def _ (op : ops .StrLstripOp , expr : TypedExpr ) -> sge .Expression :
223+ return sge .Trim (this = expr .expr , expression = sge .convert (op .to_strip ), side = "LEFT" )
224+
225+
226+ @UNARY_OP_REGISTRATION .register (ops .StrPadOp )
227+ def _ (op : ops .StrPadOp , expr : TypedExpr ) -> sge .Expression :
228+ pad_length = sge .func (
229+ "GREATEST" , sge .Length (this = expr .expr ), sge .convert (op .length )
230+ )
231+ if op .side == "left" :
232+ return sge .func (
233+ "LPAD" ,
234+ expr .expr ,
235+ pad_length ,
236+ sge .convert (op .fillchar ),
237+ )
238+ elif op .side == "right" :
239+ return sge .func (
240+ "RPAD" ,
241+ expr .expr ,
242+ pad_length ,
243+ sge .convert (op .fillchar ),
244+ )
245+ else : # side == both
246+ lpad_amount = sge .Cast (
247+ this = sge .func (
248+ "SAFE_DIVIDE" ,
249+ sge .Sub (this = pad_length , expression = sge .Length (this = expr .expr )),
250+ sge .convert (2 ),
251+ ),
252+ to = "INT64" ,
253+ ) + sge .Length (this = expr .expr )
254+ return sge .func (
255+ "RPAD" ,
256+ sge .func (
257+ "LPAD" ,
258+ expr .expr ,
259+ lpad_amount ,
260+ sge .convert (op .fillchar ),
261+ ),
262+ pad_length ,
263+ sge .convert (op .fillchar ),
264+ )
265+
266+
267+ @UNARY_OP_REGISTRATION .register (ops .StrRepeatOp )
268+ def _ (op : ops .StrRepeatOp , expr : TypedExpr ) -> sge .Expression :
269+ return sge .Repeat (this = expr .expr , times = sge .convert (op .repeats ))
188270
189271
190272@UNARY_OP_REGISTRATION .register (ops .date_op )
@@ -262,6 +344,27 @@ def _(op: ops.base_ops.UnaryOp, expr: TypedExpr) -> sge.Expression:
262344 return sge .func ("ST_BOUNDARY" , expr .expr )
263345
264346
347+ @UNARY_OP_REGISTRATION .register (ops .GeoStBufferOp )
348+ def _ (op : ops .GeoStBufferOp , expr : TypedExpr ) -> sge .Expression :
349+ return sge .func (
350+ "ST_BUFFER" ,
351+ expr .expr ,
352+ sge .convert (op .buffer_radius ),
353+ sge .convert (op .num_seg_quarter_circle ),
354+ sge .convert (op .use_spheroid ),
355+ )
356+
357+
358+ @UNARY_OP_REGISTRATION .register (ops .geo_st_centroid_op )
359+ def _ (op : ops .base_ops .UnaryOp , expr : TypedExpr ) -> sge .Expression :
360+ return sge .func ("ST_CENTROID" , expr .expr )
361+
362+
363+ @UNARY_OP_REGISTRATION .register (ops .geo_st_convexhull_op )
364+ def _ (op : ops .base_ops .UnaryOp , expr : TypedExpr ) -> sge .Expression :
365+ return sge .func ("ST_CONVEXHULL" , expr .expr )
366+
367+
265368@UNARY_OP_REGISTRATION .register (ops .geo_st_geogfromtext_op )
266369def _ (op : ops .base_ops .UnaryOp , expr : TypedExpr ) -> sge .Expression :
267370 return sge .func ("SAFE.ST_GEOGFROMTEXT" , expr .expr )
@@ -434,6 +537,17 @@ def _(op: ops.base_ops.UnaryOp, expr: TypedExpr) -> sge.Expression:
434537 return sge .Lower (this = expr .expr )
435538
436539
540+ @UNARY_OP_REGISTRATION .register (ops .MapOp )
541+ def _ (op : ops .MapOp , expr : TypedExpr ) -> sge .Expression :
542+ return sge .Case (
543+ this = expr .expr ,
544+ ifs = [
545+ sge .If (this = sge .convert (key ), true = sge .convert (value ))
546+ for key , value in op .mappings
547+ ],
548+ )
549+
550+
437551@UNARY_OP_REGISTRATION .register (ops .minute_op )
438552def _ (op : ops .base_ops .UnaryOp , expr : TypedExpr ) -> sge .Expression :
439553 return sge .Extract (this = sge .Identifier (this = "MINUTE" ), expression = expr .expr )
@@ -444,11 +558,6 @@ def _(op: ops.base_ops.UnaryOp, expr: TypedExpr) -> sge.Expression:
444558 return sge .Extract (this = sge .Identifier (this = "MONTH" ), expression = expr .expr )
445559
446560
447- @UNARY_OP_REGISTRATION .register (ops .StrLstripOp )
448- def _ (op : ops .StrLstripOp , expr : TypedExpr ) -> sge .Expression :
449- return sge .Trim (this = expr .expr , expression = sge .convert (op .to_strip ), side = "LEFT" )
450-
451-
452561@UNARY_OP_REGISTRATION .register (ops .neg_op )
453562def _ (op : ops .base_ops .UnaryOp , expr : TypedExpr ) -> sge .Expression :
454563 return sge .Neg (this = expr .expr )
@@ -484,6 +593,18 @@ def _(op: ops.base_ops.UnaryOp, expr: TypedExpr) -> sge.Expression:
484593 return sge .Extract (this = sge .Identifier (this = "QUARTER" ), expression = expr .expr )
485594
486595
596+ @UNARY_OP_REGISTRATION .register (ops .ReplaceStrOp )
597+ def _ (op : ops .ReplaceStrOp , expr : TypedExpr ) -> sge .Expression :
598+ return sge .func ("REPLACE" , expr .expr , sge .convert (op .pat ), sge .convert (op .repl ))
599+
600+
601+ @UNARY_OP_REGISTRATION .register (ops .RegexReplaceStrOp )
602+ def _ (op : ops .RegexReplaceStrOp , expr : TypedExpr ) -> sge .Expression :
603+ return sge .func (
604+ "REGEXP_REPLACE" , expr .expr , sge .convert (op .pat ), sge .convert (op .repl )
605+ )
606+
607+
487608@UNARY_OP_REGISTRATION .register (ops .reverse_op )
488609def _ (op : ops .base_ops .UnaryOp , expr : TypedExpr ) -> sge .Expression :
489610 return sge .func ("REVERSE" , expr .expr )
0 commit comments