SQLite

Check-in [846b1de6]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Ensure that the Pager.changeCountDone flag is cleared whenever dropping the write lock, even when transitioning from EXCLUSIVE locking mode into NORMAL locking mode while in WAL mode. Ticket [fb3b3024ea238d5c].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 846b1de6e5a9e418f225273dc033234c64c116fcd89c8261522b4902c248451f
User & Date: drh 2019-12-27 01:50:46
Context
2019-12-27
08:57
When determining if an aggregate within a sub-query should be processed as part of the sub-query or an outer query, consider any FILTER clause in the same way as the arguments to the aggregate. (check-in: 1ffc045d user: dan tags: trunk)
01:50
Ensure that the Pager.changeCountDone flag is cleared whenever dropping the write lock, even when transitioning from EXCLUSIVE locking mode into NORMAL locking mode while in WAL mode. Ticket [fb3b3024ea238d5c]. (check-in: 846b1de6 user: drh tags: trunk)
00:19
Fix buffer underflows in the zipfile extension associated with zero-length or NULL filename in the ZIP archive. But report on the mailing list by Yongheng and Rui. (check-in: 465a15c5 user: drh tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pager.c.

1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
    assert( pPager->eLock>=eLock );
    rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock);
    if( pPager->eLock!=UNKNOWN_LOCK ){
      pPager->eLock = (u8)eLock;
    }
    IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
  }

  return rc;
}

/*
** Lock the database file to level eLock, which must be either SHARED_LOCK,
** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
** Pager.eLock variable to the new locking state. 







>







1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
    assert( pPager->eLock>=eLock );
    rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock);
    if( pPager->eLock!=UNKNOWN_LOCK ){
      pPager->eLock = (u8)eLock;
    }
    IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
  }
  pPager->changeCountDone = pPager->tempFile; /* ticket fb3b3024ea238d5c */
  return rc;
}

/*
** Lock the database file to level eLock, which must be either SHARED_LOCK,
** RESERVED_LOCK or EXCLUSIVE_LOCK. If the caller is successful, set the
** Pager.eLock variable to the new locking state. 
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
    }

    /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here
    ** without clearing the error code. This is intentional - the error
    ** code is cleared and the cache reset in the block below.
    */
    assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
    pPager->changeCountDone = 0;
    pPager->eState = PAGER_OPEN;
  }

  /* If Pager.errCode is set, the contents of the pager cache cannot be
  ** trusted. Now that there are no outstanding references to the pager,
  ** it can safely move back to PAGER_OPEN state. This happens in both
  ** normal and exclusive-locking mode.







<







1890
1891
1892
1893
1894
1895
1896

1897
1898
1899
1900
1901
1902
1903
    }

    /* The pager state may be changed from PAGER_ERROR to PAGER_OPEN here
    ** without clearing the error code. This is intentional - the error
    ** code is cleared and the cache reset in the block below.
    */
    assert( pPager->errCode || pPager->eState!=PAGER_ERROR );

    pPager->eState = PAGER_OPEN;
  }

  /* If Pager.errCode is set, the contents of the pager cache cannot be
  ** trusted. Now that there are no outstanding references to the pager,
  ** it can safely move back to PAGER_OPEN state. This happens in both
  ** normal and exclusive-locking mode.
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
    if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
  }

  if( !pPager->exclusiveMode 
   && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
  ){
    rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
    pPager->changeCountDone = 0;
  }
  pPager->eState = PAGER_READER;
  pPager->setMaster = 0;

  return (rc==SQLITE_OK?rc2:rc);
}








<







2153
2154
2155
2156
2157
2158
2159

2160
2161
2162
2163
2164
2165
2166
    if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
  }

  if( !pPager->exclusiveMode 
   && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
  ){
    rc2 = pagerUnlockDb(pPager, SHARED_LOCK);

  }
  pPager->eState = PAGER_READER;
  pPager->setMaster = 0;

  return (rc==SQLITE_OK?rc2:rc);
}

Changes to test/exclusive.test.

506
507
508
509
510
511
512


















513
514
515
516
  sqlite3 db test.db
} {}

do_execsql_test exclusive-6.5 {
  PRAGMA locking_mode = EXCLUSIVE;
  SELECT * FROM sqlite_master;
} {exclusive}



















} ;# atomic_batch_write==0

finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
  sqlite3 db test.db
} {}

do_execsql_test exclusive-6.5 {
  PRAGMA locking_mode = EXCLUSIVE;
  SELECT * FROM sqlite_master;
} {exclusive}

# 2019-12-26 ticket fb3b3024ea238d5c
do_test exclusive-7.1 {
  db close
  forcedelete test.db test.db-journal test.db-wal
  sqlite3 db test.db
  # The following sequence of pragmas would trigger an assert()
  # associated with Pager.changeCountDone inside of assert_pager_state(),
  # prior to the fix.
  db eval {
    PRAGMA locking_mode = EXCLUSIVE;
    PRAGMA journal_mode = WAL;
    PRAGMA locking_mode = NORMAL;
    PRAGMA user_version;
    PRAGMA journal_mode = DELETE;
  }
} {exclusive wal normal 0 delete}
 

} ;# atomic_batch_write==0

finish_test