SQLite

Check-in [13d2d5a66e]
Login

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

Overview
Comment:Merge two "wal" leaves.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | wal
Files: files | file ages | folders
SHA1: 13d2d5a66e9eaa81aa6314354201ee1fbd2b3824
User & Date: dan 2010-04-28 17:49:57.000
Context
2010-04-28
18:17
Add a test to walthread.test for changing between WAL and rollback modes. (check-in: da229e44bd user: dan tags: wal)
17:49
Merge two "wal" leaves. (check-in: 13d2d5a66e user: dan tags: wal)
17:48
Change walthread.test so that tests can be run with either multiple threads or multiple processes. (check-in: 25f85f6872 user: dan tags: wal)
17:21
Changes to the interface design for the xShmLock method of the VFS. (check-in: 348409de26 user: drh tags: wal)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/main.c.
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
  return pRet;
}

/*
** Register a callback to be invoked each time a transaction is written
** into the write-ahead-log by this database connection.
*/
void *sqlite3_log_hook(
  sqlite3 *db,                    /* Attach the hook to this db handle */
  int(*xCallback)(void *, sqlite3*, const char*, int),
  void *pArg                      /* First argument passed to xCallback() */
){
  void *pRet;
  sqlite3_mutex_enter(db->mutex);
  pRet = db->pLogArg;







|







1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
  return pRet;
}

/*
** Register a callback to be invoked each time a transaction is written
** into the write-ahead-log by this database connection.
*/
void *sqlite3_wal_hook(
  sqlite3 *db,                    /* Attach the hook to this db handle */
  int(*xCallback)(void *, sqlite3*, const char*, int),
  void *pArg                      /* First argument passed to xCallback() */
){
  void *pRet;
  sqlite3_mutex_enter(db->mutex);
  pRet = db->pLogArg;
Changes to src/os_unix.c.
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
}

/*
** Create or release a lock on shared memory.
*/
static int unixShmLock(
  sqlite3_shm *pSharedMem,   /* Pointer from unixShmOpen() */
  int lockType,              /* _RDLK, _WRLK, or _UNLK, possibly ORed _BLOCK */
  int ofst,                  /* Start of lock region */
  int nByte                  /* Size of lock region in bytes */
){
  struct unixShm *p = (struct unixShm*)pSharedMem;
  struct flock f;
  int op;
  int rc;
  
  f.l_whence = SEEK_SET;
  f.l_start = ofst;
  f.l_len = nByte;
  switch( lockType & 0x07 ){
    case SQLITE_SHM_RDLK:  f.l_type = F_RDLCK;   break;
    case SQLITE_SHM_WRLK:  f.l_type = F_WRLCK;   break;
    case SQLITE_SHM_UNLK:  f.l_type = F_UNLCK;   break;
  }
  op = (lockType & 0x08)!=0 ? F_SETLKW : F_SETLK;
  rc = fcntl(p->fd.h, op, &f);
  return (rc==0) ? SQLITE_OK : SQLITE_BUSY;
}

/*
** Delete a shared-memory segment from the system.
*/
static int unixShmDelete(sqlite3_vfs *pVfs, const char *zName){
  return pVfs->xDelete(pVfs, zName, 0);







|
|
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|







4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703















4704
4705
4706
4707
4708
4709
4710
4711
}

/*
** Create or release a lock on shared memory.
*/
static int unixShmLock(
  sqlite3_shm *pSharedMem,   /* Pointer from unixShmOpen() */
  int desiredLock,           /* The locking state desired */
  int *pGotLock,             /* The locking state actually obtained */
  int shouldBlock            /* Block for the lock if true and possible */
){















  return SQLITE_OK;
}

/*
** Delete a shared-memory segment from the system.
*/
static int unixShmDelete(sqlite3_vfs *pVfs, const char *zName){
  return pVfs->xDelete(pVfs, zName, 0);
Changes to src/sqlite.h.in.
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
  ** definition.  Those that follow are added in version 2 or later
  */
  int (*xShmOpen)(sqlite3_vfs*, const char *zName, sqlite3_shm**);
  int (*xShmSize)(sqlite3_shm*, int reqSize, int *pNewSize, char**);
  int (*xShmRelease)(sqlite3_shm*);
  int (*xShmPush)(sqlite3_shm*);
  int (*xShmPull)(sqlite3_shm*);
  int (*xShmLock)(sqlite3_shm*, int lockType, int ofst, int nByte);
  int (*xShmClose)(sqlite3_shm*);
  int (*xShmDelete)(sqlite3_vfs*, const char *zName);
  int (*xRename)(sqlite3_vfs*, const char *zOld, const char *zNew, int dirSync);
  int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
  /*
  ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
  ** New fields may be appended in figure versions.  The iVersion







|







844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
  ** definition.  Those that follow are added in version 2 or later
  */
  int (*xShmOpen)(sqlite3_vfs*, const char *zName, sqlite3_shm**);
  int (*xShmSize)(sqlite3_shm*, int reqSize, int *pNewSize, char**);
  int (*xShmRelease)(sqlite3_shm*);
  int (*xShmPush)(sqlite3_shm*);
  int (*xShmPull)(sqlite3_shm*);
  int (*xShmLock)(sqlite3_shm*, int desiredLock, int *gotLock, int shouldBlock);
  int (*xShmClose)(sqlite3_shm*);
  int (*xShmDelete)(sqlite3_vfs*, const char *zName);
  int (*xRename)(sqlite3_vfs*, const char *zOld, const char *zNew, int dirSync);
  int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
  /*
  ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
  ** New fields may be appended in figure versions.  The iVersion
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890

891

892
893
894


895
896
897
898
899
900
901
#define SQLITE_ACCESS_EXISTS    0
#define SQLITE_ACCESS_READWRITE 1
#define SQLITE_ACCESS_READ      2

/*
** CAPI3REF: Flags for the xShmLock VFS method
**
** These integer constants can be used as the second parameter to
** the xShmLock method of an [sqlite3_vfs] object.  They determine
** the specific locking action.  Exactly one of the first three
** values must be used ini the lockType parameter.  The fourth
** value (SQLITE_SHM_BLOCK) can optionally be ORed into the lockType
** parameter to cause the thread to block until the lock becomes
** available.
*/

#define SQLITE_SHM_RDLK   0x01

#define SQLITE_SHM_WRLK   0x02
#define SQLITE_SHM_UNLK   0x04
#define SQLITE_SHM_BLOCK  0x08



/*
** CAPI3REF: Initialize The SQLite Library
**
** ^The sqlite3_initialize() routine initializes the
** SQLite library.  ^The sqlite3_shutdown() routine
** deallocates any resources that were allocated by sqlite3_initialize().







|
|
|
|
<
<
|

>
|
>
|
|
|
>
>







876
877
878
879
880
881
882
883
884
885
886


887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
#define SQLITE_ACCESS_EXISTS    0
#define SQLITE_ACCESS_READWRITE 1
#define SQLITE_ACCESS_READ      2

/*
** CAPI3REF: Flags for the xShmLock VFS method
**
** These integer constants define the various locking states that
** an sqlite3_shm object can be in.  The SQLITE_SHM_QUERY integer
** is not a valid data - it is a constant pasted to the 
** sqlite3_vfs.xShmLock() method for querying the current lock


** state.
*/
#define SQLITE_SHM_UNLOCK       0
#define SQLITE_SHM_READ_PREFIX  1
#define SQLITE_SHM_READ_FULL    2
#define SQLITE_SHM_WRITE        3
#define SQLITE_SHM_PENDING      4
#define SQLITE_SHM_CHECKPOINT   5
#define SQLITE_SHM_RECOVER      6
#define SQLITE_SHM_QUERY        (-1)

/*
** CAPI3REF: Initialize The SQLite Library
**
** ^The sqlite3_initialize() routine initializes the
** SQLite library.  ^The sqlite3_shutdown() routine
** deallocates any resources that were allocated by sqlite3_initialize().
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
** a fixed-length buffer on the stack.  If the log message is longer than
** a few hundred characters, it will be truncated to the length of the
** buffer.
*/
void sqlite3_log(int iErrCode, const char *zFormat, ...);

/*
** Experimental WAL callback interface.
**
** The [sqlite3_log_hook()] function is used to register a callback that
** will be invoked each time a database connection commits data to a
** write-ahead-log (i.e. whenever a transaction is committed in
** journal_mode=WAL mode). 
**
** The callback is invoked by SQLite after the commit has taken place and 
** the associated write-lock on the database released, so the implementation 
** may read, write or checkpoint the database as required.
**
** The first parameter passed to the callback function when it is invoked
** is a copy of the third parameter passed to sqlite3_log_hook() when
** registering the callback. The second is a copy of the database handle.
** The third parameter is the name of the database that was written to -
** either "main" or the name of an ATTACHed database. The fourth parameter
** is the number of pages currently in the log file, including those that
** were just committed.
**
** If an invocation of the callback function returns non-zero, then a
** checkpoint is automatically run on the database. If zero is returned,
** no special action is taken.
**
** A single database handle may have at most a single log callback 
** registered at one time. Calling [sqlite3_log_hook()] replaces any
** previously registered log callback. 
*/
void *sqlite3_log_hook(
  sqlite3*, 
  int(*)(void *,sqlite3*,const char*,int),
  void*
);

/*
** Undo the hack that converts floating point types to integer for







|

|









|











|


|







5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
** a fixed-length buffer on the stack.  If the log message is longer than
** a few hundred characters, it will be truncated to the length of the
** buffer.
*/
void sqlite3_log(int iErrCode, const char *zFormat, ...);

/*
** CAPI3REF: Write-Ahead Log Commit Hook
**
** The [sqlite3_wal_hook()] function is used to register a callback that
** will be invoked each time a database connection commits data to a
** write-ahead-log (i.e. whenever a transaction is committed in
** journal_mode=WAL mode). 
**
** The callback is invoked by SQLite after the commit has taken place and 
** the associated write-lock on the database released, so the implementation 
** may read, write or checkpoint the database as required.
**
** The first parameter passed to the callback function when it is invoked
** is a copy of the third parameter passed to sqlite3_wal_hook() when
** registering the callback. The second is a copy of the database handle.
** The third parameter is the name of the database that was written to -
** either "main" or the name of an ATTACHed database. The fourth parameter
** is the number of pages currently in the log file, including those that
** were just committed.
**
** If an invocation of the callback function returns non-zero, then a
** checkpoint is automatically run on the database. If zero is returned,
** no special action is taken.
**
** A single database handle may have at most a single log callback 
** registered at one time. Calling [sqlite3_wal_hook()] replaces any
** previously registered log callback. 
*/
void *sqlite3_wal_hook(
  sqlite3*, 
  int(*)(void *,sqlite3*,const char*,int),
  void*
);

/*
** Undo the hack that converts floating point types to integer for
Changes to src/tclsqlite.c.
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
  static const char *DB_strs[] = {
    "authorizer",         "backup",            "busy",
    "cache",              "changes",           "close",
    "collate",            "collation_needed",  "commit_hook",
    "complete",           "copy",              "enable_load_extension",
    "errorcode",          "eval",              "exists",
    "function",           "incrblob",          "interrupt",
    "last_insert_rowid",  "log_hook",          "nullvalue",
    "onecolumn",          "profile",           "progress",
    "rekey",              "restore",           "rollback_hook",     
    "status",             "timeout",           "total_changes",     
    "trace",              "transaction",       "unlock_notify",     
    "update_hook",        "version",            0                    
  };
  enum DB_enum {
    DB_AUTHORIZER,        DB_BACKUP,           DB_BUSY,
    DB_CACHE,             DB_CHANGES,          DB_CLOSE,
    DB_COLLATE,           DB_COLLATION_NEEDED, DB_COMMIT_HOOK,
    DB_COMPLETE,          DB_COPY,             DB_ENABLE_LOAD_EXTENSION,
    DB_ERRORCODE,         DB_EVAL,             DB_EXISTS,
    DB_FUNCTION,          DB_INCRBLOB,         DB_INTERRUPT,
    DB_LAST_INSERT_ROWID, DB_LOG_HOOK,         DB_NULLVALUE,
    DB_ONECOLUMN,         DB_PROFILE,          DB_PROGRESS,
    DB_REKEY,             DB_RESTORE,          DB_ROLLBACK_HOOK,    
    DB_STATUS,            DB_TIMEOUT,          DB_TOTAL_CHANGES,    
    DB_TRACE,             DB_TRANSACTION,      DB_UNLOCK_NOTIFY,    
    DB_UPDATE_HOOK,       DB_VERSION
  };
  /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
  }







|
|
|
|
|
|








|
|
|
|
|
|







1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
  static const char *DB_strs[] = {
    "authorizer",         "backup",            "busy",
    "cache",              "changes",           "close",
    "collate",            "collation_needed",  "commit_hook",
    "complete",           "copy",              "enable_load_extension",
    "errorcode",          "eval",              "exists",
    "function",           "incrblob",          "interrupt",
    "last_insert_rowid",  "nullvalue",         "onecolumn",
    "profile",            "progress",          "rekey",
    "restore",            "rollback_hook",     "status",
    "timeout",            "total_changes",     "trace",
    "transaction",        "unlock_notify",     "update_hook",
    "version",            "wal_hook",          0
  };
  enum DB_enum {
    DB_AUTHORIZER,        DB_BACKUP,           DB_BUSY,
    DB_CACHE,             DB_CHANGES,          DB_CLOSE,
    DB_COLLATE,           DB_COLLATION_NEEDED, DB_COMMIT_HOOK,
    DB_COMPLETE,          DB_COPY,             DB_ENABLE_LOAD_EXTENSION,
    DB_ERRORCODE,         DB_EVAL,             DB_EXISTS,
    DB_FUNCTION,          DB_INCRBLOB,         DB_INTERRUPT,
    DB_LAST_INSERT_ROWID, DB_NULLVALUE,        DB_ONECOLUMN,
    DB_PROFILE,           DB_PROGRESS,         DB_REKEY,
    DB_RESTORE,           DB_ROLLBACK_HOOK,    DB_STATUS,
    DB_TIMEOUT,           DB_TOTAL_CHANGES,    DB_TRACE,
    DB_TRANSACTION,       DB_UNLOCK_NOTIFY,    DB_UPDATE_HOOK,
    DB_VERSION,           DB_WAL_HOOK
  };
  /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */

  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
    return TCL_ERROR;
  }
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
      }
    }
#endif
    break;
  }

  /*
  **    $db log_hook ?script?
  **    $db update_hook ?script?
  **    $db rollback_hook ?script?
  */
  case DB_LOG_HOOK: 
  case DB_UPDATE_HOOK: 
  case DB_ROLLBACK_HOOK: {

    /* set ppHook to point at pUpdateHook or pRollbackHook, depending on 
    ** whether [$db update_hook] or [$db rollback_hook] was invoked.
    */
    Tcl_Obj **ppHook; 
    if( choice==DB_UPDATE_HOOK ){
      ppHook = &pDb->pUpdateHook;
    }else if( choice==DB_LOG_HOOK ){
      ppHook = &pDb->pLogHook;
    }else{
      ppHook = &pDb->pRollbackHook;
    }

    if( objc!=2 && objc!=3 ){
       Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");







|



|









|







2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
      }
    }
#endif
    break;
  }

  /*
  **    $db wal_hook ?script?
  **    $db update_hook ?script?
  **    $db rollback_hook ?script?
  */
  case DB_WAL_HOOK: 
  case DB_UPDATE_HOOK: 
  case DB_ROLLBACK_HOOK: {

    /* set ppHook to point at pUpdateHook or pRollbackHook, depending on 
    ** whether [$db update_hook] or [$db rollback_hook] was invoked.
    */
    Tcl_Obj **ppHook; 
    if( choice==DB_UPDATE_HOOK ){
      ppHook = &pDb->pUpdateHook;
    }else if( choice==DB_WAL_HOOK ){
      ppHook = &pDb->pLogHook;
    }else{
      ppHook = &pDb->pRollbackHook;
    }

    if( objc!=2 && objc!=3 ){
       Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?");
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
        *ppHook = objv[2];
        Tcl_IncrRefCount(*ppHook);
      }
    }

    sqlite3_update_hook(pDb->db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb);
    sqlite3_rollback_hook(pDb->db,(pDb->pRollbackHook?DbRollbackHandler:0),pDb);
    sqlite3_log_hook(pDb->db,(pDb->pLogHook?DbLogHandler:0),pDb);

    break;
  }

  /*    $db version
  **
  ** Return the version string for this database.







|







2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
        *ppHook = objv[2];
        Tcl_IncrRefCount(*ppHook);
      }
    }

    sqlite3_update_hook(pDb->db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb);
    sqlite3_rollback_hook(pDb->db,(pDb->pRollbackHook?DbRollbackHandler:0),pDb);
    sqlite3_wal_hook(pDb->db,(pDb->pLogHook?DbLogHandler:0),pDb);

    break;
  }

  /*    $db version
  **
  ** Return the version string for this database.
Changes to src/wal.h.
15
16
17
18
19
20
21

22

23
24
25
26
27
28
29






30
31
32
33
34



35
36
37
38
39
40
41
42


43



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62




63
64
65
*/

#ifndef _WAL_H_
#define _WAL_H_

#include "sqliteInt.h"


/* Connection to a log file. There is one object of this type for each pager. */

typedef struct Log Log;

/* Open and close a connection to a log file. */
int sqlite3WalOpen(sqlite3_vfs*, const char *zDb, Log **ppLog);
int sqlite3WalClose(Log *pLog, sqlite3_file *pFd, int sync_flags, u8 *zBuf);

/* Used by readers to open (lock) and close (unlock) a snapshot. */






int sqlite3WalOpenSnapshot(Log *pLog, int *);
void sqlite3WalCloseSnapshot(Log *pLog);

/* Read a page from the log, if it is present. */
int sqlite3WalRead(Log *pLog, Pgno pgno, int *pInLog, u8 *pOut);



void sqlite3WalDbsize(Log *pLog, Pgno *pPgno);

/* Obtain or release the WRITER lock. */
int sqlite3WalWriteLock(Log *pLog, int op);

/* Undo any frames written (but not committed) to the log */
int sqlite3WalUndo(Log *pLog, int (*xUndo)(void *, Pgno), void *pUndoCtx);



u32 sqlite3WalSavepoint(Log *pLog);



int sqlite3WalSavepointUndo(Log *pLog, u32 iFrame);

/* Return true if data has been written but not committed to the log file. */
int sqlite3WalDirty(Log *pLog);

/* Write a frame or frames to the log. */
int sqlite3WalFrames(Log *pLog, int, PgHdr *, Pgno, int, int);

/* Copy pages from the log to the database file */ 
int sqlite3WalCheckpoint(
  Log *pLog,                      /* Log connection */
  sqlite3_file *pFd,              /* File descriptor open on db file */
  int sync_flags,                 /* Flags to sync db file with (or 0) */
  u8 *zBuf,                       /* Temporary buffer to use */
  int (*xBusyHandler)(void *),    /* Pointer to busy-handler function */
  void *pBusyHandlerArg           /* Argument to pass to xBusyHandler */
);

/* Return the value to pass to a log callback. Or 0 for no callback. */




int sqlite3WalCallback(Log *pLog);

#endif /* _WAL_H_ */







>
|
>


|



|
>
>
>
>
>
>



|

>
>
>








>
>

>
>
>


















|
>
>
>
>



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
*/

#ifndef _WAL_H_
#define _WAL_H_

#include "sqliteInt.h"

/* Connection to a write-ahead log (WAL) file. 
** There is one object of this type for each pager. 
*/
typedef struct Log Log;

/* Open and close a connection to a write-ahead log. */
int sqlite3WalOpen(sqlite3_vfs*, const char *zDb, Log **ppLog);
int sqlite3WalClose(Log *pLog, sqlite3_file *pFd, int sync_flags, u8 *zBuf);

/* Used by readers to open (lock) and close (unlock) a snapshot.  A 
** snapshot is like a read-transaction.  It is the state of the database
** at an instant in time.  sqlite3WalOpenSnapshot gets a read lock and
** preserves the current state even if the other threads or processes
** write to or checkpoint the WAL.  sqlite3WalCloseSnapshot() closes the
** transaction and releases the lock.
*/
int sqlite3WalOpenSnapshot(Log *pLog, int *);
void sqlite3WalCloseSnapshot(Log *pLog);

/* Read a page from the write-ahead log, if it is present. */
int sqlite3WalRead(Log *pLog, Pgno pgno, int *pInLog, u8 *pOut);

/* Return the size of the database as it existed at the beginning
** of the snapshot */
void sqlite3WalDbsize(Log *pLog, Pgno *pPgno);

/* Obtain or release the WRITER lock. */
int sqlite3WalWriteLock(Log *pLog, int op);

/* Undo any frames written (but not committed) to the log */
int sqlite3WalUndo(Log *pLog, int (*xUndo)(void *, Pgno), void *pUndoCtx);

/* Return an integer that records the current (uncommitted) write
** position in the WAL */
u32 sqlite3WalSavepoint(Log *pLog);

/* Move the write position of the WAL back to iFrame.  Called in
** response to a ROLLBACK TO command. */
int sqlite3WalSavepointUndo(Log *pLog, u32 iFrame);

/* Return true if data has been written but not committed to the log file. */
int sqlite3WalDirty(Log *pLog);

/* Write a frame or frames to the log. */
int sqlite3WalFrames(Log *pLog, int, PgHdr *, Pgno, int, int);

/* Copy pages from the log to the database file */ 
int sqlite3WalCheckpoint(
  Log *pLog,                      /* Log connection */
  sqlite3_file *pFd,              /* File descriptor open on db file */
  int sync_flags,                 /* Flags to sync db file with (or 0) */
  u8 *zBuf,                       /* Temporary buffer to use */
  int (*xBusyHandler)(void *),    /* Pointer to busy-handler function */
  void *pBusyHandlerArg           /* Argument to pass to xBusyHandler */
);

/* Return the value to pass to a sqlite3_wal_hook callback, the
** number of frames in the WAL at the point of the last commit since
** sqlite3WalCallback() was called.  If no commits have occurred since
** the last call, then return 0.
*/
int sqlite3WalCallback(Log *pLog);

#endif /* _WAL_H_ */
Changes to test/tclsqlite.test.
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  set v [catch {sqlite3 bogus} msg]
  regsub {really_sqlite3} $msg {sqlite3} msg
  lappend v $msg
} [list 1 "wrong # args: should be \"$r\""]
do_test tcl-1.2 {
  set v [catch {db bogus} msg]
  lappend v $msg
} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, log_hook, nullvalue, onecolumn, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, transaction, unlock_notify, update_hook, or version}}
do_test tcl-1.2.1 {
  set v [catch {db cache bogus} msg]
  lappend v $msg
} {1 {bad option "bogus": must be flush or size}}
do_test tcl-1.2.2 {
  set v [catch {db cache} msg]
  lappend v $msg







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  set v [catch {sqlite3 bogus} msg]
  regsub {really_sqlite3} $msg {sqlite3} msg
  lappend v $msg
} [list 1 "wrong # args: should be \"$r\""]
do_test tcl-1.2 {
  set v [catch {db bogus} msg]
  lappend v $msg
} {1 {bad option "bogus": must be authorizer, backup, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, enable_load_extension, errorcode, eval, exists, function, incrblob, interrupt, last_insert_rowid, nullvalue, onecolumn, profile, progress, rekey, restore, rollback_hook, status, timeout, total_changes, trace, transaction, unlock_notify, update_hook, version, or wal_hook}}
do_test tcl-1.2.1 {
  set v [catch {db cache bogus} msg]
  lappend v $msg
} {1 {bad option "bogus": must be flush or size}}
do_test tcl-1.2.2 {
  set v [catch {db cache} msg]
  lappend v $msg
Changes to test/walhook.test.
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  [lindex $args 0] eval { 
    PRAGMA journal_mode = wal;
    PRAGMA synchronous = normal;
    PRAGMA page_size = 1024;
  }
}
sqlite3_wal db test.db
db log_hook log_hook

set ::log_hook [list]
proc log_hook {zDb nEntry} {
  lappend ::log_hook $zDb $nEntry
  return 0
}

do_test walhook-1.1 {
  execsql { CREATE TABLE t1(i PRIMARY KEY, j) }
  set ::log_hook
} {main 3}
do_test walhook-1.2 {
  set ::log_hook [list]
  execsql { INSERT INTO t1 VALUES(1, 'one') }
  set ::log_hook
} {main 5}
do_test walhook-1.3 {
  proc log_hook {args} { return 1 }
  execsql { INSERT INTO t1 VALUES(2, 'two') }
  file size test.db
} [expr 3*1024]

do_test walhook-1.4 {
  proc log_hook {zDb nEntry} { 
    execsql { PRAGMA checkpoint }
    return 0
  }
  execsql { CREATE TABLE t2(a, b) }
  file size test.db
} [expr 4*1024]

do_test walhook-1.5 {
  sqlite3_wal db2 test.db
  proc log_hook {zDb nEntry} { 
    execsql { PRAGMA checkpoint } db2
    return 0
  }
  execsql { CREATE TABLE t3(a PRIMARY KEY, b) }
  file size test.db
} [expr 6*1024]

catch { db2 close }
catch { db close }
finish_test








|

|
|
|





|


|

|


|





|









|










<
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

  [lindex $args 0] eval { 
    PRAGMA journal_mode = wal;
    PRAGMA synchronous = normal;
    PRAGMA page_size = 1024;
  }
}
sqlite3_wal db test.db
db wal_hook wal_hook

set ::wal_hook [list]
proc wal_hook {zDb nEntry} {
  lappend ::wal_hook $zDb $nEntry
  return 0
}

do_test walhook-1.1 {
  execsql { CREATE TABLE t1(i PRIMARY KEY, j) }
  set ::wal_hook
} {main 3}
do_test walhook-1.2 {
  set ::wal_hook [list]
  execsql { INSERT INTO t1 VALUES(1, 'one') }
  set ::wal_hook
} {main 5}
do_test walhook-1.3 {
  proc wal_hook {args} { return 1 }
  execsql { INSERT INTO t1 VALUES(2, 'two') }
  file size test.db
} [expr 3*1024]

do_test walhook-1.4 {
  proc wal_hook {zDb nEntry} { 
    execsql { PRAGMA checkpoint }
    return 0
  }
  execsql { CREATE TABLE t2(a, b) }
  file size test.db
} [expr 4*1024]

do_test walhook-1.5 {
  sqlite3_wal db2 test.db
  proc wal_hook {zDb nEntry} { 
    execsql { PRAGMA checkpoint } db2
    return 0
  }
  execsql { CREATE TABLE t3(a PRIMARY KEY, b) }
  file size test.db
} [expr 6*1024]

catch { db2 close }
catch { db close }
finish_test