async def fetch_many(cls, query=None, filter_by=None): from asyncpgsa import pg columns = [*cls.c, *cls.to_many_selectables] filter_expressions = [] result = [] if filter_by is not None: for column_name, filter_rule in filter_by.items(): try: column = getattr(cls.c, column_name) except AttributeError: raise ValueError(f'Table `{cls.table.name}` does not ' f'contain column `{column_name}`') filter_expressions.append((column == filter_rule)) if query is None: query = cls.query() if filter_expressions: query = query.where(sa.and_(*filter_expressions)) if len(cls._to_many_relations): query = query.group_by(cls.pk_column) query = query.with_only_columns(columns) async with pg.query(query) as cursor: async for row in cursor: resource = cls.from_row(row, columns=columns) result.append(resource) return result
async def test_pg_queury_with_await(): ps = pg.query(query) results = await ps row = sentinel = object() for row in results: assert row['a'] == 4.0 assert row['b'] == 6.0 assert row['c'] == 5.0 if row is sentinel: pytest.fail('No results')
async def test_pg_query_async_with_statement(): ps = pg.query(query) async with ps as cursor: row = sentinel = object() async for row in cursor: assert row['a'] == 4.0 assert row['b'] == 6.0 assert row['c'] == 5.0 if row is sentinel: pytest.fail('Cursor had no data')
async def test_pg_query_async_with_statement(): await _init() ps = pg.query(query) async with ps as cursor: async for row in cursor: assert row.a == 4.0 assert row.b == 6.0 assert row.c == 5.0 result = 2 assert result == 2
async def test_pg_query_with_bad_with_statement(): ps = pg.query(query) with pytest.raises(RuntimeError) as exc_info: with ps as cursor: async for row in cursor: assert row['a'] == 4.0 assert row['b'] == 6.0 assert row['c'] == 5.0 result = 2 assert result == 2 assert str(exc_info.value) == 'Must use "async with"'
async def test_pg_query_with_bad_with_statement(): await _init() ps = pg.query(query) try: with ps as cursor: async for row in cursor: assert row.a == 4.0 assert row.b == 6.0 assert row.c == 5.0 result = 2 assert result == 2 # try: # event_loop.run_until_complete(async_with()) raise Exception('Should have thrown exception') except SyntaxError as e: assert str(e) == 'Must use "async with"'
async def test_pg_query_with_no_results(): ps = pg.query("SELECT * FROM pg_tables WHERE tablename='bob'") async with ps as cursor: async for row in cursor: raise Exception('Should not have hit this line')
async def get_collection(args, *models, **kwargs): """ Fetch a heterogeneous collection of objects. Returns a heterogeneous list of objects. >>> from jsonapi.model import search >>> search({'include[user]': 'bio', >>> 'include[article]': 'keywords,author.bio,publisher.bio', >>> 'fields[user]': 'name,email', >>> 'fields[user-bio]': 'birthday,age', >>> 'fields[article]': 'title'}, >>> 'John', UserModel, ArticleModel) :param dict args: a dictionary representing the request query string :param mixed models: variable length list of model classes or instances :param str search: a PostgreSQL full text search query string (e.x. ``'foo:* & !bar'``) :return: JSON API response document """ ra = parse_arguments(args) search_term = kwargs.pop('search', None) or args.pop('search', None) models = ModelSet(*models, searchable=search_term is not None) query = select_mixed(models, order_by=ra.sort, limit=ra.page.limit, offset=ra.page.offset) \ if search_term is None else search_query(models, search_term, limit=ra.page.limit, offset=ra.page.offset) log_query(query) mixed = list() async with pg.query(query) as cursor: async for row in cursor: mixed.append(dict(type=row['resource_type'], id=row['id'])) data = defaultdict(dict) included = defaultdict(dict) meta = {'total': 0, 'subTotal': dict()} for model in models: object_id = list(obj['id'] for obj in mixed if model.type_ == obj['type']) if len(object_id) > 0: model_args = model.parse_arguments(_extract_model_args( model, args)) model.init_schema(model_args) query = select_many(model, filter_by=FilterBy( model.primary_key.in_([ cast(x, model.primary_key.type) for x in object_id ]))) log_query(query) recs = [{ 'type': model.type_, **rec } for rec in await pg.fetch(query)] await model.fetch_included(recs, model_args) for rec in model.schema.dump(recs, many=True): data[rec['type']][rec['id']] = rec if len(model.included) > 0: for resource_type in model.included.keys(): included[resource_type].update( model.included[resource_type]) model.reset() for (resource_type, query) in (select_mixed(models, count=True) \ if search_term is None else search_query(models, search_term, count=True)): meta['subTotal'][resource_type] = await pg.fetchval(query) meta['total'] += meta['subTotal'][resource_type] return dict(data=[data[rec['type']][str(rec['id'])] for rec in mixed], included=reduce(lambda a, b: a + [r for r in b.values()], included.values(), list()), meta=meta)