
    Arhs                        d dl mZmZmZmZmZmZmZ d dlm	Z	m
Z
 d dlZd dlZd dl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lmZmZmZ d d	lmZmZ d d
lmZ d dlm Z m!Z!m"Z"m#Z# d dl$m%Z%  ejL                  e'      Z(d dl)m*Z*  e*       Z+e(jY                  d        ejZ                  d      e	d               Z. ejZ                  dddg      ed               Z/ ejZ                  ddg      ed               Z0 ejZ                  ddg      ed               Z1 ejZ                  ddg      ed               Z2 ejZ                  ddg      ed               Z3 ejZ                  ddg      ed               Z4 ejZ                  d dg      ed!               Z5 ejZ                  d"dg      ed#               Z6d'd$Z7 ejZ                  d%dg      ed&               Z8y)(    )render_templateredirecturl_forflashrequestjsonifycurrent_app)login_requiredcurrent_userN)datetime	timedelta)db)database_bp)api_bp)DatabaseConnectionDatabaseSchemaQueryHistory)encrypt_passworddecrypt_password)token_required)SubscriptionUserSubscriptionPlan
QueryUsage)AIModelFactory)DatabaseConnectorz+Database connector initialized successfullyz/connectionsc                      t         j                  j                  t        j                        j                         } t        d|       S )z2List all database connections for the current useruser_idzdatabase/connections.htmlconnections)r   query	filter_byr   idallr   r    s    $/var/www/html/app/database/routes.pyr!   r!      s8     %**44\__4MQQSK6KPP    z/database/connectionsGETOPTIONS)methodsc                     t         j                  dk(  ry	 t        j                  j	                  t         j
                  j                        j                         } t        d| D cg c]  }|j                  |j                  |j                  |j                  |j                  |j                  |j                  |j                  |j                   |j"                  r|j"                  j%                         nd|j&                  r|j&                  j%                         ndd c}d      }|S c c}w # t(        $ rG}t*        j-                  dt/        |              t        d	d
t/        |       d      dfcY d}~S d}~ww xY w)zAAPI endpoint to get all database connections for the current userr)   )    r   TN)r$   namedescriptiondb_typehostportdatabase_nameservice_nameusername
created_at
updated_at)successr!   zError fetching connections: FzFailed to get connections: r8   message  )r   methodr   r"   r#   r   r$   r%   r   r.   r/   r0   r1   r2   r3   r4   r5   r6   	isoformatr7   	Exceptionloggererrorstr)r!   connresponsees       r&   get_connectionsrE   '   sP   
 ~~"  )..88AUAUAXAX8Y]]_ (  '' II#'#3#3#|| II II%)%7%7$($5$5 $AE$//";";"=VZAE$//";";"=VZ
 * '(  3CF8<=4SVH=
   	s1   AD1 &B;D,
!
D1 ,D1 1	F:<E<6F<FPOSTc                  H   	 t         j                  } ddg}| j                  d      dk7  r|j                  g d       |j	                  d       |D ]  }|| vst        dd| d      d	fc S  d
dlm}m} |j                  j                  t        j                  d      j                         }t        j                  j                  t        j                        j                         }d}|r|j                  j                  |j                         j                         }|r[|j"                  }	t%        |	t&              r
d|	v r|	d   }n5|j                   dk(  rd}n#|j                   dk(  rd}n|j                   dk(  rd}|dk7  r||k\  rt        dd| dd      dfS t)        | d         }
t        | d   | j                  dd      | d   | j                  dd      | j                  dd
      | d   | j                  d d      | j                  d!d      |
t        j                  "
      }t*        j,                  j/                  |       t*        j,                  j1                          t        d#|j                  |j2                  |j4                  |j6                  |j8                  |j:                  |j<                  |j>                  |j@                  tC        |d$d      |jD                  r|jD                  jG                         nd%|jH                  r|jH                  jG                         nd%d&d'      d(fS # tJ        $ re}t*        j,                  jM                          tN        jQ                  d)tS        |              t        dd*tS        |       d      d+fcY d%}~S d%}~ww xY w),z0API endpoint to create a new database connectionr.   r0   sqlite)r1   r2   r5   passwordr3   FMissing required field: r9     r   )r   r   active)r   statusr      plan_idconnection_limitbasic   professional
   
enterprisez*You have reached your connection limit of z3. Please upgrade your plan to add more connections.  rI   r/   r,   r1   r2   r4   r5   )
r.   r/   r0   r1   r2   r3   r4   r5   rI   r   Thas_empty_passwordNr$   r.   r/   r0   r1   r2   r3   r4   r5   rY   r6   r7   r8   
connection   zError creating connection: zFailed to create connection: r;   )*r   jsongetextendappendr   app.auth.modelsr   r   r"   r#   r   r$   firstr   countrP   features
isinstancedictr   r   sessionaddcommitr.   r/   r0   r1   r2   r3   r4   r5   getattrr6   r=   r7   r>   rollbackr?   r@   rA   )datarequired_fieldsfieldr   r   subscriptionexisting_connections_countrQ   planplan_featuresencrypted_passwordr\   rD   s                r&   create_connectionru   Q   s   d|| "9- 88I(*""#KL 	/$ 	ED $!9%A    	 	C $))33LOOT\3]cce &8%=%=%G%GP\P_P_%G%`%f%f%h" #))33L<P<P3QWWYD $mT27I]7Z'45G'H$ ||w.+,(7+-(5+-( r!&@DT&T GHXGY  ZM  N    .d:.>? (f3O&"%&!$/."5XXj"-' OO

 	

z"


 mm")55%--""!+!9!9 * 7 7&//&-j:NPU&VCMCXCXj33==?^bCMCXCXj33==?^b
   ! 	"  


23q6(;<6s1vh?
   	s3   AL3 L3 -D0L3 FL3 3	N!<ANN!N!z)/database/connections/<int:connection_id>c                    	 t         j                  j                  | t        j                        j                         }|st        ddd      dfS t        d|j                  |j                  |j                  |j                  |j                  |j                  |j                  |j                  |j                  t        |dd      |j                   r|j                   j#                         nd|j$                  r|j$                  j#                         ndd	d
      dfS # t&        $ rG}t(        j+                  dt-        |              t        ddt-        |       d      dfcY d}~S d}~ww xY w)z2API endpoint to get a specific database connectionr$   r   FConnection not foundr9     TrY   NrZ   r[   r-   zError fetching connection: zFailed to get connection: r;   )r   r"   r#   r   r$   rc   r   r.   r/   r0   r1   r2   r3   r4   r5   rk   r6   r=   r7   r>   r?   r@   rA   )connection_idr\   rD   s      r&   get_connectionr{      se   '--77=R^RaRa7bhhj
 1   
  mm")55%--""!+!9!9 * 7 7&//&-j:NPU&VCMCXCXj33==?^bCMCXCXj33==?^b
   ! 	"  23q6(;<3CF8<
   	s%   AD CD 	E/(<E*$E/*E/PUTc                    	 t         j                  j                  | t        j                        j                         }|st        ddd      dfS t        j                  }d|v r
|d   |_	        d|v r
|d   |_
        d|v r
|d   |_        d	|v r
|d	   |_        d
|v r
|d
   |_        d|v r
|d   |_        d|v r
|d   |_        d|v r1|d   dk(  rd|_        d|_        nd|_        t%        |d         |_        t&        j(                  j+                          t        d|j                  |j                  |j                  |j                  |j                  |j                  |j                  |j,                  |j                  t/        |dd      |j0                  r|j0                  j3                         nd|j4                  r|j4                  j3                         nddd      dfS # t6        $ re}t&        j(                  j9                          t:        j=                  dt?        |              t        ddt?        |       d      dfcY d}~S d}~ww xY w)z,API endpoint to update a database connectionrw   Frx   r9   ry   r.   r/   r0   r1   r2   r3   r5   rI   r,   TrY   NrZ   r[   r-   zError updating connection: zFailed to update connection: r;   ) r   r"   r#   r   r$   rc   r   r   r^   r.   r/   r0   r1   r2   r3   r5   rY   rI   r   r   rh   rj   r4   rk   r6   r=   r7   r>   rl   r?   r@   rA   )rz   r\   rm   rD   s       r&   update_connectionr~      sZ   >'--77=R^RaRa7bhhj
 1   
 || T>"6lJOD %)-%8J"!%iJT>"6lJOT>"6lJOd"'+O'<J$"&z"2JJ2%04
-&(
# 16
-&6tJ7G&H
#


 mm")55%--""!+!9!9 * 7 7&//&-j:NPU&VCMCXCXj33==?^bCMCXCXj33==?^b
   ! 	"  


23q6(;<6s1vh?
   	s&   AG$ FG$ $	I-AIIIDELETEc                    	 t         j                  j                  | t        j                  d      j                         }|st        ddd      dfS t        j                  j                  | d      j                         }|D ]  }|j                           |j                          t        j                  j                          t        ddd      d	fS # t        $ re}t        j                  j                          t        j!                  d
t#        |              t        ddt#        |       d      dfcY d}~S d}~ww xY w)z,API endpoint to delete a database connectionF)r$   r   
is_deletedrx   r9   ry   )rz   r   TzConnection deleted successfullyr-   zError deleting connection: zFailed to delete connection: r;   N)r   r"   r#   r   r$   rc   r   r   r%   soft_deleter   rh   rj   r>   rl   r?   r@   rA   )rz   r\   schemasschemarD   s        r&   delete_connectionr   $  sC   '--77=R^RaRans7tzz|
 1    !&&00}Y^0_cce 	!F 	! 	 


8
   	  


23q6(;<6s1vh?
   	s&   AC BC 	EAD?9E?Ez./database/connections/<int:connection_id>/testc                 &   t         j                  }	 	 t        j                  j	                  | |j
                        j                         }|st        ddd      dfS t        |j                        }|j                  ||j                   d|j                   |j                  d}|j                  j                         dk(  r3|j                   r'|j                   |d	<   t#        d
|j                           t$        j'                  |j                  |      }|d   rt        ddd      dfS t        d|d   d      dfS # t(        $ rG}t*        j-                  dt/        |              t        ddt/        |       d      dfcY d }~S d }~ww xY w)Nrw   Frx   r9   ry   :r5   rI   hostPortdatabaseNameoracleserviceNamezAdding Oracle service_name: r0   connection_configr8   TConnection successfulr-   r:   rK   zError testing connection: Failed to test connection: r;   )r   r   r   r"   r#   r$   rc   r   r   rI   r5   r1   r2   r3   r0   lowerr4   print	connectortest_connectionr>   r?   r@   rA   )rz   r   r\   rI   r   resultrD   s          r&   r   r   G  s    ''L>.'--77=R^RaRa7bhhj
 1    $J$7$78 #++ %??+1Z__,=>&44	
 ##%1j6M6M/9/F/Fm,01H1H0IJK **&&/ + 

 )2   
  !),     1#a&:;4SVH=
   	s+   A
E  CE  -E   	F	<FFFz/database/connections/testc                  h   t         j                  } 	 	 t        j                         }|st        ddd      dfS g d}|D ]  }||vst        dd| d      dfc S  |d   |d   |d	    d
|d    |d   d}|d   j	                         dk(  rd|v r|d   r|d   |d<   t
        j                  |d   |      }|d   rt        ddd      dfS t        d|d   d      dfS # t        $ rG}t        j                  dt        |              t        ddt        |       d      dfcY d }~S d }~ww xY w)NFNo data providedr9   rK   )r0   r1   r2   r3   r5   rI   rJ   r5   rI   r1   r   r2   r3   r   r0   r   r4   r   r   r8   Tr   r-   r:   zError testing new connection: r   r;   )r   r   get_jsonr   r   r   r   r>   r?   r@   rA   )r   rm   rn   ro   r   r   rD   s          r&   test_new_connectionr   ~  s    ''LF4! -    _$ 	ED $!9%A    	 Z(Z(<.$v,8 1	
 	?  "h.>T3IdSaNb/3N/Cm, **O/ + 

 )2   
  !),     5c!fX>?4SVH=
   	s5   %C! C! C! A1C! C! !	D1*<D,&D1,D1z0/database/connections/<int:connection_id>/schemac                    	 t         j                  j                  |       j                         }|r2t	        d|  d       |}t        j                  |j                        }nt	        d|  d       t        j                  j                  |       }|st        dd|  dd      d	fS t        |j                        }|j                  ||j                   d
|j                   |j                   d}|j"                  j%                         dk(  r@t'        |d      r4|j(                  r(|j(                  |d<   t	        d|j(                   d       t	        d|       t*        j-                  |j"                  |      }d|v r1t.        j1                  d|d           t        dd|d    d      dfS t	        d|  d       t        | |j                   t        j2                  |            }t4        j6                  j9                  |       t4        j6                  j;                          t        d||j<                  r|j<                  j?                         ndd      dfS # t@        $ re}t4        j6                  jC                          t.        j1                  dtE        |              t        ddtE        |       d      dfcY d}~S d}~ww xY w)z8API endpoint to get the schema for a database connectionrz   zJ
[DATABASE ROUTES] Getting stored schema from database, for connection ID 
zI
[DATABASE ROUTES] Fetching stored schema from source, for connection ID FzConnection with ID z
 not foundr9   ry   r   r   r   r4   r   /
[DATABASE ROUTES] Adding Oracle service_name: zConnection config:r   r@   zError fetching schema: zFailed to fetch schema: r;   z9
[DATABASE ROUTES] Creating new schema for connection ID rz   schema_nameschema_dataTN)r8   r   last_updatedr-   )#r   r"   r#   rc   r   r^   loadsr   r   r_   r   r   rI   r5   r1   r2   r3   r0   r   hasattrr4   r   get_database_schemar?   r@   dumpsr   rh   ri   rj   r   r=   r>   rl   rA   )rz   existing_schemar   r   r\   rI   r   rD   s           r&   
get_schemar     s   J )..88}8U[[]_`m_nnpqr$F**_%@%@AK ^_l^mmopq ,1155mDJ$!4]O:N    
 (
(;(;<H '//$)/q0AB * 8 8	! !!'')X5'*n:]blbyby3=3J3J!-0HI`I`Haacde&(9: $77"**"3 8 K +%6{77K6LMN$!9+g:N9OP    
 N}o]_`a#+&44 JJ{3F
 JJNN6"JJ !?E?R?RF//99;X\
  	 	
  


.s1vh781#a&:
   	s-   B%I (DI 0B-I 	K'AKKKc                 H    d| d}|j                  |       t        |      |fS )z)Helper function to return error responsesFr9   )updater   )r:   status_codekwargsresponse_datas       r&   error_responser     s*     %':M =!;..r'   z	/generatec                  `   t        j                         } | st        d      S | j                  d      }| j                  d      }| j                  d      xs | j                  dd      }t	        d|        t        ||g      st        d      S t         j                  j                  }t        j                  j                  |	      j                         }|rAt        j                  j                  |j                  
      j                         }t        j                         }t        |j                   |j"                  d      }t$        j                  j'                  t$        j(                  |k(  t$        j*                  |k\        j-                         }	d}
|rg|j.                  r[|j.                  }t1        |t2              r
d|v r|d   }
n5|j                  dk(  rd}
n#|j                  dk(  rd}
n|j                  dk(  rd}
|
dk7  r|	|
k\  rt        dd|
|	      S t4        j                  j                  |t        j                        j                         }|st        dd      S t7        |j8                        }|j:                  ||j<                   d|j>                   |j@                  d}|jB                  jE                         dk(  r@tG        |d      r4|jH                  r(|jH                  |d<   t	        d|jH                   d        |tJ        jL                  d!<   tN        j                  j                  |"      j                         }t	        d#|jB                   d$| d        |st	        d%       tP        jS                  |jB                  |      }d&|v rt        d'|d&    d      S tO        ||j@                  tU        jV                  |      (      }tX        jZ                  j]                  |       tX        jZ                  j_                          n*t	        d)       tU        j`                  |jb                        }|}t        j                         te        d*      z
  }t$        j                  j'                  t$        j(                  |k(  t$        jf                  |k(  t$        jh                  d+k(  t$        j*                  |k\        j                         }	 d,}|jE                         d-v r|rr|j.                  r|j.                  }t1        |t2              rP|jE                         dk(  r|j                  d.d/      sd/}ns|jE                         d0k(  r`|j                  d1d/      sNd/}nK|jE                         dk(  r|j                  d2vrd/}n'|jE                         d0k(  r|j                  dk7  rd/}nd/}|st	        d3| d4       d5}tk        jl                  |      }tP        jo                  |jB                  |      }|tJ        jL                  d!<   tq        jp                         }|js                  |||jB                  |j                  d6i             }t	        d7|       |j                  d8d,      }d9}d:|v r|d:   }tq        jp                         }||z
  }|d;   stu        t        j                  ||d<|d/||xr | |j                  d&d=      >	      }tX        jZ                  j]                  |       tX        jZ                  j_                          t        d?|j                  d&d@       dA|xr | B      S tu        t        j                  |||dC   |d,||xr | D      }|s|rt%        t        j                  t        j                         ||d+d/E      }tX        jZ                  j]                  |       tX        jZ                  j]                  |       tX        jZ                  j_                          nVt        j                         |_        tX        jZ                  j]                  |       tX        jZ                  j_                          d,|dC   |d   ||j                  |xr | |j                  dFd/      dG} |r|| d:<   tw        |       S # tx        $ r"}!t        dHt{        |!       d      cY d9}!~!S d9}!~!ww xY w)Iz(Generate SQL query from natural languager   rz   prompt
model_typemodelopenaiz+[API] Getting explain plan with model_type=zMissing required parametersr   rO   rN   rU   query_limitrR   d   rT   r;   rV   rW   zPYou have reached your monthly query limit. Please upgrade your plan to continue.rX   )r   query_countrw   zDatabase connection not foundry   r   r   r   r4   r   r   r   LAST_CONNECTION_CONFIGr   z'
[DATABASE ROUTES] Fetching schema for z connection ID z3Schema not found in DB, creating new schema record
r@   zFailed to get schema: r   z Updating existing schema record
)hoursgenerateT)r   claudeopenai_modelsFr   claude_models)rT   rV   z#[API] User does not have access to z  model, falling back to deepseekdeepseekconfigzResult of AI model processing:http_successNadditional_infor8   r,   zLWe could not generate the SQL query for you. We are investigating the issue.)	r   rz   natural_language_querygenerated_sqlexecution_timeis_successfulr   credit_consumederror_messagezFailed to generate SQL query: zUnknown errorrK   )r   	sql_query)r   rz   r   r   r   r   r   r   )r   r   
query_textrz   
query_type	is_cached
from_cache)r8   r"   r   r   query_idr   r   zError generating SQL query: )>r   r   r   r_   r   r%   r   r$   r   r"   r#   rc   r   rP   r   utcnowyearmonthr   filterr   r   rd   re   rf   rg   r   r   rI   r5   r1   r2   r3   r0   r   r   r4   r	   r   r   r   r   r^   r   r   rh   ri   rj   r   r   r   r   r   r   	get_modelget_db_configtimegenerate_sqlr   r   r>   rA   )"rm   rz   r   r   current_user_idrp   rr   todaymonth_startr   r   rs   r\   rI   r   r   r   
new_schemaschema_data_objone_hour_agocached_queryhas_model_accessr   db_config_result
start_timer   r   r   end_timer   query_historyquery_usager   rD   s"                                     r&   generate_queryr     s    D011 HH_-MXXhF ,'F488GX+FJ	7
|
DEv&';<< **--O  %%///HNNPL%%//8L8L/MSSU !uzz5;;: !&&--/1%%4
 %' 	 DMM MMM-.=M3Q+M: <<7*"%K\\^3"%K\\\1"$K "!;!b''	  $))33,// 4 eg  =sCC  
 3 34H ''!'q(9:"00	 !X-'*n2UZdZqZq+5+B+B-(@AXAX@YY[\] 4EK/0 !!++-+HNNPF 
4Z5G5G4HXeWffh
ijDE  33J4F4FHYZk!!$:;w;O:P"QSVWW $'"00

;/

 	

z"


12jj!3!34 "O ??$yq'99L##**o-'+!!\1	
 eg ML !55 $mT2!'')X5m>O>OP_af>g+0(#))+x7@Q@QRach@i+0( "'')X5$,,Nl:l+0(#))+x7DLLL<X+0( $)   7
|Ccde#J ((4 %22:3E3EGXY 8I34 YY[
 ##FOZ=O=OQaQeQefnprQst.7 zz.$7 &$%67O 99;!J.i  )$+'- -#% , A\1A$jj  3A  B
M JJNN=)JJ "0G_1U0VW!-!Bl2B  % OO'#) -)!(=-=	
 $$'0!+%K JJNN=)JJNN;'JJ +3//*;L' JJNN=)JJ K(G_,%((+@L0@ **\59
 />M+,}%% L <SVHEsKKLs&   Ib 0Eb 	b-b("b-(b-)rK   )9flaskr   r   r   r   r   r   r	   flask_loginr
   r   r^   r   loggingr   r   app.extensionsr   app.databaser   app.apir   app.database.modelsr   r   r   app.utils.encryptionr   r   app.utils.authr   rb   r   r   r   r   
app.modelsr   	getLogger__name__r?   app.database.db_connectorr   r   inforouter!   rE   ru   r{   r~   r   r   r   r   r   r    r'   r&   <module>r      sA   Z Z Z 4    (  $  P P C ) L L % 
		8	$ 8 	 9 :>"Q  #Q %y/AB&  C&P %x8f  9fP 9E7K!  L!F 9E7K@  L@D 9H:N  OB >Q3  R3j *VH=9  >9v @5'RL  SL^/ kF8,SL  -SLr'   