/ Check-in [0cd75a87]
Login

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

Overview
Comment:Fix memory leaks in the code on this branch. Make use of the sqlite3_index_constraint.usage field. Do not try to handle ORDER BY terms with explicit COLLATE clauses - they don't get passed to the vtab layer anyway.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | schemalint
Files: files | file ages | folders
SHA3-256: 0cd75a872c89958a7f418720a0e8c6f638f8284c488f666015c19136feae6be8
User & Date: dan 2017-04-15 14:16:04
Context
2017-04-15
14:30
Add header comment for sqlite3_vtab_collation(). check-in: d238694c user: dan tags: schemalint
14:16
Fix memory leaks in the code on this branch. Make use of the sqlite3_index_constraint.usage field. Do not try to handle ORDER BY terms with explicit COLLATE clauses - they don't get passed to the vtab layer anyway. check-in: 0cd75a87 user: dan tags: schemalint
2017-04-14
19:41
Modify the code in ext/expert/ to use the vtab interface instead of sqlite3_whereinfo_hook(). Remove sqlite3_whereinfo_hook(). check-in: 3bb65850 user: dan tags: schemalint
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/expert/sqlite3expert.c.

    35     35   **   Used to temporarily link IdxConstraint objects into lists while
    36     36   **   creating candidate indexes.
    37     37   */
    38     38   struct IdxConstraint {
    39     39     char *zColl;                    /* Collation sequence */
    40     40     int bRange;                     /* True for range, false for eq */
    41     41     int iCol;                       /* Constrained table column */
    42         -  i64 depmask;                    /* Dependency mask */
    43     42     int bFlag;                      /* Used by idxFindCompatible() */
    44     43     int bDesc;                      /* True if ORDER BY <expr> DESC */
    45     44     IdxConstraint *pNext;           /* Next constraint in pEq or pRange list */
    46     45     IdxConstraint *pLink;           /* See above */
    47     46   };
    48     47   
    49     48   /*
................................................................................
   107    106     IdxHashEntry *pNext;            /* Next entry in hash */
   108    107   };
   109    108   struct IdxHash {
   110    109     IdxHashEntry *pFirst;
   111    110     IdxHashEntry *aHash[IDX_HASH_SIZE];
   112    111   };
   113    112   
   114         -/*
   115         -** A hash table for storing a set of 64-bit values. Methods are:
   116         -**
   117         -**   idxHash64Init()
   118         -**   idxHash64Clear()
   119         -**   idxHash64Add()
   120         -*/
   121         -typedef struct IdxHash64Entry IdxHash64Entry;
   122         -typedef struct IdxHash64 IdxHash64;
   123         -struct IdxHash64Entry {
   124         -  u64 iVal;
   125         -  IdxHash64Entry *pNext;          /* Next entry in hash table */
   126         -  IdxHash64Entry *pHashNext;      /* Next entry in same hash bucket */
   127         -};
   128         -struct IdxHash64 {
   129         -  IdxHash64Entry *pFirst;         /* Most recently added entry in hash table */
   130         -  IdxHash64Entry *aHash[IDX_HASH_SIZE];
   131         -};
   132         -
   133    113   /*
   134    114   ** sqlite3expert object.
   135    115   */
   136    116   struct sqlite3expert {
   137    117     sqlite3 *db;                    /* User database */
   138    118     sqlite3 *dbm;                   /* In-memory db for this analysis */
   139    119     sqlite3 *dbv;                   /* Vtab schema for this analysis */
................................................................................
   162    142       memset(pRet, 0, nByte);
   163    143     }else{
   164    144       *pRc = SQLITE_NOMEM;
   165    145     }
   166    146     return pRet;
   167    147   }
   168    148   
   169         -/*
   170         -** Initialize an IdxHash64 hash table.
   171         -*/
   172         -static void idxHash64Init(IdxHash64 *pHash){
   173         -  memset(pHash, 0, sizeof(IdxHash64));
   174         -}
   175         -
   176         -/*
   177         -** Reset an IdxHash64 hash table.
   178         -*/
   179         -static void idxHash64Clear(IdxHash64 *pHash){
   180         -  IdxHash64Entry *pEntry;
   181         -  IdxHash64Entry *pNext;
   182         -  for(pEntry=pHash->pFirst; pEntry; pEntry=pNext){
   183         -    pNext = pEntry->pNext;
   184         -    sqlite3_free(pEntry);
   185         -  }
   186         -  memset(pHash, 0, sizeof(IdxHash64));
   187         -}
   188         -
   189         -/*
   190         -** Add iVal to the IdxHash64 hash table passed as the second argument. This
   191         -** function is a no-op if iVal is already present in the hash table.
   192         -*/
   193         -static void idxHash64Add(int *pRc, IdxHash64 *pHash, u64 iVal){
   194         -  int iHash = (int)((iVal*7) % IDX_HASH_SIZE);
   195         -  IdxHash64Entry *pEntry;
   196         -  assert( iHash>=0 );
   197         -
   198         -  for(pEntry=pHash->aHash[iHash]; pEntry; pEntry=pEntry->pHashNext){
   199         -    if( pEntry->iVal==iVal ) return;
   200         -  }
   201         -  pEntry = idxMalloc(pRc, sizeof(IdxHash64Entry));
   202         -  if( pEntry ){
   203         -    pEntry->iVal = iVal;
   204         -    pEntry->pHashNext = pHash->aHash[iHash];
   205         -    pHash->aHash[iHash] = pEntry;
   206         -    pEntry->pNext = pHash->pFirst;
   207         -    pHash->pFirst = pEntry;
   208         -  }
   209         -}
   210         -
   211    149   /*
   212    150   ** Initialize an IdxHash hash table.
   213    151   */
   214    152   static void idxHashInit(IdxHash *pHash){
   215    153     memset(pHash, 0, sizeof(IdxHash));
   216    154   }
   217    155   
................................................................................
   422    360       /* Link the new scan object into the list */
   423    361       pScan->pTab = p->pTab;
   424    362       pScan->pNextScan = p->pExpert->pScan;
   425    363       p->pExpert->pScan = pScan;
   426    364   
   427    365       /* Add the constraints to the IdxScan object */
   428    366       for(i=0; i<pIdxInfo->nConstraint; i++){
   429         -      int op = pIdxInfo->aConstraint[i].op;
   430         -      if( op&opmask ){
          367  +      struct sqlite3_index_constraint *pCons = &pIdxInfo->aConstraint[i];
          368  +      if( pCons->usable && (pCons->op & opmask) ){
   431    369           IdxConstraint *pNew;
   432    370           const char *zColl = sqlite3_vtab_collation(dbv, i);
   433    371           pNew = idxNewConstraint(&rc, zColl);
   434    372           if( pNew ){
   435         -          pNew->iCol = pIdxInfo->aConstraint[i].iColumn;
   436         -          if( op==SQLITE_INDEX_CONSTRAINT_EQ ){
          373  +          pNew->iCol = pCons->iColumn;
          374  +          if( pCons->op==SQLITE_INDEX_CONSTRAINT_EQ ){
   437    375               pNew->pNext = pScan->pEq;
   438    376               pScan->pEq = pNew;
   439    377             }else{
   440    378               pNew->bRange = 1;
   441    379               pNew->pNext = pScan->pRange;
   442    380               pScan->pRange = pNew;
   443    381             }
   444    382           }
   445         -        if( pIdxInfo->aConstraint[i].usable ){
   446         -          n++;
   447         -          pIdxInfo->aConstraintUsage[i].argvIndex = n;
   448         -        }
          383  +        n++;
          384  +        pIdxInfo->aConstraintUsage[i].argvIndex = n;
   449    385         }
   450    386       }
   451    387   
   452    388       /* Add the ORDER BY to the IdxScan object */
   453    389       for(i=pIdxInfo->nOrderBy-1; i>=0; i--){
   454         -      IdxConstraint *pNew;
   455         -      const char *zColl = sqlite3_vtab_collation(dbv, i+pIdxInfo->nConstraint);
   456         -      pNew = idxNewConstraint(&rc, zColl);
          390  +      int iCol = pIdxInfo->aOrderBy[i].iColumn;
          391  +      IdxConstraint *pNew = idxNewConstraint(&rc, p->pTab->aCol[iCol].zColl);
   457    392         if( pNew ){
   458         -        pNew->iCol = pIdxInfo->aOrderBy[i].iColumn;
          393  +        pNew->iCol = iCol;
   459    394           pNew->bDesc = pIdxInfo->aOrderBy[i].desc;
   460    395           pNew->pNext = pScan->pOrder;
   461    396           pNew->pLink = pScan->pOrder;
   462    397           pScan->pOrder = pNew;
   463    398           n++;
   464    399         }
   465    400       }
................................................................................
   809    744   
   810    745     *pRc = rc;
   811    746     return 0;
   812    747   }
   813    748   
   814    749   static int idxCreateFromCons(
   815    750     sqlite3expert *p,
   816         -  IdxTable *pTab,
   817    751     IdxScan *pScan,
   818    752     IdxConstraint *pEq, 
   819    753     IdxConstraint *pTail
   820    754   ){
   821    755     sqlite3 *dbm = p->dbm;
   822    756     int rc = SQLITE_OK;
   823    757     if( (pEq || pTail) && 0==idxFindCompatible(&rc, dbm, pScan, pEq, pTail) ){
          758  +    IdxTable *pTab = pScan->pTab;
   824    759       char *zCols = 0;
   825    760       char *zIdx = 0;
   826    761       IdxConstraint *pCons;
   827    762       int h = 0;
   828    763       const char *zFmt;
   829    764   
   830    765       for(pCons=pEq; pCons; pCons=pCons->pLink){
................................................................................
   878    813       if( p->iCol==pCmp->iCol ) return 1;
   879    814     }
   880    815     return 0;
   881    816   }
   882    817   
   883    818   static int idxCreateFromWhere(
   884    819     sqlite3expert *p, 
   885         -  IdxTable *pTab,
   886         -  i64 mask,                       /* Consider only these constraints */
   887    820     IdxScan *pScan,                 /* Create indexes for this scan */
   888         -  IdxConstraint *pEq,             /* == constraints for inclusion */
   889    821     IdxConstraint *pTail            /* range/ORDER BY constraints for inclusion */
   890    822   ){
   891         -  IdxConstraint *p1 = pEq;
          823  +  IdxConstraint *p1 = 0;
   892    824     IdxConstraint *pCon;
   893    825     int rc;
   894    826   
   895         -  /* Gather up all the == constraints that match the mask. */
          827  +  /* Gather up all the == constraints. */
   896    828     for(pCon=pScan->pEq; pCon; pCon=pCon->pNext){
   897         -    if( (mask & pCon->depmask)==pCon->depmask 
   898         -     && idxFindConstraint(p1, pCon)==0
   899         -     && idxFindConstraint(pTail, pCon)==0
   900         -    ){
          829  +    if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
   901    830         pCon->pLink = p1;
   902    831         p1 = pCon;
   903    832       }
   904    833     }
   905    834   
   906    835     /* Create an index using the == constraints collected above. And the
   907    836     ** range constraint/ORDER BY terms passed in by the caller, if any. */
   908         -  rc = idxCreateFromCons(p, pTab, pScan, p1, pTail);
          837  +  rc = idxCreateFromCons(p, pScan, p1, pTail);
   909    838   
   910    839     /* If no range/ORDER BY passed by the caller, create a version of the
   911         -  ** index for each range constraint that matches the mask. */
          840  +  ** index for each range constraint.  */
   912    841     if( pTail==0 ){
   913    842       for(pCon=pScan->pRange; rc==SQLITE_OK && pCon; pCon=pCon->pNext){
   914    843         assert( pCon->pLink==0 );
   915         -      if( (mask & pCon->depmask)==pCon->depmask
   916         -        && idxFindConstraint(pEq, pCon)==0
   917         -        && idxFindConstraint(pTail, pCon)==0
   918         -      ){
   919         -        rc = idxCreateFromCons(p, pTab, pScan, p1, pCon);
          844  +      if( !idxFindConstraint(p1, pCon) && !idxFindConstraint(pTail, pCon) ){
          845  +        rc = idxCreateFromCons(p, pScan, p1, pCon);
   920    846         }
   921    847       }
   922    848     }
   923    849   
   924    850     return rc;
   925    851   }
   926    852   
................................................................................
   927    853   /*
   928    854   ** Create candidate indexes in database [dbm] based on the data in 
   929    855   ** linked-list pScan.
   930    856   */
   931    857   static int idxCreateCandidates(sqlite3expert *p, char **pzErr){
   932    858     int rc = SQLITE_OK;
   933    859     IdxScan *pIter;
   934         -  IdxHash64 hMask;
   935         -  idxHash64Init(&hMask);
   936    860   
   937    861     for(pIter=p->pScan; pIter && rc==SQLITE_OK; pIter=pIter->pNextScan){
   938         -    IdxHash64Entry *pEntry;
   939         -    IdxConstraint *pCons;
   940         -    IdxTable *pTab = pIter->pTab;
   941         -
   942         -    idxHash64Add(&rc, &hMask, 0);
   943         -    for(pCons=pIter->pEq; pCons; pCons=pCons->pNext){
   944         -      for(pEntry=hMask.pFirst; pEntry; pEntry=pEntry->pNext){
   945         -        idxHash64Add(&rc, &hMask, pEntry->iVal | (u64)pCons->depmask);
   946         -      }
          862  +    rc = idxCreateFromWhere(p, pIter, 0);
          863  +    if( rc==SQLITE_OK && pIter->pOrder ){
          864  +      rc = idxCreateFromWhere(p, pIter, pIter->pOrder);
   947    865       }
   948         -
   949         -    for(pEntry=hMask.pFirst; rc==SQLITE_OK && pEntry; pEntry=pEntry->pNext){
   950         -      i64 mask = (i64)pEntry->iVal;
   951         -      rc = idxCreateFromWhere(p, pTab, mask, pIter, 0, 0);
   952         -      if( rc==SQLITE_OK && pIter->pOrder ){
   953         -        rc = idxCreateFromWhere(p, pTab, mask, pIter, 0, pIter->pOrder);
   954         -      }
   955         -    }
   956         -
   957         -    idxHash64Clear(&hMask);
   958    866     }
   959    867   
   960    868     return rc;
   961    869   }
   962    870   
   963    871   /*
   964    872   ** Free all elements of the linked list starting at pConstraint.
................................................................................
   999    907     for(p=pStatement; p!=pLast; p=pNext){
  1000    908       pNext = p->pNext;
  1001    909       sqlite3_free(p->zEQP);
  1002    910       sqlite3_free(p->zIdx);
  1003    911       sqlite3_free(p);
  1004    912     }
  1005    913   }
          914  +
          915  +/*
          916  +** Free the linked list of IdxTable objects starting at pTab.
          917  +*/
          918  +static void idxTableFree(IdxTable *pTab){
          919  +  IdxTable *pIter;
          920  +  IdxTable *pNext;
          921  +  for(pIter=pTab; pIter; pIter=pNext){
          922  +    pNext = pIter->pNext;
          923  +    sqlite3_free(pIter);
          924  +  }
          925  +}
  1006    926   
  1007    927   
  1008    928   /*
  1009    929   ** This function is called after candidate indexes have been created. It
  1010    930   ** runs all the queries to see which indexes they prefer, and populates
  1011    931   ** IdxStatement.zIdx and IdxStatement.zEQP with the results.
  1012    932   */
................................................................................
  1122   1042             rc = sqlite3_exec(p->dbv, zOuter, 0, 0, pzErrmsg);
  1123   1043           }
  1124   1044           sqlite3_free(zInner);
  1125   1045           sqlite3_free(zOuter);
  1126   1046         }
  1127   1047       }
  1128   1048     }
         1049  +  idxFinalize(&rc, pSchema);
  1129   1050     return rc;
  1130   1051   }
  1131   1052   
  1132   1053   /*
  1133   1054   ** Allocate a new sqlite3expert object.
  1134   1055   */
  1135   1056   sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
................................................................................
  1292   1213   */
  1293   1214   void sqlite3_expert_destroy(sqlite3expert *p){
  1294   1215     if( p ){
  1295   1216       sqlite3_close(p->dbm);
  1296   1217       sqlite3_close(p->dbv);
  1297   1218       idxScanFree(p->pScan, 0);
  1298   1219       idxStatementFree(p->pStatement, 0);
         1220  +    idxTableFree(p->pTable);
  1299   1221       idxHashClear(&p->hIdx);
         1222  +    sqlite3_free(p->zCandidates);
  1300   1223       sqlite3_free(p);
  1301   1224     }
  1302   1225   }
  1303   1226   
  1304   1227   #endif /* !defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHEREINFO_HOOK) */
  1305   1228   

Changes to src/where.c.

  3116   3116     return rc;
  3117   3117   }
  3118   3118   
  3119   3119   
  3120   3120   struct BestIndexCtx {
  3121   3121     WhereClause *pWC;
  3122   3122     sqlite3_index_info *pIdxInfo;
  3123         -  ExprList *pOrderBy;
  3124   3123     Parse *pParse;
  3125   3124   };
  3126   3125   
  3127   3126   const char *sqlite3_vtab_collation(sqlite3 *db, int iCons){
  3128   3127     struct BestIndexCtx *p = (struct BestIndexCtx*)db->pVtabWC;
  3129   3128     const char *zRet = 0;
  3130         -  if( p && iCons>=0 ){
  3131         -    if( iCons<p->pIdxInfo->nConstraint ){
  3132         -      int iTerm = p->pIdxInfo->aConstraint[iCons].iTermOffset;
  3133         -      Expr *pX = p->pWC->a[iTerm].pExpr;
  3134         -      CollSeq *pC = sqlite3BinaryCompareCollSeq(p->pParse,pX->pLeft,pX->pRight);
  3135         -      zRet = (pC ? pC->zName : "BINARY");
  3136         -    }else{
  3137         -      iCons -= p->pIdxInfo->nConstraint;
  3138         -      if( iCons<p->pIdxInfo->nOrderBy ){
  3139         -        Expr *pX = p->pOrderBy->a[iCons].pExpr;
  3140         -        CollSeq *pC = sqlite3ExprCollSeq(p->pParse, pX);
  3141         -        zRet = (pC ? pC->zName : "BINARY");
  3142         -      }
  3143         -    }
         3129  +  if( p && iCons>=0 && iCons<p->pIdxInfo->nConstraint ){
         3130  +    int iTerm = p->pIdxInfo->aConstraint[iCons].iTermOffset;
         3131  +    Expr *pX = p->pWC->a[iTerm].pExpr;
         3132  +    CollSeq *pC = sqlite3BinaryCompareCollSeq(p->pParse,pX->pLeft,pX->pRight);
         3133  +    zRet = (pC ? pC->zName : "BINARY");
  3144   3134     }
  3145   3135     return zRet;
  3146   3136   }
  3147   3137   
  3148   3138   /*
  3149   3139   ** Add all WhereLoop objects for a table of the join identified by
  3150   3140   ** pBuilder->pNew->iTab.  That table is guaranteed to be a virtual table.
................................................................................
  3208   3198       sqlite3DbFree(pParse->db, p);
  3209   3199       return SQLITE_NOMEM_BKPT;
  3210   3200     }
  3211   3201   
  3212   3202     bic.pWC = pWC;
  3213   3203     bic.pIdxInfo = p;
  3214   3204     bic.pParse = pParse;
  3215         -  bic.pOrderBy = pBuilder->pOrderBy;
  3216   3205     pSaved = pParse->db->pVtabWC;
  3217   3206     pParse->db->pVtabWC = (void*)&bic;
  3218   3207   
  3219   3208     /* First call xBestIndex() with all constraints usable. */
  3220   3209     WHERETRACE(0x40, ("  VirtualOne: all usable\n"));
  3221   3210     rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn);
  3222   3211