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
mZ ejr-d dlmZ d dlmZ dNddZdOddZdOddZdOddZdOddZdOddZdOddZdOddZ	dPdQd!d"Z	 dRdSd&d'ZdOd(d)ZdOd*d+ZdOd,d-ZdOd.d/ZdOd0d1ZdOd2d3Z dTd5d6Z!dOd7d8Z"dOd9d:Z#dOd;d<Z$d=d> fdUd@dAZ%dOdBdCZ&dOdDdEZ'dOdFdGZ(dOdHdIZ)dOdJdKZ*dOdLdMZ+dS )V    )annotationsNexpressions)UnsupportedError)find_new_namename_sequence)E)	Generator
transforms4t.List[t.Callable[[exp.Expression], exp.Expression]]return,t.Callable[[Generator, exp.Expression], str]c                   s   d fdd}|S )	a  
    Creates a new transform by chaining a sequence of transformations and converts the resulting
    expression to SQL, using either the "_sql" method corresponding to the resulting expression,
    or the appropriate `Generator.TRANSFORMS` function (when applicable -- see below).

    Args:
        transforms: sequence of transform functions. These will be called in order.

    Returns:
        Function that can be used as a generator transform.
    
expressionexp.Expressionr   strc              
     s   t |}z d |} dd  D ]}||}qW n ty2 } z| t| W Y d }~nd }~ww t| |jd d }|rB||S | jt |}|rl|t |u rgt|t	j
r]| |S td|jj d|| |S td|jj d)Nr      _sqlzExpression type z3 requires a _sql method in order to be transformed.zUnsupported expression type .)typer   unsupportedr   getattrkey
TRANSFORMSget
isinstanceexpFuncfunction_fallback_sql
ValueError	__class____name__)selfr   expression_type	transformunsupported_error_sql_handlertransforms_handlerr
    K/var/www/Datamplify/venv/lib/python3.10/site-packages/sqlglot/transforms.py_to_sql   s.   


zpreprocess.<locals>._to_sqlN)r   r   r   r   r(   )r
   r*   r(   r'   r)   
preprocess   s   r+   r   r   c              	   C  s  t | tjrd}g }| tjD ]}t |jtjtjfr,t|j	dks,t |j	d tj
s-q|j	d }|jd}|jd}|jd}|rN|rNt |tjsOq|jd}t |tjr`|jd nd}	t|d}td	|	tj|j|jd
}
t|
d}d|rd| nd }t||	}t|||t|dk}|j|dd}t|	|}||| |tjtj|d||	gd |d7 }q|r| jdpt }| dd | dg ||j	 |  d| | S )Nr   r   startendstepalias
date_valuedatedate_addunit_generated_dates_ F)distinctthistablewith	recursiveTr   )!r   r   Selectfind_allUnnestparentFromJoinlenr   GenerateDateArrayargsr   Interval
TableAliascolumnscastfuncLiteralnumbernameselectas_from_whereunionreplacesubqueryappendalias_CTEWithset)r   countrecursive_ctesunnestgenerate_date_arrayr,   r-   r.   r/   column_namer2   cast_date_addcte_name
base_queryrecursive_query	cte_querygenerate_dates_querywith_expressionr(   r(   r)   .unnest_generate_date_array_using_recursive_cte@   sT   

rg   c                 C  sP   | j }t| tjr&t|tjr&tj|gd}| jr$tj|d| jgddS |S | S )z5Unnests GENERATE_SERIES or SEQUENCE table references.r   _uF)r/   r;   copy)r9   r   r   TableGenerateSeriesr@   r/   rW   )r   r9   r]   r(   r(   r)   unnest_generate_seriesy   s   rl   c                 C  sz   t | tjr;t | jtjr;dd t| jjddD }| jD ]}t |tjr:|js:|j	|v r:|
tj||j	 q| S )ap  
    Replace references to select aliases in GROUP BY clauses.

    Example:
        >>> import sqlglot
        >>> sqlglot.parse_one("SELECT a AS b FROM x GROUP BY b").transform(unalias_group).sql()
        'SELECT a AS b FROM x GROUP BY 1'

    Args:
        expression: the expression that will be transformed.

    Returns:
        The transformed expression.
    c                 S  s$   i | ]\}}t |tjr|j|qS r(   )r   r   Aliasr/   ).0ier(   r(   r)   
<dictcomp>   s    
z!unalias_group.<locals>.<dictcomp>r   r,   )r   r   GrouprA   r>   	enumerater   Columnr;   rN   rT   rL   rM   r   )r   aliased_selectsgroup_byr(   r(   r)   unalias_group   s   


rx   c           
      C  s  t | tjr| jdrt | jd jdtjrt| jd}| jd  jd j	}tj
t |d}| jd}|rD|d|  n|dtjdd |D d t||}| j|d	d
 g }|h}| jdd D ]B}|jrxt g} n7t |tjst||jpd}t |tjr|jjdnd}	|tj|||	d}||j ||jd  qltj|dd	ij| jdd	d
d	d
jt|dd	d
S | S )a4  
    Convert SELECT DISTINCT ON statements to a subquery with a window function.

    This is useful for dialects that don't support SELECT DISTINCT ON but support window functions.

    Args:
        expression: the expression that will be transformed.

    Returns:
        The transformed expression.
    r7   on_row_number)r9   partition_byorderc                 S  s   g | ]}|  qS r(   ri   rn   cr(   r(   r)   
<listcomp>       z)eliminate_distinct_on.<locals>.<listcomp>r   Fr}   N_colquotedr   r/   ri   _tr   )r   r   r>   rF   r   Tupler   named_selectspopr   Window	RowNumberrZ   OrderrW   rO   selectsis_starStarrm   output_nameru   r9   rT   addrV   rQ   rU   rR   columneq)
r   row_number_window_aliasdistinct_colswindowr|   new_selectstaken_namesrO   r/   r   r(   r(   r)   eliminate_distinct_on   sD   


r   c                 C  s  t | tjr| jdrt| j}| jD ]}|js,t	|d}|
t|| || qddd}tjtt|| j }| jd  j}d	d
 | jD }| jrStjntjtjf}t||D ]U}	t |	tjr|r|	tjD ]}
||
j}|r|

| qpt	| jd}| jt|	|dd t|}
t |	jtjr|
}q`|	
|
 q`|	j| jvr| j|	 dd q`|j| jdddddj|ddS | S )a@  
    Convert SELECT statements that contain the QUALIFY clause into subqueries, filtered equivalently.

    The idea behind this transformation can be seen in Snowflake's documentation for QUALIFY:
    https://docs.snowflake.com/en/sql-reference/constructs/qualify

    Some dialects don't support window functions in the WHERE clause, so we need to include them as
    projections in the subquery, in order to refer to them in the outer filter using aliases. Also,
    if a column is referenced in the QUALIFY clause but is not selected, we need to include it too,
    otherwise we won't be able to refer to it in the outer query's WHERE clause. Finally, if a
    newly aliased projection is referenced in the QUALIFY clause, it will be replaced by the
    corresponding expression to avoid creating invalid column references.
    qualify_crO   r   r   str | exp.Columnc                 S  s>   | j }| jdp| j}t|tjrtj||jddS |S )Nr/   r   r   )alias_or_namerF   r   r9   r   r   
Identifierr   )rO   r   
identifierr(   r(   r)   _select_alias_or_name   s
   z0eliminate_qualify.<locals>._select_alias_or_namec                 S  s"   i | ]}t |tjr|j|jqS r(   )r   r   rm   r/   r9   )rn   rO   r(   r(   r)   rq      s    
z%eliminate_qualify.<locals>.<dictcomp>_wFr}   r   )r/   ri   N)rO   r   r   r   )r   r   r>   rF   r   rZ   r   r   r   r   rT   rW   r   rO   listmapr   r9   r   r   ru   r?   rN   r   rA   Qualifyri   rQ   rU   rR   )r   takenrO   r/   r   outer_selectsqualify_filtersexpression_by_aliasselect_candidatesselect_candidater   exprr(   r(   r)   eliminate_qualify   sH   






r   c                 C  s.   |  tjD ]}|ddd |jD  q| S )z
    Some dialects only allow the precision for parameterized types to be defined in the DDL and not in
    other expressions. This transforms removes the precision from parameterized types in expressions.
    r   c                 S  s   g | ]
}t |tjs|qS r(   )r   r   DataTypeParamrn   rp   r(   r(   r)   r   &      z8remove_precision_parameterized_types.<locals>.<listcomp>)r?   r   DataTyperZ   r   )r   noder(   r(   r)   $remove_precision_parameterized_types  s
   r   c                 C  sn   ddl m} t| tjr5dd || tjD }|r5| tjD ]}|jd }|j	dkr4|j
|v r4|  q| S )zYRemove references to unnest table aliases, added by the optimizer's qualify_columns step.r   find_all_in_scopec                 S  s&   h | ]}t |jtjtjfr|jqS r(   )r   rA   r   rB   rC   r/   )rn   r]   r(   r(   r)   	<setcomp>1  s    z#unqualify_unnest.<locals>.<setcomp>r9   )sqlglot.optimizer.scoper   r   r   r>   r@   r?   ru   partsarg_keyr9   r   )r   r   unnest_aliasesr   leftmost_partr(   r(   r)   unqualify_unnest,  s   

r   Tunnest_using_arrays_zipboolc                   s   d fdd	}ddd}t | tjr| jd}|rwt |jtjrw|j}|jd}|j}t|dk}||||^}	}
|rA|j	ng }|jd}|r\|
dt |tjrV|ntd |tj||||	|
d|rrtj|j|dndd | jdp~g }t|D ]}|j}t |tj}|r|jn|}t |tjr|r|jd}n|jd}|j}t|dk}||||}|| |r|j	ng }|st|dvrtd|jd}|r|
dt |tjr|ntd t||D ]\}}| dtj||||ddtj|j|dd qq| S ) z4Convert cross join unnest into lateral view explode.u
exp.Unnestunnest_exprst.List[exp.Expression]has_multi_exprr   r   c                   s4   |r st dtjd|dg}| d| |S |S )Nz2Cannot transpile UNNEST with multiple input arrays
ARRAYS_ZIPr9   r   r   )r   r   	AnonymousrZ   )r   r   r   	zip_exprsr   r(   r)   _unnest_zip_exprsE  s   z,unnest_to_explode.<locals>._unnest_zip_exprst.Type[exp.Func]c                 S  s"   | j dr	tjS |rtjS tjS )Noffset)rF   r   r   
PosexplodeInlineExplode)r   r   r(   r(   r)   
_udtf_typeT  s   z%unnest_to_explode.<locals>._udtf_typefromr/   r   r   r   posr   )r9   rI   N)r9   r/   joins)r      zYCROSS JOIN UNNEST to LATERAL VIEW EXPLODE transformation requires explicit column aliaseslateralsr8   T)r9   viewr/   )r   r   r   r   r   r   r   r   )r   r   r   r   r   r   )r   r   r>   rF   r   r9   r@   r   rD   rI   insertr   to_identifierrT   rj   rH   r   Lateralremover   ziprV   )r   r   r   r   rQ   r]   r/   exprsr   r9   r   rI   r   r   join	join_expr
is_lateral
alias_colsrp   r   r(   r   r)   unnest_to_explode?  s~   


r   index_offsetint,t.Callable[[exp.Expression], exp.Expression]c                   s   d fdd}|S )z4Convert explode/posexplode projections into unnests.r   r   r   c                   s  t | tjrddlm} t| j}dd || jD }d'd
d}g }||d}tjtj	tj
tj dgd||d|gd}t| jD ]~}|tj}	|	rd}
d}t |tjrd|jd }|}n0t |tjr|jd }
|jd }|tj|jddd}n|t|d}|tj}	|	sJ t |	tj}|	j}t |	tjr|d }|dd |dd tdtdtd|t dtj|dd|}t |tjr||j ||d}|s||d}|r||d}
|
s||d}
|dt | |jd j}tj!tj"||dtj"|
|dtj"||dd}|	| |rR| j#}|$|%|d tj!tj"||dtj"|
|dtj"|
|dd&|
 | d| |sl| j'dre| j(|dd d! n| j)|dd tj*|+ d"}|,| | j(tjtj	|+ gt |
d#||gdd dd$  dkr|d }| j-tj"||dtj"|
|d.tj"||d|k/tj"|
|d|dd qF|rtj0|d |dd  d%} dkr|d   }|j#d d&| | S )(Nr   )Scopec                 S  s   h | ]\}}|qS r(   r(   )rn   rN   r5   r(   r(   r)   r     r   zVexplode_projection_to_unnest.<locals>._explode_projection_to_unnest.<locals>.<setcomp>names
t.Set[str]rN   r   r   c                 S  s   t | |}| | |S N)r   r   )r   rN   r(   r(   r)   new_name  s   

zUexplode_projection_to_unnest.<locals>._explode_projection_to_unnest.<locals>.new_namer   rr   r   rh   r:   r6   r/   r   Fr}   safeTr   IF
ARRAY_SIZECOALESCEcol)r9   truer   r   CROSS)ri   	join_typer8   )r   r   )r   ri   r   r-   )r   r   rN   r   r   r   )1r   r   r>   r   r   rZ   r   
referencesrW   r@   rk   rL   rM   r   r   findr   rm   rF   AliasesaliasesrT   r9   r   ExplodeOuterrK   Arrayr   arrayru   r   r   r   Ifr   r   r   indexrP   r   r   rQ   	ArraySizeri   rV   rR   or_and_Greatest)r   r   taken_select_namestaken_source_namesr   arraysseries_aliasseriesrO   explode	pos_aliasexplode_aliasr/   is_posexplodeexplode_argbracketunnest_source_aliasseries_table_aliasr   r   sizer-   r   r(   r)   _explode_projection_to_unnest  s   


	








	


zCexplode_projection_to_unnest.<locals>._explode_projection_to_unnestNr   r   r   r   r(   )r   r  r(   r  r)   explode_projection_to_unnest  s    r  c                 C  sd   t | tjr0t | jtjs0| jr0| j }| d| j  tj	tj
|dgd}tj| |d} | S )z?Transforms percentiles by adding a WITHIN GROUP clause to them.r9   r8   r   r9   r   )r   r   PERCENTILESrA   WithinGroupr   r9   r   rZ   r   Ordered)r   r   r|   r(   r(   r)    add_within_group_for_percentilesC  s   

r  c                 C  s`   t | tjr.t | jtjr.t | jtjr.| jj}ttj	| 
tj	j}| tj||dS | S )zQTransforms percentiles by getting rid of their corresponding WITHIN GROUP clause.)r9   quantile)r   r   r  r9   r  r   r   trJ   r  r   rT   ApproxQuantile)r   r  input_valuer(   r(   r)   #remove_within_group_for_percentilesR  s   
r  c                   sp   t | tjr6| jr6td | jD ]%}|jd js5|j}t |tj	r$|j}|jd 
d fdd|jD  q| S )zVUses projection output names in recursive CTE definitions to define the CTEs' columns._c_r/   rI   c                   s   g | ]}t |jp  qS r(   )r   r   r   )rn   s	next_namer(   r)   r   m      z2add_recursive_cte_column_names.<locals>.<listcomp>)r   r   rY   r=   r   r   rF   rI   r9   SetOperationrZ   r   )r   ctequeryr(   r  r)   add_recursive_cte_column_names`  s   

r!  c                 C  sH   t | tjtjfr"| j dkr"| jjtjj	v r"| j
tjd | S )z8Replace 'epoch' in casts by the equivalent date literal.epochz1970-01-01 00:00:00)r   r   CastTryCastrN   lowertor9   r   TEMPORAL_TYPESrT   rL   stringr   r(   r(   r)   epoch_cast_to_tss  s   r*  c                 C  s   t | tjrF| jdpg D ]7}|jd}|rE|jdv rEtd|j	|}tj
|d}|jdkr:|jdd}|  | j	|dd q| S )	zIConvert SEMI and ANTI joins into equivalent forms that use EXIST instead.r   ry   )SEMIANTI1r8   r,  Fr}   )r   r   r>   rF   r   kindrO   rQ   r9   rR   Existsnot_r   )r   r   ry   rU   existsr(   r(   r)   eliminate_semi_and_anti_joins  s   
r2  c                   s  t | tjrdd t| jdpg D }t|dkr|  }| dd |d \}}| jd j	|j	f |jd	pItj
 fd
d|jdD  }|dd td| jd |}|jd | dd |tj|d }|jdd | jdd tj| |dddS | S )z
    Converts a query with a FULL OUTER join to a union of identical queries that
    use LEFT/RIGHT OUTER joins instead. This transformation currently only works
    for queries that have a single FULL OUTER join.
    c                 S  s"   g | ]\}}|j d kr||fqS )FULL)side)rn   r   r   r(   r(   r)   r     s
    
z-eliminate_full_outer_join.<locals>.<listcomp>r   r   limitNr   r   ry   c              	     s.   g | ]}t | d  t | d qS )r   r   )r   r   r   rn   r   tablesr(   r)   r     s     usingr4  leftr-  rightr8   r<   r|   F)ri   r7   )r   r   r>   rt   rF   r   rD   ri   rZ   r   r   rO   rQ   rR   r/  r0  r   rS   )r   full_outer_joinsexpression_copyr   full_outer_joinjoin_conditionsanti_join_clauser(   r7  r)   eliminate_full_outer_join  s,   

rA  r   c                 C  s   | j d}| tjD ]J}|j| u rq|s!| }| d| q|jr*|dd |	tj
}|  |rL|j|}|j|j||< |d|j q|d|j|j  q| S )a  
    Some dialects (e.g. Hive, T-SQL, Spark prior to version 3) only allow CTEs to be
    defined at the top-level, so for example queries like:

        SELECT * FROM (WITH t(c) AS (SELECT 1) SELECT * FROM t) AS subq

    are invalid in those dialects. This transformation can be used to ensure all CTEs are
    moved to the top level so that the final SQL code is valid from a syntax standpoint.

    TODO: handle name clashes whilst moving CTEs (it can get quite tricky & costly).
    r<   r=   Tr   )rF   r   r?   r   rY   rA   r   rZ   r=   find_ancestorrX   r   r   )r   top_level_with
inner_with
parent_ctero   r(   r(   r)   move_ctes_to_top_level  s&   
rF  c                 C  s2   ddl m} d
dd}|  D ]}||| q| S )zMConverts numeric values used in conditions into explicit boolean expressions.r   )ensure_boolsr   r   r   Nonec                 S  s\   | j s t| tjs| jtjjjgtjjR  s t| tj	r*| j
s,| | d d S d S d S )Nr   )	is_numberr   r   SubqueryPredicateis_typer   TypeUNKNOWNNUMERIC_TYPESru   r   rT   neq)r   r(   r(   r)   _ensure_bool  s   

z"ensure_bools.<locals>._ensure_boolN)r   r   r   rH  )sqlglot.optimizer.canonicalizerG  walk)r   rG  rP  r   r(   r(   r)   rG    s
   
rG  c                 C  s2   |  tjD ]}|jd d D ]}|  qq| S )Nr   )r?   r   ru   r   r   )r   r   partr(   r(   r)   unqualify_columns  s
   
rT  c                 C  s6   t | tjsJ | tjD ]
}|jr|j  q| S r   )r   r   Creater?   UniqueColumnConstraintrA   r   )r   
constraintr(   r(   r)   remove_unique_constraints  s   
rX  c                 C  s   | S r   r(   )rp   r(   r(   r)   <lambda>  s    rY  tmp_storage_providerc                 C  sl   t | tjsJ | jd}tdd |r|jng D }| jdkr4|r4| jr0tjd| j	| jdS || S | S )N
propertiesc                 s  s    | ]	}t |tjV  qd S r   )r   r   TemporaryProperty)rn   propr(   r(   r)   	<genexpr>
  s
    

z:ctas_with_tmp_tables_to_create_tmp_view.<locals>.<genexpr>TABLEzTEMPORARY VIEW)r.  r9   r   )
r   r   rU  rF   r   anyr   r.  r   r9   )r   rZ  r[  	temporaryr(   r(   r)   'ctas_with_tmp_tables_to_create_tmp_view  s   rb  c                   s   t | tjsJ t | jtj}| jdv }|ra|ra| tj}|ra|jrat |jtjsa| j}dd |jjD   fdd|jD |	dfdd|jD  |
tjtjdd	 | 	d
| | S )a   
    In Hive, the PARTITIONED BY property acts as an extension of a table's schema. When the
    PARTITIONED BY value is an array of column names, they are transformed into a schema.
    The corresponding columns are removed from the create statement.
    >   VIEWr_  c                 S  s   h | ]}|j  qS r(   rN   upper)rn   vr(   r(   r)   r   *  s    z8move_schema_columns_to_partitioned_by.<locals>.<setcomp>c                   s   g | ]}|j   v r|qS r(   rd  r6  )rI   r(   r)   r   +  r  z9move_schema_columns_to_partitioned_by.<locals>.<listcomp>r   c                   s   g | ]}| vr|qS r(   r(   r   )
partitionsr(   r)   r   ,      r   r8   r9   )r   r   rU  r9   Schemar.  r   PartitionedByPropertyr   rZ   rT   )r   
has_schemais_partitionabler]  schemar(   )rI   rg  r)   %move_schema_columns_to_partitioned_by  s   
rn  c                 C  s   t | tjsJ | tj}|rH|jrHt |jtjrHtdd |jjD rHtj	dd |jjD d}| j}|jjD ]}|
d| q9|d| | S )z
    Spark 3 supports both "HIVEFORMAT" and "DATASOURCE" formats for CREATE TABLE.

    Currently, SQLGlot uses the DATASOURCE format for Spark 3.
    c                 s  s"    | ]}t |tjo|jV  qd S r   )r   r   	ColumnDefr.  r   r(   r(   r)   r^  ?  s     z8move_partitioned_by_to_schema_columns.<locals>.<genexpr>c                 S  s   g | ]}t |jqS r(   )r   r   r9   r   r(   r(   r)   r   B  rh  z9move_partitioned_by_to_schema_columns.<locals>.<listcomp>r   r   r9   )r   r   rU  r   rj  r9   ri  allr   r   rV   rZ   )r   r]  	prop_thisrm  rp   r(   r(   r)   %move_partitioned_by_to_schema_columns3  s$   rr  c                 C  s(   t | tjr| ddd | jD  | S )z:Converts struct arguments to aliases, e.g. STRUCT(1 AS y).r   c                 S  s,   g | ]}t |tjrt|j|jn|qS r(   )r   r   
PropertyEQrW   r   r9   r   r(   r(   r)   r   Q  s    z&struct_kv_to_alias.<locals>.<listcomp>)r   r   StructrZ   r   r)  r(   r(   r)   struct_kv_to_aliasL  s   ru  c                 C  s  ddl m} ddlm}m} ddlm} t|| D ]L}|j}|j	
d}|j	
dg }|jr4J d|rCtdd	 |tjD sDq||j}||sQJ d
|t}	t|tjs^|gn| D ]7}
dd |
tjD }tdd	 |D }|s{qbt|dkrJ d|D ]}|dd q|	|  |
 qbdd |D }i }|j	d }|	 D ][\}}|
||j }tj|tj| dd||j< |D ]=}t|jtjr|j | t|jtjs|j}|  t|tj!r| |j"du r|j#n|j" qt|tj$r|  qq|j|v r4|% |%  }t|dks!J dt|d }|dtj&|| jd |rg| D ]!\}}||vr[||j	d j'kr[|j(sW|dd |||< q;|dt|)  q| S )aN  https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries006.htm#sthref3178

    1. You cannot specify the (+) operator in a query block that also contains FROM clause join syntax.

    2. The (+) operator can appear only in the WHERE clause or, in the context of left-correlation (that is, when specifying the TABLE clause) in the FROM clause, and can be applied only to a column of a table or view.

    The (+) operator does not produce an outer join if you specify one table in the outer query and the other table in an inner query.

    You cannot use the (+) operator to outer-join a table to itself, although self joins are valid.

    The (+) operator can be applied only to a column, not to an arbitrary expression. However, an arbitrary expression can contain one or more columns marked with the (+) operator.

    A WHERE condition containing the (+) operator cannot be combined with another condition using the OR logical operator.

    A WHERE condition cannot use the IN comparison condition to compare a column marked with the (+) operator with an expression.

    A WHERE condition cannot compare any column marked with the (+) operator with a subquery.

    -- example with WHERE
    SELECT d.department_name, sum(e.salary) as total_salary
    FROM departments d, employees e
    WHERE e.department_id(+) = d.department_id
    group by department_name

    -- example of left correlation in select
    SELECT d.department_name, (
        SELECT SUM(e.salary)
            FROM employees e
            WHERE e.department_id(+) = d.department_id) AS total_salary
    FROM departments d;

    -- example of left correlation in from
    SELECT d.department_name, t.total_salary
    FROM departments d, (
            SELECT SUM(e.salary) AS total_salary
            FROM employees e
            WHERE e.department_id(+) = d.department_id
        ) t
    r   )traverse_scope)	normalize
normalized)defaultdictrR   r   z$Correlated queries are not supportedc                 s  s    | ]	}|j d V  qdS )	join_markNrF   r   r~   r(   r(   r)   r^    s    z'eliminate_join_marks.<locals>.<genexpr>z Cannot normalize JOIN predicatesc                 S  s   g | ]
}|j d r|qS )rz  r{  r6  r(   r(   r)   r     r   z(eliminate_join_marks.<locals>.<listcomp>c                 s  s    | ]}|j V  qd S r   r:   r6  r(   r(   r)   r^    s    r   z4Cannot combine JOIN predicates from different tablesrz  Fc                 S  s   i | ]}|j |qS r(   )r   )rn   r   r(   r(   r)   rq     r   z(eliminate_join_marks.<locals>.<dictcomp>r   LEFT)r9   ry   r.  Nz:Cannot determine which table to use in the new FROM clauser8   r.  r   )*r   rv  sqlglot.optimizer.normalizerw  rx  collectionsry  reversedr   rF   r   is_correlated_subqueryr`  r?   r   ru   r9   r   r   AndflattenrZ   rD   r   rV   itemsri   rC   r   r   rA   ParenrT   Binaryr:  r;  WherekeysrB   rN   r.  values)r   rv  rw  rx  ry  scoper   rR   r   	joins_onscond	join_colsleft_join_tabler   	old_joins	new_joins
query_fromr;   
predicates	join_whatprA   only_old_joinsnew_from_namenjr(   r(   r)   eliminate_join_marksZ  sz   )

r  c                 C  s   t | tjrB| tjD ]5}|j}t |tjrq|j}t |tjrAt	d}|
| tj| |gd}|
tj| |d q| S )a=  
    Transform ANY operator to Spark's EXISTS

    For example,
        - Postgres: SELECT * FROM tbl WHERE 5 > ANY(tbl.col)
        - Spark: SELECT * FROM tbl WHERE EXISTS(tbl.col, x -> x < 5)

    Both ANY and EXISTS accept queries but currently only array expressions are supported for this
    transformation
    xr   r  )r   r   r>   r?   Anyr9   QueryrA   r  r   rT   Lambdari   r/  r]   )r   any_exprr9   binop
lambda_arglambda_exprr(   r(   r)   any_to_exists  s   

r  c                   s   t | tjrC| jdrCddlm} | jd }| dd i  d fd	d
}|D ]}|| | |j	 < q(|| tj
D ]}|| q<| S )zAEliminates the `WINDOW` query clause by inling each named window.windowsr   r   Nr   r   r   rH  c                   sR     | j }|sd S | dd  dD ]}|j |}|r&| ||  qd S )Nr/   )r{   r|   spec)r   r/   r%  rZ   rF   ri   )r   inherited_windowr   argwindow_expressionr(   r)   _inline_inherited_window  s   z9eliminate_window_clause.<locals>._inline_inherited_window)r   r   r   rH  )r   r   r>   rF   r   r   r   rZ   rN   r%  r   )r   r   r  r  r   r(   r  r)   eliminate_window_clause  s   

r  )r
   r   r   r   r  )T)r   r   r   r   r   r   )r   )r   r   r   r   )r   r   r   r   )r   r   rZ  r   r   r   ),
__future__r   typingr  sqlglotr   r   sqlglot.errorsr   sqlglot.helperr   r   TYPE_CHECKINGsqlglot._typingr   sqlglot.generatorr	   r+   rg   rl   rx   r   r   r   r   r   r  r  r  r!  r*  r2  rA  rF  rG  rT  rX  rb  rn  rr  ru  r  r  r  r(   r(   r(   r)   <module>   sN    

1
9

!
8
@
l 






&
'

	




y