o
    8Di                      @   sz   d dl mZ d dlmZ d dlmZmZ d dlmZ d dl m	Z	 dddZ
dd	d
ZdddZdd Zdd Zdd ZdS )    )exp)
normalized)build_scopefind_in_scope)simplify)DialectNc                 C   s\  ddl m} ddlm} t| }t|}t|||f}|r| }t	t
| D ]}|j}|jd}	|	r|j}
dd t|jdpEg D }d}|
 D ]-\}\}}|tjtj}t|tjr||jd	krp|||fi}
 nt|tjr||r|d
} nqO|rt|	j|
||| |jdpg D ]}|j}||jv rt|jd||j| i|| qq*| S )a  
    Rewrite sqlglot AST to pushdown predicates in FROMS and JOINS

    Example:
        >>> import sqlglot
        >>> sql = "SELECT y.a AS a FROM (SELECT x.a AS a FROM x AS x) AS y WHERE y.a = 1"
        >>> expression = sqlglot.parse_one(sql)
        >>> pushdown_predicates(expression).sql()
        'SELECT y.a AS a FROM (SELECT x.a AS a FROM x AS x WHERE x.a = 1) AS y WHERE TRUE'

    Args:
        expression (sqlglot.Expression): expression to optimize
    Returns:
        sqlglot.Expression: optimized expression
    r   )Athena)Prestowherec                 S   s   i | ]\}}|j |qS  )alias_or_name).0ijoinr   r   ^/var/www/Datamplify/venv/lib/python3.10/site-packages/sqlglot/optimizer/pushdown_predicates.py
<dictcomp>(   s    z'pushdown_predicates.<locals>.<dictcomp>joinsTRIGHTFon)sqlglot.dialects.athenar   sqlglot.dialects.prestor	   r   r   get_or_raise
isinstance	ref_countreversedlisttraverse
expressionargsgetselected_sources	enumerateitemsfind_ancestorr   JoinFromsideUnnestpushdownthisr   )r   dialectr   r	   rootunnest_requires_cross_joinscope_ref_countscopeselectr
   r    
join_indexpushdown_allowedknodesourceparentr   namer   r   r   pushdown_predicates   sP   




r7   c                 C   s   | sd S |  t| |d} t| pt| dd }tt| |r tjntjr(|  n| g}|r8t	||||d d S t
||| d S )N)r*   T)dnf)r0   )replacer   r   r   r   r   AndOrflattenpushdown_cnfpushdown_dnf)	conditionsourcesr-   r*   r0   cnf_like
predicatesr   r   r   r(   K   s   
r(   c           	         s    pi  | D ]c}t ||| D ]X}t|tjrA|j}t||} | t fdd|D rA|t	  |j
|dd  n(t|tjrh|t	  t||}t|tjra|j|dd q|j|dd qqdS )za
    If the predicates are in CNF like form, we can simply replace each block in the parent.
    c                 3   s     | ]}  |d k V  qdS )N)r   )r   tabler0   
this_indexr   r   	<genexpr>k   s    zpushdown_cnf.<locals>.<genexpr>FcopyN)nodes_for_predicatevaluesr   r   r$   r   column_table_namesallr9   truer   Selectreplace_aliasesr   AggFunchavingr
   )	rB   r@   r-   r0   	predicater3   r6   predicate_tablesinner_predicater   rE   r   r=   ^   s&   
r=   c                 C   s  t  }| D ]}t|}| D ]	}|t|M }q|| qi }t|D ]b}| D ]}	t|	||}
||
vr5q(||v rAt|| |	n|	||< q(|
 D ];\}}||vrSqJ|| }	t|tj	re|j
|	dd qJt|tjrt||	}t|tjr~|j|dd qJ|j|dd qJq$dS )z
    If the predicates are in DNF form, we can only push down conditions that are in all blocks.
    Additionally, we can't remove predicates from their original form.
    FrH   N)setr   rL   updatesortedrJ   or_r"   r   r$   r   rO   rP   r   rQ   rR   r
   )rB   r@   r-   pushdown_tablesaa_tablesb
conditionsrD   rS   nodesr6   r3   rU   r   r   r   r>   x   s8   	

r>   c                 C   s$  i }t | }t| t jt jt j}t|D ]x}||pd\}}|r.|r.|t jt j}t|t jrNt|t j	sN|j
jjd}	|	rK|	jrKi   S |j}t|t jre|jr`|jdkr`i   S |||< qt|t jrt|dkrtdd |jD }
|jds|t| dk r|
s|||< q|S )	N)NNwithr      c                 s   s     | ]}| tjr|V  qd S N)findr   Window)r   r/   r   r   r   rG      s    
z&nodes_for_predicate.<locals>.<genexpr>group   )r   rL   r   r#   r$   WhererX   r   r%   Tabler5   r   r   	recursiver&   rO   lenanyselectsid)rS   r@   r-   r_   tableswhere_conditionrD   r3   r4   with_has_window_expressionr   r   r   rJ      s8   



rJ   c                    sJ   i  | j D ]}t|tjr|j |j< q| |j< q fdd}||S )Nc                    s(   t | tjr| j v r | j  S | S rb   )r   r   Columnr6   rI   )columnaliasesr   r   _replace_alias   s   z'replace_aliases.<locals>._replace_alias)rl   r   r   Aliasr)   aliasr6   	transform)r4   rS   r/   rv   r   rt   r   rP      s   

rP   rb   )sqlglotr   sqlglot.optimizer.normalizer   sqlglot.optimizer.scoper   r   sqlglot.optimizer.simplifyr   r   r7   r(   r=   r>   rJ   rP   r   r   r   r   <module>   s    

C
1(