/* ** Locate or create an AutoincInfo structure associated with table pTab ** which is in database iDb. Return the register number for the register ** that holds the maximum rowid. ** ** There is at most one AutoincInfo structure per table even if the ** same table is autoincremented multiple times due to inserts within ** triggers. A new AutoincInfo structure is created if this is the ** first use of table pTab. On 2nd and subsequent uses, the original ** AutoincInfo structure is used. ** ** Three memory locations are allocated: ** ** (1) Register to hold the name of the pTab table. ** (2) Register to hold the maximum ROWID of pTab. ** (3) Register to hold the rowid in sqlite_sequence of pTab ** ** The 2nd register is the one that is returned. That is all the ** insert routine needs to know about. */ static int autoIncBegin( Parse pParse, /* Parsing context */ int iDb, /* Index of the database holding pTab */ Table pTab /* The table we are writing to */ ) { int memId = 0; /* Register holding maximum rowid */ if ( ( pTab.tabFlags & TF_Autoincrement ) != 0 ) { Parse pToplevel = sqlite3ParseToplevel( pParse ); AutoincInfo pInfo; pInfo = pToplevel.pAinc; while ( pInfo != null && pInfo.pTab != pTab ) { pInfo = pInfo.pNext; } if ( pInfo == null ) { pInfo = new AutoincInfo();//sqlite3DbMallocRaw(pParse.db, sizeof(*pInfo)); //if( pInfo==0 ) return 0; pInfo.pNext = pToplevel.pAinc; pToplevel.pAinc = pInfo; pInfo.pTab = pTab; pInfo.iDb = iDb; pToplevel.nMem++; /* Register to hold name of table */ pInfo.regCtr = ++pToplevel.nMem; /* Max rowid register */ pToplevel.nMem++; /* Rowid in sqlite_sequence */ } memId = pInfo.regCtr; } return memId; }
/* ** Run the parser on the given SQL string. The parser structure is ** passed in. An SQLITE_ status code is returned. If an error occurs ** then an and attempt is made to write an error message into ** memory obtained from sqlite3_malloc() and to make pzErrMsg point to that ** error message. */ static int sqlite3RunParser(Parse pParse, string zSql, ref string pzErrMsg) { int nErr = 0; /* Number of errors encountered */ int i; /* Loop counter */ yyParser pEngine; /* The LEMON-generated LALR(1) parser */ int tokenType = 0; /* type of the next token */ int lastTokenParsed = -1; /* type of the previous token */ byte enableLookaside; /* Saved value of db->lookaside.bEnabled */ sqlite3 db = pParse.db; /* The database connection */ int mxSqlLen; /* Max length of an SQL string */ mxSqlLen = db.aLimit[SQLITE_LIMIT_SQL_LENGTH]; if (db.activeVdbeCnt == 0) { db.u1.isInterrupted = false; } pParse.rc = SQLITE_OK; pParse.zTail = new StringBuilder(zSql); i = 0; Debug.Assert(pzErrMsg != null); pEngine = sqlite3ParserAlloc();//sqlite3ParserAlloc((void*(*)(size_t))sqlite3Malloc); if (pEngine == null) { //// db.mallocFailed = 1; return(SQLITE_NOMEM); } Debug.Assert(pParse.pNewTable == null); Debug.Assert(pParse.pNewTrigger == null); Debug.Assert(pParse.nVar == 0); Debug.Assert(pParse.nVarExpr == 0); Debug.Assert(pParse.nVarExprAlloc == 0); Debug.Assert(pParse.apVarExpr == null); enableLookaside = db.lookaside.bEnabled; if (db.lookaside.pStart != 0) { db.lookaside.bEnabled = 1; } while (/* 0 == db.mallocFailed && */ i < zSql.Length) { Debug.Assert(i >= 0); //pParse->sLastToken.z = &zSql[i]; pParse.sLastToken.n = sqlite3GetToken(zSql, i, ref tokenType); pParse.sLastToken.z = zSql.Substring(i); i += pParse.sLastToken.n; if (i > mxSqlLen) { pParse.rc = SQLITE_TOOBIG; break; } switch (tokenType) { case TK_SPACE: { if (db.u1.isInterrupted) { sqlite3ErrorMsg(pParse, "interrupt"); pParse.rc = SQLITE_INTERRUPT; goto abort_parse; } break; } case TK_ILLEGAL: { //sqlite3DbFree( db, ref pzErrMsg ); pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"", (object)pParse.sLastToken); nErr++; goto abort_parse; } case TK_SEMI: { //pParse.zTail = new StringBuilder(zSql.Substring( i,zSql.Length-i )); /* Fall thru into the default case */ goto default; } default: { sqlite3Parser(pEngine, tokenType, pParse.sLastToken, pParse); lastTokenParsed = tokenType; if (pParse.rc != SQLITE_OK) { goto abort_parse; } break; } } } abort_parse: pParse.zTail = new StringBuilder(zSql.Length <= i ? "" : zSql.Substring(i, zSql.Length - i)); if (zSql.Length >= i && nErr == 0 && pParse.rc == SQLITE_OK) { if (lastTokenParsed != TK_SEMI) { sqlite3Parser(pEngine, TK_SEMI, pParse.sLastToken, pParse); } sqlite3Parser(pEngine, 0, pParse.sLastToken, pParse); } #if YYTRACKMAXSTACKDEPTH sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK, sqlite3ParserStackPeak(pEngine) ); #endif //* YYDEBUG */ sqlite3ParserFree(pEngine, null);//sqlite3_free ); db.lookaside.bEnabled = enableLookaside; //if ( db.mallocFailed != 0 ) //{ // pParse.rc = SQLITE_NOMEM; //} if (pParse.rc != SQLITE_OK && pParse.rc != SQLITE_DONE && pParse.zErrMsg == "") { sqlite3SetString(ref pParse.zErrMsg, db, sqlite3ErrStr(pParse.rc)); } //assert( pzErrMsg!=0 ); if (pParse.zErrMsg != null) { pzErrMsg = pParse.zErrMsg; pParse.zErrMsg = ""; nErr++; } if (pParse.pVdbe != null && pParse.nErr > 0 && pParse.nested == 0) { sqlite3VdbeDelete(ref pParse.pVdbe); pParse.pVdbe = null; } #if !SQLITE_OMIT_SHARED_CACHE if (pParse.nested == 0) { //sqlite3DbFree( db, ref pParse.aTableLock ); pParse.aTableLock = null; pParse.nTableLock = 0; } #endif #if !SQLITE_OMIT_VIRTUALTABLE //sqlite3DbFree(db,pParse.apVtabLock); #endif if (!IN_DECLARE_VTAB) { /* If the pParse.declareVtab flag is set, do not delete any table ** structure built up in pParse.pNewTable. The calling code (see vtab.c) ** will take responsibility for freeing the Table structure. */ sqlite3DeleteTable(ref pParse.pNewTable); } #if !SQLITE_OMIT_TRIGGER sqlite3DeleteTrigger(db, ref pParse.pNewTrigger); #endif //sqlite3DbFree( db, ref pParse.apVarExpr ); //sqlite3DbFree( db, ref pParse.aAlias ); while (pParse.pAinc != null) { AutoincInfo p = pParse.pAinc; pParse.pAinc = p.pNext; //sqlite3DbFree( db, ref p ); } while (pParse.pZombieTab != null) { Table p = pParse.pZombieTab; pParse.pZombieTab = p.pNextZombie; sqlite3DeleteTable(ref p); } if (nErr > 0 && pParse.rc == SQLITE_OK) { pParse.rc = SQLITE_ERROR; } return(nErr); }
public int RunParser(string sql, ref string errMsg) { Debug.Assert(errMsg != null); Debug.Assert(NewTable == null); Debug.Assert(NewTrigger == null); Debug.Assert(VarsSeen == 0); Debug.Assert(Vars.length == 0); Debug.Assert(Vars.data == null); Context ctx = Ctx; // The database connection int maxSqlLength = ctx.Limits[(int)LIMIT.SQL_LENGTH]; // Max length of an SQL string if (ctx.ActiveVdbeCnt == 0) { ctx.u1.IsInterrupted = false; } RC = RC.OK; Tail = new StringBuilder(sql); yyParser engine = Parser_Alloc(); // The LEMON-generated LALR(1) parser if (engine == null) { ctx.MallocFailed = true; return((int)RC.NOMEM); } bool enableLookaside = ctx.Lookaside.Enabled; // Saved value of db->lookaside.bEnabled if (ctx.Lookaside.Start != 0) { ctx.Lookaside.Enabled = true; } int errs = 0; // Number of errors encountered TK tokenType = 0; // type of the next token TK lastTokenParsed = 0; // type of the previous token int i = 0; while (/* !ctx.MallocFailed && */ i < sql.Length) { Debug.Assert(i >= 0); LastToken.data = sql.Substring(i); LastToken.length = (uint)GetToken(sql, i, ref tokenType); i += (int)LastToken.length; if (i > maxSqlLength) { RC = RC.TOOBIG; break; } switch (tokenType) { case TK.SPACE: { if (ctx.u1.IsInterrupted) { ErrorMsg("interrupt"); RC = RC.INTERRUPT; goto abort_parse; } break; } case TK.ILLEGAL: { C._tagfree(ctx, ref errMsg); errMsg = SysEx.Mprintf(ctx, "unrecognized token: \"%T\"", (object)LastToken); errs++; goto abort_parse; } case TK.SEMI: { //Tail = new StringBuilder(sql.Substring(i, sql.Length - i)); goto default; } default: { Parser(engine, tokenType, LastToken, this); lastTokenParsed = tokenType; if (RC != RC.OK) { goto abort_parse; } break; } } } abort_parse: Tail = new StringBuilder(sql.Length <= i ? string.Empty : sql.Substring(i, sql.Length - i)); if (sql.Length >= i && errs == 0 && RC == RC.OK) { if (lastTokenParsed != TK.SEMI) { Parser(engine, TK.SEMI, LastToken, this); } Parser(engine, 0, LastToken, this); } #if YYTRACKMAXSTACKDEPTH sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK, sqlite3ParserStackPeak(engine)); #endif Parser_Free(engine, null); ctx.Lookaside.Enabled = enableLookaside; //if (ctx.MallocFailed) // RC = RC.NOMEM; if (RC != RC.OK && RC != RC.DONE && string.IsNullOrEmpty(ErrMsg)) { SetString(ref ErrMsg, ctx, ErrStr(RC)); } if (ErrMsg != null) { errMsg = ErrMsg; SysEx.LOG(RC, "%s", errMsg); ErrMsg = string.Empty; errs++; } if (V != null && Errs > 0 && Nested == 0) { Vdbe.Delete(ref V); V = null; } #if !OMIT_SHARED_CACHE if (Nested == 0) { C._tagfree(ctx, ref TableLocks.data); TableLocks.data = null; TableLocks.length = 0; } #endif #if !OMIT_VIRTUALTABLE VTableLocks.data = null; #endif if (!E.INDECLARE_VTABLE(this)) { // If the pParse.declareVtab flag is set, do not delete any table structure built up in pParse.pNewTable. The calling code (see vtab.c) // will take responsibility for freeing the Table structure. DeleteTable(ctx, ref NewTable); } #if !OMIT_TRIGGER DeleteTrigger(ctx, ref NewTrigger); #endif //for (i = Vars.length - 1; i >= 0; i--) // C._tagfree(ctx, ref Vars.data[i]); C._tagfree(ctx, ref Vars.data); C._tagfree(ctx, ref Alias.data); while (Ainc != null) { AutoincInfo p = Ainc; Ainc = p.Next; C._tagfree(ctx, ref p); } while (ZombieTab != null) { Table p = ZombieTab; ZombieTab = p.NextZombie; DeleteTable(ctx, ref p); } if (errs > 0 && RC == RC.OK) { RC = RC.ERROR; } return(errs); }