33
33
34
34
import google .cloud .bigquery as bq
35
35
36
- from bigframes .core import identifiers , local_data
36
+ from bigframes .core import identifiers , local_data , sequences
37
37
from bigframes .core .bigframe_node import BigFrameNode , COLUMN_SET , Field
38
38
import bigframes .core .expression as ex
39
39
from bigframes .core .ordering import OrderingExpression , RowOrdering
@@ -87,7 +87,7 @@ def child_nodes(self) -> typing.Sequence[BigFrameNode]:
87
87
return (self .child ,)
88
88
89
89
@property
90
- def fields (self ) -> Iterable [Field ]:
90
+ def fields (self ) -> Sequence [Field ]:
91
91
return self .child .fields
92
92
93
93
@property
@@ -226,8 +226,8 @@ def added_fields(self) -> Tuple[Field, ...]:
226
226
return (Field (self .indicator_col , bigframes .dtypes .BOOL_DTYPE , nullable = False ),)
227
227
228
228
@property
229
- def fields (self ) -> Iterable [Field ]:
230
- return itertools . chain (
229
+ def fields (self ) -> Sequence [Field ]:
230
+ return sequences . ChainedSequence (
231
231
self .left_child .fields ,
232
232
self .added_fields ,
233
233
)
@@ -321,15 +321,15 @@ def order_ambiguous(self) -> bool:
321
321
def explicitly_ordered (self ) -> bool :
322
322
return self .propogate_order
323
323
324
- @property
325
- def fields (self ) -> Iterable [Field ]:
326
- left_fields = self .left_child .fields
324
+ @functools . cached_property
325
+ def fields (self ) -> Sequence [Field ]:
326
+ left_fields : Iterable [ Field ] = self .left_child .fields
327
327
if self .type in ("right" , "outer" ):
328
328
left_fields = map (lambda x : x .with_nullable (), left_fields )
329
- right_fields = self .right_child .fields
329
+ right_fields : Iterable [ Field ] = self .right_child .fields
330
330
if self .type in ("left" , "outer" ):
331
331
right_fields = map (lambda x : x .with_nullable (), right_fields )
332
- return itertools . chain ( left_fields , right_fields )
332
+ return ( * left_fields , * right_fields )
333
333
334
334
@property
335
335
def joins_nulls (self ) -> bool :
@@ -430,10 +430,10 @@ def explicitly_ordered(self) -> bool:
430
430
return True
431
431
432
432
@property
433
- def fields (self ) -> Iterable [Field ]:
433
+ def fields (self ) -> Sequence [Field ]:
434
434
# TODO: Output names should probably be aligned beforehand or be part of concat definition
435
435
# TODO: Handle nullability
436
- return (
436
+ return tuple (
437
437
Field (id , field .dtype )
438
438
for id , field in zip (self .output_ids , self .children [0 ].fields )
439
439
)
@@ -505,7 +505,7 @@ def explicitly_ordered(self) -> bool:
505
505
return True
506
506
507
507
@functools .cached_property
508
- def fields (self ) -> Iterable [Field ]:
508
+ def fields (self ) -> Sequence [Field ]:
509
509
return (
510
510
Field (self .output_id , next (iter (self .start .fields )).dtype , nullable = False ),
511
511
)
@@ -626,12 +626,20 @@ class ReadLocalNode(LeafNode):
626
626
session : typing .Optional [bigframes .session .Session ] = None
627
627
628
628
@property
629
- def fields (self ) -> Iterable [Field ]:
630
- fields = (Field (col_id , dtype ) for col_id , dtype , _ in self .scan_list .items )
629
+ def fields (self ) -> Sequence [Field ]:
630
+ fields = tuple (
631
+ Field (col_id , dtype ) for col_id , dtype , _ in self .scan_list .items
632
+ )
631
633
if self .offsets_col is not None :
632
- return itertools .chain (
633
- fields ,
634
- (Field (self .offsets_col , bigframes .dtypes .INT_DTYPE , nullable = False ),),
634
+ return tuple (
635
+ itertools .chain (
636
+ fields ,
637
+ (
638
+ Field (
639
+ self .offsets_col , bigframes .dtypes .INT_DTYPE , nullable = False
640
+ ),
641
+ ),
642
+ )
635
643
)
636
644
return fields
637
645
@@ -767,8 +775,8 @@ def session(self):
767
775
return self .table_session
768
776
769
777
@property
770
- def fields (self ) -> Iterable [Field ]:
771
- return (
778
+ def fields (self ) -> Sequence [Field ]:
779
+ return tuple (
772
780
Field (col_id , dtype , self .source .table .schema_by_id [source_id ].is_nullable )
773
781
for col_id , dtype , source_id in self .scan_list .items
774
782
)
@@ -881,8 +889,8 @@ def non_local(self) -> bool:
881
889
return True
882
890
883
891
@property
884
- def fields (self ) -> Iterable [Field ]:
885
- return itertools . chain (self .child .fields , self .added_fields )
892
+ def fields (self ) -> Sequence [Field ]:
893
+ return sequences . ChainedSequence (self .child .fields , self .added_fields )
886
894
887
895
@property
888
896
def relation_ops_created (self ) -> int :
@@ -1097,7 +1105,7 @@ def _validate(self):
1097
1105
raise ValueError (f"Reference to column not in child: { ref .id } " )
1098
1106
1099
1107
@functools .cached_property
1100
- def fields (self ) -> Iterable [Field ]:
1108
+ def fields (self ) -> Sequence [Field ]:
1101
1109
input_fields_by_id = {field .id : field for field in self .child .fields }
1102
1110
return tuple (
1103
1111
Field (
@@ -1192,8 +1200,8 @@ def added_fields(self) -> Tuple[Field, ...]:
1192
1200
return tuple (fields )
1193
1201
1194
1202
@property
1195
- def fields (self ) -> Iterable [Field ]:
1196
- return itertools . chain (self .child .fields , self .added_fields )
1203
+ def fields (self ) -> Sequence [Field ]:
1204
+ return sequences . ChainedSequence (self .child .fields , self .added_fields )
1197
1205
1198
1206
@property
1199
1207
def variables_introduced (self ) -> int :
@@ -1263,7 +1271,7 @@ def non_local(self) -> bool:
1263
1271
return True
1264
1272
1265
1273
@property
1266
- def fields (self ) -> Iterable [Field ]:
1274
+ def fields (self ) -> Sequence [Field ]:
1267
1275
return (Field (self .col_id , bigframes .dtypes .INT_DTYPE , nullable = False ),)
1268
1276
1269
1277
@property
@@ -1313,7 +1321,7 @@ def non_local(self) -> bool:
1313
1321
return True
1314
1322
1315
1323
@functools .cached_property
1316
- def fields (self ) -> Iterable [Field ]:
1324
+ def fields (self ) -> Sequence [Field ]:
1317
1325
# TODO: Use child nullability to infer grouping key nullability
1318
1326
by_fields = (self .child .field_by_id [ref .id ] for ref in self .by_column_ids )
1319
1327
if self .dropna :
@@ -1411,8 +1419,8 @@ def non_local(self) -> bool:
1411
1419
return True
1412
1420
1413
1421
@property
1414
- def fields (self ) -> Iterable [Field ]:
1415
- return itertools . chain (self .child .fields , [ self .added_field ] )
1422
+ def fields (self ) -> Sequence [Field ]:
1423
+ return sequences . ChainedSequence (self .child .fields , ( self .added_field ,) )
1416
1424
1417
1425
@property
1418
1426
def variables_introduced (self ) -> int :
@@ -1547,7 +1555,7 @@ def row_preserving(self) -> bool:
1547
1555
return False
1548
1556
1549
1557
@property
1550
- def fields (self ) -> Iterable [Field ]:
1558
+ def fields (self ) -> Sequence [Field ]:
1551
1559
fields = (
1552
1560
Field (
1553
1561
field .id ,
@@ -1561,11 +1569,17 @@ def fields(self) -> Iterable[Field]:
1561
1569
for field in self .child .fields
1562
1570
)
1563
1571
if self .offsets_col is not None :
1564
- return itertools .chain (
1565
- fields ,
1566
- (Field (self .offsets_col , bigframes .dtypes .INT_DTYPE , nullable = False ),),
1572
+ return tuple (
1573
+ itertools .chain (
1574
+ fields ,
1575
+ (
1576
+ Field (
1577
+ self .offsets_col , bigframes .dtypes .INT_DTYPE , nullable = False
1578
+ ),
1579
+ ),
1580
+ )
1567
1581
)
1568
- return fields
1582
+ return tuple ( fields )
1569
1583
1570
1584
@property
1571
1585
def relation_ops_created (self ) -> int :
0 commit comments