context: ///////////////////////////////////////////////////////////////////////////////////////
  // Copyright (C) 2006-2015 Esper Team. All rights reserved.                           /
  // http://esper.codehaus.org                                                          /
  // ---------------------------------------------------------------------------------- /
  // The software in this package is published under the terms of the GPL license       /
  // a copy of which has been included with this distribution in the license.txt file.  /
  ///////////////////////////////////////////////////////////////////////////////////////
  
  using System.Collections.Generic;
  using System.Linq;
  
  using com.espertech.esper.common.client;
  using com.espertech.esper.common.client.annotation;
  using com.espertech.esper.common.client.scopetest;
  using com.espertech.esper.common.@internal.support;
  using com.espertech.esper.compat;
  using com.espertech.esper.compat.collections;
  using com.espertech.esper.regressionlib.framework;
  using com.espertech.esper.regressionlib.support.bean;
  using com.espertech.esper.regressionlib.support.epl;
  using com.espertech.esper.regressionlib.support.util;
  using com.espertech.esper.runtime.client.scopetest;
  
  using NUnit.Framework;
  
  namespace com.espertech.esper.regressionlib.suite.resultset.querytype
  {
      public class ResultSetQueryTypeLocalGroupBy
      {
          public static readonly string PLAN_CALLBACK_HOOK =
              $"@Hook(HookType={typeof(HookType).FullName}.INTERNAL_AGGLOCALLEVEL,Hook='{typeof(SupportAggLevelPlanHook).FullName}')";
  
          public static IList<RegressionExecution> Executions()
          {
              var execs = new List<RegressionExecution>();
              WithLocalUngroupedSumSimple(execs);
              WithLocalUngroupedAggSQLStandard(execs);
              WithLocalUngroupedAggEvent(execs);
              WithLocalUngroupedAggIterator(execs);
              WithLocalUngroupedParenSODA(execs);
              WithLocalUngroupedColNameRendering(execs);
              WithLocalUngroupedHaving(execs);
              WithLocalUngroupedUnidirectionalJoin(execs);
              WithLocalUngroupedThreeLevelWTop(execs);
              WithLocalGroupedSimple(execs);
              WithLocalGroupedMultiLevelMethod(execs);
              WithLocalGroupedSolutionPattern(execs);
              WithLocalGroupedMultiLevelAccess(execs);
              WithLocalGroupedMultiLevelNoDefaultLvl(execs);
              WithLocalPlanning(execs);
              WithLocalInvalid(execs);
              WithAggregateFullyVersusNotFullyAgg(execs);
              WithLocalUngroupedSameKey(execs);
              WithLocalGroupedSameKey(execs);
              WithLocalUngroupedRowRemove(execs);
              WithLocalGroupedRowRemove(execs);
              WithLocalGroupedOnSelect(execs);
              WithLocalUngroupedOrderBy(execs);
              WithLocalEnumMethods(execs);
              WithLocalUngroupedAggAdditionalAndPlugin(execs);
              WithLocalMultikeyWArray(execs);
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalMultikeyWArray(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalMultikeyWArray());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedAggAdditionalAndPlugin(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedAggAdditionalAndPlugin());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalEnumMethods(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalEnumMethods(true));
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedOrderBy(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedOrderBy());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalGroupedOnSelect(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalGroupedOnSelect());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalGroupedRowRemove(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalGroupedRowRemove());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedRowRemove(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedRowRemove());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalGroupedSameKey(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalGroupedSameKey());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedSameKey(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedSameKey());
              return execs;
          }
  
          public static IList<RegressionExecution> WithAggregateFullyVersusNotFullyAgg(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetAggregateFullyVersusNotFullyAgg());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalInvalid(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalInvalid());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalPlanning(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalPlanning());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalGroupedMultiLevelNoDefaultLvl(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalGroupedMultiLevelNoDefaultLvl());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalGroupedMultiLevelAccess(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalGroupedMultiLevelAccess());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalGroupedSolutionPattern(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalGroupedSolutionPattern());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalGroupedMultiLevelMethod(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalGroupedMultiLevelMethod());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalGroupedSimple(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalGroupedSimple());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedThreeLevelWTop(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedThreeLevelWTop());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedUnidirectionalJoin(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedUnidirectionalJoin());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedHaving(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedHaving());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedColNameRendering(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedColNameRendering());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedParenSODA(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedParenSODA(false));
              execs.Add(new ResultSetLocalUngroupedParenSODA(true));
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedAggIterator(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedAggIterator());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedAggEvent(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedAggEvent());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedAggSQLStandard(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedAggSQLStandard());
              return execs;
          }
  
          public static IList<RegressionExecution> WithLocalUngroupedSumSimple(IList<RegressionExecution> execs = null)
          {
              execs = execs ?? new List<RegressionExecution>();
              execs.Add(new ResultSetLocalUngroupedSumSimple());
              return execs;
          }
  
          private static void TryAssertionAggAndFullyAgg(
              RegressionEnvironment env,
              string selected,
              MyAssertion assertion)
          {
              var epl = "create context StartS0EndS1 start SupportBean_S0 end SupportBean_S1;" +
                        "@Name('s0') context StartS0EndS1 " +
                        selected +
                        " output snapshot when terminated;";
              env.CompileDeploy(epl).AddListener("s0");
  
              env.SendEventBean(new SupportBean_S0(0));
              MakeSendEvent(env, "E1", 10, 100);
              MakeSendEvent(env, "E2", 20, 200);
              MakeSendEvent(env, "E2", 30, 300);
              env.SendEventBean(new SupportBean_S1(0));
  
              assertion.Invoke(env.Listener("s0"));
  
              // try an empty batch
              env.SendEventBean(new SupportBean_S0(1));
              env.SendEventBean(new SupportBean_S1(1));
  
              env.UndeployAll();
          }
  
          private static void SendTime(
              RegressionEnvironment env,
              long msec)
          {
              env.AdvanceTime(msec);
          }
  
          private static void SendEventMany(
              RegressionEnvironment env,
              params string[] theString)
          {
              foreach (var value in theString) {
                  SendEvent(env, value);
              }
          }
  
          private static void SendEvent(
              RegressionEnvironment env,
              string theString)
          {
              env.SendEventBean(new SupportBean(theString, 0));
          }
  
          private static SupportBean MakeSendEvent(
              RegressionEnvironment env,
              string theString,
              int intPrimitive)
          {
              var b = new SupportBean(theString, intPrimitive);
              env.SendEventBean(b);
              return b;
          }
  
          private static SupportBean MakeSendEvent(
              RegressionEnvironment env,
              string theString,
              int intPrimitive,
              long longPrimitive)
          {
              var b = new SupportBean(theString, intPrimitive);
              b.LongPrimitive = longPrimitive;
              env.SendEventBean(b);
              return b;
          }
  
          private static void AssertCountColsAndLevels(
              RegressionEnvironment env,
              string epl,
              int colCount,
              int lvlCount)
          {
              var theEpl = PLAN_CALLBACK_HOOK + epl;
              env.Compile(theEpl);
              var plan =
                  SupportAggLevelPlanHook.GetAndReset();
              Assert.AreEqual(colCount, plan.First.NumColumns);
              Assert.AreEqual(lvlCount, plan.First.Levels.Length);
          }
  
          private static void AssertNoPlan(
              RegressionEnvironment env,
              string epl)
          {
              var theEpl = PLAN_CALLBACK_HOOK + epl;
              env.Compile(theEpl);
              Assert.IsNull(SupportAggLevelPlanHook.GetAndReset());
          }
  
          private static void AssertScalarColl(
              EventBean eventBean,
              int?[] expectedC6,
              int?[] expectedC7)
          {
              var c6 = eventBean.Get("c6").UnwrapIntoArray<int?>();
              var c7 = eventBean.Get("c7").UnwrapIntoArray<int?>();
              EPAssertionUtil.AssertEqualsExactOrder(expectedC6, c6.ToArray());
              EPAssertionUtil.AssertEqualsExactOrder(expectedC7, c7.ToArray());
          }
  
          public class ResultSetLocalMultikeyWArray : RegressionExecution
          {
              public void Run(RegressionEnvironment env)
              {
                  string epl = "@Name('s0') select " +
                               "sum(Value, group_by:(IntArray)) as c0, " +
                               "sum(Value, group_by:(LongArray)) as c1, " +
                               "sum(Value, group_by:(DoubleArray)) as c2, " +
                               "sum(Value, group_by:(IntArray, LongArray, DoubleArray)) as c3, " +
                               "sum(Value) as c4 " +
                               "from SupportThreeArrayEvent";
                  env.CompileDeploy(epl).AddListener("s0");
  
                  SendAssert(env, "E1", 10, new int[] {1}, new long[] {10}, new double[] {100}, 10, 10, 10, 10, 10);
                  SendAssert(env, "E2", 11, new int[] {2}, new long[] {20}, new double[] {200}, 11, 11, 11, 11, 21);
  
                  env.Milestone(0);
  
                  SendAssert(env, "E3", 12, new int[] {3}, new long[] {10}, new double[] {300}, 12, 22, 12, 12, 33);
                  SendAssert(env, "E4", 13, new int[] {1}, new long[] {20}, new double[] {200}, 10 + 13, 11 + 13, 11 + 13, 13, 33 + 13);
                  SendAssert(env, "E5", 14, new int[] {1}, new long[] {10}, new double[] {100}, 10 + 13 + 14, 10 + 12 + 14, 10 + 14, 10 + 14, 33 + 13 + 14);
  
                  env.Milestone(1);
  
                  SendAssert(env, "E6", 15, new int[] {3}, new long[] {20}, new double[] {300}, 12 + 15, 11 + 13 + 15, 12 + 15, 15, 33 + 13 + 14 + 15);
                  SendAssert(
                      env,
                      "E7",
                      16,
                      new int[] {2},
                      new long[] {20},
                      new double[] {200},
                      11 + 16,
                      11 + 13 + 15 + 16,
                      11 + 13 + 16,
                      11 + 16,
                      33 + 13 + 14 + 15 + 16);
  
                  env.UndeployAll();
              }
  
              private void SendAssert(
                  RegressionEnvironment env,
                  string id,
                  int value,
                  int[] ints,
                  long[] longs,
                  double[] doubles,
                  int c0,
                  int c1,
                  int c2,
                  int c3,
                  int c4)
              {
                  string[] fields = "c0,c1,c2,c3,c4".SplitCsv();
                  env.SendEventBean(new SupportThreeArrayEvent(id, value, ints, longs, doubles));
                  EPAssertionUtil.AssertProps(env.Listener("s0").AssertOneGetNewAndReset(), fields, new object[] {c0, c1, c2, c3, c4});
              }
          }
  
          public class ResultSetLocalUngroupedSumSimple : RegressionExecution
          {
              public void Run(RegressionEnvironment env)
              {
                  var fields = new[] {"c0", "c1", "c2", "c3"};
                  env.Milestone(0);
  
                  env.AdvanceTime(0);
                  var epl = "@Name('s0') select " +
                            "sum(LongPrimitive, group_by:(TheString, IntPrimitive)) as c0, " +
                            "sum(LongPrimitive, group_by:(TheString)) as c1, " +
                            "sum(LongPrimitive, group_by:(IntPrimitive)) as c2, " +
                            "sum(LongPrimitive) as c3 " +
                            "from SupportBean";
                  env.CompileDeploy(epl).AddListener("s0");
  
                  env.Milestone(1);
  
                  MakeSendEvent(env, "E1", 1, 10);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      fields,
                      new object[] {10L, 10L, 10L, 10L});
  
                  env.Milestone(2);
  
                  MakeSendEvent(env, "E2", 2, 11);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      fields,
                      new object[] {11L, 11L, 11L, 21L});
  
                  env.Milestone(3);
  
                  MakeSendEvent(env, "E1", 2, 12);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      fields,
                      new object[] {12L, 10 + 12L, 11 + 12L, 10 + 11 + 12L});
  
                  env.Milestone(4);
  
                  env.Milestone(5);
  
                  MakeSendEvent(env, "E1", 1, 13);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      fields,
                      new object[] {10 + 13L, 10 + 12 + 13L, 10 + 13L, 10 + 11 + 12 + 13L});
  
                  MakeSendEvent(env, "E2", 1, 14);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      fields,
                      new object[] {14L, 11 + 14L, 10 + 13 + 14L, 10 + 11 + 12 + 13 + 14L});
  
                  env.UndeployAll();
              }
          }
  
          internal class ResultSetLocalInvalid : RegressionExecution
          {
              public void Run(RegressionEnvironment env)
              {
                  // not valid with count-min-sketch
                  SupportMessageAssertUtil.TryInvalidCompile(
                      env,
                      "create table MyTable(approx countMinSketch(group_by:TheString) @type(SupportBean))",
                      "Failed to validate table-column expression 'countMinSketch(group_by:TheString)': The 'group_by' and 'filter' parameter is not allowed in create-table statements");
  
                  // not allowed with tables
                  SupportMessageAssertUtil.TryInvalidCompile(
                      env,
                      "create table MyTable(col sum(int, group_by:TheString) @type(SupportBean))",
                      "Failed to validate table-column expression 'sum(int,group_by:TheString)': The 'group_by' and 'filter' parameter is not allowed in create-table statements");
  
                  // invalid named parameter
                  SupportMessageAssertUtil.TryInvalidCompile(
                      env,
                      "select sum(IntPrimitive, xxx:TheString) from SupportBean",
                      "Failed to validate select-clause expression 'sum(IntPrimitive,xxx:TheString)': Invalid named parameter 'xxx' (did you mean 'group_by' or 'filter'?) [");
  
                  // invalid group-by expression
                  SupportMessageAssertUtil.TryInvalidCompile(
                      env,
                      "select sum(IntPrimitive, group_by:sum(IntPrimitive)) from SupportBean",
                      "Failed to validate select-clause expression 'sum(IntPrimitive,group_by:sum(IntPr...(44 chars)': Group-by expressions cannot contain aggregate functions");
  
                  // other functions don't accept this named parameter
                  SupportMessageAssertUtil.TryInvalidCompile(
                      env,
                      "select coalesce(0, 1, group_by:TheString) from SupportBean",
                      "Failed to validate select-clause expression 'coalesce(0,1,group_by:TheString)': Named parameters are not allowed");
                  SupportMessageAssertUtil.TryInvalidCompile(
                      env,
                      "select " +
                      typeof(SupportStaticMethodLib).FullName +
                      ".StaticMethod(group_by:IntPrimitive) from SupportBean",
                      "Failed to validate select-clause expression 'com.espertech.esper.regressionlib.s...(104 chars)': Named parameters are not allowed");
  
                  // not allowed in combination with roll-up
                  SupportMessageAssertUtil.TryInvalidCompile(
                      env,
                      "select sum(IntPrimitive, group_by:TheString) from SupportBean group by rollup(TheString)",
                      "Roll-up and group-by parameters cannot be combined ");
  
                  // not allowed in combination with into-table
                  var path = new RegressionPath();
                  env.CompileDeploy("create table mytable (thesum sum(int))", path);
                  SupportMessageAssertUtil.TryInvalidCompile(
                      env,
                      path,
                      "into table mytable select sum(IntPrimitive, group_by:TheString) as thesum from SupportBean",
                      "Into-table and group-by parameters cannot be combined");
  
                  // not allowed for match-recognize measure clauses
                  var eplMatchRecog = "select * from SupportBean match_recognize (" +
                                      "  measures count(B.IntPrimitive, group_by:B.TheString) pattern (A B* C))";
                  SupportMessageAssertUtil.TryInvalidCompile(
                      env,
                      eplMatchRecog,
                      "Match-recognize does not allow aggregation functions to specify a group-by");
  
                  // disallow subqueries to specify their own local group-by
                  var eplSubq =
                      "select (select sum(IntPrimitive, group_by:TheString) from SupportBean#keepall) from SupportBean_S0";
                  SupportMessageAssertUtil.TryInvalidCompile(
                      env,
                      eplSubq,
                      "Failed to plan subquery number 1 querying SupportBean: Subselect aggregations functions cannot specify a group-by");
  
                  env.UndeployAll();
              }
          }
  
          internal class ResultSetLocalPlanning : RegressionExecution
          {
              public void Run(RegressionEnvironment env)
              {
                  AssertNoPlan(env, "select sum(group_by:(),IntPrimitive) as c0 from SupportBean");
                  AssertNoPlan(
                      env,
                      "select sum(group_by:(TheString),IntPrimitive) as c0 from SupportBean group by TheString");
                  AssertNoPlan(
                      env,
                      "select sum(group_by:(TheString, IntPrimitive),LongPrimitive) as c0 from SupportBean group by TheString, IntPrimitive");
                  AssertNoPlan(
                      env,
                      "select sum(group_by:(IntPrimitive, TheString),LongPrimitive) as c0 from SupportBean group by TheString, IntPrimitive");
  
                  // provide column count stays at 1
                  AssertCountColsAndLevels(
                      env,
                      "select sum(group_by:(TheString),IntPrimitive) as c0, sum(group_by:(TheString),IntPrimitive) as c1 from SupportBean",
                      1,
                      1);
  
                  // prove order of group-by expressions does not matter
                  AssertCountColsAndLevels(
                      env,
                      "select sum(group_by:(IntPrimitive, TheString),LongPrimitive) as c0, sum(LongPrimitive, group_by:(TheString, IntPrimitive)) as c1 from SupportBean",
                      1,
                      1);
  
                  // prove the number of levels stays the same even when group-by expressions vary
                  AssertCountColsAndLevels(
                      env,
                      "select sum(group_by:(IntPrimitive, TheString),LongPrimitive) as c0, count(*, group_by:(TheString, IntPrimitive)) as c1 from SupportBean",
                      2,
                      1);
  
                  // prove there is one shared state factory
                  var theEpl = PLAN_CALLBACK_HOOK +
                               "@Name('s0') select window(*, group_by:TheString), last(*, group_by:TheString) from SupportBean#length(2)";
                  env.Compile(theEpl);
                  var plan =
                      SupportAggLevelPlanHook.GetAndReset();
                  Assert.AreEqual(1, plan.Second.AllLevelsForges.Length);
                  Assert.AreEqual(1, plan.Second.AllLevelsForges[0].AccessStateForges.Length);
              }
          }
  
          internal class ResultSetAggregateFullyVersusNotFullyAgg : RegressionExecution
          {
              public void Run(RegressionEnvironment env)
              {
                  var colsC0 = new[] {"c0"};
  
                  // full-aggregated and un-grouped (row for all)
                  TryAssertionAggAndFullyAgg(
                      env,
                      "select sum(group_by:(),IntPrimitive) as c0 from SupportBean",
                      listener => {
                          EPAssertionUtil.AssertProps(
                              env.Listener("s0").AssertOneGetNewAndReset(),
                              colsC0,
                              new object[] {60});
                      });
  
                  // aggregated and un-grouped (row for event)
                  TryAssertionAggAndFullyAgg(
                      env,
                      "select sum(group_by:TheString, IntPrimitive) as c0 from SupportBean#keepall",
                      listener => {
                          EPAssertionUtil.AssertPropsPerRowAnyOrder(
                              env.Listener("s0").GetAndResetLastNewData(),
                              colsC0,
                              new[] {new object[] {10}, new object[] {50}, new object[] {50}});
                      });
  
                  // fully aggregated and grouped (row for group)
                  TryAssertionAggAndFullyAgg(
                      env,
                      "select sum(IntPrimitive, group_by:()) as c0, sum(group_by:TheString, IntPrimitive) as c1, TheString " +
                      "from SupportBean group by TheString",
                      listener => {
                          EPAssertionUtil.AssertPropsPerRowAnyOrder(
                              env.Listener("s0").GetAndResetLastNewData(),
                              new[] {"TheString", "c0", "c1"},
                              new[] {new object[] {"E1", 60, 10}, new object[] {"E2", 60, 50}});
                      });
  
                  // aggregated and grouped (row for event)
                  TryAssertionAggAndFullyAgg(
                      env,
                      "select sum(LongPrimitive, group_by:()) as c0," +
                      " sum(LongPrimitive, group_by:TheString) as c1, " +
                      " sum(LongPrimitive, group_by:IntPrimitive) as c2, " +
                      " TheString " +
                      "from SupportBean#keepall group by TheString",
                      listener => {
                          EPAssertionUtil.AssertPropsPerRowAnyOrder(
                              env.Listener("s0").GetAndResetLastNewData(),
                              new[] {"TheString", "c0", "c1", "c2"},
                              new[] {
                                  new object[] {"E1", 600L, 100L, 100L}, new object[] {"E2", 600L, 500L, 200L},
                                  new object[] {"E2", 600L, 500L, 300L}
                              });
                      });
              }
          }
  
          public class ResultSetLocalUngroupedRowRemove : RegressionExecution
          {
              public void Run(RegressionEnvironment env)
              {
                  var cols = new[] {"TheString", "IntPrimitive", "c0", "c1"};
                  var epl = "create window MyWindow#keepall as SupportBean;\n" +
                            "insert into MyWindow select * from SupportBean;\n" +
                            "on SupportBean_S0 delete from MyWindow where P00 = TheString and Id = IntPrimitive;\n" +
                            "on SupportBean_S1 delete from MyWindow;\n" +
                            "@Name('s0') select TheString, IntPrimitive, sum(LongPrimitive) as c0, " +
                            "  sum(LongPrimitive, group_by:TheString) as c1 from MyWindow;\n";
                  env.CompileDeploy(epl).AddListener("s0");
  
                  MakeSendEvent(env, "E1", 10, 101);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E1", 10, 101L, 101L});
  
                  env.SendEventBean(new SupportBean_S0(10, "E1")); // delete event {"E1", 10}
                  Assert.IsFalse(env.Listener("s0").IsInvoked);
  
                  MakeSendEvent(env, "E1", 20, 102);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E1", 20, 102L, 102L});
  
                  MakeSendEvent(env, "E2", 30, 103);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E2", 30, 102 + 103L, 103L});
  
                  MakeSendEvent(env, "E1", 40, 104);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E1", 40, 102 + 103 + 104L, 102 + 104L});
  
                  env.SendEventBean(new SupportBean_S0(40, "E1")); // delete event {"E1", 40}
                  Assert.IsFalse(env.Listener("s0").IsInvoked);
  
                  MakeSendEvent(env, "E1", 50, 105);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E1", 50, 102 + 103 + 105L, 102 + 105L});
  
                  env.SendEventBean(new SupportBean_S1(-1)); // delete all
                  Assert.IsFalse(env.Listener("s0").IsInvoked);
  
                  MakeSendEvent(env, "E1", 60, 106);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E1", 60, 106L, 106L});
  
                  env.UndeployAll();
              }
          }
  
          public class ResultSetLocalGroupedRowRemove : RegressionExecution
          {
              public void Run(RegressionEnvironment env)
              {
                  var cols = new[] {"TheString", "IntPrimitive", "c0", "c1"};
                  var epl = "create window MyWindow#keepall as SupportBean;\n" +
                            "insert into MyWindow select * from SupportBean;\n" +
                            "on SupportBean_S0 delete from MyWindow where P00 = TheString and Id = IntPrimitive;\n" +
                            "on SupportBean_S1 delete from MyWindow;\n" +
                            "@Name('s0') select TheString, IntPrimitive, sum(LongPrimitive) as c0, " +
                            "  sum(LongPrimitive, group_by:TheString) as c1 " +
                            "  from MyWindow group by TheString, IntPrimitive;\n";
                  env.CompileDeploy(epl).AddListener("s0");
  
                  MakeSendEvent(env, "E1", 10, 101);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E1", 10, 101L, 101L});
  
                  env.SendEventBean(new SupportBean_S0(10, "E1")); // delete event {"E1", 10}
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E1", 10, null, null});
  
                  MakeSendEvent(env, "E1", 20, 102);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E1", 20, 102L, 102L});
  
                  MakeSendEvent(env, "E2", 30, 103);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E2", 30, 103L, 103L});
  
                  MakeSendEvent(env, "E1", 40, 104);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E1", 40, 104L, 102 + 104L});
  
                  env.SendEventBean(new SupportBean_S0(40, "E1")); // delete event {"E1", 40}
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E1", 40, null, 102L});
  
                  MakeSendEvent(env, "E1", 50, 105);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E1", 50, 105L, 102 + 105L});
  
                  env.SendEventBean(new SupportBean_S1(-1)); // delete all
                  env.Listener("s0").Reset();
  
                  MakeSendEvent(env, "E1", 60, 106);
                  EPAssertionUtil.AssertProps(
                      env.Listener("s0").AssertOneGetNewAndReset(),
                      cols,
                      new object[] {"E1", 60, 106L, 106L});
  
                  env.UndeployAll();
              }
          }
  
          public class ResultSetLocalGroupedMultiLevelMethod : RegressionExecution
          {
              public void Run(RegressionEnvironment env)
              {
                  SendTime(env, 0);
                  var fields = new[] {"TheString", "IntPrimitive", "c0", "c1", "c2", "c3", "c4"};
                  var epl = "@Name('s0') select" +
                            "   TheString, IntPrimitive," +
                            "   sum(LongPrimitive, group_by:(IntPrimitive, TheString)) as c0," +
                            "   sum(LongPrimitive) as c1," +
                            "   sum(LongPrimitive, group_by:(TheString)) as c2," +
                            "   sum(LongPrimitive, group_by:(IntPrimitive)) as c3," +
                            "   sum(LongPrimitive, group_by:()) as c4" +
                            " from SupportBean" +
                            " group by TheString, IntPrimitive" +
                            " output snapshot every 10 seconds";
                  env.CompileDeploy(epl).AddListener("s0");
  
                  MakeSendEvent(env, "E1", 10, 100);
                  MakeSendEvent(env, "E1", 20, 202);
                  MakeSendEvent(env, "E2", 10, 303);
                  MakeSendEvent(env, "E1", 10, 404);
                  MakeSendEvent(env, "E2", 10, 505);
                  SendTime(env, 10000);
  
                  EPAssertionUtil.AssertPropsPerRowAnyOrder(
                      env.Listener("s0").GetAndResetLastNewData(),
                      fields,
                      new[] {
                          new object[] {"E1", 10, 504L, 504L, 706L, 1312L, 1514L},
                          new object[] {"E1", 20, 202L, 202L, 706L, 202L, 1514L},
                          new object[] {"E2", 10, 808L, 808L, 808L, 1312L, 1514L}
                      });
  
                  MakeSendEvent(env, "E1", 10, 1);
                  SendTime(env, 20000);
  
                  EPAssertionUtil.AssertPropsPerRowAnyOrder(
                      env.Listener("s0").GetAndResetLastNewData(),
                      fields,
                      new[] {
                          new object[] {"E1", 10, 505L, 505L, 707L, 1313L, 1515L},
                          new object[] {"E1", 20, 202L, 202L, 707L, 202L, 1515L},
                          new object[] {"E2", 10, 808L, 808L, 808L, 1313L, 1515L}
                      });
  
                  env.UndeployAll();
              }
          }
  
          public class ResultSetLocalGroupedMultiLevelAccess : RegressionExecution
          {
              public void Run(RegressionEnvironment env)
              {
                  SendTime(env, 0);
                  var fields = new[] {"TheString", "IntPrimitive", "c0", "c1", "c2", "c3", "c4"};
                  var epl = "@Name('s0') select" +
                            "   TheString, IntPrimitive," +
                            "   window(*, group_by:(IntPrimitive, TheString)) as c0," +
                            "   window(*) as c1," +
                            "   window(*, group_by:TheString) as c2," +
                            "   window(*, group_by:IntPrimitive) as c3," +
                            "   window(*, group_by:()) as c4" +
                            " from SupportBean#keepall" +
                            " group by TheString, IntPrimitive" +
                            " output snapshot every 10 seconds" +
                            " order by TheString, IntPrimitive";
                  env.CompileDeploy(epl).AddListener("s0");
  
                  var b1 = MakeSendEvent(env, "E1", 10, 100);
                  var b2 = MakeSendEvent(env, "E1", 20, 202);
                  var b3 = MakeSendEvent(env, "E2", 10, 303);
                  var b4 = MakeSendEvent(env, "E1", 10, 404);
  
gt:                 var b5 = MakeSendEvent(env, "E2", 10, 505);