Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix the sqlite4RefillIndex() function. This removes the broken (and disabled) merge-sort code.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | primary-keys
Files: files | file ages | folders
SHA1: 9ac54fff5f2e5eba2c5e871ff32282b64bca1e02
User & Date: dan 2012-04-20 20:15:20.170
Context
2012-04-20
20:38
Changes so that things work without SQLITE_ENABLE_LSM. Closed-Leaf check-in: 49e419f4e8 user: dan tags: primary-keys
20:15
Fix the sqlite4RefillIndex() function. This removes the broken (and disabled) merge-sort code. check-in: 9ac54fff5f user: dan tags: primary-keys
18:35
Changes to where.c to use the PK columns appended to each auxiliary index entry. check-in: 4c1dca78b3 user: dan tags: primary-keys
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/build.c.
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
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

2376
2377
2378
2379

2380
2381





2382

2383
2384

2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
}

/*
** Generate code that will erase and refill index *pIdx.  This is
** used to initialize a newly created index or to recompute the
** content of an index in response to a REINDEX command.
*/
static void sqlite4RefillIndex(Parse *pParse, Index *pIndex){
  Table *pTab = pIndex->pTable;  /* The table that is indexed */
  int iTab = pParse->nTab++;     /* Cursor used for pTab */
  int iIdx = pParse->nTab++;     /* Cursor used for pIndex */
  int iSorter;                   /* Cursor opened by OpenSorter (if in use) */
  int addr1;                     /* Address of top of loop */
  int addr2;                     /* Address to jump to for next iteration */
  int tnum;                      /* Root page of index */
  Vdbe *v;                       /* Generate code into this virtual machine */
  KeyInfo *pKey;                 /* KeyInfo for index */
#ifdef SQLITE_OMIT_MERGE_SORT
  int regIdxKey;                 /* Registers containing the index key */
#endif
  int regRecord;                 /* Register holding assemblied index record */
  sqlite4 *db = pParse->db;      /* The database connection */
  int iDb = sqlite4SchemaToIndex(db, pIndex->pSchema);


#ifndef SQLITE_OMIT_AUTHORIZATION
  if( sqlite4AuthCheck(pParse, SQLITE_REINDEX, pIndex->zName, 0,
      db->aDb[iDb].zName ) ){
    return;
  }
#endif

  /* Require a write-lock on the table to perform this operation */
  sqlite4TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);

  v = sqlite4GetVdbe(pParse);
  if( v==0 ) return;
  tnum = pIndex->tnum;


  sqlite4VdbeAddOp2(v, OP_Clear, tnum, iDb);
  pKey = sqlite4IndexKeyinfo(pParse, pIndex);
  sqlite4VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
                    (char *)pKey, P4_KEYINFO_HANDOFF);

#ifndef SQLITE_OMIT_MERGE_SORT

  /* Open the sorter cursor if we are to use one. */
  iSorter = pParse->nTab++;
  sqlite4VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
#else
  iSorter = iTab;
#endif


  /* Open the table. Loop through all rows of the table, inserting index
  ** records into the sorter. */
  sqlite4OpenPrimaryKey(pParse, iTab, iDb, pTab, OP_OpenRead);

  addr1 = sqlite4VdbeAddOp2(v, OP_Rewind, iTab, 0);
  regRecord = sqlite4GetTempRange(pParse,2);







#ifndef SQLITE_OMIT_MERGE_SORT
  sqlite4GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1, iIdx);

  sqlite4VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
  sqlite4VdbeAddOp2(v, OP_Next, iTab, addr1+1);
  sqlite4VdbeJumpHere(v, addr1);
  addr1 = sqlite4VdbeAddOp2(v, OP_SorterSort, iSorter, 0);
  if( pIndex->onError!=OE_None ){
    int j2 = sqlite4VdbeCurrentAddr(v) + 3;
    sqlite4VdbeAddOp2(v, OP_Goto, 0, j2);
    addr2 = sqlite4VdbeCurrentAddr(v);
    sqlite4VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
    sqlite4HaltConstraint(
        pParse, OE_Abort, "indexed columns are not unique", P4_STATIC
    );
  }else{
    addr2 = sqlite4VdbeCurrentAddr(v);
  }
  sqlite4VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
  sqlite4VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);  
  sqlite4VdbeChangeP5(v, OPFLAG_USESEEKRESULT | OPFLAG_APPENDBIAS);
#else
  regIdxKey = sqlite4GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1, iIdx);
  addr2 = addr1 + 1;
  if( pIndex->onError!=OE_None ){
    const int regRowid = regIdxKey + pIndex->nColumn;
    const int j2 = sqlite4VdbeCurrentAddr(v) + 2;
    void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);

    /* The registers accessed by the OP_IsUnique opcode were allocated
    ** using sqlite4GetTempRange() inside of the sqlite4GenerateIndexKey()
    ** call above. Just before that function was freed they were released
    ** (made available to the compiler for reuse) using 
    ** sqlite4ReleaseTempRange(). So in some ways having the OP_IsUnique
    ** opcode use the values stored within seems dangerous. However, since
    ** we can be sure that no other temp registers have been allocated
    ** since sqlite4ReleaseTempRange() was called, it is safe to do so.
    */
    sqlite4VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
    sqlite4HaltConstraint(
        pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
  }
  sqlite4VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, regRecord+1);
  sqlite4VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
#endif
  sqlite4ReleaseTempRange(pParse, regRecord, 2);
  sqlite4VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
  sqlite4VdbeJumpHere(v, addr1);

  sqlite4VdbeAddOp1(v, OP_Close, iTab);
  sqlite4VdbeAddOp1(v, OP_Close, iIdx);
  sqlite4VdbeAddOp1(v, OP_Close, iSorter);
}

/*
** Create a new index for an SQL table.  pName1.pName2 is the name of the index 
** and pTblList is the name of the table that is to be indexed.  Both will 
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable







|
|
|
|





<
<
|
<


|
>


|





<
<
|


|
>
>
|
|
<
<

<
>
|
<
|
<
<
<
>

|
<
<
>


>
>
>
>
>
|
>
|
|
>
|


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



<







2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342


2343

2344
2345
2346
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
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386







































2387


2388
2389
2390

2391
2392
2393
2394
2395
2396
2397
}

/*
** Generate code that will erase and refill index *pIdx.  This is
** used to initialize a newly created index or to recompute the
** content of an index in response to a REINDEX command.
*/
static void sqlite4RefillIndex(Parse *pParse, Index *pIdx){
  Table *pTab = pIdx->pTable;    /* The table that is indexed */
  int iTab = pParse->nTab++;     /* Cursor used for PK of pTab */
  int iIdx = pParse->nTab++;     /* Cursor used for pIdx */
  int iSorter;                   /* Cursor opened by OpenSorter (if in use) */
  int addr1;                     /* Address of top of loop */
  int addr2;                     /* Address to jump to for next iteration */
  int tnum;                      /* Root page of index */
  Vdbe *v;                       /* Generate code into this virtual machine */


  int regKey;                    /* Registers containing the index key */

  int regRecord;                 /* Register holding assemblied index record */
  sqlite4 *db = pParse->db;      /* The database connection */
  int iDb = sqlite4SchemaToIndex(db, pIdx->pSchema);
  Index *pPk;

#ifndef SQLITE_OMIT_AUTHORIZATION
  if( sqlite4AuthCheck(pParse, SQLITE_REINDEX, pIdx->zName, 0,
      db->aDb[iDb].zName ) ){
    return;
  }
#endif



  pPk = sqlite4FindPrimaryKey(pTab, 0);
  v = sqlite4GetVdbe(pParse);
  if( v==0 ) return;

  /* A write-lock on the table is required to perform this operation. Easiest
  ** way to do this is to open a write-cursor on the PK - even though this
  ** operation only requires read access.  */
  sqlite4OpenPrimaryKey(pParse, iTab, iDb, pTab, OP_OpenWrite);




  /* Delete the current contents (if any) of the index. Then open a write
  ** cursor on it.  */

  sqlite4VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb);



  sqlite4OpenIndex(pParse, iIdx, iDb, pIdx, OP_OpenWrite);

  /* Loop through the contents of the PK index. At each row, insert the


  ** corresponding entry into the auxiliary index.  */
  addr1 = sqlite4VdbeAddOp2(v, OP_Rewind, iTab, 0);
  regRecord = sqlite4GetTempRange(pParse,2);
  regKey = sqlite4GetTempReg(pParse);
  sqlite4EncodeIndexKey(pParse, pPk, iTab, pIdx, iIdx, regKey);
  if( pIdx->onError!=OE_None ){
    const char *zErr = "indexed columns are not unique";
    int addrTest;
     
    addrTest = sqlite4VdbeAddOp4Int(v, OP_IsUnique, iIdx, 0, regKey, 0);
    sqlite4HaltConstraint(pParse, OE_Abort, zErr, P4_STATIC);
    sqlite4VdbeJumpHere(v, addrTest);
  }
  sqlite4VdbeAddOp3(v, OP_IdxInsert, iIdx, 0, regKey);  
  sqlite4VdbeAddOp2(v, OP_Next, iTab, addr1+1);
  sqlite4VdbeJumpHere(v, addr1);







































  sqlite4ReleaseTempReg(pParse, regKey);



  sqlite4VdbeAddOp1(v, OP_Close, iTab);
  sqlite4VdbeAddOp1(v, OP_Close, iIdx);

}

/*
** Create a new index for an SQL table.  pName1.pName2 is the name of the index 
** and pTblList is the name of the table that is to be indexed.  Both will 
** be NULL for a primary key or an index that is created to satisfy a
** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable
Changes to src/delete.c.
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520

  /* Jump here if the row had already been deleted before any BEFORE
  ** trigger programs were invoked. Or if a trigger program throws a 
  ** RAISE(IGNORE) exception.  */
  sqlite4VdbeResolveLabel(v, iLabel);
}

static void generateIndexKey(
  Parse *pParse,
  Index *pPk, int iPkCsr,
  Index *pIdx, int iIdxCsr,
  int regOut
){
  Vdbe *v = pParse->pVdbe;        /* VM to write code to */
  int nTmpReg;                    /* Number of temp registers required */







|







506
507
508
509
510
511
512
513
514
515
516
517
518
519
520

  /* Jump here if the row had already been deleted before any BEFORE
  ** trigger programs were invoked. Or if a trigger program throws a 
  ** RAISE(IGNORE) exception.  */
  sqlite4VdbeResolveLabel(v, iLabel);
}

void sqlite4EncodeIndexKey(
  Parse *pParse,
  Index *pPk, int iPkCsr,
  Index *pIdx, int iIdxCsr,
  int regOut
){
  Vdbe *v = pParse->pVdbe;        /* VM to write code to */
  int nTmpReg;                    /* Number of temp registers required */
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593

  regKey = sqlite4GetTempReg(pParse);
  pPk = sqlite4FindPrimaryKey(pTab, &iPk);

  for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
    if( pIdx!=pPk && (aRegIdx==0 || aRegIdx[i]>0) ){
      int addrNotFound;
      generateIndexKey(pParse, pPk, baseCur+iPk, pIdx, baseCur+i, regKey);
      addrNotFound = sqlite4VdbeAddOp4(v,
          OP_NotFound, baseCur+i, 0, regKey, 0, P4_INT32
      );
      sqlite4VdbeAddOp1(v, OP_Delete, baseCur+i);
      sqlite4VdbeJumpHere(v, addrNotFound);
    }
  }







|







579
580
581
582
583
584
585
586
587
588
589
590
591
592
593

  regKey = sqlite4GetTempReg(pParse);
  pPk = sqlite4FindPrimaryKey(pTab, &iPk);

  for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
    if( pIdx!=pPk && (aRegIdx==0 || aRegIdx[i]>0) ){
      int addrNotFound;
      sqlite4EncodeIndexKey(pParse, pPk, baseCur+iPk, pIdx, baseCur+i, regKey);
      addrNotFound = sqlite4VdbeAddOp4(v,
          OP_NotFound, baseCur+i, 0, regKey, 0, P4_INT32
      );
      sqlite4VdbeAddOp1(v, OP_Delete, baseCur+i);
      sqlite4VdbeJumpHere(v, addrNotFound);
    }
  }
Changes to src/sqliteInt.h.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#define SQLITE_OMIT_WAL 1
#define SQLITE_OMIT_VACUUM 1
#define SQLITE_OMIT_AUTOVACUUM 1
#define SQLITE_OMIT_SHARED_CACHE 1
/*#define SQLITE_OMIT_PAGER_PRAGMAS 1*/
#define SQLITE_OMIT_PROGRESS_CALLBACK 1

#define SQLITE_OMIT_MERGE_SORT 1 

/*
** These #defines should enable >2GB file support on POSIX if the
** underlying operating system supports it.  If the OS lacks
** large file support, or if the OS is windows, these should be no-ops.
**
** Ticket #2739:  The _LARGEFILE_SOURCE macro must appear before any







|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#define SQLITE_OMIT_WAL 1
#define SQLITE_OMIT_VACUUM 1
#define SQLITE_OMIT_AUTOVACUUM 1
#define SQLITE_OMIT_SHARED_CACHE 1
/*#define SQLITE_OMIT_PAGER_PRAGMAS 1*/
#define SQLITE_OMIT_PROGRESS_CALLBACK 1

#define SQLITE_OMIT_MERGE_SORT 1

/*
** These #defines should enable >2GB file support on POSIX if the
** underlying operating system supports it.  If the OS lacks
** large file support, or if the OS is windows, these should be no-ops.
**
** Ticket #2739:  The _LARGEFILE_SOURCE macro must appear before any
2875
2876
2877
2878
2879
2880
2881

2882
2883
2884
2885
2886
2887
2888
int sqlite4ExprCanBeNull(const Expr*);
void sqlite4ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
int sqlite4ExprNeedsNoAffinityChange(const Expr*, char);
int sqlite4IsRowid(const char*);
void sqlite4GenerateRowDelete(Parse*, Table*, int, int, int, Trigger *, int);
void sqlite4GenerateRowIndexDelete(Parse*, Table*, int, int*);
int sqlite4GenerateIndexKey(Parse*, Index*, int, int, int, int);

void sqlite4GenerateConstraintChecks(Parse*,Table*,int,int,
                                     int*,int,int,int,int,int*);
void sqlite4CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
int sqlite4OpenTableAndIndices(Parse*, Table*, int, int);
void sqlite4BeginWriteOperation(Parse*, int, int);
void sqlite4MultiWrite(Parse*);
void sqlite4MayAbort(Parse*);







>







2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
int sqlite4ExprCanBeNull(const Expr*);
void sqlite4ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
int sqlite4ExprNeedsNoAffinityChange(const Expr*, char);
int sqlite4IsRowid(const char*);
void sqlite4GenerateRowDelete(Parse*, Table*, int, int, int, Trigger *, int);
void sqlite4GenerateRowIndexDelete(Parse*, Table*, int, int*);
int sqlite4GenerateIndexKey(Parse*, Index*, int, int, int, int);
void sqlite4EncodeIndexKey(Parse *, Index *, int, Index *, int, int);
void sqlite4GenerateConstraintChecks(Parse*,Table*,int,int,
                                     int*,int,int,int,int,int*);
void sqlite4CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
int sqlite4OpenTableAndIndices(Parse*, Table*, int, int);
void sqlite4BeginWriteOperation(Parse*, int, int);
void sqlite4MultiWrite(Parse*);
void sqlite4MayAbort(Parse*);
Changes to src/where.c.
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608

609
610
611
612
613
614
615
  int iCur,             /* Cursor number of LHS */
  int iColumn,          /* Column number of LHS */
  Bitmask notReady,     /* RHS must not overlap with this mask */
  u32 op,               /* Mask of WO_xx values describing operator */
  Index *pIdx           /* Must be compatible with this index, if not NULL */
){
  sqlite4 *db = pWC->pParse->db;  /* Database handle */
  Table *pTab = pIdx->pTable;     /* Table object for cursor iCur */
  WhereTerm *pTerm;
  int k;

  assert( iCur>=0 );
  op &= WO_ALL;
  for(; pWC; pWC=pWC->pOuter){
    for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
      if( pTerm->leftCursor==iCur
         && (pTerm->prereqRight & notReady)==0
         && pTerm->u.leftColumn==iColumn
         && (pTerm->eOperator & op)!=0
      ){
        if( iColumn>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){

          const char *zColl;      /* Collation sequence used by index */
          CollSeq *pColl;         /* Collation sequence used by expression */
          Expr *pX = pTerm->pExpr;
          int j;
          Parse *pParse = pWC->pParse;
  
          if( !sqlite4IndexAffinityOk(pX, pTab->aCol[iColumn].affinity) ){







<













>







588
589
590
591
592
593
594

595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
  int iCur,             /* Cursor number of LHS */
  int iColumn,          /* Column number of LHS */
  Bitmask notReady,     /* RHS must not overlap with this mask */
  u32 op,               /* Mask of WO_xx values describing operator */
  Index *pIdx           /* Must be compatible with this index, if not NULL */
){
  sqlite4 *db = pWC->pParse->db;  /* Database handle */

  WhereTerm *pTerm;
  int k;

  assert( iCur>=0 );
  op &= WO_ALL;
  for(; pWC; pWC=pWC->pOuter){
    for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
      if( pTerm->leftCursor==iCur
         && (pTerm->prereqRight & notReady)==0
         && pTerm->u.leftColumn==iColumn
         && (pTerm->eOperator & op)!=0
      ){
        if( iColumn>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){
          Table *pTab = pIdx->pTable;
          const char *zColl;      /* Collation sequence used by index */
          CollSeq *pColl;         /* Collation sequence used by expression */
          Expr *pX = pTerm->pExpr;
          int j;
          Parse *pParse = pWC->pParse;
  
          if( !sqlite4IndexAffinityOk(pX, pTab->aCol[iColumn].affinity) ){