U a=@sJdZddlmZddlmZddlZddlmZddlmZddlmZ dd lm Z dd lm Z dd l m Z d dlmZd d lmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlm Z d dl!m"Z"d dl#m$Z$ddZ%dd Z&dTd"d#Z'd$d%Z(d&d'Z)d(d)Z*d*d+Z+d,d-Z,dUd.d/Z-dVd0d1Z.d2d3Z/d4d5Z0dWd7d8Z1dXd9d:Z2d;d<Z3d=d>Z4d?d@Z5dAdBZ6dCdDZ7dEdFZ8dGdHZ9dIdJZ:e;ZdMdNGdOdPdPe e=Z?e>dMdQGdRdSdSee=Z@dS)Yzprivate module containing functions used to emit INSERT, UPDATE and DELETE statements on behalf of a :class:`_orm.Mapper` and its descending mappers. The functions here are called only by the unit of work functions in unitofwork.py. )chain)groupbyN) attributes) evaluator)exc)loading)sync) state_str)future)sql)util)result) coercions) expression) operators)roles)select)_entity_namespace_key) CompileState)Options)DeleteDMLState)UpdateDMLState)BooleanClauseList)LABEL_STYLE_TABLENAME_PLUS_COLc sj}|jjrtd|rL|r@sz _bulk_insert..cSsg|] \}}|qSrr)r r!dict_rrr"r#AscSsg|] }|jqSrrrrrr"r#Csc 3s2|]*\}}}}}}}}d|||||fVqdSNr) r r! state_dictparamsmpconn value_params has_all_pkshas_all_defaults connectionmapperrr" Ls$ z_bulk_insert..c3s|]}d|fVqdSr%rr mappingr-rr"r0bsT)bulkreturn_defaults render_nulls bookkeepingcSsg|] }|jqSrkeyr prrr"r#sscsg|] }|qSrr)r r9)r$rr"r#ws) base_mappersessionconnection_callableNotImplementedErrorlistr._sorted_tablesitemsisa_collect_insert_commands_emit_insert_statementsZ_identity_classZ_identity_key_propstupler9)r/mappingssession_transactionisstatesr4r5r<statestable super_mapperrecordsZ identity_clsZidentity_propsr!r)r.r$r/r" _bulk_insert.sN     rNc sj}jjr"jjhfdd|r\|rLfdd|D}qddd|D}nt|}|jjrttd| ||j D]H\}} |sqt d|fdd|Dd d }t|d|||d d qdS) NcstfddjDS)Nc3s,|]$\}}|jks|kr||fVqdSr%)committed_stater kv) search_keysr!rr"r0s z6_bulk_update.._changed_dict..)rrB)r/r!)rSr!r" _changed_dictsz#_bulk_update.._changed_dictcsg|]}|qSrrr)rUr/rr"r#sz _bulk_update..cSsg|] }|jqSrrrrrr"r#szJconnection_callable / per-instance sharding not supported in bulk_update()c3s.|]&}d|jr |jjndfVqdSr%)_version_id_propr9r1r-rr"r0s z_bulk_update..T)r3Fr6)r<Z_primary_key_propkeysrVr9unionr@r=r>r?r.rArBrC_collect_update_commands_emit_update_statements) r/rGrHrIZupdate_changed_onlyr<rKrLrMr)rUr.r/rSr" _bulk_update{sD    rZFcCs|s0|js0t||D]}t||g|ddqdSg}g}t|||D]B\}}}} } } } | s^| rt||||| | fqD||||| fqD|jD]J\} }| |jkrqt| |}t || |}t |||| |t |||| |qt ||t dd|Ddd|DdS)a;Issue ``INSERT`` and/or ``UPDATE`` statements for a list of objects. This is called within the context of a UOWTransaction during a flush operation, given a list of states to be flushed. The base mapper in an inheritance hierarchy handles the inserts/ updates for all descendant mappers. T)singleNcss$|]\}}}}||||dfVqdS)FNr)r r!r&r/r.rrr"r0s zsave_obj..css&|]\}}}}}||||dfVqdS)TNr)r r!r&r/r.update_version_idrrr"r0s)batch _sort_statessave_obj_organize_states_for_saveappendrArB _pks_by_tablerDrXrYrE _finalize_insert_update_commandsr)r<rJuowtransactionr[r!states_to_updatestates_to_insertr$r/r. has_identity row_switchr\rKinsertupdaterrr"r_sn     r_cshtt|||}|jD]H\jkr.qfdd|D}t||||}t|||qdS)z\Issue UPDATE statements on behalf of a relationship() which specifies post_update. c 3sH|]@\}}}}|jkr||||jdk r:||jndfVqdSr%)rbversion_id_col#_get_committed_state_attr_by_column)r r!r&Z sub_mapperr.r/rKrr"r0s  zpost_update..N)r@ _organize_states_for_post_updaterArBrb_collect_post_update_commands_emit_post_update_statements)r<rJrdpost_update_colsrerjrrmr" post_updates.   rrc Cstt|||}|j}tt|D]F}||}||jkr@q&n|jrN|jrNq&t||||}t |||||q&|D]\}} }} } |j || |qrdS)zIssue ``DELETE`` statements for a list of objects. This is called within the context of a UOWTransaction during a flush operation. N) r@_organize_states_for_deleterAreversedkeysrbZinheritsZpassive_deletes_collect_delete_commands_emit_delete_statementsdispatchZ after_delete) r<rJrdstates_to_deleteZtable_to_mapperrKr/deleter!r&r.r\rrr" delete_obj;s>   r{c csJt|||D]6\}}}}t|j}|jp2||}d} } |sR|j|||n|j||||jrv|||||s||jj kr|jj |} t | } | | s| | stdt||t| fn&|d|t|t| || | } |s| r0|jdk r0|| r| n|| r&| jn||j} |||||| | fVq dS)aTMake an initial pass across a set of states for INSERT or UPDATE. This includes splitting out into distinct lists for each, calling before_insert/before_update, obtaining key information for each state including its dictionary, mapper, the connection to use for the execution per state, and the identity flag. NzJNew instance %s with identity key %s conflicts with persistent instance %szPdetected row switch for identity %s. will update %s, remove %s from transaction)_connections_for_statesboolr9_identity_key_from_staterxZ before_insertZ before_updateZ_validate_polymorphic_identityr= identity_maprinstance_stateZwas_already_deleted is_deletedrwarnr Z _log_debugZremove_state_actionsrkrlr) r<rJrdr!r$r/r.rgZ instance_keyrhr\instanceexistingrrr"r`fs`         r`cCs t|||S)zMake an initial pass across a set of states for UPDATE corresponding to post_update. This includes obtaining key information for each state including its dictionary, mapper, the connection to use for the execution per state. )r|)r<rJrdrrr"rns rnccs^t|||D]L\}}}}|j||||jdk rD||||j}nd}|||||fVq dS)zMake an initial pass across a set of states for DELETE. This includes calling out before_delete and obtaining key information for each state including its dictionary, mapper, the connection to use for the execution per state. N)r|rxZ before_deleterkrl)r<rJrdr!r$r/r.r\rrr"rss rsc cs|D]x\}}}}||jkrqi} i} |j|} |j|} t| |D]l} || }| | }|dkrt|| krt|stqHqH|st|dst|tjrt|dr| n|| |<qH|| |j <qH|s|j | |  dd| DD] }d| |<q|r|r$|j || }|jjr|j|| }nd}nd}}|jdk rh|jdk rh|j|j|krh|d| |jj <||| ||| ||fVqdS)zSIdentify sets of values to use in INSERT statements for a list of states. N__clause_element__cSsg|] }|jqSrr8r crrr"r# sz,_collect_insert_commands..TF)rb_propkey_to_colZ_insert_cols_evaluating_noneset intersectionhasattr isinstancer ClauseElementrr9Z_insert_cols_as_none differenceZ_pk_keys_by_tableissubsetr<eager_defaultsZ_server_default_colsversion_id_generatorrk_cols_by_table)rKrfr3r4r5r!r&r/r.r'r*propkey_to_colZ eval_nonepropkeyvaluecolZcolkeyr+r,rrr"rDsp              rDc #sf|D]Z\}}}}||jkr q|j|}i} |j||rptfddt|j|D} d} ni} t|jD]n} | } | }t| dst | t j rt| dr| n| | |<q|j | j| |j| dk r| | |j<q|jjr|j|| } nd} |dk r|j|j|kr|s~| s~| s~|jD].}|j |jj|tj}|jrLq~qLq|j}| o| }|| |j<|s|j| kr|jdk r||}|| |j<n|jdkr|r|| |j<n| s| sqd}d}|r4tfddt|j|D}ni}|D]}|j|j} |j | j|tj}|jr|j rd||f|jkrd}|jd ||j<| !|jdn|j d ||j<|| krd}n|j"d ||j<||jdkr.TrNFc3s"|]}|j|fVqdSr%)_labelgetrrrr"r0sZ pk_cascadedrzCCan't update table %s using NULL for primary key value on column %s)*rbrrrrrZ_pk_attr_keys_by_tablerOrrr rrmanagerimplZis_equalr9r<rZ_server_onupdate_default_colsrrkr_columntopropertyvalues get_historyrPASSIVE_NO_INITIALIZEaddedrr PASSIVE_OFFZdeletedpopZ unchangedorm_exc FlushErrorrj_table_to_equatedr populatepassive_updates)rdrKrer3r!r/r.r\pksr*r'r,rrrprophistoryZ no_paramsvalr+Zexpect_pk_cascadedZ pk_paramsm equated_pairsrrr"rX3s                     rXccs,|D] \}}}}} |j|} i} d} |j|D]|} | | krX|j||| tjd| | j<q0| |ksj| jdk r0|j| }|j|j j ||tj }|j r0|j d}|| | j <d} q0| r| dk r|j|j|kr|j} | | | j<t|j r| j | kr|jdk r|| }|| | j <||||| fVqdS)zrIdentify sets of values to use in UPDATE statements for a list of states within a post_update operation. F)ZpassiveNrT)rbrZ_get_state_attr_by_columnrrrZonupdaterrr9rrrrrkr}r)r<rdrKrerqr!r&r/r.r\rr'Zhasdatarrrrrrrr"rosZ       roc cs|D]\}}}}}||jkrqi} |j|D]6} |||| | | j<} | dkr,td|| fq,|dk r|j|j|kr|| |jj<| |fVqdS)zSIdentify values to use in DELETE statements for a list of states to be deleted.NzHCan't delete from table %s using NULL for primary key value on column %s)rbrlr9rrrkr) r<rdrKryr!r&r/r.r\r'rrrrr"rv$s@   rvTc sjdk ojjkd|ji}fdd}|df|}t|ddD]R\\} } } } } }d}t|}|}d }| s|}d }n8|r| sjjr|}d }njdk r|j}d }|s| j j n| j j }|o| j j }| o }| r`|D]b\}}}} }} } | j ||||d }|rLt|||||jjd|d |j ||j7}|}qn|s|}|D]Z\}}}} }} } | j |||d }|rt|||||jjd|d |j ||j7}qnnd d |D}|p|ot|dk}| j |||d }||j7}|D]N\}}}} }} } |rt|||||jjd|d |jjsV|jnd q|r|t|krtdjt||fqRrRtd|j jqRdS)z`Emit UPDATE statements corresponding to value lists collected by _collect_update_commands().Ncompiled_cachecstttj}jD]"}|j|tj|j |j dkqrb|jj tjj j j j dk |}|SN)type_)r_construct_rawrand_rbclausesrar bindparamrtyperkrjwhererrstmtr/Zneeds_version_idrKrr" update_stmt]s  z,_emit_update_statements..update_stmtrjcSs*|dt|dt|d|d|dfSNr rr}recrrr"xs   z)_emit_update_statements..rFTexecution_optionscSsg|] }|dqSr rr rrrr"r#sz+_emit_update_statements..rMUPDATE statement on table '%s' expected to update %d row(s); %d were matched.MDialect %s does not support updated rowcount - versioning cannot be verified.)rkr_compiled_cache_memorr@r4r<rdialectsupports_sane_rowcount supports_sane_rowcount_returningsupports_sane_multi_rowcount _execute_20r _postfetchcontextcompiled_parametersreturned_defaultsrowcountlen executemanyrStaleDataError descriptionrrdialect_description)r<rdr/rKrjr7rr cached_stmtr.Z paramkeyshasvaluer,r+rMrows statementr4assert_singlerowassert_multirowallow_multirowr!r&r'r*rcheck_rowcount multiparamsrrr"rYKs*                  rYc Cs*|d|f|j}d|ji}t|ddD]\\}} } } } } |}|r`| sX|jrX|jjs| r| st| } dd| D}|j|||d}|rt | |j j D]R\\}}}}}}} } }|rt ||||||||d|j j s|jnd qt|||qq*t| } | s|jjrt| d krd }nd}| s6|jr6|}n,|jd k rP||j}n|rb|j|j}|r.cSsg|] }|dqSrrrrrr"r#Dsz+_emit_insert_statements..rFNrTcSsg|] }|dqSrrrrrr"r#srr)rrirrrrZimplicit_returningr@rziprrrrr_postfetch_bulk_saveZinsert_executemany_returningrr4rk primary_keyr zip_longestZinserted_primary_key_rowsZreturned_defaults_rowsrbrrr9rinserted_primary_key) r<rdr/rKrir7rrr.Zpkeysrr+r,rMrrrr!r&r' mapper_recr)r*Zlast_inserted_paramsZdo_executemanyrrpkrrrrrrr"rEsT                  rEc sd|ji}jdk o"jjkfdd}|df|}t|ddD]X\}} d} t| } |d} jdkr| jjn| jj} | o| jj }  p| }|s| }| D]D\}}}} }| j |||d }t ||||||j j d| |j7} qnrd d | D}| p| ot|d k}| j |||d }| |j7} | D],\}}}} }t ||||||j j dq8|r| t| krtd jt| | fqRrRtd|jjqRdS)zeEmit UPDATE statements corresponding to value lists collected by _collect_post_update_commands().rNcsttj}jD]"}|j|tj|j |j dkqrb|jj tjj j j j dk |}j dk r|j }|Sr)rrrrrbrrar rrrrkrjrr4rrrr"rs$   z1_emit_post_update_statements..update_stmtrrcSs|dt|dfS)Nr)rrrrr"rz._emit_post_update_statements..rrcSsg|]\}}}}}|qSrr)r r!r&rr)r'rrr"r#9s z0_emit_post_update_statements..rrr)rrkrrrr@rrrrr_postfetch_post_updaterrrrrrrrrr)r<rdr/rKrjrrrr9rMrr.rrrrr!r&rr'rrrrr"rps         rpcs`jdk ojjkfdd}|df|}t|ddD]\}}dd|D} d |ji} t| } d } d } r|jjs|jjrd } | D]}|j ||| d }| |j 7} qqt d|jj |j || | d n|j || | d }sd} |j } |jrH| d krH| | krH|jjs&t| dkrH| rDt dj| | fqHtdj| | fqHdS)z`Emit DELETE statements corresponding to value lists collected by _collect_delete_commands().Ncspttj}jD]"}|j|tj|j |j dkqrb|jj tjj j j j dk |Sr)rrrrrbrrar rr9rrkrzr)rrr/Zneed_version_idrKrr" delete_stmtms z,_emit_delete_statements..delete_stmtrzcSs|dS)Nrrrrrr"rrz)_emit_delete_statements..cSsg|] \}}|qSrr)r r'r.rrr"r#sz+_emit_delete_statements..rFrrzMDialect %s does not support deleted rowcount - versioning cannot be verified.TrzDELETE statement on table '%s' expected to delete %d row(s); %d were matched. Please set confirm_deleted_rows=False within the mapper configuration to prevent this warning.)rkrrrrrrrrrrrrrZconfirm_deleted_rowsrrr)r<rdr/rKrzrrr.ZrecsZ del_objectsrexpectedZ rows_matchedZ only_warnr'rrrr"rwbs~      rwc s(|D]\}}}}|jrFfdd|jD}|rFj|g}|jrd|j|j|j dk r|j dkr|j j j kr||j j g|r|_ t|t} tj|j| j |d|s|j||n|j|||j dkr|j dk r||j j dkrtdqdS)zzfinalize state on states that have been inserted or updated, including calling after_insert/after_update events. csBg|]:}|jr |jr8|jjks8|js|js|jjkr|jqSr)Zexpire_on_flushdeferredr9rr:rTrr"r#s  z4_finalize_insert_update_commands..NF)Z refresh_stateZonly_load_propsz2Instance does not contain a non-NULL version value)Z_readonly_propsZunmodified_intersection_expire_attributesrrextendZ_unloaded_non_objectrZ&_server_default_plus_onupdate_propkeysrkrrVr9Zunloadedr~r rZset_label_stylerrZ load_on_identr=rxZ after_insertZ after_updaterr) r<rdrJr&r/r.rgreadonlyZ toload_nowrrrTr"rcsZ    rcc s||rdS|jjj}|jjj}jdk rLjj|krLt|jg}tj j j } | rbg} |D]D} | j |krf| j krf|| j |j | j <| rf| j | j qf| r| rƈj j ||| |r||jfdd|DdS)Ncs"g|]}|jkrj|jqSrrr9rr/rr"r#1s z*_postfetch_post_update..)rrcompiledprefetch postfetchrkrr@r} class_managerrx refresh_flushr9rrarr) r/rdrKr!r$rr' prefetch_colspostfetch_colsrload_evt_attrsrrrr"rs<    rc  s|jjj} |jjj} |jjjjdk rHjj|krHt| jg} tj j j } | r^g} r| }|dk rt |D]B\}}|j r|jjrqxj|}|rx|||j<| rx| |jqx| D]D}|j|kr|jkr||j|j|j<| r| j|jq| r$| r$j j ||| |rH|rH| fdd|D| rj||jfdd| Dj|D]"\}}t||||||jqtdS)zExpire attributes in need of newly persisted database state, after an INSERT or UPDATE statement has proceeded for that state.Ncsg|]}|jr|kr|qSr)r)r r)returning_colsrr"r#zsz_postfetch..cs"g|]}|jkrj|jqSrrrrrr"r#s )rrrr returningrkrr@r}rrxrrrZisinsertrrr9rarrrrr rr)r/rdrKr!r$rr'r*ZisupdaterrrrrrowZ row_valuerrrrrr)r/rr"r9sp          rcCs&|j|D]\}}t|||q dSr%)rr Zbulk_populate_inherit_keys)r/r$rKrrrrr"rsrccs`|jjr|jj}n|j|}d}t||D].}|rB|||}|jj}||j||fVq,dS)zReturn an iterator of (state, state.dict, mapper, connection). The states are sorted according to _sort_states, then paired with the connection they should be using for the given unit of work transaction. N) r=r>Z transactionr.r^objrr/r)r<rdrJr>r.r!r/rrr"r|s   r|c Cst|}tdd|D}||zt||jd}Wn:tk rp}ztjtd||dW5d}~XYnXt|t dd|S)Ncss|]}|jdk r|VqdSr%r8)r srrr"r0s z_sort_states..r8z^Could not sort objects by primary key; primary key values must be sortable in Python (was: %s))Zreplace_contextZ insert_order) rdifference_updatesortedZ_persistent_sortkey_fn TypeErrorrraise_sa_excInvalidRequestErroroperator attrgetter)r/rJpending persistentZpersistent_sortederrrrr"r^s*  r^c@speZdZGdddeZeddZeddZeddZed d Z ed d Z ed dZ eddZ dS)BulkUDCompileStatec@s0eZdZdZdZdZeZeZeZ dZ dZ dZ dS)z)BulkUDCompileState.default_update_optionsevaluateTN) __name__ __module__ __qualname___synchronize_session _autoflush_subject_mapper _EMPTY_DICT_resolved_values_resolved_keys_as_propnames_value_evaluators_matched_objects _matched_rows_refresh_identity_tokenrrrr"default_update_optionssr c Cs |r ||fStjddh||j\}}|j}|dk rF|dkrFtd||d<z|jd} Wn tk r|dsxt dYn X| j |d <|d | j i7}|j r| | d|ji}|jd kr| ||||||}n|jd kr|||||||}|t|t|d fS)N_sa_orm_update_optionssynchronize_session)rfetchFzKValid strategies for session synchronization are 'evaluate', 'fetch', FalseZclauseplugin_subjectFz0statement had 'orm' plugin but no plugin_subjectr/rrr#)r!)rr Zfrom_execution_optionsZ_execution_optionsrr  ArgumentErrorZ_propagate_attrsKeyErrorAssertionErrorr/rZ _annotate_do_pre_synchronize_evaluate_do_pre_synchronize_fetchr immutabledictrWr) clsr=rr'rbind_argumentsZis_reentrant_invokeupdate_optionsr r$rrr"orm_pre_session_execsh      z'BulkUDCompileState.orm_pre_session_execcCs>|d}|jdkr"||||n|jdkr:|||||S)Nr!rr#)r_do_post_synchronize_evaluate_do_post_synchronize_fetch)r+r=rr'rr,rr-rrr"orm_setup_cursor_result0s   z*BulkUDCompileState.orm_setup_cursor_resultcs~d}jrjnddjf|krF|tfdd|djfD7}jjdk r`|jjf7}rztfdd|D}|S)aApply extra criteria filtering. For all distinct single-table-inheritance mappers represented in the table being updated or deleted, produce additional WHERE criteria such that only the appropriate subtypes are selected from the total results. Additionally, add WHERE criteria originating from LoaderCriteriaOptions collected from the statement. rNZadditional_entity_criteriac3s(|] }|js|jkr|VqdSr%)Zinclude_aliasesentityZ_resolve_where_criteria)r Zae)ext_inforr"r0`s z@BulkUDCompileState._adjust_for_extra_criteria..c3s|]}|VqdSr%)Ztraverse)r crit)adapterrr"r0ls)Zis_aliased_classZ_adapterr/rFZ_single_table_criterion)r+global_attributesr3Z return_critr)r5r3r"_adjust_for_extra_criteriaKs"   z-BulkUDCompileState._adjust_for_extra_criteriac stjj}t}} znt|} d} |jr4| |j7} i} |jD]} | jr>| | q>| rh| | | 7} | rx| j | nddWn<tj k r}zt j td||dW5d}~XYnX|jdkr|j}n|}|jdkrH||}i}||} | D]D\}}z| ttj|}Wntj k r:Yn X|||<qfdd |jD}||| d S) NrcSsdS)NTr)rrrr"eval_conditionszGBulkUDCompileState._do_pre_synchronize_evaluate..eval_conditionz{Could not evaluate current criteria in Python: "%s". Specify 'fetch' or False for the synchronize_session execution option.)from_lambda_elementrjcsHg|]@}|jr|js|rjdks<|jjkr|qSr%)r/rCZexpiredrridentity_tokenrr8r/r-rr"r#s   zCBulkUDCompileState._do_pre_synchronize_evaluate..)rrr)rclass_rrEvaluatorCompiler_where_criteria _with_options_is_criteria_optionget_global_criteriar7processUnevaluatableErrorrr r r __visit_name__ _resolved_get_resolved_valuesrrexpectrExpressionElementRolerZ all_states)r+r=rr'rr,r- target_clsvalue_evaluatorsresolved_keys_as_propnamesevaluator_compilerr4r6optreffective_statementresolved_valuesr9r _evaluatorZmatched_objectsrr<r"r(pst            z/BulkUDCompileState._do_pre_synchronize_evaluatec Cs|jr gS|jr|j}n|jr*|j}ngSg}|r|D]\}}|rt|tjrnt||}|| |qd|j kr|j }t|d|d} || |q| ||fq:| ||fq:|S)NZentity_namespace proxy_key) Z _multi_values_ordered_values_valuesrBrr string_typesrrZ_bulk_update_tuples _annotationsra) r+r/riteratorrrQrRdescZk_annoattrrrr"rGs0     z'BulkUDCompileState._get_resolved_valuesc Csg}|D]\}}t|tjr0||j|fqnt|drB|}|rt|tjrz|j |}Wnt j k rvYqX||j|fqt d|q|S)NrzInvalid expression type: %r)rrZQueryableAttributerar9rrrZ ColumnElementrrZUnmappedColumnErrorr r )r+r/rPrrQrRrYrrr"rs"   z.BulkUDCompileState._resolved_keys_as_propnamesc Cs |j}t|j|jf|j|j}|j|_dd} |j||||| d} | } t } |j dkrh|j } n|} | j dkr|j }t|}||| }|||}|||}i} |D]@\}}z|ttj|}Wntjk rYqX|| |<qnt }|| | |dS)NcSs(|jjf|j}|jjr tSdSdSr%)r=Zget_bindr,rfull_returning_resultZ null_result)Z orm_contextbindrrr"skip_for_full_returningszMBulkUDCompileState._do_pre_synchronize_fetch..skip_for_full_returning)Z _add_eventr:rj)rrr)rrrZselect_identity_token select_fromoptionsr@r?executeZfetchallrrErFr=rr>rGrrCrrHrrIrD)r+r=rr'rr,r-r/Z select_stmtr]r matched_rowsrKrOrJrMrPrLr9rrQrrr"r)sf       z,BulkUDCompileState._do_pre_synchronize_fetchN) rrrrr  classmethodr.r1r7r(rGrr)rrrr"rs  P  $ _  rZormrjc@s0eZdZeddZeddZeddZdS) BulkORMUpdatec Ks||}|jjd}|j|_}i|_||||_i}|jD]}|jr@| |q@|j sn|j rnt |j|_t jt j} | j|j|j| _|jr|j| _n|j r|j| _ |||} | r| j| } |jdddkr|jjr| jrtd| j|j} tj|| |f||S)N parententityr"r#z?Can't use synchronize_session='fetch' with explicit returning())__new__rKrVr/extra_criteria_entitiesrGrr@rArBZ_preserve_parameter_orderrTrr ZUpdate__dict__rjZ local_tablerSr7rrrrZZ _returningr r rrr__init__) r+rcompilerkwselfr3r/extra_criteria_attributesrNZnew_stmtnew_critrrr"create_for_statementVsF          z"BulkORMUpdate.create_for_statementcCst}t|j}|j}tdd|D}|jD]}t|t|} } |j dk rd| j |j krdq2| j |} | D]} | | krt|j| || | <qt| j j| d| | | t| | | | } | r| | | || q2||dS)Ncss|]\}}|VqdSr%rrPrrr"r0sz>BulkORMUpdate._do_post_synchronize_evaluate..)rr@rrurrrr instance_dictrr; unmodifiedrrrxrefresh_commitrradd_register_altered)r+r=rr-rJevaluated_keysrattribrr!r$ to_evaluater9 to_expirerrr"r/s4     z+BulkORMUpdate._do_post_synchronize_evaluatecs.jt}tj}|jr8fdd|D}nj}fddfdddd|DDD}j}tdd|D} |D]} t | t | } } | j |} | D]}|| krj|| | |<q| jj| d| | | t| | | | }|r| | ||| q|dS)Ncsg|]}t|jfqSrrFrr rr-rr"r#sz.cs g|]}|jkrj|qSr)r)r identity_key)r=rr"r#s cs6g|].\}}jdks |jkrjt||dqS)Nr;)ridentity_key_from_primary_keyr@)r rr;) target_mapperr-rr"r#s  cSs g|]}|dd|dfqS)rrrrzrrr"r#scss|]\}}|VqdSr%rrPrrr"r0sz;BulkORMUpdate._do_post_synchronize_fetch..)rrr@rru returns_rowsallrrrrrorprrrxrqrrrrrsrt)r+r=rr-rJruraobjsrrvrr!r$rwr9rxr)r=rr-r"r0s@      z(BulkORMUpdate._do_post_synchronize_fetchNrrrrbrnr/r0rrrr"rcTs  : (rcrzc@s0eZdZeddZeddZeddZdS) BulkORMDeletec Ks||}|jjd}|j|_}i|_i}|jD]}|jr2||q2|||} | rb|j | }|r|j dddkr|j j r|j |j}tj|||f||S)Nrdr"r#)rerKrVr/rfr@rArBr7rrrrZrrrrh) r+rrirjrkr3r/rlrNrmrrr"rns2        z"BulkORMDelete.create_for_statementcCs|dd|jDdS)NcSsg|]}t|qSr)rr)r rrrr"r# sz?BulkORMDelete._do_post_synchronize_evaluate..)_remove_newly_deletedr)r+r=rr-rrr"r/ s z+BulkORMDelete._do_post_synchronize_evaluatec sj}|jr$fdd|D}nj}|D]L}|dd}|d}|jt||d} | |jkr.|t |j| gq.dS)Ncsg|]}t|jfqSrryrzr{rr"r#$ sz.rrr}) rrrrr~r@rrrr) r+r=rr-rrarrr;r|rr{r"r0 s(   z(BulkORMDelete._do_post_synchronize_fetchNrrrrr"rs   r)F)FFF)F)T)T)A__doc__ itertoolsrrr rrrrrr baser r r r rZenginerr[rrrrrZsql.baserrrZsql.dmlrrZ sql.elementsrZsql.selectablerrNrZr_rrr{r`rnrsrDrXrorvrYrErprwrcrrrr|r^r*rrZ plugin_forrcrrrrr"s                         MB S++Q  Y :8- R R{dJ)a