source: trunk/src/3rdparty/sqlite/pragma.c@ 205

Last change on this file since 205 was 205, checked in by rudi, 14 years ago

Added SQLite 2.8.17 sources. This allows to build at least one of the sql drivers / plugins.

File size: 24.6 KB
Line 
1/*
2** 2003 April 6
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** This file contains code used to implement the PRAGMA command.
13**
14** $Id: pragma.c,v 1.19 2004/04/23 17:04:45 drh Exp $
15*/
16#include "sqliteInt.h"
17#include <ctype.h>
18
19/*
20** Interpret the given string as a boolean value.
21*/
22static int getBoolean(const char *z){
23 static char *azTrue[] = { "yes", "on", "true" };
24 int i;
25 if( z[0]==0 ) return 0;
26 if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
27 return atoi(z);
28 }
29 for(i=0; i<sizeof(azTrue)/sizeof(azTrue[0]); i++){
30 if( sqliteStrICmp(z,azTrue[i])==0 ) return 1;
31 }
32 return 0;
33}
34
35/*
36** Interpret the given string as a safety level. Return 0 for OFF,
37** 1 for ON or NORMAL and 2 for FULL. Return 1 for an empty or
38** unrecognized string argument.
39**
40** Note that the values returned are one less that the values that
41** should be passed into sqliteBtreeSetSafetyLevel(). The is done
42** to support legacy SQL code. The safety level used to be boolean
43** and older scripts may have used numbers 0 for OFF and 1 for ON.
44*/
45static int getSafetyLevel(char *z){
46 static const struct {
47 const char *zWord;
48 int val;
49 } aKey[] = {
50 { "no", 0 },
51 { "off", 0 },
52 { "false", 0 },
53 { "yes", 1 },
54 { "on", 1 },
55 { "true", 1 },
56 { "full", 2 },
57 };
58 int i;
59 if( z[0]==0 ) return 1;
60 if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
61 return atoi(z);
62 }
63 for(i=0; i<sizeof(aKey)/sizeof(aKey[0]); i++){
64 if( sqliteStrICmp(z,aKey[i].zWord)==0 ) return aKey[i].val;
65 }
66 return 1;
67}
68
69/*
70** Interpret the given string as a temp db location. Return 1 for file
71** backed temporary databases, 2 for the Red-Black tree in memory database
72** and 0 to use the compile-time default.
73*/
74static int getTempStore(const char *z){
75 if( z[0]>='0' && z[0]<='2' ){
76 return z[0] - '0';
77 }else if( sqliteStrICmp(z, "file")==0 ){
78 return 1;
79 }else if( sqliteStrICmp(z, "memory")==0 ){
80 return 2;
81 }else{
82 return 0;
83 }
84}
85
86/*
87** If the TEMP database is open, close it and mark the database schema
88** as needing reloading. This must be done when using the TEMP_STORE
89** or DEFAULT_TEMP_STORE pragmas.
90*/
91static int changeTempStorage(Parse *pParse, const char *zStorageType){
92 int ts = getTempStore(zStorageType);
93 sqlite *db = pParse->db;
94 if( db->temp_store==ts ) return SQLITE_OK;
95 if( db->aDb[1].pBt!=0 ){
96 if( db->flags & SQLITE_InTrans ){
97 sqliteErrorMsg(pParse, "temporary storage cannot be changed "
98 "from within a transaction");
99 return SQLITE_ERROR;
100 }
101 sqliteBtreeClose(db->aDb[1].pBt);
102 db->aDb[1].pBt = 0;
103 sqliteResetInternalSchema(db, 0);
104 }
105 db->temp_store = ts;
106 return SQLITE_OK;
107}
108
109/*
110** Check to see if zRight and zLeft refer to a pragma that queries
111** or changes one of the flags in db->flags. Return 1 if so and 0 if not.
112** Also, implement the pragma.
113*/
114static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
115 static const struct {
116 const char *zName; /* Name of the pragma */
117 int mask; /* Mask for the db->flags value */
118 } aPragma[] = {
119 { "vdbe_trace", SQLITE_VdbeTrace },
120 { "full_column_names", SQLITE_FullColNames },
121 { "short_column_names", SQLITE_ShortColNames },
122 { "show_datatypes", SQLITE_ReportTypes },
123 { "count_changes", SQLITE_CountRows },
124 { "empty_result_callbacks", SQLITE_NullCallback },
125 };
126 int i;
127 for(i=0; i<sizeof(aPragma)/sizeof(aPragma[0]); i++){
128 if( sqliteStrICmp(zLeft, aPragma[i].zName)==0 ){
129 sqlite *db = pParse->db;
130 Vdbe *v;
131 if( strcmp(zLeft,zRight)==0 && (v = sqliteGetVdbe(pParse))!=0 ){
132 sqliteVdbeOp3(v, OP_ColumnName, 0, 1, aPragma[i].zName, P3_STATIC);
133 sqliteVdbeOp3(v, OP_ColumnName, 1, 0, "boolean", P3_STATIC);
134 sqliteVdbeCode(v, OP_Integer, (db->flags & aPragma[i].mask)!=0, 0,
135 OP_Callback, 1, 0,
136 0);
137 }else if( getBoolean(zRight) ){
138 db->flags |= aPragma[i].mask;
139 }else{
140 db->flags &= ~aPragma[i].mask;
141 }
142 return 1;
143 }
144 }
145 return 0;
146}
147
148/*
149** Process a pragma statement.
150**
151** Pragmas are of this form:
152**
153** PRAGMA id = value
154**
155** The identifier might also be a string. The value is a string, and
156** identifier, or a number. If minusFlag is true, then the value is
157** a number that was preceded by a minus sign.
158*/
159void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
160 char *zLeft = 0;
161 char *zRight = 0;
162 sqlite *db = pParse->db;
163 Vdbe *v = sqliteGetVdbe(pParse);
164 if( v==0 ) return;
165
166 zLeft = sqliteStrNDup(pLeft->z, pLeft->n);
167 sqliteDequote(zLeft);
168 if( minusFlag ){
169 zRight = 0;
170 sqliteSetNString(&zRight, "-", 1, pRight->z, pRight->n, 0);
171 }else{
172 zRight = sqliteStrNDup(pRight->z, pRight->n);
173 sqliteDequote(zRight);
174 }
175 if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, 0) ){
176 sqliteFree(zLeft);
177 sqliteFree(zRight);
178 return;
179 }
180
181 /*
182 ** PRAGMA default_cache_size
183 ** PRAGMA default_cache_size=N
184 **
185 ** The first form reports the current persistent setting for the
186 ** page cache size. The value returned is the maximum number of
187 ** pages in the page cache. The second form sets both the current
188 ** page cache size value and the persistent page cache size value
189 ** stored in the database file.
190 **
191 ** The default cache size is stored in meta-value 2 of page 1 of the
192 ** database file. The cache size is actually the absolute value of
193 ** this memory location. The sign of meta-value 2 determines the
194 ** synchronous setting. A negative value means synchronous is off
195 ** and a positive value means synchronous is on.
196 */
197 if( sqliteStrICmp(zLeft,"default_cache_size")==0 ){
198 static VdbeOpList getCacheSize[] = {
199 { OP_ReadCookie, 0, 2, 0},
200 { OP_AbsValue, 0, 0, 0},
201 { OP_Dup, 0, 0, 0},
202 { OP_Integer, 0, 0, 0},
203 { OP_Ne, 0, 6, 0},
204 { OP_Integer, 0, 0, 0}, /* 5 */
205 { OP_ColumnName, 0, 1, "cache_size"},
206 { OP_Callback, 1, 0, 0},
207 };
208 int addr;
209 if( pRight->z==pLeft->z ){
210 addr = sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
211 sqliteVdbeChangeP1(v, addr+5, MAX_PAGES);
212 }else{
213 int size = atoi(zRight);
214 if( size<0 ) size = -size;
215 sqliteBeginWriteOperation(pParse, 0, 0);
216 sqliteVdbeAddOp(v, OP_Integer, size, 0);
217 sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
218 addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
219 sqliteVdbeAddOp(v, OP_Ge, 0, addr+3);
220 sqliteVdbeAddOp(v, OP_Negative, 0, 0);
221 sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
222 sqliteEndWriteOperation(pParse);
223 db->cache_size = db->cache_size<0 ? -size : size;
224 sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
225 }
226 }else
227
228 /*
229 ** PRAGMA cache_size
230 ** PRAGMA cache_size=N
231 **
232 ** The first form reports the current local setting for the
233 ** page cache size. The local setting can be different from
234 ** the persistent cache size value that is stored in the database
235 ** file itself. The value returned is the maximum number of
236 ** pages in the page cache. The second form sets the local
237 ** page cache size value. It does not change the persistent
238 ** cache size stored on the disk so the cache size will revert
239 ** to its default value when the database is closed and reopened.
240 ** N should be a positive integer.
241 */
242 if( sqliteStrICmp(zLeft,"cache_size")==0 ){
243 static VdbeOpList getCacheSize[] = {
244 { OP_ColumnName, 0, 1, "cache_size"},
245 { OP_Callback, 1, 0, 0},
246 };
247 if( pRight->z==pLeft->z ){
248 int size = db->cache_size;;
249 if( size<0 ) size = -size;
250 sqliteVdbeAddOp(v, OP_Integer, size, 0);
251 sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
252 }else{
253 int size = atoi(zRight);
254 if( size<0 ) size = -size;
255 if( db->cache_size<0 ) size = -size;
256 db->cache_size = size;
257 sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
258 }
259 }else
260
261 /*
262 ** PRAGMA default_synchronous
263 ** PRAGMA default_synchronous=ON|OFF|NORMAL|FULL
264 **
265 ** The first form returns the persistent value of the "synchronous" setting
266 ** that is stored in the database. This is the synchronous setting that
267 ** is used whenever the database is opened unless overridden by a separate
268 ** "synchronous" pragma. The second form changes the persistent and the
269 ** local synchronous setting to the value given.
270 **
271 ** If synchronous is OFF, SQLite does not attempt any fsync() systems calls
272 ** to make sure data is committed to disk. Write operations are very fast,
273 ** but a power failure can leave the database in an inconsistent state.
274 ** If synchronous is ON or NORMAL, SQLite will do an fsync() system call to
275 ** make sure data is being written to disk. The risk of corruption due to
276 ** a power loss in this mode is negligible but non-zero. If synchronous
277 ** is FULL, extra fsync()s occur to reduce the risk of corruption to near
278 ** zero, but with a write performance penalty. The default mode is NORMAL.
279 */
280 if( sqliteStrICmp(zLeft,"default_synchronous")==0 ){
281 static VdbeOpList getSync[] = {
282 { OP_ColumnName, 0, 1, "synchronous"},
283 { OP_ReadCookie, 0, 3, 0},
284 { OP_Dup, 0, 0, 0},
285 { OP_If, 0, 0, 0}, /* 3 */
286 { OP_ReadCookie, 0, 2, 0},
287 { OP_Integer, 0, 0, 0},
288 { OP_Lt, 0, 5, 0},
289 { OP_AddImm, 1, 0, 0},
290 { OP_Callback, 1, 0, 0},
291 { OP_Halt, 0, 0, 0},
292 { OP_AddImm, -1, 0, 0}, /* 10 */
293 { OP_Callback, 1, 0, 0}
294 };
295 if( pRight->z==pLeft->z ){
296 int addr = sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
297 sqliteVdbeChangeP2(v, addr+3, addr+10);
298 }else{
299 int addr;
300 int size = db->cache_size;
301 if( size<0 ) size = -size;
302 sqliteBeginWriteOperation(pParse, 0, 0);
303 sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
304 sqliteVdbeAddOp(v, OP_Dup, 0, 0);
305 addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
306 sqliteVdbeAddOp(v, OP_Ne, 0, addr+3);
307 sqliteVdbeAddOp(v, OP_AddImm, MAX_PAGES, 0);
308 sqliteVdbeAddOp(v, OP_AbsValue, 0, 0);
309 db->safety_level = getSafetyLevel(zRight)+1;
310 if( db->safety_level==1 ){
311 sqliteVdbeAddOp(v, OP_Negative, 0, 0);
312 size = -size;
313 }
314 sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
315 sqliteVdbeAddOp(v, OP_Integer, db->safety_level, 0);
316 sqliteVdbeAddOp(v, OP_SetCookie, 0, 3);
317 sqliteEndWriteOperation(pParse);
318 db->cache_size = size;
319 sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
320 sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
321 }
322 }else
323
324 /*
325 ** PRAGMA synchronous
326 ** PRAGMA synchronous=OFF|ON|NORMAL|FULL
327 **
328 ** Return or set the local value of the synchronous flag. Changing
329 ** the local value does not make changes to the disk file and the
330 ** default value will be restored the next time the database is
331 ** opened.
332 */
333 if( sqliteStrICmp(zLeft,"synchronous")==0 ){
334 static VdbeOpList getSync[] = {
335 { OP_ColumnName, 0, 1, "synchronous"},
336 { OP_Callback, 1, 0, 0},
337 };
338 if( pRight->z==pLeft->z ){
339 sqliteVdbeAddOp(v, OP_Integer, db->safety_level-1, 0);
340 sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
341 }else{
342 int size = db->cache_size;
343 if( size<0 ) size = -size;
344 db->safety_level = getSafetyLevel(zRight)+1;
345 if( db->safety_level==1 ) size = -size;
346 db->cache_size = size;
347 sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
348 sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
349 }
350 }else
351
352#ifndef NDEBUG
353 if( sqliteStrICmp(zLeft, "trigger_overhead_test")==0 ){
354 if( getBoolean(zRight) ){
355 always_code_trigger_setup = 1;
356 }else{
357 always_code_trigger_setup = 0;
358 }
359 }else
360#endif
361
362 if( flagPragma(pParse, zLeft, zRight) ){
363 /* The flagPragma() call also generates any necessary code */
364 }else
365
366 if( sqliteStrICmp(zLeft, "table_info")==0 ){
367 Table *pTab;
368 pTab = sqliteFindTable(db, zRight, 0);
369 if( pTab ){
370 static VdbeOpList tableInfoPreface[] = {
371 { OP_ColumnName, 0, 0, "cid"},
372 { OP_ColumnName, 1, 0, "name"},
373 { OP_ColumnName, 2, 0, "type"},
374 { OP_ColumnName, 3, 0, "notnull"},
375 { OP_ColumnName, 4, 0, "dflt_value"},
376 { OP_ColumnName, 5, 1, "pk"},
377 };
378 int i;
379 sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
380 sqliteViewGetColumnNames(pParse, pTab);
381 for(i=0; i<pTab->nCol; i++){
382 sqliteVdbeAddOp(v, OP_Integer, i, 0);
383 sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zName, 0);
384 sqliteVdbeOp3(v, OP_String, 0, 0,
385 pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", 0);
386 sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0);
387 sqliteVdbeOp3(v, OP_String, 0, 0,
388 pTab->aCol[i].zDflt, P3_STATIC);
389 sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0);
390 sqliteVdbeAddOp(v, OP_Callback, 6, 0);
391 }
392 }
393 }else
394
395 if( sqliteStrICmp(zLeft, "index_info")==0 ){
396 Index *pIdx;
397 Table *pTab;
398 pIdx = sqliteFindIndex(db, zRight, 0);
399 if( pIdx ){
400 static VdbeOpList tableInfoPreface[] = {
401 { OP_ColumnName, 0, 0, "seqno"},
402 { OP_ColumnName, 1, 0, "cid"},
403 { OP_ColumnName, 2, 1, "name"},
404 };
405 int i;
406 pTab = pIdx->pTable;
407 sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
408 for(i=0; i<pIdx->nColumn; i++){
409 int cnum = pIdx->aiColumn[i];
410 sqliteVdbeAddOp(v, OP_Integer, i, 0);
411 sqliteVdbeAddOp(v, OP_Integer, cnum, 0);
412 assert( pTab->nCol>cnum );
413 sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[cnum].zName, 0);
414 sqliteVdbeAddOp(v, OP_Callback, 3, 0);
415 }
416 }
417 }else
418
419 if( sqliteStrICmp(zLeft, "index_list")==0 ){
420 Index *pIdx;
421 Table *pTab;
422 pTab = sqliteFindTable(db, zRight, 0);
423 if( pTab ){
424 v = sqliteGetVdbe(pParse);
425 pIdx = pTab->pIndex;
426 }
427 if( pTab && pIdx ){
428 int i = 0;
429 static VdbeOpList indexListPreface[] = {
430 { OP_ColumnName, 0, 0, "seq"},
431 { OP_ColumnName, 1, 0, "name"},
432 { OP_ColumnName, 2, 1, "unique"},
433 };
434
435 sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
436 while(pIdx){
437 sqliteVdbeAddOp(v, OP_Integer, i, 0);
438 sqliteVdbeOp3(v, OP_String, 0, 0, pIdx->zName, 0);
439 sqliteVdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0);
440 sqliteVdbeAddOp(v, OP_Callback, 3, 0);
441 ++i;
442 pIdx = pIdx->pNext;
443 }
444 }
445 }else
446
447 if( sqliteStrICmp(zLeft, "foreign_key_list")==0 ){
448 FKey *pFK;
449 Table *pTab;
450 pTab = sqliteFindTable(db, zRight, 0);
451 if( pTab ){
452 v = sqliteGetVdbe(pParse);
453 pFK = pTab->pFKey;
454 }
455 if( pTab && pFK ){
456 int i = 0;
457 static VdbeOpList indexListPreface[] = {
458 { OP_ColumnName, 0, 0, "id"},
459 { OP_ColumnName, 1, 0, "seq"},
460 { OP_ColumnName, 2, 0, "table"},
461 { OP_ColumnName, 3, 0, "from"},
462 { OP_ColumnName, 4, 1, "to"},
463 };
464
465 sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
466 while(pFK){
467 int j;
468 for(j=0; j<pFK->nCol; j++){
469 sqliteVdbeAddOp(v, OP_Integer, i, 0);
470 sqliteVdbeAddOp(v, OP_Integer, j, 0);
471 sqliteVdbeOp3(v, OP_String, 0, 0, pFK->zTo, 0);
472 sqliteVdbeOp3(v, OP_String, 0, 0,
473 pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
474 sqliteVdbeOp3(v, OP_String, 0, 0, pFK->aCol[j].zCol, 0);
475 sqliteVdbeAddOp(v, OP_Callback, 5, 0);
476 }
477 ++i;
478 pFK = pFK->pNextFrom;
479 }
480 }
481 }else
482
483 if( sqliteStrICmp(zLeft, "database_list")==0 ){
484 int i;
485 static VdbeOpList indexListPreface[] = {
486 { OP_ColumnName, 0, 0, "seq"},
487 { OP_ColumnName, 1, 0, "name"},
488 { OP_ColumnName, 2, 1, "file"},
489 };
490
491 sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
492 for(i=0; i<db->nDb; i++){
493 if( db->aDb[i].pBt==0 ) continue;
494 assert( db->aDb[i].zName!=0 );
495 sqliteVdbeAddOp(v, OP_Integer, i, 0);
496 sqliteVdbeOp3(v, OP_String, 0, 0, db->aDb[i].zName, 0);
497 sqliteVdbeOp3(v, OP_String, 0, 0,
498 sqliteBtreeGetFilename(db->aDb[i].pBt), 0);
499 sqliteVdbeAddOp(v, OP_Callback, 3, 0);
500 }
501 }else
502
503
504 /*
505 ** PRAGMA temp_store
506 ** PRAGMA temp_store = "default"|"memory"|"file"
507 **
508 ** Return or set the local value of the temp_store flag. Changing
509 ** the local value does not make changes to the disk file and the default
510 ** value will be restored the next time the database is opened.
511 **
512 ** Note that it is possible for the library compile-time options to
513 ** override this setting
514 */
515 if( sqliteStrICmp(zLeft, "temp_store")==0 ){
516 static VdbeOpList getTmpDbLoc[] = {
517 { OP_ColumnName, 0, 1, "temp_store"},
518 { OP_Callback, 1, 0, 0},
519 };
520 if( pRight->z==pLeft->z ){
521 sqliteVdbeAddOp(v, OP_Integer, db->temp_store, 0);
522 sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc);
523 }else{
524 changeTempStorage(pParse, zRight);
525 }
526 }else
527
528 /*
529 ** PRAGMA default_temp_store
530 ** PRAGMA default_temp_store = "default"|"memory"|"file"
531 **
532 ** Return or set the value of the persistent temp_store flag. Any
533 ** change does not take effect until the next time the database is
534 ** opened.
535 **
536 ** Note that it is possible for the library compile-time options to
537 ** override this setting
538 */
539 if( sqliteStrICmp(zLeft, "default_temp_store")==0 ){
540 static VdbeOpList getTmpDbLoc[] = {
541 { OP_ColumnName, 0, 1, "temp_store"},
542 { OP_ReadCookie, 0, 5, 0},
543 { OP_Callback, 1, 0, 0}};
544 if( pRight->z==pLeft->z ){
545 sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc);
546 }else{
547 sqliteBeginWriteOperation(pParse, 0, 0);
548 sqliteVdbeAddOp(v, OP_Integer, getTempStore(zRight), 0);
549 sqliteVdbeAddOp(v, OP_SetCookie, 0, 5);
550 sqliteEndWriteOperation(pParse);
551 }
552 }else
553
554#ifndef NDEBUG
555 if( sqliteStrICmp(zLeft, "parser_trace")==0 ){
556 extern void sqliteParserTrace(FILE*, char *);
557 if( getBoolean(zRight) ){
558 sqliteParserTrace(stdout, "parser: ");
559 }else{
560 sqliteParserTrace(0, 0);
561 }
562 }else
563#endif
564
565 if( sqliteStrICmp(zLeft, "integrity_check")==0 ){
566 int i, j, addr;
567
568 /* Code that initializes the integrity check program. Set the
569 ** error count 0
570 */
571 static VdbeOpList initCode[] = {
572 { OP_Integer, 0, 0, 0},
573 { OP_MemStore, 0, 1, 0},
574 { OP_ColumnName, 0, 1, "integrity_check"},
575 };
576
577 /* Code to do an BTree integrity check on a single database file.
578 */
579 static VdbeOpList checkDb[] = {
580 { OP_SetInsert, 0, 0, "2"},
581 { OP_Integer, 0, 0, 0}, /* 1 */
582 { OP_OpenRead, 0, 2, 0},
583 { OP_Rewind, 0, 7, 0}, /* 3 */
584 { OP_Column, 0, 3, 0}, /* 4 */
585 { OP_SetInsert, 0, 0, 0},
586 { OP_Next, 0, 4, 0}, /* 6 */
587 { OP_IntegrityCk, 0, 0, 0}, /* 7 */
588 { OP_Dup, 0, 1, 0},
589 { OP_String, 0, 0, "ok"},
590 { OP_StrEq, 0, 12, 0}, /* 10 */
591 { OP_MemIncr, 0, 0, 0},
592 { OP_String, 0, 0, "*** in database "},
593 { OP_String, 0, 0, 0}, /* 13 */
594 { OP_String, 0, 0, " ***\n"},
595 { OP_Pull, 3, 0, 0},
596 { OP_Concat, 4, 1, 0},
597 { OP_Callback, 1, 0, 0},
598 };
599
600 /* Code that appears at the end of the integrity check. If no error
601 ** messages have been generated, output OK. Otherwise output the
602 ** error message
603 */
604 static VdbeOpList endCode[] = {
605 { OP_MemLoad, 0, 0, 0},
606 { OP_Integer, 0, 0, 0},
607 { OP_Ne, 0, 0, 0}, /* 2 */
608 { OP_String, 0, 0, "ok"},
609 { OP_Callback, 1, 0, 0},
610 };
611
612 /* Initialize the VDBE program */
613 sqliteVdbeAddOpList(v, ArraySize(initCode), initCode);
614
615 /* Do an integrity check on each database file */
616 for(i=0; i<db->nDb; i++){
617 HashElem *x;
618
619 /* Do an integrity check of the B-Tree
620 */
621 addr = sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb);
622 sqliteVdbeChangeP1(v, addr+1, i);
623 sqliteVdbeChangeP2(v, addr+3, addr+7);
624 sqliteVdbeChangeP2(v, addr+6, addr+4);
625 sqliteVdbeChangeP2(v, addr+7, i);
626 sqliteVdbeChangeP2(v, addr+10, addr+ArraySize(checkDb));
627 sqliteVdbeChangeP3(v, addr+13, db->aDb[i].zName, P3_STATIC);
628
629 /* Make sure all the indices are constructed correctly.
630 */
631 sqliteCodeVerifySchema(pParse, i);
632 for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){
633 Table *pTab = sqliteHashData(x);
634 Index *pIdx;
635 int loopTop;
636
637 if( pTab->pIndex==0 ) continue;
638 sqliteVdbeAddOp(v, OP_Integer, i, 0);
639 sqliteVdbeOp3(v, OP_OpenRead, 1, pTab->tnum, pTab->zName, 0);
640 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
641 if( pIdx->tnum==0 ) continue;
642 sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
643 sqliteVdbeOp3(v, OP_OpenRead, j+2, pIdx->tnum, pIdx->zName, 0);
644 }
645 sqliteVdbeAddOp(v, OP_Integer, 0, 0);
646 sqliteVdbeAddOp(v, OP_MemStore, 1, 1);
647 loopTop = sqliteVdbeAddOp(v, OP_Rewind, 1, 0);
648 sqliteVdbeAddOp(v, OP_MemIncr, 1, 0);
649 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
650 int k, jmp2;
651 static VdbeOpList idxErr[] = {
652 { OP_MemIncr, 0, 0, 0},
653 { OP_String, 0, 0, "rowid "},
654 { OP_Recno, 1, 0, 0},
655 { OP_String, 0, 0, " missing from index "},
656 { OP_String, 0, 0, 0}, /* 4 */
657 { OP_Concat, 4, 0, 0},
658 { OP_Callback, 1, 0, 0},
659 };
660 sqliteVdbeAddOp(v, OP_Recno, 1, 0);
661 for(k=0; k<pIdx->nColumn; k++){
662 int idx = pIdx->aiColumn[k];
663 if( idx==pTab->iPKey ){
664 sqliteVdbeAddOp(v, OP_Recno, 1, 0);
665 }else{
666 sqliteVdbeAddOp(v, OP_Column, 1, idx);
667 }
668 }
669 sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
670 if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
671 jmp2 = sqliteVdbeAddOp(v, OP_Found, j+2, 0);
672 addr = sqliteVdbeAddOpList(v, ArraySize(idxErr), idxErr);
673 sqliteVdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
674 sqliteVdbeChangeP2(v, jmp2, sqliteVdbeCurrentAddr(v));
675 }
676 sqliteVdbeAddOp(v, OP_Next, 1, loopTop+1);
677 sqliteVdbeChangeP2(v, loopTop, sqliteVdbeCurrentAddr(v));
678 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
679 static VdbeOpList cntIdx[] = {
680 { OP_Integer, 0, 0, 0},
681 { OP_MemStore, 2, 1, 0},
682 { OP_Rewind, 0, 0, 0}, /* 2 */
683 { OP_MemIncr, 2, 0, 0},
684 { OP_Next, 0, 0, 0}, /* 4 */
685 { OP_MemLoad, 1, 0, 0},
686 { OP_MemLoad, 2, 0, 0},
687 { OP_Eq, 0, 0, 0}, /* 7 */
688 { OP_MemIncr, 0, 0, 0},
689 { OP_String, 0, 0, "wrong # of entries in index "},
690 { OP_String, 0, 0, 0}, /* 10 */
691 { OP_Concat, 2, 0, 0},
692 { OP_Callback, 1, 0, 0},
693 };
694 if( pIdx->tnum==0 ) continue;
695 addr = sqliteVdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
696 sqliteVdbeChangeP1(v, addr+2, j+2);
697 sqliteVdbeChangeP2(v, addr+2, addr+5);
698 sqliteVdbeChangeP1(v, addr+4, j+2);
699 sqliteVdbeChangeP2(v, addr+4, addr+3);
700 sqliteVdbeChangeP2(v, addr+7, addr+ArraySize(cntIdx));
701 sqliteVdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC);
702 }
703 }
704 }
705 addr = sqliteVdbeAddOpList(v, ArraySize(endCode), endCode);
706 sqliteVdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
707 }else
708
709 {}
710 sqliteFree(zLeft);
711 sqliteFree(zRight);
712}
Note: See TracBrowser for help on using the repository browser.