Ë
    Þš§jyW  ã                   ó¾   — d dl Z d dlZd dlZd dlZd dlmZ d dlmZ d dlm	Z	 dZ
 G d„ d«      Z G d„ d	«      Zd
ededefd„Z G d„ d«      Zdd„Zedk(  r e«        yy)é    N)Úreduce)ÚPath)ÚDuckDBPyConnectiona  
:root {
  --text-primary-color: #0d0d0d;
  --text-secondary-color: #444;
  --doc-codebox-border-color: #e6e6e6;
  --doc-codebox-background-color: #f7f7f7;
  --doc-scrollbar-bg: #e6e6e6;
  --doc-scrollbar-slider: #ccc;
  --duckdb-accent: #009982;
  --duckdb-accent-light: #00b89a;
  --card-bg: #fff;
  --border-radius: 8px;
  --shadow: 0 4px 14px rgba(0,0,0,0.05);
}

html, body {
  margin: 0;
  padding: 0;
  font-family: Inter, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  color: var(--text-primary-color);
  background: #fafafa;
  line-height: 1.55;
}

.container {
  max-width: 1000px;
  margin: 40px auto;
  padding: 0 20px;
}

header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 5px;
}

header img {
  width: 100px;
  height: 100px;
}

header h1 {
  font-size: 1.5rem;
  font-weight: 600;
  margin: 0;
  color: var(--text-primary-color);
}

/* === Table Styling (DuckDB documentation style, flat header) === */
table {
  border-collapse: collapse;
  width: 100%;
  margin-bottom: 20px;
  text-align: left;
  font-variant-numeric: tabular-nums;
  border: 1px solid var(--doc-codebox-border-color);
  border-radius: var(--border-radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  background: var(--card-bg);
}

thead {
  background-color: var(--duckdb-accent);
  color: white;
}

th, td {
  padding: 10px 12px;
  font-size: 14px;
  vertical-align: top;
}

th {
  font-weight: 700;
}

tbody tr {
  border-bottom: 1px solid var(--doc-codebox-border-color);
}

tbody tr:last-child td {
  border-bottom: none;
}

tbody tr:hover {
  background: var(--doc-codebox-border-color);
}

tbody tr.phase-details-row {
  border-bottom: none;
}

tbody tr.phase-details-row:hover {
  background: transparent;
}

tbody tr.phase-details-row details summary {
  font-size: 12px;
  padding: 4px 0;
}

tbody tr.phase-details-row details[open] summary {
  margin-bottom: 4px;
}

/* === Chart/Card Section === */
.chart {
  padding: 20px;
  border: 1px solid var(--doc-codebox-border-color);
  border-radius: var(--border-radius);
  background: var(--card-bg);
  box-shadow: var(--shadow);
  overflow: visible;
}

/* === Tree Layout Styling === */
.tf-tree {
  overflow-x: visible;
  overflow-y: visible;
  padding-top: 20px;
}

.tf-nc {
  background: var(--card-bg);
  border: 1px solid var(--doc-codebox-border-color);
  border-radius: var(--border-radius);
  padding: 6px;
  display: inline-block;
}

.node-body {
  font-size: 13px;
  text-align: left;
  padding: 10px;
  white-space: nowrap;
}

.node-body p {
  margin: 2px 0;
}

.node-details {
  white-space: nowrap;
  overflow: visible;
  display: inline-block;
}

/* === Metric Boxes === */
.chart .metrics-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 16px;
  margin-bottom: 20px;
}

.chart .metric-box {
  background: var(--card-bg);
  border: 1px solid var(--doc-codebox-border-color);
  border-radius: var(--border-radius);
  box-shadow: var(--shadow);
  padding: 12px 16px;
  text-align: center;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.chart .metric-box:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08);
}

.chart .metric-title {
  font-size: 13px;
  color: var(--text-secondary-color);
  margin-bottom: 4px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

.chart .metric-value {
  font-size: 18px;
  font-weight: 600;
  color: var(--duckdb-accent);
}


/* === SQL Query Block === */
.chart.sql-block {
  background: var(--doc-codebox-background-color);
  border: 1px solid var(--doc-codebox-border-color);
  border-radius: var(--border-radius);
  box-shadow: var(--shadow);
  padding: 16px;
  overflow-x: auto;
  margin-top: 20px;
}

.chart.sql-block pre {
  margin: 0;
  font-family: "JetBrains Mono", "Fira Code", Consolas, monospace;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--text-primary-color);
  white-space: pre;
}

.chart.sql-block code {
  color: var(--duckdb-accent);
  font-weight: 500;
}


/* === Links, Typography, and Consistency === */
a {
  color: var(--duckdb-accent);
  text-decoration: underline;
  transition: color 0.3s;
}

a:hover {
  color: black;
}

strong {
  font-weight: 600;
}

/* === Dark Mode Support === */
@media (prefers-color-scheme: dark) {
  :root {
    --text-primary-color: #e6e6e6;
    --text-secondary-color: #b3b3b3;
    --doc-codebox-border-color: #2a2a2a;
    --doc-codebox-background-color: #1e1e1e;
    --card-bg: #111;
  }
  body {
    background: #0b0b0b;
  }
  thead {
    background-color: var(--duckdb-accent);
  }
  tbody tr:hover {
    background: #222;
  }
  
  /* Fix tree node text visibility in dark mode */
  .tf-nc .node-body,
  .tf-nc .node-body p,
  .tf-nc .node-details {
    color: #1a1a1a !important;
  }
  
  /* Fix metric title visibility in dark mode */
  .chart .metric-title {
    color: #b3b3b3;
  }
}
c                   ó<   — e Zd Zdedededdfd„Zdeddfd„Zd
d	„Zy)Ú
NodeTimingÚphaseÚtimeÚdepthÚreturnNc                 ó<   — || _         || _        || _        d| _        y ©Nr   )r   r	   r
   Ú
percentage)Úselfr   r	   r
   s       ú^C:\Users\Luka\AppData\Local\Temp\pip-target-o84fipzb\lib\python\duckdb/query_graph/__main__.pyÚ__init__zNodeTiming.__init__  s   € ØˆŒ
ØˆŒ	ØˆŒ
àˆ�ó    Ú
total_timec                 ó,   — | j                   |z  | _        y ©N)r	   r   )r   r   s     r   Úcalculate_percentagezNodeTiming.calculate_percentage  s   € ØŸ)™) jÑ0ˆ�r   c                 óv   — | j                   |j                   z   }t        | j                  || j                  «      S r   )r	   r   r   r
   )r   Úrr   s      r   Úcombine_timingzNodeTiming.combine_timing  s+   € à—Y‘Y §¡Ñ'ˆ
Ü˜$Ÿ*™* j°$·*±*Ó=Ð=r   )r   r   r   r   )	Ú__name__Ú
__module__Ú__qualname__ÚstrÚfloatÚintr   r   r   © r   r   r   r     s;   „ ð˜cð ¨ð °sð ¸tó ð1¨uð 1¸ó 1ô>r   r   c                   óh   — e Zd Zdd„Zdeddfd„Zdedee   fd„Zdedefd„Z	dee   fd	„Z
defd
„Zy)Ú
AllTimingsr   Nc                 ó   — i | _         y r   ©Úphase_to_timings©r   s    r   r   zAllTimings.__init__"  s
   € Ø "ˆÕr   Únode_timingc                 óº   — |j                   | j                  v r)| j                  |j                      j                  |«       y |g| j                  |j                   <   y r   )r   r%   Úappend)r   r'   s     r   Úadd_node_timingzAllTimings.add_node_timing%  sM   € Ø×Ñ × 5Ñ 5Ñ5Ø×!Ñ! +×"3Ñ"3Ñ4×;Ñ;¸KÕHà8C°}ˆD×!Ñ! +×"3Ñ"3Ò4r   r   c                 ó    — | j                   |   S r   r$   ©r   r   s     r   Úget_phase_timingszAllTimings.get_phase_timings+  s   € Ø×$Ñ$ UÑ+Ð+r   c                 óP   — t        t        j                  | j                  |   «      S r   )r   r   r   r%   r,   s     r   Úget_summary_phase_timingsz$AllTimings.get_summary_phase_timings.  s    € Ü”j×/Ñ/°×1FÑ1FÀuÑ1MÓNÐNr   c                 ó˜   ‡ — t        ‰ j                  j                  «       «      }|j                  ˆ fd„¬«       |j	                  «        |S )Nc                 ó:   •— ‰j                  | «      j                  S r   )r/   r	   )Úxr   s    €r   Ú<lambda>z'AllTimings.get_phases.<locals>.<lambda>3  s   ø€  4×#AÑ#AÀ!Ó#D×"JÒ"Jr   )Úkey)Úlistr%   ÚkeysÚsortÚreverse)r   Úphasess   ` r   Ú
get_phaseszAllTimings.get_phases1  s:   ø€ Ü�d×+Ñ+×0Ñ0Ó2Ó3ˆØ�‰ÓJˆÔKØ�‰ÔØˆr   c                 óh   — d}| j                   D ]   }|| j                  |«      j                  z  }Œ" |S r   )r%   r/   r	   )r   Útotal_timing_sumr   s      r   Úget_sum_of_all_timingsz!AllTimings.get_sum_of_all_timings7  s:   € ØÐØ×*Ô*ˆEØ × >Ñ >¸uÓ E× JÑ JÑJÑð +àÐr   ©r   N)r   r   r   r   r   r*   r   r5   r-   r/   r:   r   r=   r    r   r   r"   r"   !  sh   „ ó#ðE¨:ð E¸$ó Eð, sð ,¨t°JÑ/?ó ,ðO¨sð O°zó Oð˜D Ñ,ó ð ¨ô  r   r"   ÚfpathÚflagsr   c                 ó:   — t        | «      j                  |d¬«      S )NÚutf8)ÚmodeÚencoding)r   Úopen)r?   r@   s     r   Ú	open_utf8rF   >  s   € Ü�‹;×Ñ °ÐÓ8Ð8r   c                   óŠ  — e Zd Zd(dedz  dedz  ddfd„Zdefd„Zdefd„Zd)dedefd	„Z	d*d
e
de
dedefd„Zededefd„«       Zdedededededededefd„Zde
dedefd„Zde
de
de
fd„Zededefd„«       Zededefd„«       Zde
defd„Zdedefd „Zeded!eddfd"„«       Zd#ede
ddfd$„Z	 d+d%edz  d&edz  deddfd'„Zy),ÚProfilingInfoNÚconnÚ	from_filer   c                 ó    — || _         || _        y r   )rI   rJ   )r   rI   rJ   s      r   r   zProfilingInfo.__init__C  s   € ØˆŒ	Ø"ˆ�r   c                 óÊ   — | j                   �0t        | j                   d«      5 }|j                  «       cd d d «       S | j                  j	                  d¬«      S # 1 sw Y   Œ%xY w)Nr   Újson)Úformat)rJ   rF   ÚreadrI   Úget_profiling_information)r   Úfs     r   Úto_jsonzProfilingInfo.to_jsonG  sP   € Ø�>‰>Ð%Ü˜4Ÿ>™>¨3Ô/°1Ø—v‘v“x÷ 0Ñ/ð �y‰y×2Ñ2¸&Ð2ÓAÐA÷ 0Ð/ús   £AÁA"c                 óH   — t        j                  | j                  «       «      S r   )rM   ÚloadsrR   r&   s    r   Ú	to_pydictzProfilingInfo.to_pydictN  s   € Ü�z‰z˜$Ÿ,™,›.Ó)Ð)r   Úoutput_filec                 óL   — | j                  «       }| j                  ||¬«      }|S )N)Ú
input_textrV   )rR   Ú_translate_json_to_html)r   rV   Úprofiling_info_textÚhtml_outputs       r   Úto_htmlzProfilingInfo.to_htmlQ  s+   € Ø"Ÿl™l›nÐØ×2Ñ2Ð>QÐ_jÐ2ÓkˆØÐr   Útop_nodeÚquery_timingsr
   c                 óž   — t        |d   t        |d   «      |«      }|j                  |«       |d   D ]  }| j                  |||dz   «       Œ y )NÚoperator_typeÚoperator_timingÚchildrené   )r   r   r*   Ú_get_child_timings)r   r]   r^   r
   r'   Úchilds         r   rd   z ProfilingInfo._get_child_timingsV  sT   € Ü  ¨/Ñ!:¼EÀ(ÐK\ÑB]Ó<^Ð`eÓfˆØ×%Ñ% kÔ2Ø˜jÔ)ˆEØ×#Ñ# E¨=¸%À!¹)ÕDñ *r   Úfractionc                 óü   — t        dt        d| «      «      } d}d}t        |d   |d   |d   z
  | z  z   «      }t        |d   |d   |d   z
  | z  z   «      }t        |d   |d   |d   z
  | z  z   «      }d|d›|d›|d›�S )zƒReturns a shade between very light (#f7fff0) and a slightly darker green-yellow,
        depending on the fraction (0..1).
        r   rc   )é÷   éÿ   éð   )éÈ   ri   é–   é   Ú#Ú02x)ÚmaxÚminr   )rf   Úlight_colorÚ
dark_colorr   ÚgÚbs         r   Ú_get_f7fff0_shade_hexz#ProfilingInfo._get_f7fff0_shade_hex\  s¯   € ô
 �qœ#˜a Ó*Ó+ˆð &ˆØ$ˆ
ô �˜A‘ *¨Q¡-°+¸a±.Ñ"@ÀHÑ!LÑLÓMˆÜ�˜A‘ *¨Q¡-°+¸a±.Ñ"@ÀHÑ!LÑLÓMˆÜ�˜A‘ *¨Q¡-°+¸a±.Ñ"@ÀHÑ!LÑLÓMˆà�1�S�'˜!˜C˜  3 Ð(Ð(r   ÚnameÚresultÚcpu_timeÚcardÚestÚresult_sizeÚ
extra_infoc                 óf  — d| j                  t        |«      |z  «      › d�}|dk(  rdn|j                  dd«      }	t        |«      d›}
d|› d	�}|d
z  }|d|	› d�z  }|dkD  r$|d|
› d�z  }|d|› d�z  }|d|› d�z  }|d|› d�z  }|dz  }|dz  }|dz  }|d|› d�z  }|dz  }|dz  }|dz  }|dz  }|S )z5Generate the HTML body for a single node in the tree.zbackground-color: Ú;ÚINVALIDÚBRIDGEÚ_Ú ú.4fz<span class="tf-nc" style="z">z<div class="node-body">z<p><b>z</b></p>r   z	<p>time: zs</p>z<p>cardinality: z</p>z<p>estimate: z<p>result size: z
 bytes</p>z	<details>z<summary>Extra info</summary>z<div class="node-details">z<p>ú</div>z
</details>z</span>)rv   r   Úreplace)r   rw   rx   ry   rz   r{   r|   r}   Ú
node_styleÚnew_nameÚformatted_numÚbodys               r   Ú_get_node_bodyzProfilingInfo._get_node_bodyn  s1  € ð *¨$×*DÑ*DÄUÈ6Ã]ÐU]ÑE]Ó*^Ð)_Ð_`Ðaˆ
Ø $¨	Ò 1‘8¸¿¹ÀSÈ#Ó8NˆÜ  ›=¨Ð-ˆà,¨Z¨L¸Ð;ˆØÐ)Ñ)ˆØ�&˜˜
 (Ð+Ñ+ˆØ˜Š?Ø�i ˜¨eÐ4Ñ4ˆDØÐ& t f¨DÐ1Ñ1ˆDØ�m C 5¨Ð-Ñ-ˆDØÐ& { m°:Ð>Ñ>ˆDØ�ÑˆØÐ/Ñ/ˆØÐ,Ñ,ˆØ�#�j�\ Ð&Ñ&ˆà�ÑˆØ�ÑˆØ�ÑˆØ�	ÑˆØˆr   Ú
json_graphc                 óÈ  — d}d}d}d}|d   D ]&  }|d   |   }|dk(  rt        |«      }Œ||› d|› d�z  }Œ( t        j                  d	d
|«      }t        j                  dd|«      }| j                  |d   |d   ||d   ||d   t        j                  dd|«      «      }	d}
t	        |d   «      dk\  r)|
dz  }
|d   D ]  }|
| j                  ||«      z  }
Œ |
dz  }
||	z   |
z   |z   S )Nz<li>z</li>Ú r   r}   zEstimated Cardinalityz: z <br>z__internal_\s*Ú__zcompress_integral\s*Úcompressr`   ra   Úoperator_cardinalityÚresult_set_sizez,\s*z, rb   rc   z<ul>z</ul>)r   ÚreÚsubr‹   ÚlenÚ_generate_tree_recursive)r   rŒ   ry   Únode_prefix_htmlÚnode_suffix_htmlr}   Úestimater4   ÚvalueÚ	node_bodyÚchildren_htmlre   s               r   r–   z&ProfilingInfo._generate_tree_recursive‰  s9  € Ø!ÐØ"Ðàˆ
ØˆØ˜lÔ+ˆCØ˜|Ñ,¨SÑ1ˆEØÐ-Ò-Ü˜u›:‘à   R¨ w¨eÐ4Ñ4‘
ð ,ô —V‘VÐ-¨t°ZÓ@ˆ
Ü—V‘VÐ3°ZÀÓLˆ
à×'Ñ'Ø�Ñ'ØÐ(Ñ)ØØÐ-Ñ.ØØÐ(Ñ)Ü�F‰F�7˜D *Ó-ó
ˆ	ð ˆÜˆz˜*Ñ%Ó&¨!Ò+Ø˜VÑ#ˆMØ# JÔ/�Ø ×!>Ñ!>¸uÀhÓ!OÑO‘ð 0à˜WÑ$ˆMØ )Ñ+¨mÑ;Ð>NÑNÐNr   Ú
graph_jsonc                 óT  — t        j                  |«      }| j                  ||«       d}d}d}|j                  «       }|j	                  «       }|j                  t        d|d«      «       dg|¢}|D �]+  }	|j                  |	«      }
|
j                  |«       |	dk(  rd|	› d�n|	}|d|› d	t        |
j                  d
«      › d	t        |
j                  dz  «      dd › d�z  }|	dk7  sŒu|j                  |	«      }t        |«      dkD  sŒ•|dt        |«      › d�z  }t        |d„ d¬«      D ]n  }|j                  |«       d|j                   dz  z  }|d|› d|j                   › dt        |j                  d
«      › dt        |j                  dz  «      dd › d�	z  }Œp |dz  }�Œ. ||z  }||z   S )z3Generates timing HTML table with expandable phases.z§
      <table>
        <thead>
          <tr>
            <th>Phase</th>
            <th>Time (s)</th>
            <th>Percentage</th>
          </tr>
        </thead>z<tbody>z</tbody></table>zExecution Time (CPU)Nz<b>z</b>z
      <tr>
          <td>z</td>
                <td>é   éd   é   z%</td>
        </tr>
    rc   zç
        <tr class="phase-details-row">
            <td colspan="3">
                <details>
                    <summary style="cursor: pointer; padding: 4px 0; color: var(--text-secondary-color);">
                        Show zª nodes
                    </summary>
                    <table style="margin: 8px 0; width: 100%; border: none; box-shadow: none;">
                        <tbody>
    c                 ó   — | j                   S r   )r	   )r2   s    r   r3   z5ProfilingInfo._generate_timing_html.<locals>.<lambda>à  s   € È1Ï6Ê6r   T)r4   r8   z&nbsp;é   z¨
                            <tr style="background: var(--doc-codebox-background-color);">
                                <td style="padding: 4px 12px; border: none;">u
   â†³ Depth zS</td>
                                <td style="padding: 4px 12px; border: none;">z-%</td>
                            </tr>
    z~
                        </tbody>
                    </table>
                </details>
            </td>
        </tr>
    )rM   rT   Ú_gather_timing_informationr=   r:   r*   r   r/   r   Úroundr	   r   r   r-   r•   Úsortedr
   )r   r�   r^   rŒ   Ú
table_headÚ
table_bodyÚ	table_endÚexecution_timeÚ
all_phasesr   Úsummarized_phaseÚphase_columnÚphase_timingsr'   Údepth_indents                  r   Ú_generate_timing_htmlz#ProfilingInfo._generate_timing_html­  s:  € ä—Z‘Z 
Ó+ˆ
Ø×'Ñ'¨
°MÔBðˆ
ð ˆ
Ø&ˆ	à&×=Ñ=Ó?ˆà"×-Ñ-Ó/ˆ
Ø×%Ñ%¤jÐ1GÈÐY]Ó&^Ô_Ø,Ð:¨zÐ:ˆ
äˆEØ,×FÑFÀuÓMÐØ×1Ñ1°.ÔAØ05Ð9OÒ0O˜S   tÑ,ÐUZˆLð ð àˆnð ÜÐ+×0Ñ0°!Ó4Ð5ð 6ÜÐ)×4Ñ4°sÑ:Ó;¸B¸QÐ?Ð@ð Að	ñ ˆJð Ð.Ó.Ø -× ?Ñ ?ÀÓ F�Ü�}Ó%¨Ó)Øð 'ô
 " -Ó0Ð1ð 2ð	#ñ 	�Jô (.¨mÑAQÐ[_×'`˜Ø#×8Ñ8¸ÔHØ'/°;×3DÑ3DÀqÑ3HÑ'I˜Ø"ð +NàNZÈ^Ð[eÐfq×fwÑfwÐexð yNÜNSÐT_×TdÑTdÐfgÓNhÐMið jNÜNQÐR]×RhÑRhÐknÑRnÓNoÐprÐqrÐNsÐMtð uð	'ñ ™
ð (að ð #ñ ’JðM  ð\ 	�iÑˆ
Ø˜JÑ&Ð&r   c           	      ó@  — t        j                  | «      }t        |j                  dd«      «      d›|j                  dd«      dk7  r t        |j                  dd«      «      dz  d›nd|j                  dd«      dk7  r t        |j                  dd«      «      dz  d›nd|j                  dd«      dk7  r t        |j                  dd«      «      dz  d›nd|j                  dd«      dk7  r|j                  dd«      d	›ndd
œ}d}|D ]  }|d|› d||   › d�z  }Œ |dz  }|S )NÚlatencyúN/Ar„   Útotal_bytes_readi   @Útotal_bytes_writtenÚsystem_peak_buffer_memoryÚcumulative_rows_scannedÚ,)zExecution Time (s)zTotal GB ReadzTotal GB WrittenzPeak Memory (GB)zRows Scannedz<div class="metrics-grid">zP
            <div class="metric-box">
                <div class="metric-title">z1</div>
                <div class="metric-value">z&</div>
            </div>
            r…   )rM   rT   r   Úget)r�   rŒ   ÚmetricsÚmetric_grid_htmlr4   s        r   Ú_generate_metric_grid_htmlz(ProfilingInfo._generate_metric_grid_htmlõ  s[  € ä—Z‘Z 
Ó+ˆ
ä%*¨:¯>©>¸)ÀUÓ+KÓ%LÈSÐ$Qà�~‰~Ð0°%Ó8¸EÒAô !& j§n¡nÐ5GÈÓ&OÓ PÐT[Ñ \Ð]`Ñaàà�~‰~Ð3°UÓ;¸uÒDô $)¨¯©Ð8MÈuÓ)UÓ#VÐZaÑ#bÐcfÑ"gàà�~‰~Ð9¸5ÓAÀUÒJô $)¨¯©Ð8SÐUZÓ)[Ó#\Ð`gÑ#hÐilÑ"màà�~‰~Ð7¸Ó?À5ÒHð  *Ÿ~™~Ð.GÈÓOÐPQÑRàñ
ˆð <ÐÛˆCØð %+à+.¨%ð 0+Ø+2°3©<¨.ð 9ð!ñ Ñð ð 	˜HÑ$ÐØÐr   c                 ó`   — t        j                  | «      }|j                  dd«      }d|› d�}|S )NÚ
query_namer³   zx
        <details><summary><b>SQL Query</b></summary>
        <div class="chart sql-block">
            <pre><code>
    zI
            </code></pre>
        </div>
        </details><br>
        )rM   rT   r¹   )r�   rŒ   Ú	sql_queryÚsql_htmls       r   Ú_generate_sql_query_htmlz&ProfilingInfo._generate_sql_query_html  s?   € ä—Z‘Z 
Ó+ˆ
Ø—N‘N <°Ó7ˆ	ðð €Kð 	ð	ˆð ˆr   c                 ó�   — t        j                  |«      }t        |d   «      }d}d}| j                  |d   d   |«      }||z   |z   S )Nry   z&<div class="tf-tree tf-gap-sm"> 
 <ul>z</ul> </div>rb   r   )rM   rT   r   r–   )r   r�   rŒ   ry   Útree_prefixÚtree_suffixÚ	tree_bodys          r   Ú_generate_tree_htmlz!ProfilingInfo._generate_tree_html!  sW   € Ü—Z‘Z 
Ó+ˆ
Ü˜ JÑ/Ó0ˆØ?ˆØ$ˆð ×1Ñ1°*¸ZÑ2HÈÑ2KÈXÓVˆ	Ø˜YÑ&¨Ñ4Ð4r   Ú
json_inputc                 ó´   — ddl m} | j                  |d«      } |dj                  d|d   «      j                  d|d   «      j                  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_htmlr†   )r   rÇ   rÉ   r[   s       r   Ú_generate_ipythonzProfilingInfo._generate_ipython+  s[   € Ý-à×)Ñ)¨*°eÓ<ˆáànç‰W�X˜{¨5Ñ1Ó2ß‰WÐ&¨°NÑ(CÓDß‰W�^ [°Ñ%=Ó>ó
ð 	
r   Úinclude_meta_infoc                 ó    — d}d}|t         |ddœS )NzP<link rel="stylesheet" href="https://unpkg.com/treeflex/dist/css/treeflex.css">
zp<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
rŽ   )Útreeflex_cssÚ
duckdb_cssrÌ   rË   )Ú
qgraph_css)r�   rÐ   rÒ   rÌ   s       r   Ú_generate_style_htmlz"ProfilingInfo._generate_style_html9  s    € àjˆð Hˆ	Ø ,¼JÐU^ÐprÑsÐsr   rM   c                 ó4   — | j                  |d   d   |«       y )Nrb   r   )rd   )r   rM   r^   s      r   r¤   z(ProfilingInfo._gather_timing_information?  s   € ð 	×Ñ  ZÑ 0°Ñ 3°]ÕCr   Ú
input_filerX   c                 ó°  — t        «       }|�|}n>|�&t        |d«      5 }|j                  «       }d d d «       nt        d«       t	        d«       | j                  d«      }| j                  |«      }| j                  ||«      }	| j                  |«      }
| j                  |«      }t        |d«      5 }d}|j                  d|d   «      }|j                  d	|d
   «      }|j                  d|«      }|j                  d|«      }|j                  d|	«      }|j                  d|
«      }|j                  |«       d d d «       y # 1 sw Y   ŒûxY w# 1 sw Y   y xY w)Nr   z.please provide either input file or input textrc   Tzw+a  <!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 class="container">
            <header>
                <img src="https://raw.githubusercontent.com/duckdb/duckdb/refs/heads/main/logo/DuckDB_Logo-horizontal.svg" alt="DuckDB Logo">
                <h1>Query Profile Graph</h1>
            </header>
        <div class="chart" id="query-overview">
            ${METRIC_GRID}
        </div>
      <div class="chart" id="query-profile">
            ${SQL_QUERY}
            ${TIMING_TABLE}
      </div>
      ${TREE}
    </body>
    </html>
    z${TREEFLEX_CSS}rÒ   z${DUCKDB_CSS}rÓ   z${METRIC_GRID}z${SQL_QUERY}z${TIMING_TABLE}z${TREE})r"   rF   rO   ÚprintÚexitrÕ   r¼   r°   rÆ   rÁ   r†   Úwrite)r   r×   rX   rV   r^   ÚtextrQ   r[   Úhighlight_metric_gridÚtiming_tableÚtree_outputÚsql_query_htmlÚhtmls                r   rY   z%ProfilingInfo._translate_json_to_htmlE  sK  € ô #›ˆØÐ!Ø‰DØÐ#Ü˜: sÔ+¨qØ—v‘v“x�÷ ,Ð+ô ÐBÔCÜ�ŒGØ×/Ñ/°°dÓ;ˆØ $× ?Ñ ?ÀÓ EÐØ×1Ñ1°$¸ÓFˆØ×.Ñ.¨tÓ4ˆØ×6Ñ6°tÓ<ˆä�{ DÔ)¨QðˆDð8 —<‘<Ð 1°;¸~Ñ3NÓOˆDØ—<‘< °¸\Ñ1JÓKˆDØ—<‘<Ð 0Ð2GÓHˆDØ—<‘< °Ó?ˆDØ—<‘<Ð 1°<Ó@ˆDØ—<‘< 	¨;Ó7ˆDØ�G‰G�DŒM÷G *Ð)÷ ,Ð+ú÷ *Ð)ús   žE Â1BEÅ E	ÅE)NN)úprofile.html)r   )NNrâ   )r   r   r   r   r   r   rR   ÚdictrU   r\   Úobjectr   rd   Ústaticmethodr   rv   r‹   r–   r°   r¼   rÁ   rÆ   rÏ   ÚboolrÕ   r¤   rY   r    r   r   rH   rH   B  s  „ ñ#Ð/°$Ñ6ð #È#ÐPTÉ*ð #Ð`dó #ðB˜ó Bð*˜4ó *ñ 3ð ¸Có ñ
E¨6ð EÀ&ð EÐQTð EÐ]`ó Eð ð)¨ð )°#ò )ó ð)ð"ØðØ!$ðØ05ðØ=@ðØGJðØY\ðØjmðà	óð6!O°6ð !OÀUð !OÈsó !OðHF'°ð F'Àvð F'ÐRXó F'ðP ð ¨sð  °sò  ó ð ð8 ð¨Sð °Sò ó ðð5¨fð 5¸ó 5ð
¨Cð 
°Có 
ð ðt¨ð tÀð tÈ$ò tó ðtð
D¨sð DÀ6ð DÈdó Dð `nñ5Ø ™*ð5Ø9<¸t¹ð5ØY\ð5à	ô5r   rH   c                  óŒ  — t        j                  dd¬«      } | j                  dd¬«       | j                  ddd¬	«       | j                  d
ddd¬«       | j                  «       }|j                  }|j
                  }|j
                  s.d|v r|j                  dd«      }nHt        d«       t        d«       n1d|j
                  v r|j
                  }nt        d«       t        d«       |j                  }t        |¬«      }|j                  |¬«       |r2t        j                  dt        |«      j                  «       › �d¬«       y y )NzQuery Graph GeneratorzjGiven a json profile output, generate a html file showing the query graph and
        timings of operators)ÚprogÚdescriptionz--profile_inputzprofile input in json)Úhelpz--outF)ÚrequiredÚdefaultz--openÚ
store_trueT)rë   Úactionrì   z.jsonz.htmlz%please provide profile output in jsonrc   z/please provide valid .html file for output name)rJ   )rV   zfile://rm   )Únew)ÚargparseÚArgumentParserÚadd_argumentÚ
parse_argsÚprofile_inputÚoutr†   rÙ   rÚ   rE   rH   r\   Ú
webbrowserr   Úresolve)ÚparserÚargsÚinputÚoutputÚopen_outputÚprofiling_infos         r   Úmainrþ   }  s"  € Ü×$Ñ$Ø$ð ô€Fð
 ×ÑÐ)Ð0GÐÔHØ
×Ñ˜¨%¸ÐÔ?Ø
×Ñ˜¨5¸ÈtÐÔTØ×ÑÓ€Dà×Ñ€EØ�X‰X€FØ�8Š8Ø�eÑØ—]‘] 7¨GÓ4‰FäÐ9Ô:Ü��Gà�d—h‘hÑØ—X‘X‰FäÐCÔDÜ�ŒGà—)‘)€KÜ"¨UÔ3€NØ×Ñ vÐÔ.áÜ�‰˜'¤$ v£,×"6Ñ"6Ó"8Ð!9Ð:ÀÖBð r   Ú__main__r>   )rð   rM   r“   rö   Ú	functoolsr   Úpathlibr   Úduckdbr   rÔ   r   r"   r   rä   rF   rH   rþ   r   r    r   r   Ú<module>r     sy   ðÛ Û Û 	Û Ý Ý å %ðC€
÷L>ñ >÷" ñ  ð:9�Sð 9 ð 9¨ó 9÷xñ xóv	CðD ˆzÒÙ…Fð r   