U
    b+dV                     @   s6   d dl Z G dd dZG dd dZG dd dZdS )    Nc                   @   s   e Zd ZdZdd ZdS )ProfileStatszB
    ProfileStats, runtime execution statistics of operation.
    c                 C   s   || _ || _d S N)records_producedexecution_time)selfr   r    r   G/tmp/pip-unpacked-wheel-cdsyf3nb/redis/commands/graph/execution_plan.py__init__	   s    zProfileStats.__init__N)__name__
__module____qualname____doc__r	   r   r   r   r   r      s   r   c                   @   sH   e Zd ZdZdddZdd Zdd Zeed	d
dZ	e
dddZdS )	Operationz<
    Operation, single operation within execution plan.
    Nc                 C   s   || _ || _|| _g | _dS )z
        Create a new operation.

        Args:
            name: string that represents the name of the operation
            args: operation arguments
            profile_stats: profile statistics
        N)nameargsprofile_statschildren)r   r   r   r   r   r   r   r	      s    	zOperation.__init__c                 C   s*   t |tr| |krtd| j| | S )Nzchild must be Operation)
isinstancer   	Exceptionr   append)r   childr   r   r   append_child!   s    zOperation.append_childc                 C   s
   t | jS r   lenr   )r   r   r   r   child_count(   s    zOperation.child_countoreturnc                 C   s&   t |tsdS | j|jko$| j|jkS )NF)r   r   r   r   )r   r   r   r   r   __eq__+   s    
zOperation.__eq__r   c                 C   s&   | j d krdnd| j  }| j | S )N z | )r   r   )r   args_strr   r   r   __str__1   s    zOperation.__str__)NN)r
   r   r   r   r	   r   r   objectboolr   strr"   r   r   r   r   r      s   
r   c                   @   sN   e Zd ZdZdd Zdd ZedddZee	d	d
dZ
dd Zdd ZdS )ExecutionPlanz2
    ExecutionPlan, collection of operations.
    c                 C   sB   t |tstdt |d tr.dd |D }|| _|  | _dS )z
        Create a new execution plan.

        Args:
            plan: array of strings that represents the collection operations
                  the output from GRAPH.EXPLAIN
        zplan must be an arrayr   c                 S   s   g | ]}|  qS r   )decode).0br   r   r   
<listcomp>G   s     z*ExecutionPlan.__init__.<locals>.<listcomp>N)r   listr   bytesplan_operation_treestructured_plan)r   r-   r   r   r   r	   ;   s    
zExecutionPlan.__init__c                 C   sT   ||krdS |  |  kr dS t|  D ]"}| |j| |j| s, dS q,dS )z{
        Compare execution plan operation tree

        Return: True if operation trees are equal, False otherwise
        FT)r   range_compare_operationsr   )r   root_aroot_bir   r   r   r1   L   s    z!ExecutionPlan._compare_operationsr   c                 C   s"   dd }dd }|  | jt||S )Nc                 S   s   d dd | D S )N
c                 S   s"   g | ]}|  D ]}d | qqS )    )
splitlines)r(   Z	str_childliner   r   r   r*   e   s   
 z?ExecutionPlan.__str__.<locals>.aggraget_str.<locals>.<listcomp>)join)Zstr_childrenr   r   r   aggraget_strc   s
    z+ExecutionPlan.__str__.<locals>.aggraget_strc                 S   s   |  d| S )Nr5   r   )xyr   r   r   combine_strl   s    z*ExecutionPlan.__str__.<locals>.combine_str)_operation_traverser/   r%   )r   r:   r=   r   r   r   r"   b   s    	   zExecutionPlan.__str__r   c                 C   s&   t |tsdS | j}|j}| ||S )zfCompares two execution plans

        Return: True if the two plans are equal False otherwise
        F)r   r&   r/   r1   )r   r   r2   r3   r   r   r   r   s   s
    
zExecutionPlan.__eq__c                    sF   |}t |jdkr|S  fdd|jD }| |S dS )aq  
        Traverse operation tree recursively applying functions

        Args:
            op: operation to traverse
            op_f: function applied for each operation
            aggregate_f: aggregation function applied for all children of a single operation
            combine_f: combine function applied for the operation result and the children result
        r   c                    s   g | ]} | qS r   )r>   )r(   r   aggregate_f	combine_fop_fr   r   r   r*      s   z5ExecutionPlan._operation_traverse.<locals>.<listcomp>Nr   )r   oprB   r@   rA   Zop_resr   r   r?   r   r>      s    z!ExecutionPlan._operation_traversec                 C   s   d}d}g }d}dd }|t | jk r| j| }|d}||krt||d}|rf| }|| |}|d7 }q||d kr||d}|| || |}|d7 }|d7 }q||k r|| d }	t|	D ]}
| }q||	8 }qtdq|d S )	z7Build the operation tree from the string representationr   Nc                 S   s   d }| d   }| d t| dkrzd| d krzttd| d d}ttd| d d}t||}| d t	|t| dkrd n
| d   |S )Nr   zRecords producedzRecords produced: (\d+)   zExecution time: (\d+.\d+) ms)
strippopr   intresearchgroupfloatr   r   )r   r   r   r   r   r   r   r   _create_operation   s"    


  z8ExecutionPlan._operation_tree.<locals>._create_operationr6   |rE   zcorrupted plan)	r   r-   countsplitrG   r   r   r0   r   )r   r4   levelstackcurrentrM   Z
current_opZop_levelr   Zlevels_back_r   r   r   r.      s:    









zExecutionPlan._operation_treeN)r
   r   r   r   r	   r1   r%   r"   r#   r$   r   r>   r.   r   r   r   r   r&   6   s   r&   )rI   r   r   r&   r   r   r   r   <module>   s   
(