
    (j*                     |    d dl  d dlmZ d dlmZmZmZ d dlmZ d dl	Z	 e	j                  e      Z G d de      Zy)    )*)CmfPluginDatasource)create_enginetext	bindparam)SQLAlchemyErrorNc                        e Zd Zej                  dgz   Zi Zd ZddZd Zd Z	d Z
d Zd Zdd	Zd
 Z fdZ fdZd Zd Z fdZ xZS )r   sql_connect_testc                    | j                  g d       t        j                         5  | j                  j                  j
                  j                  dd      j                  dd      }ddddd	}| j                  dk(  ru|| j                      d
| j                  j                   d| j                  j                  j                          d| d| j                  j                   d| j                   }nt|| j                      d
| j                  j                   d| j                  j                  j                          d| d| j                  j                   d| j                   }ddd       |S # 1 sw Y   S xY w)uH   
        Формирует строку подключения
        )zplugin.ext_urlzplugin.ext_portzplugin.ext_passwordzplugin.ext_logindb_typequery_timeoutzhttp:// zhttps://zpostgresql+psycopg2zmysql+mysqlconnectorzmssql+pymssqloracle)
postgresqlmysqlmssqlr   z://:@z/?service_name=/N)load_fieldscmfutildisable_aclpluginext_urlvaluereplacer   	ext_loginext_passworddecryptext_portname)selfr   dialect_driverconnection_strings       4./modules/datasource/models/cmf_plugin_datasource.py_sql_build_connection_stringz0CmfPluginDatasource._sql_build_connection_string   sp    	  F  	G  " 	kk))//77	2FNNz[]^G 4/("	N ||x'
 &dll34C8M8M7NaPTP[P[PhPhPpPpPrOsy$++"6"6!7tyykS " &dll34C8M8M7NaPTP[P[PhPhPpPpPrOsy$++"6"6!7qE "'	0 ! 1	0 ! s   E E22E<c                    | j                   | j                  v rZ|r?| j                  | j                      j                          | j                  | j                   = n| j                  | j                      S | j                  dg       | j                  dk(  r	 ddl}ddl}d|_        ||j                  d<   	 | j                         }t        |dd	d
| j                  d      }|| j                  | j                   <   |S # t        $ r}t        j                  d|         d}~ww xY w# t        $ r+}t        j                  d| j                    d|         d}~ww xY w)u?   
        Получает или создает engine
        r   r   r   Nz8.3.0	cx_Oracleu1   Драйвер oracle не установлен:    
      F)	pool_sizepool_recyclemax_overflowpool_timeoutechou7   Ошбика создания engine для datasource z: )id_enginesdisposer   r   sysoracledbversionmodulesImportErrorloggererrorr&   r   r   	Exception)r"   refresh_enginer4   r5   er$   engines          r%   _sql_get_or_create_enginez-CmfPluginDatasource._sql_get_or_create_engine4   sC    77dmm#dgg&..0MM$''*}}TWW--)%<<8##* +3K(
	 $ A A C"!!//F &,DMM$''"M  PQRPSTU   	LLRSWSZSZR[[]^_]`ab	s1   C: 4AD$ :	D!DD!$	E-&EEc                 (     |j                   dd      S )u7    Очищает SQL от лишних символов      r   )r"   r   s     r%   sql_text_cleanerz$CmfPluginDatasource.sql_text_cleaner[   s    t||FC((    c                 z    |s|S |j                  dd      }|j                  dd      }|j                  dd      }|S )uI   
        Экранирует спецсимволы LIKE: %, _,         \z\\%z\%_z\_rC   )r"   searchs     r%   _escape_like_patternz(CmfPluginDatasource._escape_like_pattern_   sC     M f-U+U+rE   c                     t        |      }|s|S g }|j                         D ]=  \  }}t        |t        t        t
        f      s"|j                  t        |d             ? |r |j                  | }|S )u   
        Готовит text() statement, добавляя expanding=True
        только для list/tuple/set параметров.
        T)	expanding)	r   items
isinstancelisttuplesetappendr   
bindparams)r"   queryparamsstmtbindskeyr   s          r%   _prepare_text_statementz+CmfPluginDatasource._prepare_text_statementm   sq    
 E{K ,,. 	=JC%$s!34Ysd;<	= "4??E*DrE   c                 H    |syt        d |j                         D              S )NFc              3   r   K   | ]/  }t        |t        t        t        f      xr t	        |      d k(   1 yw)r   N)rO   rP   rQ   rR   len).0r   s     r%   	<genexpr>zBCmfPluginDatasource._has_empty_param_collection.<locals>.<genexpr>   s6      
 utUC01Ec%jAoE
s   57)anyvalues)r"   rV   s     r%   _has_empty_param_collectionz/CmfPluginDatasource._has_empty_param_collection   s(     

 
 	
rE   c                     dg g ddS )NTr   successcolumnsdatarowcount r"   s    r%   _empty_resultz!CmfPluginDatasource._empty_result   s    	
 	
rE   c                    |s| j                  dg       | j                  }	 | j                  t        |            }|xs i }| j	                  |      r| j                         S |rf|rd| j                  |      }g }	t        |      D ]+  \  }
}d|
 }|	j                  d| d| d       d| d||<   - d| dd	j                  |	       d
}| j                         }| j                  ||      }|j                         5 }|j                  ||      }|j                  r|j                         }|j!                  t#        |            }g }|D ]C  }i }t        |      D ]   \  }
}||
   }|d||<   t        |      ||<   " |j                  |       E d|||j$                  dcddd       S 	 ddd       y# 1 sw Y   yxY w# t&        $ r?}t)        |t*              rd| }nd| }t,        j/                  |       d|dcY d}~S d}~ww xY w)u  
        Выполняет запрос и возвращает результат

        TODO1: Вероятно ещё нужно валидировать запрос
        и запрещать модифицирующие запросы
        (SQL For Confluence выполняет такие запросы но сразу делает rollback транзакции)
        На техкоме обсуждали, что безопасность возлагается на DBA клиента
        
rows_limitsp_zLOWER(subq.z) LIKE LOWER(:z) ESCAPE '\'rH   z=
                    SELECT * FROM (
                        z9
                    ) AS subq
                    WHERE z OR z
                NTrd   u2   Ошибка выполнения запроса: u+   Непредвиденная ошибка: Fre   message)r   rm   rD   strrb   rk   rK   	enumeraterS   joinr?   rZ   connectexecutereturns_rowskeys	fetchmanyintrh   r;   rO   r   r9   r:   )r"   rU   rV   limitrJ   search_colscleaned_queryexec_paramsescaped_search
conditionsidxcol
param_namer>   rW   
connectionresultrf   rowsrg   rowrow_dictcolumnr   r=   	error_msgs                             r%   sql_executezCmfPluginDatasource.sql_execute   sb    l^,OOEL	 11#e*=M ,BK //<))++ +!%!:!:6!B
 )+ 6 	DHC
 $'seJ%%%cU.MR 12.1A.CK
+	D%& (!;;z23 4	! 335F//{KD! Z#++D+>&&$kkmG!++CJ7DD# .#%+4W+= >KC$'HE$}37 036u: 0> H-. $(#* $$*OO	'  '  2  	 !_-PQRPST	I!M	LL# !$ 	sJ   A G  #BG  =B#F4 	G  +G  4F=9G  =G   	H	4H=HHc                    	 | j                  d      }|j                         5 }d| j                  _        | j                  j	                          dddcd d d        S # 1 sw Y   y xY w# t
        $ rf}d| j                  _        | j                  j	                          t                d| }t        j                  |       t        |d       Y d }~y d }~ww xY w)	NT)r<   re   u:   Соединение успешно установленоro   r:   u>   Ошибка подключения к базе данных: abort)
r?   rt   r   sync_statussaver;   commit_with_eventr9   r:   	cmf_alert)r"   r>   r   r=   r   s        r%   r
   z$CmfPluginDatasource.sql_connect_test   s    	-3343HF! Z*3'  "  $[    	-&-DKK#KKXYZX[\ILL#it,,	-s5   "A* 0A	A* A'#A* 'A* *	C3ACCc                 *    t         |          ddgz   S )Nr   zplugin.sync_status)supersave_preload_fields)r"   	__class__s    r%   r   z'CmfPluginDatasource.save_preload_fields  s    w*,:N/OOOrE   c                 b    | j                          | j                          t        |   di |S )Nri   )_calc_plugin_calc_enginer   r   )r"   kwargsr   s     r%   r   zCmfPluginDatasource.save
  s-    w|%f%%rE   c                     | j                   ri| j                  | j                  v rP| j                  | j                     j                          | j                  | j                  = d| j                  _        y y y )Ndisabled)
is_changedr1   r2   r3   r   r   rj   s    r%   r   z CmfPluginDatasource._calc_engine  sT    ??tww$--7MM$''"**,dgg&&0DKK#  8?rE   c                     | j                   j                  }|s9t        j                  d| j                        }|j                          || _         y y )Nsql)typer!   )r   r   models	CmfPluginr!   r   )r"   r   s     r%   r   z CmfPluginDatasource._calc_plugin  sB    ""%%5tyy%AFKKM DK rE   c                     dd| g}t         j                  j                  |      s t         j                  j                  |      rt	        dd       t        |   |i |S )N
datasourcez==)filteruz   Нельзя удалить источник базы данных, т.к. используется объектами SQLTr   )r   CmfDatasourceWikiQuerycountCmfDatasourceFieldQueryr   r   delete)r"   argsr   _filterr   s       r%   r   zCmfPluginDatasource.delete  sg    t,((..g.>&B`B`BfBfnuBfBv  S  [_  `w~t.v..rE   )F)NNNN)__name__
__module____qualname__r   api_methodsr2   r&   r?   rD   rK   rZ   rb   rk   r   r
   r   r   r   r   r   __classcell__)r   s   @r%   r   r   
   sr    %115 K H!!F%N)*

Zx-0P&
1!/ /rE   r   )cmf.include/modules.datasource.fields.cmf_plugin_datasourcer   
sqlalchemyr   r   r   sqlalchemy.excr   logging	getLoggerr   r9   ri   rE   r%   <module>r      s:     O 5 5 *  
		8	$V/- V/rE   