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