4

I am trying to do something like:

t.set(field("ColumnName"), select(max(field("ColumnName"))).from("TableName"));

But I am getting the following compile error:

    Ambiguous method call, Both
    set(Field,Object)                    in InsertSetStep and
    set(Field,Select<? extends Record1>) in InsertSetStep match

I have tried to resolve the ambiguity with casting, but I still receive the same error

Select<? extends Record1> sq = select(max(field("ColumnName"))).from("TableName");
t.set( field("ColumnName"), (Select<? extends Record1>)sq );

I have a couple questions:

  1. Why does casting not resolve the ambiguity in this scenario? (I have tried casting to (Object) and that does resolve the ambiguity)
  2. Is there a way for me to resolve the ambiguity?
jkchu
  • 98
  • 10
  • Looks like this may be related to a bug filed by Lukas Eder (jOOQ author): [https://bugs.java.com/bugdatabase/view_bug.do?bug_id=7031404](https://bugs.java.com/bugdatabase/view_bug.do?bug_id=7031404) – jkchu Jun 27 '18 at 21:35

1 Answers1

1

This is a very unfortunate, but specified behaviour of the Java language and the various compilers. While pre-generics, the method taking a Select type is going to be more specific for your particular call, it is no longer so, once generics are involved. The rationale can be seen here.

There's not much a heavily generic and overloaded API like jOOQ can do, but you can, as a user. You have to avoid binding <T> to Object in such cases, either by using the code generator, or by passing data types manually:

// Assuming this is an INTEGER type
t.set(
    field("ColumnName", SQLDataType.INTEGER), 
    select(max(field("ColumnName", SQLDataType.INTEGER))).from("TableName"));

Or, you start storing your column references in some static variables like:

Field<Integer> COLUMN_NAME = field("ColumnName", SQLDataType.INTEGER);

// And then:
t.set(COLUMN_NAME, select(max(COLUMN_NAME)).from("TableName"));

Using the code generator

Note, this is hardly ever a problem when you're using the code generator, in case of which you have specific type information bound to the <T> types of your Field<T> references, in case of which the overloads won't both be applicable anymore.

I really recommend you use the code generator for this reason (and for many others).

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
  • Thank you for your response, super helpful. Unfortunately, I don't think using the code generators will work with my current use case. The library I am building is meant to allow users to create tables and update columns dynamically, so the schema is not stable for these tables. I tried your suggestion of passing in data types manually, but I am still getting that same ambiguous method error: `Field columnName = field("ColumnName", SQLDataType.BIGINTUNSIGNED);` `t.set(columnName, select(max(columnName)).from("TableName"));` – jkchu Jun 28 '18 at 19:53
  • 1
    @jkchu: Oh I see, *that* use-case :) Then indeed, no code generation for you... Really, still that same error? With what Java version / IDE, etc? Are any raw types involved (e.g. is the type of `t` a raw type)? – Lukas Eder Jun 29 '18 at 06:05
  • Ah that was the issue! `t` was a raw type of `InsertSetStep`, changing that fixed the ambiguous method error. Actually, it fixes my original issue (don't even need to pass in data types manually). Thanks for your help and all your great work with jOOQ! – jkchu Jun 29 '18 at 18:02