diff --git a/Musoq.Evaluator.Tests/CteTests.cs b/Musoq.Evaluator.Tests/CteTests.cs index 59b6fae0..094d525a 100644 --- a/Musoq.Evaluator.Tests/CteTests.cs +++ b/Musoq.Evaluator.Tests/CteTests.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Text; using Microsoft.VisualStudio.TestTools.UnitTesting; using Musoq.Evaluator.Tests.Schema.Basic; @@ -641,5 +642,180 @@ with p as ( Assert.AreEqual("MUNICH", table[4].Values[0]); Assert.AreEqual("GERMANY", table[4].Values[1]); } + + [TestMethod] + public void WhenMixedQueriesGroupingAreUsed_Variant1_ShouldPass() + { + var query = @" +with first as ( + select 1 as Test from #A.entities() +), second as ( + select 2 as Test from #B.entities() group by 'fake' +) +select c.GetBytes(c.Name) from first a + inner join #A.entities() c on 1 = 1 + inner join second b on 1 = 1"; + + var sources = new Dictionary> + { + { + "#A", + new[] + { + new BasicEntity("First"), + } + }, + { + "#B", + new[] + { + new BasicEntity("Second"), + } + } + }; + + var vm = CreateAndRunVirtualMachine(query, sources); + var table = vm.Run(); + + Assert.AreEqual(1, table.Count); + Assert.AreEqual("First", Encoding.UTF8.GetString((byte[])table[0].Values[0])); + } + + [TestMethod] + public void WhenMixedQueriesGroupingAreUsed_Variant2_ShouldPass() + { + var query = @" +with first as ( + select Name from #A.entities() +), second as ( + select Name from #B.entities() group by Name +) +select + c.GetBytes(c.Name) +from first a + inner join #A.entities() c on 1 = 1 + inner join second b on 1 = 1"; + + var sources = new Dictionary> + { + { + "#A", + new[] + { + new BasicEntity("First"), + } + }, + { + "#B", + new[] + { + new BasicEntity("Second"), + } + } + }; + + var vm = CreateAndRunVirtualMachine(query, sources); + var table = vm.Run(); + + Assert.AreEqual(1, table.Count); + Assert.AreEqual("First", Encoding.UTF8.GetString((byte[])table[0].Values[0])); + } + + [TestMethod] + public void WhenMixedQueriesGroupingAreUsed_Variant3_ShouldPass() + { + var query = @" +with first as ( + select Name from #A.entities() +), second as ( + select Name from #B.entities() group by Name +) +select + a.Name, + b.Name, + c.GetBytes(c.Name) +from first a + inner join #A.entities() c on 1 = 1 + inner join second b on 1 = 1"; + + var sources = new Dictionary> + { + { + "#A", + new[] + { + new BasicEntity("First"), + } + }, + { + "#B", + new[] + { + new BasicEntity("Second"), + } + } + }; + + var vm = CreateAndRunVirtualMachine(query, sources); + var table = vm.Run(); + + Assert.AreEqual(1, table.Count); + Assert.AreEqual("First", (string)table[0].Values[0]); + Assert.AreEqual("Second", (string)table[0].Values[1]); + Assert.AreEqual("First", Encoding.UTF8.GetString((byte[])table[0].Values[2])); + } + + [TestMethod] + public void WhenMixedQueriesGroupingAreUsed_Variant4_ShouldPass() + { + var query = @" +with first as ( + select a.Name as Name from #A.entities() a group by a.Name having Count(a.Name) > 0 +), second as ( + select b.Name() as Name from #B.entities() b inner join first a on 1 = 1 +), third as ( + select b.Name as Name from second b group by b.Name having Count(b.Name) > 0 +), fourth as ( + select + c.Name() as Name + from second b + inner join #A.entities() c on 1 = 1 + inner join third d on 1 = 1 +) +select + c.Name as Name +from fourth c"; + + var sources = new Dictionary> + { + { + "#A", + new[] + { + new BasicEntity("First"), + } + }, + { + "#B", + new[] + { + new BasicEntity("Second"), + } + }, + { + "#C", + new[] + { + new BasicEntity("Third"), + } + } + }; + + var vm = CreateAndRunVirtualMachine(query, sources); + var table = vm.Run(); + + Assert.AreEqual(1, table.Count); + Assert.AreEqual("First", (string)table[0].Values[0]); + } } } \ No newline at end of file diff --git a/Musoq.Evaluator.Tests/GenericTests.cs b/Musoq.Evaluator.Tests/GenericTests.cs index 2ee37638..c0386ae9 100644 --- a/Musoq.Evaluator.Tests/GenericTests.cs +++ b/Musoq.Evaluator.Tests/GenericTests.cs @@ -124,4 +124,31 @@ public void WhenRetrieveLengthFromArrayType_ShouldPass() Assert.AreEqual(1, table.Count); Assert.AreEqual(5, (int)table[0].Values[0]); } + + [TestMethod] + public void WhenSkipWithoutReductionRequired_ShouldPass() + { + var table = TestResultMethodTemplate("EnumerableToArray(Skip(GetBytes('test1'), 1))"); + + Assert.AreEqual(1, table.Count); + Assert.AreEqual("est1", Encoding.UTF8.GetString((byte[])table[0].Values[0])); + } + + [TestMethod] + public void WhenTakeWithoutReductionRequired_ShouldPass() + { + var table = TestResultMethodTemplate("EnumerableToArray(Take(GetBytes('test1'), 1))"); + + Assert.AreEqual(1, table.Count); + Assert.AreEqual("t", Encoding.UTF8.GetString((byte[])table[0].Values[0])); + } + + [TestMethod] + public void WhenSkipAndTakeWithoutReductionRequired_ShouldPass() + { + var table = TestResultMethodTemplate("EnumerableToArray(SkipAndTake(GetBytes('test1'), 1, 1))"); + + Assert.AreEqual(1, table.Count); + Assert.AreEqual("e", Encoding.UTF8.GetString((byte[])table[0].Values[0])); + } } \ No newline at end of file diff --git a/Musoq.Evaluator/Helpers/EvaluationHelper.cs b/Musoq.Evaluator/Helpers/EvaluationHelper.cs index 870d1285..e0a35538 100644 --- a/Musoq.Evaluator/Helpers/EvaluationHelper.cs +++ b/Musoq.Evaluator/Helpers/EvaluationHelper.cs @@ -296,7 +296,7 @@ public GroupResolver(Group item) _item = item; } - public object[] Contexts => new object[] { _item }; + public object[] Contexts => Array.Empty(); public object this[string name] { diff --git a/Musoq.Evaluator/Musoq.Evaluator.csproj b/Musoq.Evaluator/Musoq.Evaluator.csproj index d78c1040..511e820b 100644 --- a/Musoq.Evaluator/Musoq.Evaluator.csproj +++ b/Musoq.Evaluator/Musoq.Evaluator.csproj @@ -4,7 +4,7 @@ net6.0 AnyCPU;x64 true - 5.6.6 + 5.6.7 Jakub Puchała Musoq https://github.com/Puchaczov/Musoq diff --git a/Musoq.Evaluator/Visitors/BuildMetadataAndInferTypeVisitor.cs b/Musoq.Evaluator/Visitors/BuildMetadataAndInferTypeVisitor.cs index 51482b31..830efe3f 100644 --- a/Musoq.Evaluator/Visitors/BuildMetadataAndInferTypeVisitor.cs +++ b/Musoq.Evaluator/Visitors/BuildMetadataAndInferTypeVisitor.cs @@ -1674,15 +1674,22 @@ private static bool TryConstructGenericMethod(MethodInfo methodInfo, ArgsListNod foreach (var genericArgument in genericArguments) { - for (int i = 0; i < parameters.Length; i++) + for (var i = 0; i < parameters.Length; i++) { var parameter = parameters[i]; var returnType = args.Args.Where((arg, index) => index == i).Single().ReturnType; var elementType = returnType.GetElementType(); + if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == parameter.ParameterType.GetGenericTypeDefinition()) + { + genericArgumentsDistinct.Add(returnType.GetGenericArguments()[0]); + continue; + } + if (parameter.ParameterType.IsGenericType && parameter.ParameterType.IsAssignableTo(typeof(IEnumerable<>).MakeGenericType(genericArgument)) && elementType is not null) { genericArgumentsDistinct.Add(elementType); + continue; } if (parameter.ParameterType.IsGenericType) diff --git a/Musoq.Evaluator/Visitors/ExtractAccessColumnFromQueryVisitor.cs b/Musoq.Evaluator/Visitors/ExtractAccessColumnFromQueryVisitor.cs index 5242e27f..79c21d4a 100644 --- a/Musoq.Evaluator/Visitors/ExtractAccessColumnFromQueryVisitor.cs +++ b/Musoq.Evaluator/Visitors/ExtractAccessColumnFromQueryVisitor.cs @@ -49,4 +49,11 @@ public override void Visit(SchemaFromNode node) base.Visit(node); } + + public override void Visit(InMemoryTableFromNode node) + { + _accessColumns.TryAdd(node.Alias, new List()); + + base.Visit(node); + } } \ No newline at end of file