U
    d                     @   sX  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 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   )	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)r3   r2   r   r   r0   r   render_query   s    	

r4   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)	r5   	Exceptionr   Zdata_sourcesitemsr6   Zsqlalchemy.poolr:   new_dd)Z
queue_poolr8   	ds_configr:   r   r   r   init_dsH   s    r@   c                  C   s*   t  D ]} t |    t | = qt  dS )u8   
    Отключаем все соединения
    N)r5   copyclose_all_sessionsr@   r7   r   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)r5   r=   printinit_dbNotImplementedError)r8   Zds_ddr   r   r   rE   b   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;   )r6   
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>   m   s    



r>   c                  C   s   t  D ]} |   qd S r   )r5   valuesbefore_requestddr   r   r   rR   |   s    rR   c                  C   s   t  D ]} |   qd S r   )r5   rQ   before_first_requestrS   r   r   r   rU      s    rU   c                 C   sV   t  D ]H}| r.ttdr$td |  qttdrHt| d |  qd S )NdebugZROLLBACKz COMMIT)r5   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 )r5   rQ   r   rV   rX   rS   r   r   r   rollback_all_ds   s    r[   c                  C   s(   ddl m}  t D ]}||  qdS )zmake_models hookr   modelsN)cmf.includer]   r5   rQ   make_models)r]   rT   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   r6      s    zBaseDataDriver.getc                 O   s   d S r   r   r   instancerg   r   r   r   r   create   s    zBaseDataDriver.createc                 O   s   d S r   r   rh   r   r   r   delete   s    zBaseDataDriver.deletec                 O   s   d S r   r   rh   r   r   r   update   s    zBaseDataDriver.updatec                 O   s   d S r   r   re   r   r   r   r!      s    zBaseDataDriver.listc                 O   s   d S r   r   re   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   rn   r   r   r   rX      s    zBaseDataDriver.rollbackc                 C   s   d S r   r   rn   r   r   r   rR      s    zBaseDataDriver.before_requestc                 C   s   d S r   r   rn   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   ro      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   rg   r   r   r   r   query_deprecated   s    zBaseDataDriver.query_deprecatedc                 C   s   t dS )u2   Создание/миграция схемы БД.NrF   rn   r   r   r   rE      s    zBaseDataDriver.init_dbc                 C   s   dS )u8   Закрываем текущие подключенияNr   rn   r   r   r   rB      s    z!BaseDataDriver.close_all_sessions)r,   r-   r.   __doc__rd   r6   rj   rk   rl   r!   rm   rY   rX   rR   rU   rp   ro   rq   r_   rs   rE   rB   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   rn   r   r   r   post_mapping_hook   s    zBaseMapper.post_mapping_hookNc                 C   s   t d S r   rt   )r   obj
cmf_entityrf   
model_namefull_fields_loadr   r   r   object_to_cmf   s    zBaseMapper.object_to_cmfc                 C   s   t d S r   rt   )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__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 )rf   r{   )r|   )r   rx   r{   rf   r   r   r   r      s     z*BaseMapper.list_to_cmf.<locals>.<listcomp>r   )r   Zlstr{   rf   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   
issubclassrL   )clsmapperr   r   r   
get_mapper  s    

zBaseMapper.get_mapper)NNNN)N)N)
r,   r-   r.   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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   rn   r   r   r   __repr__  s    
z!SimpleMapper.SimpleModel.__repr__N)r,   r-   r.   r   r   r   r   r   SimpleModel  s   r   VirtualInitDatar   rf   
field_listc                    s   t    g | _d S r   )r)   rd   _virtual_init_listrn   r1   r   r   rd   %  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   r6   rf   r   r   r   r   rP   _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 ]|}|j	
|}	|	svq^|	jr|s|	jdkr||	 q^t|	t	jt	jfrt||	 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r6q^nt||d}|dkrNq^t|	t	jr| ||op|
|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\   rH   uI   Передан cmf_entity в SimpleMapper, вероятно это баг)defaultalways.N_sub__id)r{   tzinfo)r   rf   r   )%r^   r]   r   rM   rP   r   r   r   rL   r   r6   virtual	load_modeappendr   CmfRelationCmfGenericRelationid_fieldnamer|   r   
CmfM2MBaseCmfBackrefBaseCmfDateRangeCmfObjectListr   CmfDateTimer   replacer   timezoneutcCmfJsonujsonloadsr   r   r   )r   rx   ry   rf   rz   r{   r]   Zvirtual_fieldsr   r   obj_related_idfield_valuesub_fflr   r   r   r|   =  sl    




 
zSimpleMapper.object_to_cmf)NNNN)r,   r-   r.   ru   dataclassesZ	dataclassr   r   r   rd   rw   r|   r/   r   r   r1   r   r     s   r   c                   @   s   e Zd ZdddZdd ZdS )r   Nc              	   C   s  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||
d	}t|tjr|d	krqn| ||o||
t||jd }t|tjtjfrt|| d	}|d	kr(qn|dkr8d}n|oF||
}|rnt||
 d
ddkrnt|tjr~|dd n|j}t||d}|r| j| ||
||d}nd}nqnnqnnt|tjtjtjfrqn|d	krqnt|tjr|r|js|jtjjd}t|tjr.|r.t !|}t||
}|rJ|jd	krvt"|t#t$t%tdt&frl||_n
t'||_||_qnd|_(|)  |S )u  
        отображение obj -> cmf_entity
        если cmf_entity не указан, то создадим новый на основе модели cmf_model или её имени model_name
        возвращаем ссылку на cmf_entity
        r   r\   rH   T)emptyFr   N.r   r   r   )*r^   r]   r   rM   rP   r   r   r   r6   r   r   r   Z_oldr   r   r   r   r   r   rf   r|   r   r   r   r   r   r   r   r   r   r   r   jsonr   r    strr&   floatboolr   Zis_newZmark_exists_in_db)r   rx   ry   rf   rz   r{   r]   Zcmf_is_existsr   r   kr   r   r   r   r   Z	model_subZ	field_objr   r   r   r|     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   ry   rx   rf   r   vZvvr   r   r   r}     s2    
zMapper.cmf_to_object)NNNN)r,   r-   r.   r|   r}   r   r   r   r   r     s   
ir   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   )rf   data_source_ddr   Z
mapper_cls)r   r   rf   r   r   r   rd   *  s    zDataProvider.__init__c                 C   s   | j st| j| _ | j S r   )r   r9   r   rn   r   r   r   data_driver0  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<   rf   r   _get_filtercmfapp	CMF_CACHEhashr,   cache_is_lockedr6   r   print_debugDEBUGr   r;   add_query_params)	r   r   r   r   rg   r   keycachedb_resr   r   r   r6   6  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   rj   )r   r   rj   r;   r   r   r   
invalidate)r   ri   rg   r   r   r   r   r   rj   \  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 )	Nrl   r   r   r   Tcmf_deletedrk   rj   )r   r   rl   r<   rf   r   r;   r6   r   r   Z
is_changedr   r   r   r   )r   ri   r   rg   r   r   r   r   r   r   rl   l  s    zDataProvider.updatec                 O   s   | j j||}|S r   )r   rY   )r   rg   r   retr   r   r   rY   ~  s    zDataProvider.commitc                 O   s   | j j||S r   )r   rX   rr   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   rk   )r   rk   r;   r   r   r   r   )r   rg   r   r   r   r   r   rk     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)r6   r    r   r   r   rA   r=   r   r   r   r   )r   rf   r   Zsmart_filterr   r   r   r   r   r     s     


zDataProvider._get_filterANDc                 C   sp  ddl m} tg g g g g d}|rf|D ]>}|dkr4q&|drJ|d d }|d |j d|  q&|r|D ]4}	|	dr|	d d }	|d |j d|	  qn|s|S t|d tr|D ]0}
| j||
|d		 D ]\}}|| 
| qqnx|d d
kr@| j||dd  |d d		 D ]\}}|| 
| q"n,|d dkrt|dksj|d dkrrtd|d D ]F}|dkrqz|dr|d d }|d |j d|  qznt|dkrXd }|d d}|d d}d }d }|d dkr|S |d |jkrT|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}|rl|s|dkr|dkr|d }t|ts|g}g }|D ]@}tt|tjr8|j}tt|trP|jj}|| q|dkrv|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r<|dkr<| D ]>}|s|d |j  |r|d |j d|  q|d |j d|  n|d| ddd |S )Nr   )	cmf_alert)r]   r   parentscache_clusterslistsr   Z_idr   .)parent_oper)r   ORrI   r      )=r   ut   Операция order_by в фильтре должна быть в формате: ["order_by", "=", [поля..]]r	   r   FT)r   r   INr   parentr   Zcache_clusterr   r   r]   uP   Ошибка  при выполнении UBQL - неверный запрос. uM    Проверьте правильность введенных данных.)abort)r^   r   r   endswithr   r   r    r!   r   r=   extendlenr<   rM   r   r   r   r   r   r
   r   ZCmfTUUIDr6   Z
CmfRelBaseZrelated_models)r   rf   Z
obj_filterZobj_order_byZobj_group_byr   r   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<   rf   r   r   r   r   r   r   r   r,   r   r6   r   r   r   r!   r;   r   r   )
r   r   r   r   rg   r   r   r   r   r   r   r   r   r!   ;  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<   rf   r   r   r   r   r   r   r   r,   r   r6   r   r   rL   r   rm   r   r   )	r   r   r   rg   r   r   r   r   r   r   r   r   rm   `  s*     
"zDataProvider.count)r   c                O   s   t | jj||| j| j|dS N)rT   rf   r   )
QueryProxyr   queryrf   )r   r   rg   r   r   r   r   rs   y  s       zDataProvider.query_deprecated)NN)NNr   )r,   r-   r.   ru   recompileZTABLE_FIELD_RErd   propertyr   r6   rj   rl   rY   rX   rk   r   r   r!   rm   rs   r   r   r   r   r   &  s    


&5
r%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   rf   r    rv   _mapper_is_myr   _mapper)r   r	  rT   rf   r   r   r   r   rd     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   rf   r  )rg   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)rf   )r   rq   r  r|   ro   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   colrn   r   r   	<genexpr>  s     z&QueryProxy._map_row.<locals>.<genexpr>)r    tupler  )r   rowr   rn   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  rn   r   r   r     s     z"QueryProxy.all.<locals>.<listcomp>)r4   r  r   r   r   r   r   r6   r   r   r   r   rf   r,   r  r  rw   r   sqlr   r   r   r   rn   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 )r4   r  r   r   r   r   r   r6   r   r   r   firstr  r   rf   r,   r  r  rw   )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   r4   r  r   r   r   r   r   r6   r   r   rm   r   rf   r,   r  r   r   r   rm     s"    

zQueryProxy.countc                 O   s   | j j||}|S r   )r  rk   )r   rg   r   r   r   r   r   rk     s    zQueryProxy.deletec                 C   s   | j S r   )r  rn   r   r   r   dd_query  s    zQueryProxy.dd_queryc                 C   s   t |  S )u+   Чтение строк из запроса)iterr  rn   r   r   r   __iter__  s    zQueryProxy.__iter__)NNN)r,   r-   r.   ru   rd   r  r  r  r  r  rm   rk   r  r  r   r   r   r   r   r  ~  s   

r  )N)N)N)r   ))r   rN   r   r   r
  collectionsr   r   rA   r   typingr   r   Zflaskr   Zcmf.appr   r   r^   r   Zmodels.base_modelr
   r5   r4   r9   r@   rC   rE   r>   rR   rU   rZ   r[   r_   r`   rv   r   r   r   r   r  r   r   r   r   <module>   sF   
+


<7v 	
  Z