Hello Christopher,
A first draft of this implementation is committed to SVN trunk and
GitHub. While implementing this, the general feeling of how the API
should look got a lot better. Essentially, the new org.jooq.Converter
type is stabilising:
https://github.com/lukaseder/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/Converter.java
Here are some facts:
1. I'm calling this type Converter rather than Mapper, as the notion
of "conversion" is already present in jOOQ's org.jooq.tools.Convert
and various other places. So this whole discussion is about custom
data type conversion.
2. I found that it is necessary for jOOQ's internals to get a hold of
both Java types involved in type conversion, i.e. the database type
(e.g. java.lang.Integer, java.sql.Date, etc) and the custom type
(com.example.MyEnum, com.example.MyDateType).
3. There are two elements to be configured in source code generation:
3.1. The "custom type" (e.g. MyEnum and MyEnumConverter)
3.2. The "forced type" (e.g. MyEnum and a regular expression matching
all columns upon which this forced type should be mapped). "Forced
types" can be used for other purposes, too. For example, forcing a
NUMBER(1) column to be java.lang.Boolean. This is currently still
experimental but should be working in 2.1.0
A sample configuration can be seen here:
https://github.com/lukaseder/jOOQ/blob/f53818504ef1d0345a8aae40fd29b7a9ccd6976a/jOOQ-test/configuration/org/jooq/configuration/lukas/hsqldb/library.xml
4. You were right, essentially, about custom enum types being a
special case of arbitrary custom types. As of now, they are treated no
differently. Some convenience in code generation may be added in the
next release, in order to be able to generate custom enum converters.
For now, there is EnumConverter, which can be extended by manually
written custom converters (overriding the to() method):
https://github.com/lukaseder/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/impl/EnumConverter.java
5. Generated tables will use the custom type as bound for <T>. A
sample table can be seen here:
https://github.com/lukaseder/jOOQ/blob/f53818504ef1d0345a8aae40fd29b7a9ccd6976a/jOOQ-test/src/org/jooq/test/hsqldb/generatedclasses/tables/TMappedTypes.java
6. There is a central custom type registry providing a mapping between
MyEnum -> MyEnumConverter. This is the registry:
https://github.com/lukaseder/jOOQ/blob/master/jOOQ/src/main/java/org/jooq/impl/DataTypes.java
It is used by jOOQ to know how to bind and inline custom types in
SQL. A custom type can only be converted by a single converter,
globally. i.e. it is currently not possible to have MyEnum ->
Converter1 in one place, and MyEnum -> Converter2 in another. The
reason for this is, jOOQ needs an unambiguous registry in
"context-less" cases like this:
create.select(MyEnum.VAL).fetch();
This will be an open point. I'm curious about your feedback on
this topic. You suggested to use the Factory's Settings as an
(additional) Converter registry. This might be a viable workaround for
a future release, if several converters are really needed for the same
custom type. I feel it might be a bit overkill, though.
7. Fields (Parameters) hold direct references to their
"ConvertedDataType". This means that when fetching data from a
ResultSet (CallableStatement, SQLInput), this information is available
directly from the Field.
I feel this is on a good track!
Here's a preliminary, simplistic test-case for these converters. It
involves custom converters for enums and java.util.Date /
java.util.Calendar:
https://github.com/lukaseder/jOOQ/blob/f53818504ef1d0345a8aae40fd29b7a9ccd6976a/jOOQ-test/src/org/jooq/test/jOOQHSQLDBTest.java#L683
Next week, I'll create many more test cases for all sorts of queries
and I'll consolidate the existing experimental functionality.
> No, I think we are on the same train of thought now, so I am going to
> be less of a pain :)
You may speak up again :-)
Cheers
Lukas