blob: 850e1e1a0448ef639178deb881528886bece8cc5 [file] [log] [blame]
drh5c4d9702001-08-20 00:33:58 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drh5c4d9702001-08-20 00:33:58 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drh5c4d9702001-08-20 00:33:58 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** 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.
drh5c4d9702001-08-20 00:33:58 +000010**
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.
drh5c4d9702001-08-20 00:33:58 +000015*/
16#include "sqliteInt.h"
mistachkin52b1dbb2016-07-28 14:37:04 +000017#if defined(INCLUDE_SQLITE_TCL_H)
18# include "sqlite_tcl.h"
19#else
20# include "tcl.h"
21#endif
drh5c4d9702001-08-20 00:33:58 +000022#include <stdlib.h>
23#include <string.h>
drh3088d592008-03-21 16:45:47 +000024#include <ctype.h>
drh5c4d9702001-08-20 00:33:58 +000025
mistachkine84d8d32013-04-29 03:09:10 +000026extern const char *sqlite3ErrName(int);
drh5c4d9702001-08-20 00:33:58 +000027
28/*
drh90f5ecb2004-07-22 01:19:35 +000029** Page size and reserved size used for testing.
30*/
31static int test_pagesize = 1024;
32
33/*
drh4775ecd2009-07-24 19:01:19 +000034** Dummy page reinitializer
35*/
36static void pager_test_reiniter(DbPage *pNotUsed){
37 return;
38}
39
40/*
drh5c4d9702001-08-20 00:33:58 +000041** Usage: pager_open FILENAME N-PAGE
42**
43** Open a new pager
44*/
mistachkin7617e4a2016-07-28 17:11:20 +000045static int SQLITE_TCLAPI pager_open(
drh5c4d9702001-08-20 00:33:58 +000046 void *NotUsed,
47 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
48 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +000049 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +000050){
drhb2eced52010-08-12 02:41:12 +000051 u32 pageSize;
drh5c4d9702001-08-20 00:33:58 +000052 Pager *pPager;
53 int nPage;
54 int rc;
55 char zBuf[100];
56 if( argc!=3 ){
57 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
58 " FILENAME N-PAGE\"", 0);
59 return TCL_ERROR;
60 }
61 if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
danielk197771d5d2c2008-09-29 11:49:47 +000062 rc = sqlite3PagerOpen(sqlite3_vfs_find(0), &pPager, argv[1], 0, 0,
drh4775ecd2009-07-24 19:01:19 +000063 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB,
64 pager_test_reiniter);
drh5c4d9702001-08-20 00:33:58 +000065 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +000066 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh5c4d9702001-08-20 00:33:58 +000067 return TCL_ERROR;
68 }
danielk19773b8a05f2007-03-19 17:44:26 +000069 sqlite3PagerSetCachesize(pPager, nPage);
danielk1977a1644fd2007-08-29 12:31:25 +000070 pageSize = test_pagesize;
drhfa9601a2009-06-18 17:22:39 +000071 sqlite3PagerSetPagesize(pPager, &pageSize, -1);
drhfe63d1c2004-09-08 20:13:04 +000072 sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPager);
drh5c4d9702001-08-20 00:33:58 +000073 Tcl_AppendResult(interp, zBuf, 0);
74 return TCL_OK;
75}
76
77/*
78** Usage: pager_close ID
79**
80** Close the given pager.
81*/
mistachkin7617e4a2016-07-28 17:11:20 +000082static int SQLITE_TCLAPI pager_close(
drh5c4d9702001-08-20 00:33:58 +000083 void *NotUsed,
84 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
85 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +000086 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +000087){
88 Pager *pPager;
89 int rc;
90 if( argc!=2 ){
91 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
92 " ID\"", 0);
93 return TCL_ERROR;
94 }
drhe8f52c52008-07-12 14:52:20 +000095 pPager = sqlite3TestTextToPtr(argv[1]);
dan7fb89902016-08-12 16:21:15 +000096 rc = sqlite3PagerClose(pPager, 0);
drh5c4d9702001-08-20 00:33:58 +000097 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +000098 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh5c4d9702001-08-20 00:33:58 +000099 return TCL_ERROR;
100 }
101 return TCL_OK;
102}
103
104/*
105** Usage: pager_rollback ID
106**
107** Rollback changes
108*/
mistachkin7617e4a2016-07-28 17:11:20 +0000109static int SQLITE_TCLAPI pager_rollback(
drh5c4d9702001-08-20 00:33:58 +0000110 void *NotUsed,
111 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
112 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000113 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000114){
115 Pager *pPager;
116 int rc;
117 if( argc!=2 ){
118 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
119 " ID\"", 0);
120 return TCL_ERROR;
121 }
drhe8f52c52008-07-12 14:52:20 +0000122 pPager = sqlite3TestTextToPtr(argv[1]);
danielk19773b8a05f2007-03-19 17:44:26 +0000123 rc = sqlite3PagerRollback(pPager);
drh5c4d9702001-08-20 00:33:58 +0000124 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +0000125 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh5c4d9702001-08-20 00:33:58 +0000126 return TCL_ERROR;
127 }
128 return TCL_OK;
129}
130
131/*
132** Usage: pager_commit ID
133**
134** Commit all changes
135*/
mistachkin7617e4a2016-07-28 17:11:20 +0000136static int SQLITE_TCLAPI pager_commit(
drh5c4d9702001-08-20 00:33:58 +0000137 void *NotUsed,
138 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
139 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000140 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000141){
142 Pager *pPager;
143 int rc;
144 if( argc!=2 ){
145 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
146 " ID\"", 0);
147 return TCL_ERROR;
148 }
drhe8f52c52008-07-12 14:52:20 +0000149 pPager = sqlite3TestTextToPtr(argv[1]);
drh49b9d332009-01-02 18:10:42 +0000150 rc = sqlite3PagerCommitPhaseOne(pPager, 0, 0);
drh80e35f42007-03-30 14:06:34 +0000151 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +0000152 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh80e35f42007-03-30 14:06:34 +0000153 return TCL_ERROR;
154 }
155 rc = sqlite3PagerCommitPhaseTwo(pPager);
drh5c4d9702001-08-20 00:33:58 +0000156 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +0000157 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh5c4d9702001-08-20 00:33:58 +0000158 return TCL_ERROR;
159 }
160 return TCL_OK;
161}
162
163/*
drh3aac2dd2004-04-26 14:10:20 +0000164** Usage: pager_stmt_begin ID
drhfa86c412002-02-02 15:01:15 +0000165**
166** Start a new checkpoint.
167*/
mistachkin7617e4a2016-07-28 17:11:20 +0000168static int SQLITE_TCLAPI pager_stmt_begin(
drhfa86c412002-02-02 15:01:15 +0000169 void *NotUsed,
170 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
171 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000172 const char **argv /* Text of each argument */
drhfa86c412002-02-02 15:01:15 +0000173){
174 Pager *pPager;
175 int rc;
176 if( argc!=2 ){
177 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
178 " ID\"", 0);
179 return TCL_ERROR;
180 }
drhe8f52c52008-07-12 14:52:20 +0000181 pPager = sqlite3TestTextToPtr(argv[1]);
danielk1977fd7f0452008-12-17 17:30:26 +0000182 rc = sqlite3PagerOpenSavepoint(pPager, 1);
drhfa86c412002-02-02 15:01:15 +0000183 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +0000184 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drhfa86c412002-02-02 15:01:15 +0000185 return TCL_ERROR;
186 }
187 return TCL_OK;
188}
189
190/*
drh3aac2dd2004-04-26 14:10:20 +0000191** Usage: pager_stmt_rollback ID
drhfa86c412002-02-02 15:01:15 +0000192**
193** Rollback changes to a checkpoint
194*/
mistachkin7617e4a2016-07-28 17:11:20 +0000195static int SQLITE_TCLAPI pager_stmt_rollback(
drhfa86c412002-02-02 15:01:15 +0000196 void *NotUsed,
197 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
198 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000199 const char **argv /* Text of each argument */
drhfa86c412002-02-02 15:01:15 +0000200){
201 Pager *pPager;
202 int rc;
203 if( argc!=2 ){
204 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
205 " ID\"", 0);
206 return TCL_ERROR;
207 }
drhe8f52c52008-07-12 14:52:20 +0000208 pPager = sqlite3TestTextToPtr(argv[1]);
danielk1977fd7f0452008-12-17 17:30:26 +0000209 rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, 0);
210 sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0);
drhfa86c412002-02-02 15:01:15 +0000211 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +0000212 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drhfa86c412002-02-02 15:01:15 +0000213 return TCL_ERROR;
214 }
215 return TCL_OK;
216}
217
218/*
drh3aac2dd2004-04-26 14:10:20 +0000219** Usage: pager_stmt_commit ID
drhfa86c412002-02-02 15:01:15 +0000220**
221** Commit changes to a checkpoint
222*/
mistachkin7617e4a2016-07-28 17:11:20 +0000223static int SQLITE_TCLAPI pager_stmt_commit(
drhfa86c412002-02-02 15:01:15 +0000224 void *NotUsed,
225 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
226 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000227 const char **argv /* Text of each argument */
drhfa86c412002-02-02 15:01:15 +0000228){
229 Pager *pPager;
230 int rc;
231 if( argc!=2 ){
232 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
233 " ID\"", 0);
234 return TCL_ERROR;
235 }
drhe8f52c52008-07-12 14:52:20 +0000236 pPager = sqlite3TestTextToPtr(argv[1]);
danielk1977fd7f0452008-12-17 17:30:26 +0000237 rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_RELEASE, 0);
drhfa86c412002-02-02 15:01:15 +0000238 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +0000239 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drhfa86c412002-02-02 15:01:15 +0000240 return TCL_ERROR;
241 }
242 return TCL_OK;
243}
244
245/*
drh5c4d9702001-08-20 00:33:58 +0000246** Usage: pager_stats ID
247**
248** Return pager statistics.
249*/
mistachkin7617e4a2016-07-28 17:11:20 +0000250static int SQLITE_TCLAPI pager_stats(
drh5c4d9702001-08-20 00:33:58 +0000251 void *NotUsed,
252 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
253 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000254 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000255){
256 Pager *pPager;
257 int i, *a;
258 if( argc!=2 ){
259 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
260 " ID\"", 0);
261 return TCL_ERROR;
262 }
drhe8f52c52008-07-12 14:52:20 +0000263 pPager = sqlite3TestTextToPtr(argv[1]);
danielk19773b8a05f2007-03-19 17:44:26 +0000264 a = sqlite3PagerStats(pPager);
drh5c4d9702001-08-20 00:33:58 +0000265 for(i=0; i<9; i++){
266 static char *zName[] = {
267 "ref", "page", "max", "size", "state", "err",
268 "hit", "miss", "ovfl",
269 };
270 char zBuf[100];
271 Tcl_AppendElement(interp, zName[i]);
drhfe63d1c2004-09-08 20:13:04 +0000272 sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",a[i]);
drh5c4d9702001-08-20 00:33:58 +0000273 Tcl_AppendElement(interp, zBuf);
274 }
275 return TCL_OK;
276}
277
278/*
279** Usage: pager_pagecount ID
280**
281** Return the size of the database file.
282*/
mistachkin7617e4a2016-07-28 17:11:20 +0000283static int SQLITE_TCLAPI pager_pagecount(
drh5c4d9702001-08-20 00:33:58 +0000284 void *NotUsed,
285 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
286 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000287 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000288){
289 Pager *pPager;
290 char zBuf[100];
danielk1977ad0132d2008-06-07 08:58:22 +0000291 int nPage;
drh5c4d9702001-08-20 00:33:58 +0000292 if( argc!=2 ){
293 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
294 " ID\"", 0);
295 return TCL_ERROR;
296 }
drhe8f52c52008-07-12 14:52:20 +0000297 pPager = sqlite3TestTextToPtr(argv[1]);
danielk1977ad0132d2008-06-07 08:58:22 +0000298 sqlite3PagerPagecount(pPager, &nPage);
299 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nPage);
drh5c4d9702001-08-20 00:33:58 +0000300 Tcl_AppendResult(interp, zBuf, 0);
301 return TCL_OK;
302}
303
304/*
305** Usage: page_get ID PGNO
306**
307** Return a pointer to a page from the database.
308*/
mistachkin7617e4a2016-07-28 17:11:20 +0000309static int SQLITE_TCLAPI page_get(
drh5c4d9702001-08-20 00:33:58 +0000310 void *NotUsed,
311 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
312 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000313 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000314){
315 Pager *pPager;
316 char zBuf[100];
mistachkin27b2f052015-01-12 19:49:46 +0000317 DbPage *pPage = 0;
drh5c4d9702001-08-20 00:33:58 +0000318 int pgno;
319 int rc;
320 if( argc!=3 ){
321 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
322 " ID PGNO\"", 0);
323 return TCL_ERROR;
324 }
drhe8f52c52008-07-12 14:52:20 +0000325 pPager = sqlite3TestTextToPtr(argv[1]);
drh5c4d9702001-08-20 00:33:58 +0000326 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
danielk197789bc4bc2009-07-21 19:25:24 +0000327 rc = sqlite3PagerSharedLock(pPager);
328 if( rc==SQLITE_OK ){
drh9584f582015-11-04 20:22:37 +0000329 rc = sqlite3PagerGet(pPager, pgno, &pPage, 0);
danielk197789bc4bc2009-07-21 19:25:24 +0000330 }
drh5c4d9702001-08-20 00:33:58 +0000331 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +0000332 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh5c4d9702001-08-20 00:33:58 +0000333 return TCL_ERROR;
334 }
drhfe63d1c2004-09-08 20:13:04 +0000335 sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage);
drh5c4d9702001-08-20 00:33:58 +0000336 Tcl_AppendResult(interp, zBuf, 0);
337 return TCL_OK;
338}
339
340/*
341** Usage: page_lookup ID PGNO
342**
343** Return a pointer to a page if the page is already in cache.
344** If not in cache, return an empty string.
345*/
mistachkin7617e4a2016-07-28 17:11:20 +0000346static int SQLITE_TCLAPI page_lookup(
drh5c4d9702001-08-20 00:33:58 +0000347 void *NotUsed,
348 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
349 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000350 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000351){
352 Pager *pPager;
353 char zBuf[100];
danielk19773b8a05f2007-03-19 17:44:26 +0000354 DbPage *pPage;
drh5c4d9702001-08-20 00:33:58 +0000355 int pgno;
356 if( argc!=3 ){
357 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
358 " ID PGNO\"", 0);
359 return TCL_ERROR;
360 }
drhe8f52c52008-07-12 14:52:20 +0000361 pPager = sqlite3TestTextToPtr(argv[1]);
drh5c4d9702001-08-20 00:33:58 +0000362 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
danielk19773b8a05f2007-03-19 17:44:26 +0000363 pPage = sqlite3PagerLookup(pPager, pgno);
drh5c4d9702001-08-20 00:33:58 +0000364 if( pPage ){
drhfe63d1c2004-09-08 20:13:04 +0000365 sqlite3_snprintf(sizeof(zBuf),zBuf,"%p",pPage);
drh5c4d9702001-08-20 00:33:58 +0000366 Tcl_AppendResult(interp, zBuf, 0);
367 }
368 return TCL_OK;
369}
370
371/*
danielk1977aca790a2005-01-13 11:07:52 +0000372** Usage: pager_truncate ID PGNO
373*/
mistachkin7617e4a2016-07-28 17:11:20 +0000374static int SQLITE_TCLAPI pager_truncate(
danielk1977aca790a2005-01-13 11:07:52 +0000375 void *NotUsed,
376 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
377 int argc, /* Number of arguments */
378 const char **argv /* Text of each argument */
379){
380 Pager *pPager;
danielk1977aca790a2005-01-13 11:07:52 +0000381 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 }
drhe8f52c52008-07-12 14:52:20 +0000387 pPager = sqlite3TestTextToPtr(argv[1]);
danielk1977aca790a2005-01-13 11:07:52 +0000388 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
danielk1977f90b7262009-01-07 15:18:20 +0000389 sqlite3PagerTruncateImage(pPager, pgno);
danielk1977aca790a2005-01-13 11:07:52 +0000390 return TCL_OK;
391}
392
393
394/*
drh5c4d9702001-08-20 00:33:58 +0000395** Usage: page_unref PAGE
396**
397** Drop a pointer to a page.
398*/
mistachkin7617e4a2016-07-28 17:11:20 +0000399static int SQLITE_TCLAPI page_unref(
drh5c4d9702001-08-20 00:33:58 +0000400 void *NotUsed,
401 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
402 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000403 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000404){
danielk19773b8a05f2007-03-19 17:44:26 +0000405 DbPage *pPage;
drh5c4d9702001-08-20 00:33:58 +0000406 if( argc!=2 ){
407 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
408 " PAGE\"", 0);
409 return TCL_ERROR;
410 }
drhe8f52c52008-07-12 14:52:20 +0000411 pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]);
danielk1977bea2a942009-01-20 17:06:27 +0000412 sqlite3PagerUnref(pPage);
drh5c4d9702001-08-20 00:33:58 +0000413 return TCL_OK;
414}
415
416/*
417** Usage: page_read PAGE
418**
419** Return the content of a page
420*/
mistachkin7617e4a2016-07-28 17:11:20 +0000421static int SQLITE_TCLAPI page_read(
drh5c4d9702001-08-20 00:33:58 +0000422 void *NotUsed,
423 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
424 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000425 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000426){
427 char zBuf[100];
danielk19773b8a05f2007-03-19 17:44:26 +0000428 DbPage *pPage;
drh5c4d9702001-08-20 00:33:58 +0000429 if( argc!=2 ){
430 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
431 " PAGE\"", 0);
432 return TCL_ERROR;
433 }
drhe8f52c52008-07-12 14:52:20 +0000434 pPage = sqlite3TestTextToPtr(argv[1]);
danielk19773b8a05f2007-03-19 17:44:26 +0000435 memcpy(zBuf, sqlite3PagerGetData(pPage), sizeof(zBuf));
drh5c4d9702001-08-20 00:33:58 +0000436 Tcl_AppendResult(interp, zBuf, 0);
437 return TCL_OK;
438}
439
440/*
441** Usage: page_number PAGE
442**
443** Return the page number for a page.
444*/
mistachkin7617e4a2016-07-28 17:11:20 +0000445static int SQLITE_TCLAPI page_number(
drh5c4d9702001-08-20 00:33:58 +0000446 void *NotUsed,
447 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
448 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000449 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000450){
451 char zBuf[100];
danielk19773b8a05f2007-03-19 17:44:26 +0000452 DbPage *pPage;
drh5c4d9702001-08-20 00:33:58 +0000453 if( argc!=2 ){
454 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
455 " PAGE\"", 0);
456 return TCL_ERROR;
457 }
drhe8f52c52008-07-12 14:52:20 +0000458 pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]);
danielk19773b8a05f2007-03-19 17:44:26 +0000459 sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3PagerPagenumber(pPage));
drh5c4d9702001-08-20 00:33:58 +0000460 Tcl_AppendResult(interp, zBuf, 0);
461 return TCL_OK;
462}
463
464/*
465** Usage: page_write PAGE DATA
466**
467** Write something into a page.
468*/
mistachkin7617e4a2016-07-28 17:11:20 +0000469static int SQLITE_TCLAPI page_write(
drh5c4d9702001-08-20 00:33:58 +0000470 void *NotUsed,
471 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
472 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000473 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000474){
danielk19773b8a05f2007-03-19 17:44:26 +0000475 DbPage *pPage;
476 char *pData;
drh5c4d9702001-08-20 00:33:58 +0000477 int rc;
478 if( argc!=3 ){
479 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
480 " PAGE DATA\"", 0);
481 return TCL_ERROR;
482 }
drhe8f52c52008-07-12 14:52:20 +0000483 pPage = (DbPage *)sqlite3TestTextToPtr(argv[1]);
danielk19773b8a05f2007-03-19 17:44:26 +0000484 rc = sqlite3PagerWrite(pPage);
drh5c4d9702001-08-20 00:33:58 +0000485 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +0000486 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh5c4d9702001-08-20 00:33:58 +0000487 return TCL_ERROR;
488 }
danielk19773b8a05f2007-03-19 17:44:26 +0000489 pData = sqlite3PagerGetData(pPage);
490 strncpy(pData, argv[2], test_pagesize-1);
491 pData[test_pagesize-1] = 0;
drh5c4d9702001-08-20 00:33:58 +0000492 return TCL_OK;
493}
494
danielk197744ee5bf2005-05-27 09:41:12 +0000495#ifndef SQLITE_OMIT_DISKIO
drh5c4d9702001-08-20 00:33:58 +0000496/*
drhd0d006e2002-12-01 02:00:57 +0000497** Usage: fake_big_file N FILENAME
498**
499** Write a few bytes at the N megabyte point of FILENAME. This will
500** create a large file. If the file was a valid SQLite database, then
501** the next time the database is opened, SQLite will begin allocating
502** new pages after N. If N is 2096 or bigger, this will test the
503** ability of SQLite to write to large files.
504*/
mistachkin7617e4a2016-07-28 17:11:20 +0000505static int SQLITE_TCLAPI fake_big_file(
drhd0d006e2002-12-01 02:00:57 +0000506 void *NotUsed,
507 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
508 int argc, /* Number of arguments */
509 const char **argv /* Text of each argument */
510){
danielk1977b4b47412007-08-17 15:53:36 +0000511 sqlite3_vfs *pVfs;
512 sqlite3_file *fd = 0;
drhd0d006e2002-12-01 02:00:57 +0000513 int rc;
514 int n;
drheb206252004-10-01 02:00:31 +0000515 i64 offset;
drh69578ac2012-01-11 00:38:51 +0000516 char *zFile;
517 int nFile;
drhd0d006e2002-12-01 02:00:57 +0000518 if( argc!=3 ){
519 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
520 " N-MEGABYTES FILE\"", 0);
521 return TCL_ERROR;
522 }
523 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
danielk1977b4b47412007-08-17 15:53:36 +0000524
drhd677b3d2007-08-20 22:48:41 +0000525 pVfs = sqlite3_vfs_find(0);
drh83cc1392012-04-19 18:04:28 +0000526 nFile = (int)strlen(argv[2]);
drh69578ac2012-01-11 00:38:51 +0000527 zFile = sqlite3_malloc( nFile+2 );
528 if( zFile==0 ) return TCL_ERROR;
529 memcpy(zFile, argv[2], nFile+1);
530 zFile[nFile+1] = 0;
531 rc = sqlite3OsOpenMalloc(pVfs, zFile, &fd,
danielk1977967a4a12007-08-20 14:23:44 +0000532 (SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB), 0
danielk1977fee2d252007-08-18 10:59:19 +0000533 );
drhd0d006e2002-12-01 02:00:57 +0000534 if( rc ){
mistachkine84d8d32013-04-29 03:09:10 +0000535 Tcl_AppendResult(interp, "open failed: ", sqlite3ErrName(rc), 0);
drh69578ac2012-01-11 00:38:51 +0000536 sqlite3_free(zFile);
drhd0d006e2002-12-01 02:00:57 +0000537 return TCL_ERROR;
538 }
539 offset = n;
540 offset *= 1024*1024;
danielk197762079062007-08-15 17:08:46 +0000541 rc = sqlite3OsWrite(fd, "Hello, World!", 14, offset);
danielk1977b4b47412007-08-17 15:53:36 +0000542 sqlite3OsCloseFree(fd);
drh69578ac2012-01-11 00:38:51 +0000543 sqlite3_free(zFile);
drhd0d006e2002-12-01 02:00:57 +0000544 if( rc ){
mistachkine84d8d32013-04-29 03:09:10 +0000545 Tcl_AppendResult(interp, "write failed: ", sqlite3ErrName(rc), 0);
drhd0d006e2002-12-01 02:00:57 +0000546 return TCL_ERROR;
547 }
drhd0d006e2002-12-01 02:00:57 +0000548 return TCL_OK;
549}
danielk197744ee5bf2005-05-27 09:41:12 +0000550#endif
drhd0d006e2002-12-01 02:00:57 +0000551
drh3088d592008-03-21 16:45:47 +0000552
drhd0d006e2002-12-01 02:00:57 +0000553/*
drhc7a3bb92009-02-05 16:31:45 +0000554** test_control_pending_byte PENDING_BYTE
555**
556** Set the PENDING_BYTE using the sqlite3_test_control() interface.
557*/
mistachkin7617e4a2016-07-28 17:11:20 +0000558static int SQLITE_TCLAPI testPendingByte(
drhc7a3bb92009-02-05 16:31:45 +0000559 void *NotUsed,
560 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
561 int argc, /* Number of arguments */
562 const char **argv /* Text of each argument */
563){
564 int pbyte;
565 int rc;
566 if( argc!=2 ){
567 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
568 " PENDING-BYTE\"", (void*)0);
dan8d6ad1c2010-05-04 10:36:20 +0000569 return TCL_ERROR;
drhc7a3bb92009-02-05 16:31:45 +0000570 }
571 if( Tcl_GetInt(interp, argv[1], &pbyte) ) return TCL_ERROR;
572 rc = sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, pbyte);
573 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
574 return TCL_OK;
drhc007f612014-05-16 14:17:01 +0000575}
576
577/*
578** The sqlite3FaultSim() callback:
579*/
580static Tcl_Interp *faultSimInterp = 0;
581static int faultSimScriptSize = 0;
582static char *faultSimScript;
583static int faultSimCallback(int x){
584 char zInt[30];
585 int i;
586 int isNeg;
587 int rc;
588 if( x==0 ){
589 memcpy(faultSimScript+faultSimScriptSize, "0", 2);
590 }else{
591 /* Convert x to text without using any sqlite3 routines */
592 if( x<0 ){
593 isNeg = 1;
594 x = -x;
595 }else{
596 isNeg = 0;
597 }
598 zInt[sizeof(zInt)-1] = 0;
599 for(i=sizeof(zInt)-2; i>0 && x>0; i--, x /= 10){
600 zInt[i] = (x%10) + '0';
601 }
602 if( isNeg ) zInt[i--] = '-';
603 memcpy(faultSimScript+faultSimScriptSize, zInt+i+1, sizeof(zInt)-i);
604 }
605 rc = Tcl_Eval(faultSimInterp, faultSimScript);
606 if( rc ){
607 fprintf(stderr, "fault simulator script failed: [%s]", faultSimScript);
608 rc = SQLITE_ERROR;
609 }else{
610 rc = atoi(Tcl_GetStringResult(faultSimInterp));
611 }
612 Tcl_ResetResult(faultSimInterp);
613 return rc;
614}
615
616/*
617** sqlite3_test_control_fault_install SCRIPT
618**
619** Arrange to invoke SCRIPT with the integer argument to sqlite3FaultSim()
620** appended, whenever sqlite3FaultSim() is called. Or, if SCRIPT is the
621** empty string, cancel the sqlite3FaultSim() callback.
622*/
mistachkin7617e4a2016-07-28 17:11:20 +0000623static int SQLITE_TCLAPI faultInstallCmd(
drhc007f612014-05-16 14:17:01 +0000624 void *NotUsed,
625 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
626 int argc, /* Number of arguments */
627 const char **argv /* Text of each argument */
628){
629 const char *zScript;
630 int nScript;
631 int rc;
632 if( argc!=1 && argc!=2 ){
633 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
634 " SCRIPT\"", (void*)0);
635 }
636 zScript = argc==2 ? argv[1] : "";
637 nScript = (int)strlen(zScript);
638 if( faultSimScript ){
639 free(faultSimScript);
640 faultSimScript = 0;
641 }
642 if( nScript==0 ){
643 rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, 0);
644 }else{
645 faultSimScript = malloc( nScript+100 );
646 if( faultSimScript==0 ){
647 Tcl_AppendResult(interp, "out of memory", (void*)0);
648 return SQLITE_ERROR;
649 }
650 memcpy(faultSimScript, zScript, nScript);
651 faultSimScript[nScript] = ' ';
652 faultSimScriptSize = nScript+1;
653 faultSimInterp = interp;
654 rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, faultSimCallback);
655 }
656 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
657 return SQLITE_OK;
658}
drhc7a3bb92009-02-05 16:31:45 +0000659
660/*
drh3088d592008-03-21 16:45:47 +0000661** sqlite3BitvecBuiltinTest SIZE PROGRAM
662**
663** Invoke the SQLITE_TESTCTRL_BITVEC_TEST operator on test_control.
664** See comments on sqlite3BitvecBuiltinTest() for additional information.
drhf5e7bb52008-02-18 14:47:33 +0000665*/
mistachkin7617e4a2016-07-28 17:11:20 +0000666static int SQLITE_TCLAPI testBitvecBuiltinTest(
drhf5e7bb52008-02-18 14:47:33 +0000667 void *NotUsed,
668 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
669 int argc, /* Number of arguments */
670 const char **argv /* Text of each argument */
671){
drh3088d592008-03-21 16:45:47 +0000672 int sz, rc;
673 int nProg = 0;
674 int aProg[100];
675 const char *z;
drhf5e7bb52008-02-18 14:47:33 +0000676 if( argc!=3 ){
drh3088d592008-03-21 16:45:47 +0000677 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
678 " SIZE PROGRAM\"", (void*)0);
drhf5e7bb52008-02-18 14:47:33 +0000679 }
drh3088d592008-03-21 16:45:47 +0000680 if( Tcl_GetInt(interp, argv[1], &sz) ) return TCL_ERROR;
681 z = argv[2];
682 while( nProg<99 && *z ){
danielk197778ca0e72009-01-20 16:53:39 +0000683 while( *z && !sqlite3Isdigit(*z) ){ z++; }
drh3088d592008-03-21 16:45:47 +0000684 if( *z==0 ) break;
685 aProg[nProg++] = atoi(z);
danielk197778ca0e72009-01-20 16:53:39 +0000686 while( sqlite3Isdigit(*z) ){ z++; }
drh3088d592008-03-21 16:45:47 +0000687 }
688 aProg[nProg] = 0;
689 rc = sqlite3_test_control(SQLITE_TESTCTRL_BITVEC_TEST, sz, aProg);
690 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
drhf5e7bb52008-02-18 14:47:33 +0000691 return TCL_OK;
692}
drhf5e7bb52008-02-18 14:47:33 +0000693
694/*
drh5c4d9702001-08-20 00:33:58 +0000695** Register commands with the TCL interpreter.
696*/
697int Sqlitetest2_Init(Tcl_Interp *interp){
drhd5eb79e2007-03-15 12:17:42 +0000698 extern int sqlite3_io_error_persist;
danielk19776f8a5032004-05-10 10:34:51 +0000699 extern int sqlite3_io_error_pending;
drhc9ac5ca2005-11-04 22:03:30 +0000700 extern int sqlite3_io_error_hit;
drh1aa5af12008-03-07 19:51:14 +0000701 extern int sqlite3_io_error_hardhit;
drh047d4832004-10-01 14:38:02 +0000702 extern int sqlite3_diskfull_pending;
drhf307a4a2005-09-09 10:46:19 +0000703 extern int sqlite3_diskfull;
drhc2eef3b2002-08-31 18:53:06 +0000704 static struct {
705 char *zName;
706 Tcl_CmdProc *xProc;
707 } aCmd[] = {
708 { "pager_open", (Tcl_CmdProc*)pager_open },
709 { "pager_close", (Tcl_CmdProc*)pager_close },
710 { "pager_commit", (Tcl_CmdProc*)pager_commit },
711 { "pager_rollback", (Tcl_CmdProc*)pager_rollback },
drh3aac2dd2004-04-26 14:10:20 +0000712 { "pager_stmt_begin", (Tcl_CmdProc*)pager_stmt_begin },
713 { "pager_stmt_commit", (Tcl_CmdProc*)pager_stmt_commit },
714 { "pager_stmt_rollback", (Tcl_CmdProc*)pager_stmt_rollback },
drhc2eef3b2002-08-31 18:53:06 +0000715 { "pager_stats", (Tcl_CmdProc*)pager_stats },
716 { "pager_pagecount", (Tcl_CmdProc*)pager_pagecount },
717 { "page_get", (Tcl_CmdProc*)page_get },
718 { "page_lookup", (Tcl_CmdProc*)page_lookup },
719 { "page_unref", (Tcl_CmdProc*)page_unref },
720 { "page_read", (Tcl_CmdProc*)page_read },
721 { "page_write", (Tcl_CmdProc*)page_write },
722 { "page_number", (Tcl_CmdProc*)page_number },
danielk1977aca790a2005-01-13 11:07:52 +0000723 { "pager_truncate", (Tcl_CmdProc*)pager_truncate },
danielk197744ee5bf2005-05-27 09:41:12 +0000724#ifndef SQLITE_OMIT_DISKIO
drhd0d006e2002-12-01 02:00:57 +0000725 { "fake_big_file", (Tcl_CmdProc*)fake_big_file },
danielk197744ee5bf2005-05-27 09:41:12 +0000726#endif
drhc7a3bb92009-02-05 16:31:45 +0000727 { "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest },
drhc007f612014-05-16 14:17:01 +0000728 { "sqlite3_test_control_pending_byte", (Tcl_CmdProc*)testPendingByte },
729 { "sqlite3_test_control_fault_install", (Tcl_CmdProc*)faultInstallCmd },
drhc2eef3b2002-08-31 18:53:06 +0000730 };
731 int i;
732 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
733 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
734 }
danielk1977369f27e2004-06-15 11:40:04 +0000735 Tcl_LinkVar(interp, "sqlite_io_error_pending",
danielk19776f8a5032004-05-10 10:34:51 +0000736 (char*)&sqlite3_io_error_pending, TCL_LINK_INT);
drhd5eb79e2007-03-15 12:17:42 +0000737 Tcl_LinkVar(interp, "sqlite_io_error_persist",
738 (char*)&sqlite3_io_error_persist, TCL_LINK_INT);
drhc9ac5ca2005-11-04 22:03:30 +0000739 Tcl_LinkVar(interp, "sqlite_io_error_hit",
740 (char*)&sqlite3_io_error_hit, TCL_LINK_INT);
drh1aa5af12008-03-07 19:51:14 +0000741 Tcl_LinkVar(interp, "sqlite_io_error_hardhit",
742 (char*)&sqlite3_io_error_hardhit, TCL_LINK_INT);
drh047d4832004-10-01 14:38:02 +0000743 Tcl_LinkVar(interp, "sqlite_diskfull_pending",
744 (char*)&sqlite3_diskfull_pending, TCL_LINK_INT);
drhf307a4a2005-09-09 10:46:19 +0000745 Tcl_LinkVar(interp, "sqlite_diskfull",
746 (char*)&sqlite3_diskfull, TCL_LINK_INT);
drhf83dc1e2010-06-03 12:09:52 +0000747#ifndef SQLITE_OMIT_WSD
danielk1977fd5f5b62005-09-16 09:52:29 +0000748 Tcl_LinkVar(interp, "sqlite_pending_byte",
drhc7a3bb92009-02-05 16:31:45 +0000749 (char*)&sqlite3PendingByte, TCL_LINK_INT | TCL_LINK_READ_ONLY);
drhf83dc1e2010-06-03 12:09:52 +0000750#endif
drh5c4d9702001-08-20 00:33:58 +0000751 return TCL_OK;
752}