
    ;i)                       d dl Z d dlZd dlmZmZ d dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlZd dlZd dlZd dlZd dlmZ d dlmZmZmZ d d	lmZmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlm Z  d dl!m"Z"m#Z# d dl$m%Z% d dl&m'Z' ddl(m)Z)m*Z*m+Z+ ddl,m-Z-m.Z.m/Z/m0Z0 ddl1m2Z2m3Z3m4Z4m5Z5 ddl6m7Z7 ddl8m9Z9m:Z:m;Z; d dlmZm<Z<m=Z=  G d de2      Z> G d d      Z?y)    N)defaultdict
namedtuple)copy)List)OrderedDict)	timedelta)IntegrityError)
ForeignKeyfuncinspect)jsong)Config)command)UNIQUE_VIOLATION)errors)close_all_sessions)
CmfRelBaseCmfType)fields)models   )CmfOrmErrorCmfOrmUniqueErrorCmfOrmIntegrityError)BaseModelMetaDEFAULT_DATASOURCE	BaseModelCmfGM2MModel   )BaseDataDriver
BaseMapperMapperinc_select_count)imutable_deep_copy)cache_obj_lock_release_allemit_delayed_eventsmake_prof_point)r   DictAnyc                   &    e Zd ZdZi Z ej                         Zej                  j                  j                  ee      Z e       ZdZd Z fdZed        Zed        Zed        ZedJd	       ZdJd
Zd Zd Zd Zd Zd Zed        Zd Zd Zd Zd Z d Z!e"d        Z#e"d        Z$ e%dd      Z&dKdZ'e"dLde(e&   fd       Z)dJdZ*e"d         Z+ejX                  dddfd!Z-e"d"        Z.e"d#        Z/d$ Z0e"dMd%       Z1dJd&e&fd'Z2dddd(d)Z3ddddddddddd*
d+Z4ddd,d-Z5ddddddd.d/Z6dNd0Z7d1 Z8d2 Z9dd3d4Z:d5 Z;dNd6Z<ddd7d8e=fd9Z>d:d;d<Z?dd=d>Z@dd=d?ZA fd@ZBdA ZCdB ZDdC ZEdD ZFdOdEZGe fdF       ZHdG ZIdH ZJdI ZK xZLS )PSQLAlchemyDataDriveru  
    dataproviders['default'] = {
        'type': 'sqlalchemy',
        'sqlachemy.url': 'postgresql://user:password@host/db',
        'sqlachemy.echo': True,  # Достаточно для отладки запросов в develop mode
    }

    # Для отладки в продакшене логгеры:
    sqlalchemy.engine - controls SQL echoing. set to
        logging.INFO for SQL query output, logging.
        DEBUG for query + result set output.
        These settings are equivalent to echo=True and echo="debug" on create_engine.echo, respectively.
    sqlalchemy.pool - controls connection pool logging.
         set to logging.INFO to log connection invalidation and recycle events;
         set to logging.DEBUG to additionally log all pool checkins and checkouts.
         These settings are equivalent to pool_echo=True and pool_echo="debug" on create_engine.echo_pool, respectively.
    sqlalchemy.dialects - controls custom logging for SQL dialects, to the extend that logging
         is used within specific dialects, which is generally minimal.
    sqlalchemy.orm - controls logging of various ORM functions to the extent that logging
         is used within the ORM, which is generally minimal.
         Set to logging.INFO to log some top-level information on mapper configurations.

    Example:
        logging.basicConfig()
        logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
    )class_registrymetadataNc                 V    t         j                  j                  | j                        S )N)bind)
sqlalchemyormsessionmakerengineselfs    "./cmf/data_providers/sqlalchemy.py_session_factoryz%SQLAlchemyDataDriver._session_factoryF   s    ~~***<<    c                    t        |   |i | t        j                  | j                  fi |j                         D ci c]*  \  }}|j                  d      r|j                  ddd      |, c}}| _        t        j                  j                  | j                               | _        | j                          y c c}}w )Nzsqlalchemy. r    )super__init__r1   engine_from_configconfigitems
startswithreplacer4   r2   scoped_sessionr8   Session	init_meta)r6   argskwargskv	__class__s        r7   r=   zSQLAlchemyDataDriver.__init__e   s    $)&) 33KK
 #LLNAq<<. 		-Q/2
 "~~44T5J5J5LMs    /B=c                    g }|j                   j                         D ]  \  }}t        |t              r|j                  s|j
                  s1d |g}g }|j                  rt        |j                        }|j                  r|r|j
                  r d|vrt        d| d|j                   d      |D ]  }|dk(  r/|j                  t        j                  |d|j
                  i       7|dk(  r>|j                  t        j                  d|j                   d| d| |d	|d
i             z|j                  t        j                  d|j                   d| d| |||j
                                W|j                  t        j                  |d|j
                  i        t        |d      rN|j                  rB|j                  t        j                  d|j                   dg|j                  dddi       |S )Ndefaultu   В поле .uU    указана уникальность, но не указан индекс defaultuniquegin_trgmix__gingin_trgm_ops)postgresql_usingpostgresql_ops)rT   rN   orderno_partition_by_orderno_partition_by_clusterordernoF)r   r@   
issubclassr   indexrN   index_usinglistr   
class_nameappendr1   Index	tablenamehasattrrV   )cls	cmf_modelindexescmf_field_name	cmf_fieldrF   r[   idx_types           r7   __get_indexesz"SQLAlchemyDataDriver.__get_indexess   s!   )2)9)9)?)?)A #	M%NI)Z0OOy'7'7.)DK$$"9#8#89;##	(D%YKqAUAU@V  Wl  'm  n  n + H  9,z'7'7'WiFVFV'WX!Z/z'7'7!)"5"5!6a7Gq
S*-2"0.,	(    z'7'7!)"5"5!6a7Gq
S*-5#,#3#3	( ( NN:++TK):J:JKLG#	MN 945):X:XNN:++!)"5"5!66ST&;; & $)	  r9   c                 v    | j                   j                  |      }|r| j                   j                  |       |S N)cached_queriesgetmove_to_end)rb   keyrets      r7   	get_queryzSQLAlchemyDataDriver.get_query   s6     ""3'**3/
r9   c                 z   || j                   |<   | j                  sPt        j                  d      t        j                  d      z  dz  dz  }|dz  }|dz  }|dk  rd}|dkD  rd}|| _        t	        | j                         | j                  kD  r.| j                   j                  d      \  }}t        d	|        y y )
NSC_PAGE_SIZESC_PHYS_PAGESi   i         F)lastzDEV: set_query evicted key )rk   cached_queries_limitossysconflenpopitemprint)rb   queryrn   sys_memsize_mbchunk_countqueries_limitevicted_keyrQ   s           r7   	set_queryzSQLAlchemyDataDriver.set_query   s    "'3
 ''ZZ7"**_:UUX\\_ccN(C/K'",Mr! "s" #'4C$s!!"S%=%== //77U7CNK/}=> >r9   c                    |j                   }|j                  ryt        |t        j                        rt        j                         }nt        |t        j                        rt
        j                  }nUt        |t        j                        r,t        j                  |j                  |j                        }nt        |t        j                        r{|t        j                  |j                        g}|j                   r$|j#                  t%        |j                                t        j&                  ||j(                  |j*                  dS t        |t        j,                        rt        j.                         }nJt        |t        j0                        r!t        j                  |j                        }nt        |t        j2                        r!t        j4                  |j                        }nt        |t        j6                        ryt        |t        j8                        ryt        |t        j:                        ryt        |t        j<                        ryt        |t        j>                        ryt        |t        j@                        rt        jB                  d      }nt        |t        jD                        rt        jF                         }nt        |t        jH                        rt        j.                         }nt        |t        jJ                        ryt        |t        jL                        ryt        |t        jN                        rt
        jP                  }n\t        |t        jR                        rt
        jT                  }n1t        |t        jV                        r	ddl,m-} |}nt]        d|       t        j&                  |||j^                  |j*                  |j(                        S )	u0   Создадим SA поле для моделиN)primary_keynullableT)timezoner   )TSVECTORu"   Не найден тип поля )rL   r   r   )0r]   virtualrY   r   	CmfBigIntr1   BIGINTCmfIntInteger
CmfNumericNumeric	precisionscaleCmfTUUIDString
max_lengthforeign_keyr^   r
   Columnr   r   CmfTextTEXTCmfStrCmfBytesLargeBinaryCmfRelationCmfGenericRelationCmfGenericM2MCmfDateRangeCmfM2MCmfDateTime	TIMESTAMPCmfDateDATECmfJson
CmfBackrefCmfGenericBackrefCmfBoolBooleanCmfTimeTimeCmfTsVectorsqlalchemy.dialects.postgresqlr   	ExceptionrL   )rb   
_cmf_modelrf   _db_field_namecolumn_namesa_typerF   r   s           r7   _make_sa_columnz$SQLAlchemyDataDriver._make_sa_column   s     **i!1!12 '')G	6==1 ((G	6#4#45 (()<)<iooNG	6??3!2!293G3G!HID $$Jy'<'<=>$$9#8#89CUCU  	6>>2 oo'G	6==1 ''	(<(<=G	6??3 ,,Y-A-ABG	6#5#56 	6#<#<=	6#7#78	6#6#67	6==1	6#5#56 **D9G	6>>2 oo'G	6>>2 oo'G	6#4#45	6#;#;<	6>>2 ((G	6>>2 ooG
 	6#5#56?G @LMM  %%''!--
 	
r9   c                 R    t        | j                        j                  ||      }|S )N)schema)r   r4   get_columns)r6   
table_namer   columnss       r7   inspect_table_columnsz*SQLAlchemyDataDriver.inspect_table_columns  s%    $++&22:f2Mr9   c                     | j                  |      }| j                  j                  j                  | j                  |j                        S rj   )dp_modelr4   dialect	has_table	__table__)r6   rc   sa_models      r7   r   zSQLAlchemyDataDriver.has_table  s7    ==+{{"",,T[[(:L:LMMr9   c                    | j                  d |      j                  }t        |t        j                        r| d}t        d       | j                         }d| d| d| }|j                  s#|j                  d| | d|j                   d}t        d	       |j                  |       t        d
       |j                          t        d       y )NTZzadd_custom_column open sessionzalter table z add column IF NOT EXISTS  uH   Значение по умолчанию не может быть None: z	 default z	 NOT NULLzadd_custom_column run executezadd_custom_column run commitzadd_custom_column done)r   typerY   r   r   r|   rD   r   rL   executecommit)r6   r   r   cmf_field_typesa_column_typessqls          r7   add_custom_columnz&SQLAlchemyDataDriver.add_custom_column  s    --dNCHHnf&8&89 ./r2N./LLNZL(B;-qQ_P`a&&%%-`ao`pqqE>#9#9":)DC-.			#,-	
&'r9   c                 6   dddd}t        j                  t         j                  ddd      |d<   t        j                  t         j                  ddd      |d	<   t        j                  t         j                  d
d      |d<   t        j                  t         j                  dd      |d<   t	        |t
        f|      }ddl}t        j                  |j                  dd             | j                  |      rt        d| d       yddl}t        j                  |j                  dd             | j                  |      rt        d| d       yt        j                  j                  |j                  j                         }| j#                         }	 t        d       |j%                  |       t        d       |j'                          t        d       y# t(        $ r5}|j*                  j-                          t        d| d|        Y d}~yd}~ww xY w)u5   
        Создаем М2М таблицу
        Tcustom.r;   abstract
__module____qualname__u   ID Объекта)captionr   rZ   left_idu   ID Элементаright_id   Имя объекта)r   r   left_name_cacheu   Имя элементаright_name_cacher   Ng?g      ?u$   add_custom_m2m_model Таблица uT    уже создана в БД. Вероятно, на другом инстансеz!add_custom_m2m_model create tablezadd_custom_m2m_model run commitzadd_custom_m2m_model doneuB   add_custom_m2m_model Ошбика создания таблицы : )r   Fieldr   	CmfStr256r   r   randomtimesleepuniformr   r|   r1   r   CreateTabler   r   rD   r   r   r   transactionrollback)r6   
model_namerG   rc   r   smtpr   es           r7   add_custom_m2m_modelz)SQLAlchemyDataDriver.add_custom_m2m_model.  s    #)RP"LLBU`dlpqy#\\&//CXcgostz$*LL1A1AKbmq$r !%+\\&2B2BLept%u!"l_f=	 	

6>>#s+,>>)$8  DX  Y  Z 	

6>>#s+,>>)$8  DX  Y  Z  ,,Y-?-?-I-IJLLN	d56IIdO34HHJ-. 	dMM""$VW[V\\^_`^abcc	ds   AG 	H#+HHc           	         dddd}t        j                  t         j                  dddddd      |d	<   t        j                  t         j                  d
d      |d<   t        j                  t         j                  ddddd      |d<   t        j                  t         j
                  ddddd      |d<   t        j                  t         j
                  dddd      |d<   t        j                  t         j                  ddddd      |d<   t        j                  t         j
                  ddddd       |d<   t        |t        f|      }|S )NTr   r;   r   u)   Идентификатор объектаu3   Автоматически генерируетсяF)r   commentr   r   readonlyvisibleidr   )r   rZ   nameu   Сортировкаr   )r   rZ   r   r   rL   rX   u   Кодu3   Код в реальном мире из жизни)r   rN   r   r   r   codeu:   Код родителя в каскадном выборе)r   r   r   rZ   choice_parent_idu   Скрыть
cmf_hiddenu!   Конфигурация поляcust_field_conf_id)	r   r   r   r   r   CmfStr64r   r   r   )r6   r   rG   rc   s       r7   gen_custom_choice_modelz,SQLAlchemyDataDriver.gen_custom_choice_modelR  sI   ")RP||OO?I
t  +
v
 #LLMM*
y  OOI
v &,\\OOP&
!"  &||NN" 
| (.||OO7(
#$ i\6:	r9   c                 r   | j                  |      }t        j                  j                  |j                  j
                        }| j                         }	 |j                  |       |j                          y# t        $ r5}|j                  j                          t        d| d|        Y d}~yd}~ww xY w)ur   
        Создаем пользовательский справочник выбора таблицу
        u-   Ошбика создания таблицы r   N)r   r1   r   r   r   r   rD   r   r   r   r   r   r|   )r6   r   rc   r   r   r   s         r7   add_custom_choice_modelz,SQLAlchemyDataDriver.add_custom_choice_model  s     00<	  ,,Y-?-?-I-IJLLN	OIIdOHHJ 	OMM""$A$r!MNN	Os   !A8 8	B6+B11B6c                 @   |j                   }| j                  j                  |      }|s|j                  }g }g }ddi}|j                  j                         D ].  \  }}	|}
| j                  ||	|
      }||j                  |       0 |j                  | j                  |             |j                  |       |t        |      d}|j                  |D ci c]  }|j                  | c}       t        || j                  f|      }|| j                  |<   |S c c}w )u]   
        Вернём SA модель для CMF модели.
        TODO: db_name
        extend_existingT)__tablename____table_args__)__name__models_registryrl   r`   r   r@   r   r^   extend"_SQLAlchemyDataDriver__get_indexestupleupdater   r   sa_base_model)rb   rc   r   r   r`   
sa_columnsr   __table_kwargs__re   rf   sa_field_name	sa_columnsa_model_kwargscs                 r7   dp_model_clsz!SQLAlchemyDataDriver.dp_model_cls  s2    ''
&&**:6 "++IJN 148-6-=-=-C-C-E -)	 .//	9mT	$!!),- !!#"3"3I">?!!  "+"'"7O ""z#B!AFFAI#BCJ):):(<oNH.6C
+ $Cs   Dc                 $    | j                  |      S rj   )r  )r6   rc   s     r7   r   zSQLAlchemyDataDriver.dp_model  s      ++r9   c                 6    t        t        |j                        S )uG   
        Вернём CMF модель для SA модели.
        )getattrr   r   )r6   r   s     r7   rc   zSQLAlchemyDataDriver.cmf_model  s     vx0011r9   c                 6    t        |t        j                        S rj   )
isinstancer,   r   )r6   dp_instances     r7   is_instancez SQLAlchemyDataDriver.is_instance  s    +';'I'IJJr9   c                     i }|D ]9  }|j                   j                  ||j                   j                  j                  <   ; t        j                  j                  |d|      S )N
table_type)r   r   fullnamer1   r2   polymorphic_union)r6   
cmf_modelsaliastablesmodels        r7   _union_modelsz"SQLAlchemyDataDriver._union_models  sW     	QE8=8P8PF5>>++445	Q ~~//eLLr9   c	                     	 dfd	}	i }
|D ]9  }|j                   j                  |
|j                   j                  j                  <   ;  |	|
d      j                  |      S )Nc                 ^   t         j                  j                         }i i | D ]  }| |   }t        |t         j                  j
                        s	 |j                         }|| |<   i }|j                  D ]V  }r|j                  vr|j                  |j                         |||j                  <   |j                  |j                  <   X ||<    fd}	g }
| j                         D ]  \  }}||
j                  t         j                  j                  |D cg c]  } |	||       c}t         j                  j                  t         j                  j                  j                  |            j!                  |      gz   |g      j#                  t%        j                   d      |j                  j&                  k(        j)                  |             |
j                  t         j                  j                  |D cg c]  } |	||       c}|g      j#                  t%        j                   d      |j                  j&                  k(        j)                  |              t        j                  j*                  |
 j                  |      S c c}w c c}w )Nc                 t   	 |   |    S # t         $ r rPt        j                  j                  t        j                  j	                         |          j                  |       cY S t        j                  j                  t        j                  j	                         |          j                  |       cY S w xY wrj   )KeyErrorr1   r   castnulllabeltype_coerce)r   table
cast_nullscolnamemapstypess     r7   colzPSQLAlchemyDataDriver._union_models2.<locals>.hack_polymorphic_union.<locals>.col  s    j&u-d33 j!)~~22:>>3F3F3H%PT+V\\]abb)~~99*..:M:M:OQVW[Q\]ccdhii	js    AB7&AB76B7from_obj_id)r1   util
OrderedSetr  r   Selectr  r  rn   addr   r@   r^   selectliteral_column_quote_ddl_exprr  wherer  r   correlate_except	union_all)	table_maptypecolname	aliasnamer  colnamesrn   r  mr  r   resulttype_r   r  r  left_field_name
left_tablesub_ffls      `         @@r7   hack_polymorphic_unionzCSQLAlchemyDataDriver._union_models2.<locals>.hack_polymorphic_union  sV    "113HKE   '!#( eZ^^%:%:;t!KKME%*IcN *A155#7 LL' AaeeH#$66E!%%L* &'E"A 'Dj F ) 1 u*MM"--:BC$Su-C * = =$.NN$7$7$G$G$N!""'%"4 ',W .   %
8I6M NRWRYRYR\R\ \]--e4 MM"--:BC$Su-Cug . %
8I6M NRWRYRYR\R\ \]--e4	* >>++V4::9EE# D Ds   #J%J*r  )p_unionT)r   r   r  lateral)r6   r6  right_tabler  r5  right_modelmodels_is_unionr7  r8  	join_subqr2  s    `  `   `   r7   _union_models2z#SQLAlchemyDataDriver._union_models2  sb    HLJ	FZ 	 	LA78zz7K7KIajj**334	L%i>FFuMMr9   c                 t    d}| d   |v r| d   | d   | d   fS | d   |v r| d   | d   | d   fS t        d| |      )N)><==>=<==IN!=><<>NOT INLIKENOT LIKEILIKE	NOT ILIKEz
SIMILAR TOzNOT SIMILAR TOEXISTS
NOT EXISTS	MEMBER_OF@@HISTORYNOT HISTORYr   r    r   zInvalid filter operation)r   )paramsop_lists     r7   _parse_paramsz"SQLAlchemyDataDriver._parse_params/  se    + !9!9fQi22AY'!!9fQi228&'JJr9   c                    |dk(  rd }| dk(  r||kD  S | dk(  r||k\  S | dk(  r||k  S | dk(  r||k  S | dv r||k(  S | dv r||k7  S | dk(  r|j                  |      S | d	k(  r|j                  |      S | d
k(  r|j                  |      S | dk(  r|j                  |       S | dk(  r|j                  |      S | dk(  r|j                  |       S | dk(  r|j                  |      S | dk(  r|j                  |       S  |j                  |       |      S )NNULLrB  rE  rC  rF  )rD  rG  )rI  rJ  rK  rH  rS  rT  rL  rM  rN  rO  rP  )in_likeilikeop)operfieldvals      r7   _expressionz SQLAlchemyDataDriver._expression=  sB   &=C3;3;T\C<S[3;T\C<[ C<''C<T\99S>![ 99S>!T\99S>!XIIcN?"V^::c?"ZJJsO##W_;;s##[ KK$$$!588D>#&&r9   JoinDatazJleft_table, right_table, alias, left_field_name, right_model, right_modelsTc           
      8   |r|j                   }|j                  }n|j                  j                  |      }|s| j	                  ||       t        |t        j                  t        j                  f      rt        |t        j                        r&t        d|j                    d|j                    d      |j                    d}|r| d| n|}|j                         }	|	s,|r)t        d| d|j                    d|j                    d      y |	d	   }
t        |	      d
k(  r6t        j                  j                  |
j                  j                   |      }n.|| j#                  |d |||
|	d|      }n| j%                  |	|      }| j'                  |||||
|	      }|S )NuX   Недопустимый тип поля для вложенной фильтрации rM   up   . Вложенная фильтрация возможно только для CmfRelation и CmfGenericRelation_sub__uj   Не возможно построить запрос для вложенной фильтрации по u   , т.к. у поля u#    не указаны related_modelsr   r    )r   T)r>  r7  )r]   instance_classr   rl   _raise_invalid_fieldrY   r   r   CmfSubclassedGenericRelationr   related_modelsrz   r1   r2   aliasedr   r   r@  r  rd  )r6   r  r6  
field_name
from_aliasis_models_required	field_clsr7  
alias_partr=  r<  r;  	join_datas                r7   _calc_join_dataz$SQLAlchemyDataDriver._calc_join_datab  s   "--J,,E((4I))*e<i&*<*<f>W>W)XY!)V-P-PQ!notoo  oA  AB  CL  CW  CW  BX XF GH H ",,-T2
6@
|2j\2j
**,!! A  BL  AM M++0+;+;*<Ai>R>R=SSvxy y ajw<1$..001E1E1O1OV`0aK#--j$
JXcelw{  FM-  NK,,WjAKMM*k:zS^`gh	r9   Fjoinsc           	         |r
t               n_| j                  j                         D ch c]<  }t        |t        j
                  j                  j                        r|j                  > c}}|D ]y  }|j                  |v r| j                  |j                  t        |j                  j                  |j                   d      |j                  j                  j                   k(        } { | S c c}w )uP  
        TODO cmf_deleted
        Все данные для необходимых присоединений в joins, добавим недостающие присоединения в запрос.
        froms могут быть от филдов, при этом без джойна, чтобы принудительно создать join нужен force = True.
        Или более продвинутый способ определения наличия нужного джойна.
        Сейчас при построении основного запроса, джойны принудительно добавляются.
        А при расчёте фильтров, когда нет алиасов от полей, джойн делается только если нет нужного алиаса.
        r#  )set	statementlocate_all_fromsr  r1   r   
selectableAliasr   r  	outerjoinr;  r  r6  r  r5  r   )r}   rt  forcer  available_joinsrr  s         r7   _make_joinsz SQLAlchemyDataDriver._make_joins  s     $)#%99;/C%!:!:!@!@A JJ/C
  	rI/1OO%%	,,..93L3L2MS0QRV_VkVkVmVmVpVpprE		r /Cs   AC-c                    d }g }|d }|j                   j                  }n|j                  }|j                  d      D ]K  }| j	                  ||||      }|j                  |       |j                  }|j                  }|j                  }M |S )NrM   )	r   r   r   splitrs  r^   r  r<  r;  )r6   	join_pathr  r6  rn  rt  rm  rr  s           r7   _calc_joins_by_pathz(SQLAlchemyDataDriver._calc_joins_by_path  s    
J11J#J#//#. 	/J,,UJ
JWILL#"J))E"..J	/ r9   c                     t        |j                        j                  dd      }t        |  d|j                   d|       )N,z,
u+    не существует у модели u   , но есть: 
)strr   rB   r   r]   )rm  r  fields_s      r7   ri  z)SQLAlchemyDataDriver._raise_invalid_field  sV    ell#++C7ZL(STYTdTdSeex  zA  yB  C  D  	Dr9   c	                 &  ; |s|d fS t        |d   t              r?g }	|D ]1  }
| j                  |
||||||      \  }}|!|	j                  |       3 | ||	 fS |d   dk(  r| j                  |dd  ||||||      S |d   dk(  r*| j                  |dd  |||t        j
                  |||      S |d   dk(  r;t        |      dk7  s|d   d	vrt        d
      | j                  ||d   |      }|d fS | j                  |      \  }}}|j                  d      }|j                  j                  |d         }d}t        |      dkD  rpt        |t        j                  t        j                  t        j                   f      r7|d   }dj#                  |dd        ||g}d}||j$                  j&                  }nt        |      dkD  rv|j)                  d      \  }}}| j+                  |||      }| j-                  ||      }|d   }|j.                  }|j                  j                  |      }|j0                  }d}n||j$                  j&                  }|dk(  r |dk(  r|j                  j                  d      }|st        d| d|j2                         || j5                  ||       ;fd; ;|      }t        |t        j                        r|dv r.t        |t              st        |t6              st        d|||      |d	v r|t        d|||      |dv rddlm} | j=                  |d||      }|t        d| d       |j>                  rG|j@                  r:|jB                  r-|jE                         }| j%                  |      }|j&                  }|jF                  r|jH                  }|jJ                  }n2|jL                  r|jJ                  }|jH                  }nt        d!||      | j%                  tN        jP                        }|j&                  }g }|j@                  D ]i  } | j                  d      \  }!}"|j                  t	        jR                  |jT                  jV                  |"k(  |jT                  jX                  |!k(               k t	        j
                  | }|jZ                  j]                  |      }#|#j_                  |t	        jR                  ||jT                  j`                  k(  |            }#|d	v r'|#jc                  ||k(        je                         }#||# fS |#jc                  ||k(  t	        j
                  | jg                  d"||      | jg                  d"|jT                  jh                  |                  je                         }#n#|j@                  r(| j%                  tN        jP                        }$|d	v rb|jZ                  j]                  |$      jc                  |$j`                  |k(  |$jV                  |j2                  k(        je                         }#||# fS |jj                  s{|jZ                  j]                  |$      jc                  |$j`                  |k(  |$jV                  |j2                  k(  | jg                  d"|$jh                  |            je                         }#n
t        jl                  jo                  t        jp                  js                  |$j`                  g|$g#      ju                  |$j`                        jw                  | jg                  d"|$jh                  |            jw                  |$jV                  |j2                  k(              }#|j_                  |#t        |#jT                        d   |k(        }||d"k(  rt        |#jT                        d   d k7  fS t        |#jT                        d   d k(  fS |jE                         }$| j%                  |$      }%|jF                  r|%jH                  }&|%jJ                  }'n2|jL                  r|%jJ                  }&|%jH                  }'nt        d!||      |d	v r@|jZ                  j]                  |%      jc                  |&|k(        je                         }#||# fS |jx                  sN|jZ                  j]                  |%      jc                  |&|k(  | jg                  d"|'|            je                         }#nt        jl                  jo                  t        jp                  js                  |&g|%g#      ju                  |&      jw                  | jg                  d"|'|                  }#|j_                  |#t        |#jT                        d   |k(        }||d"k(  rt        |#jT                        d   d k7  fS t        |#jT                        d   d k(  fS ||d"k(  r|#fS |# fS |d$v r| j=                  |d||      }(|(t        d| d%      | j{                  | d d d |&      })|)j.                  }*|)j0                  }+|jZ                  j]                  |+jT                  j|                        },ddlm} |j>                  r|j@                  r|jB                  r|jE                         }| j%                  |      }|j&                  }|jF                  r|jH                  }|jJ                  }n2|jL                  r|jJ                  }|jH                  }nt        d!||      | j%                  tN        jP                        }-|-j&                  }.|,j_                  |.|.jT                  jh                  |+jT                  j|                  k(        },g }|j@                  D ]i  } | j                  d      \  }!}"|j                  t	        jR                  |.jT                  jV                  |"k(  |.jT                  jX                  |!k(               k t	        j
                  | }|,j#                  |t	        j
                  ||+jT                  j|                  k(  t	        jR                  ||.jT                  j`                  k(  |                  },|,jc                  ||(k(        },n8|j@                  r| j%                  tN        jP                        }-|-j&                  }.|,j#                  |.|-jh                  |+jT                  j|                  k(        },|,jc                  |-j`                  |(k(  |-jV                  |j2                  k(        },n|jL                  rd'}/d(}0nd(}/d'}0|jE                         }$| j%                  |$      }-|-j&                  }.t        |-|/      }1t        |-|0      }2|,j#                  |.|2|+jT                  j|                  k(        },|,jc                  |1|(k(        },t        |+jT                  d)      r|sg d*}3ng }3t        |+jT                  d+      r|s|3g d,g}3|r|3|g}3| j                  |3|*|*j$                  |,|+||      \  },}3|,jc                  |3      },|,je                         },|j                  d-      r|, },||,fS t        d.|||      t        |t        j                  t        j                   f      rI|dv r|j                  d-      rd/nd}dd"|g}|d$vrt        d0|||      | j=                  |d||      }(|(t        d| d1      | j{                  | d d d |&      }4|4j.                  }5|4j0                  }6|j                   d2}7t        |6jT                  |7      }8|jZ                  j]                  |8      },|7d3|(g}3t        |6jT                  d)      r|3g d*g}3|r|3|g}3| j                  |3|5|5j$                  |,|6||      \  },}3|,jc                  |3      },|,je                         },|j                  d-      r|, },||,fS t        |t        j                        r~| d2}|d4k(  rs| j{                  | d d d |&      })|)j.                  }*|)j0                  }+|jZ                  j]                  |+jT                  j|                        },| j%                  tN        jP                        }-|-j&                  }.|,j#                  |.|-jh                  |+jT                  j|                  k(        },|,jc                  t	        j
                  | jg                  d"|-j`                  |      | jg                  d"|-j                  |            |-jV                  d5k(        },| j=                  ||||      }|t	        j
                  | jg                  d"||      | jg                  d"||,            fS |d6v rJt        |t        j                        rt        d7      tN        j                  }*|*j$                  j&                  }+| j=                  |j&                  d||      }(|(t        d|+ d%      |jZ                  j]                  |+jT                  j|                        },d8}0| j%                  |*      }9t        |9|0      }2|,jc                  |2|(k(        },|d9d3|j2                  gg}3| j                  |3|*|*j$                  |,|+:      \  },}3|,jc                  |3      },|,je                         },|j                  d-      r|, },||,fS |dk(  r_tN        j                  j                  |j2                  ||ddd;g<      }:|:sd=g}:| j=                  |d||      }|| jg                  d"||:      fS | j=                  ||||      }|t        d| d>| d?      || jg                  |||      fS )@Nr   )field_tableinclude_deletedinclude_dummyANDr    OR)cmdr  r  r  order_by   )rG  rD  ut   Операция order_by в фильтре должна быть в формате: ["order_by", "=", [поля..]]r   r  rM   FrQ  )r6  TANYrT  r   u	   Поле u    не найдено у c                 x   ddl m}m} t        | t              r-| j
                  du r ||j                  d       | j                  } t        | t        t        f      r| D cg c]
  } |       } }| S t        | t              r| j                  j                  } | S t        | t              r	d| v r| d   } | S c c}w )Nr   print_debugr?   .u<   collect_filter_exp: Значение не загруженоr   )cmf.includer  r?   r  r   _valueDEBUGvaluer\   r   r   r   dict)right_r  r?   sub_rnormalize_rights       r7   r  z@SQLAlchemyDataDriver.collect_filter_exp.<locals>.normalize_right  s    7&'*==C'0ln
 &4-0>DEU/%0EE M FI.
 M FD)dfnM Fs   !B7)rH  rL  u   Правое значение для IN, NOT IN для m2m должно быть list, т.е. в квадратных скобках, например "field", "IN", "[obj.id]"u   Недопустимая операция над m2m полем (сравнение = только на None), допустимые IN, NOT IN, = None)rH  rL  rG  rD  r?   
with_aliasu   В таблице u3    нет поля id для фильтрации m2muD   Надо указать для поля либо left либо rightrH  r!  )rQ  rR  uG    нет поля id для фильтрации в подзапросе)rp  r   r   cmf_deletedr  rD  Fis_dummyr  rD  FzNOT uh   Недопустимая операция над m2m полем, допустимые IN, NOT IN, = NonerR  ul   Недопустимая операция над backref полем, допустимые EXISTS, NOT EXISTSu7    нет поля id для фильтрации backrefr#  rD  rS  
rg_members)rU  rV  uA   History для м2м полей не поддерживаетсяobj_idrm  )r  '  )r   rm  search_queryonly_idssliceNOTFOUNDu    нет поля u    для фильтрации)Ir  r\   collect_filter_expr^   r1   or_rz   r   order_queryrY  r  r   rl   rY   
CmfM2MBaser   r   joinr   r   
rpartitionr  r~  r<  r;  r]   ri  r   r  r?   _query_columnRELATION_CACHE_EDGE_OPTIMIZEnested_fieldsnested_fields_is_edge_parentm2m_model_clsrightr   r   leftr   RelationCacheand_r  parent_fieldparent_modelsessionr}   r{  	parent_idfilterexistsrc  child_idORM_RELCACHE_EXISTS_VIA_JOINr2   rl  r   r(  distinctr+  ORM_M2M_EXISTS_VIA_JOINrs  r   r  ra   rA   backrefCmfRelationBaseparent_coder   CmfOrmColumnHistoryCmfFullSearchfulltext_search)<r6   	in_filterr  r   r}   r  r  r  r  
filter_resrI   expr`  r  r  
left_partsrp  r  r  rQ   rt  rr  r?   field_columnm2m_link_modeldp_m2m_link_modelm2m_link_tabledp_m2m_link_field_selfdp_m2m_link_field_theirrelcache_modelrelcache_table	nf_filternfnf_modelnf_fieldm2m_subquery	m2m_modeldp_m2m_modeldp_m2m_field_selfdp_m2m_field_theirself_columnsub_data	sub_model	sub_table	sub_querym2m_sa_model	m2m_tablemy_id_field_namesub_id_field_namemy_sa_fieldsub_sa_fieldsub_filter_expbackref_databackref_modelbackref_tablebackref_column_namebackref_columnsub_sa_model	found_idsr  s<                                                              @r7   r  z'SQLAlchemyDataDriver.collect_filter_exp  s    $;	!d+J '!44Qx\g  zICP 5 R
s;!!#&' #z***q\U"**9QR=%5^i  |K9F + H Hq\T!**!"uh:>>Wb  uD+ + - - q\Z'9~"il+&E!  #Y  Z  Z$$UIaL$FE$; !..y9dE ZZ_
LL$$Z]3	
z?Qy6+<+<f>O>OQWQiQi*jk a=DXXjn-tU;ED"#nn66_q !%!5Iq$,,Y+,VE$$UE2Eb	I))E((.I#//KJ"#nn66 5=TT\((.I	$/GHXHXGYZ[[%%dE2	0  &i!2!23''E41HJW\^cLd! G  IM  OT  V_` ` {"5=! m  os  uz  |EF F 22.#11+tUWa1b'%(:;-Gz&{||669;R;RW`W}W} &/%<%<%>N(,n(E%%6%@%@N 1B1K1K.2C2K2K/"1B1J1J.2C2L2L/)*prw  zC  D  D &*]]63G3G%HN%3%=%=N !#I'55 -/XXc]*(!((*,,99XE*,,99XE*  !+	 :I#(==#6#67H#IL $0#9#9.:D//<SWeWgWgWqWq<q<E;<$;L {* (4':':2lB( &( %  %|m33'3':':2lB&NN $ 0 07NPU V $ 0 0~7G7G7P7PRW X( !&( % ,, !%f.B.B CI{*',}}':':9'E'L'L%//<?%22i6J6JJ(LLRFH %  %|m33%BB+0==+>+>y+I+P+P ) 3 3| C ) 6 6):N:N N $ 0 0y7I7I5 Q,S TZSYS[ )
 ,6>>+A+A*..BWBW!*!4!4 5 CX C&hy':':;EE$BRBRSWYbYkYkmrBs<tuzuz$-$:$:i>R>R$RvT,UL
 %*OOL$|~~BVWXBY]iBi$jE#(TUY\$|~~*>q*AT*I#~~_cdpdrdr_stu_vz~_~#~~ !* 7 7 9I#'==#;L ,8,A,A)-9-A-A*",8,@,@)-9-B-B*)*prw  zC  D  D{*',}}':':<'H'O'O-=(??Evx %$|m33%==+0==+>+>|+L+S+S 1\ A $ 0 07I5 Q,SSYSYS[ ) ,6>>+A+A*..BWBW!2 3|n CX C&h'89%%@P@PQUWikp@q:r,tL %*OOL$|~~BVWXBY]iBi$jE#(TUY\$|~~*>q*AT*I#~~_cdpdrdr_stu_vz~_~#~~ddllMMMM//"00dEV`0a&%(:;-  HO  'P  Q  Q  //dD$R[/\$00	$00	!MM//	?	.669;R;RW`W}W} &/%<%<%>N(,n(E%%6%@%@N 1B1K1K.2C2K2K/"1B1J1J.2C2L2L/)*prw  zC  D  D $(==1E1E#FL , 6 6I ) 3 3Iy{{?S?SW`WbWbWeWe?e fI !#I'55 -/XXc]*(!((%KK44@%KK44@*  !+	 :I )~/9~~3Jikknn3\3=??4Ky{{OdOd4d4=4501!I !* 0 01G;1V WI,, $(==1E1E#FL , 6 6I )y,:O:OS\S^S^SaSa:a bI ) 0 0$..+=$11Y5I5II!KI !~~+4(,6)+5(,5) ) 7 7 9I#'==#;L , 6 6I"),8H"IK#*<9J#KL )y,)++..:X YI ) 0 01K LI9;;6%AN%'N9;;
3M&46O%PN&4e%<N,0,C,C"Iy/A/A9Zc  vE"/ -D -1)	> &,,^<	%,,.	??6*!*
Ii'' "~  AE  GL  NWX X	F$5$5v7O7O#PQ'''+v'>|HtU+33! C%, , ,,[$R\,]K"!$6{mCz"{||  //dD$R[/\L(44M(44M%.%6%6$7s";$]__6IJN++N;I14EN}6"02N!O"0%!8(,(?(?}/E/Ey^k  ~M+ )@ )-%I~ "((8I!((*Iv&&J	)##	6#9#9:V3<D{"//dD$R[/\$00	$00	!MM//	?	#}}V-A-AB(22	%NN9l6K6Ky{{~~6]^	%,,NN4#3#3D,:P:PRW#X#'#3#3D,:R:RTY#Z\ --=?	  $11+tUWa1bjnnT-=-=dLRW-X-1-=-=dLR[-\^ ^ ^--)V%6%67 cdd22I!**44I,,X-?-?uYc,dK"!$6yk  BI  #J  K  K ++IKKNN;I (==3L"<1BCL!(()DEI#lD):N:N%OPN(,(?(?	9+=+=y% )@ )'%I~ "((8I!((*Iv&&J	)##4<,,<<HXHXHLJOFJDEu:	 = OI
 'L	--k4S]-^L$**4yIII ))+tUz)Z 2;-?PQUPVVrsttd&&t\5AAAr9   c                     |  dS )N_m2m_direct rm  s    r7   _m2m_depth_alias_namez*SQLAlchemyDataDriver._m2m_depth_alias_nameq  s    [))r9   c                     |  dS )N_m2m_idr  r  s    r7   _m2m_alias_namez$SQLAlchemyDataDriver._m2m_alias_nameu  s    W%%r9   c                    |j                  dg       }t        |t              rt        j                  |      }|rt        |d   t
              s|g}|j                         D ](  \  }}||j                  v s|j                  |d|g       * |S )u   
        Преобразуем обычные kwargs в продвинутый фильтр для однообразной логики фильтрования
        :param model:
        :param kwargs:
        :return:
        r  r   rD  )	rl   r  r  r   loadsr\   r@   r   r^   )r6   r  rG   smart_filterrH   rI   s         r7   _get_filterz SQLAlchemyDataDriver._get_filtery  s     zz(B/lC(::l3L
<?D AL LLN 	2DAqELL ##QaL1	2 r9   c                 L   |rj|j                   j                         D ]M  }t        |t        j                  j
                  j                        s2| j                  |j                  k(  sL|} O d|v rm|j                  d      \  }}|dv r=t        | j                  |d      } t        t        |      |      j                  |      }n/t        | j                  |d      }nt        | j                  |d      }|.|r*|j                  t        |      j                  dd            S |S y)u   Для полей "основной" таблицы не нужен префикс таблицы, для этого нужно указать with_alias=Falserg  )sumavgcountminmaxNrM   )rw  rx  r  r1   r   ry  rz  r   r  r  r  r   r  r  rB   )r  r   r}   r  from_	func_namecolumn_name_shortcolumns           r7   r  z"SQLAlchemyDataDriver._query_column  s    99; "eZ^^%>%>%D%DE%**X]XbXbJb!E" ;+6+<+<T+B(I(AA *;TB1y1&9??L +t<UWWk48FCM6<<F 3 3C >?YSYY r9   parent_joinc           	         |r|j                   n|j                  j                  }|j                         D ].  \  }}| j	                  ||t        |            }	|	|j                  |	       8|s;|r|j                  xs g n|g}
|
D cg c]e  }|j                  j                  |      x}rFt        |t        j                  t        j                  f      rt        |t        j                        s|g }}|s|d   }|j                  }|r|j                  nd}| j!                  ||||d|      }|s|j                  |       | j#                  ||||j$                  |       1 yc c}w )u2   Соберём поля и таблицы по fflr  Nr   F)ro  r7  )r	  )r;  r   r   r@   r  boolr^   right_modelsr   rl   rY   r   r   rj  rh  r  rs  _select_joined_columnsr<  )r6   fflrt  r   r  r	  r  rm  r7  r  rk  related_modelrp  
fields_cls
left_modelrn  rr  s                    r7   r  z+SQLAlchemyDataDriver._select_joined_columns  sq   +6''ENN<T<T#&99; 	sJ''zd;FW'XF!v&EP+":":"@bW\V] *8X%%2%9%9%=%=j%II	I"9v/A/A6C\C\.]^&y&2U2UV	 X
 X "&qM	&55
2=[..4
 00z:RWah 1 j	 Y'++GUGYEZEZhq+r3	sXs   	A*E()r  group_byr  c                   | j                  |      }| j                         }	ddlm}
 |
j	                  d|j
                   |      }t        |       j                  |      }|r"|j                         }|j                  |	      }nt        j                         }g }g }| j                  ||||        |	j                  | }| j                  ||d      }t        j                         |z
  dkD  r:|j                         j                  d       }t        |       j                  ||       t        |      dkD  r0|j                   }t#        t        |            D ]  }||   |||   <    | j%                  ||      }|r+| j'                  ||||||      \  }}|j)                  |      }|rg }|D ]  }||j*                  j,                  v r)|j/                  |j*                  j,                  |          D| d	|j*                  j,                  v s`|j/                  |j*                  j,                  | d	            |j0                  | }|S )
Nr   	CMF_CACHEzquery: full_fields_loadT)r|  g{Gz?r  r  r#  )r   rD   r  r  hashr   r   rp   _clonewith_sessionr   r  r}   r~  r   rz   r   ranger  r  r  r   r  r^   r  )r6   r  r  r  r  r  rF   rG   r   r   r  rn   r}   start_calc_timert  r   clone_qpkeyir  
filter_expr   s                         r7   _create_queryz"SQLAlchemyDataDriver._create_query  s1   =='LLN)nnwu~~&67JZn[T
$$S)LLNE&&q)E"iikOEG''(8%%PAGGW%E$$UE$>E
 		O+u4  ,,.55d;T
$$Wc2 t9q=$$D3t9% *"&q'tAw* ''v6 $ 7 7eXW\n}FS !8 !UE:LL,EG' N("4"4"6"66NN8#5#5#7#7#DE#}C(H,>,>,@,@@NN8#5#5#7#7;-s8K#LM	N
 #ENNG,Er9   )
r  r  r  
for_updatemapperr  load_m2mr  aggregate_selectr  c       
   	      p   t        |t               }t        j                  |      }| j                  |      }| j	                  |      } | j
                  |f||||	|
d|j                         }| j                  ||||
|      }|r |j                  | }|
r;|j                         }t        j                  d      }|j                  |||      }|S |r|j                         }|j                         }|j                  |||      }|r*|r| j                  |||||       |r|j                          |S )   Грубо селектим всю таблицу, фильтры:
          - в kwargs: поле -> значение
        )r  r  r  r  r&  )r  r&  r  simpler  r  r  )r  r"   
get_mappermap_args
map_kwargsr"  with_labelsr  r  alllist_to_cmfwith_for_update	_load_m2mpost_mapping_hook)r6   r  r  r  r  r#  r$  r  r%  r  r&  r  rF   rG   mapper_is_my_argsqsql_resres_objss                      r7   r\   zSQLAlchemyDataDriver.list  sf    &fj99&&v.d#(D
$4oer  ~F  Yi
 ms

+- 	
 QHX`efAeegG**84F))'DT\a)bHO%%'eegG))*:% * IHNN8-=vWf  wDN  E,,.Or9   )r  r  c                   | j                  |      }| j                  |      } | j                  |fd|i|j                         }|r
| j	                  |      }|D 	cg c]  }	|j
                  j                  |	    }
}	  |j                  j                  |j                  j                   j                  g |
t        j                               j                  |
 j                  d      }t        |j                   j#                  |            }g }|D ]8  }i }t%        |      D ]  \  }}	||   ||	<    |d   |d<   |j'                  |       : |S  |j                  j                  |j                  j                   j                  t        j                         g      j                  d      }|j                   j#                  |      j)                         }|S c c}	w )r(  r  Nr  r  )r,  r-  r"  r.  r   r   r  rw  select_fromfromswith_only_columnsr   r  r  r  r\   r  r   	enumerater^   scalar)r6   r  r  r  rF   rG   r5  r6  r   r   r   count_qres_listresrowrow_resr   r  s                     r7   r  zSQLAlchemyDataDriver.count  s    d#(D
$4
8>

+- 	
 }}U+HLTU[x))++K8UGU-akk--q{{/@/@A""#;W#;djjl#;<7$ $  AII--g67HC $&/&9 2NA{+.q6GK(2#&r7 

7#$ J-akk--q{{/@/@ASSUYU_U_UaTbcllmqrGII%%g.557E# Vs    G)r  r  r#  r$  r  r  c                   t        |t               }
t        j                  |      }| j                  |      }| j	                  |	      }	 | j
                  |g||||d|	}|j                         }| j                  ||ddg|      }|r|j                         }|j                         }|r?|j                  |||      }| j                  |g||||       |
r|j                          |S y)u   
        Выбрать один объект по фильтру:
          - в args - первичный ключ(опционально)
          - в kwargs - другие поля: поле -> значение)r  r  r  r   r    )r  r  r*  )r$  r  r  N)r  r"   r+  r,  r-  r"  r.  r  r1  firstobject_to_cmfr2  r3  )r6   r  r  r  r#  r$  r  r  rF   rG   r4  r6  sa_instanceres_objs                 r7   rl   zSQLAlchemyDataDriver.get8  s   
 &fj99&&v.}}T"(Du Ft F>N`o-:F>DFMMOQAeD!!#Awwy**;IYaf*gGNNG9&6vWf  wDN  E((*N r9   c                   A |r|syt        |t              AAfd}d }t        |      }t        t              }	t        t              }
t        t              }|D ]:  }|	 ||         j	                  |       |
|j
                     j	                  |       < |
D ]  }t        t        |      }|D ]  }||   s	t        ||d      }|st        |t        j                        s4t        |t        j                        r||    Tt        |t        j                  t        j                  f      s||   j	                  |         |j                         D ]I  \  }}g }|D ]  }t        t        |j
                        }|j                  j                  |      }|s<t        |t        j                        sWArt        ||      }|j                   dur(|j                   |j	                  |j                          d|_        |j"                  du rd|_        |j%                         }t        ||      }|j                   }|du rnt'        d||      t        ||d      }|dur|r|j	                  |       t)        ||d       |j%                         }t        ||d      }|du rt'        d||      |sU|j+                  d      d   }||   |   j	                  |        |j                         D ]  \  }}t        t        |d      }|st-                dd	t        |      g}| j                  |||   ||
      }|D ]>  } ||      }||   D ],  }Art        ||      }||_        ||_         t)        |||       . @  |s1| j/                  |||   |||       L |j                         D ]	  \  }}|D ]  }|j
                  }|
|   }t        ||      }t        |t        j                        r|j0                  rt3               } |j0                   d}!|!d	|D "cg c]
  }" ||"       c}"g}#t5        t3        ||   fi |!i i      }$|j7                         D ]f  }%|#}&d|%j                  v r|s|#g dg}&d|%j                  v r|s|&g dg}&| j9                  |%|$|&||      }'| j;                  |'|%      | |%j<                  <   h | s8ddlm }(m!})  |(|)jD                  d|j
                   d|j
                   d       HtG        |       dk(  r;t-                tI        tK        | jM                                     jO                         }*nst-                | jQ                  tR        jT                  jW                  | j                         D +,ci c]  \  }+},|+|,jX                   c},}+d            jO                         }*t        t              }-|*D ]"  }.t        |.|!      }/|-|/   j	                  |.       $ g }0|D ]  }|-j                   ||            }1Art        ||      }|1sg |_        |j"                  du rg |_        G|j[                  |1||         |_        |j"                  du rt]        |j                         |_        |0j_                  |j                          |1st)        ||g        |j[                  |1||         }t)        |||       |0j_                  |        |0s,| j/                  |0||   |||       Gt        |t        j                        sc|j`                  rd}2d}3nd}2d}3|jc                         }4| je                  |4      }5t        |5|2      }6t        |5|3      }7| jQ                  |6|7      jg                  |6ji                  |D "cg c]
  }" ||"       c}"            }8t        t              }9t        t              }:t-                |8D ]D  \  };}<|<r|;s|:|<   j	                  |;       |9|<j+                  d      d      j	                  |<       F |9j                         D ]  \  }}=t        t        |      }t-                dd	|=g}|stk        |d      rg d|g}|stk        |d      rg d|g}| j                  |||   ||d      }0|0r| j/                  |0||   |||       |0D ]  }|: ||         D ]u  };|	|;   D ]k  }>Ar6|>|   }?|?j                   du rg |?_        |?j                   j	                  |       ;t        |>|d      }|du rg }t)        |>||       |j	                  |       m w   |D ]t  }ArS||   }@|@j                   du rg @_        @j"                  du rt]        @j                         |@_        @jm                          Xt        ||d      du sht)        ||g        v    yc c}"w c c},}+w c c}"w )u   
        Прогрузка М2М и М2О полей
        :param objs: список обьектов
        :param full_fields_load: поля обьектов
        :return:
        Nc                 L    r| j                   j                  S | j                   S rj   )r   r  )obj_is_heavys    r7   r  z.SQLAlchemyDataDriver._load_m2m.<locals>.obj_id^  s    ww~~%77Nr9   c                      d } t        |       S )Nc                       t        t              S rj   )r   r\   r  r9   r7   id_to_list_factoryzWSQLAlchemyDataDriver._load_m2m.<locals>.model_to_id_factory.<locals>.id_to_list_factoryj  s    "4((r9   r   )rO  s    r7   model_to_id_factoryz;SQLAlchemyDataDriver._load_m2m.<locals>.model_to_id_factoryi  s    )122r9   .u#   Не загружено id поле:r   r   rH  )r  r$  r  r  r#  r  r  r  r  )r  r  r  r  r  r  zORM: skip load field rM   z die no related modelsr    r  r   r   F)r  r  r$  r%  )7r  r#   r   r\   r^   r]   r  r   rY   r   r   r  r  CmfBackrefBaser@   rl   r  _oldid_fieldnamer   setattr	partitionr$   r2  r  r  r%   rk  r"  r  r`   r  r  r?   r  rz   nextitervaluesr/  r}   r1   r2   r  rw  r0  r   r   r  r  r   r  r\  ra   apply_changes)Br6   objsr  r$  r  r  r  rQ  to_load_mappingmy_objs_by_idmy_objs_by_model_namemodels_by_rel_fieldsobjr   r  rm  rp  model_to_idalready_loaded_obj_listra  id_field_nameid_fieldid_field_valuefield_valuerel_model_nameid_to_obj_list_filter	load_objsload_obj	loaded_idmodels_listobj_listm2mquerybackref_field_nameofilter_q	field_ffl	rel_modelmodel_query_filterr6  r  r?   r@  rH   r2  res_dictrb  m2m_idsub_objsref_obj_listr  r  r  r   r  r  	m2m_queryid_by_modelsmy_id_by_sub_idmy_idsub_idsub_id_listmy_objmy_field	obj_fieldrL  sB                                                                    @r7   r2  zSQLAlchemyDataDriver._load_m2mR  sA
     tff-		3 &&9: $D) +D 1*40 	>C&+&--c2!#..188=	> 0 	GJFJ/E. 
G
'
3 #E:t<	Iv7H7H!I!)V-C-CD'
3#I0A0A6CXCX/YZ,Z8??F
G	G (7'<'<'> H	<#J ')#  #P7!LL,,Z8	Iv7M7M!N 'Z 8 <<s2$||7 7 > >u|| L$ (, ::,)-EJ(1(>(>(@#*3#>)1)S0"-.SU]_d"ee&-c:s&C&c1* 7 > >{ K$  Z6(1(>(>(@)0mS)I)S0"-.SUbdi"jj%)7)A)A#)Fq)I#N3NCJJ3OG#PL /:.?.?.A ?*
N
D9 "tN';< II,<Z,H!' & 3	 !* ?H &x 0I-i8 
?#$+C$<E+3EL *2EJ#CX>
???4 '68H8TV\n}-:  <OH	<X (<'A'A'C ]	=#J$ \="--
0< $E:6	 i)>)>?IDUDU  $vH,5,=,=+>c)B& 2Dh:W6!9:WXH 248H8T3qYkmoXp3q rI%.%=%=%? ]	-5*(I,<,<<_2:<X1Y.%)9)99-2DF_1`. ..y9]o  BQ=J / L 9=8H8HR[8H8\!4!45] $C#"LL3E4D4D3EQyG[G[F\\rsu !X!+(*#'X__->(?#@#D#D#F(* $(::&NN<<<DNN<L MDAqAKK M|]$^^a^a^c !  +40H' 5!(.@!A (//45  "H' 9'/||F3K'@#$+C$<E#//1#(::#413EJ (+1+=+=lL\]gLh+iEL$zzS0-1%,,-?
 %OOELL9#/ 'Z < (*0*<*<\K[\fKg*hK#C[A$OOK8-92  x1A*1Mvgv5B ' D	6+<+<= !~~+4(,6)+5(,5) ) 7 7 9I#}}Y7H")(4D"EK#*85F#GL $

; EH0Mq0M NO #.t#4L&1$&7O$&)2 Nv%U$'/66u=$V%5%5c%:1%=>EEfMN 4@3E3E3G @/
K '
 ;(*#'{";.75-3P'CW&MG,
1K'@'&JG#'99!4DZ4P#*6E $- $K $ NN85Ej5QSYkz9F + H#+ @C)8)E @.;E.B !@F'/39*3E+3??c+A>@HO(0(>(>s(C6=fjRU6V+6#+=:<K,3FJ,T(3(:(:3(?!@@@#@B  ( 
=#(+JI(//3635	 0(~~415i6F6F1G	%335&sJ<C 'Z <
=e\=]	= ;XD !Nl 1Ns   "f?gg
c                     g }|D ]I  }t        |t        j                        r|j                  |j                         9|j                  |       K |S rj   )r  r   r   r^   r  )r6   rF   new_argsargs       r7   r,  zSQLAlchemyDataDriver.map_argst  sG     	%C#v~~.		*$		%
 r9   c                     i }|j                         D ]4  \  }}t        |t        j                        r|j                  ||<   0|||<   6 |S rj   )r@   r  r   r   r  )r6   rG   
new_kwargsrH   rI   s        r7   r-  zSQLAlchemyDataDriver.map_kwargs}  sL    
LLN 	"DAq!V^^, !
1 !
1		"
 r9   )	no_reloadc                   | j                  |      }| j                  |      }| j                         }| j                  |j                        } |       }	t        j                         }
|
j                  ||	       	 |j                  |	       |j                  |	g       d|_        |ry|
j-                  |	|      }|
j/                          d|_        |S # t        $ rd}|j                  j                          t        |j                  t        j                   t"                    rt%        |      |t'        |      |d}~wt(        $ r!}|j                  j                          |d}~ww xY w)um   
        no_reload - не загружать объект из базы и не возвращать
        objectsNT)
cmf_entity)r,  r-  rD   r   rJ   r"   r+  cmf_to_objectr'  flushr	   r   r   r  origr   lookupr   r   r   r   is_newrF  r3  )r6   instancer  rF   rG   r5  _kwargsr   r   rG  r$  r   ra  s                r7   createzSQLAlchemyDataDriver.create  s5    d#//&)LLN==!3!34j&&(X{3	EE+GG[MG* "";8"D  "

'  	1MM""$!&&&--0@"AB'*1&q)q0  	MM""$G	s%   <$C 	E+AD>>E+
E&&E+c                    | j                  |      }| j                  |      }| j                         }| j                  j                        }t              j                  }| j                  t        fd|D                    }	|j                  |      j                  |	      }
	 |j                  |
       S # t        $ r!}|j                  j                          |d}~ww xY w)u*   TODO логическое удалениеc              3   6   K   | ]  }t        |        y wrj   r  .0fr  s     r7   	<genexpr>z.SQLAlchemyDataDriver.delete.<locals>.<genexpr>       'K!(<'K   N)r,  r-  rD   r   rJ   r   r   r   r}   rl   deleter   r   r   )r6   r  rF   rG   r5  r  r   r   r  get_argsrG  r   s    `          r7   r  zSQLAlchemyDataDriver.delete  s    d#//&)LLN==!3!34H~))=='Kd'K!LMggh'++H5	HH[!   	MM""$G	s   (B; ;	C%C  C%c                    | j                  |      }| j                         }|j                  |      }| j                  ||      }|r+| j	                  ||||||      \  }}	|j                  |	      }|j                  d      }
|
S )Nr  fetch)synchronize_session)r   rD   r}   r  r  r  r  )r6   r  r  r  rG   r   r   r}   r  r!  
delete_cnts              r7   bulk_deletez SQLAlchemyDataDriver.bulk_delete  s    =='LLN!''v6 $ 7 7eXuoer !8 !tE:LL,E\\g\>
r9   r  rZ  c                $   ddl m} | j                  |      }| j                         }	|	j	                  |      }
| j                  ||      }|r+| j                  ||||
||      \  }
}|
j                  |      }
|
j                  }|
j                  } ||      j                  |      j                  |j                        }|D ]  }|j                  |      } |j                  |      }|	j                  |      }|D cg c]  }|d   	 c}S c c}w )Nr   r   r  )r1   r   r   rD   r}   r  r  r  
_criterion_join_entitiesrZ  	returningr   r:  r+  r   )r6   r  rZ  r  r  rF   rG   r   r   r   r}   r  r!  filter_criteriajoin_clausesstmtjoin_clauser3  rB  s                      r7   bulk_updatez SQLAlchemyDataDriver.bulk_update  s   %=='LLN!''v6 $ 7 7eXW\n}FS !8 !UE:LL,E**++h&&v.88E' 	1K##K0D	1 zz/*4"()3A)))s   >Dr  )
chunk_sizec                <   ddl m} ddlm}m} |sg S | j                  |      }|j                  }|j                  D 	ch c]  }	|	j                   }
}	|j                  D 	ch c]A  }	|	j                  s3|	j                  dk7  r$|	j                  |	j                  |	j                  C }}	 |t              }|D ]U  }|j                         D ci c]  \  }}||
v s|| }}}|t        |j                                  j!                  |       W |D cg c]  }|d   	 }}| j#                         }	  ||      }|j                         D ]  \  }}|t%        |      z
  }|r5|D ]0  }|D ])  }|dv r |j&                         ||<   t)        d| d       2 t+        dt-        |      |      D ]*  }||||z    }|j/                  |j1                  |             ,  |S c c}	w c c}	w c c}}w c c}w # t2        $ r!}|j4                  j7                          |d }~ww xY w)Nr   rP  )insertr   r   )cmf_created_atcmf_modified_atu   bulk_insert: колонка 'u>   ' NOT NULL без default; передайте значение)collectionsr   r1   r  r   r   r   r   r   r   server_defaultrL   r\   r@   	frozensetkeysr^   rD   rv  now
ValueErrorr  rz   r   rZ  r   r   r   )r6   r  rZ  r  r   	sa_insertr   r   tblr  
table_colsrequired_namesbucketsrB  rH   rI   ridsr   	base_stmtkeysetrowsneed_addr   r   batchr   s                              r7   bulk_insertz SQLAlchemyDataDriver.bulk_insert  s7   +8I=='  &)kk2aff2
2
  KK
::!&&D.  (QYY-> FF
 
 d# 	3C"%))+A$!QjAAAAIaffh'(//2	3 !''1qw''LLN	!#I ' 7)CK7! W$, WD#'LL*2$((*$&03PQUPV  WU  2V  'W  !W	WW q#d)Z8 7A 1z>2EIIi..u5677 JG 3
 B ((  	MM""$G	s7   G!AG!G&G&G,2B)G1 1	H:HHr  c          	      X   ddl m} | j                         }| j                  t	                    }t	              j
                  }| j                  t        fd|D                    }	i }
t	              j                  j                         D ]k  \  }}t        |t        j                        r"t        |t        j                        r=t        |t        j                        rXt        |t        j                        rst        |t        j                        rt        |t        j                         rt        |t        j"                        rt%        |      }t'        |t        j(                        rF|j*                  du s|j,                  r|j.                  s|j0                  s |j3                         }|du rt5        dt6         d| d|       ||
|<   |   j0                  sbd|   _        n |
st9        d d	       S  ||      j;                  |
      }|j=                  t%        ||d         |	d   k(        j?                  |j@                        }	 tC        tE        |jG                  |                  d
k(  sJ d       	 S # tH        $ rb}|jJ                  jM                          t'        |jN                  tQ        jR                  tT                    rtW               |tY               |d }~wt4        $ r!}|jJ                  jM                          |d }~ww xY w)Nr   r  c              3   6   K   | ]  }t        |        y wrj   r  r  s     r7   r  z1SQLAlchemyDataDriver.update_v2.<locals>.<genexpr>  r  r  .u%   Попытка update field=Ellipsis r   FzDEV: warning! UPDATE u*    не содержит изменений.r    uA   Доп.защита, что только 1 объект в update)-r1   r   rD   r   r   r   r,  r   r   r@   rY   r   r   r   r   r   r   r   r  r  r   r  r   
is_changed	orm_dirty	db_formatr   r  r|   rZ  r+  r  r   rz   r\   r   r	   r   r   r  r   r  r   r   r   )r6   r  r  rF   rG   r   r   r   r  r  rZ  rH   rI   vvr  r   s    `              r7   	update_v2zSQLAlchemyDataDriver.update_v2  s   %LLN==h0H~))=='Kd'K!LMN))//1 	.DAq!V//0!V667!V]]+!V112!V../!V001!V5561%B"fnn-99#rzz}}R\\\\^Sy"G
|STUVTWWXY[X\ ]^^F1I{$$(-%7	.: )(3]^_Oh&&v.zz'(DG4CDNNx{{[	tAIIdO,-2w4ww2   	0MM""$!&&&--0@"AB')q0&(a/  	MM""$G	s%   &-J 	L)AK<<L)L$$L)c                   ddl m} |j                  r | j                  g|dd i|S | j	                  |      }| j                  |      }| j                         }| j                  t                    }t              j                  }| j	                  t        fd|D                    }	|j                  |      j                  |	      }
t        j                         }|j                  |
       	 |j!                  |
g       j8                  }|j;                  |
|      }|j=                          ||_        |S # t"        $ rb}|j$                  j'                          t)        |j*                  t-        j.                  t0                    rt3               |t5               |d }~wt6        $ r!}|j$                  j'                          |d }~ww xY w)Nr   r  r  c              3   6   K   | ]  }t        |        y wrj   r  r  s     r7   r  z.SQLAlchemyDataDriver.update.<locals>.<genexpr>V  r  r  r  )r  r  )r  r?   ORM_RAW_UPDATE_V2r  r,  r-  rD   r   r   r   r   r}   rl   r"   r+  r  r  r	   r   r   r  r  r   r  r   r   r   r   r  rF  r3  )r6   r  r  rF   rG   r?   r   r   r  r  rG  r$  r   r  ra  s    `             r7   r   zSQLAlchemyDataDriver.updateM  s   &##!4>>(STSDSFSS}}T"(LLN==h0H~))=='Kd'K!LMggh'++H5&&(X{3	GG[MG*$ "";8Vf"g  "

'  	0MM""$!&&&--0@"AB')q0&(a/  	MM""$G	s%   7E 	GAF))G5GGc                 "    t         |           y rj   )r<   before_request)r6   rJ   s    r7   r  z#SQLAlchemyDataDriver.before_requestu  s     r9   c                 8   ddl m} |j                          |j                          t	        dd      }| j                         j                           |        t	        dd      }| j
                  j                           |        t        d       t                y )	Nr   r  z#SQLAlchemyDataDriver.Session.commiti,  z#SQLAlchemyDataDriver.Session.removed   Tnear_commit_or_rollback)
r  r  cache_unlockcache_transaction_startr(   rD   r   remover&   r'   )r6   r  
prof_points      r7   r   zSQLAlchemyDataDriver.commitx  ss    ) ))+$%JCP
$%JCP
 	#4@r9   c                     ddl m} t        d       |j                          | j	                         j                          | j                  j                          t                y )Nr   r  Tr  )r  r  r&   r  rD   r   r  r'   )r6   r  s     r7   r   zSQLAlchemyDataDriver.rollback  sA    )"4@ !r9   c                 B     | j                         j                  |i |S rj   rD   r}   r6   rF   rG   s      r7   r}   zSQLAlchemyDataDriver.query       #t||~##T4V44r9   c                 B     | j                         j                  |i |S rj   r  r  s      r7   query_deprecatedz%SQLAlchemyDataDriver.query_deprecated  r  r9   c                    ddl m} |r
|d   dk(  r|S g }|s j                  xs g }|j                         }|r|}|r
|r|s|dgz  }dt        ffd}|D ]  }	d}
|	j                  d      r|	d	d
 }	d}
 ||	      }|j                  j                  d   j                  j                  |      }|2|j                  j                  d   j                  j                  |	      }| |j                  D ]  }|d   |	k(  s|d   } n |t        d|	 d      ddlm} |j                  rt        |j                   t"        j$                  j&                        r|dz   }nqt        |j                   t"        j$                  j(                        r|dz   }n=t        |j                   t"        j$                  j*                        r|t-        d      z   }|
rt#        j.                  |      }|j1                  |      } |S )u3   Сортировка по логике моделиr   )
QueryProxyz--r   cmf_column_namec                     d}	 | j                  d      \  }}}|s|} n|} |r	| d| d}n| d}-|sj                   d}| |  S )Nr;   rM   rQ   _sub_)rW  r`   )r  alias_prefixp1rQ   p2r  s        r7   calc_dp_column_namez=SQLAlchemyDataDriver.order_query.<locals>.calc_dp_column_name  s|    L+55c:	Ar&(O"$&2^1RD#>L&(T<L   "'//!2!4"^O#455r9   F-r    NTr   expru   Не найдено поле uK    или тип поля не поддерживает сортировку.r  r;   )minutes)cmf.data_providers.baser  orderingr   r  rA   ry  r;  r  rl   column_descriptionsr   r  r?   ORM_ORDERBY_IDX_SKIPr  r   r1   r  r   r   DateTimer   descr  )r6   r}   r  r  r&  r  r  order_fieldsr  rn   
order_descdp_column_name	dp_columncolumn_descriptionr?   s        `         r7   r  z SQLAlchemyDataDriver.order_query  s   6 t+L >>/RL',,.L#L E*:TF"L	6 	6    0	.CJ~~c"!"g!
 15N((..q13377GI  !,,221577;;C@	  */*C*C &)&1S8$6v$>	
  !$A#  GR  #S  T  T***innj.>.>.F.FG )AI	
0@0@0G0GH )BI	
0@0@0I0IJ )Ia,@ @I&OOI6	NN9-Ea0	.b r9   c                 $    t         |   |       y rj   )r<   make_models)rb   r=  rJ   s     r7   r  z SQLAlchemyDataDriver.make_models  s    G$r9   c                 2   t        t              D ]  }t        t        |      }t        |t              r|j
                  r0|j                  r| j                  |j                  vrU|j                  s| j                  t        k7  ru| j                  |        y)u   Создадим схемуN)
dirr   r  r  r   r   data_sourcesr   r   r   )r6   r   rc   s      r7   rE   zSQLAlchemyDataDriver.init_meta  s{     f+ 	%J
3Ii79;M;M %%$))9;Q;Q*Q))dii;M.MMM)$	%r9   c                     | j                         }t        |j                               }d|j                         v rt	        d      |j                  d       |j                          | j                  j                  | j                         t        j                  j                  t        j                         d      }t        |      }|j                  d| j                   d          t#        j$                  |d       y )Nalembic_versionzDatabase has alembic versionz'CREATE EXTENSION IF NOT EXISTS pg_trgm;zalembic.inizsqlalchemy.urlhead)rD   r   
connectionget_table_namesFileExistsErrorr   r   db_meta
create_allr4   rx   pathr  getcwdr   set_main_optionr?   r   stamp)r6   r   	inspectoralembic_config_filealembic_configs        r7   init_dbzSQLAlchemyDataDriver.init_db  s    LLN ALLN+		 9 9 ;;!"@AA			;<	
, ggll299;F 34&&'7EU9VWnf-r9   c                 L    | j                   j                  j                          y rj   )r4   pooldisposer5   s    r7   r   z'SQLAlchemyDataDriver.close_all_sessions  s      "r9   rj   )NTNN)F)NT)FF)NNNN)Mr   r   r   __doc__r   r1   MetaDatar  extdeclarativedeclarative_baser   r   rk   rw   r8   r=   classmethodr   rp   r   r   r   r   r   r   r   r   r  r   rc   r
  r  r@  staticmethodrY  rc  r   rd  rs  r   r~  r  ri  r  r  r  r  r  r  r  r"  r\   r  rl   r2  r,  r-  r  r  r  r  r  r  r  r   r  r   r   r}   r  r  r  rE   r  r   __classcell__)rJ   s   @r7   r,   r,   !   s   8 O!j!!#GNN..??& @ M !]N=> 3 3j   ? ?* I
 I
VN($"dH9vO $ $L,2K
MQNf K K  '  'D *&rsH!F $x.  ." D D ISei  |A).|B| * * & &( Z Z&sh s< MR\`pu 1f +/E$X\T D 48$ "H *.QV_cuz  KP 4`=D	 16 "H"
 FKZ_ * *0 8= /b ;? ;z 8< &P! 55Wr % %%$.$#r9   r,   c                       e Zd Zd Zy)SAModelAccessorc                 R    |dv ry t         j                  t        t        |            S )N)_pytestfixturefunction__test__)r,   r  r  r   )r6   items     r7   __getattr__zSAModelAccessor.__getattr__  s&    99#001FGGr9   N)r   r   r   r   r  r9   r7   r  r    s    Hr9   r  )@rx   r   r  r   r   r   typingr   r   datetimer   sqlalchemy.typesr1   sqlalchemy.ext.declarativesqlalchemy.ormsqlalchemy.sql.selectablesqlalchemy.excr	   r
   r   r   flaskr   r   alembic.configr   alembicr   psycopg2.errorcodesr   psycopg2r   r   cmf.fields.base_fieldsr   r   cmfr   r  r   
base_errorr   r   r   models.base_modelr   r   r   r   baser!   r"   r#   r$   util.immutablesr%   util.cmfutilr&   r'   r(   r)   r*   r,   r  r  r9   r7   <module>r4     s    	  /   #   !    ) 0 0  !  0  - 6   M M Z Z F F 0 [ [ " "x#> x#v?H Hr9   