Beispiel #1
0
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
Beispiel #2
0
  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)
Beispiel #3
0
  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)