1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-14 00:22:38 +03:00

Merge with main branch.

FossilOrigin-Name: 6e09e28751a7071969ef9f3445f4092d2c28f358
This commit is contained in:
dan
2009-08-31 05:39:58 +00:00
11 changed files with 266 additions and 209 deletions

View File

@@ -1 +1 @@
3.6.17 3.6.18

BIN
art/src_logo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

20
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.62 for sqlite 3.6.17. # Generated by GNU Autoconf 2.62 for sqlite 3.6.18.
# #
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
@@ -743,8 +743,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package. # Identity of this package.
PACKAGE_NAME='sqlite' PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite' PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.6.17' PACKAGE_VERSION='3.6.18'
PACKAGE_STRING='sqlite 3.6.17' PACKAGE_STRING='sqlite 3.6.18'
PACKAGE_BUGREPORT='' PACKAGE_BUGREPORT=''
# Factoring default headers for most tests. # Factoring default headers for most tests.
@@ -1487,7 +1487,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures sqlite 3.6.17 to adapt to many kinds of systems. \`configure' configures sqlite 3.6.18 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1552,7 +1552,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.6.17:";; short | recursive ) echo "Configuration of sqlite 3.6.18:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@@ -1670,7 +1670,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
sqlite configure 3.6.17 sqlite configure 3.6.18
generated by GNU Autoconf 2.62 generated by GNU Autoconf 2.62
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1684,7 +1684,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.6.17, which was It was created by sqlite $as_me 3.6.18, which was
generated by GNU Autoconf 2.62. Invocation command line was generated by GNU Autoconf 2.62. Invocation command line was
$ $0 $@ $ $0 $@
@@ -2065,7 +2065,7 @@ please regen with autoconf" >&2;}
fi fi
# The following RCS revision string applies to configure.in # The following RCS revision string applies to configure.in
# $Revision: 1.74 $ # $Revision: 1.56 $
######### #########
# Programs needed # Programs needed
@@ -13972,7 +13972,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by sqlite $as_me 3.6.17, which was This file was extended by sqlite $as_me 3.6.18, which was
generated by GNU Autoconf 2.62. Invocation command line was generated by GNU Autoconf 2.62. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@@ -14025,7 +14025,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_version="\\ ac_cs_version="\\
sqlite config.status 3.6.17 sqlite config.status 3.6.18
configured by $0, generated by GNU Autoconf 2.62, configured by $0, generated by GNU Autoconf 2.62,
with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"

View File

@@ -1,11 +1,11 @@
C Fix\sanother\stest\sproblem\sand\ssome\sinstances\swhere\san\sOOM\smay\scause\sa\ssegfault. C Merge\swith\smain\sbranch.
D 2009-08-31T05:23:33 D 2009-08-31T05:39:59
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 73ddeec9dd10b85876c5c2ce1fdce627e1dcc7f8 F Makefile.in 73ddeec9dd10b85876c5c2ce1fdce627e1dcc7f8
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F Makefile.vxworks 10010ddbf52e2503c7c49c7c0b7c7a096f8638a6 F Makefile.vxworks 10010ddbf52e2503c7c49c7c0b7c7a096f8638a6
F README b974cdc3f9f12b87e851b04e75996d720ebf81ac F README b974cdc3f9f12b87e851b04e75996d720ebf81ac
F VERSION 8fd162479ea9d3932d4492a889db80634742fe90 F VERSION 7260e7baf934051dee42458206e915b75570f41d
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F addopcodes.awk 215333be9d99c260e076c3080a81dba3ae928c45 F addopcodes.awk 215333be9d99c260e076c3080a81dba3ae928c45
F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248 F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248
@@ -15,10 +15,11 @@ F art/SQLiteLogo3.tiff b9e6bf022ae939bc986cddb8ab99583ca1b02cb3
F art/SQLite_big.gif 2b8e4603b91ba2a2c7062a82ff570d945034bb30 F art/SQLite_big.gif 2b8e4603b91ba2a2c7062a82ff570d945034bb30
F art/nocopy.gif 716aa07d4bb7250d4e75756073bf8ef9f56bec8f F art/nocopy.gif 716aa07d4bb7250d4e75756073bf8ef9f56bec8f
F art/powered_by_sqlite.gif 7fbcd7d3675391fd3d21672c14c05f5999eb60d1 F art/powered_by_sqlite.gif 7fbcd7d3675391fd3d21672c14c05f5999eb60d1
F art/src_logo.gif 9341ef09f0e53cd44c0c9b6fc3c16f7f3d6c2ad9
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 868fdb48c028421a203470e15c69ada15b9ba673 F config.h.in 868fdb48c028421a203470e15c69ada15b9ba673
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55 F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure 486c870218ec915bd8edfece7109b6c864e82a5a F configure bccfdabb9982b7e88a33470741f1d6ba14a6b684
F configure.ac 14740970ddb674d92a9f5da89083dff1179014ff F configure.ac 14740970ddb674d92a9f5da89083dff1179014ff
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538 F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
@@ -105,7 +106,7 @@ F src/auth.c 802a9439dfa0b8c208b10055cba400e82ef18025
F src/backup.c 6f1c2d9862c8a3feb7739dfcca02c1f5352e37f3 F src/backup.c 6f1c2d9862c8a3feb7739dfcca02c1f5352e37f3
F src/bitvec.c e08f6c1a9551b88081fc737916c6c3fd5029a6cf F src/bitvec.c e08f6c1a9551b88081fc737916c6c3fd5029a6cf
F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7 F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7
F src/btree.c 49212ddaee8d7d12b4f1e17b9de62f7ea91ca59d F src/btree.c 6b60ece56141bbe23aa6efca10f1612d34271c2f
F src/btree.h 577448a890c2ab9b21e6ab74f073526184bceebe F src/btree.h 577448a890c2ab9b21e6ab74f073526184bceebe
F src/btreeInt.h 1c86297e69380f6577e7ae67452597dd8d5c2705 F src/btreeInt.h 1c86297e69380f6577e7ae67452597dd8d5c2705
F src/build.c 212476dc971756e7f7429e677059fafc678afbd5 F src/build.c 212476dc971756e7f7429e677059fafc678afbd5
@@ -144,7 +145,7 @@ F src/os.c 9fea283e336ee31caa4654d6cb05a129a1c42d2f
F src/os.h 00a1334a4eecee7f7bef79ac606b88d325119f21 F src/os.h 00a1334a4eecee7f7bef79ac606b88d325119f21
F src/os_common.h 8c61457df58f1a4bd5f5adc3e90e01b37bf7afbc F src/os_common.h 8c61457df58f1a4bd5f5adc3e90e01b37bf7afbc
F src/os_os2.c bed77dc26e3a95ce4a204936b9a1ca6fe612fcc5 F src/os_os2.c bed77dc26e3a95ce4a204936b9a1ca6fe612fcc5
F src/os_unix.c 1546de71b888c9a2bb0589d04e7e4267d40ef944 F src/os_unix.c f14ff07aec3c3c0796e1a743d1bdafddc15d1af1
F src/os_win.c 58bb163f327e79726dd119344d908e4d98483c3f F src/os_win.c 58bb163f327e79726dd119344d908e4d98483c3f
F src/pager.c a47be286477ed6c7b9a342dd53d4e4043f29d8c2 F src/pager.c a47be286477ed6c7b9a342dd53d4e4043f29d8c2
F src/pager.h 11852d044c86cf5a9d6e34171fb0c4fcf1f6265f F src/pager.h 11852d044c86cf5a9d6e34171fb0c4fcf1f6265f
@@ -160,7 +161,7 @@ F src/resolve.c 92ef8a85d53b305a7de9faef27d652b96c2b4db6
F src/rowset.c c64dafba1f9fd876836c8db8682966b9d197eb1f F src/rowset.c c64dafba1f9fd876836c8db8682966b9d197eb1f
F src/select.c 56ecb073e6f6696173ad80493aa14355225b6e53 F src/select.c 56ecb073e6f6696173ad80493aa14355225b6e53
F src/shell.c db2643650b9268df89a4bedca3f1c6d9e786f1bb F src/shell.c db2643650b9268df89a4bedca3f1c6d9e786f1bb
F src/sqlite.h.in 3ccf717d82101f19548d0b1243f0a6f4854d51ee F src/sqlite.h.in 9d03ceaad971882482c158c0e3d39d361c2c18a1
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
F src/sqliteInt.h d87eb4976edacb68fb9b7557163ae0def733354b F src/sqliteInt.h d87eb4976edacb68fb9b7557163ae0def733354b
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
@@ -208,12 +209,12 @@ F src/vdbe.c 5e9d870ec390fbc329f11424b121681e8da5d75c
F src/vdbe.h 080fe6bc1264438becb8bf9b9f3c84074c336b78 F src/vdbe.h 080fe6bc1264438becb8bf9b9f3c84074c336b78
F src/vdbeInt.h 1291908344bcbaa8cf47de86d7108cb92c3a71a3 F src/vdbeInt.h 1291908344bcbaa8cf47de86d7108cb92c3a71a3
F src/vdbeapi.c 8d5013ab6104be757c208a70ffb191cc27d2b688 F src/vdbeapi.c 8d5013ab6104be757c208a70ffb191cc27d2b688
F src/vdbeaux.c d8ca68164d20c5b65dfa713095febcb5d37d45b0 F src/vdbeaux.c 1cc9dd48848059d1c1cd05775659323e0a8654dc
F src/vdbeblob.c f93cb60ac388633ed3bde8a94ef161ad2dbfb689 F src/vdbeblob.c f93cb60ac388633ed3bde8a94ef161ad2dbfb689
F src/vdbemem.c dc551981833756ea34a3e0b238f759479e7cf526 F src/vdbemem.c dc551981833756ea34a3e0b238f759479e7cf526
F src/vtab.c 10df5c77cea34a49f2ad4e5de763f820d6223eb4 F src/vtab.c 10df5c77cea34a49f2ad4e5de763f820d6223eb4
F src/walker.c 1edca756275f158b80f20eb6f104c8d3fcc96a04 F src/walker.c 1edca756275f158b80f20eb6f104c8d3fcc96a04
F src/where.c b9ad2d2db4a7d1cda7bed8a7299eb73fde63b5b1 F src/where.c a3218dfcf32e3d933270b76a72b97065f24b3f2c
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45 F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
@@ -663,7 +664,7 @@ F test/tkt3929.test 6a4c3baefb4e75127356b7d675b5df42c35c00d1
F test/tkt3935.test e15261fedb9e30a4305a311da614a5d8e693c767 F test/tkt3935.test e15261fedb9e30a4305a311da614a5d8e693c767
F test/tkt3992.test 2ba939cc646eaa46761dfd55f975cad69bf4e254 F test/tkt3992.test 2ba939cc646eaa46761dfd55f975cad69bf4e254
F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd
F test/tkt4018.test f581cf52dc359171875cb649bdc38b525d7b9309 F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7 F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
F test/trace.test 19ffbc09885c3321d56358a5738feae8587fb377 F test/trace.test 19ffbc09885c3321d56358a5738feae8587fb377
F test/trans.test d887cb07630dc39879a322d958ad8b006137485c F test/trans.test d887cb07630dc39879a322d958ad8b006137485c
@@ -747,7 +748,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746 F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746
P 9eb91efda5241609ff18ff15ef5eaa0e86788eab P 31199db0f77cf4b32d5589a29abd9535b155164b 6abcba1021b237452f542f1fbb69eb75d9f50f53
R 63b174d38f0bc479f8becc3f97b1ed05 R 31e80012e316e6ca372fbf461bf4b6ab
U dan U dan
Z 2a154fc741e40d1c8378264e43f74ea7 Z 33710f063b4132081e125750db8134c3

View File

@@ -1 +1 @@
31199db0f77cf4b32d5589a29abd9535b155164b 6e09e28751a7071969ef9f3445f4092d2c28f358

View File

@@ -4346,9 +4346,12 @@ int sqlite3BtreeMovetoUnpacked(
goto moveto_finish; goto moveto_finish;
} }
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0); rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
if( rc ){
sqlite3_free(pCellKey);
goto moveto_finish;
}
c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey); c = sqlite3VdbeRecordCompare(nCell, pCellKey, pIdxKey);
sqlite3_free(pCellKey); sqlite3_free(pCellKey);
if( rc ) goto moveto_finish;
} }
} }
if( c==0 ){ if( c==0 ){

View File

@@ -167,6 +167,19 @@
#define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY)) #define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY))
/*
** Sometimes, after a file handle is closed by SQLite, the file descriptor
** cannot be closed immediately. In these cases, instances of the following
** structure are used to store the file descriptor while waiting for an
** opportunity to either close or reuse it.
*/
typedef struct UnixUnusedFd UnixUnusedFd;
struct UnixUnusedFd {
int fd; /* File descriptor to close */
int flags; /* Flags this file descriptor was opened with */
UnixUnusedFd *pNext; /* Next unused file descriptor on same file */
};
/* /*
** The unixFile structure is subclass of sqlite3_file specific to the unix ** The unixFile structure is subclass of sqlite3_file specific to the unix
** VFS implementations. ** VFS implementations.
@@ -181,7 +194,7 @@ struct unixFile {
unsigned char locktype; /* The type of lock held on this fd */ unsigned char locktype; /* The type of lock held on this fd */
int lastErrno; /* The unix errno from the last I/O error */ int lastErrno; /* The unix errno from the last I/O error */
void *lockingContext; /* Locking style specific state */ void *lockingContext; /* Locking style specific state */
int flags; /* Flags value returned by xOpen() */ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */
#if SQLITE_ENABLE_LOCKING_STYLE #if SQLITE_ENABLE_LOCKING_STYLE
int openFlags; /* The flags specified at open() */ int openFlags; /* The flags specified at open() */
#endif #endif
@@ -748,14 +761,10 @@ struct unixOpenCnt {
struct unixFileId fileId; /* The lookup key */ struct unixFileId fileId; /* The lookup key */
int nRef; /* Number of pointers to this structure */ int nRef; /* Number of pointers to this structure */
int nLock; /* Number of outstanding locks */ int nLock; /* Number of outstanding locks */
int nPending; /* Number of pending close() operations */ UnixUnusedFd *pUnused; /* Unused file descriptors to close */
struct PendingClose {
int fd; /* File descriptor to close */
int flags; /* Flags this file descriptor was opened with */
} *aPending; /* Malloced space holding fds awaiting close() */
#if OS_VXWORKS #if OS_VXWORKS
sem_t *pSem; /* Named POSIX semaphore */ sem_t *pSem; /* Named POSIX semaphore */
char aSemName[MAX_PATHNAME+1]; /* Name of that semaphore */ char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */
#endif #endif
struct unixOpenCnt *pNext, *pPrev; /* List of all unixOpenCnt objects */ struct unixOpenCnt *pNext, *pPrev; /* List of all unixOpenCnt objects */
}; };
@@ -910,7 +919,7 @@ static void releaseOpenCnt(struct unixOpenCnt *pOpen){
assert( pOpen->pNext->pPrev==pOpen ); assert( pOpen->pNext->pPrev==pOpen );
pOpen->pNext->pPrev = pOpen->pPrev; pOpen->pNext->pPrev = pOpen->pPrev;
} }
sqlite3_free(pOpen->aPending); assert( !pOpen->pUnused );
sqlite3_free(pOpen); sqlite3_free(pOpen);
} }
} }
@@ -1028,19 +1037,12 @@ static int findLockInfo(
rc = SQLITE_NOMEM; rc = SQLITE_NOMEM;
goto exit_findlockinfo; goto exit_findlockinfo;
} }
memset(pOpen, 0, sizeof(*pOpen));
pOpen->fileId = fileId; pOpen->fileId = fileId;
pOpen->nRef = 1; pOpen->nRef = 1;
pOpen->nLock = 0;
pOpen->nPending = 0;
pOpen->aPending = 0;
pOpen->pNext = openList; pOpen->pNext = openList;
pOpen->pPrev = 0;
if( openList ) openList->pPrev = pOpen; if( openList ) openList->pPrev = pOpen;
openList = pOpen; openList = pOpen;
#if OS_VXWORKS
pOpen->pSem = NULL;
pOpen->aSemName[0] = '\0';
#endif
}else{ }else{
pOpen->nRef++; pOpen->nRef++;
} }
@@ -1405,57 +1407,46 @@ end_lock:
} }
/* /*
** Close all file descriptors accumuated in the p->aPending[] array. If ** Close all file descriptors accumuated in the unixOpenCnt->pUnused list.
** all such file descriptors are closed without error, the aPending[] ** If all such file descriptors are closed without error, the list is
** array is deleted and SQLITE_OK returned. ** cleared and SQLITE_OK returned.
** **
** Otherwise, if an error occurs, then successfully closed file descriptor ** Otherwise, if an error occurs, then successfully closed file descriptor
** entries in the aPending[] array are set to -1, the aPending[] array ** entries are removed from the list, and SQLITE_IOERR_CLOSE returned.
** not deleted and SQLITE_IOERR_CLOSE returned. ** not deleted and SQLITE_IOERR_CLOSE returned.
*/ */
static int closePendingFds(unixFile *pFile){ static int closePendingFds(unixFile *pFile){
struct unixOpenCnt *pOpen = pFile->pOpen;
struct PendingClose *aPending = pOpen->aPending;
int i;
int rc = SQLITE_OK; int rc = SQLITE_OK;
assert( unixMutexHeld() ); struct unixOpenCnt *pOpen = pFile->pOpen;
for(i=0; i<pOpen->nPending; i++){ UnixUnusedFd *pError = 0;
if( aPending[i].fd>=0 ){ UnixUnusedFd *p;
if( close(aPending[i].fd) ){ UnixUnusedFd *pNext;
pFile->lastErrno = errno; for(p=pOpen->pUnused; p; p=pNext){
rc = SQLITE_IOERR_CLOSE; pNext = p->pNext;
}else{ if( close(p->fd) ){
aPending[i].fd = -1; pFile->lastErrno = errno;
} rc = SQLITE_IOERR_CLOSE;
p->pNext = pError;
pError = p;
}else{
sqlite3_free(p);
} }
} }
if( rc==SQLITE_OK ){ pOpen->pUnused = pError;
sqlite3_free(aPending);
pOpen->nPending = 0;
pOpen->aPending = 0;
}
return rc; return rc;
} }
/* /*
** Add the file descriptor used by file handle pFile to the corresponding ** Add the file descriptor used by file handle pFile to the corresponding
** aPending[] array to be closed after some other connection releases ** pUnused list.
** a lock.
*/ */
static void setPendingFd(unixFile *pFile){ static void setPendingFd(unixFile *pFile){
struct PendingClose *aNew;
struct unixOpenCnt *pOpen = pFile->pOpen; struct unixOpenCnt *pOpen = pFile->pOpen;
int nByte = (pOpen->nPending+1)*sizeof(pOpen->aPending[0]); UnixUnusedFd *p = pFile->pUnused;
aNew = sqlite3_realloc(pOpen->aPending, nByte); p->pNext = pOpen->pUnused;
if( aNew==0 ){ pOpen->pUnused = p;
/* If a malloc fails, just leak the file descriptor */ pFile->h = -1;
}else{ pFile->pUnused = 0;
pOpen->aPending = aNew;
pOpen->aPending[pOpen->nPending].fd = pFile->h;
pOpen->aPending[pOpen->nPending].flags = pFile->flags;
pOpen->nPending++;
pFile->h = -1;
}
} }
/* /*
@@ -1573,7 +1564,7 @@ static int unixUnlock(sqlite3_file *id, int locktype){
pOpen = pFile->pOpen; pOpen = pFile->pOpen;
pOpen->nLock--; pOpen->nLock--;
assert( pOpen->nLock>=0 ); assert( pOpen->nLock>=0 );
if( pOpen->nLock==0 && pOpen->nPending>0 ){ if( pOpen->nLock==0 ){
int rc2 = closePendingFds(pFile); int rc2 = closePendingFds(pFile);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = rc2; rc = rc2;
@@ -1627,6 +1618,7 @@ static int closeUnixFile(sqlite3_file *id){
#endif #endif
OSTRACE2("CLOSE %-3d\n", pFile->h); OSTRACE2("CLOSE %-3d\n", pFile->h);
OpenCounter(-1); OpenCounter(-1);
sqlite3_free(pFile->pUnused);
memset(pFile, 0, sizeof(unixFile)); memset(pFile, 0, sizeof(unixFile));
} }
return SQLITE_OK; return SQLITE_OK;
@@ -1644,8 +1636,8 @@ static int unixClose(sqlite3_file *id){
if( pFile->pOpen && pFile->pOpen->nLock ){ if( pFile->pOpen && pFile->pOpen->nLock ){
/* If there are outstanding locks, do not actually close the file just /* If there are outstanding locks, do not actually close the file just
** yet because that would clear those locks. Instead, add the file ** yet because that would clear those locks. Instead, add the file
** descriptor to pOpen->aPending. It will be automatically closed when ** descriptor to pOpen->pUnused list. It will be automatically closed
** the last lock is cleared. ** when the last lock is cleared.
*/ */
setPendingFd(pFile); setPendingFd(pFile);
} }
@@ -2616,7 +2608,7 @@ static int afpUnlock(sqlite3_file *id, int locktype) {
struct unixOpenCnt *pOpen = pFile->pOpen; struct unixOpenCnt *pOpen = pFile->pOpen;
pOpen->nLock--; pOpen->nLock--;
assert( pOpen->nLock>=0 ); assert( pOpen->nLock>=0 );
if( pOpen->nLock==0 && pOpen->nPending>0 ){ if( pOpen->nLock==0 ){
rc = closePendingFds(pFile); rc = closePendingFds(pFile);
} }
} }
@@ -2734,7 +2726,7 @@ static int unixRead(
/* If this is a database file (not a journal, master-journal or temp /* If this is a database file (not a journal, master-journal or temp
** file), the bytes in the locking range should never be read or written. */ ** file), the bytes in the locking range should never be read or written. */
assert( (pFile->flags&SQLITE_OPEN_MAIN_DB)==0 assert( pFile->pUnused==0
|| offset>=PENDING_BYTE+512 || offset>=PENDING_BYTE+512
|| offset+amt<=PENDING_BYTE || offset+amt<=PENDING_BYTE
); );
@@ -2807,7 +2799,7 @@ static int unixWrite(
/* If this is a database file (not a journal, master-journal or temp /* If this is a database file (not a journal, master-journal or temp
** file), the bytes in the locking range should never be read or written. */ ** file), the bytes in the locking range should never be read or written. */
assert( (pFile->flags&SQLITE_OPEN_MAIN_DB)==0 assert( pFile->pUnused==0
|| offset>=PENDING_BYTE+512 || offset>=PENDING_BYTE+512
|| offset+amt<=PENDING_BYTE || offset+amt<=PENDING_BYTE
); );
@@ -3174,7 +3166,7 @@ static int unixDeviceCharacteristics(sqlite3_file *NotUsed){
** **
** (1) The real finder-function named "FImpt()". ** (1) The real finder-function named "FImpt()".
** **
** (2) A constant pointer to this functio named just "F". ** (2) A constant pointer to this function named just "F".
** **
** **
** A pointer to the F pointer is used as the pAppData value for VFS ** A pointer to the F pointer is used as the pAppData value for VFS
@@ -3438,13 +3430,10 @@ static int fillInUnixFile(
assert( pNew->pLock==NULL ); assert( pNew->pLock==NULL );
assert( pNew->pOpen==NULL ); assert( pNew->pOpen==NULL );
/* Parameter isDelete is only used on vxworks. /* Parameter isDelete is only used on vxworks. Express this explicitly
** Express this explicitly here to prevent compiler warnings ** here to prevent compiler warnings about unused parameters.
** about unused parameters.
*/ */
#if !OS_VXWORKS
UNUSED_PARAMETER(isDelete); UNUSED_PARAMETER(isDelete);
#endif
OSTRACE3("OPEN %-3d %s\n", h, zFilename); OSTRACE3("OPEN %-3d %s\n", h, zFilename);
pNew->h = h; pNew->h = h;
@@ -3474,6 +3463,28 @@ static int fillInUnixFile(
if( pLockingStyle == &posixIoMethods ){ if( pLockingStyle == &posixIoMethods ){
unixEnterMutex(); unixEnterMutex();
rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen); rc = findLockInfo(pNew, &pNew->pLock, &pNew->pOpen);
if( rc!=SQLITE_OK ){
/* If an error occured in findLockInfo(), close the file descriptor
** immediately, before releasing the mutex. findLockInfo() may fail
** in two scenarios:
**
** (a) A call to fstat() failed.
** (b) A malloc failed.
**
** Scenario (b) may only occur if the process is holding no other
** file descriptors open on the same file. If there were other file
** descriptors on this file, then no malloc would be required by
** findLockInfo(). If this is the case, it is quite safe to close
** handle h - as it is guaranteed that no posix locks will be released
** by doing so.
**
** If scenario (a) caused the error then things are not so safe. The
** implicit assumption here is that if fstat() fails, things are in
** such bad shape that dropping a lock or two doesn't matter much.
*/
close(h);
h = -1;
}
unixLeaveMutex(); unixLeaveMutex();
} }
@@ -3525,9 +3536,9 @@ static int fillInUnixFile(
if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){ if( (rc==SQLITE_OK) && (pNew->pOpen->pSem==NULL) ){
char *zSemName = pNew->pOpen->aSemName; char *zSemName = pNew->pOpen->aSemName;
int n; int n;
sqlite3_snprintf(MAX_PATHNAME, zSemName, "%s.sem", sqlite3_snprintf(MAX_PATHNAME, zSemName, "/%s.sem",
pNew->pId->zCanonicalName); pNew->pId->zCanonicalName);
for( n=0; zSemName[n]; n++ ) for( n=1; zSemName[n]; n++ )
if( zSemName[n]=='/' ) zSemName[n] = '_'; if( zSemName[n]=='/' ) zSemName[n] = '_';
pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1); pNew->pOpen->pSem = sem_open(zSemName, O_CREAT, 0666, 1);
if( pNew->pOpen->pSem == SEM_FAILED ){ if( pNew->pOpen->pSem == SEM_FAILED ){
@@ -3549,7 +3560,7 @@ static int fillInUnixFile(
#endif #endif
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
if( dirfd>=0 ) close(dirfd); /* silent leak if fail, already in error */ if( dirfd>=0 ) close(dirfd); /* silent leak if fail, already in error */
close(h); if( h>=0 ) close(h);
}else{ }else{
pNew->pMethod = pLockingStyle; pNew->pMethod = pLockingStyle;
OpenCounter(+1); OpenCounter(+1);
@@ -3674,8 +3685,15 @@ static int proxyTransformUnixFile(unixFile*, const char*);
** If a suitable file descriptor is found, then it is returned. If no ** If a suitable file descriptor is found, then it is returned. If no
** such file descriptor is located, -1 is returned. ** such file descriptor is located, -1 is returned.
*/ */
static int findReusableFd(const char *zPath, int flags){ static UnixUnusedFd *findReusableFd(const char *zPath, int flags){
int fd = -1; /* Return value */ UnixUnusedFd *pUnused = 0;
/* Do not search for an unused file descriptor on vxworks. Not because
** vxworks would not benefit from the change (it might, we're not sure),
** but because no way to test it is currently available. It is better
** not to risk breaking vxworks support for the sake of such an obscure
** feature. */
#if !OS_VXWORKS
struct stat sStat; /* Results of stat() call */ struct stat sStat; /* Results of stat() call */
/* A stat() call may fail for various reasons. If this happens, it is /* A stat() call may fail for various reasons. If this happens, it is
@@ -3687,28 +3705,25 @@ static int findReusableFd(const char *zPath, int flags){
** Even if a subsequent open() call does succeed, the consequences of ** Even if a subsequent open() call does succeed, the consequences of
** not searching for a resusable file descriptor are not dire. */ ** not searching for a resusable file descriptor are not dire. */
if( 0==stat(zPath, &sStat) ){ if( 0==stat(zPath, &sStat) ){
struct unixOpenCnt *p; struct unixOpenCnt *pO;
struct unixFileId id; struct unixFileId id;
id.dev = sStat.st_dev; id.dev = sStat.st_dev;
id.ino = sStat.st_ino; id.ino = sStat.st_ino;
unixEnterMutex(); unixEnterMutex();
for(p=openList; p&& memcmp(&id, &p->fileId, sizeof(id)); p=p->pNext); for(pO=openList; pO && memcmp(&id, &pO->fileId, sizeof(id)); pO=pO->pNext);
if( p && p->aPending ){ if( pO ){
int i; UnixUnusedFd **pp;
struct PendingClose *aPending = p->aPending; for(pp=&pO->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
for(i=0; i<p->nPending; i++){ pUnused = *pp;
if( aPending[i].fd>=0 && flags==aPending[i].flags ){ if( pUnused ){
fd = aPending[i].fd; *pp = pUnused->pNext;
aPending[i].fd = -1;
break;
}
} }
} }
unixLeaveMutex(); unixLeaveMutex();
} }
#endif /* if !OS_VXWORKS */
return fd; return pUnused;
} }
/* /*
@@ -3796,14 +3811,17 @@ static int unixOpen(
memset(p, 0, sizeof(unixFile)); memset(p, 0, sizeof(unixFile));
if( eType==SQLITE_OPEN_MAIN_DB ){ if( eType==SQLITE_OPEN_MAIN_DB ){
/* Try to find an unused file descriptor to reuse. This is not done UnixUnusedFd *pUnused;
** for vxworks. Not because vxworks would not benefit from the change pUnused = findReusableFd(zName, flags);
** (it might, we're not sure), but because no way to test it is if( pUnused ){
** currently available. It is better not to risk breaking vxworks for fd = pUnused->fd;
** the sake of such an obscure feature. */ }else{
#if !OS_VXWORKS pUnused = sqlite3_malloc(sizeof(*pUnused));
fd = findReusableFd(zName, flags); if( !pUnused ){
#endif return SQLITE_NOMEM;
}
}
p->pUnused = pUnused;
}else if( !zName ){ }else if( !zName ){
/* If zName is NULL, the upper layer is requesting a temp file. */ /* If zName is NULL, the upper layer is requesting a temp file. */
assert(isDelete && !isOpenDirectory); assert(isDelete && !isOpenDirectory);
@@ -3825,24 +3843,32 @@ static int unixOpen(
openFlags |= (O_LARGEFILE|O_BINARY); openFlags |= (O_LARGEFILE|O_BINARY);
if( fd<0 ){ if( fd<0 ){
fd = open(zName, openFlags, isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS); mode_t openMode = (isDelete?0600:SQLITE_DEFAULT_FILE_PERMISSIONS);
fd = open(zName, openFlags, openMode);
OSTRACE4("OPENX %-3d %s 0%o\n", fd, zName, openFlags); OSTRACE4("OPENX %-3d %s 0%o\n", fd, zName, openFlags);
if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){ if( fd<0 && errno!=EISDIR && isReadWrite && !isExclusive ){
/* Failed to open the file for read/write access. Try read-only. */ /* Failed to open the file for read/write access. Try read-only. */
flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE);
openFlags &= ~(O_RDWR|O_CREAT);
flags |= SQLITE_OPEN_READONLY; flags |= SQLITE_OPEN_READONLY;
return unixOpen(pVfs, zPath, pFile, flags, pOutFlags); openFlags |= O_RDONLY;
fd = open(zName, openFlags, openMode);
} }
if( fd<0 ){ if( fd<0 ){
return SQLITE_CANTOPEN; rc = SQLITE_CANTOPEN;
goto open_finished;
} }
} }
assert( fd>=0 ); assert( fd>=0 );
p->flags = flags;
if( pOutFlags ){ if( pOutFlags ){
*pOutFlags = flags; *pOutFlags = flags;
} }
if( p->pUnused ){
p->pUnused->fd = fd;
p->pUnused->flags = flags;
}
if( isDelete ){ if( isDelete ){
#if OS_VXWORKS #if OS_VXWORKS
zPath = zName; zPath = zName;
@@ -3861,11 +3887,11 @@ static int unixOpen(
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
/* It is safe to close fd at this point, because it is guaranteed not /* It is safe to close fd at this point, because it is guaranteed not
** to be open on a database file. If it were open on a database file, ** to be open on a database file. If it were open on a database file,
** it would not be safe to close as this would cause any locks held ** it would not be safe to close as this would release any locks held
** on the file by this process to be released. */ ** on the file by this process. */
assert( eType!=SQLITE_OPEN_MAIN_DB ); assert( eType!=SQLITE_OPEN_MAIN_DB );
close(fd); /* silently leak if fail, already in error */ close(fd); /* silently leak if fail, already in error */
return rc; goto open_finished;
} }
} }
@@ -3876,7 +3902,7 @@ static int unixOpen(
noLock = eType!=SQLITE_OPEN_MAIN_DB; noLock = eType!=SQLITE_OPEN_MAIN_DB;
#if SQLITE_PREFER_PROXY_LOCKING #if SQLITE_PREFER_PROXY_LOCKING
if( zPath!=NULL && !noLock ){ if( zPath!=NULL && !noLock && pVfs->xOpen ){
char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING"); char *envforce = getenv("SQLITE_FORCE_PROXY_LOCKING");
int useProxy = 0; int useProxy = 0;
@@ -3887,10 +3913,20 @@ static int unixOpen(
}else{ }else{
struct statfs fsInfo; struct statfs fsInfo;
if( statfs(zPath, &fsInfo) == -1 ){ if( statfs(zPath, &fsInfo) == -1 ){
((unixFile*)pFile)->lastErrno = errno; /* In theory, the close(fd) call is sub-optimal. If the file opened
if( dirfd>=0 ) close(dirfd); /* silently leak if fail, in error */ ** with fd is a database file, and there are other connections open
** on that file that are currently holding advisory locks on it,
** then the call to close() will cancel those locks. In practice,
** we're assuming that statfs() doesn't fail very often. At least
** not while other file descriptors opened by the same process on
** the same file are working. */
p->lastErrno = errno;
if( dirfd>=0 ){
close(dirfd); /* silently leak if fail, in error */
}
close(fd); /* silently leak if fail, in error */ close(fd); /* silently leak if fail, in error */
return SQLITE_IOERR_ACCESS; rc = SQLITE_IOERR_ACCESS;
goto open_finished;
} }
useProxy = !(fsInfo.f_flags&MNT_LOCAL); useProxy = !(fsInfo.f_flags&MNT_LOCAL);
} }
@@ -3899,14 +3935,20 @@ static int unixOpen(
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:"); rc = proxyTransformUnixFile((unixFile*)pFile, ":auto:");
} }
return rc; goto open_finished;
} }
} }
#endif #endif
return fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete); rc = fillInUnixFile(pVfs, fd, dirfd, pFile, zPath, noLock, isDelete);
open_finished:
if( rc!=SQLITE_OK ){
sqlite3_free(p->pUnused);
}
return rc;
} }
/* /*
** Delete the file at zPath. If the dirSync argument is true, fsync() ** Delete the file at zPath. If the dirSync argument is true, fsync()
** the directory after deleting the file. ** the directory after deleting the file.
@@ -4575,33 +4617,43 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
** but also for freeing the memory associated with the file descriptor. ** but also for freeing the memory associated with the file descriptor.
*/ */
static int proxyCreateUnixFile(const char *path, unixFile **ppFile) { static int proxyCreateUnixFile(const char *path, unixFile **ppFile) {
int fd;
int dirfd = -1;
unixFile *pNew; unixFile *pNew;
int flags = SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE;
int rc = SQLITE_OK; int rc = SQLITE_OK;
sqlite3_vfs dummyVfs; sqlite3_vfs dummyVfs;
fd = open(path, O_RDWR | O_CREAT, SQLITE_DEFAULT_FILE_PERMISSIONS);
if( fd<0 ){
return SQLITE_CANTOPEN;
}
pNew = (unixFile *)sqlite3_malloc(sizeof(unixFile)); pNew = (unixFile *)sqlite3_malloc(sizeof(unixFile));
if( pNew==NULL ){ if( !pNew ){
rc = SQLITE_NOMEM; return SQLITE_NOMEM;
goto end_create_proxy;
} }
memset(pNew, 0, sizeof(unixFile)); memset(pNew, 0, sizeof(unixFile));
/* Call unixOpen() to open the proxy file. The flags passed to unixOpen()
** suggest that the file being opened is a "main database". This is
** necessary as other file types do not necessarily support locking. It
** is better to use unixOpen() instead of opening the file directly with
** open(), as unixOpen() sets up the various mechanisms required to
** make sure a call to close() does not cause the system to discard
** POSIX locks prematurely.
**
** It is important that the xOpen member of the VFS object passed to
** unixOpen() is NULL. This tells unixOpen() may try to open a proxy-file
** for the proxy-file (creating a potential infinite loop).
*/
dummyVfs.pAppData = (void*)&autolockIoFinder; dummyVfs.pAppData = (void*)&autolockIoFinder;
rc = fillInUnixFile(&dummyVfs, fd, dirfd, (sqlite3_file*)pNew, path, 0, 0); dummyVfs.xOpen = 0;
if( rc==SQLITE_OK ){ rc = unixOpen(&dummyVfs, path, (sqlite3_file *)pNew, flags, &flags);
*ppFile = pNew; if( rc==SQLITE_OK && (flags&SQLITE_OPEN_READONLY) ){
return SQLITE_OK; pNew->pMethod->xClose((sqlite3_file *)pNew);
rc = SQLITE_CANTOPEN;
} }
end_create_proxy:
close(fd); /* silently leak fd if error, we're already in error */ if( rc!=SQLITE_OK ){
sqlite3_free(pNew); sqlite3_free(pNew);
pNew = 0;
}
*ppFile = pNew;
return rc; return rc;
} }

View File

@@ -2500,7 +2500,8 @@ typedef struct sqlite3_context sqlite3_context;
** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding} ** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
** **
** In the SQL strings input to [sqlite3_prepare_v2()] and its variants, ** In the SQL strings input to [sqlite3_prepare_v2()] and its variants,
** literals may be replaced by a [parameter] in one of these forms: ** literals may be replaced by a [parameter] that matches one of following
** templates:
** **
** <ul> ** <ul>
** <li> ? ** <li> ?
@@ -2510,8 +2511,8 @@ typedef struct sqlite3_context sqlite3_context;
** <li> $VVV ** <li> $VVV
** </ul> ** </ul>
** **
** In the parameter forms shown above NNN is an integer literal, ** In the templates above, NNN represents an integer literal,
** and VVV is an alpha-numeric parameter name. The values of these ** and VVV represents an alphanumeric identifer. The values of these
** parameters (also called "host parameter names" or "SQL parameters") ** parameters (also called "host parameter names" or "SQL parameters")
** can be set using the sqlite3_bind_*() routines defined here. ** can be set using the sqlite3_bind_*() routines defined here.
** **
@@ -5250,6 +5251,7 @@ typedef struct sqlite3_pcache sqlite3_pcache;
/* /*
** CAPI3REF: Application Defined Page Cache. ** CAPI3REF: Application Defined Page Cache.
** KEYWORDS: {page cache}
** EXPERIMENTAL ** EXPERIMENTAL
** **
** The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can ** The [sqlite3_config]([SQLITE_CONFIG_PCACHE], ...) interface can
@@ -5259,12 +5261,14 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** from, or ready to be written to, the database file. By implementing a ** from, or ready to be written to, the database file. By implementing a
** custom page cache using this API, an application can control more ** custom page cache using this API, an application can control more
** precisely the amount of memory consumed by SQLite, the way in which ** precisely the amount of memory consumed by SQLite, the way in which
** said memory is allocated and released, and the policies used to ** that memory is allocated and released, and the policies used to
** determine exactly which parts of a database file are cached and for ** determine exactly which parts of a database file are cached and for
** how long. ** how long.
** **
** The contents of the structure are copied to an internal buffer by SQLite ** The contents of the sqlite3_pcache_methods structure are copied to an
** within the call to [sqlite3_config]. ** internal buffer by SQLite within the call to [sqlite3_config]. Hence
** the application may discard the parameter after the call to
** [sqlite3_config()] returns.
** **
** The xInit() method is called once for each call to [sqlite3_initialize()] ** The xInit() method is called once for each call to [sqlite3_initialize()]
** (usually only once during the lifetime of the process). It is passed ** (usually only once during the lifetime of the process). It is passed
@@ -5285,71 +5289,71 @@ typedef struct sqlite3_pcache sqlite3_pcache;
** SQLite will never invoke xInit() more than once without an intervening ** SQLite will never invoke xInit() more than once without an intervening
** call to xShutdown(). ** call to xShutdown().
** **
** The xCreate() method is used to construct a new cache instance. The ** The xCreate() method is used to construct a new cache instance. SQLite
** will typically create one cache instance for each open database file,
** though this is not guaranteed. The
** first parameter, szPage, is the size in bytes of the pages that must ** first parameter, szPage, is the size in bytes of the pages that must
** be allocated by the cache. szPage will not be a power of two. The ** be allocated by the cache. szPage will not be a power of two. szPage
** second argument, bPurgeable, is true if the cache being created will ** will the page size of the database file that is to be cached plus an
** be used to cache database pages read from a file stored on disk, or ** increment (here called "R") of about 100 or 200. SQLite will use the
** extra R bytes on each page to store metadata about the underlying
** database page on disk. The value of R depends
** on the SQLite version, the target platform, and how SQLite was compiled.
** R is constant for a particular build of SQLite. The second argument to
** xCreate(), bPurgeable, is true if the cache being created will
** be used to cache database pages of a file stored on disk, or
** false if it is used for an in-memory database. The cache implementation ** false if it is used for an in-memory database. The cache implementation
** does not have to do anything special based on the value of bPurgeable, ** does not have to do anything special based with the value of bPurgeable;
** it is purely advisory. ** it is purely advisory. On a cache where bPurgeable is false, SQLite will
** never invoke xUnpin() except to deliberately delete a page.
** In other words, a cache created with bPurgeable set to false will
** never contain any unpinned pages.
** **
** The xCachesize() method may be called at any time by SQLite to set the ** The xCachesize() method may be called at any time by SQLite to set the
** suggested maximum cache-size (number of pages stored by) the cache ** suggested maximum cache-size (number of pages stored by) the cache
** instance passed as the first argument. This is the value configured using ** instance passed as the first argument. This is the value configured using
** the SQLite "[PRAGMA cache_size]" command. As with the bPurgeable parameter, ** the SQLite "[PRAGMA cache_size]" command. As with the bPurgeable parameter,
** the implementation is not required to do anything special with this ** the implementation is not required to do anything with this
** value, it is advisory only. ** value; it is advisory only.
** **
** The xPagecount() method should return the number of pages currently ** The xPagecount() method should return the number of pages currently
** stored in the cache supplied as an argument. ** stored in the cache.
** **
** The xFetch() method is used to fetch a page and return a pointer to it. ** The xFetch() method is used to fetch a page and return a pointer to it.
** A 'page', in this context, is a buffer of szPage bytes aligned at an ** A 'page', in this context, is a buffer of szPage bytes aligned at an
** 8-byte boundary. The page to be fetched is determined by the key. The ** 8-byte boundary. The page to be fetched is determined by the key. The
** mimimum key value is 1. After it has been retrieved using xFetch, the page ** mimimum key value is 1. After it has been retrieved using xFetch, the page
** is considered to be pinned. ** is considered to be "pinned".
** **
** If the requested page is already in the page cache, then a pointer to ** If the requested page is already in the page cache, then the page cache
** the cached buffer should be returned with its contents intact. If the ** implementation must return a pointer to the page buffer with its content
** page is not already in the cache, then the expected behaviour of the ** intact. If the requested page is not already in the cache, then the
** cache is determined by the value of the createFlag parameter passed ** behavior of the cache implementation is determined by the value of the
** to xFetch, according to the following table: ** createFlag parameter passed to xFetch, according to the following table:
** **
** <table border=1 width=85% align=center> ** <table border=1 width=85% align=center>
** <tr><th>createFlag<th>Expected Behaviour ** <tr><th> createFlag <th> Behaviour when page is not already in cache
** <tr><td>0<td>NULL should be returned. No new cache entry is created. ** <tr><td> 0 <td> Do not allocate a new page. Return NULL.
** <tr><td>1<td>If createFlag is set to 1, this indicates that ** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
** SQLite is holding pinned pages that can be unpinned ** Otherwise return NULL.
** by writing their contents to the database file (a ** <tr><td> 2 <td> Make every effort to allocate a new page. Only return
** relatively expensive operation). In this situation the ** NULL if allocating a new page is effectively impossible.
** cache implementation has two choices: it can return NULL,
** in which case SQLite will attempt to unpin one or more
** pages before re-requesting the same page, or it can
** allocate a new page and return a pointer to it. If a new
** page is allocated, then the first sizeof(void*) bytes of
** it (at least) must be zeroed before it is returned.
** <tr><td>2<td>If createFlag is set to 2, then SQLite is not holding any
** pinned pages associated with the specific cache passed
** as the first argument to xFetch() that can be unpinned. The
** cache implementation should attempt to allocate a new
** cache entry and return a pointer to it. Again, the first
** sizeof(void*) bytes of the page should be zeroed before
** it is returned. If the xFetch() method returns NULL when
** createFlag==2, SQLite assumes that a memory allocation
** failed and returns SQLITE_NOMEM to the user.
** </table> ** </table>
** **
** SQLite will normally invoke xFetch() with a createFlag of 0 or 1. If
** a call to xFetch() with createFlag==1 returns NULL, then SQLite will
** attempt to unpin one or more cache pages by spilling the content of
** pinned pages to disk and synching the operating system disk cache. After
** attempting to unpin pages, the xFetch() method will be invoked again with
** a createFlag of 2.
**
** xUnpin() is called by SQLite with a pointer to a currently pinned page ** xUnpin() is called by SQLite with a pointer to a currently pinned page
** as its second argument. If the third parameter, discard, is non-zero, ** as its second argument. If the third parameter, discard, is non-zero,
** then the page should be evicted from the cache. In this case SQLite ** then the page should be evicted from the cache. In this case SQLite
** assumes that the next time the page is retrieved from the cache using ** assumes that the next time the page is retrieved from the cache using
** the xFetch() method, it will be zeroed. If the discard parameter is ** the xFetch() method, it will be zeroed. If the discard parameter is
** zero, then the page is considered to be unpinned. The cache implementation ** zero, then the page is considered to be unpinned. The cache implementation
** may choose to reclaim (free or recycle) unpinned pages at any time. ** may choose to evict unpinned pages at any time.
** SQLite assumes that next time the page is retrieved from the cache
** it will either be zeroed, or contain the same data that it did when it
** was unpinned.
** **
** The cache is not required to perform any reference counting. A single ** The cache is not required to perform any reference counting. A single
** call to xUnpin() unpins the page regardless of the number of prior calls ** call to xUnpin() unpins the page regardless of the number of prior calls

View File

@@ -779,6 +779,9 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i); sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i);
}else if( pMem->flags & MEM_Real ){ }else if( pMem->flags & MEM_Real ){
sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r); sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r);
}else{
assert( pMem->flags & MEM_Blob );
zP4 = "(blob)";
} }
break; break;
} }
@@ -1345,7 +1348,7 @@ int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
} }
/* /*
** Close all cursors. ** Close all cursors.
** **
** Also release any dynamic memory held by the VM in the Vdbe.aMem memory ** Also release any dynamic memory held by the VM in the Vdbe.aMem memory
** cell array. This is necessary as the memory cell array may contain ** cell array. This is necessary as the memory cell array may contain
@@ -2728,9 +2731,7 @@ int sqlite3VdbeIdxRowid(sqlite3 *db, BtCursor *pCur, i64 *rowid){
assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey ); assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey );
/* Read in the complete content of the index entry */ /* Read in the complete content of the index entry */
m.flags = 0; memset(&m, 0, sizeof(m));
m.db = db;
m.zMalloc = 0;
rc = sqlite3VdbeMemFromBtree(pCur, 0, (int)nCellKey, 1, &m); rc = sqlite3VdbeMemFromBtree(pCur, 0, (int)nCellKey, 1, &m);
if( rc ){ if( rc ){
return rc; return rc;
@@ -2808,9 +2809,7 @@ int sqlite3VdbeIdxKeyCompare(
*res = 0; *res = 0;
return SQLITE_CORRUPT; return SQLITE_CORRUPT;
} }
m.db = 0; memset(&m, 0, sizeof(m));
m.flags = 0;
m.zMalloc = 0;
rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m); rc = sqlite3VdbeMemFromBtree(pC->pCursor, 0, (int)nCellKey, 1, &m);
if( rc ){ if( rc ){
return rc; return rc;

View File

@@ -1974,6 +1974,7 @@ static int whereRangeRegion(
} }
} }
assert( i>=0 && i<=SQLITE_INDEX_SAMPLES );
*piRegion = i; *piRegion = i;
} }
return SQLITE_OK; return SQLITE_OK;
@@ -2038,8 +2039,8 @@ static int whereRangeScanEst(
if( nEq==0 && p->aSample ){ if( nEq==0 && p->aSample ){
int iEst; int iEst;
int iUpper; int iLower = 0;
int iLower; int iUpper = SQLITE_INDEX_SAMPLES;
u8 aff = p->pTable->aCol[0].affinity; u8 aff = p->pTable->aCol[0].affinity;
if( pLower ){ if( pLower ){
@@ -2057,24 +2058,21 @@ static int whereRangeScanEst(
goto range_est_fallback; goto range_est_fallback;
}else if( pLowerVal==0 ){ }else if( pLowerVal==0 ){
rc = whereRangeRegion(pParse, p, pUpperVal, &iUpper); rc = whereRangeRegion(pParse, p, pUpperVal, &iUpper);
iLower = pLower ? iUpper/2 : 0; if( pLower ) iLower = iUpper/2;
}else if( pUpperVal==0 ){ }else if( pUpperVal==0 ){
rc = whereRangeRegion(pParse, p, pLowerVal, &iLower); rc = whereRangeRegion(pParse, p, pLowerVal, &iLower);
iUpper = pUpper ? (iLower + SQLITE_INDEX_SAMPLES + 1)/2 if( pUpper ) iUpper = (iLower + SQLITE_INDEX_SAMPLES + 1)/2;
: SQLITE_INDEX_SAMPLES;
}else{ }else{
rc = whereRangeRegion(pParse, p, pUpperVal, &iUpper); rc = whereRangeRegion(pParse, p, pUpperVal, &iUpper);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = whereRangeRegion(pParse, p, pLowerVal, &iLower); rc = whereRangeRegion(pParse, p, pLowerVal, &iLower);
}else{
iLower = 0;
} }
} }
iEst = iUpper - iLower; iEst = iUpper - iLower;
if( iEst>SQLITE_INDEX_SAMPLES ){ testcase( iEst==SQLITE_INDEX_SAMPLES );
iEst = SQLITE_INDEX_SAMPLES; assert( iEst<=SQLITE_INDEX_SAMPLES );
}else if( iEst<1 ){ if( iEst<1 ){
iEst = 1; iEst = 1;
} }

View File

@@ -43,7 +43,7 @@ do_test tkt4018-1.1 {
} {} } {}
# The database is locked by connection [db]. Open and close a second # The database is locked by connection [db]. Open and close a second
# connection to test.db 20000 times. If file-descriptors are not being # connection to test.db 10000 times. If file-descriptors are not being
# reused, then the process will quickly exceed its maximum number of # reused, then the process will quickly exceed its maximum number of
# file descriptors (1024 by default on linux). # file descriptors (1024 by default on linux).
do_test tkt4018-1.2 { do_test tkt4018-1.2 {