2016-11-14 174 views
0

我們正在重構我們的Framework Postgresql驅動程序以允許進行事務處理。在這個過程中,我們已經介紹了導致以下錯誤php Postgresql pg_query():重複鍵值違反了唯一性約束

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

相關的測試(S)這個問題是

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

我拿到表序列以某種方式搞砸了,但我在爲什麼表順序弄亂了,甚至只是如何修復代碼,以便測試正常功能喪失。

注:我相信這個故障有關的準備和無準備的語句

回答

0

在線路519重新啓動序列和truncate table看起來不錯,但如果一個rollbacked事務中運行,截斷不會發生,但序列重啓will

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

「TRUNCATE ... RESTART IDENTITY」也是如此。 –

+0

這是一個有趣的筆記。但我不確定它適用於這裏的具體失敗。隔離測試我仍然失敗。這似乎與使用預處理語句有關,因爲它們只是運行我們沒有使用事務的執行測試。 –

0

我們仍然不確定根本原因,但整個問題都與單元測試有關。即使僅僅檢查了一個失敗的測試,也有/正在全局重新啓動表序列。我們找到了解決問題的方法,但仍在尋找根本原因。

我們還發現我們需要改進所有驅動程序測試的tearDown()方法。

相關問題