Hello again,
 

> No, indeed. RecordType is a type descriptor, not an actual value / tuple. 
> Here's the distinction:
>
> - Row: an actual QueryPart that can generate a row constructor in SQL. It 
> can contain column references as well as values
> - RecordType: A type descriptor for records and rows
> - Record: A map of column references / values pairs
>

Thanks, that's what I thought. And that's what struck me as a lack of 
symmetry (RecordType being Record keys, what should hold Record values?), 
hence that "RecordValue" idea. And I didn't see Row as a good candidate 
because it's not Record-parameterized.

But then this RecordType/Row duality make me realize there are two 
different use cases here:
- use jOOQ to generate SQL
- use jOOQ-generated objects as a database model

So maybe that's another reason I tend to like RecordType more than Row: 
it's not part of the DSL, so it belongs to the second use-case (which is 
clearly the one I'm working with here). Also the 22-arity seems quite 
linked to the SQL generation...
Any thought about this distinction?

Clearly, you won't be getting what you're looking for out of the existing 
> type systems too soon, as it was not designed for this use-case, yet.
>
> There are some unfortunate inconsistencies in jOOQ's API which are due to 
> the late decision (version 3.0 only) to have those 22-arity "overloads" for 
> a variety of types (but not for others). For some types, these 22-overloads 
> make a lot of sense, mostly because you get immediate value in your SQL 
> construction. For other types, they would have made sense, but were much 
> too hard to implement correctly because of the limitations of the Java type 
> systems, or because of backwards compatibility with jOOQ 2.0. For other 
> types, they made no sense.
>
> Yes, a Key should really be a "more compatible" type with RecordType. In 
> fact, UpdatableRecord.key() returns a Record, which is covariantly 
> overridden by concrete generated tables to return a Record1<T1>, or 
> Record2<T1, T2>, etc. so this concept certainly exists in jOOQ. Just not 
> for Key.
>
> We might be able to redesign these API types in a way that improves the 
> current situation. Certainly not in a backwards-compatible way, though. 
> This means we would have two parallel APIs that do the same thing for the 
> "rest" of version 3.x (or we fix this only in version 4.0).
>

Yes I agree this is not a backward-compatible refactoring. It is a long 
shot anyway, not expecting changes in jOOQ in the next release ;)
 

> Now, before we proceed, I'd really love to have some more concrete 
> examples of use-cases where constraint meta data needs to be queried in 
> client code. I know you're trying to implement that tree persistence on top 
> of jOOQ (see other discussion), but let's not go to the bigger picture, 
> let's focus on concrete operations that you're trying to do and where the 
> lack of type information is bothering you. Do you have some minimal 
> examples you could share?
>

With an hypothetical Key<R, K> type:


// Extracting a key
<K extends Record> K extract(Record record, Key<?, K> key)

But that's just a generic version of UpdatableRecord.key() as you 
pointed-out before.


// Copying key values
<K extends Record> void copy(Record fromRecord, Key<?, K> fromKey, Record 
toRecord, Key<?, K> toKey)

// Which I thought could be written with Row types, but it cannot,
// since passing a Row2 and Row19 below will just make K resolve to Row.
<K extends Row> void copy(Record fromRecord, K fromKey, Record toRecord, K 
toKey)

Showing that a subclassed type (Row) need the 22-arity to ensure 
type-safety, while a parameterized type (RecordType) doesn't.


// When using a type with a parameter for the primary key type ...
class TreeNode<K extends Record, R extends TableRecord<R>>

// ... it could be great to have a factory like this
<K extends Record, R extends TableRecord<R>> TreeNode<K, R> create(Key<R, K> 
key)

// ... or even like this, if Table had a key type
<K extends Record, R extends TableRecord<R>> TreeNode<K, R> create(Table<R, 
K> table)

Well, if Key gets a additional type, it's only fair that UpdatableRecord 
gets one too. And from there why not go all the way to Table (or rather 
some kind of UpdatableTable subtype)?


// For CRUD, the "get" (or "delete") operation needs an ID, that is values 
matching a primary key
<K extends Record, R extends TableRecord<R>> R get(TreeNode<K, R> node, 
SomeValueType<K> id)

With a RecordType-like container for values, you can call the last method 
as get(node, DSL.valueType("some", "key", "value")).
The idea being that you only need the 22 overloads on the factory method 
(as is done for DSL.recordType()) and then everything is handled with 
generics.

I realize that this CRUD thing is already addressed in the generated DAOs, 
where there is a notion of primary key type. But it's all based on 
generated overloads with specific types, so that's not exactly my point. 
Well unless I try to generate DAOs with tree capabilities... that's another 
way...

Thomas

-- 
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 [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to