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$
15 */
16 #include "sqliteInt.h"
17 #include <ctype.h>
18
19 /*
20 ** Interpret the given string as a boolean value.
21 */
getBoolean(const char * z)22 static 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 */
getSafetyLevel(char * z)45 static 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 */
getTempStore(const char * z)74 static 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 */
changeTempStorage(Parse * pParse,const char * zStorageType)91 static 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 */
flagPragma(Parse * pParse,const char * zLeft,const char * zRight)114 static 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 */
sqlitePragma(Parse * pParse,Token * pLeft,Token * pRight,int minusFlag)159 void 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 }
713