
    
id                    "   d Z ddlmZ ddlZddlmZmZmZmZm	Z	m
Z
mZmZ ddlZddlmZ ddlmZ ddlmZmZmZmZmZmZ ddlmZmZmZ dd	lmZmZ dd
lm Z  ddl!m"Z" ddl#m$Z$ d dZ% e%             d!dZ&ddd"dZ'd#dZ( G d d          Z)dS )$%SQLAlchemy wrapper around a database.    )annotationsN)AnyDictIterableListLiteralOptionalSequenceUnion)
deprecated)get_from_env)MetaDataTablecreate_engineinspectselecttext)URLEngineResult)ProgrammingErrorSQLAlchemyError)CreateTable)
Executable)NullTypereturnNonec                     	 ddl } t          | d          rEt          | j        d          r2| j        j        }t          |d          r|j        d	d}||_        dS dS dS dS # t
          $ r Y dS w xY w)
z?Patch DuckDBPyType to be hashable for SQLAlchemy compatibility.r   NtypingDuckDBPyType__hash__r   intc                :    t          t          |                     S N)hashstrselfs    C:\Users\Dell Inspiron 16\Desktop\tws\AgrotaPowerBi\back-agrota-powerbi\mcp-client-agrota\venv\Lib\site-packages\langchain_community/utilities/sql_database.pyr"   z%_patch_duckdb_types.<locals>.__hash__&   s    D		??*    )r   r#   )duckdbhasattrr    r!   r"   ImportError)r,   duckdb_typer"   s      r*   _patch_duckdb_typesr0      s     68$$ 	0)O)O 	0 -4K;
33 0{7K7S+ + + + (0$$$	0 	0 	0 	07S7S    s   AA! !
A/.A/index+sqlalchemy.engine.interfaces.ReflectedIndexr'   c           	     V    d| d          d| d          dt          | d                    S )NzName: namez
, Unique: uniquez, Columns: column_namesr'   )r1   s    r*   _format_indexr8   3   sF    	2v 	2 	2%/ 	2 	2~.//	2 	2r+   z...)suffixcontentr   lengthr#   r9   c                   t          | t                    r|dk    r| S t          |           |k    r| S | d|t          |          z
                               dd          d         |z   S )z]
    Truncate a string to a certain number of words, based on the max string
    length.
    r   N    )
isinstancer'   lenrsplit)r:   r;   r9   s      r*   truncate_wordrB   :   so     gs## v{{
7||v)Vc&kk))*11#q99!<vEEr+   schemac                V    t          j        d|           st          d|  d          | S )zHSanitize a schema name to only contain letters, digits, and underscores.z^[a-zA-Z0-9_]+$zSchema name 'z_' contains invalid characters. Schema names must contain only letters, digits, and underscores.)rematch
ValueErrorrC   s    r*   sanitize_schemarI   I   sJ    8&// 
OF O O O
 
 	
 Mr+   c                     e Zd ZdZ	 	 	 	 	 	 	 	 	 	 dXdYdZe	 dZd[d            Ze ed d!d"#          	 	 	 	 	 d\d]d*                        Ze	 	 	 	 	 d^d_d5            Z	e
d`d6            Zdad8Z ed9d:d";          dad<            Ze
d`d=            Z	 dbdcd@ZdddCZdddDZ	 dedddFdfdOZ	 	 dgdddFdhdRZdZdidSZ	 	 dgdddFdjdUZdkdWZdS )lSQLDatabaser   N   F,  enginer   rC   Optional[str]metadataOptional[MetaData]ignore_tablesOptional[List[str]]include_tablessample_rows_in_table_infor#   indexes_in_table_infoboolcustom_table_infoOptional[dict]view_supportmax_string_lengthlazy_table_reflectionc                    | _         | _        |r|rt          d          t           j                    _        t          t           j                            |                    |	r j                            |          ng z              _	        |rt          |          nt                       _
         j
        r$ j
         j	        z
  }|rt          d| d          |rt          |          nt                       _         j        r$ j         j	        z
  }|rt          d| d                                           }|rt          |          n j	         _        t          |t                    st!          d          | _        | _        | _         j        r{t           j        t(                    st!          d          t           j                                       j	                  t)           fd j        D                        _        |
 _        |	 _        |pt1                       _        |s< j                            |	 j         t           j                   j        	           d
S d
S )z Create engine from database URI.z4Cannot specify both include_tables and ignore_tablesrH   zinclude_tables  not found in databasezignore_tables z,sample_rows_in_table_info must be an integerz]table_info must be a dictionary with table names as keys and the desired table info as valuesc              3  >   K   | ]}|v |j         |         fV  d S r%   )_custom_table_info).0tableintersectionr)   s     r*   	<genexpr>z'SQLDatabase.__init__.<locals>.<genexpr>   sG       + +L(( /67((((+ +r+   viewsbindonlyrC   N)_engine_schemarG   r   
_inspectorsetlistget_table_namesget_view_names_all_tables_include_tables_ignore_tablesget_usable_table_names_usable_tablesr?   r#   	TypeError_sample_rows_in_table_info_indexes_in_table_infor`   dictrc   _max_string_length_view_supportr   	_metadatareflect)r)   rN   rC   rP   rR   rT   rU   rV   rX   rZ   r[   r\   missing_tablesusable_tablesrc   s   `             @r*   __init__zSQLDatabase.__init__V   s     	Um 	USTTT!$,// 000??@@@LTt--V-<<<RTV
 

 7EOs>222#%% 	!1D4DDN  LnLLL   5BLc-000suu 	!043CCN  K^KKK   33554AWc-000tGW3S99 	LJKKK*C'&;#"3" 	d5t<< 3  
 t677DDTEUVVL&* + + + + +!4+ + + ' 'D# #4)!/XZZ$ 	N"""\$-..|	 #     	 	r+   database_uriUnion[str, URL]engine_argskwargsr   r   c                2    |pi } | t          |fi |fi |S )z'Construct a SQLAlchemy engine from URI.)r   )clsr   r   r   _engine_argss        r*   from_urizSQLDatabase.from_uri   s6     #(bs=>>>>II&IIIr+   z0.3.18zFor performing structured retrieval using Databricks SQL, see the latest best practices and recommended APIs at https://docs.unitycatalog.io/ai/integrations/langchain/ insteadz1.0)messageremovalcatalogr'   host	api_tokenwarehouse_id
cluster_idc           
        	 ddl m}	 n# t          $ r t          d          w xY wd}
	 ddlm}  |            }
|
j        }n# t          t          f$ r d}Y nw xY w|t          dd|          }|
r|
j        nd}|t          dd	|          }|||
r|
j	        }nt          d
          |r|rt          d          |rd| }nd| }d| d| d| d| d| 
} | j        d||d|S )a	  
        Class method to create an SQLDatabase instance from a Databricks connection.
        This method requires the 'databricks-sql-connector' package. If not installed,
        it can be added using `pip install databricks-sql-connector`.

        Args:
            catalog (str): The catalog name in the Databricks database.
            schema (str): The schema name in the catalog.
            host (Optional[str]): The Databricks workspace hostname, excluding
                'https://' part. If not provided, it attempts to fetch from the
                environment variable 'DATABRICKS_HOST'. If still unavailable and if
                running in a Databricks notebook, it defaults to the current workspace
                hostname. Defaults to None.
            api_token (Optional[str]): The Databricks personal access token for
                accessing the Databricks SQL warehouse or the cluster. If not provided,
                it attempts to fetch from 'DATABRICKS_TOKEN'. If still unavailable
                and running in a Databricks notebook, a temporary token for the current
                user is generated. Defaults to None.
            warehouse_id (Optional[str]): The warehouse ID in the Databricks SQL. If
                provided, the method configures the connection to use this warehouse.
                Cannot be used with 'cluster_id'. Defaults to None.
            cluster_id (Optional[str]): The cluster ID in the Databricks Runtime. If
                provided, the method configures the connection to use this cluster.
                Cannot be used with 'warehouse_id'. If running in a Databricks notebook
                and both 'warehouse_id' and 'cluster_id' are None, it uses the ID of the
                cluster the notebook is attached to. Defaults to None.
            engine_args (Optional[dict]): The arguments to be used when connecting
                Databricks. Defaults to None.
            **kwargs (Any): Additional keyword arguments for the `from_uri` method.

        Returns:
            SQLDatabase: An instance of SQLDatabase configured with the provided
                Databricks connection details.

        Raises:
            ValueError: If 'databricks-sql-connector' is not found, or if both
                'warehouse_id' and 'cluster_id' are provided, or if neither
                'warehouse_id' nor 'cluster_id' are provided and it's not executing
                inside a Databricks notebook.
        r   )sqlzfdatabricks-sql-connector package not found, please install with `pip install databricks-sql-connector`N)get_contextr   DATABRICKS_HOSTr   DATABRICKS_TOKENz6Need to provide either 'warehouse_id' or 'cluster_id'.z/Can't have both 'warehouse_id' or 'cluster_id'.z/sql/1.0/warehouses/z/sql/protocolv1/o/0/zdatabricks://token:@z?http_path=z	&catalog=z&schema=)r   r    )
databricksr   r.   !dbruntime.databricks_repl_contextr   browserHostNameAttributeErrorr   apiToken	clusterIdrG   r   )r   r   rC   r   r   r   r   r   r   r   contextr   default_hostdefault_api_token	http_pathuris                   r*   from_databrickszSQLDatabase.from_databricks   s   x	&&&&&&& 	 	 	:  	
 	 EEEEEE!kmmG"2LL^, 	  	  	 LLL	  <(9<HHD07AG,,T$[2DFWXXIJ$6 $.

 L    	PJ 	PNOOO 	<=|==II;z;;IG) G Gd G G"G G-4G G>DG G 	 s|P+PPPPPs   	 #A AA127.0.0.1:8902root cnosdbpublicurluserpasswordtenantdatabasec                    	 ddl m}  ||||||          }|                     |          S # t          $ r t          d          w xY w)a  
        Class method to create an SQLDatabase instance from a CnosDB connection.
        This method requires the 'cnos-connector' package. If not installed, it
        can be added using `pip install cnos-connector`.

        Args:
            url (str): The HTTP connection host name and port number of the CnosDB
                service, excluding "http://" or "https://", with a default value
                of "127.0.0.1:8902".
            user (str): The username used to connect to the CnosDB service, with a
                default value of "root".
            password (str): The password of the user connecting to the CnosDB service,
                with a default value of "".
            tenant (str): The name of the tenant used to connect to the CnosDB service,
                with a default value of "cnosdb".
            database (str): The name of the database in the CnosDB tenant.

        Returns:
            SQLDatabase: An instance of SQLDatabase configured with the provided
            CnosDB connection details.
        r   )make_cnosdb_langchain_uri)r   zRcnos-connector package not found, please install with `pip install cnos-connector`)cnosdb_connectorr   r   r.   )r   r   r   r   r   r   r   r   s           r*   from_cnosdbzSQLDatabase.from_cnosdb  sw    <		BBBBBB++CxRRC<<S<111 	 	 	0  	s	   *- Ac                $    | j         j        j        S )z/Return string representation of dialect to use.)ri   dialectr4   r(   s    r*   r   zSQLDatabase.dialectC  s     |#((r+   Iterable[str]c                p    | j         rt          | j                   S t          | j        | j        z
            S zGet names of tables available.)rq   sortedrp   rr   r(   s    r*   rs   z"SQLDatabase.get_usable_table_namesH  s7     	0$.///d&)<<===r+   z0.0.1rs   )alternativer   c                *    |                                  S r   )rs   r(   s    r*   rn   zSQLDatabase.get_table_namesN  s     **,,,r+   c                *    |                                  S )z-Information about all tables in the database.)get_table_infor(   s    r*   
table_infozSQLDatabase.table_infoS  s     ""$$$r+   table_namesget_col_commentsc                @                                      |9t          |                                        }|rt          d| d          |d  j        j        D             }t                    t          |          z
  }|r: j                             j         j        t          |           j
                    fd j        j        D             }g }|D ]} j        r4|j         j        v r&|                     j        |j                            >	 |j                                        D ]:\  }	}
t!          |
j                  t"          u r|j                            |
           ;nq# t(          $ rd t+          |j                                                  D ]:\  }	}
t!          |
j                  t"          u r|j                            |
           ;Y nw xY wt-          t/          |                               j                            }|                                 }|rL	 i }|j        D ]}|j        r|j        ||j        <   |r	|d| dz  }n# t6          $ r t          d	          w xY w j        p j        }|r|d
z  } j        r|d                     |           dz  } j        r|d                     |           dz  }|r|dz  }|                    |           |                                  d!                    |          }|S )f  Get information about specified tables.

        Follows best practices as specified in: Rajkumar et al, 2022
        (https://arxiv.org/abs/2204.00498)

        If `sample_rows_in_table_info`, the specified number of sample rows will be
        appended to each table description. This can increase performance as
        demonstrated in the paper.
        Nztable_names r^   c                    g | ]	}|j         
S r   r4   )ra   tbls     r*   
<listcomp>z.SQLDatabase.get_table_info.<locals>.<listcomp>k  s    QQQSQQQr+   re   c                    g | ]?}|j         t                    v r'j        d k    r|j                             d          =|@S )sqlitesqlite_)r4   rl   r   
startswith)ra   r   all_table_namesr)   s     r*   r   z.SQLDatabase.get_table_info.<locals>.<listcomp>u  s\     
 
 
x3////\X--#(2E2Ei2P2P-  .--r+   z

/*
Column Comments: z
*/z:Column comments are available on PostgreSQL, MySQL, Oraclez

/*
z*/z

)"rs   rl   
differencerG   r{   sorted_tablesr|   rz   ri   rm   rj   r`   r4   appendcolumnsitemstyper   _columnsremover   rx   r'   r   compilerstripcomment	Exceptionrw   rv   _get_table_indexes_get_sample_rowssortjoin)r)   r   r   r}   metadata_table_names
to_reflectmeta_tablestablesrb   kvcreate_tabler   column_comments_dictcolumnhas_extra_info	final_strr   s   `                @r*   r   zSQLDatabase.get_table_infoX  s    5577" --88IIN X !V!V!V!VWWW)OQQDN4PQQQ))C0D,E,EE
 	N""(\*%%|	 #   
 
 
 
 
~3
 
 
   1	& 1	&E& 5:9P+P+Pd5ejABBB	1!M//11 1 1DAqAF||x//--a0001 " 1 1 1 //5577 1 1DAqAF||x//--a0001 11 {51199$,GGHHL(//113J   +-("'- O O!> O@F0=+ "R8LRRR
 !   $T   +Nt/N   'h&
* FE4#:#:5#A#AEEEE
. DC4#8#8#?#?CCCC
 #d"
MM*%%%%KK''	s    AE44A+G"!G"1-II9rb   r   c                    | j                             |j                  }d                    t	          t
          |                    }d| S )Nr   zTable Indexes:
)rk   get_indexesr4   r   mapr8   )r)   rb   indexesindexes_formatteds       r*   r   zSQLDatabase._get_table_indexes  sD    /--ej99 IIc-&A&ABB5"3555r+   c                   t          |                              | j                  }d                    d |j        D                       }	 | j                                        5 }|                    |          }t          t          d |                    }d d d            n# 1 swxY w Y   d                    d |D                       }n# t          $ r d}Y nw xY w| j         d|j         d| d| S )	N	c                    g | ]	}|j         
S r   r   )ra   cols     r*   r   z0SQLDatabase._get_sample_rows.<locals>.<listcomp>  s     C C Cc C C Cr+   c                    d | D             S )Nc                <    g | ]}t          |          d d         S )Nd   r7   )ra   is     r*   r   zBSQLDatabase._get_sample_rows.<locals>.<lambda>.<locals>.<listcomp>  s&    #=#=#=QCFF4C4L#=#=#=r+   r   )lss    r*   <lambda>z.SQLDatabase._get_sample_rows.<locals>.<lambda>  s    #=#="#=#=#= r+   r   c                8    g | ]}d                      |          S )r   )r   ra   rows     r*   r   z0SQLDatabase._get_sample_rows.<locals>.<listcomp>  s"    (O(O(OC3(O(O(Or+   r   z rows from z table:
)r   limitrv   r   r   ri   connectexecuterm   r   r   r4   )r)   rb   commandcolumns_str
connectionsample_rows_resultsample_rowssample_rows_strs           r*   r   zSQLDatabase._get_sample_rows  sk   --%%d&EFF ii C CU] C C CDD	!%%'' :%/%7%7%@%@""==?QRR                #ii(O(O;(O(O(OPPOO   	! 	! 	! OOO	! . ! !5: ! !! !! !	
s6   C &4B&C &B**C -B*."C C C all
parametersexecution_optionsr   Union[str, Executable]fetchLiteral['all', 'one', 'cursor']r  Optional[Dict[str, Any]]r  'Union[Sequence[Dict[str, Any]], Result]c               ,   |pi }|pi }| j                                         5 }| j        N| j        dk    r |                    d| j        f|           n#| j        dk    r|                    d| j        f|           n| j        dk    rn| j        dk    r|                    d	| j        f|           n| j        d
k    r |                    d| j         |           n| j        dk    r |                    d| j         |           nm| j        dk    rna| j        dk    r|                    d| j        f|           n7| j        dk    r,|                    dt          | j                   |           t          |t                    rt          |          }n5t          |t                    rnt          dt          |                     |                    |||          }|j        r|dk    rd |                                D             }nW|dk    r.|                                }|g n|                                g}n#|dk    r|cddd           S t#          d          |cddd           S 	 ddd           n# 1 swxY w Y   g S )z
        Executes SQL command through underlying engine.

        If the statement returns no rows, an empty list is returned.
        N	snowflakez"ALTER SESSION SET search_path = %s)r  bigqueryzSET @@dataset_id=?mssqltrinozUSE ?r,   zSET search_path TO oraclez#ALTER SESSION SET CURRENT_SCHEMA = sqlany
postgresqlzSET search_path TO %shanazSET SCHEMA z#Query expression has unknown type: r   c                6    g | ]}|                                 S r   )_asdict)ra   xs     r*   r   z(SQLDatabase._execute.<locals>.<listcomp>'  s     EEEaaiikkEEEr+   onecursorz8Fetch parameter must be either 'one', 'all', or 'cursor')ri   beginrj   r   exec_driver_sqlrI   r?   r'   r   r   ru   r   r   returns_rowsfetchallfetchoner  rG   )	r)   r   r  r  r  r   r  resultfirst_results	            r*   _executezSQLDatabase._execute  s     %2
-3\!! L	Z|'<;....<*; /    
 \Z//..,*; /    
 \W,,\W,,..*; /    
 \X--
 ..<dl<<*; /     \X--..LdlLL*; /     \X-- \\11../*; /    
 \V++..Eodl&C&CEE*; /   
 '3'' Ww--GZ00 W Ud7mm U UVVV''"3 (  F " E>>EE6??3D3DEEEFFe^^#)??#4#4L#/#7RRl>R>R>T>T=UFFh&&!OL	 L	 L	 L	 L	 L	 L	 L	R %R   YL	 L	 L	 L	 L	 L	 L	 L	@AL	 L	 L	 L	 L	 L	 L	 L	 L	 L	 L	 L	 L	 L	 L	Z 	s   H0J	J		JJinclude_columns1Union[str, Sequence[Dict[str, Any]], Result[Any]]c                                          ||||          }|dk    r|S  fd|D             }|sd |D             }|sdS t          |          S )zExecute a SQL command and return a string representing the results.

        If the statement returns rows, a string of the results is returned.
        If the statement returns no rows, an empty string is returned.
        r   r  c                P    g | ]"}fd |                                 D             #S )c                D    i | ]\  }}|t          |j                   S ))r;   )rB   ry   )ra   r   valuer)   s      r*   
<dictcomp>z.SQLDatabase.run.<locals>.<listcomp>.<dictcomp>J  s?       !FE eD4KLLL  r+   )r   )ra   rr)   s     r*   r   z#SQLDatabase.run.<locals>.<listcomp>I  sT     
 
 

 	   %&WWYY  
 
 
r+   c                P    g | ]#}t          |                                          $S r   )tuplevaluesr   s     r*   r   z#SQLDatabase.run.<locals>.<listcomp>R  s(    66635&&666r+   r   )r  r'   )r)   r   r  r  r  r  r  ress   `       r*   runzSQLDatabase.run4  s     UzEV  
 
 HM
 
 
 

 
 
 
  	766#666C 	2s88Or+   c                h    	 |                      |          S # t          $ r}	 d| cY d}~S d}~ww xY w)r   Error: N)r   rG   )r)   r   es      r*   get_table_info_no_throwz#SQLDatabase.get_table_info_no_throwY  sX    	!&&{333 	! 	! 	!* Q==      	!s    
1,11Literal['all', 'one']c               r    	 |                      |||||          S # t          $ r}	 d| cY d}~S d}~ww xY w)a*  Execute a SQL command and return a string representing the results.

        If the statement returns rows, a string of the results is returned.
        If the statement returns no rows, an empty string is returned.

        If the statement throws an error, the error message is returned.
        )r  r  r  r,  N)r*  r   )r)   r   r  r  r  r  r-  s          r*   run_no_throwzSQLDatabase.run_no_throwi  sp     
	!88%"3 /      	! 	! 	!* Q==      	!s    
6166Dict[str, Any]c                    t          |                                           }|                                 }|d                    |          dS )z4Return db context that you may want in agent prompt.z, )r   r   )rm   rs   r.  r   )r)   r   r   s      r*   r   zSQLDatabase.get_context  sF    46688991133
(;9O9OPPPr+   )
NNNNrL   FNFrM   F)rN   r   rC   rO   rP   rQ   rR   rS   rT   rS   rU   r#   rV   rW   rX   rY   rZ   rW   r[   r#   r\   rW   r%   )r   r   r   rY   r   r   r   rK   )NNNNN)r   r'   rC   r'   r   rO   r   rO   r   rO   r   rO   r   rY   r   r   r   rK   )r   r   r   r   r   )r   r'   r   r'   r   r'   r   r'   r   r'   r   rK   )r   r'   )r   r   )NF)r   rS   r   rW   r   r'   )rb   r   r   r'   )r   )
r   r  r  r  r  r  r  r  r   r  )r   F)r   r  r  r  r  rW   r  r  r  r  r   r  )r   rS   r   r'   )r   r'   r  r/  r  rW   r  r  r  r  r   r  )r   r2  )__name__
__module____qualname____doc__r   classmethodr   r   r   r   propertyr   rs   rn   r   r   r   r   r  r*  r.  r1  r   r   r+   r*   rK   rK   S   s       //
 !%'+-1.2)*&+,0"!$&+N N N N N`  '+J J J J [J Z    ##'&*$(&*^Q ^Q ^Q ^Q  [^Q@  $ & & & & [&P ) ) ) X)> > > > Z%=uMMM- - - NM- % % % X%
 QVY Y Y Y Yv6 6 6 6

 
 
 
B 27\
 046:\ \ \ \ \ \B 27 %	# 046:# # # # # #J! ! ! ! !& (- %	! 046:! ! ! ! ! !8Q Q Q Q Q Qr+   rK   )r   r   )r1   r2   r   r'   )r:   r   r;   r#   r9   r'   r   r'   )rC   r'   r   r'   )*r7  
__future__r   rE   r    r   r   r   r   r	   r
   r   r   
sqlalchemylangchain_core._apir   langchain_core.utilsr   r   r   r   r   r   r   sqlalchemy.enginer   r   r   sqlalchemy.excr   r   sqlalchemy.schemar   sqlalchemy.sql.expressionr   sqlalchemy.typesr   r0   r8   rB   rI   rK   r   r+   r*   <module>rC     s   + + " " " " " " 				 P P P P P P P P P P P P P P P P P P P P     * * * * * * - - - - - -                2 1 1 1 1 1 1 1 1 1 < < < < < < < < ) ) ) ) ) ) 0 0 0 0 0 0 % % % % % %
   (         ?D F F F F F F   vQ vQ vQ vQ vQ vQ vQ vQ vQ vQr+   