U
    /\h                    @   sP  d dl Z d dlZd dl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Zd dlmZ d dlZd dlmZ d dlmZ dd	lmZ i Zd+d
dZdd Zdd Zdd Zd,ddZdd Zd-ddZdd Zdd Z G dd dZ!G dd dZ"G d d! d!e"Z#G d"d# d#e"Z$d.d%d&Z%G d'd( d(Z&G d)d* d*Z'dS )/    N)defaultdict
namedtuple)deepcopy)List)g)fields)config   )	BaseModelc                    s   ddl mm ddl m  ddlm} t| |rL|d krD| jjj}| j	} n|d kr\| jj}G  fddd|j
  || | S )Nr   )date	timedelta)datetime)Queryc                       s6   e Zd ZdddZdd Z fddZ  ZS )	z%render_query.<locals>.LiteralCompilerFc                 [   s   |  |j|jS N)render_literal_valuevaluetype)selfZ	bindparamZwithin_columns_clauseZliteral_bindskwargs r   ./cmf/data_providers/base.pyvisit_bindparam.   s    z5render_query.<locals>.LiteralCompiler.visit_bindparamc                    s4   t |tr(dd fdd|D  S | S )Nz{%s},c                    s   g | ]} | qS r   )render_array_value.0x	item_typer   r   r   
<listcomp>4   s     zLrender_query.<locals>.LiteralCompiler.render_array_value.<locals>.<listcomp>)
isinstancelistjoinr   )r   valr   r   r   r   r   2   s    
z8render_query.<locals>.LiteralCompiler.render_array_valuec                    s   t |trt|S t |fr.d|d S t |rLdt|dd S t |trtdd fdd|D  S t 	|S )	Nz'%s'z%Y-%m-%d %H:%M:%S'z''z'{%s}'r   c                    s   g | ]}  |jqS r   )r   r   r   r   type_r   r   r   @   s     zNrender_query.<locals>.LiteralCompiler.render_literal_value.<locals>.<listcomp>)
r    intreprstrftimestrreplacer!   r"   superr   )r   r   r&   )LiteralCompiler	__class__r   r   r   r%   r   r   7   s    


z:render_query.<locals>.LiteralCompiler.render_literal_value)FF)__name__
__module____qualname__r   r   r   __classcell__r   r-   r   r   r   r.   r   r-   ,   s
     
r-   )r   r   r   Zsqlalchemy.ormr   r    ZsessionZbinddialect	statementZstatement_compilerZprocess)r6   r5   r   r   r3   r   render_query   s    	

r7   c                 C   s
   t | S )uK   Вернём драйвер по имени источника данных)ds_registryget)ds_namer   r   r   get_ddF   s    r;   c                  C   sf   t rtdd} tj D ]F\}}|ddkrP| dkrHddlm} |} | |d< t||dt |< qdS )uY   Инициализация всех источников данных из конфигаuZ   Источники данных нельзя инициализировать дваждыNzsqlalchemy.poolclass	QueuePoolr   )r<   )name)	r8   	Exceptionr   Zdata_sourcesitemsr9   Zsqlalchemy.poolr<   new_dd)Z
queue_poolr:   	ds_configr<   r   r   r   init_dsK   s    rB   c               	   C   sN   t  D ]@\} }td|   z|  W q tk
rF   td Y qX qdS )u=   Инициализация, миграция схемы БД.zInit DB u        не реализовано.N)r8   r?   printinit_dbNotImplementedError)r:   Zds_ddr   r   r   rD   [   s    rD   c                 C   sf   |  d}|s$|  d}|dkr$d}|s4td|| |jddd\}}t|}t||}|| |d	S )
Nclassr   Z
sqlalchemyz2cmf.data_providers.sqlalchemy:SQLAlchemyDataDriverzDYou must specify valid "type" or "class" in datasource configuration:   )maxsplitrA   r=   )r9   
ValueErrorsplit	importlibimport_modulegetattr)rA   r=   Zdd_mod_classZdd_typeZdd_module_nameZdd_class_nameZ	dd_moduleZdd_classr   r   r   r@   f   s    



r@   c                  C   s   t  D ]} |   qd S r   )r8   valuesbefore_requestddr   r   r   rQ   u   s    rQ   c                 C   s@   | rt tdrtd t D ]}| r2|  q |  q d S )NdebugZROLLBACK)hasattrr   rT   r8   rP   rollbackcommit)	exceptionrS   r   r   r   commit_all_ds{   s    


rY   c                  C   s*   t  D ]} td|   |   qd S )Nz	ROLLBACK )r8   rP   r   rT   rV   rR   r   r   r   rollback_all_ds   s    rZ   c                  C   s(   ddl m}  t D ]}||  qdS )zmake_models hookr   modelsN)cmf.includer\   r8   rP   make_models)r\   rS   r   r   r   r^      s    r^   c                   @   s   e Zd ZdZdddddZdd Zdd	 Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zd d! Zd"d# Zd$d% ZdS )&BaseDataDriver NrJ   c                O   s   || _ || _d S r   )r   r=   )r   rA   r=   _args_kwargsr   r   r   __init__   s    zBaseDataDriver.__init__c                 O   s   d S r   r   r   modelargsr   r   r   r   r9      s    zBaseDataDriver.getc                 O   s   d S r   r   r   instancerf   r   r   r   r   create   s    zBaseDataDriver.createc                 O   s   d S r   r   rg   r   r   r   delete   s    zBaseDataDriver.deletec                 O   s   d S r   r   rg   r   r   r   update   s    zBaseDataDriver.updatec                 O   s   d S r   r   rd   r   r   r   r!      s    zBaseDataDriver.listc                 O   s   d S r   r   rd   r   r   r   count   s    zBaseDataDriver.countc                 C   s   d S r   r   r   r   r   r   rW      s    zBaseDataDriver.commitc                 C   s   d S r   r   rm   r   r   r   rV      s    zBaseDataDriver.rollbackc                 C   s   d S r   r   rm   r   r   r   rQ      s    zBaseDataDriver.before_requestc                 C   s   d S r   r   )r   	cmf_modelr   r   r   dp_model   s    zBaseDataDriver.dp_modelc                 C   s   d S r   r   )r   Zsa_modelr   r   r   rn      s    zBaseDataDriver.cmf_modelc                 C   s   d S r   r   )r   Zdp_instancer   r   r   is_instance   s    zBaseDataDriver.is_instancec                 C   s   d S r   r   )r   Zmodels_r   r   r   r^      s    zBaseDataDriver.make_modelsc                 O   s   dS )u,   Вернём кастомный запросNr   r   rf   r   r   r   r   query_deprecated   s    zBaseDataDriver.query_deprecatedc                 C   s   t dS )u2   Создание/миграция схемы БД.NrE   rm   r   r   r   rD      s    zBaseDataDriver.init_dbc                 C   s   dS )u8   Закрываем текущие подключенияNr   rm   r   r   r   close_all_sessions   s    z!BaseDataDriver.close_all_sessions)r/   r0   r1   __doc__rc   r9   ri   rj   rk   r!   rl   rW   rV   rQ   ro   rn   rp   r^   rr   rD   rt   r   r   r   r   r_      s$   r_   c                   @   sF   e Zd Zdd ZdddZdd Zdd	 Zdd
dZedddZ	dS )
BaseMapperc                 C   s   dS )u  
        Вызывать по завершению маппинга всех объектов в запросе, постобработка.
        Обычно должен вызывать тот, кто создал экземпляр маппера.
        Nr   rm   r   r   r   post_mapping_hook   s    zBaseMapper.post_mapping_hookNc                 C   s   t d S r   rs   )r   obj
cmf_entityre   
model_namefull_fields_loadr   r   r   object_to_cmf   s    zBaseMapper.object_to_cmfc                 C   s   t d S r   rs   )r   ry   rx   r   r   r   cmf_to_object   s    zBaseMapper.cmf_to_objectc                    s~   |sdS  fdd|j D }tdtf|}| |_ |j D ]>}|  dr:d|ddd }t||t|| q:|S )u  
        TODO: создание промежуточного объекта плохо для производительности, нужно маппить напрямую из ResultSet
          да и в целом можно зарефакторить
        Nc                    s6   i | ].}|   d rd|ddd dqS )_sub__rH   N)
startswithr"   rL   )r   field
field_namer   r   
<dictcomp>   s    z4BaseMapper.obj_from_result_query.<locals>.<dictcomp>ZCmfObjr~   r   rH   )	_fieldsr   objectkeysr   r"   rL   setattrrO   )r   result_queryr   Z
obj_fieldsresr   Zattnamer   r   r   obj_from_result_query   s    


z BaseMapper.obj_from_result_queryc                    s    fdd|D S )Nc                    s   g | ]}j | d qS )re   r{   )r|   )r   rx   r{   re   r   r   r   r      s     z*BaseMapper.list_to_cmf.<locals>.<listcomp>r   )r   Zlstr{   re   r   r   r   list_to_cmf   s    zBaseMapper.list_to_cmfc                 C   sB   |s
t  S |dkrt S t|tr&|S t|tr6| S tddS )u   
        :param mapper: тип маппера
        :type mapper: None, str, Mapper subclass, Mapper instance
        :return: экземпляр маппера
        :rtype:  Mapper
        ZsimplezInvalid mapperN)MapperSimpleMapperr    rv   
issubclassrK   )clsmapperr   r   r   
get_mapper   s    

zBaseMapper.get_mapper)NNNN)N)N)
r/   r0   r1   rw   r|   r}   r   r   classmethodr   r   r   r   r   rv      s   

rv   c                       sX   e Zd ZdZe G dd dZeddddgZ fdd	Z	d
d Z
dddZ  ZS )r   u   
    Dataclass as model, для лёгкой сериализации в json
    fill class_name
    TODO fill meta для api, но вероятно это драйвер будет делать, там дешевле
    c                   @   s"   e Zd ZU dZeed< dd ZdS )zSimpleMapper.SimpleModelNidc                 C   s@   t | dr&| j d| j d| j dS | j dt| dd  dS )Nr=   (z: )r   )rU   
class_namecoder=   rO   rm   r   r   r   __repr__  s    
z!SimpleMapper.SimpleModel.__repr__)r/   r0   r1   r   r*   __annotations__r   r   r   r   r   SimpleModel  s   
r   VirtualInitDatar   re   
field_listc                    s   t    g | _d S r   )r,   rc   _virtual_init_listrm   r4   r   r   rc     s    
zSimpleMapper.__init__c                 C   s   i }t | jD ]j}||jj}|r.|j|_n|j|jd}|||jj< |jD ](}t||j}d|_	t
|j|j|j qNqg | _dS )uN   Вычислим все запрошенные виртуальные поля)simple_objectN)reversedr   r9   re   r   r   r   r   rO   _valuer   r   )r   Zcmf_instancesZ	init_dataZcmf_wrapper	field_clsZvirtual_fieldr   r   r   rw   #  s    

zSimpleMapper.post_mapping_hookNc              	   C   s  ddl m} |s.|s$|jdd }t||}|sDt }|j|_ntd||g }|p\|j	D ]}d|krt
||t||d q^|j	|}	|	sq^|	jr|s|	jdkr||	 q^t|	t	jt	jfr8t||	 d}
|
dkrq^|
dkrd}nF|o||}|r^t|| d	ddk	r^| j| |||d
}nq^nq^n(t|	t	jt	jt	jfrTq^nt||d}|dkrlq^t|	t	jr| ||o||t||	jd }nLt|	t	jr|r|js|jtjjd}nt|	t	j r|rt!"|}t
||| q^|r| j#tj$|||d |S )u  
        отображение obj -> simple_model
        если cmf_entity не указан, то создадим новый на основе модели cmf_model или её имени model_name
        возвращаем simple_model
        r   r[   rG   uI   Передан cmf_entity в SimpleMapper, вероятно это багr   .)defaultalwaysN_sub__id)r{   tzinfo)r   re   r   )%r]   r\   r   rL   rO   r   r   r   rK   r   r   r9   virtual	load_modeappendr   CmfRelationCmfGenericRelationid_fieldnamer|   r   
CmfM2MBaseCmfBackrefBaseCmfDateRangeCmfObjectListr   CmfDateTimer   r+   r   timezoneutcCmfJsonujsonloadsr   r   )r   rx   ry   re   rz   r{   r\   Zvirtual_fieldsr   r   obj_related_idfield_valuesub_fflr   r   r   r|   6  sr    




 
zSimpleMapper.object_to_cmf)NNNN)r/   r0   r1   ru   dataclassesZ	dataclassr   r   r   rc   rw   r|   r2   r   r   r4   r   r     s   r   c                   @   s   e Zd ZdddZdd ZdS )r   Nc              	   C   sF  ddl m} |sB|s2|s(|jdd }t||}|dd}d}nd}|sRt|}|}|r`|}	n
|j }	|	D ]}
|j|
 }sqn|j	r|s|j
dkrt||
}d|_d|_qnt|tjtjtjfrqnt||
d	}t|tjr|d	krqn| ||o||
t||jd }t|tjtjfrt|| d	}|d	krDqn|dkrTd}n|ob||
}|rnt||
 d
ddkrnt||
 d
rnt|tjr|dd n|j}t||d}|r| j| ||
||d}nd}nqnnqn|d	krqnt|tjr |r |js |jtjjd}t|tjr:| |}nt|tj!rX|rXt"#|}t|tj$r|
%dr|
dd |	krt&||
dd r|'|}|r||
dd  jd	kr|||
dd  _|||
dd  _t||
}|r |jd	kr,t(|t)t*t+tdt,fr"||_n
t-||_||_qnd|_.|/  |S )u  
        отображение obj -> cmf_entity
        если cmf_entity не указан, то создадим новый на основе модели cmf_model или её имени model_name
        возвращаем ссылку на cmf_entity
        r   r[   rG   T)emptyFr   N.r   r   r   _id)0r]   r\   r   rL   rO   r   r   r   r9   r   r   r   Z_oldr   r   r   r   r   r   r   r   r   re   r|   r   r   r   r+   r   r   r   ZCmfIPv4NetworkListZdb_castr   jsonr   CmfTUUIDendswithrU   Zmake_ellipsis_idobjr    r*   r'   floatboolr   is_newZmark_exists_in_db)r   rx   ry   re   rz   r{   r\   Zcmf_is_existsr   r   kr   r   r   r   r   Z	model_subZelipsis_objZ	field_objr   r   r   r|     s    




  

&
 

2


zMapper.object_to_cmfc                 C   s   t |}|j D ]\}}t|tjr(qt|tjr6qt|tjrDqt|tjrRqt|tjr`qt|tj	rnqt|tj
r|qt||}t|tjr|jdks|jrq|js|jsq| }|dkrtd| d| d| t||| q|S )N.u%   Попытка update field=Ellipsis  )r   r   r?   r   r   r   ZCmfM2MZCmfGenericM2MZ
CmfBackrefr   ZCmfGenericBackrefrO   r    CmfTyper   r   
is_changedZ	orm_dirtyZ	db_formatr>   r   )r   ry   rx   re   r   vZvvr   r   r   r}      s6    
zMapper.cmf_to_object)NNNN)r/   r0   r1   r|   r}   r   r   r   r   r     s   
vr   selectc              
   C   s   zdt krttt _W n( tk
r> } z
W Y dS d}~X Y nX t jdtt t jd | d t jd |   d7  < t jd dd t jd d  d7  < dS )uK   
    Глобальный счетчик запросов
    :return:
    profiler_dataNZselect_countr   rH   total)r   r   dictr   r>   
setdefault)actioner   r   r   inc_select_count$  s    r   c                   @   s   e Zd ZdZedZd.ddZedd Z	ddddd	d
dZ
ddddZdd Zdd Zdd ZddddZdd Zdd Zdd Zdd  Zd/d"d#Zd$d% Zddddd	d&d'Zdddd(d)d*Zdd+d,d-ZdS )0DataProvideruV   Объект, связывающий модель с источником данныхz"\b(?P<table>\w+)\.(?P<field>\w+)\bNc                 C   s   || _ || _d | _t| _d S r   )re   data_source_ddr   Z
mapper_cls)r   r   re   r   r   r   rc   ;  s    zDataProvider.__init__c                 C   s   | j st| j| _ | j S r   )r   r;   r   rm   r   r   r   data_driverA  s    zDataProvider.data_driverF)no_cacheTECHCOM_nocache
for_updatecache_inmemoryc                   s  |rt d| jjp2|p2tjp2|p2tjj| jj	}| 
| j||d<  fdd tjrdr| jj	dkr| jj	tjjjkri tjjj| jj	< tjjj| jj	 }|ddrĈ ||dd ||d< tjjj| jj	 d	f|d
|i|}|rd}	ntjjj||d}	t  |	dkr6tjtjjjd|  dS |	dk	r^tjtjjjd|  |	S tjtjjjd|  | jj| jf|d|i|}
| jjdkr|
S |r|
rd|
_|r|
S tjjj||
| jj	 | | j|d |d|d|d |
S dS )zF
        :param args:
        :param kwargs:
        :return:
        8   no_cache запрещен и будет удален osvfilterc                    sF   |  D ]8\}}|| kr&|| | |< q| | |kr | | | qd S r   )r?   )Z_fields_grow_cacheZ_full_fields_loadr   r   _grow_merger   r   r   [  s
    z%DataProvider.get.<locals>._grow_mergeF)Z
CmfProjectZCmfWorkflowZCmfLogicTypeZCmfSchemeWfZCmfSchemeWfRuleZCmfActivityr{   Nz.getr   r   EmptyzDP: get() cache Empty zDP: get() cache zDP: get() NOcache r   rdiskTorder_bygroup_byquery_paramsr   )r>   re   TEXKOM_no_cacher   import_modecmfapp	CMF_CACHEcache_is_lockedr/   _get_filterZTEXCOM_ENABLE_GROWCACHE_HACKZtexcom_growcache_hack_cacher9   hashr   print_debugDEBUGr   r=   readonlyadd_query_params)r   r   r   r   r   rf   r   Zfields_grow_cachekeycachedb_resr   r   r   r9   G  sV    	

(

   zDataProvider.getT)
invalidatec                O   sd   t d | jj|f||}| jjdkr,|S |s4|S |d krPtjj|d d S tjj|d |S )Ninsertr   ri   )r   r   ri   r=   r   r   r   r   )r   rh   r   rf   r   r   r   r   r   ri     s    zDataProvider.createc                 O   s   t d | jj||}|S )Nrj   )r   r   bulk_deleter   rf   r   r   r   r   r   r     s    zDataProvider.bulk_deletec                 O   sF   t d td| d| d|  | jj|f||}td |S )Nr   zbulk_insert start model= args= kwargs=zbulk_insert end)r   r   rT   r   bulk_insert)r   re   rf   r   r   r   r   r   r     s
    
zDataProvider.bulk_insertc           
   	   O   s   dd l }ddlm} dd l}td td| d| d|  | jj|f||}td |j	s|  }t
|dkrtjj|jd  n|rtjj|j| |  | d }	|d	t
| d
| d|	dd |	dkr|d|	dd |S )Nr   	cmf_alertrk   zbulk_update start model=r   r   zbulk_update endi  u)   Инвалидировали кеш по u$    обьектам у таблицы u    за z.2fu    мс   u2   DEV: Инвалидация кэша заняла )timer]   r   loggingr   r   rT   r   bulk_updater   lenr   r   r   Zinvalidate_idsr   Zwarning)
r   re   rf   r   r  r   r  r   Z
start_timeZelapsed_timer   r   r   r    s$    
$zDataProvider.bulk_update)r   c                O   s   t d | jjs"td|j  | jj|f||}| jjsPtd|j  |r\td| jj}| jj	dkrt|S |s|
ddrd}d|jkr|jjr|jrd	nd
}|jrd
}tjj|| td|j  |S )Nrk   z+Run self.data_driver.update(), instance_id=z+End self.data_driver.update(), instance_id=r   r   r   Tcmf_deletedrj   ri   z0End cmf.app.CMF_CACHE.invalidate(), instance_id=)r   re   r   r   rT   r   r   rk   r>   r=   r9   r   r  r   r   r   r   r   r   )r   rh   r   rf   r   r   r   r   r   r   rk     s(    zDataProvider.updatec                 O   s   | j j||}|S r   )r   rW   )r   rf   r   retr   r   r   rW     s    zDataProvider.commitc                 O   s   | j j||S r   )r   rV   rq   r   r   r   rV     s    zDataProvider.rollbackc                 O   s2   | j j||}| j jdkr|S tjj|d |S )u   
        Logical delete. Реализация в провайдере или в модели?
        self.deleted = 1
        self.update()
        r   rj   )r   rj   r=   r   r   r   r   r   r   r   r   rj     s
    zDataProvider.deletec           
         s  ddl mmmmmmmm	 ddl	m
 ddlm}m}m}m} d#ddd$ddd%fd	d	d&fd
d	d'fdd	d(fdd	d)fdd	d*fdd	d+fdd	d,	fdd	d
ddddddddddd
 |dg }|dk rg }|d

s
i 
t|tr t|}|r,|g}|  D ]@\}}	||jkr8||= t|	tjrf|	j}	||d|	g q8fdd fddtdfdd 
fd!d"|}|S )-u   
        Преобразуем обычные kwargs в продвинутый фильтр для однообразной логики фильтрования
        :param model:
        :param kwargs:
        :return:
        r   )start_of_day
end_of_daystart_of_weekend_of_weekstart_of_monthend_of_monthstart_of_yearend_of_yearstr_to_timedelta)r   r   r  r   Nc                 S   s
   t | S r   )r   nowoffsetr   r   r   <lambda>      z*DataProvider._get_filter.<locals>.<lambda>c                 S   s
   t | S r   )r   r   r  r   r   r   r    r  c                    s    | S r   r   r  )r  r   r   r    r  c                    s    | S r   r   r  )r	  r   r   r    r  c                    s    | S r   r   r  )r
  r   r   r    r  c                    s    | S r   r   r  )r  r   r   r    r  c                    s    | S r   r   r  )r  r   r   r  	  r  c                    s    | S r   r   r  )r  r   r   r  
  r  c                    s    | S r   r   r  )r  r   r   r    r  c                    s    | S r   r   r  )r  r   r   r    r  )
__G_NOW__G_DATE__START_OF_DAY__END_OF_DAY__START_OF_WEEK__END_OF_WEEK__START_OF_MONTH__END_OF_MONTH__START_OF_YEAR__END_OF_YEARdwMy)
r  r  r  r  r  r  r  r   r  r  r   filter_context==c                    sb   t | tr|  krdS | dkr$d}n| dkr2d}nd}|rXttddsJ|n
ttj|t_ |   S )z plain '__G_NOW' / '__G_DATE' Nr  ,  r  ip  jscache_timelife)r    r*   rO   r   minr(  )sttl)_TIME_BASE_FUNCSr   r   _maybe_time_plain_string-  s    z:DataProvider._get_filter.<locals>._maybe_time_plain_stringc                    s   t tddd}t| tr| s"dS | d }t|t r<|kr@dS t| dkrV|  S | d }t|t std| dt|j ||r |}|r| | }|	 s|  S | |S )	u!    ['KEY'] или ['KEY','offset'] )r*  returnc                 S   s"   | pd  } t| o | d S )Nr`   z+-)stripr   lstripisdigitr*  r   r   r   _is_plain_int>  s    zIDataProvider._get_filter.<locals>._maybe_time_list.<locals>._is_plain_intNr   rH   u   Offset для u9    должен быть строкой, получено: )
r*   r   r    r!   r  rK   r   r/   r9   r/  )Znoder3  r   r  unit)_NATURAL_UNITr,  r   r   _maybe_time_list<  s$    



z2DataProvider._get_filter.<locals>._maybe_time_listr2  c                    s  t | tsd S tdtj}||  }|s2d S d}ttdd sF|n
t	tj
|t_
dd l}|j  }|dpvd}| s||jjS td}d}|}	||D ]^\}
}}|
p|}
|
}|sd	}| }|d
krd}n|dkrd}n|}|	 |
 | | 7 }	q|	|jjS )NzE^\s*now\(\)\s*(?P<tail>(?:\s*[+-]?\s*\d+\s*(?:y|M|min|[wdhms]))*)\s*$r'  r(  r   tailr`   z([+-]?)\s*(\d+)\s*([A-Za-z]+)?+r!  r)  mr#  )r    r*   recompileI	fullmatchr/  rO   r   r)  r(  r   r  Z
astimezonegroupr   r   findalllower)r*  Z_NOW_CALL_POSTFIX_REr9  r+  Z_dtZ
base_localr7  Ztoken_reZ	last_signZ	base_calcsignZnumr4  ZulZnormr  r   r   _maybe_time_call_stringY  s@    

z9DataProvider._get_filter.<locals>._maybe_time_call_stringc                    s   | }|d k	r|S t | tr0fdd| D S | }|d k	rD|S | }|d k	rX|S t | tr| drd fdd	  | dd  S t | tr| dkrtjjjS | S )	Nc                    s   g | ]} |qS r   r   )r   i)_recursive_params_replacer   r   r     s     zODataProvider._get_filter.<locals>._recursive_params_replace.<locals>.<listcomp>z__SELF.c                    sB   |  d\}}}|d k	r&t||d }n | }|r>||d}|S )N.)r   )	partitionrO   )pathr   headsepr7  )r%  get_ctx_attrr   r   rJ    s    zQDataProvider._get_filter.<locals>._recursive_params_replace.<locals>.get_ctx_attrr	   Z__G_CURRENT_USER)N)r    r!   r*   r   r   Zcurrent_userr   r   )r   r   )rB  r6  r-  rD  r%  )rJ  r   rD    s"    
	
z;DataProvider._get_filter.<locals>._recursive_params_replace)N)N)N)N)N)N)N)N)N)N)r]   r  r	  r
  r  r  r  r  r  Zcmf.util.cmfutilr  r   r   r  r   r9   r    r*   r   r   copyr?   r   r   r   r   )
r   re   r   r   r   r  r   Zsmart_filterr   r   r   )r5  r,  rB  r6  r-  rD  r	  r  r  r  r%  r  r  r
  r  r  r   r     s^    (     


0&zDataProvider._get_filterANDc                 C   s<  ddl m} ddl m} tg g i d}|r|D ]f}	|	dkr<q.|	drd|	d d |jkrd|	d d }	|	drz|	d	d  }	|d
 |j d|	  q.|r|D ]F}
|
dr|
d d |jkr|
d d }
|d
 |j d|
  q|s|S t	|d t
rV|D ]N}| j|||d D ]2\}}|dkr<|| | n|| | qqn|d dkr| j||d	d  |d d D ]2\}}|dkr|| | n|| | qn||d dkrVt|dks|d	 dkrtd|d D ]Z}	|	dkrq|	dr4|	d d |jkr4|	d d }	|d
 |j d|	  qnt|dkr$d }|d d}|d	 d}d }d }|d dkr|S |d dkrd|d< |d |jkr|d	 }|j|d  }|d }t|d	kr>|d	 }nD|d |jkr>|d }|j|d  }|d }t|d	kr>|d	 }d}|drr|d d |jkrr|d d }d}|r|dr| }|r|d d |d jkr|d d }d}|r8|s|dkr|dkr|d }t	|trt
|}t	|t
s|g}g }|D ]@}tt|tjr,|j}tt|trD|jj}|| q|dkrr|d |g | ||jkr|d |g | |dkrt|tjrd}|D ]B}t	|tr|dd	krt|dd t|ksd}q|rd}t|tj r8|jdkr8|j!|jd d p6|}t|tjr|dkr| D ]>}|st|d |j  |rX|d
 |j d|  qXt|tjr|dkr| D ]N}| ||d  D ]2\}}|dkr|| | n|| | qАq|d
 |j d|  n|d| d dd! |S )"Nr   r   r[   )r\   r   cache_clustersr   r   r   -rH   r   rE  )parent_operrM  )rL  ORr      )=r&  ut   Операция order_by в фильтре должна быть в формате: ["order_by", "=", [поля..]]r	   r  ANYtextFT)rR  r&  INrP  parentrG   r\   EXISTSuP   Ошибка  при выполнении UBQL - неверный запрос. uM    Проверьте правильность введенных данных.)abort)"r]   r   r\   r   r   r   r   r   r   r    r!   r   r?   rk   extendr  r>   rL   Zrelated_modelssetr   r   r   r   r
   r   r   Zcache_cluster_fieldsZ
CmfRelBaser*   rl   varsr   r9   )r   re   Z
obj_filterZobj_order_byZobj_group_byrO  r   r\   r   r   r   Zfilt_lsr   r#   r   Zobj_filter0Zobj_filter1Zfield__field_namer   ZoperZfield_is_tuuidZ
_relmodelsZrule_values_dirtyZrule_valuesrvZmaybe_field_is_tuuidZ_vZrmodelr   r   r   r     s    

(

 "
 
8

zDataProvider._query_paramsc                 C   s*  dddddgdddgggdgd	d
dgg g g dgdddgdgdgg g dgdgdddgg dgg g g dgdddgdgddgg g g dgdddgdddggg ddgg g g dgdddggg dgg g g dgdddggg dgg g g dgdddggg dgg g g dgd ddggd!gd"d#gg g g dgd$dd%ggg d&d#gg g g dgd'dd%ggd!gd&d#gg g g dgdddgd(dd)ggg dd*gg g g dgd+ddggg dgg g g dgd,ddggd!gd#gg g g dgg}d-d.l m} |D ]R\}}|jj|j|}||krtd/| d0 td1|  td2|  qd3S )4ug   
        Тестирование
        Запуск: models.CmfTask.dp._test_query_params()
        listsrW  Zcache_status_typerR  ZIN_PROGRESSZlogic_prefixzlist.agile_sprintZCmfListzCmfList.cache_status_typezCmfList.logic_prefixzCmfTask.lists)r\   r   parentsrM  r]  r&  {   r=   ZqwezCmfTask.namezcmf_owner.idzCmfPerson:12312321Z	CmfPersonzCmfPerson.idzCmfTask.cmf_ownerzCmfTask.cache_status_typezCmfTask.logic_prefixZext_idZLIKEz
%::qwe::%%zCmfTask.ext_idz::qwe::zparent.ext_idzCmfTask.parentzstatus.ext_idZ	CmfStatuszCmfStatus.ext_idzCmfTask.statuszstatus.status_code_idZ12345zCmfStatus.status_codezstatus.status_coder   Z	qweqweqwez
CmfTask.idzparent.project.namestatusr   r[   uC   Ошибка в результате _query_params(models.CmfTask, r   u   Факт:        u   Должно быть: N)r]   r\   ZCmfTaskZdpr   rC   )r   Zf_listr\   fZres_origr   r   r   r   _test_query_paramsc  sf    








@
zDataProvider._test_query_paramsc                O   s"  |rt d| jjp2|p2tjp2|p2tjj| jj	}t
  | | j||d< tjjj| jj	 df|d|i|}|r~d}nBt }	tjjj||d}t |	 dkrtdt |	   |d	krtjtjjjd
|  g S |dk	rtjtjjjd|  |S tjtjjjd|  t }	| jj| jf|d|i|}
t |	 dkrxtdt |	   | jjdkr|
S |r|
D ]}d|_q|st }	| | j|d |d|d}tjjj||
| jj	 ||d t |	 dkrtdt |	   |
S dS )u   
        Пробросили сюда relation_load и relation_load_only для реализации join и подселектов в будущем
        :param args:
        :param kwargs:
        :return:
        r   r   z.listr   Nr   g333333?z%PROF DataProvider.list cache.get got r   zlist() From cache  Empty zlist() From cache zDP: list() From NOcache r   g      ?z1PROF DataProvider.list self.data_driver.list got r   Tr   r   r   z%PROF DataProvider.list cache.add got )r>   re   r   r   r   r   r   r   r   r/   r   r   r   r  r9   rT   r   r   r   r!   r=   r   r   r   )r   r   r   r   r   rf   r   r   r   Zprof_str   rC  r   r   r   r   r!     sJ    (

"zDataProvider.list)r   r   r   c          
      O   sD  |rt d| jjp.|p.tjp.tjj| jj	}t
  | | j||d< tjjj| jj	 df|d|i|}|rzd }ntjjj||d}|dkrtjtjjjd|  tdn|d k	rtjtjjjd	|  |S t
  | jj| jf||}|s@| | j|d |d
|d}	tjjj||| jj	 |	|d |S )Nr   r   z.countr   r   r   zcount() From cache Empty z$BUG: count() cache can not be empty!zcount() From cache r   r   r   )r>   re   r   r   r   r   r   r   r   r/   r   r   r   r9   r   r   rK   r   rl   r   r   )
r   r   r   r   rf   r   r   r   r   r   r   r   r   rl     s.    (
"zDataProvider.count)r   c                O   s   t | jj||| j| j|dS NrS   re   r   )
QueryProxyr   queryre   )r   r   rf   r   r   r   r   rr     s       zDataProvider.query_deprecated)NN)NNrL  )r/   r0   r1   ru   r:  r;  ZTABLE_FIELD_RErc   propertyr   r9   ri   r   r   r  rk   rW   rV   rj   r   r   rb  r!   rl   rr   r   r   r   r   r   7  s,   


J =
 1O6r   c                   @   sp   e Zd ZdZdddZdd ZdddZd	d
 Zdd Zdd Z	dd Z
dd Zdd Zedd Zdd ZdS )re  u   
    Оборачиваем кастомный запрос и добавляем возможность извлекать данные с автомаппингом.
    TODO: Проверить слайсы query[a:b]
    Nc                 C   s0   || _ || _|| _t|t | _t|| _d S r   )_queryr   re   r    rv   _mapper_is_myr   _mapper)r   rf  rS   re   r   r   r   r   rc     s
    zQueryProxy.__init__c                    s    fdd}|S )u   Обёртка для методов, которые возвращают новый запрос на основании текущего.c                     s(   t j | |}t|jjjdS rc  )rO   rh  re  r   re   rj  )rf   r   	new_queryitemr   r   r   method_proxy  s    z,QueryProxy.__getattr__.<locals>.method_proxyr   )r   rm  rn  r   rl  r   __getattr__  s    zQueryProxy.__getattr__c                 C   s0   | j j| j| j|||d}t|| j | j| jdS )uR   
        Логика сортировки на основе модели
        )re   r   sliceaggregate_selectrd  )r   order_queryrh  re   re  rj  )r   r   rp  rq  rk  r   r   r   rr    s        zQueryProxy.order_queryc                 C   s2   | j r.| j |r.| jj|| j t|d}|S )u6   Автоконвертация объектов в CMF)re   )r   rp   rj  r|   rn   r   )r   r   r   r   r   
_map_value#  s    zQueryProxy._map_valuec                    s.   t |tr t fdd|D S  |S d S )Nc                 3   s   | ]}  |V  qd S r   )rs  )r   colrm   r   r   	<genexpr>,  s     z&QueryProxy._map_row.<locals>.<genexpr>)r    tuplers  )r   rowr   rm   r   _map_row)  s    
zQueryProxy._map_rowc                    s   t  j}d}tjj||}tjj jjr6d}ntjj	|}t
  |dkrptjtjjjd|  g S |dk	rtjtjjjd|  |S tjtjjjd|   fdd jD }tjj|| jj   jr j  |S dS )	uo   Метод извлечения всех данных из текущего запрос с маппингом.Z
custom_allNr   zall() From cache Empty zall() From cache zDP: all() From NOcache c                    s   g | ]}  |qS r   )rx  )r   rw  rm   r   r   r   E  s     z"QueryProxy.all.<locals>.<listcomp>)r7   rh  r   r   r   r   r   re   r/   r9   r   r   r   r   ri  rj  rw   r   sql_kr   r   r   r   rm   r   all0  s&    

zQueryProxy.allc                 C   s   t | j}d}tjj||}tjj| jjr6d}ntjj	|}t
  |dkrptjtjjjd|  dS |dk	rtjtjjjd|  |S tjtjjjd|  | j }| |}tjj||| jj  | jr| j  |S dS )uP   Метод извлечения первой строки с маппингом.Zcustom_firstNr   zDP: first() From cache Empty zDP: first() From cache zDP: first() From NOcache )r7   rh  r   r   r   r   r   re   r/   r9   r   r   r   firstrx  r   ri  rj  rw   )r   rz  r{  r   r   rw  r   r   r   r   r}  K  s(    



zQueryProxy.firstc                 C   s   t   t| j}d}tjj||}tjj| jj	r<d }ntjj
|}t   |dkrvtjtjjjd|  d S |d k	rtjtjjjd|  |S tjtjjjd | j }tjj||| jj	  |S )NZcustom_countr   zDP: count() From cache Empty zDP: count() From cache zDP: count() From NOcache TODO)r   r7   rh  r   r   r   r   r   re   r/   r9   r   r   rl   r   ry  r   r   r   rl   g  s$    

zQueryProxy.countc                 O   s   | j j||}|S r   )rh  rj   )r   rf   r   r   r   r   r   rj     s    zQueryProxy.deletec                 C   s   | j S r   )rh  rm   r   r   r   dd_query  s    zQueryProxy.dd_queryc                 C   s   t |  S )u+   Чтение строк из запроса)iterr|  rm   r   r   r   __iter__  s    zQueryProxy.__iter__)NNN)NNN)r/   r0   r1   ru   rc   ro  rr  rs  rx  r|  r}  rl   rj   rg  r~  r  r   r   r   r   re    s   


re  )N)N)N)r   )(r   rM   r   r   r:  r  collectionsr   r   rK  r   typingr   r   Zflaskr   Zcmf.appr   r   r]   r   Zmodels.base_modelr
   r8   r7   r;   rB   rD   r@   rQ   rY   rZ   r^   r_   rv   r   r   r   r   re  r   r   r   r   <module>   sL   
-

97  
     V