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

Make IDocumentSchemaProvider accessible from IMartenQueryable #3543

Open
cafour opened this issue Nov 5, 2024 · 5 comments
Open

Make IDocumentSchemaProvider accessible from IMartenQueryable #3543

cafour opened this issue Nov 5, 2024 · 5 comments

Comments

@cafour
Copy link

cafour commented Nov 5, 2024

This is pretty much just a small quality-of-life improvement.

That being said, I'd like to be able to access IDocumentSchemaProvider from within extension methods that extend IQueryable and mix LINQ functions with raw SQL. Best shown with an example:

public static IQueryable<T> WhereAccountHasPermission<T>(
    this IQueryable<T> query,
    IDocumentSchemaResolver schema,
    Permission permission,
    Guid accountId
) where T : IEntity
{
    var sql = $"""
    (
        SELECT
            (perms.data -> 'AccountEntries' -> ? -> 'EffectivePermission')::int
        FROM {schema.For<EntityPermissionInfo>()} AS perms
        WHERE perms.id = d.id
    )::int & ? = ?
    """;
    return query.Where(e => e.MatchesSql(
        sql,
        accountId.ToString(),
        (int)permission,
        (int)permission));
}

The extension method above applies a where clause that filters documents of type T based on whether a user with accountId has the correct permission flags for each of the documents. To do this, it needs to access documents of type EntityPermissionInfo. The type's table doesn't necessarily have to be in the public schema, so we have to use IDocumentSchemaResolver.For.

Right now, we pass the resolver each time we call the method, which is a bit cumbersome. Especially if I consider that Marten's queryable has a reference to a query session, from which one can navigate to the schema resolver.

The easiest thing to do would be to just make IMartenLinqQueryable public, then I could just check if the queryable implements it and use the query session within. I'm fine with making a PR for it, but I have no idea if it would break anything else, so I'm opening this issue instead.

@jeremydmiller
Copy link
Member

@cafour Any reason why you're not just using the AdvancedSql API that already does a lot of that?

@cafour
Copy link
Author

cafour commented Nov 5, 2024

@jeremydmiller I did experiment with it but realized that by using it, I lose the comfort of composing an IQueryable and being able to rely on Marten's LINQ provider to handle things like sorting and pagination. With AdvancedSql I have to write all of the SQL myself, not just a where clause. Or at least it seems to me that way. It is possible that I missed something.

@jeremydmiller
Copy link
Member

Okay, I'll buy that. I think I'd look for more usable alternatives though. Maybe a WhereMatchesSql(this IMartenQueryable queryable, Func< IDocumentSchemaResolver, string>) ?

@jeremydmiller
Copy link
Member

Or alternatively, have some kind of markup in the SQL that gets resolved by Marten at the time the SQL is compiled. The underlying codegen has something like that and that's been helpful

@cafour
Copy link
Author

cafour commented Nov 13, 2024

@jeremydmiller The WhereMatchesSql seems simpler to me but I can look into the markup option as well. Would you mind if I made a PR at some point?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants