/* ** 2008 August 18 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** This file contains routines used for walking the parser tree and ** resolve all identifiers by associating them with a particular ** table and column. ************************************************************************* ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart ** C#-SQLite is an independent reimplementation of the SQLite software library ** ** SQLITE_SOURCE_ID: 2010-08-23 18:52:01 42537b60566f288167f1b5864a5435986838e3a3 ** ************************************************************************* */ //#include "sqliteInt.h" //#include <stdlib.h> //#include <string.h> /* ** Turn the pExpr expression into an alias for the iCol-th column of the ** result set in pEList. ** ** If the result set column is a simple column reference, then this routine ** makes an exact copy. But for any other kind of expression, this ** routine make a copy of the result set column as the argument to the ** TK_AS operator. The TK_AS operator causes the expression to be ** evaluated just once and then reused for each alias. ** ** The reason for suppressing the TK_AS term when the expression is a simple ** column reference is so that the column reference will be recognized as ** usable by indices within the WHERE clause processing logic. ** ** Hack: The TK_AS operator is inhibited if zType[0]=='G'. This means ** that in a GROUP BY clause, the expression is evaluated twice. Hence: ** ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY x ** ** Is equivalent to: ** ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 ** ** The result of random()%5 in the GROUP BY clause is probably different ** from the result in the result-set. We might fix this someday. Or ** then again, we might not... */ static void resolveAlias( Parse pParse, /* Parsing context */ ExprList pEList, /* A result set */ int iCol, /* A column in the result set. 0..pEList.nExpr-1 */ Expr pExpr, /* Transform this into an alias to the result set */ string zType /* "GROUP" or "ORDER" or "" */ ) { Expr pOrig; /* The iCol-th column of the result set */ Expr pDup; /* Copy of pOrig */ sqlite3 db; /* The database connection */ Debug.Assert( iCol >= 0 && iCol < pEList.nExpr ); pOrig = pEList.a[iCol].pExpr; Debug.Assert( pOrig != null ); Debug.Assert( ( pOrig.flags & EP_Resolved ) != 0 ); db = pParse.db; if ( pOrig.op != TK_COLUMN && ( zType.Length == 0 || zType[0] != 'G' ) ) { pDup = sqlite3ExprDup( db, pOrig, 0 ); pDup = sqlite3PExpr( pParse, TK_AS, pDup, null, null ); if ( pDup == null ) return; if ( pEList.a[iCol].iAlias == 0 ) { pEList.a[iCol].iAlias = (u16)( ++pParse.nAlias ); } pDup.iTable = pEList.a[iCol].iAlias; } else if ( ExprHasProperty( pOrig, EP_IntValue ) || pOrig.u.zToken == null ) { pDup = sqlite3ExprDup( db, pOrig, 0 ); if ( pDup == null ) return; } else { string zToken = pOrig.u.zToken; Debug.Assert( zToken != null ); pOrig.u.zToken = null; pDup = sqlite3ExprDup( db, pOrig, 0 ); pOrig.u.zToken = zToken; if ( pDup == null ) return; Debug.Assert( ( pDup.flags & ( EP_Reduced | EP_TokenOnly ) ) == 0 ); pDup.flags2 |= EP2_MallocedToken; pDup.u.zToken = zToken;// sqlite3DbStrDup( db, zToken ); } if ( ( pExpr.flags & EP_ExpCollate ) != 0 ) { pDup.pColl = pExpr.pColl; pDup.flags |= EP_ExpCollate; } /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This ** prevents ExprDelete() from deleting the Expr structure itself, ** allowing it to be repopulated by the memcpy() on the following line. */ ExprSetProperty( pExpr, EP_Static ); sqlite3ExprDelete( db, ref pExpr ); pExpr.CopyFrom( pDup ); //memcpy(pExpr, pDup, sizeof(*pExpr)); sqlite3DbFree( db, ref pDup ); }