def _ProjectionPartialEntityGenerator(cursor): """Generator that creates partial entities for projection. Generate partial datastore entities from a cursor, holding only the values being projected. These entities might share a key. Args: cursor: a SQLite3.Cursor or subclass. Yields: Partial entities resulting from the projection. """ for row in cursor: entity_original = entity_pb.EntityProto(row[1]) entity = entity_pb.EntityProto() entity.mutable_key().MergeFrom(entity_original.key()) entity.mutable_entity_group().MergeFrom(entity_original.entity_group()) for name, value_data in zip(row[2::2], row[3::2]): prop_to_add = entity.add_property() prop_to_add.set_name(ToUtf8(name)) value_decoder = sortable_pb_encoder.Decoder( array.array('B', str(value_data))) prop_to_add.mutable_value().Merge(value_decoder) prop_to_add.set_multiple(False) datastore_stub_util.PrepareSpecialPropertiesForLoad(entity) yield entity
def Query(self, query, filters, orders): """Perform a query on this pseudo-kind. Args: query: the original datastore_pb.Query filters: the filters from query orders: the orders from query Returns: A query cursor to iterate over the query results, or None if the query is invalid. """ property_range = datastore_stub_util.ParsePropertyQuery( query, filters, orders) keys_only = query.keys_only() conn = self._stub._GetConnection() cursor = None try: prefix = self._stub._GetTablePrefix(query) filters = [] def AddExtremeFilter(extreme, inclusive, is_end): """Add filter for kind start/end.""" if not is_end: op = datastore_pb.Query_Filter.GREATER_THAN_OR_EQUAL else: op = datastore_pb.Query_Filter.LESS_THAN_OR_EQUAL filters.append(('kind', op, extreme[0])) property_range.MapExtremes(AddExtremeFilter) for name in datastore_stub_util.GetInvisibleSpecialPropertyNames(): filters.append(('name', '!=', name)) params = [] sql_filters = self._stub._CreateFilterString(filters, params) if not keys_only: sql_stmt = ( 'SELECT kind, name, value FROM "%s!EntitiesByProperty" %s ' 'GROUP BY kind, name, substr(value, 1, 1) ' 'ORDER BY kind, name' % (prefix, sql_filters)) else: sql_stmt = ( 'SELECT kind, name FROM "%s!EntitiesByProperty" %s ' 'GROUP BY kind, name ORDER BY kind, name' % (prefix, sql_filters)) c = conn.execute(sql_stmt, params) properties = [] kind = None name = None property_pb = None for row in c.fetchall(): if not (row[0] == kind and row[1] == name): if not property_range.Contains((row[0], row[1])): continue kind, name = row[:2] if property_pb: properties.append(property_pb) property_pb = MakeEntityForQuery(query, KindPseudoKind.name, ToUtf8(kind), self.name, ToUtf8(name)) if not keys_only: value_data = row[2] value_decoder = sortable_pb_encoder.Decoder( array.array('B', str(value_data))) raw_value_pb = entity_pb.PropertyValue() raw_value_pb.Merge(value_decoder) tag = datastore_types.GetPropertyValueTag(raw_value_pb) tag_name = datastore_stub_util._PROPERTY_TYPE_NAMES[tag] representation_pb = property_pb.add_property() representation_pb.set_name('property_representation') representation_pb.set_multiple(True) representation_pb.mutable_value().set_stringvalue(tag_name) if property_pb: properties.append(property_pb) cursor = datastore_stub_util._ExecuteQuery(properties, query, [], [], []) finally: self._stub._ReleaseConnection(conn) return cursor