1111from enum import Enum
1212from typing import Generic , List , Optional , Type , TypeVar , Union , Dict , Any
1313
14+ import snowflake .snowpark .context as context
1415import snowflake .snowpark ._internal .analyzer .expression as expression
1516import snowflake .snowpark ._internal .proto .generated .ast_pb2 as proto
1617
1718# Use correct version from here:
1819from snowflake .snowpark ._internal .utils import installed_pandas , pandas , quote_name
19- import snowflake .snowpark .context as context
2020
2121# TODO: connector installed_pandas is broken. If pyarrow is not installed, but pandas is this function returns the wrong answer.
2222# The core issue is that in the connector detection of both pandas/arrow are mixed, which is wrong.
@@ -334,16 +334,22 @@ class ArrayType(DataType):
334334 def __init__ (
335335 self ,
336336 element_type : Optional [DataType ] = None ,
337- structured : bool = False ,
337+ structured : Optional [ bool ] = None ,
338338 ) -> None :
339- self .structured = structured
340- self .element_type = element_type if element_type else StringType ()
339+ if context ._should_use_structured_type_semantics ():
340+ self .structured = (
341+ structured if structured is not None else element_type is not None
342+ )
343+ self .element_type = element_type
344+ else :
345+ self .structured = structured or False
346+ self .element_type = element_type if element_type else StringType ()
341347
342348 def __repr__ (self ) -> str :
343349 return f"ArrayType({ repr (self .element_type ) if self .element_type else '' } )"
344350
345351 def _as_nested (self ) -> "ArrayType" :
346- if not context ._should_use_structured_type_semantics :
352+ if not context ._should_use_structured_type_semantics () :
347353 return self
348354 element_type = self .element_type
349355 if isinstance (element_type , (ArrayType , MapType , StructType )):
@@ -378,6 +384,10 @@ def json_value(self) -> Dict[str, Any]:
378384
379385 def _fill_ast (self , ast : proto .SpDataType ) -> None :
380386 ast .sp_array_type .structured = self .structured
387+ if self .element_type is None :
388+ raise NotImplementedError (
389+ "SNOW-1862700: AST does not support empty element_type."
390+ )
381391 self .element_type ._fill_ast (ast .sp_array_type .ty )
382392
383393
@@ -388,20 +398,36 @@ def __init__(
388398 self ,
389399 key_type : Optional [DataType ] = None ,
390400 value_type : Optional [DataType ] = None ,
391- structured : bool = False ,
401+ structured : Optional [ bool ] = None ,
392402 ) -> None :
393- self .structured = structured
394- self .key_type = key_type if key_type else StringType ()
395- self .value_type = value_type if value_type else StringType ()
403+ if context ._should_use_structured_type_semantics ():
404+ if (key_type is None and value_type is not None ) or (
405+ key_type is not None and value_type is None
406+ ):
407+ raise ValueError (
408+ "Must either set both key_type and value_type or leave both unset."
409+ )
410+ self .structured = (
411+ structured if structured is not None else key_type is not None
412+ )
413+ self .key_type = key_type
414+ self .value_type = value_type
415+ else :
416+ self .structured = structured or False
417+ self .key_type = key_type if key_type else StringType ()
418+ self .value_type = value_type if value_type else StringType ()
396419
397420 def __repr__ (self ) -> str :
398- return f"MapType({ repr (self .key_type ) if self .key_type else '' } , { repr (self .value_type ) if self .value_type else '' } )"
421+ type_str = ""
422+ if self .key_type and self .value_type :
423+ type_str = f"{ repr (self .key_type )} , { repr (self .value_type )} "
424+ return f"MapType({ type_str } )"
399425
400426 def is_primitive (self ):
401427 return False
402428
403429 def _as_nested (self ) -> "MapType" :
404- if not context ._should_use_structured_type_semantics :
430+ if not context ._should_use_structured_type_semantics () :
405431 return self
406432 value_type = self .value_type
407433 if isinstance (value_type , (ArrayType , MapType , StructType )):
@@ -447,6 +473,10 @@ def valueType(self):
447473
448474 def _fill_ast (self , ast : proto .SpDataType ) -> None :
449475 ast .sp_map_type .structured = self .structured
476+ if self .key_type is None or self .value_type is None :
477+ raise NotImplementedError (
478+ "SNOW-1862700: AST does not support empty key or value type."
479+ )
450480 self .key_type ._fill_ast (ast .sp_map_type .key_ty )
451481 self .value_type ._fill_ast (ast .sp_map_type .value_ty )
452482
@@ -578,7 +608,7 @@ def __init__(
578608
579609 @property
580610 def name (self ) -> str :
581- if self ._is_column or not context ._should_use_structured_type_semantics :
611+ if self ._is_column or not context ._should_use_structured_type_semantics () :
582612 return self .column_identifier .name
583613 else :
584614 return self ._name
@@ -593,7 +623,7 @@ def name(self, n: Union[ColumnIdentifier, str]) -> None:
593623 self .column_identifier = ColumnIdentifier (n )
594624
595625 def _as_nested (self ) -> "StructField" :
596- if not context ._should_use_structured_type_semantics :
626+ if not context ._should_use_structured_type_semantics () :
597627 return self
598628 datatype = self .datatype
599629 if isinstance (datatype , (ArrayType , MapType , StructType )):
@@ -651,9 +681,17 @@ class StructType(DataType):
651681 """Represents a table schema or structured column. Contains :class:`StructField` for each field."""
652682
653683 def __init__ (
654- self , fields : Optional [List ["StructField" ]] = None , structured = False
684+ self ,
685+ fields : Optional [List ["StructField" ]] = None ,
686+ structured : Optional [bool ] = None ,
655687 ) -> None :
656- self .structured = structured
688+ if context ._should_use_structured_type_semantics ():
689+ self .structured = (
690+ structured if structured is not None else fields is not None
691+ )
692+ else :
693+ self .structured = structured or False
694+
657695 self .fields = []
658696 for field in fields or []:
659697 self .add (field )
@@ -683,7 +721,7 @@ def add(
683721 return self
684722
685723 def _as_nested (self ) -> "StructType" :
686- if not context ._should_use_structured_type_semantics :
724+ if not context ._should_use_structured_type_semantics () :
687725 return self
688726 return StructType (
689727 [field ._as_nested () for field in self .fields ], self .structured
0 commit comments