1919from sqlglot import Dialect , exp
2020from sqlglot .errors import ErrorLevel
2121from sqlglot .helper import ensure_list
22+ from sqlglot .optimizer .qualify_columns import quote_identifiers
2223
2324from sqlmesh .core .dialect import pandas_to_sql
2425from sqlmesh .core .engine_adapter .shared import DataObject , TransactionType
@@ -698,7 +699,9 @@ def _merge(
698699 match_expressions : t .List [exp .When ],
699700 ) -> None :
700701 this = exp .alias_ (exp .to_table (target_table ), alias = MERGE_TARGET_ALIAS , table = True )
701- using = exp .Subquery (this = source_table , alias = MERGE_SOURCE_ALIAS )
702+ using = exp .alias_ (
703+ exp .Subquery (this = source_table ), alias = MERGE_SOURCE_ALIAS , copy = False , table = True
704+ )
702705 self .execute (
703706 exp .Merge (
704707 this = this ,
@@ -778,33 +781,49 @@ def fetchone(
778781 self ,
779782 query : t .Union [exp .Expression , str ],
780783 ignore_unsupported_errors : bool = False ,
784+ quote_identifiers : bool = False ,
781785 ) -> t .Tuple :
782- self .execute (query , ignore_unsupported_errors = ignore_unsupported_errors )
786+ self .execute (
787+ query ,
788+ ignore_unsupported_errors = ignore_unsupported_errors ,
789+ quote_identifiers = quote_identifiers ,
790+ )
783791 return self .cursor .fetchone ()
784792
785793 def fetchall (
786794 self ,
787795 query : t .Union [exp .Expression , str ],
788796 ignore_unsupported_errors : bool = False ,
797+ quote_identifiers : bool = False ,
789798 ) -> t .List [t .Tuple ]:
790- self .execute (query , ignore_unsupported_errors = ignore_unsupported_errors )
799+ self .execute (
800+ query ,
801+ ignore_unsupported_errors = ignore_unsupported_errors ,
802+ quote_identifiers = quote_identifiers ,
803+ )
791804 return self .cursor .fetchall ()
792805
793- def _fetch_native_df (self , query : t .Union [exp .Expression , str ]) -> DF :
806+ def _fetch_native_df (
807+ self , query : t .Union [exp .Expression , str ], quote_identifiers : bool = False
808+ ) -> DF :
794809 """Fetches a DataFrame that can be either Pandas or PySpark from the cursor"""
795- self .execute (query )
810+ self .execute (query , quote_identifiers = quote_identifiers )
796811 return self .cursor .fetchdf ()
797812
798- def fetchdf (self , query : t .Union [exp .Expression , str ]) -> pd .DataFrame :
813+ def fetchdf (
814+ self , query : t .Union [exp .Expression , str ], quote_identifiers : bool = False
815+ ) -> pd .DataFrame :
799816 """Fetches a Pandas DataFrame from the cursor"""
800- df = self ._fetch_native_df (query )
817+ df = self ._fetch_native_df (query , quote_identifiers = quote_identifiers )
801818 if not isinstance (df , pd .DataFrame ):
802819 raise NotImplementedError (
803820 "The cursor's `fetch_native_df` method is not returning a pandas DataFrame. Need to update `fetchdf` so a Pandas DataFrame is returned"
804821 )
805822 return df
806823
807- def fetch_pyspark_df (self , query : t .Union [exp .Expression , str ]) -> PySparkDataFrame :
824+ def fetch_pyspark_df (
825+ self , query : t .Union [exp .Expression , str ], quote_identifiers : bool = False
826+ ) -> PySparkDataFrame :
808827 """Fetches a PySpark DataFrame from the cursor"""
809828 raise NotImplementedError (f"Engine does not support PySpark DataFrames: { type (self )} " )
810829
@@ -835,6 +854,7 @@ def execute(
835854 self ,
836855 expressions : t .Union [str , exp .Expression , t .Sequence [exp .Expression ]],
837856 ignore_unsupported_errors : bool = False ,
857+ quote_identifiers : bool = True ,
838858 ** kwargs : t .Any ,
839859 ) -> None :
840860 """Execute a sql query."""
@@ -843,7 +863,11 @@ def execute(
843863 )
844864
845865 for e in ensure_list (expressions ):
846- sql = self ._to_sql (e , ** to_sql_kwargs ) if isinstance (e , exp .Expression ) else e
866+ sql = (
867+ self ._to_sql (e , quote = quote_identifiers , ** to_sql_kwargs )
868+ if isinstance (e , exp .Expression )
869+ else e
870+ )
847871 logger .debug (f"Executing SQL:\n { sql } " )
848872 self .cursor .execute (sql , ** kwargs )
849873
@@ -882,7 +906,7 @@ def _create_table_properties(
882906 """Creates a SQLGlot table properties expression for ddl."""
883907 return None
884908
885- def _to_sql (self , e : exp .Expression , ** kwargs : t .Any ) -> str :
909+ def _to_sql (self , expression : exp .Expression , quote : bool = True , ** kwargs : t .Any ) -> str :
886910 """
887911 Converts an expression to a SQL string. Has a set of default kwargs to apply, and then default
888912 kwargs defined for the given dialect, and then kwargs provided by the user when defining the engine
@@ -896,7 +920,11 @@ def _to_sql(self, e: exp.Expression, **kwargs: t.Any) -> str:
896920 ** self .sql_gen_kwargs ,
897921 ** kwargs ,
898922 }
899- return e .sql (** sql_gen_kwargs ) # type: ignore
923+
924+ if quote :
925+ quote_identifiers (expression )
926+
927+ return expression .sql (** sql_gen_kwargs ) # type: ignore
900928
901929 def _get_data_objects (
902930 self , schema_name : str , catalog_name : t .Optional [str ] = None
@@ -917,9 +945,11 @@ def _get_temp_table(
917945 """
918946 table = t .cast (exp .Table , exp .to_table (table ).copy ())
919947 table .set ("this" , exp .to_identifier (f"__temp_{ table .name } _{ uuid .uuid4 ().hex } " ))
948+
920949 if table_only :
921950 table .set ("db" , None )
922951 table .set ("catalog" , None )
952+
923953 return table
924954
925955 def _add_where_to_query (self , query : Query , where : t .Optional [exp .Expression ]) -> Query :
@@ -933,8 +963,10 @@ def _add_where_to_query(self, query: Query, where: t.Optional[exp.Expression]) -
933963 .from_ (query .subquery ("_subquery" , copy = False ), copy = False )
934964 .where (where , copy = False )
935965 )
966+
936967 if with_ :
937968 query .set ("with" , with_ )
969+
938970 return query
939971
940972
0 commit comments