blob: e3ed310c8104fe3621cebb0f51d10145018d4fac [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 btree.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"
danielk1977a1644fd2007-08-29 12:31:25 +000017#include "btreeInt.h"
drh5c4d9702001-08-20 00:33:58 +000018#include "tcl.h"
19#include <stdlib.h>
20#include <string.h>
21
mistachkine84d8d32013-04-29 03:09:10 +000022extern const char *sqlite3ErrName(int);
drh5c4d9702001-08-20 00:33:58 +000023
24/*
drha2451e22007-08-20 23:50:24 +000025** A bogus sqlite3 connection structure for use in the btree
26** tests.
27*/
28static sqlite3 sDb;
29static int nRefSqlite3 = 0;
30
31/*
drh75c014c2010-08-30 15:02:28 +000032** Usage: btree_open FILENAME NCACHE
drh5c4d9702001-08-20 00:33:58 +000033**
34** Open a new database
35*/
36static int btree_open(
37 void *NotUsed,
38 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
39 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +000040 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +000041){
42 Btree *pBt;
drh75c014c2010-08-30 15:02:28 +000043 int rc, nCache;
drh5c4d9702001-08-20 00:33:58 +000044 char zBuf[100];
drhc02a43a2012-01-10 23:18:38 +000045 int n;
46 char *zFilename;
drh75c014c2010-08-30 15:02:28 +000047 if( argc!=3 ){
drh5c4d9702001-08-20 00:33:58 +000048 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh23e11ca2004-05-04 17:27:28 +000049 " FILENAME NCACHE FLAGS\"", 0);
drh5c4d9702001-08-20 00:33:58 +000050 return TCL_ERROR;
51 }
drh23e11ca2004-05-04 17:27:28 +000052 if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
drha2451e22007-08-20 23:50:24 +000053 nRefSqlite3++;
54 if( nRefSqlite3==1 ){
55 sDb.pVfs = sqlite3_vfs_find(0);
danielk197759f8c082008-06-18 17:09:10 +000056 sDb.mutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE);
drh27641702007-08-22 02:56:42 +000057 sqlite3_mutex_enter(sDb.mutex);
drha2451e22007-08-20 23:50:24 +000058 }
drh83cc1392012-04-19 18:04:28 +000059 n = (int)strlen(argv[1]);
drhc02a43a2012-01-10 23:18:38 +000060 zFilename = sqlite3_malloc( n+2 );
61 if( zFilename==0 ) return TCL_ERROR;
62 memcpy(zFilename, argv[1], n+1);
63 zFilename[n+1] = 0;
64 rc = sqlite3BtreeOpen(sDb.pVfs, zFilename, &sDb, &pBt, 0,
drh33f4e022007-09-03 15:19:34 +000065 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_MAIN_DB);
drhc02a43a2012-01-10 23:18:38 +000066 sqlite3_free(zFilename);
drh5c4d9702001-08-20 00:33:58 +000067 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +000068 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh5c4d9702001-08-20 00:33:58 +000069 return TCL_ERROR;
70 }
drh90f5ecb2004-07-22 01:19:35 +000071 sqlite3BtreeSetCacheSize(pBt, nCache);
drhfe63d1c2004-09-08 20:13:04 +000072 sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pBt);
drh5c4d9702001-08-20 00:33:58 +000073 Tcl_AppendResult(interp, zBuf, 0);
74 return TCL_OK;
75}
76
77/*
78** Usage: btree_close ID
79**
80** Close the given database.
81*/
82static int btree_close(
83 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 Btree *pBt;
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 pBt = sqlite3TestTextToPtr(argv[1]);
drh23e11ca2004-05-04 17:27:28 +000096 rc = sqlite3BtreeClose(pBt);
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 }
drha2451e22007-08-20 23:50:24 +0000101 nRefSqlite3--;
102 if( nRefSqlite3==0 ){
drh27641702007-08-22 02:56:42 +0000103 sqlite3_mutex_leave(sDb.mutex);
drha2451e22007-08-20 23:50:24 +0000104 sqlite3_mutex_free(sDb.mutex);
105 sDb.mutex = 0;
drha2451e22007-08-20 23:50:24 +0000106 sDb.pVfs = 0;
107 }
drh5c4d9702001-08-20 00:33:58 +0000108 return TCL_OK;
109}
110
drh27641702007-08-22 02:56:42 +0000111
drh5c4d9702001-08-20 00:33:58 +0000112/*
113** Usage: btree_begin_transaction ID
114**
115** Start a new transaction
116*/
117static int btree_begin_transaction(
118 void *NotUsed,
119 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
120 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000121 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000122){
123 Btree *pBt;
124 int rc;
125 if( argc!=2 ){
126 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
127 " ID\"", 0);
128 return TCL_ERROR;
129 }
drhe8f52c52008-07-12 14:52:20 +0000130 pBt = sqlite3TestTextToPtr(argv[1]);
drhff0587c2007-08-29 17:43:19 +0000131 sqlite3BtreeEnter(pBt);
danielk197740b38dc2004-06-26 08:38:24 +0000132 rc = sqlite3BtreeBeginTrans(pBt, 1);
drhff0587c2007-08-29 17:43:19 +0000133 sqlite3BtreeLeave(pBt);
drh5c4d9702001-08-20 00:33:58 +0000134 if( rc!=SQLITE_OK ){
mistachkine84d8d32013-04-29 03:09:10 +0000135 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh5c4d9702001-08-20 00:33:58 +0000136 return TCL_ERROR;
137 }
138 return TCL_OK;
139}
140
141/*
drh5c4d9702001-08-20 00:33:58 +0000142** Usage: btree_pager_stats ID
143**
144** Returns pager statistics
145*/
146static int btree_pager_stats(
147 void *NotUsed,
148 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
149 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000150 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000151){
152 Btree *pBt;
153 int i;
154 int *a;
155
156 if( argc!=2 ){
157 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
158 " ID\"", 0);
159 return TCL_ERROR;
160 }
drhe8f52c52008-07-12 14:52:20 +0000161 pBt = sqlite3TestTextToPtr(argv[1]);
danielk1977f3c62652007-08-30 08:27:39 +0000162
163 /* Normally in this file, with a b-tree handle opened using the
164 ** [btree_open] command it is safe to call sqlite3BtreeEnter() directly.
165 ** But this function is sometimes called with a btree handle obtained
166 ** from an open SQLite connection (using [btree_from_db]). In this case
167 ** we need to obtain the mutex for the controlling SQLite handle before
168 ** it is safe to call sqlite3BtreeEnter().
169 */
drhe5fe6902007-12-07 18:55:28 +0000170 sqlite3_mutex_enter(pBt->db->mutex);
danielk1977f3c62652007-08-30 08:27:39 +0000171
drh27641702007-08-22 02:56:42 +0000172 sqlite3BtreeEnter(pBt);
danielk19773b8a05f2007-03-19 17:44:26 +0000173 a = sqlite3PagerStats(sqlite3BtreePager(pBt));
danielk197742741be2005-01-08 12:42:39 +0000174 for(i=0; i<11; i++){
drh5c4d9702001-08-20 00:33:58 +0000175 static char *zName[] = {
176 "ref", "page", "max", "size", "state", "err",
danielk197742741be2005-01-08 12:42:39 +0000177 "hit", "miss", "ovfl", "read", "write"
drh5c4d9702001-08-20 00:33:58 +0000178 };
179 char zBuf[100];
180 Tcl_AppendElement(interp, zName[i]);
drhfe63d1c2004-09-08 20:13:04 +0000181 sqlite3_snprintf(sizeof(zBuf), zBuf,"%d",a[i]);
drh5c4d9702001-08-20 00:33:58 +0000182 Tcl_AppendElement(interp, zBuf);
183 }
drh27641702007-08-22 02:56:42 +0000184 sqlite3BtreeLeave(pBt);
danielk1977f3c62652007-08-30 08:27:39 +0000185
186 /* Release the mutex on the SQLite handle that controls this b-tree */
drhe5fe6902007-12-07 18:55:28 +0000187 sqlite3_mutex_leave(pBt->db->mutex);
drh5c4d9702001-08-20 00:33:58 +0000188 return TCL_OK;
189}
190
191/*
drhecdc7532001-09-23 02:35:53 +0000192** Usage: btree_cursor ID TABLENUM WRITEABLE
drh5c4d9702001-08-20 00:33:58 +0000193**
194** Create a new cursor. Return the ID for the cursor.
195*/
196static int btree_cursor(
197 void *NotUsed,
198 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
199 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000200 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000201){
202 Btree *pBt;
203 int iTable;
204 BtCursor *pCur;
dan93a696f2010-01-07 11:27:30 +0000205 int rc = SQLITE_OK;
drhecdc7532001-09-23 02:35:53 +0000206 int wrFlag;
drh5c4d9702001-08-20 00:33:58 +0000207 char zBuf[30];
208
drhecdc7532001-09-23 02:35:53 +0000209 if( argc!=4 ){
drh5c4d9702001-08-20 00:33:58 +0000210 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drhecdc7532001-09-23 02:35:53 +0000211 " ID TABLENUM WRITEABLE\"", 0);
drh5c4d9702001-08-20 00:33:58 +0000212 return TCL_ERROR;
213 }
drhe8f52c52008-07-12 14:52:20 +0000214 pBt = sqlite3TestTextToPtr(argv[1]);
drh5c4d9702001-08-20 00:33:58 +0000215 if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
drhecdc7532001-09-23 02:35:53 +0000216 if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
danielk1977cd3e8f72008-03-25 09:47:35 +0000217 pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize());
218 memset(pCur, 0, sqlite3BtreeCursorSize());
drhff0587c2007-08-29 17:43:19 +0000219 sqlite3BtreeEnter(pBt);
dan93a696f2010-01-07 11:27:30 +0000220#ifndef SQLITE_OMIT_SHARED_CACHE
danielk197796d48e92009-06-29 06:00:37 +0000221 rc = sqlite3BtreeLockTable(pBt, iTable, wrFlag);
dan93a696f2010-01-07 11:27:30 +0000222#endif
danielk197796d48e92009-06-29 06:00:37 +0000223 if( rc==SQLITE_OK ){
224 rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur);
225 }
drhff0587c2007-08-29 17:43:19 +0000226 sqlite3BtreeLeave(pBt);
drh5c4d9702001-08-20 00:33:58 +0000227 if( rc ){
danielk1977cd3e8f72008-03-25 09:47:35 +0000228 ckfree((char *)pCur);
mistachkine84d8d32013-04-29 03:09:10 +0000229 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh5c4d9702001-08-20 00:33:58 +0000230 return TCL_ERROR;
231 }
drhfe63d1c2004-09-08 20:13:04 +0000232 sqlite3_snprintf(sizeof(zBuf), zBuf,"%p", pCur);
drh5c4d9702001-08-20 00:33:58 +0000233 Tcl_AppendResult(interp, zBuf, 0);
234 return SQLITE_OK;
235}
236
237/*
238** Usage: btree_close_cursor ID
239**
240** Close a cursor opened using btree_cursor.
241*/
242static int btree_close_cursor(
243 void *NotUsed,
244 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
245 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000246 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000247){
248 BtCursor *pCur;
drhff0587c2007-08-29 17:43:19 +0000249 Btree *pBt;
drh5c4d9702001-08-20 00:33:58 +0000250 int rc;
251
252 if( argc!=2 ){
253 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
254 " ID\"", 0);
255 return TCL_ERROR;
256 }
drhe8f52c52008-07-12 14:52:20 +0000257 pCur = sqlite3TestTextToPtr(argv[1]);
drhff0587c2007-08-29 17:43:19 +0000258 pBt = pCur->pBtree;
259 sqlite3BtreeEnter(pBt);
drh23e11ca2004-05-04 17:27:28 +0000260 rc = sqlite3BtreeCloseCursor(pCur);
drhff0587c2007-08-29 17:43:19 +0000261 sqlite3BtreeLeave(pBt);
danielk1977cd3e8f72008-03-25 09:47:35 +0000262 ckfree((char *)pCur);
drh5c4d9702001-08-20 00:33:58 +0000263 if( rc ){
mistachkine84d8d32013-04-29 03:09:10 +0000264 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh5c4d9702001-08-20 00:33:58 +0000265 return TCL_ERROR;
266 }
267 return SQLITE_OK;
268}
269
270/*
drh5c4d9702001-08-20 00:33:58 +0000271** Usage: btree_next ID
272**
drh2dcc9aa2002-12-04 13:40:25 +0000273** Move the cursor to the next entry in the table. Return 0 on success
274** or 1 if the cursor was already on the last entry in the table or if
275** the table is empty.
drh5c4d9702001-08-20 00:33:58 +0000276*/
277static int btree_next(
278 void *NotUsed,
279 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
280 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000281 const char **argv /* Text of each argument */
drh5c4d9702001-08-20 00:33:58 +0000282){
283 BtCursor *pCur;
284 int rc;
drh0de8c112002-07-06 16:32:14 +0000285 int res = 0;
286 char zBuf[100];
drh5c4d9702001-08-20 00:33:58 +0000287
288 if( argc!=2 ){
289 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
290 " ID\"", 0);
291 return TCL_ERROR;
292 }
drhe8f52c52008-07-12 14:52:20 +0000293 pCur = sqlite3TestTextToPtr(argv[1]);
drhff0587c2007-08-29 17:43:19 +0000294 sqlite3BtreeEnter(pCur->pBtree);
drh4fc0fb42004-05-07 02:26:28 +0000295 rc = sqlite3BtreeNext(pCur, &res);
drhff0587c2007-08-29 17:43:19 +0000296 sqlite3BtreeLeave(pCur->pBtree);
drh5c4d9702001-08-20 00:33:58 +0000297 if( rc ){
mistachkine84d8d32013-04-29 03:09:10 +0000298 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh5c4d9702001-08-20 00:33:58 +0000299 return TCL_ERROR;
300 }
drhfe63d1c2004-09-08 20:13:04 +0000301 sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
drh0de8c112002-07-06 16:32:14 +0000302 Tcl_AppendResult(interp, zBuf, 0);
303 return SQLITE_OK;
304}
305
306/*
307** Usage: btree_first ID
308**
drh2dcc9aa2002-12-04 13:40:25 +0000309** Move the cursor to the first entry in the table. Return 0 if the
310** cursor was left point to something and 1 if the table is empty.
drh0de8c112002-07-06 16:32:14 +0000311*/
312static int btree_first(
313 void *NotUsed,
314 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
315 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000316 const char **argv /* Text of each argument */
drh0de8c112002-07-06 16:32:14 +0000317){
318 BtCursor *pCur;
319 int rc;
320 int res = 0;
321 char zBuf[100];
322
323 if( argc!=2 ){
324 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
325 " ID\"", 0);
326 return TCL_ERROR;
327 }
drhe8f52c52008-07-12 14:52:20 +0000328 pCur = sqlite3TestTextToPtr(argv[1]);
drhff0587c2007-08-29 17:43:19 +0000329 sqlite3BtreeEnter(pCur->pBtree);
drh4fc0fb42004-05-07 02:26:28 +0000330 rc = sqlite3BtreeFirst(pCur, &res);
drhff0587c2007-08-29 17:43:19 +0000331 sqlite3BtreeLeave(pCur->pBtree);
drh0de8c112002-07-06 16:32:14 +0000332 if( rc ){
mistachkine84d8d32013-04-29 03:09:10 +0000333 Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
drh0de8c112002-07-06 16:32:14 +0000334 return TCL_ERROR;
335 }
drhfe63d1c2004-09-08 20:13:04 +0000336 sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",res);
drh0de8c112002-07-06 16:32:14 +0000337 Tcl_AppendResult(interp, zBuf, 0);
drh5c4d9702001-08-20 00:33:58 +0000338 return SQLITE_OK;
339}
340
341/*
drhc39e0002004-05-07 23:50:57 +0000342** Usage: btree_eof ID
343**
344** Return TRUE if the given cursor is not pointing at a valid entry.
345** Return FALSE if the cursor does point to a valid entry.
346*/
347static int btree_eof(
348 void *NotUsed,
349 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
350 int argc, /* Number of arguments */
351 const char **argv /* Text of each argument */
352){
353 BtCursor *pCur;
drhff0587c2007-08-29 17:43:19 +0000354 int rc;
drhc39e0002004-05-07 23:50:57 +0000355 char zBuf[50];
356
357 if( argc!=2 ){
358 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
359 " ID\"", 0);
360 return TCL_ERROR;
361 }
drhe8f52c52008-07-12 14:52:20 +0000362 pCur = sqlite3TestTextToPtr(argv[1]);
drhff0587c2007-08-29 17:43:19 +0000363 sqlite3BtreeEnter(pCur->pBtree);
364 rc = sqlite3BtreeEof(pCur);
365 sqlite3BtreeLeave(pCur->pBtree);
366 sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", rc);
drhc39e0002004-05-07 23:50:57 +0000367 Tcl_AppendResult(interp, zBuf, 0);
368 return SQLITE_OK;
369}
370
371/*
drh0de8c112002-07-06 16:32:14 +0000372** Usage: btree_payload_size ID
373**
374** Return the number of bytes of payload
375*/
376static int btree_payload_size(
377 void *NotUsed,
378 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
379 int argc, /* Number of arguments */
drhc2eef3b2002-08-31 18:53:06 +0000380 const char **argv /* Text of each argument */
drh0de8c112002-07-06 16:32:14 +0000381){
382 BtCursor *pCur;
drh4fc0fb42004-05-07 02:26:28 +0000383 int n2;
drha34b6762004-05-07 13:30:42 +0000384 u64 n1;
drh0de8c112002-07-06 16:32:14 +0000385 char zBuf[50];
386
387 if( argc!=2 ){
388 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
389 " ID\"", 0);
390 return TCL_ERROR;
391 }
drhe8f52c52008-07-12 14:52:20 +0000392 pCur = sqlite3TestTextToPtr(argv[1]);
drhff0587c2007-08-29 17:43:19 +0000393 sqlite3BtreeEnter(pCur->pBtree);
danielk197730548662009-07-09 05:07:37 +0000394
395 /* The cursor may be in "require-seek" state. If this is the case, the
396 ** call to BtreeDataSize() will fix it. */
397 sqlite3BtreeDataSize(pCur, (u32*)&n2);
shanecbcadd42009-07-09 03:20:46 +0000398 if( pCur->apPage[pCur->iPage]->intKey ){
drha34b6762004-05-07 13:30:42 +0000399 n1 = 0;
400 }else{
drh03d847e2005-12-09 20:21:58 +0000401 sqlite3BtreeKeySize(pCur, (i64*)&n1);
drha34b6762004-05-07 13:30:42 +0000402 }
drhff0587c2007-08-29 17:43:19 +0000403 sqlite3BtreeLeave(pCur->pBtree);
drhfe63d1c2004-09-08 20:13:04 +0000404 sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", (int)(n1+n2));
drh0de8c112002-07-06 16:32:14 +0000405 Tcl_AppendResult(interp, zBuf, 0);
drh0de8c112002-07-06 16:32:14 +0000406 return SQLITE_OK;
407}
408
409/*
drh6d2fb152004-05-14 16:50:06 +0000410** usage: varint_test START MULTIPLIER COUNT INCREMENT
411**
shane3f8d5cf2008-04-24 19:15:09 +0000412** This command tests the putVarint() and getVarint()
drh6d2fb152004-05-14 16:50:06 +0000413** routines, both for accuracy and for speed.
414**
shane3f8d5cf2008-04-24 19:15:09 +0000415** An integer is written using putVarint() and read back with
416** getVarint() and varified to be unchanged. This repeats COUNT
drh6d2fb152004-05-14 16:50:06 +0000417** times. The first integer is START*MULTIPLIER. Each iteration
418** increases the integer by INCREMENT.
419**
420** This command returns nothing if it works. It returns an error message
421** if something goes wrong.
422*/
423static int btree_varint_test(
424 void *NotUsed,
425 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
426 int argc, /* Number of arguments */
427 const char **argv /* Text of each argument */
428){
429 u32 start, mult, count, incr;
430 u64 in, out;
drhd8820e82004-05-18 15:57:42 +0000431 int n1, n2, i, j;
drh6d2fb152004-05-14 16:50:06 +0000432 unsigned char zBuf[100];
433 if( argc!=5 ){
434 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
435 " START MULTIPLIER COUNT INCREMENT\"", 0);
436 return TCL_ERROR;
437 }
438 if( Tcl_GetInt(interp, argv[1], (int*)&start) ) return TCL_ERROR;
439 if( Tcl_GetInt(interp, argv[2], (int*)&mult) ) return TCL_ERROR;
440 if( Tcl_GetInt(interp, argv[3], (int*)&count) ) return TCL_ERROR;
441 if( Tcl_GetInt(interp, argv[4], (int*)&incr) ) return TCL_ERROR;
442 in = start;
443 in *= mult;
drh7da5fcb2012-03-30 14:59:43 +0000444 for(i=0; i<(int)count; i++){
drhd8820e82004-05-18 15:57:42 +0000445 char zErr[200];
shane3f8d5cf2008-04-24 19:15:09 +0000446 n1 = putVarint(zBuf, in);
drh6d2fb152004-05-14 16:50:06 +0000447 if( n1>9 || n1<1 ){
shane3f8d5cf2008-04-24 19:15:09 +0000448 sprintf(zErr, "putVarint returned %d - should be between 1 and 9", n1);
drhd8820e82004-05-18 15:57:42 +0000449 Tcl_AppendResult(interp, zErr, 0);
drh6d2fb152004-05-14 16:50:06 +0000450 return TCL_ERROR;
451 }
shane3f8d5cf2008-04-24 19:15:09 +0000452 n2 = getVarint(zBuf, &out);
drh6d2fb152004-05-14 16:50:06 +0000453 if( n1!=n2 ){
shane3f8d5cf2008-04-24 19:15:09 +0000454 sprintf(zErr, "putVarint returned %d and getVarint returned %d", n1, n2);
drhd8820e82004-05-18 15:57:42 +0000455 Tcl_AppendResult(interp, zErr, 0);
drh6d2fb152004-05-14 16:50:06 +0000456 return TCL_ERROR;
457 }
458 if( in!=out ){
drhd8820e82004-05-18 15:57:42 +0000459 sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx", in, out);
460 Tcl_AppendResult(interp, zErr, 0);
drh6d2fb152004-05-14 16:50:06 +0000461 return TCL_ERROR;
462 }
drh9d213ef2004-06-30 04:02:11 +0000463 if( (in & 0xffffffff)==in ){
464 u32 out32;
shane3f8d5cf2008-04-24 19:15:09 +0000465 n2 = getVarint32(zBuf, out32);
drh9d213ef2004-06-30 04:02:11 +0000466 out = out32;
467 if( n1!=n2 ){
shane3f8d5cf2008-04-24 19:15:09 +0000468 sprintf(zErr, "putVarint returned %d and GetVarint32 returned %d",
drh9d213ef2004-06-30 04:02:11 +0000469 n1, n2);
470 Tcl_AppendResult(interp, zErr, 0);
471 return TCL_ERROR;
472 }
473 if( in!=out ){
474 sprintf(zErr, "Wrote 0x%016llx and got back 0x%016llx from GetVarint32",
475 in, out);
476 Tcl_AppendResult(interp, zErr, 0);
477 return TCL_ERROR;
478 }
479 }
drhd8820e82004-05-18 15:57:42 +0000480
481 /* In order to get realistic timings, run getVarint 19 more times.
482 ** This is because getVarint is called about 20 times more often
483 ** than putVarint.
484 */
485 for(j=0; j<19; j++){
shane3f8d5cf2008-04-24 19:15:09 +0000486 getVarint(zBuf, &out);
drhd8820e82004-05-18 15:57:42 +0000487 }
drh6d2fb152004-05-14 16:50:06 +0000488 in += incr;
489 }
490 return TCL_OK;
491}
drh9b171272004-05-08 02:03:22 +0000492
493/*
danielk197742741be2005-01-08 12:42:39 +0000494** usage: btree_from_db DB-HANDLE
495**
496** This command returns the btree handle for the main database associated
497** with the database-handle passed as the argument. Example usage:
498**
499** sqlite3 db test.db
500** set bt [btree_from_db db]
501*/
502static int btree_from_db(
503 void *NotUsed,
504 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
505 int argc, /* Number of arguments */
506 const char **argv /* Text of each argument */
507){
508 char zBuf[100];
509 Tcl_CmdInfo info;
510 sqlite3 *db;
511 Btree *pBt;
danielk197763c64f32007-05-17 14:45:12 +0000512 int iDb = 0;
danielk197742741be2005-01-08 12:42:39 +0000513
danielk197763c64f32007-05-17 14:45:12 +0000514 if( argc!=2 && argc!=3 ){
danielk197742741be2005-01-08 12:42:39 +0000515 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
danielk197763c64f32007-05-17 14:45:12 +0000516 " DB-HANDLE ?N?\"", 0);
danielk197742741be2005-01-08 12:42:39 +0000517 return TCL_ERROR;
518 }
519
520 if( 1!=Tcl_GetCommandInfo(interp, argv[1], &info) ){
521 Tcl_AppendResult(interp, "No such db-handle: \"", argv[1], "\"", 0);
522 return TCL_ERROR;
523 }
danielk197763c64f32007-05-17 14:45:12 +0000524 if( argc==3 ){
525 iDb = atoi(argv[2]);
526 }
527
danielk197742741be2005-01-08 12:42:39 +0000528 db = *((sqlite3 **)info.objClientData);
529 assert( db );
530
danielk197763c64f32007-05-17 14:45:12 +0000531 pBt = db->aDb[iDb].pBt;
danielk197742741be2005-01-08 12:42:39 +0000532 sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", pBt);
533 Tcl_SetResult(interp, zBuf, TCL_VOLATILE);
534 return TCL_OK;
535}
536
danielk197717b90b52008-06-06 11:11:25 +0000537/*
538** Usage: btree_ismemdb ID
539**
540** Return true if the B-Tree is in-memory.
541*/
542static int btree_ismemdb(
543 void *NotUsed,
544 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
545 int argc, /* Number of arguments */
546 const char **argv /* Text of each argument */
547){
548 Btree *pBt;
549 int res;
550
551 if( argc!=2 ){
552 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
553 " ID\"", 0);
554 return TCL_ERROR;
555 }
drhe8f52c52008-07-12 14:52:20 +0000556 pBt = sqlite3TestTextToPtr(argv[1]);
danielk197717b90b52008-06-06 11:11:25 +0000557 sqlite3_mutex_enter(pBt->db->mutex);
558 sqlite3BtreeEnter(pBt);
559 res = sqlite3PagerIsMemdb(sqlite3BtreePager(pBt));
560 sqlite3BtreeLeave(pBt);
561 sqlite3_mutex_leave(pBt->db->mutex);
562 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(res));
563 return SQLITE_OK;
564}
565
danielk197730548662009-07-09 05:07:37 +0000566/*
567** usage: btree_set_cache_size ID NCACHE
568**
569** Set the size of the cache used by btree $ID.
570*/
571static int btree_set_cache_size(
572 void *NotUsed,
573 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
574 int argc, /* Number of arguments */
575 const char **argv /* Text of each argument */
576){
577 int nCache;
578 Btree *pBt;
579
580 if( argc!=3 ){
581 Tcl_AppendResult(
582 interp, "wrong # args: should be \"", argv[0], " BT NCACHE\"", 0);
583 return TCL_ERROR;
584 }
585 pBt = sqlite3TestTextToPtr(argv[1]);
586 if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
587
588 sqlite3_mutex_enter(pBt->db->mutex);
589 sqlite3BtreeEnter(pBt);
590 sqlite3BtreeSetCacheSize(pBt, nCache);
591 sqlite3BtreeLeave(pBt);
592 sqlite3_mutex_leave(pBt->db->mutex);
593 return TCL_OK;
594}
595
596
danielk19771ad7f642005-01-20 05:24:32 +0000597
danielk197742741be2005-01-08 12:42:39 +0000598/*
drh5c4d9702001-08-20 00:33:58 +0000599** Register commands with the TCL interpreter.
600*/
601int Sqlitetest3_Init(Tcl_Interp *interp){
drhc2eef3b2002-08-31 18:53:06 +0000602 static struct {
603 char *zName;
604 Tcl_CmdProc *xProc;
605 } aCmd[] = {
606 { "btree_open", (Tcl_CmdProc*)btree_open },
607 { "btree_close", (Tcl_CmdProc*)btree_close },
608 { "btree_begin_transaction", (Tcl_CmdProc*)btree_begin_transaction },
drhc2eef3b2002-08-31 18:53:06 +0000609 { "btree_pager_stats", (Tcl_CmdProc*)btree_pager_stats },
drhc2eef3b2002-08-31 18:53:06 +0000610 { "btree_cursor", (Tcl_CmdProc*)btree_cursor },
611 { "btree_close_cursor", (Tcl_CmdProc*)btree_close_cursor },
drhc2eef3b2002-08-31 18:53:06 +0000612 { "btree_next", (Tcl_CmdProc*)btree_next },
drhc39e0002004-05-07 23:50:57 +0000613 { "btree_eof", (Tcl_CmdProc*)btree_eof },
drhc2eef3b2002-08-31 18:53:06 +0000614 { "btree_payload_size", (Tcl_CmdProc*)btree_payload_size },
615 { "btree_first", (Tcl_CmdProc*)btree_first },
drh6d2fb152004-05-14 16:50:06 +0000616 { "btree_varint_test", (Tcl_CmdProc*)btree_varint_test },
danielk197742741be2005-01-08 12:42:39 +0000617 { "btree_from_db", (Tcl_CmdProc*)btree_from_db },
danielk197730548662009-07-09 05:07:37 +0000618 { "btree_ismemdb", (Tcl_CmdProc*)btree_ismemdb },
619 { "btree_set_cache_size", (Tcl_CmdProc*)btree_set_cache_size }
drhc2eef3b2002-08-31 18:53:06 +0000620 };
621 int i;
622
623 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
624 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
625 }
danielk1977312d6b32004-06-29 13:18:23 +0000626
drh5c4d9702001-08-20 00:33:58 +0000627 return TCL_OK;
628}