Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Duplicates the tenant id in a sub query when using ctid in the case o… #3579

Merged
merged 1 commit into from
Dec 8, 2024
Merged
Show file tree
Hide file tree
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,58 @@
using System.Linq;
using System.Threading.Tasks;
using Marten;
using Marten.Testing.Documents;
using Marten.Testing.Harness;
using Shouldly;
using Xunit;
using Xunit.Abstractions;

namespace CoreTests.Partitioning;

public class querying_against_conjoined_partitioning_with_tenant_id_and_subquery : OneOffConfigurationsContext
{
private readonly ITestOutputHelper _output;

public querying_against_conjoined_partitioning_with_tenant_id_and_subquery(ITestOutputHelper output)
{
_output = output;
}

[Fact]
public async Task do_not_bleed_tenant_data_because_of_select_queries()
{
var reds = Target.GenerateRandomData(100).ToArray();
var blues = Target.GenerateRandomData(1000).ToArray();

StoreOptions(opts =>
{
opts.Policies.AllDocumentsAreMultiTenantedWithPartitioning(x =>
{
x.ByList()
.AddPartition("red", "red")
.AddPartition("blue", "blue");
});
});

await theStore.BulkInsertAsync("red", reds);
await theStore.BulkInsertAsync("blue", blues);

using var session = theStore.LightweightSession("red");
session.Logger = new TestOutputMartenLogger(_output);

var matching = await session.Query<Target>()
.Where(x => x.Children.Any(c => c.Number > 8))
.OrderBy(x => x.Id)
.Select(x => x.Id)
.ToListAsync();

var expected = reds.Where(x => x.Children.Any(c => c.Number > 8))
.OrderBy(x => x.Id)
.Select(x => x.Id)
.ToList();

matching.Count.ShouldBe(expected.Count);

matching.ShouldBe(expected);
}
}
4 changes: 4 additions & 0 deletions src/Marten/Linq/Members/DocumentQueryableMemberCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
using System.Linq.Expressions;
using System.Reflection;
using JasperFx.Core;
using JasperFx.Core.Reflection;
using Marten.Linq.Parsing.Operators;
using Marten.Schema;
using Marten.Storage;
using Weasel.Postgresql;
using Weasel.Postgresql.SqlGeneration;

Expand All @@ -24,6 +26,8 @@ public DocumentQueryableMemberCollection(IDocumentMapping mapping, StoreOptions
ElementType = mapping.DocumentType;
}

public TenancyStyle TenancyStyle { get; set; } = TenancyStyle.Single;

public string MemberName => string.Empty;

public string JsonPathSegment => "";
Expand Down
11 changes: 11 additions & 0 deletions src/Marten/Linq/SqlGeneration/Filters/SubQueryFilter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#nullable enable
using Marten.Internal;
using Marten.Linq.Members;
using Marten.Storage;
using Weasel.Postgresql;
using Weasel.Postgresql.SqlGeneration;

Expand Down Expand Up @@ -43,6 +44,16 @@ void ISqlFragment.Apply(ICommandBuilder builder)
builder.Append("NOT(");
}

if (builder.TenantId != Tenancy.DefaultTenantId && Member is ChildCollectionMember child)
{
if (child.Ancestors[0] is DocumentQueryableMemberCollection c && c.TenancyStyle == TenancyStyle.Conjoined)
{
builder.Append("d.tenant_id = ");
builder.AppendParameter(builder.TenantId);
builder.Append(" and ");
}
}

builder.Append("d.ctid in (select ctid from ");
builder.Append(_exportName!);
builder.Append(")");
Expand Down
2 changes: 2 additions & 0 deletions src/Marten/Schema/DocumentMapping.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ public DocumentMapping(Type documentType, StoreOptions storeOptions)

StoreOptions.applyPostPolicies(this);

QueryMembers.TenancyStyle = TenancyStyle;

_schema = new Lazy<DocumentSchema>(() => new DocumentSchema(this));

if (DisablePartitioningIfAny)
Expand Down
Loading