Index: src/tokenize.c ================================================================== --- src/tokenize.c +++ src/tokenize.c @@ -220,24 +220,25 @@ ** ** Instead of using sqlite3GetToken() to parse tokens directly, this function ** uses windowGetToken(). This is to avoid recursion if the input is similar ** to "window window window window". */ -static void analyzeWindowKeyword(const unsigned char *z, int *tokenType){ +static int analyzeWindowKeyword(const unsigned char *z){ int t; - assert( *tokenType==TK_WINDOW ); + int ret = TK_WINDOW; while( (t = windowGetToken(&z))==TK_SPACE ); if( t!=TK_ID && t!=TK_STRING && t!=TK_JOIN_KW && sqlite3ParserFallback(t)!=TK_ID ){ - *tokenType = TK_ID; + ret = TK_ID; }else{ while( (t = windowGetToken(&z))==TK_SPACE ); if( t!=TK_AS ){ - *tokenType = TK_ID; + ret = TK_ID; } } + return ret; } /* ** Return the length (in bytes) of the token that begins at z[0]. ** Store the token type in *tokenType before returning. @@ -480,16 +481,11 @@ ** be an identifier instead */ i++; break; } *tokenType = TK_ID; - keywordCode((char*)z, i, tokenType); - if( *tokenType==TK_WINDOW ){ - assert( i==6 ); - analyzeWindowKeyword(&z[6], tokenType); - } - return i; + return keywordCode((char*)z, i, tokenType); } case CC_X: { #ifndef SQLITE_OMIT_BLOB_LITERAL testcase( z[0]=='x' ); testcase( z[0]=='X' ); if( z[1]=='\'' ){ @@ -592,10 +588,13 @@ sqlite3ErrorMsg(pParse, "unrecognized token: \"%.*s\"", n, zSql); break; } zSql += n; }else{ + if( tokenType==TK_WINDOW ){ + tokenType = analyzeWindowKeyword((const u8*)&zSql[6]); + } pParse->sLastToken.z = zSql; pParse->sLastToken.n = n; sqlite3Parser(pEngine, tokenType, pParse->sLastToken); lastTokenParsed = tokenType; zSql += n;