| OLD | NEW | 
 | (Empty) | 
|    1 /* |  | 
|    2 ** 2001 September 15 |  | 
|    3 ** |  | 
|    4 ** The author disclaims copyright to this source code.  In place of |  | 
|    5 ** a legal notice, here is a blessing: |  | 
|    6 ** |  | 
|    7 **    May you do good and not evil. |  | 
|    8 **    May you find forgiveness for yourself and forgive others. |  | 
|    9 **    May you share freely, never taking more than you give. |  | 
|   10 ** |  | 
|   11 ************************************************************************* |  | 
|   12 ** Code for testing the pager.c module in SQLite.  This code |  | 
|   13 ** is not included in the SQLite library.  It is used for automated |  | 
|   14 ** testing of the SQLite library. |  | 
|   15 ** |  | 
|   16 ** $Id: test2.c,v 1.74 2009/07/24 19:01:20 drh Exp $ |  | 
|   17 */ |  | 
|   18 #include "sqliteInt.h" |  | 
|   19 #include "tcl.h" |  | 
|   20 #include <stdlib.h> |  | 
|   21 #include <string.h> |  | 
|   22 #include <ctype.h> |  | 
|   23  |  | 
|   24 /* |  | 
|   25 ** Interpret an SQLite error number |  | 
|   26 */ |  | 
|   27 static char *errorName(int rc){ |  | 
|   28   char *zName; |  | 
|   29   switch( rc ){ |  | 
|   30     case SQLITE_OK:         zName = "SQLITE_OK";          break; |  | 
|   31     case SQLITE_ERROR:      zName = "SQLITE_ERROR";       break; |  | 
|   32     case SQLITE_PERM:       zName = "SQLITE_PERM";        break; |  | 
|   33     case SQLITE_ABORT:      zName = "SQLITE_ABORT";       break; |  | 
|   34     case SQLITE_BUSY:       zName = "SQLITE_BUSY";        break; |  | 
|   35     case SQLITE_NOMEM:      zName = "SQLITE_NOMEM";       break; |  | 
|   36     case SQLITE_READONLY:   zName = "SQLITE_READONLY";    break; |  | 
|   37     case SQLITE_INTERRUPT:  zName = "SQLITE_INTERRUPT";   break; |  | 
|   38     case SQLITE_IOERR:      zName = "SQLITE_IOERR";       break; |  | 
|   39     case SQLITE_CORRUPT:    zName = "SQLITE_CORRUPT";     break; |  | 
|   40     case SQLITE_FULL:       zName = "SQLITE_FULL";        break; |  | 
|   41     case SQLITE_CANTOPEN:   zName = "SQLITE_CANTOPEN";    break; |  | 
|   42     case SQLITE_PROTOCOL:   zName = "SQLITE_PROTOCOL";    break; |  | 
|   43     case SQLITE_EMPTY:      zName = "SQLITE_EMPTY";       break; |  | 
|   44     case SQLITE_SCHEMA:     zName = "SQLITE_SCHEMA";      break; |  | 
|   45     case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT";  break; |  | 
|   46     case SQLITE_MISMATCH:   zName = "SQLITE_MISMATCH";    break; |  | 
|   47     case SQLITE_MISUSE:     zName = "SQLITE_MISUSE";      break; |  | 
|   48     case SQLITE_NOLFS:      zName = "SQLITE_NOLFS";       break; |  | 
|   49     default:                zName = "SQLITE_Unknown";     break; |  | 
|   50   } |  | 
|   51   return zName; |  | 
|   52 } |  | 
|   53  |  | 
|   54 /* |  | 
|   55 ** Page size and reserved size used for testing. |  | 
|   56 */ |  | 
|   57 static int test_pagesize = 1024; |  | 
|   58  |  | 
|   59 /* |  | 
|   60 ** Dummy page reinitializer |  | 
|   61 */ |  | 
|   62 static void pager_test_reiniter(DbPage *pNotUsed){ |  | 
|   63   return; |  | 
|   64 } |  | 
|   65  |  | 
|   66 /* |  | 
|   67 ** Usage:   pager_open FILENAME N-PAGE |  | 
|   68 ** |  | 
|   69 ** Open a new pager |  | 
|   70 */ |  | 
|   71 static int pager_open( |  | 
|   72   void *NotUsed, |  | 
|   73   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|   74   int argc,              /* Number of arguments */ |  | 
|   75   const char **argv      /* Text of each argument */ |  | 
|   76 ){ |  | 
|   77   u16 pageSize; |  | 
|   78   Pager *pPager; |  | 
|   79   int nPage; |  | 
|   80   int rc; |  | 
|   81   char zBuf[100]; |  | 
|   82   if( argc!=3 ){ |  | 
|   83     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|   84        " FILENAME N-PAGE\"", 0); |  | 
|   85     return TCL_ERROR; |  | 
|   86   } |  | 
|   87   if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR; |  | 
|   88   rc = sqlite3PagerOpen(sqlite3_vfs_find(0), &pPager, argv[1], 0, 0, |  | 
|   89       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB, |  | 
|   90       pager_test_reiniter); |  | 
|   91   if( rc!=SQLITE_OK ){ |  | 
|   92     Tcl_AppendResult(interp, errorName(rc), 0); |  | 
|   93     return TCL_ERROR; |  | 
|   94   } |  | 
|   95   sqlite3PagerSetCachesize(pPager, nPage); |  | 
|   96   pageSize = test_pagesize; |  | 
|   97   sqlite3PagerSetPagesize(pPager, &pageSize, -1); |  | 
|   98   sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPager); |  | 
|   99   Tcl_AppendResult(interp, zBuf, 0); |  | 
|  100   return TCL_OK; |  | 
|  101 } |  | 
|  102  |  | 
|  103 /* |  | 
|  104 ** Usage:   pager_close ID |  | 
|  105 ** |  | 
|  106 ** Close the given pager. |  | 
|  107 */ |  | 
|  108 static int pager_close( |  | 
|  109   void *NotUsed, |  | 
|  110   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  111   int argc,              /* Number of arguments */ |  | 
|  112   const char **argv      /* Text of each argument */ |  | 
|  113 ){ |  | 
|  114   Pager *pPager; |  | 
|  115   int rc; |  | 
|  116   if( argc!=2 ){ |  | 
|  117     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  118        " ID\"", 0); |  | 
|  119     return TCL_ERROR; |  | 
|  120   } |  | 
|  121   pPager = sqlite3TestTextToPtr(argv[1]); |  | 
|  122   rc = sqlite3PagerClose(pPager); |  | 
|  123   if( rc!=SQLITE_OK ){ |  | 
|  124     Tcl_AppendResult(interp, errorName(rc), 0); |  | 
|  125     return TCL_ERROR; |  | 
|  126   } |  | 
|  127   return TCL_OK; |  | 
|  128 } |  | 
|  129  |  | 
|  130 /* |  | 
|  131 ** Usage:   pager_rollback ID |  | 
|  132 ** |  | 
|  133 ** Rollback changes |  | 
|  134 */ |  | 
|  135 static int pager_rollback( |  | 
|  136   void *NotUsed, |  | 
|  137   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  138   int argc,              /* Number of arguments */ |  | 
|  139   const char **argv      /* Text of each argument */ |  | 
|  140 ){ |  | 
|  141   Pager *pPager; |  | 
|  142   int rc; |  | 
|  143   if( argc!=2 ){ |  | 
|  144     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  145        " ID\"", 0); |  | 
|  146     return TCL_ERROR; |  | 
|  147   } |  | 
|  148   pPager = sqlite3TestTextToPtr(argv[1]); |  | 
|  149   rc = sqlite3PagerRollback(pPager); |  | 
|  150   if( rc!=SQLITE_OK ){ |  | 
|  151     Tcl_AppendResult(interp, errorName(rc), 0); |  | 
|  152     return TCL_ERROR; |  | 
|  153   } |  | 
|  154   return TCL_OK; |  | 
|  155 } |  | 
|  156  |  | 
|  157 /* |  | 
|  158 ** Usage:   pager_commit ID |  | 
|  159 ** |  | 
|  160 ** Commit all changes |  | 
|  161 */ |  | 
|  162 static int pager_commit( |  | 
|  163   void *NotUsed, |  | 
|  164   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  165   int argc,              /* Number of arguments */ |  | 
|  166   const char **argv      /* Text of each argument */ |  | 
|  167 ){ |  | 
|  168   Pager *pPager; |  | 
|  169   int rc; |  | 
|  170   if( argc!=2 ){ |  | 
|  171     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  172        " ID\"", 0); |  | 
|  173     return TCL_ERROR; |  | 
|  174   } |  | 
|  175   pPager = sqlite3TestTextToPtr(argv[1]); |  | 
|  176   rc = sqlite3PagerCommitPhaseOne(pPager, 0, 0); |  | 
|  177   if( rc!=SQLITE_OK ){ |  | 
|  178     Tcl_AppendResult(interp, errorName(rc), 0); |  | 
|  179     return TCL_ERROR; |  | 
|  180   } |  | 
|  181   rc = sqlite3PagerCommitPhaseTwo(pPager); |  | 
|  182   if( rc!=SQLITE_OK ){ |  | 
|  183     Tcl_AppendResult(interp, errorName(rc), 0); |  | 
|  184     return TCL_ERROR; |  | 
|  185   } |  | 
|  186   return TCL_OK; |  | 
|  187 } |  | 
|  188  |  | 
|  189 /* |  | 
|  190 ** Usage:   pager_stmt_begin ID |  | 
|  191 ** |  | 
|  192 ** Start a new checkpoint. |  | 
|  193 */ |  | 
|  194 static int pager_stmt_begin( |  | 
|  195   void *NotUsed, |  | 
|  196   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  197   int argc,              /* Number of arguments */ |  | 
|  198   const char **argv      /* Text of each argument */ |  | 
|  199 ){ |  | 
|  200   Pager *pPager; |  | 
|  201   int rc; |  | 
|  202   if( argc!=2 ){ |  | 
|  203     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  204        " ID\"", 0); |  | 
|  205     return TCL_ERROR; |  | 
|  206   } |  | 
|  207   pPager = sqlite3TestTextToPtr(argv[1]); |  | 
|  208   rc = sqlite3PagerOpenSavepoint(pPager, 1); |  | 
|  209   if( rc!=SQLITE_OK ){ |  | 
|  210     Tcl_AppendResult(interp, errorName(rc), 0); |  | 
|  211     return TCL_ERROR; |  | 
|  212   } |  | 
|  213   return TCL_OK; |  | 
|  214 } |  | 
|  215  |  | 
|  216 /* |  | 
|  217 ** Usage:   pager_stmt_rollback ID |  | 
|  218 ** |  | 
|  219 ** Rollback changes to a checkpoint |  | 
|  220 */ |  | 
|  221 static int pager_stmt_rollback( |  | 
|  222   void *NotUsed, |  | 
|  223   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  224   int argc,              /* Number of arguments */ |  | 
|  225   const char **argv      /* Text of each argument */ |  | 
|  226 ){ |  | 
|  227   Pager *pPager; |  | 
|  228   int rc; |  | 
|  229   if( argc!=2 ){ |  | 
|  230     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  231        " ID\"", 0); |  | 
|  232     return TCL_ERROR; |  | 
|  233   } |  | 
|  234   pPager = sqlite3TestTextToPtr(argv[1]); |  | 
|  235   rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, 0); |  | 
|  236   sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0); |  | 
|  237   if( rc!=SQLITE_OK ){ |  | 
|  238     Tcl_AppendResult(interp, errorName(rc), 0); |  | 
|  239     return TCL_ERROR; |  | 
|  240   } |  | 
|  241   return TCL_OK; |  | 
|  242 } |  | 
|  243  |  | 
|  244 /* |  | 
|  245 ** Usage:   pager_stmt_commit ID |  | 
|  246 ** |  | 
|  247 ** Commit changes to a checkpoint |  | 
|  248 */ |  | 
|  249 static int pager_stmt_commit( |  | 
|  250   void *NotUsed, |  | 
|  251   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  252   int argc,              /* Number of arguments */ |  | 
|  253   const char **argv      /* Text of each argument */ |  | 
|  254 ){ |  | 
|  255   Pager *pPager; |  | 
|  256   int rc; |  | 
|  257   if( argc!=2 ){ |  | 
|  258     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  259        " ID\"", 0); |  | 
|  260     return TCL_ERROR; |  | 
|  261   } |  | 
|  262   pPager = sqlite3TestTextToPtr(argv[1]); |  | 
|  263   rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0); |  | 
|  264   if( rc!=SQLITE_OK ){ |  | 
|  265     Tcl_AppendResult(interp, errorName(rc), 0); |  | 
|  266     return TCL_ERROR; |  | 
|  267   } |  | 
|  268   return TCL_OK; |  | 
|  269 } |  | 
|  270  |  | 
|  271 /* |  | 
|  272 ** Usage:   pager_stats ID |  | 
|  273 ** |  | 
|  274 ** Return pager statistics. |  | 
|  275 */ |  | 
|  276 static int pager_stats( |  | 
|  277   void *NotUsed, |  | 
|  278   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  279   int argc,              /* Number of arguments */ |  | 
|  280   const char **argv      /* Text of each argument */ |  | 
|  281 ){ |  | 
|  282   Pager *pPager; |  | 
|  283   int i, *a; |  | 
|  284   if( argc!=2 ){ |  | 
|  285     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  286        " ID\"", 0); |  | 
|  287     return TCL_ERROR; |  | 
|  288   } |  | 
|  289   pPager = sqlite3TestTextToPtr(argv[1]); |  | 
|  290   a = sqlite3PagerStats(pPager); |  | 
|  291   for(i=0; i<9; i++){ |  | 
|  292     static char *zName[] = { |  | 
|  293       "ref", "page", "max", "size", "state", "err", |  | 
|  294       "hit", "miss", "ovfl", |  | 
|  295     }; |  | 
|  296     char zBuf[100]; |  | 
|  297     Tcl_AppendElement(interp, zName[i]); |  | 
|  298     sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",a[i]); |  | 
|  299     Tcl_AppendElement(interp, zBuf); |  | 
|  300   } |  | 
|  301   return TCL_OK; |  | 
|  302 } |  | 
|  303  |  | 
|  304 /* |  | 
|  305 ** Usage:   pager_pagecount ID |  | 
|  306 ** |  | 
|  307 ** Return the size of the database file. |  | 
|  308 */ |  | 
|  309 static int pager_pagecount( |  | 
|  310   void *NotUsed, |  | 
|  311   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  312   int argc,              /* Number of arguments */ |  | 
|  313   const char **argv      /* Text of each argument */ |  | 
|  314 ){ |  | 
|  315   Pager *pPager; |  | 
|  316   char zBuf[100]; |  | 
|  317   int nPage; |  | 
|  318   if( argc!=2 ){ |  | 
|  319     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  320        " ID\"", 0); |  | 
|  321     return TCL_ERROR; |  | 
|  322   } |  | 
|  323   pPager = sqlite3TestTextToPtr(argv[1]); |  | 
|  324   sqlite3PagerPagecount(pPager, &nPage); |  | 
|  325   sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nPage); |  | 
|  326   Tcl_AppendResult(interp, zBuf, 0); |  | 
|  327   return TCL_OK; |  | 
|  328 } |  | 
|  329  |  | 
|  330 /* |  | 
|  331 ** Usage:   page_get ID PGNO |  | 
|  332 ** |  | 
|  333 ** Return a pointer to a page from the database. |  | 
|  334 */ |  | 
|  335 static int page_get( |  | 
|  336   void *NotUsed, |  | 
|  337   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  338   int argc,              /* Number of arguments */ |  | 
|  339   const char **argv      /* Text of each argument */ |  | 
|  340 ){ |  | 
|  341   Pager *pPager; |  | 
|  342   char zBuf[100]; |  | 
|  343   DbPage *pPage; |  | 
|  344   int pgno; |  | 
|  345   int rc; |  | 
|  346   if( argc!=3 ){ |  | 
|  347     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  348        " ID PGNO\"", 0); |  | 
|  349     return TCL_ERROR; |  | 
|  350   } |  | 
|  351   pPager = sqlite3TestTextToPtr(argv[1]); |  | 
|  352   if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; |  | 
|  353   rc = sqlite3PagerSharedLock(pPager); |  | 
|  354   if( rc==SQLITE_OK ){ |  | 
|  355     rc = sqlite3PagerGet(pPager, pgno, &pPage); |  | 
|  356   } |  | 
|  357   if( rc!=SQLITE_OK ){ |  | 
|  358     Tcl_AppendResult(interp, errorName(rc), 0); |  | 
|  359     return TCL_ERROR; |  | 
|  360   } |  | 
|  361   sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); |  | 
|  362   Tcl_AppendResult(interp, zBuf, 0); |  | 
|  363   return TCL_OK; |  | 
|  364 } |  | 
|  365  |  | 
|  366 /* |  | 
|  367 ** Usage:   page_lookup ID PGNO |  | 
|  368 ** |  | 
|  369 ** Return a pointer to a page if the page is already in cache. |  | 
|  370 ** If not in cache, return an empty string. |  | 
|  371 */ |  | 
|  372 static int page_lookup( |  | 
|  373   void *NotUsed, |  | 
|  374   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  375   int argc,              /* Number of arguments */ |  | 
|  376   const char **argv      /* Text of each argument */ |  | 
|  377 ){ |  | 
|  378   Pager *pPager; |  | 
|  379   char zBuf[100]; |  | 
|  380   DbPage *pPage; |  | 
|  381   int pgno; |  | 
|  382   if( argc!=3 ){ |  | 
|  383     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  384        " ID PGNO\"", 0); |  | 
|  385     return TCL_ERROR; |  | 
|  386   } |  | 
|  387   pPager = sqlite3TestTextToPtr(argv[1]); |  | 
|  388   if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; |  | 
|  389   pPage = sqlite3PagerLookup(pPager, pgno); |  | 
|  390   if( pPage ){ |  | 
|  391     sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage); |  | 
|  392     Tcl_AppendResult(interp, zBuf, 0); |  | 
|  393   } |  | 
|  394   return TCL_OK; |  | 
|  395 } |  | 
|  396  |  | 
|  397 /* |  | 
|  398 ** Usage:   pager_truncate ID PGNO |  | 
|  399 */ |  | 
|  400 static int pager_truncate( |  | 
|  401   void *NotUsed, |  | 
|  402   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  403   int argc,              /* Number of arguments */ |  | 
|  404   const char **argv      /* Text of each argument */ |  | 
|  405 ){ |  | 
|  406   Pager *pPager; |  | 
|  407   int pgno; |  | 
|  408   if( argc!=3 ){ |  | 
|  409     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  410        " ID PGNO\"", 0); |  | 
|  411     return TCL_ERROR; |  | 
|  412   } |  | 
|  413   pPager = sqlite3TestTextToPtr(argv[1]); |  | 
|  414   if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR; |  | 
|  415   sqlite3PagerTruncateImage(pPager, pgno); |  | 
|  416   return TCL_OK; |  | 
|  417 } |  | 
|  418  |  | 
|  419  |  | 
|  420 /* |  | 
|  421 ** Usage:   page_unref PAGE |  | 
|  422 ** |  | 
|  423 ** Drop a pointer to a page. |  | 
|  424 */ |  | 
|  425 static int page_unref( |  | 
|  426   void *NotUsed, |  | 
|  427   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  428   int argc,              /* Number of arguments */ |  | 
|  429   const char **argv      /* Text of each argument */ |  | 
|  430 ){ |  | 
|  431   DbPage *pPage; |  | 
|  432   if( argc!=2 ){ |  | 
|  433     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  434        " PAGE\"", 0); |  | 
|  435     return TCL_ERROR; |  | 
|  436   } |  | 
|  437   pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); |  | 
|  438   sqlite3PagerUnref(pPage); |  | 
|  439   return TCL_OK; |  | 
|  440 } |  | 
|  441  |  | 
|  442 /* |  | 
|  443 ** Usage:   page_read PAGE |  | 
|  444 ** |  | 
|  445 ** Return the content of a page |  | 
|  446 */ |  | 
|  447 static int page_read( |  | 
|  448   void *NotUsed, |  | 
|  449   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  450   int argc,              /* Number of arguments */ |  | 
|  451   const char **argv      /* Text of each argument */ |  | 
|  452 ){ |  | 
|  453   char zBuf[100]; |  | 
|  454   DbPage *pPage; |  | 
|  455   if( argc!=2 ){ |  | 
|  456     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  457        " PAGE\"", 0); |  | 
|  458     return TCL_ERROR; |  | 
|  459   } |  | 
|  460   pPage = sqlite3TestTextToPtr(argv[1]); |  | 
|  461   memcpy(zBuf, sqlite3PagerGetData(pPage), sizeof(zBuf)); |  | 
|  462   Tcl_AppendResult(interp, zBuf, 0); |  | 
|  463   return TCL_OK; |  | 
|  464 } |  | 
|  465  |  | 
|  466 /* |  | 
|  467 ** Usage:   page_number PAGE |  | 
|  468 ** |  | 
|  469 ** Return the page number for a page. |  | 
|  470 */ |  | 
|  471 static int page_number( |  | 
|  472   void *NotUsed, |  | 
|  473   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  474   int argc,              /* Number of arguments */ |  | 
|  475   const char **argv      /* Text of each argument */ |  | 
|  476 ){ |  | 
|  477   char zBuf[100]; |  | 
|  478   DbPage *pPage; |  | 
|  479   if( argc!=2 ){ |  | 
|  480     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  481        " PAGE\"", 0); |  | 
|  482     return TCL_ERROR; |  | 
|  483   } |  | 
|  484   pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); |  | 
|  485   sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3PagerPagenumber(pPage)); |  | 
|  486   Tcl_AppendResult(interp, zBuf, 0); |  | 
|  487   return TCL_OK; |  | 
|  488 } |  | 
|  489  |  | 
|  490 /* |  | 
|  491 ** Usage:   page_write PAGE DATA |  | 
|  492 ** |  | 
|  493 ** Write something into a page. |  | 
|  494 */ |  | 
|  495 static int page_write( |  | 
|  496   void *NotUsed, |  | 
|  497   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  498   int argc,              /* Number of arguments */ |  | 
|  499   const char **argv      /* Text of each argument */ |  | 
|  500 ){ |  | 
|  501   DbPage *pPage; |  | 
|  502   char *pData; |  | 
|  503   int rc; |  | 
|  504   if( argc!=3 ){ |  | 
|  505     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  506        " PAGE DATA\"", 0); |  | 
|  507     return TCL_ERROR; |  | 
|  508   } |  | 
|  509   pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]); |  | 
|  510   rc = sqlite3PagerWrite(pPage); |  | 
|  511   if( rc!=SQLITE_OK ){ |  | 
|  512     Tcl_AppendResult(interp, errorName(rc), 0); |  | 
|  513     return TCL_ERROR; |  | 
|  514   } |  | 
|  515   pData = sqlite3PagerGetData(pPage); |  | 
|  516   strncpy(pData, argv[2], test_pagesize-1); |  | 
|  517   pData[test_pagesize-1] = 0; |  | 
|  518   return TCL_OK; |  | 
|  519 } |  | 
|  520  |  | 
|  521 #ifndef SQLITE_OMIT_DISKIO |  | 
|  522 /* |  | 
|  523 ** Usage:   fake_big_file  N  FILENAME |  | 
|  524 ** |  | 
|  525 ** Write a few bytes at the N megabyte point of FILENAME.  This will |  | 
|  526 ** create a large file.  If the file was a valid SQLite database, then |  | 
|  527 ** the next time the database is opened, SQLite will begin allocating |  | 
|  528 ** new pages after N.  If N is 2096 or bigger, this will test the |  | 
|  529 ** ability of SQLite to write to large files. |  | 
|  530 */ |  | 
|  531 static int fake_big_file( |  | 
|  532   void *NotUsed, |  | 
|  533   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  534   int argc,              /* Number of arguments */ |  | 
|  535   const char **argv      /* Text of each argument */ |  | 
|  536 ){ |  | 
|  537   sqlite3_vfs *pVfs; |  | 
|  538   sqlite3_file *fd = 0; |  | 
|  539   int rc; |  | 
|  540   int n; |  | 
|  541   i64 offset; |  | 
|  542   if( argc!=3 ){ |  | 
|  543     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  544        " N-MEGABYTES FILE\"", 0); |  | 
|  545     return TCL_ERROR; |  | 
|  546   } |  | 
|  547   if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR; |  | 
|  548  |  | 
|  549   pVfs = sqlite3_vfs_find(0); |  | 
|  550   rc = sqlite3OsOpenMalloc(pVfs, argv[2], &fd,  |  | 
|  551       (SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0 |  | 
|  552   ); |  | 
|  553   if( rc ){ |  | 
|  554     Tcl_AppendResult(interp, "open failed: ", errorName(rc), 0); |  | 
|  555     return TCL_ERROR; |  | 
|  556   } |  | 
|  557   offset = n; |  | 
|  558   offset *= 1024*1024; |  | 
|  559   rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset); |  | 
|  560   sqlite3OsCloseFree(fd); |  | 
|  561   if( rc ){ |  | 
|  562     Tcl_AppendResult(interp, "write failed: ", errorName(rc), 0); |  | 
|  563     return TCL_ERROR; |  | 
|  564   } |  | 
|  565   return TCL_OK; |  | 
|  566 } |  | 
|  567 #endif |  | 
|  568  |  | 
|  569  |  | 
|  570 /* |  | 
|  571 ** test_control_pending_byte  PENDING_BYTE |  | 
|  572 ** |  | 
|  573 ** Set the PENDING_BYTE using the sqlite3_test_control() interface. |  | 
|  574 */ |  | 
|  575 static int testPendingByte( |  | 
|  576   void *NotUsed, |  | 
|  577   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  578   int argc,              /* Number of arguments */ |  | 
|  579   const char **argv      /* Text of each argument */ |  | 
|  580 ){ |  | 
|  581   int pbyte; |  | 
|  582   int rc; |  | 
|  583   if( argc!=2 ){ |  | 
|  584     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  585                      " PENDING-BYTE\"", (void*)0); |  | 
|  586   } |  | 
|  587   if( Tcl_GetInt(interp, argv[1], &pbyte) ) return TCL_ERROR; |  | 
|  588   rc = sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, pbyte); |  | 
|  589   Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); |  | 
|  590   return TCL_OK; |  | 
|  591 }   |  | 
|  592  |  | 
|  593 /* |  | 
|  594 ** sqlite3BitvecBuiltinTest SIZE PROGRAM |  | 
|  595 ** |  | 
|  596 ** Invoke the SQLITE_TESTCTRL_BITVEC_TEST operator on test_control. |  | 
|  597 ** See comments on sqlite3BitvecBuiltinTest() for additional information. |  | 
|  598 */ |  | 
|  599 static int testBitvecBuiltinTest( |  | 
|  600   void *NotUsed, |  | 
|  601   Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ |  | 
|  602   int argc,              /* Number of arguments */ |  | 
|  603   const char **argv      /* Text of each argument */ |  | 
|  604 ){ |  | 
|  605   int sz, rc; |  | 
|  606   int nProg = 0; |  | 
|  607   int aProg[100]; |  | 
|  608   const char *z; |  | 
|  609   if( argc!=3 ){ |  | 
|  610     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], |  | 
|  611                      " SIZE PROGRAM\"", (void*)0); |  | 
|  612   } |  | 
|  613   if( Tcl_GetInt(interp, argv[1], &sz) ) return TCL_ERROR; |  | 
|  614   z = argv[2]; |  | 
|  615   while( nProg<99 && *z ){ |  | 
|  616     while( *z && !sqlite3Isdigit(*z) ){ z++; } |  | 
|  617     if( *z==0 ) break; |  | 
|  618     aProg[nProg++] = atoi(z); |  | 
|  619     while( sqlite3Isdigit(*z) ){ z++; } |  | 
|  620   } |  | 
|  621   aProg[nProg] = 0; |  | 
|  622   rc = sqlite3_test_control(SQLITE_TESTCTRL_BITVEC_TEST, sz, aProg); |  | 
|  623   Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); |  | 
|  624   return TCL_OK; |  | 
|  625 }   |  | 
|  626  |  | 
|  627 /* |  | 
|  628 ** Register commands with the TCL interpreter. |  | 
|  629 */ |  | 
|  630 int Sqlitetest2_Init(Tcl_Interp *interp){ |  | 
|  631   extern int sqlite3_io_error_persist; |  | 
|  632   extern int sqlite3_io_error_pending; |  | 
|  633   extern int sqlite3_io_error_hit; |  | 
|  634   extern int sqlite3_io_error_hardhit; |  | 
|  635   extern int sqlite3_diskfull_pending; |  | 
|  636   extern int sqlite3_diskfull; |  | 
|  637   static struct { |  | 
|  638     char *zName; |  | 
|  639     Tcl_CmdProc *xProc; |  | 
|  640   } aCmd[] = { |  | 
|  641     { "pager_open",              (Tcl_CmdProc*)pager_open          }, |  | 
|  642     { "pager_close",             (Tcl_CmdProc*)pager_close         }, |  | 
|  643     { "pager_commit",            (Tcl_CmdProc*)pager_commit        }, |  | 
|  644     { "pager_rollback",          (Tcl_CmdProc*)pager_rollback      }, |  | 
|  645     { "pager_stmt_begin",        (Tcl_CmdProc*)pager_stmt_begin    }, |  | 
|  646     { "pager_stmt_commit",       (Tcl_CmdProc*)pager_stmt_commit   }, |  | 
|  647     { "pager_stmt_rollback",     (Tcl_CmdProc*)pager_stmt_rollback }, |  | 
|  648     { "pager_stats",             (Tcl_CmdProc*)pager_stats         }, |  | 
|  649     { "pager_pagecount",         (Tcl_CmdProc*)pager_pagecount     }, |  | 
|  650     { "page_get",                (Tcl_CmdProc*)page_get            }, |  | 
|  651     { "page_lookup",             (Tcl_CmdProc*)page_lookup         }, |  | 
|  652     { "page_unref",              (Tcl_CmdProc*)page_unref          }, |  | 
|  653     { "page_read",               (Tcl_CmdProc*)page_read           }, |  | 
|  654     { "page_write",              (Tcl_CmdProc*)page_write          }, |  | 
|  655     { "page_number",             (Tcl_CmdProc*)page_number         }, |  | 
|  656     { "pager_truncate",          (Tcl_CmdProc*)pager_truncate      }, |  | 
|  657 #ifndef SQLITE_OMIT_DISKIO |  | 
|  658     { "fake_big_file",           (Tcl_CmdProc*)fake_big_file       }, |  | 
|  659 #endif |  | 
|  660     { "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest     }, |  | 
|  661     { "sqlite3_test_control_pending_byte", (Tcl_CmdProc*)testPendingByte }, |  | 
|  662   }; |  | 
|  663   int i; |  | 
|  664   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ |  | 
|  665     Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); |  | 
|  666   } |  | 
|  667   Tcl_LinkVar(interp, "sqlite_io_error_pending", |  | 
|  668      (char*)&sqlite3_io_error_pending, TCL_LINK_INT); |  | 
|  669   Tcl_LinkVar(interp, "sqlite_io_error_persist", |  | 
|  670      (char*)&sqlite3_io_error_persist, TCL_LINK_INT); |  | 
|  671   Tcl_LinkVar(interp, "sqlite_io_error_hit", |  | 
|  672      (char*)&sqlite3_io_error_hit, TCL_LINK_INT); |  | 
|  673   Tcl_LinkVar(interp, "sqlite_io_error_hardhit", |  | 
|  674      (char*)&sqlite3_io_error_hardhit, TCL_LINK_INT); |  | 
|  675   Tcl_LinkVar(interp, "sqlite_diskfull_pending", |  | 
|  676      (char*)&sqlite3_diskfull_pending, TCL_LINK_INT); |  | 
|  677   Tcl_LinkVar(interp, "sqlite_diskfull", |  | 
|  678      (char*)&sqlite3_diskfull, TCL_LINK_INT); |  | 
|  679   Tcl_LinkVar(interp, "sqlite_pending_byte", |  | 
|  680      (char*)&sqlite3PendingByte, TCL_LINK_INT | TCL_LINK_READ_ONLY); |  | 
|  681   return TCL_OK; |  | 
|  682 } |  | 
| OLD | NEW |