On 2015-04-09 07:57 PM, Simon Slavin wrote:
> On 9 Apr 2015, at 6:04pm, Gustav Melno <knarks at online.de> wrote:
>
>> Thanks for the help. Adding a trailing underscore helped also. I'm still
>> wondering why insertion worked at all because defining oid as column name
>> with the type VARCHAR should result in an error on execution.
> The three names for the integer primary key column (oid, rowid, _rowid_) work
> only if the table doesn't have a defined column of that name. This allows
> compatibility with people who didn't know that they were had special meanings
> for SQLite. Clever, isn't it ?
Except it clearly did not work like that in the OP's case. He had
defined "oid" in his table, but then when he inserted into column oid,
the value either went to the rowid column or somehow messed up the rowid
enough to cause a constraint failure. I'm starting to think this might
be a bug.
I've checked it like this (Copy paste this to a file and feed to an
sqlite parser):
-- 2015-04-09 20:34:18.791 | [Info] Script Initialized,
Started executing...
--
================================================================================================
CREATE TABLE idTest( -- Table with every row id reference
id INTEGER PRIMARY KEY,
col1 TEXT,
oid INTEGER,
rowid INTEGER,
_rowid_ INTEGER
);
CREATE TABLE fkTest( -- table to test the Foreign Key
id INTEGER PRIMARY KEY,
Data TEXT,
FOREIGN KEY (id) REFERENCES idTest(id)
ON UPDATE CASCADE
ON DELETE CASCADE -- changes and deletes must cascade
);
INSERT INTO idTest (col1, oid, rowid, _rowid_) VALUES
('TestA', 10, 100, 1000),
('TestA', 20, 200, 2000),
('TestA', 30, 300, 3000)
;
INSERT INTO idTest (col1, oid) VALUES ('TestB', 'aaa');
INSERT INTO fkTest (id, Data) VALUES (last_insert_rowid(), 'FK 1');
INSERT INTO idTest (col1, oid) VALUES ('TestC', 20);
INSERT INTO fkTest (id, Data) VALUES (last_insert_rowid(), 'FK 2');
-- So far all happens as expected and works perfectly...
SELECT * FROM idTest;
-- id | col1 | oid | rowid | _rowid_
-- ------------ | ------- | ----- | ----- | -------
-- 1 | TestA | 10 | 100 | 1000
-- 2 | TestA | 20 | 200 | 2000
-- 3 | TestA | 30 | 300 | 3000
-- 4 | TestB | aaa | |
-- 5 | TestC | 20 | |
SELECT F.*, I.*
FROM fkTest AS F
LEFT JOIN idTest AS I ON F.id=I.id;
-- id | Data | id | col1 | oid | rowid |
_rowid_
-- ------------ | ------ | ------------ | ------- | ----- | ----- |
-------
-- 4 | FK 1 | 4 | TestB | aaa | |
-- 5 | FK 2 | 5 | TestC | 20 | |
-- Here the problem happens. this statement should in SQL terms succeed
and update the fkTest
-- table - here I am NOT using oid as the OP did, I am using the correct
reference but it still fails.
-- And - it works if I remove the rowid references from the first table
create.
UPDATE idTest SET id = 40 WHERE id = 4;
-- 2015-04-09 20:34:18.807 | [ERROR] FOREIGN KEY constraint failed
-- Script Stats: Total Script Execution Time: 0d 00h 00m and
00.029s
-- Total Script Query Time: 0d 00h 00m and
00.005s
-- Total Database Rows Changed: 8
-- Total Virtual-Machine Steps: 396
-- Last executed Item Index: 12
-- Last Script Error: Script Failed in Item 11:
FOREIGN KEY constraint failed
--
------------------------------------------------------------------------------------------------
I won't add more test script outputs, but it fails for a DELETE request
too. I think including rowid / oid / _rowid_ in a table works normally
since the correct values ended up in the correct columns, but somehow
including those aliases confuses the FK check mechanism.