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: 7f6b4708c2a5e73d412febabf73899db96308afd
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
Unified Diff Ignore Whitespace Patch
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
1453
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);
      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;












      }
      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
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
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368

2369
2370
2371
2372
2373
2374
2375
      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







|





|








>







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
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
    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 *
**







<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<







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
3605

3606
3607
3608
3609
3610
3611
3612

  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);







|
>







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


3718
3719
3720
3721
3722
3723
3724
3725
  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;







>
>
|







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
430
431
432
433
434
435
436
437
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








|







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
191


192
193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
    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;







|
>
>










>







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

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
  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;







>
|




|





|













|
|



|












>
|




|











|



|
|




|
|







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





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
    ** 
    ** 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;
}







>
>
>
>
>
|
>
>


<






|
|





|
<
<
<











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
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
# 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