Search code examples
javasqljooq

Are the jOOQ fluent API intermediate results immutable?


If I save an intermediate result from the fluent API query builder, will later calls modify it? (In other words, are the intermediate results immutable?) For example,

final var a = create.select().from(AUTHOR);
final var before1920 = a.where(AUTHOR.YEAR_OF_BIRTH.gt(1920).fetch();
final var authorSql = a.where(AUTHOR.FIRST_NAME.eq("Paulo")).getSql();

Can I be confident that a was not modified by the later statements?

If this is not the case, my main desire is to sometimes log the SQL from queries either to audit logs or debugging logs. Can I safely call getSQL() before or after calling fetch*() methods?


Solution

  • Mutability of the jOOQ DSL

    As of jOOQ 3.16, yes, those particular methods expose mutable behaviour, so you can dynamically construct the query as you did. See also the jOOQ manual's section about mutability, which hints at this possibly changing in the (far) future, in favour of more predictable immutable DSL APIs.

    But even if this can be exploited, you should not construct dynamic SQL queries like this. Use the recommended approach:

    Condition condition = AUTHOR.YEAR_OF_BIRTH.gt(1920);
    
    if (...)
        condition = condition.and(AUTHOR.FIRST_NAME.eq("Paulo"));
    
    create.select()
          .from(AUTHOR)
          .where(condition)
          .fetch();
    

    This doesn't help you with your actual question, but it answers parts of the question you have asked, namely, you shouldn't rely on this mutable behaviour.

    Specific questions

    Can I be confident that a was not modified by the later statements?

    No, you cannot. a was modified, see the section about mutability.

    my main desire is to sometimes log the SQL from queries either to audit logs or debugging logs

    You can either use the built in execute logging, which logs all queries to the DEBUG level.

    Can I safely call getSQL() before or after calling fetch*() methods?

    Yes, those calls are safe. That's what the above execute logging does, too, in order to apply formatting, inlining of bind values for logging purposes, etc.