
    7                         d Z ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZ dd	lmZ dd
lmZ ddZd Zd Zd Zd Zd Zd Zd Zd Zd Z G d de      Zy)z5Common methods to display parts of SQL query results.    )absolute_import)division)unicode_literals)partial)encoding)resource_printer)text)lexer)tokensc                 l    | D ].  }|j                   |k(  st        |d      r|j                  c S  |S  |S )a  Gets the value for the given key in a list of properties.

  Looks through a list of properties and tries to find the value for the given
  key. If it's not found, not_found_value is returned.

  Args:
    properties: A dictionary of key string, value string pairs.
    property_key: The key string for which we want to get the value.
    not_found_value: The string value to return if the key is not found.

  Returns:
    A string containing the value for the given key, or `not_found_value` if
    the key is not found.
  value)keyhasattrr   )
propertiesproperty_keynot_found_valueprops       -lib/googlecloudsdk/command_lib/spanner/sql.py_GetAdditionalPropertyr      s?     dxx<	w	zz	 
 
    c                      t        | | d         S )a  Creates tree of Node objects from the plan_nodes in server response.

  Args:
    plan_nodes (spanner_v1_messages.PlanNode[]): The plan_nodes from the server
      response. Plan nodes are topologically sorted.

  Returns:
    A Node, root of a tree built from `plan_nodes`.
  r   )_BuildSubTree)
plan_nodess    r   _ConvertToTreer   4   s     
z:a=	11r   c                     d}|j                   r0|j                   D cg c]  }t        | | |j                            }}t        ||      S c c}w )a>  Helper for building the subtree of a query plan node.

  Args:
    plan_nodes (spanner_v1_messages.PlanNode[]): The plan_nodes from the server
      response. Plan nodes are topologically sorted.
    node (spanner_v1_messages.PlanNode): The root node of the subtree to be
      built.

  Returns:
    A Node object.
  N)
childLinksr   
childIndexNode)r   nodechildrenlinks       r   r   r   B   sV     (	__ OO-+D j*T__*EF+  -	dH	-s    Ac                     t        | d|       S )zConverts the prop to a string if it exists.

  Args:
    prop (object_value): The value returned from _GetAdditionalProperty.

  Returns:
    A string value for the given prop, or the `not_found_value` if the prop does
    not exist.
  string_value)getattr)r   s    r   _ConvertToStringValuer%   U   s     
~t	,,r   c                     |rd}nd}| dk(  r"|j                  |j                  | d             y|j                  |j                  | d             y)aB  Prints number of rows modified by a DML statement.

  Args:
    row_count: Either the exact number of rows modified by statement or the
      lower bound of rows modified by a Partitioned DML statement.
    is_exact_count: Boolean stating whether the number is the exact count.
    out: Output stream to which we print.
  zStatement modified {} {}z)Statement modified a lower bound of {} {}   rowrowsN)Printformat)	row_countis_exact_countout
output_strs       r   _DisplayNumberOfRowsModifiedr0   b   sJ     +J<J!^IIj	512IIj	623r   c                 T   | j                         j                         } t        j                  |       }t	        |      D ]g  }|t
        j                  j                  dfk(  xs@ |t
        j                  j                  dfk(  xs |t
        j                  j                  dfk(  }|sg y y)zDetermines if the sql string contains a DML query.

  Args:
    sql (string): The sql string entered by the user.

  Returns:
    A boolean.
  insertupdatedeleteTF)lstriplowerr
   tokenizelistTKeywordDML)sql	tokenizedtokenhas_dmls       r   QueryHasDmlr@   v   s     	

#nnS!)Ie!))--** 	+!))--**	+!))--**    
r   c                 P    t        | d      xr t        | j                  dd      duS )zChecks if the given results have aggregate statistics.

  Args:
    result (spanner_v1_messages.ResultSetStats): The stats for a query.

  Returns:
    A boolean indicating whether 'results' contain aggregate statistics.
  stats
queryStatsN)r   r$   rB   )results    r   QueryHasAggregateStatsrE      s2     
g
 
Q"6<<tDDPQr   c           	         t        t        | j                        }t         |d            t         |d            t         |d            t         |d            t         |d            d}t	        j
                  |d|       y	)
aZ  Displays the aggregate stats for a Spanner SQL query.

  Looks at the queryStats portion of the query response and prints some of
  the aggregate statistics.

  Args:
    query_stats (spanner_v1_messages.ResultSetStats.QueryStatsValue): The query
      stats taken from the server response to a query.
    out: Output stream to which we print.
  elapsed_timecpu_timerows_returnedrows_scannedoptimizer_version)total_elapsed_timerH   rI   rJ   rK   zXtable[box](total_elapsed_time, cpu_time, rows_returned, rows_scanned, optimizer_version)r.   N)r   r   additionalPropertiesr%   r   r*   )query_statsr.   get_proprB   s       r   DisplayQueryAggregateStatsrQ      sy     +[-M-MN(1(>2JK'(<=,Xo-FG+H^,DE0:M1NO% `
r   c                 x    t        | j                  j                  j                        }|j	                  |       y)zDisplays a graphical query plan for a query.

  Args:
    result (spanner_v1_messages.ResultSet): The server response to a query.
    out: Output stream to which we print.
  N)r   rB   	queryPlan	planNodesPrettyPrint)rD   r.   node_tree_roots      r   DisplayQueryPlanrW      s,     "&,,"8"8"B"BC.S!r   c                    t        | j                  d      r7| j                  j                  !t        | j                  j                  d|       t        | j                  d      r7| j                  j                  !t        | j                  j                  d|       | j
                  j                  j                  r| j
                  j                  j                  D cg c]  }|j                  xs d }}dj                  d t        |      D              }| j                  D cg c]#  }d	t        j                  |j                        i% }}t        j                   |d
j#                  |      |       yyc c}w c c}w )zPrints the result rows for a query.

  Args:
    result (spanner_v1_messages.ResultSet): The server response to a query.
    out: Output stream to which we print.
  rowCountExactNTrowCountLowerBoundFz(Unspecified),c              3   F   K   | ]  \  }}d j                  ||        yw)z!row.slice({0}).join():label="{1}"N)r+   ).0ifs      r   	<genexpr>z&DisplayQueryResults.<locals>.<genexpr>   s*      ;(91 @FFq!L(9s   !r(   z
table({0})rM   )r   rB   rY   r0   rZ   metadatarowTypefieldsnamejoin	enumerater)   r   MessageToPyValueentryr   r*   r+   )rD   r.   fieldrc   table_formatr(   r)   s          r   DisplayQueryResultsrk      sP    V\\"(,,"<"<"H !;!;T3Gll & ? ? K !@!@%M__## __,,333E 	

%o%3   88 ;(1&(9; ;L # 	x((3 	 
 4!4!4\!BL $s   E8%(E=c                   D    e Zd ZdZddZd Zd Zd Zd Zd Z	d	 Z
dd
Zy)r   zRepresents a single node in a Spanner query plan.

  Attributes:
    properties (spanner_v1_messages.PlanNode): The details about a given node
      as returned from the server.
    children: A list of children in the query plan of type Node.
  Nc                 (    |xs g | _         || _        y N)r    r   )selfr   r    s      r   __init__zNode.__init__   s    NDM DOr   c                     dj                  ||| j                  j                  | j                  j                        }|j	                  |       y)z@Prints the kind of the node (SCALAR or RELATIONAL) and its name.z
{}{} {} {}N)r+   r   kinddisplayNamer*   )ro   r.   prependstubkind_and_names        r   _DisplayKindAndNamezNode._DisplayKindAndName   s<     ''t7K7K(,(C(CEMIImr   c                     t        | j                  j                  j                  |d      }|syt        |j                  j                  |d      }|r|j
                  S y)av  Gets a nested property name on this object's executionStats.

    Args:
      prop_name: A string of the key name for the outer property on
        executionStats.
      nested_prop_name: A string of the key name of the nested property.

    Returns:
      The string value of the nested property, or None if the outermost
      property or nested property don't exist.
     N)r   r   executionStatsrN   object_valuer#   )ro   	prop_namenested_prop_namer   nested_props        r   _GetNestedStatPropertyzNode._GetNestedStatProperty   s[     "&&;;YLD():):)E)E)92?K%%%r   c                 H   | j                   j                  syg }| j                  dd      }|rBt        |      }dj	                  |t        j                  |d            }|j                  |       | j                  dd      }| j                  dd      }| j                  dd	      }	|r"|j                  d
j	                  ||	             n#|r!|j                  dj	                  ||	             |r4dj	                  ||dj                  |            }
|j                  |
       yy)a  Prints the relevant execution statistics for a node.

    More specifically, print out latency information and the number of
    executions. This information only exists when query is run in 'PROFILE'
    mode.

    Args:
      out: Output stream to which we print.
      prepend: String that precedes any information about this node to maintain
        a visible hierarchy.
      beneath_stub: String that preserves the indentation of the vertical lines.
    Nexecution_summarynum_executionsz{} {}	executionlatencymeantotalunitz{} {} average latencyz{} {} total latencyz	{}{} ({}), )
r   rz   r   intr+   r	   	Pluralizeappendre   r*   )ro   r.   rt   beneath_stub
stat_propsr   executions_strmean_latencytotal_latencyr   executions_stats_strs              r   _DisplayExecutionStatszNode._DisplayExecutionStats	  s    ??))J001D1ACN>*n~~n&*nn^5@'BCn ' ..y&AL//	7CM&&y&9D/66|TJK	-44]DIJ(//04		*0EG	ii$% r   c           	      v   | j                   j                  rg }| j                   j                  j                  D ]A  }|j                  dj	                  |j
                  |j                  j                               C dj	                  ||dj                  t        |                  }|j                  |       yy)a0  Prints the keys and values of the metadata for a node.

    Args:
      out: Output stream to which we print.
      prepend: String that precedes any information about this node to maintain
        a visible hierarchy.
      beneath_stub: String that preserves the indentation of the vertical lines.
    z{}: {}{}{} {}r   N)r   ra   rN   r   r+   r   r   r#   re   sortedr*   )ro   r.   rt   r   additional_propsr   ra   s          r   _DisplayMetadatazNode._DisplayMetadata3  s     //**??$OODHHdjj&=&=>	@ @ !!'<"&))F3C,D"EGh	ii  r   c                     | j                   j                  rCdj                  ||| j                   j                  j                        }|j	                  |       y y )Nr   )r   shortRepresentationr+   descriptionr*   )ro   r.   rt   r   	short_reps        r   _DisplayShortRepresentationz Node._DisplayShortRepresentationF  sJ    **""
<
//
-
-
9
9;i 
ii		 +r   c                     |rdnd}|| j                   rdndz  }dj                  |||      }|j                  |j                                y)a  Displays an empty line between nodes for visual breathing room.

    Keeps in tact the vertical lines connecting all immediate children of a
    node to each other.

    Args:
      out: Output stream to which we print.
      prepend: String that precedes any information about this node to maintain
        a visible hierarchy.
      beneath_stub: String that preserves the indentation of the vertical lines.
      is_root: Boolean indicating whether this node is the root of the tree.
      ry   z  |z{}{}{}N)r    r+   r*   rstrip)ro   r.   rt   r   is_rootabove_child
break_lines          r   _DisplayBreakLinezNode._DisplayBreakLineM  sH     "$rKDMM5r1K,DJ IIj!"r   c                    |xs d}|rdn|rdnd}|rdn|rdnd}| j                  |||       | j                  |||       | j                  |||       | j                  |||       | j	                  ||||       t        | j                        D ]C  \  }}|t        | j                        dz
  k(  }	d}
||rdnd	z   |
z   }|j                  |||	d
       E y)a  Prints a string representation of this node in the tree.

    Args:
      out: Output stream to which we print.
      prepend: String that precedes any information about this node to maintain
        a visible hierarchy.
      is_last: Boolean indicating whether this node is the last child of its
        parent.
      is_root: Boolean indicating whether this node is the root of the tree.
    ry   z\-z+-r   z| r'   z    |F)rt   is_lastr   N)	rw   r   r   r   r   rf   r    lenrU   )ro   r.   rt   r   r   ru   r   idxchildis_last_childindentchild_prepends               r   rU   zNode.PrettyPrintb  s     mG 2uTD !2wtDLS'40Wl;#w5$$S'<@3w?.
US/!33mf S9FBm
}mU  L /r   rn   )NTT)__name__
__module____qualname____doc__rp   rw   r   r   r   r   r   rU    r   r   r   r      s1    !0(&T&#*#Lr   r   N)Unknown)r   
__future__r   r   r   	functoolsr   apitools.base.pyr   googlecloudsdk.core.resourcer   googlecloudsdk.core.utilr	   sqlparser
   r   r9   r   r   r   r%   r0   r@   rE   rQ   rW   rk   objectr   r   r   r   <module>r      sj    < &  '  % 9 )   .2&
-4(*
Q2"MDgL6 gLr   