
    7                         S r SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSK	J
r
  SSKJr  SS	KJr  SS
KJr  SS jrS rS rS rS rS rS rS rS rS r " S S\5      rg)z5Common methods to display parts of SQL query results.    )absolute_import)division)unicode_literals)partial)encoding)resource_printer)text)lexer)tokensc                 |    U  H5  nUR                   U:X  d  M  [        US5      (       a  UR                  s  $   U$    U$ )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      sB     dxx<	w		zz	 
 
    c                     [        X S   5      $ )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     
za=	11r   c                     SnUR                   (       a2  UR                    Vs/ s H  n[        X UR                     5      PM     nn[        X5      $ s  snf )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   sR     (	__ OO-+D jT__*EF+  -	d	-s   "Ac                     [        U SU 5      $ )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                     U(       a  SnOSnU S:X  a"  UR                  UR                  U S5      5        gUR                  UR                  U S5      5        g)a6  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                 x   U R                  5       R                  5       n [        R                  " U 5      n[	        U5       Hw  nU[
        R                  R                  S4:H  =(       dE    U[
        R                  R                  S4:H  =(       d    U[
        R                  R                  S4:H  nU(       d  Mw    g   g)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!))--** 	+!))--**	+!))--**  w  
r   c                 Z    [        U S5      =(       a    [        U R                  SS5      SL$ )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           	      
   [        [        U R                  5      n[        U" S5      5      [        U" S5      5      [        U" S5      5      [        U" S5      5      [        U" S5      5      S.n[        R
                  " USUS9  g	)
aL  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    [        U R                  R                  R                  5      nUR	                  U5        g)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                 :   [        U R                  S5      (       a8  U R                  R                  b!  [        U R                  R                  SU5        [        U R                  S5      (       a8  U R                  R                  b!  [        U R                  R                  SU5        U R
                  R                  R                  (       a  U R
                  R                  R                   Vs/ s H  nUR                  =(       d    SPM     nnSR                  S [        U5       5       5      nU R                   Vs/ s H%  nS	[        R                  " UR                  5      0PM'     nn[        R                   " US
R#                  U5      US9  ggs  snf s  snf )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   H   #    U  H  u  pS R                  X5      v   M     g7f)z!row.slice({0}).join():label="{1}"N)r+   ).0ifs      r   	<genexpr>&DisplayQueryResults.<locals>.<genexpr>   s(      ;(9 @FFqL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.   fieldrd   table_formatr(   r)   s          r   DisplayQueryResultsrl      sZ    V\\ "(,,"<"<"H !;!;T3Gll  & ? ? K !@!@%M__## __,,333E 	

%o%3   88 ;(1&(9; ;L # 	x((3 	 
 4!4!4\!BL $s   .F>,Fc                   P    \ rS rSrSrSS jrS rS rS rS r	S	 r
S
 rSS jrSrg)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                 0    U=(       d    / U l         Xl        g Nr    r   )selfr   r    s      r   __init__Node.__init__   s    NDM Or   c                     SR                  X#U R                  R                  U R                  R                  5      nUR	                  U5        g)z@Prints the kind of the node (SCALAR or RELATIONAL) and its name.z
{}{} {} {}N)r+   r   kinddisplayNamer*   )rr   r.   prependstubkind_and_names        r   _DisplayKindAndNameNode._DisplayKindAndName   s:     ''t7K7K(,(C(CEMIImr   c                     [        U R                  R                  R                  US5      nU(       d  g[        UR                  R                  US5      nU(       a  UR
                  $ g)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#   )rr   	prop_namenested_prop_namer   nested_props        r   _GetNestedStatPropertyNode._GetNestedStatProperty   s[     "&&;;YLD():):)E)E)92?K%%%r   c                 v   U R                   R                  (       d  g/ nU R                  SS5      nU(       aC  [        U5      nSR	                  U[
        R                  " US5      5      nUR                  U5        U R                  SS5      nU R                  SS5      nU R                  SS	5      n	U(       a!  UR                  S
R	                  Xy5      5        O'U(       a   UR                  SR	                  X5      5        U(       a3  SR	                  X#SR                  U5      5      n
UR                  U
5        gg)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   r   r   intr+   r	   	Pluralizeappendrf   r*   )rr   r.   rx   beneath_stub
stat_propsr   executions_strmean_latencytotal_latencyr   executions_stats_strs              r   _DisplayExecutionStatsNode._DisplayExecutionStats	  s    ??))J001D1ACN>*n~~n&*nn^5@'BCn ' ..y&AL//	7CM&&y&9D/66|JK	-44]IJ(//04		*0EG	ii$% r   c           	         U R                   R                  (       a  / nU R                   R                  R                   HB  nUR                  SR	                  UR
                  UR                  R                  5      5        MD     SR	                  X#SR                  [        U5      5      5      nUR                  U5        gg)a  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   rb   rN   r   r+   r   r   r#   rf   sortedr*   )rr   r.   rx   r   additional_propsr   rb   s          r   _DisplayMetadataNode._DisplayMetadata3  s     //**??$OODHHdjj&=&=>	@ @ !!'"&))F3C,D"EGh	ii  r   c                     U R                   R                  (       aB  SR                  X#U R                   R                  R                  5      nUR	                  U5        g g )Nr   )r   shortRepresentationr+   descriptionr*   )rr   r.   rx   r   	short_reps        r   _DisplayShortRepresentation Node._DisplayShortRepresentationF  sH    **""

//
-
-
9
9;i 
ii		 +r   c                     U(       a  SOSnXPR                   (       a  SOS-  nSR                  X#U5      nUR                  UR                  5       5        g)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.
  r~   z  |z{}{}{}N)r    r+   r*   rstrip)rr   r.   rx   r   is_rootabove_child
break_lines          r   _DisplayBreakLineNode._DisplayBreakLineM  sD     "$rKMM5r1KDJ IIj!"r   c                    U=(       d    SnU(       a  SO
U(       a  SOSnU(       a  SO
U(       a  SOSnU R                  XU5        U R                  XU5        U R                  XU5        U R                  XU5        U R	                  XXd5        [        U R                  5       HC  u  pxU[        U R                  5      S-
  :H  n	Sn
X#(       a  SOS	-   U
-   nUR                  XU	S
S9  ME     g)ak  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.
r~   z\-z+-r   z| r'   z    |F)rx   is_lastr   N)	r{   r   r   r   r   rg   r    lenrU   )rr   r.   rx   r   r   ry   r   idxchildis_last_childindentchild_prepends               r   rU   Node.PrettyPrintb  s     mG 2uTD !2wtDLS40l;#5$$S<@3?.
S/!33mf S9FBm
mU  L /r   rq   rp   )NTT)__name__
__module____qualname____firstlineno____doc__rs   r{   r   r   r   r   r   rU   __static_attributes__ 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   rl   objectr   r   r   r   <module>r      sj    < &  '  % 9 )   .2&
-4(*
Q2"MDgL6 gLr   