o
    ?Di+                     @   sr  d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlZdZG dd dZ	G dd dZ
ded	ed
efddZdeded
efddZdefddZdededededededed
efddZdeded
efddZd eded
efd!d"Zd ed
efd#d$Zd%ed
efd&d'Zd ed(ed
dfd)d*Zd+eded
dfd,d-Zd.ed/ed
dfd0d1Zd5d2d3Zed4kre  dS dS )6    N)reducea^  
.styled-table {
	border-collapse: collapse;
	margin: 25px 0;
	font-size: 0.9em;
	font-family: sans-serif;
	min-width: 400px;
	box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
}
.styled-table thead tr {
	background-color: #009879;
	color: #ffffff;
	text-align: left;
}
.styled-table th,
.styled-table td {
	padding: 12px 15px;
}
.styled-table tbody tr {
	border-bottom: 1px solid #dddddd;
}

.styled-table tbody tr:nth-of-type(even) {
	background-color: #f3f3f3;
}

.styled-table tbody tr:last-of-type {
	border-bottom: 2px solid #009879;
}

.node-body {
	font-size:15px;
}
.tf-nc {
	position: relative;
	width: 180px;
	text-align: center;
	background-color: #fff100;
}
.custom-tooltip {
  position: relative;
  display: inline-block;
}

.tooltip-text {
  visibility: hidden;
  background-color: #333;
  color: #fff;
  text-align: center;
  padding: 0px;
  border-radius: 1px;
  
  /* Positioning */
  position: absolute;
  z-index: 1;
  bottom: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-bottom: 8px;
  
  /* Tooltip Arrow */
  width: 400px;
}

.custom-tooltip:hover .tooltip-text {
  visibility: visible;
}
c                   @   sJ   e Zd ZdededefddZdeddfdd	Zd
ededefddZdS )
NodeTimingphasetimereturnc                 C   s   || _ || _d| _d S Nr   )r   r   
percentage)selfr   r    r
   T/var/www/Datamplify/venv/lib/python3.10/site-packages/duckdb/query_graph/__main__.py__init__Q   s   
zNodeTiming.__init__
total_timeNc                 C   s   | j | | _d S N)r   r   )r	   r   r
   r
   r   calculate_percentageW   s   zNodeTiming.calculate_percentagelrc                 C   s   | j |j  }t| j|S r   )r   r   r   )r   r   r   r
   r
   r   combine_timingZ   s   zNodeTiming.combine_timing)	__name__
__module____qualname__strfloatobjectr   r   r   r
   r
   r
   r   r   O   s    r   c                   @   sN   e Zd Zdd ZdefddZdefddZdefd	d
Zdd Z	dd Z
dS )
AllTimingsc                 C   s
   i | _ d S r   phase_to_timingsr	   r
   r
   r   r   b      
zAllTimings.__init__node_timingc                 C   s4   |j | jv r| j|j  | d S |g| j|j < d S r   )r   r   append)r	   r   r
   r
   r   add_node_timinge   s   zAllTimings.add_node_timingr   c                 C   s
   | j | S r   r   r	   r   r
   r
   r   get_phase_timingsk   r   zAllTimings.get_phase_timingsc                 C   s   t tj| j| S r   )r   r   r   r   r!   r
   r
   r   get_summary_phase_timingsn   s   z$AllTimings.get_summary_phase_timingsc                    s.   t  j }|j fddd |  |S )Nc                    s     | jS r   )r#   r   )xr   r
   r   <lambda>s   s    z'AllTimings.get_phases.<locals>.<lambda>)key)listr   keyssortreverse)r	   phasesr
   r   r   
get_phasesq   s   zAllTimings.get_phasesc                 C   s(   d}| j  D ]
}|| |j7 }q|S r   )r   r(   r#   r   )r	   total_timing_sumr   r
   r
   r   get_sum_of_all_timingsw   s   z!AllTimings.get_sum_of_all_timingsN)r   r   r   r   r   r    r   r"   r#   r,   r.   r
   r
   r
   r   r   `   s    r   fpathflagsr   c                 C   s   t | |ddS )Nutf8)encoding)open)r/   r0   r
   r
   r   	open_utf8~   s   r4   top_nodequery_timingsc                 C   s<   t | d t| d }|| | d D ]}t|| qd S )Noperator_typeoperator_timingchildren)r   r   r    get_child_timings)r5   r6   r   childr
   r
   r   r:      s
   
r:   fractionc                 C   s   t dtd| } d}d}t|d |d |d  |   }t|d |d |d  |   }t|d |d |d  |   }d|d|d|dS )Nr      )      r?   )r>            #02x)maxminint)r<   
light_pink	dark_pinkr   gbr
   r
   r   get_pink_shade_hex   s      rL   nameresultcpu_timecardestwidth
extra_infoc                 C   s   dt t||  d}d| d}|d7 }| dkrdn| dd	}	t|d
}
|d|	 d|
 d7 }|d| d7 }|dkrW|d| d7 }|d| d7 }|d| d7 }|d7 }|d7 }|S )Nzbackground-color: ;z*<span class="tf-nc custom-tooltip" style="z">z<div class="node-body">INVALIDBRIDGE_ z.4fz<p><b>z</b> </p><p>time: z seconds</p>z<span class="tooltip-text"> z </span>r   z<p>cardinality: z</p>z<p>estimate: z
<p>width: z
 bytes</p>z</div>z</span>)rL   r   replace)rM   rN   rO   rP   rQ   rR   rS   
node_stylebodynew_nameformatted_numr
   r
   r   get_node_body   s   r^   
json_graphc                 C   s   d}d}d}d}| d D ]}| d | }|dkrt |}q|| d| d7 }q| d	 }t | d
 td| }	tdd|}tdd|}t| d | d ||||	tdd|}
d}t| d dkrx|d7 }| d D ]	}|t||7 }qj|d7 }||
 | | S )Nz<li>z</li> r   rS   zEstimated Cardinalityz: z <br>operator_cardinalityresult_set_sizer=   z__internal_\s*__zcompress_integral\s*compressr7   r8   z,\s*z, r9   z<ul>z</ul>)rG   rE   resubr^   lengenerate_tree_recursive)r_   rO   node_prefix_htmlnode_suffix_htmlrS   estimater&   valuecardinalityrR   	node_bodychildren_htmlr;   r
   r
   r   rh      s2   
rh   
graph_jsonc              
   C   s   t | }t|| t|dp|d}d}d}d}| }| }|td| |td| ddg| }|D ]4}	|	|	}
|

| |	dksP|	dkrVd|	 d	n|	}|d
| d|
j dt|
jd d d  d7 }q<||7 }|| S )Nr8   latencyz
	<table class="styled-table"> 
		<thead>
			<tr>
				<th>Phase</th>
				<th>Time</th>
				<th>Percentage</th>
			</tr>
		</thead>z<tbody>z</tbody></table>z
TOTAL TIMEzExecution Timez<b>z</b>z
	<tr>
			<td>z</td>
            <td>d      z%</td>
    </tr>
)jsonloadsgather_timing_informationr   getr.   r,   r    r   r#   r   r   r   r   )rp   r6   r_   r   
table_head
table_body	table_endexecution_time
all_phasesr   summarized_phasephase_columnr
   r
   r   generate_timing_html   s0   




 r   c                 C   s<   t | }t|d }d}d}t|d d |}|| | S )NrO   z&<div class="tf-tree tf-gap-sm"> 
 <ul>z</ul> </div>r9   r   )rt   ru   r   rh   )rp   r_   rO   tree_prefixtree_suffix	tree_bodyr
   r
   r   generate_tree_html   s   
r   
json_inputc                 C   sB   ddl m} t| d}|dd|d d|d d	|d
 S )Nr   )HTMLFzW
	${CSS}
	${LIBRARIES}
	<div class="chart" id="query-profile"></div>
	${CHART_SCRIPT}
	z${CSS}cssz${CHART_SCRIPT}chart_scriptz${LIBRARIES}	libraries)IPython.core.displayr   generate_htmlrY   )r   r   html_outputr
   r
   r   generate_ipython   s   
r   include_meta_infoc                 C   s*   d}d}|t d 7 }|d7 }||dddS )NzP<link rel="stylesheet" href="https://unpkg.com/treeflex/dist/css/treeflex.css">
z<style>

z	</style>
r`   )treeflex_css
duckdb_cssr   r   )
qgraph_css)rp   r   r   r   r
   r
   r   generate_style_html  s   r   rt   c                 C   s   t | d d | d S )Nr9   r   )r:   )rt   r6   r
   r
   r   rv     s   rv   
input_fileoutput_filec           	      C   s   t  }t| d}| }W d    n1 sw   Y  t|d}t||}t|}t|d,}d}|d|d }|d|d }|d	|}|d
|}|| W d    d S 1 s^w   Y  d S )Nr   Tzw+aT  <!DOCTYPE html>
<html>
	<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width">
	<title>Query Profile Graph for Query</title>
	${TREEFLEX_CSS}
	<style>
		${DUCKDB_CSS}
	</style>
</head>
<body>
	<div id="meta-info"></div>
	<div class="chart" id="query-profile">
		${TIMING_TABLE}
	</div>
	${TREE}
</body>
</html>
z${TREEFLEX_CSS}r   z${DUCKDB_CSS}r   z${TIMING_TABLE}z${TREE})r   r4   readr   r   r   rY   write)	r   r   r6   ftextr   timing_tabletree_outputhtmlr
   r
   r   translate_json_to_html!  s   


"r   c                  C   s   t jd dk rtd td tjddd} | jdd	d
 | jdddd | jddddd |  }|j}|j	}|j	sOd|v rF|
dd}ntd td nd|j	v rX|j	}ntd td |j}t|| |rytjdtj| dd d S d S )Nr      zPlease use python3r=   zQuery Graph GeneratorzbGiven a json profile output, generate a html file showing the query graph and timings of operators)progdescriptionprofile_inputzprofile input in json)helpz--outF)requireddefaultz--open
store_trueT)r   actionr   z.jsonz.htmlz%please provide profile output in jsonz/please provide valid .html file for output namezfile://rB   )new)sysversion_infoprintexitargparseArgumentParseradd_argument
parse_argsr   outrY   r3   r   
webbrowserospathabspath)parserargsinputoutputopen_outputr
   r
   r   mainG  s6   


r   __main__)r   N)rt   r   r   re   r   	functoolsr   r   r   r   r   r   r   r4   r:   r   rL   rG   r^   rh   r   r   r   boolr   rv   r   r   r   r
   r
   r
   r   <module>   s2    F*"&
&#
