1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Merge recent trunk enhancements.

FossilOrigin-Name: c60cdb47612c05c252613e50a8ac10635469fdfe
This commit is contained in:
drh
2017-03-02 13:22:04 +00:00
15 changed files with 314 additions and 68 deletions

View File

@@ -3408,8 +3408,10 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */ const u32 nMinMerge = 64; /* Minimum amount of incr-merge work to do */
Fts3Table *p = (Fts3Table*)pVtab; Fts3Table *p = (Fts3Table*)pVtab;
int rc = sqlite3Fts3PendingTermsFlush(p); int rc;
i64 iLastRowid = sqlite3_last_insert_rowid(p->db);
rc = sqlite3Fts3PendingTermsFlush(p);
if( rc==SQLITE_OK if( rc==SQLITE_OK
&& p->nLeafAdd>(nMinMerge/16) && p->nLeafAdd>(nMinMerge/16)
&& p->nAutoincrmerge && p->nAutoincrmerge!=0xff && p->nAutoincrmerge && p->nAutoincrmerge!=0xff
@@ -3424,6 +3426,7 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge); if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge);
} }
sqlite3Fts3SegmentsClose(p); sqlite3Fts3SegmentsClose(p);
sqlite3_set_last_insert_rowid(p->db, iLastRowid);
return rc; return rc;
} }

View File

@@ -545,11 +545,6 @@ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel, sqlite3_value **apVal){
} }
} }
/* Write the averages record */
if( rc==SQLITE_OK ){
rc = fts5StorageSaveTotals(p);
}
return rc; return rc;
} }
@@ -753,11 +748,6 @@ int sqlite3Fts5StorageIndexInsert(
} }
sqlite3_free(buf.p); sqlite3_free(buf.p);
/* Write the averages record */
if( rc==SQLITE_OK ){
rc = fts5StorageSaveTotals(p);
}
return rc; return rc;
} }
@@ -1092,12 +1082,17 @@ int sqlite3Fts5StorageRowCount(Fts5Storage *p, i64 *pnRow){
** Flush any data currently held in-memory to disk. ** Flush any data currently held in-memory to disk.
*/ */
int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit){ int sqlite3Fts5StorageSync(Fts5Storage *p, int bCommit){
if( bCommit && p->bTotalsValid ){ int rc = SQLITE_OK;
int rc = fts5StorageSaveTotals(p); i64 iLastRowid = sqlite3_last_insert_rowid(p->pConfig->db);
p->bTotalsValid = 0; if( p->bTotalsValid ){
if( rc!=SQLITE_OK ) return rc; rc = fts5StorageSaveTotals(p);
if( bCommit ) p->bTotalsValid = 0;
} }
return sqlite3Fts5IndexSync(p->pIndex, bCommit); if( rc==SQLITE_OK ){
rc = sqlite3Fts5IndexSync(p->pIndex, bCommit);
}
sqlite3_set_last_insert_rowid(p->pConfig->db, iLastRowid);
return rc;
} }
int sqlite3Fts5StorageRollback(Fts5Storage *p){ int sqlite3Fts5StorageRollback(Fts5Storage *p){

View File

@@ -0,0 +1,73 @@
# 2017 Feb 27
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests of the last_insert_rowid functionality with fts5.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5lastrowid
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(str);
}
do_execsql_test 1.1 {
INSERT INTO t1 VALUES('one string');
INSERT INTO t1 VALUES('two string');
INSERT INTO t1 VALUES('three string');
SELECT last_insert_rowid();
} {3}
do_execsql_test 1.2 {
BEGIN;
INSERT INTO t1 VALUES('one string');
INSERT INTO t1 VALUES('two string');
INSERT INTO t1 VALUES('three string');
COMMIT;
SELECT last_insert_rowid();
} {6}
do_execsql_test 1.3 {
INSERT INTO t1(rowid, str) VALUES(-22, 'some more text');
SELECT last_insert_rowid();
} {-22}
do_execsql_test 1.4 {
BEGIN;
INSERT INTO t1(rowid, str) VALUES(45, 'some more text');
INSERT INTO t1(rowid, str) VALUES(46, 'some more text');
INSERT INTO t1(rowid, str) VALUES(222, 'some more text');
SELECT last_insert_rowid();
COMMIT;
SELECT last_insert_rowid();
} {222 222}
do_execsql_test 1.5 {
CREATE TABLE x1(x);
INSERT INTO x1 VALUES('john'), ('paul'), ('george'), ('ringo');
INSERT INTO t1 SELECT x FROM x1;
SELECT last_insert_rowid();
} {226}
do_execsql_test 1.6 {
INSERT INTO t1(rowid, str) SELECT rowid+10, x FROM x1;
SELECT last_insert_rowid();
} {14}
finish_test

View File

@@ -21,6 +21,10 @@
*/ */
#ifdef SQLITE_USER_AUTHENTICATION #ifdef SQLITE_USER_AUTHENTICATION
#ifdef __cplusplus
extern "C" {
#endif
/* /*
** If a database contains the SQLITE_USER table, then the ** If a database contains the SQLITE_USER table, then the
** sqlite3_user_authenticate() interface must be invoked with an ** sqlite3_user_authenticate() interface must be invoked with an
@@ -85,4 +89,8 @@ int sqlite3_user_delete(
const char *zUsername /* Username to remove */ const char *zUsername /* Username to remove */
); );
#ifdef __cplusplus
} /* end of the 'extern "C"' block */
#endif
#endif /* SQLITE_USER_AUTHENTICATION */ #endif /* SQLITE_USER_AUTHENTICATION */

View File

@@ -1,5 +1,5 @@
C Add\stwo\sNEVER()\soperators\sin\sthe\ssqlite3BtreeRowCountEst()\sroutine. C Merge\srecent\strunk\senhancements.
D 2017-02-23T02:15:33.201 D 2017-03-02T13:22:04.261
F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918 F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc a89ea37ab5928026001569f056973b9059492fe2 F Makefile.msc a89ea37ab5928026001569f056973b9059492fe2
@@ -70,7 +70,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314 F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c c4d7eecb12de9749851bcab6e5ca616a5803047a F ext/fts3/fts3.c 95c7041ea75d82d2d9a4cd058904ba889751f5b8
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
@@ -106,7 +106,7 @@ F ext/fts5/fts5_expr.c c6ecc2280162a3714d15dce2a8f2299f748b627c
F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2 F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2
F ext/fts5/fts5_index.c f67032a9a529ba52a545e6e3ab970764199c05d4 F ext/fts5/fts5_index.c f67032a9a529ba52a545e6e3ab970764199c05d4
F ext/fts5/fts5_main.c f85281445dcf8be32d18841c93a6f90fe27dbfe2 F ext/fts5/fts5_main.c f85281445dcf8be32d18841c93a6f90fe27dbfe2
F ext/fts5/fts5_storage.c de0ed8a06738bde433afe11e92295ceaffbc4e58 F ext/fts5/fts5_storage.c 8f0e65cb33bde8f449e1c9b4be4600d18b4da6e9
F ext/fts5/fts5_tcl.c 4a901f00c8553740dba63511603f5527d741c26a F ext/fts5/fts5_tcl.c 4a901f00c8553740dba63511603f5527d741c26a
F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc
F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be
@@ -165,6 +165,7 @@ F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741
F ext/fts5/test/fts5fuzz1.test bece4695fc169b61ab236ada7931c6e4942cbef9 F ext/fts5/test/fts5fuzz1.test bece4695fc169b61ab236ada7931c6e4942cbef9
F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d
F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d F ext/fts5/test/fts5integrity.test f5e4f8d284385875068ad0f3e894ce43e9de835d
F ext/fts5/test/fts5lastrowid.test 4fac1aba696dd6c956e03b0cf91f6f1f3aaec494
F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b F ext/fts5/test/fts5matchinfo.test f7dde99697bcb310ea8faa8eb2714d9f4dfc0e1b
F ext/fts5/test/fts5merge.test 9f65f090d214ff865c56bef4f864aaa1182af6e3 F ext/fts5/test/fts5merge.test 9f65f090d214ff865c56bef4f864aaa1182af6e3
F ext/fts5/test/fts5merge2.test a6da3c16d694235938d1939f503cfa53f0943d75 F ext/fts5/test/fts5merge2.test a6da3c16d694235938d1939f503cfa53f0943d75
@@ -313,7 +314,7 @@ F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
F ext/session/sqlite3session.c 13642d9c754cc18f17e141f82860d269e2adf920 F ext/session/sqlite3session.c 13642d9c754cc18f17e141f82860d269e2adf920
F ext/session/sqlite3session.h d4db650adfcc7a4360e9f12a09c2d117b1db6b53 F ext/session/sqlite3session.h d4db650adfcc7a4360e9f12a09c2d117b1db6b53
F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386 F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220 F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
@@ -338,7 +339,7 @@ F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33 F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
F src/btree.c 19746a7db19308053ff6cb2ac002834822809e54 F src/btree.c 83e2bc48be6e09eb88e312eb791f4bbd96986d93
F src/btree.h bf64dfeeddeebdb775a5eba0098bbc00d073290d F src/btree.h bf64dfeeddeebdb775a5eba0098bbc00d073290d
F src/btreeInt.h cd55d39d9916270837a88c12e701047cba0729b0 F src/btreeInt.h cd55d39d9916270837a88c12e701047cba0729b0
F src/build.c 43f903c9082040ced2b421543cb0300c2973647d F src/build.c 43f903c9082040ced2b421543cb0300c2973647d
@@ -360,7 +361,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 3ed64afc49c0a2221e397b9f65d231ffbef506fe F src/insert.c 3ed64afc49c0a2221e397b9f65d231ffbef506fe
F src/legacy.c e88ed13c2d531decde75d42c2e35623fb9ce3cb0 F src/legacy.c e88ed13c2d531decde75d42c2e35623fb9ce3cb0
F src/loadext.c a68d8d1d14cf7488bb29dc5311cb1ce9a4404258 F src/loadext.c a68d8d1d14cf7488bb29dc5311cb1ce9a4404258
F src/main.c e207b81542d13b9f13d61e78ca441f9781f055b0 F src/main.c 158326243c5ddc8b98a1e983fa488650cf76d760
F src/malloc.c d0a1474236486165bcb349af82e2a6560178bf7b F src/malloc.c d0a1474236486165bcb349af82e2a6560178bf7b
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c fd7cd6fe21d46fe0a4186367dd8dc26d87b787eb F src/mem1.c fd7cd6fe21d46fe0a4186367dd8dc26d87b787eb
@@ -396,8 +397,8 @@ F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c f9bc0de45a30a450da47b3766de00be89bf9be79 F src/resolve.c f9bc0de45a30a450da47b3766de00be89bf9be79
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c d12f3539f80db38b09015561b569e0eb1c4b6c5f F src/select.c d12f3539f80db38b09015561b569e0eb1c4b6c5f
F src/shell.c bf976d5301be9d8a4c52852c97909cc9a41ee20d F src/shell.c 27d2b31099fd2cd749e44d025ef9b54ca26692cb
F src/sqlite.h.in 751ff125eb159c8f92c182b8df980a5e4f50e966 F src/sqlite.h.in 4d0c08f8640c586564a7032b259c5f69bf397850
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
F src/sqliteInt.h df268ce1d04df042cf43b557d2309eb0b71e86c4 F src/sqliteInt.h df268ce1d04df042cf43b557d2309eb0b71e86c4
@@ -465,8 +466,8 @@ F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569
F src/vdbe.c f520378e510fd36bbf289921798dbc8f2b3dc30d F src/vdbe.c f520378e510fd36bbf289921798dbc8f2b3dc30d
F src/vdbe.h 59998ffd71d7caa8886bc78dafaf8caeccd4c13c F src/vdbe.h 59998ffd71d7caa8886bc78dafaf8caeccd4c13c
F src/vdbeInt.h 4e4b15b2e1330e1636e4e01974eab2b0b985092f F src/vdbeInt.h 4e4b15b2e1330e1636e4e01974eab2b0b985092f
F src/vdbeapi.c 3e4a8893feeb78620f4aac4ac5b85d92255b97e1 F src/vdbeapi.c 70aabe108c411e529a59d8800445513965334062
F src/vdbeaux.c 2f48204a0f2875b098ee046bba9265907297b0b5 F src/vdbeaux.c b632f9151a296c5eb22a2cc955c487ebc2347cb6
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9 F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
F src/vdbemem.c 3b5a9a5b375458d3e12a50ae1aaa41eeec2175fd F src/vdbemem.c 3b5a9a5b375458d3e12a50ae1aaa41eeec2175fd
F src/vdbesort.c eda25cb2d1727efca6f7862fea32b8aa33c0face F src/vdbesort.c eda25cb2d1727efca6f7862fea32b8aa33c0face
@@ -807,6 +808,7 @@ F test/fts4growth.test e5390da74619cacc389711bac9349640b32c4f9a
F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269 F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
F test/fts4langid.test 65a7332c9bc257919e259a304aa8a38c41655b9d F test/fts4langid.test 65a7332c9bc257919e259a304aa8a38c41655b9d
F test/fts4lastrowid.test fa5e157955a3121615ef3e16ff5196e96c9e1e64
F test/fts4merge.test d2b39f6b1bd4a9738a13540e2d044cba11c43d47 F test/fts4merge.test d2b39f6b1bd4a9738a13540e2d044cba11c43d47
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891 F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0 F test/fts4merge3.test 8d9ccb4a3d41c4c617a149d6c4b13ad02de797d0
@@ -1468,10 +1470,10 @@ F test/wordcount.c 06efb84b7c48a4973c2c24ea06c93d00bce24389
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5 F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
F tool/GetTclKit.bat f94784e3bdc2f50c539266f5467cbf1f27612cb3 F tool/GetTclKit.bat 6afa640edc7810725aec61c3076ac617c4aaf0b7
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91 F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
F tool/addopcodes.tcl 10c889c4a65ec6c5604e4a47306fa77ff57ae189 F tool/addopcodes.tcl 10c889c4a65ec6c5604e4a47306fa77ff57ae189
F tool/build-all-msvc.bat 018c1b273458a90c8ba633c6f0c5654cfcb138bf x F tool/build-all-msvc.bat c12328d06c45fec8baada5949e3d5af54bf8c887 x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367 F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2 F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
@@ -1558,7 +1560,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 188300a337c87b7ee0dd1f4b9a4f1bd80e70cca4 P 7a959f6d1ea038988cdb4c02d6f37abaec2580a0 29f54b899e5cf22ece98ab41c39c41d75a4b228d
R ea4c0d1070247cd8f7e1aa7ed210345c R 6bb37f552ece3665cee38d0fc37ff06c
U drh U drh
Z 01ff8d763fbc7e4c3e39020edd5b116b Z 8ce562b5567814952b66c349d10ab9fa

View File

@@ -1 +1 @@
7a959f6d1ea038988cdb4c02d6f37abaec2580a0 c60cdb47612c05c252613e50a8ac10635469fdfe

View File

@@ -1317,17 +1317,18 @@ static void ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell, int *pRC){
/* /*
** Defragment the page given. All Cells are moved to the ** Defragment the page given. This routine reorganizes cells within the
** end of the page and all free space is collected into one ** page so that there are no free-blocks on the free-block list.
** big FreeBlk that occurs in between the header and cell **
** pointer array and the cell content area. ** Parameter nMaxFrag is the maximum amount of fragmented space that may be
** present in the page after this routine returns.
** **
** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a ** EVIDENCE-OF: R-44582-60138 SQLite may from time to time reorganize a
** b-tree page so that there are no freeblocks or fragment bytes, all ** b-tree page so that there are no freeblocks or fragment bytes, all
** unused bytes are contained in the unallocated space region, and all ** unused bytes are contained in the unallocated space region, and all
** cells are packed tightly at the end of the page. ** cells are packed tightly at the end of the page.
*/ */
static int defragmentPage(MemPage *pPage){ static int defragmentPage(MemPage *pPage, int nMaxFrag){
int i; /* Loop counter */ int i; /* Loop counter */
int pc; /* Address of the i-th cell */ int pc; /* Address of the i-th cell */
int hdr; /* Offset to the page header */ int hdr; /* Offset to the page header */
@@ -1342,7 +1343,6 @@ static int defragmentPage(MemPage *pPage){
int iCellFirst; /* First allowable cell index */ int iCellFirst; /* First allowable cell index */
int iCellLast; /* Last possible cell index */ int iCellLast; /* Last possible cell index */
assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) );
assert( pPage->pBt!=0 ); assert( pPage->pBt!=0 );
assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE );
@@ -1354,10 +1354,44 @@ static int defragmentPage(MemPage *pPage){
cellOffset = pPage->cellOffset; cellOffset = pPage->cellOffset;
nCell = pPage->nCell; nCell = pPage->nCell;
assert( nCell==get2byte(&data[hdr+3]) ); assert( nCell==get2byte(&data[hdr+3]) );
iCellFirst = cellOffset + 2*nCell;
/* This block handles pages with two or fewer free blocks and nMaxFrag
** or fewer fragmented bytes. In this case it is faster to move the
** two (or one) blocks of cells using memmove() and add the required
** offsets to each pointer in the cell-pointer array than it is to
** reconstruct the entire page. */
if( (int)data[hdr+7]<=nMaxFrag ){
int iFree = get2byte(&data[hdr+1]);
if( iFree ){
int iFree2 = get2byte(&data[iFree]);
if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
u8 *pEnd = &data[cellOffset + nCell*2];
u8 *pAddr;
int sz2 = 0;
int sz = get2byte(&data[iFree+2]);
int top = get2byte(&data[hdr+5]);
if( iFree2 ){
sz2 = get2byte(&data[iFree2+2]);
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
sz += sz2;
}
cbrk = top+sz;
memmove(&data[cbrk], &data[top], iFree-top);
for(pAddr=&data[cellOffset]; pAddr<pEnd; pAddr+=2){
pc = get2byte(pAddr);
if( pc<iFree ){ put2byte(pAddr, pc+sz); }
else if( pc<iFree2 ){ put2byte(pAddr, pc+sz2); }
}
goto defragment_out;
}
}
}
usableSize = pPage->pBt->usableSize; usableSize = pPage->pBt->usableSize;
cbrk = usableSize; cbrk = usableSize;
iCellFirst = cellOffset + 2*nCell;
iCellLast = usableSize - 4; iCellLast = usableSize - 4;
for(i=0; i<nCell; i++){ for(i=0; i<nCell; i++){
u8 *pAddr; /* The i-th cell pointer */ u8 *pAddr; /* The i-th cell pointer */
pAddr = &data[cellOffset + i*2]; pAddr = &data[cellOffset + i*2];
@@ -1390,16 +1424,18 @@ static int defragmentPage(MemPage *pPage){
} }
memcpy(&data[cbrk], &src[pc], size); memcpy(&data[cbrk], &src[pc], size);
} }
data[hdr+7] = 0;
defragment_out:
if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
return SQLITE_CORRUPT_BKPT;
}
assert( cbrk>=iCellFirst ); assert( cbrk>=iCellFirst );
put2byte(&data[hdr+5], cbrk); put2byte(&data[hdr+5], cbrk);
data[hdr+1] = 0; data[hdr+1] = 0;
data[hdr+2] = 0; data[hdr+2] = 0;
data[hdr+7] = 0;
memset(&data[iCellFirst], 0, cbrk-iCellFirst); memset(&data[iCellFirst], 0, cbrk-iCellFirst);
assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) );
if( cbrk-iCellFirst!=pPage->nFree ){
return SQLITE_CORRUPT_BKPT;
}
return SQLITE_OK; return SQLITE_OK;
} }
@@ -1537,10 +1573,10 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
testcase( gap+2+nByte==top ); testcase( gap+2+nByte==top );
if( gap+2+nByte>top ){ if( gap+2+nByte>top ){
assert( pPage->nCell>0 || CORRUPT_DB ); assert( pPage->nCell>0 || CORRUPT_DB );
rc = defragmentPage(pPage); rc = defragmentPage(pPage, MIN(4, pPage->nFree - (2+nByte)));
if( rc ) return rc; if( rc ) return rc;
top = get2byteNotZero(&data[hdr+5]); top = get2byteNotZero(&data[hdr+5]);
assert( gap+nByte<=top ); assert( gap+2+nByte<=top );
} }
@@ -7713,7 +7749,7 @@ static int balance_nonroot(
** free space needs to be up front. ** free space needs to be up front.
*/ */
assert( nNew==1 || CORRUPT_DB ); assert( nNew==1 || CORRUPT_DB );
rc = defragmentPage(apNew[0]); rc = defragmentPage(apNew[0], -1);
testcase( rc!=SQLITE_OK ); testcase( rc!=SQLITE_OK );
assert( apNew[0]->nFree == assert( apNew[0]->nFree ==
(get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2) (get2byte(&apNew[0]->aData[5])-apNew[0]->cellOffset-apNew[0]->nCell*2)

View File

@@ -921,6 +921,21 @@ sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){
return db->lastRowid; return db->lastRowid;
} }
/*
** Set the value returned by the sqlite3_last_insert_rowid() API function.
*/
void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return;
}
#endif
sqlite3_mutex_enter(db->mutex);
db->lastRowid = iRowid;
sqlite3_mutex_leave(db->mutex);
}
/* /*
** Return the number of changes in the most recent call to sqlite3_exec(). ** Return the number of changes in the most recent call to sqlite3_exec().
*/ */

View File

@@ -4344,6 +4344,7 @@ static int do_meta_command(char *zLine, ShellState *p){
session_close_all(p); session_close_all(p);
sqlite3_close(p->db); sqlite3_close(p->db);
p->db = 0; p->db = 0;
p->zDbFilename = 0;
sqlite3_free(p->zFreeOnClose); sqlite3_free(p->zFreeOnClose);
p->zFreeOnClose = 0; p->zFreeOnClose = 0;
/* Check for command-line arguments */ /* Check for command-line arguments */

View File

@@ -2040,20 +2040,30 @@ int sqlite3_extended_result_codes(sqlite3*, int onoff);
** the table has a column of type [INTEGER PRIMARY KEY] then that column ** the table has a column of type [INTEGER PRIMARY KEY] then that column
** is another alias for the rowid. ** is another alias for the rowid.
** **
** ^The sqlite3_last_insert_rowid(D) interface returns the [rowid] of the ** ^The sqlite3_last_insert_rowid(D) interface usually returns the [rowid] of
** most recent successful [INSERT] into a rowid table or [virtual table] ** the most recent successful [INSERT] into a rowid table or [virtual table]
** on database connection D. ** on database connection D. ^Inserts into [WITHOUT ROWID] tables are not
** ^Inserts into [WITHOUT ROWID] tables are not recorded. ** recorded. ^If no successful [INSERT]s into rowid tables have ever occurred
** ^If no successful [INSERT]s into rowid tables ** on the database connection D, then sqlite3_last_insert_rowid(D) returns
** have ever occurred on the database connection D, ** zero.
** then sqlite3_last_insert_rowid(D) returns zero.
** **
** ^(If an [INSERT] occurs within a trigger or within a [virtual table] ** As well as being set automatically as rows are inserted into database
** method, then this routine will return the [rowid] of the inserted ** tables, the value returned by this function may be set explicitly by
** row as long as the trigger or virtual table method is running. ** [sqlite3_set_last_insert_rowid()]
** But once the trigger or virtual table method ends, the value returned **
** by this routine reverts to what it was before the trigger or virtual ** Some virtual table implementations may INSERT rows into rowid tables as
** table method began.)^ ** part of committing a transaction (e.g. to flush data accumulated in memory
** to disk). In this case subsequent calls to this function return the rowid
** associated with these internal INSERT operations, which leads to
** unintuitive results. Virtual table implementations that do write to rowid
** tables in this way can avoid this problem by restoring the original
** rowid value using [sqlite3_set_last_insert_rowid()] before returning
** control to the user.
**
** ^(If an [INSERT] occurs within a trigger then this routine will
** return the [rowid] of the inserted row as long as the trigger is
** running. Once the trigger program ends, the value returned
** by this routine reverts to what it was before the trigger was fired.)^
** **
** ^An [INSERT] that fails due to a constraint violation is not a ** ^An [INSERT] that fails due to a constraint violation is not a
** successful [INSERT] and does not change the value returned by this ** successful [INSERT] and does not change the value returned by this
@@ -2080,6 +2090,16 @@ int sqlite3_extended_result_codes(sqlite3*, int onoff);
*/ */
sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*); sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
/*
** CAPI3REF: Set the Last Insert Rowid value.
** METHOD: sqlite3
**
** The sqlite3_set_last_insert_rowid(D, R) method allows the application to
** set the value returned by calling sqlite3_last_insert_rowid(D) to R
** without inserting a row into the database.
*/
void sqlite3_set_last_insert_rowid(sqlite3*,sqlite3_int64);
/* /*
** CAPI3REF: Count The Number Of Rows Modified ** CAPI3REF: Count The Number Of Rows Modified
** METHOD: sqlite3 ** METHOD: sqlite3

View File

@@ -154,7 +154,8 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
sqlite3VdbeMemRelease(&p->aVar[i]); sqlite3VdbeMemRelease(&p->aVar[i]);
p->aVar[i].flags = MEM_Null; p->aVar[i].flags = MEM_Null;
} }
if( p->isPrepareV2 && p->expmask ){ assert( p->isPrepareV2 || p->expmask==0 );
if( p->expmask ){
p->expired = 1; p->expired = 1;
} }
sqlite3_mutex_leave(mutex); sqlite3_mutex_leave(mutex);
@@ -1258,9 +1259,8 @@ static int vdbeUnbind(Vdbe *p, int i){
** as if there had been a schema change, on the first sqlite3_step() call ** as if there had been a schema change, on the first sqlite3_step() call
** following any change to the bindings of that parameter. ** following any change to the bindings of that parameter.
*/ */
if( p->isPrepareV2 && assert( p->isPrepareV2 || p->expmask==0 );
((i<32 && p->expmask & ((u32)1 << i)) || p->expmask==0xffffffff) if( p->expmask & ((u32)1 << (i&0x001F)) && (i<32 || p->expmask==0xffffffff) ){
){
p->expired = 1; p->expired = 1;
} }
return SQLITE_OK; return SQLITE_OK;
@@ -1523,10 +1523,12 @@ int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
if( pFrom->nVar!=pTo->nVar ){ if( pFrom->nVar!=pTo->nVar ){
return SQLITE_ERROR; return SQLITE_ERROR;
} }
if( pTo->isPrepareV2 && pTo->expmask ){ assert( pTo->isPrepareV2 || pTo->expmask==0 );
if( pTo->expmask ){
pTo->expired = 1; pTo->expired = 1;
} }
if( pFrom->isPrepareV2 && pFrom->expmask ){ assert( pFrom->isPrepareV2 || pFrom->expmask==0 );
if( pFrom->expmask ){
pFrom->expired = 1; pFrom->expired = 1;
} }
return sqlite3TransferBindings(pFromStmt, pToStmt); return sqlite3TransferBindings(pFromStmt, pToStmt);

View File

@@ -57,6 +57,7 @@ void sqlite3VdbeError(Vdbe *p, const char *zFormat, ...){
void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
assert( isPrepareV2==1 || isPrepareV2==0 ); assert( isPrepareV2==1 || isPrepareV2==0 );
if( p==0 ) return; if( p==0 ) return;
if( !isPrepareV2 ) p->expmask = 0;
#if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG) #if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG)
if( !isPrepareV2 ) return; if( !isPrepareV2 ) return;
#endif #endif
@@ -85,6 +86,7 @@ void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
pA->zSql = pB->zSql; pA->zSql = pB->zSql;
pB->zSql = zTmp; pB->zSql = zTmp;
pB->isPrepareV2 = pA->isPrepareV2; pB->isPrepareV2 = pA->isPrepareV2;
pB->expmask = pA->expmask;
} }
/* /*

73
test/fts4lastrowid.test Normal file
View File

@@ -0,0 +1,73 @@
# 2017 Feb 27
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# Tests of the last_insert_rowid functionality with fts4.
#
set testdir [file dirname $argv0]
source [file join [file dirname [info script]] tester.tcl]
set testprefix fts4lastrowid
ifcapable !fts3 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts4(str);
}
do_execsql_test 1.1 {
INSERT INTO t1 VALUES('one string');
INSERT INTO t1 VALUES('two string');
INSERT INTO t1 VALUES('three string');
SELECT last_insert_rowid();
} {3}
do_execsql_test 1.2 {
BEGIN;
INSERT INTO t1 VALUES('one string');
INSERT INTO t1 VALUES('two string');
INSERT INTO t1 VALUES('three string');
COMMIT;
SELECT last_insert_rowid();
} {6}
do_execsql_test 1.3 {
INSERT INTO t1(rowid, str) VALUES(-22, 'some more text');
SELECT last_insert_rowid();
} {-22}
do_execsql_test 1.4 {
BEGIN;
INSERT INTO t1(rowid, str) VALUES(45, 'some more text');
INSERT INTO t1(rowid, str) VALUES(46, 'some more text');
INSERT INTO t1(rowid, str) VALUES(222, 'some more text');
SELECT last_insert_rowid();
COMMIT;
SELECT last_insert_rowid();
} {222 222}
do_execsql_test 1.5 {
CREATE TABLE x1(x);
INSERT INTO x1 VALUES('john'), ('paul'), ('george'), ('ringo');
INSERT INTO t1 SELECT x FROM x1;
SELECT last_insert_rowid();
} {226}
do_execsql_test 1.6 {
INSERT INTO t1(rowid, str) SELECT rowid+10, x FROM x1;
SELECT last_insert_rowid();
} {14}
finish_test

View File

@@ -124,7 +124,7 @@ IF NOT EXIST "%FRAMEWORKDIR%\csc.exe" (
GOTO errors GOTO errors
) )
SET PATH=%FRAMEWORKDIR%;%PATH% CALL :fn_PrependToPath FRAMEWORKDIR
:skip_addToPath :skip_addToPath
@@ -246,6 +246,18 @@ GOTO no_errors
ENDLOCAL && SET %1=%VALUE% ENDLOCAL && SET %1=%VALUE%
GOTO :EOF GOTO :EOF
:fn_PrependToPath
IF NOT DEFINED %1 GOTO :EOF
SETLOCAL
SET __ECHO_CMD=ECHO %%%1%%
FOR /F "delims=" %%V IN ('%__ECHO_CMD%') DO (
SET VALUE=%%V
)
SET VALUE=%VALUE:"=%
REM "
ENDLOCAL && SET PATH=%VALUE%;%PATH%
GOTO :EOF
:fn_ResetErrorLevel :fn_ResetErrorLevel
VERIFY > NUL VERIFY > NUL
GOTO :EOF GOTO :EOF

View File

@@ -460,7 +460,7 @@ FOR %%P IN (%PLATFORMS%) DO (
REM REM
REM NOTE: Reset the PATH here to the absolute bare minimum required. REM NOTE: Reset the PATH here to the absolute bare minimum required.
REM REM
SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot% CALL :fn_ResetPath
REM REM
REM NOTE: This is the inner loop. There are normally two iterations, one REM NOTE: This is the inner loop. There are normally two iterations, one
@@ -818,6 +818,10 @@ GOTO no_errors
CALL :fn_ResetErrorLevel CALL :fn_ResetErrorLevel
GOTO :EOF GOTO :EOF
:fn_ResetPath
SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot%
GOTO :EOF
:fn_AppendVariable :fn_AppendVariable
SET __ECHO_CMD=ECHO %%%1%% SET __ECHO_CMD=ECHO %%%1%%
IF DEFINED %1 ( IF DEFINED %1 (