# Buggy code
async def _prefetch_m2m_relation(
    self, instance_list: list, field: str, related_query
) -> list:
    instance_id_set = {instance.pk for instance in instance_list}  # type: Set[Any]

    field_object = self.model._meta.fields_map[field]

    through_table = Table(field_object.through)

    subquery = (
        self.db.query_class.from_(through_table)
        .select(
            getattr(through_table, field_object.backward_key).as_(
                "_backward_relation_key"
            ),
            getattr(through_table, field_object.forward_key).as_(
                "_forward_relation_key"
            ),
        )
        .where(getattr(through_table, field_object.backward_key).isin(instance_id_set))
    )

    related_query_table = Table(related_query.model._meta.table)
    related_pk_field = related_query.model._meta.db_pk_field
    query = (
        related_query.query.join(subquery)
        .on(
            subquery._forward_relation_key
            == getattr(related_query_table, related_pk_field)
        )
        .select(
            subquery._backward_relation_key.as_("_backward_relation_key"),
            *[
                getattr(related_query_table, field).as_(field)
                for field in related_query.fields
            ],
        )
    )

    if related_query._q_objects:
        joined_tables = []  # type: List[Table]
        modifier = QueryModifier()
        for node in related_query._q_objects:
            modifier &= node.resolve(
                model=related_query.model,
                annotations=related_query._annotations,
                custom_filters=related_query._custom_filters,
            )

        where_criterion, joins, having_criterion = modifier.get_query_modifiers()
        for join in joins:
            if join[0] not in joined_tables:
                query = query.join(join[0], how=JoinType.left_outer).on(join[1])
                joined_tables.append(join[0])

        if where_criterion:
            query = query.where(where_criterion)

        if having_criterion:
            query = query.having(having_criterion)

    raw_results = await self.db.execute_query(query.get_sql())
    relations = {
        (
            self.model._meta.pk.to_python_value(e["_backward_relation_key"]),
            field_object.type._meta.pk.to_python_value(e[related_pk_field]),
        )
        for e in raw_results
    }
    related_object_list = [related_query.model._init_from_db(**e) for e in raw_results]
    await self.__class__(
        model=related_query.model, db=self.db, prefetch_map=related_query._prefetch_map
    ).fetch_for_list(related_object_list)
    related_object_map = {e.pk: e for e in related_object_list}
    relation_map = {}  # type: Dict[str, list]

    for object_id, related_object_id in relations:
        if object_id not in relation_map:
            relation_map[object_id] = []
        relation_map[object_id].append(related_object_map[related_object_id])

    for instance in instance_list:
        relation_container = getattr(instance, field)
        relation_container._set_result_for_query(relation_map.get(instance.pk, []))
    return instance_list


# Traceback (asyncpg.exceptions.PostgresSyntaxError)
DEBUG:asyncio:Using selector: EpollSelector
INFO:tortoise:Tortoise-ORM startup
connections: {'default': {'engine': 'tortoise.backends.asyncpg', 'credentials': {'port': 5432, 'database': 'postgres', 'host': '172.20.0.2', 'user': 'postgres', 'password': 'postgres'}}}
apps: {'models': {'models': ['__main__'], 'default_connection': 'default'}}
DEBUG:db_client:Created connection <asyncpg.connection.Connection object at 0x7fd621f828b8> with params: {'host': '172.20.0.2', 'port': 5432, 'user': 'postgres', 'database': 'postgres'}
DEBUG:db_client:CREATE TABLE IF NOT EXISTS "modela" ("id" UUID NOT NULL PRIMARY KEY); CREATE TABLE IF NOT EXISTS "modelb" ("id" UUID NOT NULL PRIMARY KEY); CREATE TABLE IF NOT EXISTS "modelb_modela" ("modelb_id" UUID NOT NULL REFERENCES "modelb" (id) ON DELETE CASCADE,"modela_id" UUID NOT NULL REFERENCES "modela" (id) ON DELETE CASCADE);
DEBUG:db_client:INSERT INTO "modela" ("id") VALUES ($1): ['075c03a6-b777-4044-876e-d5877478318d']
DEBUG:db_client:INSERT INTO "modelb" ("id") VALUES ($1): ['8a5ad9d6-fc30-4aba-a41b-377595cddb5f']
DEBUG:db_client:SELECT "modelb_id","modela_id" FROM "modelb_modela" WHERE "modelb_id"='8a5ad9d6-fc30-4aba-a41b-377595cddb5f' AND "modela_id"='075c03a6-b777-4044-876e-d5877478318d'
DEBUG:db_client:INSERT INTO "modelb_modela" ("modela_id","modelb_id") VALUES ('075c03a6-b777-4044-876e-d5877478318d','8a5ad9d6-fc30-4aba-a41b-377595cddb5f')
INFO:root:asyncpg result [<Record _backward_relation_key=UUID('075c03a6-b777-4044-876e-d5877478318d') id=UUID('8a5ad9d6-fc30-4aba-a41b-377595cddb5f')>]
DEBUG:db_client:SELECT "id" FROM "modela" WHERE "id"='075c03a6-b777-4044-876e-d5877478318d' LIMIT 2
DEBUG:db_client:SELECT "sq0"."_backward_relation_key" "_backward_relation_key","modelb"."id" "id" FROM "modelb" JOIN (SELECT "modela_id" "_backward_relation_key","modelb_id" "_forward_relation_key" FROM "modelb_modela" WHERE "modela_id" IN (075c03a6-b777-4044-876e-d5877478318d)) "sq0" ON "sq0"."_forward_relation_key"="modelb"."id"
Traceback (most recent call last):
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/tortoise/backends/asyncpg/client.py", line 63, in translate_exceptions_
return await func(self, *args)
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/tortoise/backends/asyncpg/client.py", line 30, in retry_connection_
return await func(self, *args)
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/tortoise/backends/asyncpg/client.py", line 174, in execute_query
return await connection.fetch(query)
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/asyncpg/connection.py", line 421, in fetch
return await self._execute(query, args, 0, timeout)
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/asyncpg/connection.py", line 1414, in _execute
query, args, limit, timeout, return_status=return_status)
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/asyncpg/connection.py", line 1422, in __execute
return await self._do_execute(query, executor, timeout)
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/asyncpg/connection.py", line 1434, in _do_execute
stmt = await self._get_statement(query, None)
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/asyncpg/connection.py", line 329, in _get_statement
statement = await self._protocol.prepare(stmt_name, query, timeout)
File "asyncpg/protocol/protocol.pyx", line 163, in prepare
asyncpg.exceptions.PostgresSyntaxError: syntax error at or near "c03a6"

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "main.py", line 50, in <module>
asyncio.run(main())
File "/usr/lib64/python3.7/asyncio/runners.py", line 43, in run
return loop.run_until_complete(main)
File "/usr/lib64/python3.7/asyncio/base_events.py", line 584, in run_until_complete
return future.result()
File "main.py", line 47, in main
await a.fetch_related("b_models")
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/tortoise/models.py", line 422, in fetch_related
await db.executor_class(model=self.__class__, db=db).fetch_for_list([self], *args)
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/tortoise/backends/base/executor.py", line 284, in fetch_for_list
await self._execute_prefetch_queries(instance_list)
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/tortoise/backends/base/executor.py", line 267, in _execute_prefetch_queries
await self._do_prefetch(instance_list, field, related_query)
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/tortoise/backends/base/executor.py", line 259, in _do_prefetch
return await self._prefetch_m2m_relation(instance_id_list, field, related_query)
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/tortoise/backends/base/executor.py", line 201, in _prefetch_m2m_relation
raw_results = await self.db.execute_query(query.get_sql())
File "/home/nik/.virtualenvs/tortoise-pk-error/lib/python3.7/site-packages/tortoise/backends/asyncpg/client.py", line 65, in translate_exceptions_
raise OperationalError(exc)
tortoise.exceptions.OperationalError: syntax error at or near "c03a6"

# Fixed code
async def _prefetch_m2m_relation(
    self, instance_list: list, field: str, related_query
) -> list:
    instance_id_set = {
        self._field_to_db(instance._meta.pk, instance.pk, instance)
        for instance in instance_list
    }  # type: Set[Any]

    field_object = self.model._meta.fields_map[field]

    through_table = Table(field_object.through)

    subquery = (
        self.db.query_class.from_(through_table)
        .select(
            getattr(through_table, field_object.backward_key).as_(
                "_backward_relation_key"
            ),
            getattr(through_table, field_object.forward_key).as_(
                "_forward_relation_key"
            ),
        )
        .where(getattr(through_table, field_object.backward_key).isin(instance_id_set))
    )

    related_query_table = Table(related_query.model._meta.table)
    related_pk_field = related_query.model._meta.db_pk_field
    query = (
        related_query.query.join(subquery)
        .on(
            subquery._forward_relation_key
            == getattr(related_query_table, related_pk_field)
        )
        .select(
            subquery._backward_relation_key.as_("_backward_relation_key"),
            *[
                getattr(related_query_table, field).as_(field)
                for field in related_query.fields
            ],
        )
    )

    if related_query._q_objects:
        joined_tables = []  # type: List[Table]
        modifier = QueryModifier()
        for node in related_query._q_objects:
            modifier &= node.resolve(
                model=related_query.model,
                annotations=related_query._annotations,
                custom_filters=related_query._custom_filters,
            )

        where_criterion, joins, having_criterion = modifier.get_query_modifiers()
        for join in joins:
            if join[0] not in joined_tables:
                query = query.join(join[0], how=JoinType.left_outer).on(join[1])
                joined_tables.append(join[0])

        if where_criterion:
            query = query.where(where_criterion)

        if having_criterion:
            query = query.having(having_criterion)

    raw_results = await self.db.execute_query(query.get_sql())
    relations = {
        (
            self.model._meta.pk.to_python_value(e["_backward_relation_key"]),
            field_object.type._meta.pk.to_python_value(e[related_pk_field]),
        )
        for e in raw_results
    }
    related_object_list = [related_query.model._init_from_db(**e) for e in raw_results]
    await self.__class__(
        model=related_query.model, db=self.db, prefetch_map=related_query._prefetch_map
    ).fetch_for_list(related_object_list)
    related_object_map = {e.pk: e for e in related_object_list}
    relation_map = {}  # type: Dict[str, list]

    for object_id, related_object_id in relations:
        if object_id not in relation_map:
            relation_map[object_id] = []
        relation_map[object_id].append(related_object_map[related_object_id])

    for instance in instance_list:
        relation_container = getattr(instance, field)
        relation_container._set_result_for_query(relation_map.get(instance.pk, []))
    return instance_list