Skip to content

Commit

Permalink
Поправить последовательности в set_autoincrement_counters (#138)
Browse files Browse the repository at this point in the history
Во время работы над добавлением PostgreSQL (#29), мы добавили функцию `set_autoincrement_counters`. При этом получение последовательностей, счетчик которых необходимо изменить, было реализовано довольно примитивным способом:
```python
queries = ""
for tablename in Base.metadata.tables:
    queries += f"ALTER SEQUENCE {tablename}_id_seq RESTART WITH 10000;"
```
В этой реализации, для получения последовательностей мы просто использовали имена таблиц, предполагая, что все наши последовательности будут связаны с колонками с названием `id`.

Но такая реализация оказалась достаточно хрупкой и у неё есть ряд очевидных проблем:

- если например в какой-либо таблице, появится колонка с автогенерируемой последовательностью и названием отличающимся от `id` (например `account_id`), то наша функция не сможет найти такие последовательности, т.к. она будет пытаться изменить `table_id_seq` вместо `table_account_id_seq`;

- если в какой-либо таблице вообще не будет ни одной колонки с автогенерирумой последовательностью, то запрос
  ```python
  f"ALTER SEQUENCE {tablename}_id_seq RESTART WITH 10000;"
  ```
  упадёт с ошибкой, т.к. алгоритм использует все существующие таблицы в бд и не учитывает, есть ли в них вообще какие-либо последовательности, или нет.

Для решения этих проблем можно использовать следующий запрос, который получит имена всех последовательностей, объявленных в нашей бд в явном виде:
```sql
SELECT sequencename FROM pg_sequences;
```
Таким образом нам не надо будет проходить по всем таблицам и "угадывать" названия предполагаемых последовательностей - мы просто можем получить все последовательности в явном виде.

В рамках этой задачи необходимо поправить получение последовательностей, счетчик которых необходимо изменить в функции `set_autoincrement_counters`, используя указанный выше sql запрос.
  • Loading branch information
birthdaysgift committed Nov 4, 2023
1 parent 83a1dcc commit 045eace
Showing 1 changed file with 8 additions and 5 deletions.
13 changes: 8 additions & 5 deletions tests/utils/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

from sqlalchemy import text

from src.shared.database import Base, sync_engine
from src.shared.database import sync_engine


def set_autoincrement_counters() -> None:
"""Set initial value for all auto-incremented sequences in db tables.
This is needed to avoid conflicts between rows created by fixtures
and values created by the app itself.
This is needed to avoid conflicts between db objects created by fixtures
and db objects created by the app itself.
For example:
fixture creates a new user with id = 1
Expand All @@ -23,9 +23,12 @@ def set_autoincrement_counters() -> None:
So this function just sets autoincrement counter for `id` columns in all database tables.
"""
with sync_engine.connect() as connection:
sequences = connection.execute(text("SELECT sequencename FROM pg_sequences;")).all()

queries = ""
for tablename in Base.metadata.tables:
queries += f"ALTER SEQUENCE {tablename}_id_seq RESTART WITH 10000;" # pylint: disable=consider-using-join
for sequence_name, *_ in sequences:
queries += f"ALTER SEQUENCE {sequence_name} RESTART WITH 10000;"

# we avoid executing of empty query since this will give us an error from sqlalchemy
if not queries:
Expand Down

0 comments on commit 045eace

Please sign in to comment.