U
    [Qc                     @   s\  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mZ dd	lmZ i Zd/d
dZdd Zdd Zdd Zdd Zd0ddZdd Zdd Zd1d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&d2d)d*Z'G d+d, d,Z(G d-d. d.Z)dS )3    N)defaultdict
namedtuple)deepcopy)List)g)fields)configmodels   )	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   ./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>3   s     zLrender_query.<locals>.LiteralCompiler.render_array_value.<locals>.<listcomp>)
isinstancelistjoinr   )r   valr   r   r   r   r   1   s    
z8render_query.<locals>.LiteralCompiler.render_array_valuec                    sj   t |trt|S t |fr0d|d S t |trXdd fdd|D  S t |S )Nz'%s'z%Y-%m-%d %H:%M:%Sz'{%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strftimer"   r#   superr   )r   r   r&   )LiteralCompiler	__class__r   r   r   r%   r   r   6   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)r4   r3   r   r   r1   r   render_query   s    	

r5   c                 C   s
   t | S )uK   Вернём драйвер по имени источника данных)ds_registryget)ds_namer   r   r   get_ddC   s    r9   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)	r6   	Exceptionr   Zdata_sourcesitemsr7   Zsqlalchemy.poolr:   new_dd)Z
queue_poolr8   	ds_configr:   r   r   r   init_dsH   s    r@   c                  C   s   t  D ]\} }|  qdS )u8   
    Отключаем все соединения
    N)r6   r=   close_all_sessionsr8   Zds_ddr   r   r   close_all_dsX   s    rC   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)r6   r=   printinit_dbNotImplementedErrorrB   r   r   r   rE   `   s    rE   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r?   r;   )r7   
ValueErrorsplit	importlibimport_modulegetattr)r?   r;   Zdd_mod_classZdd_typeZdd_module_nameZdd_class_nameZ	dd_moduleZdd_classr   r   r   r>   k   s    



r>   c                  C   s   t  D ]} |   qd S r   )r6   valuesbefore_requestddr   r   r   rR   z   s    rR   c                  C   s   t  D ]} |   qd S r   )r6   rQ   before_first_requestrS   r   r   r   rU      s    rU   c                 C   sP   t  D ]B}| r.ttdr$td |  qttdrBtd |  qd S )NdebugZROLLBACKZCOMMIT)r6   rQ   hasattrr   rV   rollbackcommit)Z	exceptionrT   r   r   r   commit_all_ds   s    




rZ   c                  C   s*   t  D ]} td|   |   qd S )Nz	ROLLBACK )r6   rQ   r   rV   rX   rS   r   r   r   rollback_all_ds   s    r[   c                  C   s   t  D ]} | t qdS )zmake_models hookN)r6   rQ   make_modelsr	   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&d' ZdS )(BaseDataDriver NrK   c                O   s   || _ || _d S r   )r   r;   )r   r?   r;   _args_kwargsr   r   r   __init__   s    zBaseDataDriver.__init__c                 O   s   d S r   r   r   modelargsr   r   r   r   r7      s    zBaseDataDriver.getc                 O   s   d S r   r   r   instancerd   r   r   r   r   create   s    zBaseDataDriver.createc                 O   s   d S r   r   re   r   r   r   delete   s    zBaseDataDriver.deletec                 O   s   d S r   r   re   r   r   r   update   s    zBaseDataDriver.updatec                 O   s   d S r   r   rb   r   r   r   r"      s    zBaseDataDriver.listc                 O   s   d S r   r   rb   r   r   r   count   s    zBaseDataDriver.countc                 C   s   d S r   r   r   r   r   r   rY      s    zBaseDataDriver.commitc                 C   s   d S r   r   rk   r   r   r   rX      s    zBaseDataDriver.rollbackc                 C   s   d S r   r   rk   r   r   r   rR      s    zBaseDataDriver.before_requestc                 C   s   d S r   r   rk   r   r   r   rU      s    z#BaseDataDriver.before_first_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   rl      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   rd   r   r   r   r   query_deprecated   s    zBaseDataDriver.query_deprecatedc                 C   s   t dS )u2   Создание/миграция схемы БД.NrF   rk   r   r   r   rE      s    zBaseDataDriver.init_dbc                 C   s   dS )u8   Закрываем текущие подключенияNr   rk   r   r   r   rA      s    z!BaseDataDriver.close_all_sessions)r-   r.   r/   __doc__ra   r7   rg   rh   ri   r"   rj   rY   rX   rR   rU   rm   rl   rn   r\   rp   rE   rA   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   rk   r   r   r   post_mapping_hook   s    zBaseMapper.post_mapping_hookNc                 C   s   t d S r   rq   )r   obj
cmf_entityrc   
model_namefull_fields_loadr   r   r   object_to_cmf   s    zBaseMapper.object_to_cmfc                 C   s   t d S r   rq   )r   rv   ru   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__rI   N)
startswithr#   rM   )r   field
field_namer   r   
<dictcomp>   s    z4BaseMapper.obj_from_result_query.<locals>.<dictcomp>ZCmfObjr{   r|   rI   )	_fieldsr   objectkeysr}   r#   rM   setattrrP   )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 )rc   rx   )ry   )r   ru   rx   rc   r   r   r   r       s     z*BaseMapper.list_to_cmf.<locals>.<listcomp>r   )r   Zlstrx   rc   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!   rs   
issubclassrL   )clsmapperr   r   r   
get_mapper   s    

zBaseMapper.get_mapper)NNNN)N)N)
r-   r.   r/   rt   ry   rz   r   r   classmethodr   r   r   r   r   rs      s   

rs   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dd ZdS )zSimpleMapper.SimpleModelc                 C   s@   t | dr&| j d| j d| j dS | j dt| dd  dS )Nr;   (z: )id)rW   
class_namecoder;   rP   rk   r   r   r   __repr__  s    
z!SimpleMapper.SimpleModel.__repr__N)r-   r.   r/   r   r   r   r   r   SimpleModel  s   r   VirtualInitDatar   rc   
field_listc                    s   t    g | _d S r   )r*   ra   _virtual_init_listrk   r2   r   r   ra   !  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   r7   rc   r   r   r   r   rP   _valuer   r   )r   Zcmf_instancesZ	init_dataZcmf_wrapper	field_clsZvirtual_fieldr   r   r   rt   &  s    

zSimpleMapper.post_mapping_hookNc              	   C   s  |s"|s|j dd }tt|}|s8t }|j|_ntd||g }|pP|jD ]|}|j	|}|sjqR|j
r|s~|jdkr|| qRt|tjtjfrt|| d}	|	dkrqR|	dkrd}
nF|o|	|}|rRt|| dddk	rR| j| |||d}
nqRnqRn(t|tjtjtjfr*qRnt||d}
|
dkrBqRt|tjrx| |
|od|	|tt|jd }
nLt|tjr|
r|
js|
jtjjd	}
nt|tjr|
rt |
}
t!|||
 qR|r| j"tj#|||d
 |S )u  
        отображение obj -> simple_model
        если cmf_entity не указан, то создадим новый на основе модели cmf_model или её имени model_name
        возвращаем simple_model
        rH   r   uI   Передан cmf_entity в SimpleMapper, вероятно это баг)defaultalways.N_sub__id)rx   tzinfo)r   rc   r   )$r   rM   rP   r	   r   r   r   rL   r   r7   virtual	load_modeappendr   CmfRelationCmfGenericRelationid_fieldnamery   r   
CmfM2MBaseCmfBackrefBaseCmfDateRangeCmfObjectListr   CmfDateTimer   replacer   timezoneutcCmfJsonujsonloadsr   r   r   )r   ru   rv   rc   rw   rx   Zvirtual_fieldsr   r   obj_related_idfield_valuesub_fflr   r   r   ry   9  sj    




 
zSimpleMapper.object_to_cmf)NNNN)r-   r.   r/   rr   dataclassesZ	dataclassr   r   r   ra   rt   ry   r0   r   r   r2   r   r     s   r   c                   @   s   e Zd ZdddZdd ZdS )r   Nc              	   C   s  |s6|s&|s|j dd }tt|}|dd}d}nd}|sFt|}|}|rT|}n
|j }|D ]}	|j|	 }
szqb|
jr|s|
j	dkrt||	}d|_
d|_qbt||	d}t|
tjr|dkrqb| ||o||	tt|
jd }t|
tjtjfrt||
 d}|dkrqb|dkr,d}n|o:||	}|rbt||	 d	d
d
krbt|
tjrr|dd n|
j}tt|d}|r| j| ||	||d}nd}nqbnqbnt|
tjtjtjfrqb|dkrqbt|
tjr|r|js|jtjjd}t|
tjr"|r"t |}t||	}|r>|jdkrjt!|t"t#t$tdt%fr`||_n
t&||_||_
qbd|_'|(  |S )u  
        отображение obj -> cmf_entity
        если cmf_entity не указан, то создадим новый на основе модели cmf_model или её имени model_name
        возвращаем ссылку на cmf_entity
        rH   r   T)emptyFr   N.r   r   r   ))r   rM   rP   r	   r   r   r   r7   r   r   r   Z_oldr   r   r   r   r   r   rc   ry   r   r   r   r   r   r   r   r   r   r   r   jsonr   r!   strr'   floatboolr   Zis_newZmark_exists_in_db)r   ru   rv   rc   rw   rx   Zcmf_is_existsr   r   kr   r~   r   r   r   Z	model_subZ	field_objr   r   r   ry     s    




  


 



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| }|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CmfGenericBackrefrP   r!   CmfTyper   r   Z	db_formatr<   r   )r   rv   ru   rc   r   vZvvr   r   r   rz     s2    
zMapper.cmf_to_object)NNNN)r-   r.   r/   ry   rz   r   r   r   r   r     s   
gr   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   rI   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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dd	ddZddddd Zdd!d"d#ZdS )&DataProvideruV   Объект, связывающий модель с источником данныхz"\b(?P<table>\w+)\.(?P<field>\w+)\bNc                 C   s   || _ || _d | _t| _d S r   )rc   data_source_ddr   Z
mapper_cls)r   r   rc   r   r   r   ra   "  s    zDataProvider.__init__c                 C   s   | j st| j| _ | j S r   )r   r9   r   rk   r   r   r   data_driver(  s    zDataProvider.data_driverF)no_cacheTECHCOM_nocache
for_updatec          	      O   sP  |rt d| jjp|}| | j||d< tjjj| jj df||}|s^|s^tjj	 rdd}ntjj
|}t  |dkrt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j
| jf|d	|i|}| jjd
k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filterz.getNEmptyzDP: get() cache Empty zDP: get() cache zDP: get() NOcache r   rdiskorder_bygroup_byquery_params)r<   rc   r   _get_filtercmfapp	CMF_CACHEhashr-   cache_is_lockedr7   r   print_debugDEBUGr   r;   add_query_params)	r   r   r   r   rd   r   keycachedb_resr   r   r   r7   .  s4        zDataProvider.getc                 O   s\   t d | jj|f||}| jjdkr,|S |d krHtjj|d d S tjj|d |S )Ninsertr   rg   )r   r   rg   r;   r   r   r   
invalidate)r   rf   rd   r   r   r   r   r   rg   T  s    zDataProvider.create)r   c                O   s   t d | jj|f||}|r(td| jj}| jjdkr@|S |s|ddrd}d|jkrt|j	j
rt|j	rpdnd}tjj|| |S )	Nri   r   r   r   Tcmf_deletedrh   rg   )r   r   ri   r<   rc   r   r;   r7   r   r   Z
is_changedr   r   r   r   )r   rf   r   rd   r   r   r   r   r   r   ri   d  s    zDataProvider.updatec                 O   s   | j j||}|S r   )r   rY   )r   rd   r   retr   r   r   rY   v  s    zDataProvider.commitc                 O   s   | j j||S r   )r   rX   ro   r   r   r   rX   {  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   rh   )r   rh   r;   r   r   r   r   )r   rd   r   r   r   r   r   rh   ~  s
    zDataProvider.deletec                    s   | dg }|dkrg }t|tr,t|}|r6|g}|  D ]:\}}||jkrB||= t|tjrl|j	}|
|d|g qB fdd  |}|S )u   
        Преобразуем обычные kwargs в продвинутый фильтр для однообразной логики фильтрования
        :param model:
        :param kwargs:
        :return:
        r   N==c                    s   t | tr fdd| D S t | tr| dkr8tjjjS | dkrdtjsNdt_nttjdt_t	 S | dkrtjszdt_nttjdt_t
 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__G_CURRENT_USERZ__G_NOWi,  Z__G_DATEip  )r!   r"   r   r   Zcurrent_userr   r   Zjscache_timelifeminZnowr   )r   r   r   r   r     s     


z;DataProvider._get_filter.<locals>._recursive_params_replace)r7   r!   r   r   r   copyr=   r   r   r   r   )r   rc   r   Zsmart_filterr   r   r   r   r   r     s     


zDataProvider._get_filterANDc                 C   s^  t g g g g g d}|rZ|D ]>}|dkr(q|dr>|d d }|d |j d|  q|r|D ]4}|dr||d d }|d |j d|  qb|s|S t|d tr|D ]0}	| j||	|d D ]\}
}||
 | qqnr|d d	kr4| j||d
d  |d d D ]\}
}||
 | qn&|d dkrt	|dks^|d
 dkrft
d|d D ]F}|dkrqn|dr|d d }|d |j d|  qnnt	|dkrLd }|d d}|d
 d}d }d }|d dkr|S |d |jkrH|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r|d d }d}|r|dr|d d }d}|rZ|s|dkr|dkr|d }t|ts|g}g }|D ]@}tt|tjr,|j}tt|trD|jj}|| q|dkrj|d | |dkr|d | |dkr|d | t|tjr|jdkr|j|jd d p|}t|tjr0|dkr0| D ]>}|s|d |j  |r|d |j d|  q|d |j d|  nt
d| |S )N)r	   r   parentscache_clusterslistsr   Z_idr   .r   )parent_oper)r   ORrI   r      )=r   ut   Операция order_by в фильтре должна быть в формате: ["order_by", "=", [поля..]]r
   r   FT)r   r   INr   parentr   Zcache_clusterr   r   r	   u-   Неверный формат фильтра )r   endswithr   r   r!   r"   r   r=   extendlenr<   rM   r   r   r   r   r   r   r   ZCmfTUUIDr7   Z
CmfRelBaseZrelated_models)r   rc   Z
obj_filterZobj_order_byZobj_group_byr   r   r   r   Zfilt_lsr   r$   r~   Zobj_filter0Zobj_filter1Zfield__field_namer   ZoperZfield_is_tuuidZrule_values_dirtyZrule_valuesrvZrmodelr   r   r   r     s    

(
"




zDataProvider._query_paramsc          
      O   sZ  |rt d| jjp|}t  | | j||d< tjjj| jj	 df||}|sd|sdtjj
 rjd}ntjj|}|dkrt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|  | jj| jf|d	|i|}| jjd
kr|S |sR| | j|d |d|d}	tjjj||| jj	 |	d |S dS )u   
        Пробросили сюда relation_load и relation_load_only для реализации join и подселектов в будущем
        :param args:
        :param kwargs:
        :return:
        r   r   z.listNr   zlist() From cache  Empty zlist() From cache zDP: list() From NOcache r   r   r   r   r   )r<   rc   r   r   r   r   r   r   r   r-   r   r7   r   r   r   r"   r;   r   r   )
r   r   r   r   rd   r   r   r   r   r   r   r   r   r"   2  s.     "zDataProvider.list)r   r   c          	      O   s*  |rt d| jjp|}t  | | j||d< tjjj| jj	 df||}|s`tjj
 rfd }ntjj|}|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   zcount() From cache Empty z$BUG: count() cache can not be empty!zcount() From cache r   r   r   )r<   rc   r   r   r   r   r   r   r   r-   r   r7   r   r   rL   r   rj   r   r   )	r   r   r   rd   r   r   r   r   r   r   r   r   rj   W  s*     
"zDataProvider.count)r   c                O   s   t | jj||| j| j|dS N)rT   rc   r   )
QueryProxyr   queryrc   )r   r   rd   r   r   r   r   rp   p  s       zDataProvider.query_deprecated)NN)NNr   )r-   r.   r/   rr   recompileZTABLE_FIELD_REra   propertyr   r7   rg   ri   rY   rX   rh   r   r   r"   rj   rp   r   r   r   r   r     s    


&5
q%r   c                   @   sf   e Zd ZdZ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edd Zdd ZdS )r  u   
    Оборачиваем кастомный запрос и добавляем возможность извлекать данные с автомаппингом.
    TODO: Проверить слайсы query[a:b]
    Nc                 C   s0   || _ || _|| _t|t | _t|| _d S r   )_queryr   rc   r!   rs   _mapper_is_myr   _mapper)r   r  rT   rc   r   r   r   r   ra   z  s
    zQueryProxy.__init__c                    s    fdd}|S )u   Обёртка для методов, которые возвращают новый запрос на основании текущего.c                     s(   t j | |}t|jjjdS r  )rP   r	  r  r   rc   r  )rd   r   Z	new_queryitemr   r   r   method_proxy  s    z,QueryProxy.__getattr__.<locals>.method_proxyr   )r   r  r  r   r  r   __getattr__  s    zQueryProxy.__getattr__c                 C   s2   | j r.| j |r.| jj|| j t|d}|S )u6   Автоконвертация объектов в CMF)rc   )r   rn   r  ry   rl   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   )r  )r   colrk   r   r   	<genexpr>  s     z&QueryProxy._map_row.<locals>.<genexpr>)r!   tupler  )r   rowr   rk   r   _map_row  s    
zQueryProxy._map_rowc                    s   t  j}tjjd| }tjj r.d}ntjj|}t  |dkrht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   )r  )r   r  rk   r   r   r      s     z"QueryProxy.all.<locals>.<listcomp>)r5   r	  r   r   r   r   r   r7   r   r   r   r   rc   r-   r
  r  rt   r   sqlr   r   r   r   rk   r   all  s$    

zQueryProxy.allc                 C   s   t | j}tjjd| }tjj r.d}ntjj|}t  |dkrht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 )r5   r	  r   r   r   r   r   r7   r   r   r   firstr  r   rc   r-   r
  r  rt   )r   r  r   r   r  r   r   r   r   r    s&    



zQueryProxy.firstc                 C   s   t   t| j}tjjd| }tjj r4d }ntjj|}t   |dkrnt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   r5   r	  r   r   r   r   r   r7   r   r   rj   r   rc   r-   r  r   r   r   rj     s"    

zQueryProxy.countc                 O   s   | j j||}|S r   )r	  rh   )r   rd   r   r   r   r   r   rh     s    zQueryProxy.deletec                 C   s   | j S r   )r	  rk   r   r   r   dd_query  s    zQueryProxy.dd_queryc                 C   s   t |  S )u+   Чтение строк из запроса)iterr  rk   r   r   r   __iter__  s    zQueryProxy.__iter__)NNN)r-   r.   r/   rr   ra   r  r  r  r  r  rj   rh   r  r  r  r   r   r   r   r  u  s   

r  )N)N)N)r   )*r   rN   r   r   r  collectionsr   r   r   r   typingr   r   Zflaskr   Zcmf.appr   r   Zcmf.includer   r	   Zmodels.base_modelr   r6   r5   r9   r@   rC   rE   r>   rR   rU   rZ   r[   r\   r]   rs   r   r   r   r   r  r   r   r   r   <module>   sF   
+

<7t 
  Y