
    oi                       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dl m}m} t        |t        j
                        r.|j                  du r ||j                  d       |j                  }nt        |t              r{t               }|D ]j  }t        |t        j
                        r=|j                  du r ||j                  d       |j                  |j                         Z|j                  |       l |}|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 )Nr   print_debugr?   .u<   collect_filter_exp: Значение не загруженоNULLrB  rE  rC  rF  )rD  rG  )rI  rJ  rK  rH  rS  rT  rL  rM  rN  rO  rP  )cmf.includer\  r?   r  r   r   _valueDEBUGvaluer\   r^   in_likeilikeop)operfieldvalr\  r?   new_valrI   s          r7   _expressionz SQLAlchemyDataDriver._expression=  s   3c6>>*zzS FLL*hi))CT"fG &a0xx3#FLL2pqNN177+NN1%& C&=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  rk  )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_dataq  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}   r{  forcer  available_joinsry  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   splitrz  r^   r  r<  r;  )r6   	join_pathr  r6  ru  r{  rt  ry  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]   )rt  r  fields_s      r7   rp  z)SQLAlchemyDataDriver._raise_invalid_field  sV    ell#++C7ZL(STYTdTdSeex  zA  yB  C  D  	Dr9   c	                 4)   |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                  |      \  }}}t        t        |      t              r|j                  }t        t        |      t              r|j                  j                  }t        |t        t         f      rg }|D ]  }t        t        |      t              rot        t        |j                        t              r0|j                  |j                  j                  j                         o|j                  |j                         t        t        |      t              r&|j                  |j                  j                         |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}||j0                  j2                  }nt        |      dkD  rv|j5                  d      \  }}}| j7                  |||      }| j9                  ||      }|d   }|j:                  }|j$                  j'                  |      }|j<                  }d}n||j0                  j2                  }|dk(  r |dk(  r|j$                  j'                  d      }|st        d| d|j>                         || jA                  ||       t        |t$        j(                        r|dv r.t        |t              st        |t               st        d|||      |d	v r|t        d|||      |dv rddl!m"} | jG                  |d||      }|t        d| d      |jH                  rG|jJ                  r:|jL                  r-|jO                         }| j1                  |      }|j2                  }|jP                  r|jR                  }|jT                  }n2|jV                  r|jT                  }|jR                  }nt        d ||      | j1                  tX        jZ                        }|j2                  } g }!|jJ                  D ]i  }"|"j#                  d      \  }#}$|!j                  t	        j\                  | j^                  j`                  |$k(  | j^                  jb                  |#k(               k t	        j
                  |! }!|jd                  jg                  |      }%|%ji                  | t	        j\                  || j^                  jj                  k(  |!            }%|d	v r'|%jm                  ||k(        jo                         }%||% fS |%jm                  ||k(  t	        j
                  | jq                  d!||      | jq                  d!| j^                  jr                  |                  jo                         }%n#|jJ                  r(| j1                  tX        jZ                        }&|d	v rb|jd                  jg                  |&      jm                  |&jj                  |k(  |&j`                  |j>                  k(        jo                         }%||% fS |jt                  s{|jd                  jg                  |&      jm                  |&jj                  |k(  |&j`                  |j>                  k(  | jq                  d!|&jr                  |            jo                         }%n
t        jv                  jy                  t        jz                  j}                  |&jj                  g|&g"      j                  |&jj                        j                  | jq                  d!|&jr                  |            j                  |&j`                  |j>                  k(              }%|ji                  |%t        |%j^                        d   |k(        }||d!k(  rt        |%j^                        d   d k7  fS t        |%j^                        d   d k(  fS |jO                         }&| j1                  |&      }'|jP                  r|'jR                  }(|'jT                  })n2|jV                  r|'jT                  }(|'jR                  })nt        d ||      |d	v r@|jd                  jg                  |'      jm                  |(|k(        jo                         }%||% fS |j                  sN|jd                  jg                  |'      jm                  |(|k(  | jq                  d!|)|            jo                         }%nt        jv                  jy                  t        jz                  j}                  |(g|'g"      j                  |(      j                  | jq                  d!|)|                  }%|ji                  |%t        |%j^                        d   |k(        }||d!k(  rt        |%j^                        d   d k7  fS t        |%j^                        d   d k(  fS ||d!k(  r|%fS |% fS |d#v r| jG                  |d||      }*|*t        d| d$      | j                  | d d d |%      }+|+j:                  },|+j<                  }-|jd                  jg                  |-j^                  j                        }.ddl!m"} |jH                  r|jJ                  r|jL                  r|jO                         }| j1                  |      }|j2                  }|jP                  r|jR                  }|jT                  }n2|jV                  r|jT                  }|jR                  }nt        d ||      | j1                  tX        jZ                        }/|/j2                  }0|.ji                  |0|0j^                  jr                  |-j^                  j                  k(        }.g }!|jJ                  D ]i  }"|"j#                  d      \  }#}$|!j                  t	        j\                  |0j^                  j`                  |$k(  |0j^                  jb                  |#k(               k t	        j
                  |! }!|.j/                  |t	        j
                  ||-j^                  j                  k(  t	        j\                  ||0j^                  jj                  k(  |!                  }.|.jm                  ||*k(        }.n8|jJ                  r| j1                  tX        jZ                        }/|/j2                  }0|.j/                  |0|/jr                  |-j^                  j                  k(        }.|.jm                  |/jj                  |*k(  |/j`                  |j>                  k(        }.n|jV                  rd&}1d'}2nd'}1d&}2|jO                         }&| j1                  |&      }/|/j2                  }0t        |/|1      }3t        |/|2      }4|.j/                  |0|4|-j^                  j                  k(        }.|.jm                  |3|*k(        }.t        |-j^                  d(      r|sg d)}5ng }5t        |-j^                  d*      r|s|5g d+g}5|r|5|g}5| j                  |5|,|,j0                  |.|-||      \  }.}5|.jm                  |5      }.|.jo                         }.|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        d/|||      | jG                  |d||      }*|*t        d| d0      | j                  | d d d |%      }6|6j:                  }7|6j<                  }8|j                   d1}9t        |8j^                  |9      }:|jd                  jg                  |:      }.|9d2|*g}5t        |8j^                  d(      r|5g d)g}5|r|5|g}5| j                  |5|7|7j0                  |.|8||      \  }.}5|.jm                  |5      }.|.jo                         }.|j                  d,      r|. }.||.fS t        |t$        j                        r~| d1}|d3k(  rs| j                  | d d d |%      }+|+j:                  },|+j<                  }-|jd                  jg                  |-j^                  j                        }.| j1                  tX        jZ                        }/|/j2                  }0|.j/                  |0|/jr                  |-j^                  j                  k(        }.|.jm                  t	        j
                  | jq                  d!|/jj                  |      | jq                  d!|/j                  |            |/j`                  d4k(        }.| jG                  ||||      }|t	        j
                  | jq                  d!||      | jq                  d!||.            fS |d5v rJt        |t$        j(                        rt        d6      tX        j                  },|,j0                  j2                  }-| jG                  |j2                  d||      }*|*t        d|- d$      |jd                  jg                  |-j^                  j                        }.d7}2| j1                  |,      };t        |;|2      }4|.jm                  |4|*k(        }.|d8d2|j>                  gg}5| j                  |5|,|,j0                  |.|-9      \  }.}5|.jm                  |5      }.|.jo                         }.|j                  d,      r|. }.||.fS |dk(  r_tX        j                  j                  |j>                  ||ddd:g;      }<|<sd<g}<| jG                  |d||      }|| jq                  d!||<      fS | jG                  ||||      }|t        d| d=| d>      || jq                  |||      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    не найдено у )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 для фильтрации в подзапросе)rw  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_idrt  )r  '  )r   rt  search_queryonly_idssliceNOTFOUNDu    нет поля u    для фильтрации)Mr  r\   collect_filter_expr^   r1   or_rz   r   order_queryrY  rY   r   r   ra  r   r   r   r  r   rl   
CmfM2MBaser   r   joinr   r   
rpartitionr  r  r<  r;  r]   rp  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existsrj  child_idORM_RELCACHE_EXISTS_VIA_JOINr2   rs  r   r(  distinctr+  ORM_M2M_EXISTS_VIA_JOINrz  r  ra   rA   backrefCmfRelationBaseparent_coder   CmfOrmColumnHistoryCmfFullSearchfulltext_search)=r6   	in_filterr  r   r}   r  r  r  r  
filter_resrI   exprf  r  r  _righti
left_partsrw  r  r  rQ   r{  ry  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_idss=                                                                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$; !% 2 29 =D$$u+w/$u+y1%$/  
)A!$q'73%d177mY?"MM!''***:*:;"MM!''2#DGY7addjj1a(
)  CJ((A7IJ:""9v/@/@&BSBSU[UmUm.no "!}*QR.14?&"'..":":KZ1$%)__S%9"	1d00Ek0Z((6!"I	!--!LL,,T2	'33!
&"'..":":K
 u}!LL,,T2	!IdV3KEL\L\K]"^__ ))$6)V%6%67++Zt5LPZ[`bgPh% K  MQ  SX  Zcd d ;&u}% q  sw  y~  @IJ J 662#'#5#5k4[e#5#fL#+),>{mK~*  A  A::y?V?V[d  \B  \B *3)@)@)B,0MM.,I)):)D)D$??5F5O5O26G6O6O3&^^5F5N5N26G6P6P3"-.tv{  ~G  #H  H *.v7K7K)L)7)A)A %'	"+"9"9 B13#.Hh%,,Z__ . 0 0 = = I . 0 0 = = I.  %/NNI$>	',}}':':;L'M (4'='=n>Hoo@W[i[k[k[u[u@u@I?@(?  ;. ,8+>+> 6, F,$fh ) $)<-#77+7+>+> 6, F *$($4$4T;RTY$Z$($4$4T>;K;K;T;TV[$\!", %fh ) #00 %)MM&2F2F$G	;.+0==+>+>y+I+P+P ) 3 3| C ) 6 6):N:N N,PPVPVPX ) $)<-#77#)#F#F/4}}/B/B9/M/T/T$-$7$7<$G$-$:$:i>R>R$R$($4$4T9;M;Mu$U0W X^W]W_ !-
 0:~~/E/EjnnF[F[%.%8%8$9YK G\ G""*(9+>+>"?dFVFVW[]f]o]oqvFw@xy~y~(1(>(>)BVBV(VzX0Y
 ).d<>>FZ[\F]amFm(n',QUY]Q]d<>>.B1.E.M  (C  !Ccghthvhvcwxycz  C  dC  (C  !C %.$;$;$=	'+}}Y'?$??0<0E0E-1=1E1E.&^^0<0D0D-1=1F1F."-.tv{  ~G  #H  H;.+0==+>+>|+L+S+S 1\ A,CCI68 )#(<-#77#)#A#A/4}}/B/B</P/W/W$5$E$($4$4T;Mu$U0WW]W]W_ !- 0:~~/E/EjnnF[F[%6$7<. G\ G""*(+<"=eeDDTDTUY[motDu>v0x ).d<>>FZ[\F]amFm(n',QUY]Q]d<>>.B1.E.M  (C  !Ccghthvhvcwxycz  C  dC  (C  !C $$,,QQ\MQQ33"&"4"4[$Zd"4"eK"*),>{m  LS  +T  U  U  $33D$dV_3`H ( 4 4I ( 4 4I % 3 3IKKNN CI2::y?V?V[d  \B  \B *3)@)@)B,0MM.,I)):)D)D$??5F5O5O26G6O6O3&^^5F5N5N26G6P6P3"-.tv{  ~G  #H  H (,}}V5I5I'J$0$:$:	$-$7$7	9;;CWCW[d[f[f[i[iCi$j	 %'	"+"9"9 B13#.Hh%,,Z__ ) 8 8H D ) 8 8H D.  %/NNI$>	$-NN>3=>>7NR[R]R]R`R`7`7A8OS\S^S^ShSh8h8A8945%	 %.$4$45K{5Z$[	"00 (,}}V5I5I'J$0$:$:	$-NN9l>S>SW`WbWbWeWe>e$f	$-$4$4(22kA(559M9MM%O	 %>>/8,0:-/9,09-$-$;$;$=	'+}}Y'?$0$:$:	&-l<L&M'.|=N'O$-NN9likknn>\$]	$-$4$4[K5O$P	y{{M:?)E)+y{{J7*8:S)T*8%)@040G0G&	93E3Ey^g  zI&3 1H 15-I~ !* 0 0 @I ) 0 0 2Iv.%.J	 )++ & C  EI  KP  R[\ \I(9(96;S;S'TU+++/??6+B<D!4/E77% GeY0 0 #00dEV`0a&%(:;-G~&  A  A  $33D$dV_3` , 8 8 , 8 8)2):):(;3&?#!(:M!N!MM//?	"5t[!I=??M:&46R%SN&4e%<N,0,C,C"M=3I3I9bo  BQ"/ -D -1)	> &,,^<	%,,.	??6*!*
Ii''Iv'='=>s|;&#33D$dV_3`H ( 4 4I ( 4 4I % 3 3IKKNN CI#'==1E1E#FL , 6 6I )y,:O:OS\S^S^SaSa:a bI ) 0 0"t'7'7l>T>TV['\'+'7'7l>V>VX]'^`$11\A!CI $(#5#5k4[e#5#fL *..1A1A$V[1\151A1A$V_1`#b b b11i):):;#$ghh"66	%..88	"001C1CT5]g0h&%(:9+  FM  'N  O  O "MM//	?	$,!#}}Y7&|5FG%,,\[-HI	"',i>R>R)S!T,0,C,C"Iy/A/A9 ) -D -+)	> &,,^<	%,,.	??6*!*
Ii''t|"00@@EL\L\LPNSJNHI5z	 A S	
 !!+I#11+tUWa1bd..t\9MMM  --k4S]-^L#!$6{mCTUYTZZv"wxx$**4uEEEr9   c                     |  dS )N_m2m_direct rt  s    r7   _m2m_depth_alias_namez*SQLAlchemyDataDriver._m2m_depth_alias_name{  s    [))r9   c                     |  dS )N_m2m_idr  r  s    r7   _m2m_alias_namez$SQLAlchemyDataDriver._m2m_alias_name  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_filter  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=Falsern  )sumavgcountminmaxNrM   )r~  r  r  r1   r   r  r  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)rv  r7  )r  )r;  r   r   r@   r  boolr^   right_modelsr   rl   rY   r   r   rq  ro  r  rz  _select_joined_columnsr<  )r6   fflr{  r   r  r  r  rt  r7  r  rr  related_modelrw  
fields_cls
left_modelru  ry  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_timer{  r   clone_qpkeyr  r  
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  r~  select_fromfromswith_only_columnsr   r   r  r  r\   r  r   	enumerater^   scalar)r6   r  r  r  rF   rG   r2  r3  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  r.  firstobject_to_cmfr/  r0  )r6   r  r  r  r   r!  r  r  rF   rG   r1  r3  sa_instanceres_objs                 r7   rl   zSQLAlchemyDataDriver.getB  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_idh  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_factoryt  s    "4((r9   r   )rL  s    r7   model_to_id_factoryz;SQLAlchemyDataDriver._load_m2m.<locals>.model_to_id_factorys  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$   r/  r  dictr%   rr  r  r  r`   r^  r\  r?   r`  rz   nextitervaluesr,  r}   r1   r2   r  r~  r-  r   r   r  r  r   r  rb  ra   apply_changes)Br6   objsr  r!  r  r  r  rN  to_load_mappingmy_objs_by_idmy_objs_by_model_namemodels_by_rel_fieldsobjr   r  rt  rw  model_to_idalready_loaded_obj_listrg  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_filterr3  r\  r?   r=  rH   r2  res_dictrh  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_fieldrI  sB                                                                    @r7   r/  zSQLAlchemyDataDriver._load_m2m\  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^   ra  )r6   rF   new_argsargs       r7   r)  zSQLAlchemyDataDriver.map_args~  sG     	%C#v~~.		*$		%
 r9   c                     i }|j                         D ]4  \  }}t        |t        j                        r|j                  ||<   0|||<   6 |S rj   )r@   r  r   r   ra  )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_newrC  r0  )r6   instancer  rF   rG   r2  _kwargsr   r   rD  r!  r   r_  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   r2  r  r   r   r  get_argsrD  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  rX  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_entitiesrX  	returningr   r7  r+  r   )r6   r  rX  r  r  rF   rG   r   r   r   r}   r  r  filter_criteriajoin_clausesstmtjoin_clauser3  r?  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   rM  )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   r}  now
ValueErrorr  rz   r   rX  r   r   r   )r6   r  rX  r  r   	sa_insertr   r   tblr  
table_colsrequired_namesbucketsr?  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|   rX  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  rX  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>`  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  rC  r0  )r6   r  r  rF   rG   r?   r   r   r  r  rD  r!  r   r  r_  s    `             r7   r   zSQLAlchemyDataDriver.updateW  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_request  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.commit  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_)rT  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   r  r8  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  rj  r   rk  rz  r   r  r  rp  r  r  r  r  r  r  r  r  r\   r   rl   r/  r)  r*  r  r  r  rU  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 /' /'b *&rsH!F $x.  ." D D ISei  |A).wFr * * & &( 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>r2     s    	  /   #   !    ) 0 0  !  0  - 6   M M Z Z F F 0 [ [ " "B #> B #J@H Hr9   