o
    8Dihx                     @  s.  d dl mZ d dlZd dlZd dl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lmZmZmZ edZejejejfZG d	d
 d
e	ZG dd dZd3ddZd4ddZdd Zdd Zdd Zdd Z d5d d!Z!d6d"d#Z"d$d% Z#d&d' Z$d(d) Z%d7d+d,Z&d8d-d.Z'd8d/d0Z(d1d2 Z)dS )9    )annotationsN)defaultdict)Enumauto)exp)OptimizeError)ensure_collectionfind_new_nameseq_getsqlglotc                   @  s0   e Zd Ze Ze Ze Ze Ze Ze Z	dS )	ScopeTypeN)
__name__
__module____qualname__r   ROOTSUBQUERYDERIVED_TABLECTEUNIONUDTF r   r   P/var/www/Datamplify/venv/lib/python3.10/site-packages/sqlglot/optimizer/scope.pyr      s    
r   c                   @  s  e Zd ZdZdddejdddfddZdd Z	dTddZd	d
 Z	dd Z
dUddZddddZddddZdd Zedd Zedd Zedd Zedd Zedd  ZedVd#d$Zed%d& Zed'd( Zed)d* ZedWd,d-Zed.d/ Zed0d1 Zed2d3 Zed4d5 Zed6d7 Zd8d9 Zed:d; Z ed<d= Z!ed>d? Z"ed@dA Z#edBdC Z$edDdE Z%edFdG Z&dHdI Z'dJdK Z(dLdM Z)dNdO Z*dPdQ Z+dRdS Z,dS )XScopea  
    Selection scope.

    Attributes:
        expression (exp.Select|exp.SetOperation): Root expression of this scope
        sources (dict[str, exp.Table|Scope]): Mapping of source name to either
            a Table expression or another Scope instance. For example:
                SELECT * FROM x                     {"x": Table(this="x")}
                SELECT * FROM x AS y                {"y": Table(this="x")}
                SELECT * FROM (SELECT ...) AS y     {"y": Scope(...)}
        lateral_sources (dict[str, exp.Table|Scope]): Sources from laterals
            For example:
                SELECT c FROM x LATERAL VIEW EXPLODE (a) AS c;
            The LATERAL VIEW EXPLODE gets x as a source.
        cte_sources (dict[str, Scope]): Sources from CTES
        outer_columns (list[str]): If this is a derived table or CTE, and the outer query
            defines a column list for the alias of this scope, this is that list of columns.
            For example:
                SELECT * FROM (SELECT ...) AS y(col1, col2)
            The inner query would have `["col1", "col2"]` for its `outer_columns`
        parent (Scope): Parent scope
        scope_type (ScopeType): Type of this scope, relative to it's parent
        subquery_scopes (list[Scope]): List of all child scopes for subqueries
        cte_scopes (list[Scope]): List of all child scopes for CTEs
        derived_table_scopes (list[Scope]): List of all child scopes for derived_tables
        udtf_scopes (list[Scope]): List of all child scopes for user defined tabular functions
        table_scopes (list[Scope]): derived_table_scopes + udtf_scopes, in the order that they're defined
        union_scopes (list[Scope, Scope]): If this Scope is for a Union expression, this will be
            a list of the left and right child scopes.
    Nc	           	      C  s   || _ |pi | _|pi | _|pi | _| j| j | j| j |p#g | _|| _|| _g | _g | _	g | _
g | _g | _g | _|| _|   d S N)
expressionsourceslateral_sourcescte_sourcesupdateouter_columnsparent
scope_typesubquery_scopesderived_table_scopestable_scopes
cte_scopesunion_scopesudtf_scopescan_be_correlatedclear_cache)	selfr   r   r   r    r!   r   r   r(   r   r   r   __init__;   s"   



zScope.__init__c                 C  sd   d| _ d | _d | _d | _d | _d | _d | _d | _d | _d | _	d | _
d | _d | _d | _d | _d | _d S )NF)
_collected_raw_columns_table_columns_stars_derived_tables_udtfs_tables_ctes_subqueries_selected_sources_columns_external_columns_join_hints_pivots_references_semi_anti_join_tablesr*   r   r   r   r)   X   s    
zScope.clear_cachec                 K  sZ   t d| |r| nd| |i | j|pi |r| nd| jp'|tjtjfv d|S )z3Branch from the current scope to a new, inner scopeN)r   r   r    r!   r   r   r(   r   )r   unnestcopyr   r(   r   r   r   )r*   r   r!   r   r   r   kwargsr   r   r   branchj   s   	zScope.branchc                 C  s  g | _ g | _g | _g | _g | _g | _g | _g | _g | _t	 | _
| jddD ]}|| ju r-q%t|tjr=|jr=| j| q%t|tjrXt|jtjrQ| j| q%| j| q%t|tjrt|jtjs|j}t|tjrx|jrx| j
|j | j | q%t|tjr| j| q%t|tjr| j| q%t|tjr| j| q%t|rt|r| j| q%t|tj r| j| q%t|tj!r| j| q%d| _"d S )NFbfsT)#r2   r3   r4   r0   r1   r-   r.   r/   r8   setr;   walkr   
isinstancer   Dotis_starappendColumnthisStarTabler    JoinHintJoinis_semi_or_anti_joinaddalias_or_namer   r   _is_derived_table_is_from_or_joinUNWRAPPED_QUERIESTableColumnr,   )r*   noder    r   r   r   _collectz   sL   

zScope._collectc                 C  s   | j s	|   d S d S r   )r,   rW   r<   r   r   r   _ensure_collected   s   zScope._ensure_collectedTc                 C  s   t | j|d dS )NrB   prune)walk_in_scoper   )r*   rB   rZ   r   r   r   rD         z
Scope.walkrA   c                G     t | j||dS NrA   )find_in_scoper   r*   rB   expression_typesr   r   r   find   r\   z
Scope.findc                G  r]   r^   )find_all_in_scoper   r`   r   r   r   find_all   r\   zScope.find_allc                 C  s   | | |   dS )z
        Replace `old` with `new`.

        This can be used instead of `exp.Expression.replace` to ensure the `Scope` is kept up-to-date.

        Args:
            old (exp.Expression): old node
            new (exp.Expression): new node
        N)replacer)   )r*   oldnewr   r   r   re      s   

zScope.replacec                 C     |    | jS )ze
        List of tables in this scope.

        Returns:
            list[exp.Table]: tables
        )rX   r2   r<   r   r   r   tables      zScope.tablesc                 C  rh   )z_
        List of CTEs in this scope.

        Returns:
            list[exp.CTE]: ctes
        )rX   r3   r<   r   r   r   ctes   rj   z
Scope.ctesc                 C  rh   )z
        List of derived tables in this scope.

        For example:
            SELECT * FROM (SELECT ...) <- that's a derived table

        Returns:
            list[exp.Subquery]: derived tables
        )rX   r0   r<   r   r   r   derived_tables      zScope.derived_tablesc                 C  rh   )z}
        List of "User Defined Tabular Functions" in this scope.

        Returns:
            list[exp.UDTF]: UDTFs
        )rX   r1   r<   r   r   r   udtfs   rj   zScope.udtfsc                 C  rh   )z
        List of subqueries in this scope.

        For example:
            SELECT * FROM x WHERE a IN (SELECT ...) <- that's a subquery

        Returns:
            list[exp.Select | exp.SetOperation]: subqueries
        )rX   r4   r<   r   r   r   
subqueries   rm   zScope.subqueriesreturnt.List[exp.Column | exp.Dot]c                 C  rh   )zK
        List of star expressions (columns or dots) in this scope.
        )rX   r/   r<   r   r   r   stars   s   zScope.starsc                 C  s  | j du r|   | j}dd t| j| jdd | jD D }t| j	j
}g | _ || D ]W}|tjtjtjtjtjtjtjtj}|r~|js~t|tjs~t|tjr[t|jtjr~t|tjtjfrst|jtjtjfs~|j|vs~t|tjr|jdks| j | q-| j S )z
        List of columns in this scope.

        Returns:
            list[exp.Column]: Column instances in this scope, plus any
                Columns that reference this scope from correlated subqueries.
        Nc                 S  s   g | ]
}|j D ]}|qqS r   )external_columns).0scopecolumnr   r   r   
<listcomp>  s    z!Scope.columns.<locals>.<listcomp>c                 s  s    | ]}|j r|V  qd S r   )r(   )rt   dtsr   r   r   	<genexpr>  s    z Scope.columns.<locals>.<genexpr>except)r6   rX   r-   	itertoolschainr"   r'   r#   rC   r   named_selectsfind_ancestorr   SelectQualifyOrderHavingHintrL   rK   DistincttablerE   rJ   Funcr    WindowWithinGroupnamearg_keyrH   )r*   columnsrs   r}   rv   ancestorr   r   r   r     sX   
	



	

zScope.columnsc                 C  s   | j d u r	|   | j S r   )r.   rX   r<   r   r   r   table_columns<  s   
zScope.table_columnsc                 C  sh   | j du r1i }| jD ]#\}}|| jv rq
||v rtd| || jv r-|| j| f||< q
|| _ | j S )an  
        Mapping of nodes and sources that are actually selected from in this scope.

        That is, all tables in a schema are selectable at any point. But a
        table only becomes a selected source if it's included in a FROM or JOIN clause.

        Returns:
            dict[str, (exp.Table|exp.Select, exp.Table|Scope)]: selected sources and nodes
        NzAlias already used: )r5   
referencesr;   r   r   )r*   resultr   rV   r   r   r   selected_sourcesC  s   


zScope.selected_sources$t.List[t.Tuple[str, exp.Expression]]c                 C  sr   | j d u r6g | _ | jD ]}| j |j|f qt| j| jD ]}| j t||j	
dr/|n| f q| j S )Npivots)r:   ri   rH   rQ   r{   r|   rl   rn   _get_source_aliasargsgetr=   )r*   r   r   r   r   r   r   _  s   

zScope.referencesc                   sR    j du r&t jtjr j\}}|j|j  _  j S  fdd jD  _  j S )z
        Columns that appear to reference sources in outer scopes.

        Returns:
            list[exp.Column]: Column instances that don't reference
                sources in the current scope.
        Nc                   s(   g | ]}|j  jvr|j  jvr|qS r   )r   r   semi_or_anti_join_tablesrt   cr<   r   r   rw   ~  s    z*Scope.external_columns.<locals>.<listcomp>)r7   rE   r   r   SetOperationr&   rs   r   )r*   leftrightr   r<   r   rs   p  s   
	
	
zScope.external_columnsc                 C  s   dd | j D S )z
        Unqualified columns in the current scope.

        Returns:
             list[exp.Column]: Unqualified columns
        c                 S  s   g | ]}|j s|qS r   r   r   r   r   r   rw     s    z-Scope.unqualified_columns.<locals>.<listcomp>r   r<   r   r   r   unqualified_columns  s   zScope.unqualified_columnsc                 C  s   | j du rg S | j S )z
        Hints that exist in the scope that reference tables

        Returns:
            list[exp.JoinHint]: Join hints that are referenced within the scope
        N)r8   r<   r   r   r   
join_hints  s   
zScope.join_hintsc                 C  s   | j sdd | jD | _ | j S )Nc                 S  s*   g | ]\}}|j d pg D ]}|qqS )r   )r   r   )rt   _rV   pivotr   r   r   rw     s
    z Scope.pivots.<locals>.<listcomp>)r9   r   r<   r   r   r   r     s
   zScope.pivotsc                 C  s   | j pt S r   )r;   rC   r<   r   r   r   r     s   zScope.semi_or_anti_join_tablesc                   s    fdd| j D S )z
        Get all columns in the current scope for a particular source.

        Args:
            source_name (str): Name of the source
        Returns:
            list[exp.Column]: Column instances that reference `source_name`
        c                   s   g | ]	}|j  kr|qS r   r   )rt   rv   source_namer   r   rw     s    z(Scope.source_columns.<locals>.<listcomp>r   )r*   r   r   r   r   source_columns  s   	zScope.source_columnsc                 C     | j tjkS )z%Determine if this scope is a subquery)r!   r   r   r<   r   r   r   is_subquery     zScope.is_subqueryc                 C  r   )z*Determine if this scope is a derived table)r!   r   r   r<   r   r   r   is_derived_table  r   zScope.is_derived_tablec                 C  r   )z"Determine if this scope is a union)r!   r   r   r<   r   r   r   is_union  r   zScope.is_unionc                 C  r   )z4Determine if this scope is a common table expression)r!   r   r   r<   r   r   r   is_cte  r   zScope.is_ctec                 C  r   )z#Determine if this is the root scope)r!   r   r   r<   r   r   r   is_root  r   zScope.is_rootc                 C  r   )z?Determine if this scope is a UDTF (User Defined Table Function))r!   r   r   r<   r   r   r   is_udtf  r   zScope.is_udtfc                 C  s   t | jo| jS )z0Determine if this scope is a correlated subquery)boolr(   rs   r<   r   r   r   is_correlated_subquery  s   zScope.is_correlated_subqueryc                 C  s    | j |pdg }|| j |< dS )zRename a source in this scope N)r   pop)r*   old_namenew_namer   r   r   r   rename_source  s   zScope.rename_sourcec                 C  s   || j |< |   dS )zAdd a source to this scopeN)r   r)   )r*   r   sourcer   r   r   
add_source  s   
zScope.add_sourcec                 C  s   | j |d |   dS )zRemove a source from this scopeN)r   r   r)   )r*   r   r   r   r   remove_source  s   zScope.remove_sourcec                 C  s   d| j   dS )NzScope<>)r   sqlr<   r   r   r   __repr__  s   zScope.__repr__c                 c  sV    | g}g }|r"|  }|| |t|j|j|j|j |st	|E dH  dS )z
        Traverse the scope tree from this node.

        Yields:
            Scope: scope instances in depth-first-search post-order
        N)
r   rH   extendr{   r|   r%   r&   r$   r"   reversed)r*   stackr   ru   r   r   r   traverse  s    
zScope.traversec                 C  sF   t dd }|  D ]}|j D ]\}}|t|  d7  < qq
|S )z
        Count the number of times each scope in this tree is referenced.

        Returns:
            dict[int, int]: Mapping of Scope instance ID to reference count
        c                   S  s   dS )Nr   r   r   r   r   r   <lambda>  s    z!Scope.ref_count.<locals>.<lambda>   )r   r   r   valuesid)r*   scope_ref_countru   r   r   r   r   r   	ref_count  s   zScope.ref_count)NNNTN)rp   rq   )rp   r   )-r   r   r   __doc__r   r   r+   r)   r@   rW   rX   rD   rb   rd   re   propertyri   rk   rl   rn   ro   rr   r   r   r   r   rs   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r      s    "

,









6



	









r   r   exp.Expressionrp   t.List[Scope]c                 C  s   t | trttt| S g S )a  
    Traverse an expression by its "scopes".

    "Scope" represents the current context of a Select statement.

    This is helpful for optimizing queries, where we need more information than
    the expression tree itself. For example, we might care about the source
    names within a subquery. Returns a list because a generator could result in
    incomplete properties which is confusing.

    Examples:
        >>> import sqlglot
        >>> expression = sqlglot.parse_one("SELECT a FROM (SELECT a FROM x) AS y")
        >>> scopes = traverse_scope(expression)
        >>> scopes[0].expression.sql(), list(scopes[0].sources)
        ('SELECT a FROM x', ['x'])
        >>> scopes[1].expression.sql(), list(scopes[1].sources)
        ('SELECT a FROM (SELECT a FROM x) AS y', ['y'])

    Args:
        expression: Expression to traverse

    Returns:
        A list of the created scope instances
    )rE   TRAVERSABLESlist_traverse_scoper   r   r   r   r   traverse_scope  s   
r   t.Optional[Scope]c                 C  s   t t| dS )z
    Build a scope tree.

    Args:
        expression: Expression to build the scope tree for.

    Returns:
        The root scope
    )r
   r   r   r   r   r   build_scope0  s   
r   c                 c  s|   | j }t|tjrt| E d H  nt|tjr(t| E d H  t| E d H  d S t|tjrA| j	r9t| E d H  nt
| E d H  nxt|tjrOt| E d H  njt|tjr]t| E d H  n\t|tjrt|j tjr~t| E d H  tt|j | jdE d H  d S t|tjrt| E d H  t|tjD ]}t|jtjtjfstt|| jdE d H  qd S td|t| d S | V  d S )N)r   z'Cannot traverse scope %s with type '%s')r   rE   r   r   _traverse_selectr   _traverse_ctes_traverse_unionSubqueryr   _traverse_subqueriesrL   _traverse_tablesr   _traverse_udtfsDDLQueryr   r   r   DMLrc   r    r   loggerwarningtype)ru   r   queryr   r   r   r   =  s>   
r   c                 c  s0    t | E d H  t| E d H  t| E d H  d S r   )r   r   r   )ru   r   r   r   r   b  s   r   c                 c  s    d }| g}| j j| j jg}|r_| }|d }|j||jtjd}t|t	j
r>t|E d H  || ||j|jg qt|D ]} | V  qB|rY|  || g|_|}|V  n| }|sd S d S )Nr   )r   r!   )r   r   r   r   r@   r   r   r   rE   r   r   r   rH   r   r   r&   )ru   
prev_scopeunion_scope_stackexpression_stackr   union_scope	new_scoper   r   r   r   h  s4   

r   c                 c  s    i }| j D ]G}|j}| jjd}|r+|jr+|j}t|tj	r+| j
|jtjd||< d }t| j
|j||jtjdD ]}|V  q;|rM|||< | j| q| j| | j| d S )Nwithr!   )r   r   r!   )rk   aliasr   r   r   	recursiverJ   rE   r   r   r@   r   r   r   alias_column_namesr%   rH   r   r   r   )ru   r   ctecte_namewith_unionchild_scoper   r   r   r     s2   

r   exp.Subqueryr   c                 C  s$   t | tjot| jpt | jtjS )z
    We represent (tbl1 JOIN tbl2) as a Subquery, but it's not really a "derived table",
    as it doesn't introduce a new scope. If an alias is present, it shadows all names
    under the Subquery, so that's one exception to this rule.
    )rE   r   r   r   r   rJ   rT   r   r   r   r   rR     s   rR   c                 C  s6   | j }t|tjr|j }t|tjs	t|tjtjfS )zU
    Determine if `expression` is the FROM or JOIN clause of a SELECT statement.
    )r    rE   r   r   FromrN   )r   r    r   r   r   rS     s
   rS   c                 c  s2   i }g }| j jd}|r||j | j jdpg D ]}||j qt| j tjr3|| j  || j jdp=g  |D ]}t|tj	rL|j}t|tjr|j
}|j}|| jv rx|jsx|jd}|rp|||d j< n| j| ||< n||v r||t||< n|||< || j ur|dd |jdpg D  qAt|tjsqAt|tjr|}	tj}
| j}n4t|rd }	tj}
| j}|dd |jdpg D  n||j |d	d |jdpg D  qAd }t| j||	|j|
d
D ]}|V  ||t|< q|r|| | j| qA| j| d S )Nfromjoinslateralsr   r   c                 s      | ]}|j V  qd S r   rJ   rt   joinr   r   r   ry         z#_traverse_tables.<locals>.<genexpr>c                 s  r   r   r   r   r   r   r   ry     r   c                 s  r   r   r   r   r   r   r   ry     r   )r   r   r!   )r   r   r   rH   rJ   rE   r   rL   r   Finalr   rQ   r   dbr   r	   DerivedTabler   r   r'   rR   r   r#   r   r@   r   r   r$   r   )ru   r   expressionsfrom_r   r   
table_namer   r   r   r!   scopesr   r   r   r   r     st   
 " 
r   c                 c  sF    | j D ]}d }t| j|tjdD ]}|V  |}q| j| qd S )Nr   )ro   r   r@   r   r   r"   rH   )ru   subquerytopr   r   r   r   r     s   
r   c                 c  s    t | jtjr| jj}nt | jtjr| jjg}ng }i }|D ](}t|rHd }t| j	|t
j|jdD ]}|V  |}||t|< q4| j| q | j| d S )N)r!   r   )rE   r   r   Unnestr   LateralrJ   rR   r   r@   r   r   r   r   r"   rH   r   r   )ru   r   r   r   r   r   r   r   r   r   '  s.   
r   Tc                 #  s    d | j | fdddD ]Y}d |V  || u rqt|tjsDt|jtjtjtjfr1t|sDt|jtj	r>t|tj
sDt|tjrhd t|tjtj	frhdD ]}|j|pZg D ]}t||dE dH  q[qQqdS )	a3  
    Returns a generator object which visits all nodes in the syntrax tree, stopping at
    nodes that start child scopes.

    Args:
        expression (exp.Expression):
        bfs (bool): if set to True the BFS traversal order will be applied,
            otherwise the DFS traversal will be used instead.
        prune ((node, parent, arg_key) -> bool): callable that returns True if
            the generator should stop traversing this branch of the tree.

    Yields:
        tuple[exp.Expression, Optional[exp.Expression], str]: node, parent, arg key
    Fc                   s    po| S r   r   )ncrossed_scope_boundaryrZ   r   r   r   W  s    zwalk_in_scope.<locals>.<lambda>rY   T)r   r   r   rA   N)rD   rE   r   r   r    r   rN   r   rR   r   r   rT   r   r   r[   )r   rB   rZ   rV   keyargr   r  r   r[   C  s:   



	r[   c                 c  s0    t | |dD ]} t| tt|r| V  qdS )a  
    Returns a generator object which visits all nodes in this scope and only yields those that
    match at least one of the specified expression types.

    This does NOT traverse into subscopes.

    Args:
        expression (exp.Expression):
        expression_types (tuple[type]|type): the expression type(s) to match.
        bfs (bool): True to use breadth-first search, False to use depth-first.

    Yields:
        exp.Expression: nodes
    rA   N)r[   rE   tupler   r   ra   rB   r   r   r   rc   r  s   rc   c                 C  s   t t| ||ddS )a  
    Returns the first node in this scope which matches at least one of the specified types.

    This does NOT traverse into subscopes.

    Args:
        expression (exp.Expression):
        expression_types (tuple[type]|type): the expression type(s) to match.
        bfs (bool): True to use breadth-first search, False to use depth-first.

    Returns:
        exp.Expression: the node which matches the criteria or None if no node matching
        the criteria was found.
    rA   N)nextrc   r	  r   r   r   r_     s   r_   c                 C  s@   | j d}| j}|st|tjrt|jdkr|jd j}|S )Nr   r   r   )	r   r   r   rE   r   
TableAliaslenr   r   )r   	alias_arg
alias_namer   r   r   r     s
   r   )r   r   rp   r   )r   r   rp   r   )r   r   rp   r   )r   r   rp   r   r   )T)*
__future__r   r{   loggingtypingtcollectionsr   enumr   r   r   r   sqlglot.errorsr   sqlglot.helperr   r	   r
   	getLoggerr   r   r   r   r   r   r   r   r   r   r   r   r   rR   rS   r   r   r   r[   rc   r_   r   r   r   r   r   <module>   s>    
	   
y
%#
$
W	

/
