o
    8Di                     @  s   d dl mZ d dlZd dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZmZmZ edZd!d"ddZd#d$ddZd	edfd%ddZedd fddZdd Zdd  ZdS )&    )annotationsN)exp)OptimizeError)while_changing)find_all_in_scope)flattenrewrite_between	uniq_sortsqlglotF   
expressionexp.Expressiondnfboolmax_distanceintc                   s
  t | jdd dD ]x}t|tjrt| drq
|| u }| }|jtdd t	| d}|krBt
d| d	  |   S z|t| fd
d}W n, ty} } z t
| || |ro|W  Y d}~  S | W  Y d}~  S d}~ww |r|} q
| S )a  
    Rewrite sqlglot AST into conjunctive normal form or disjunctive normal form.

    Example:
        >>> import sqlglot
        >>> expression = sqlglot.parse_one("(x AND y) OR z")
        >>> normalize(expression, dnf=False).sql()
        '(x OR z) AND (y OR z)'

    Args:
        expression: expression to normalize
        dnf: rewrite in disjunctive normal form instead.
        max_distance (int): the maximal estimated distance from cnf/dnf to attempt conversion
    Returns:
        sqlglot.Expression: normalized expression
    c                 S  s   t | tjS N)
isinstancer   	Connectore r   T/var/www/Datamplify/venv/lib/python3.10/site-packages/sqlglot/optimizer/normalize.py<lambda>       znormalize.<locals>.<lambda>)pruner   Fcopyr   max_z(Skipping normalization because distance  exceeds max c                      t |  S r   distributive_lawr   r   r   r   r   r   1   r   N)tuplewalkr   r   r   
normalizedr   	transformr   normalization_distanceloggerinforeplacer   r   )r   r   r   noderootoriginaldistancer   r   r%   r   	normalize   s:   

r2   returnc                   s>   |rt jt jfnt jt jf\ }t fddt| |D  S )av  
    Checks whether a given expression is in a normal form of interest.

    Example:
        >>> from sqlglot import parse_one
        >>> normalized(parse_one("(a AND b) OR c OR (d AND e)"), dnf=True)
        True
        >>> normalized(parse_one("(a OR b) AND c"))  # Checks CNF by default
        True
        >>> normalized(parse_one("a AND (b OR c)"), dnf=True)
        False

    Args:
        expression: The expression to check if it's normalized.
        dnf: Whether to check if the expression is in Disjunctive Normal Form (DNF).
            Default: False, i.e. we check if it's in Conjunctive Normal Form (CNF).
    c                 3  s    | ]}|  V  qd S r   )find_ancestor).0	connectorancestorr   r   	<genexpr>S   s    

znormalized.<locals>.<genexpr>)r   AndOranyr   )r   r   r/   r   r7   r   r(   @   s    
r(   infr    floatc                 C  sN   t dd | tjD d  }t| ||D ]}||7 }||kr$|  S q|S )a  
    The difference in the number of predicates between a given expression and its normalized form.

    This is used as an estimate of the cost of the conversion which is exponential in complexity.

    Example:
        >>> import sqlglot
        >>> expression = sqlglot.parse_one("(a AND b) OR (c AND d)")
        >>> normalization_distance(expression)
        4

    Args:
        expression: The expression to compute the normalization distance for.
        dnf: Whether to check if the expression is in Disjunctive Normal Form (DNF).
            Default: False, i.e. we check if it's in Conjunctive Normal Form (CNF).
        max_: stop early if count exceeds this.

    Returns:
        The normalization distance.
    c                 s  s    | ]}d V  qdS )   Nr   )r5   _r   r   r   r9   o   s    z)normalization_distance.<locals>.<genexpr>r?   )sumfind_allr   r   _predicate_lengths)r   r   r    totallengthr   r   r   r*   X   s    r*   c                 c  s    ||kr
|V  dS |   } t| tjsdV  dS |d7 }| j \}}t| |r+tjntjrJt||||D ]}t||||D ]}|| V  q?q6dS t||||E dH  t||||E dH  dS )z
    Returns a list of predicate lengths when expanded to normalized form.

    (A AND B) OR C -> [2, 2] because len(A OR C), len(B OR C).
    Nr?   )	unnestr   r   r   argsvaluesr:   r;   rC   )r   r   r    depthleftrightabr   r   r   rC   y   s$   rC   c           
        s>  t |  dr| S t|  d}|krtd| d t|  fdd  r0tjtjfntjtjf\}}t| |r|  \}}|tjkrKtj	ntj
}|tjkrVtj	ntj
}	t||rt||rtt|tjtt|tjkr~t||||	S t||||	S t||rt||||	S t||rt||||	S | S )z
    x OR (y AND z) -> (x OR y) AND (x OR z)
    (x AND y) OR (y AND z) -> (x OR y) AND (x OR z) AND (y OR y) AND (y OR z)
    r   r   zNormalization distance r!   c                   r"   r   r#   r   r%   r   r   r      r   z"distributive_law.<locals>.<lambda>)r(   r*   r   r   replace_childrenr;   r:   r   unnest_operandsand_or_lenr&   rB   r   _distribute)
r   r   r   r1   to_expfrom_exprL   rM   	from_functo_funcr   r%   r   r$      s(    
(

r$   c                   sZ   t | tjrt|  fdd | S tt|  jtt|  jdd} | S )Nc                   s.   t t|  jt t|  jddS )NFr   )r	   r   rJ   rK   )crM   rV   rW   r   r   r      s
    z_distribute.<locals>.<lambda>Fr   )r   r   r   rN   r	   r   rJ   rK   )rL   rM   rV   rW   r   rY   r   rS      s   rS   )Fr   )r   r   r   r   r   r   )F)r   r   r   r   r3   r   )r   r   r   r   r    r>   r3   r   )
__future__r   loggingr
   r   sqlglot.errorsr   sqlglot.helperr   sqlglot.optimizer.scoper   sqlglot.optimizer.simplifyr   r   r	   	getLoggerr+   r2   r(   r>   r*   rC   r$   rS   r   r   r   r   <module>   s    
2!"