2

Let's take the query from my other question:

SelectConditionStep<Record1<String>> query = create
        .select(AUTHOR.LASTNAME.as("AuthorName"))
            .from(
                    (
                            BOOK.leftOuterJoin(BOOK_AUTHOR).on(BOOK.ID.eq(BOOK_AUTHOR.BOOKID))
                    ).leftOuterJoin(AUTHOR).on(AUTHOR.ID.eq(BOOK_AUTHOR.AUTHORID))
            )
            .where(BOOK.ID.eq(1))
        ;

//when
Result<Record1<String>> result = query.fetch();

If I try to replace SelectConditionStep<Record1<String>> with SelectConditionStep<Record>, I get

Incompatible types.

Required: SelectConditionStep<org.jooq.Record>

Found: SelectConditionStep<org.jooq.Record1<java.lang.String>>

and yet ...

package org.jooq;

import javax.annotation.Generated;

/**
 * A model type for a records with degree <code>1</code>
 *
 * @see Row1
 * @author Lukas Eder
 */
@Generated("This class was generated using jOOQ-tools")
public interface Record1<T1> extends Record {...}

So ... what gives?

Unless I'm missing something very obvious, shouldn't I be allowed to treat instances of Record1 as if they were Records?

(And yes, I started questioning myself to the point I needed to check I'm not completely mental: https://ideone.com/0O4mOU )

User1291
  • 7,664
  • 8
  • 51
  • 108

2 Answers2

3

That is just how generics work in Java.

This does not compile either, with the same error message:

ArrayList<Animal> x = new ArrayList<Dog>(); 
ArrayList<List<String>> x = new ArrayList<ArrayList<String>>();

You may want to type your variable something like SelectConditionStep<? extends Record> query. This way, you tell the compiler that any subclass of Record is acceptable (which is not otherwise the case). If you do that, you will also get a Result<? extends Record> back at the end, though, no longer something typesafe in the number and shape of the columns.

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • It's amazing how very basic things I keep forgetting when I haven't used them in a while. -.- Thank you. – User1291 Mar 19 '19 at 10:10
2

Using wildcards for <R extends Record>

While the correct answer to your specific question has already been given by Thilo, what I believe you wanted to do is simply not spell out the entire type signature of this intermediate type, because you don't need it and because it's tedious. You could use a wildcard:

SelectConditionStep<?> query = ...;
Result<?> result = query.fetch();

Because throughout the jOOQ API, the <R extends Record> type is bounded by Record, this wildcard is still implicitly bounded by Record as well, so in principle, the above is implicitly the same as:

SelectConditionStep<? extends Record> query = ...;
Result<? extends Record> result = query.fetch();

This means that when you iterate the result, you can still assign the elements to Record:

for (Record record : result) { ... }

Caveat: Unions, correlated subqueries, etc.

The <R extends Record> type is used in a few API elements, including unions, correlated subqueries, etc. If you use a wild card, you cannot use your query as a subquery in those syntax elements

Side note regarding jOOQ's XYZStep types

As a side note, do note that it is recommeded you try to avoid referencing jOOQ's XYZStep types. Assign your query to Select<?> or ResultQuery<?> instead:

Select<?> query = ...;
Result<?> result = query.fetch();
Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509