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 195361 2005-09-07 15:11:33Z iliaa $
15 : */
16 : #include "sqliteInt.h"
17 : #include <ctype.h>
18 :
19 : /*
20 : ** Interpret the given string as a boolean value.
21 : */
22 4 : static int getBoolean(const char *z){
23 : static char *azTrue[] = { "yes", "on", "true" };
24 : int i;
25 4 : if( z[0]==0 ) return 0;
26 4 : if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
27 0 : return atoi(z);
28 : }
29 12 : for(i=0; i<sizeof(azTrue)/sizeof(azTrue[0]); i++){
30 10 : if( sqliteStrICmp(z,azTrue[i])==0 ) return 1;
31 : }
32 2 : 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 : */
45 0 : 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 0 : if( z[0]==0 ) return 1;
60 0 : if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
61 0 : return atoi(z);
62 : }
63 0 : for(i=0; i<sizeof(aKey)/sizeof(aKey[0]); i++){
64 0 : if( sqliteStrICmp(z,aKey[i].zWord)==0 ) return aKey[i].val;
65 : }
66 0 : 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 : */
74 0 : static int getTempStore(const char *z){
75 0 : if( z[0]>='0' && z[0]<='2' ){
76 0 : return z[0] - '0';
77 0 : }else if( sqliteStrICmp(z, "file")==0 ){
78 0 : return 1;
79 0 : }else if( sqliteStrICmp(z, "memory")==0 ){
80 0 : return 2;
81 : }else{
82 0 : 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 : */
91 0 : static int changeTempStorage(Parse *pParse, const char *zStorageType){
92 0 : int ts = getTempStore(zStorageType);
93 0 : sqlite *db = pParse->db;
94 0 : if( db->temp_store==ts ) return SQLITE_OK;
95 0 : if( db->aDb[1].pBt!=0 ){
96 0 : if( db->flags & SQLITE_InTrans ){
97 0 : sqliteErrorMsg(pParse, "temporary storage cannot be changed "
98 : "from within a transaction");
99 0 : return SQLITE_ERROR;
100 : }
101 0 : sqliteBtreeClose(db->aDb[1].pBt);
102 0 : db->aDb[1].pBt = 0;
103 0 : sqliteResetInternalSchema(db, 0);
104 : }
105 0 : db->temp_store = ts;
106 0 : 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 : */
114 4 : 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 16 : for(i=0; i<sizeof(aPragma)/sizeof(aPragma[0]); i++){
128 16 : if( sqliteStrICmp(zLeft, aPragma[i].zName)==0 ){
129 4 : sqlite *db = pParse->db;
130 : Vdbe *v;
131 4 : if( strcmp(zLeft,zRight)==0 && (v = sqliteGetVdbe(pParse))!=0 ){
132 0 : sqliteVdbeOp3(v, OP_ColumnName, 0, 1, aPragma[i].zName, P3_STATIC);
133 0 : sqliteVdbeOp3(v, OP_ColumnName, 1, 0, "boolean", P3_STATIC);
134 0 : sqliteVdbeCode(v, OP_Integer, (db->flags & aPragma[i].mask)!=0, 0,
135 : OP_Callback, 1, 0,
136 : 0);
137 4 : }else if( getBoolean(zRight) ){
138 2 : db->flags |= aPragma[i].mask;
139 : }else{
140 2 : db->flags &= ~aPragma[i].mask;
141 : }
142 4 : return 1;
143 : }
144 : }
145 0 : 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 : */
159 4 : void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
160 4 : char *zLeft = 0;
161 4 : char *zRight = 0;
162 4 : sqlite *db = pParse->db;
163 4 : Vdbe *v = sqliteGetVdbe(pParse);
164 4 : if( v==0 ) return;
165 :
166 4 : zLeft = sqliteStrNDup(pLeft->z, pLeft->n);
167 4 : sqliteDequote(zLeft);
168 4 : if( minusFlag ){
169 0 : zRight = 0;
170 0 : sqliteSetNString(&zRight, "-", 1, pRight->z, pRight->n, 0);
171 : }else{
172 4 : zRight = sqliteStrNDup(pRight->z, pRight->n);
173 4 : sqliteDequote(zRight);
174 : }
175 4 : if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, 0) ){
176 0 : sqliteFree(zLeft);
177 0 : sqliteFree(zRight);
178 0 : 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 4 : 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 0 : if( pRight->z==pLeft->z ){
210 0 : addr = sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
211 0 : sqliteVdbeChangeP1(v, addr+5, MAX_PAGES);
212 : }else{
213 0 : int size = atoi(zRight);
214 0 : if( size<0 ) size = -size;
215 0 : sqliteBeginWriteOperation(pParse, 0, 0);
216 0 : sqliteVdbeAddOp(v, OP_Integer, size, 0);
217 0 : sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
218 0 : addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
219 0 : sqliteVdbeAddOp(v, OP_Ge, 0, addr+3);
220 0 : sqliteVdbeAddOp(v, OP_Negative, 0, 0);
221 0 : sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
222 0 : sqliteEndWriteOperation(pParse);
223 0 : db->cache_size = db->cache_size<0 ? -size : size;
224 0 : 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 4 : 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 0 : if( pRight->z==pLeft->z ){
248 0 : int size = db->cache_size;;
249 0 : if( size<0 ) size = -size;
250 0 : sqliteVdbeAddOp(v, OP_Integer, size, 0);
251 0 : sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
252 : }else{
253 0 : int size = atoi(zRight);
254 0 : if( size<0 ) size = -size;
255 0 : if( db->cache_size<0 ) size = -size;
256 0 : db->cache_size = size;
257 0 : 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 4 : 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 0 : if( pRight->z==pLeft->z ){
296 0 : int addr = sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
297 0 : sqliteVdbeChangeP2(v, addr+3, addr+10);
298 : }else{
299 : int addr;
300 0 : int size = db->cache_size;
301 0 : if( size<0 ) size = -size;
302 0 : sqliteBeginWriteOperation(pParse, 0, 0);
303 0 : sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
304 0 : sqliteVdbeAddOp(v, OP_Dup, 0, 0);
305 0 : addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
306 0 : sqliteVdbeAddOp(v, OP_Ne, 0, addr+3);
307 0 : sqliteVdbeAddOp(v, OP_AddImm, MAX_PAGES, 0);
308 0 : sqliteVdbeAddOp(v, OP_AbsValue, 0, 0);
309 0 : db->safety_level = getSafetyLevel(zRight)+1;
310 0 : if( db->safety_level==1 ){
311 0 : sqliteVdbeAddOp(v, OP_Negative, 0, 0);
312 0 : size = -size;
313 : }
314 0 : sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
315 0 : sqliteVdbeAddOp(v, OP_Integer, db->safety_level, 0);
316 0 : sqliteVdbeAddOp(v, OP_SetCookie, 0, 3);
317 0 : sqliteEndWriteOperation(pParse);
318 0 : db->cache_size = size;
319 0 : sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
320 0 : 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 4 : if( sqliteStrICmp(zLeft,"synchronous")==0 ){
334 : static VdbeOpList getSync[] = {
335 : { OP_ColumnName, 0, 1, "synchronous"},
336 : { OP_Callback, 1, 0, 0},
337 : };
338 0 : if( pRight->z==pLeft->z ){
339 0 : sqliteVdbeAddOp(v, OP_Integer, db->safety_level-1, 0);
340 0 : sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
341 : }else{
342 0 : int size = db->cache_size;
343 0 : if( size<0 ) size = -size;
344 0 : db->safety_level = getSafetyLevel(zRight)+1;
345 0 : if( db->safety_level==1 ) size = -size;
346 0 : db->cache_size = size;
347 0 : sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
348 0 : 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 4 : if( flagPragma(pParse, zLeft, zRight) ){
363 : /* The flagPragma() call also generates any necessary code */
364 : }else
365 :
366 0 : if( sqliteStrICmp(zLeft, "table_info")==0 ){
367 : Table *pTab;
368 0 : pTab = sqliteFindTable(db, zRight, 0);
369 0 : 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 0 : sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
380 0 : sqliteViewGetColumnNames(pParse, pTab);
381 0 : for(i=0; i<pTab->nCol; i++){
382 0 : sqliteVdbeAddOp(v, OP_Integer, i, 0);
383 0 : sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zName, 0);
384 0 : sqliteVdbeOp3(v, OP_String, 0, 0,
385 : pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", 0);
386 0 : sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0);
387 0 : sqliteVdbeOp3(v, OP_String, 0, 0,
388 : pTab->aCol[i].zDflt, P3_STATIC);
389 0 : sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0);
390 0 : sqliteVdbeAddOp(v, OP_Callback, 6, 0);
391 : }
392 : }
393 : }else
394 :
395 0 : if( sqliteStrICmp(zLeft, "index_info")==0 ){
396 : Index *pIdx;
397 : Table *pTab;
398 0 : pIdx = sqliteFindIndex(db, zRight, 0);
399 0 : 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 0 : pTab = pIdx->pTable;
407 0 : sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
408 0 : for(i=0; i<pIdx->nColumn; i++){
409 0 : int cnum = pIdx->aiColumn[i];
410 0 : sqliteVdbeAddOp(v, OP_Integer, i, 0);
411 0 : sqliteVdbeAddOp(v, OP_Integer, cnum, 0);
412 : assert( pTab->nCol>cnum );
413 0 : sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[cnum].zName, 0);
414 0 : sqliteVdbeAddOp(v, OP_Callback, 3, 0);
415 : }
416 : }
417 : }else
418 :
419 0 : if( sqliteStrICmp(zLeft, "index_list")==0 ){
420 : Index *pIdx;
421 : Table *pTab;
422 0 : pTab = sqliteFindTable(db, zRight, 0);
423 0 : if( pTab ){
424 0 : v = sqliteGetVdbe(pParse);
425 0 : pIdx = pTab->pIndex;
426 : }
427 0 : if( pTab && pIdx ){
428 0 : 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 0 : sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
436 0 : while(pIdx){
437 0 : sqliteVdbeAddOp(v, OP_Integer, i, 0);
438 0 : sqliteVdbeOp3(v, OP_String, 0, 0, pIdx->zName, 0);
439 0 : sqliteVdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0);
440 0 : sqliteVdbeAddOp(v, OP_Callback, 3, 0);
441 0 : ++i;
442 0 : pIdx = pIdx->pNext;
443 : }
444 : }
445 : }else
446 :
447 0 : if( sqliteStrICmp(zLeft, "foreign_key_list")==0 ){
448 : FKey *pFK;
449 : Table *pTab;
450 0 : pTab = sqliteFindTable(db, zRight, 0);
451 0 : if( pTab ){
452 0 : v = sqliteGetVdbe(pParse);
453 0 : pFK = pTab->pFKey;
454 : }
455 0 : if( pTab && pFK ){
456 0 : 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 0 : sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
466 0 : while(pFK){
467 : int j;
468 0 : for(j=0; j<pFK->nCol; j++){
469 0 : sqliteVdbeAddOp(v, OP_Integer, i, 0);
470 0 : sqliteVdbeAddOp(v, OP_Integer, j, 0);
471 0 : sqliteVdbeOp3(v, OP_String, 0, 0, pFK->zTo, 0);
472 0 : sqliteVdbeOp3(v, OP_String, 0, 0,
473 : pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
474 0 : sqliteVdbeOp3(v, OP_String, 0, 0, pFK->aCol[j].zCol, 0);
475 0 : sqliteVdbeAddOp(v, OP_Callback, 5, 0);
476 : }
477 0 : ++i;
478 0 : pFK = pFK->pNextFrom;
479 : }
480 : }
481 : }else
482 :
483 0 : 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 0 : sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
492 0 : for(i=0; i<db->nDb; i++){
493 0 : if( db->aDb[i].pBt==0 ) continue;
494 : assert( db->aDb[i].zName!=0 );
495 0 : sqliteVdbeAddOp(v, OP_Integer, i, 0);
496 0 : sqliteVdbeOp3(v, OP_String, 0, 0, db->aDb[i].zName, 0);
497 0 : sqliteVdbeOp3(v, OP_String, 0, 0,
498 : sqliteBtreeGetFilename(db->aDb[i].pBt), 0);
499 0 : 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 0 : 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 0 : if( pRight->z==pLeft->z ){
521 0 : sqliteVdbeAddOp(v, OP_Integer, db->temp_store, 0);
522 0 : sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc);
523 : }else{
524 0 : 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 0 : 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 0 : if( pRight->z==pLeft->z ){
545 0 : sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc);
546 : }else{
547 0 : sqliteBeginWriteOperation(pParse, 0, 0);
548 0 : sqliteVdbeAddOp(v, OP_Integer, getTempStore(zRight), 0);
549 0 : sqliteVdbeAddOp(v, OP_SetCookie, 0, 5);
550 0 : 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 0 : 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 0 : sqliteVdbeAddOpList(v, ArraySize(initCode), initCode);
614 :
615 : /* Do an integrity check on each database file */
616 0 : for(i=0; i<db->nDb; i++){
617 : HashElem *x;
618 :
619 : /* Do an integrity check of the B-Tree
620 : */
621 0 : addr = sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb);
622 0 : sqliteVdbeChangeP1(v, addr+1, i);
623 0 : sqliteVdbeChangeP2(v, addr+3, addr+7);
624 0 : sqliteVdbeChangeP2(v, addr+6, addr+4);
625 0 : sqliteVdbeChangeP2(v, addr+7, i);
626 0 : sqliteVdbeChangeP2(v, addr+10, addr+ArraySize(checkDb));
627 0 : sqliteVdbeChangeP3(v, addr+13, db->aDb[i].zName, P3_STATIC);
628 :
629 : /* Make sure all the indices are constructed correctly.
630 : */
631 0 : sqliteCodeVerifySchema(pParse, i);
632 0 : for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){
633 0 : Table *pTab = sqliteHashData(x);
634 : Index *pIdx;
635 : int loopTop;
636 :
637 0 : if( pTab->pIndex==0 ) continue;
638 0 : sqliteVdbeAddOp(v, OP_Integer, i, 0);
639 0 : sqliteVdbeOp3(v, OP_OpenRead, 1, pTab->tnum, pTab->zName, 0);
640 0 : for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
641 0 : if( pIdx->tnum==0 ) continue;
642 0 : sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
643 0 : sqliteVdbeOp3(v, OP_OpenRead, j+2, pIdx->tnum, pIdx->zName, 0);
644 : }
645 0 : sqliteVdbeAddOp(v, OP_Integer, 0, 0);
646 0 : sqliteVdbeAddOp(v, OP_MemStore, 1, 1);
647 0 : loopTop = sqliteVdbeAddOp(v, OP_Rewind, 1, 0);
648 0 : sqliteVdbeAddOp(v, OP_MemIncr, 1, 0);
649 0 : 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 0 : sqliteVdbeAddOp(v, OP_Recno, 1, 0);
661 0 : for(k=0; k<pIdx->nColumn; k++){
662 0 : int idx = pIdx->aiColumn[k];
663 0 : if( idx==pTab->iPKey ){
664 0 : sqliteVdbeAddOp(v, OP_Recno, 1, 0);
665 : }else{
666 0 : sqliteVdbeAddOp(v, OP_Column, 1, idx);
667 : }
668 : }
669 0 : sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
670 0 : if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
671 0 : jmp2 = sqliteVdbeAddOp(v, OP_Found, j+2, 0);
672 0 : addr = sqliteVdbeAddOpList(v, ArraySize(idxErr), idxErr);
673 0 : sqliteVdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
674 0 : sqliteVdbeChangeP2(v, jmp2, sqliteVdbeCurrentAddr(v));
675 : }
676 0 : sqliteVdbeAddOp(v, OP_Next, 1, loopTop+1);
677 0 : sqliteVdbeChangeP2(v, loopTop, sqliteVdbeCurrentAddr(v));
678 0 : 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 0 : if( pIdx->tnum==0 ) continue;
695 0 : addr = sqliteVdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
696 0 : sqliteVdbeChangeP1(v, addr+2, j+2);
697 0 : sqliteVdbeChangeP2(v, addr+2, addr+5);
698 0 : sqliteVdbeChangeP1(v, addr+4, j+2);
699 0 : sqliteVdbeChangeP2(v, addr+4, addr+3);
700 0 : sqliteVdbeChangeP2(v, addr+7, addr+ArraySize(cntIdx));
701 0 : sqliteVdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC);
702 : }
703 : }
704 : }
705 0 : addr = sqliteVdbeAddOpList(v, ArraySize(endCode), endCode);
706 0 : sqliteVdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
707 : }else
708 :
709 : {}
710 4 : sqliteFree(zLeft);
711 4 : sqliteFree(zRight);
712 : }
|