
    17                         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 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.    )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   1   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   ?   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"   R   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   _DisplayNumberOfRowsModifiedr-   _   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=   s   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!   r?   )results    r   QueryHasAggregateStatsrB      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_timerE   rF   rG   rH   zXtable[box](total_elapsed_time, cpu_time, rows_returned, rows_scanned, optimizer_version)r+   N)r   r   additionalPropertiesr"   r   r'   )query_statsr+   get_propr?   s       r   DisplayQueryAggregateStatsrN      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   r?   	queryPlan	planNodesPrettyPrint)rA   r+   node_tree_roots      r   DisplayQueryPlanrT      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})rJ   )r   r?   rV   r-   rW   metadatarowTypefieldsnamejoin	enumerater&   r   MessageToPyValueentryr   r'   r(   )rA   r+   fieldra   table_formatr%   r&   s          r   DisplayQueryResultsri      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'   )ro   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   executionStatsrK   object_valuer    )ro   	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appendrc   r'   )ro   r+   ru   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   r_   rK   r   r(   r   r
   r    rc   sortedr'   )ro   r+   ru   r   additional_propsr   r_   s          r   _DisplayMetadataNode._DisplayMetadata0  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'   )ro   r+   ru   r   	short_reps        r   _DisplayShortRepresentation Node._DisplayShortRepresentationC  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)ro   r+   ru   r   is_rootabove_child
break_lines          r   _DisplayBreakLineNode._DisplayBreakLineJ  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)ru   is_lastr   N)	rx   r   r   r   r   rd   r   lenrR   )ro   r+   ru   r   r   rv   r   idxchildis_last_childindentchild_prepends               r   rR   Node.PrettyPrint_  s     mG 2uTD !2wtDLS40l;#5$$S<@3?.
S/!33mf S9FBm
mU  L /r   rn   rm   )NTT)__name__
__module____qualname____firstlineno____doc__rp   rx   r   r   r   r   r   rR   __static_attributes__ r   r   r   r      s1    !0(&T&#*#Lr   r   N)Unknown)r   	functoolsr   apitools.base.pyr   googlecloudsdk.core.resourcer   googlecloudsdk.core.utilr   sqlparser   r   r6   r   r   r   r"   r-   r=   rB   rN   rT   ri   objectr   r   r   r   <module>r      sc    <  % 9 )   .2&
-4(*
Q2"MDgL6 gLr   