diff options
author | drh <drh@noemail.net> | 2013-10-10 20:13:18 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2013-10-10 20:13:18 +0000 |
commit | a63b85299290b7eca076ea6e031e7f43d4feadcf (patch) | |
tree | e925eb05965ec76f37b6483581d5bd8f8ea9e53b /src/build.c | |
parent | 59255f9a98381960cfede9253277f128895531f6 (diff) | |
parent | 7e65c94bdc689bebd222321dec5c034194267ac9 (diff) | |
download | sqlite-a63b85299290b7eca076ea6e031e7f43d4feadcf.tar.gz sqlite-a63b85299290b7eca076ea6e031e7f43d4feadcf.zip |
Synchronize with the trunk.
FossilOrigin-Name: 136445ba020c9475d3f5a7843d7d0add98477138
Diffstat (limited to 'src/build.c')
-rw-r--r-- | src/build.c | 99 |
1 files changed, 80 insertions, 19 deletions
diff --git a/src/build.c b/src/build.c index 491ca2838..e14988ae1 100644 --- a/src/build.c +++ b/src/build.c @@ -879,7 +879,7 @@ void sqlite3StartTable( pTable->iPKey = -1; pTable->pSchema = db->aDb[iDb].pSchema; pTable->nRef = 1; - pTable->nRowEst = 1000000; + pTable->nRowEst = 1048576; assert( pParse->pNewTable==0 ); pParse->pNewTable = pTable; @@ -1026,6 +1026,7 @@ void sqlite3AddColumn(Parse *pParse, Token *pName){ ** be called next to set pCol->affinity correctly. */ pCol->affinity = SQLITE_AFF_NONE; + pCol->szEst = 1; p->nCol++; } @@ -1067,15 +1068,18 @@ void sqlite3AddNotNull(Parse *pParse, int onError){ ** If none of the substrings in the above table are found, ** SQLITE_AFF_NUMERIC is returned. */ -char sqlite3AffinityType(const char *zIn){ +char sqlite3AffinityType(const char *zIn, u8 *pszEst){ u32 h = 0; char aff = SQLITE_AFF_NUMERIC; + const char *zChar = 0; - if( zIn ) while( zIn[0] ){ + if( zIn==0 ) return aff; + while( zIn[0] ){ h = (h<<8) + sqlite3UpperToLower[(*zIn)&0xff]; zIn++; if( h==(('c'<<24)+('h'<<16)+('a'<<8)+'r') ){ /* CHAR */ - aff = SQLITE_AFF_TEXT; + aff = SQLITE_AFF_TEXT; + zChar = zIn; }else if( h==(('c'<<24)+('l'<<16)+('o'<<8)+'b') ){ /* CLOB */ aff = SQLITE_AFF_TEXT; }else if( h==(('t'<<24)+('e'<<16)+('x'<<8)+'t') ){ /* TEXT */ @@ -1083,6 +1087,7 @@ char sqlite3AffinityType(const char *zIn){ }else if( h==(('b'<<24)+('l'<<16)+('o'<<8)+'b') /* BLOB */ && (aff==SQLITE_AFF_NUMERIC || aff==SQLITE_AFF_REAL) ){ aff = SQLITE_AFF_NONE; + if( zIn[0]=='(' ) zChar = zIn; #ifndef SQLITE_OMIT_FLOATING_POINT }else if( h==(('r'<<24)+('e'<<16)+('a'<<8)+'l') /* REAL */ && aff==SQLITE_AFF_NUMERIC ){ @@ -1100,6 +1105,28 @@ char sqlite3AffinityType(const char *zIn){ } } + /* If pszEst is not NULL, store an estimate of the field size. The + ** estimate is scaled so that the size of an integer is 1. */ + if( pszEst ){ + *pszEst = 1; /* default size is approx 4 bytes */ + if( aff<=SQLITE_AFF_NONE ){ + if( zChar ){ + while( zChar[0] ){ + if( sqlite3Isdigit(zChar[0]) ){ + int v; + sqlite3GetInt32(zChar, &v); + v = v/4 + 1; + if( v>255 ) v = 255; + *pszEst = v; /* BLOB(k), VARCHAR(k), CHAR(k) -> r=(k/4+1) */ + break; + } + zChar++; + } + }else{ + *pszEst = 5; /* BLOB, TEXT, CLOB -> r=5 (approx 20 bytes)*/ + } + } + } return aff; } @@ -1121,7 +1148,7 @@ void sqlite3AddColumnType(Parse *pParse, Token *pType){ pCol = &p->aCol[p->nCol-1]; assert( pCol->zType==0 ); pCol->zType = sqlite3NameFromToken(pParse->db, pType); - pCol->affinity = sqlite3AffinityType(pCol->zType); + pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst); } /* @@ -1469,7 +1496,7 @@ static char *createTableStmt(sqlite3 *db, Table *p){ zType = azType[pCol->affinity - SQLITE_AFF_TEXT]; len = sqlite3Strlen30(zType); assert( pCol->affinity==SQLITE_AFF_NONE - || pCol->affinity==sqlite3AffinityType(zType) ); + || pCol->affinity==sqlite3AffinityType(zType, 0) ); memcpy(&zStmt[k], zType, len); k += len; assert( k<=n ); @@ -1479,6 +1506,34 @@ static char *createTableStmt(sqlite3 *db, Table *p){ } /* +** Estimate the total row width for a table. +*/ +static void estimateTableWidth(Table *pTab){ + unsigned wTable = 0; + const Column *pTabCol; + int i; + for(i=pTab->nCol, pTabCol=pTab->aCol; i>0; i--, pTabCol++){ + wTable += pTabCol->szEst; + } + if( pTab->iPKey<0 ) wTable++; + pTab->szTabRow = sqlite3LogEst(wTable*4); +} + +/* +** Estimate the average size of a row for an index. +*/ +static void estimateIndexWidth(Index *pIdx){ + unsigned wIndex = 1; + int i; + const Column *aCol = pIdx->pTable->aCol; + for(i=0; i<pIdx->nColumn; i++){ + assert( pIdx->aiColumn[i]>=0 && pIdx->aiColumn[i]<pIdx->pTable->nCol ); + wIndex += aCol[pIdx->aiColumn[i]].szEst; + } + pIdx->szIdxRow = sqlite3LogEst(wIndex*4); +} + +/* ** This routine is called to report the final ")" that terminates ** a CREATE TABLE statement. ** @@ -1504,9 +1559,10 @@ void sqlite3EndTable( Token *pEnd, /* The final ')' token in the CREATE TABLE */ Select *pSelect /* Select from a "CREATE ... AS SELECT" */ ){ - Table *p; - sqlite3 *db = pParse->db; - int iDb; + Table *p; /* The new table */ + sqlite3 *db = pParse->db; /* The database connection */ + int iDb; /* Database in which the table lives */ + Index *pIdx; /* An implied index of the table */ if( (pEnd==0 && pSelect==0) || db->mallocFailed ){ return; @@ -1526,6 +1582,12 @@ void sqlite3EndTable( } #endif /* !defined(SQLITE_OMIT_CHECK) */ + /* Estimate the average row size for the table and for all implied indices */ + estimateTableWidth(p); + for(pIdx=p->pIndex; pIdx; pIdx=pIdx->pNext){ + estimateIndexWidth(pIdx); + } + /* If the db->init.busy is 1 it means we are reading the SQL off the ** "sqlite_master" or "sqlite_temp_master" table on the disk. ** So do not write to the disk again. Extract the root page number @@ -1722,9 +1784,8 @@ void sqlite3CreateView( } sqlite3TwoPartName(pParse, pName1, pName2, &pName); iDb = sqlite3SchemaToIndex(db, p->pSchema); - if( sqlite3FixInit(&sFix, pParse, iDb, "view", pName) - && sqlite3FixSelect(&sFix, pSelect) - ){ + sqlite3FixInit(&sFix, pParse, iDb, "view", pName); + if( sqlite3FixSelect(&sFix, pSelect) ){ sqlite3SelectDelete(db, pSelect); return; } @@ -2485,9 +2546,10 @@ Index *sqlite3CreateIndex( int iDb; /* Index of the database that is being written */ Token *pName = 0; /* Unqualified name of the index to create */ struct ExprList_item *pListItem; /* For looping over pList */ - int nCol; - int nExtra = 0; - char *zExtra; + const Column *pTabCol; /* A column in the table */ + int nCol; /* Number of columns */ + int nExtra = 0; /* Space allocated for zExtra[] */ + char *zExtra; /* Extra space after the Index object */ assert( pParse->nErr==0 ); /* Never called with prior errors */ if( db->mallocFailed || IN_DECLARE_VTAB ){ @@ -2524,9 +2586,8 @@ Index *sqlite3CreateIndex( } #endif - if( sqlite3FixInit(&sFix, pParse, iDb, "index", pName) && - sqlite3FixSrcList(&sFix, pTblName) - ){ + sqlite3FixInit(&sFix, pParse, iDb, "index", pName); + if( sqlite3FixSrcList(&sFix, pTblName) ){ /* Because the parser constructs pTblName from a single identifier, ** sqlite3FixSrcList can never fail. */ assert(0); @@ -2715,7 +2776,6 @@ Index *sqlite3CreateIndex( */ for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ const char *zColName = pListItem->zName; - Column *pTabCol; int requestedSortOrder; char *zColl; /* Collation sequence name */ @@ -2752,6 +2812,7 @@ Index *sqlite3CreateIndex( if( pTab->aCol[j].notNull==0 ) pIndex->uniqNotNull = 0; } sqlite3DefaultRowEst(pIndex); + if( pParse->pNewTable==0 ) estimateIndexWidth(pIndex); if( pTab==pParse->pNewTable ){ /* This routine has been called to create an automatic index as a |