From 3da9c04712ed96e74427c8168fcfac5527413e1c Mon Sep 17 00:00:00 2001 From: drh Date: Mon, 22 Dec 2014 18:41:21 +0000 Subject: [PATCH] Redefine the way PRAGMA data_version works: It continues to change when any other connection commits, including shared-cache connections, but does not change if the local connection commits. FossilOrigin-Name: 7a97826f33460f3b4f3890c9cf97116c3355eeda --- manifest | 16 ++--- manifest.uuid | 2 +- src/btree.c | 3 +- src/btreeInt.h | 1 + test/pragma3.test | 146 ++++++++++++++++++++++++++++++++-------------- 5 files changed, 114 insertions(+), 54 deletions(-) diff --git a/manifest b/manifest index d7e15132e7..8ae7e71d4a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fixes\sto\sthe\sREADME.md\sfile.\s\sNo\schanges\sto\scode. -D 2014-12-21T11:56:02.079 +C Redefine\sthe\sway\sPRAGMA\sdata_version\sworks:\s\sIt\scontinues\sto\schange\swhen\nany\sother\sconnection\scommits,\sincluding\sshared-cache\sconnections,\sbut\sdoes\snot\nchange\sif\sthe\slocal\sconnection\scommits. +D 2014-12-22T18:41:21.243 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 6c4f961fa91d0b4fa121946a19f9e5eac2f2f809 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -173,9 +173,9 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c 7ddee9c7d505e07e959a575b18498f17c71e53ea F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5 -F src/btree.c b2b2bd0aa02430fe86bc891295db919fcafb0d64 +F src/btree.c 1de0560426ecde85ff3ea95d7c94261d7652e284 F src/btree.h 94277c1d30c0b75705974bcc8b0c05e79c03d474 -F src/btreeInt.h 3363e18fd76f69a27a870b25221b2345b3fd4d21 +F src/btreeInt.h a3d0ae1d511365e1a2b76ad10960dbe55c286f34 F src/build.c 162d84e4833b03f9d07192ef06057b0226f6e543 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c 198a0066ba60ab06fc00fba1998d870a4d575463 @@ -785,7 +785,7 @@ F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54 F test/permutations.test 4e12d43f4639ea8a0e366d9c64e0009afe2eb544 F test/pragma.test aa16dedfe01c02c8895169012f7dfde9c163f0d5 F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13 -F test/pragma3.test 1935dfdd0082250df4cf4caed52bdfef527c34ff +F test/pragma3.test 3da08d907ba027c50ede8d6e95418f32898971a5 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 F test/printf2.test b4acd4bf8734243257f01ddefa17c4fb090acc8a F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d @@ -1234,7 +1234,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P b9330b887cc8bed2b6b3e6c1b269788e08ccf50d -R 92e5107af7d9564747f56fe6b5bf8f20 +P ef4b734d1ff3dbb9c802c60dc1384033fdfd87e5 +R 717423e0d3aaa97f5eb5c0e7357ce13c U drh -Z 2bbd439edb2e1185c83f3c807f675b2f +Z 78337e4052167193689952903ddb287b diff --git a/manifest.uuid b/manifest.uuid index 08ca74492b..327aa0952b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ef4b734d1ff3dbb9c802c60dc1384033fdfd87e5 \ No newline at end of file +7a97826f33460f3b4f3890c9cf97116c3355eeda \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 1223f78e48..e6a7e2c2b9 100644 --- a/src/btree.c +++ b/src/btree.c @@ -3550,6 +3550,7 @@ int sqlite3BtreeCommitPhaseTwo(Btree *p, int bCleanup){ sqlite3BtreeLeave(p); return rc; } + p->iDataVersion--; /* Compensate for pPager->iDataVersion++; */ pBt->inTransaction = TRANS_READ; btreeClearHasContent(pBt); } @@ -8195,7 +8196,7 @@ void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){ assert( idx>=0 && idx<=15 ); if( idx==BTREE_DATA_VERSION ){ - *pMeta = sqlite3PagerDataVersion(pBt->pPager); + *pMeta = sqlite3PagerDataVersion(pBt->pPager) + p->iDataVersion; }else{ *pMeta = get4byte(&pBt->pPage1->aData[36 + idx*4]); } diff --git a/src/btreeInt.h b/src/btreeInt.h index a28a6a297e..ed4d75ee9f 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -351,6 +351,7 @@ struct Btree { u8 locked; /* True if db currently has pBt locked */ int wantToLock; /* Number of nested calls to sqlite3BtreeEnter() */ int nBackup; /* Number of backup operations reading this btree */ + u32 iDataVersion; /* Combines with pBt->pPager->iDataVersion */ Btree *pNext; /* List of other sharable Btrees from the same db */ Btree *pPrev; /* Back pointer of the same list */ #ifndef SQLITE_OMIT_SHARED_CACHE diff --git a/test/pragma3.test b/test/pragma3.test index 5918d0f0ed..e6069f6e53 100644 --- a/test/pragma3.test +++ b/test/pragma3.test @@ -32,25 +32,20 @@ do_execsql_test pragma3-102 { # EVIDENCE-OF: R-27726-60934 The "PRAGMA data_version" command provides # an indication that the database file has been modified. # -# EVIDENCE-OF: R-30058-27547 The integer values returned by two -# invocations of "PRAGMA data_version" will be different if changes -# where committed to that database in between the two invocations. -# -# EVIDENCE-OF: R-10201-09349 The "PRAGMA data_version" command responses -# to changes committed by the same database connection, by database -# connections sharing a cache in shared cache mode, and by completely -# independent database connections including connections in separate -# threads and processes. -# -# In this test, it response to two separate changes on the same database -# connection. +# EVIDENCE-OF: R-25838-33704 The "PRAGMA data_version" value is +# unchanced for commits made on the same database connection. # do_execsql_test pragma3-110 { + PRAGMA data_version; + BEGIN IMMEDIATE; + PRAGMA data_version; CREATE TABLE t1(a); INSERT INTO t1 VALUES(100),(200),(300); + PRAGMA data_version; + COMMIT; SELECT * FROM t1; PRAGMA data_version; -} {100 200 300 3} +} {1 1 1 100 200 300 1} sqlite3 db2 test.db do_test pragma3-120 { @@ -61,44 +56,88 @@ do_test pragma3-120 { } {100 200 300 1} do_execsql_test pragma3-130 { + PRAGMA data_version; + BEGIN IMMEDIATE; + PRAGMA data_version; INSERT INTO t1 VALUES(400),(500); + PRAGMA data_version; + COMMIT; SELECT * FROM t1; PRAGMA data_version; -} {100 200 300 400 500 4} +} {1 1 1 100 200 300 400 500 1} -# EVIDENCE-OF: R-10201-09349 The "PRAGMA data_version" command responses -# to changes committed by the same database connection, by database -# connections sharing a cache in shared cache mode, and by completely -# independent database connections including connections in separate -# threads and processes. +# EVIDENCE-OF: R-63005-41812 The integer values returned by two +# invocations of "PRAGMA data_version" from the same connection will be +# different if changes were committed to the database by any other +# connection in the interim. # -# In these test, it response to changes in a different database connection -# part of the same process. +# Value went from 1 in pragma3-120 to 2 here. # do_test pragma3-140 { db2 eval { SELECT * FROM t1; PRAGMA data_version; + BEGIN IMMEDIATE; + PRAGMA data_version; UPDATE t1 SET a=a+1; + COMMIT; SELECT * FROM t1; PRAGMA data_version; } -} {100 200 300 400 500 2 101 201 301 401 501 3} +} {100 200 300 400 500 2 2 101 201 301 401 501 2} do_execsql_test pragma3-150 { SELECT * FROM t1; PRAGMA data_version; -} {101 201 301 401 501 5} +} {101 201 301 401 501 2} -# EVIDENCE-OF: R-10201-09349 The "PRAGMA data_version" command responses -# to changes committed by the same database connection, by database -# connections sharing a cache in shared cache mode, and by completely -# independent database connections including connections in separate -# threads and processes. # -# This test verifies behavior when a separate process changes the database -# file. +do_test pragma3-160 { + db eval { + BEGIN; + PRAGMA data_version; + UPDATE t1 SET a=555 WHERE a=501; + PRAGMA data_version; + SELECT * FROM t1 ORDER BY a; + PRAGMA data_version; + } +} {2 2 101 201 301 401 555 2} +do_test pragma3-170 { + db2 eval { + PRAGMA data_version; + } +} {2} +do_test pragma3-180 { + db eval { + COMMIT; + PRAGMA data_version; + } +} {2} +do_test pragma3-190 { + db2 eval { + PRAGMA data_version; + } +} {3} + +# EVIDENCE-OF: R-19326-44825 The "PRAGMA data_version" value is a local +# property of each database connection and so values returned by two +# concurrent invocations of "PRAGMA data_version" on separate database +# connections are often different even though the underlying database is +# identical. +# +do_test pragma3-195 { + expr {[db eval {PRAGMA data_version}]!=[db2 eval {PRAGMA data_version}]} +} {1} + +# EVIDENCE-OF: R-54562-06892 The behavior of "PRAGMA data_version" is +# the same for all database connections, including database connections +# in separate processes and shared cache database connections. +# +# The next block checks the behavior for separate processes. # do_test pragma3-200 { + db eval {PRAGMA data_version; SELECT * FROM t1;} +} {2 101 201 301 401 555} +do_test pragma3-201 { set fd [open pragma3.txt wb] puts $fd { sqlite3 db test.db; @@ -113,18 +152,15 @@ do_test pragma3-200 { PRAGMA data_version; SELECT * FROM t1; } -} {6 101 201} +} {3 101 201} db2 close db close -# EVIDENCE-OF: R-10201-09349 The "PRAGMA data_version" command responses -# to changes committed by the same database connection, by database -# connections sharing a cache in shared cache mode, and by completely -# independent database connections including connections in separate -# threads and processes. +# EVIDENCE-OF: R-54562-06892 The behavior of "PRAGMA data_version" is +# the same for all database connections, including database connections +# in separate processes and shared cache database connections. # -# The next series of tests verifies the behavior for shared-cache -# database connections. +# The next block checks that behavior is the same for shared-cache. # ifcapable shared_cache { set ::enable_shared_cache [sqlite3_enable_shared_cache 1] @@ -133,24 +169,46 @@ ifcapable shared_cache { do_test pragma3-300 { db eval { PRAGMA data_version; + BEGIN; CREATE TABLE t3(a,b,c); + CREATE TABLE t4(x,y,z); + INSERT INTO t4 VALUES(123,456,789); + PRAGMA data_version; + COMMIT; PRAGMA data_version; } - } {1 2} + } {1 1 1} do_test pragma3-310 { db2 eval { PRAGMA data_version; + BEGIN; INSERT INTO t3(a,b,c) VALUES('abc','def','ghi'); SELECT * FROM t3; PRAGMA data_version; } - } {2 abc def ghi 3} + } {2 abc def ghi 2} + # The transaction in db2 has not yet committed, so the data_version in + # db is unchanged. do_test pragma3-320 { db eval { PRAGMA data_version; - SELECT * FROM t3; + SELECT * FROM t4; } - } {3 abc def ghi} + } {1 123 456 789} + do_test pragma3-330 { + db2 eval { + COMMIT; + PRAGMA data_version; + SELECT * FROM t4; + } + } {2 123 456 789} + do_test pragma3-340 { + db eval { + PRAGMA data_version; + SELECT * FROM t3; + SELECT * FROM t4; + } + } {2 abc def ghi 123 456 789} db2 close db close sqlite3_enable_shared_cache $::enable_shared_cache @@ -168,7 +226,7 @@ ifcapable wal { PRAGMA journal_mode; SELECT * FROM t1; } - } {3 wal 101 201} + } {2 wal 101 201} do_test pragma3-410 { db2 eval { PRAGMA data_version; @@ -178,7 +236,7 @@ ifcapable wal { } {2 wal 101 201} do_test pragma3-420 { db eval {UPDATE t1 SET a=111*(a/100); PRAGMA data_version; SELECT * FROM t1} - } {4 111 222} + } {2 111 222} do_test pragma3-430 { db2 eval {PRAGMA data_version; SELECT * FROM t1;} } {3 111 222}