blob: e08c189e272a84354579eebf28e2f9352ebad179 [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.
15**
drhb19a2bc2001-09-16 00:13:26 +000016** $Id: test2.c,v 1.5 2001/09/16 00:13:27 drh Exp $
drh5c4d9702001-08-20 00:33:58 +000017*/
18#include "sqliteInt.h"
19#include "pager.h"
20#include "tcl.h"
21#include <stdlib.h>
22#include <string.h>
23
24/*
25** Interpret an SQLite error number
26*/
27static 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_INTERNAL: zName = "SQLITE_INTERNAL"; break;
33 case SQLITE_PERM: zName = "SQLITE_PERM"; break;
34 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
35 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
36 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
37 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
38 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
39 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
40 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
41 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
42 case SQLITE_FULL: zName = "SQLITE_FULL"; break;
43 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
44 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
45 default: zName = "SQLITE_Unknown"; break;
46 }
47 return zName;
48}
49
50/*
51** Usage: pager_open FILENAME N-PAGE
52**
53** Open a new pager
54*/
55static int pager_open(
56 void *NotUsed,
57 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
58 int argc, /* Number of arguments */
59 char **argv /* Text of each argument */
60){
61 Pager *pPager;
62 int nPage;
63 int rc;
64 char zBuf[100];
65 if( argc!=3 ){
66 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
67 " FILENAME N-PAGE\"", 0);
68 return TCL_ERROR;
69 }
70 if( Tcl_GetInt(interp, argv[2], &nPage) ) return TCL_ERROR;
71 rc = sqlitepager_open(&pPager, argv[1], nPage, 0);
72 if( rc!=SQLITE_OK ){
73 Tcl_AppendResult(interp, errorName(rc), 0);
74 return TCL_ERROR;
75 }
76 sprintf(zBuf,"0x%x",(int)pPager);
77 Tcl_AppendResult(interp, zBuf, 0);
78 return TCL_OK;
79}
80
81/*
82** Usage: pager_close ID
83**
84** Close the given pager.
85*/
86static int pager_close(
87 void *NotUsed,
88 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
89 int argc, /* Number of arguments */
90 char **argv /* Text of each argument */
91){
92 Pager *pPager;
93 int rc;
94 if( argc!=2 ){
95 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
96 " ID\"", 0);
97 return TCL_ERROR;
98 }
99 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
100 rc = sqlitepager_close(pPager);
101 if( rc!=SQLITE_OK ){
102 Tcl_AppendResult(interp, errorName(rc), 0);
103 return TCL_ERROR;
104 }
105 return TCL_OK;
106}
107
108/*
109** Usage: pager_rollback ID
110**
111** Rollback changes
112*/
113static int pager_rollback(
114 void *NotUsed,
115 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
116 int argc, /* Number of arguments */
117 char **argv /* Text of each argument */
118){
119 Pager *pPager;
120 int rc;
121 if( argc!=2 ){
122 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
123 " ID\"", 0);
124 return TCL_ERROR;
125 }
126 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
127 rc = sqlitepager_rollback(pPager);
128 if( rc!=SQLITE_OK ){
129 Tcl_AppendResult(interp, errorName(rc), 0);
130 return TCL_ERROR;
131 }
132 return TCL_OK;
133}
134
135/*
136** Usage: pager_commit ID
137**
138** Commit all changes
139*/
140static int pager_commit(
141 void *NotUsed,
142 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
143 int argc, /* Number of arguments */
144 char **argv /* Text of each argument */
145){
146 Pager *pPager;
147 int rc;
148 if( argc!=2 ){
149 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
150 " ID\"", 0);
151 return TCL_ERROR;
152 }
153 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
154 rc = sqlitepager_commit(pPager);
155 if( rc!=SQLITE_OK ){
156 Tcl_AppendResult(interp, errorName(rc), 0);
157 return TCL_ERROR;
158 }
159 return TCL_OK;
160}
161
162/*
163** Usage: pager_stats ID
164**
165** Return pager statistics.
166*/
167static int pager_stats(
168 void *NotUsed,
169 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
170 int argc, /* Number of arguments */
171 char **argv /* Text of each argument */
172){
173 Pager *pPager;
174 int i, *a;
175 if( argc!=2 ){
176 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
177 " ID\"", 0);
178 return TCL_ERROR;
179 }
180 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
181 a = sqlitepager_stats(pPager);
182 for(i=0; i<9; i++){
183 static char *zName[] = {
184 "ref", "page", "max", "size", "state", "err",
185 "hit", "miss", "ovfl",
186 };
187 char zBuf[100];
188 Tcl_AppendElement(interp, zName[i]);
189 sprintf(zBuf,"%d",a[i]);
190 Tcl_AppendElement(interp, zBuf);
191 }
192 return TCL_OK;
193}
194
195/*
196** Usage: pager_pagecount ID
197**
198** Return the size of the database file.
199*/
200static int pager_pagecount(
201 void *NotUsed,
202 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
203 int argc, /* Number of arguments */
204 char **argv /* Text of each argument */
205){
206 Pager *pPager;
207 char zBuf[100];
208 if( argc!=2 ){
209 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
210 " ID\"", 0);
211 return TCL_ERROR;
212 }
213 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
214 sprintf(zBuf,"%d",sqlitepager_pagecount(pPager));
215 Tcl_AppendResult(interp, zBuf, 0);
216 return TCL_OK;
217}
218
219/*
220** Usage: page_get ID PGNO
221**
222** Return a pointer to a page from the database.
223*/
224static int page_get(
225 void *NotUsed,
226 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
227 int argc, /* Number of arguments */
228 char **argv /* Text of each argument */
229){
230 Pager *pPager;
231 char zBuf[100];
232 void *pPage;
233 int pgno;
234 int rc;
235 if( argc!=3 ){
236 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
237 " ID PGNO\"", 0);
238 return TCL_ERROR;
239 }
240 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
241 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
242 rc = sqlitepager_get(pPager, pgno, &pPage);
243 if( rc!=SQLITE_OK ){
244 Tcl_AppendResult(interp, errorName(rc), 0);
245 return TCL_ERROR;
246 }
247 sprintf(zBuf,"0x%x",(int)pPage);
248 Tcl_AppendResult(interp, zBuf, 0);
249 return TCL_OK;
250}
251
252/*
253** Usage: page_lookup ID PGNO
254**
255** Return a pointer to a page if the page is already in cache.
256** If not in cache, return an empty string.
257*/
258static int page_lookup(
259 void *NotUsed,
260 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
261 int argc, /* Number of arguments */
262 char **argv /* Text of each argument */
263){
264 Pager *pPager;
265 char zBuf[100];
266 void *pPage;
267 int pgno;
268 if( argc!=3 ){
269 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
270 " ID PGNO\"", 0);
271 return TCL_ERROR;
272 }
273 if( Tcl_GetInt(interp, argv[1], (int*)&pPager) ) return TCL_ERROR;
274 if( Tcl_GetInt(interp, argv[2], &pgno) ) return TCL_ERROR;
275 pPage = sqlitepager_lookup(pPager, pgno);
276 if( pPage ){
277 sprintf(zBuf,"0x%x",(int)pPage);
278 Tcl_AppendResult(interp, zBuf, 0);
279 }
280 return TCL_OK;
281}
282
283/*
284** Usage: page_unref PAGE
285**
286** Drop a pointer to a page.
287*/
288static int page_unref(
289 void *NotUsed,
290 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
291 int argc, /* Number of arguments */
292 char **argv /* Text of each argument */
293){
294 void *pPage;
295 int rc;
296 if( argc!=2 ){
297 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
298 " PAGE\"", 0);
299 return TCL_ERROR;
300 }
301 if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
302 rc = sqlitepager_unref(pPage);
303 if( rc!=SQLITE_OK ){
304 Tcl_AppendResult(interp, errorName(rc), 0);
305 return TCL_ERROR;
306 }
307 return TCL_OK;
308}
309
310/*
311** Usage: page_read PAGE
312**
313** Return the content of a page
314*/
315static int page_read(
316 void *NotUsed,
317 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
318 int argc, /* Number of arguments */
319 char **argv /* Text of each argument */
320){
321 char zBuf[100];
322 void *pPage;
323 if( argc!=2 ){
324 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
325 " PAGE\"", 0);
326 return TCL_ERROR;
327 }
328 if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
329 memcpy(zBuf, pPage, sizeof(zBuf));
330 Tcl_AppendResult(interp, zBuf, 0);
331 return TCL_OK;
332}
333
334/*
335** Usage: page_number PAGE
336**
337** Return the page number for a page.
338*/
339static int page_number(
340 void *NotUsed,
341 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
342 int argc, /* Number of arguments */
343 char **argv /* Text of each argument */
344){
345 char zBuf[100];
346 void *pPage;
347 if( argc!=2 ){
348 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
349 " PAGE\"", 0);
350 return TCL_ERROR;
351 }
352 if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
353 sprintf(zBuf, "%d", sqlitepager_pagenumber(pPage));
354 Tcl_AppendResult(interp, zBuf, 0);
355 return TCL_OK;
356}
357
358/*
359** Usage: page_write PAGE DATA
360**
361** Write something into a page.
362*/
363static int page_write(
364 void *NotUsed,
365 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
366 int argc, /* Number of arguments */
367 char **argv /* Text of each argument */
368){
369 void *pPage;
370 int rc;
371 if( argc!=3 ){
372 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
373 " PAGE DATA\"", 0);
374 return TCL_ERROR;
375 }
376 if( Tcl_GetInt(interp, argv[1], (int*)&pPage) ) return TCL_ERROR;
377 rc = sqlitepager_write(pPage);
378 if( rc!=SQLITE_OK ){
379 Tcl_AppendResult(interp, errorName(rc), 0);
380 return TCL_ERROR;
381 }
382 strncpy((char*)pPage, argv[2], SQLITE_PAGE_SIZE-1);
383 ((char*)pPage)[SQLITE_PAGE_SIZE-1] = 0;
384 return TCL_OK;
385}
386
387/*
388** Register commands with the TCL interpreter.
389*/
390int Sqlitetest2_Init(Tcl_Interp *interp){
391 Tcl_CreateCommand(interp, "pager_open", pager_open, 0, 0);
392 Tcl_CreateCommand(interp, "pager_close", pager_close, 0, 0);
393 Tcl_CreateCommand(interp, "pager_commit", pager_commit, 0, 0);
394 Tcl_CreateCommand(interp, "pager_rollback", pager_rollback, 0, 0);
395 Tcl_CreateCommand(interp, "pager_stats", pager_stats, 0, 0);
396 Tcl_CreateCommand(interp, "pager_pagecount", pager_pagecount, 0, 0);
397 Tcl_CreateCommand(interp, "page_get", page_get, 0, 0);
398 Tcl_CreateCommand(interp, "page_lookup", page_lookup, 0, 0);
399 Tcl_CreateCommand(interp, "page_unref", page_unref, 0, 0);
400 Tcl_CreateCommand(interp, "page_read", page_read, 0, 0);
401 Tcl_CreateCommand(interp, "page_write", page_write, 0, 0);
402 Tcl_CreateCommand(interp, "page_number", page_number, 0, 0);
403 return TCL_OK;
404}