xref: /sqlite-3.40.0/src/test2.c (revision a70a01db)
15c4d9703Sdrh /*
2b19a2bc6Sdrh ** 2001 September 15
35c4d9703Sdrh **
4b19a2bc6Sdrh ** The author disclaims copyright to this source code.  In place of
5b19a2bc6Sdrh ** a legal notice, here is a blessing:
65c4d9703Sdrh **
7b19a2bc6Sdrh **    May you do good and not evil.
8b19a2bc6Sdrh **    May you find forgiveness for yourself and forgive others.
9b19a2bc6Sdrh **    May you share freely, never taking more than you give.
105c4d9703Sdrh **
115c4d9703Sdrh *************************************************************************
125c4d9703Sdrh ** Code for testing the pager.c module in SQLite.  This code
135c4d9703Sdrh ** is not included in the SQLite library.  It is used for automated
145c4d9703Sdrh ** testing of the SQLite library.
155c4d9703Sdrh */
165c4d9703Sdrh #include "sqliteInt.h"
1752b1dbb5Smistachkin #if defined(INCLUDE_SQLITE_TCL_H)
1852b1dbb5Smistachkin #  include "sqlite_tcl.h"
1952b1dbb5Smistachkin #else
205c4d9703Sdrh #  include "tcl.h"
2152b1dbb5Smistachkin #endif
225c4d9703Sdrh #include <stdlib.h>
235c4d9703Sdrh #include <string.h>
243088d59eSdrh #include <ctype.h>
255c4d9703Sdrh 
26e84d8d32Smistachkin extern const char *sqlite3ErrName(int);
275c4d9703Sdrh 
285c4d9703Sdrh /*
2990f5ecb3Sdrh ** Page size and reserved size used for testing.
3090f5ecb3Sdrh */
3190f5ecb3Sdrh static int test_pagesize = 1024;
3290f5ecb3Sdrh 
3390f5ecb3Sdrh /*
344775ecd0Sdrh ** Dummy page reinitializer
354775ecd0Sdrh */
pager_test_reiniter(DbPage * pNotUsed)364775ecd0Sdrh static void pager_test_reiniter(DbPage *pNotUsed){
374775ecd0Sdrh   return;
384775ecd0Sdrh }
394775ecd0Sdrh 
404775ecd0Sdrh /*
415c4d9703Sdrh ** Usage:   pager_open FILENAME N-PAGE
425c4d9703Sdrh **
435c4d9703Sdrh ** Open a new pager
445c4d9703Sdrh */
pager_open(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)457617e4a8Smistachkin static int SQLITE_TCLAPI pager_open(
465c4d9703Sdrh   void *NotUsed,
475c4d9703Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
485c4d9703Sdrh   int argc,              /* Number of arguments */
49c2eef3b3Sdrh   const char **argv      /* Text of each argument */
505c4d9703Sdrh ){
51b2eced5dSdrh   u32 pageSize;
525c4d9703Sdrh   Pager *pPager;
535c4d9703Sdrh   int nPage;
545c4d9703Sdrh   int rc;
555c4d9703Sdrh   char zBuf[100];
565c4d9703Sdrh   if( argc!=3 ){
575c4d9703Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
585c4d9703Sdrh        " FILENAME N-PAGE\"", 0);
595c4d9703Sdrh     return TCL_ERROR;
605c4d9703Sdrh   }
615c4d9703Sdrh   if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
6271d5d2cdSdanielk1977   rc = sqlite3PagerOpen(sqlite3_vfs_find(0), &pPager, argv[1], 0, 0,
634775ecd0Sdrh       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB,
644775ecd0Sdrh       pager_test_reiniter);
655c4d9703Sdrh   if( rc!=SQLITE_OK ){
66e84d8d32Smistachkin     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
675c4d9703Sdrh     return TCL_ERROR;
685c4d9703Sdrh   }
693b8a05f6Sdanielk1977   sqlite3PagerSetCachesize(pPager, nPage);
70a1644fd8Sdanielk1977   pageSize = test_pagesize;
71fa9601a9Sdrh   sqlite3PagerSetPagesize(pPager, &pageSize, -1);
72fe63d1c9Sdrh   sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPager);
735c4d9703Sdrh   Tcl_AppendResult(interp, zBuf, 0);
745c4d9703Sdrh   return TCL_OK;
755c4d9703Sdrh }
765c4d9703Sdrh 
775c4d9703Sdrh /*
785c4d9703Sdrh ** Usage:   pager_close ID
795c4d9703Sdrh **
805c4d9703Sdrh ** Close the given pager.
815c4d9703Sdrh */
pager_close(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)827617e4a8Smistachkin static int SQLITE_TCLAPI pager_close(
835c4d9703Sdrh   void *NotUsed,
845c4d9703Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
855c4d9703Sdrh   int argc,              /* Number of arguments */
86c2eef3b3Sdrh   const char **argv      /* Text of each argument */
875c4d9703Sdrh ){
885c4d9703Sdrh   Pager *pPager;
895c4d9703Sdrh   int rc;
905c4d9703Sdrh   if( argc!=2 ){
915c4d9703Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
925c4d9703Sdrh        " ID\"", 0);
935c4d9703Sdrh     return TCL_ERROR;
945c4d9703Sdrh   }
95e8f52c50Sdrh   pPager = sqlite3TestTextToPtr(argv[1]);
967fb89906Sdan   rc = sqlite3PagerClose(pPager, 0);
975c4d9703Sdrh   if( rc!=SQLITE_OK ){
98e84d8d32Smistachkin     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
995c4d9703Sdrh     return TCL_ERROR;
1005c4d9703Sdrh   }
1015c4d9703Sdrh   return TCL_OK;
1025c4d9703Sdrh }
1035c4d9703Sdrh 
1045c4d9703Sdrh /*
1055c4d9703Sdrh ** Usage:   pager_rollback ID
1065c4d9703Sdrh **
1075c4d9703Sdrh ** Rollback changes
1085c4d9703Sdrh */
pager_rollback(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)1097617e4a8Smistachkin static int SQLITE_TCLAPI pager_rollback(
1105c4d9703Sdrh   void *NotUsed,
1115c4d9703Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1125c4d9703Sdrh   int argc,              /* Number of arguments */
113c2eef3b3Sdrh   const char **argv      /* Text of each argument */
1145c4d9703Sdrh ){
1155c4d9703Sdrh   Pager *pPager;
1165c4d9703Sdrh   int rc;
1175c4d9703Sdrh   if( argc!=2 ){
1185c4d9703Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1195c4d9703Sdrh        " ID\"", 0);
1205c4d9703Sdrh     return TCL_ERROR;
1215c4d9703Sdrh   }
122e8f52c50Sdrh   pPager = sqlite3TestTextToPtr(argv[1]);
1233b8a05f6Sdanielk1977   rc = sqlite3PagerRollback(pPager);
1245c4d9703Sdrh   if( rc!=SQLITE_OK ){
125e84d8d32Smistachkin     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
1265c4d9703Sdrh     return TCL_ERROR;
1275c4d9703Sdrh   }
1285c4d9703Sdrh   return TCL_OK;
1295c4d9703Sdrh }
1305c4d9703Sdrh 
1315c4d9703Sdrh /*
1325c4d9703Sdrh ** Usage:   pager_commit ID
1335c4d9703Sdrh **
1345c4d9703Sdrh ** Commit all changes
1355c4d9703Sdrh */
pager_commit(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)1367617e4a8Smistachkin static int SQLITE_TCLAPI pager_commit(
1375c4d9703Sdrh   void *NotUsed,
1385c4d9703Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
1395c4d9703Sdrh   int argc,              /* Number of arguments */
140c2eef3b3Sdrh   const char **argv      /* Text of each argument */
1415c4d9703Sdrh ){
1425c4d9703Sdrh   Pager *pPager;
1435c4d9703Sdrh   int rc;
1445c4d9703Sdrh   if( argc!=2 ){
1455c4d9703Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1465c4d9703Sdrh        " ID\"", 0);
1475c4d9703Sdrh     return TCL_ERROR;
1485c4d9703Sdrh   }
149e8f52c50Sdrh   pPager = sqlite3TestTextToPtr(argv[1]);
15049b9d338Sdrh   rc = sqlite3PagerCommitPhaseOne(pPager, 0, 0);
15180e35f46Sdrh   if( rc!=SQLITE_OK ){
152e84d8d32Smistachkin     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
15380e35f46Sdrh     return TCL_ERROR;
15480e35f46Sdrh   }
15580e35f46Sdrh   rc = sqlite3PagerCommitPhaseTwo(pPager);
1565c4d9703Sdrh   if( rc!=SQLITE_OK ){
157e84d8d32Smistachkin     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
1585c4d9703Sdrh     return TCL_ERROR;
1595c4d9703Sdrh   }
1605c4d9703Sdrh   return TCL_OK;
1615c4d9703Sdrh }
1625c4d9703Sdrh 
1635c4d9703Sdrh /*
1643aac2dd7Sdrh ** Usage:   pager_stmt_begin ID
165fa86c412Sdrh **
166fa86c412Sdrh ** Start a new checkpoint.
167fa86c412Sdrh */
pager_stmt_begin(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)1687617e4a8Smistachkin static int SQLITE_TCLAPI pager_stmt_begin(
169fa86c412Sdrh   void *NotUsed,
170fa86c412Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
171fa86c412Sdrh   int argc,              /* Number of arguments */
172c2eef3b3Sdrh   const char **argv      /* Text of each argument */
173fa86c412Sdrh ){
174fa86c412Sdrh   Pager *pPager;
175fa86c412Sdrh   int rc;
176fa86c412Sdrh   if( argc!=2 ){
177fa86c412Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
178fa86c412Sdrh        " ID\"", 0);
179fa86c412Sdrh     return TCL_ERROR;
180fa86c412Sdrh   }
181e8f52c50Sdrh   pPager = sqlite3TestTextToPtr(argv[1]);
182fd7f0452Sdanielk1977   rc = sqlite3PagerOpenSavepoint(pPager, 1);
183fa86c412Sdrh   if( rc!=SQLITE_OK ){
184e84d8d32Smistachkin     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
185fa86c412Sdrh     return TCL_ERROR;
186fa86c412Sdrh   }
187fa86c412Sdrh   return TCL_OK;
188fa86c412Sdrh }
189fa86c412Sdrh 
190fa86c412Sdrh /*
1913aac2dd7Sdrh ** Usage:   pager_stmt_rollback ID
192fa86c412Sdrh **
193fa86c412Sdrh ** Rollback changes to a checkpoint
194fa86c412Sdrh */
pager_stmt_rollback(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)1957617e4a8Smistachkin static int SQLITE_TCLAPI pager_stmt_rollback(
196fa86c412Sdrh   void *NotUsed,
197fa86c412Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
198fa86c412Sdrh   int argc,              /* Number of arguments */
199c2eef3b3Sdrh   const char **argv      /* Text of each argument */
200fa86c412Sdrh ){
201fa86c412Sdrh   Pager *pPager;
202fa86c412Sdrh   int rc;
203fa86c412Sdrh   if( argc!=2 ){
204fa86c412Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
205fa86c412Sdrh        " ID\"", 0);
206fa86c412Sdrh     return TCL_ERROR;
207fa86c412Sdrh   }
208e8f52c50Sdrh   pPager = sqlite3TestTextToPtr(argv[1]);
209fd7f0452Sdanielk1977   rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, 0);
210fd7f0452Sdanielk1977   sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0);
211fa86c412Sdrh   if( rc!=SQLITE_OK ){
212e84d8d32Smistachkin     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
213fa86c412Sdrh     return TCL_ERROR;
214fa86c412Sdrh   }
215fa86c412Sdrh   return TCL_OK;
216fa86c412Sdrh }
217fa86c412Sdrh 
218fa86c412Sdrh /*
2193aac2dd7Sdrh ** Usage:   pager_stmt_commit ID
220fa86c412Sdrh **
221fa86c412Sdrh ** Commit changes to a checkpoint
222fa86c412Sdrh */
pager_stmt_commit(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)2237617e4a8Smistachkin static int SQLITE_TCLAPI pager_stmt_commit(
224fa86c412Sdrh   void *NotUsed,
225fa86c412Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
226fa86c412Sdrh   int argc,              /* Number of arguments */
227c2eef3b3Sdrh   const char **argv      /* Text of each argument */
228fa86c412Sdrh ){
229fa86c412Sdrh   Pager *pPager;
230fa86c412Sdrh   int rc;
231fa86c412Sdrh   if( argc!=2 ){
232fa86c412Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
233fa86c412Sdrh        " ID\"", 0);
234fa86c412Sdrh     return TCL_ERROR;
235fa86c412Sdrh   }
236e8f52c50Sdrh   pPager = sqlite3TestTextToPtr(argv[1]);
237fd7f0452Sdanielk1977   rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0);
238fa86c412Sdrh   if( rc!=SQLITE_OK ){
239e84d8d32Smistachkin     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
240fa86c412Sdrh     return TCL_ERROR;
241fa86c412Sdrh   }
242fa86c412Sdrh   return TCL_OK;
243fa86c412Sdrh }
244fa86c412Sdrh 
245fa86c412Sdrh /*
2465c4d9703Sdrh ** Usage:   pager_stats ID
2475c4d9703Sdrh **
2485c4d9703Sdrh ** Return pager statistics.
2495c4d9703Sdrh */
pager_stats(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)2507617e4a8Smistachkin static int SQLITE_TCLAPI pager_stats(
2515c4d9703Sdrh   void *NotUsed,
2525c4d9703Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
2535c4d9703Sdrh   int argc,              /* Number of arguments */
254c2eef3b3Sdrh   const char **argv      /* Text of each argument */
2555c4d9703Sdrh ){
2565c4d9703Sdrh   Pager *pPager;
2575c4d9703Sdrh   int i, *a;
2585c4d9703Sdrh   if( argc!=2 ){
2595c4d9703Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2605c4d9703Sdrh        " ID\"", 0);
2615c4d9703Sdrh     return TCL_ERROR;
2625c4d9703Sdrh   }
263e8f52c50Sdrh   pPager = sqlite3TestTextToPtr(argv[1]);
2643b8a05f6Sdanielk1977   a = sqlite3PagerStats(pPager);
2655c4d9703Sdrh   for(i=0; i<9; i++){
2665c4d9703Sdrh     static char *zName[] = {
2675c4d9703Sdrh       "ref", "page", "max", "size", "state", "err",
2685c4d9703Sdrh       "hit", "miss", "ovfl",
2695c4d9703Sdrh     };
2705c4d9703Sdrh     char zBuf[100];
2715c4d9703Sdrh     Tcl_AppendElement(interp, zName[i]);
272fe63d1c9Sdrh     sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",a[i]);
2735c4d9703Sdrh     Tcl_AppendElement(interp, zBuf);
2745c4d9703Sdrh   }
2755c4d9703Sdrh   return TCL_OK;
2765c4d9703Sdrh }
2775c4d9703Sdrh 
2785c4d9703Sdrh /*
2795c4d9703Sdrh ** Usage:   pager_pagecount ID
2805c4d9703Sdrh **
2815c4d9703Sdrh ** Return the size of the database file.
2825c4d9703Sdrh */
pager_pagecount(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)2837617e4a8Smistachkin static int SQLITE_TCLAPI pager_pagecount(
2845c4d9703Sdrh   void *NotUsed,
2855c4d9703Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
2865c4d9703Sdrh   int argc,              /* Number of arguments */
287c2eef3b3Sdrh   const char **argv      /* Text of each argument */
2885c4d9703Sdrh ){
2895c4d9703Sdrh   Pager *pPager;
2905c4d9703Sdrh   char zBuf[100];
291ad0132dfSdanielk1977   int nPage;
2925c4d9703Sdrh   if( argc!=2 ){
2935c4d9703Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2945c4d9703Sdrh        " ID\"", 0);
2955c4d9703Sdrh     return TCL_ERROR;
2965c4d9703Sdrh   }
297e8f52c50Sdrh   pPager = sqlite3TestTextToPtr(argv[1]);
298ad0132dfSdanielk1977   sqlite3PagerPagecount(pPager, &nPage);
299ad0132dfSdanielk1977   sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nPage);
3005c4d9703Sdrh   Tcl_AppendResult(interp, zBuf, 0);
3015c4d9703Sdrh   return TCL_OK;
3025c4d9703Sdrh }
3035c4d9703Sdrh 
3045c4d9703Sdrh /*
3055c4d9703Sdrh ** Usage:   page_get ID PGNO
3065c4d9703Sdrh **
3075c4d9703Sdrh ** Return a pointer to a page from the database.
3085c4d9703Sdrh */
page_get(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)3097617e4a8Smistachkin static int SQLITE_TCLAPI page_get(
3105c4d9703Sdrh   void *NotUsed,
3115c4d9703Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
3125c4d9703Sdrh   int argc,              /* Number of arguments */
313c2eef3b3Sdrh   const char **argv      /* Text of each argument */
3145c4d9703Sdrh ){
3155c4d9703Sdrh   Pager *pPager;
3165c4d9703Sdrh   char zBuf[100];
31727b2f053Smistachkin   DbPage *pPage = 0;
3185c4d9703Sdrh   int pgno;
3195c4d9703Sdrh   int rc;
3205c4d9703Sdrh   if( argc!=3 ){
3215c4d9703Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3225c4d9703Sdrh        " ID PGNO\"", 0);
3235c4d9703Sdrh     return TCL_ERROR;
3245c4d9703Sdrh   }
325e8f52c50Sdrh   pPager = sqlite3TestTextToPtr(argv[1]);
3265c4d9703Sdrh   if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
32789bc4bc6Sdanielk1977   rc = sqlite3PagerSharedLock(pPager);
32889bc4bc6Sdanielk1977   if( rc==SQLITE_OK ){
3299584f58cSdrh     rc = sqlite3PagerGet(pPager, pgno, &pPage, 0);
33089bc4bc6Sdanielk1977   }
3315c4d9703Sdrh   if( rc!=SQLITE_OK ){
332e84d8d32Smistachkin     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
3335c4d9703Sdrh     return TCL_ERROR;
3345c4d9703Sdrh   }
335fe63d1c9Sdrh   sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage);
3365c4d9703Sdrh   Tcl_AppendResult(interp, zBuf, 0);
3375c4d9703Sdrh   return TCL_OK;
3385c4d9703Sdrh }
3395c4d9703Sdrh 
3405c4d9703Sdrh /*
3415c4d9703Sdrh ** Usage:   page_lookup ID PGNO
3425c4d9703Sdrh **
3435c4d9703Sdrh ** Return a pointer to a page if the page is already in cache.
3445c4d9703Sdrh ** If not in cache, return an empty string.
3455c4d9703Sdrh */
page_lookup(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)3467617e4a8Smistachkin static int SQLITE_TCLAPI page_lookup(
3475c4d9703Sdrh   void *NotUsed,
3485c4d9703Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
3495c4d9703Sdrh   int argc,              /* Number of arguments */
350c2eef3b3Sdrh   const char **argv      /* Text of each argument */
3515c4d9703Sdrh ){
3525c4d9703Sdrh   Pager *pPager;
3535c4d9703Sdrh   char zBuf[100];
3543b8a05f6Sdanielk1977   DbPage *pPage;
3555c4d9703Sdrh   int pgno;
3565c4d9703Sdrh   if( argc!=3 ){
3575c4d9703Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3585c4d9703Sdrh        " ID PGNO\"", 0);
3595c4d9703Sdrh     return TCL_ERROR;
3605c4d9703Sdrh   }
361e8f52c50Sdrh   pPager = sqlite3TestTextToPtr(argv[1]);
3625c4d9703Sdrh   if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
3633b8a05f6Sdanielk1977   pPage = sqlite3PagerLookup(pPager, pgno);
3645c4d9703Sdrh   if( pPage ){
365fe63d1c9Sdrh     sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage);
3665c4d9703Sdrh     Tcl_AppendResult(interp, zBuf, 0);
3675c4d9703Sdrh   }
3685c4d9703Sdrh   return TCL_OK;
3695c4d9703Sdrh }
3705c4d9703Sdrh 
3715c4d9703Sdrh /*
372aca790acSdanielk1977 ** Usage:   pager_truncate ID PGNO
373aca790acSdanielk1977 */
pager_truncate(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)3747617e4a8Smistachkin static int SQLITE_TCLAPI pager_truncate(
375aca790acSdanielk1977   void *NotUsed,
376aca790acSdanielk1977   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
377aca790acSdanielk1977   int argc,              /* Number of arguments */
378aca790acSdanielk1977   const char **argv      /* Text of each argument */
379aca790acSdanielk1977 ){
380aca790acSdanielk1977   Pager *pPager;
381aca790acSdanielk1977   int pgno;
382aca790acSdanielk1977   if( argc!=3 ){
383aca790acSdanielk1977     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
384aca790acSdanielk1977        " ID PGNO\"", 0);
385aca790acSdanielk1977     return TCL_ERROR;
386aca790acSdanielk1977   }
387e8f52c50Sdrh   pPager = sqlite3TestTextToPtr(argv[1]);
388aca790acSdanielk1977   if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
389f90b7260Sdanielk1977   sqlite3PagerTruncateImage(pPager, pgno);
390aca790acSdanielk1977   return TCL_OK;
391aca790acSdanielk1977 }
392aca790acSdanielk1977 
393aca790acSdanielk1977 
394aca790acSdanielk1977 /*
3955c4d9703Sdrh ** Usage:   page_unref PAGE
3965c4d9703Sdrh **
3975c4d9703Sdrh ** Drop a pointer to a page.
3985c4d9703Sdrh */
page_unref(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)3997617e4a8Smistachkin static int SQLITE_TCLAPI page_unref(
4005c4d9703Sdrh   void *NotUsed,
4015c4d9703Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
4025c4d9703Sdrh   int argc,              /* Number of arguments */
403c2eef3b3Sdrh   const char **argv      /* Text of each argument */
4045c4d9703Sdrh ){
4053b8a05f6Sdanielk1977   DbPage *pPage;
4065c4d9703Sdrh   if( argc!=2 ){
4075c4d9703Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4085c4d9703Sdrh        " PAGE\"", 0);
4095c4d9703Sdrh     return TCL_ERROR;
4105c4d9703Sdrh   }
411e8f52c50Sdrh   pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]);
412bea2a948Sdanielk1977   sqlite3PagerUnref(pPage);
4135c4d9703Sdrh   return TCL_OK;
4145c4d9703Sdrh }
4155c4d9703Sdrh 
4165c4d9703Sdrh /*
4175c4d9703Sdrh ** Usage:   page_read PAGE
4185c4d9703Sdrh **
4195c4d9703Sdrh ** Return the content of a page
4205c4d9703Sdrh */
page_read(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)4217617e4a8Smistachkin static int SQLITE_TCLAPI page_read(
4225c4d9703Sdrh   void *NotUsed,
4235c4d9703Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
4245c4d9703Sdrh   int argc,              /* Number of arguments */
425c2eef3b3Sdrh   const char **argv      /* Text of each argument */
4265c4d9703Sdrh ){
4275c4d9703Sdrh   char zBuf[100];
4283b8a05f6Sdanielk1977   DbPage *pPage;
4295c4d9703Sdrh   if( argc!=2 ){
4305c4d9703Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4315c4d9703Sdrh        " PAGE\"", 0);
4325c4d9703Sdrh     return TCL_ERROR;
4335c4d9703Sdrh   }
434e8f52c50Sdrh   pPage = sqlite3TestTextToPtr(argv[1]);
4353b8a05f6Sdanielk1977   memcpy(zBuf, sqlite3PagerGetData(pPage), sizeof(zBuf));
4365c4d9703Sdrh   Tcl_AppendResult(interp, zBuf, 0);
4375c4d9703Sdrh   return TCL_OK;
4385c4d9703Sdrh }
4395c4d9703Sdrh 
4405c4d9703Sdrh /*
4415c4d9703Sdrh ** Usage:   page_number PAGE
4425c4d9703Sdrh **
4435c4d9703Sdrh ** Return the page number for a page.
4445c4d9703Sdrh */
page_number(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)4457617e4a8Smistachkin static int SQLITE_TCLAPI page_number(
4465c4d9703Sdrh   void *NotUsed,
4475c4d9703Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
4485c4d9703Sdrh   int argc,              /* Number of arguments */
449c2eef3b3Sdrh   const char **argv      /* Text of each argument */
4505c4d9703Sdrh ){
4515c4d9703Sdrh   char zBuf[100];
4523b8a05f6Sdanielk1977   DbPage *pPage;
4535c4d9703Sdrh   if( argc!=2 ){
4545c4d9703Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4555c4d9703Sdrh        " PAGE\"", 0);
4565c4d9703Sdrh     return TCL_ERROR;
4575c4d9703Sdrh   }
458e8f52c50Sdrh   pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]);
4593b8a05f6Sdanielk1977   sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3PagerPagenumber(pPage));
4605c4d9703Sdrh   Tcl_AppendResult(interp, zBuf, 0);
4615c4d9703Sdrh   return TCL_OK;
4625c4d9703Sdrh }
4635c4d9703Sdrh 
4645c4d9703Sdrh /*
4655c4d9703Sdrh ** Usage:   page_write PAGE DATA
4665c4d9703Sdrh **
4675c4d9703Sdrh ** Write something into a page.
4685c4d9703Sdrh */
page_write(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)4697617e4a8Smistachkin static int SQLITE_TCLAPI page_write(
4705c4d9703Sdrh   void *NotUsed,
4715c4d9703Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
4725c4d9703Sdrh   int argc,              /* Number of arguments */
473c2eef3b3Sdrh   const char **argv      /* Text of each argument */
4745c4d9703Sdrh ){
4753b8a05f6Sdanielk1977   DbPage *pPage;
4763b8a05f6Sdanielk1977   char *pData;
4775c4d9703Sdrh   int rc;
4785c4d9703Sdrh   if( argc!=3 ){
4795c4d9703Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
4805c4d9703Sdrh        " PAGE DATA\"", 0);
4815c4d9703Sdrh     return TCL_ERROR;
4825c4d9703Sdrh   }
483e8f52c50Sdrh   pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]);
4843b8a05f6Sdanielk1977   rc = sqlite3PagerWrite(pPage);
4855c4d9703Sdrh   if( rc!=SQLITE_OK ){
486e84d8d32Smistachkin     Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
4875c4d9703Sdrh     return TCL_ERROR;
4885c4d9703Sdrh   }
4893b8a05f6Sdanielk1977   pData = sqlite3PagerGetData(pPage);
4903b8a05f6Sdanielk1977   strncpy(pData, argv[2], test_pagesize-1);
4913b8a05f6Sdanielk1977   pData[test_pagesize-1] = 0;
4925c4d9703Sdrh   return TCL_OK;
4935c4d9703Sdrh }
4945c4d9703Sdrh 
49544ee5bf7Sdanielk1977 #ifndef SQLITE_OMIT_DISKIO
4965c4d9703Sdrh /*
497d0d006e2Sdrh ** Usage:   fake_big_file  N  FILENAME
498d0d006e2Sdrh **
499d0d006e2Sdrh ** Write a few bytes at the N megabyte point of FILENAME.  This will
500d0d006e2Sdrh ** create a large file.  If the file was a valid SQLite database, then
501d0d006e2Sdrh ** the next time the database is opened, SQLite will begin allocating
502d0d006e2Sdrh ** new pages after N.  If N is 2096 or bigger, this will test the
503d0d006e2Sdrh ** ability of SQLite to write to large files.
504d0d006e2Sdrh */
fake_big_file(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)5057617e4a8Smistachkin static int SQLITE_TCLAPI fake_big_file(
506d0d006e2Sdrh   void *NotUsed,
507d0d006e2Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
508d0d006e2Sdrh   int argc,              /* Number of arguments */
509d0d006e2Sdrh   const char **argv      /* Text of each argument */
510d0d006e2Sdrh ){
511b4b47411Sdanielk1977   sqlite3_vfs *pVfs;
512b4b47411Sdanielk1977   sqlite3_file *fd = 0;
513d0d006e2Sdrh   int rc;
514d0d006e2Sdrh   int n;
515eb206256Sdrh   i64 offset;
51669578ac4Sdrh   char *zFile;
51769578ac4Sdrh   int nFile;
518d0d006e2Sdrh   if( argc!=3 ){
519d0d006e2Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
520d0d006e2Sdrh        " N-MEGABYTES FILE\"", 0);
521d0d006e2Sdrh     return TCL_ERROR;
522d0d006e2Sdrh   }
523d0d006e2Sdrh   if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
5241da477d3Sdrh #if defined(_WIN32)
5251da477d3Sdrh   if( n>2 ){
526*a70a01dbSdrh     Tcl_AppendResult(interp, "cannot create ", argv[1],
527*a70a01dbSdrh        "MB file because Windows "
528*a70a01dbSdrh        "does not support sparse files", (void*)0);
5291da477d3Sdrh     return TCL_ERROR;
5301da477d3Sdrh   }
5311da477d3Sdrh #endif
532b4b47411Sdanielk1977 
533d677b3d6Sdrh   pVfs = sqlite3_vfs_find(0);
53483cc1392Sdrh   nFile = (int)strlen(argv[2]);
53569578ac4Sdrh   zFile = sqlite3_malloc( nFile+2 );
53669578ac4Sdrh   if( zFile==0 ) return TCL_ERROR;
53769578ac4Sdrh   memcpy(zFile, argv[2], nFile+1);
53869578ac4Sdrh   zFile[nFile+1] = 0;
53969578ac4Sdrh   rc = sqlite3OsOpenMalloc(pVfs, zFile, &fd,
540967a4a1cSdanielk1977       (SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0
541fee2d25aSdanielk1977   );
542d0d006e2Sdrh   if( rc ){
543e84d8d32Smistachkin     Tcl_AppendResult(interp, "open failed: ", sqlite3ErrName(rc), 0);
54469578ac4Sdrh     sqlite3_free(zFile);
545d0d006e2Sdrh     return TCL_ERROR;
546d0d006e2Sdrh   }
547d0d006e2Sdrh   offset = n;
548d0d006e2Sdrh   offset *= 1024*1024;
54962079060Sdanielk1977   rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset);
550b4b47411Sdanielk1977   sqlite3OsCloseFree(fd);
55169578ac4Sdrh   sqlite3_free(zFile);
552d0d006e2Sdrh   if( rc ){
553e84d8d32Smistachkin     Tcl_AppendResult(interp, "write failed: ", sqlite3ErrName(rc), 0);
554d0d006e2Sdrh     return TCL_ERROR;
555d0d006e2Sdrh   }
556d0d006e2Sdrh   return TCL_OK;
557d0d006e2Sdrh }
55844ee5bf7Sdanielk1977 #endif
559d0d006e2Sdrh 
560f5e7bb51Sdrh 
5613088d59eSdrh /*
562c7a3bb94Sdrh ** test_control_pending_byte  PENDING_BYTE
563c7a3bb94Sdrh **
564c7a3bb94Sdrh ** Set the PENDING_BYTE using the sqlite3_test_control() interface.
565c7a3bb94Sdrh */
testPendingByte(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)5667617e4a8Smistachkin static int SQLITE_TCLAPI testPendingByte(
567c7a3bb94Sdrh   void *NotUsed,
568c7a3bb94Sdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
569c7a3bb94Sdrh   int argc,              /* Number of arguments */
570c7a3bb94Sdrh   const char **argv      /* Text of each argument */
571c7a3bb94Sdrh ){
572c7a3bb94Sdrh   int pbyte;
573c7a3bb94Sdrh   int rc;
574c7a3bb94Sdrh   if( argc!=2 ){
575c7a3bb94Sdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
576c7a3bb94Sdrh                      " PENDING-BYTE\"", (void*)0);
5778d6ad1ccSdan     return TCL_ERROR;
578c7a3bb94Sdrh   }
579c7a3bb94Sdrh   if( Tcl_GetInt(interp, argv[1], &pbyte) ) return TCL_ERROR;
580c7a3bb94Sdrh   rc = sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, pbyte);
581c7a3bb94Sdrh   Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
582c7a3bb94Sdrh   return TCL_OK;
583c7a3bb94Sdrh }
584c7a3bb94Sdrh 
585c7a3bb94Sdrh /*
586c007f61bSdrh ** The sqlite3FaultSim() callback:
587c007f61bSdrh */
588c007f61bSdrh static Tcl_Interp *faultSimInterp = 0;
589c007f61bSdrh static int faultSimScriptSize = 0;
590c007f61bSdrh static char *faultSimScript;
faultSimCallback(int x)591c007f61bSdrh static int faultSimCallback(int x){
592c007f61bSdrh   char zInt[30];
593c007f61bSdrh   int i;
594c007f61bSdrh   int isNeg;
595c007f61bSdrh   int rc;
596c007f61bSdrh   if( x==0 ){
597c007f61bSdrh     memcpy(faultSimScript+faultSimScriptSize, "0", 2);
598c007f61bSdrh   }else{
599c007f61bSdrh     /* Convert x to text without using any sqlite3 routines */
600c007f61bSdrh     if( x<0 ){
601c007f61bSdrh       isNeg = 1;
602c007f61bSdrh       x = -x;
603c007f61bSdrh     }else{
604c007f61bSdrh       isNeg = 0;
605c007f61bSdrh     }
606c007f61bSdrh     zInt[sizeof(zInt)-1] = 0;
607c007f61bSdrh     for(i=sizeof(zInt)-2; i>0 && x>0; i--, x /= 10){
608c007f61bSdrh       zInt[i] = (x%10) + '0';
609c007f61bSdrh     }
610c007f61bSdrh     if( isNeg ) zInt[i--] = '-';
611c007f61bSdrh     memcpy(faultSimScript+faultSimScriptSize, zInt+i+1, sizeof(zInt)-i);
612c007f61bSdrh   }
613c007f61bSdrh   rc = Tcl_Eval(faultSimInterp, faultSimScript);
614c007f61bSdrh   if( rc ){
615c007f61bSdrh     fprintf(stderr, "fault simulator script failed: [%s]", faultSimScript);
616c007f61bSdrh     rc = SQLITE_ERROR;
617c007f61bSdrh   }else{
618c007f61bSdrh     rc = atoi(Tcl_GetStringResult(faultSimInterp));
619c007f61bSdrh   }
620c007f61bSdrh   Tcl_ResetResult(faultSimInterp);
621c007f61bSdrh   return rc;
622c007f61bSdrh }
623c007f61bSdrh 
624c007f61bSdrh /*
625c007f61bSdrh ** sqlite3_test_control_fault_install SCRIPT
626c007f61bSdrh **
627c007f61bSdrh ** Arrange to invoke SCRIPT with the integer argument to sqlite3FaultSim()
628c007f61bSdrh ** appended, whenever sqlite3FaultSim() is called.  Or, if SCRIPT is the
629c007f61bSdrh ** empty string, cancel the sqlite3FaultSim() callback.
630c007f61bSdrh */
faultInstallCmd(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)6317617e4a8Smistachkin static int SQLITE_TCLAPI faultInstallCmd(
632c007f61bSdrh   void *NotUsed,
633c007f61bSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
634c007f61bSdrh   int argc,              /* Number of arguments */
635c007f61bSdrh   const char **argv      /* Text of each argument */
636c007f61bSdrh ){
637c007f61bSdrh   const char *zScript;
638c007f61bSdrh   int nScript;
639c007f61bSdrh   int rc;
640c007f61bSdrh   if( argc!=1 && argc!=2 ){
641c007f61bSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
642c007f61bSdrh                      " SCRIPT\"", (void*)0);
643c007f61bSdrh   }
644c007f61bSdrh   zScript = argc==2 ? argv[1] : "";
645c007f61bSdrh   nScript = (int)strlen(zScript);
646c007f61bSdrh   if( faultSimScript ){
647c007f61bSdrh     free(faultSimScript);
648c007f61bSdrh     faultSimScript = 0;
649c007f61bSdrh   }
650c007f61bSdrh   if( nScript==0 ){
651c007f61bSdrh     rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, 0);
652c007f61bSdrh   }else{
653c007f61bSdrh     faultSimScript = malloc( nScript+100 );
654c007f61bSdrh     if( faultSimScript==0 ){
655c007f61bSdrh       Tcl_AppendResult(interp, "out of memory", (void*)0);
656c007f61bSdrh       return SQLITE_ERROR;
657c007f61bSdrh     }
658c007f61bSdrh     memcpy(faultSimScript, zScript, nScript);
659c007f61bSdrh     faultSimScript[nScript] = ' ';
660c007f61bSdrh     faultSimScriptSize = nScript+1;
661c007f61bSdrh     faultSimInterp = interp;
662c007f61bSdrh     rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, faultSimCallback);
663c007f61bSdrh   }
664c007f61bSdrh   Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
665c007f61bSdrh   return SQLITE_OK;
666c007f61bSdrh }
667c007f61bSdrh 
668c007f61bSdrh /*
6693088d59eSdrh ** sqlite3BitvecBuiltinTest SIZE PROGRAM
6703088d59eSdrh **
6713088d59eSdrh ** Invoke the SQLITE_TESTCTRL_BITVEC_TEST operator on test_control.
6723088d59eSdrh ** See comments on sqlite3BitvecBuiltinTest() for additional information.
6733088d59eSdrh */
testBitvecBuiltinTest(void * NotUsed,Tcl_Interp * interp,int argc,const char ** argv)6747617e4a8Smistachkin static int SQLITE_TCLAPI testBitvecBuiltinTest(
6753088d59eSdrh   void *NotUsed,
6763088d59eSdrh   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
6773088d59eSdrh   int argc,              /* Number of arguments */
6783088d59eSdrh   const char **argv      /* Text of each argument */
6793088d59eSdrh ){
6803088d59eSdrh   int sz, rc;
6813088d59eSdrh   int nProg = 0;
6823088d59eSdrh   int aProg[100];
6833088d59eSdrh   const char *z;
6843088d59eSdrh   if( argc!=3 ){
6853088d59eSdrh     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
6863088d59eSdrh                      " SIZE PROGRAM\"", (void*)0);
6873088d59eSdrh   }
6883088d59eSdrh   if( Tcl_GetInt(interp, argv[1], &sz) ) return TCL_ERROR;
6893088d59eSdrh   z = argv[2];
6903088d59eSdrh   while( nProg<99 && *z ){
69178ca0e7eSdanielk1977     while( *z && !sqlite3Isdigit(*z) ){ z++; }
6923088d59eSdrh     if( *z==0 ) break;
6933088d59eSdrh     aProg[nProg++] = atoi(z);
69478ca0e7eSdanielk1977     while( sqlite3Isdigit(*z) ){ z++; }
6953088d59eSdrh   }
6963088d59eSdrh   aProg[nProg] = 0;
6973088d59eSdrh   rc = sqlite3_test_control(SQLITE_TESTCTRL_BITVEC_TEST, sz, aProg);
6983088d59eSdrh   Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
6993088d59eSdrh   return TCL_OK;
7003088d59eSdrh }
701f5e7bb51Sdrh 
702f5e7bb51Sdrh /*
7035c4d9703Sdrh ** Register commands with the TCL interpreter.
7045c4d9703Sdrh */
Sqlitetest2_Init(Tcl_Interp * interp)7055c4d9703Sdrh int Sqlitetest2_Init(Tcl_Interp *interp){
706d5eb79ebSdrh   extern int sqlite3_io_error_persist;
7076f8a503dSdanielk1977   extern int sqlite3_io_error_pending;
708c9ac5caaSdrh   extern int sqlite3_io_error_hit;
7091aa5af11Sdrh   extern int sqlite3_io_error_hardhit;
710047d4836Sdrh   extern int sqlite3_diskfull_pending;
711f307a4aaSdrh   extern int sqlite3_diskfull;
712c2eef3b3Sdrh   static struct {
713c2eef3b3Sdrh     char *zName;
714c2eef3b3Sdrh     Tcl_CmdProc *xProc;
715c2eef3b3Sdrh   } aCmd[] = {
716c2eef3b3Sdrh     { "pager_open",              (Tcl_CmdProc*)pager_open          },
717c2eef3b3Sdrh     { "pager_close",             (Tcl_CmdProc*)pager_close         },
718c2eef3b3Sdrh     { "pager_commit",            (Tcl_CmdProc*)pager_commit        },
719c2eef3b3Sdrh     { "pager_rollback",          (Tcl_CmdProc*)pager_rollback      },
7203aac2dd7Sdrh     { "pager_stmt_begin",        (Tcl_CmdProc*)pager_stmt_begin    },
7213aac2dd7Sdrh     { "pager_stmt_commit",       (Tcl_CmdProc*)pager_stmt_commit   },
7223aac2dd7Sdrh     { "pager_stmt_rollback",     (Tcl_CmdProc*)pager_stmt_rollback },
723c2eef3b3Sdrh     { "pager_stats",             (Tcl_CmdProc*)pager_stats         },
724c2eef3b3Sdrh     { "pager_pagecount",         (Tcl_CmdProc*)pager_pagecount     },
725c2eef3b3Sdrh     { "page_get",                (Tcl_CmdProc*)page_get            },
726c2eef3b3Sdrh     { "page_lookup",             (Tcl_CmdProc*)page_lookup         },
727c2eef3b3Sdrh     { "page_unref",              (Tcl_CmdProc*)page_unref          },
728c2eef3b3Sdrh     { "page_read",               (Tcl_CmdProc*)page_read           },
729c2eef3b3Sdrh     { "page_write",              (Tcl_CmdProc*)page_write          },
730c2eef3b3Sdrh     { "page_number",             (Tcl_CmdProc*)page_number         },
731aca790acSdanielk1977     { "pager_truncate",          (Tcl_CmdProc*)pager_truncate      },
73244ee5bf7Sdanielk1977 #ifndef SQLITE_OMIT_DISKIO
733d0d006e2Sdrh     { "fake_big_file",           (Tcl_CmdProc*)fake_big_file       },
73444ee5bf7Sdanielk1977 #endif
7353088d59eSdrh     { "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest     },
736c7a3bb94Sdrh     { "sqlite3_test_control_pending_byte",  (Tcl_CmdProc*)testPendingByte },
737c007f61bSdrh     { "sqlite3_test_control_fault_install", (Tcl_CmdProc*)faultInstallCmd },
738c2eef3b3Sdrh   };
739c2eef3b3Sdrh   int i;
740c2eef3b3Sdrh   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
741c2eef3b3Sdrh     Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
742c2eef3b3Sdrh   }
743369f27ebSdanielk1977   Tcl_LinkVar(interp, "sqlite_io_error_pending",
7446f8a503dSdanielk1977      (char*)&sqlite3_io_error_pending, TCL_LINK_INT);
745d5eb79ebSdrh   Tcl_LinkVar(interp, "sqlite_io_error_persist",
746d5eb79ebSdrh      (char*)&sqlite3_io_error_persist, TCL_LINK_INT);
747c9ac5caaSdrh   Tcl_LinkVar(interp, "sqlite_io_error_hit",
748c9ac5caaSdrh      (char*)&sqlite3_io_error_hit, TCL_LINK_INT);
7491aa5af11Sdrh   Tcl_LinkVar(interp, "sqlite_io_error_hardhit",
7501aa5af11Sdrh      (char*)&sqlite3_io_error_hardhit, TCL_LINK_INT);
751047d4836Sdrh   Tcl_LinkVar(interp, "sqlite_diskfull_pending",
752047d4836Sdrh      (char*)&sqlite3_diskfull_pending, TCL_LINK_INT);
753f307a4aaSdrh   Tcl_LinkVar(interp, "sqlite_diskfull",
754f307a4aaSdrh      (char*)&sqlite3_diskfull, TCL_LINK_INT);
755f83dc1efSdrh #ifndef SQLITE_OMIT_WSD
756fd5f5b65Sdanielk1977   Tcl_LinkVar(interp, "sqlite_pending_byte",
757c7a3bb94Sdrh      (char*)&sqlite3PendingByte, TCL_LINK_INT | TCL_LINK_READ_ONLY);
758f83dc1efSdrh #endif
7595c4d9703Sdrh   return TCL_OK;
7605c4d9703Sdrh }
761