Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Marten;
using Marten.Linq;
using Marten.Testing.Documents;
using Marten.Testing.Harness;
using Shouldly;

namespace LinqTests.Bugs;

public class compiled_query_problem_with_search_by_string_and_string_collections(DefaultStoreFixture fixture): IntegrationContext(fixture)
{
protected override async Task fixtureSetup()
{
await theStore.Advanced.ResetAllData();
}

public class IssuesByTitles: ICompiledListQuery<Issue>, IQueryPlanning
{
[Marten.Events.CodeGeneration.MartenIgnore]
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not sure if this should be used or not. without this attribute it throws an exception because it tries to use undrying type (string) as document type

System.ArgumentOutOfRangeException: This type cannot be used as a Marten document (Parameter 'documentType')
at Marten.Schema.DocumentMapping..ctor(Type documentType, StoreOptions storeOptions) in //src/Marten/Schema/DocumentMapping.cs:line 116
at Marten.Schema.DocumentMapping`1..ctor(StoreOptions storeOptions) in //src/Marten/Schema/DocumentMapping.cs:line 843
....

public required string[] Titles { get; set; }
public required string Status { get; set; }

public Expression<Func<IMartenQueryable<Issue>, IEnumerable<Issue>>> QueryIs()
{
return query => query.Where(x => x.Status == Status && x.Title.IsOneOf(Titles));
}
void IQueryPlanning.SetUniqueValuesForQueryPlanning()
{
Status = "status";
Titles = ["title"];
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems that the issue is in code generation when IQueryPlanning is used. It produces valid sql and parameters, but it does not use the value from the _query for this array param. Maybe due to MartenIgnore.

public override void ConfigureCommand(Weasel.Postgresql.ICommandBuilder builder, Marten.Internal.IMartenSession session)
{
	var parameters1 = builder.AppendWithParameters(@"select d.data from public.mt_doc_issue as d where (d.data ->> 'Status' = ^ and d.data ->> 'Title' = ANY(^));", '^');

	parameters1[0].NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Text;
	parameters1[0].Value = _query.Status;
	parameters1[1].Value = new string[]{"title"}; // <---- here is the constant instead of _query.Titles
	parameters1[1].NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Array | NpgsqlTypes.NpgsqlDbType.Varchar;
}

if i edit it manually to _query.Titles it returns valid results

}
}

[Fact]
public async Task can_search_isOneOf_strings_with_compiled_queries_and_query_planning()
{
var issue1 = new Issue { Title = "Issue1", Status = "Open" };
var issue2 = new Issue { Title = "Issue2", Status = "Open"};
var issue3 = new Issue { Title = "Issue3", Status = "Open" };

theSession.Store(issue1, issue2, issue3);
await theSession.SaveChangesAsync();

await using var session = theStore.QuerySession();
var query = new IssuesByTitles { Titles = [issue1.Title, issue2.Title], Status = issue1.Status };
var issues = await session.QueryAsync(query);

issues.Count().ShouldBe(2);
}
}
Loading