/ Check-in [45efc94f]
Login

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

Overview
Comment:Add a procedure to handle the messy details of allocating an Index object from the heap.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | omit-rowid
Files: files | file ages | folders
SHA1: 45efc94f9a8169433ffcb4aa35760551c55df4c4
User & Date: drh 2013-10-22 14:28:02
Context
2013-10-22
18:01
The Index object now has nKeyCol and nColumn. nColumn is the total number of columns and nKeyCol is the number of key columns. Currently these always differ by one. Refactor aiColumn[] to be of type i16 instead of int. check-in: a106ce86 user: drh tags: omit-rowid
14:28
Add a procedure to handle the messy details of allocating an Index object from the heap. check-in: 45efc94f user: drh tags: omit-rowid
10:23
Extra backwards-compatibility tests verify that UNIQUE and PRIMARY KEY indices are created in the correct order. Other backwards-compatibility tests already cover this, but it does not hurt to double up. check-in: 5ca0ea2e user: drh tags: omit-rowid
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/build.c.

  2510   2510     sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
  2511   2511     sqlite3VdbeJumpHere(v, addr1);
  2512   2512   
  2513   2513     sqlite3VdbeAddOp1(v, OP_Close, iTab);
  2514   2514     sqlite3VdbeAddOp1(v, OP_Close, iIdx);
  2515   2515     sqlite3VdbeAddOp1(v, OP_Close, iSorter);
  2516   2516   }
         2517  +
         2518  +/*
         2519  +** Allocate heap space to hold an Index object with nCol columns.
         2520  +**
         2521  +** Increase the allocation size to provide an extra nExtra bytes
         2522  +** of 8-byte aligned space after the Index object and return a
         2523  +** pointer to this extra space in *ppExtra.
         2524  +*/
         2525  +Index *sqlite3AllocateIndexObject(
         2526  +  sqlite3 *db,         /* Database connection */
         2527  +  int nCol,            /* Number of columns in the index */
         2528  +  int nExtra,          /* Number of bytes of extra space to alloc */
         2529  +  char **ppExtra       /* Pointer to the "extra" space */
         2530  +){
         2531  +  Index *p;            /* Allocated index object */
         2532  +  int nByte;           /* Bytes of space for Index object + arrays */
         2533  +
         2534  +  nByte = ROUND8(sizeof(Index)) +              /* Index structure  */
         2535  +          ROUND8(sizeof(char*)*nCol) +         /* Index.azColl     */
         2536  +          ROUND8(sizeof(tRowcnt)*(nCol+1) +    /* Index.aiRowEst   */
         2537  +                 sizeof(int)*nCol +            /* Index.aiColumn   */
         2538  +                 sizeof(u8)*nCol);             /* Index.aSortOrder */
         2539  +  p = sqlite3DbMallocZero(db, nByte + nExtra);
         2540  +  if( p ){
         2541  +    char *pExtra = ((char*)p)+ROUND8(sizeof(Index));
         2542  +    p->azColl = (char**)pExtra;      pExtra += ROUND8(sizeof(char*)*nCol);
         2543  +    p->aiRowEst = (tRowcnt*)pExtra;  pExtra += sizeof(tRowcnt)*(nCol+1);
         2544  +    p->aiColumn = (int*)pExtra;      pExtra += sizeof(int)*nCol;
         2545  +    p->aSortOrder = (u8*)pExtra;
         2546  +    p->nColumn = nCol;
         2547  +    *ppExtra = ((char*)p) + nByte;
         2548  +  }
         2549  +  return p;
         2550  +}
  2517   2551   
  2518   2552   /*
  2519   2553   ** Create a new index for an SQL table.  pName1.pName2 is the name of the index 
  2520   2554   ** and pTblList is the name of the table that is to be indexed.  Both will 
  2521   2555   ** be NULL for a primary key or an index that is created to satisfy a
  2522   2556   ** UNIQUE constraint.  If pTable and pIndex are NULL, use pParse->pNewTable
  2523   2557   ** as the table to be indexed.  pParse->pNewTable is a table that is
................................................................................
  2554   2588     int sortOrderMask;   /* 1 to honor DESC in index.  0 to ignore. */
  2555   2589     sqlite3 *db = pParse->db;
  2556   2590     Db *pDb;             /* The specific table containing the indexed database */
  2557   2591     int iDb;             /* Index of the database that is being written */
  2558   2592     Token *pName = 0;    /* Unqualified name of the index to create */
  2559   2593     struct ExprList_item *pListItem; /* For looping over pList */
  2560   2594     const Column *pTabCol;           /* A column in the table */
  2561         -  int nCol;                        /* Number of columns */
  2562   2595     int nExtra = 0;                  /* Space allocated for zExtra[] */
  2563   2596     char *zExtra;                    /* Extra space after the Index object */
  2564   2597   
  2565   2598     assert( pParse->nErr==0 );      /* Never called with prior errors */
  2566   2599     if( db->mallocFailed || IN_DECLARE_VTAB ){
  2567   2600       goto exit_create_index;
  2568   2601     }
................................................................................
  2726   2759       }
  2727   2760     }
  2728   2761   
  2729   2762     /* 
  2730   2763     ** Allocate the index structure. 
  2731   2764     */
  2732   2765     nName = sqlite3Strlen30(zName);
  2733         -  nCol = pList->nExpr;
  2734         -  pIndex = sqlite3DbMallocZero(db, 
  2735         -      ROUND8(sizeof(Index)) +              /* Index structure  */
  2736         -      ROUND8(sizeof(tRowcnt)*(nCol+1)) +   /* Index.aiRowEst   */
  2737         -      sizeof(char *)*nCol +                /* Index.azColl     */
  2738         -      sizeof(int)*nCol +                   /* Index.aiColumn   */
  2739         -      sizeof(u8)*nCol +                    /* Index.aSortOrder */
  2740         -      nName + 1 +                          /* Index.zName      */
  2741         -      nExtra                               /* Collation sequence names */
  2742         -  );
         2766  +  pIndex = sqlite3AllocateIndexObject(db, pList->nExpr,
         2767  +                                      nName + nExtra + 1, &zExtra);
  2743   2768     if( db->mallocFailed ){
  2744   2769       goto exit_create_index;
  2745   2770     }
  2746         -  zExtra = (char*)pIndex;
  2747         -  pIndex->aiRowEst = (tRowcnt*)&zExtra[ROUND8(sizeof(Index))];
  2748         -  pIndex->azColl = (char**)
  2749         -     ((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1));
  2750   2771     assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) );
  2751   2772     assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) );
  2752         -  pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]);
  2753         -  pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]);
  2754         -  pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]);
  2755         -  zExtra = (char *)(&pIndex->zName[nName+1]);
         2773  +  pIndex->zName = zExtra;
         2774  +  zExtra += nName + 1;
  2756   2775     memcpy(pIndex->zName, zName, nName+1);
  2757   2776     pIndex->pTable = pTab;
  2758   2777     pIndex->nColumn = pList->nExpr;
  2759   2778     pIndex->onError = (u8)onError;
  2760   2779     pIndex->uniqNotNull = onError==OE_Abort;
  2761   2780     pIndex->autoIndex = (u8)(pName==0);
  2762   2781     pIndex->pSchema = db->aDb[iDb].pSchema;

Changes to src/sqliteInt.h.

  2822   2822                                         Token*, Select*, Expr*, IdList*);
  2823   2823   void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
  2824   2824   int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
  2825   2825   void sqlite3SrcListShiftJoinType(SrcList*);
  2826   2826   void sqlite3SrcListAssignCursors(Parse*, SrcList*);
  2827   2827   void sqlite3IdListDelete(sqlite3*, IdList*);
  2828   2828   void sqlite3SrcListDelete(sqlite3*, SrcList*);
         2829  +Index *sqlite3AllocateIndexObject(sqlite3*,int,int,char**);
  2829   2830   Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
  2830   2831                             Expr*, int, int);
  2831   2832   void sqlite3DropIndex(Parse*, SrcList*, int);
  2832   2833   int sqlite3Select(Parse*, Select*, SelectDest*);
  2833   2834   Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
  2834   2835                            Expr*,ExprList*,u16,Expr*,Expr*);
  2835   2836   void sqlite3SelectDelete(sqlite3*, Select*);

Changes to src/where.c.

  2004   2004     struct SrcList_item *pSrc,  /* The FROM clause term to get the next index */
  2005   2005     Bitmask notReady,           /* Mask of cursors that are not available */
  2006   2006     WhereLevel *pLevel          /* Write new index here */
  2007   2007   ){
  2008   2008     int nColumn;                /* Number of columns in the constructed index */
  2009   2009     WhereTerm *pTerm;           /* A single term of the WHERE clause */
  2010   2010     WhereTerm *pWCEnd;          /* End of pWC->a[] */
  2011         -  int nByte;                  /* Byte of memory needed for pIdx */
  2012   2011     Index *pIdx;                /* Object describing the transient index */
  2013   2012     Vdbe *v;                    /* Prepared statement under construction */
  2014   2013     int addrInit;               /* Address of the initialization bypass jump */
  2015   2014     Table *pTable;              /* The table being indexed */
  2016   2015     KeyInfo *pKeyinfo;          /* Key information for the index */   
  2017   2016     int addrTop;                /* Top of the index fill loop */
  2018   2017     int regRecord;              /* Register holding an index record */
  2019   2018     int n;                      /* Column counter */
  2020   2019     int i;                      /* Loop counter */
  2021   2020     int mxBitCol;               /* Maximum column in pSrc->colUsed */
  2022   2021     CollSeq *pColl;             /* Collating sequence to on a column */
  2023   2022     WhereLoop *pLoop;           /* The Loop object */
         2023  +  char *zNotUsed;             /* Extra space on the end of pIdx */
  2024   2024     Bitmask idxCols;            /* Bitmap of columns used for indexing */
  2025   2025     Bitmask extraCols;          /* Bitmap of additional columns */
  2026   2026     u8 sentWarning = 0;         /* True if a warnning has been issued */
  2027   2027   
  2028   2028     /* Generate code to skip over the creation and initialization of the
  2029   2029     ** transient index on 2nd and subsequent iterations of the loop. */
  2030   2030     v = pParse->pVdbe;
................................................................................
  2079   2079     }
  2080   2080     if( pSrc->colUsed & MASKBIT(BMS-1) ){
  2081   2081       nColumn += pTable->nCol - BMS + 1;
  2082   2082     }
  2083   2083     pLoop->wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY;
  2084   2084   
  2085   2085     /* Construct the Index object to describe this index */
  2086         -  nByte = sizeof(Index);
  2087         -  nByte += nColumn*sizeof(int);     /* Index.aiColumn */
  2088         -  nByte += nColumn*sizeof(char*);   /* Index.azColl */
  2089         -  nByte += nColumn;                 /* Index.aSortOrder */
  2090         -  pIdx = sqlite3DbMallocZero(pParse->db, nByte);
         2086  +  pIdx = sqlite3AllocateIndexObject(pParse->db, nColumn, 0, &zNotUsed);
  2091   2087     if( pIdx==0 ) return;
  2092   2088     pLoop->u.btree.pIndex = pIdx;
  2093         -  pIdx->azColl = (char**)&pIdx[1];
  2094         -  pIdx->aiColumn = (int*)&pIdx->azColl[nColumn];
  2095         -  pIdx->aSortOrder = (u8*)&pIdx->aiColumn[nColumn];
  2096   2089     pIdx->zName = "auto-index";
  2097         -  pIdx->nColumn = nColumn;
  2098   2090     pIdx->pTable = pTable;
  2099   2091     n = 0;
  2100   2092     idxCols = 0;
  2101   2093     for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
  2102   2094       if( termCanDriveIndex(pTerm, pSrc, notReady) ){
  2103   2095         int iCol = pTerm->u.leftColumn;
  2104   2096         Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol);