00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "sqliteInt.h"
00017 #include <ctype.h>
00018
00019
00020
00021
00022 static int getBoolean(const char *z){
00023 static char *azTrue[] = { "yes", "on", "true" };
00024 int i;
00025 if( z[0]==0 ) return 0;
00026 if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
00027 return atoi(z);
00028 }
00029 for(i=0; i<sizeof(azTrue)/sizeof(azTrue[0]); i++){
00030 if( sqliteStrICmp(z,azTrue[i])==0 ) return 1;
00031 }
00032 return 0;
00033 }
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 static int getSafetyLevel(char *z){
00046 static const struct {
00047 const char *zWord;
00048 int val;
00049 } aKey[] = {
00050 { "no", 0 },
00051 { "off", 0 },
00052 { "false", 0 },
00053 { "yes", 1 },
00054 { "on", 1 },
00055 { "true", 1 },
00056 { "full", 2 },
00057 };
00058 int i;
00059 if( z[0]==0 ) return 1;
00060 if( isdigit(z[0]) || (z[0]=='-' && isdigit(z[1])) ){
00061 return atoi(z);
00062 }
00063 for(i=0; i<sizeof(aKey)/sizeof(aKey[0]); i++){
00064 if( sqliteStrICmp(z,aKey[i].zWord)==0 ) return aKey[i].val;
00065 }
00066 return 1;
00067 }
00068
00069
00070
00071
00072
00073
00074 static int getTempStore(const char *z){
00075 if( z[0]>='0' && z[0]<='2' ){
00076 return z[0] - '0';
00077 }else if( sqliteStrICmp(z, "file")==0 ){
00078 return 1;
00079 }else if( sqliteStrICmp(z, "memory")==0 ){
00080 return 2;
00081 }else{
00082 return 0;
00083 }
00084 }
00085
00086
00087
00088
00089
00090
00091 static int changeTempStorage(Parse *pParse, const char *zStorageType){
00092 int ts = getTempStore(zStorageType);
00093 sqlite *db = pParse->db;
00094 if( db->temp_store==ts ) return SQLITE_OK;
00095 if( db->aDb[1].pBt!=0 ){
00096 if( db->flags & SQLITE_InTrans ){
00097 sqliteErrorMsg(pParse, "temporary storage cannot be changed "
00098 "from within a transaction");
00099 return SQLITE_ERROR;
00100 }
00101 sqliteBtreeClose(db->aDb[1].pBt);
00102 db->aDb[1].pBt = 0;
00103 sqliteResetInternalSchema(db, 0);
00104 }
00105 db->temp_store = ts;
00106 return SQLITE_OK;
00107 }
00108
00109
00110
00111
00112
00113
00114 static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
00115 static const struct {
00116 const char *zName;
00117 int mask;
00118 } aPragma[] = {
00119 { "vdbe_trace", SQLITE_VdbeTrace },
00120 { "full_column_names", SQLITE_FullColNames },
00121 { "short_column_names", SQLITE_ShortColNames },
00122 { "show_datatypes", SQLITE_ReportTypes },
00123 { "count_changes", SQLITE_CountRows },
00124 { "empty_result_callbacks", SQLITE_NullCallback },
00125 };
00126 int i;
00127 for(i=0; i<sizeof(aPragma)/sizeof(aPragma[0]); i++){
00128 if( sqliteStrICmp(zLeft, aPragma[i].zName)==0 ){
00129 sqlite *db = pParse->db;
00130 Vdbe *v;
00131 if( strcmp(zLeft,zRight)==0 && (v = sqliteGetVdbe(pParse))!=0 ){
00132 sqliteVdbeOp3(v, OP_ColumnName, 0, 1, aPragma[i].zName, P3_STATIC);
00133 sqliteVdbeOp3(v, OP_ColumnName, 1, 0, "boolean", P3_STATIC);
00134 sqliteVdbeCode(v, OP_Integer, (db->flags & aPragma[i].mask)!=0, 0,
00135 OP_Callback, 1, 0,
00136 0);
00137 }else if( getBoolean(zRight) ){
00138 db->flags |= aPragma[i].mask;
00139 }else{
00140 db->flags &= ~aPragma[i].mask;
00141 }
00142 return 1;
00143 }
00144 }
00145 return 0;
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){
00160 char *zLeft = 0;
00161 char *zRight = 0;
00162 sqlite *db = pParse->db;
00163 Vdbe *v = sqliteGetVdbe(pParse);
00164 if( v==0 ) return;
00165
00166 zLeft = sqliteStrNDup(pLeft->z, pLeft->n);
00167 sqliteDequote(zLeft);
00168 if( minusFlag ){
00169 zRight = 0;
00170 sqliteSetNString(&zRight, "-", 1, pRight->z, pRight->n, 0);
00171 }else{
00172 zRight = sqliteStrNDup(pRight->z, pRight->n);
00173 sqliteDequote(zRight);
00174 }
00175 if( sqliteAuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, 0) ){
00176 sqliteFree(zLeft);
00177 sqliteFree(zRight);
00178 return;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 if( sqliteStrICmp(zLeft,"default_cache_size")==0 ){
00198 static VdbeOpList getCacheSize[] = {
00199 { OP_ReadCookie, 0, 2, 0},
00200 { OP_AbsValue, 0, 0, 0},
00201 { OP_Dup, 0, 0, 0},
00202 { OP_Integer, 0, 0, 0},
00203 { OP_Ne, 0, 6, 0},
00204 { OP_Integer, 0, 0, 0},
00205 { OP_ColumnName, 0, 1, "cache_size"},
00206 { OP_Callback, 1, 0, 0},
00207 };
00208 int addr;
00209 if( pRight->z==pLeft->z ){
00210 addr = sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
00211 sqliteVdbeChangeP1(v, addr+5, MAX_PAGES);
00212 }else{
00213 int size = atoi(zRight);
00214 if( size<0 ) size = -size;
00215 sqliteBeginWriteOperation(pParse, 0, 0);
00216 sqliteVdbeAddOp(v, OP_Integer, size, 0);
00217 sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
00218 addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
00219 sqliteVdbeAddOp(v, OP_Ge, 0, addr+3);
00220 sqliteVdbeAddOp(v, OP_Negative, 0, 0);
00221 sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
00222 sqliteEndWriteOperation(pParse);
00223 db->cache_size = db->cache_size<0 ? -size : size;
00224 sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
00225 }
00226 }else
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 if( sqliteStrICmp(zLeft,"cache_size")==0 ){
00243 static VdbeOpList getCacheSize[] = {
00244 { OP_ColumnName, 0, 1, "cache_size"},
00245 { OP_Callback, 1, 0, 0},
00246 };
00247 if( pRight->z==pLeft->z ){
00248 int size = db->cache_size;;
00249 if( size<0 ) size = -size;
00250 sqliteVdbeAddOp(v, OP_Integer, size, 0);
00251 sqliteVdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize);
00252 }else{
00253 int size = atoi(zRight);
00254 if( size<0 ) size = -size;
00255 if( db->cache_size<0 ) size = -size;
00256 db->cache_size = size;
00257 sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
00258 }
00259 }else
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 if( sqliteStrICmp(zLeft,"default_synchronous")==0 ){
00281 static VdbeOpList getSync[] = {
00282 { OP_ColumnName, 0, 1, "synchronous"},
00283 { OP_ReadCookie, 0, 3, 0},
00284 { OP_Dup, 0, 0, 0},
00285 { OP_If, 0, 0, 0},
00286 { OP_ReadCookie, 0, 2, 0},
00287 { OP_Integer, 0, 0, 0},
00288 { OP_Lt, 0, 5, 0},
00289 { OP_AddImm, 1, 0, 0},
00290 { OP_Callback, 1, 0, 0},
00291 { OP_Halt, 0, 0, 0},
00292 { OP_AddImm, -1, 0, 0},
00293 { OP_Callback, 1, 0, 0}
00294 };
00295 if( pRight->z==pLeft->z ){
00296 int addr = sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
00297 sqliteVdbeChangeP2(v, addr+3, addr+10);
00298 }else{
00299 int addr;
00300 int size = db->cache_size;
00301 if( size<0 ) size = -size;
00302 sqliteBeginWriteOperation(pParse, 0, 0);
00303 sqliteVdbeAddOp(v, OP_ReadCookie, 0, 2);
00304 sqliteVdbeAddOp(v, OP_Dup, 0, 0);
00305 addr = sqliteVdbeAddOp(v, OP_Integer, 0, 0);
00306 sqliteVdbeAddOp(v, OP_Ne, 0, addr+3);
00307 sqliteVdbeAddOp(v, OP_AddImm, MAX_PAGES, 0);
00308 sqliteVdbeAddOp(v, OP_AbsValue, 0, 0);
00309 db->safety_level = getSafetyLevel(zRight)+1;
00310 if( db->safety_level==1 ){
00311 sqliteVdbeAddOp(v, OP_Negative, 0, 0);
00312 size = -size;
00313 }
00314 sqliteVdbeAddOp(v, OP_SetCookie, 0, 2);
00315 sqliteVdbeAddOp(v, OP_Integer, db->safety_level, 0);
00316 sqliteVdbeAddOp(v, OP_SetCookie, 0, 3);
00317 sqliteEndWriteOperation(pParse);
00318 db->cache_size = size;
00319 sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
00320 sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
00321 }
00322 }else
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 if( sqliteStrICmp(zLeft,"synchronous")==0 ){
00334 static VdbeOpList getSync[] = {
00335 { OP_ColumnName, 0, 1, "synchronous"},
00336 { OP_Callback, 1, 0, 0},
00337 };
00338 if( pRight->z==pLeft->z ){
00339 sqliteVdbeAddOp(v, OP_Integer, db->safety_level-1, 0);
00340 sqliteVdbeAddOpList(v, ArraySize(getSync), getSync);
00341 }else{
00342 int size = db->cache_size;
00343 if( size<0 ) size = -size;
00344 db->safety_level = getSafetyLevel(zRight)+1;
00345 if( db->safety_level==1 ) size = -size;
00346 db->cache_size = size;
00347 sqliteBtreeSetCacheSize(db->aDb[0].pBt, db->cache_size);
00348 sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);
00349 }
00350 }else
00351
00352 #ifndef NDEBUG
00353 if( sqliteStrICmp(zLeft, "trigger_overhead_test")==0 ){
00354 if( getBoolean(zRight) ){
00355 always_code_trigger_setup = 1;
00356 }else{
00357 always_code_trigger_setup = 0;
00358 }
00359 }else
00360 #endif
00361
00362 if( flagPragma(pParse, zLeft, zRight) ){
00363
00364 }else
00365
00366 if( sqliteStrICmp(zLeft, "table_info")==0 ){
00367 Table *pTab;
00368 pTab = sqliteFindTable(db, zRight, 0);
00369 if( pTab ){
00370 static VdbeOpList tableInfoPreface[] = {
00371 { OP_ColumnName, 0, 0, "cid"},
00372 { OP_ColumnName, 1, 0, "name"},
00373 { OP_ColumnName, 2, 0, "type"},
00374 { OP_ColumnName, 3, 0, "notnull"},
00375 { OP_ColumnName, 4, 0, "dflt_value"},
00376 { OP_ColumnName, 5, 1, "pk"},
00377 };
00378 int i;
00379 sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
00380 sqliteViewGetColumnNames(pParse, pTab);
00381 for(i=0; i<pTab->nCol; i++){
00382 sqliteVdbeAddOp(v, OP_Integer, i, 0);
00383 sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[i].zName, 0);
00384 sqliteVdbeOp3(v, OP_String, 0, 0,
00385 pTab->aCol[i].zType ? pTab->aCol[i].zType : "numeric", 0);
00386 sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].notNull, 0);
00387 sqliteVdbeOp3(v, OP_String, 0, 0,
00388 pTab->aCol[i].zDflt, P3_STATIC);
00389 sqliteVdbeAddOp(v, OP_Integer, pTab->aCol[i].isPrimKey, 0);
00390 sqliteVdbeAddOp(v, OP_Callback, 6, 0);
00391 }
00392 }
00393 }else
00394
00395 if( sqliteStrICmp(zLeft, "index_info")==0 ){
00396 Index *pIdx;
00397 Table *pTab;
00398 pIdx = sqliteFindIndex(db, zRight, 0);
00399 if( pIdx ){
00400 static VdbeOpList tableInfoPreface[] = {
00401 { OP_ColumnName, 0, 0, "seqno"},
00402 { OP_ColumnName, 1, 0, "cid"},
00403 { OP_ColumnName, 2, 1, "name"},
00404 };
00405 int i;
00406 pTab = pIdx->pTable;
00407 sqliteVdbeAddOpList(v, ArraySize(tableInfoPreface), tableInfoPreface);
00408 for(i=0; i<pIdx->nColumn; i++){
00409 int cnum = pIdx->aiColumn[i];
00410 sqliteVdbeAddOp(v, OP_Integer, i, 0);
00411 sqliteVdbeAddOp(v, OP_Integer, cnum, 0);
00412 assert( pTab->nCol>cnum );
00413 sqliteVdbeOp3(v, OP_String, 0, 0, pTab->aCol[cnum].zName, 0);
00414 sqliteVdbeAddOp(v, OP_Callback, 3, 0);
00415 }
00416 }
00417 }else
00418
00419 if( sqliteStrICmp(zLeft, "index_list")==0 ){
00420 Index *pIdx;
00421 Table *pTab;
00422 pTab = sqliteFindTable(db, zRight, 0);
00423 if( pTab ){
00424 v = sqliteGetVdbe(pParse);
00425 pIdx = pTab->pIndex;
00426 }
00427 if( pTab && pIdx ){
00428 int i = 0;
00429 static VdbeOpList indexListPreface[] = {
00430 { OP_ColumnName, 0, 0, "seq"},
00431 { OP_ColumnName, 1, 0, "name"},
00432 { OP_ColumnName, 2, 1, "unique"},
00433 };
00434
00435 sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
00436 while(pIdx){
00437 sqliteVdbeAddOp(v, OP_Integer, i, 0);
00438 sqliteVdbeOp3(v, OP_String, 0, 0, pIdx->zName, 0);
00439 sqliteVdbeAddOp(v, OP_Integer, pIdx->onError!=OE_None, 0);
00440 sqliteVdbeAddOp(v, OP_Callback, 3, 0);
00441 ++i;
00442 pIdx = pIdx->pNext;
00443 }
00444 }
00445 }else
00446
00447 if( sqliteStrICmp(zLeft, "foreign_key_list")==0 ){
00448 FKey *pFK;
00449 Table *pTab;
00450 pTab = sqliteFindTable(db, zRight, 0);
00451 if( pTab ){
00452 v = sqliteGetVdbe(pParse);
00453 pFK = pTab->pFKey;
00454 }
00455 if( pTab && pFK ){
00456 int i = 0;
00457 static VdbeOpList indexListPreface[] = {
00458 { OP_ColumnName, 0, 0, "id"},
00459 { OP_ColumnName, 1, 0, "seq"},
00460 { OP_ColumnName, 2, 0, "table"},
00461 { OP_ColumnName, 3, 0, "from"},
00462 { OP_ColumnName, 4, 1, "to"},
00463 };
00464
00465 sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
00466 while(pFK){
00467 int j;
00468 for(j=0; j<pFK->nCol; j++){
00469 sqliteVdbeAddOp(v, OP_Integer, i, 0);
00470 sqliteVdbeAddOp(v, OP_Integer, j, 0);
00471 sqliteVdbeOp3(v, OP_String, 0, 0, pFK->zTo, 0);
00472 sqliteVdbeOp3(v, OP_String, 0, 0,
00473 pTab->aCol[pFK->aCol[j].iFrom].zName, 0);
00474 sqliteVdbeOp3(v, OP_String, 0, 0, pFK->aCol[j].zCol, 0);
00475 sqliteVdbeAddOp(v, OP_Callback, 5, 0);
00476 }
00477 ++i;
00478 pFK = pFK->pNextFrom;
00479 }
00480 }
00481 }else
00482
00483 if( sqliteStrICmp(zLeft, "database_list")==0 ){
00484 int i;
00485 static VdbeOpList indexListPreface[] = {
00486 { OP_ColumnName, 0, 0, "seq"},
00487 { OP_ColumnName, 1, 0, "name"},
00488 { OP_ColumnName, 2, 1, "file"},
00489 };
00490
00491 sqliteVdbeAddOpList(v, ArraySize(indexListPreface), indexListPreface);
00492 for(i=0; i<db->nDb; i++){
00493 if( db->aDb[i].pBt==0 ) continue;
00494 assert( db->aDb[i].zName!=0 );
00495 sqliteVdbeAddOp(v, OP_Integer, i, 0);
00496 sqliteVdbeOp3(v, OP_String, 0, 0, db->aDb[i].zName, 0);
00497 sqliteVdbeOp3(v, OP_String, 0, 0,
00498 sqliteBtreeGetFilename(db->aDb[i].pBt), 0);
00499 sqliteVdbeAddOp(v, OP_Callback, 3, 0);
00500 }
00501 }else
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 if( sqliteStrICmp(zLeft, "temp_store")==0 ){
00516 static VdbeOpList getTmpDbLoc[] = {
00517 { OP_ColumnName, 0, 1, "temp_store"},
00518 { OP_Callback, 1, 0, 0},
00519 };
00520 if( pRight->z==pLeft->z ){
00521 sqliteVdbeAddOp(v, OP_Integer, db->temp_store, 0);
00522 sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc);
00523 }else{
00524 changeTempStorage(pParse, zRight);
00525 }
00526 }else
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 if( sqliteStrICmp(zLeft, "default_temp_store")==0 ){
00540 static VdbeOpList getTmpDbLoc[] = {
00541 { OP_ColumnName, 0, 1, "temp_store"},
00542 { OP_ReadCookie, 0, 5, 0},
00543 { OP_Callback, 1, 0, 0}};
00544 if( pRight->z==pLeft->z ){
00545 sqliteVdbeAddOpList(v, ArraySize(getTmpDbLoc), getTmpDbLoc);
00546 }else{
00547 sqliteBeginWriteOperation(pParse, 0, 0);
00548 sqliteVdbeAddOp(v, OP_Integer, getTempStore(zRight), 0);
00549 sqliteVdbeAddOp(v, OP_SetCookie, 0, 5);
00550 sqliteEndWriteOperation(pParse);
00551 }
00552 }else
00553
00554 #ifndef NDEBUG
00555 if( sqliteStrICmp(zLeft, "parser_trace")==0 ){
00556 extern void sqliteParserTrace(FILE*, char *);
00557 if( getBoolean(zRight) ){
00558 sqliteParserTrace(stdout, "parser: ");
00559 }else{
00560 sqliteParserTrace(0, 0);
00561 }
00562 }else
00563 #endif
00564
00565 if( sqliteStrICmp(zLeft, "integrity_check")==0 ){
00566 int i, j, addr;
00567
00568
00569
00570
00571 static VdbeOpList initCode[] = {
00572 { OP_Integer, 0, 0, 0},
00573 { OP_MemStore, 0, 1, 0},
00574 { OP_ColumnName, 0, 1, "integrity_check"},
00575 };
00576
00577
00578
00579 static VdbeOpList checkDb[] = {
00580 { OP_SetInsert, 0, 0, "2"},
00581 { OP_Integer, 0, 0, 0},
00582 { OP_OpenRead, 0, 2, 0},
00583 { OP_Rewind, 0, 7, 0},
00584 { OP_Column, 0, 3, 0},
00585 { OP_SetInsert, 0, 0, 0},
00586 { OP_Next, 0, 4, 0},
00587 { OP_IntegrityCk, 0, 0, 0},
00588 { OP_Dup, 0, 1, 0},
00589 { OP_String, 0, 0, "ok"},
00590 { OP_StrEq, 0, 12, 0},
00591 { OP_MemIncr, 0, 0, 0},
00592 { OP_String, 0, 0, "*** in database "},
00593 { OP_String, 0, 0, 0},
00594 { OP_String, 0, 0, " ***\n"},
00595 { OP_Pull, 3, 0, 0},
00596 { OP_Concat, 4, 1, 0},
00597 { OP_Callback, 1, 0, 0},
00598 };
00599
00600
00601
00602
00603
00604 static VdbeOpList endCode[] = {
00605 { OP_MemLoad, 0, 0, 0},
00606 { OP_Integer, 0, 0, 0},
00607 { OP_Ne, 0, 0, 0},
00608 { OP_String, 0, 0, "ok"},
00609 { OP_Callback, 1, 0, 0},
00610 };
00611
00612
00613 sqliteVdbeAddOpList(v, ArraySize(initCode), initCode);
00614
00615
00616 for(i=0; i<db->nDb; i++){
00617 HashElem *x;
00618
00619
00620
00621 addr = sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb);
00622 sqliteVdbeChangeP1(v, addr+1, i);
00623 sqliteVdbeChangeP2(v, addr+3, addr+7);
00624 sqliteVdbeChangeP2(v, addr+6, addr+4);
00625 sqliteVdbeChangeP2(v, addr+7, i);
00626 sqliteVdbeChangeP2(v, addr+10, addr+ArraySize(checkDb));
00627 sqliteVdbeChangeP3(v, addr+13, db->aDb[i].zName, P3_STATIC);
00628
00629
00630
00631 sqliteCodeVerifySchema(pParse, i);
00632 for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){
00633 Table *pTab = sqliteHashData(x);
00634 Index *pIdx;
00635 int loopTop;
00636
00637 if( pTab->pIndex==0 ) continue;
00638 sqliteVdbeAddOp(v, OP_Integer, i, 0);
00639 sqliteVdbeOp3(v, OP_OpenRead, 1, pTab->tnum, pTab->zName, 0);
00640 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
00641 if( pIdx->tnum==0 ) continue;
00642 sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
00643 sqliteVdbeOp3(v, OP_OpenRead, j+2, pIdx->tnum, pIdx->zName, 0);
00644 }
00645 sqliteVdbeAddOp(v, OP_Integer, 0, 0);
00646 sqliteVdbeAddOp(v, OP_MemStore, 1, 1);
00647 loopTop = sqliteVdbeAddOp(v, OP_Rewind, 1, 0);
00648 sqliteVdbeAddOp(v, OP_MemIncr, 1, 0);
00649 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
00650 int k, jmp2;
00651 static VdbeOpList idxErr[] = {
00652 { OP_MemIncr, 0, 0, 0},
00653 { OP_String, 0, 0, "rowid "},
00654 { OP_Recno, 1, 0, 0},
00655 { OP_String, 0, 0, " missing from index "},
00656 { OP_String, 0, 0, 0},
00657 { OP_Concat, 4, 0, 0},
00658 { OP_Callback, 1, 0, 0},
00659 };
00660 sqliteVdbeAddOp(v, OP_Recno, 1, 0);
00661 for(k=0; k<pIdx->nColumn; k++){
00662 int idx = pIdx->aiColumn[k];
00663 if( idx==pTab->iPKey ){
00664 sqliteVdbeAddOp(v, OP_Recno, 1, 0);
00665 }else{
00666 sqliteVdbeAddOp(v, OP_Column, 1, idx);
00667 }
00668 }
00669 sqliteVdbeAddOp(v, OP_MakeIdxKey, pIdx->nColumn, 0);
00670 if( db->file_format>=4 ) sqliteAddIdxKeyType(v, pIdx);
00671 jmp2 = sqliteVdbeAddOp(v, OP_Found, j+2, 0);
00672 addr = sqliteVdbeAddOpList(v, ArraySize(idxErr), idxErr);
00673 sqliteVdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC);
00674 sqliteVdbeChangeP2(v, jmp2, sqliteVdbeCurrentAddr(v));
00675 }
00676 sqliteVdbeAddOp(v, OP_Next, 1, loopTop+1);
00677 sqliteVdbeChangeP2(v, loopTop, sqliteVdbeCurrentAddr(v));
00678 for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
00679 static VdbeOpList cntIdx[] = {
00680 { OP_Integer, 0, 0, 0},
00681 { OP_MemStore, 2, 1, 0},
00682 { OP_Rewind, 0, 0, 0},
00683 { OP_MemIncr, 2, 0, 0},
00684 { OP_Next, 0, 0, 0},
00685 { OP_MemLoad, 1, 0, 0},
00686 { OP_MemLoad, 2, 0, 0},
00687 { OP_Eq, 0, 0, 0},
00688 { OP_MemIncr, 0, 0, 0},
00689 { OP_String, 0, 0, "wrong # of entries in index "},
00690 { OP_String, 0, 0, 0},
00691 { OP_Concat, 2, 0, 0},
00692 { OP_Callback, 1, 0, 0},
00693 };
00694 if( pIdx->tnum==0 ) continue;
00695 addr = sqliteVdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
00696 sqliteVdbeChangeP1(v, addr+2, j+2);
00697 sqliteVdbeChangeP2(v, addr+2, addr+5);
00698 sqliteVdbeChangeP1(v, addr+4, j+2);
00699 sqliteVdbeChangeP2(v, addr+4, addr+3);
00700 sqliteVdbeChangeP2(v, addr+7, addr+ArraySize(cntIdx));
00701 sqliteVdbeChangeP3(v, addr+10, pIdx->zName, P3_STATIC);
00702 }
00703 }
00704 }
00705 addr = sqliteVdbeAddOpList(v, ArraySize(endCode), endCode);
00706 sqliteVdbeChangeP2(v, addr+2, addr+ArraySize(endCode));
00707 }else
00708
00709 {}
00710 sqliteFree(zLeft);
00711 sqliteFree(zRight);
00712 }