Source code for sgcache.api3.read

import time
import cProfile as profile

import sqlalchemy as sa

from ..exceptions import EntityMissing, FieldMissing, NoFieldData
from ..path import FieldPath
from ..select import SelectBuilder

[docs]class Api3ReadOperation(object): """Operation to process an API3-style "read" request. :param dict request: The request itself with: - ``type`` - ``filters`` - ``return_fields`` - ``paging.entities_per_page`` - ``paging.current_page`` - ``sorts`` - ``return_only`` """ def __init__(self, request): self.request = request self.entity_type_name = request['type'] self.filters = request['filters'] self.return_fields = request['return_fields'] self.limit = request['paging']['entities_per_page'] self.offset = self.limit * (request['paging']['current_page'] - 1) self.sorts = request.get('sorts', []) self.return_active = request.get('return_only') != 'retired' self._start_time = self._last_time = time.time() def _debug_time(self, msg): now = time.time() print '%3dms (+%6dus): %s' % ( 1000 * (now - self._start_time), 1000000 * (now - self._last_time), msg ) self._last_time = now
[docs] def run(self, cache): """Run the operation. :param cache: The :class:`.Cache`. :returns: API3 compatible results. """ selector = SelectBuilder(cache, self.entity_type_name) selector.return_active = self.return_active selector.add_return_field('id') for field in self.return_fields: selector.add_return_field(field) selector.add_api3_filters(self.filters) selector.add_api3_sorts(self.sorts) query = selector.finalize() # print '========' # print str(query) # print '--------' if self.offset: query = query.offset(self.offset) if self.limit: query = query.limit(self.limit) #self._debug_time('prepared query') if False: try: sql = str(query.compile(cache.db, compile_kwargs={"literal_binds": True})) explain_res = cache.db.execute('EXPLAIN ANALYZE ' + sql) print sql print for row in explain_res: print row[0] print '=========' except Exception as e: print 'EXPLAIN FAILED:', e db_res = cache.db.execute(query) entity_iter = selector.extract(db_res) #self._debug_time('executed query') if False: profiler = profile.Profile() entities = profiler.runcall(list, entity_iter) profiler.print_stats() else: entities = list(entity_iter) #self._debug_time('extracted results') # paging_info.entity_count represents the total entities that would # be returned if there was no paging applied. Since the shotgun_api3 # does not care about the specific value, only if it signals that there # *might* be more data to grab, we fake it for now. entity_count = self.offset + len(entities) if len(entities) == self.limit: # fake that there is more than one full page left. entity_count += self.limit + 1 return { 'entities': entities, 'paging_info': { 'entity_count': entity_count, }, }