mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-15 11:41:13 +03:00
Updates to comments and code organization to reflect changes in os_unix.c;
Updated winShmLock() with logic changes from unixShmLock(); Modified IO error returns in winShmMap() to match those in unixShmMap(); FossilOrigin-Name: b73fe2754b68af4c76a1788aa18b93359720d1f1
This commit is contained in:
14
manifest
14
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Fix\stest_stat.c\sso\sthat\sit\sdoes\snot\scause\scompilation\serrors\sif\sSQLITE_OMIT_VIRTUALTABLE\sis\sdefined.
|
C Updates\sto\scomments\sand\scode\sorganization\sto\sreflect\schanges\sin\sos_unix.c;\s\s\nUpdated\swinShmLock()\swith\slogic\schanges\sfrom\sunixShmLock();\s\nModified\sIO\serror\sreturns\sin\swinShmMap()\sto\smatch\sthose\sin\sunixShmMap();
|
||||||
D 2010-07-12T18:12:41
|
D 2010-07-12T20:46:34
|
||||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||||
F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e
|
F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -155,7 +155,7 @@ F src/os.h d7775504a51e6e0d40315aa427b3e229ff9ff9ca
|
|||||||
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
|
||||||
F src/os_os2.c 665876d5eec7585226b0a1cf5e18098de2b2da19
|
F src/os_os2.c 665876d5eec7585226b0a1cf5e18098de2b2da19
|
||||||
F src/os_unix.c c6112f0ae34f23ae5ca0189a685e084befbdcf26
|
F src/os_unix.c c6112f0ae34f23ae5ca0189a685e084befbdcf26
|
||||||
F src/os_win.c b39c2c26342d6d4ceaaa4a5e764284444ae6ce98
|
F src/os_win.c 04c8828e4c5c2e7d5abcb9ce170ae6bfb02aa98d
|
||||||
F src/pager.c 1d42e2cdaa9b1765f7df8e350509318917cd651d
|
F src/pager.c 1d42e2cdaa9b1765f7df8e350509318917cd651d
|
||||||
F src/pager.h 879fdde5a102d2f21a3135d6f647530b21c2796c
|
F src/pager.h 879fdde5a102d2f21a3135d6f647530b21c2796c
|
||||||
F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
|
F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
|
||||||
@@ -834,7 +834,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 d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||||
P e6cd15451d8c47bfc86d07565655920134b494fe
|
P bf4fc0888705108aab997e1cb491fc7f9c64c443
|
||||||
R 1f9d6ed2ba44f2915e3c41809f76e2bf
|
R 1e9b9e9a767f3c74af22f298a155d2ee
|
||||||
U dan
|
U shaneh
|
||||||
Z c74a18dab14d1190c93da6ff3459824a
|
Z 69258ba9752eb7fe9649055c47247468
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
bf4fc0888705108aab997e1cb491fc7f9c64c443
|
b73fe2754b68af4c76a1788aa18b93359720d1f1
|
||||||
230
src/os_win.c
230
src/os_win.c
@@ -1180,11 +1180,6 @@ static int winDeviceCharacteristics(sqlite3_file *id){
|
|||||||
return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN;
|
return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
********************************* Shared Memory *****************************
|
|
||||||
**
|
|
||||||
** The next subdivision of code manages the shared-memory primitives.
|
|
||||||
*/
|
|
||||||
#ifndef SQLITE_OMIT_WAL
|
#ifndef SQLITE_OMIT_WAL
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1234,11 +1229,6 @@ static int winShmMutexHeld(void) {
|
|||||||
** winShmMutexHeld() is true when reading or writing any other field
|
** winShmMutexHeld() is true when reading or writing any other field
|
||||||
** in this structure.
|
** in this structure.
|
||||||
**
|
**
|
||||||
** To avoid deadlocks, mutex and mutexBuf are always released in the
|
|
||||||
** reverse order that they are acquired. mutexBuf is always acquired
|
|
||||||
** first and released last. This invariant is check by asserting
|
|
||||||
** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or
|
|
||||||
** released.
|
|
||||||
*/
|
*/
|
||||||
struct winShmNode {
|
struct winShmNode {
|
||||||
sqlite3_mutex *mutex; /* Mutex to access this object */
|
sqlite3_mutex *mutex; /* Mutex to access this object */
|
||||||
@@ -1272,17 +1262,21 @@ static winShmNode *winShmNodeList = 0;
|
|||||||
** Structure used internally by this VFS to record the state of an
|
** Structure used internally by this VFS to record the state of an
|
||||||
** open shared memory connection.
|
** open shared memory connection.
|
||||||
**
|
**
|
||||||
** winShm.pFile->mutex must be held while reading or writing the
|
** The following fields are initialized when this object is created and
|
||||||
** winShm.pNext and winShm.locks[] elements.
|
** are read-only thereafter:
|
||||||
**
|
**
|
||||||
** The winShm.pFile element is initialized when the object is created
|
** winShm.pShmNode
|
||||||
** and is read-only thereafter.
|
** winShm.id
|
||||||
|
**
|
||||||
|
** All other fields are read/write. The winShm.pShmNode->mutex must be held
|
||||||
|
** while accessing any read/write fields.
|
||||||
*/
|
*/
|
||||||
struct winShm {
|
struct winShm {
|
||||||
winShmNode *pShmNode; /* The underlying winShmNode object */
|
winShmNode *pShmNode; /* The underlying winShmNode object */
|
||||||
winShm *pNext; /* Next winShm with the same winShmNode */
|
winShm *pNext; /* Next winShm with the same winShmNode */
|
||||||
u8 hasMutex; /* True if holding the winShmNode mutex */
|
u8 hasMutex; /* True if holding the winShmNode mutex */
|
||||||
u8 hasMutexBuf; /* True if holding pFile->mutexBuf */
|
u16 sharedMask; /* Mask of shared locks held */
|
||||||
|
u16 exclMask; /* Mask of exclusive locks held */
|
||||||
#ifdef SQLITE_DEBUG
|
#ifdef SQLITE_DEBUG
|
||||||
u8 id; /* Id of this connection with its winShmNode */
|
u8 id; /* Id of this connection with its winShmNode */
|
||||||
#endif
|
#endif
|
||||||
@@ -1317,7 +1311,6 @@ static int winShmSystemLock(
|
|||||||
dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
|
dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
|
||||||
if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
|
if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
|
||||||
|
|
||||||
/* Find the first bit in lockMask that is set */
|
|
||||||
memset(&ovlp, 0, sizeof(OVERLAPPED));
|
memset(&ovlp, 0, sizeof(OVERLAPPED));
|
||||||
ovlp.Offset = ofst;
|
ovlp.Offset = ofst;
|
||||||
|
|
||||||
@@ -1327,14 +1320,14 @@ static int winShmSystemLock(
|
|||||||
}else{
|
}else{
|
||||||
rc = LockFileEx(pFile->hFile.h, dwFlags, 0, nByte, 0, &ovlp);
|
rc = LockFileEx(pFile->hFile.h, dwFlags, 0, nByte, 0, &ovlp);
|
||||||
}
|
}
|
||||||
if( !rc ){
|
|
||||||
OSTRACE(("SHM-LOCK %d %s ERROR 0x%08lx\n",
|
|
||||||
pFile->hFile.h,
|
|
||||||
lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx",
|
|
||||||
GetLastError()));
|
|
||||||
}
|
|
||||||
rc = (rc!=0) ? SQLITE_OK : SQLITE_BUSY;
|
rc = (rc!=0) ? SQLITE_OK : SQLITE_BUSY;
|
||||||
|
|
||||||
|
OSTRACE(("SHM-LOCK %d %s %s 0x%08lx\n",
|
||||||
|
pFile->hFile.h,
|
||||||
|
rc==SQLITE_OK ? "ok" : "failed",
|
||||||
|
lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx",
|
||||||
|
GetLastError()));
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1511,6 +1504,7 @@ static int winShmClose(
|
|||||||
|
|
||||||
pDbFd = (winFile*)fd;
|
pDbFd = (winFile*)fd;
|
||||||
p = pDbFd->pShm;
|
p = pDbFd->pShm;
|
||||||
|
if( p==0 ) return SQLITE_OK;
|
||||||
pShmNode = p->pShmNode;
|
pShmNode = p->pShmNode;
|
||||||
|
|
||||||
/* Remove connection p from the set of connections associated
|
/* Remove connection p from the set of connections associated
|
||||||
@@ -1537,6 +1531,127 @@ static int winShmClose(
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Change the lock state for a shared-memory segment.
|
||||||
|
*/
|
||||||
|
static int winShmLock(
|
||||||
|
sqlite3_file *fd, /* Database file holding the shared memory */
|
||||||
|
int ofst, /* First lock to acquire or release */
|
||||||
|
int n, /* Number of locks to acquire or release */
|
||||||
|
int flags /* What to do with the lock */
|
||||||
|
){
|
||||||
|
winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
|
||||||
|
winShm *p = pDbFd->pShm; /* The shared memory being locked */
|
||||||
|
winShm *pX; /* For looping over all siblings */
|
||||||
|
winShmNode *pShmNode = p->pShmNode;
|
||||||
|
int rc = SQLITE_OK; /* Result code */
|
||||||
|
u16 mask; /* Mask of locks to take or release */
|
||||||
|
|
||||||
|
assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
|
||||||
|
assert( n>=1 );
|
||||||
|
assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
|
||||||
|
|| flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
|
||||||
|
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
|
||||||
|
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
|
||||||
|
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
|
||||||
|
|
||||||
|
mask = (u16)((1U<<(ofst+n)) - (1U<<ofst));
|
||||||
|
assert( n>1 || mask==(1<<ofst) );
|
||||||
|
sqlite3_mutex_enter(pShmNode->mutex);
|
||||||
|
if( flags & SQLITE_SHM_UNLOCK ){
|
||||||
|
u16 allMask = 0; /* Mask of locks held by siblings */
|
||||||
|
|
||||||
|
/* See if any siblings hold this same lock */
|
||||||
|
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
||||||
|
if( pX==p ) continue;
|
||||||
|
assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
|
||||||
|
allMask |= pX->sharedMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlock the system-level locks */
|
||||||
|
if( (mask & allMask)==0 ){
|
||||||
|
rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n);
|
||||||
|
}else{
|
||||||
|
rc = SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Undo the local locks */
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
p->exclMask &= ~mask;
|
||||||
|
p->sharedMask &= ~mask;
|
||||||
|
}
|
||||||
|
}else if( flags & SQLITE_SHM_SHARED ){
|
||||||
|
u16 allShared = 0; /* Union of locks held by connections other than "p" */
|
||||||
|
|
||||||
|
/* Find out which shared locks are already held by sibling connections.
|
||||||
|
** If any sibling already holds an exclusive lock, go ahead and return
|
||||||
|
** SQLITE_BUSY.
|
||||||
|
*/
|
||||||
|
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
||||||
|
if( (pX->exclMask & mask)!=0 ){
|
||||||
|
rc = SQLITE_BUSY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
allShared |= pX->sharedMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get shared locks at the system level, if necessary */
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
if( (allShared & mask)==0 ){
|
||||||
|
rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n);
|
||||||
|
}else{
|
||||||
|
rc = SQLITE_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the local shared locks */
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
p->sharedMask |= mask;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
/* Make sure no sibling connections hold locks that will block this
|
||||||
|
** lock. If any do, return SQLITE_BUSY right away.
|
||||||
|
*/
|
||||||
|
for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
|
||||||
|
if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
|
||||||
|
rc = SQLITE_BUSY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the exclusive locks at the system level. Then if successful
|
||||||
|
** also mark the local connection as being locked.
|
||||||
|
*/
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
assert( (p->sharedMask & mask)==0 );
|
||||||
|
p->exclMask |= mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_mutex_leave(pShmNode->mutex);
|
||||||
|
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x %s\n",
|
||||||
|
p->id, (int)GetCurrentProcessId(), p->sharedMask, p->exclMask,
|
||||||
|
rc ? "failed" : "ok"));
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Implement a memory barrier or memory fence on shared memory.
|
||||||
|
**
|
||||||
|
** All loads and stores begun before the barrier must complete before
|
||||||
|
** any load or store begun after the barrier.
|
||||||
|
*/
|
||||||
|
static void winShmBarrier(
|
||||||
|
sqlite3_file *fd /* Database holding the shared memory */
|
||||||
|
){
|
||||||
|
UNUSED_PARAMETER(fd);
|
||||||
|
/* MemoryBarrier(); // does not work -- do not know why not */
|
||||||
|
winShmEnterMutex();
|
||||||
|
winShmLeaveMutex();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This function is called to obtain a pointer to region iRegion of the
|
** This function is called to obtain a pointer to region iRegion of the
|
||||||
** shared-memory associated with the database file fd. Shared-memory regions
|
** shared-memory associated with the database file fd. Shared-memory regions
|
||||||
@@ -1584,6 +1699,7 @@ static int winShmMap(
|
|||||||
*/
|
*/
|
||||||
rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
|
rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
|
rc = SQLITE_IOERR_SHMSIZE;
|
||||||
goto shmpage_out;
|
goto shmpage_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1597,6 +1713,7 @@ static int winShmMap(
|
|||||||
if( !isWrite ) goto shmpage_out;
|
if( !isWrite ) goto shmpage_out;
|
||||||
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
|
rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
|
rc = SQLITE_IOERR_SHMSIZE;
|
||||||
goto shmpage_out;
|
goto shmpage_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1647,67 +1764,19 @@ shmpage_out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** Change the lock state for a shared-memory segment.
|
|
||||||
*/
|
|
||||||
static int winShmLock(
|
|
||||||
sqlite3_file *fd, /* Database file holding the shared memory */
|
|
||||||
int ofst, /* First lock to acquire or release */
|
|
||||||
int n, /* Number of locks to acquire or release */
|
|
||||||
int flags /* What to do with the lock */
|
|
||||||
){
|
|
||||||
winFile *pDbFd = (winFile*)fd;
|
|
||||||
winShm *p = pDbFd->pShm;
|
|
||||||
winShmNode *pShmNode = p->pShmNode;
|
|
||||||
int rc = SQLITE_PROTOCOL;
|
|
||||||
|
|
||||||
assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
|
|
||||||
assert( n>=1 );
|
|
||||||
assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
|
|
||||||
|| flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
|
|
||||||
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
|
|
||||||
|| flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
|
|
||||||
assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
|
|
||||||
|
|
||||||
sqlite3_mutex_enter(pShmNode->mutex);
|
|
||||||
if( flags & SQLITE_SHM_UNLOCK ){
|
|
||||||
rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n);
|
|
||||||
}else if( flags & SQLITE_SHM_SHARED ){
|
|
||||||
rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n);
|
|
||||||
}else{
|
|
||||||
rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
|
|
||||||
}
|
|
||||||
sqlite3_mutex_leave(pShmNode->mutex);
|
|
||||||
OSTRACE(("SHM-LOCK shmid-%d, pid-%d %s\n",
|
|
||||||
p->id, (int)GetCurrentProcessId(), rc ? "failed" : "ok"));
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Implement a memory barrier or memory fence on shared memory.
|
|
||||||
**
|
|
||||||
** All loads and stores begun before the barrier must complete before
|
|
||||||
** any load or store begun after the barrier.
|
|
||||||
*/
|
|
||||||
static void winShmBarrier(
|
|
||||||
sqlite3_file *fd /* Database holding the shared memory */
|
|
||||||
){
|
|
||||||
UNUSED_PARAMETER(fd);
|
|
||||||
/* MemoryBarrier(); // does not work -- do not know why not */
|
|
||||||
winShmEnterMutex();
|
|
||||||
winShmLeaveMutex();
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
# define winShmOpen 0
|
# define winShmOpen 0
|
||||||
# define winShmMap 0
|
|
||||||
# define winShmLock 0
|
# define winShmLock 0
|
||||||
|
# define winShmMap 0
|
||||||
# define winShmBarrier 0
|
# define winShmBarrier 0
|
||||||
# define winShmClose 0
|
# define winShmClose 0
|
||||||
#endif /* #ifndef SQLITE_OMIT_WAL */
|
#endif /* #ifndef SQLITE_OMIT_WAL */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
***************************** End Shared Memory *****************************
|
** Here ends the implementation of all sqlite3_file methods.
|
||||||
****************************************************************************/
|
**
|
||||||
|
********************** End sqlite3_file Methods *******************************
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This vector defines all the methods that can operate on an
|
** This vector defines all the methods that can operate on an
|
||||||
@@ -1734,11 +1803,12 @@ static const sqlite3_io_methods winIoMethod = {
|
|||||||
winShmClose /* xShmClose */
|
winShmClose /* xShmClose */
|
||||||
};
|
};
|
||||||
|
|
||||||
/***************************************************************************
|
/****************************************************************************
|
||||||
** Here ends the I/O methods that form the sqlite3_io_methods object.
|
**************************** sqlite3_vfs methods ****************************
|
||||||
**
|
**
|
||||||
** The next block of code implements the VFS methods.
|
** This division contains the implementation of methods on the
|
||||||
****************************************************************************/
|
** sqlite3_vfs object.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Convert a UTF-8 filename into whatever form the underlying
|
** Convert a UTF-8 filename into whatever form the underlying
|
||||||
|
|||||||
Reference in New Issue
Block a user