@@ -1128,14 +1128,48 @@ def map(self, values: List[Any]) -> Optional[List[Any]]:
11281128 return [self .mapper .map (value ) for value in values ]
11291129
11301130
1131+ class NamedRowTuple (tuple ):
1132+ """Custom tuple class as namedtuple doesn't support missing or duplicate names"""
1133+ def __new__ (cls , values , names : List [str ], types : List [str ]):
1134+ return super ().__new__ (cls , values )
1135+
1136+ def __init__ (self , values , names : List [str ], types : List [str ]):
1137+ self ._names = names
1138+ # With names and types users can retrieve the name and Trino data type of a row
1139+ self .__annotations__ = dict ()
1140+ self .__annotations__ ["names" ] = names
1141+ self .__annotations__ ["types" ] = types
1142+ elements : List [Any ] = []
1143+ for name , value in zip (names , values ):
1144+ if names .count (name ) == 1 :
1145+ setattr (self , name , value )
1146+ elements .append (f"{ name } : { repr (value )} " )
1147+ else :
1148+ elements .append (repr (value ))
1149+ self ._repr = "(" + ", " .join (elements ) + ")"
1150+
1151+ def __getattr__ (self , name ):
1152+ if self ._names .count (name ):
1153+ raise ValueError ("Ambiguous row field reference: " + name )
1154+
1155+ def __repr__ (self ):
1156+ return self ._repr
1157+
1158+
11311159class RowValueMapper (ValueMapper [Tuple [Optional [Any ], ...]]):
1132- def __init__ (self , mappers : List [ValueMapper [Any ]]):
1160+ def __init__ (self , mappers : List [ValueMapper [Any ]], names : List [ str ], types : List [ str ] ):
11331161 self .mappers = mappers
1162+ self .names = names
1163+ self .types = types
11341164
11351165 def map (self , values : List [Any ]) -> Optional [Tuple [Optional [Any ], ...]]:
11361166 if values is None :
11371167 return None
1138- return tuple (self .mappers [index ].map (value ) for index , value in enumerate (values ))
1168+ return NamedRowTuple (
1169+ list (self .mappers [index ].map (value ) for index , value in enumerate (values )),
1170+ self .names ,
1171+ self .types
1172+ )
11391173
11401174
11411175class MapValueMapper (ValueMapper [Dict [Any , Optional [Any ]]]):
@@ -1183,8 +1217,14 @@ def _create_value_mapper(self, column) -> ValueMapper:
11831217 value_mapper = self ._create_value_mapper (column ['arguments' ][0 ]['value' ])
11841218 return ArrayValueMapper (value_mapper )
11851219 elif col_type == 'row' :
1186- mappers = [self ._create_value_mapper (arg ['value' ]['typeSignature' ]) for arg in column ['arguments' ]]
1187- return RowValueMapper (mappers )
1220+ mappers = []
1221+ names = []
1222+ types = []
1223+ for arg in column ['arguments' ]:
1224+ mappers .append (self ._create_value_mapper (arg ['value' ]['typeSignature' ]))
1225+ names .append (arg ['value' ]['fieldName' ]['name' ] if "fieldName" in arg ['value' ] else None )
1226+ types .append (arg ['value' ]['typeSignature' ]['rawType' ])
1227+ return RowValueMapper (mappers , names , types )
11881228 elif col_type == 'map' :
11891229 key_mapper = self ._create_value_mapper (column ['arguments' ][0 ]['value' ])
11901230 value_mapper = self ._create_value_mapper (column ['arguments' ][1 ]['value' ])
0 commit comments