o
    8Di;                     @  s   d dl mZ d dlZd dlZd dlZd dlmZmZ d dl	m
Z
mZmZ d dlmZ d dlmZmZmZmZmZ d dlmZ ejrGd dlmZ ed	Zed
dG dd dZ					
d+d,ddZ					
d+d-d'd(ZG d)d* d*ZdS ).    )annotationsN)	dataclassfield)Schemaexpmaybe_parse)SqlglotError)Scopebuild_scopefind_all_in_scopenormalize_identifiersqualify)	ScopeType)DialectTypesqlglotT)frozenc                   @  sf   e Zd ZU ded< ded< ded< eedZded< d	Zded
< d	Zded< dddZ	ddddZ
dS )Nodestrnamezexp.Expression
expressionsource)default_factoryzt.List[Node]
downstream source_namereference_node_namereturnt.Iterator[Node]c                 c  s&    | V  | j D ]	}| E d H  qd S N)r   walk)selfd r"   H/var/www/Datamplify/venv/lib/python3.10/site-packages/sqlglot/lineage.pyr      s
   
z	Node.walkNdialectr   	GraphHTMLc                   s   i }g }|   D ]] t jtjr'd jj }d j d jj d}d}n! jjd|d} jj	 fdd	d
djd|d}d| d}d}t
 }	|	|||d||	<  jD ]}
||	t
|
d qXqt||fi |S )NzFROM z<pre>SELECT z FROM z</pre>   T)prettyr$   c                   s   |  j u rtj| dddS | S )Nz<b>z</b>)thisprefixpostfix)r   r   Tag)nnoder"   r#   <lambda>.   s   zNode.to_html.<locals>.<lambda>F)copyz<pre>r   )idlabeltitlegroup)fromto)r   
isinstancer   r   Tabler(   r   sqlr   	transformr1   r   appendr%   )r    r$   optsnodesedgesr2   r3   r4   r   node_idr!   r"   r-   r#   to_html"   s4   


zNode.to_html)r   r   r   )r$   r   r   r%   )__name__
__module____qualname____annotations__r   listr   r   r   r   r@   r"   r"   r"   r#   r      s   
 
r   columnstr | exp.Columnr9   str | exp.Expressionschemat.Optional[t.Dict | Schema]sources+t.Optional[t.Mapping[str, str | exp.Query]]r$   r   scopet.Optional[Scope]trim_selectsboolr   c           	        s   t |d}tj dj |r!tj|fdd| D d}|s8tj|f|dddd|}t|}|s>tdt	 fdd	|j
jD sStd
  dt ||dS )a6  Build the lineage graph for a column of a SQL query.

    Args:
        column: The column to build the lineage for.
        sql: The SQL string or expression.
        schema: The schema of tables.
        sources: A mapping of queries which will be used to continue building lineage.
        dialect: The dialect of input SQL.
        scope: A pre-created scope to use instead.
        trim_selects: Whether or not to clean up selects by trimming to only relevant columns.
        **kwargs: Qualification optimizer kwargs.

    Returns:
        A lineage node.
    r$   c              
     s(   i | ]\}}|t tjt| d qS )rQ   )tcastr   Queryr   ).0kvrQ   r"   r#   
<dictcomp>d   s   ( zlineage.<locals>.<dictcomp>)r$   rI   F)validate_qualify_columnsidentifyz(Cannot build lineage, sql must be SELECTc                 3  s    | ]}|j  kV  qd S r   alias_or_namerU   selectrF   r"   r#   	<genexpr>u       zlineage.<locals>.<genexpr>zCannot find column 'z' in query.)rO   )r   r   r   r   expanditemsr   r
   r   anyr   selectsto_node)	rF   r9   rI   rK   r$   rM   rO   kwargsr   r"   )rF   r$   r#   lineageD   s.   rh   	str | intr	   
scope_namet.Optional[str]upstreamt.Optional[Node]r   r   c           #        s  t  tr|jj  nt fdd|jjD |jjrt n|j}t |jtjr;|j	D ]}	t
 |	|||||d  S t |jtjrt|jj }
|pSt|
|j|d}t  tr[ nt fddt|jjD d}|dkrztd  d|j |jD ]}t
|||||||d q}|S |rt |jtjrttj|jj|d	d
}	n|j}	t|r| d  nt |	||pd|pdd}|r|j| dd |j	D }t|tjD ]'}|t|}|st d|j!|d  q|j"D ]}
t
|
||||d qq|jr"|j#$ D ]}	t |	t%r|	j}	|jt|j!d	d|	|	d qt&t|tj'}t |	tj(rF|t&|	)tj'O }dd |j#$ D }n|j*}dd |D }|j+}t,|dkrd|d j-sd|d nd }|r|j.d }t,|j/}i }t|j/D ] \}}t0|)tj'}t1|t,||D ]
}|||| j2< qqz|D ]}|j3}|j#|}	t |	t%rd }|	j4t5j6kr||vr|}n|	j4t5j7kr|j8|d\}} |r|j2nd }t
|j2|	|||||p|||d q|r^|j9|j3kr^g }!|j2t:fdd|D r|!;|  n|!tj<|j=|j>j9d |!D ]=}"|"j3}|j#|}	t |	t%rDt
|"j2|	|||||p=|||d q|	pJt? }	|jt|"j!d	d|	|	d qq|	pdt? }	|jt|j!d	d|	|	d q|S )Nc                 3  s    | ]
}|j  kr|V  qd S r   r[   r]   r_   r"   r#   r`      s    zto_node.<locals>.<genexpr>)rM   r$   rl   r   r   rO   )r   r   r   c                 3  s(    | ]\}}|j  ks|jr|V  qd S r   )r\   is_star)rU   ir^   r_   r"   r#   r`      s    zCould not find z in F)r;   .r   )r   r   r   r   r   c                 S  s   i | ]}t |j|qS r"   )r1   r   )rU   subquery_scoper"   r"   r#   rX      s    zto_node.<locals>.<dictcomp>zUnknown subquery scope: rQ   )rM   r$   rl   rO   )commentsc                 S  s$   g | ]}t |tr|jr|jjqS r"   )r7   r	   is_derived_tabler   parent)rU   r   r"   r"   r#   
<listcomp>   s    zto_node.<locals>.<listcomp>c                 S  s8   i | ]}|j r|j d  dr|j|j d   d qS )r   zsource: r&   )rs   
startswithaliassplit)rU   dtr"   r"   r#   rX      s    r&   r   columns)NN)rM   r$   rj   rl   r   r   rO   c                 3  s    | ]} |j kV  qd S r   )r   )rU   pivot_column)column_namer"   r#   r`   1  ra   )table)rM   rj   r$   rl   r   r   rO   )@r7   intr   re   nextrn   r   StarSubquerysubquery_scopesrf   SetOperationtyperA   upperr   	enumerate
ValueErrorunion_scopesSelectrR   rS   
Expressionr^   r   r   r;   r   UNWRAPPED_QUERIESgetr1   loggerwarningr9   named_selectsrK   valuesr	   setColumnUDTFfind_allderived_tablespivotslenunpivotargsexpressionsrE   ranger   r~   
scope_typer   DERIVED_TABLECTEselected_sourcesr\   rd   extendrF   r(   ru   Placeholder)#rF   rM   r$   rj   rl   r   r   rO   r^   r   r   indexsr.   r   subqueryrr   source_columnsr   source_namesr   pivotpivot_columnspivot_aggs_countpivot_column_mappingro   aggagg_cols	col_indexcr~   selected_node_downstream_columnsdownstream_columnr"   )rF   r}   r#   rf   {   s4  	

	





&






rf   c                   @  s0   e Zd ZdZ	ddddZdd ZdddZdS )r%   z`Node to HTML generator using vis.js.

    https://visjs.github.io/vis-network/docs/network/
    TNr=   t.Dictr>   t.ListimportsrP   optionst.Optional[t.Dict]c              
   C  sZ   || _ dddddddiddd	d
diddiddddidd|p"i | _|| _|| _d S )N500pxz100%hierarchicalT   directed)enablednodeSpacing
sortMethodF)	dragNodes
selectabler   arrowsr6   z20px monacoboxmaximumi,  )fontshapewidthConstraint)heightwidthlayoutinteractionphysicsr>   r=   )r   r   r=   r>   )r    r=   r>   r   r   r"   r"   r#   __init__b  s4   
zGraphHTML.__init__c              	   C  sX   t t| j }t | j}t | j}| jrdnd}d| d| d| d| d	S )NaG  <script type="text/javascript" src="https://unpkg.com/vis-data@latest/peer/umd/vis-data.min.js"></script>
  <script type="text/javascript" src="https://unpkg.com/vis-network@latest/peer/umd/vis-network.min.js"></script>
  <link rel="stylesheet" type="text/css" href="https://unpkg.com/vis-network/styles/vis-network.min.css" />r   z+<div>
  <div id="sqlglot-lineage"></div>
  zC
  <script type="text/javascript">
    var nodes = new vis.DataSet(a
  )
    nodes.forEach(row => row["title"] = new DOMParser().parseFromString(row["title"], "text/html").body.childNodes[0])

    new vis.Network(
        document.getElementById("sqlglot-lineage"),
        {
            nodes: nodes,
            edges: new vis.DataSet(z)
        },
        z,
    )
  </script>
</div>)jsondumpsrE   r=   r   r>   r   r   )r    r=   r>   r   r   r"   r"   r#   __str__  s    zGraphHTML.__str__r   r   c                 C  s   |   S r   )r   )r    r"   r"   r#   _repr_html_  s   zGraphHTML._repr_html_)TN)r=   r   r>   r   r   rP   r   r   )r   r   )rA   rB   rC   __doc__r   r   r   r"   r"   r"   r#   r%   \  s    &r%   )NNNNT)rF   rG   r9   rH   rI   rJ   rK   rL   r$   r   rM   rN   rO   rP   r   r   )rF   ri   rM   r	   r$   r   rj   rk   rl   rm   r   rk   r   rk   rO   rP   r   r   ) 
__future__r   r   loggingtypingrR   dataclassesr   r   r   r   r   r   sqlglot.errorsr   sqlglot.optimizerr	   r
   r   r   r   sqlglot.optimizer.scoper   TYPE_CHECKINGsqlglot.dialects.dialectr   	getLoggerr   r   rh   rf   r%   r"   r"   r"   r#   <module>   s8    
3; b