Index: src/analyze.c ================================================================== --- src/analyze.c +++ src/analyze.c @@ -1250,17 +1250,17 @@ ** the array aOut[]. */ static void decodeIntArray( char *zIntArray, /* String containing int array to decode */ int nOut, /* Number of slots in aOut[] */ - tRowcnt *aOut, /* Store integers here */ + LogEst *aOut, /* Convert values to 10*log2() and store here */ Index *pIndex /* Handle extra flags for this index, if not NULL */ ){ char *z = zIntArray; int c; int i; - tRowcnt v; + u64 v; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 if( z==0 ) z = ""; #else if( NEVER(z==0) ) z = ""; @@ -1269,11 +1269,11 @@ v = 0; while( (c=z[0])>='0' && c<='9' ){ v = v*10 + c - '0'; z++; } - aOut[i] = v; + aOut[i] = sqlite3LogEst(v); if( *z==' ' ) z++; } if( pIndex ){ if( strcmp(z, "unordered")==0 ){ pIndex->bUnordered = 1; @@ -1366,31 +1366,31 @@ IndexSample *aSample = pIdx->aSample; IndexSample *pFinal = &aSample[pIdx->nSample-1]; int iCol; for(iCol=0; iColnColumn; iCol++){ int i; /* Used to iterate through samples */ - tRowcnt sumEq = 0; /* Sum of the nEq values */ - tRowcnt nSum = 0; /* Number of terms contributing to sumEq */ - tRowcnt avgEq = 0; - tRowcnt nDLt = pFinal->anDLt[iCol]; + u64 sumEq = 0; /* Sum of the nEq values */ + u64 nSum = 0; /* Number of terms contributing to sumEq */ + u64 avgEq = 0; + u64 nDLt = sqlite3LogEstToInt(pFinal->anDLt[iCol]); /* Set nSum to the number of distinct (iCol+1) field prefixes that ** occur in the stat4 table for this index before pFinal. Set ** sumEq to the sum of the nEq values for column iCol for the same ** set (adding the value only once where there exist dupicate ** prefixes). */ for(i=0; i<(pIdx->nSample-1); i++){ if( aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){ - sumEq += aSample[i].anEq[iCol]; + sumEq += sqlite3LogEstToInt(aSample[i].anEq[iCol]); nSum++; } } if( nDLt>nSum ){ - avgEq = (pFinal->anLt[iCol] - sumEq)/(nDLt - nSum); + avgEq = (sqlite3LogEstToInt(pFinal->anLt[iCol]) - sumEq)/(nDLt - nSum); } - if( avgEq==0 ) avgEq = 1; - pIdx->aAvgEq[iCol] = avgEq; + if( avgEq<=0 ) avgEq = 1; + pIdx->aAvgEq[iCol] = sqlite3LogEst(avgEq); if( pIdx->nSampleCol==1 ) break; } } } @@ -1436,11 +1436,11 @@ char *zIndex; /* Index name */ Index *pIdx; /* Pointer to the index object */ int nSample; /* Number of samples */ int nByte; /* Bytes of space required */ int i; /* Bytes of space required */ - tRowcnt *pSpace; + LogEst *pSpace; zIndex = (char *)sqlite3_column_text(pStmt, 0); if( zIndex==0 ) continue; nSample = sqlite3_column_int(pStmt, 1); pIdx = sqlite3FindIndex(db, zIndex, zDb); @@ -1452,19 +1452,19 @@ nIdxCol = pIdx->nColumn+1; nAvgCol = pIdx->nColumn; } pIdx->nSampleCol = nIdxCol; nByte = sizeof(IndexSample) * nSample; - nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample; - nByte += nAvgCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */ + nByte += sizeof(LogEst) * nIdxCol * 3 * nSample; + nByte += nAvgCol * sizeof(LogEst); /* Space for Index.aAvgEq[] */ pIdx->aSample = sqlite3DbMallocZero(db, nByte); if( pIdx->aSample==0 ){ sqlite3_finalize(pStmt); return SQLITE_NOMEM; } - pSpace = (tRowcnt*)&pIdx->aSample[nSample]; + pSpace = (LogEst*)&pIdx->aSample[nSample]; pIdx->aAvgEq = pSpace; pSpace += nAvgCol; for(i=0; iaSample[i].anEq = pSpace; pSpace += nIdxCol; pIdx->aSample[i].anLt = pSpace; pSpace += nIdxCol; pIdx->aSample[i].anDLt = pSpace; pSpace += nIdxCol; Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -877,11 +877,11 @@ } pTable->zName = zName; pTable->iPKey = -1; pTable->pSchema = db->aDb[iDb].pSchema; pTable->nRef = 1; - pTable->nRowEst = 1000000; + pTable->nRowEst = 200; assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; /* If this is the magic sqlite_sequence table used by autoincrement, ** then record a pointer to this table in the main database structure @@ -2720,11 +2720,11 @@ */ nName = sqlite3Strlen30(zName); nCol = pList->nExpr; pIndex = sqlite3DbMallocZero(db, ROUND8(sizeof(Index)) + /* Index structure */ - ROUND8(sizeof(tRowcnt)*(nCol+1)) + /* Index.aiRowEst */ + ROUND8(sizeof(LogEst)*(nCol+1)) + /* Index.aiRowEst */ sizeof(char *)*nCol + /* Index.azColl */ sizeof(int)*nCol + /* Index.aiColumn */ sizeof(u8)*nCol + /* Index.aSortOrder */ nName + 1 + /* Index.zName */ nExtra /* Collation sequence names */ @@ -2731,13 +2731,13 @@ ); if( db->mallocFailed ){ goto exit_create_index; } zExtra = (char*)pIndex; - pIndex->aiRowEst = (tRowcnt*)&zExtra[ROUND8(sizeof(Index))]; + pIndex->aiRowEst = (LogEst*)&zExtra[ROUND8(sizeof(Index))]; pIndex->azColl = (char**) - ((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1)); + ((char*)pIndex->aiRowEst + ROUND8(sizeof(LogEst)*nCol+1)); assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) ); assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) ); pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]); pIndex->aSortOrder = (u8 *)(&pIndex->aiColumn[nCol]); pIndex->zName = (char *)(&pIndex->aSortOrder[nCol]); @@ -3012,23 +3012,24 @@ ** Apart from that, we have little to go on besides intuition as to ** how aiRowEst[] should be initialized. The numbers generated here ** are based on typical values found in actual indices. */ void sqlite3DefaultRowEst(Index *pIdx){ - tRowcnt *a = pIdx->aiRowEst; + LogEst *a = pIdx->aiRowEst; int i; - tRowcnt n; + LogEst n; assert( a!=0 ); a[0] = pIdx->pTable->nRowEst; - if( a[0]<10 ) a[0] = 10; - n = 10; + assert( 33==sqlite3LogEst(10) ); + if( a[0]<34 ){ a[0] = 34; } + n = 34; for(i=1; i<=pIdx->nColumn; i++){ a[i] = n; - if( n>5 ) n--; + if( n>24 ) n -= 2; } if( pIdx->onError!=OE_None ){ - a[pIdx->nColumn] = 1; + a[pIdx->nColumn] = 0; } } /* ** This routine will drop an existing named index. This routine Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -1478,11 +1478,11 @@ /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside ** is disabled */ assert( db->lookaside.bEnabled==0 ); pTab->nRef = 1; pTab->zName = 0; - pTab->nRowEst = 1000000; + pTab->nRowEst = 200; selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect); pTab->iPKey = -1; if( db->mallocFailed ){ sqlite3DeleteTable(db, pTab); @@ -3396,11 +3396,11 @@ pTab->nRef = 1; pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab); while( pSel->pPrior ){ pSel = pSel->pPrior; } selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol); pTab->iPKey = -1; - pTab->nRowEst = 1000000; + pTab->nRowEst = 200; pTab->tabFlags |= TF_Ephemeral; #endif }else{ /* An ordinary table or view name in the FROM clause */ assert( pFrom->pTab==0 ); Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -1380,15 +1380,15 @@ FKey *pFKey; /* Linked list of all foreign keys in this table */ char *zColAff; /* String defining the affinity of each column */ #ifndef SQLITE_OMIT_CHECK ExprList *pCheck; /* All CHECK constraints */ #endif - tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */ int tnum; /* Root BTree node for this table (see note above) */ i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */ i16 nCol; /* Number of columns in this table */ u16 nRef; /* Number of pointers to this Table */ + LogEst nRowEst; /* Estimated number of rows in the table */ LogEst szTabRow; /* Estimated size of each table row in bytes */ u8 tabFlags; /* Mask of TF_* values */ u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */ #ifndef SQLITE_OMIT_ALTERTABLE int addColOffset; /* Offset in CREATE TABLE stmt to add a new column */ @@ -1575,11 +1575,11 @@ ** element. */ struct Index { char *zName; /* Name of this index */ int *aiColumn; /* Which columns are used by this index. 1st is 0 */ - tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */ + LogEst *aiRowEst; /* From ANALYZE: Est. rows selected by each column */ Table *pTable; /* The SQL table being indexed */ char *zColAff; /* String defining the affinity of each column */ Index *pNext; /* The next index associated with the same table */ Schema *pSchema; /* Schema containing this index */ u8 *aSortOrder; /* for each column: True==DESC, False==ASC */ @@ -1593,11 +1593,11 @@ unsigned bUnordered:1; /* Use this index for == or IN queries only */ unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ - tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ + LogEst *aAvgEq; /* Average nEq values for keys not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ #endif }; /* @@ -1606,13 +1606,13 @@ ** analyze.c source file for additional information. */ struct IndexSample { void *p; /* Pointer to sampled record */ int n; /* Size of record in bytes */ - tRowcnt *anEq; /* Est. number of rows where the key equals this sample */ - tRowcnt *anLt; /* Est. number of rows where key is less than this sample */ - tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */ + LogEst *anEq; /* Est. number of rows where the key equals this sample */ + LogEst *anLt; /* Est. number of rows where key is less than this sample */ + LogEst *anDLt; /* Est. number of distinct keys less than this sample */ }; /* ** Each token coming out of the lexer is an instance of ** this structure. Tokens are also used as part of an expression. Index: src/util.c ================================================================== --- src/util.c +++ src/util.c @@ -1211,11 +1211,10 @@ /* ** Find (an approximate) sum of two LogEst values. This computation is ** not a simple "+" operator because LogEst is stored as a logarithmic ** value. -** */ LogEst sqlite3LogEstAdd(LogEst a, LogEst b){ static const unsigned char x[] = { 10, 10, /* 0,1 */ 9, 9, /* 2,3 */ Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -2326,11 +2326,11 @@ static void whereKeyStats( Parse *pParse, /* Database connection */ Index *pIdx, /* Index to consider domain of */ UnpackedRecord *pRec, /* Vector of values to consider */ int roundUp, /* Round up if true. Round down if false */ - tRowcnt *aStat /* OUT: stats written here */ + LogEst *aStat /* OUT: stats written here */ ){ IndexSample *aSample = pIdx->aSample; int iCol; /* Index of required stats in anEq[] etc. */ int iMin = 0; /* Smallest sample not yet tested */ int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */ @@ -2379,19 +2379,20 @@ */ if( res==0 ){ aStat[0] = aSample[i].anLt[iCol]; aStat[1] = aSample[i].anEq[iCol]; }else{ - tRowcnt iLower, iUpper, iGap; + LogEst iLower, iUpper, iGap; if( i==0 ){ iLower = 0; iUpper = aSample[0].anLt[iCol]; }else{ iUpper = i>=pIdx->nSample ? pIdx->aiRowEst[0] : aSample[i].anLt[iCol]; - iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol]; + iLower = sqlite3LogEstAdd(aSample[i-1].anEq[iCol], + aSample[i-1].anLt[iCol]); } - aStat[1] = (pIdx->nColumn>iCol ? pIdx->aAvgEq[iCol] : 1); + aStat[1] = (pIdx->nColumn>iCol ? pIdx->aAvgEq[iCol] : 0); if( iLower>=iUpper ){ iGap = 0; }else{ iGap = iUpper - iLower; } @@ -2464,11 +2465,11 @@ && nEq==pBuilder->nRecValid && nEqnSampleCol && OptimizationEnabled(pParse->db, SQLITE_Stat3) ){ UnpackedRecord *pRec = pBuilder->pRec; - tRowcnt a[2]; + LogEst a[2]; u8 aff; /* Variable iLower will be set to the estimate of the number of rows in ** the index that are less than the lower bound of the range query. The ** lower bound being the concatenation of $P and $L, where $P is the @@ -2484,12 +2485,12 @@ ** Similarly, iUpper is to be set to the estimate of the number of rows ** less than the upper bound of the range query. Where the upper bound ** is either ($P) or ($P:$U). Again, even if $U is available, both values ** of iUpper are requested of whereKeyStats() and the smaller used. */ - tRowcnt iLower; - tRowcnt iUpper; + LogEst iLower; + LogEst iUpper; if( nEq==p->nColumn ){ aff = SQLITE_AFF_INTEGER; }else{ aff = p->pTable->aCol[p->aiColumn[nEq]].affinity; @@ -2501,23 +2502,23 @@ }else{ /* Note: this call could be optimized away - since the same values must ** have been requested when testing key $P in whereEqualScanEst(). */ whereKeyStats(pParse, p, pRec, 0, a); iLower = a[0]; - iUpper = a[0] + a[1]; + iUpper = sqlite3LogEstAdd(a[0],a[1]); } /* If possible, improve on the iLower estimate using ($P:$L). */ if( pLower ){ int bOk; /* True if value is extracted from pExpr */ Expr *pExpr = pLower->pExpr->pRight; assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 ); rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); if( rc==SQLITE_OK && bOk ){ - tRowcnt iNew; + LogEst iNew; whereKeyStats(pParse, p, pRec, 0, a); - iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0); + iNew = sqlite3LogEstAdd(a[0],((pLower->eOperator & WO_GT) ? a[1] : 0)); if( iNew>iLower ) iLower = iNew; nOut--; } } @@ -2526,31 +2527,31 @@ int bOk; /* True if value is extracted from pExpr */ Expr *pExpr = pUpper->pExpr->pRight; assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk); if( rc==SQLITE_OK && bOk ){ - tRowcnt iNew; + LogEst iNew; whereKeyStats(pParse, p, pRec, 1, a); - iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0); + iNew = sqlite3LogEstAdd(a[0],((pUpper->eOperator & WO_LE) ? a[1] : 0)); if( iNewpRec = pRec; if( rc==SQLITE_OK ){ - if( iUpper>iLower ){ - nNew = sqlite3LogEst(iUpper - iLower); - }else{ - nNew = 10; assert( 10==sqlite3LogEst(2) ); - } + if( iUpper<=iLower ) iUpper = iLower+1; + nNew = sqlite3LogEst(sqlite3LogEstToInt(iUpper) + - sqlite3LogEstToInt(iLower)); if( nNewpNew->u.btree.pIndex; int nEq = pBuilder->pNew->u.btree.nEq; UnpackedRecord *pRec = pBuilder->pRec; u8 aff; /* Column affinity */ int rc; /* Subfunction return code */ - tRowcnt a[2]; /* Statistics */ + LogEst a[2]; /* Statistics */ int bOk; assert( nEq>=1 ); assert( nEq<=(p->nColumn+1) ); assert( p->aSample!=0 ); @@ -2631,11 +2632,12 @@ if( rc!=SQLITE_OK ) return rc; if( bOk==0 ) return SQLITE_NOTFOUND; pBuilder->nRecValid = nEq; whereKeyStats(pParse, p, pRec, 0, a); - WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1])); + WHERETRACE(0x100,("equality scan regions: %d (%llu)\n", a[1], + sqlite3LogEstToInt(a[1]))); *pnRow = a[1]; return rc; } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ @@ -2659,31 +2661,32 @@ */ static int whereInScanEst( Parse *pParse, /* Parsing & code generating context */ WhereLoopBuilder *pBuilder, ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ - tRowcnt *pnRow /* Write the revised row estimate here */ + LogEst *pnRow /* Write the revised row estimate here */ ){ Index *p = pBuilder->pNew->u.btree.pIndex; int nRecValid = pBuilder->nRecValid; int rc = SQLITE_OK; /* Subfunction return code */ - tRowcnt nEst; /* Number of rows for a single term */ - tRowcnt nRowEst = 0; /* New estimate of the number of rows */ + LogEst nEst; /* Number of rows for a single term */ + u64 nRowEst = 0; /* New estimate of the number of rows */ int i; /* Loop counter */ assert( p->aSample!=0 ); for(i=0; rc==SQLITE_OK && inExpr; i++){ nEst = p->aiRowEst[0]; rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst); - nRowEst += nEst; + nRowEst += sqlite3LogEstToInt(nEst); pBuilder->nRecValid = nRecValid; } if( rc==SQLITE_OK ){ - if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0]; - *pnRow = nRowEst; - WHERETRACE(0x100,("IN row estimate: est=%g\n", nRowEst)); + nEst = sqlite3LogEst(nRowEst); + if( nEst > p->aiRowEst[0] ) nEst = p->aiRowEst[0]; + *pnRow = nEst; + WHERETRACE(0x100,("IN row estimate: est=%d (%llu)\n", nEst, nRowEst)); } assert( pBuilder->nRecValid==nRecValid ); return rc; } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ @@ -4249,12 +4252,12 @@ if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); assert( pNew->u.btree.nEq<=pProbe->nColumn ); if( pNew->u.btree.nEq < pProbe->nColumn ){ iCol = pProbe->aiColumn[pNew->u.btree.nEq]; - nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]); - if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1; + nRowEst = pProbe->aiRowEst[pNew->u.btree.nEq+1]; + if( nRowEst<10 && pProbe->onError==OE_None ) nRowEst = 10; }else{ iCol = -1; nRowEst = 0; } pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol, @@ -4263,11 +4266,11 @@ saved_nLTerm = pNew->nLTerm; saved_wsFlags = pNew->wsFlags; saved_prereq = pNew->prereq; saved_nOut = pNew->nOut; pNew->rSetup = 0; - rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0])); + rLogSize = estLog(pProbe->aiRowEst[0]); for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ int nIn = 0; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 int nRecValid = pBuilder->nRecValid; #endif @@ -4344,24 +4347,21 @@ && pProbe->nSample && pNew->u.btree.nEq<=pProbe->nSampleCol && OptimizationEnabled(db, SQLITE_Stat3) ){ Expr *pExpr = pTerm->pExpr; - tRowcnt nOut = 0; + LogEst nOut = pNew->nOut; if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){ testcase( pTerm->eOperator & WO_EQ ); testcase( pTerm->eOperator & WO_ISNULL ); rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut); }else if( (pTerm->eOperator & WO_IN) && !ExprHasProperty(pExpr, EP_xIsSelect) ){ rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut); } - assert( nOut==0 || rc==SQLITE_OK ); - if( nOut ){ - nOut = sqlite3LogEst(nOut); - pNew->nOut = MIN(nOut, saved_nOut); - } + assert( nOut==pNew->nOut || rc==SQLITE_OK ); + if( nOutnOut ) pNew->nOut = nOut; } #endif if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){ /* Each row involves a step of the index, then a binary search of ** the main table */ @@ -4458,11 +4458,11 @@ Bitmask mExtra /* Extra prerequesites for using this table */ ){ WhereInfo *pWInfo; /* WHERE analysis context */ Index *pProbe; /* An index we are evaluating */ Index sPk; /* A fake index object for the primary key */ - tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ + LogEst aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ SrcList *pTabList; /* The FROM clause */ struct SrcList_item *pSrc; /* The FROM clause btree term to add */ WhereLoop *pNew; /* Template WhereLoop object */ int rc = SQLITE_OK; /* Return code */ @@ -4493,20 +4493,20 @@ sPk.aiColumn = &aiColumnPk; sPk.aiRowEst = aiRowEstPk; sPk.onError = OE_Replace; sPk.pTable = pSrc->pTab; aiRowEstPk[0] = pSrc->pTab->nRowEst; - aiRowEstPk[1] = 1; + aiRowEstPk[1] = 0; pFirst = pSrc->pTab->pIndex; if( pSrc->notIndexed==0 ){ /* The real indices of the table are only considered if the ** NOT INDEXED qualifier is omitted from the FROM clause */ sPk.pNext = pFirst; } pProbe = &sPk; } - rSize = sqlite3LogEst(pSrc->pTab->nRowEst); + rSize = pSrc->pTab->nRowEst; rLogSize = estLog(rSize); #ifndef SQLITE_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pOrSet