Index: src/os_win.c ================================================================== --- src/os_win.c +++ src/os_win.c @@ -305,10 +305,11 @@ ** Allowed values for winFile.ctrlFlags */ #define WINFILE_RDONLY 0x02 /* Connection is read only */ #define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ #define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ +#define WINFILE_PPS 0x20 /* SQLITE_IOCAP_PAGE_PER_SECTOR */ /* * The size of the buffer used by sqlite3_win32_write_debug(). */ #ifndef SQLITE_WIN32_DBG_BUF_SIZE @@ -3465,10 +3466,15 @@ } case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { winModeBit(pFile, WINFILE_PSOW, (int*)pArg); OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; + } + case SQLITE_FCNTL_PAGE_PER_SECTOR: { + winModeBit(pFile, WINFILE_PPS, (int*)pArg); + OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); + return SQLITE_OK; } case SQLITE_FCNTL_VFSNAME: { *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); return SQLITE_OK; @@ -3557,10 +3563,11 @@ ** Return a vector of device characteristics. */ static int winDeviceCharacteristics(sqlite3_file *id){ winFile *p = (winFile*)id; return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | + ((p->ctrlFlags & WINFILE_PPS)?SQLITE_IOCAP_PAGE_PER_SECTOR:0) | ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0); } /* ** Windows will only let you create file view mappings @@ -5104,10 +5111,13 @@ if( isReadonly ){ pFile->ctrlFlags |= WINFILE_RDONLY; } if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){ pFile->ctrlFlags |= WINFILE_PSOW; + } + if( sqlite3_uri_boolean(zName, "pps", 0) ){ + pFile->ctrlFlags |= WINFILE_PPS; } pFile->lastErrno = NO_ERROR; pFile->zPath = zName; #if SQLITE_MAX_MMAP_SIZE>0 pFile->hMap = NULL; Index: src/pager.c ================================================================== --- src/pager.c +++ src/pager.c @@ -4761,11 +4761,13 @@ if( rc==SQLITE_OK ){ int iDc = sqlite3OsDeviceCharacteristics(pPager->fd); if( !readOnly ){ setSectorSize(pPager); assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE); - if( szPageDfltsectorSize ){ + if( iDc&SQLITE_IOCAP_PAGE_PER_SECTOR ){ + szPageDflt = (u32)pPager->sectorSize; + }else if( szPageDfltsectorSize ){ if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){ szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE; }else{ szPageDflt = (u32)pPager->sectorSize; } Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -577,11 +577,13 @@ ** and that adjacent bytes, even bytes within the same sector are ** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN ** flag indicates that a file cannot be deleted when open. The ** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on ** read-only media and cannot be changed even by processes with -** elevated privileges. +** elevated privileges. The SQLITE_IOCAP_PAGE_PER_SECTOR flag indicates +** the initial page size for new databases should set to the sector size +** reported by the VFS. */ #define SQLITE_IOCAP_ATOMIC 0x00000001 #define SQLITE_IOCAP_ATOMIC512 0x00000002 #define SQLITE_IOCAP_ATOMIC1K 0x00000004 #define SQLITE_IOCAP_ATOMIC2K 0x00000008 @@ -593,10 +595,11 @@ #define SQLITE_IOCAP_SAFE_APPEND 0x00000200 #define SQLITE_IOCAP_SEQUENTIAL 0x00000400 #define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800 #define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000 #define SQLITE_IOCAP_IMMUTABLE 0x00002000 +#define SQLITE_IOCAP_PAGE_PER_SECTOR 0x00004000 /* ** CAPI3REF: File Locking Levels ** ** SQLite uses one of these integer values as the second @@ -727,10 +730,11 @@ **
  • [SQLITE_IOCAP_SAFE_APPEND] **
  • [SQLITE_IOCAP_SEQUENTIAL] **
  • [SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN] **
  • [SQLITE_IOCAP_POWERSAFE_OVERWRITE] **
  • [SQLITE_IOCAP_IMMUTABLE] +**
  • [SQLITE_IOCAP_PAGE_PER_SECTOR] ** ** ** The SQLITE_IOCAP_ATOMIC property means that all writes of ** any size are atomic. The SQLITE_IOCAP_ATOMICnnn values ** mean that writes of blocks that are nnn bytes in size and @@ -1010,10 +1014,19 @@ ** **
  • [[SQLITE_FCNTL_RBU]] ** The [SQLITE_FCNTL_RBU] opcode is implemented by the special VFS used by ** the RBU extension only. All other VFS should return SQLITE_NOTFOUND for ** this opcode. +** +**
  • [[SQLITE_FCNTL_PAGE_PER_SECTOR]] +** ^The [SQLITE_FCNTL_PAGE_PER_SECTOR] opcode is used to set or query the +** persistent "page-per-sector" or "PPS" setting. The PPS setting determines +** the [SQLITE_IOCAP_PAGE_PER_SECTOR] bit of the xDeviceCharacteristics +** methods. The fourth parameter to [sqlite3_file_control()] for this opcode +** should be a pointer to an integer. That integer is 0 to disable +** page-per-sector mode or 1 to enable page-per-sector mode. If the integer +** is -1, then it is overwritten with the current page-per-sector mode setting. ** */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 @@ -1041,10 +1054,11 @@ #define SQLITE_FCNTL_RBU 26 #define SQLITE_FCNTL_VFS_POINTER 27 #define SQLITE_FCNTL_JOURNAL_POINTER 28 #define SQLITE_FCNTL_WIN32_GET_HANDLE 29 #define SQLITE_FCNTL_PDB 30 +#define SQLITE_FCNTL_PAGE_PER_SECTOR 31 /* deprecated names */ #define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE #define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE #define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO