
    ؄_#                         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e          Z	 G d	 d
e
          Z G 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                   L     e Zd Z fdZd Zd Zd Z	 	 d fd	Zd	 fd	Z xZ	S )
r   c                      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__s      d/var/www/book.euthymeo.com/html/venv/lib/python3.11/site-packages/sqlalchemy/ext/horizontal_shard.pyr   zShardedQuery.__init__   sI    *lD!!*D;F;;;,1!\7    c                 <    |                                  }||_        |S )zReturn 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qs      r   	set_shardzShardedQuery.set_shard!   s     KKMMr   c                       fd}j          |j                   S  j         | j                  S g }                                D ] }|                     ||                     !t	          |          S )Nc                     | xj         d<   _                                                            |                               j        j                  }                    |          S )Nr   )mapperr   )
attributesidentity_token_connection_from_session_bind_mapperexecute	statement_params	instances)r   resultcontextr   s     r   iter_for_shardz;ShardedQuery._execute_and_instances.<locals>.iter_for_shard.   sp    FNNGz*W-C22((**X 3  gg'66  >>&'222r   )r!   r   r   extenditer)r   r)   r*   partialr   s   ``   r   _execute_and_instancesz#ShardedQuery._execute_and_instances-   s    	3 	3 	3 	3 	3 	3 !-!>'"8999^'!>$.111G ..t44 9 9~~h778888 == r   c                       fd} j          | j                   S d}g }                                D ],} ||          }||j        z  }|                    |           -t	          ||          S )Nc                 p                         | d          }|                    j                  }|S )NT)r   r   clauseclose_with_result)r"   r$   r&   )r   connr(   r   r   stmts      r   exec_for_shardz2ShardedQuery._execute_crud.<locals>.exec_for_shardC   sE    00!"&	 1  D \\$55FMr       )r   r   rowcountappendShardedResult)r   r4   r   r5   r7   resultsr   r(   s   ```     r   _execute_crudzShardedQuery._execute_crudB   s    	 	 	 	 	 	 	 >%!>$.111HG ..t44 ' ''11FO+v&&&& (333r   Nc                 <   |$ t          t          |           j        ||fd|i|S | j                            |          }|r|                    |          }|                     ||          D ],} t          t          |           j        ||fd|i|}||c S -dS )zOverride 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   s
            r   r=   zShardedQuery._identity_lookupY   s     %=5t,,=$   . 	   ""6**A ;(()9:: OOA/CDD  @eL$//@0 AIMO  ?JJJ # 4r   c                       fd}| j          j         }t          t                                         |||          S )zOverride 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                     j          |          S t          j        |          }                    |          D ])}                    |          } ||          }||c S *d S r   )r   r   to_listr   r   )r>   r@   identr   r   o
db_load_fnr   s         r   _db_load_fnz+ShardedQuery._get_impl.<locals>._db_load_fn   s     ~)!z$(<===%9:: !%e < <    Hx00A"
1e,,A}  %  4r   N)r!   )r   r   r   	_get_impl)r   r@   rI   r!   rJ   r   s   ` `  r   rK   zShardedQuery._get_impl{   sg    	  	  	  	  	  	 $ !dn&@!^N\4((22 +n 3 
 
 	
r   )NNr   )
__name__
__module____qualname__r   r   r.   r;   r=   rK   __classcell__r   s   @r   r   r      s            
 
 
! ! !*4 4 46            D
 
 
 
 
 
 
 
 
 
r   c                   2    e Zd ZdZdZd Zed             ZdS )r9   a  A value object that represents multiple :class:`_engine.ResultProxy`
    objects.

    This is used by the :meth:`.ShardedQuery._execute_crud` hook to return
    an object that takes the place of the single :class:`_engine.ResultProxy`.

    Attribute include ``result_proxies``, which is a sequence of the
    actual :class:`_engine.ResultProxy` objects,
    as well as ``aggregate_rowcount``
    or ``rowcount``, which is the sum of all the individual rowcount values.

    .. versionadded::  1.3

    result_proxiesaggregate_rowcountc                 "    || _         || _        d S r   rR   )r   rS   rT   s      r   r   zShardedResult.__init__   s    ,"4r   c                     | j         S r   )rT   )r   s    r   r7   zShardedResult.rowcount   s    &&r   N)rL   rM   rN   __doc__	__slots__r   propertyr7    r   r   r9   r9      sO          9I5 5 5 ' ' X' ' 'r   r9   c                   B     e Zd Zdef fd	Zd ZddZ	 ddZd Z xZ	S )r   Nc                      t          t          |           j        dd|i| || _        || _        || _        i | _        | j        | _        |!|D ] }| 	                    |||                    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_clsNrZ   )
r   r   r   shard_chooserr   r   _ShardedSession__binds
connectionconnection_callable
bind_shard)	r   r^   r   r   shardsr]   r   kr   s	           r   r   zShardedSession.__init__   s    < 	-nd##,KKyKFKKK*$*#'?  . .6!9---- . .r   c                     |7t          |          }|j        r|j        d         }|J |S |j        r|j        S  | j        ||fi |}|||_        |S )Nr   )r   keyr!   r^   )r   r   instancerB   statetokenr   s          r   _choose_shard_and_assignz'ShardedSession._choose_shard_and_assign   s~    H%%Ey ,	!(((% ,++%4%fh=="==#+E r   c                     ||                      ||          }| j        | j                            ||          S  |                     |||          j        di |S )N)r   )r   rg   rZ   )rj   transactionr`   get_bind_contextual_connect)r   r   rg   r   r   s        r   r`   zShardedSession.connection   s    44VXFFH'#..v.III"4==H !  !, ,$*, , ,r   c                 P    ||                      |||          }| j        |         S )N)r1   )rj   r_   )r   r   r   rg   r1   rB   s         r   rm   zShardedSession.get_bind   s:     44 5  H |H%%r   c                     || j         |<   d S r   )r_   )r   r   binds      r   rb   zShardedSession.bind_shard  s    !%Xr   )NNN)
rL   rM   rN   r   r   rj   r`   rm   rb   rO   rP   s   @r   r   r      s         &. &. &. &. &. &.P  	, 	, 	, 	, <@& & & && & & & & & &r   N)rW    r   r   	orm.queryr   orm.sessionr   __all__r   objectr9   r   rZ   r   r   <module>rw      s                       ! ! ! ! ! !^
,
 
 
 
 
5 
 
 
D' ' ' ' 'F ' ' '6M& M& M& M& M&W M& M& M& M& M&r   