Esempio n. 1
0
        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);
        }