
    z                        S r SSKJr  SSKrSSK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\R"                  5      r " S S\R"                  5      r " S S\R"                  5      rS r " S S\R"                  5      r " S S\R"                  5      r\R0                  " SS9r\R4                  R7                  \\5        S,S jrS rS rS r " S S\ 5      r!\RD                  RF                  r#\RD                  RH                  r$\RD                  RJ                  r%\RD                  RH                  \RL                  RH                  :X  d   e\RD                  RJ                  \RL                  RJ                  :X  d   e\'" \RP                  RR                  /5      r*\'" \RP                  RV                  \RP                  RX                  \RP                  RZ                  \RP                  R\                  /5      r/\'" \RP                  R`                  /5      r1S r2S  r3S! r4S" r5S# r6S$ r7S% r8S& r9S' r:S( r;S) r<S* r=S+ r>g)-a  Primitives for dealing with datastore indexes.

Example index.yaml file:
------------------------

indexes:

- kind: Cat
  ancestor: no
  properties:
  - name: name
  - name: age
    direction: desc

- kind: Cat
  properties:
  - name: name
    direction: ascending
  - name: whiskers
    direction: descending

- kind: Store
  ancestor: yes
  properties:
  - name: business
    direction: asc
  - name: owner
    direction: asc

- kind: Mountain
  properties:
  - name: name
  - name: location
    mode: geospatial
    )absolute_importN)appinfo)datastore_types)
validation)yaml_errors)yaml_object)datastore_pb)	entity_pb)yamlc                       \ rS rSrSr0 rSrg)VectorFlatIndexK   zRepresents the configuration for a vector FlatIndex.

Currently there are not options for a Vector FlatIndex, but it exists to
distinguish itself from future index types.
 N)__name__
__module____qualname____firstlineno____doc__
ATTRIBUTES__static_attributes__r       9lib/googlecloudsdk/appengine/datastore/datastore_index.pyr   r   K   s     *r   r   c                   ^    \ rS rSrSr\R                  " \SS9\R                  " \SS9S.r	Sr
g)VectorConfigU   zQRepresents the configuration for a vector indexed property as it appears in YAML.Fconvert)	dimensionflatr   N)r   r   r   r   r   r   Typeintr   r   r   r   r   r   r   r   U   s*    Y ??36ooou=*r   r   c            
          ^  \ rS rSrSr\R                  " \SS9\R                  " SS/5      \R                  " S/5      \R                  " \R                  " \	SS95      S.r
S	 rU 4S
 jrSrU =r$ )Property^   aZ  Representation for a property of an index as it appears in YAML.

Attributes (all in string form):
  name: Name of attribute to sort by.
  direction: Direction of sort.
  mode: How the property is indexed. Either 'geospatial'
      or None (unspecified).
  vectorConfig: Indicates that the property is part of a Vector Index
      configuration.
Fr   )asc)	ascending)desc)
descending
geospatial)name	directionmodevectorConfigc                      U R                   S:g  $ )Nr'   )r+   selfs    r   IsAscendingProperty.IsAscendingv   s     >>V##r   c                    > SnU R                   b  US-  nU R                  b  US-  nU R                  b  US-  nUS:  a  [        R                  " S5      e[
        [        U ]  5         g )Nr      z8direction, mode, and vectorConfig are mutually exclusive)r+   r,   r-   r   ValidationErrorsuperr#   CheckInitialized)r0   field_count	__class__s     r   r7   Property.CheckInitialized   sr    K~~!QkyyQk$QkQ&&
D  
(D*,r   r   )r   r   r   r   r   r   r    strOptionalr   r   r1   r7   r   __classcell__r9   s   @r   r#   r#   ^   su    	 ooc51&&
!
#( 	 !!<.1 ))
//,
6
*$- -r   r#   c                     [         R                   " U5      nUR                  c  U?UR                  c  U?UR                  c  U?U R	                  U5      $ )aB  A PyYaml presenter for Property.

It differs from the default by not outputting 'mode: null' and direction when
mode is specified. This is done in order to ensure backwards compatibility.

Args:
  dumper: the Dumper object provided by PyYaml.
  prop: the Property object to serialize.

Returns:
  A PyYaml object mapping.
)copyr,   r+   r-   represent_object)dumperprop	prop_copys      r   PropertyPresenterrE      sU     iio) 
YY	^^			 	 	++r   c                      ^  \ rS rSrSr\R                  " \SS9\R                  " \SSS9\R                  " \R                  " \5      5      S.rU 4S jrS rS	rU =r$ )
Index   zIndividual index definition.

Order of the properties determines a given index's sort priority.

Attributes:
  kind: Datastore kind that index belongs to.
  ancestors: Include ancestors in index.
  properties: Properties to be included.
Fr   )r   default)kindancestor
propertiesc                 J   > U R                  5         [        [        U ]  5         g N)
_Normalizer6   rG   r7   )r0   r9   s    r   r7   Index.CheckInitialized   s    OO	%')r   c                 z   U R                   c  g [        S U R                    5       5      nS nU R                    H  nUR                  S LnU(       a%  UR                  b  [        R
                  " S5      eM=  U(       a  Ub  [        R
                  " S5      eUnMa  UR                  5       (       d  Mx  SUl        M     g )Nc              3   >   #    U  H  oR                   S :H  v   M     g7fr)   Nr,   .0xs     r   	<genexpr>#Index._Normalize.<locals>.<genexpr>   s     AA<'   z-direction not supported in a geospatial indexz#only one vector property is allowedr%   )rL   anyr-   r+   r   r5   r1   )r0   is_geovector_propertyrC   	is_vectors        r   rO   Index._Normalize   s    AAAFO##4/i	>>%**=  & &**3    $.!  r   r   )r   r   r   r   r   r   r    r;   boolr<   Repeatedr#   r   r7   rO   r   r=   r>   s   @r   rG   rG      sW     ooc51//$uE''
(;(;H(EF**! !r   rG   c                       \ rS rSrSr\R                  \R                  " \R                  5      S\R                  " \R                  " \5      5      0rSrg)IndexDefinitions   zXTop level for index definition file.

Attributes:
  indexes: List of Index definitions.
indexesr   N)r   r   r   r   r   r   APPLICATIONr   r<   APPLICATION_RE_STRINGra   rG   r   r   r   r   r   rc   rc      sG     :..w/L/LM$$Z%8%8%?@*r   rc   unsafe)typc                 n     [         R                  " [        U 5      $ ! [        R                   a     gf = f)a  Parse an individual index definitions document from string or stream.

Args:
  document: Yaml document as a string or file-like stream.
  open_fn: Function for opening files. Unused.

Raises:
  EmptyConfigurationFile when the configuration file is empty.
  MultipleConfigurationFile when the configuration file contains more than
  one document.

Returns:
  Single parsed yaml file if one is defined, else None.
N)r   BuildSingleObjectrc   r   EmptyConfigurationFile)documentopen_fns     r   ParseIndexDefinitionsro      s3    (()98DD		+	+ s    44c                 8    [         R                  " [        U 5      $ )zParse multiple index definitions documents from a string or stream.

Args:
  document: Yaml document as a string or file-like stream.

Returns:
  A list of datastore_index.IndexDefinitions objects, one for each document.
)r   BuildObjectsrc   )rm   s    r   ParseMultipleIndexDefinitionsrr      s     
	!	!"2H	==r   c                     [        5       nU b>  U R                  (       a-  U R                   H  nUR                  [        U5      5        M     U$ )a#  Convert IndexDefinitions to set of keys.

Args:
  indexes: A datastore_index.IndexDefinitions instance, or None.

Returns:
  A set of keys constructed from the argument, each key being a
  tuple of the form (kind, ancestor, properties) where properties is
  a tuple of PropertySpec objects.
)setre   add
IndexToKey)re   keysetindexs      r   IndexDefinitionsToKeysry     s<     5&??%

:e$% #	-r   c                    / nU R                   bU  U R                    HE  nUR                  [        UR                  UR	                  5       (       a  [
        O[        S95        MG     U R                  U R                  [        U5      4$ )zConvert Index to key.

Args:
  index: A datastore_index.Index instance (not None!).

Returns:
  A tuple of the form (kind, ancestor, properties) where properties
  is a sequence of PropertySpec objects derived from the Index.
r*   r+   )
rL   appendPropertySpecr*   r1   	ASCENDING
DESCENDINGrJ   rK   tuple)rx   propsrC   s      r   rv   rv   !  sn     %
!  ll<TYY:>:J:J:L:LY2<? @ ! 
U^^U5\	11r   c                       \ rS rSrSrSS jr\S 5       r\S 5       r\S 5       r	S r
S	 rS
 rS rS rS rS rS rS rS rS rSrg)r}   i9  z6Index property attributes required to satisfy a query.Nc                 8    Ub  Ub   eXl         X l        X0l        g rN   _name
_direction_mode)r0   r*   r+   r,   s       r   __init__PropertySpec.__init__<  s!    ,,JOJr   c                     U R                   $ rN   )r   r/   s    r   r*   PropertySpec.nameB      ::r   c                     U R                   $ rN   )r   r/   s    r   r+   PropertySpec.directionF  s    ??r   c                     U R                   $ rN   )r   r/   s    r   r,   PropertySpec.modeJ  r   r   c                 j    [        U[        5      (       d  [        $ U R                  UR                  :H  $ rN   )
isinstancer}   NotImplemented__dict__r0   others     r   __eq__PropertySpec.__eq__N  s(    e\**==ENN**r   c                     X:X  + $ rN   r   r   s     r   __ne__PropertySpec.__ne__S  s    r   c                 H    U R                   U R                  U R                  4$ )z)Produces a tuple for comparison purposes.r   r/   s    r   __tuplePropertySpec.__tupleV  s    JJ44r   c                 z    [        U[        5      (       d  [        $ U R                  5       UR                  5       :  $ rN   r   r}   r   _PropertySpec__tupler   s     r   __lt__PropertySpec.__lt__Z  ,    e\**<<>EMMO++r   c                 z    [        U[        5      (       d  [        $ U R                  5       UR                  5       :*  $ rN   r   r   s     r   __le__PropertySpec.__le___  ,    e\**<<>U]]_,,r   c                 z    [        U[        5      (       d  [        $ U R                  5       UR                  5       :  $ rN   r   r   s     r   __gt__PropertySpec.__gt__d  r   r   c                 z    [        U[        5      (       d  [        $ U R                  5       UR                  5       :  $ rN   r   r   s     r   __ge__PropertySpec.__ge__i  r   r   c                 \    [        SU R                  U R                  U R                  45      $ )Nr}   )hashr   r   r   r/   s    r   __hash__PropertySpec.__hash__n  s"    T__djjIJJr   c                 l   SU R                   -  /nU R                  b;  UR                  S[        R                  R                  U R                  5      -  5        U R                  b;  UR                  S[        R                  R                  U R                  5      -  5        SR                  U5      < S3$ )NzPropertySpec(name=%szdirection=%szmode=%sz, ))	r   r   r|   r
   Index_PropertyDirection_Namer   	Mode_Namejoin)r0   builders     r   __repr__PropertySpec.__repr__q  s    %

23G"nn^i&>&>&M&Mdoo&^^_zznnY!9!9!C!CDJJ!OOPIIg&((r   c                     [        U[        5      (       d   eU R                  UR                  :w  a  gU R                  c  UR                  b  gUR                  c  gU R                  UR                  :H  $ )zDetermines whether existing index can satisfy requirements of a new query.

Used in finding matching postfix with traditional "ordered" index specs.
FT)r   r}   r   r   r   r   s     r   	SatisfiesPropertySpec.Satisfiesy  sh    
 e\****zzU[[ zz!8   ??e....r   c                     UR                  U R                  5        U R                  c)  UR                  U R                  =(       d    [
        5        g UR                  U R                  5        g rN   )set_namer   r   set_directionr   r~   set_mode)r0   pbs     r   CopyToIndexPbPropertySpec.CopyToIndexPb  sE    KK

 	

t3)4kk$**r   )r   r   r   )NN)r   r   r   r   r   r   propertyr*   r+   r,   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r}   r}   9  s~    >      +
5,
-
,
-
K)/&r   r}   c                 Z   [        5       n[        5       nU  H  nUR                  5       [        R                  R                  :X  a=  UR                  5       S:X  a)  UR                  [        R                  R                  5        UR                  5       [        ;   a0  UR                  UR                  S5      R                  5       5        M  UR                  5       [        ;   d  M  UR                  UR                  S5      R                  5       5        M     X4-  nUR                  5       n/ nU HI  nUR                  5       U;  d  M  UR                  UR                  5       5        UR                  U5        MK     UnUR                  U5        / n	U  Hv  nUR                  5       [         ;  a  U	R                  U5        M.  UR                  S5      R                  5       n
X;  d  MT  UR                  U
5        U	R                  U5        Mx     U H  nX;  d  M
  UR                  U5        [        R                  " 5       nUR                  [        R                  R"                  5        UR%                  5       nUR'                  U5        UR)                  S5        UR+                  5         U	R                  U5        M     U	n [,        R.                  U;   a  / n/ nU HI  nUR                  5       [,        R.                  :X  a  UR                  U5          OUR                  U5        MK     UnX4$ )a~  Normalizes filter and order query components.

The resulting components have the same effect as the given components if used
in a query.

Args:
  filters: the filters set on the query
  orders: the orders set on the query
  exists: the names of properties that require an exists filter if
    not already specified

Returns:
  (filter, orders) the reduced set of filters and orders
r4   r   F)rt   opr	   Query_FilterINproperty_sizeset_opEQUALEQUALITY_OPERATORSru   r   r*   INEQUALITY_OPERATORSr@   r|   updateEXISTS_OPERATORSEXISTSadd_propertyr   set_multiplemutable_valuer   KEY_SPECIAL_PROPERTY)filtersordersexistseq_propertiesinequality_propertiesf
remove_set
new_ordersonew_filtersr*   rC   
new_filternew_props                 r   	Normalizer     s     %-% attv**---!//2Cq2Hhh|((../ttv##

1**,-	
'	'

1 2 2 45  (- !!#**azz|:%nnQZZ\"  &)* +attv%%::a=DnnT  dnnT,,.j11889((*hE"$  ' ))]:F *azz|;;;a	 
 &
	r   c                 d   [        XU5      u  pU  H   nUR                  5       [        ;   d  M  X4s  $    SnU(       aH  US   R                  5       [        R
                  :X  a#  US   R                  5       [        :X  a  USS nOSnU(       d  U  HR  nUR                  5       [        ;   d  M  UR                  S5      R                  5       [        R
                  :w  d  MP    X4$    U  Vs/ s H8  nUR                  S5      R                  5       [        R
                  :w  d  M6  UPM:     n nX4$ s  snf )a  Removes query components that are natively supported by the datastore.

The resulting filters and orders should not be used in an actual query.

Args:
  filters: the filters set on the query
  orders: the orders set on the query
  exists: the names of properties that require an exists filter if
    not already specified

Returns:
  (filters, orders) the reduced set of filters and orders
FNTr   )
r   r   r   r   r   r   r+   r~   r   r*   )r   r   r   r   has_key_desc_orders        r   !RemoveNativelySupportedComponentsr     s      87attv!!   r
##%)M)MMbz*cr{f 

$$&(
(
**Q-


/"F"F
F 	  KZZ]!_%I%II W  K 		Ks   )5D-"D-c                   ^ SnU R                  5       nU R                  5       nU R                  5       nU R                  5       nU H  nUR	                  5       [
        R                  R                  :w  d   S5       e[        UR                  5       5      nUS:X  d
   SU-  5       eUR	                  5       [
        R                  R                  :X  d  M  [        U 5      s  $    U(       d  Sn[        U R                  5       5      nUR                  U R                  5       5        [!        XEU5      u  pEU V	s/ s H  oR	                  5       ["        ;   d  M  U	PM      n
n	U V	s/ s H  oR	                  5       [$        ;   d  M  U	PM      nn	U V	s/ s H  oR	                  5       [&        ;   d  M  U	PM      nn	[        U
5      [        U5      -   [        U5      -   [        U5      :X  d   S5       eU(       aM  U(       dF  U(       d?  U(       d8  [)        S U
 5       5      nUR+                  [,        R.                  5      (       d  SnSnU(       a  U H  nUR1                  S	5      R3                  5       [,        R4                  :X  a  M6  U(       d!  UR1                  S	5      R3                  5       nM^  UR1                  S	5      R3                  5       U:X  a  M   e   [)        U R                  5       5      m[7        S
 U
 5       5      nU Vs/ s H)  n[9        UR1                  5       UR;                  5       S9PM+     nn[7        U4S jU 5       5      n[7        U4S jU 5       5      nU(       a8  U(       a  XS	   R1                  5       :X  d   eOUR=                  [9        US95        [        U5      [        U5      -   [        U5      -   [        U5      -   nU(       aO  U(       dH  US::  aB  SnU(       a9  US	   nUR2                  [,        R>                  :X  a  UR:                  [@        :X  a  SnU[C        U5      UU44nXUU4$ s  sn	f s  sn	f s  sn	f s  snf )a  Return the composite index needed for a query.

A query is translated into a tuple, as follows:

- The first item is the kind string, or None if we're not filtering
  on kind (see below).

- The second item is a bool giving whether the query specifies an
  ancestor.

- After that come (property, ASCENDING) pairs for those Filter
  entries whose operator is EQUAL or IN.  Since the order of these
  doesn't matter, they are sorted by property name to normalize them
  in order to avoid duplicates.

- After that comes at most one (property, ASCENDING) pair for a
  Filter entry whose operator is on of the four inequalities.  There
  can be at most one of these.

- After that come all the (property, direction) pairs for the Order
  entries, in the order given in the query.  Exceptions:
    (a) if there is a Filter entry with an inequality operator that matches
        the first Order entry, the first order pair is omitted (or,
        equivalently, in this case the inequality pair is omitted).
    (b) if an Order entry corresponds to an equality filter, it is ignored
        (since there will only ever be one value returned).
    (c) if there is an equality filter on __key__ all orders are dropped
        (since there will be at most one result returned).
    (d) if there is an order on __key__ all further orders are dropped (since
        keys are unique).
    (e) orders on __key__ ASCENDING are dropped (since this is supported
        natively by the datastore).

- Finally, if there are Filter entries whose operator is EXISTS, and
  whose property names are not already listed, they are added, with
  the direction set to ASCENDING.

This algorithm should consume all Filter and Order entries.

Additional notes:

- The low-level implementation allows queries that don't specify a
  kind; but the Python API doesn't support this yet.

- If there's an inequality filter and one or more sort orders, the
  first sort order *must* match the inequality filter.

- The following indexes are always built in and should be suppressed:
  - query on kind only;
  - query on kind and one filter *or* one order;
  - query on ancestor only, without kind (not exposed in Python yet);
  - query on kind and equality filters only, no order (with or without
    ancestor).

- While the protocol buffer allows a Filter to contain multiple
  properties, we don't use this.  It is only needed for the IN operator
  but this is (currently) handled on the client side, so in practice
  each Filter is expected to have exactly one property.

Args:
  query: A datastore_pb.Query instance.

Returns:
  A tuple of the form (required, kind, ancestor, properties).
    required: boolean, whether the index is required;
    kind: the kind or None;
    ancestor: True if this is an ancestor query;
    properties: A tuple consisting of:
    - the prefix, represented by a set of property names
    - the postfix, represented by a tuple consisting of any number of:
      - Sets of property names or PropertySpec objects: these
        properties can appear in any order.
      - Sequences of PropertySpec objects: Indicates the properties
        must appear in the given order, with the specified direction (if
        specified in the PropertySpec).
TzFilter.op()==INr4   z$Filter has %s properties, expected 1FzNot all filters usedc              3   ^   #    U  H#  oR                  S 5      R                  5       v   M%     g7fr   Nr   r*   rV   r   s     r   rX   )CompositeIndexForQuery.<locals>.<genexpr>  s"     9j

1""$$j   +-Nr   c              3   ^   #    U  H#  oR                  S 5      R                  5       v   M%     g7fr   r   r   s     r   rX   r     s"     >:aZZ]'')):r   r{   c              3      >#    U  HI  nUR                  S 5      R                  5       T;   d  M(  UR                  S 5      R                  5       v   MK     g7fr   r   rV   r   group_by_propss     r   rX   r     sF      J^"#**Q-"4"4"6."H  4qzz!}1133^
   'A&Ac              3      >#    U  HI  nUR                  S 5      R                  5       T;  d  M(  UR                  S 5      R                  5       v   MK     g7fr   r   r   s     r   rX   r     sF       On#$::a=#5#5#7~#M !5

1 2 2 4 4nr   r*   )"rJ   has_ancestorfilter_list
order_listr   r	   r   r   lenproperty_listCONTAINED_IN_REGIONCompositeIndexForGeoQuerylistproperty_name_listextendgroup_by_property_name_listr   r   r   r   rt   intersectionr   _SPECIAL_PROPERTIESr   r*   )_UNAPPLIED_LOG_TIMESTAMP_SPECIAL_PROPERTY	frozensetr}   r+   r|   r   r   r   )queryrequiredrJ   rK   r   r   filternpropsr   r   
eq_filtersineq_filtersexists_filtersnamesineq_propertyprefixorderpostfix_orderedpostfix_group_bypostfix_unorderedproperty_countrC   r   r   s                          @r   CompositeIndexForQueryr  5  s   Z ( 
$!('& f99;,33666I8II6%%'(FQ;G>GG;yy{l//CCC&u--  
 H((*+&--11345gvN/' #C7addf0B&B7*C$GW2F(F!W,G&Ew!$$&4D*DAw.E
j/C-
-
n
"%g,
/ G0FG 
/ <
 9j99EoAABBh -
//!

!
!
#

C
CD*//1q!&&(M999  u88:;. >:>>& % (EOO4EF  
  J^ J J    On  O O  Qi002222\}=>K#o"66=M9NN+,-.	(~2 H Qd
));;
;
..J
& 5)+;=NO
O%	5	((O DGEBs*   5P3P3 P8?P8P=*P=>0Qc                 L   SnU R                  5       nU R                  5       (       a   eSnU R                  5       n[        5       n[        5       nU H  nUR	                  S5      R                  5       nUR                  5       [        R                  R                  :X  a  UR                  [        US95        Mh  UR                  5       [        R                  R                  :X  d   eUR                  [        U[        S95        M     [        U5      n	[        U5      4n
XX9U
44$ )zBuilds a descriptor for a composite index needed for a geo query.

Args:
  query: A datastore_pb.Query instance.

Returns:
  A tuple in the same form as produced by CompositeIndexForQuery.
TFr   r   )r*   r,   )rJ   r   r   rt   r   r*   r   r	   r   r   ru   r}   r   
GEOSPATIALr  )r  r  rJ   rK   r   preintersection_props	geo_propsr  r*   r  postfixs              r   r   r     s     (	$!!!	!('%e)f??1""$Dyy{l//555$ 78 YY[L55IIIIImmLd<=  *+&y!#'	G#4	44r   c                    U u  p/ n[         R                  " U4U5       H  n[        U[        [        45      (       aK  UR                  [        U5       Vs/ s H#  n[        U[        5      (       a  UO[        US9PM%     sn5        Mi  UR                  U Vs/ s H)  oUR                  c  [        UR                  [        S9OUPM+     sn5        M     [        U5      $ s  snf s  snf )aZ  Converts the properties returned by datastore_index.CompositeIndexForQuery
into a recommended list of index properties with the desired constraints.

Sets (of property names or PropertySpec objects) are sorted, so as to
normalize them.

Args:
  properties: See datastore_index.CompositeIndexForQuery

Returns:
  A tuple of PropertySpec objects.

r   r{   )	itertoolschainr   r  rt   r   sortedr}   r+   r*   r~   r   )rL   r  r  resultsub_listps         r   GetRecommendedIndexPropertiesr!    s     /&&//6)W5h(Y,-- mm:@:JL:JQ &a66a'Q/0:JL M mm>FH>F, #)D234>FH I 6 
vLHs   *C
0C"
c                    [        U5      n[        U 5       H  n[        R                  " U[        U5      5      n[	        U[
        [        45      (       a  [        S U 5       5      nXS:w  a    gMY  [        U5      n[        U5      [        U5      :w  a    g[        U[        U5      5       H  u  pgUR                  U5      (       a  M      g   M     [        U5      nUR                  5         U$ )aL  Matches a postfix constraint with an existing index.

postfix_props constraints are specified through a list of:
- sets of string: any order any direction;
- list of tuples(string, direction): the given order, and, if specified, the
given direction.

For example (PropertySpec objects shown here in their legacy shorthand form):
  [set('A', 'B'), [('C', None), ('D', ASC)]]
matches:
  [('F', ASC), ('B', ASC), ('A', DESC), ('C', DESC), ('D', ASC)]
with a return value of [('F', ASC)], but does not match:
  [('F', ASC), ('A', DESC), ('C', DESC), ('D', ASC)]
  [('B', ASC), ('F', ASC), ('A', DESC), ('C', DESC), ('D', ASC)]
  [('F', ASC), ('B', ASC), ('A', DESC), ('C', DESC), ('D', DESC)]

Args:
  postfix_props: A tuple of sets and lists, as output by
      CompositeIndexForQuery. They should define the requirements for the
      postfix of the index.
  index_props: A list of PropertySpec objects that
      define the index to try and match.

Returns:
  The list of PropertySpec objects that define the prefix properties
  in the given index.  None if the constraints could not be
  satisfied.

c              3   8   #    U  H  oR                   v   M     g 7frN   r   )rV   rC   s     r   rX    _MatchPostfix.<locals>.<genexpr>K  s     ?.>d		.>s   N)reversedr  islicer   r   r  rt   r   zipr   reverse)	postfix_propsindex_propsindex_props_revproperty_groupindex_group_iterindex_group	candidatespec	remainings	            r   _MatchPostfixr2  &  s    @ [)/ /n ''^9LM.9c"233?.>??k		& 
'
 )*k	[	S0	0 h~.FG/)""4(( H 0  ?#)	r   c                 P   [        U 5      u  p#nu  pVU(       d  g0 nU H  nX8R                  :w  d  U(       d  UR                  (       a  M,  [        U5      u    p[	        Xj5      nUc  MJ  [        U Vs/ s H  oR                  PM     sn5      nX-
  (       a  Mz  [        U
[        U5      S 5      nUR                  U5      nUc  UR                  5       U4nUu  nnUU-  nUR                  (       a  SnU(       d	  U(       d    gUU4U:X  a  M  UU4X~'   M     U(       d  SX4XV44$ S nUR                  5       u  nnUu  nnU" UU5      nUR                  5        H"  u  nu  nnU" UU5      nUU:  d  M  UnUnUnUnM$     [        U5      U[        5       [        5       44nSUUU4$ s  snf )a2  Computes the minimal composite index for this query.

Unlike datastore_index.CompositeIndexForQuery, this function takes into
account indexes that already exist in the system.

Args:
  query: the datastore_pb.Query to compute suggestions for
  index_defs: a list of datastore_index.Index objects that already exist.

Returns:
  None if no index is needed, otherwise the minimal index in the form
(is_most_efficient, kind, ancestor, properties). Where is_most_efficient is a
boolean denoting if the suggested index is the most efficient (i.e. the one
returned by datastore_index.CompositeIndexForQuery). kind and ancestor
are the same variables returned by datastore_index.CompositeIndexForQuery.
properties is a tuple consisting of the prefix and postfix properties
returend by datastore_index.CompositeIndexForQuery.
NFTc                 4    [        U 5      nU(       a  US-  nU$ )N   )r   )minimal_propsminimal_ancestorr  s      r   	calc_cost0MinimalCompositeIndexForQuery.<locals>.calc_cost  s    FkfMr   )r  rJ   rK   rv   r2  rt   r*   r   r   getr@   popitemitemsr  )r  
index_defsr  rJ   rK   r  r  remaining_dict
definition_r*  index_prefixrC   remaining_index_propsindex_postfixr1  props_remainingancestor_remainingr8  minimal_postfixr6  r7  minimal_costcostr   s                            r   MinimalCompositeIndexForQueryrI  \  s   ( 1Gu0M-((-V	 .j*--":.Aq 6L| D|t| DE% +c,&7&89:M""=1I++-)i +4'O',,O 1+,	9 &56H$IN!O R 
$6"344  .557/9$-!-!=*:;, ;m:o'9_&89Dll%o%m+  M
"_ik9;$O
O%	&	--g !Es   1F#
c                    / nUR                  SU -  5        U(       a  UR                  S5        U(       a  UR                  S5        U Hl  nUR                  SUR                  -  5        UR                  [        :X  a  UR                  S5        UR                  [
        L d  M[  UR                  S5        Mn     SR                  U5      $ )a  Return the composite index definition YAML needed for a query.

Given a query, the arguments for this method can be computed with:
  _, kind, ancestor, props = datastore_index.CompositeIndexForQuery(query)
  props = datastore_index.GetRecommendedIndexProperties(props)

Args:
  kind: the kind or None
  ancestor: True if this is an ancestor query, False otherwise
  props: PropertySpec objects

Returns:
  A string with the YAML for the composite index needed by the query.
z
- kind: %sz  ancestor: yesz  properties:z  - name: %sz    direction: descz    mode: geospatial
)r|   r*   r+   r   r,   r  r   )rJ   rK   r   serialized_yamlrC   s        r   IndexYamlForQueryrM    s      /,-,-
?+^dii78	:	%45	j	 56  
?	##r   c                    / n[        S U 5       5      nU(       a  SnOSU(       a  SOS< S3nUR                  SU < SU< S	35        U Hb  nUR                  [        L a  S
nO%U(       a  SnOSUR                  [
        :X  a  SOS-  nUR                  SUR                  < SU< S35        Md     UR                  S5        SR                  U5      $ )a  Return the composite index definition XML needed for a query.

Given a query, the arguments for this method can be computed with:
  _, kind, ancestor, props = datastore_index.CompositeIndexForQuery(query)
  props = datastore_index.GetRecommendedIndexProperties(props)

Args:
  kind: the kind or None
  ancestor: True if this is an ancestor query, False otherwise
  props: PropertySpec objects

Returns:
  A string with the XML for the composite index needed by the query.
c              3   D   #    U  H  oR                   [        L v   M     g 7frN   )r,   r  )rV   r   s     r   rX   #IndexXmlForQuery.<locals>.<genexpr>  s     3Uvv#Us     z
ancestor="truefalse"z  <datastore-index kind="z" >z mode="geospatial"z direction="%s"r'   r%   z    <property name="z />z  </datastore-index>rK  )r[   r|   r,   r  r+   r   r*   r   )rJ   rK   r   serialized_xmlr\   ancestor_clauserC   quals           r   IndexXmlForQueryrY    s      . 3U33&O  4<)HJO2 3dyyJ!d	d DNNj,H&',.dDIItLM  ./	>	""r   c                 |   [         R                  " 5       nUR                  U 5        UR                  S5        UR	                  [         R                  R
                  5        UR                  5       nUR                  UR                  5        UR                  UR                  5        UR                  Gb  [        S UR                   5       5      nUR                   H  nUR                  5       nUR                  UR                  5        UR                   S:X  a+  UR#                  [         R$                  R&                  5        Mi  U(       a  Mr  UR)                  5       (       a+  UR+                  [         R$                  R,                  5        M  UR+                  [         R$                  R.                  5        M     U$ )a%  Transform individual Index definition to protocol buffer.

Args:
  app_id: Application id for new protocol buffer CompositeIndex.
  index_definition: datastore_index.Index object to transform.

Returns:
  New entity_pb.CompositeIndex with default values set and index
  information filled in.
r   c              3   >   #    U  H  oR                   S :H  v   M     g7frS   rT   rU   s     r   rX   )IndexDefinitionToProto.<locals>.<genexpr>  s     M1LA<'1LrZ   r)   )r
   CompositeIndex
set_app_idset_id	set_state
WRITE_ONLYmutable_definitionset_entity_typerJ   set_ancestorrK   rL   r[   r   r   r*   r,   r   r   r  r1   r   r~   r   )app_idindex_definitionprotodefinition_protor\   rC   
prop_protos          r   IndexDefinitionToProtorj    sG    
"
"
$%6,,q///)**556--/""#3#8#89 0 9 9:  ,M1A1L1LMMF ++#002j$))$	l	"I44??@
 	  !9!9!C!CD  !9!9!D!DE ," 
,r   c                 D    U Vs/ s H  n[        X5      PM     sn$ s  snf )aP  Transform multiple index definitions to composite index records

Args:
  app_id: Application id for new protocol buffer CompositeIndex.
  index_definition: A list of datastore_index.Index objects to transform.

Returns:
  A list of tranformed entity_pb.Compositeindex entities with default values
  set and index information filled in.
)rj  )re  index_definitionsrx   s      r   IndexDefinitionsToProtosrm  2  s.     )
*(e !
/(
* * 
*   c                 F   / nU R                  5       nUR                  5        H  n[        UR                  5       S9nUR	                  5       [
        R                  R                  :X  a  SUl        OgUR                  5       [
        R                  R                  :X  a  SUl        O3UR                  5       [
        R                  R                  :X  a  SUl        UR                  U5        M     [        UR                  5       US9nUR                  5       (       a  SUl        U$ )zTransform individual index protocol buffer to index definition.

Args:
  proto: An instance of entity_pb.CompositeIndex to transform.

Returns:
  A new instance of datastore_index.Index.
r   r)   r'   r%   )rJ   rL   T)r?  r   r#   r*   r,   r
   r   r  r+   r   r~   r|   rG   entity_typerK   )rg  rL   proto_indexri  prop_definitionrx   s         r   ProtoToIndexDefinitionrs  A  s     *  "+--/jJOO$56OI44???)o				9#;#;#F#F	F"(o				9#;#;#E#E	E"'oo& 0 [,,.:
F%EN	,r   c                 D    U  Vs/ s H  n[        U5      PM     sn$ s  snf )zlTransform multiple index protocol buffers to index definitions.

Args:
  A list of entity_pb.Index records.
)rs  )protosr?  s     r   ProtosToIndexDefinitionsrv  ^  s$     @F	Fv
 
,v	FF	Frn  rN   )?r   
__future__r   r@   r  googlecloudsdk.appengine.apir   r   r   r   r   "googlecloudsdk.appengine.datastorer	   2googlecloudsdk.appengine.googlestorage.onestore.v3r
   ruamelr   	Validatedr   r   r#   rE   rG   rc   YAML
index_yamlrepresenteradd_representerro   rr   ry   rv   objectr}   r   r  r~   r   Query_Orderrt   r   r   r   	LESS_THANLESS_THAN_OR_EQUALGREATER_THANGREATER_THAN_OR_EQUALr   r   r   r   r   r  r   r!  r2  rI  rM  rY  rj  rm  rs  rv  r   r   r   <module>r     s4  "T '   0 8 3 4 4 ; H j** :'' --z## --`,<*!J   *!Z
z++ 
 YY8$
 
   & &x1B C*	>,20a6 aJ %%00
$$..	%%00
 ))\-E-E-O-OO OO  ++  ++	, - 	, ,3399:; L55??(55HH(55BB(55KKM N  11889: Qh.bp)f5>>3l].H$>%#P(V*:Gr   