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 | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
7f6b4708c2a5e73d412febabf73899db |
User & Date: | dan 2013-07-23 16:50:55 |
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
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
....
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
|
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); } /* Generate code to serialize array of registers into a database record. */ regRec = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp3(v, OP_MakeRecord, regContent, pTab->nCol, regRec); sqlite4TableAffinityStr(v, pTab); sqlite4ExprCacheAffinityChange(pParse, regContent, pTab->nCol); /* 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); ................................................................................ } else if( aRegIdx[i] ){ int regData = 0; int flags = 0; if( pIdx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){ regData = regRec; flags = pik_flags; } sqlite4VdbeAddOp3(v, OP_IdxInsert, baseCur+i, regData, aRegIdx[i]); sqlite4VdbeChangeP5(v, flags); } } } |
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
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
....
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); ................................................................................ } 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 .... 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 .... 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 .... 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 .... 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 .... 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 .... 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 |
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]; ................................................................................ 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 ); ................................................................................ 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 rescord */ 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, 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); } } 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 ................................................................................ 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{ assert( pIdx->pKeyInfo->nPK>0 ); assert( pPk->pKeyInfo->nPK==0 ); rc = sqlite4KVCursorKey(pIdx->pKVCur, &aKey, &nKey); if( rc==SQLITE4_OK ){ 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); } } } break; } /* Opcode: SeekGe P1 P2 P3 P4 * ** ................................................................................ ** 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 * * * * * ** ................................................................................ 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]; assert( pC!=0 ); 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); ................................................................................ i64 v; const KVByteArray *aKey; KVSize nKey; int n; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=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; |
> > > > > > | | > | < < < < < < < < < < < < < < < < < < < < < > | > > > | |
2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 .... 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 .... 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 .... 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 .... 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 .... 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 .... 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 |
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]; ................................................................................ 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 ); ................................................................................ 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 ................................................................................ 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 * ** ................................................................................ ** 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 * * * * * ** ................................................................................ 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); ................................................................................ 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 ... 359 360 361 362 363 364 365 366 367 368 369 370 371 372 ... 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 |
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; }; /* ................................................................................ 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 */ ................................................................................ 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 sqlite4VdbeRollback(sqlite4 *db, int iLevel); int sqlite4VdbeCommit(sqlite4 *db, int iLevel); #ifdef SQLITE4_DEBUG void sqlite4VdbeMemAboutToChange(Vdbe*,Mem*); #endif |
> > | |
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 ... 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 ... 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 |
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; }; /* ................................................................................ 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 */ ................................................................................ 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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
...
221
222
223
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
|
x = 127; while( v>x && n<8 ){ n++; x *= 256; } } return n; } /* ** Encode 1 or more values using the data encoding. ** ** 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 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; ................................................................................ aOut = sqlite4DbMallocZero(db, (nIn+1)*9); if( aOut==0 ){ rc = SQLITE4_NOMEM; goto vdbeEncodeData_error; } nOut = 9; for(i=0; i<nIn; i++){ int flags = aIn[i].flags; if( flags & MEM_Null ){ aOut[nOut++] = 0; }else if( flags & MEM_Int ){ i64 i1; i1 = sqlite4_num_to_int64(aIn[i].u.num, 0); n = significantBytes(i1); aOut[nOut++] = n+2; nPayload += n; aAux[i].n = n; }else if( flags & MEM_Real ){ sqlite4_num *p = &aIn[i].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 = aIn[i].n; if( n && (encoding!=SQLITE4_UTF8 || aIn[i].z[0]<3) ) n++; nPayload += n; nOut += sqlite4PutVarint64(aOut+nOut, 24+3*(sqlite4_int64)n); }else{ n = aIn[i].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++){ int flags = aIn[i].flags; if( flags & MEM_Null ){ /* No content */ }else if( flags & MEM_Int ){ sqlite4_int64 v; v = sqlite4_num_to_int64(aIn[i].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 = aIn[i].n; if( n ){ if( encoding==SQLITE4_UTF16LE ) aOut[nOut++] = 1; else if( encoding==SQLITE4_UTF16BE ) aOut[nOut++] = 2; else if( aIn[i].z[0]<3 ) aOut[nOut++] = 0; memcpy(aOut+nOut, aIn[i].z, n); nOut += n; } }else{ assert( flags & MEM_Blob ); memcpy(aOut+nOut, aIn[i].z, aIn[i].n); nOut += aIn[i].n; } } *pzOut = aOut; *pnOut = nOut; sqlite4StackFree(db, aAux); return SQLITE4_OK; |
|
>
>
>
>
|
|
|
|
|
|
>
|
|
|
|
|
|
|
|
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
...
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
|
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; ................................................................................ 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
....
6163
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
|
*/ 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 ................................................................................ ** ** 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_AUTO_INDEX) && !db->mallocFailed ){ int k, j, last; VdbeOp *pOp; Index *pIdx = pLoop->u.btree.pIndex; 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<pIdx->nColumn; j++){ if( pOp->p2==pIdx->aiColumn[j] ){ pOp->p2 = j; pOp->p1 = pLevel->iIdxCur; break; } } assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || j<pIdx->nColumn ); }else if( pOp->opcode==OP_Rowid ){ pOp->p1 = pLevel->iIdxCur; pOp->opcode = OP_IdxRowid; } } } } /* Final cleanup */ pParse->nQueryLoop = pWInfo->savedNQueryLoop; whereInfoFree(db, pWInfo); return; } |
>
>
>
>
>
>
|
>
>
<
|
|
|
<
<
<
|
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
....
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
|
*/ 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 ................................................................................ ** ** 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 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 33}
do_test collate4-2.2.10 {
execsql {
DROP TABLE collate4t1;
DROP TABLE collate4t2;
}
} {}
|
| |
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
..
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
# 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} {
................................................................................
} {
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
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
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
|
# 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} { ................................................................................ } { 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 |