o
    y¬´\u  ã                   @   s`   d Z ddlmZ ddlmZ ddlmZ ddlmZ ddgZG dd„ deƒZ	G d	d„ deƒZ
d
S )a  Horizontal 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.

é   )Úinspect)Úutil)ÚQuery)ÚSessionÚShardedSessionÚShardedQueryc                       sL   e Zd Z‡ fdd„Zdd„ Zdd„ Z		d‡ fdd	„	Zd‡ fd
d„	Z‡  ZS )r   c                    s4   t t| ƒj|i |¤Ž | jj| _| jj| _d | _d S ©N)Úsuperr   Ú__init__ÚsessionÚ
id_chooserÚquery_chooserÚ	_shard_id)ÚselfÚargsÚkwargs©Ú	__class__© úQ/var/www/html/env/lib/python3.10/site-packages/sqlalchemy/ext/horizontal_shard.pyr
      s   


zShardedQuery.__init__c                 C   s   |   ¡ }||_|S )z¹return 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.
        )Ú_cloner   )r   Úshard_idÚqr   r   r   Ú	set_shard!   s   zShardedQuery.set_shardc                    s`   ‡ ‡fdd„}ˆ j d ur|ˆ j ƒS ˆjd ur|ˆjƒS g }ˆ ˆ¡D ]	}| ||ƒ¡ q"t|ƒS )Nc                    s:   |  ˆ j d< ˆ _ˆjˆ ¡ | d� ˆ jˆj¡}ˆ |ˆ ¡S )Nr   )Úmapperr   )Ú
attributesÚidentity_tokenÚ_connection_from_sessionÚ_mapper_zeroÚexecuteÚ	statementÚ_paramsÚ	instances)r   Úresult©Úcontextr   r   r   Úiter_for_shard-   s   ÿþz;ShardedQuery._execute_and_instances.<locals>.iter_for_shard)r   r   r   ÚextendÚiter)r   r%   r&   Úpartialr   r   r$   r   Ú_execute_and_instances,   s   



z#ShardedQuery._execute_and_instancesNc           	         s„   |durt t| ƒj||fd|i|¤ŽS | j |¡}|r | |¡}|  ||¡D ]}t t| ƒj||fd|i|¤Ž}|dur?|  S q&dS )z¿override the default Query._identity_lookup method so that we
        search for a given non-token primary key identity across all
        possible identity tokens (e.g. shard ids).

        Nr   )r	   r   Ú_identity_lookupr   ÚqueryÚ_set_lazyload_fromr   )	r   r   Úprimary_key_identityr   Úlazy_loaded_fromÚkwr   r   Úobjr   r   r   r+   A   s0   
þýü

ÿÿÿÿzShardedQuery._identity_lookupc                    s<   ‡ ‡fdd„}|du rˆj durˆj }ttˆƒj|||d�S )z©Override the default Query._get_impl() method so that we emit
        a query to the DB for each possible identity token, if we don't
        have one already.

        c                    sX   ˆj d ur
ˆ ˆ|ƒS t |¡}ˆ ˆ|¡D ]}ˆ |¡}ˆ ||ƒ}|d ur)|  S qd S r   )r   r   Úto_listr   r   )r,   r.   Úidentr   r   Úo©Ú
db_load_fnr   r   r   Ú_db_load_fnj   s   




ÿz+ShardedQuery._get_impl.<locals>._db_load_fnN)r   )r   r	   r   Ú	_get_impl)r   r.   r6   r   r7   r   r5   r   r8   c   s   
ÿzShardedQuery._get_impl)NNr   )	Ú__name__Ú
__module__Ú__qualname__r
   r   r*   r+   r8   Ú__classcell__r   r   r   r   r      s    û"c                       sH   e Zd Zdef‡ fdd„	Zdd„ Zddd„Z	ddd	„Zd
d„ Z‡  Z	S )r   Nc                    sd   t t| ƒjdd|i|¤Ž || _|| _|| _i | _| j| _|dur.|D ]}|  	||| ¡ q#dS dS )a  Construct a ShardedSession.

        :param shard_chooser: A callable which, passed a Mapper, a mapped
          instance, and possibly a SQL clause, returns a shard ID.  This id
          may be based off of the attributes present within the object, or on
          some round-robin scheme. If the scheme is based on a selection, it
          should set whatever state on the instance to mark it in the future as
          participating in that shard.

        :param id_chooser: A callable, passed a query and a tuple of identity
          values, which should return a list of shard ids where the ID might
          reside.  The databases will be queried in the order of this listing.

        :param query_chooser: For a given Query, returns the list of shard_ids
          where the query should be issued.  Results from all shards returned
          will be combined together into a single listing.

        :param shards: A dictionary of string shard names
          to :class:`~sqlalchemy.engine.Engine` objects.

        Ú	query_clsNr   )
r	   r   r
   Úshard_chooserr   r   Ú_ShardedSession__bindsÚ
connectionÚconnection_callableÚ
bind_shard)r   r>   r   r   Úshardsr=   r   Úkr   r   r   r
   …   s   þzShardedSession.__init__c                 K   sb   |d urt |ƒ}|jr|jd }|d usJ ‚|S |jr|jS | j||fi |¤Ž}|d ur/||_|S )Nr   )r   Úkeyr   r>   )r   r   Úinstancer0   ÚstateÚtokenr   r   r   r   Ú_choose_shard_and_assign­   s   
z'ShardedSession._choose_shard_and_assignc                 K   sJ   |d u r
|   ||¡}| jd ur| jj||d�S | j|||d�jdi |¤ŽS )N)r   )r   rF   r   )rI   Útransactionr@   Úget_bindÚcontextual_connect)r   r   rF   r   r   r   r   r   r@   ¼   s   
ÿþþzShardedSession.connectionc                 K   s"   |d u r| j |||d�}| j| S )N)Úclause)rI   r?   )r   r   r   rF   rM   r0   r   r   r   rK   Ç   s
   ÿ
zShardedSession.get_bindc                 C   s   || j |< d S r   )r?   )r   r   Úbindr   r   r   rB   Ð   s   zShardedSession.bind_shard)NNN)
r9   r:   r;   r   r
   rI   r@   rK   rB   r<   r   r   r   r   r   „   s    ú(

ÿ	N)Ú__doc__Ú r   r   Ú	orm.queryr   Úorm.sessionr   Ú__all__r   r   r   r   r   r   Ú<module>   s   
j