php Postgresql pg_query (): двойное значение ключа нарушает ограничение уникальности

Мы работаем над рефакторингом нашего Framework Postgresql драйвера для транзакций. В процессе, мы представили некоторые проблемы, приводящие к следующей ошибке

pg_query(): duplicate key value violates unique constraint DETAIL: Key (id)=(1) already exists

ссылка на тест Трэвиса с некоторыми подробностями
https://travis-ci.org/photodude/database/jobs/175596877

Соответствующая часть драйвера, имеющего проблемы, находится по этой ссылке

https://github.com/joomla-framework/database/blob/master/src/Postgresql/PostgresqlDriver.php#L711-L819

Связанные тесты с проблемой

https://github.com/joomla-framework/database/blob/master/Tests/DriverPostgresqlTest.php#L1116-L1163

Я получаю, что последовательность таблиц каким-то образом испорчена, но я не понимаю, почему последовательность таблиц испорчена или даже просто как исправить код, чтобы тесты функционировали правильно.

примечание: я считаю, что эта ошибка связана с подготовленными и неподготовленными заявлениями

0

Решение

В строке 519 перезапускается последовательность и таблица усечения, которая выглядит нормально, но если она выполняется внутри транзакции с откатом, усечение не произойдет, но перезапуск последовательности будут

    Important: Because sequences are non-transactional, changes made by setval are not undone if the transaction rolls back.

увидеть:

s1=> create table test1 ( id serial primary key, a text not null);
CREATE TABLE
s1=> \d
List of relations
Schema |     Name     |   Type   | Owner
--------+--------------+----------+--------
public | test1        | table    | albert
public | test1_id_seq | sequence | albert
(2 rows)

s1=> insert into test1(a) values ('apple');
INSERT 0 1
s1=> select * from test1;
id |   a
----+-------
1 | apple
(1 row)

s1=> select * from test1_id_seq;
sequence_name | last_value | start_value | increment_by |      max_value      | min_value | cache_value | log_cnt | is_cycled | is_called
---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
test1_id_seq  |          1 |           1 |            1 | 9223372036854775807 |         1 |           1 |      32 | f         | t
(1 row)

s1=> insert into test1(a) values ('bannana');
INSERT 0 1
s1=> select * from test1;
id |    a
----+---------
1 | apple
2 | bannana
(2 rows)

s1=> insert into test1(a) values ('bannana');
INSERT 0 1
s1=> select * from test1;
id |    a
----+---------
1 | apple
2 | bannana
3 | bannana
(3 rows)

s1=> select * from test1_id_seq;
sequence_name | last_value | start_value | increment_by |      max_value      | min_value | cache_value | log_cnt | is_cycled | is_called
---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
test1_id_seq  |          3 |           1 |            1 | 9223372036854775807 |         1 |           1 |      30 | f         | t
(1 row)

s1=> begin;
BEGIN
s1=> alter sequence test1_id_seq RESTART WITH 1;
ALTER SEQUENCE
s1=> truncate table test1;
TRUNCATE TABLE
s1=> rollback;
ROLLBACK
s1=> select * from test1_id_seq;
sequence_name | last_value | start_value | increment_by |      max_value      | min_value | cache_value | log_cnt | is_cycled | is_called
---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
test1_id_seq  |          1 |           1 |            1 | 9223372036854775807 |         1 |           1 |       0 | f         | f
(1 row)

s1=> select * from test1;
id |    a
----+---------
1 | apple
2 | bannana
3 | bannana
(3 rows)

s1=>
0

Другие решения

Мы до сих пор не уверены в первопричине, но вся проблема связана с юнит-тестами. что-то / глобально перезапускает последовательность таблиц, даже когда проверяется только один провальный тест. Мы нашли способ обойти эту проблему, но все еще ищем основную причину.

Мы также обнаружили, что нам нужно улучшить методы tearDown () для всех тестов драйверов.

0

По вопросам рекламы [email protected]