Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Change where.c to read values from covering indexes instead of tables whenever possible. Modify OP_SeekPk to defer seeks (as OP_Seek does in sqlite3). |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
7f6b4708c2a5e73d412febabf73899db |
User & Date: | dan 2013-07-23 16:50:55.593 |
Context
2013-07-24
| ||
18:30 | Reenable covering index support in NGQP. check-in: 9e99914519 user: dan tags: trunk | |
2013-07-23
| ||
16:50 | Change where.c to read values from covering indexes instead of tables whenever possible. Modify OP_SeekPk to defer seeks (as OP_Seek does in sqlite3). check-in: 7f6b4708c2 user: dan tags: trunk | |
2013-07-22
| ||
20:12 | Add two new value-encoding header codes to represent REAL-IN-KEY and NONREAL-IN-KEY. This is an incompatible file format change. check-in: b7ac369ba7 user: drh tags: trunk | |
Changes
Changes to src/insert.c.
︙ | ︙ | |||
1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 | int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */ ){ int i; Vdbe *v; Index *pIdx; u8 pik_flags; int regRec; v = sqlite4GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ if( pParse->nested ){ pik_flags = 0; }else{ pik_flags = OPFLAG_NCHANGE | (isUpdate?OPFLAG_ISUPDATE:0); } | > | > > > > > > > > > > > > > > > > > > | 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 | int useSeekResult /* True to set the USESEEKRESULT flag on OP_[Idx]Insert */ ){ int i; Vdbe *v; Index *pIdx; u8 pik_flags; int regRec; int regCover; v = sqlite4GetVdbe(pParse); assert( v!=0 ); assert( pTab->pSelect==0 ); /* This table is not a VIEW */ if( pParse->nested ){ pik_flags = 0; }else{ pik_flags = OPFLAG_NCHANGE | (isUpdate?OPFLAG_ISUPDATE:0); } /* Generate code to serialize array of registers into a database record. ** This OP_MakeRecord also serves to apply affinities to the array of ** input registers at regContent. For this reason it must be executed ** before any MakeRecord instructions used to create covering index ** records. */ regRec = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp3(v, OP_MakeRecord, regContent, pTab->nCol, regRec); sqlite4TableAffinityStr(v, pTab); sqlite4ExprCacheAffinityChange(pParse, regContent, pTab->nCol); regCover = sqlite4GetTempReg(pParse); /* Write the entry to each index. */ for(i=0, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ assert( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY || aRegIdx[i] ); if( pIdx->eIndexType==SQLITE4_INDEX_FTS5 ){ int iPK; sqlite4FindPrimaryKey(pTab, &iPK); sqlite4Fts5CodeUpdate(pParse, pIdx, 0, aRegIdx[iPK], regContent, 0); } else if( aRegIdx[i] ){ int regData = 0; int flags = 0; if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){ regData = regRec; flags = pik_flags; }else if( pIdx->nCover>0 ){ int nByte = sizeof(int)*pIdx->nCover; int *aiPermute = (int *)sqlite4DbMallocRaw(pParse->db, nByte); if( aiPermute ){ memcpy(aiPermute, pIdx->aiCover, nByte); sqlite4VdbeAddOp4( v, OP_Permutation, 0, 0, 0, (char*)aiPermute, P4_INTARRAY ); } regData = regCover; sqlite4VdbeAddOp3(v, OP_MakeRecord, regContent, pIdx->nCover, regData); } sqlite4VdbeAddOp3(v, OP_IdxInsert, baseCur+i, regData, aRegIdx[i]); sqlite4VdbeChangeP5(v, flags); } } } |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 | pC = p->apCsr[p1]; assert( pC!=0 ); #ifndef SQLITE4_OMIT_VIRTUALTABLE assert( pC->pVtabCursor==0 ); #endif pKVCur = pC->pKVCur; if( pKVCur!=0 ){ if( pC->nullRow ){ aData = 0; }else{ rc = sqlite4KVCursorData(pKVCur, 0, -1, &aData, &nData); } }else if( ALWAYS(pC->pseudoTableReg>0) ){ pReg = &aMem[pC->pseudoTableReg]; | > > | 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 | pC = p->apCsr[p1]; assert( pC!=0 ); #ifndef SQLITE4_OMIT_VIRTUALTABLE assert( pC->pVtabCursor==0 ); #endif pKVCur = pC->pKVCur; if( pKVCur!=0 ){ rc = sqlite4VdbeCursorMoveto(db, pC); if( rc!=SQLITE4_OK ) break; if( pC->nullRow ){ aData = 0; }else{ rc = sqlite4KVCursorData(pKVCur, 0, -1, &aData, &nData); } }else if( ALWAYS(pC->pseudoTableReg>0) ){ pReg = &aMem[pC->pseudoTableReg]; |
︙ | ︙ | |||
2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 | char *zAffinity; /* The affinity string for the record */ VdbeCursor *pC; /* Cursor to generate key for */ Mem *pKeyOut; /* Where to store the generated key */ int keyReg; /* Register into which to write the key */ u8 *aRec; /* The constructed key or value */ int nRec; /* Size of aRec[] in bytes */ if( pOp->opcode==OP_MakeKey ){ pC = p->apCsr[pOp->p1]; keyReg = pOp->p2; pKeyOut = &aMem[keyReg]; memAboutToChange(p, pKeyOut); assert( pC!=0 ); assert( pC->pKeyInfo!=0 ); | > > > > | 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 | char *zAffinity; /* The affinity string for the record */ VdbeCursor *pC; /* Cursor to generate key for */ Mem *pKeyOut; /* Where to store the generated key */ int keyReg; /* Register into which to write the key */ u8 *aRec; /* The constructed key or value */ int nRec; /* Size of aRec[] in bytes */ assert( aPermute==0 || pOp->opcode!=OP_MakeKey ); assert( aPermute==0 || pOp->p4type==P4_NOTUSED ); assert( aPermute==0 || pOp->p3 ); if( pOp->opcode==OP_MakeKey ){ pC = p->apCsr[pOp->p1]; keyReg = pOp->p2; pKeyOut = &aMem[keyReg]; memAboutToChange(p, pKeyOut); assert( pC!=0 ); assert( pC->pKeyInfo!=0 ); |
︙ | ︙ | |||
2347 2348 2349 2350 2351 2352 2353 | rc = sqlite4VdbeMemSetStr(pKeyOut, (char *)aRec, nRec, 0, SQLITE4_DYNAMIC, 0); REGISTER_TRACE(keyReg, pKeyOut); UPDATE_MAX_BLOBSIZE(pKeyOut); } } | | | > | 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 | rc = sqlite4VdbeMemSetStr(pKeyOut, (char *)aRec, nRec, 0, SQLITE4_DYNAMIC, 0); REGISTER_TRACE(keyReg, pKeyOut); UPDATE_MAX_BLOBSIZE(pKeyOut); } } /* If P3 is not 0, compute the data record */ if( rc==SQLITE4_OK && pOp->p3 ){ assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 ); pOut = &aMem[pOp->p3]; memAboutToChange(p, pOut); aRec = 0; rc = sqlite4VdbeEncodeData(db, pData0, aPermute, nField, &aRec, &nRec); if( rc ){ sqlite4DbFree(db, aRec); }else{ rc = sqlite4VdbeMemSetStr(pOut, (char *)aRec, nRec, 0, SQLITE4_DYNAMIC,0); REGISTER_TRACE(pOp->p3, pOut); UPDATE_MAX_BLOBSIZE(pOut); } } aPermute = 0; break; } /* Opcode: Count P1 P2 * * * ** ** Store the number of entries (an integer value) in the table or index ** opened by cursor P1 in register P2 |
︙ | ︙ | |||
2904 2905 2906 2907 2908 2909 2910 | rc = sqlite4Fts5Pk(pIdx->pFts, pPk->iRoot, &aPkKey, &nPkKey); if( rc==SQLITE4_OK ){ rc = sqlite4KVCursorSeek(pPk->pKVCur, aPkKey, nPkKey, 0); if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_CORRUPT_BKPT; pPk->nullRow = 0; } }else{ | < < < < < < < | < < < < < < < < < < < < < < | 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 | rc = sqlite4Fts5Pk(pIdx->pFts, pPk->iRoot, &aPkKey, &nPkKey); if( rc==SQLITE4_OK ){ rc = sqlite4KVCursorSeek(pPk->pKVCur, aPkKey, nPkKey, 0); if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_CORRUPT_BKPT; pPk->nullRow = 0; } }else{ pPk->pIdxCsr = pIdx; } break; } /* Opcode: SeekGe P1 P2 P3 P4 * ** |
︙ | ︙ | |||
3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 | ** P1 must not be pseudo-table. It has to be a real table. */ case OP_Delete: { VdbeCursor *pC; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); rc = sqlite4KVCursorDelete(pC->pKVCur); if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; break; } /* Opcode: ResetCount * * * * * ** | > | 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 | ** P1 must not be pseudo-table. It has to be a real table. */ case OP_Delete: { VdbeCursor *pC; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->pIdxCsr==0 ); rc = sqlite4KVCursorDelete(pC->pKVCur); if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; break; } /* Opcode: ResetCount * * * * * ** |
︙ | ︙ | |||
3598 3599 3600 3601 3602 3603 3604 | pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); /* Note that RowKey and RowData are really exactly the same instruction */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; | | > | 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 | pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); /* Note that RowKey and RowData are really exactly the same instruction */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; rc = sqlite4VdbeCursorMoveto(db, pC); if( rc!=SQLITE4_OK ) break; assert( pC->nullRow==0 ); assert( pC->pseudoTableReg==0 ); assert( pC->pKVCur!=0 ); pCrsr = pC->pKVCur; if( pOp->opcode==OP_RowKey ){ rc = sqlite4KVCursorKey(pCrsr, &pData, &nData); |
︙ | ︙ | |||
3711 3712 3713 3714 3715 3716 3717 | i64 v; const KVByteArray *aKey; KVSize nKey; int n; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; | > > | | 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 | i64 v; const KVByteArray *aKey; KVSize nKey; int n; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; rc = sqlite4VdbeCursorMoveto(db, pC); if( rc!=SQLITE4_OK ) break; assert( pC->pIdxCsr==0 ); assert( pC->pseudoTableReg==0 ); if( pC->nullRow ){ pOut->flags = MEM_Null; break; #ifndef SQLITE4_OMIT_VIRTUALTABLE }else if( pC->pVtabCursor ){ pVtab = pC->pVtabCursor->pVtab; |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
65 66 67 68 69 70 71 72 73 74 75 76 77 78 | Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */ sqlite4_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ const sqlite4_module *pModule; /* Module for cursor pVtabCursor */ i64 seqCount; /* Sequence counter */ i64 movetoTarget; /* Argument to the deferred move-to */ VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */ Fts5Cursor *pFts; /* Fts5 cursor object (or NULL) */ /* Result of last sqlite4-Moveto() done by an OP_NotExists or ** OP_IsUnique opcode on this cursor. */ int seekResult; }; /* | > | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */ sqlite4_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ const sqlite4_module *pModule; /* Module for cursor pVtabCursor */ i64 seqCount; /* Sequence counter */ i64 movetoTarget; /* Argument to the deferred move-to */ VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */ Fts5Cursor *pFts; /* Fts5 cursor object (or NULL) */ VdbeCursor *pIdxCsr; /* Index cursor for deferred seek (OP_SeekPk) */ /* Result of last sqlite4-Moveto() done by an OP_NotExists or ** OP_IsUnique opcode on this cursor. */ int seekResult; }; /* |
︙ | ︙ | |||
359 360 361 362 363 364 365 366 367 368 369 370 371 372 | int iVal, /* Index of the value to decode. First is 0 */ Mem *pDefault, /* The default value. Often NULL */ Mem *pOut /* Write the result here */ ); int sqlite4VdbeEncodeData( sqlite4 *db, /* The database connection */ Mem *aIn, /* Array of values to encode */ int nIn, /* Number of entries in aIn[] */ u8 **pzOut, /* The output data record */ int *pnOut /* Bytes of content in pzOut */ ); int sqlite4VdbeEncodeKey( sqlite4 *db, /* The database connection */ Mem *aIn, /* Values to be encoded */ | > | 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | int iVal, /* Index of the value to decode. First is 0 */ Mem *pDefault, /* The default value. Often NULL */ Mem *pOut /* Write the result here */ ); int sqlite4VdbeEncodeData( sqlite4 *db, /* The database connection */ Mem *aIn, /* Array of values to encode */ int *aPermute, /* Permutation (or NULL) */ int nIn, /* Number of entries in aIn[] */ u8 **pzOut, /* The output data record */ int *pnOut /* Bytes of content in pzOut */ ); int sqlite4VdbeEncodeKey( sqlite4 *db, /* The database connection */ Mem *aIn, /* Values to be encoded */ |
︙ | ︙ | |||
423 424 425 426 427 428 429 | void sqlite4VdbeFrameDelete(VdbeFrame*); int sqlite4VdbeFrameRestore(VdbeFrame *); void sqlite4VdbeMemStoreType(Mem *pMem); int sqlite4VdbeTransferError(Vdbe *p); int sqlite4VdbeSeekEnd(VdbeCursor*, int); int sqlite4VdbeNext(VdbeCursor*); int sqlite4VdbePrevious(VdbeCursor*); | | | 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | void sqlite4VdbeFrameDelete(VdbeFrame*); int sqlite4VdbeFrameRestore(VdbeFrame *); void sqlite4VdbeMemStoreType(Mem *pMem); int sqlite4VdbeTransferError(Vdbe *p); int sqlite4VdbeSeekEnd(VdbeCursor*, int); int sqlite4VdbeNext(VdbeCursor*); int sqlite4VdbePrevious(VdbeCursor*); int sqlite4VdbeCursorMoveto(sqlite4 *, VdbeCursor *); int sqlite4VdbeRollback(sqlite4 *db, int iLevel); int sqlite4VdbeCommit(sqlite4 *db, int iLevel); #ifdef SQLITE4_DEBUG void sqlite4VdbeMemAboutToChange(Vdbe*,Mem*); #endif |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
2271 2272 2273 2274 2275 2276 2277 | assert( iVar>0 ); if( iVar>32 ){ v->expmask = 0xffffffff; }else{ v->expmask |= ((u32)1 << (iVar-1)); } } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 | assert( iVar>0 ); if( iVar>32 ){ v->expmask = 0xffffffff; }else{ v->expmask |= ((u32)1 << (iVar-1)); } } /* ** Cursor pPk is open on a primary key index. If there is currently a ** deferred seek pending on the cursor, do the actual seek now. ** ** If the operation is a success, SQLITE4_OK is returned. Or, if the ** required entry is not found in the PK index, SQLITE4_CORRUPT. Or if ** some other error occurs, an error code is returned. */ int sqlite4VdbeCursorMoveto(sqlite4 *db, VdbeCursor *pPk){ int rc = SQLITE4_OK; /* Return code */ VdbeCursor *pIdx; /* Index cursor to base seek on */ if( (pIdx = pPk->pIdxCsr) ){ KVByteArray const *aKey; /* Key data from cursor pIdx */ KVSize nKey; /* Size of aKey[] in bytes */ assert( pIdx->pKeyInfo->nPK>0 ); assert( pPk->pKeyInfo->nPK==0 ); rc = sqlite4KVCursorKey(pIdx->pKVCur, &aKey, &nKey); if( rc==SQLITE4_OK ){ int nShort; /* Size of aKey[] without PK fields */ KVByteArray *aPkKey; /* Pointer to PK buffer */ KVSize nPkKey; /* Size of aPkKey in bytes */ nShort = sqlite4VdbeShortKey(aKey, nKey, pIdx->pKeyInfo->nField - pIdx->pKeyInfo->nPK, 0 ); nPkKey = sqlite4VarintLen(pPk->iRoot) + nKey - nShort; aPkKey = sqlite4DbMallocRaw(db, nPkKey); if( aPkKey ){ putVarint32(aPkKey, pPk->iRoot); memcpy(&aPkKey[nPkKey - (nKey-nShort)], &aKey[nShort], nKey-nShort); rc = sqlite4KVCursorSeek(pPk->pKVCur, aPkKey, nPkKey, 0); if( rc==SQLITE4_NOTFOUND ){ rc = SQLITE4_CORRUPT_BKPT; } pPk->nullRow = 0; sqlite4DbFree(db, aPkKey); } pPk->pIdxCsr = 0; } } return rc; } |
Changes to src/vdbecodec.c.
︙ | ︙ | |||
184 185 186 187 188 189 190 | x = 127; while( v>x && n<8 ){ n++; x *= 256; } } return n; } /* | | > > > | 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 | x = 127; while( v>x && n<8 ){ n++; x *= 256; } } return n; } /* ** Encode nIn values from array aIn[] using the data encoding. If argument ** aPermute[] is NULL, then the nIn elements are elements 0, 1 ... (nIn-1) ** of the array. Otherwise, aPermute[0], aPermute[1] ... aPermute[nIn-1]. ** ** Assume that affinity has already been applied to all elements of the ** input array aIn[]. ** ** Space to hold the record is obtained from sqlite4DbMalloc() and should ** be freed by the caller using sqlite4DbFree() to avoid a memory leak. */ int sqlite4VdbeEncodeData( sqlite4 *db, /* The database connection */ Mem *aIn, /* Array of values to encode */ int *aPermute, /* Permutation or NULL (see above) */ int nIn, /* Number of entries in aIn[] */ u8 **pzOut, /* The output data record */ int *pnOut /* Bytes of content in pzOut */ ){ int i, j; int rc = SQLITE4_OK; int nHdr; |
︙ | ︙ | |||
221 222 223 224 225 226 227 | aOut = sqlite4DbMallocZero(db, (nIn+1)*9); if( aOut==0 ){ rc = SQLITE4_NOMEM; goto vdbeEncodeData_error; } nOut = 9; for(i=0; i<nIn; i++){ | > | | | | | | > | | | | | | | | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | aOut = sqlite4DbMallocZero(db, (nIn+1)*9); if( aOut==0 ){ rc = SQLITE4_NOMEM; goto vdbeEncodeData_error; } nOut = 9; for(i=0; i<nIn; i++){ Mem *pIn = &aIn[ aPermute ? aPermute[i] : i ]; int flags = pIn->flags; if( flags & MEM_Null ){ aOut[nOut++] = 0; }else if( flags & MEM_Int ){ i64 i1; i1 = sqlite4_num_to_int64(pIn->u.num, 0); n = significantBytes(i1); aOut[nOut++] = n+2; nPayload += n; aAux[i].n = n; }else if( flags & MEM_Real ){ sqlite4_num *p = &pIn->u.num; int e; assert( p->sign==0 || p->sign==1 ); if( p->e<0 ){ e = (p->e*-4) + 2 + p->sign; }else{ e = (p->e*4) + p->sign; } n = sqlite4PutVarint64(aAux[i].z, (sqlite4_uint64)e); n += sqlite4PutVarint64(aAux[i].z+n, p->m); aAux[i].n = n; aOut[nOut++] = n+9; nPayload += n; }else if( flags & MEM_Str ){ n = pIn->n; if( n && (encoding!=SQLITE4_UTF8 || pIn->z[0]<3) ) n++; nPayload += n; nOut += sqlite4PutVarint64(aOut+nOut, 24+3*(sqlite4_int64)n); }else{ n = pIn->n; assert( flags & MEM_Blob ); nPayload += n; nOut += sqlite4PutVarint64(aOut+nOut, 25+3*(sqlite4_int64)n); } } nHdr = nOut - 9; n = sqlite4PutVarint64(aOut, nHdr); for(i=n, j=9; j<nOut; j++) aOut[i++] = aOut[j]; nOut = i; aOut = sqlite4DbReallocOrFree(db, aOut, nOut + nPayload); if( aOut==0 ){ rc = SQLITE4_NOMEM; goto vdbeEncodeData_error; } for(i=0; i<nIn; i++){ Mem *pIn = &aIn[ aPermute ? aPermute[i] : i ]; int flags = pIn->flags; if( flags & MEM_Null ){ /* No content */ }else if( flags & MEM_Int ){ sqlite4_int64 v; v = sqlite4_num_to_int64(pIn->u.num, 0); n = aAux[i].n; aOut[nOut+(--n)] = v & 0xff; while( n ){ v >>= 8; aOut[nOut+(--n)] = v & 0xff; } nOut += aAux[i].n; }else if( flags & MEM_Real ){ memcpy(aOut+nOut, aAux[i].z, aAux[i].n); nOut += aAux[i].n; }else if( flags & MEM_Str ){ n = pIn->n; if( n ){ if( encoding==SQLITE4_UTF16LE ) aOut[nOut++] = 1; else if( encoding==SQLITE4_UTF16BE ) aOut[nOut++] = 2; else if( pIn->z[0]<3 ) aOut[nOut++] = 0; memcpy(aOut+nOut, pIn->z, n); nOut += n; } }else{ assert( flags & MEM_Blob ); memcpy(aOut+nOut, pIn->z, pIn->n); nOut += pIn->n; } } *pzOut = aOut; *pnOut = nOut; sqlite4StackFree(db, aAux); return SQLITE4_OK; |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 | */ sqlite4VdbeResolveLabel(v, pWInfo->iBreak); /* Close all of the cursors that were opened by sqlite4WhereBegin. */ assert( pWInfo->nLevel<=pTabList->nSrc ); for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){ struct SrcListItem *pTabItem = &pTabList->a[pLevel->iFrom]; Table *pTab = pTabItem->pTab; assert( pTab!=0 ); pLoop = pLevel->pWLoop; if( (pTab->tabFlags & TF_Ephemeral)==0 && pTab->pSelect==0 && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 | > | 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 | */ sqlite4VdbeResolveLabel(v, pWInfo->iBreak); /* Close all of the cursors that were opened by sqlite4WhereBegin. */ assert( pWInfo->nLevel<=pTabList->nSrc ); for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){ Index *pIdx = 0; struct SrcListItem *pTabItem = &pTabList->a[pLevel->iFrom]; Table *pTab = pTabItem->pTab; assert( pTab!=0 ); pLoop = pLevel->pWLoop; if( (pTab->tabFlags & TF_Ephemeral)==0 && pTab->pSelect==0 && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 |
︙ | ︙ | |||
6163 6164 6165 6166 6167 6168 6169 | ** ** Calls to the code generator in between sqlite4WhereBegin and ** sqlite4WhereEnd will have created code that references the table ** directly. This loop scans all that code looking for opcodes ** that reference the table and converts them into opcodes that ** reference the index. */ | > > > > > | > > < | | | < < < | 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 | ** ** Calls to the code generator in between sqlite4WhereBegin and ** sqlite4WhereEnd will have created code that references the table ** directly. This loop scans all that code looking for opcodes ** that reference the table and converts them into opcodes that ** reference the index. */ if( pLoop->wsFlags & (WHERE_INDEXED|WHERE_IDX_ONLY) ){ pIdx = pLoop->u.btree.pIndex; }else if( pLoop->wsFlags & WHERE_MULTI_OR ){ pIdx = pLevel->u.pCovidx; } if( pIdx && !db->mallocFailed ){ int *aiCover = pIdx->aiCover; int nCover = pIdx->nCover; int k, j, last; VdbeOp *pOp; pOp = sqlite4VdbeGetOp(v, pWInfo->iTop); last = sqlite4VdbeCurrentAddr(v); for(k=pWInfo->iTop; k<last; k++, pOp++){ if( pOp->p1!=pLevel->iTabCur ) continue; if( pOp->opcode==OP_Column ){ for(j=0; j<nCover; j++){ if( pOp->p2==aiCover[j] ){ pOp->p2 = j; pOp->p1 = pLevel->iIdxCur; break; } } assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || j<nCover ); } } } } /* Final cleanup */ pParse->nQueryLoop = pWInfo->savedNQueryLoop; whereInfoFree(db, pWInfo); return; } |
Changes to test/collate4.test.
︙ | ︙ | |||
432 433 434 435 436 437 438 | execsql { DROP INDEX collate4i1; CREATE INDEX collate4i1 ON collate4t1(a, b, c COLLATE text); } count { SELECT * FROM collate4t2 NATURAL JOIN collate4t1; } | | | 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 | execsql { DROP INDEX collate4i1; CREATE INDEX collate4i1 ON collate4t1(a, b, c COLLATE text); } count { SELECT * FROM collate4t2 NATURAL JOIN collate4t1; } } {0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 25} do_test collate4-2.2.10 { execsql { DROP TABLE collate4t1; DROP TABLE collate4t2; } } {} |
︙ | ︙ |
Changes to test/covidx.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # INDEX statement. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix covidx do_execsql_test 1.0 { CREATE TABLE t1(a, b, c); CREATE TABLE t2("123abc", "odd column name"); CREATE TABLE "frivolous table name"(x, y); } foreach {tn sql res} { | > > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # INDEX statement. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix covidx #------------------------------------------------------------------------- # do_execsql_test 1.0 { CREATE TABLE t1(a, b, c); CREATE TABLE t2("123abc", "odd column name"); CREATE TABLE "frivolous table name"(x, y); } foreach {tn sql res} { |
︙ | ︙ | |||
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | } { do_catchsql_test 1.$tn "CREATE INDEX i1 ON $sql" $res execsql { DROP INDEX IF EXISTS i1; } } do_execsql_test 2.1 { CREATE TABLE x1(x); CREATE INDEX xi1 ON x1(x) COVERING (x); CREATE INDEX xi2 ON x1(x) COVERING ALL ; SELECT sql FROM sqlite_master where type = 'index'; } { {CREATE INDEX xi1 ON x1(x) COVERING (x)} {CREATE INDEX xi2 ON x1(x) COVERING ALL} } finish_test | > > > > > > > > > > > > > > > > | 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 | } { do_catchsql_test 1.$tn "CREATE INDEX i1 ON $sql" $res execsql { DROP INDEX IF EXISTS i1; } } #------------------------------------------------------------------------- # do_execsql_test 2.1 { CREATE TABLE x1(x); CREATE INDEX xi1 ON x1(x) COVERING (x); CREATE INDEX xi2 ON x1(x) COVERING ALL ; SELECT sql FROM sqlite_master where type = 'index'; } { {CREATE INDEX xi1 ON x1(x) COVERING (x)} {CREATE INDEX xi2 ON x1(x) COVERING ALL} } #------------------------------------------------------------------------- # reset_db do_execsql_test 3.1 { CREATE TABLE t1(a PRIMARY KEY, b, c); CREATE INDEX i1 ON t1(b) COVERING(c, b); } {} do_execsql_test 3.2 { INSERT INTO t1 VALUES(1, 'x', 'y'); } {} do_execsql_test 3.3 { SELECT c FROM t1 ORDER BY b; } {y} finish_test |