def test__build_protobuf_all_values(self): from google.cloud.datastore._generated import query_pb2 from google.cloud.datastore.query import Query client = _Client(None, None) query = Query(client) limit = 15 offset = 9 start_bytes = b'i\xb7\x1d' start_cursor = 'abcd' end_bytes = b'\xc3\x1c\xb3' end_cursor = 'wxyz' iterator = self._make_one(query, client, limit=limit, offset=offset, start_cursor=start_cursor, end_cursor=end_cursor) self.assertEqual(iterator.max_results, limit) iterator.num_results = 4 iterator._skipped_results = 1 pb = iterator._build_protobuf() expected_pb = query_pb2.Query( start_cursor=start_bytes, end_cursor=end_bytes, offset=offset - iterator._skipped_results, ) expected_pb.limit.value = limit - iterator.num_results self.assertEqual(pb, expected_pb)
def test__next_page(self): from google.cloud.iterator import Page from google.cloud.datastore._generated import query_pb2 from google.cloud.datastore.query import Query connection = _Connection() more_enum = query_pb2.QueryResultBatch.NOT_FINISHED result = ([], b'', more_enum, 0) connection._results = [result] project = 'prujekt' client = _Client(project, connection) query = Query(client) iterator = self._make_one(query, client) page = iterator._next_page() self.assertIsInstance(page, Page) self.assertIs(page._parent, iterator) self.assertEqual(connection._called_with, [{ 'query_pb': query_pb2.Query(), 'project': project, 'namespace': None, 'transaction_id': None, }])
def test__build_protobuf_empty(self): from google.cloud.datastore._generated import query_pb2 from google.cloud.datastore.query import Query client = _Client(None, None) query = Query(client) iterator = self._make_one(query, client) pb = iterator._build_protobuf() expected_pb = query_pb2.Query() self.assertEqual(pb, expected_pb)
def _pb_from_query(query): """Convert a Query instance to the corresponding protobuf. :type query: :class:`Query` :param query: The source query. :rtype: :class:`google.cloud.datastore._generated.query_pb2.Query` :returns: A protobuf that can be sent to the protobuf API. N.b. that it does not contain "in-flight" fields for ongoing query executions (cursors, offset, limit). """ pb = _query_pb2.Query() for projection_name in query.projection: pb.projection.add().property.name = projection_name if query.kind: pb.kind.add().name = query.kind composite_filter = pb.filter.composite_filter composite_filter.op = _query_pb2.CompositeFilter.AND if query.ancestor: ancestor_pb = query.ancestor.to_protobuf() # Filter on __key__ HAS_ANCESTOR == ancestor. ancestor_filter = composite_filter.filters.add().property_filter ancestor_filter.property.name = '__key__' ancestor_filter.op = _query_pb2.PropertyFilter.HAS_ANCESTOR ancestor_filter.value.key_value.CopyFrom(ancestor_pb) for property_name, operator, value in query.filters: pb_op_enum = query.OPERATORS.get(operator) # Add the specific filter property_filter = composite_filter.filters.add().property_filter property_filter.property.name = property_name property_filter.op = pb_op_enum # Set the value to filter on based on the type. if property_name == '__key__': key_pb = value.to_protobuf() property_filter.value.key_value.CopyFrom(key_pb) else: helpers._set_protobuf_value(property_filter.value, value) if not composite_filter.filters: pb.ClearField('filter') for prop in query.order: property_order = pb.order.add() if prop.startswith('-'): property_order.property.name = prop[1:] property_order.direction = property_order.DESCENDING else: property_order.property.name = prop property_order.direction = property_order.ASCENDING for distinct_on_name in query.distinct_on: pb.distinct_on.add().name = distinct_on_name return pb
def _make_query_pb(self, kind): from google.cloud.datastore._generated import query_pb2 pb = query_pb2.Query() pb.kind.add().name = kind return pb