def parse_gql(query_string): """Parse a GQL query string. Args: query_string: Full GQL query, e.g. 'SELECT * FROM Kind WHERE prop = 1'. Returns: A tuple (query, options, bindings) where query is a Query instance, options a datastore_query.QueryOptions instance, and bindings a dict mapping integers and strings to Binding instances. """ gql_qry = gql.GQL(query_string) ancestor = None flt = gql_qry.filters() bindings = {} filters = [] for ((name, op), values) in flt.iteritems(): op = op.lower() if op == 'is' and name == gql.GQL._GQL__ANCESTOR: assert len(values) == 1 [(func, args)] = values ancestor = _args_to_val(func, args, bindings) continue assert op in _OPS.values() for (func, args) in values: val = _args_to_val(func, args, bindings) filters.append(FilterNode(name, op, val)) if filters: filters.sort() # For predictable tests. filters = ConjunctionNode(filters) else: filters = None orderings = gql_qry.orderings() orders = [] for (name, direction) in orderings: orders.append(datastore_query.PropertyOrder(name, direction)) if not orders: orders = None elif len(orders) == 1: orders = orders[0] else: orders = datastore_query.CompositeOrder(orders) qry = Query(kind=gql_qry._entity, ancestor=ancestor, filters=filters, orders=orders) offset = gql_qry.offset() if offset < 0: offset = None limit = gql_qry.limit() if limit < 0: limit = None options = QueryOptions(offset=offset, limit=limit) return qry, options, bindings
def __init__(self, query_string, model_class, *args, **kwds): """Constructor. Args: query_string: Properly formatted GQL query string. model_class: Model class from which entities are constructed. *args: Positional arguments used to bind numeric references in the query. **kwds: Dictionary-based arguments for named references. """ from google.appengine.ext import gql app = kwds.pop('_app', None) self._proto_query = gql.GQL(query_string, _app=app) super(db.GqlQuery, self).__init__(model_class) self.bind(*args, **kwds)
def get(self, project_id): """ Displays a list of entities for a given kind. Args: project_id: A string specifying the project ID. """ self.ensure_user_has_admin(project_id) ds_access = DatastoreDistributed(project_id, DATASTORE_LOCATION, trusted=True) kind = self.request.get('kind', None) namespace = self.request.get('namespace', '') order = self.request.get('order', None) message = self.request.get('message', None) gql_string = self.request.get('gql', None) try: page = int(self.request.get('page', '1')) except ValueError: page = 1 kinds = self._get_kinds(ds_access, namespace) if gql_string is not None: start = (page - 1) * self.NUM_ENTITIES_PER_PAGE total_entities = 0 entities = [] try: gql_query = gql.GQL(gql_string, _app=project_id, namespace=namespace) kind = gql_query.kind() query = gql_query.Bind([], {}) total_entities = query.Count() entities = list( query.Run(limit=self.NUM_ENTITIES_PER_PAGE, offset=start)) except datastore.datastore_errors.NeedIndexError as error: message = ('Error during GQL query: <pre>{}</pre> Note: Queries ' 'requiring a composite index are not yet supported by the ' 'AppScale datastore viewer.'.format(error)) except datastore.datastore_errors.Error as error: message = 'Error during GQL query: <pre>{}</pre>'.format(error) headers, template_entities, total_entities = ( self._format_entity_template_data(ds_access, self.request.uri, entities, total_entities)) num_pages = int(math.ceil(float(total_entities) / self.NUM_ENTITIES_PER_PAGE)) else: if not kind and kinds: self.redirect(self._construct_url(add={'kind': kinds[0]})) return if kind: start = (page-1) * self.NUM_ENTITIES_PER_PAGE entities, total_entities = _get_entities( ds_access, kind, namespace, order, start, self.NUM_ENTITIES_PER_PAGE) headers, template_entities, total_entities = ( self._format_entity_template_data(ds_access, self.request.uri, entities, total_entities)) num_pages = int(math.ceil(float(total_entities) / self.NUM_ENTITIES_PER_PAGE)) else: start = 0 headers = [] template_entities = [] total_entities = 0 num_pages = 0 select_namespace_url = self._construct_url( remove=['message'], add={'namespace': self.request.get('namespace')}) context = { 'entities': template_entities, 'gql_string': gql_string, 'headers': headers, 'kind': kind, 'kinds': kinds, 'message': message, 'namespace': namespace, 'num_pages': num_pages, 'order': order, 'order_base_url': self._construct_url(remove=['message', 'order']), 'page': page, 'page_content': self.TEMPLATE, 'paging_base_url': self._construct_url(remove=['message', 'page']), 'project_id': project_id, 'request': self.request, 'select_namespace_url': select_namespace_url, 'show_namespace': self.request.get('namespace', None) is not None, 'start': start, 'total_entities': total_entities } self.render_app_page(page='datastore_viewer', values=context)