jooq-checker: Allow and Require

9 views
Skip to first unread message

Victor Noël

unread,
Aug 30, 2019, 9:35:27 AM8/30/19
to jOOQ User Group
Hi,

I think I'm a bit thick with this, but I just can't wrap my head around the difference (and more importantly the need) for both Allow and Require annotations with jooq-checker.

Maybe it's because my use case does not need both, so let me explain what it is:
- I have some code (maybe used by different applications, so it's kind of library code) that do db related stuffs, and if it is possible, I want this code as generic as possible w.r.t. the database dialect
- because I mostly use postgresql, sometimes I use postgresql-specific features (still in library code)
- in some specific cases, I DO know which database I am using (disclaimer: it's postgresql :P) for my application (so it's not library code)

What I did is annotate most of this code with `Allow(SQLDialect.DEFAULT)` and when it wasn't enough, I used `Allow(SQLDIALECT.POSTGRES)`.

Some questions:
- I'm not sure it is correct to use the DEFAULT dialect for this, but I suppose it is?
- I don't see the need for Require here, is it only needed when I am working with multiple dialects (not DEFAULT) at the same?
- Is Allow some kind of architecture-level rule while Require some kind of class-level assertion?

Thanks for any help to understand this :)

Lukas Eder

unread,
Aug 30, 2019, 10:51:30 AM8/30/19
to jOOQ User Group
Hi Victor,

Put shortly, Allow is a disjunction (OR) whereas Require is a conjunction (AND)
  • @Allow({ ORACLE, POSTGRES }) means that you allow for both of these dialects to be used in general. No other dialect may be used (e.g. MYSQL). If an API supports only one of the two dialects, e.g. CONNECT BY (supported by Oracle), then it is still allowed.
  • @Require({ ORACLE, POSTGRES }) will now require *both* Oracle and PostgreSQL support on any API. In this case, CONNECT BY will no longer work, because it is not supported by PostgreSQL
In your case, you could just use @Allow(POSTGRES) only. You don't have to Allow(DEFAULT), I don't think this adds much value. If you're only working with a single RDBMS, you don't need @Require. But you could add it, and then add a second dialect in the future, should you choose to support another RDBMS.

Perhaps, code explains this better? Here's the implementation from Tools.checkSQLDialect():

boolean allowedFail = true;
allowedLoop:
for (SQLDialect a : allowed) {
    for (SQLDialect s : supported) {
        if (a.supports(s)) {
            allowedFail = false;
            break allowedLoop;
        }
    }
}

if (allowedFail)
    return error.apply("The allowed dialects in scope " + allowed + " do not include any of the supported dialects: " + supported);

boolean requiredFail = false;
requiredLoop:
for (SQLDialect r : required) {
    for (SQLDialect s : supported)
        if (r.supports(s))
            continue requiredLoop;

    requiredFail = true;
    break requiredLoop;
}

if (requiredFail)
    return error.apply("Not all of the required dialects " + required + " from the current scope are supported " + supported);


I hope this helps.
Lukas

--
You received this message because you are subscribed to the Google Groups "jOOQ User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jooq-user/903973c4-9f0b-4d91-9750-540cdb4232a0%40googlegroups.com.

Victor Noël

unread,
Aug 30, 2019, 10:56:09 AM8/30/19
to jOOQ User Group
Yes, it does help, what I was missing is that if I need to have code that works with TWO dialect at the same time, I need `Require` to force my code to be compatible with both. `Allow` wouldn't help with this.

Following this, I'm wondering what would be the use case for `Allow` then: is there some case when it makes sense to allow two different dialects?
You wouldn't want to mix in a same query two dialects, and if it's in different queries, then you juste need to apply two different `Require` annotation on different scope.

Does this make sense?
To unsubscribe from this group and stop receiving emails from it, send an email to jooq...@googlegroups.com.

Lukas Eder

unread,
Aug 30, 2019, 11:19:38 AM8/30/19
to jOOQ User Group
Think in terms of trees of code.

On the package level, you'll allow Oracle and PostgreSQL
On most class levels, you'll require both
On some specialised DAOs, you'll require only *either* Oracle *or* PostgreSQL, e.g. you'll have an OracleCustomerDAO and a PostgresCustomerDAO, because those queries needed special tuning, or whatever
And on another, third, specialised service, you're going to use H2, but you'll limit that to only this one service. So, you'll add another Allow (and Require) H2 annotation.

We may have overengineered this a bit, but think of it as a two way access control list. Allow grants additional dialects. Require revokes them again, but instead of revoking, we chose requiring as a verb, with the inverse set of dialects to be passed, because that's more practical. Thinking of it (to add to the confusion), we *could* support an additional @Deny annotation ;-)

To unsubscribe from this group and stop receiving emails from it, send an email to jooq-user+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jooq-user/7ca00849-10f1-4279-b7f1-dca2481fa5d3%40googlegroups.com.

Victor Noël

unread,
Aug 30, 2019, 11:28:21 AM8/30/19
to jOOQ User Group
I see ok.

Technically, I feel like I could just use Require to express your example and things would be as expressive I feel (this is related to the fact that at the lowest scope, you never want to mix two dialect at the same time).

But as I said in my first post, I believe it could make sense to have different reasons for
- allowing only some dialects: it is an architectural choice, for example a team says that only Oracle and Postgres can be used and that should be inforced for the whole code base, which btw is a good motivation for https://github.com/jOOQ/jOOQ/issues/9115
- requiring some dialects in a given scope to be sure we are not introducing bugs by using incompatible dialects, this matches well with the example you gave.

Thank you for taking the time, I think everything is clear for me now :)
Reply all
Reply to author
Forward
0 new messages