@@ -177,14 +177,96 @@ def _(op: ops.base_ops.UnaryOp, expr: TypedExpr) -> sge.Expression:
177
177
)
178
178
179
179
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
+
180
185
@UNARY_OP_REGISTRATION .register (ops .StrContainsRegexOp )
181
186
def _ (op : ops .StrContainsRegexOp , expr : TypedExpr ) -> sge .Expression :
182
187
return sge .RegexpLike (this = expr .expr , expression = sge .convert (op .pat ))
183
188
184
189
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 ))
188
270
189
271
190
272
@UNARY_OP_REGISTRATION .register (ops .date_op )
@@ -262,6 +344,27 @@ def _(op: ops.base_ops.UnaryOp, expr: TypedExpr) -> sge.Expression:
262
344
return sge .func ("ST_BOUNDARY" , expr .expr )
263
345
264
346
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
+
265
368
@UNARY_OP_REGISTRATION .register (ops .geo_st_geogfromtext_op )
266
369
def _ (op : ops .base_ops .UnaryOp , expr : TypedExpr ) -> sge .Expression :
267
370
return sge .func ("SAFE.ST_GEOGFROMTEXT" , expr .expr )
@@ -434,6 +537,17 @@ def _(op: ops.base_ops.UnaryOp, expr: TypedExpr) -> sge.Expression:
434
537
return sge .Lower (this = expr .expr )
435
538
436
539
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
+
437
551
@UNARY_OP_REGISTRATION .register (ops .minute_op )
438
552
def _ (op : ops .base_ops .UnaryOp , expr : TypedExpr ) -> sge .Expression :
439
553
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:
444
558
return sge .Extract (this = sge .Identifier (this = "MONTH" ), expression = expr .expr )
445
559
446
560
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
-
452
561
@UNARY_OP_REGISTRATION .register (ops .neg_op )
453
562
def _ (op : ops .base_ops .UnaryOp , expr : TypedExpr ) -> sge .Expression :
454
563
return sge .Neg (this = expr .expr )
@@ -484,6 +593,18 @@ def _(op: ops.base_ops.UnaryOp, expr: TypedExpr) -> sge.Expression:
484
593
return sge .Extract (this = sge .Identifier (this = "QUARTER" ), expression = expr .expr )
485
594
486
595
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
+
487
608
@UNARY_OP_REGISTRATION .register (ops .reverse_op )
488
609
def _ (op : ops .base_ops .UnaryOp , expr : TypedExpr ) -> sge .Expression :
489
610
return sge .func ("REVERSE" , expr .expr )
0 commit comments