Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | First version of sqlite_stat2 (schema forces exactly 10 samples). |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
dd96bda2a85c1d94fb4a0bf5f27e2977 |
User & Date: | dan 2009-08-17 17:06:59.000 |
Context
2009-08-18
| ||
16:24 | Change the sqlite_stat2 schema to be more flexible. (check-in: ded9dec645 user: dan tags: trunk) | |
2009-08-17
| ||
17:06 | First version of sqlite_stat2 (schema forces exactly 10 samples). (check-in: dd96bda2a8 user: dan tags: trunk) | |
2009-08-14
| ||
18:18 | Update the amalgamation builder so that it avoids putting redundant SQLITE_API macros on declarations. (check-in: 0d5b058717 user: drh tags: trunk) | |
Changes
Changes to src/analyze.c.
︙ | ︙ | |||
13 14 15 16 17 18 19 | ** ** @(#) $Id: analyze.c,v 1.52 2009/04/16 17:45:48 drh Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" /* | | > | > > > > > > < < < < > > > | | | | | | | < | | < < < < < < < < | | | > > | < < < < < < < < < | > > > > > > > | > > > > > | | | > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | ** ** @(#) $Id: analyze.c,v 1.52 2009/04/16 17:45:48 drh Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" /* ** This routine generates code that opens the sqlite_stat1 table for ** writing with cursor iStatCur. The sqlite_stat2 table is opened ** for writing using cursor (iStatCur+1). ** ** If the sqlite_stat1 tables does not previously exist, it is created. ** If it does previously exist, all entires associated with table zWhere ** are removed. If zWhere==0 then all entries are removed. */ static void openStatTable( Parse *pParse, /* Parsing context */ int iDb, /* The database we are looking in */ int iStatCur, /* Open the sqlite_stat1 table on this cursor */ const char *zWhere /* Delete entries associated with this table */ ){ const char *aName[] = { "sqlite_stat1", "sqlite_stat2" }; const char *aCols[] = { "tbl,idx,stat", "tbl,idx," SQLITE_INDEX_SAMPLE_COLS }; int aRoot[] = {0, 0}; int aCreateTbl[] = {0, 0}; int i; sqlite3 *db = pParse->db; Db *pDb; Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; assert( sqlite3BtreeHoldsAllMutexes(db) ); assert( sqlite3VdbeDb(v)==db ); pDb = &db->aDb[iDb]; for(i=0; i<ArraySize(aName); i++){ Table *pStat; if( (pStat = sqlite3FindTable(db, aName[i], pDb->zName))==0 ){ /* The sqlite_stat[12] table does not exist. Create it. Note that a ** side-effect of the CREATE TABLE statement is to leave the rootpage ** of the new table in register pParse->regRoot. This is important ** because the OpenWrite opcode below will be needing it. */ sqlite3NestedParse(pParse, "CREATE TABLE %Q.%s(%s)", pDb->zName, aName[i], aCols[i] ); aRoot[i] = pParse->regRoot; aCreateTbl[i] = 1; }else{ /* The table already exists. If zWhere is not NULL, delete all entries ** associated with the table zWhere. If zWhere is NULL, delete the ** entire contents of the table. */ aRoot[i] = pStat->tnum; sqlite3TableLock(pParse, iDb, aRoot[i], 1, aName[i]); if( zWhere ){ sqlite3NestedParse(pParse, "DELETE FROM %Q.%s WHERE tbl=%Q", pDb->zName, aName[i], zWhere ); }else{ /* The sqlite_stat[12] table already exists. Delete all rows. */ sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb); } } } /* Open the sqlite_stat[12] tables for writing. */ for(i=0; i<ArraySize(aName); i++){ sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb); sqlite3VdbeChangeP4(v, -1, (char *)3, P4_INT32); sqlite3VdbeChangeP5(v, aCreateTbl[i]); } } /* ** Generate code to do an analysis of all indices associated with ** a single table. */ static void analyzeOneTable( |
︙ | ︙ | |||
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | return; } #endif /* Establish a read-lock on the table at the shared-cache level. */ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); iIdxCur = pParse->nTab++; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); int regFields; /* Register block for building records */ int regRec; /* Register holding completed record */ int regTemp; /* Temporary use register */ int regCol; /* Content of a column from the table being analyzed */ int regRowid; /* Rowid for the inserted record */ int regF2; /* Open a cursor to the index to be analyzed */ assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) ); nCol = pIdx->nColumn; sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb, (char *)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); | > > | > > > > > > > > | > > | < | | > | > > | > | | | > > > > | > > | | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | return; } #endif /* Establish a read-lock on the table at the shared-cache level. */ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); iMem += 3; iIdxCur = pParse->nTab++; for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx); int regFields; /* Register block for building records */ int regRec; /* Register holding completed record */ int regTemp; /* Temporary use register */ int regCol; /* Content of a column from the table being analyzed */ int regRowid; /* Rowid for the inserted record */ int regF2; int regStat2; /* Open a cursor to the index to be analyzed */ assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) ); nCol = pIdx->nColumn; sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb, (char *)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); regStat2 = iMem+nCol*2+1; regFields = regStat2+2+SQLITE_INDEX_SAMPLES; regTemp = regRowid = regCol = regFields+3; regRec = regCol+1; if( regRec>pParse->nMem ){ pParse->nMem = regRec; } /* Fill in the register with the total number of rows. */ if( pTab->pIndex==pIdx ){ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, iMem-3); } sqlite3VdbeAddOp2(v, OP_Integer, 0, iMem-2); sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem-1); /* Memory cells are used as follows. All memory cell addresses are ** offset by iMem. That is, cell 0 below is actually cell iMem, cell ** 1 is cell 1+iMem, etc. ** ** 0: The total number of rows in the table. ** ** 1..nCol: Number of distinct entries in index considering the ** left-most N columns, where N is the same as the ** memory cell number. ** ** nCol+1..2*nCol: Previous value of indexed columns, from left to ** right. ** ** 2*nCol+1..2*nCol+10: 10 evenly spaced samples. ** ** Cells iMem through iMem+nCol are initialized to 0. The others ** are initialized to NULL. */ for(i=0; i<=nCol; i++){ sqlite3VdbeAddOp2(v, OP_Integer, 0, iMem+i); } for(i=0; i<nCol; i++){ sqlite3VdbeAddOp2(v, OP_Null, 0, iMem+nCol+i+1); } /* Start the analysis loop. This loop runs through all the entries inof ** the index b-tree. */ endOfLoop = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop); topOfLoop = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1); for(i=0; i<nCol; i++){ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regCol); if( i==0 ){ sqlite3VdbeAddOp3(v, OP_Sample, iMem-3, regCol, regStat2+2); } sqlite3VdbeAddOp3(v, OP_Ne, regCol, 0, iMem+nCol+i+1); /**** TODO: add collating sequence *****/ sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); } sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop); for(i=0; i<nCol; i++){ sqlite3VdbeJumpHere(v, topOfLoop + 1 + 2*(i + 1)); sqlite3VdbeAddOp2(v, OP_AddImm, iMem+i+1, 1); sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1); } /* End of the analysis loop. */ sqlite3VdbeResolveLabel(v, endOfLoop); sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop); sqlite3VdbeAddOp1(v, OP_Close, iIdxCur); /* Store the results in sqlite_stat1. ** ** The result is a single row of the sqlite_stat1 table. The first ** two columns are the names of the table and index. The third column ** is a string composed of a list of integer statistics about the ** index. The first integer in the list is the total number of entries ** in the index. There is one additional integer in the list for each ** column of the table. This additional integer is a guess of how many |
︙ | ︙ | |||
215 216 217 218 219 220 221 222 223 224 225 226 227 228 | sqlite3VdbeAddOp1(v, OP_ToInt, regTemp); sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regF2, regF2); } sqlite3VdbeAddOp4(v, OP_MakeRecord, regFields, 3, regRec, "aaa", 0); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3VdbeJumpHere(v, addr); } } /* ** Generate code that will cause the most recent index analysis to ** be laoded into internal hash tables where is can be used. | > > > > > > > > > > | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | sqlite3VdbeAddOp1(v, OP_ToInt, regTemp); sqlite3VdbeAddOp3(v, OP_Concat, regTemp, regF2, regF2); } sqlite3VdbeAddOp4(v, OP_MakeRecord, regFields, 3, regRec, "aaa", 0); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur, regRec, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); /* Store the results in sqlite_stat2. */ sqlite3VdbeAddOp4(v, OP_String8, 0, regStat2, 0, pTab->zName, 0); sqlite3VdbeAddOp4(v, OP_String8, 0, regStat2+1, 0, pIdx->zName, 0); sqlite3VdbeAddOp4(v, OP_MakeRecord, regStat2, SQLITE_INDEX_SAMPLES+2, regRec, "aabbbbbbbbbb", 0 ); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regRowid); sqlite3VdbeJumpHere(v, addr); } } /* ** Generate code that will cause the most recent index analysis to ** be laoded into internal hash tables where is can be used. |
︙ | ︙ | |||
241 242 243 244 245 246 247 | sqlite3 *db = pParse->db; Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */ HashElem *k; int iStatCur; int iMem; sqlite3BeginWriteOperation(pParse, 0, iDb); | | > | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 | sqlite3 *db = pParse->db; Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */ HashElem *k; int iStatCur; int iMem; sqlite3BeginWriteOperation(pParse, 0, iDb); iStatCur = pParse->nTab; pParse->nTab += 2; openStatTable(pParse, iDb, iStatCur, 0); iMem = pParse->nMem+1; for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ Table *pTab = (Table*)sqliteHashData(k); analyzeOneTable(pParse, pTab, iStatCur, iMem); } loadAnalysis(pParse, iDb); |
︙ | ︙ | |||
263 264 265 266 267 268 269 | int iDb; int iStatCur; assert( pTab!=0 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); sqlite3BeginWriteOperation(pParse, 0, iDb); | | > | 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | int iDb; int iStatCur; assert( pTab!=0 ); assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); sqlite3BeginWriteOperation(pParse, 0, iDb); iStatCur = pParse->nTab; pParse->nTab += 2; openStatTable(pParse, iDb, iStatCur, pTab->zName); analyzeOneTable(pParse, pTab, iStatCur, pParse->nMem+1); loadAnalysis(pParse, iDb); } /* ** Generate code for the ANALYZE command. The parser calls this routine |
︙ | ︙ | |||
383 384 385 386 387 388 389 | pIndex->aiRowEst[i] = v; if( *z==' ' ) z++; } return 0; } /* | | > | 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 | pIndex->aiRowEst[i] = v; if( *z==' ' ) z++; } return 0; } /* ** Load the content of the sqlite_stat1 and sqlite_stat2 tables into the ** index hash tables. */ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ analysisInfo sInfo; HashElem *i; char *zSql; int rc; |
︙ | ︙ | |||
408 409 410 411 412 413 414 | /* Check to make sure the sqlite_stat1 table existss */ sInfo.db = db; sInfo.zDatabase = db->aDb[iDb].zName; if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){ return SQLITE_ERROR; } | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > | > > > > > > > > > | 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 | /* Check to make sure the sqlite_stat1 table existss */ sInfo.db = db; sInfo.zDatabase = db->aDb[iDb].zName; if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){ return SQLITE_ERROR; } /* Load new statistics out of the sqlite_stat1 table */ zSql = sqlite3MPrintf(db, "SELECT idx, stat FROM %Q.sqlite_stat1", sInfo.zDatabase); if( zSql==0 ){ rc = SQLITE_NOMEM; }else{ (void)sqlite3SafetyOff(db); rc = sqlite3_exec(db, zSql, analysisLoader, &sInfo, 0); (void)sqlite3SafetyOn(db); sqlite3DbFree(db, zSql); } /* Load the statistics from the sqlite_stat2 table */ if( rc==SQLITE_OK ){ zSql = sqlite3MPrintf(db, "SELECT idx," SQLITE_INDEX_SAMPLE_COLS " FROM %Q.sqlite_stat2", sInfo.zDatabase ); if( zSql ){ sqlite3_stmt *pStmt = 0; (void)sqlite3SafetyOff(db); rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); if( rc==SQLITE_OK ){ while( SQLITE_ROW==sqlite3_step(pStmt) ){ char *zIndex = (char *)sqlite3_column_text(pStmt, 0); Index *pIdx; pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase); if( pIdx ){ char *pSpace; IndexSample *pSample; int iCol; int nAlloc = SQLITE_INDEX_SAMPLES * sizeof(IndexSample); for(iCol=1; iCol<=SQLITE_INDEX_SAMPLES; iCol++){ int eType = sqlite3_column_type(pStmt, iCol); if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ nAlloc += sqlite3_column_bytes(pStmt, iCol); } } pSample = sqlite3DbMallocRaw(db, nAlloc); if( !pSample ){ rc = SQLITE_NOMEM; break; } sqlite3DbFree(db, pIdx->aSample); pIdx->aSample = pSample; pSpace = (char *)&pSample[SQLITE_INDEX_SAMPLES]; for(iCol=1; iCol<=SQLITE_INDEX_SAMPLES; iCol++){ int eType = sqlite3_column_type(pStmt, iCol); pSample[iCol-1].eType = eType; switch( eType ){ case SQLITE_BLOB: case SQLITE_TEXT: { const char *z = (const char *)( (eType==SQLITE_BLOB) ? sqlite3_column_blob(pStmt, iCol): sqlite3_column_text(pStmt, iCol) ); int n = sqlite3_column_bytes(pStmt, iCol); if( n>24 ){ n = 24; } pSample[iCol-1].nByte = n; pSample[iCol-1].u.z = pSpace; memcpy(pSpace, z, n); pSpace += n; break; } case SQLITE_INTEGER: case SQLITE_FLOAT: pSample[iCol-1].u.r = sqlite3_column_double(pStmt, iCol); break; case SQLITE_NULL: break; } } } } if( rc==SQLITE_NOMEM ){ sqlite3_finalize(pStmt); }else{ rc = sqlite3_finalize(pStmt); } } (void)sqlite3SafetyOn(db); sqlite3DbFree(db, zSql); }else{ rc = SQLITE_NOMEM; } } if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; return rc; } #endif /* SQLITE_OMIT_ANALYZE */ |
Changes to src/build.c.
︙ | ︙ | |||
339 340 341 342 343 344 345 346 347 348 349 350 351 352 | /* ** Reclaim the memory used by an index */ static void freeIndex(Index *p){ sqlite3 *db = p->pTable->dbMem; /* testcase( db==0 ); */ sqlite3DbFree(db, p->zColAff); sqlite3DbFree(db, p); } /* ** Remove the given index from the index hash table, and free ** its memory structures. | > | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | /* ** Reclaim the memory used by an index */ static void freeIndex(Index *p){ sqlite3 *db = p->pTable->dbMem; /* testcase( db==0 ); */ sqlite3DbFree(db, p->aSample); sqlite3DbFree(db, p->zColAff); sqlite3DbFree(db, p); } /* ** Remove the given index from the index hash table, and free ** its memory structures. |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 | } } if( isAppropriateForFactoring(pExpr) ){ int r1 = ++pParse->nMem; int r2; r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1); pExpr->op = TK_REGISTER; pExpr->iTable = r2; return WRC_Prune; } return WRC_Continue; } | > | 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 | } } if( isAppropriateForFactoring(pExpr) ){ int r1 = ++pParse->nMem; int r2; r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); if( NEVER(r1!=r2) ) sqlite3ReleaseTempReg(pParse, r1); pExpr->iColumn = pExpr->op; pExpr->op = TK_REGISTER; pExpr->iTable = r2; return WRC_Prune; } return WRC_Continue; } |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
73 74 75 76 77 78 79 80 81 82 83 84 85 86 | #ifdef HAVE_STDINT_H #include <stdint.h> #endif #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif /* ** This macro is used to "hide" some ugliness in casting an int ** value to a ptr value under the MSVC 64-bit compiler. Casting ** non 64-bit values to ptr types results in a "hard" error with ** the MSVC 64-bit compiler which this attempts to avoid. ** ** A simple compiler pragma or casting sequence could not be found | > > > | 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | #ifdef HAVE_STDINT_H #include <stdint.h> #endif #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif #define SQLITE_INDEX_SAMPLES 10 #define SQLITE_INDEX_SAMPLE_COLS "s1,s2,s3,s4,s5,s6,s7,s8,s9,s10" /* ** This macro is used to "hide" some ugliness in casting an int ** value to a ptr value under the MSVC 64-bit compiler. Casting ** non 64-bit values to ptr types results in a "hard" error with ** the MSVC 64-bit compiler which this attempts to avoid. ** ** A simple compiler pragma or casting sequence could not be found |
︙ | ︙ | |||
591 592 593 594 595 596 597 598 599 600 601 602 603 604 | typedef struct ExprList ExprList; typedef struct ExprSpan ExprSpan; typedef struct FKey FKey; typedef struct FuncDef FuncDef; typedef struct FuncDefHash FuncDefHash; typedef struct IdList IdList; typedef struct Index Index; typedef struct KeyClass KeyClass; typedef struct KeyInfo KeyInfo; typedef struct Lookaside Lookaside; typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; typedef struct Parse Parse; | > | 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 | typedef struct ExprList ExprList; typedef struct ExprSpan ExprSpan; typedef struct FKey FKey; typedef struct FuncDef FuncDef; typedef struct FuncDefHash FuncDefHash; typedef struct IdList IdList; typedef struct Index Index; typedef struct IndexSample IndexSample; typedef struct KeyClass KeyClass; typedef struct KeyInfo KeyInfo; typedef struct Lookaside Lookaside; typedef struct LookasideSlot LookasideSlot; typedef struct Module Module; typedef struct NameContext NameContext; typedef struct Parse Parse; |
︙ | ︙ | |||
1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ Schema *pSchema; /* Schema containing this index */ u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ char **azColl; /* Array of collation sequence names for index */ }; /* ** Each token coming out of the lexer is an instance of ** this structure. Tokens are also used as part of an expression. ** ** Note if Token.z==0 then Token.dyn and Token.n are undefined and | > > > > > > > > > > > > > > | 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 | u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */ u8 autoIndex; /* True if is automatically created (ex: by UNIQUE) */ char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ Schema *pSchema; /* Schema containing this index */ u8 *aSortOrder; /* Array of size Index.nColumn. True==DESC, False==ASC */ char **azColl; /* Array of collation sequence names for index */ IndexSample *aSample; /* Array of SQLITE_INDEX_SAMPLES samples */ }; /* ** Each sample stored in the sqlite_stat2 table is represented in memory ** using a structure of this type. */ struct IndexSample { union { char *z; /* Value if eType is SQLITE_TEXT or SQLITE_BLOB */ double r; /* Value if eType is SQLITE_FLOAT or SQLITE_INTEGER */ } u; u8 eType; /* SQLITE_NULL, SQLITE_INTEGER ... etc. */ u8 nByte; /* Size in byte of text or blob. */ }; /* ** Each token coming out of the lexer is an instance of ** this structure. Tokens are also used as part of an expression. ** ** Note if Token.z==0 then Token.dyn and Token.n are undefined and |
︙ | ︙ | |||
2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 | const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); void sqlite3ValueFree(sqlite3_value*); sqlite3_value *sqlite3ValueNew(sqlite3 *); char *sqlite3Utf16to8(sqlite3 *, const void*, int); int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); #ifndef SQLITE_AMALGAMATION extern const unsigned char sqlite3UpperToLower[]; extern const unsigned char sqlite3CtypeMap[]; extern SQLITE_WSD struct Sqlite3Config sqlite3Config; extern SQLITE_WSD FuncDefHash sqlite3GlobalFunctions; | > | 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 | const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*)); void sqlite3ValueFree(sqlite3_value*); sqlite3_value *sqlite3ValueNew(sqlite3 *); char *sqlite3Utf16to8(sqlite3 *, const void*, int); char *sqlite3Utf8to16(sqlite3 *, int, char *, int, int *); int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); #ifndef SQLITE_AMALGAMATION extern const unsigned char sqlite3UpperToLower[]; extern const unsigned char sqlite3CtypeMap[]; extern SQLITE_WSD struct Sqlite3Config sqlite3Config; extern SQLITE_WSD FuncDefHash sqlite3GlobalFunctions; |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
2305 2306 2307 2308 2309 2310 2311 2312 | case SQLITE_UTF16BE: Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1)); break; default: assert(0); } pVal = sqlite3ValueNew(0); | > > | | | | | | | | | > > | 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 | case SQLITE_UTF16BE: Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1)); break; default: assert(0); } sqlite3BeginBenignMalloc(); pVal = sqlite3ValueNew(0); if( pVal ){ sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC); n = sqlite3_value_bytes(pVal); Tcl_ListObjAppendElement(i,pX, Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC); n = sqlite3_value_bytes(pVal); Tcl_ListObjAppendElement(i,pX, Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n)); sqlite3ValueFree(pVal); } sqlite3EndBenignMalloc(); Tcl_EvalObjEx(i, pX, 0); Tcl_DecrRefCount(pX); Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res); return res; } static int test_collate( |
︙ | ︙ |
Changes to src/utf.c.
︙ | ︙ | |||
449 450 451 452 453 454 455 456 457 458 459 460 461 462 | sqlite3VdbeMemRelease(&m); m.z = 0; } assert( (m.flags & MEM_Term)!=0 || db->mallocFailed ); assert( (m.flags & MEM_Str)!=0 || db->mallocFailed ); return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3DbStrDup(db, m.z); } /* ** pZ is a UTF-16 encoded unicode string at least nChar characters long. ** Return the number of bytes in the first nChar unicode characters ** in pZ. nChar must be non-negative. */ int sqlite3Utf16ByteLen(const void *zIn, int nChar){ | > > > > > > > > > > > > > > > > > > > > > > > > | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 | sqlite3VdbeMemRelease(&m); m.z = 0; } assert( (m.flags & MEM_Term)!=0 || db->mallocFailed ); assert( (m.flags & MEM_Str)!=0 || db->mallocFailed ); return (m.flags & MEM_Dyn)!=0 ? m.z : sqlite3DbStrDup(db, m.z); } /* ** Convert a UTF-8 string to the UTF-16 encoding specified by parameter ** enc. A pointer to the new string is returned, and the value of *pnOut ** is set to the length of the returned string in bytes. The call should ** arrange to call sqlite3DbFree() on the returned pointer when it is ** no longer required. ** ** If a malloc failure occurs, NULL is returned and the db.mallocFailed ** flag set. */ char *sqlite3Utf8to16(sqlite3 *db, int enc, char *z, int n, int *pnOut){ Mem m; memset(&m, 0, sizeof(m)); m.db = db; sqlite3VdbeMemSetStr(&m, z, n, SQLITE_UTF8, SQLITE_STATIC); if( sqlite3VdbeMemTranslate(&m, enc) ){ assert( db->mallocFailed ); return 0; } assert( m.z==m.zMalloc ); *pnOut = m.n; return m.z; } /* ** pZ is a UTF-16 encoded unicode string at least nChar characters long. ** Return the number of bytes in the first nChar unicode characters ** in pZ. nChar must be non-negative. */ int sqlite3Utf16ByteLen(const void *zIn, int nChar){ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 | ** then only the currently executing statement is affected. */ case OP_Expire: { if( !pOp->p1 ){ sqlite3ExpirePreparedStatements(db); }else{ p->expired = 1; } break; } #ifndef SQLITE_OMIT_SHARED_CACHE /* Opcode: TableLock P1 P2 P3 P4 * ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 | ** then only the currently executing statement is affected. */ case OP_Expire: { if( !pOp->p1 ){ sqlite3ExpirePreparedStatements(db); }else{ p->expired = 1; } break; } /* Opcode: Sample P1 P2 P3 * * ** ** Register P1 contains the total number of rows in the index being ** analyzed. Register P1+1 contains an integer between 0 and 9, the ** index of the next sample required. Register P1+2 contains an index ** between 1 and *P1, the number of the next sample required. Register ** P1+3 contains the current row index. ** ** If the integer in register P1+3 is the same as the integer in register ** P1+1, then the following takes place: ** ** (a) the contents of register P1+1 is incremented. ** ** (b) the contents of the register identified by parameter P2 is ** copied to register number (P3 + X), where X is the newly ** incremented value of register P1+1. ** ** (c) register P1+2 is set to the index of the next sample required. */ case OP_Sample: { int p1 = pOp->p1; i64 iReq = p->aMem[p1+2].u.i; i64 iRow = p->aMem[p1+3].u.i; while( iReq==iRow ){ i64 nRow = p->aMem[p1].u.i; int iSample = ++p->aMem[p1+1].u.i; Mem *pReg = &p->aMem[pOp->p3 + iSample - 1]; assert( pReg<&p->aMem[p->nMem] ); sqlite3VdbeMemShallowCopy(pReg, &p->aMem[pOp->p2], MEM_Ephem); Deephemeralize(pReg); if( iSample==SQLITE_INDEX_SAMPLES ){ iReq = 0; }else{ iReq = iRow + (nRow-iRow)/(SQLITE_INDEX_SAMPLES - iSample); p->aMem[p1+2].u.i = iReq; } } break; } #ifndef SQLITE_OMIT_SHARED_CACHE /* Opcode: TableLock P1 P2 P3 P4 * ** |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 | sqlite3_value *pVal = 0; if( !pExpr ){ *ppVal = 0; return SQLITE_OK; } op = pExpr->op; if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ pVal = sqlite3ValueNew(db); if( pVal==0 ) goto no_mem; if( ExprHasProperty(pExpr, EP_IntValue) ){ sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue); }else{ | > > > | 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 | sqlite3_value *pVal = 0; if( !pExpr ){ *ppVal = 0; return SQLITE_OK; } op = pExpr->op; if( op==TK_REGISTER ){ op = pExpr->iColumn; } if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ pVal = sqlite3ValueNew(db); if( pVal==0 ) goto no_mem; if( ExprHasProperty(pExpr, EP_IntValue) ){ sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue); }else{ |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 | /* Try to find a more efficient access pattern by using multiple indexes ** to optimize an OR expression within the WHERE clause. */ bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost); } #endif /* SQLITE_OMIT_VIRTUALTABLE */ /* ** Find the query plan for accessing a particular table. Write the ** best query plan and its cost into the WhereCost object supplied as the ** last parameter. ** ** The lowest cost plan wins. The cost is an estimate of the amount of | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 | /* Try to find a more efficient access pattern by using multiple indexes ** to optimize an OR expression within the WHERE clause. */ bestOrClauseIndex(pParse, pWC, pSrc, notReady, pOrderBy, pCost); } #endif /* SQLITE_OMIT_VIRTUALTABLE */ /* ** Argument pIdx is a pointer to an index structure that has an array of ** SQLITE_INDEX_SAMPLES evenly spaced samples of the first indexed column ** stored in Index.aSample. The domain of values stored in said column ** may be thought of as divided into (SQLITE_INDEX_SAMPLES+1) regions. ** Region 0 contains all values smaller than the first sample value. Region ** 1 contains values larger than or equal to the value of the first sample, ** but smaller than the value of the second. And so on. ** ** If successful, this function determines which of the regions value ** pVal lies in, sets *piRegion to the region index and returns SQLITE_OK. ** Or, if an OOM occurs while converting text values between encodings, ** SQLITE_NOMEM is returned. */ static int whereRangeRegion( Parse *pParse, /* Database connection */ Index *pIdx, /* Index to consider domain of */ sqlite3_value *pVal, /* Value to consider */ int *piRegion /* OUT: Region of domain in which value lies */ ){ if( pVal ){ IndexSample *aSample = pIdx->aSample; int i = 0; int eType = sqlite3_value_type(pVal); if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ double r = sqlite3_value_double(pVal); for(i=0; i<SQLITE_INDEX_SAMPLES; i++){ if( aSample[i].eType==SQLITE_NULL ) continue; if( aSample[i].eType>=SQLITE_TEXT || aSample[i].u.r>r ) break; } }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ sqlite3 *db = pParse->db; CollSeq *pColl; const u8 *z; int n; if( eType==SQLITE_BLOB ){ z = (const u8 *)sqlite3_value_blob(pVal); pColl = db->pDfltColl; assert( pColl->enc==SQLITE_UTF8 ); }else{ pColl = sqlite3FindCollSeq(db, SQLITE_UTF8, *pIdx->azColl, 0); if( sqlite3CheckCollSeq(pParse, pColl) ){ return SQLITE_ERROR; } z = (const u8 *)sqlite3ValueText(pVal, pColl->enc); if( !z ){ return SQLITE_NOMEM; } assert( z && pColl && pColl->xCmp ); } n = sqlite3ValueBytes(pVal, pColl->enc); for(i=0; i<SQLITE_INDEX_SAMPLES; i++){ int r; int eSampletype = aSample[i].eType; if( eSampletype==SQLITE_NULL || eSampletype<eType ) continue; if( (eSampletype!=eType) ) break; if( pColl->enc==SQLITE_UTF8 ){ r = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z); }else{ int nSample; char *zSample = sqlite3Utf8to16( db, pColl->enc, aSample[i].u.z, aSample[i].nByte, &nSample ); if( !zSample ){ assert( db->mallocFailed ); return SQLITE_NOMEM; } r = pColl->xCmp(pColl->pUser, nSample, zSample, n, z); sqlite3DbFree(db, zSample); } if( r>0 ) break; } } *piRegion = i; } return SQLITE_OK; } /* ** This function is used to estimate the number of rows that will be visited ** by scanning an index for a range of values. The range may have an upper ** bound, a lower bound, or both. The WHERE clause terms that set the upper ** and lower bounds are represented by pLower and pUpper respectively. For ** example, assuming that index p is on t1(a): ** ** ... FROM t1 WHERE a > ? AND a < ? ... ** |_____| |_____| ** | | ** pLower pUpper ** ** If the upper or lower bound is not present, then NULL should be passed in ** place of a WhereTerm. ** ** The nEq parameter is passed the index of the index column subject to the ** range constraint. Or, equivalently, the number of equality constraints ** optimized by the proposed index scan. For example, assuming index p is ** on t1(a, b), and the SQL query is: ** ** ... FROM t1 WHERE a = ? AND b > ? AND b < ? ... ** ** then nEq should be passed the value 1 (as the range restricted column, ** b, is the second left-most column of the index). Or, if the query is: ** ** ... FROM t1 WHERE a > ? AND a < ? ... ** ** then nEq should be passed 0. ** ** The returned value is an integer between 1 and 9, inclusive. A return ** value of 1 indicates that the proposed range scan is expected to visit ** approximately 1/9 (11%) of the rows selected by the nEq equality constraints ** (if any). A return value of 9 indicates that it is expected that the ** range scan will visit 9/9 (100%) of the rows selected by the equality ** constraints. */ static int whereRangeScanEst( Parse *pParse, Index *p, int nEq, WhereTerm *pLower, WhereTerm *pUpper, int *piEst /* OUT: Return value */ ){ sqlite3 *db = pParse->db; sqlite3_value *pLowerVal = 0; sqlite3_value *pUpperVal = 0; int rc = SQLITE_OK; if( nEq==0 && p->aSample ){ int iEst; int iUpper = SQLITE_INDEX_SAMPLES; int iLower = 0; u8 aff = p->pTable->aCol[0].affinity; if( pLower ){ Expr *pExpr = pLower->pExpr->pRight; rc = sqlite3ValueFromExpr(db, pExpr, SQLITE_UTF8, aff, &pLowerVal); if( !pLowerVal ) goto fallback; } if( pUpper ){ Expr *pExpr = pUpper->pExpr->pRight; rc = sqlite3ValueFromExpr(db, pExpr, SQLITE_UTF8, aff, &pUpperVal); if( !pUpperVal ){ sqlite3ValueFree(pLowerVal); goto fallback; } } rc = whereRangeRegion(pParse, p, pUpperVal, &iUpper); if( rc==SQLITE_OK ){ rc = whereRangeRegion(pParse, p, pLowerVal, &iLower); } iEst = iUpper - iLower; if( iEst>=SQLITE_INDEX_SAMPLES ) iEst = SQLITE_INDEX_SAMPLES-1; else if( iEst<1 ) iEst = 1; sqlite3ValueFree(pLowerVal); sqlite3ValueFree(pUpperVal); *piEst = iEst; return rc; } fallback: assert( pLower || pUpper ); *piEst = (SQLITE_INDEX_SAMPLES-1) / ((pLower&&pUpper)?9:3); return rc; } /* ** Find the query plan for accessing a particular table. Write the ** best query plan and its cost into the WhereCost object supplied as the ** last parameter. ** ** The lowest cost plan wins. The cost is an estimate of the amount of |
︙ | ︙ | |||
2039 2040 2041 2042 2043 2044 2045 | ** ** SELECT a, b FROM tbl WHERE a = 1; ** SELECT a, b, c FROM tbl WHERE a = 1; */ int nEq; int bInEst = 0; int nInMul = 1; | | | 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 | ** ** SELECT a, b FROM tbl WHERE a = 1; ** SELECT a, b, c FROM tbl WHERE a = 1; */ int nEq; int bInEst = 0; int nInMul = 1; int nBound = 9; int bSort = 0; int bLookup = 0; /* Determine the values of nEq and nInMul */ for(nEq=0; nEq<pProbe->nColumn; nEq++){ WhereTerm *pTerm; /* A single term of the WHERE clause */ int j = pProbe->aiColumn[nEq]; |
︙ | ︙ | |||
2071 2072 2073 2074 2075 2076 2077 2078 2079 | /* Determine the value of nBound. */ if( nEq<pProbe->nColumn ){ int j = pProbe->aiColumn[nEq]; if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){ WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pIdx); WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pIdx); if( pTop ){ wsFlags |= WHERE_TOP_LIMIT; | > < < | 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 | /* Determine the value of nBound. */ if( nEq<pProbe->nColumn ){ int j = pProbe->aiColumn[nEq]; if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){ WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pIdx); WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pIdx); whereRangeScanEst(pParse, pProbe, nEq, pBtm, pTop, &nBound); if( pTop ){ wsFlags |= WHERE_TOP_LIMIT; used |= pTop->prereqRight; } if( pBtm ){ wsFlags |= WHERE_BTM_LIMIT; used |= pBtm->prereqRight; } wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE); } }else if( pProbe->onError!=OE_None ){ testcase( wsFlags & WHERE_COLUMN_IN ); testcase( wsFlags & WHERE_COLUMN_NULL ); |
︙ | ︙ | |||
2148 2149 2150 2151 2152 2153 2154 | ** works well in practice and causes the test suite to pass. */ nRow = (double)(aiRowEst[nEq] * nInMul); if( bInEst && nRow*2>aiRowEst[0] ){ nRow = aiRowEst[0]/2; nInMul = nRow / aiRowEst[nEq]; } cost = nRow + nInMul*estLog(aiRowEst[0]); | | | | 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 | ** works well in practice and causes the test suite to pass. */ nRow = (double)(aiRowEst[nEq] * nInMul); if( bInEst && nRow*2>aiRowEst[0] ){ nRow = aiRowEst[0]/2; nInMul = nRow / aiRowEst[nEq]; } cost = nRow + nInMul*estLog(aiRowEst[0]); nRow = nRow * (double)nBound / 9.0; cost = cost * (double)nBound / 9.0; if( bSort ){ cost += cost*estLog(cost); } if( pIdx && bLookup==0 ){ cost /= 2; } #endif |
︙ | ︙ |
Changes to test/auth.test.
︙ | ︙ | |||
2312 2313 2314 2315 2316 2317 2318 | do_test auth-5.2 { execsql { SELECT name FROM ( SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type='table' ORDER BY name } | | | 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 | do_test auth-5.2 { execsql { SELECT name FROM ( SELECT * FROM sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type='table' ORDER BY name } } {sqlite_stat1 sqlite_stat2 t1 t2 t3 t4} } # Ticket #3944 # ifcapable trigger { do_test auth-5.3.1 { execsql { |
︙ | ︙ |