From 816e6b3e5f3e097fe54ed4288dd677ac54070e6e Mon Sep 17 00:00:00 2001 From: Massimo Di Pierro Date: Sun, 10 Jun 2012 00:32:14 -0500 Subject: [PATCH] GAE datastore projection support, thanks Christian --- VERSION | 2 +- gluon/dal.py | 30 ++++++++++++++++++++++-------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/VERSION b/VERSION index fadc3591..9cbdcbf7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-06-09 11:51:26) dev +Version 2.00.0 (2012-06-10 00:32:10) dev diff --git a/gluon/dal.py b/gluon/dal.py index 14eb400c..e9dacc02 100644 --- a/gluon/dal.py +++ b/gluon/dal.py @@ -4080,10 +4080,21 @@ class GoogleDatastoreAdapter(NoSQLAdapter): if use_common_filters(query): query = self.common_filter(query,[tablename]) + if len(self.db[tablename].fields) == len(fields): + #getting all fields, not a projection query + projection = None + else: + projection = [f.name for f in fields] + + #tableobj is a GAE Model class (or subclass) tableobj = self.db[tablename]._tableobj - items = tableobj.all() filters = self.expand(query) - projection = [field.name for field in fields] + + #projection's can't include 'id'. it will be added to the result later + query_projection = [p for p in projection if p != 'id'] if projection \ + else None + items = gae.Query(tableobj, projection=query_projection) + for filter in filters: if filter.name=='__key__' and filter.op=='>' and filter.value==0: continue @@ -4091,10 +4102,14 @@ class GoogleDatastoreAdapter(NoSQLAdapter): if filter.value==0: items = [] elif isinstance(filter.value, Key): - item = tableobj.get(filter.value,projection=projection) + #key qeuries return a class instance, can't use projection + # extra values will be ignored in post-processing later + item = tableobj.get(filter.value) items = (item and [item]) or [] else: - item = tableobj.get_by_id(filter.value) ## FIX projection? + #key qeuries return a class instance, can't use projection + # extra values will be ignored in post-processing later + item = tableobj.get_by_id(filter.value) items = (item and [item]) or [] elif isinstance(items,list): # i.e. there is a single record! items = [i for i in items if filter.apply( @@ -4103,7 +4118,7 @@ class GoogleDatastoreAdapter(NoSQLAdapter): if filter.name=='__key__': items.order('__key__') items = items.filter('%s %s' % (filter.name,filter.op), - filter.value,projection=projection) + filter.value) if not isinstance(items,list): if attributes.get('left', None): raise SyntaxError, 'Set: no left join in appengine' @@ -4123,8 +4138,8 @@ class GoogleDatastoreAdapter(NoSQLAdapter): if attributes.get('limitby', None): (lmin, lmax) = attributes['limitby'] (limit, offset) = (lmax - lmin, lmin) - items = items.fetch(limit,offset=offset,projection=projection) - return (items, tablename, projection) + items = items.fetch(limit,offset=offset) + return (items, tablename, projection or self.db[tablename].fields) def select(self,query,fields,attributes): (items, tablename, fields) = self.select_raw(query,fields,attributes) @@ -4136,7 +4151,6 @@ class GoogleDatastoreAdapter(NoSQLAdapter): processor = attributes.get('processor',self.parse) return processor(rows,fields,colnames,False) - def count(self,query,distinct=None): if distinct: raise RuntimeError, "COUNT DISTINCT not supported"