
    7|hZ                        d Z ddlm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$ddddZ% G d d      Z&y)%SQLAlchemy wrapper around a database.    )annotations)AnyDictIterableListLiteralOptionalSequenceUnionN)
deprecated)get_from_env)MetaDataTablecreate_engineinspectselecttext)URLEngineResult)ProgrammingErrorSQLAlchemyError)CreateTable)
Executable)NullTypec           	     <    d| d    d| d    dt        | d          S )NzName: namez
, Unique: uniquez, Columns: column_namesstr)indexs    i/var/www/html/test/engine/venv/lib/python3.12/site-packages/langchain_community/utilities/sql_database.py_format_indexr%      s7    
vz%/): ;~./0	2    z...)suffixc                   t        | t              r|dk  r| S t        |       |k  r| S | d|t        |      z
   j                  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)contentlengthr'   s      r$   truncate_wordr0       sX     gs#v{
7|v)Vc&k)*11#q9!<vEEr&   c                     e Zd ZdZ	 	 	 	 	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZe	 d	 	 	 	 	 	 	 dd       Ze eddd      	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d d	              Ze	 	 	 	 	 d!	 	 	 	 	 	 	 	 	 	 	 d"d
       Z	e
d#d       Zd$dZ eddd      d$d       Ze
d#d       Zdd%dZd&dZd&dZ	 d'ddd	 	 	 	 	 	 	 	 	 d(dZ	 	 d)ddd	 	 	 	 	 	 	 	 	 	 	 d*dZdd%dZ	 	 d)ddd	 	 	 	 	 	 	 	 	 	 	 d+dZd,dZy)-SQLDatabaser   Nc                    | _         | _        |r|rt        d      t         j                          _        t        t         j                  j                  |            |	r j                  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       j                         }|rt        |      n j                   _        t        |t              st!        d      | _        | _        | _         j&                  rwt         j&                  t(              st!        d      t         j&                        j+                   j                        t)         fd j&                  D               _        |
 _        |	 _        |xs
 t1                _        |sG j2                  j5                  |	 j                   t         j                         j                  	       y
y
)z Create engine from database URI.z4Cannot specify both include_tables and ignore_tables)schemaz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  H   K   | ]  }|v r|j                   |   f  y wN)_custom_table_info).0tableintersectionselfs     r$   	<genexpr>z'SQLDatabase.__init__.<locals>.<genexpr>o   s1      +L( //67+s   "viewsbindonlyr4   N)_engine_schema
ValueErrorr   
_inspectorsetlistget_table_namesget_view_names_all_tables_include_tables_ignore_tablesget_usable_table_names_usable_tablesr+   int	TypeError_sample_rows_in_table_info_indexes_in_table_infor8   dictr;   _max_string_length_view_supportr   	_metadatareflect)r<   enginer4   metadataignore_tablesinclude_tablessample_rows_in_table_infoindexes_in_table_infocustom_table_infoview_supportmax_string_lengthlazy_table_reflectionmissing_tablesusable_tablesr;   s   `             @r$   __init__zSQLDatabase.__init__2   sE    mSTT!$,,/ 000?@@Lt--V-<RTV

 7Es>2#%!11D4D4DDN %n%55KL  5Bc-0su!0043C3CCN $^$44JK  3354Ac-0tGWGW3S9JKK*C'&;#"3""d55t<3 
 t667DDTEUEUVL&* +!44+ 'D# #4)!/XZ$NN"""\\$--.||	 #  %r&   c                4    |xs i } | t        |fi |fi |S )z'Construct a SQLAlchemy engine from URI.)r   )clsdatabase_uriengine_argskwargs_engine_argss        r$   from_urizSQLDatabase.from_uri   s(     #(b=>>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removalc           
        	 ddl m}	 d}
	 ddlm}  |       }
|
j
                  }|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 # t        $ r t        d      w xY w# t        t        f$ r d}Y w xY w)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_contexthostDATABRICKS_HOST	api_token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=)rg   rh    )
databricksro   ImportError!dbruntime.databricks_repl_contextrp   browserHostNameAttributeErrorr   apiToken	clusterIdrD   rk   )rf   catalogr4   rq   rs   warehouse_id
cluster_idrh   ri   ro   contextrp   default_hostdefault_api_token	http_pathuris                   r$   from_databrickszSQLDatabase.from_databricks   sJ   x	& 	 E!mG"22L <(9<HD07G,,T$[2DFWXIJ$6$..
 L  JNOO.|n=I.zl;I ")AdV 4"9WIXfXG 	 s||P+PPPS  	: 	 ^, 	 L	 s   B2 C
 2C
CCc                |    	 ddl m}  ||||||      }| j                  |      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)rg   zRcnos-connector package not found, please install with `pip install cnos-connector`)cnosdb_connectorr   rk   rx   )rf   urluserpasswordtenantdatabaser   r   s           r$   from_cnosdbzSQLDatabase.from_cnosdb   sN    <		B+CxRC<<S<11 	0 	s   #& ;c                B    | j                   j                  j                  S )z/Return string representation of dialect to use.)rB   dialectr   r<   s    r$   r   zSQLDatabase.dialect  s     ||##(((r&   c                    | j                   rt        | j                         S t        | j                  | j                  z
        S zGet names of tables available.)rK   sortedrJ   rL   r   s    r$   rM   z"SQLDatabase.get_usable_table_names$  s8    $..//d&&)<)<<==r&   z0.0.1rM   )alternativerm   c                "    | j                         S r   )rM   r   s    r$   rH   zSQLDatabase.get_table_names*  s     **,,r&   c                "    | j                         S )z-Information about all tables in the database.)get_table_infor   s    r$   
table_infozSQLDatabase.table_info/  s     ""$$r&   c                   | j                         }|-t        |      j                  |      }|rt        d| d      |}| j                  j
                  D cg c]  }|j                   }}t        |      t        |      z
  }|rF| j                  j                  | j                  | j                  t        |      | j                         | j                  j
                  D cg c]E  }|j                  t        |      v r,| j                  dk(  r|j                  j                  d      s|G }}g }|D ]h  }	| j                  rA|	j                  | j                  v r)|j                  | j                  |	j                            Q|	j                   j#                         D ]<  \  }
}t%        |j$                        t&        u s"|	j(                  j+                  |       > t-        t/        |	      j1                  | j                              }|j3                          }| j4                  xs | j6                  }|r|dz  }| j4                  r|d| j9                  |	       dz  }| j6                  r|d| j;                  |	       dz  }|r|dz  }|j                  |       k |j=                          d	j?                  |      }|S c c}w c c}w )
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.
        ztable_names r5   r>   sqlitesqlite_z

/*
z*/z

) rM   rF   
differencerD   rV   sorted_tablesr   rW   rU   rB   rG   rC   r   
startswithr8   appendcolumnsitemstyper   _columnsremover"   r   compilerstriprR   rQ   _get_table_indexes_get_sample_rowssortjoin)r<   table_namesall_table_namesrb   tblmetadata_table_names
to_reflectmeta_tablestablesr:   kvcreate_tabler   has_extra_info	final_strs                   r$   r   zSQLDatabase.get_table_info4  s    557" -88IN </??U!VWW)O48NN4P4PQSQQ)C0D,EE
NN""((\\*%||	 #  ~~33
xx3//\\X-#((2E2Ei2P 
 
   	&E&&5::9P9P+Pd55ejjAB ++- -1<8+NN))!,-
 {5199$,,GHL(//12J++Nt/N/N  h&
**4#:#:5#A"B"EE
..4#8#8#?"@CC
d"
MM*%1	&2 	KK'	[  R
s   K$A
Kc                    | j                   j                  |j                        }dj                  t	        t
        |            }d| S )Nr   zTable Indexes:
)rE   get_indexesr   r   mapr%   )r<   r:   indexesindexes_formatteds       r$   r   zSQLDatabase._get_table_indexest  s?    //--ejj9 IIc-&AB!"3!455r&   c                2   t        |      j                  | j                        }dj                  |j                  D cg c]  }|j
                   c}      }	 | j                  j                         5 }|j                  |      }t        t        d |            }d d d        dj                  D cg c]  }dj                  |       c}      }	| j                   d|j
                   d| d|	 S c c}w # 1 sw Y   ]xY wc c}w # t        $ r d}	Y Dw xY w)N	c                D    | D cg c]  }t        |      d d  c}S c c}w )Nd   r!   )lsis     r$   <lambda>z.SQLDatabase._get_sample_rows.<locals>.<lambda>  s    "#=QCF4CL#= #=s   r    z rows from z table:
)r   limitrQ   r   r   r   rB   connectexecuterG   r   r   )
r<   r:   commandcolcolumns_str
connectionsample_rows_resultsample_rowsrowsample_rows_strs
             r$   r   zSQLDatabase._get_sample_rowsy  s   -%%d&E&EF iiU]] Cc CD	!%%' :%/%7%7%@""=?QR #ii;(OC3(OPO ../{5::,im2!	
' !D  )P   	! O	!s;   C2D 3(C7D 2D
D 7D <D DD
parametersexecution_optionsc                  |xs i }|xs i }| j                   j                         5 }| j                  <| j                  dk(  r!|j	                  d| j                  f|       n| j                  dk(  r |j	                  d| j                  f|       n| j                  dk(  rn| j                  dk(  r |j	                  d	| j                  f|       n| j                  d
k(  r!|j	                  d| j                   |       nn| j                  dk(  r!|j	                  d| j                   |       n>| j                  dk(  rn.| j                  dk(  r|j	                  d| j                  f|       t        |t              rt        |      }n(t        |t              rnt        dt        |             |j                  |||      }|j                  r|dk(  r,|j                         D cg c]  }|j                          }}nF|dk(  r&|j                         }	|	g n|	j                         g}n|dk(  r|cddd       S t!        d      |cddd       S 	 ddd       g S c c}w # 1 sw Y   g S xY w)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 ?duckdbzSET search_path TO oraclez#ALTER SESSION SET CURRENT_SCHEMA = sqlany
postgresqlzSET search_path TO %sz#Query expression has unknown type: allonecursorz8Fetch parameter must be either 'one', 'all', or 'cursor')rB   beginrC   r   exec_driver_sqlr+   r"   r   r   rP   r   r   returns_rowsfetchall_asdictfetchonerD   )
r<   r   fetchr   r   r   r   xresultfirst_results
             r$   _executezSQLDatabase._execute  s     %2
-3\\! G	Z||'<<;...<*; / 
 \\Z/..,*; / 
 \\W,\\W,..*; / 
 \\X-
 ..-dll^<*; /  \\X-..=dll^L*; /  \\X- \\\1../*; /  '3'w-GZ0"Ed7m_ UVV''"3 ( F ""E>39??3DEaaiikEFEe^#)??#4L#/#7Rl>R>R>T=UFh&!EG	 G	H %R  OG	 G	v #wG	P 	 F{G	P 	s$   GI',I"4I'I'"I''I1c               ^   | j                  ||||      }|dk(  r|S |D 	cg c];  }|j                         D 	ci c]  \  }}	|t        |	| j                         c}	}= }
}}}	|s&|
D cg c]  }t	        |j                                }
}|
syt        |
      S c c}	}w c c}	}}w c c}w )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   )r/   r   )r   r   r0   rT   tuplevaluesr"   )r<   r   r   include_columnsr   r   r   rcolumnvalueresr   s               r$   runzSQLDatabase.run  s     UzEV  
 HM 
 

  &'WWY!FE eD4K4KLL
 
 25635&6C6s8O
 7s   B#"BB#- B*B#c                ^    	 | j                  |      S # t        $ r}	 d| cY d}~S d}~ww xY w)r   Error: N)r   rD   )r<   r   es      r$   get_table_info_no_throwz#SQLDatabase.get_table_info_no_throw  s7    	!&&{33 	!*QC= 	!s    	,',,c               h    	 | j                  |||||      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_throw%  sM     
	!88%"3 /     	!*QC= 	!s    	1,11c                |    t        | j                               }| j                         }|dj                  |      dS )z4Return db context that you may want in agent prompt.z, )r   r   )rG   rM   r   r   )r<   r   r   s      r$   rp   zSQLDatabase.get_contextA  s7    46689113
(;9OPPr&   )
NNNN   FNFi,  F)rX   r   r4   Optional[str]rY   zOptional[MetaData]rZ   Optional[List[str]]r[   r   r\   rO   r]   boolr^   Optional[dict]r_   r   r`   rO   ra   r   r7   )rg   zUnion[str, URL]rh   r  ri   r   returnr2   )NNNNN)r~   r"   r4   r"   rq   r   rs   r   r   r   r   r   rh   r  ri   r   r  r2   )z127.0.0.1:8902rootr   cnosdbpublic)r   r"   r   r"   r   r"   r   r"   r   r"   r  r2   )r  r"   )r  zIterable[str])r   r   r  r"   )r:   r   r  r"   )r   )
r   Union[str, Executable]r   Literal['all', 'one', 'cursor']r   Optional[Dict[str, Any]]r   r  r  z'Union[Sequence[Dict[str, Any]], Result])r   F)r   r  r   r  r   r   r   r  r   r  r  1Union[str, Sequence[Dict[str, Any]], Result[Any]])r   r"   r   zLiteral['all', 'one']r   r   r   r  r   r  r  r	  )r  zDict[str, Any])__name__
__module____qualname____doc__rd   classmethodrk   r   r   r   propertyr   rM   rH   r   r   r   r   r   r   r   r   rp   rv   r&   r$   r2   r2   /   sV   /
 !%'+-1.2)*&+,0"!$&+NN N %	N
 +N ,N $'N  $N *N N N  $N`  '+J%J $J 	J
 
J J   ##'&*$(&*^Q^Q ^Q 	^Q
 !^Q $^Q "^Q $^Q ^Q 
^Q ^Q@  $ && & 	&
 & & 
& &P ) )> %=uM- N- % %>@6

B 27W
 046:W'W /W
 -W 4W 
1Wx 27 %	# 046:#'# /# 	# -# 4# 
;#J!& (- %	! 046:!! %! 	! -! 4! 
;!8Qr&   r2   )r#   z+sqlalchemy.engine.interfaces.ReflectedIndexr  r"   )r.   r   r/   rO   r'   r"   r  r"   )'r  
__future__r   typingr   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   r%   r0   r2   rv   r&   r$   <module>r     sZ    + " P P P  * -  2 1 < ) 0 % ?D FVQ VQr&   