Upgrade bundled library to 2.8.14 + misc fixes

(http://www.sqlite.org/cvstrac/chngview?cn=1742)
This commit is contained in:
Wez Furlong 2004-07-10 12:27:51 +00:00
parent cd732f1a3f
commit e563b4eafa
43 changed files with 5953 additions and 5559 deletions

View file

@ -42,6 +42,9 @@ Select *sqliteSelectNew(
sqliteExprDelete(pHaving);
sqliteExprListDelete(pOrderBy);
}else{
if( pEList==0 ){
pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL,0,0,0), 0);
}
pNew->pEList = pEList;
pNew->pSrc = pSrc;
pNew->pWhere = pWhere;
@ -335,9 +338,7 @@ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
sqliteExprCode(pParse, pOrderBy->a[i].pExpr);
}
zSortOrder[pOrderBy->nExpr] = 0;
sqliteVdbeAddOp(v, OP_SortMakeKey, pOrderBy->nExpr, 0);
sqliteVdbeChangeP3(v, -1, zSortOrder, strlen(zSortOrder));
sqliteFree(zSortOrder);
sqliteVdbeOp3(v, OP_SortMakeKey, pOrderBy->nExpr, 0, zSortOrder, P3_DYNAMIC);
sqliteVdbeAddOp(v, OP_SortPut, 0, 0);
}
@ -360,8 +361,7 @@ void sqliteAddKeyType(Vdbe *v, ExprList *pEList){
zType[i] = sqliteExprType(pEList->a[i].pExpr)==SQLITE_SO_NUM ? 'n' : 't';
}
zType[i] = 0;
sqliteVdbeChangeP3(v, -1, zType, nColumn);
sqliteFree(zType);
sqliteVdbeChangeP3(v, -1, zType, P3_DYNAMIC);
}
/*
@ -564,18 +564,19 @@ static void generateSortTail(
int eDest, /* Write the sorted results here */
int iParm /* Optional parameter associated with eDest */
){
int end = sqliteVdbeMakeLabel(v);
int end1 = sqliteVdbeMakeLabel(v);
int end2 = sqliteVdbeMakeLabel(v);
int addr;
if( eDest==SRT_Sorter ) return;
sqliteVdbeAddOp(v, OP_Sort, 0, 0);
addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end);
addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end1);
if( p->iOffset>=0 ){
sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+4);
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
}
if( p->iLimit>=0 ){
sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, end);
sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, end2);
}
switch( eDest ){
case SRT_Callback: {
@ -601,7 +602,7 @@ static void generateSortTail(
case SRT_Mem: {
assert( nColumn==1 );
sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);
sqliteVdbeAddOp(v, OP_Goto, 0, end);
sqliteVdbeAddOp(v, OP_Goto, 0, end1);
break;
}
case SRT_Subroutine: {
@ -619,7 +620,9 @@ static void generateSortTail(
}
}
sqliteVdbeAddOp(v, OP_Goto, 0, addr);
sqliteVdbeResolveLabel(v, end);
sqliteVdbeResolveLabel(v, end2);
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
sqliteVdbeResolveLabel(v, end1);
sqliteVdbeAddOp(v, OP_SortReset, 0, 0);
}
@ -645,9 +648,6 @@ static void generateColumnTypes(
){
Vdbe *v = pParse->pVdbe;
int i, j;
if( pParse->useCallback && (pParse->db->flags & SQLITE_ReportTypes)==0 ){
return;
}
for(i=0; i<pEList->nExpr; i++){
Expr *p = pEList->a[i].pExpr;
char *zType = 0;
@ -672,15 +672,14 @@ static void generateColumnTypes(
zType = "NUMERIC";
}
}
sqliteVdbeAddOp(v, OP_ColumnName, i + pEList->nExpr, 0);
sqliteVdbeChangeP3(v, -1, zType, P3_STATIC);
sqliteVdbeOp3(v, OP_ColumnName, i + pEList->nExpr, 0, zType, 0);
}
}
/*
** Generate code that will tell the VDBE the names of columns
** in the result set. This information is used to provide the
** azCol[] vaolues in the callback.
** azCol[] values in the callback.
*/
static void generateColumnNames(
Parse *pParse, /* Parser context */
@ -689,21 +688,24 @@ static void generateColumnNames(
){
Vdbe *v = pParse->pVdbe;
int i, j;
sqlite *db = pParse->db;
int fullNames, shortNames;
assert( v!=0 );
if( pParse->colNamesSet || v==0 || sqlite_malloc_failed ) return;
pParse->colNamesSet = 1;
fullNames = (db->flags & SQLITE_FullColNames)!=0;
shortNames = (db->flags & SQLITE_ShortColNames)!=0;
for(i=0; i<pEList->nExpr; i++){
Expr *p;
char *zType = 0;
int showFullNames;
int p2 = i==pEList->nExpr-1;
p = pEList->a[i].pExpr;
if( p==0 ) continue;
if( pEList->a[i].zName ){
char *zName = pEList->a[i].zName;
sqliteVdbeAddOp(v, OP_ColumnName, i, 0);
sqliteVdbeChangeP3(v, -1, zName, strlen(zName));
sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, 0);
continue;
}
showFullNames = (pParse->db->flags & SQLITE_FullColNames)!=0;
if( p->op==TK_COLUMN && pTabList ){
Table *pTab;
char *zCol;
@ -715,39 +717,31 @@ static void generateColumnNames(
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
if( iCol<0 ){
zCol = "_ROWID_";
zType = "INTEGER";
}else{
zCol = pTab->aCol[iCol].zName;
zType = pTab->aCol[iCol].zType;
}
if( p->span.z && p->span.z[0] && !showFullNames ){
int addr = sqliteVdbeAddOp(v,OP_ColumnName, i, 0);
sqliteVdbeChangeP3(v, -1, p->span.z, p->span.n);
if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){
int addr = sqliteVdbeOp3(v,OP_ColumnName, i, p2, p->span.z, p->span.n);
sqliteVdbeCompressSpace(v, addr);
}else if( pTabList->nSrc>1 || showFullNames ){
}else if( fullNames || (!shortNames && pTabList->nSrc>1) ){
char *zName = 0;
char *zTab;
zTab = pTabList->a[j].zAlias;
if( showFullNames || zTab==0 ) zTab = pTab->zName;
if( fullNames || zTab==0 ) zTab = pTab->zName;
sqliteSetString(&zName, zTab, ".", zCol, 0);
sqliteVdbeAddOp(v, OP_ColumnName, i, 0);
sqliteVdbeChangeP3(v, -1, zName, strlen(zName));
sqliteFree(zName);
sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, P3_DYNAMIC);
}else{
sqliteVdbeAddOp(v, OP_ColumnName, i, 0);
sqliteVdbeChangeP3(v, -1, zCol, 0);
sqliteVdbeOp3(v, OP_ColumnName, i, p2, zCol, 0);
}
}else if( p->span.z && p->span.z[0] ){
int addr = sqliteVdbeAddOp(v,OP_ColumnName, i, 0);
sqliteVdbeChangeP3(v, -1, p->span.z, p->span.n);
int addr = sqliteVdbeOp3(v,OP_ColumnName, i, p2, p->span.z, p->span.n);
sqliteVdbeCompressSpace(v, addr);
}else{
char zName[30];
assert( p->op!=TK_COLUMN || pTabList==0 );
sprintf(zName, "column%d", i+1);
sqliteVdbeAddOp(v, OP_ColumnName, i, 0);
sqliteVdbeChangeP3(v, -1, zName, strlen(zName));
sqliteVdbeOp3(v, OP_ColumnName, i, p2, zName, 0);
}
}
}
@ -777,8 +771,9 @@ static int fillInColumnList(Parse*, Select*);
*/
Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
Table *pTab;
int i;
int i, j;
ExprList *pEList;
Column *aCol;
if( fillInColumnList(pParse, pSelect) ){
return 0;
@ -791,17 +786,27 @@ Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
pEList = pSelect->pEList;
pTab->nCol = pEList->nExpr;
assert( pTab->nCol>0 );
pTab->aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
for(i=0; i<pTab->nCol; i++){
Expr *p;
Expr *p, *pR;
if( pEList->a[i].zName ){
pTab->aCol[i].zName = sqliteStrDup(pEList->a[i].zName);
}else if( (p=pEList->a[i].pExpr)->span.z && p->span.z[0] ){
aCol[i].zName = sqliteStrDup(pEList->a[i].zName);
}else if( (p=pEList->a[i].pExpr)->op==TK_DOT
&& (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
int cnt;
sqliteSetNString(&aCol[i].zName, pR->token.z, pR->token.n, 0);
for(j=cnt=0; j<i; j++){
if( sqliteStrICmp(aCol[j].zName, aCol[i].zName)==0 ){
int n;
char zBuf[30];
sprintf(zBuf,"_%d",++cnt);
n = strlen(zBuf);
sqliteSetNString(&aCol[i].zName, pR->token.z, pR->token.n, zBuf, n,0);
j = -1;
}
}
}else if( p->span.z && p->span.z[0] ){
sqliteSetNString(&pTab->aCol[i].zName, p->span.z, p->span.n, 0);
}else if( p->op==TK_DOT && p->pRight && p->pRight->token.z &&
p->pRight->token.z[0] ){
sqliteSetNString(&pTab->aCol[i].zName,
p->pRight->token.z, p->pRight->token.n, 0);
}else{
char zBuf[30];
sprintf(zBuf, "column%d", i+1);
@ -1262,7 +1267,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p){
** |
** `-----> SELECT b FROM t2
** |
** `------> SELECT c FROM t1
** `------> SELECT a FROM t1
**
** The arrows in the diagram above represent the Select.pPrior pointer.
** So if this routine is called with p equal to the t3 query, then
@ -1485,14 +1490,6 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
" do not have the same number of result columns", selectOpName(p->op));
return 1;
}
/* Issue a null callback if that is what the user wants.
*/
if( eDest==SRT_Callback &&
(pParse->useCallback==0 || (pParse->db->flags & SQLITE_NullCallback)!=0)
){
sqliteVdbeAddOp(v, OP_NullCallback, p->pEList->nExpr, 0);
}
return 0;
}
@ -1512,25 +1509,29 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){
static void substExprList(ExprList*,int,ExprList*); /* Forward Decl */
static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
if( pExpr==0 ) return;
if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable && pExpr->iColumn>=0 ){
Expr *pNew;
assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 );
pNew = pEList->a[pExpr->iColumn].pExpr;
assert( pNew!=0 );
pExpr->op = pNew->op;
pExpr->dataType = pNew->dataType;
assert( pExpr->pLeft==0 );
pExpr->pLeft = sqliteExprDup(pNew->pLeft);
assert( pExpr->pRight==0 );
pExpr->pRight = sqliteExprDup(pNew->pRight);
assert( pExpr->pList==0 );
pExpr->pList = sqliteExprListDup(pNew->pList);
pExpr->iTable = pNew->iTable;
pExpr->iColumn = pNew->iColumn;
pExpr->iAgg = pNew->iAgg;
sqliteTokenCopy(&pExpr->token, &pNew->token);
sqliteTokenCopy(&pExpr->span, &pNew->span);
if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
}else{
Expr *pNew;
assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 );
pNew = pEList->a[pExpr->iColumn].pExpr;
assert( pNew!=0 );
pExpr->op = pNew->op;
pExpr->dataType = pNew->dataType;
assert( pExpr->pLeft==0 );
pExpr->pLeft = sqliteExprDup(pNew->pLeft);
assert( pExpr->pRight==0 );
pExpr->pRight = sqliteExprDup(pNew->pRight);
assert( pExpr->pList==0 );
pExpr->pList = sqliteExprListDup(pNew->pList);
pExpr->iTable = pNew->iTable;
pExpr->iColumn = pNew->iColumn;
pExpr->iAgg = pNew->iAgg;
sqliteTokenCopy(&pExpr->token, &pNew->token);
sqliteTokenCopy(&pExpr->span, &pNew->span);
}
}else{
substExpr(pExpr->pLeft, iTable, pEList);
substExpr(pExpr->pRight, iTable, pEList);
@ -1835,18 +1836,23 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
Vdbe *v;
int seekOp;
int cont;
ExprList eList;
ExprList *pEList, *pList, eList;
struct ExprList_item eListItem;
SrcList *pSrc;
/* Check to see if this query is a simple min() or max() query. Return
** zero if it is not.
*/
if( p->pGroupBy || p->pHaving || p->pWhere ) return 0;
if( p->pSrc->nSrc!=1 ) return 0;
if( p->pEList->nExpr!=1 ) return 0;
pExpr = p->pEList->a[0].pExpr;
pSrc = p->pSrc;
if( pSrc->nSrc!=1 ) return 0;
pEList = p->pEList;
if( pEList->nExpr!=1 ) return 0;
pExpr = pEList->a[0].pExpr;
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
if( pExpr->pList==0 || pExpr->pList->nExpr!=1 ) return 0;
pList = pExpr->pList;
if( pList==0 || pList->nExpr!=1 ) return 0;
if( pExpr->token.n!=3 ) return 0;
if( sqliteStrNICmp(pExpr->token.z,"min",3)==0 ){
seekOp = OP_Rewind;
@ -1855,10 +1861,10 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
}else{
return 0;
}
pExpr = pExpr->pList->a[0].pExpr;
pExpr = pList->a[0].pExpr;
if( pExpr->op!=TK_COLUMN ) return 0;
iCol = pExpr->iColumn;
pTab = p->pSrc->a[0].pTab;
pTab = pSrc->a[0].pTab;
/* If we get to here, it means the query is of the correct form.
** Check to make sure we have an index and make pIdx point to the
@ -1886,24 +1892,30 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
generateColumnTypes(pParse, p->pSrc, p->pEList);
}
/* If the output is destined for a temporary table, open that table.
*/
if( eDest==SRT_TempTable ){
sqliteVdbeAddOp(v, OP_OpenTemp, iParm, 0);
}
/* Generating code to find the min or the max. Basically all we have
** to do is find the first or the last entry in the chosen index. If
** the min() or max() is on the INTEGER PRIMARY KEY, then find the first
** or last entry in the main table.
*/
sqliteCodeVerifySchema(pParse, pTab->iDb);
base = p->pSrc->a[0].iCursor;
base = pSrc->a[0].iCursor;
computeLimitRegisters(pParse, p);
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenRead, base, pTab->tnum);
sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
if( pSrc->a[0].pSelect==0 ){
sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0);
sqliteVdbeOp3(v, OP_OpenRead, base, pTab->tnum, pTab->zName, 0);
}
cont = sqliteVdbeMakeLabel(v);
if( pIdx==0 ){
sqliteVdbeAddOp(v, seekOp, base, 0);
}else{
sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
sqliteVdbeAddOp(v, OP_OpenRead, base+1, pIdx->tnum);
sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
sqliteVdbeOp3(v, OP_OpenRead, base+1, pIdx->tnum, pIdx->zName, P3_STATIC);
sqliteVdbeAddOp(v, seekOp, base+1, 0);
sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0);
sqliteVdbeAddOp(v, OP_Close, base+1, 0);
@ -1916,6 +1928,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont);
sqliteVdbeResolveLabel(v, cont);
sqliteVdbeAddOp(v, OP_Close, base, 0);
return 1;
}
@ -1935,7 +1948,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
**
** SRT_Union Store results as a key in a temporary table iParm
**
** SRT_Except Remove results form the temporary table iParm.
** SRT_Except Remove results from the temporary table iParm.
**
** SRT_Table Store results in temporary table iParm
**
@ -2156,14 +2169,6 @@ int sqliteSelect(
generateColumnNames(pParse, pTabList, pEList);
}
/* Check for the special case of a min() or max() function by itself
** in the result set.
*/
if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){
rc = 0;
goto select_end;
}
/* Generate code for all sub-queries in the FROM clause
*/
for(i=0; i<pTabList->nSrc; i++){
@ -2193,6 +2198,14 @@ int sqliteSelect(
isDistinct = p->isDistinct;
}
/* Check for the special case of a min() or max() function by itself
** in the result set.
*/
if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){
rc = 0;
goto select_end;
}
/* Check to see if this is a subquery that can be "flattened" into its parent.
** If flattening is a possiblity, do so and return immediately.
*/
@ -2262,8 +2275,7 @@ int sqliteSelect(
for(i=0; i<pParse->nAgg; i++){
FuncDef *pFunc;
if( (pFunc = pParse->aAgg[i].pFunc)!=0 && pFunc->xFinalize!=0 ){
sqliteVdbeAddOp(v, OP_AggInit, 0, i);
sqliteVdbeChangeP3(v, -1, (char*)pFunc, P3_POINTER);
sqliteVdbeOp3(v, OP_AggInit, 0, i, (char*)pFunc, P3_POINTER);
}
}
if( pGroupBy==0 ){
@ -2308,6 +2320,7 @@ int sqliteSelect(
** processing.
*/
else{
AggExpr *pAgg;
if( pGroupBy ){
int lbl1;
for(i=0; i<pGroupBy->nExpr; i++){
@ -2317,29 +2330,27 @@ int sqliteSelect(
if( pParse->db->file_format>=4 ) sqliteAddKeyType(v, pGroupBy);
lbl1 = sqliteVdbeMakeLabel(v);
sqliteVdbeAddOp(v, OP_AggFocus, 0, lbl1);
for(i=0; i<pParse->nAgg; i++){
if( pParse->aAgg[i].isAgg ) continue;
sqliteExprCode(pParse, pParse->aAgg[i].pExpr);
for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){
if( pAgg->isAgg ) continue;
sqliteExprCode(pParse, pAgg->pExpr);
sqliteVdbeAddOp(v, OP_AggSet, 0, i);
}
sqliteVdbeResolveLabel(v, lbl1);
}
for(i=0; i<pParse->nAgg; i++){
for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){
Expr *pE;
int j;
if( !pParse->aAgg[i].isAgg ) continue;
pE = pParse->aAgg[i].pExpr;
int nExpr;
FuncDef *pDef;
if( !pAgg->isAgg ) continue;
assert( pAgg->pFunc!=0 );
assert( pAgg->pFunc->xStep!=0 );
pDef = pAgg->pFunc;
pE = pAgg->pExpr;
assert( pE!=0 );
assert( pE->op==TK_AGG_FUNCTION );
if( pE->pList ){
for(j=0; j<pE->pList->nExpr; j++){
sqliteExprCode(pParse, pE->pList->a[j].pExpr);
}
}
nExpr = sqliteExprCodeExprList(pParse, pE->pList, pDef->includeTypes);
sqliteVdbeAddOp(v, OP_Integer, i, 0);
sqliteVdbeAddOp(v, OP_AggFunc, 0, pE->pList ? pE->pList->nExpr : 0);
assert( pParse->aAgg[i].pFunc!=0 );
assert( pParse->aAgg[i].pFunc->xStep!=0 );
sqliteVdbeChangeP3(v, -1, (char*)pParse->aAgg[i].pFunc, P3_POINTER);
sqliteVdbeOp3(v, OP_AggFunc, 0, nExpr, (char*)pDef, P3_POINTER);
}
}
@ -2375,13 +2386,16 @@ int sqliteSelect(
generateSortTail(p, v, pEList->nExpr, eDest, iParm);
}
/* Issue a null callback if that is what the user wants.
/* If this was a subquery, we have now converted the subquery into a
** temporary table. So delete the subquery structure from the parent
** to prevent this subquery from being evaluated again and to force the
** the use of the temporary table.
*/
if( eDest==SRT_Callback &&
(pParse->useCallback==0 || (pParse->db->flags & SQLITE_NullCallback)!=0)
){
sqliteVdbeAddOp(v, OP_NullCallback, pEList->nExpr, 0);
if( pParent ){
assert( pParent->pSrc->nSrc>parentTab );
assert( pParent->pSrc->a[parentTab].pSelect==p );
sqliteSelectDelete(p);
pParent->pSrc->a[parentTab].pSelect = 0;
}
/* The SELECT was successfully coded. Set the return code to 0