コード例 #1
0
 private RoutineScope GetRoutineScopeFromRoutineInfo(RoutineInfo ri)
 {
   RoutineScope rs = new RoutineScope() { OwningRoutine = ri, Variables = new Dictionary<string,StoreType>() };
   foreach (StoreType st in ri.Locals.Values)
   {
     rs.Variables.Add(st.Name, new StoreType(st));
   }
   return rs;
 }
コード例 #2
0
    /// <summary>
    /// Replaces in the current statement, any references to local variables/arguments 
    /// with their value.
    /// </summary>
    /// <param name="t"></param>
    /// <returns>A string with the expression after replacing the values.</returns>
    internal string ReplaceVarsWithValues(CommonTree t, CommonTokenStream cts, RoutineScope rs )
    {
      Dictionary<string, StoreType> vars = rs.Variables;
      StringBuilder sb = new StringBuilder();

      //foreach (IToken tok in cts.GetTokens(t.TokenStartIndex, t.TokenStopIndex))
      for (int i = t.TokenStartIndex; i <= t.TokenStopIndex; i++)
      {
        IToken tok = cts.Get(i);
        IToken tok2 = null;
        StoreType st = null;
        if ((tok.Type == MySQL51Parser.AT1) && ((i + 1) <= t.TokenStopIndex) &&
           ((tok2 = cts.Get(i + 1)).Type == MySQL51Parser.ID))
        {
          string id = string.Format("@{0}", tok2.Text );
          // TODO: What about qualified names line a.b? There's no way to add variables like that (until we support triggers and new.col).
          if (vars.TryGetValue(id, out st))
          {
            i++;
            sb.Append(StoreType.WrapValue(st.Value));
          }
        }
        else if (((tok.Type == MySQL51Parser.NEW) || ( Cmp( tok.Text, "old" ) == 0 )) &&
          ((i + 1) <= t.TokenStopIndex) &&
          ( cts.Get( i + 1 ).Type == MySQL51Parser.DOT ) && ( ( i + 2 ) <= t.TokenStopIndex ) &&
          ( ( tok2 = cts.Get( i + 2 ) ).Type == MySQL51Parser.ID ))
        {
          string id = string.Format("{0}.{1}", tok.Text, tok2.Text );
          if (vars.TryGetValue(id, out st))
          {
            i += 2;
            sb.Append(StoreType.WrapValue(st.Value));
          }
          else
          {
            sb.Append(tok.Text);
          }
        }
        else if (vars.TryGetValue(tok.Text, out st))
        {
          sb.Append(StoreType.WrapValue(st.Value));
        }
        else
        {
          sb.Append(tok.Text);
        }
      }
      return sb.ToString();
    }
コード例 #3
0
 public object Eval(string expression, RoutineScope rs)
 {
   CommonTokenStream cts;
   StringBuilder sb = new StringBuilder();
   MySQL51Parser.program_return pr = this.ParseSql(
     string.Format("select {0}", expression), false, out sb, out cts);
   return Eval((CommonTree)((CommonTree)pr.Tree).GetChild(0), cts, rs);
 }
コード例 #4
0
 private object Eval(CommonTree t, CommonTokenStream cts, RoutineScope rs)
 {
   string expr = ReplaceVarsWithValues(t, cts, rs);
   return ExecuteScalar(expr);
 }
コード例 #5
0
    /// <summary>
    /// Instruments a routine.
    /// </summary>
    /// <param name="routine"></param>
    private void InstrumentRoutine( RoutineInfo routine )
    {
      /*
       * - Parse formal arguments.
       * - Parse begin block.
       * - For each begin block parse declare's, then instructions.
       * - When finish parsing tree, make a backup.
       * - Then instrument it.
       * */
      // Parse args
      StringBuilder sb = new StringBuilder();
      CommonTokenStream tokenStream;
      MySQL51Parser.program_return tree = 
        ParseSql(routine.SourceCode, false, out sb, out tokenStream);
      routine.ParsedTree = ( CommonTree )( tree.Tree );
      if (routine.ParsedTree.IsNil)
      {
        routine.ParsedTree = ( CommonTree )routine.ParsedTree.GetChild(0);
      }
      routine.TokenStream = tokenStream;
      Dictionary<string, StoreType> args = ParseArgs( routine.ParsedTree );
      
      
      // Parse Begin block
      CommonTree beginEnd = GetBeginEnd(routine.ParsedTree);
      // There won't be always a begin/end block.
      if (beginEnd == null)
      {
        // begin/end block
        StringBuilder sbNewRoutineSql = new StringBuilder();
        ITree lastChild = routine.ParsedTree.GetChild(routine.ParsedTree.ChildCount - 1);
        ConcatTokens(sbNewRoutineSql, routine.TokenStream, 0, lastChild.TokenStartIndex - 1);
        sbNewRoutineSql.AppendLine();
        sbNewRoutineSql.AppendLine("begin");
        ConcatTokens(sbNewRoutineSql, routine.TokenStream, lastChild.TokenStartIndex, lastChild.TokenStopIndex);
        if ( Cmp( routine.TokenStream.Get( lastChild.TokenStopIndex ).Text, ";" ) != 0 )
        {
          sbNewRoutineSql.Append(';');
        }
        sbNewRoutineSql.AppendLine();
        sbNewRoutineSql.AppendLine( "end" );
        StringBuilder sbErrors;
        tokenStream = null;
        string sSql = sbNewRoutineSql.ToString();
        tree = ParseSql(sSql, false, out sbErrors, out tokenStream);
        routine.TokenStream = tokenStream;
        routine.SourceCode = sSql;
        routine.ParsedTree = (CommonTree)(tree.Tree);
        if (routine.ParsedTree.IsNil)
        {
          routine.ParsedTree = (CommonTree)routine.ParsedTree.GetChild(0);
        }
        // No need to reparse args, just begin/end
        beginEnd = GetBeginEnd(routine.ParsedTree);
      }
      // Get declare variables, sessions, new & old
      ParseDeclares(beginEnd, args);
      ParseSessions(tokenStream, args);
      RegisterInternalVars(args);
      if (routine.Type == RoutineInfoType.Trigger)
      {
        RegisterNewOldVars(routine, args);
      }

      // forces to backup the routine
      if (Scope.Count == 0)
      {
        RoutineScope tempScope = new RoutineScope();
        tempScope.OwningRoutine = routine;
        tempScope.GetFileName();
      }
      else
        CurrentScope.GetFileName();

      // generate instrumentation code
      StringBuilder preInscode = new StringBuilder();
      // track internal variables...
      // Workaround: row_count() is affected by any precious SET statement, so must be first
      preInscode.AppendFormat("set {0} = row_count();", VAR_DBG_ROW_COUNT);
      preInscode.AppendLine();
      preInscode.AppendFormat("set {0} = last_insert_id();", VAR_DBG_LAST_INSERT_ID);
      preInscode.AppendLine();
      preInscode.AppendFormat("set {0} = found_rows();", VAR_DBG_FOUND_ROWS);
      preInscode.AppendLine();
      preInscode.Append(" call `serversidedebugger`.`SetDebugScopeVar`( {3}, {0}, '@@@lineno', {1} );" ).AppendLine();      
      preInscode.Append(" call `serversidedebugger`.`SetDebugScopeVar`( {3}, {0}, '@@@colno', {4} );").AppendLine();      
      // ...and user variables
      foreach (StoreType st in args.Values)
      {
        if (st.VarKind == VarKindEnum.Internal) continue;        
        preInscode.AppendLine("call `serversidedebugger`.`SetDebugScopeVar`( {3}, {0}, ").
          AppendFormat("'{0}', cast( {0} as binary ) );", st.Name).AppendLine();
      }
      StringBuilder postInscode = new StringBuilder();
      foreach (StoreType st in args.Values)
      {
        if (st.VarKind == VarKindEnum.Internal) continue;
        postInscode.AppendFormat(
          @"set {0} = ( select cast( `serversidedebugger`.`DebugScope`.`VarValue` as {1} ) from `serversidedebugger`.`DebugScope` where `serversidedebugger`.`DebugScope`.`DebugSessionId` = {2} ", st.Name, st.GetCastExpressionFromBinary(), DebugSessionId).
          AppendFormat(" and `serversidedebugger`.`DebugScope`.`DebugScopeLevel` = {0} and `serversidedebugger`.`DebugScope`.`VarName` = '{1}' and `serversidedebugger`.`DebugScope`.`Id` = ( select max( `serversidedebugger`.`DebugScope`.`Id` ) from `serversidedebugger`.`DebugScope` where `serversidedebugger`.`DebugScope`.`DebugSessionId` = {2} and `serversidedebugger`.`DebugScope`.`DebugScopeLevel` = {0} and `serversidedebugger`.`DebugScope`.`VarName` = '{1}' ));",
            "{0}", st.Name, DebugSessionId );
        postInscode.AppendLine();
      }
      routine.PreInstrumentationCode = preInscode.ToString();
      routine.PostInstrumentationCode = postInscode.ToString();
      routine.Locals = args;
      // finally instrument.
      StringBuilder sql = new StringBuilder();
      // Instrumeting code...
      GenerateInstrumentedCode(routine, sql);
      routine.InstrumentedSourceCode = sql.ToString();
      string sqlDrop = string.Format("drop {0} {1}", routine.Type.ToString(), routine.Name);
      string db = _utilCon.Database;
      if (!string.IsNullOrEmpty(routine.Schema))
      {
        ExecuteRaw(string.Format("use `{0}`", routine.Schema ));
      }
      ExecuteRaw(sqlDrop);
      try
      {
        ExecuteRaw(string.Format("delimiter //\n{0}\n//", routine.InstrumentedSourceCode));
      }
      catch (Exception)
      {
        // In case of exception restore previous non-instrumented version.
        ExecuteRaw(string.Format("delimiter //\n{0}\n//", routine.SourceCode));
        throw;
      }
      finally
      {
        ExecuteRaw(string.Format("use `{0}`", db));
      }
    }