thirdparty/google_appengine/google/appengine/api/datastore_admin.py
changeset 109 620f9b141567
child 149 f2e327a7c5de
equal deleted inserted replaced
108:261778de26ff 109:620f9b141567
       
     1 #!/usr/bin/env python
       
     2 #
       
     3 # Copyright 2007 Google Inc.
       
     4 #
       
     5 # Licensed under the Apache License, Version 2.0 (the "License");
       
     6 # you may not use this file except in compliance with the License.
       
     7 # You may obtain a copy of the License at
       
     8 #
       
     9 #     http://www.apache.org/licenses/LICENSE-2.0
       
    10 #
       
    11 # Unless required by applicable law or agreed to in writing, software
       
    12 # distributed under the License is distributed on an "AS IS" BASIS,
       
    13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    14 # See the License for the specific language governing permissions and
       
    15 # limitations under the License.
       
    16 #
       
    17 
       
    18 """The Python datastore admin API for managing indices and schemas.
       
    19 """
       
    20 
       
    21 
       
    22 
       
    23 from google.appengine.api import api_base_pb
       
    24 from google.appengine.api import apiproxy_stub_map
       
    25 from google.appengine.api import datastore
       
    26 from google.appengine.api import datastore_errors
       
    27 from google.appengine.api import datastore_types
       
    28 from google.appengine.datastore import datastore_index
       
    29 from google.appengine.datastore import datastore_pb
       
    30 from google.appengine.runtime import apiproxy_errors
       
    31 from google.appengine.datastore import entity_pb
       
    32 
       
    33 _LOCAL_APP_ID = datastore_types._LOCAL_APP_ID
       
    34 
       
    35 
       
    36 _DIRECTION_MAP = {
       
    37     'asc':        entity_pb.Index_Property.ASCENDING,
       
    38     'ascending':  entity_pb.Index_Property.ASCENDING,
       
    39     'desc':       entity_pb.Index_Property.DESCENDING,
       
    40     'descending': entity_pb.Index_Property.DESCENDING,
       
    41     }
       
    42 
       
    43 
       
    44 def GetSchema(_app=_LOCAL_APP_ID):
       
    45   """Infers an app's schema from the entities in the datastore.
       
    46 
       
    47   Note that the PropertyValue PBs in the returned EntityProtos are empty
       
    48   placeholders, so they may cause problems if you try to convert them to
       
    49   python values with e.g. datastore_types. In particular, user values will
       
    50   throw UserNotFoundError because their email and auth domain fields will be
       
    51   empty.
       
    52 
       
    53   Returns:
       
    54     list of entity_pb.EntityProto, with kind and property names and types
       
    55   """
       
    56   req = api_base_pb.StringProto()
       
    57   req.set_value(_app)
       
    58   resp = datastore_pb.Schema()
       
    59 
       
    60   _Call('GetSchema', req, resp)
       
    61   return resp.kind_list()
       
    62 
       
    63 
       
    64 def GetIndices(_app=_LOCAL_APP_ID):
       
    65   """Fetches all composite indices in the datastore for this app.
       
    66 
       
    67   Returns:
       
    68     list of entity_pb.CompositeIndex
       
    69   """
       
    70   req = api_base_pb.StringProto()
       
    71   req.set_value(_app)
       
    72   resp = datastore_pb.CompositeIndices()
       
    73   try:
       
    74     apiproxy_stub_map.MakeSyncCall('datastore_v3', 'GetIndices', req, resp)
       
    75   except apiproxy_errors.ApplicationError, err:
       
    76     raise datastore._ToDatastoreError(err)
       
    77 
       
    78   return resp.index_list()
       
    79 
       
    80 
       
    81 def CreateIndex(index):
       
    82   """Creates a new composite index in the datastore for this app.
       
    83 
       
    84   Args:
       
    85     index: entity_pb.CompositeIndex
       
    86 
       
    87   Returns:
       
    88     int, the id allocated to the index
       
    89   """
       
    90   resp = api_base_pb.Integer64Proto()
       
    91   _Call('CreateIndex', index, resp)
       
    92   return resp.value()
       
    93 
       
    94 
       
    95 def UpdateIndex(index):
       
    96   """Updates an index's status. The entire index definition must be present.
       
    97 
       
    98   Args:
       
    99     index: entity_pb.CompositeIndex
       
   100   """
       
   101   _Call('UpdateIndex', index, api_base_pb.VoidProto())
       
   102 
       
   103 
       
   104 def DeleteIndex(index):
       
   105   """Deletes an index. The entire index definition must be present.
       
   106 
       
   107   Args:
       
   108     index: entity_pb.CompositeIndex
       
   109   """
       
   110   _Call('DeleteIndex', index, api_base_pb.VoidProto())
       
   111 
       
   112 
       
   113 def _Call(call, req, resp):
       
   114   """Generic method for making a datastore API call.
       
   115 
       
   116   Args:
       
   117     call: string, the name of the RPC call
       
   118     req: the request PB. if the app_id field is not set, it defaults to the
       
   119       local app.
       
   120     resp: the response PB
       
   121   """
       
   122   if hasattr(req, 'app_id') and not req.app_id():
       
   123     req.set_app_id(_LOCAL_APP_ID)
       
   124 
       
   125   try:
       
   126     apiproxy_stub_map.MakeSyncCall('datastore_v3', call, req, resp)
       
   127   except apiproxy_errors.ApplicationError, err:
       
   128     raise datastore._ToDatastoreError(err)
       
   129 
       
   130 
       
   131 def IndexDefinitionToProto(app_id, index_definition):
       
   132   """Transform individual Index definition to protocol buffer.
       
   133 
       
   134   Args:
       
   135     app_id: Application id for new protocol buffer CompositeIndex.
       
   136     index_definition: datastore_index.Index object to transform.
       
   137 
       
   138   Returns:
       
   139     New entity_pb.CompositeIndex with default values set and index
       
   140     information filled in.
       
   141   """
       
   142   proto = entity_pb.CompositeIndex()
       
   143 
       
   144   proto.set_app_id(app_id)
       
   145   proto.set_id(0)
       
   146   proto.set_state(entity_pb.CompositeIndex.WRITE_ONLY)
       
   147 
       
   148   definition_proto = proto.mutable_definition()
       
   149   definition_proto.set_entity_type(index_definition.kind)
       
   150   definition_proto.set_ancestor(index_definition.ancestor)
       
   151 
       
   152   if index_definition.properties is not None:
       
   153     for prop in index_definition.properties:
       
   154       prop_proto = definition_proto.add_property()
       
   155       prop_proto.set_name(prop.name)
       
   156       prop_proto.set_direction(_DIRECTION_MAP[prop.direction])
       
   157 
       
   158   return proto
       
   159 
       
   160 
       
   161 def IndexDefinitionsToProtos(app_id, index_definitions):
       
   162   """Transform multiple index definitions to composite index records
       
   163 
       
   164   Args:
       
   165     app_id: Application id for new protocol buffer CompositeIndex.
       
   166     index_definition: A list of datastore_index.Index objects to transform.
       
   167 
       
   168   Returns:
       
   169     A list of tranformed entity_pb.Compositeindex entities with default values
       
   170     set and index information filled in.
       
   171   """
       
   172   return [IndexDefinitionToProto(app_id, index)
       
   173           for index in index_definitions]
       
   174 
       
   175 
       
   176 def ProtoToIndexDefinition(proto):
       
   177   """Transform individual index protocol buffer to index definition.
       
   178 
       
   179   Args:
       
   180     proto: An instance of entity_pb.CompositeIndex to transform.
       
   181 
       
   182   Returns:
       
   183     A new instance of datastore_index.Index.
       
   184   """
       
   185   properties = []
       
   186   proto_index = proto.definition()
       
   187   for prop_proto in proto_index.property_list():
       
   188     prop_definition = datastore_index.Property(name=prop_proto.name())
       
   189     if prop_proto.direction() == entity_pb.Index_Property.DESCENDING:
       
   190       prop_definition.direction = 'descending'
       
   191     properties.append(prop_definition)
       
   192 
       
   193   index = datastore_index.Index(kind=proto_index.entity_type(),
       
   194                                 properties=properties)
       
   195   if proto_index.ancestor():
       
   196     index.ancestor = True
       
   197   return index
       
   198 
       
   199 def ProtosToIndexDefinitions(protos):
       
   200   """Transform multiple index protocol buffers to index definitions.
       
   201 
       
   202   Args:
       
   203     A list of entity_pb.Index records.
       
   204   """
       
   205   return [ProtoToIndexDefinition(definition) for definition in protos]