/ Check-in [4da49a95]
Login

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

Overview
Comment:Optimization to the ExprList object to make it slightly smaller and faster.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 4da49a95c0f07ed7790169e8833c3e2dacda504a3d997f567572020148abe30b
User & Date: drh 2017-09-15 15:17:48
References
2017-09-17
19:45
Do not make the assumption (as check-in [4da49a95c0f07] incorrectly did) that the ExprList returned by sqlite3ExprListDup() would never be passed into sqlite3ExprListAppend(). Include a new test case that shows this sometimes does happen. check-in: 29227d00 user: drh tags: trunk
Context
2017-09-15
15:38
Improved the header-comment documentation on sqlite3ExprCodeExprList(). No changes to code. check-in: 5dc3ecb5 user: drh tags: trunk
15:17
Optimization to the ExprList object to make it slightly smaller and faster. check-in: 4da49a95 user: drh tags: trunk
14:36
Fix a harmless comment typo. No changes to code. check-in: f7f0bf1d user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

  1301   1301     int i;
  1302   1302     Expr *pPriorSelectCol = 0;
  1303   1303     assert( db!=0 );
  1304   1304     if( p==0 ) return 0;
  1305   1305     pNew = sqlite3DbMallocRawNN(db, 
  1306   1306                sizeof(*pNew)+sizeof(pNew->a[0])*(p->nExpr-1) );
  1307   1307     if( pNew==0 ) return 0;
  1308         -  pNew->nAlloc = pNew->nExpr = p->nExpr;
         1308  +  pNew->nExpr = p->nExpr;
         1309  +  /* After being duplicated, the ExprList may not be expanded again using
         1310  +  ** Append() because Append() assumes that the number of slots in
         1311  +  ** ExprList.a[] is a power of 2 */
         1312  +  VVA_ONLY( pNew->bFixedSize = 1 );
  1309   1313     pItem = pNew->a;
  1310   1314     pOldItem = p->a;
  1311   1315     for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
  1312   1316       Expr *pOldExpr = pOldItem->pExpr;
  1313   1317       Expr *pNewExpr;
  1314   1318       pItem->pExpr = sqlite3ExprDup(db, pOldExpr, flags);
  1315   1319       if( pOldExpr 
................................................................................
  1455   1459   #endif
  1456   1460   
  1457   1461   
  1458   1462   /*
  1459   1463   ** Add a new element to the end of an expression list.  If pList is
  1460   1464   ** initially NULL, then create a new expression list.
  1461   1465   **
         1466  +** The pList argument must be either NULL or a pointer to an ExprList
         1467  +** obtained from a prior call to sqlite3ExprListAppend().  This routine
         1468  +** may not be used with an ExprList obtained from sqlite3ExprListDup().
         1469  +** Reason:  This routine assumes that the number of slots in pList->a[]
         1470  +** is a power of two.  That is true for sqlite3ExprListAppend() returns
         1471  +** but is not necessarily true from the return value of sqlite3ExprListDup().
         1472  +**
  1462   1473   ** If a memory allocation error occurs, the entire list is freed and
  1463   1474   ** NULL is returned.  If non-NULL is returned, then it is guaranteed
  1464   1475   ** that the new entry was successfully appended.
  1465   1476   */
  1466   1477   ExprList *sqlite3ExprListAppend(
  1467   1478     Parse *pParse,          /* Parsing context */
  1468   1479     ExprList *pList,        /* List to which to append. Might be NULL */
  1469   1480     Expr *pExpr             /* Expression to be appended. Might be NULL */
  1470   1481   ){
  1471   1482     struct ExprList_item *pItem;
  1472   1483     sqlite3 *db = pParse->db;
  1473   1484     assert( db!=0 );
         1485  +  assert( pList==0 || pList->bFixedSize==0 );
  1474   1486     if( pList==0 ){
  1475   1487       pList = sqlite3DbMallocRawNN(db, sizeof(ExprList) );
  1476   1488       if( pList==0 ){
  1477   1489         goto no_mem;
  1478   1490       }
  1479   1491       pList->nExpr = 0;
  1480         -    pList->nAlloc = 1;
  1481         -  }else if( pList->nExpr==pList->nAlloc ){
         1492  +    VVA_ONLY( pList->bFixedSize = 0 );
         1493  +  }else if( (pList->nExpr & (pList->nExpr-1))==0 ){
  1482   1494       ExprList *pNew;
  1483   1495       pNew = sqlite3DbRealloc(db, pList, 
  1484         -             sizeof(*pList)+(2*pList->nAlloc - 1)*sizeof(pList->a[0]));
         1496  +             sizeof(*pList)+(2*pList->nExpr - 1)*sizeof(pList->a[0]));
  1485   1497       if( pNew==0 ){
  1486   1498         goto no_mem;
  1487   1499       }
  1488   1500       pList = pNew;
  1489         -    pList->nAlloc *= 2;
  1490   1501     }
  1491   1502     pItem = &pList->a[pList->nExpr++];
  1492   1503     assert( offsetof(struct ExprList_item,zName)==sizeof(pItem->pExpr) );
  1493   1504     assert( offsetof(struct ExprList_item,pExpr)==0 );
  1494   1505     memset(&pItem->zName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zName));
  1495   1506     pItem->pExpr = pExpr;
  1496   1507     return pList;

Changes to src/sqliteInt.h.

  2464   2464   ** column expression as it exists in a SELECT statement.  However, if
  2465   2465   ** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
  2466   2466   ** of the result column in the form: DATABASE.TABLE.COLUMN.  This later
  2467   2467   ** form is used for name resolution with nested FROM clauses.
  2468   2468   */
  2469   2469   struct ExprList {
  2470   2470     int nExpr;             /* Number of expressions on the list */
  2471         -  int nAlloc;            /* Number of a[] slots allocated */
         2471  +#ifdef SQLITE_DEBUG
         2472  +  u8 bFixedSize;         /* May not be expanded using sqlite3ExprListAppend() */
         2473  +#endif
  2472   2474     struct ExprList_item { /* For each expression in the list */
  2473   2475       Expr *pExpr;            /* The parse tree for this expression */
  2474   2476       char *zName;            /* Token associated with this expression */
  2475   2477       char *zSpan;            /* Original text of the expression */
  2476   2478       u8 sortOrder;           /* 1 for DESC or 0 for ASC */
  2477   2479       unsigned done :1;       /* A flag to indicate when processing is finished */
  2478   2480       unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */