
    h$a                        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%ddddZ&ddZ' G d d      Z(y)%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)NullTypec           	     <    d| d    d| d    dt        | d          S )NzName: namez
, Unique: uniquez, Columns: column_namesstr)indexs    h/var/www/html/eduruby.in/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                P    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schemas    r$   sanitize_schemar7   0   s8    88&/F8 $O O
 	
 Mr&   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_tablesr5   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  H   K   | ]  }|v r|j                   |   f  y wN)_custom_table_info).0tableintersectionselfs     r$   	<genexpr>z'SQLDatabase.__init__.<locals>.<genexpr>z   s1      +L( //67+s   "viewsbindonlyr6   N)_engine_schemar4   r   
_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_infor>   dictrA   _max_string_length_view_supportr   	_metadatareflect)rB   enginer6   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_tablesrA   s   `             @r$   __init__zSQLDatabase.__init__=   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=)rl   rm    )
databricksrt   ImportError!dbruntime.databricks_repl_contextru   browserHostNameAttributeErrorr   apiToken	clusterIdr4   rp   )rk   catalogr6   rv   rx   warehouse_id
cluster_idrm   rn   rt   contextru   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)rl   zRcnos-connector package not found, please install with `pip install cnos-connector`)cnosdb_connectorr   rp   r}   )rk   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.)rH   dialectr   rB   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.)rP   sortedrO   rQ   r   s    r$   rR   z"SQLDatabase.get_usable_table_names/  s8    $..//d&&)<)<<==r&   z0.0.1rR   )alternativerr   c                "    | j                         S r   )rR   r   s    r$   rM   zSQLDatabase.get_table_names5  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 ]  }
| j                  rA|
j                  | j                  v r)|	j                  | j                  |
j                            Q	 |
j                   j#                         D ]<  \  }}t%        |j$                        t&        u s"|
j(                  j+                  |       > 	 t1        t3        |
      j5                  | j                              }|j7                          }|rE	 i }|
j                   D ](  }|j8                  s|j8                  ||j                  <   * |r	|d| dz  }| j<                  xs | j>                  }|r|d	z  }| j<                  r|d
| jA                  |
       d
z  }| j>                  r|d
| jC                  |
       d
z  }|r|dz  }|	j                  |        |	jE                          djG                  |	      }|S c c}w c c}w # t,        $ rf t/        |
j                         j#                         D ]<  \  }}t%        |j$                        t&        u s"|
j(                  j+                  |       > Y w xY w# t:        $ r t        d      w xY 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 r;   rD   sqlitesqlite_z

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

/*
z*/z

)$rR   rK   
differencer4   r[   sorted_tablesr   r\   rZ   rH   rL   rI   r   
startswithr>   appendcolumnsitemstyper   _columnsremover   rX   r"   r   compilerstripcomment	ExceptionrW   rV   _get_table_indexes_get_sample_rowssortjoin)rB   table_namesget_col_commentsall_table_namesrg   tblmetadata_table_names
to_reflectmeta_tablestablesr@   kvcreate_tabler   column_comments_dictcolumnhas_extra_info	final_strs                      r$   r   zSQLDatabase.get_table_info?  sl    557" -88IN </??U!VWW)O48NN4P4PQSQQ)C0D,EE
NN""((\\*%||	 #  ~~33
xx3//\\X-#((2E2Ei2P 
 
   1	&E&&5::9P9P+Pd55ejjAB	1!MM//1 1DAqAFF|x/--a01 {5199$,,GHL(//12J  +-("'-- O!>>@F0=O ,"78L7MTR
 ++Nt/N/N  h&
**4#:#:5#A"B"EE
..4#8#8#?"@CC
d"
MM*%c1	&d 	KK'	M  R
& " 1 /557 1DAqAFF|x/--a011, ! $T s>   L$A
L;LL!N?&NAN$NNNc                    | j                   j                  |j                        }dj                  t	        t
        |            }d| S )Nr   zTable Indexes:
)rJ   get_indexesr   r   mapr%   )rB   r@   indexesindexes_formatteds       r$   r   zSQLDatabase._get_table_indexes  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   limitrV   r   r   r   rH   connectexecuterL   r   r   )
rB   r@   commandcolcolumns_str
connectionsample_rows_resultsample_rowsrowsample_rows_strs
             r$   r   zSQLDatabase._get_sample_rows  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                  w| j                  dk(  r!|j	                  d| j                  f|       nG| 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                   |       n| j                  dk(  r!|j	                  d| j                   |       nw| j                  dk(  rng| j                  dk(  r |j	                  d| j                  f|       n8| j                  dk(  r)|j	                  dt        | j                         |       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 %shanazSET SCHEMA z#Query expression has unknown type: allonecursorz8Fetch parameter must be either 'one', 'all', or 'cursor')rH   beginrI   r   exec_driver_sqlr7   r+   r"   r   r   rU   r   r   returns_rowsfetchall_asdictfetchoner4   )
rB   r   fetchr   r   r   r   xresultfirst_results
             r$   _executezSQLDatabase._execute  s     %2
-3\\! L	Z||'<<;...<*; / 
 \\Z/..,*; / 
 \\W,\\W,..*; / 
 \\X-
 ..-dll^<*; /  \\X-..=dll^L*; /  \\X- \\\1../*; / 
 \\V+..%odll&C%DE*; / 
 '3'w-GZ0"Ed7m_ UVV''"3 ( F ""E>39??3DEaaiikEFEe^#)??#4L#/#7Rl>R>R>T=UFh&!OL	 L	R %R  YL	 L	@ #AL	Z 	 FEL	Z 	s$   H J"'J>4J"<J"J""J,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   rY   tuplevaluesr"   )rB   r   r   include_columnsr   r   r   rr   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   r4   )rB   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   )rB   r   r   r   r   r   r  s          r$   run_no_throwzSQLDatabase.run_no_throwP  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   )rL   rR   r  r   )rB   r   r   s      r$   ru   zSQLDatabase.get_contextl  s7    46689113
(;9OPPr&   )
NNNN   FNFi,  F)r]   r   r6   Optional[str]r^   zOptional[MetaData]r_   Optional[List[str]]r`   r	  ra   rT   rb   boolrc   Optional[dict]rd   r
  re   rT   rf   r
  r=   )rl   zUnion[str, URL]rm   r  rn   r   returnr9   )NNNNN)r   r"   r6   r"   rv   r  rx   r  r   r  r   r  rm   r  rn   r   r  r9   )z127.0.0.1:8902rootr   cnosdbpublic)r   r"   r   r"   r   r"   r   r"   r   r"   r  r9   )r  r"   )r  zIterable[str])NF)r   r	  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  r"   )r   r"   r   zLiteral['all', 'one']r   r
  r   r  r   r  r  r  )r  zDict[str, Any])__name__
__module____qualname____doc__ri   classmethodrp   r   r   r   propertyr   rR   rM   r   r   r   r   r   r   r  r  ru   r{   r&   r$   r9   r9   :   sy   /
 !%'+-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- % %
 QVY.YIMY	Yv6

B 27\
 046:\'\ /\
 -\ 4\ 
1\B 27 %	# 046:#'# /# 	# -# 4# 
;#J!& (- %	! 046:!! %! 	! -! 4! 
;!8Qr&   r9   )r#   z+sqlalchemy.engine.interfaces.ReflectedIndexr  r"   )r.   r   r/   rT   r'   r"   r  r"   )r6   r"   r  r"   ))r  
__future__r   r2   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   r7   r9   r{   r&   r$   <module>r$     sb    + " 	 P P P  * -  2 1 < ) 0 % ?D FvQ vQr&   