U kfnA@svdZddlmZddlmZddlmZddlmZddlmZddlmZddlm Z dd lm Z dd lm Z dd lm Z dd lm Z d dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlm Z d dl!m"Z"d dl!m#Z#e rd dl$m%Z%d dl$m&Z&d dl$m'Z'd dl(m)Z)d d l(m*Z*d d!lm+Z+d d"lm,Z,d d#l-m.Z.d d$l/m0Z0d d%lm1Z1d d&lm2Z2d d'lm3Z3d d(l4m5Z5d d)l6m7Z7d d*l8m9Z9d d+l:m;Z;d,d-gZZ?Gd0d1d1e"Z@Gd2d3d3e"ZAGd4d-d-ee=ZBGd5d,d,e ZCGd6d7d7eZDd8d9d:d;d<ZEd=S)>aHorizontal sharding support. Defines a rudimental 'horizontal sharding' system which allows a Session to distribute queries and persistence operations across multiple databases. For a usage example, see the :ref:`examples_sharding` example included in the source distribution. .. deepalchemy:: The horizontal sharding extension is an advanced feature, involving a complex statement -> database interaction as well as use of semi-public APIs for non-trivial cases. Simpler approaches to refering to multiple database "shards", most commonly using a distinct :class:`_orm.Session` per "shard", should always be considered first before using this more complex and less-production-tested system. ) annotations)Any)Callable)Dict)Iterable)Optional)Tuple)Type) TYPE_CHECKING)TypeVar)Union)event)exc)inspect)util) PassiveFlag)OrmExecuteOptionsParameter) ORMOption)Mapper)Query)_BindArguments)_PKIdentityArgument)Session)Protocol)Self) Connection)Engine) OptionEngine)IteratorResult)Result)LoaderCallableStatus)_O)BulkUDCompileState) QueryContext)_EntityBindKey) _SessionBind)ORMExecuteState) InstanceState) Executable)_TP) ClauseElementShardedSession ShardedQuery_T)boundc@s eZdZdddddddZdS) ShardChooserOptional[Mapper[_T]]rOptional[ClauseElement])mapperinstanceclausereturncCsdSN)selfr3r4r5r8r8O/opt/hc_python/lib64/python3.8/site-packages/sqlalchemy/ext/horizontal_shard.py__call__QszShardChooser.__call__N__name__ __module__ __qualname__r;r8r8r8r:r0Psr0c@s&eZdZdddddddddd Zd S) IdentityChooser Mapper[_T]rOptional[InstanceState[Any]]rrrr3 primary_keylazy_loaded_fromexecution_optionsbind_argumentskwr6cKsdSr7r8)r9r3rDrErFrGrHr8r8r:r;Zs zIdentityChooser.__call__Nr<r8r8r8r:r@Ysr@cs:eZdZdZddddfdd Zddd d d ZZS) r-aQuery class used with :class:`.ShardedSession`. .. legacy:: The :class:`.ShardedQuery` is a subclass of the legacy :class:`.Query` class. The :class:`.ShardedSession` now supports 2.0 style execution via the :meth:`.ShardedSession.execute` method. rNone)argskwargsr6cs<tj||t|jtst|jj|_|jj|_d|_dSr7) super__init__ isinstancesessionr,AssertionErroridentity_chooserexecute_chooserZ _shard_id)r9rJrK __class__r8r:rMos   zShardedQuery.__init__ShardIdentifierrshard_idr6cCs |j|dS)aReturn a new query, limited to a single shard ID. All subsequent operations with the returned query will be against the single shard regardless of other state. The shard_id can be passed for a 2.0 style execution to the bind_arguments dictionary of :meth:`.Session.execute`:: results = session.execute( stmt, bind_arguments={"shard_id": "my_shard"} ) ) _sa_shard_id)rF)r9rWr8r8r: set_shardwszShardedQuery.set_shard)r=r>r?__doc__rMrY __classcell__r8r8rSr:r-fsc seZdZUded<ded<ded<dddefddddd d d d d dddd fddZdejdej dfdddddddddd fdd Z ddddd d!d"Z d4d#dd$dd%d&d'd(Z d5dddd)dd$dd*dd+d,d-d.Z d/d0dd1d2d3ZZS)6r,r0 shard_chooserr@rQz*Callable[[ORMExecuteState], Iterable[Any]]rRN) id_chooser query_chooserzOptional[IdentityChooser]z4Optional[Callable[[ORMExecuteState], Iterable[Any]]]zOptional[Dict[str, Any]]zType[Query[_T]]z._legacy_identity_chooserz*identity_chooser or id_chooser is requiredzNThe ``query_chooser`` parameter is deprecated; please use ``execute_chooser``.z1.4z>Can't pass query_chooser and execute_chooser at the same time.r'z Iterable[Any] orm_contextr6cs |jSr7)Z statementrg)_query_chooserr8r:_default_execute_choosersz9ShardedSession.__init__.._default_execute_chooserNz,execute_chooser or query_chooser is required)rLrMrlistenexecute_and_instancesr\rZwarn_deprecatedrQr ArgumentErrorrR_ShardedSession__shards bind_shard) r9r\rQrRr_r`r]r^rKrerjkrS)rdrir9r:rMsV,  zShardedSession.__init__z Mapper[_O]zUnion[Any, Tuple[Any, ...]]z Optional[Any]rrBrzOptional[_BindArguments]z)Union[Optional[_O], LoaderCallableStatus]) r3primary_key_identityidentity_tokenpassiverErFrGrHr6c  s|dk r&tj||fd|i|} | S|j|||||r>t|nidD]0} tj||f| |d|} | dk rF| SqFdSdS)a_override the default :meth:`.Session._identity_lookup` method so that we search for a given non-token primary key identity across all possible identity tokens (e.g. shard ids). .. versionchanged:: 1.4 Moved :meth:`.Session._identity_lookup` from the :class:`_query.Query` object to the :class:`.Session`. Nrr)rErFrG)rrrE)rL_identity_lookuprQdict) r9r3rqrrrsrErFrGrHobjrWobj2rSr8r:rts:  zShardedSession._identity_lookupzOptional[_EntityBindKey[_O]])r3r4rHr6cKsl|dk r|}|dk s0t|j||dS|j|||d}t|trd|jf|St|t srt|SdS)zaProvide a :class:`_engine.Connection` to use in the unit of work flush process. N)rW)r3rWr4) r{Zin_transactionZget_transactionrP connectionget_bindrNrconnectr)r9r3r4rWrHZtransbindr8r8r:connection_callableDs     z"ShardedSession.connection_callable)rWr4r5r2r&)r3rWr4r5rHr6cKs.|dkr$|j|||d}|dk s$t|j|S)N)r4r5)r{rPrn)r9r3rWr4r5rHr8r8r:r}bs  zShardedSession.get_bindrUzUnion[Engine, OptionEngine])rWrr6cCs||j|<dSr7)rn)r9rWrr8r8r:rorszShardedSession.bind_shard)NNN)N)r=r>r?__annotations__r-rMrZ PASSIVE_OFFr EMPTY_DICTrtr{rr}ror[r8r8rSr:r,s:  &t$1 c@s&eZdZdZdZd dddddZdS) set_shard_idaa loader option for statements to apply a specific shard id to the primary query as well as for additional relationship and column loaders. The :class:`_horizontal.set_shard_id` option may be applied using the :meth:`_sql.Executable.options` method of any executable statement:: stmt = ( select(MyObject). where(MyObject.name == 'some name'). options(set_shard_id("shard1")) ) Above, the statement when invoked will limit to the "shard1" shard identifier for the primary query as well as for all relationship and column loading strategies, including eager loaders such as :func:`_orm.selectinload`, deferred column loaders like :func:`_orm.defer`, and the lazy relationship loader :func:`_orm.lazyload`. In this way, the :class:`_horizontal.set_shard_id` option has much wider scope than using the "shard_id" argument within the :paramref:`_orm.Session.execute.bind_arguments` dictionary. .. versionadded:: 2.0.0 rWpropagate_to_loadersTrUboolcCs||_||_dS)aHConstruct a :class:`_horizontal.set_shard_id` option. :param shard_id: shard identifier :param propagate_to_loaders: if left at its default of ``True``, the shard option will take place for lazy loaders such as :func:`_orm.lazyload` and :func:`_orm.defer`; if False, the option will not be propagated to loaded objects. Note that :func:`_orm.defer` always limits to the shard_id of the parent row in any case, so the parameter only has a net effect on the behavior of the :func:`_orm.lazyload` strategy. Nr)r9rWrr8r8r:rMszset_shard_id.__init__N)T)r=r>r?rZ __slots__rMr8r8r8r:rxsrr'&Union[Result[_T], IteratorResult[_TP]]rfcsjrj}njsjr"j}nd}j}t|ts:tdddfdd }j D]}t|t rT|j }qqT|r|j dk r|j }n0dj krj d}ndjkrjd}nd}|dk r||Sg}|D]}||}||q|dj|d dSdS) NrUrrVcs*tj}||d<j|dj|dS)NrW)rr)rG)rurGZupdate_execution_optionsZinvoke_statement)rWrGrhr8r:iter_for_shards  z-execute_and_instances..iter_for_shardrXrWr)Z is_selectZ load_optionsZ is_updateZ is_deleteZupdate_delete_optionsrOrNr,rPZ_non_compile_orm_optionsrrWZ_identity_tokenrFrGrRappendmerge)rgZactive_optionsrOrZorm_optrWpartialZresult_r8rhr:rls4         rlN)FrZ __future__rtypingrrrrrrr r r r rrrrZormrZ orm._typingrZorm.interfacesrZ orm.mapperrZ orm.queryrZ orm.sessionrrrZ util.typingrrZ engine.baserrrZ engine.resultrr r!r"Zorm.bulk_persistencer#Z orm.contextr$r%r&r'Z orm.stater(sqlr)Z sql._typingr*Z sql.elementsr+__all__r.strrUr0r@r-r,rrlr8r8r8r:sh                                            #p2