
    /i                       d dl Z d dlZd dlZd dlZd dlmZmZ d dlmZ d dlm	Z	 d dl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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/m0Z0m1Z1m2Z2m3Z3 ddl4m5Z5m6Z6m7Z7m8Z8 ddl9m:Z: ddl;m<Z<m=Z=m>Z> d dlm	Z	m?Z?m@Z@  G d de5      ZA G d d      ZBy)    N)defaultdict
namedtuple)copy)List)OrderedDict)	timedelta)IntegrityErrorNoSuchTableError)
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dSd	       ZdSd
Zededefd       ZdefdZdefdZdTdefdZd Zd Z d 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/j`                   G d! d"             Z1dUd$Z2edVd&e3e1   fd'       Z4dSd(Z5ed)        Z6ejn                  dd%d%fd*Z8ed+        Z9ed,        Z:d- Z;edWd.       Z<dSd/e1fd0Z=d%dd%d1d2Z>dddd%dd%d#ddd%d3
d4Z?ddd5d6Z@ddd%dd%d%d7d8ZAdXd9ZBd: ZCd; ZDd%d<d=ZEd> ZFdXd?ZGd%d%d@dAefdBZHdCdDdEZIddFdGZJddFdHZK fdIZLdJ ZMdK ZNdL ZOdM ZPdYdNZQe fdO       ZRdP ZSdQ ZTdR ZU xZVS )Z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_factoryH   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                               | _        ddlmm j                  sj                   r)ddlm} fd}|j%                  | j                  d|       | j'                          y c c}}w )	Nzsqlalchemy. r!   r   print_debugconfig)eventc                 <   | j                   }d| _         | j                         }j                  r% j                  d       |j	                  d       n0j
                  r$ j                  d       |j	                  d       |j                          || _         y )NTzPostgres: SET SESSION jit=offzSET SESSION jit='off'zIPostgres: SET SESSION jit_inline_above_cost=-1 jit_optimize_above_cost=-1zMSET SESSION jit_inline_above_cost=-1; SET SESSION jit_optimize_above_cost=-1;)
autocommitcursorORM_DISABLE_JITDEBUGexecuteORM_DISABLE_JIT_OPTIMIZEclose)dbapi_connectionconnection_recordexisting_autocommitrC   r?   r>   s       r8   apply_configz3SQLAlchemyDataDriver.__init__.<locals>.apply_config|   s    &6&A&A#.2 +)002))0MONN#:;440y{NN#rs.A +r:   connect)super__init__r2   engine_from_configr?   items
startswithreplacer5   r3   scoped_sessionr9   Sessioncmf.includer>   rD   rG   r@   listen	init_meta)
r7   argskwargskvr@   rL   r?   r>   	__class__s
          @@r8   rO   zSQLAlchemyDataDriver.__init__g   s    $)&) 33KK
 #LLNAq<<. 		-Q/2
 "~~44T5J5J5LM3!!V%D%D
 )B LLi>=s   /D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)rg   ra   orderno_partition_by_orderno_partition_by_clusterordernoF)r   rQ   
issubclassr   indexra   index_usinglistr   
class_nameappendr2   Index	tablenamehasattrri   )cls	cmf_modelindexescmf_field_name	cmf_fieldrY   rn   idx_types           r8   __get_indexesz"SQLAlchemyDataDriver.__get_indexes   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&;; & $)	  r:   c                 v    | j                   j                  |      }|r| j                   j                  |       |S N)cached_queriesgetmove_to_end)ru   keyrets      r8   	get_queryzSQLAlchemyDataDriver.get_query   s6     ""3'**3/
r:   c                    || 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  r6| j                   j                  d      \  }}t        j                  d	|       y y )
NSC_PAGE_SIZESC_PHYS_PAGESi   i         F)lastzDEV: set_query evicted key %s)r~   cached_queries_limitossysconflenpopitemloggingdebug)ru   queryr   sys_memsize_mbchunk_countqueries_limitevicted_keyrd   s           r8   	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MM9;G >r:   c                 &   |j                   }|j                  ry|j                  dkD  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        j0                         }nJt        |t        j2                        r!t        j                  |j                         }nt        |t        j4                        r!t        j6                  |j                         }nt        |t        j8                        ryt        |t        j:                        ryt        |t        j<                        ryt        |t        j>                        ryt        |t        j@                        ryt        |t        jB                        rt        jD                  d      }nt        |t        jF                        rt        jH                         }nt        |t        jJ                        rt        j0                         }nt        |t        jL                        ryt        |t        jN                        ryt        |t        jP                        rt        jR                  }n\t        |t        jT                        rt        jV                  }n1t        |t        jX                        r	ddl-m.} |}nt_        d|       t        j(                  |||j`                  |j,                  |j*                        S )	u0   Создадим SA поле для моделиNr   )primary_keynullableT)timezone)TSVECTORu"   Не найден тип поля )r_   r   r   )1rp   virtualcustom_table_norl   r   	CmfBigIntr2   BIGINTCmfIntInteger
CmfNumericNumeric	precisionscaleCmfTUUIDString
max_lengthforeign_keyrq   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   	Exceptionr_   )ru   
_cmf_modelry   _db_field_namecolumn_namesa_typerY   r   s           r8   _make_sa_columnz$SQLAlchemyDataDriver._make_sa_column   s     **$$q(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  %%''!--
 	
r:   c                 R    t        | j                        j                  ||      }|S )N)schema)r   r5   get_columns)r7   
table_namer   columnss       r8   inspect_table_columnsz*SQLAlchemyDataDriver.inspect_table_columns0  s%    $++&22:f2Mr:   ext_noreturnc                 &    | j                    d|dS )uS   Имя ext-таблицы для модели и номера расширения._ext02d)rs   rv   r   s     r8   ext_tablenamez"SQLAlchemyDataDriver.ext_tablename4  s     %%&d6#,77r:   c                     | j                  ||      }t        j                  || j                  d| j                  d       | j                  j
                  |   S )u@   SA-таблица ext-расширения (autoload из БД).Tautoloadautoload_withextend_existing)r   r2   Tabledb_metar5   tables)r7   rv   r   r   s       r8   ext_sa_modelz!SQLAlchemyDataDriver.ext_sa_model9  sK    ''	6:
T\\D'+{{D	J||"":..r:   c                     i }t        dd      D ]]  }| j                  ||      s |S | j                  ||      }| j                  |      D ]  }|d   j	                  d      s|||d   <   ! _ |S )ue  Возвращает словарь cf_*-колонок из всех ext-таблиц модели.

        Ключ — имя колонки, значение — descriptor из inspect_table_columns.
        Сканирует ext_no от 1 до 100; останавливается на первой отсутствующей таблице.
        r!   e   r   namecf_)range	has_tabler   r   rR   )r7   rv   resultr   r   columns         r8   inspect_ext_columnsz(SQLAlchemyDataDriver.inspect_ext_columns@  s     Asm 	4F>>If>E
 	 ++Iv>J44Z@ 4&>,,U3-3F6&>*4		4 r:   c                     |B| j                  ||      }| j                  j                  j                  | j                  |      S | j	                  |      }| j                  j                  j                  | j                  |j
                        S r}   )r   r5   dialectr   dp_model	__table__)r7   rv   r   r   sa_models        r8   r   zSQLAlchemyDataDriver.has_tableP  sp    ++Iv>J;;&&00jII==+{{"",,T[[(:L:LMMr:   c                 8   ddl m} i }|j                         D ]~  \  }}| j                  ||      }	 ||	      j	                  |      j                  |	j                  j                  j                  |            }
|j                  |
      j                  ||<    |S )uN  UPDATE ext-таблиц по списку obj_ids.

        Возвращает dict {ext_no: rowcount} — вызывающий код решает,
        требовать ли попадания строго в одну строку (update_v2) или
        допускать произвольное (bulk_update).
        r   update)r2   r   rQ   r   valueswherecidin_rF   rowcount)r7   s	model_clsobj_ids
ext_values	sa_updateresultsr   vals	ext_tablestmts              r8   _update_ext_tablesz'SQLAlchemyDataDriver._update_ext_tablesW  s     	3&,,. 	7LFD)))V<IY'..t4::9;;>>;M;Mg;VWDiio66GFO	7 r:   c                    | j                  d |      j                  }t        |t        j                        r| d}t        j                  d       | j                         }d| d| d| }|j                  s#|j                  d| | d|j                   d}t        j                  d	       |j                  |       t        j                  d
       |j                          t        j                  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   typerl   r   r   r   inforU   r   r_   rF   commit)r7   r   r   cmf_field_typesa_column_typer   sqls          r8   add_custom_columnz&SQLAlchemyDataDriver.add_custom_columnf  s    --dNCHHnf&8&89 ./r2N89LLNZL(B;-qQ_P`a&&%%-`ao`pqqE>#9#9":)DC78			#67	
01r:   c                    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        j                  d|       yddl}t        j                  |j                  dd             | j                  |      rt        j                  d|       yt        j                  j                  |j                   j"                        }| j%                         }	 t        j&                  d       |j)                  |       t        j&                  d       |j+                          t        j&                  d       y# t,        $ r3 |j.                  j1                          t        j2                  d|       Y yw xY w)u5   
        Создаем М2М таблицу
        Tcustom.r<   abstract
__module____qualname__u   ID Объекта)captionr   rm   left_idu   ID Элементаright_id   Имя объекта)r  r   left_name_cacheu   Имя элементаright_name_cacher   N皙?      ?u}   add_custom_m2m_model(): Таблица %s уже создана в БД. Вероятно, на другом инстансеz$add_custom_m2m_model(): create tablez"add_custom_m2m_model(): run commitzadd_custom_m2m_model(): doneuG   add_custom_m2m_model(): Ошибка создания таблицы %s)r   Fieldr   	CmfStr256r  r    randomtimesleepuniformr   r   warningr2   r   CreateTabler   r   rU   r  rF   r  r   transactionrollback	exception)r7   
model_namerZ   rv   r  smtpr   s          r8   add_custom_m2m_modelz)SQLAlchemyDataDriver.add_custom_m2m_modelx  s    #)RP"LLBU`dlpqy#\\&//CXcgostz$*LL1A1AKbmq$r !%+\\&2B2BLept%u!"l_f=	 	

6>>#s+,>>)$OO P  R[\ 	

6>>#s+,>>)$OO P  S\]  ,,Y-?-?-I-IJLLN	oLL?@IIdOLL=>HHJLL78 	oMM""$gimn	os   %A H 9IIc                 Z   |j                    d|d}dddd}t        |t        f|      }ddl}t	        j
                  |j                  d	d
             | j                  |      rt        j                  d|       yt	        j
                  |j                  d	d
             | j                  |      rt        j                  d|       yt        j                  j                  |j                  j                        }| j                         }	 t        j                   d|       |j#                  |       t        j                   d       |j%                          t        j                   d       y# t&        $ r2 |j(                  j+                          t        j,                  d|        w xY w)u   
        Создаём extension-таблицу для кастомных полей.
        Аналогично add_custom_m2m_model, но для ext-таблиц.
        Extr   Tr
  r<   r  r   Nr  r  u}   add_custom_ext_model(): Таблица %s уже создана в БД. Вероятно, на другом инстансеz'add_custom_ext_model(): create table %sz"add_custom_ext_model(): run commitzadd_custom_ext_model(): doneuG   add_custom_ext_model(): Ошибка создания таблицы %s)rp   r  r    r  r  r  r  r   r   r  r2   r   r  r   r   rU   r  rF   r  r   r  r   r!  )	r7   r   r   rp   rZ   rv   r  r   r   s	            r8   add_custom_ext_modelz)SQLAlchemyDataDriver.add_custom_ext_model  si   
 ",,-S=
#

 l_f=	 	

6>>#s+,>>)$OO P  R[\ 	

6>>#s+,>>)$OO P  R[\  ,,Y-?-?-I-IJLLN		LLBJOIIdOLL=>HHJLL78 	MM""$gimn	s   A!E/ /;F*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        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        |t        f|      }|S )$NTr
  r<   r  )   Идентификатор объекта3   Автоматически генерируетсяFr  commentr   r   readonlyvisibler   u   Значениеr  rm   r      Сортировкаr   r  rm   r.  r   r_   rk      Код3   Код в реальном мире из жизниr  ra   r,  r-  r   code:   Код родителя в каскадном выбореr  r-  r   rm   choice_parent_id   Скрыть
cmf_hidden!   Конфигурация поляcust_field_conf_idu%   Предыдущее значениеprev_ext_valueu   Дата создания)r  autoauto_now_addrm   r   cmf_created_atu   Дата изменения)r  r>  auto_nowrm   r   cmf_modified_at)
r   r  r   r   r   CmfStr64r   r   r  r   r7   r"  rZ   rv   s       r8   gen_custom_choice_model_extz0SQLAlchemyDataDriver.gen_custom_choice_model_ext  s   ")RP||OO?I
t  MM&
v
 #LLMM*
y  MMI
v &,\\OOP&
!"  &||NN" 
| (.||OO7(
#$ $*<<MM;$
  $*<</$
  %+LL1%
 ! i\6:	r:   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  r)  r*  Fr+  r   r  r/  r   r0  r   r1  rk   r2  r3  r4  r5  r6  r7  r8  r9  r:  r;  r<  )	r   r  r   r  r   rC  r   r  r   rD  s       r8   gen_custom_choice_modelz,SQLAlchemyDataDriver.gen_custom_choice_model  sI   ")RP||OO?I
t  +
v
 #LLMM*
y  OOI
v &,\\OOP&
!"  &||NN" 
| (.||OO7(
#$ i\6:	r:   c                 n   | j                  |      }t        j                  j                  |j                  j
                        }| j                         }	 |j                  |       |j                          y# t        $ r3 |j                  j                          t        j                  d|       Y yw xY wur   
        Создаем пользовательский справочник выбора таблицу
        u/   Ошибка создания таблицы %sN)rG  r2   r   r  r   r   rU   rF   r  r   r  r   r   r!  )r7   r"  rv   r#  r   s        r8   add_custom_choice_modelz,SQLAlchemyDataDriver.add_custom_choice_modelU  s     00<	  ,,Y-?-?-I-IJLLN	XIIdOHHJ 	XMM""$ ORVW	Xs   !A8 89B43B4c                 |   | j                  |      }t        j                  j                  |j                  j
                        }| j                         }	 |j                  |       |j                          y# t        $ r:}|j                  j                          t        j                  d|       Y d}~yd}~ww xY wrI  )rE  r2   r   r  r   r   rU   rF   r  r   r  r   r   r!  )r7   r"  rv   r#  r   es         r8   add_custom_choice_model_extz0SQLAlchemyDataDriver.add_custom_choice_model_exte  s     44Z@	  ,,Y-?-?-I-IJLLN	XIIdOHHJ 	XMM""$ ORVWW	Xs   !A8 8	B;0B66B;c                 `   |j                   }| j                  j                  |      }|s|j                  }g }g }ddi}|j                  j                         D ]>  \  }}	|	j                  dkD  r|}
| j                  ||	|
      }|.|j                  |       @ |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
        r   Tr   )__tablename____table_args__)__name__models_registryr   rs   r   rQ   r   r   rq   extend"_SQLAlchemyDataDriver__get_indexestupler   r   r  sa_base_model)ru   rv   r"  r   rs   
sa_columnsrP  __table_kwargs__rx   ry   sa_field_name	sa_columnsa_model_kwargsr   s                 r8   dp_model_clsz!SQLAlchemyDataDriver.dp_model_clsu  sC    ''
&&**:6 "++IJN 148-6-=-=-C-C-E 	-)	,,q0 .//	9mT	$!!),	- !!#"3"3I">?!!  "+"'"7O ""z#B!AFFAI#BCJ):):(<oNH.6C
+ $Cs   'D+c                 $    | j                  |      S r}   )r\  )r7   rv   s     r8   r   zSQLAlchemyDataDriver.dp_model  s      ++r:   c                 6    t        t        |j                        S )uG   
        Вернём CMF модель для SA модели.
        )getattrr   rQ  )r7   r   s     r8   rv   zSQLAlchemyDataDriver.cmf_model  s     vx0011r:   c                 6    t        |t        j                        S r}   )
isinstancer-   rV  )r7   dp_instances     r8   is_instancez SQLAlchemyDataDriver.is_instance  s    +';'I'IJJr:   c                     i }|D ]9  }|j                   j                  ||j                   j                  j                  <   ; t        j                  j                  |d|      S )N
table_type)r   r   fullnamer2   r3   polymorphic_union)r7   
cmf_modelsaliasr   models        r8   _union_modelsz"SQLAlchemyDataDriver._union_models  sW     	QE8=8P8PF5>>++445	Q ~~//eLLr:   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r}   )KeyErrorr2   r  castnulllabeltype_coerce)r   table
cast_nullscolnamemapstypess     r8   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)r2   util
OrderedSetra  r  Selectri  r   r   addr  rQ   rq   selectliteral_column_quote_ddl_exprrr  r   r_  r   correlate_except	union_all)	table_maptypecolname	aliasnameru  colnamesr   rt  mr   rx  r   type_r   rv  rw  left_field_name
left_tablesub_ffls      `         @@r8   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*re  )p_unionT)r   r   rf  lateral)r7   r  right_tableri  r  right_modelmodels_is_unionr  r  	join_subqr  s    `  `   `   r8   _union_models2z#SQLAlchemyDataDriver._union_models2  sb    HLJ	FZ 	 	LA78zz7K7KIajj**334	L%i>FFuMMr:   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     r8   _parse_paramsz"SQLAlchemyDataDriver._parse_params  se    + !9!9fQi22AY'!!9fQi228&'JJr:   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NULLr  r  r  r  )r  r  )r  r  r  r  r  r  r  r  r  r  r  )r   likeilikeop)operfieldvals      r8   _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>#&&r:   c                   X    e Zd ZU eed<   eed<   eed<   eed<   eed<   eed<   dZeed<   y)	SQLAlchemyDataDriver.JoinDatar  r  ri  r  r  right_modelsNjoin_condition)rQ  r  r  object__annotations__strro   r   r:   r8   JoinDatar  <  s/    
!%%r:   r  Tc           
      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   Недопустимый тип поля для вложенной фильтрации r`   up   . Вложенная фильтрация возможно только для CmfRelation и CmfGenericRelation_sub__uj   Не возможно построить запрос для вложенной фильтрации по u   , т.к. у поля u#    не указаны related_modelsr   r!   r   T)r  r  )rp   instance_classr   r   _raise_invalid_fieldrl   r   r   CmfSubclassedGenericRelationr   related_modelsr   r2   r3   aliasedr   r   r  rk  r  )r7   rj  r  
field_name
from_aliasis_models_required	field_clsr  
alias_partr  r  r  	join_datas                r8   _calc_join_dataz$SQLAlchemyDataDriver._calc_join_dataF  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	r:   Fjoinsc           	      J   |r
t               n_| j                  j                         D ch c]<  }t        |t        j
                  j                  j                        r|j                  > c}}|D ]  }|j                  |v r|j                  '| j                  |j                  |j                        } E| 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_fromsra  r2   r  
selectableAliasr   ri  r  	outerjoinr  r_  r  r   r  r   )r   r  forceri  available_joinsr  s         r8   _make_joinsz SQLAlchemyDataDriver._make_joinsi  s     $)#%99;/C%!:!:!@!@A JJ/C
  		vI/1''3	(=(=y?W?WX))I0022y7P7P6QQT4UVZcZoZoZqZqZtZttv		v /Cs   AD c                    d }g }|d }|j                   j                  }n|j                  }|j                  d      D ]K  }| j	                  ||||      }|j                  |       |j                  }|j                  }|j                  }M |S )Nr`   )	r   r   r   splitr  rq   ri  r  r  )r7   	join_pathrj  r  r  r  r  r  s           r8   _calc_joins_by_pathz(SQLAlchemyDataDriver._calc_joins_by_path  s    
J11J#J#//#. 	/J,,UJ
JWILL#"J))E"..J	/ r:   c                     t        |j                        j                  dd      }t        |  d|j                   d|       )N,z,
u+    не существует у модели u   , но есть: 
)r  r   rS   r   rp   )r  rj  fields_s      r8   r  z)SQLAlchemyDataDriver._raise_invalid_field  sV    ell#++C7ZL(STYTdTdSeex  zA  yB  C  D  	Dr:   c	                 +  B |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                  ||       BfdB B|      }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>                  rI|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 |jf                  so|#jc                  ||k(  t	        j
                  | ji                  d"||      | ji                  d"|jT                  jj                  |                  je                         }#n|#jc                  t	        j
                  | ji                  d"||      | ji                  d"|jT                  jj                  |                  }#|#jm                  |      }#|#jo                  |      }#|#jq                         }#|j_                  |#t        |#jT                        d   |k(        }||d"k(  rt        |#jT                        d   d k7  fS t        |#jT                        d   d k(  fS |j@                  r(| j%                  tN        jP                        }$|d	v rb|jZ                  j]                  |$      jc                  |$j`                  |k(  |$jV                  |j2                  k(        je                         }#||# fS |jr                  s{|jZ                  j]                  |$      jc                  |$j`                  |k(  |$jV                  |j2                  k(  | ji                  d"|$jj                  |            je                         }#n
t        jt                  jw                  t        jx                  j{                  |$j`                  g|$g#      jo                  |$j`                        j}                  | ji                  d"|$jj                  |            j}                  |$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 |j~                  sN|jZ                  j]                  |%      jc                  |&|k(  | ji                  d"|'|            je                         }#nt        jt                  jw                  t        jx                  j{                  |&g|%g#      jo                  |&      j}                  | ji                  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                  jj                  |+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#                  |.|-jj                  |+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#                  |.|-jj                  |+jT                  j                  k(        },|,jc                  t	        j
                  | ji                  d"|-j`                  |      | ji                  d"|-j                  |            |-jV                  d5k(        },| j=                  ||||      }|t	        j
                  | ji                  d"||      | ji                  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||      }|| ji                  d"||:      fS | j=                  ||||      }|r|j                  d>      r`|j                  j                  |      };|;rB|;j                  dkD  r2|j                   d?|;j                  d@}<|j                  j                         D ]5  }=t        |=dA      s|=j                  |<k(  s | j=                  |=|||      } n || j%                  |      j&                  }>|>j                  }?	 t	        j                  |<|?d| j                  dB       |?j                  |<   }@|@j                  |< dCD      }A|j_                  |A|>jT                  j                  |AjT                  j                  k(        }| j=                  |A|||      }|t        d| dE| dF      || ji                  |||      fS # t        $ r Y 4w xY w)GNr   )field_tableinclude_deletedinclude_dummyANDr!   OR)cmdr  r  r  order_by   )r  r  ut   Операция order_by в фильтре должна быть в формате: ["order_by", "=", [поля..]]r   rj  r`   Fr  )r  TANYr  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   r=   .u<   collect_filter_exp: Значение не загруженоr   )rV   r>   r?   ra  r   _valuerE   valuero   rU  r   r   dict)right_r>   r?   sub_rnormalize_rights       r8   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)r  r  u   Правое значение для IN, NOT IN для m2m должно быть list, т.е. в квадратных скобках, например "field", "IN", "[obj.id]"u   Недопустимая операция над m2m полем (сравнение = только на None), допустимые IN, NOT IN, = None)r  r  r  r  r?   
with_aliasu   В таблице u3    нет поля id для фильтрации m2muD   Надо указать для поля либо left либо rightr  ry  )r  r  uG    нет поля id для фильтрации в подзапросе)r  r  r  cmf_deletedr  r  Fis_dummyr  r  FzNOT uh   Недопустимая операция над m2m полем, допустимые IN, NOT IN, = Noner  ul   Недопустимая операция над backref полем, допустимые EXISTS, NOT EXISTSu7    нет поля id для фильтрации backrefr{  r  r  
rg_members)r  r  uA   History для м2м полей не поддерживаетсяobj_idr  )r  '  )r"  r  search_queryonly_idssliceNOTFOUNDr   r   r   r   r   _fltr  u    нет поля u    для фильтрации)Wra  ro   collect_filter_exprq   r2   or_r   r   order_queryr  r  r   r   rl   
CmfM2MBaser   r   joinr   r   
rpartitionr  r  r  r  rp   r  rU  rV   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exists-ORM_RELCACHE_EXISTS_VIA_JOIN_ON_EDGE_OPTIMIZEr  child_idwith_entitiesdistinctsubqueryORM_RELCACHE_EXISTS_VIA_JOINr3   r  r  r  r   ORM_M2M_EXISTS_VIA_JOINr  r   r_  rt   rR   backrefCmfRelationBaseparent_coder   CmfOrmColumnHistoryCmfFullSearchfulltext_searchr   rs   r  r  r   r/   r   r5   r   ri  r
   )Cr7   	in_filterrj  r   r   r  r  r  r  
filter_resr\   expr  r  r  
left_partsr  r  r  rd   r  r  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_idsfield_cls_extext_table_namefrom_
main_tabler/   ext_sa_table	ext_aliasr  sC                                                                     @r8   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%SS+7+>+> 6, F *$($4$4T;RTY$Z$($4$4T>;K;K;T;TV[$\!", %fh ) ,8+>+> *$($4$4T;RTY$Z$($4$4T>;K;K;T;TV[$\!",L ,8+E+EF\+]L+7+@+@AW+XL+7+@+@+BL %*OOL$|~~BVWXBY]iBi$jE#(TUY\$|~~*>q*AT*I#~~_cdpdrdr_stu_vz~_~#~~,, !%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DOOE$:!LL,,T2M!>!>!B$)OO#4D9V9VWZ8[!\"__==? Euf-%**2N'+'9'9%uYc'9'd
  '!%u!5!?!?J)22H	i"((D7;{{TXZ
 (0~'F$0$6$6~>Nd<S$6$T	 %	:<<??ikknn;\ ]'+'9'9)T5]g'9'h 2;-?PQUPVVrsttd&&t\5AAA , s   T$AW W	AWWAWc                     |  dS )N_m2m_directr  r  s    r8   _m2m_depth_alias_namez*SQLAlchemyDataDriver._m2m_depth_alias_name  s    [))r:   c                     |  dS )N_m2m_idr  rX  s    r8   _m2m_alias_namez$SQLAlchemyDataDriver._m2m_alias_name  s    W%%r:   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   r  )	r   ra  r  r   loadsro   rQ   r   rq   )r7   rj  rZ   smart_filterr[   r\   s         r8   _get_filterz SQLAlchemyDataDriver._get_filter  s     zz(B/lC(::l3L
<?D AL LLN 	2DAqELL ##QaL1	2 r:   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=Falser  )sumavgcountminmaxNr`   )r  r  ra  r2   r  r  r  r   r  r_  r   r   rr  r  rS   )rt  r   r   r  rR  	func_namecolumn_name_shortr   s           r8   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 r:   parent_joinc                 ^   |r|j                   n|j                  j                  }i }|s't               }|D ]K  }	|j                  j                  |	      }
|
s!|
j                  dkD  s1|j                  |
j                         M t        |      D ]  }|j                   d|d}|j                  }	 t        j                  ||d| j                  d       |j                  |   }|j!                  |      }|||<   | j#                  |||ddg |j$                  j&                  |j$                  j&                  k(  	      }|j)                  |        |j+                         D ]  \  }	}| j-                  ||	t/        |      
      }||j)                  |       8|s|r|j                  j                  |	      }
|
rc|
j                  dkD  rT|j                  |
j                        }|7| j-                  ||	d
      }|!|j)                  |j1                  |	             |s|r|j2                  xs g n|g}|D cg c]e  }|j                  j                  |	      x}
rFt5        |
t        j6                  t        j8                  f      rt5        |
t        j:                        s|
g }}|sH|d   }
|
j<                  }|r|j                   nd}| j?                  |||	|d|      }|s|j)                  |       | jA                  ||||jB                  |        y# t        $ r Y w xY wc c}w )u2   Соберём поля и таблицы по fflr   r   r   Tr   r  r<   N)r  r  ri  r  r  r  r  r  F)r  r  )ri  )"r  r   r   r  r   r   r   r  sortedrs   r/   r2   r   r5   r
   r   ri  r  r   r   rq   rQ   r  boolrr  r  rl   r   r   r  r  r  _select_joined_columnsr  )r7   fflr  r   rj  ri  rt  ext_table_aliasesext_nosr  r  r   rQ  r/   rT  rU  r  r  r   
ext_columnr  related_model
fields_cls
left_modelr  s                            r8   rm  z+SQLAlchemyDataDriver._select_joined_columns  s2   +6''ENN<T<T eG! ;
!LL,,Z8	!:!:Q!>KK	 9 9:; !/ ($)OO#4D!E >>$$^X37;;PTV  (~>(..N.C	,5!&) MM$ )($& $!##(77::#? * 	 Y')(, $'99; %	sJ''zd;FW'XF!v&#4!LL,,Z8	!:!:Q!> 1 5 5i6O6O PI ,%)%7%7	:Z_%7%`
%1#NN:+;+;J+GH$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+rK%	s! ( HXs   1$L9A*L*	L'&L')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 r,|j/                  |j*                  j,                  | d	          |j1                  d
      s|j2                  D ]   }|d   |k(  s|j/                  |d              |j4                  | }|S )Nr   	CMF_CACHEzquery: full_fields_loadT)r  g{Gz?r  r  r{  r   r   expr)r   rU   rV   rx  hashrQ  r  r   _clonewith_sessionr  rm  r   r  r   r   r   r   r`  r  r  r   r   rq   rR   column_descriptionsru  )r7   rj  rz  r  ru  r  rY   rZ   r   r   rx  r   r   start_calc_timer  r   clone_qpkeyir_  
filter_expr   cds                          r8   _create_queryz"SQLAlchemyDataDriver._create_query  sq   =='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' 
"("4"4"6"66NN8#5#5#7#7#DE#}C(H,>,>,@,@@NN8#5#5#7#7;-s8K#LM ++E2#77 "f:4#NN2f:6!"
" #ENNG,Er:   )
r  rz  r  
for_updatemapperr  load_m2mru  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: поле -> значение
        )rz  r  r  ru  r  )r  r  rj  simplerz  rj  r{  )ra  r#   
get_mappermap_args
map_kwargsr  with_labelsr  r  alllist_to_cmfwith_for_update	_load_m2mpost_mapping_hook)r7   rj  r  rz  r  r  r  r  r  ru  r  r  rY   rZ   mapper_is_my_argsqsql_resres_objss                      r8   ro   zSQLAlchemyDataDriver.list2  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,,.Or:   )rz  ru  c                   | j                  |      }| j                  |      } | j                  |fd|i|j                         }|r| j	                  |      }g }	|D ]  }
|
|j
                  j                  v r)|	j                  |j
                  j                  |
          D|
j                  d      sV|j                  j                         D ]<  }t        |d      rt        |j                  |
d      nd}|+|	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-                  |      j1                         }|S )r  rz  r   r   Nr  rd  )r  r  r  r  r   r   r   rq   rR   r  r  rt   r_  select_fromfromswith_only_columnsr   rd  ru  r  ro   r  rF   	enumeratescalar)r7   rj  rz  ru  rY   rZ   r  r  r   r   r   rR  rx  count_qres_listresrowrow_resr  rd  s                       r8   rd  zSQLAlchemyDataDriver.countT  s@    d#(D
$4
8>

+- 	
 }}U+HG' 	"("4"4"6"66NN8#5#5#7#7#DE ++E2!"!=!=!? "ELUTWEXgegg{DA^b?#NN3/!	"	"-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r:   )r  rz  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 - другие поля: поле -> значение)rz  r  r  r   r!   )r  rj  r  )r  r  r  N)ra  r#   r  r  r  r  r  r  r  firstobject_to_cmfr  r  )r7   rj  r  rz  r  r  r  r  rY   rZ   r  r  sa_instanceres_objs                 r8   r   zSQLAlchemyDataDriver.get  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 r:   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 r}   )r   r  )obj_is_heavys    r8   r  z.SQLAlchemyDataDriver._load_m2m.<locals>.obj_id  s    ww~~%77Nr:   c                      d } t        |       S )Nc                       t        t              S r}   )r   ro   r  r:   r8   id_to_list_factoryzWSQLAlchemyDataDriver._load_m2m.<locals>.model_to_id_factory.<locals>.id_to_list_factory  s    "4((r:   r   )r  s    r8   model_to_id_factoryz;SQLAlchemyDataDriver._load_m2m.<locals>.model_to_id_factory  s    )122r:   .u#   Не загружено id поле:r   r   r  )rz  r  r  r{  r{  r  r  r  r  )rz  r  r  r  r  r=   zORM: skip load field r`   z die no related modelsr!   re  r  r  F)rz  r  r  r  )7ra  r$   r   ro   rq   rp   r_  r   rl   r   r   r#  r	  CmfBackrefBaserQ   r   r  _oldid_fieldnamer   setattr	partitionr%   r  r"  r  r&   r  r  r  rs   rV   r>   r?   rE   r   nextiterr   r  r   r2   r3   rg  r  r  r   rS  r  r  r   r  r   rt   apply_changes)Br7   objsrz  r  r  r  r  r  to_load_mappingmy_objs_by_idmy_objs_by_model_namemodels_by_rel_fieldsobjr"  rj  r  r  model_to_idalready_loaded_obj_listr  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_filterr  r>   r?   r  r[   r  res_dictr  m2m_idsub_objsref_obj_listrD  rE  r9  r   rF  rG  	m2m_queryid_by_modelsmy_id_by_sub_idmy_idsub_idsub_id_listmy_objmy_field	obj_fieldr  sB                                                                    @r8   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 r}   )ra  r   r   rq   r  )r7   rY   new_argsargs       r8   r  zSQLAlchemyDataDriver.map_args  sG     	%C#v~~.		*$		%
 r:   c                     i }|j                         D ]4  \  }}t        |t        j                        r|j                  ||<   0|||<   6 |S r}   )rQ   ra  r   r   r  )r7   rZ   
new_kwargsr[   r\   s        r8   r  zSQLAlchemyDataDriver.map_kwargs  sL    
LLN 	"DAq!V^^, !
1 !
1		"
 r:   )	no_reloadc                v   | j                  |      }| j                  |      }| j                         }| j                  |j                        } |       }	t        j                         }
|
j                  ||	       	 |j                  |	       |j                  |	g       i }t        |      }|j                  j                         D ]t  \  }}|j                  }|dkD  s||vri ||<   t        ||      }t        |t               r+|j"                  du s|j$                  rX|j'                         }|du rm|||   |<   v |rddlm} |j,                  }|j.                  }|	j0                  }|j                         D ]u  \  }}|j2                   d|d}t)        j4                  ||d| j6                  d       |j8                  |   }||d	<   |j;                   ||      j=                  |             w d|_)        |ry
|
jU                  |	|      }|
jW                          d|_)        |S # t>        $ rd}|j@                  jC                          t        |jD                  tG        jH                  tJ                    rtM        |      |tO        |      |d
}~wtP        $ r |j@                  jC                           w xY w)um   
        no_reload - не загружать объект из базы и не возвращать
        objectsr   .)insertr   r   Tr   r   N)
cmf_entity),r  r  rU   r   r]   r#   r  cmf_to_objectr  flushr  r   rQ   r   r_  ra  r   r  r   	db_formatr2   r  r   r/   r   rs   r   r5   r   rF   r   r	   r  r   origr   lookupr   r   r   r   is_newr  r  )r7   instancer  rY   rZ   r  _kwargsr   r   r  r  ext_datar   r  r  r   r  	sa_insertrS  r/   r  r   rQ  r   rL  r  s                             r8   createzSQLAlchemyDataDriver.create  s    d#//&)LLN==!3!34j&&(X{3+	EE+GG[MG* HXI)2)9)9)?)?)A 7%
I"22A:X-+-(!(J7C!#w/::,$!mmocz 36HV$Z07 :%//
%..$$,NN$4 ALFD(1(;(;'<D%MN$$^X37;;PTV ( ?I!'DJIIi	299$?@A& "";8"D  "

'  	1MM""$!&&&--0@"AB'*1&q)q0  	MM""$	s!   <A"H( DH( (	J81AJ(J8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r}   r_  .0fr  s     r8   	<genexpr>z.SQLAlchemyDataDriver.delete.<locals>.<genexpr>       'K!(<'K   N)r  r  rU   r   r]   r  r   rU  r   r   deleter   r  r   )r7   r  rY   rZ   r  r  r   r   r  get_argsr  rL  s    `          r8   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   rU   r   r`  r  r  r  )r7   rj  r  r  rZ   r   r   r   r_  r  
delete_cnts              r8   bulk_deletez SQLAlchemyDataDriver.bulk_delete"  s    =='LLN!''v6 $ 7 7eXuoer !8 !tE:LL,E\\g\>
r:   r{  r   c                   ddl m} i }i }	|j                         D ]P  \  }
}|j                  j	                  |
      }|r|j
                  nd}|dkD  r||	j                  |i       |
<   L|||
<   R | j                  |      }| j                         }|j                  |      }| j                  ||      }|r+| j                  ||||||      \  }}|j                  |      }|j                  |j                        }|j                         D cg c]  }|d   	 }}|rR|rP ||      j!                  |      j#                  |j                  j%                  |            }|j'                  |       |	r|r| j)                  ||||	       |S c c}w )Nr   r   r{  )r2   r   rQ   r   r   r   
setdefaultr   rU   r   r`  r  r  r  r   r  r   r   r   rF   r   )r7   rj  r   r  r  rY   rZ   r   main_valuesext_values_by_tabler[   r\   r  r   r   r   r   r_  r  id_queryr  updated_idsr   s                          r8   bulk_updatez SQLAlchemyDataDriver.bulk_update.  s   %  LLN 	#DAq((+I2;Y..Fz@A#..vr:1=!"A	# =='LLN!''v6 $ 7 7eXW\n}FS !8 !UE:LL,E &&x{{3)18#s1v88;(#**;7==,D IIdO ;##Auk;NO 9s   Fr   )
chunk_sizec                   ddl m} ddlm}m} |sg S | j                  |      }|j                  }|j                  D 	ch c]  }	|	j                   }
}	i }t               }|j                  j                         D ]-  \  }}|j                  }|dkD  s|||<   |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 t1        dt3        |      |      D ]*  }||||z    }|j5                  |j7                  |             ,  |r|j8                  } |t"              } |D ]m  }|d   }! |t:              }"|j                         D ]  \  }}||v s||   |"|   |<    |D ]-  }|"j=                  |i       }#|!|#d<   | |   j)                  |#       / o | j                         D ]  \  }}$|j>                   d|d	}%t        j@                  |%|d
| jB                  d
       |jD                  |%   }& ||&      }' |t"              }(|$D ]-  })|(t%        |)j'                                  j)                  |)       / |(j                         D ]H  \  }}t1        dt3        |      |      D ]*  }||||z    }|j5                  |'j7                  |             , J  |S c c}	w c c}	w c c}}w c c}w # tF        $ r |jH                  jK                           w xY w)Nr   r  )r  r   r   )r@  rB  u   bulk_insert: колонка 'u>   ' NOT NULL без default; передайте значениеr   r   Tr   )&collectionsr   r2   r  r   r   r   r   r   r  r   rQ   r   r  r   server_defaultr_   ro   	frozensetkeysrq   rU   now
ValueErrorr   r   rF   r   r/   r  r   rs   r   r5   r   r   r  r   )*r7   rj  r   r  r   r  r   r   tblr   
table_colsext_field_nosrp  r  r  r   required_namesbucketsr  r[   r\   ridsr   	base_stmtkeysetrowsneed_addr   r  batchr/   ext_rows_by_tabler  row_extext_rowext_rowsrQ  r   ext_stmtext_bucketsers*                                             r8   bulk_insertz SQLAlchemyDataDriver.bulk_insertV  sD   +8I=='  &)kk2aff2
2 %%*\\%7%7%9 	$!J	..Fz,2j)F#		$  KK
::!&&D.  (QYY-> FF
 
 d# 	3C"%))+A$!QjAAAAIaffh'(//2	3 !''1qw''LLN3	!#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 <<$/$5!! 
BC YF)$/G.;.A.A.C J*
F%,:=j/GFOJ7J #* B")++fb"9(.)&188AB
B ):(?(?(A >$FH(-'8VCL%IN$$^X37;;PTV ( ?I(3H"-d"3K& E#Ibggi$89@@DE(3(9(9(; >!&q#d)Z!@ >A$(1z>$:EIIhooe&<=>>> JW 3
 B (h  	MM""$	s2   N=7AO#O0O)OC3O <E O %O7ry  c          
         ddl m} | j                         }| j                  t	                    }t	              j
                  }| j                  t        fd|D                    }	i }
i }t	              j                  j                         D ]  \  }}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 d| d|       |j6                  }|dkD  r||j9                  |i       |<   n||
|<   |   j0                  sd|   _         |
s|st;        j<                  d d	d
       S 	 |
r ||      j?                  |
      }|jA                  t%        ||d         |	d   k(        jC                  |jD                        }|jG                  |      jI                         }tK        |      dk7  rtM        d dtK        |             |rit	              }|	d   }| jO                  |||g|      }|j                         D ]1  \  }}|dk7  s| jQ                  ||      }tM        d| d| d| d       S # tR        $ rb}|jT                  jW                          t'        |jX                  t[        j\                  t^                    rta               |tc               |d }~wt4        $ r |jT                  jW                           w xY w)Nr   r   c              3   6   K   | ]  }t        |        y wr}   r   r  s     r8   r  z1SQLAlchemyDataDriver.update_v2.<locals>.<genexpr>  r  r  .u%   Попытка update field=Ellipsis r  FzDEV: warning! UPDATE u*    не содержит изменений.WARNING)levelr!   zUPDATE u8   : ожидалась 1 строка, обновлено u    затронул u    строк для id=u   , ожидалась 1)2r2   r   rU   r   r  r   r  rU  r   rQ   rl   r   r   r   r   r   r   r   r_  ra  r   r  r   
is_changed	orm_dirtyr  r   r   r  r   r   r   r   	returningr   rF   fetchallr   r   r   r   r	   r  r   r  r   r  r   r   r   )r7   r  rz  rY   rZ   r   r   r   r  r  r   r   r[   r\   vvr   r   r&  r   r  	rowcountsrcrQ  rL  s    `                      r8   	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zQRSTRUUVWYVZ [\\&&Fz79
%%fb1!4q	{$$(-%?	.B jGG+H:5_`hqrO#	h'..v6zz'(DG"<"KLVVW_WbWbcyy//1t9>%!(+cdghldmcno 
  N	!! 33Ay6(JW	"+//"3 JFBQw)-););Iv)N)%n%55Gt L))/0FH *   	0MM""$!&&&--0@"AB')q0&(a/  	MM""$	s    CM %(M 	OAN55(O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  rz  c              3   6   K   | ]  }t        |        y wr}   r   r  s     r8   r  z.SQLAlchemyDataDriver.update.<locals>.<genexpr>	  r  r  r  )r  rz  )rV   r?   ORM_RAW_UPDATE_V2r<  r  r  rU   r   r  r   rU  r   r   r#   r  r  r  r	   r  r   ra  r  r   r  r   r   r   r   r  r  r  )r7   r  rz  rY   rZ   r?   r   r   r  r  r  r  rL  r  r  s    `             r8   r   zSQLAlchemyDataDriver.update	  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 r}   )rN   before_request)r7   r]   s    r8   rA  z#SQLAlchemyDataDriver.before_request-	  s     r:   c                 8   ddl m} |j                          |j                          t	        dd      }| j                         j                           |        t	        dd      }| j
                  j                           |        t        d       t                y )	Nr   rw  z#SQLAlchemyDataDriver.Session.commiti,  z#SQLAlchemyDataDriver.Session.removed   Tnear_commit_or_rollback)
rV   rx  cache_unlockcache_transaction_startr)   rU   r  remover'   r(   )r7   rx  
prof_points      r8   r  zSQLAlchemyDataDriver.commit0	  ss    ) ))+$%JCP
$%JCP
 	#4@r:   c                     ddl m} t        d       |j                          | j	                         j                          | j                  j                          t                y )Nr   rw  TrD  )rV   rx  r'   rF  rU   r   rH  r(   )r7   rx  s     r8   r   zSQLAlchemyDataDriver.rollback@	  sA    )"4@ !r:   c                 B     | j                         j                  |i |S r}   rU   r   r7   rY   rZ   s      r8   r   zSQLAlchemyDataDriver.queryH	       #t||~##T4V44r:   c                 B     | j                         j                  |i |S r}   rL  rM  s      r8   query_deprecatedz%SQLAlchemyDataDriver.query_deprecatedK	  rN  r:   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      rr}j                  j                  |	      }|r`|j                  dkD  rQj                   d|j                  dd|	 }|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*                  j0                        r|t3        d      z   }|
rt)        j4                  |      }|j7                  |      }2 |S )u3   Сортировка по логике моделиr   )
QueryProxyz--r   cmf_column_namec                     d}	 | j                  d      \  }}}|s|} n|} |r	| d| d}n| d}-|sj                   d}| |  S )Nr<   r`   rd   _sub_)r  rs   )rS  alias_prefixp1rd   p2rj  s        r8   calc_dp_column_namez=SQLAlchemyDataDriver.order_query.<locals>.calc_dp_column_named	  s|    L+55c:	Ar&(O"$&2^1RD#>L&(T<L   "'//!2!4"^O#455r:   F-r!   NTr   r   r   rd   r   r|  u   Не найдено поле uK    или тип поля не поддерживает сортировку.r  r<   )minutes)cmf.data_providers.baserR  orderingr   r  rR   r  r  r   r   r   r   rs   r  r   rV   r?   ORM_ORDERBY_IDX_SKIPra  r  r2   rw  r   r   DateTimer   descr  )r7   r   r  r  r  rj  rR  order_fieldsrY  r   
order_descdp_column_name	dp_columnrP  
ext_prefixcolumn_descriptionr?   s        `           r8   r  z SQLAlchemyDataDriver.order_queryN	  s   6 t+L >>/RL',,.L#L E*:TF"L	6 	6    7	.CJ~~c"!"g!
 15N((..q13377GI  !,,221577;;C@	  S^^E%:u % 0 0 5 ]%B%BQ%F$)OO#4D9V9VWZ8[[\]`\a!bJ % 0 0 6 6q 9 ; ; ? ?
 KI  */*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-Eo7	.p r:   c                 $    t         |   |       y r}   )rN   make_models)ru   r  r]   s     r8   rh  z SQLAlchemyDataDriver.make_models	  s    G$r:   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_  ra  r   r  data_sourcesr   r   r   )r7   r"  rv   s      r8   rX   zSQLAlchemyDataDriver.init_meta	  s{     f+ 	%J
3Ii79;M;M %%$))9;Q;Q*Q))dii;M.MMM)$	%r:   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)rU   r   
connectionget_table_namesFileExistsErrorrF   r  r   
create_allr5   r   pathr
  getcwdr   set_main_optionr?   r   stamp)r7   r   	inspectoralembic_config_filealembic_configs        r8   init_dbzSQLAlchemyDataDriver.init_db	  s    LLN ALLN+		 9 9 ;;!"@AA			;<	
, ggll299;F 34&&'7EU9VWnf-r:   c                 L    | j                   j                  j                          y r}   )r5   pooldisposer6   s    r8   r   z'SQLAlchemyDataDriver.close_all_sessions	  s      "r:   r}   )NN)NTNN)F)NT)FF)NNNN)WrQ  r  r  __doc__rR  r2   MetaDatar   extdeclarativedeclarative_baserV  r   r~   r   r9   rO   classmethodrT  r   r   r   r   staticmethodintr  r   r   r  r   r   r   r  r$  r'  rE  rG  rJ  rM  r\  r   rv   rc  rk  r  r  r  dataclasses	dataclassr  r  r   r  r  r  r  r  rY  r\  r`  r  rm  r  ro   rd  r   r  r  r  r  r  r  r  r0  r<  r   rA  r  r   r   rP  r  rh  rX   rz  r   __classcell__)r]   s   @r8   r-   r-   #   sa   8 O!j!!#GNN..??& @ M !]N=>#J 3 3j   H H* L
 L
\ 8 8 8 8/c /  N N2$$oN&PQf9vX X  ' 'R,2K
MQNf K K  '  'D & & &!F $x.  4" D D ISei  |A).dBL * * & &( Z Z&Gsh GsR MR\`pu 7r +/E$X\T D 48$ ,\ *.QV_cuz  KP 4`=D	 16 ?B"
 FKZ_ & &P 8= Wr ;? Tl 8< &P! 55^@ % %%$.$#r:   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   )r7   items     r8   __getattr__zSAModelAccessor.__getattr__	  s&    99#001FGGr:   N)rQ  r  r  r  r  r:   r8   r  r  	  s    Hr:   r  )Cr  r   r   r  r  r   r   r   typingr   r   datetimer   sqlalchemy.typesr2   sqlalchemy.ext.declarativesqlalchemy.ormsqlalchemy.sql.selectablesqlalchemy.excr	   r
   r   r   r   flaskr   r   alembic.configr   alembicr   psycopg2.errorcodesr   psycopg2r   r   cmf.fields.base_fieldsr   r   cmfr   rV   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  r:   r8   <module>r     s      	  /   #   !    ; 0 0  !  0  - 6   M M Z Z F F 0 [ [ " "u&#> u&#pMH Hr:   