2727from sqlmesh .core .schema_diff import SchemaDiffer
2828from sqlmesh .utils import optional_import
2929from sqlmesh .utils .errors import SQLMeshError
30+ from sqlmesh .utils .pandas import columns_to_types_from_dtypes
3031
3132logger = logging .getLogger (__name__ )
3233snowpark = optional_import ("snowflake.snowpark" )
@@ -298,13 +299,23 @@ def query_factory() -> Query:
298299
299300 if is_snowpark_dataframe :
300301 temp_table .set ("catalog" , database )
301- df_renamed = df .rename (
302- {
303- col : exp .to_identifier (col ).sql (dialect = self .dialect , identify = True )
304- for col in columns_to_types
305- }
306- ) # type: ignore
307- df_renamed .createOrReplaceTempView (
302+
303+ # only quote columns if they arent already quoted
304+ # if the Snowpark dataframe was created from a Pandas dataframe via snowpark.create_dataframe(pandas_df),
305+ # then they will be quoted already. But if the Snowpark dataframe was created manually by the user, then the
306+ # columns may not be quoted
307+ columns_already_quoted = all (
308+ col .startswith ('"' ) and col .endswith ('"' ) for col in df .columns
309+ )
310+ local_df = df
311+ if not columns_already_quoted :
312+ local_df = df .rename (
313+ {
314+ col : exp .to_identifier (col ).sql (dialect = self .dialect , identify = True )
315+ for col in columns_to_types
316+ }
317+ ) # type: ignore
318+ local_df .createOrReplaceTempView (
308319 temp_table .sql (dialect = self .dialect , identify = True )
309320 ) # type: ignore
310321 elif isinstance (df , pd .DataFrame ):
@@ -356,6 +367,11 @@ def query_factory() -> Query:
356367
357368 def cleanup () -> None :
358369 if is_snowpark_dataframe :
370+ if hasattr (df , "table_name" ):
371+ if isinstance (df .table_name , str ):
372+ # created by the Snowpark library if the Snowpark DataFrame was created from a Pandas DataFrame
373+ # (if the Snowpark DataFrame was created via native means then there is no 'table_name' property and no temp table)
374+ self .drop_table (df .table_name )
359375 self .drop_view (temp_table )
360376 else :
361377 self .drop_table (temp_table )
@@ -381,6 +397,15 @@ def _fetch_native_df(
381397 columns = self .cursor ._result_set .batches [0 ].column_names
382398 return pd .DataFrame ([dict (zip (columns , row )) for row in rows ])
383399
400+ def _native_df_to_pandas_df (
401+ self ,
402+ query_or_df : QueryOrDF ,
403+ ) -> t .Union [Query , pd .DataFrame ]:
404+ if snowpark and isinstance (query_or_df , snowpark .DataFrame ):
405+ return query_or_df .to_pandas ()
406+
407+ return super ()._native_df_to_pandas_df (query_or_df )
408+
384409 def _get_data_objects (
385410 self , schema_name : SchemaName , object_names : t .Optional [t .Set [str ]] = None
386411 ) -> t .List [DataObject ]:
@@ -426,6 +451,10 @@ def _get_data_objects(
426451 if object_names :
427452 query = query .where (exp .column ("TABLE_NAME" ).isin (* object_names ))
428453
454+ # exclude SNOWPARK_TEMP_TABLE tables that are managed by the Snowpark library and are an implementation
455+ # detail of dealing with DataFrame's
456+ query = query .where (exp .column ("TABLE_NAME" ).like ("SNOWPARK_TEMP_TABLE%" ).not_ ())
457+
429458 df = self .fetchdf (query , quote_identifiers = True )
430459 if df .empty :
431460 return []
@@ -537,3 +566,21 @@ def clone_table(
537566 clone_kwargs = clone_kwargs ,
538567 ** kwargs ,
539568 )
569+
570+ @t .overload
571+ def _columns_to_types (
572+ self , query_or_df : DF , columns_to_types : t .Optional [t .Dict [str , exp .DataType ]] = None
573+ ) -> t .Dict [str , exp .DataType ]: ...
574+
575+ @t .overload
576+ def _columns_to_types (
577+ self , query_or_df : Query , columns_to_types : t .Optional [t .Dict [str , exp .DataType ]] = None
578+ ) -> t .Optional [t .Dict [str , exp .DataType ]]: ...
579+
580+ def _columns_to_types (
581+ self , query_or_df : QueryOrDF , columns_to_types : t .Optional [t .Dict [str , exp .DataType ]] = None
582+ ) -> t .Optional [t .Dict [str , exp .DataType ]]:
583+ if not columns_to_types and snowpark and isinstance (query_or_df , snowpark .DataFrame ):
584+ return columns_to_types_from_dtypes (query_or_df .sample (n = 1 ).to_pandas ().dtypes .items ())
585+
586+ return super ()._columns_to_types (query_or_df , columns_to_types )
0 commit comments