Skip to content

Commit

Permalink
Fixed passing parameters to methods that was clashing due to improper…
Browse files Browse the repository at this point in the history
… object instance passed due to table context type mismatch -computed earlier table context weren't discarded properly
  • Loading branch information
Puchaczov committed Dec 8, 2024
1 parent d11701d commit df89b68
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 22 deletions.
49 changes: 48 additions & 1 deletion Musoq.Evaluator.Tests/CrossApplyCteTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Musoq.Evaluator.Tests.Schema.Generic;
Expand Down Expand Up @@ -35,6 +36,11 @@ private class CrossApplyClass3
public string[] Skills { get; set; }
}

public class CrossApplyClass4
{
public string Name { get; set; }
}

[TestMethod]
public void WhenSchemaMethodCrossAppliedWithAnotherSchema_WithinCte_ShouldPass()
{
Expand Down Expand Up @@ -320,4 +326,45 @@ with first as (
Assert.AreEqual("Name3", table[8].Values[0]);
Assert.AreEqual("Skill9", table[8].Values[1]);
}

[TestMethod]
public void WhenCrossApplyComponentsMustInjectMultipleEntities_ShouldNotThrow()
{
var query = """
with first as (
select
r.AggregateValues(r.Name) as Name1,
r.AggregateValues(r.Name) as Name2
from #schema.first() r
cross apply r.JustReturnArrayOfString() b
cross apply r.JustReturnArrayOfString() c
group by 'fake'
)
select
b.Name1,
b.Name2,
p.Value
from first b
inner join #schema.first() r on 1 = 1
cross apply r.MethodArrayOfStrings(r.TestMethodWithInjectEntityAndParameter(b.Name1), r.TestMethodWithInjectEntityAndParameter(b.Name2)) p
""";

var firstSource = new List<CrossApplyClass4>
{
new() {Name = "Name1"}
}.ToArray();

var vm = CreateAndRunVirtualMachine(
query,
firstSource);

try
{
vm.Run();
}
catch (Exception)
{
Assert.Fail($"Expected not to throw exception but got: ");
}
}
}
4 changes: 2 additions & 2 deletions Musoq.Evaluator.Tests/MethodInvocationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,8 @@ cross apply x.JustReturnArrayOfString() b
select
p.Value
from first b
inner join #A.entities() r2 on 1 = 1
cross apply r2.MethodArrayOfStrings(r2.TestMethodWithInjectEntityAndParameter(b.Name), r2.TestMethodWithInjectEntityAndParameter(b.Name)) p
inner join #A.entities() r on 1 = 1
cross apply r.MethodArrayOfStrings(r.TestMethodWithInjectEntityAndParameter(b.Name), r.TestMethodWithInjectEntityAndParameter(b.Name)) p
""";

var sources = new Dictionary<string, IEnumerable<BasicEntity>>()
Expand Down
25 changes: 24 additions & 1 deletion Musoq.Evaluator.Tests/Schema/Generic/GenericLibrary.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
using Musoq.Plugins;
using Musoq.Plugins.Attributes;

namespace Musoq.Evaluator.Tests.Schema.Generic;

public class GenericLibrary : LibraryBase;
public class GenericLibrary : LibraryBase
{
[BindableMethod]
public string[] JustReturnArrayOfString()
{
return ["1", "2", "3"];
}

[BindableMethod]
public string TestMethodWithInjectEntityAndParameter(string name)
{
return name;
}

[BindableMethod]
public string[] MethodArrayOfStrings<TEntity>([InjectSpecificSource(typeof(object))] TEntity entity, string name1, string name2)
{
return [
name1,
name2
];
}
}
2 changes: 1 addition & 1 deletion Musoq.Evaluator/Musoq.Evaluator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>7.5.1</Version>
<Version>7.5.2</Version>
<Authors>Jakub Puchała</Authors>
<Product>Musoq</Product>
<PackageProjectUrl>https://github.com/Puchaczov/Musoq</PackageProjectUrl>
Expand Down
16 changes: 10 additions & 6 deletions Musoq.Evaluator/Tables/TableRowSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,30 @@ namespace Musoq.Evaluator.Tables;

public class TableRowSource : RowSource
{
private static readonly object[] DiscardedContexts = [new DiscardedRowContext()];

private readonly IDictionary<string, int> _columnToIndexMap;
private readonly Table _table;
private readonly bool _skipContext;
private readonly bool _discardedContext;

public TableRowSource(Table rowSource, bool skipContext)
public TableRowSource(Table rowSource, bool discardContext)
{
_table = rowSource;
_skipContext = skipContext;
_discardedContext = discardContext;

_columnToIndexMap = new Dictionary<string, int>();

foreach (var column in _table.Columns)
_columnToIndexMap.Add(column.ColumnName, column.ColumnIndex);
}

public override IEnumerable<IObjectResolver> Rows => _skipContext ? RowsWithSkippedContexts : RowsWithContexts;
public override IEnumerable<IObjectResolver> Rows => _discardedContext ? RowsWithDiscardedContexts : RowsWithContexts;

private IEnumerable<IObjectResolver> RowsWithContexts =>
_table.Select(row => new RowResolver((ObjectsRow)row, _columnToIndexMap));

private IEnumerable<IObjectResolver> RowsWithSkippedContexts =>
_table.Select(row => new RowResolver(new ObjectsRow(row.Values, row.Values), _columnToIndexMap));
private IEnumerable<IObjectResolver> RowsWithDiscardedContexts =>
_table.Select(row => new RowResolver(new ObjectsRow(row.Values, DiscardedContexts), _columnToIndexMap));

private class DiscardedRowContext;
}
15 changes: 11 additions & 4 deletions Musoq.Evaluator/Visitors/BuildMetadataAndInferTypesVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1482,8 +1482,11 @@ private void VisitAccessMethod(AccessMethodNode node, Func<FunctionToken, Node,
method = reducedMethod;
}

if (!isAggregateMethod && method.IsGenericMethod && !method.IsConstructedGenericMethod &&
TryConstructGenericMethod(method, args, out var constructedMethod))
if (
!isAggregateMethod &&
method.IsGenericMethod &&
!method.IsConstructedGenericMethod &&
TryConstructGenericMethod(method, args, entityType, out var constructedMethod))
{
method = constructedMethod;
}
Expand Down Expand Up @@ -2076,7 +2079,7 @@ private static bool TryReduceDimensions(MethodInfo method, ArgsListNode args, ou
return true;
}

private static bool TryConstructGenericMethod(MethodInfo methodInfo, ArgsListNode args, out MethodInfo constructedMethod)
private static bool TryConstructGenericMethod(MethodInfo methodInfo, ArgsListNode args, Type entity, out MethodInfo constructedMethod)
{
var genericArguments = methodInfo.GetGenericArguments();
var genericArgumentsDistinct = new List<Type>();
Expand All @@ -2090,6 +2093,10 @@ private static bool TryConstructGenericMethod(MethodInfo methodInfo, ArgsListNod
{
i = 1;
shiftArgsWhenInjectSpecificSourcePresent = 1;
if ((genericArgument.IsGenericParameter || genericArgument.IsGenericMethodParameter) && parameters[0].ParameterType.IsGenericParameter)
{
genericArgumentsDistinct.Add(entity);
}
}
for (; i < parameters.Length; i++)
{
Expand Down Expand Up @@ -2138,7 +2145,7 @@ private static bool TryConstructGenericMethod(MethodInfo methodInfo, ArgsListNod
}

var genericArgumentsConcreteTypes = genericArgumentsDistinct.Distinct().ToArray();

constructedMethod = methodInfo.MakeGenericMethod(genericArgumentsConcreteTypes);
return true;
}
Expand Down
6 changes: 1 addition & 5 deletions Musoq.Evaluator/Visitors/RewriteQueryVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -463,8 +463,6 @@ public void Visit(QueryNode node)
var scoreWhere = where;
var scoreOrderBy = orderBy;

QueryNode query;

var splitNodes = new List<Node>();
var source = from.Alias.ToRowsSource().WithRowsUsage();

Expand Down Expand Up @@ -860,7 +858,7 @@ public void Visit(QueryNode node)
modifiedOrderBy = new OrderByNode(splitOrderBy);
}

query = new DetailedQueryNode(
QueryNode query = new DetailedQueryNode(
outSelect,
new Parser.ExpressionFromNode(
new InMemoryGroupedFromNode(returnScore)),
Expand All @@ -887,8 +885,6 @@ public void Visit(QueryNode node)

if (IsQueryWithMixedAggregateAndNonAggregateMethods(split))
{
query = new InternalQueryNode(select, from, where, null, orderBy, skip, take,
CreateRefreshMethods(usedRefreshMethods));
throw new NotImplementedException("Mixing aggregate and non aggregate methods is not implemented yet");
}

Expand Down
5 changes: 3 additions & 2 deletions Musoq.Evaluator/Visitors/ToCSharpRewriteTreeVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,7 @@ public void Visit(AccessMethodNode node)
(IndexBasedContextsPositionsSymbol) _scope.ScopeSymbolTable.GetSymbol(MetaAttributes
.PreformatedContexts);
var orderNumber = int.Parse(_scope[MetaAttributes.OrderNumber]);

currentContext = preformattedContexts.GetIndexFor(orderNumber, node.Alias);
}
else
Expand Down Expand Up @@ -2067,7 +2068,7 @@ public void Visit(InMemoryTableFromNode node)
_inMemoryTableIndexes[
node.VariableName])))))));

var literalFalseArgument = SyntaxFactory.Argument(
var literalTrueArgument = SyntaxFactory.Argument(
SyntaxFactory.LiteralExpression(
SyntaxKind.TrueLiteralExpression));

Expand All @@ -2084,7 +2085,7 @@ public void Visit(InMemoryTableFromNode node)
SyntaxFactory.ArgumentList(
SyntaxFactory.SeparatedList([
tableArgument,
literalFalseArgument
literalTrueArgument
])))))))));
}

Expand Down

0 comments on commit df89b68

Please sign in to comment.