Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.351 2008/01/19 23:50:26 drh Exp $ +** $Id: expr.c,v 1.352 2008/01/23 14:51:49 drh Exp $ */ #include "sqliteInt.h" #include /* @@ -2920,36 +2920,29 @@ ** for variables that need to be added to the pParse->aAgg[] array. ** Make additional entries to the pParse->aAgg[] array as necessary. ** ** This routine should only be called after the expression has been ** analyzed by sqlite3ExprResolveNames(). -** -** If errors are seen, leave an error message in zErrMsg and return -** the number of errors. */ -int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ - int nErr = pNC->pParse->nErr; +void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ walkExprTree(pExpr, analyzeAggregate, pNC); - return pNC->pParse->nErr - nErr; } /* ** Call sqlite3ExprAnalyzeAggregates() for every expression in an ** expression list. Return the number of errors. ** ** If an error is found, the analysis is cut short. */ -int sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){ +void sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){ struct ExprList_item *pItem; int i; - int nErr = 0; if( pList ){ - for(pItem=pList->a, i=0; nErr==0 && inExpr; i++, pItem++){ - nErr += sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); + for(pItem=pList->a, i=0; inExpr; i++, pItem++){ + sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); } } - return nErr; } /* ** Allocate or deallocate temporary use registers during code generation. */ Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -10,11 +10,11 @@ ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.406 2008/01/19 03:35:59 drh Exp $ +** $Id: select.c,v 1.407 2008/01/23 14:51:50 drh Exp $ */ #include "sqliteInt.h" /* @@ -500,11 +500,11 @@ ** If srcTab and nColumn are both zero, then the pEList expressions ** are evaluated in order to get the data for this row. If nColumn>0 ** then data is pulled from srcTab and pEList is used only to get the ** datatypes for each column. */ -static int selectInnerLoop( +static void selectInnerLoop( Parse *pParse, /* The parser context */ Select *p, /* The complete select statement being coded */ ExprList *pEList, /* List of values being extracted */ int srcTab, /* Pull data from this table */ int nColumn, /* Number of columns in the source table */ @@ -522,11 +522,11 @@ int eDest = pDest->eDest; /* How to dispose of results */ int iParm = pDest->iParm; /* First argument to disposal method */ int nResultCol; /* Number of result columns */ int nToFree; /* Number of result columns to release */ - if( v==0 ) return 0; + if( v==0 ) return; assert( pEList!=0 ); /* If there was a LIMIT clause on the SELECT statement, then do the check ** to see if this row should be output. */ @@ -575,11 +575,11 @@ codeOffset(v, p, iContinue); } } if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ - return 0; + return; } switch( eDest ){ /* In this mode, write each query result to the key of the temporary ** table iParm. @@ -720,11 +720,10 @@ if( p->iLimit>=0 && pOrderBy==0 ){ sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak); } sqlite3ReleaseTempRange(pParse, regResult, nToFree); - return 0; } /* ** Given an expression list, generate a KeyInfo structure that records ** the collating sequence for each expression in that expression list. @@ -2055,16 +2054,12 @@ iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); iStart = sqlite3VdbeCurrentAddr(v); - rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, - pOrderBy, -1, &dest, iCont, iBreak, 0); - if( rc ){ - rc = 1; - goto multi_select_end; - } + selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, + pOrderBy, -1, &dest, iCont, iBreak, 0); sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); } @@ -2139,16 +2134,12 @@ sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); r1 = sqlite3GetTempReg(pParse); iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); sqlite3VdbeAddOp3(v, OP_NotFound, tab2, iCont, r1); sqlite3ReleaseTempReg(pParse, r1); - rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, - pOrderBy, -1, &dest, iCont, iBreak, 0); - if( rc ){ - rc = 1; - goto multi_select_end; - } + selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, + pOrderBy, -1, &dest, iCont, iBreak, 0); sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); @@ -2917,26 +2908,23 @@ ** If possible, the SELECT statement is modified so that NULL values ** are stored in the temporary table for all columns for which the ** corresponding bit in argument mask is not set. If mask takes the ** special value 0xffffffff, then all columns are populated. */ -int sqlite3SelectMask(Parse *pParse, Select *p, u32 mask){ +void sqlite3SelectMask(Parse *pParse, Select *p, u32 mask){ if( !p->pPrior && !p->isDistinct && mask!=0xffffffff ){ ExprList *pEList; int i; - if( sqlite3SelectResolve(pParse, p, 0) ){ - return SQLITE_ERROR; - } + sqlite3SelectResolve(pParse, p, 0); pEList = p->pEList; for(i=0; inExpr && i<32; i++){ if( !(mask&((u32)1<a[i].pExpr); pEList->a[i].pExpr = sqlite3Expr(pParse->db, TK_NULL, 0, 0, 0); } } } - return SQLITE_OK; } #endif /* ** Generate code for the given SELECT statement. @@ -3199,13 +3187,10 @@ ** we figure out that the sorting index is not needed. The addrSortIndex ** variable is used to facilitate that change. */ if( pOrderBy ){ KeyInfo *pKeyInfo; - if( pParse->nErr ){ - goto select_end; - } pKeyInfo = keyInfoFromExprList(pParse, pOrderBy); pOrderBy->iECursor = pParse->nTab++; p->addrOpenEphm[2] = addrSortIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pOrderBy->iECursor, pOrderBy->nExpr+2, 0, @@ -3256,14 +3241,12 @@ } /* Use the standard inner loop */ assert(!isDistinct); - if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest, - pWInfo->iContinue, pWInfo->iBreak, aff) ){ - goto select_end; - } + selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest, + pWInfo->iContinue, pWInfo->iBreak, aff); /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); }else{ @@ -3300,24 +3283,18 @@ sNC.pParse = pParse; sNC.pSrcList = pTabList; sNC.pAggInfo = &sAggInfo; sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0; sAggInfo.pGroupBy = pGroupBy; - if( sqlite3ExprAnalyzeAggList(&sNC, pEList) ){ - goto select_end; - } - if( sqlite3ExprAnalyzeAggList(&sNC, pOrderBy) ){ - goto select_end; - } - if( pHaving && sqlite3ExprAnalyzeAggregates(&sNC, pHaving) ){ - goto select_end; + sqlite3ExprAnalyzeAggList(&sNC, pEList); + sqlite3ExprAnalyzeAggList(&sNC, pOrderBy); + if( pHaving ){ + sqlite3ExprAnalyzeAggregates(&sNC, pHaving); } sAggInfo.nAccumulator = sAggInfo.nColumn; for(i=0; ipList) ){ - goto select_end; - } + sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->pList); } if( db->mallocFailed ) goto select_end; /* Processing for aggregates with GROUP BY is very different and ** much more complex than aggregates without a GROUP BY. @@ -3375,16 +3352,13 @@ sqlite3VdbeAddOp2(v, OP_Return, 0, 0); finalizeAggFunctions(pParse, &sAggInfo); if( pHaving ){ sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, SQLITE_JUMPIFNULL); } - rc = selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, - distinct, pDest, - addrOutputRow+1, addrSetAbort, aff); - if( rc ){ - goto select_end; - } + selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, + distinct, pDest, + addrOutputRow+1, addrSetAbort, aff); sqlite3VdbeAddOp2(v, OP_Return, 0, 0); VdbeComment((v, "end groupby result generator")); /* Generate a subroutine that will reset the group-by accumulator */ Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.654 2008/01/23 03:03:05 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.655 2008/01/23 14:51:50 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* @@ -1758,11 +1758,11 @@ void sqlite3DropIndex(Parse*, SrcList*, int); int sqlite3Select(Parse*, Select*, SelectDest*, Select*, int, int*, char *aff); Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, Expr*,ExprList*,int,Expr*,Expr*); void sqlite3SelectDelete(Select*); -int sqlite3SelectMask(Parse *, Select *, u32); +void sqlite3SelectMask(Parse *, Select *, u32); Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); @@ -1783,12 +1783,12 @@ void sqlite3Vacuum(Parse*); int sqlite3RunVacuum(char**, sqlite3*); char *sqlite3NameFromToken(sqlite3*, Token*); int sqlite3ExprCompare(Expr*, Expr*); int sqlite3ExprResolveNames(NameContext *, Expr *); -int sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); -int sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); +void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); +void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); Vdbe *sqlite3GetVdbe(Parse*); Expr *sqlite3CreateIdExpr(Parse *, const char*); void sqlite3Randomness(int, void*); void sqlite3RollbackAll(sqlite3*); void sqlite3CodeVerifySchema(Parse*, int); Index: src/table.c ================================================================== --- src/table.c +++ src/table.c @@ -68,15 +68,11 @@ ** the names of all columns. */ if( p->nRow==0 ){ p->nColumn = nCol; for(i=0; iazResult[p->nData++] = z; } }else if( p->nColumn!=nCol ){ sqlite3_free(p->zErrMsg); @@ -128,11 +124,11 @@ int *pnColumn, /* Write the number of columns of result here */ char **pzErrMsg /* Write error messages here */ ){ int rc; TabResult res; - if( pazResult==0 ){ return SQLITE_ERROR; } + *pazResult = 0; if( pnColumn ) *pnColumn = 0; if( pnRow ) *pnRow = 0; res.zErrMsg = 0; res.nResult = 0; @@ -146,14 +142,12 @@ db->errCode = SQLITE_NOMEM; return SQLITE_NOMEM; } res.azResult[0] = 0; rc = sqlite3_exec(db, zSql, sqlite3_get_table_cb, &res, pzErrMsg); - if( res.azResult ){ - assert( sizeof(res.azResult[0])>= sizeof(res.nData) ); - res.azResult[0] = (char*)res.nData; - } + assert( sizeof(res.azResult[0])>= sizeof(res.nData) ); + res.azResult[0] = (char*)res.nData; if( (rc&0xff)==SQLITE_ABORT ){ sqlite3_free_table(&res.azResult[1]); if( res.zErrMsg ){ if( pzErrMsg ){ sqlite3_free(*pzErrMsg); @@ -193,13 +187,13 @@ char **azResult /* Result returned from from sqlite3_get_table() */ ){ if( azResult ){ int i, n; azResult--; - if( azResult==0 ) return; + assert( azResult!=0 ); n = (int)azResult[0]; for(i=1; i #include @@ -492,11 +492,11 @@ Tcl_AppendResult(interp, zStr, 0); return TCL_OK; } /* -** Usage: sqlite3_get_table_printf DB FORMAT STRING +** Usage: sqlite3_get_table_printf DB FORMAT STRING ?--no-counts? ** ** Invoke the sqlite3_get_table_printf() interface using the open database ** DB. The SQL is the string FORMAT. The format string should contain ** one %s or %q. STRING is the value inserted into %s or %q. */ @@ -513,28 +513,39 @@ int nRow, nCol; char **aResult; int i; char zBuf[30]; char *zSql; - if( argc!=4 ){ + int resCount = -1; + if( argc==5 ){ + if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR; + } + if( argc!=4 && argc!=5 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " DB FORMAT STRING", 0); + " DB FORMAT STRING ?COUNT?", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; Tcl_DStringInit(&str); zSql = sqlite3_mprintf(argv[2],argv[3]); - rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr); + if( argc==5 ){ + rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr); + }else{ + rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr); + resCount = (nRow+1)*nCol; + } sqlite3_free(zSql); sprintf(zBuf, "%d", rc); Tcl_AppendElement(interp, zBuf); if( rc==SQLITE_OK ){ - sprintf(zBuf, "%d", nRow); - Tcl_AppendElement(interp, zBuf); - sprintf(zBuf, "%d", nCol); - Tcl_AppendElement(interp, zBuf); - for(i=0; i<(nRow+1)*nCol; i++){ + if( argc==4 ){ + sprintf(zBuf, "%d", nRow); + Tcl_AppendElement(interp, zBuf); + sprintf(zBuf, "%d", nCol); + Tcl_AppendElement(interp, zBuf); + } + for(i=0; i47 ORDER BY a; invalid } {} } {1 {near "invalid": syntax error}} +do_test tableapi-2.3.4 { +breakpoint + sqlite3_get_table_printf $::dbx { + SELECT * FROM xyz WHERE a>47 ORDER BY a + } {} 8 +} {0 a b 48 (48) 49 (49) 50 (50)} do_test tableapi-2.4 { set manyquote '''''''' append manyquote $manyquote append manyquote $manyquote append manyquote $manyquote