aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordan <dan@noemail.net>2018-12-20 17:32:33 +0000
committerdan <dan@noemail.net>2018-12-20 17:32:33 +0000
commite46201e264082d02490e20f778b3f0fc00ba136f (patch)
treefc0fed1bd8b458816f6cacc0808924625f346be1
parent16dd3985f0c78b77f0fd753ff151363d663d7413 (diff)
downloadsqlite-e46201e264082d02490e20f778b3f0fc00ba136f.tar.gz
sqlite-e46201e264082d02490e20f778b3f0fc00ba136f.zip
Fix a bug in the code that detects self-referencing rows as part of foreign
key processing. Fix for [50d2a6c2]. FossilOrigin-Name: 16fff05347f42fe9fa0f3150290b98b59a9bb921e49dc07ca397aa1de7a7e17d
-rw-r--r--manifest15
-rw-r--r--manifest.uuid2
-rw-r--r--src/fkey.c14
-rw-r--r--test/fkey8.test34
4 files changed, 50 insertions, 15 deletions
diff --git a/manifest b/manifest
index 06f2d232f..e9af7febb 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\ssegfault\scaused\sby\susing\sthe\sRAISE\sfunction\sincorrectly\s(library\snow\nreturns\san\serror\sinstead\sof\scrashing).
-D 2018-12-20T15:04:38.546
+C Fix\sa\sbug\sin\sthe\scode\sthat\sdetects\sself-referencing\srows\sas\spart\sof\sforeign\nkey\sprocessing.\sFix\sfor\s[50d2a6c2].
+D 2018-12-20T17:32:33.680
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in d8b254f8bb81bab43c340d70d17dc3babab40fcc8a348c8255881f780a45fee6
@@ -461,7 +461,7 @@ F src/dbstat.c 3c8bd4e77f0244fd2bd7cc90acf116ad2f8e82d70e536637f35ac2bc99b726f9
F src/delete.c f7938125847e8ef485448db5fbad29acb2991381a02887dd854c1617315ab9fb
F src/expr.c 5bf5ccc9a1ecf8e952bd6314091e698ea85de6446e10a852c0b9058a0f5cb0cc
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
-F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812
+F src/fkey.c 012dd7dba1a62fda6b76e633ab303b2232ee2874a685c915065227ab20ad6ae0
F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
F src/global.c 8291eee0782b83124de14ec0389ec9fd6ae1873358a6b0d9469fe17a46ad803b
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
@@ -842,7 +842,7 @@ F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
F test/fkey5.test 24dd28eb3d9f1b5a174f47e9899ace5facb08373a4223593c8c631e6cf9f7d5a
F test/fkey6.test d078a1e323a740062bed38df32b8a736fd320dc0
F test/fkey7.test 24076d43d3449f12f25503909ca4bfb5fc5fefd5af1f930723a496343eb28454
-F test/fkey8.test e5372e32cdb4481f121ec3550703eeb7b4e0762c
+F test/fkey8.test 863c6d84f0d289fd2c1a1c293abb9803f77efd35211d9012c0986c8f6ccf5d5a
F test/fkey_malloc.test 594a7ea1fbab553c036c70813cd8bd9407d63749
F test/fordelete.test eb93a2f34137bb87bdab88fcab06c0bd92719aff
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
@@ -1787,8 +1787,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 23e200da5cfbde0798e67cd9e016e4a1cd73b67981e1af841493fcd123d8f547
-R 44eff2c3614ea3b3372ea87dffe406f1
-T +closed c9c163a60dab4258c8e410dd56086b78bc8b716ea8bf2037c015eeb34d45c86d
+P ddf06db702761d663119d508afe21d7dfebe963d576bb42fc2f2024205ab86f8
+R 4df05a7a0e4d60cba77e3740f8e11451
U dan
-Z 90e5f7468069591ede852249e33e7f76
+Z 1374d5384d9ce4b161c9c44c45208645
diff --git a/manifest.uuid b/manifest.uuid
index 899cc4ee0..4a6fc65c3 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-ddf06db702761d663119d508afe21d7dfebe963d576bb42fc2f2024205ab86f8 \ No newline at end of file
+16fff05347f42fe9fa0f3150290b98b59a9bb921e49dc07ca397aa1de7a7e17d \ No newline at end of file
diff --git a/src/fkey.c b/src/fkey.c
index 6777d71ea..8f465bb7b 100644
--- a/src/fkey.c
+++ b/src/fkey.c
@@ -602,8 +602,11 @@ static void fkScanChildren(
** NOT( $current_a==a AND $current_b==b AND ... )
**
** The first form is used for rowid tables. The second form is used
- ** for WITHOUT ROWID tables. In the second form, the primary key is
- ** (a,b,...)
+ ** for WITHOUT ROWID tables. In the second form, the *parent* key is
+ ** (a,b,...). Either the parent or primary key could be used to
+ ** uniquely identify the current row, but the parent key is more convenient
+ ** as the required values have already been loaded into registers
+ ** by the caller.
*/
if( pTab==pFKey->pFrom && nIncr>0 ){
Expr *pNe; /* Expression (pLeft != pRight) */
@@ -615,14 +618,13 @@ static void fkScanChildren(
pNe = sqlite3PExpr(pParse, TK_NE, pLeft, pRight);
}else{
Expr *pEq, *pAll = 0;
- Index *pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pIdx!=0 );
- for(i=0; i<pPk->nKeyCol; i++){
+ for(i=0; i<pIdx->nKeyCol; i++){
i16 iCol = pIdx->aiColumn[i];
assert( iCol>=0 );
pLeft = exprTableRegister(pParse, pTab, regData, iCol);
- pRight = exprTableColumn(db, pTab, pSrc->a[0].iCursor, iCol);
- pEq = sqlite3PExpr(pParse, TK_EQ, pLeft, pRight);
+ pRight = sqlite3Expr(db, TK_ID, pTab->aCol[iCol].zName);
+ pEq = sqlite3PExpr(pParse, TK_IS, pLeft, pRight);
pAll = sqlite3ExprAnd(db, pAll, pEq);
}
pNe = sqlite3PExpr(pParse, TK_NOT, pAll, 0);
diff --git a/test/fkey8.test b/test/fkey8.test
index 4269c20a9..f38e835ae 100644
--- a/test/fkey8.test
+++ b/test/fkey8.test
@@ -164,4 +164,38 @@ do_catchsql_test 2.3.1 {
DELETE FROM p3 WHERE a=1
} {1 {FOREIGN KEY constraint failed}}
+
+do_execsql_test 3.0 {
+ PRAGMA foreign_keys=ON;
+ CREATE TABLE t2(
+ a PRIMARY KEY, b, c, d, e,
+ FOREIGN KEY(b, c) REFERENCES t2(d, e)
+ ) WITHOUT ROWID;
+ CREATE UNIQUE INDEX idx ON t2(d, e);
+
+ INSERT INTO t2 VALUES(1, 'one', 'one', 'one', 'one'); -- row is parent of self
+ INSERT INTO t2 VALUES(2, 'one', 'one', 'one', NULL); -- parent is row 1
+}
+
+do_catchsql_test 3.1 {
+ DELETE FROM t2 WHERE a=1;
+} {1 {FOREIGN KEY constraint failed}}
+
+do_execsql_test 4.0 {
+ CREATE TABLE t1 (
+ c1 PRIMARY KEY,
+ c2 NUMERIC,
+ FOREIGN KEY(c1) REFERENCES t1(c2)
+ ) WITHOUT ROWID ;
+ CREATE INDEX t1c1 ON t1(c1);
+ CREATE UNIQUE INDEX t1c1unique ON t1(c2);
+}
+do_catchsql_test 4.1 {
+ INSERT OR REPLACE INTO t1 VALUES(10000, 20000);
+} {1 {FOREIGN KEY constraint failed}}
+do_execsql_test 4.2 {
+ INSERT OR REPLACE INTO t1 VALUES(20000, 20000);
+}
+
finish_test
+