The jOOQ Release Note History
jOOQ Release notes
- For an interactive overview, see also https://github.com/jOOQ/jOOQ/issues
- For a formatted text version, see https://www.jooq.org/notes
- For a text version, see https://www.jooq.org/inc/RELEASENOTES.txt
- For an API diff, see https://www.jooq.org/api-diff
Version 3.19.16 - December 10, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Features and Improvements
#17567 | Add DataType.getFromType(): Class<?> and DataType.getToType(): Class<T> |
#17617 | Add more Javadoc to Binding and Converter, discussing when they are invoked |
Bug Fixes
#17532 | Regression in code generation for MariaDB where unsignedTypes=false is ignored |
#17538 | Wrong error message with DataTypeException: "Cannot cast [T] to [T]" |
#17541 | Error when converting String valued but Object typed column to Enum type |
#17546 | SQLDialect.JAVA renders currentLocalTime() instead of currentLocalDateTime() for CURRENT_DATE |
#17550 | Add DataType.isRowId() and use it instead of comparing Field.getType() == RowId.class internally |
#17554 | MySQLDSL encryption functions should work with argument Field.getDataType(), not Field.getType() |
#17558 | Field::collate should use getDataType().isString() instead of getType() == String.class to enable converters |
#17562 | The LIKE and SIMILAR TO predicates should use DataType.isString() internally to decide whether to auto-cast arguments, not Field.getType() == String.class |
#17571 | Avoid calling Typed.getType() in jOOQ internals, to be more Converter aware |
#17575 | MockResultSetMetaData::getColumnClassName returns user type instead of database type if MockResult uses converted data types |
#17581 | PostgresUtils.toPGString() should use JSONB.data() not JSONB.toString() |
#17584 | Avoid calling JSONB::toString in jOOQ internals |
#17587 | AbstractRecord::compareTo doesn't produce correct ordering |
#17594 | Missing Generated annotations on nested Path classes |
#17602 | Avoid CAST(? AS BLOB) in Oracle and render TO_BLOB(?) instead |
#17605 | ORA-22848 thrown if a BLOB or CLOB field is used in comparison predicates |
#17611 | BINARY, VARBINARY and LONGVARBINARY should be mapped to BLOB in SQLite |
#17626 | Wrong ON DELETE support annotated for Informix and MemSQL |
#17638 | NullPointerException in interpreter when trying to work with schema that doesn't exist |
#17643 | Interpreter should show current query when there's an error |
#17653 | Accept CONSTRAINT_INDEX_ as a possible system index name prefix in H2 |
#17661 | DatePart Javadoc should clarify that @Support doesn't mean the DatePart is supported on all functions |
#17667 | Inaccurate Javadoc on ExecuteContext setters |
#17673 | Misleading warning about configured schemas in code generator, when the database doesn't supply any schemata |
#17678 | Add more context information to "Ambiguous key name" warning in code generator |
#17682 | Compilation error in generated many-to-many paths when turning off <implicitJoinPathsToOne/> |
#17690 | Excess whitespace rendered in DROP SEQUENCE |
#17693 | Diff should ignore irrelevant CAST on literals in certain contexts |
#17698 | Diff between interpreted Meta and MetaImpl produces unnecessary ALTER INDEX .. RENAME statements |
#17705 | Diff reports unnecessary ALTER SEQUENCE .. START WITH 1 statement between interpreted sequence and MetaImpl sequence |
#17709 | Wrong SQL syntax generated for empty inserts of fetched records without any touched values |
#17715 | KotlinGenerator doesn't respect visibility modifier configuration for companion object and its contents |
#17718 | Null-encoding converter doesn't work with PostgreSQL nested records |
#17721 | ORA-01790 when inserting CLOBs with mixture of null and non-null values into a table with auditing active |
#17726 | Map CLOB type to STRING in DuckDB |
#17728 | Regression when using expressions in ORDER BY clauses of MULTISET subqueries in PostgreSQL |
#17735 | Parser expects unsigned integer for sequence flags |
#17738 | Diff reports unnecessary ALTER SEQUENCE .. INCREMENT BY 1 MINVALUE .. MAXVALUE .. statements between interpreted sequence and HSQLDB MetaImpl sequence |
#17746 | <globalObjectNames/> should not generate empty classes |
#17748 | Wrong Javadoc in <globalObjectNames/> generated classes |
#17749 | INSERT .. RETURNING TableRecords attached to wrong Configuration when AbstractDMLQuery::emulateOracleReturning is true |
#17753 | Code generator produces wrong ordering of DataType properties for nullable and defaulted array types |
Version 3.19.15 - November 4, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Features and Improvements
#17471 | Add <description/> to all pom.xml files |
Bug Fixes
#17467 | IndexOutOfBoundsException when calling PostgreSQL table valued function returning empty result, with <tableValuedFunction/> turned off |
#17478 | Bad code generated when activating <springDao/> but not <springAnnotations/> |
#17484 | Parser should support SQL Server's NTEXT type and parse it into NCLOB |
#17490 | Invalid constraint type "n" in jOOQ-meta query on PostgreSQL 17 when trying to fetch pg_get_constraintdef for a NOT NULL constraint on a domain |
#17499 | GenerationTool should be more clear about commercial dependencies, when lookups don't work |
#17509 | ORA-00904: invalid identifier when trying to insert into tables with lower case identifier in Oracle |
#17519 | NullPointerException when using AutoConverter with a custom ConverterProvider |
#17522 | Suppressed NoSuchElementException from ThreadLocalTransactionProvider.rollback prevents rollback when commit fails |
#17526 | Oracle RETURNING emulation doesn't use configured ConverterProvider from an AutoConverter |
Version 3.19.14 - October 21, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Bug Fixes
#17391 | Javadoc typos on trigger related methods |
#17393 | Generated trigger names aren't escaped |
#17394 | Meta.ddl() includes synonyms or aliases as tables for some dialects |
#17398 | IN-list padding truncates row IN lists to 1000 elements in Oracle pre 23ai |
#17403 | DefaultGeneratorStrategy should guard against path classes receiving the same name as their enclosing class |
#17409 | Wrong XML import in InformationSchemaMetaImpl for trigger table schemas |
#17415 | NUMERIC bind values passed to SQL Server VALUES constructor may lose scale if not explicit DataType is supplied |
#17422 | VALUES types decimal and int cannot be matched when inlining NUMERIC types in CockroachDB |
#17430 | DSLContext::fetchCount for selects with nested records causes DataAccessException |
#17436 | Cannot call Record.reset(Field), Record.original(Field), Record.changed(Field) with embeddable field arguments |
#17442 | ClassCastException during invocation of double-wrapped ConvertedDataType |
#17445 | Wrong field indexes in code generated in record getters and setters for non-replacing embeddables when database reports non-consecutive column ordinals |
#17448 | CREATE TABLE and other DDL statements don't qualify tables in BigQuery |
#17454 | Diff doesn't export COMMENT ON MATERIALIZED VIEW statements correctly |
#17456 | Converter<byte[], U> for binary columns doesn't work from within MULTISET expressions |
Version 3.19.13 - September 26, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Features and Improvements
#17334 | MetaImpl exceptions should indicate table and column if applicable, which caused the exception |
#17377 | Add a link to DSL::coerce from DSL::cast and Field::cast |
Bug Fixes
#17324 | Upgrade Spring dependency from jOOQ-meta-extensions-hibernate to 5.3.39 due to CVE-2024-38808 |
#17327 | Upgrade jOOQ-checker's transitive guava dependency to 32.1.3-jre due to CVE-2023-2976 |
#17330 | R2DBC Connection leak when cancelling pending connection with ConnectionPool |
#17338 | ORA-17068: Invalid arguments in call when calling OracleDatabaseMetaData.getIndexInfo() with quoted object names |
#17345 | MetaImpl and code generator should ignore MySQL's dummy REMARKS column on DatabaseMetaData::getTables for views |
#17350 | Meta::ddl re-ordering logic cannot parse views from MetaImpl in certain dialects |
#17356 | Regression when generating DDL from certain generated views |
#17360 | DDL::applyAsPlainSQL should trim plain SQL string to check if it starts with CREATE |
#17366 | UserImpl::$replace produces a RoleImpl instance |
#17371 | Oracle PL/SQL %ROWTYPE references should be declared as such in anonymous blocks when calling procedures |
Version 3.19.12 - September 23, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Features and Improvements
#17101 | Add DataType.isTimestampWithTimeZone() for INSTANT and OFFSETDATETIME and isTimeWithTimeZone() for OffsetTime |
#17209 | Revert deprecation of serialization support |
#17248 | Log warnings when Java record constructor has more than 254 parameters |
#17275 | Add Converter.fromSupported() and Converter.toSupported() default methods |
#17295 | Document the fact that org.jooq.Binding does not necessarily have to implement a complete org.jooq.Converter |
#17302 | Add new DataType.isDecimal() method to check if DataType.isNumeric() and it has a decimal representation |
Bug Fixes
#17049 | Upgrade pgjdbc dependency to 42.7.3 to mitigate CVE-2024-1597 |
#17064 | Update DataType.isXYZ() Javadoc with new types |
#17071 | TIME(0), LOCALTIME(0), OFFSETDATETIME(0), and INSTANT(0) don't work in DDL statements as the datetime precision is simply omitted |
#17076 | Redundant unique index on primary key makes foreign keys disappear in PostgreSQL |
#17084 | HANA's WITH ORDINALITY emulation doesn't maintain correct ordering of ORDINALITY |
#17091 | Fix R2DBC support for TIMESTAMP WITH TIME ZONE types |
#17096 | Fix support for special float values NaN, Infinity in MULTISET usage |
#17108 | Implicit path correlation produces correlation predicate in ON clause rather than WHERE clause in some cases |
#17109 | Invalid SQL generated for INSERT .. ON DUPLICATE KEY IGNORE or ON DUPLICATE KEY UPDATE emulations using MERGE |
#17114 | KotlinGenerator contains incomplete list of Kotlin forbidden identifier characters |
#17118 | Bad code generated for enum values containing backslash character |
#17121 | CASE expression on BOOLEAN type emulation in JSON constructor causes ORA-40590: invalid format on Oracle XE 18 |
#17127 | MySQL boolean type information isn't maintained across expressions when embedded into JSON |
#17136 | <unsignedTypes/> flag doesn't work outside of MySQLDatabase |
#17151 | Join paths don't work when embeddable keys or domains on keys are present |
#17160 | Meta::ddl produces incorrect DDL for SQLite, when there are FOREIGN KEY constraints |
#17166 | Using embedded domains with POJO generation results in duplicate getters |
#17172 | Overload resolution ambiguity in KotlinGenerator generated code for embeddable domains |
#17191 | Multiset Result and Records are attached to derived configuration, not original one |
#17197 | ScalaGenerator produces wrong code when generated interfaces (traits) extend multiple other interfaces |
#17204 | IllegalAccessException when creating DSL.table(R...) from list of Kotlin generated TableRecords |
#17213 | NPE while reading timestamp data type value for SAP SQL Anywhere 17 with jconn4 |
#17217 | Error in SybaseDatabase when generating code for routines |
#17228 | Missing Support and NotNull annotations in ConstraintForeignKeyReferencesStepN |
#17237 | Improve error message in GeneratorWriter when brackets mismatch, including the offending file |
#17253 | Error when generating code for DuckDB user defined types from non-main schema |
#17256 | Parser should accept qualified field references in MERGE .. INSERT statement |
#17260 | Meta::filterCatalogs is applied too late for internal MetaImpl queries executed by Meta::ddl |
#17264 | NullPointerException in MetaImpl::lookupTable when Schema isn't available for lookup of cross-schema foreign keys |
#17267 | Exception when accessing MetaImpl::ddl with a user that lacks privileges to access certain databasese in SQL Server |
#17277 | TableRecord null value has its changed flag reset despite a Converter encoding the null value as a non-null value |
#17281 | Work around DERBY-7170 when fetching sources for tables in MetaImpl or DerbyDatabase |
#17285 | Cannot parse default expression in Derby using MetaImpl when computed column is reported as DEFAULT |
#17289 | NullPointerException in MetaImpl.getUniqueKeys() query when unique key cannot look up column references due to missing privileges |
#17299 | SQLite's binding of BigDecimal through PreparedStatement.setString() doesn't work for predicates |
#17305 | Records.mapping() implementations should handle null records |
#17312 | JPADatabase should throw Hibernate's exceptions when there is anything going wrong with the SchemaExport |
#17316 | Upgrade jOOQ-checker's protobuf-java transitive dependency due to CVE-2024-7254 |
Version 3.19.11 - August 13, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Features and Improvements
#16885 | Improve DataTypeException error message when encountering internal UnknownType |
#16919 | Clarify in manual and Javadoc that NoXYZ QueryParts are to be used only with the DSL API, not with the QOM API |
Bug Fixes
#16838 | Wrong DuckDB binary literals generated when inlining bind values |
#16846 | Correctly implement numerous Oracle specific ST_Geometry spatial functions |
#16851 | jOOQ-codegen-gradle 3.19.10 assumes presence of a "main" source set, which isn't always the case |
#16855 | MySQL error "BLOB, TEXT, GEOMETRY or JSON column can't have a default value" when running DDL from generated code |
#16858 | SQLite's MetaImpl can't distinguish between multiple unnamed UNIQUE constraints |
#16864 | Avoid static members in jOOQ-meta Definition classes to avoid stale build caching |
#16870 | Cannot generate DuckDB code due to wrong qualification of system.main objects |
#16879 | Wrong cast syntax used for BigQuery ARRAY types |
#16883 | BigQuery DELETE statements contain unnecessary AND TRUE clause in WHERE clause |
#16893 | Invalid link in Fields javadoc |
#16897 | TIMESTAMP(0) doens't work in DDL statements as the datetime precision is simply omitted |
#16903 | Wrong replacement output when emulating data change delta tables in CockroachDB |
#16913 | Wrong syntax rendered for SQL Server UNION queries with LIMIT in their subqueries |
#16923 | Invalid SQL generated when UNION subselects contain ORDER BY |
#16929 | Wrong SQL generated in SQL Server when using UNION .. LIMIT without OFFSET |
#16935 | SQL Server MULTISET subquery ORDER BY clause doesn't work with UNION |
#16939 | Work around SQL Server's peculiar UNION with ORDER BY .. OFFSET .. FETCH implementation in derived tables |
#16943 | Bad OFFSET emulation in UNION queries when OFFSET contains an expression |
#16947 | Wrong emulation of DISTINCT ON with UNION |
#16950 | Wrong combination of emulations: DISTINCT ON with UNION and LIMIT with expressions |
#16955 | Empty window definition in WINDOW clause isn't emulated correctly in SQLDialect.ORACLE18C |
#16958 | Wrong WITH TIES emulation when combined with QUALIFY if QUALIFY is supported natively |
#16964 | Remove TERADATA support for CREATE MATERIALIZED VIEW |
#16966 | org.jooq.impl.Alias not Serializable, due to Lambda wrapInParantheses |
#16969 | Force inline bind values after 2536 in Teradata |
#16989 | Correctly name Apache-2.0 everywhere |
#17000 | Code generation order provider isn't being applied to TableDefinition.getXYZ() methods |
#17006 | Error when trying to delay DataType inference for scalar SQL type converted to user array type |
#17010 | SQLite unnamed unique constraints are listed in a non-deterministic order by code generator |
#17014 | Exception when doing Meta.ddl() export with tables that have USE or GO or similar field or table aliases |
#17022 | Row[N].in(Row[N]...), Row[N].between(...), and Row[N].is[Not]DistinctFrom(...) should apply data type bindings if necessary |
#17027 | Repeated WHERE FALSE clause in CREATE TABLE AS SELECT .. WITH NO DATA emulation, when query is nested |
#17031 | JDBCUtils.dialect() detects wrong MySQL dialect for versions > 8.1 |
#17041 | SQLDialect.JAVA warning message about derived tables not being supported is misleading |
#17044 | jOOQ-codegen-gradle plugin doesn't work with Gradle's configuration cache feature |
Version 3.19.10 - June 14, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Features and Improvements
#16806 | Clarify EmbeddableRecord Javadoc |
#16820 | Allow for specifying inputs to the gradle CodegenTask in order to participate in incremental builds |
#16828 | Add Source.resolve(String) to allow for varied, string based input sources |
#16829 | The code generation initScript property should be able to read from the file system |
Bug Fixes
#16735 | Redundant policy related logic in UpdateQueryImpl |
#16740 | Internal SelectQueryImpl::copy behaviour may produce inconsistent copy of WINDOW clause |
#16746 | Wrong SQL rendered for MS Access CONCAT function with more than 2 arguments |
#16756 | Work around BigQuery's SELECT without FROM clause cannot use aggregation limitation |
#16763 | Parser meta lookup fails for DUAL table |
#16770 | Work around BigQuery ORDER BY clause limitation where identifiers cannot be resolved if the table and the column share the same name |
#16774 | Work around BigQuery limitation of using: HAVING clause on a non-aggregate query |
#16778 | Support BigQuery's QUALIFY .. WINDOW keyword order |
#16787 | Fix null treatment syntax of window functions in BigQuery |
#16793 | Inconsistent formatting of HSQLDB DUAL table emulation |
#16798 | Parser error when trying to parse hypothetical set function with FILTER clause |
#16811 | MULTISET nested projection's ContextConverters don't receive correct ConverterContext |
#16822 | Don't delay jOOQ-codegen-gradle's configuration until execution by default |
Version 3.19.9 - May 30, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Bug Fixes
#16647 | BlobBinding and ClobBinding should fall back to byte[] and String binding also in HANA |
#16652 | TableRecords should refresh() themselves for HANA dialect, when any non-identity value should be fetched after an insert |
#16657 | Improve warning log message about static type registry usage and how to remedy it |
#16663 | Wrong source code generated when newline escape sequence of long view source is split into two |
#16672 | Update using multi-column set clause with DSL.row and custom type logs warn on deprecated static type registry |
#16676 | SQLite "Cannot parse or interpret sql for table" error with both unique columns and foreign key constraints |
#16687 | Error in CockroachDBDatabase when running SHOW INDEXES for table valued function |
#16692 | Work around KT-68407 compiler error in generated AbstractSpringDAOImpl class in kotlin 2.0 |
#16697 | Memory leak in DefaultCacheProvider when large amounts of arbitrary projections are mapped with DefaultRecordMapper |
#16703 | Settings.transformPatternsUnnecessaryScalarSubquery produces wrong SQL when subquery column is aliased |
#16706 | Pattern replacement activates RETURNING clause of DELETE / UPDATE statements |
#16709 | Settings.transformPatternsUnnecessaryScalarSubquery produces wrong SQL when subquery column is an embeddable |
#16722 | Confusing error message when reading a non-existing Field from a Record containing accidentally nested row types |
#16726 | Avoid operator associativity rendering logic if operator isn't nested |
Version 3.19.8 - May 2, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Bug Fixes
#16548 | Auto wrap Field arguments to a Routine's Object typed parameter in Field<Object> |
#16553 | Work around lack of support for INSERT .. SELECT .. UNION [ ALL ] SELECT in SingleStore |
#16572 | DELETE .. ORDER BY .. LIMIT on partitioned tables without unique constraint uses non-unique ctid for self joins |
#16575 | Cannot configure matchers using jOOQ-codegen-gradle plugin |
#16577 | SAXParseException warnings when using jOOQ-codegen-gradle or any other MiniJAXB.unmarshal() usage |
#16582 | Time zone information lost when fetching TIMETZ[] value in PostgreSQL |
#16586 | Work around HSQLDB bug where wrong LocalTime value is fetched when using bind values of type LocalTime[] |
#16603 | Wrong cast type name when casting value to NCLOB in Firebird |
#16617 | Fix order of NOT NULL and DEFAULT clauses in BigQuery CREATE TABLE statements |
Version 3.19.7 - April 4, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Features and Improvements
#16437 | Document DSL.jsonGetElement() index being 0 based |
Bug Fixes
#16428 | DefaultDataType.getDataType logger should add more details about how to fix the problem |
#16429 | Row[N].eq(Row[N]) should apply data type bindings if necessary |
#16430 | Unnecessary static type registry warning when inlining custom converted enum value |
#16431 | Static type registry deprecation warning shouldn't appear when using the INSERT valuesOfRows() clause with converted data types |
#16440 | QuantifiedSelect wrapping array doesn't correctly convert array component types |
#16453 | Fix other cases where org.jooq.impl.Val uses "inferred data type," but cannot actually lazily infer the type |
#16457 | ParsingConnection should not rely on org.jooq.impl.Val identity to match user bind value indexes with rendered indexes |
#16462 | SEEK doesn't work correctly when there are multiple noField() arguments and ORDER BY is uniform and Settings.renderRowConditionForSeekClause is true |
#16471 | Work around CockroachDB's lack of support for the POWER() function accepting integer arguments |
#16474 | jOOQ parser parses indexed parameters as named |
#16480 | SQL Server's CREATE cannot fully qualify a sequence name |
#16495 | Intercept SQLFeatureNotSupportedException caused by DatabaseMetaData::getImportedKeys and other calls |
#16504 | Improve compilation speeds of generated QOM types |
#16511 | Avoid PostgreSQL empty array cast when explicit cast is given |
#16536 | Parser fails to parse TIME[STAMP] WITH TIME ZONE literals |
#16540 | Incorrect conversion of LocalDateTime to LocalDate during daylight saving time |
Version 3.19.6 - March 8, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Bug Fixes
#16348 | Parser fails with StringIndexOutOfBoundsException when encountering invalid PostgreSQL unicode literal |
#16351 | Parser shouldn't fail with NumberFormatException |
#16357 | ParsingConnection doesn't correctly execute batches when using ParamType.INLINED or StatementType.STATIC_STATEMENT |
#16364 | UUID bind values should be auto-cast to avoid issues with lack of auto-conversion support in PostgreSQL |
#16371 | Parser always parses NULL literal of type BOOLEAN |
#16374 | Cast NULL literal in subquery SELECT projection in PostgreSQL |
#16382 | DataType should cache null_() and notNull() variants |
#16386 | Add some WARN logs when synthetic key objects aren't matched |
#16389 | Add arity check to synthetic foreign key configuration to avoid wrong generated code when FK / UK columns mismatch |
#16394 | Empty derived column lists generate wrong SQL syntax |
#16397 | Regression in fetchCount execution when argument query uses plain SQL tables |
#16400 | jOOQ-codegen-gradle should lazily evaluate its configuration |
#16406 | Parser doesn't support GROUPING SETS with <ordinary grouping set> specification |
#16411 | Code generator and MetaImpl return CREATE DEFAULT statement instead of just the default expression |
Version 3.19.5 - February 27, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Bug Fixes
#16317 | Regression: Gradle plugin thinks it's up to date when it's not |
#16320 | Wrong SQL generated when nesting predicates on subqueries projecting embeddables within MULTISET |
#16323 | SelectIsNull renders invalid SQL when SELECT projection is embeddable |
#16327 | DSLContext.fetchCount(Select) produces wrong SQL when query projects embeddables |
#16337 | NumberFormatException in parser when encountering double value with implicit 0 exponent |
#16341 | DefaultRenderContext::peekIndex doesn't contain correct bind index |
Version 3.19.4 - February 20, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Features and Improvements
#16122 | Add Context.scopeParts(Class<Q>): Iterable<Q> to allow for iterating over the values that are currently in scope |
Bug Fixes
#16115 | jOOQ-codegen-gradle fails with UnknownDomainObjectException when java plugin isn't applied first |
#16116 | Generated implicit join alias collision when child table foreign keys share the same name |
#16124 | RenderTable.WHEN_AMBIGUOUS_COLUMNS doesn't cover all ambiguous column name cases |
#16126 | RenderTable.WHEN_MULTIPLE_TABLES doesn't work correctly in correlated subqueries |
#16129 | Maximum consumed results reached when Hikari close a SQL Server connection, leading to excessive logging |
#16134 | jOOQ-codegen-gradle doesn't consider basedir property for its OutputDirectory |
#16181 | %ROWTYPE UDT types generate invalid system columns when underlying table references object types |
#16185 | Settings.returnDefaultOnUpdatableRecord and Settings.returnComputedOnUpdatableRecord don't work for replacing embeddables |
#16196 | Overall performance improvement in AbstractNamed.hashCode() specialisations by avoiding Name::append |
#16204 | Remove internal AbstractContext::toggle utilities |
#16210 | AbstractScope::dsl, ::settings, ::dialect, and ::family should avoid unnecessary null-checks on Configuration |
#16223 | BatchCRUD implementation should extract bind values with SQL string in one go |
#16230 | Emulate LIMIT 0 where not supported |
#16233 | Wrong Support annotation on CREATE TRIGGER for INFORMIX |
#16238 | IndexOutOfBoundsException in DerbyDatabase when <includeExcludeColumns/> excludes a column from an index |
#16247 | Avoid allocating DataMap in short lived Scope implementations |
#16250 | Cache TableRecord Constructor in TableImpl for use in Tools.recordFactory() |
#16256 | JavaGenerator doesn't generate serialVersionUID in Path classes |
#16259 | Avoid allocating Collections.nCopies in ScopeStack |
#16263 | Avoid allocating JoinNode in scope registration of tables if unnecessary |
#16267 | Avoid constructing DSL.name() for constant internal names |
#16271 | Refactor QualifiedName to improve performance |
#16276 | name(null, "") should equal to name("") |
#16280 | Result::formatXML should omit type attribute on columns whose type is unknown |
#16284 | Meta::ddl generates incorrect queries for SQL Server (max) lengths |
#16294 | Remove unnecessary up-to-date prevention in jOOQ-codegen-gradle plugin |
#16295 | Wrong SQL generated for CREATE TABLE in non-default schemas for DuckDB |
#16298 | MULTISET equality is ORDER dependent in dialects without support for correlated derived tables |
#16303 | Can't parse MySQL ALTER TABLE .. DROP .., DROP .. syntax |
Version 3.19.3 - January 19, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Breaking changes
#16085 | Wrong order of MiniJAXB.append() calls in jOOQ-codegen-gradle |
Bug Fixes
#16076 | Compilation error in ScalaGenerator generated code of generated DAOs when using scalac 3 |
#16079 | Remove unnecessary runtimeClasspath dependency of the jOOQ-codegen-gradle plugin |
#16082 | Syntax error in generated SQL of ALTER INDEX or ALTER SCHEMA statement, when identifiers aren't quoted |
#16086 | jOOQ-gradle-plugin multi execution configuration shouldn't require an explicit default configuration |
#16095 | Compilation error in ScalaGenerator generated Keys.scala class when using GeneratorStrategy |
#16106 | Wrong Javadoc in RTRIM() and LTRIM() |
Version 3.19.2 - January 12, 2024
This is a 3.19 patch release with minor improvements and bug fixes
Features and Improvements
#16023 | Add Javadoc to discourage using any Fields.field(x, Class<T>) method if there's an Fields.field(x, DataType<T>) overload, as well as inline(T), value(T), and val(T) |
#16032 | SQLPerformanceWarning should log hint about gathering dictionary statistics in OracleDatabase |
#16045 | org.jooq.tools.Convert should delegate to org.jooq.impl.Convert, instead of duplicating implementations |
Breaking changes
#16058 | Remove mandatory dependency from compileJava to jOOQ-codegen-gradle tasks |
Bug Fixes
#15976 | Wrong statement generated for MySQL when leading unqualified asterisk is used with plain SQL template table |
#15983 | Comparison predicates and quantified comparison predicates should hint array type to org.jooq.impl.Array for empty expression array casts |
#15985 | Regression in PostgreSQL query using 'x' = ANY (ARRAY [(SELECT ARRAY ['x'])]) style quantified comparison predicate on multi dimensional arrays |
#15994 | RenderTable.WHEN_MULTIPLE_TABLES only works with table lists, not with joins |
#16004 | Misleading XSD warnings logged when working with MiniJAXB |
#16010 | Code generator fails when generating triggers because TriggerExecution value is null |
#16014 | Compilation error in KotlinGenerator generated code when GeneratorStrategy produces identifiers conflicting with property access syntax of AbstractRoutine getters |
#16026 | Cannot project TableAsField if table contains embeddables in PostgreSQL |
#16030 | Regression: NullPointerException in KotlinGenerator generated code when InlineDerivedTable constructor calls TableImpl.where(null) |
#16038 | ScalaGenerator produces duplicate paths for cyclic foreign key relationships |
#16040 | Compilation error in JavaGenerator generated code when <pojosAsJavaRecordClasses> is active and a table references a UDT |
#16049 | DATE column in Oracle is null when fetched through multiset |
#16057 | Cannot look up tasks.named("jooqCodegen") from gradle scripts |
#16060 | MetaSQL lookups are done with SQLDialect.family(), not SQLDialect |
#16063 | Regression: Table metadata calculation for Oracle does not work after 3.19.0 |
#16066 | Add Javadoc to all XJC-generated "withers" and setters of boolean types |
Version 3.19.1 - December 20, 2023
This is a 3.19 patch release with minor improvements and bug fixes
Bug Fixes
#15945 | jOOQ-codegen-gradle should resolve relative directories with respect to the gradle project, not the running process |
#15947 | KeepNamesGeneratorStrategy generates ambiguous path names if implicitJoinPathTableSubtypes is activated |
#15948 | Compilation error in KotlinGenerator generated code with KeepNamesGeneratorStrategy and generated implicit join paths |
#15954 | SQLite requires parenthesised DEFAULT expressions in DDL |
#15959 | YugabyteDB doesn't support ALTER TABLE .. DROP CONSTRAINT IF EXISTS |
#15971 | Implicit path correlation shouldn't generate correlation predicate if correlation isn't in scope |
#15973 | Regression in LiquibaseDatabase when omitting the database.liquibaseSchemaName value |
Version 3.19.0 - December 15, 2023
New dialects
It's been a few releases since we've added support for new dialects, but finally some very interesting RDBMS of increasing popularity have joined the jOOQ family including:
- DuckDB (experimental support)
- Trino
These dialects are available in all jOOQ editions.
New dialect versions
In addition to these entirely new dialects, big new CockroachDB and Oracle versions have shipped:
- CockroachDB 23
- Oracle 23c
We've added support for many new Oracle features, including:
- Domains
- UPDATE .. FROM
- IF [ NOT ] EXISTS
- Table value constructor
- SELECT without FROM
As well as CockroachDB features, including:
- Triggers
- Stored functions
- UDTs
- Materialized views
- LATERAL
- New native DML clauses
- NULLS FIRST and NULLS LAST
Join path improvements
Implicit to-one path joins have been with jOOQ since version 3.11. Now, we've greatly improved this very useful feature by adding support for:
- Explicit path joins, allowing for more fine grained control of the path join type: https://www.jooq.org/doc/3.19/manual/sql-building/sql-statements/select-statement/explicit-path-join/
- To-many path joins, including many-to-many paths for implicit and explicit joins going from parent to children: https://www.jooq.org/doc/3.19/manual/sql-building/sql-statements/select-statement/implicit-to-many-join/
- Implicit path correlation, allowing to greatly simplify correlated subqueries, including the powerful MULTISET correlated subqueries: https://www.jooq.org/doc/3.19/manual/sql-building/sql-statements/select-statement/implicit-path-correlation/
- Join elimination, allowing to skip unnecessary path segments of a join path
This is best shown by example:
// Before 3.19: ctx.select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME) .from(ACTOR) .where(exists( selectOne() .from(FILM_ACTOR) .where(FILM_ACTOR.ACTOR_ID.eq(ACTOR.ACTOR_ID)) .and(FILM_ACTOR.film().TITLE.like("A%")) )) .fetch(); // After 3.19: ctx.select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME) .from(ACTOR) .where(exists( selectOne() .from(ACTOR.film()) .where(ACTOR.film().TITLE.like("A%")) )) .fetch();
This feature is available in all jOOQ editions.
Gradle plugin
One of the longest awaited features is an official jooq-codegen-gradle plugin, that offers a tight integration with gradle's task system while being released in the same release cadence as jOOQ itself.
Our new gradle plugin supports all of the code generation features in both an idiomatic groovy or kotlin DSL
More information here: https://www.jooq.org/doc/3.19/manual/code-generation/codegen-gradle/
This feature is available in all jOOQ editions.
Commercial maven repository
A feature that many of our paying customers have wanted for a long time has finally been implemented: our commercial maven repository at https://repo.jooq.org, where all historic and new commercial only jOOQ artifacts as well as snapshot versions will be hosted, in addition to our ZIP file download website: https://www.jooq.org/download/versions
This feature is available only in commercial jOOQ editions.
Policies
Similar to PostgreSQL's powerful POLICY feature, or Oracle's Virtual Private Database, jOOQ 3.19 allows for declaring policies that act as automatic filters on some of your tables, to allow for a simple and thorough row level security implementation.
For example, with a policy on the multi tenancy capable CUSTOMER table, a query like this:
ctx.select(CUSTOMER.ID, CUSTOMER.NAME) .from(CUSTOMER) .fetch();
Might in fact run a SQL statement like this, instead:
SELECT CUSTOMER.ID, CUSTOMER.NAME FROM CUSTOMER WHERE CUSTOMER.TENANT_ID = 42
Not just queries, but all DML statements are rewritten to disallow any inaccessible data from being written / read.
More information here: https://www.jooq.org/doc/3.19/manual/sql-building/queryparts/policies/
This feature is available only in commercial jOOQ editions.
UDT paths
In addition to adding User Defined Type (UDT) support to CockroachDB and Informix, we've improved our code generator support for UDTs in a way for attribute paths to be made accessible to client code in a type safe way.
So, with types like these:
CREATE TYPE country AS ( iso_code TEXT ); CREATE TYPE name AS ( first_name TEXT, last_name TEXT ); CREATE TYPE address AS ( street TEXT, ..., country COUNTRY ); CREATE TABLE customer ( id INT PRIMARY KEY, name NAME, address ADDRESS );
You can now destructure the UDTs directly in your SQL query like this:
ctx.select( CUSTOMER.NAME.FIRST_NAME, CUSTOMER.NAME.LAST_NAME, CUSTOMER.ADDRESS.COUNTRY.ISO_CODE) .from(CUSTOMER) .fetchOne();
More information here: https://www.jooq.org/doc/3.19/manual/sql-building/column-expressions/user-defined-type-attribute-paths/
This feature is available in all jOOQ editions.
Trigger meta data
The code generator can now reverse engineer trigger meta data from most RDBMS that support triggers. This meta data can be helpful at runtime, e.g. to render improved RETURNING support in the absence of triggers, in dialects where triggers require special emulations (e.g. SQLite or SQL Server).
This feature is available only in commercial jOOQ editions.
Hierarchies
A new Collector has been added to recursively collect a flat representation of hierarchical data into an object hierarchy. This plays very well with our MULTISET nested collection support.
For more details, see this blog post: https://blog.jooq.org/how-to-turn-a-list-of-flat-elements-into-a-hierarchy-in-java-sql-or-jooq/
This feature is available in all jOOQ editions.
Java 8 support removed from jOOQ Express and Professional Editions
Like other leading platforms, we're moving on to help with the adoption of newer JDK versions. Our Java 8 support will be discontinued for the jOOQ Express Edition and jOOQ Professional Edition. If you require Java 8 support, you can upgrade to the jOOQ Enterprise Edition, which will continue supporting Java 8 for another few minor releases, or stay on jOOQ 3.18, which will also receive bug fixes for another while.
This change affects only commercial jOOQ editions.
For a complete list other, minor improvements, see the below change notes.
Features and Improvements
#228 | Enhance API to provide access to UDT members |
#2356 | Support PostgreSQL multi table TRUNCATE statement |
#2536 | DAO should copy the inserted identity value back to the POJO on DAO.insert(P) |
#2682 | Add org.jooq.Policy, to support shared-schema multi-tenancy and row level security |
#3751 | Support UDT object names in MatcherStrategy |
#3862 | Improve Javadoc on DSLContext.executeInsert(), executeUpdate(), and executeDelete() about optimistic locking not applying |
#4092 | Add a section to the manual showing how to bind LOBs via org.jooq.Binding |
#5210 | Add code generation option to generate string constants for all object names |
#6028 | Add JSONFormat.NullFormat to offer different NULL encoding options |
#6182 | Support renaming Keys and Indexes with matcher strategy |
#6542 | Add some gifs to the README.md on Github, also for examples |
#6587 | Add InsertQuery.setRecordForUpdate(Record) |
#8012 | Override Table.where(Condition) methods in generated tables |
#8474 | Add support for CREATE TYPE AS <member list> |
#8617 | Add org.jooq.Generated annotation with RUNTIME retention for generated code |
#9483 | Add support for { CREATE | ALTER | DROP } MATERIALIZED VIEW |
#9635 | Add DSL.noTable() for optional, dynamic joins |
#9906 | Offer a public Maven repository for commercial distributions |
#10096 | LiquibaseDatabase should create database.liquibaseSchemaName, if configured |
#10504 | Update manual to show also Gradle/Kotlin configuration examples |
#11248 | Add Trigger runtime meta model |
#11251 | Add emulation support for IF [ NOT ] EXISTS to MySQL for DDL on INDEX and VIEW objects |
#11263 | Add KeyColumnUsage.positionInUniqueConstraint to the InformationSchema for use with XMLDatabase |
#11485 | Support for Trino DB |
#11584 | Add parser support for SQL Server CREATE TYPE and DROP TYPE |
#11944 | Add Firebird 4.0 native support for DELETE .. ORDER BY and UPDATE .. ORDER BY |
#12052 | Add experimental DuckDB support |
#12083 | Work around missing support for REMARKS on DatabaseMetaData.getColumns() |
#12270 | Add Javadoc hints about Record.changed() values to InsertValuesStep[N].valuesOfRecords(...) |
#12341 | Add a Records::intoHierarchy Collector to turn Result into tree representations |
#12493 | Support INSERTING, UPDATING, DELETING in PostgreSQL via TG_OP |
#12747 | Add support for Informix UDTs |
#12985 | Create an official jooq-codegen-gradle plugin |
#13065 | Document the InlineDerivedTable feature |
#13295 | Allow for specifying both <name> and <binding> / <converter> in <forcedType> |
#13301 | Allow kotlin pojos to not have defaulted constructor parameters |
#13639 | Add support for to-many path expressions |
#13786 | Parser should support TIMESTAMP 'YYYY-MM-DD' and TIME 'HH:MM' literals |
#13912 | Simplify SQL Server's RETURNING emulation in the absence of triggers |
#13947 | Support CockroachDB 23 user defined functions |
#14011 | Add SQLDialect.ORACLE23C |
#14429 | Builds should log their build date with the logo |
#14551 | Add more startup tips to be logged with the jOOQ logo |
#14614 | Implicit JOIN improvements |
#14756 | Continue work on public query object model API |
#14777 | Add <E, R : Record1<E>>ResultQuery<R>.fetchValue(): E? extension method to kotlin |
#14790 | Add DataType.isUUID() |
#14799 | Add support for TRY_CAST() |
#14800 | Error when PostgreSQL anonymous block contains dollar quoted string token |
#14803 | BlobBinding and ClobBinding should fall back to byte[] and String binding if unavailable |
#14808 | Add more documentation after 3.18 release |
#14814 | Split Aliased tables section of the manual into subsections |
#14818 | Add a remark on the Converter Javadoc that implementations must be able to handle NULL |
#14840 | Apply Settings.batchSize also to other batch API |
#14876 | Add warnings to manual and Javadoc about ON KEY ambiguity caveats |
#14895 | Add Javadoc to DAO::insert and DAO::update regarding Settings.returnRecordToPojo |
#14914 | Add DSL.domain(Name, DataType<T>) and overloads |
#14932 | Add a jooq.codegen.propertyOverride system property to GenerationTool |
#14933 | Add the missing DSLContext.fetchValue(TableField, Condition) and other overloads |
#14934 | Upgrade liquibase-core to 4.21.0 |
#14953 | Add Javadoc hints about implementation of JSONB::toString, JSONB::hashCode, and JSONB::equals |
#14967 | Reactive batch implementations should throw UnsupportedOperationException with a message |
#14975 | Upgrade Jackson to 2.15.0 |
#14985 | Allow for specifying explicit path joins |
#14988 | Emulate LATERAL (TableImpl | JoinTable) where not supported |
#14992 | Join elimination for implicit join paths |
#14993 | Add a new <matchers/> subelement <foreignKeys/> |
#14998 | Add code generation flag <implicitJoinPathUnusedConstructors/> to offer an option to stop generating unused implicit join path constructors |
#15002 | Add native support for NULLS FIRST and NULLS LAST in CockroachDB 23 |
#15003 | Add SQLDialect.COCKROACHDB_23 |
#15006 | Support Oracle 23c's new 64k IN list limit |
#15023 | Add a section to the manual about SQL translation |
#15024 | Improve Javadoc of lookupLiteral() for generated enums |
#15025 | Generate annotations on generated EnumType::getLiteral method, if so configured |
#15050 | Add support for generic org.jooq.log.<logger>=threshold system properties |
#15051 | Add JooqLogger.isErrorEnabled() |
#15060 | Add DataType.isOther() |
#15065 | Upgrade maven plugins |
#15070 | MiniJAXB should support reading simple elements as attributes |
#15072 | Add error message to maven-install.sh which doesn't work with Maven 3.9.0 due to MNG-7679 |
#15075 | maven-install and maven-deploy shell scripts should use -e flag to report more error info |
#15093 | Add API support for ( UNION | INTERSECT | EXCEPT ) DISTINCT |
#15103 | Add DSLContext.transactionCoroutine overload accepting CoroutineContext |
#15117 | Recognise :yugabytedb: JDBC URLs in JDBCUtils |
#15126 | Add SQLDialect.SQLITE_3_40 |
#15142 | Support parsing T-SQL's named DEFAULT constraints in CREATE TABLE |
#15143 | Add native support for CockroachDB 23 DELETE .. USING clause |
#15144 | Add native support for DELETE .. LIMIT and DELETE .. ORDER BY in CockroachDB |
#15145 | Add runtime support for CockroachDB 23 UDTs |
#15148 | Add CockroachDB support for LATERAL |
#15156 | Add Context.inScope(QueryPart): boolean |
#15160 | Add parser support for Teradata specific analytic functions |
#15171 | Upgrade various dependencies |
#15181 | Remove manual section about interning |
#15186 | Add a section about operator precedence to the manual |
#15188 | SelectQueryImpl::toSQLReferenceLimitWithWindowFunctions should use QUALIFY to emulate WITH TIES where possible |
#15207 | Add a configuration flag to avoid generating DefaultCatalog and DefaultSchema |
#15209 | Support ad-hoc compilation of programmatic GeneratorStrategy objects in the code generator |
#15210 | Add code generation flags to avoid overrides of as() methods or rename() methods |
#15212 | Add <genericConverter/> and <genericBinding/> to allow for passing T and U types to custom Converter and Binding instances |
#15213 | Support ad-hoc compilation of programmatic Generator or Database objects in the code generator |
#15230 | Add support for MySQL DECIMAL/FLOAT/DOUBLE/REAL UNSIGNED types in Meta and code generation |
#15239 | Add Settings.parseMetaViewSource to allow for opting out of parsing view source in MetaImpl |
#15248 | Add documentation about the nullability of kotlin generated properties in the presence of DEFAULT or IDENTITY expressions |
#15249 | Add ExecuteContext.skipUpdateCounts to allow for setting the AbstractContext.skipUpdateCounts flag in an ExecuteListener |
#15258 | Manual section about the QUALIFY clause should reference the QUALIFY transformation section |
#15261 | Add Javadoc to plain SQL DSL.field() constructors recommending to use code generation or at least pass a DataType |
#15275 | Update jakarta.xml.bind:jakarta.xml.bind-api from 3.0.0 to 4.0.0 |
#15276 | Add code generation support for synthetic enums |
#15277 | Add Replacers.transformPatterns(Configuration) public API to give access to the internal Replacer |
#15279 | EnumConverter should support org.jooq.EnumType as U type |
#15281 | Generated code should import user defined types in data type definitions |
#15293 | Various Meta DDL related issues |
#15307 | Emulate CREATE SCHEMA with CREATE USER .. NO AUTHENTICATION in Oracle 18c |
#15315 | Upgrade pgjdbc to 42.6.0 |
#15316 | Add support for SQLite 3.35 RETURNING |
#15323 | Add native support for Db2 XML type in DDL, code generator, etc. |
#15347 | Support single-statement trigger bodies on RDBMS that only support SQL triggers |
#15350 | Add SQLDialect.H2_2_2_220 |
#15351 | Add PostgreSQL support for CREATE TRIGGER and DROP TRIGGER |
#15354 | Emulate REFERENCING clause in CREATE TRIGGER in dialects that don't support it natively |
#15356 | Add Replacers.mappingTable(Function<? super Table<?>, ? extends Table<?>) |
#15357 | Add manual sections for built-in Replacers |
#15372 | Make EACH an optional keyword in FOR EACH ROW / FOR EACH STATEMENT in the parser |
#15400 | Add a jOOQ-meta-kotlin module for kotlin extensions to the jOOQ-meta module |
#15401 | Add extension functions for Settings, InformationSchema, MigrationsType |
#15413 | "Ambiguous match found" warning log should reference qualified field name, if available |
#15419 | Add support for CockroachDB 21 MATERIALIZED VIEWS |
#15442 | Upgrade dependencies |
#15452 | Add parser support for Redshift's DATE_PART_YEAR() function |
#15453 | Manual section about data type conversion should contain an example showing how to attach a converter to a DataType or Field |
#15455 | Add InsertSetStep.set(Collection<? extends Record>) and set(Record...) |
#15464 | Add matcher strategy to name path Table subclasses |
#15465 | Create manual subsections for matcher strategy |
#15468 | INSERT .. ON CONFLICT .. DO NOTHING emulation should use MERGE in Firebird 3, HANA |
#15488 | DefaultRecordMapper should be able to reflectively map multisets into Sets of POJOs |
#15499 | Upgrade jOOR dependency to 0.9.15 |
#15509 | Add a log message whenever an exception occurs with the SQLDialect.DEFAULT |
#15510 | Upgrade scala.version to 2.13.11 |
#15514 | Upgrade Liquibase to 4.23.1 |
#15531 | Meta.ddl() exports broken DDL for materialized views |
#15546 | Add Database.getComments(): Map<Definition, String> |
#15551 | Add runtime UDT mapping |
#15554 | JavaWriter should have a Mode reference |
#15588 | Add support for ALTER TYPE IF EXISTS |
#15591 | Remove unnecessary line breaks in formatted DDL |
#15592 | Add missing Asterisk and QualifiedAsterisk.except(Collection<? extends Field<?>>) overloads |
#15593 | Add support for and emulate CREATE OR REPLACE MATERIALIZED VIEW and other objects |
#15594 | Add CockroachDB support for CREATE VIEW IF NOT EXISTS |
#15607 | Add support for COMMENT ON MATERIALIZED VIEW |
#15608 | Upgrade H2 to 2.2.224 |
#15611 | Add a disclaimer tip to the DAO section |
#15620 | Upgrade third party libraries for JDK 21 build |
#15627 | Add parser support for functions without parameter names |
#15632 | Support InlineDerivedTables in DML |
#15635 | Add a Context::scopePart property |
#15644 | Add Policy::inherited to specify whether child tables should inherit a parent table's policies |
#15657 | Add link to explanation blog article about inline values from manual |
#15682 | Emulate INSERT .. DEFAULT VALUES for dialects where no DEFAULT expression exists for DML |
#15684 | Add support for POSITION() in Informix via INSTR |
#15685 | Emulate DEFAULT expression in multi row INSERT .. VALUES, where that is emulated with INSERT .. SELECT |
#15712 | Add documentation about some client side features not working with plain SQL templating |
#15719 | Remove experimental status of transform patterns and computed columns |
#15731 | Add a section to the manual highlighting the commercial only or experimental features |
#15745 | TableDefinition.getTable() should return better meta data |
#15754 | Add RenderImplicitJoinType.SCALAR_SUBQUERY to allow for configuring the DML implicit join path behaviour also for SELECT |
#15755 | Add Settings.renderImplicitJoinToManyType: RenderImplicitJoinType to govern the implicit to-many join style |
#15783 | Add Javadoc to the Query::bind methods indicating that they bind values in the rendered order, not the input order |
#15807 | Add support for JOIN algorithm hints |
#15808 | Support H2's USE INDEX hint |
#15815 | Add more emulation support for ALTER TABLE .. DROP CONSTRAINT IF EXISTS |
#15822 | Support parsing dynamic intervals in MySQL DATE_ADD() and DATE_SUB() expressions |
#15824 | Add parser support for STRING_AGG() |
#15825 | Support parsing a few Oracle DBMS_LOB functions |
#15835 | Remove workaround for ojdbc bug where JSON_ARRAY() couldn't combine bind parameter marker with FORMAT JSON |
#15843 | Deprecation log warning about <dateAsTimestamp/> should link to relevant manual section |
#15844 | Add support for MD5 in SNOWFLAKE dialect |
#15845 | Upgrade Jackson dependency to 2.16 |
#15847 | Upgrade com.oracle.database.r2dbc:oracle-r2dbc to version 1.2.0 |
#15860 | Get SNOWFLAKE dialect up to date |
#15862 | Remove unnecessary managed JDBC drivers from parent pom.xml |
#15864 | Add support for PostgreSQL DROP TRIGGER .. ON <table name> |
#15897 | Offer Java 8 support only in the jOOQ Enterprise Edition |
#15939 | Add a Don't do This: SELECT DISTINCT section to the manual |
Breaking changes
#13694 | Remove pre 3.8 deprecated API and pre 3.8 documentation |
#14306 | Avoid second ExecuteContext for native implementations of RETURNING |
#15005 | Add org.jooq.Path<R>, a type to model join paths |
#15046 | Let SchemaImpl and TableImpl avoid traversal and replacement recursion |
#15201 | Experimental migrations API changes |
#15303 | Meta.ddl() generates broken DDL for columns of unknown types |
#15394 | Exception thrown inside blocking TransactionPublishable gets wrapped by DataAccessException unlike when thrown from non-blocking TransactionPublishable |
#15476 | Internal DefaultDataType.getDataType(SQLDialect, String) should parse precision and scale and return it |
#15487 | Turn off <recordsImplementingRecordN/> by default |
#15634 | Distinguish between Context::qualify and Context::qualifySchema |
#15872 | QOM.CreateTrigger and related API should work with new org.jooq.Trigger type |
Deprecations
#15196 | Deprecate inconsistent DSL.jsonObject(Field...) and DSL.jsonbObject(Field...) overloads |
#15286 | Add Javadoc to discourage using any m(Class<T>) method if there's an m(DataType<T>) overload |
#15583 | UDTImpl should use Name instead of String in constructor |
Bug Fixes
#7941 | Allow for using EnumType not referencing any Schema to be used in PostgreSQL |
#8283 | BatchCRUD does not update optimistic locking version and timestamp values in UpdatableRecord |
#8439 | PostgreSQL: array(<domain over UUID>) causes exception |
#8930 | Fix known issues of PL/SQL BOOLEAN type in SQL emulation |
#10107 | DDLDatabase throws parse error 'DEFAULT custom_function_name()' |
#10234 | Unable to rename table with qualified target table name |
#11205 | ORA-38104: Columns referenced in the ON Clause cannot be updated |
#11311 | HSQLDB MetaImpl based DataTypes are missing length of array element type |
#11975 | Fix known limitations of embeddable types |
#12098 | Fix known limitations of the QUALIFY SQL transformation |
#12456 | Ambiguous match found when using aliases with implicit join and joining the same table twice |
#12547 | Internal patchIso8601Timestamp() isn't safe for 5 digit years |
#13171 | Confusing (outdated) gradle examples in manual |
#13541 | Various runtime errors when using features in dialects that do not support them |
#13680 | Remove workaround for H2 process hanging when using FINAL TABLE (MERGE ...) |
#14256 | Syntax error when from current_timestamp when precision bind value is specified for Postgres |
#14764 | Avoid dialect version lookup in AbstractDatabase, if unnecessary |
#14769 | <clinit> race conditions in jOOQ internals |
#14771 | NullPointerException when using plain SQL identity and additional column in INSERT .. RETURNING |
#14776 | Javadoc contains warning boxes |
#14780 | Correctly annotate SIMILAR TO operator |
#14785 | Compilation error in KotlinGenerator generated code when <kotlinNotNullRecordAttributes/> and <recordsGeneratingRecordN/> are both active |
#14791 | SQLDialect version check throws NumberFormatException in Percona DB |
#14801 | JavaGenerator creates broken code for arrays when kotlinNotNullPojoAttributes is true |
#14802 | [#14801] Fix Java String generation for non-nullable arrays |
#14817 | Nullable kotlin records break columns with default values |
#14830 | Compilation error in generated code when table valued function returns table with client side computed columns and <recordsImplementingRecordN/> is active |
#14833 | Version support check shouldn't log error message for MockConnection |
#14839 | PL/SQL procedure returns wrong result when combining boolean and record type as input |
#14841 | ERROR: type "blob" does not exist when casting NULL as a domain converted as user defined type using class literal |
#14843 | Switch links from /doc/dev to /doc/latest for recently added diagnostics |
#14845 | Upgrade Spring to mitigate CVE-2023-20861 |
#14849 | ROLLUP, CUBE should generate Keyword, not Name |
#14853 | Kotlin Code generator generates invalid code for embeddables in POJOs when immutable interfaces is activated |
#14855 | Compilation error in generated code for embeddable properties when reducing visibility to internal, and generating interfaces |
#14872 | Regression when using INSERT .. RETURNING pre MariaDB 10.5 |
#14875 | Inconsistent implementation of TableImpl::equals and TableImpl::hashCode when comparing generated tables with plain SQL ones |
#14882 | Generate nullable annotations also on record constructor, when <pojosAsJavaRecordClasses/> is set |
#14883 | Regression: KotlinGenerator produces superfluous public keyword for overriding methods |
#14890 | QUALIFY transformation should unalias columns again |
#14902 | Work around Oracle 23c regression when nesting aggregate JSON functions in MULTISET |
#14906 | Internal API leaks into client code via generated table's join(TableLike<?>, JoinType) method |
#14908 | Missing parentheses when second subquery in set operation contains deep nesting |
#14916 | Compilation error with embedded domains and postgres types |
#14923 | Explicitly set locale to English in maven-javadoc-plugin |
#14924 | Explicitly set locale to English in maven-javadoc-plugin |
#14930 | jOOQ-meta should avoid redundancies between getTables0() and sources() methods to fetch view sources |
#14937 | Support NULL bind values of type Interval in R2DBC integration |
#14938 | Unstable ordering of Derby generated foreign keys |
#14942 | Manual section about code generation configuration contains wrong comment about LiquibaseDatabase |
#14944 | Wrong warning logged regarding CockroachDB version support |
#14949 | Upgrade spring-core dependency to mitigate CVE-2023-20863 |
#14960 | No-arg DefaultConfiguration() constructor clones default settings twice |
#14991 | KotlinGenerator produces wrong code with kotlinNotNullPojoAttributes when multiple references to an embeddable have different nullability |
#14995 | OffsetDateTimeRange javadoc should reference tstzrange not tsrange |
#14996 | #14995 fix OffsetDateTimeRange javadoc |
#14997 | Use awaitSingle instead of awaitFirstOrNull in transactionCoroutine to correctly sequence transaction script |
#15007 | Change DSL.multisetAgg() overload accepting Field<?>...|Collection<? extends Field<?>> to work with SelectField<?> instead |
#15008 | Cannot pass Table reference to row() constructor in array or list |
#15013 | GROUPING() support was only added in MySQL 8 |
#15015 | A few MySQL 5.6 related fixes |
#15022 | SchemaImpl and CatalogImpl $replace() and $traverse() methods shouldn't recurse into Name or Comment parts |
#15028 | R2DBC bind value related exceptions produce misleading error message |
#15035 | Support NULL bind values of type Year in R2DBC integration |
#15039 | The exported DDL of the table for POSTGRES_15 dialect is missing a default value |
#15042 | Support NULL bind values of type UUID in R2DBC integration |
#15048 | DDLDatabase defaultNameCase=lower doesn't work with ENUM types |
#15052 | JooqLogger log methods don't check if log level is enabled |
#15056 | Parser meta lookup fails when using qualified asterisk on a table alias |
#15088 | Misleading error message when ON KEY finds ambiguous keys |
#15095 | Generate property access syntax in KotlinGenerator generated tables |
#15096 | Ambiguous type name warning for non-ambiguous type name in OracleDatabase |
#15097 | Compilation error in Oracle generated code for package type in PL/SQL RECORD constructor |
#15104 | InlineDerivedTable should wrap query lazily |
#15114 | Upgrade sqlite dependency to 3.42.0.0 to mitigate CVE-2023-32697 |
#15115 | Improve error message when unversioned, row based optimistic locking doesn't work with DAOs and POJOs |
#15121 | Derived column list doesn't work on InlineDerivedTable |
#15125 | Handle SQLite's incompatible change of implementation for LOG(x) |
#15127 | DefaultConfiguration::toString logs wrong flags in R2DBC context |
#15149 | PostgresDatabase and subtypes may produce wrong table comments in presence of stored functions |
#15154 | Fix various Javadoc links |
#15168 | NullPointerException in code generator when omitting <target> directory |
#15182 | Add tests to prevent leaking of invisible, internal API through generated code |
#15183 | Compilation error in generated DAO code when visibility of a field is changed to private |
#15190 | DISTINCT .. LIMIT emulation renders redundant DENSE_RANK() OVER (ORDER BY ...) clauses |
#15195 | H2 dialect should cast binary data of unknown length as VARBINARY, not as BINARY |
#15202 | Add missing Experimental annotation to migrations API types |
#15218 | NullPointerException in AbstractMeta::lookupTable and other methods, when there is no DefaultCatalog |
#15238 | MetaImpl::ddl() should produce plain SQL CREATE VIEW statements if it can't parse the view contents |
#15250 | LoggerListener logs some batch queries twice, when using BatchMultiple |
#15253 | ScalaGenerator produces wrong code when generator strategy adds multiple interfaces to legacy enum type |
#15270 | Wrong implementation of SelectQueryImpl::wrapQueryExpressionBodyInDerivedTable in jOOQ Open Source Edition |
#15278 | CheckDefinition.getSource() should return CheckDefinition.getCheckClause() contents |
#15282 | Wrong encoding of lists in generated programmatic code generation configuration examples |
#15291 | Meta.ddl() export generates wrong DDL for constraints with USING INDEX clause in Oracle |
#15302 | Meta.ddl() generates broken DDL for smallserial columns |
#15318 | MetaImpl is missing view source code or unique constraints for objects in other catalogs |
#15319 | Error when generating code from a MariaDB database containing packages |
#15326 | Meta.ddl() should export tables first, then views |
#15331 | Batch::executeAsync throws NullPointerException when executed with R2DBC driver |
#15336 | Parser error when using SET new.x = y syntax in triggers |
#15341 | Bad syntax in Firebird when creating triggers for unquoted table names |
#15359 | Block::$replace doesn't replace anything |
#15364 | Wrong deprecation notices in PostgresDSL |
#15366 | Avoid generating sort specification in indexes in dialects that don't support it |
#15375 | Table with 255 columns generates record and POJO objects whose constructors have too many parameters |
#15383 | Compilation error in generated code when global object references conflict with schema names |
#15388 | Settings.metaIncludeSystemIndexes doesn't work for system indexes of unnamed constraints in HSQLDB |
#15395 | Exception when MockResult contains UDTRecord |
#15402 | Bad formatting of hints at the end of maven-install.sh scripts |
#15412 | Missing CAST in generated MERGE statement when using inline values in PostgreSQL 15's ON DUPLICATE KEY UPDATE emulation |
#15414 | Can't generate code using CockroachDB materialized view |
#15423 | Table list to ANSI JOIN transformation doesn't work if table declarations are fully qualified, but references are not |
#15433 | AutoConverter loses nanosecond precision when converting from Instant to LocalDateTime or OffsetDateTime |
#15472 | Code generation fails on BigQuery when querying INFORMATION_SCHEMA without a DefaultDataset being specified |
#15473 | Failure in MetaImpl.MetaSchema::source in BigQueryDatabase |
#15478 | AutoConverter should be lenient about TIME type fractional seconds |
#15482 | Can't invoke default methods on proxied types returned by DefaultRecordMapper in JDK 9 or more |
#15497 | Work around SQL Server's 1000 row value limitation for INSERT statements |
#15504 | Query::isExecutable should be checked in the R2DBC implementation, allowing no-ops for non-executable queries |
#15507 | Fix various UDT related issues in KotlinGenerator |
#15511 | Manual should stop recommending use of deprecated DefaultExecuteListener or DefaultRecordListener |
#15524 | Missing Stringly annotation on String... varargs parameters |
#15553 | AbstractTypedElementDefinition should cache resolvedType property only once per file |
#15555 | Datetime precision isn't maintained by code generator for domain types |
#15559 | KotlinGenerator - isKotlinNotNullPojoAttributes setting prevents generated DAO to set serial ID to pojo |
#15563 | DefaultRecordMapper should skip most mappers when an instance is provided |
#15564 | MutablePOJOMapper should be able to map to instance, even if there isn't a default constructor |
#15569 | Record.into(recordInstance) should modify argument record |
#15574 | DefaultOtherBinding shouldn't create string literals for inline values for numeric data types |
#15582 | MariaDB UPDATE .. RETURNING emulation should work on tables with unique constraints only |
#15584 | Install shell/batch scripts should be clearer about Java 17+ support |
#15595 | DefaultStringBinding should bind java.sql.Clob for CLOB types in Oracle MERGE statements |
#15598 | Fix DefaultRecordMapper Javadoc to reflect actual behaviour |
#15602 | Plain SQL Javadoc disclaimer is absent on api generator generated step methods |
#15610 | Bump org.eclipse.jgit:org.eclipse.jgit from 5.9.0.202009080501-r to 6.6.1.202309021850-r in /jOOQ-migrations |
#15614 | Wrong Support annotation on COMMENT ON COLUMN for MariaDB |
#15619 | On JDK 21, generated code should apply "this-escape" warning suppression |
#15621 | Synthetic comment flag <deprecated> should produce @Deprecated annotation in addition to Javadoc |
#15623 | Stop using deprecated DSL API in jOOQ-meta |
#15625 | QOM.Delete mutators produce a copy that always has a RETURNING clause |
#15629 | InlineDerivedTable can't be outer joined |
#15639 | RenderMapping doesn't apply to QualifiedRowid |
#15650 | DefaultConfiguration doesn't serialize AuditProvider or TransformProvider |
#15656 | InlineDerivedTable doesn't maintain contained table's meta data in some cases |
#15658 | Copy paste errors in likeIgnoreCase and containsIgnoreCase Javadoc |
#15668 | INSERT .. ON DUPLICATE KEY UPDATE emulation mustn't silently insert the last row only in Derby multi row inserts |
#15673 | Domains aren't generated if they don't have a CHECK constraint associated with them, in HSQLDB |
#15677 | Code generator doesn't generate multiple check constraints for DOMAIN types |
#15683 | Incorrect DEFAULT values generated for Informix |
#15686 | Generated DEFAULT expressions should always be syntactically valid for all data types in HANA |
#15687 | HANA sort indirection doesn't work with bind values |
#15693 | Fix a typo in a Tip |
#15697 | Upgrade jgit from the jOOQ-migrations prototype to 6.6.1.202309021850-r |
#15702 | Reactive transaction hangs when exception thrown in lambda constructing reactive flow |
#15714 | Possible compilation errors in generated code when column names contain double quotes |
#15724 | BindingSetStatementContext should reference actual ExecuteContext, if available |
#15735 | Ill-formed Javadoc causes JDK 21 javadoc tool to crash |
#15752 | JSONB inline values should be rendered using JSONB.data() not JSONB.toString() |
#15756 | Implicit JOIN implementation for DML is incorrect if paths navigate self joins |
#15760 | Compile errors of generated classes using scala 3 |
#15767 | MiniJAXB::marshal(XMLAppendable, OutputStream) does not flush decorating writer |
#15799 | LazyVal::generatesCast should return true |
#15803 | MetaImpl reports system indexes for Derby 10.16 |
#15816 | Misleading example in manual's section about the CREATE TRIGGER statement |
#15820 | Incorrect query generated when combining SEEK with GROUP BY |
#15823 | Wrong grammar for intervalLiteral in manual |
#15826 | Parser cannot parse undocumented reverse syntactic order of FOR UPDATE and LIMIT clauses from PostgreSQL |
#15828 | Support overlapping embeddables when enabling <embeddablePrimaryKeys/> |
#15832 | Oracle UDTs are sometimes inlined as [UDT] instead of IDENTIFIER(CONTENT) |
#15848 | Compilation error in KotlinGenerator generated code for tables containing a FROM column, when <interfaces> is activated |
#15850 | Accidental override when enabling <interfaces> for tables with columns X and IS_X in Kotlin |
#15873 | IllegalArgumentException when calling UpdatableRecord methods on tables with embedded domains that replace their underlying fields |
#15876 | Internal RecordDataType.getDataType() should be non-nullable for records consisting of all non-null fields |
#15883 | Compilation error in generated code when using <embeddableDomains/> and the domain is part of a composite key |
#15899 | Upgrade logback dependency in jOOQ-jooby-example to mitigate CVE-2023-6378 |
#15901 | Incorrect ExecuteListener Javadoc regarding ExecuteListener lifecycle |
#15917 | Swapped examples in manual section "group-by-tables" |
#15918 | AbstractDatabase::markUsed doesn't work in some edge cases |
#15927 | SnowflakeDataType is missing references to Snowflake's JDBC-internal spellings of TIMESTAMPNTZ, TIMESTAMPLTZ, TIMESTAMPTZ |
Version 3.18.0 - March 8, 2023
DiagnosticsListener improvements
A lot of additional diagnostics have been added, including the automated detection of pattern replacements, helping you lint your SQL queries irrespective of whether you're using jOOQ to write your SQL, or if you're using it as a JDBC / R2DBC proxy for an existing application.
A lot of these diagnostics are available as ordinary pattern transformations, which we've started adding in jOOQ 3.17. Some new patterns include:
CASE WHEN a = b THEN 1 END
toCASE a WHEN b THEN 1 END
CASE WHEN x IS NULL THEN y ELSE x END
toNVL(x, y)
CASE WHEN x = y THEN NULL ELSE x END
toNULLIF(x, y)
(SELECT COUNT(*) FROM t) > 0
toEXISTS(SELECT 1 FROM t)
- And much more
See these sections for more details:
- https://www.jooq.org/doc/3.18/manual/sql-execution/diagnostics/
- https://www.jooq.org/doc/3.18/manual/sql-building/dsl-context/custom-settings/settings-diagnostics-connection/
- https://www.jooq.org/doc/3.18/manual/sql-building/dsl-context/custom-settings/settings-diagnostics-logging/
- https://www.jooq.org/doc/3.18/manual/sql-building/queryparts/sql-transformation/transform-patterns/
More SQL/JSON support
SQL/JSON is one of the most promising recent additions to the SQL language, and we're always keen on improving jOOQ's support for these features. In this release, we've added support for a variety of useful, vendor specific SQL/JSON extensions, including:
- JSON_KEYS (from MySQL)
- JSON_SET (from MySQL)
- JSON_INSERT (from MySQL)
- JSON_REPLACE (from MySQL)
- JSON_REMOVE (from MySQL)
- Accessors -> and ->> (from PostgreSQL)
More information on new JSON function support can be found here:
More QOM implementation
The Query Object Model (QOM) API, which was introduced in jOOQ 3.16, has been enhanced with more statement, function, expression support, allowing for more complete SQL transformation and traversal. This is specifically interesting for pattern replacements, diagnostics, and custom SQL transformations.
The QOM API is still in an experimental state. While we don't expect any fundamental changes anymore, there can still be source incompatibilities between minor releases.
For details about the model API, please refer to:
Oracle associative array support
When using stored procedures in Oracle, users are likely going to make heavy use of Oracle PL/SQL package types. We've supported PL/SQL RECORD types and PL/SQL TABLE types for a while, both of which had limited ojdbc support in the past. Associative array support can still be a challenge with ojdbc, but with jOOQ and its code generator, most associative arrays can be bound and fetched very easily.
PostgreSQL Multi dimensional array types
An often requested feature from our PostgreSQL integration is multi dimensional array support. This version of jOOQ will support those types in code generation (where possible) and at runtime via multi dimensional Java arrays.
Kotlin specific improvements
jOOQ is also the best way to write SQL in kotlin. We're always looking out for new convenience via the jOOQ-kotlin extension module, for example:
- ResultQuery Collectors
- JSON access
- More nullability support in generated code
For more details, see:
R2DBC 1.0 support
This jOOQ version upgrades its R2DBC dependency to 1.0.0.RELEASE.
For a complete list other, minor improvements, see the below change notes.
Features and Improvements
#252 | Add support for multi-dimensional ARRAY types |
#3173 | Add SQL transformation to inline CTE |
#5254 | Add some additional description to each jOOQ-example |
#5620 | Add support for PL/SQL TABLE and associative array types in Oracle 18c |
#5679 | Document MySQL and T-SQL style hints in the manual |
#5799 | Add support for the SQL Standard WITH ORDINALITY clause |
#6237 | Merge all manual versions into one |
#6311 | Add <oracleUseDBAViews/> flag to code generator to use DBA_XYZ views instead of ALL_XYZ views |
#7106 | Add support for START TRANSACTION, COMMIT, ROLLBACK, SAVEPOINT statements |
#7398 | Add Settings for each individual diagnostic |
#7503 | Add support for PostgreSQL functions returning anonymous RECORD types |
#7512 | Emulate LATERAL on SQL Server for table lists |
#7527 | Add more diagnostics to DiagnosticsListener SPI |
#8630 | Support MySQL GROUPING() function |
#8893 | Add Settings.renderTable |
#8952 | Support parsing JSON_VALID(x) and ISJSON(x) as x IS JSON |
#9720 | Support logical XOR operator |
#9743 | Support qualified asterisk on unaliased JoinTables |
#9760 | Translator's "identifier case" option is confusing |
#9818 | Get view source code from org.jooq.Meta views |
#9844 | Generator strategies should support <schemaExtends/>, <tableExtends/>, <recordExtends/>, <daoExtends/>, <routineExtends/> |
#9880 | Translate SQL Server WITH (ROWLOCK) clauses to corresponding FOR UPDATE |
#10018 | Add support for PostgreSQL's JSON/JSONB -> and ->> operators |
#10026 | Emulate LATERAL on SQL Server for simple JOIN with trivial ON |
#10212 | Add options to generate non-null attributes on Records, Pojos, and interfaces in KotlinGenerator |
#10340 | Add SQLDialect.category() |
#10619 | Create manual subsections for each function |
#10730 | Add support for JSON_ARRAYAGG(DISTINCT) |
#11355 | Log warning when unsupported dialect version is being used |
#11681 | Get SQLDialect.VERTICA up to date |
#11830 | Add Settings.renderRowConditionForSeekClause to allow for avoiding row predicate usage |
#11966 | Various parser bugs / missing features |
#11981 | Add support for more array functions |
#11986 | Get HANA dialect support up to date |
#12022 | Add code generator support for MySQL's invisible columns |
#12033 | Add MULTISET_AGG(DISTINCT ...) aggregate and window function support |
#12037 | Implicit JOIN improvements |
#12045 | Support correlating MULTISET operators in dialects that can't correlated subqueries from derived tables |
#12531 | Auto-inline bind values in ON CONFLICT .. WHERE clause |
#12621 | Split manual section about the SELECT clause into its subsections |
#12907 | Add a QOM.UConvertibleOperator utility with methods like $converse() |
#13182 | Improve formatting XMLATTRIBUTES |
#13249 | Emulate JSON_OBJECT's ABSENT ON NULL clause in MySQL |
#13262 | Manual should distinguish more clearly between Maven XML and standalone XML content |
#13358 | Add SQLDialect.POSTGRES_15 |
#13375 | Add support for unnesting collections of expressions with DSL::unnest |
#13408 | Get TERADATA dialect up to date |
#13418 | Add a Settings.emulateComputedColumns |
#13423 | Add more "Don't Do This" content to the manual |
#13592 | Add more startup tips to be logged with the jOOQ logo |
#13593 | Replace more common patterns in query object model |
#13596 | Add QOM.Aliasable, a query object model type implemented by all aliasable objects |
#13640 | Continue work on public query object model API |
#13656 | Add a SQLDialect.SQLSERVER2022 |
#13698 | Support parsing H2's CREATE MEMORY TABLE and CREATE CACHED TABLE |
#13701 | Add a section to the manual about runtime vs code generation version compatibility |
#13706 | OnError.FAIL should log a message about the user's option how to handle the problem |
#13718 | Log warning should show jOOQ-meta type to help disambiguate objects that share the same name |
#13728 | Add SQLDialect.SQLITE_3_39 |
#13737 | Getting started section should clarify that jooq is the main dependency, and jooq-meta, jooq-codegen are typically unneeded |
#13747 | Add a "main types overview" to the manual |
#13748 | Support parsing the PostgreSQL DATE_PART function |
#13763 | Support DB2 selectivity-Keyword in Query-Parser |
#13764 | Refactor internal schema mapping logic to use the new QualifiedImpl type |
#13769 | Emulate GROUP BY <column index> using substitution in dialects where this isn't natively supported |
#13781 | Add SQLDialect.COCKROACHDB_22 |
#13791 | Apply an auto-converter to <forcedType> in the absence of an explicit converter, if possible |
#13850 | Get MEMSQL dialect up to date |
#13881 | Parse and ignore SQLite DDL conflict-clause |
#13882 | Parse length on unknown data types |
#13891 | H2 dialect should always generate standard OFFSET .. FETCH |
#13893 | Add SQLDialect.H2_2_1_214 |
#13894 | Add SQLDialect.precedesStrictly(SQLDialect) |
#13902 | Support H2's strict mode |
#13925 | Show deprecation warning for javax.persistence annotations also for method and field annotations |
#13928 | Emulate UPDATE .. RETURNING in MariaDB 10.5+ using INSERT .. SELECT .. ON DUPLICATE KEY UPDATE .. RETURNING |
#13935 | Support H2's qualified domains |
#13936 | Code generator should properly qualify H2 domain enums |
#13944 | Add Traversers.consuming(Consumer<? super QueryPart>): Traverser<?, Void> |
#13951 | Add support for MySQL's JSON modification functions |
#13957 | Add support for Oracle associative array of object types as IN parameter |
#13964 | Add a SQL building in kotlin section |
#13970 | PostgreSQL code generation fails when user defined type starts with _ |
#13971 | Add DataType.array() as a DSL style shortcut for getArrayDataType() |
#13973 | Add DataType.getArrayBaseDataType() and getArrayBaseType() |
#13986 | Add support for Db2 11.1 LISTAGG(DISTINCT) |
#13995 | Improve documentation on Fields lookup methods |
#14002 | KotlinGenerator shouldn't generate public default constructor if non-nullable attributes are generated on records |
#14004 | Add documentation for KotlinGenerator and ScalaGenerator |
#14006 | Add ResultQuery<Record2<T1, T2>>.fetchMap() and fetchGroups() extension methods to jOOQ-kotlin |
#14009 | Add DataType.isBoolean() |
#14014 | Slow query against SYS.ALL_INDEXES in OracleDatabase |
#14046 | Add support for MySQL's JSON_KEYS() |
#14064 | Add SQL Server 2016 support for JSON_VALUE |
#14065 | Add internal utilities to help avoid repeating expressions |
#14066 | Split SimpleQueryPart into two, allowing for marking types that are always simple |
#14071 | Add parser support for undocumented AS keyword in SQL Server procedure parameter list |
#14074 | Add support for passing a list of bind values to DSL.unnest(Collection) |
#14077 | Add support for SQL Server's ALTER VIEW .. AS syntax |
#14081 | Translator should use 100% screen width |
#14082 | Add parser support for MySQL's CREATE INDEX .. VISIBLE keyword |
#14084 | Parser should parse Oracle WITH FUNCTION syntax (and throw an unsupported exception) |
#14089 | Add parser support for CREATE SCHEMA .. DEFAULT CHARSET |
#14098 | Document the fact that some DDL emulations may require the commercial editions |
#14099 | Upgrade pgjdbc to 42.5.0 |
#14103 | Add parser support for MySQL USE / FORCE / IGNORE INDEX hints |
#14110 | License header should use HTTPS rather than HTTP |
#14118 | Support defaulted PL/SQL RECORD and TABLE parameters to stored procedures |
#14131 | Improve Val.getName() for array values |
#14136 | Let DiagnosticsContext extends Scope |
#14146 | Add a LoggingDiagnosticsListener, a default DiagnosticsListener implementation that logs events |
#14155 | Add ExecuteListener::transformStart and ::transformEnd events |
#14157 | Upgrade to kotlin 1.7.20 |
#14158 | Add ExecuteContext::batchMode to indicate what type of batch is being executed |
#14159 | Add parser support for <grouping column reference list> |
#14160 | Parse and ignore the T-SQL SPARSE column definition flag |
#14166 | Render correct SQL when COALESCE or CASE have empty contents |
#14179 | Add a QOM.UReturnsNullOnNullInput marker interface |
#14180 | MANIFEST.MF contains unnecessary javax.persistence dependency |
#14181 | All QOM function types should implement UOperator[N] |
#14186 | All UOperator[N] types should extend UOperator, offering an $args():List<?> |
#14201 | Improve formatting of non ordinary grouping sets |
#14202 | QOM API mutator methods should be annotated with @CheckReturnValue |
#14214 | Add Traverser.recurseChildren(): Predicate<QueryPart> |
#14230 | Add native support for Snowflake * EXCLUDE (columns) syntax |
#14242 | Add support for DB2 ROWNUMBER and DENSERANK window function in parser |
#14248 | Add parser support for CockroachDB STRING type |
#14249 | Add support for RIGHT JOIN and FULL JOIN in REDSHIFT |
#14251 | Add an internal Tools.allMatch() utility |
#14262 | Field::contains should implement PostgreSQL @> also for JSONB types |
#14268 | Add support for SQL Server 2022 GENERATE_SERIES |
#14269 | Add support for SQL Server 2022 GREATEST and LEAST |
#14270 | Add support for SQL Server 2022 WINDOW |
#14271 | Emulate SPLIT_PART using STRING_SPLIT in SQL Server 2022 |
#14272 | Add support for SQL Server 2022 IGNORE NULLS and RESPECT NULLS |
#14301 | Add SQLDialect.MYSQL_8_0_31 |
#14302 | Add support for INTERSECT ALL and EXCEPT ALL in MySQL |
#14303 | Add support for INTERSECT ALL and EXCEPT ALL in MariaDB 10.5 |
#14308 | Support qualified asterisk on aliased JoinTables |
#14309 | Add Field::nullsFirst and Field::nullsLast convenience methods |
#14310 | Add support for aliased JoinTables |
#14311 | Improve formatting of nested JoinTable |
#14320 | Add native Informix DECODE support |
#14331 | Add Settings.renderRedundantConditionForSeekClause to improve SEEK predicate performance in some RDBMS |
#14336 | Parse and ignore Teradata (TITLE '...') syntax |
#14337 | Parse the Teradata (NAMED ...) syntax |
#14342 | Generate referenced sections list in manual |
#14360 | Add parser support for prefixed PARTITION BY .. OUTER JOIN syntax |
#14361 | Add API support for fullJoin(..).partitionBy(..) |
#14363 | Support BITNOT in HANA dialect |
#14365 | Emulate expressions in LIMIT .. OFFSET where not natively supported in more dialects |
#14366 | Add HANA support for UPDATE .. FROM |
#14379 | Add DSL.raw(String) and Settings.renderPlainSQLTemplatesAsRaw to allow plain SQL without templating |
#14388 | Add support for ARRAY concatenation |
#14406 | The AutoAlias feature isn't applied from within the JOIN tree, only from the TableList |
#14416 | Support UNNEST(ARRAY[...]) in dialects that do not otherwise support arrays |
#14426 | OUTER APPLY emulation should use TrueCondition, not hard coded 1 = 1 |
#14440 | Add Teradata support for STRTOK via SplitPart |
#14441 | Support parsing && and ! logical operators in MySQL |
#14442 | Add ParserContext::parseCategory |
#14447 | Get BigQuery dialect up to date |
#14450 | Add native support for WINDOW in BigQuery |
#14457 | Add support for MySQL style ELT() function (equivalent to CHOOSE()) |
#14458 | Add native DECODE() support in MemSQL and DECODE_ORACLE() support in MariaDB |
#14464 | Improve confusing parser error message "SELECT or SEL" expected |
#14465 | Add parser support for SQL Server OPENJSON with WITH clause |
#14473 | Refactor Db2 v9 and Teradata LISTAGG emulation to use native support for XMLSERIALIZE instead of plain SQL templates |
#14481 | Add parser support for bitemporal table queries with system_time and business_time |
#14488 | Parser should disambiguate SQL Server + operand based on operand lookup |
#14496 | Implement BatchMultiple::toString and BatchSingle::toString |
#14499 | Add an R2DBC LoggingConnection |
#14506 | Add a manual section for LoggingConnection |
#14510 | Add Field<T>.comment(Comment): Field<T> |
#14511 | GROUP_CONCAT manual page is missing a reference to `Settings.renderGroupConcatMaxLenSessionVariable` |
#14512 | CREATE TABLE statements should generate COMMENT clauses for Field comments |
#14513 | ALTER TABLE statements should generate COMMENT clauses for Field comments |
#14534 | Add <generatedAnnotationJooqVersion/> option to the code generator |
#14537 | Add org.jooq.True, org.jooq.False, and org.jooq.Null to QOM API |
#14538 | Add DataType.isFloat() |
#14539 | Add ALTER TABLE .. ADD .. [ FIRST | AFTER .. ] support for MariaDB |
#14548 | UOperator[N] QOM types should generate both named accessors and mutators |
#14555 | Improved emulation of row value expression predicates of degree 3+ |
#14560 | Refactor QuantifiedSelectImpl into separate subtypes |
#14572 | Document kotlin coroutine usage in manual |
#14573 | Add Settings.returnDefaultOnUpdatableRecord and Settings.returnComputedOnUpdatableRecord |
#14578 | Add native support for DISTINCT predicate in SQLDialect.SQLSERVER2022 |
#14579 | Add native support for LEFT_SHIFT(), RIGHT_SHIFT() in SQLDialect.SQLSERVER2022 |
#14580 | Add native support for BIT_COUNT() in SQLDialect.SQLSERVER2022 |
#14581 | Add support for BIT_SET or BIT_GET functions |
#14584 | Add bitwise operation support for EXASOL |
#14586 | Update third party dependencies |
#14592 | Add parser support for T-SQL table hints without WITH keyword |
#14594 | Support parsing whitespace between : and named parameter identifier |
#14595 | Support parsing WITH READ ONLY and WITH CHECK OPTION clauses |
#14611 | Support WITH CHECK OPTION and WITH READ ONLY in other dialects |
#14631 | Add parser support for SQLite's STRICT tables |
#14641 | Settings.emulateMultiset should use NestedCollectionEmulation.JSONB as default again, in PostgreSQL |
#14642 | Add a SQLExceptionLoggerListener that logs additional information to help debug constraint violations |
#14648 | Get SNOWFLAKE dialect up to date |
#14653 | Add SQL/JSON support for the SNOWFLAKE dialect |
#14655 | Add Snowflake support for the TABLE() constructor to call table valued functions |
#14658 | Get MariaDB dialect up to date |
#14660 | Work around Snowflake's INSERT .. VALUES limitation of not being able to reference expressions |
#14665 | Non-boolean field emulation should be NOT NULL aware |
#14690 | Add parser support for SQLite's WITHOUT ROWID tables |
#14701 | Let DataAccessException::sqlStateClass be based on SQL Server error codes for SQLStateClass 22 or 23 |
#14708 | Add Queries.batch(): Batch |
#14711 | Add missing set(String, Param) and setLocal(String, Param) overloads |
#14713 | Add support for interval types in DefaultConverterProvider |
#14717 | Transform MySQL IN (SELECT .. LIMIT) to derived table also for MemSQL |
#14718 | Add dialect versions for MEMSQL |
#14722 | Add bitwise aggregate function support for Vertica |
#14726 | Document Converter behaviour for UNION and other set operation subqueries |
#14738 | Add parser support for Snowflake's EQUAL_NULL function |
#14742 | Remove MariaDB's self-reference-in-DML-subquery restriction workaround |
#14755 | Link to execute with jOOQ blog post from jOOQ / JPA manual sections |
#14763 | Update maven-plugin-api and maven-core depedency |
Breaking changes
#2500 | Add support for the MySQL YEAR data type, mapping to java.time.Year |
#5405 | Generated SETOF table_type functions should reuse the TableRecord type of the referenced table |
#7841 | DSL.asterisk() does not work well with plain SQL |
#13047 | Make JAXB API dependency optional |
#13565 | Update R2DBC dependency to 1.0.0.RELEASE |
#13961 | Add ContextConverter, a Converter subtype that receives a ConverterContext in from() and to() methods |
#14007 | Exclude SQLITE_SEQUENCE, SQLITE_MASTER, SQLITE_STAT% when <includeSystemTables/> is false |
#14058 | WindowSpecification::$partitionBy should return UnmodifiableList<? extends GroupField> |
#14095 | DSL.createView() returns raw type CreateViewAsStep |
#14138 | DiagnosticsConnection should store duplicate SQL strings in Configuration, not static variable |
#14153 | Make NullStatement a UTransient QueryPart |
#14263 | Add jsonbObject() convenience overloads for single element objects |
#14267 | Upgrade liquibase-core dependency to 4.17 in jooq-meta-extensions-liquibase |
#14409 | Refactor Values to implement AutoAlias |
#14445 | Delay ExecuteContext::connection in BatchMultiple and BatchSingle |
#14476 | Move experimental migrations API to DSLContext::migrations to avoid conflicts with transaction statements |
#14546 | QOM mutators on generic types such as UOperator should return covariant type |
#14561 | Rename various QOM accessors / mutators from $select() to $query() |
#14675 | Add a DataException for SQLState 22 and a IntegrityConstraintViolationException for SQLState 23 |
#14727 | Generated TRecord.from(IT) method behaves differently from Record.from() with respect to NOT NULL DEFAULT columns |
Deprecations
#14634 | Deprecate transformInConditionSubqueryWithLimitToDerivedTable configuration and offer transformation in the jOOQ Open Source Edition |
Bug Fixes
#6359 | PostgreSQL inlined numeric arrays shouldn't generate string literals |
#6516 | ORA-01704 when generating large CLOB inline values in Oracle |
#7076 | ForcedType enum with no matching value being converted to last enum value |
#7552 | INSERT .. ON DUPLICATE KEY { IGNORE | UPDATE } emulation should consider all UNIQUE keys on PostgreSQL |
#8277 | Manual example for running the code generator with ant is missing the JDBC driver dependency |
#8609 | MemSQL does not support "nested scalar subselects in project list" |
#9623 | Update manual example about binding JSON types |
#10014 | Infinite loop in code generation templating language if a parameter is forgotten |
#10712 | Firebird invalid ORDER BY clause when using ORDER BY column with set operation |
#10819 | NULL clause on H2's columns should not be produced |
#11015 | VALUES() must cast NULL literals in the first row, if the type is known and the RDBMS cannot infer it |
#11620 | In MySQL, withReturnAllOnUpdatableRecord(true) causes two SELECT statements |
#11682 | Avoid generating field names using toString() |
#11856 | StackOverflowError in parser with Settings.parseWithMetaLookups == IGNORE_ON_FAILURE |
#12214 | JoinTable.onKey(ForeignKey) does not work when tables are aliased |
#12942 | maven-deploy and maven-install bash and batch scripts should terminate on mvn command error |
#13343 | R2DBC implementation may hang when there's an exception in the rendering logic |
#13575 | Support EXCLUDED table emulation also in expressions |
#13669 | Connection::close call is skipped when R2DBC query fails |
#13689 | Cannot parse computed columns in the presence of identity column |
#13690 | Data type rewrites to BOOLEAN don't work in Oracle JSON_OBJECT |
#13703 | Ill formatted Javadoc in DSLContext |
#13717 | Wrong query in example of manual section about dynamic SQL |
#13722 | Regression: Client code no longer compiles when calling DSLContext.fetchSingle(Table, Condition...) |
#13723 | Regression: Zero-length delimited identifier is generated for enum columns when using <outputSchemaToDefault/> |
#13730 | Generated sources emits "reference not accessible" warning for `org.jooq.impl.AbstractTable#convertFrom` |
#13732 | Wrong Javadoc in generated AbstractSpringDAOImpl |
#13738 | Reactive transactions don't call Connection::close |
#13751 | GROUP BY <table> does not use table alias |
#13752 | Returning null from transactionCoroutine throws NoSuchElementException |
#13762 | DefaultRecordBinding.pgRenderRecordCast and others don't apply schema mapping |
#13766 | Upgrade log4j to 2.18.0 to mitigate CVE-2022-33915 |
#13771 | Parser doesn't support parsing parenthesised GROUP BY expression |
#13780 | ERROR: unknown function: nameconcatoid() in CockroachDBDatabase on CockroachDB 22 |
#13796 | Virtual client side computed columns must be excluded from generated DDL statements |
#13798 | GenerationOption.DEFAULT should act as STORED in client side computed columns |
#13800 | Improve formatting of H2 computed columns |
#13802 | TransactionPublisher does not commit transaction when wrapped in reactor's Mono |
#13803 | AbstractSpringDAOImpl imported from wrong package when generating multiple schemas |
#13804 | Wrong kotlin code generated for SQL Server stored procedures |
#13808 | ArrayGet should not produce parentheses when used as a store assignment target, e.g. in UPDATE |
#13816 | Wrong example in manual section about ST_Equals |
#13818 | MySQL DEFAULT CURRENT_TIMESTAMP column is generated as computed column |
#13827 | NullPointerException when calling DBMS_AQ.dequeue |
#13843 | Cannot use Table as SelectField from derived table where nesting records is supported natively |
#13844 | Fix typo in code generation log message |
#13851 | Wrong DDL generated for computed columns in MEMSQL |
#13854 | Syntax error in MemSQL code generation |
#13857 | Upgrade pgjdbc to mitigate CVE-2022-31197 |
#13866 | KotlinGenerator produces directory names with backticks when catalog names contain special characters |
#13867 | MemSQL doesn't support the SET @@var = @other_var syntax |
#13872 | PostgreSQL arrays don't deserialise correctly when using XML MULTISET emulation |
#13880 | Parser should parse and ignore PRIMARY KEY UNIQUE |
#13890 | Broken Javadoc link for JDK Generated annotation in manual |
#13897 | The maven codegen plugin does not load syntheticObjects from external configurationFile |
#13904 | Code generation fails with H2 2.1.214 when using CASE_INSENSITIVE_IDENTIFIERS |
#13906 | Logger name repeated twice |
#13913 | Convert truncates microseconds from OffsetDateTime when converting to Instant |
#13919 | PostgreSQL generated code doesn't maintain precision / scale on NUMERIC or TIME, TIMETZ, TIMESTAMP, TIMESTAMPTZ types |
#13926 | NullPointerException thrown instead of DetachedException, when executing detached query |
#13934 | DDLDatabase cannot handle qualified enum types in CREATE TABLE |
#13952 | IsNotDistinctFrom predicate doesn't declare non-nullability |
#13965 | Work around HSQLDB bug where NULL literal cannot be fetched as array |
#13974 | ParsingConnection doesn't correctly relay Statement::getResultSet, Statement::getUpdateCount, or Statement::getMoreResults on static Statement |
#13976 | Wrong Java version support listed on website for jOOQ 3.17 Open Source Edition |
#13993 | Wrong value returned from NullCondition::isNullable |
#14003 | Compilation error in generated code when combining <pojos/>, <interfaces/> and <embeddables/> |
#14010 | Postgres array of single-field UDT reads UDT's field as null instead of actual value |
#14017 | Moderately slow query on ALL_TAB_COLS due to cartesian product in OracleTableDefinition |
#14021 | Moderately slow query on ALL_ARGUMENTS due to EXTENDED DATA LINK FULL in OracleTableDefinition |
#14026 | Fix "Use case" -> "Possible solution" field name in feature request template |
#14027 | ClobBinding and BlobBinding shouldn't delegate sql() generation to internal DefaultStringBinding or DefaultBytesBinding |
#14033 | Fix incorrect grammar in XSD documentation |
#14034 | Upgrade to Scala 2.13.9 to mitigate CVE-2022-36944 |
#14052 | Upgrade to HSQLDB 2.7.1 to mitigate CVE-2022-41853 |
#14053 | Upgrade jackson-databind dependency to 2.13.4 to mitigate CVE-2022-42004 |
#14055 | Upgrade protobuf-java to 3.16.3 to mitigate CVE-2021-22569 |
#14060 | Work around Derby's Error [30000] [54002]: A string constant starting with '...' is too long |
#14067 | ClobBinding and BlobBinding shouldn't bind a null value on PreparedStatement::setClob and ::setBlob in Firebird, HSQLDB |
#14086 | Support parsing SELECT .. INTO <qualified table> FROM .. |
#14094 | Manual shouldn't suggest calling JSON::toString or JSONB::toString |
#14097 | Cannot pass null values as arguments for associative arrays |
#14100 | Table as SelectField native support relies on actual column order, not generated order |
#14105 | ClassCastException when nesting array(select row) projections in PostgreSQL |
#14108 | Upgrade jackson-databind dependency to 2.13.4.2 to mitigate CVE-2022-42003 |
#14111 | Wrong key data type stored in associative record |
#14112 | Cannot pass null values as arguments for PL/SQL RECORD types |
#14125 | Document a few missing SQL transformations in the manual |
#14126 | Wrong descriptions in manual section "codegen-extension-postgres" |
#14130 | Wrong claims about SQL standard optional FROM clause in manual |
#14132 | Code generator shouldn't generate JPA Column precision on non-decimal types |
#14141 | Generated text blocks for view sources should escape \ |
#14163 | Wrong transformation for transformPatternsTrivialPredicates when DISTINCT predicate operand is NULL |
#14169 | HAVING TRUE is not a trivial predicate for the transformPatternsTrivialPredicates transformation |
#14176 | ParserCLI in interactive mode should use Settings defaults for its SQL transformation flags |
#14182 | Typo in window function section of the manual |
#14185 | [#14182] Fix typo in percentRank javadoc comment |
#14187 | StackOverflowError in transformPatternsArithmeticExpressions when commutative operator has 2 inline arguments |
#14191 | DefaultDiagnosticsContext should cache resultSetFetchedRows |
#14194 | Bad syntax generated when using the Field.collate() clause in CREATE TABLE statements |
#14195 | Cannot query geometry value in a multiset |
#14204 | AbstractToJacksonConverter does not work when userType is array |
#14205 | ResultSet diagnostics don't work for PreparedStatement |
#14206 | Improve formatting of H2 procedural ELSE statement |
#14210 | Regression in MS Access CONCAT implementation |
#14213 | Typo in mapping exception message |
#14215 | Plain SQL INSERT .. RETURNING doesn't work with unqualified field templates in SQL Server |
#14220 | Update blog links from Javadoc and comments |
#14225 | Missing changelog for version 3.17.5 |
#14226 | Outdated Javadoc on DSL.array() for how jOOQ renders H2 array constructors |
#14231 | Cannot query geometry value in a nested ROW |
#14232 | ORA-00904: "v0"."GET_WKT": invalid identifier |
#14236 | DefaultDiagnosticsContext shouldn't call ResultSet::getMetaData on already closed ResultSet |
#14239 | Work around SQLite's error: HAVING clause on a non-aggregate query |
#14245 | Replace internal DSL.NULL(x) by DSL.inline(null, x) |
#14246 | Improve DERBY emulation of ROUND |
#14252 | Document CHOOSE |
#14255 | Improve generated unknown data type javadoc when forcedTypes match return type, but there are still unknown parameter types |
#14258 | ClassCastException in WithImpl::$replace |
#14276 | Median emulation ignores FILTER and OVER clauses |
#14282 | Bump postgresql from 42.5.0 to 42.5.1 |
#14283 | Kotlin Value Classes in Constructor lead to name based mapping failure |
#14286 | Upgrade pgjdbc to 42.5.1 to mitigate CVE-2022-41946 |
#14289 | ScalaGenerator generated code should avoid "procedure syntax" |
#14294 | ON CONFLICT DO NOTHING emulation should continue to be applied for PostgreSQL 9.3 and 9.4 |
#14300 | Expand unqualified asterisk in MySQL when it's not leading |
#14313 | Informix DDL statements generate invalid SQL for timestamp columns |
#14316 | Informix CURRENT_TIMESTAMP emulation doesn't work as DDL DEFAULT expression |
#14319 | Informix BOOLEAN expressions can't be compared in some cases |
#14321 | Wrong NULL behaviour of BitAndAgg, BitOrAgg, and related aggregate function emulations |
#14325 | Informix BOOLEAN literals 't' and 'f' need to be cast to BOOLEAN explicitly |
#14328 | Excess query executed against SQLite when emulating INSERT .. RETURNING |
#14333 | ArrayIndexOutOfBoundsException when parsing ill formed SQL ending with a comment and a semicolon |
#14339 | Exception in Teradata code generation: Unknown column TVName |
#14346 | Error: Invalid Top N Value: N is too big for Teradata OFFSET emulation |
#14349 | Teradata TOP expression or DISTINCT TOP don't work |
#14352 | PostgresDSL arrayOverlap does not properly cast arguments |
#14353 | Parser meta lookups don't work correctly when using DELETE .. FROM with aliased tables |
#14356 | java.lang.StackOverflowError at org.jooq.impl.Expression.acceptAssociative |
#14357 | Use ? as parameter marker on MySQL, MariaDB when using R2DBC |
#14368 | Meta::getTables should list also PARTITIONED TABLE in PostgreSQL |
#14371 | Slow TableAlias::equals implementation, when argument type is TableImpl |
#14372 | Parser reports wrong Ambiguous field identifier error when derived tables share column names |
#14373 | Parser produces wrong projection data type when parsing doubly nested derived table |
#14382 | Wrong example code in manual section "connection-access" |
#14383 | Broken link in a logging statement and Javadoc |
#14387 | Table::useIndex and similar table wrapping methods break joins using onKey() |
#14395 | DSL::noField doesn't work in SEEK clause |
#14403 | "You can't specify target table '...' for update in FROM clause" when target table has index hint in MySQL |
#14421 | Update error reporting URL in log messages |
#14425 | Code generation for sequences fails for SQL Server 2014 |
#14431 | Generated TableImpl::getSchema override should be annotated Nullable |
#14432 | Correctly hint nullability of getSchema() method |
#14437 | UnsupportedOperationException when selecting row with YearToSecond |
#14448 | BigQuery * EXCEPT can't have qualified identifiers |
#14451 | WindowSpecificationPartitionByStep::partitionBy doesn't match dialects from WindowPartitionByStep::partitionBy |
#14452 | BigQuery without FROM clause cannot use SELECT DISTINCT |
#14453 | Emulate BETWEEN SYMMETRIC in BigQuery |
#14454 | Wrong cast to CHAR type when generated code references SQLDataType.CHAR in BigQuery |
#14459 | Work around Db2 error "The string constant beginning with ... is too long" |
#14463 | Work around SQL Server's 4000 character JSON_VALUE length limitation |
#14466 | Wrong result column type for requested conversion when reading JSONB_ARRAYAGG and JSONB_OBJECTAGG in DB2 |
#14469 | MULTISET comparison doesn't work in Db2 with XML or JSONB emulation |
#14470 | Support parsing ALL keyword in aggregate functions |
#14477 | Wrong SQL generated in SQL Server when virtual client side computed columns are referenced in RETURNING clause |
#14479 | SQL Server RETURNING clause emulation for fetching trigger generated values generates incorrect SQL if no columns are fetched |
#14489 | Syntax errors lead to unclosed R2DBC connection in SQL Server |
#14507 | Remove redundant manual section "connection access" |
#14514 | Feedback about translation tool |
#14519 | Building jOOQ on Java 19 fails in xtend |
#14524 | Compilation error due to missing import in generated code when using <lambdaConverter/> on a routine |
#14528 | Update ParserCLI manual page with --help output |
#14530 | NullPointerException in DB2Database when constraint schema is unavailable |
#14535 | Fix org.jooq.Null Javadoc |
#14541 | Add support for top level nested records in R2DBC queries |
#14553 | Some QOM mutators of optional function parameters are annotated @Nullable, when they are not |
#14564 | KotlinGenerator generates invalid code in equals() and hashCode() methods for inline value class fields |
#14565 | Add missing documentation about <pojosEqualsAndHashCode/> |
#14571 | Regression: UpdateQuery.execute() with RETURNING clause returns 1 even when no records were updated |
#14574 | Regression: Meta::getTables returns tables of type TableType.TABLE when they're actually system views |
#14597 | CockroachDBDatabase doesn't report enum types on columns correctly anymore |
#14598 | Exception while executing meta query on MySQL 5.6: Unknown column 'information_schema.COLUMNS.GENERATION_EXPRESSION' |
#14599 | setAllToExcluded also sets fields not specified in insert to excluded when using INSERT .. SET syntax |
#14607 | Manual dialects comparison should turn off the generation of optional AS keywords |
#14615 | Wrong window function example in manual |
#14617 | SQL Server nullability information isn't generated correctly for domains |
#14618 | Missing nullability information on nullable DOMAIN types that are made non-null by CREATE TABLE |
#14621 | Work around a YugabyteDB regression querying the INFORMATION_SCHEMA.ATTRIBUTES table |
#14628 | Missing default information on DOMAIN types that get an overridden DEFAULT by CREATE TABLE |
#14635 | Single message JooqLogger doesn't work |
#14644 | LoggerListener::fetchEnd should check if DEBUG logging is enabled |
#14650 | Wrong emulation of GENERATE_SERIES with STEP parameter for Snowflake |
#14657 | Nesting MULTISET/ROW/MULTISET/ROW with ad-hoc converters and JSON emulation results in ClassCastException |
#14668 | Wrong ON KEY JOIN generated when aliased table appears twice in the JOIN tree |
#14671 | Wrong column resolved by JoinTable.field(Field), when JoinTable contains aliased tables and lookup uses unaliased tables |
#14684 | Translator duplicates comment only content when retaining comments |
#14694 | INSERT statement does not apply types to bind values in VALUES clause when using valuesOfRows() |
#14696 | Wrapping SQLException must copy SQLState and other info from wrapped SQLException |
#14699 | PostgreSQL interval parser handle fractional seconds with interval style iso_8601 |
#14703 | SQL Server RETURNING clause emulation for fetching server side computed columns generates incorrect SQL if only computed columns are fetched |
#14721 | performace regression after upgrade from 3.14.16 to 3.17.8 |
#14723 | Work around Vertica's ERROR: Subqueries not allowed in target of insert limitation |
#14730 | Push down ScopeMappable marker interface from AbstractField to AbstractWindowFunction and TableFieldImpl |
#14731 | Use LazyName in AbstractParam |
#14736 | PostgreSQL Numeric array type with precision/scale too large in generated code |
#14747 | Speed up AbstractRow.equals() and hashCode() when comparing with other AbstractRow |
Version 3.17.0 - June 22, 2022
Client side computed columns
A ground breaking new core feature available in all commercial distributions is the new client side computed columns feature, building on top of jOOQ 3.16's commercial support for readonly columns and server side computed columns.
Not all RDBMS support computed columns (e.g. using the standard SQL syntax
GENERATED ALWAYS AS
), and if they do, they might not support them
in both STORED
(computed on write) and VIRTUAL
(computed on read) variants. jOOQ can now emulate both features at the client
side, by transforming your SQL queries:
STORED
affectsINSERT
,UPDATE
,DELETE
, andMERGE
VIRTUAL
affectsSELECT
and theRETURNING
clause of DML statements. To make use of these, combine them with the new synthetic column generation feature.
Unlike their server side counterparts, these client side features can produce arbitrary expressions, including:
- Implicit joins
- Scalar subqueries
MULTISET
subqueries- Much more
Think of this as "views" written in jOOQ, on a per-column basis. An expecially useful feature combination is to combine these computed columns with the new visibility modifier that allows for keeping computed columns (or the underlying base columns) private and thus invisible to user code.
More about this feature here:
Audit columns
A special case of STORED
client side computed columns are audit
columns, whose most basic implementation comes in the form of:
CREATED_AT
CREATED_BY
MODIFIED_AT
MODIFIED_BY
Other approaches to auditing exist, including soft deletion, additional meta data, (bi)temporal versioning, but these columns are among the most popular approaches, making this commercial only convenience feature very useful to a lot of customers.
More about this feature here:
Java 17 baseline for the jOOQ Open Source Edition
Java 17 has been the latest LTS, and it includes a lot of really cool features, including:
- sealed types (essential for pattern matching)
- records
- instanceof pattern matching
- text blocks
- switch expressions
jOOQ 3.16's experimental new Query Object Model (QOM) API experiments with sealed types, which will be adopted more generally once the QOM API is finalized.
To get broader user feedback on these improvements, as well as to embrace Java's new LTS update cadence, we've decided to make Java 17 the baseline for the jOOQ 3.17 Open Source Edition, continuing our Java 8 and 11 support in the commercial jOOQ distributions.
The following older jOOQ releases will continue to receive upgrades for a while:
- jOOQ 3.14: The last release with Java 8 support in the jOOQ Open Source Edition and Java 6 support in the jOOQ Enterprise Edition
- jOOQ 3.15 and 3.16: The last releases with Java 11 support in the jOOQ Open Source Edition.
PostgreSQL data type support
The jooq-postgres-extensions module, which contained support for the
HSTORE
type, now has a lot more support for PostgreSQL specific
data types, including array types of each of:
CIDR
CITEXT
LTREE
HSTORE
INET
RANGE
(including all the specialisations forINT4
,INT8
, etc.)
In order to profit from these data types, just add the
org.jooq:jooq-postgres-extensions
module to your code generation
and runtime dependencies, and the types are generated automatically.
Implicit JOIN improvements
In this release, we experimented with a few new implicit JOIN features, including support for implicit JOIN in DML statements. The current implementation produces correlated subqueries where JOIN isn't supported in DML statements.
We've also experimented with creating a "convenience syntax" for other commonly
used correlated subqueries, such as EXISTS(...)
subqueries or
MULTISET(...)
subqueries. The experiment has been very interesting.
The prototype, however, was rejected. See the discussions here:
Future jOOQ versions will implement the desired convenience in the form of more implicit JOIN functionality, offering the feature also as an implicit to-many JOIN.
A leftover from the prototype is the fact that you can now more easily project
expressions other than classic Field<T>
in your SELECT
clause, namely:
Table<R>
now extendsSelectField<R>
Condition
now extendsField<Boolean>
This means you can write a query like this:
Result<Record3<CustomerRecord, AddressRecord, Boolean>> result = ctx.select( // Project a CustomerRecord directly CUSTOMER, // Project an AddressRecord from an implicit JOIN CUSTOMER.address(), // Project a boolean expression, instead of wrapping it with DSL.field() exists( selectOne() .from(PAYMENT) .where(PAYMENT.CUSTOMER_ID.eq(CUSTOMER.CUSTOMER_ID)) ) .from(CUSTOMER) .fetch();
Pattern matching SQL Transformations
SQL transformations have been a strategic feature set to recent jOOQ releases, offering additional compatibility between SQL dialects to commercial customers, such as, for example:
- Transforming Oracle's
ROWNUM
into equivalent window functions orLIMIT
clauses. - Turning table lists including Oracle's
(+)
operator into ANSI JOIN syntax.
This release ships with a new commercial only feature that directly transforms the new Query Object Model (QOM)'s expression tree prior to rendering. It does so by applying pattern matching to the expression tree. Some assorted examples include:
LTRIM(RTRIM(x))
intoTRIM(x)
x != a AND x != b
intox NOT IN (a, b)
x IN (a, b, c) AND x IN (b, c, d)
intox IN (b, c)
NOT (NOT (x = 1))
intox = 1
NOT (x = 1)
intox != 1
And much more. The primary use-cases for this functionality are:
- SQL linting, e.g. as part of an
ExecuteListener
- SQL auto cleanup, including in a
ParsingConnection
- Dialect migration, when upgrading database versions, or moving between dialects
- Patching specific SQL features
For more information about the feature, see:
Note that this feature is also available for free online:
Reactive and kotlin coroutine support
A lot of minor improvements have been implemented. A few more significant ones include:
- R2DBC 0.9.1.RELEASE is now supported
- A new reactive transaction API has been added, which offers the same nested transaction semantics as the existing blocking transaction API, see also: https://blog.jooq.org/nested-transactions-in-jooq/
- jOOQ's reactive streams bindings via the
Publisher
SPI are now bridged automatically to kotlin coroutines in the neworg.jooq:jooq-kotlin-coroutines
module using the usual utilitesorg.jetbrains.kotlinx:kotlinx-coroutines-core
andorg.jetbrains.kotlinx:kotlinx-coroutines-reactor
- The
org.jooq:jooq-kotlin
extensions module now has additional extension functions for moreMULTISET
and other nesting related convenience. - The entire blocking execution API is now annotated with
org.jetbrains.annotations.Blocking
to help reactive jOOQ users avoid accidentally blocking on a query, when using IntelliJ. In addition, we now annotate experimental and internal API with theApiStatus
annotation from the same package.
For a complete list other, minor improvements, see the below change notes.
Features and Improvements
#1592 | Add formal support for "audit" fields, such as CREATED_AT, CREATED_BY, MODIFIED_AT, MODIFIED_BY |
#2092 | Add support for the Postgres INET data type (java.net.InetAddress) |
#2333 | Add DSL.noField() for "conditional" LIMIT, OFFSET, GROUP BY, ORDER BY support when creating dynamic SQL |
#2968 | Add support for PostgreSQL RANGE types |
#3497 | Add methods to Context to distinguish between derived tables and other types of subqueries |
#4727 | Let Table<R> extend SelectField<R> |
#5214 | Add support for PostgreSQL's EXCLUDED table |
#5641 | Support overriding code generation <target/> configuration via system properties |
#5695 | Allow for expressions to be put in LIMIT / OFFSET |
#5934 | Add support for the Postgres CITEXT type |
#5970 | Add Setting to auto-inline all bind variables that participate in predicates on certain fields |
#6454 | Support converting from java.sql.Array to Object[] types |
#6489 | Code generator should support SQL-generated "dynamic regular expressions" |
#7284 | Replace common patterns in query object model |
#7508 | Add support for path expressions ("implicit joins") in DML |
#7803 | Let ArrayRecord extend Formattable |
#7912 | Add InsertOnDuplicateSetStep::setAllToExcluded to auto-set all insert column list columns to their EXCLUDED value |
#8653 | Add support for parsing VALUES <row value special case>, ... |
#8997 | Remove jOOQ-spring-example and documentation |
#9335 | Add a jooq-kotlin-coroutines module to support transactional coroutines based on reactive streams Publishers |
#9347 | DataType#getCastTypeName() does not respect rendering settings |
#9425 | Add Meta.migrateTo(Meta):Queries to generate a migration script between two Meta versions |
#9768 | Support MySQL inline INDEX specifications in DDLDatabase |
#9817 | Add support for text blocks in generated code |
#9879 | Add support for VIRTUAL and STORED client side computed columns |
#10120 | Add some more aliasing examples to the manual |
#10132 | Cast NULL literal to known type in Derby |
#10407 | Add support for FIREBIRD 4 RETURNING * syntax |
#10521 | Push down derived column list aliases to derived table's SELECT clause instead of using UNION ALL emulation, if possible |
#10523 | Emulate UPDATE .. SET row = (SELECT ...) for dialects with no native support |
#10537 | Split manual section about forcedTypes into different subsections |
#10677 | Add <onUnused/> to code generation configuration to specify behaviour when encountering unused objects |
#10756 | Generate @Transactional on DAOImpl and generated DAOs query-methods |
#10763 | Official jOOQ-postgres-extensions bindings should register themselves as low priority bindings if found on the code generation classpath |
#10832 | Review our Nullable and NotNull annotation usage |
#11232 | Parser should parse all Names.* values at least once |
#11331 | Support SQLDataType.XML in DDL |
#11467 | LoggerListener should log batch sizes for BatchSingle and BatchMultiple |
#11575 | Replace internal dialect switches by Set<SQLDialect> |
#11717 | Known limitations of the R2DBC integration |
#11731 | Emulate Oracle INSERT .. SELECT.. RETURNING |
#11770 | UpdatableRecord::merge should use new EXCLUDED semantics to avoid repeating bind values |
#11823 | Investigate whether read-only converters really require the Class<U> reference |
#11969 | Let Condition extend Field<Boolean> |
#12481 | ParsingConnection's PreparedStatement.getMetaData should be able to produce ResultSetMetaData prior to execution |
#12515 | Support for RowN.mapping(Function<? super Object[], ? extends U>) |
#12533 | Use org.jetbrains.annotations.ApiStatus |
#12608 | Support referencing the same embeddable type multiple times per table |
#12688 | Add support for H2's BIT_NAND_AGG, BIT_NOR_AGG, BIT_XNOR_AGG aggregate functions |
#12721 | Add more startup tips to be logged with the jOOQ logo |
#12734 | Address known limitations of MULTISET support |
#12779 | Add support for MySQL COMMENT syntax in DDLDatabase's CREATE TABLE statements |
#12782 | Add DiagnosticsContext.message(): String to give access to a text message |
#12785 | Add DiagnosticsListener::exception to handle exceptions encountered while running diagnostics |
#12807 | Parse and ignore Teradata's COMPRESS DDL clauses |
#12829 | Support parsing H2's undocumented DROP TABLE .. CASCADE CONSTRAINTS syntax |
#12830 | Support DROP TABLE .. CASCADE in Oracle |
#12832 | Improve parser error message when encountering unterminated quoted identifier |
#12834 | Support parsing empty column lists in INSERT statements |
#12836 | Parser should support VALUES constructor in FROM clause without parentheses |
#12838 | Support parsing DATABASE() as synonym for CURRENT_CATALOG() or CURRENT_DATABASE() |
#12840 | Parser improvements thanks to the sqlancer team related test cases |
#12843 | Support parsing LOG(n) without explicit base, based on input dialect |
#12846 | Support parsing alternative H2 and HSQLDB DROP CONSTRAINT c IF EXISTS clause |
#12848 | Support parsing HSQLDB's inline FOREIGN KEY syntax |
#12862 | Upgrade all relevant R2DBC dependencies to 0.9.0.RELEASE |
#12874 | Upgrade org.jetbrains:annotations dependency to 23.0.0 |
#12875 | Annotate all blocking execution methods with org.jetbrains.annotations.Blocking |
#12877 | Improve blocking call error message when trying to run Query.execute(), etc. with R2DBC |
#12883 | Add DSL.nullCondition(), a condition that correctly represents the NULL / UNKNOWN predicate value |
#12893 | Add an Replacers.listening(Replacer, BiConsumer<QueryPart, QueryPart>) to allow for listening to QueryPart.$replace() events |
#12894 | Add accessors for Select::$limit, ::$limitPercent, $limitWithTies, ::$offset |
#12896 | Add Settings.renderOptionalAssociativityParentheses |
#12905 | Emulate expressions in LIMIT .. OFFSET where not natively supported |
#12906 | Add a QOM.UCommutativeOperator utility with methods like $swap() |
#12911 | QOM type accessors should accept Collection when they return UnmodifiableList |
#12912 | Add missing Select.$groupBy(), $orderBy(), setter accessors |
#12914 | Document QOM API outside of the QOM type, and annotate it as @Experimental |
#12920 | Add Traversers.recursing() |
#12921 | Replace internal org.jooq.impl.Finder utility by Traverser API usage |
#12945 | Add Field<Result<Record[N]>>.mapping(Function[N]<T[N], E>): Field<List<E>> kotlin extension functions |
#12959 | Gradle examples should list the usual commercial groupIds |
#12973 | Add Traversers.containing(Predicate<? super QueryPart>) |
#12989 | Update R2DBC dependency to 0.9.1.RELEASE |
#13000 | Add Replacers.decomposing(): Replacer to decompose a compound statement into equivalent individual statements |
#13001 | Refine Replacer Javadoc |
#13004 | Add a TableElement type, a super type of Field<?> | Constraint | Index |
#13014 | Add support for providing a --schema to the ParserCLI |
#13031 | Add a rootPath property to the LiquibaseDatabase configuration for the FileSystemResourceAccessor |
#13037 | Add documentation for the new FormattingProvider |
#13070 | Change Function[N] to be non-experimental |
#13072 | Remove experimental status on Row[N].mapping(Function[N]) |
#13077 | Bump postgresql from 42.3.2 to 42.3.3 |
#13078 | Add internal Tools.CONFIG as a convenience for Tools.CTX.configuration() |
#13093 | Remove a few redundant null checks in jOOQ's internals |
#13097 | Add Converters.forArrayComponents(Converter<T[], U[]>): Converter<T, U> |
#13104 | Reimplement SQL Server RETURNING emulation using QueryPart.$replace instead of SchemaMapping |
#13109 | Add Settings.parseIgnoreCommercialOnlyFeatures |
#13118 | Pull up Field::convert, ::convertFrom, ::convertTo methods to SelectField |
#13129 | Add Context::predicandSubquery |
#13131 | Add sections to the manual about using Table references as GroupField, SelectField |
#13132 | DSLContext.fetchValue(SelectField<T>) should work with Table<R> |
#13135 | Generate mapping() deconstruction convenience methods on generated Tables if <recordsImplementingRecordN/> is set |
#13137 | Change default for <pojosEqualsAndHashCode/> code generation option to true |
#13142 | Add JSONFormat.mutable(), XMLFormat.mutable() |
#13143 | Add code generation flags to turn off the recognition of jOOQ-specific types |
#13157 | Remove Oracle work around for JSON_ARRAYAGG causing ORA-40590: invalid format in Oracle 21c |
#13161 | Add support for array bindings for the PostgreSQL HSTORE, INET, and CIDR types |
#13162 | SchemaVersionProvider etc should be looked up using context classloader, too |
#13183 | Add Javadoc warnings to UpdatableRecord::fetchChildren, and TableRecord::fetchParent about the N+1 problem |
#13188 | Add support for the LTREE data type in the jooq-postgres-extensions module |
#13192 | Add SQLDialect.MARIADB_10_7 |
#13194 | Various third party dependency updates |
#13195 | Add a SQLDialect.SQLITE_3_38 dialect |
#13201 | Add SQL Server JSON_ARRAY support via JSON_MODIFY |
#13223 | Emulate inline indexes in CockroachDB |
#13224 | Document declaration vs reference rendering mode of Field, Table, WindowDefinition, Parameter, CommonTableExpression |
#13244 | Upgrade kotlin dependency to 1.6 |
#13246 | Add more examples to manual section "codegen-database-version-providers" |
#13248 | Amend manual sections about data types (XML, Spatial, JSON) |
#13255 | Support casting VARCHAR to XML / XMLTYPE in Oracle |
#13260 | Add DAO.deleteById(T) overload |
#13264 | Manual anchors should be generated from text, not from XSL generated ID |
#13267 | Make QOM::unmodifiable public, internal |
#13271 | Add support for SQLite 3.33 UPDATE .. FROM |
#13272 | Add support for SQLite 3.35 ALTER TABLE DROP COLUMN |
#13275 | Add SQLite 3.35 support for CTE MATERIALIZED hint |
#13277 | Add support for SQLite 3.35's built-in math functions |
#13278 | Add support for inverse hyperbolic functions ASINH, ACOSH, ATANH, ACOTH |
#13281 | Add more explicit links to Record::from and RecordUnmapper wherever this applies |
#13284 | Add support for T-SQL FOR XML EXPLICIT clause |
#13286 | Emulate SQL/XML XMLELEMENT and XMLATTRIBUTES in SQL Server using FOR XML EXPLICIT |
#13287 | Emulate SQL/XML XMLCOMMENT in T-SQL |
#13288 | Emluate SQL/XML XMLCONCAT in T-SQL |
#13289 | Support XMLQUERY() and XMLEXISTS() also in SQL Server |
#13306 | Separate QOM.Ln (natural logarithm) from QOM.Log (logarithm with base) |
#13324 | Code generation output shouldn't print table mapping output, if it's the same as the input |
#13325 | Refactor internal FieldMapForUpdate to support the row assignments, too |
#13326 | Emulate UPDATE .. FROM with MERGE, where available |
#13329 | Add a FieldOrRowOrSelect nominal union type |
#13334 | Add native support for MySQL's derived column lists starting from SQLDialect.MYSQL8_0_19 |
#13335 | Add Table::as and TableLike::asTable overloads accepting Collection<? extends X> for derived column lists |
#13336 | Generate covariant overrides for Table.rename(Table) and Table.as(Table) methods |
#13342 | Refactor Multiset::jsonxArrayaggEmulation |
#13391 | Add support for the FOR XML BINARY BASE64 clause |
#13393 | Replace internal usage of DatatypeConverter::parseBase64Binary by java.util.Base64 |
#13399 | jOOQ-checker should system property defaults that apply to the entire checked code |
#13400 | Add native Informix MULTISET and nested ROW support |
#13410 | Add a "Don't Do This" page to the manual |
#13417 | Add native EXASOL ROWNUM support |
#13432 | Add <visibilityModifier/> code generation option to <forcedType/> |
#13434 | Add <columns/> to <syntheticObjects/> to generate synthetic columns |
#13437 | Add Definition.isSynthetic() to indicate that a jOOQ-meta object has been created synthetically |
#13446 | Add H2_2_0_202 support for UPDATE .. RETURNING and DELETE .. RETURNING |
#13457 | New configuration to generate implicit join definitions ALWAYS from foreign key name |
#13458 | PI() emulation should be ACOS(-1) rather than ASIN(1) * 2 |
#13461 | ResultQueryTrait::getFields should accept Supplier<ResultSetMetaData> instead of ResultSetMetaData |
#13467 | KotlinGenerator should generate open properties in generated records |
#13471 | Add Scope.creationTime() and make it available through GeneratorContext.renderTime() |
#13482 | Upgrade H2 dependency to 2.1.212 |
#13485 | Add a QOM.UOpaque marker interface for non-traversable QueryPart types |
#13486 | Replace internal ConstantSortField by noField() |
#13496 | Specify the various Scope subtype's lifecycle in their Javadoc |
#13497 | Add BindingScope, a common super type of the various BindingXYZContext types |
#13502 | Add a reactive transaction API |
#13508 | Add MySQL support for INSERT .. ON DUPLICATE KEY UPDATE .. WHERE |
#13516 | KotlinGenerator should generate implicit joins path accessors as properties |
#13523 | Add support for parsing ! (bang) as equivalent to . (dot) in MS Access identifiers |
#13525 | Improve Documentation for DSLContext.fetchStream() and related methods |
#13528 | Document <implicitJoinPathsToOne/> flag |
#13534 | Avoid rendering PostgreSQL native cast operator :: which cannot be used in Hibernate native queries |
#13538 | Add a <T, E> Field<Result<R>>.collecting(Collector<R, ?, E>) kotlin extension function, and similar |
#13540 | Remove "inline" and "reified" keywords from jOOQ-kotlin extensions where unnecessary |
#13544 | Remove EXPERIMENTAL remark from ad-hoc converter and MULTISET construction API |
#13546 | Stop aligning generated POJO members and constructor arguments in columns |
#13552 | Change DSL.multiset(Select<R>) into DSL.multiset(TableLike<R>) |
#13553 | Add TableLike<R>.asMultiset(): Field<Result<R>> |
#13556 | Consistently use org.jooq Maven groupId across the manual |
#13558 | Add a PrefixSuffixGeneratorStrategy to jOOQ-codegen |
#13571 | Emulate the PostgreSQL ON CONFLICT .. EXCLUDED pseudo table in MERGE emulation |
#13572 | Add SQLDialect.MYSQL_8_0_20 |
#13573 | Add parser support for the PostgreSQL EXCLUDED pseudo table and MySQL VALUES() syntax |
#13578 | Add native support for BITXNOR in H2 |
#13579 | Add documentation to the manual for bitwise aggregate functions |
#13582 | DefaultRecordMapper should check whether user is attempting to map into an inner class |
#13591 | Add a new ColumnElement type |
#13594 | Change the Java 17 distribution to --release 17 |
#13599 | Let Context extends ExecuteScope |
#13605 | Add JSONtoJacksonConverter, JSONBtoJacksonConverter, XMLtoJAXBConverter implementations |
#13607 | Add JSONtoJacksonConverter, JSONBtoJacksonConverter, XMLtoJAXBConverter forcedType configuration convenience |
#13616 | Scala extensions should have some multiset convenience |
#13618 | Document EnumType::lookupLiteral's nullable result |
#13631 | Add Context.topLevel() and Context.topLevelForLanguageContext() to give access to the top level QueryPart type that is being rendered |
#13632 | DDLDatabase should have a sql property, as an alternative to scripts |
#13634 | Add Field<Record[N]>.mapping(Function[N]<T[N], E>): Field<E> kotlin extension functions, and the Scala equivalent |
#13642 | Add a section about security to the manual's reference section |
#13650 | Settings.emulateMultiset should have NestedCollectionEmulation.JSON as default in PostgreSQL |
#13657 | Ability to download OSS edition snapshot |
#13666 | Support Oracle JSON data type in DDL |
#13670 | Add support for Oracle SYS.XMLTYPE in plain SQL templates |
#13679 | Upgrade HSQLDB to 2.6.1 |
#13693 | JPA code examples should produce a jakarta.persistence.* import |
Breaking changes
#12430 | Make Java 17 the baseline for the jOOQ Open Source Edition |
#12772 | Continue work on public query object model API |
#12781 | Remove pre 3.7 deprecated API and pre 3.7 documentation |
#12895 | Rename QOM.UOperator[N]::constructor to ::$constructor |
#12904 | Remove redundant limit(int) and offset(int) overloads |
#12910 | Add DSL.emptyGroupingSet(): GroupField for explicit empty grouping sets |
#13028 | Generated DAOs should use an embeddable's referencingName, not name for the fetchByXYZ() and fetchRangeOfXYZ() methods |
#13053 | java.lang.NoClassDefFoundError: org/postgresql/util/PGInterval when rendering SQL without the pgjdbc dependency |
#13068 | Change selectFrom(Table<R>) methods to selectFrom(TableLike<R>) |
#13080 | Standard SQL MULTISET emulation using XML produces a null Result |
#13082 | SQL Server MULTISET as JSON emulation of empty subquery produces NULL instead of empty Result |
#13094 | Throw an exception when calling ConvertedDataType.getArrayDataType() when the type has a custom Binding |
#13114 | SelectField.as() should return SelectField<T>, not Field<T> |
#13115 | Change Table::getType to Table::getTableType |
#13116 | Rename QOM.RowField to QOM.RowAsField |
#13149 | Let Query.keepStatement() return CloseableQuery and ResultQuery.keepStatement() return CloseableResultQuery |
#13181 | MULTISET emulation using SQL/XML doesn't correctly distinguish between NULL and '' |
#13208 | SQL Server JSON_OBJECT should implement NULL ON NULL semantics by default |
#13307 | Change $number() arguments in experimental QOM function types to $value() |
#13426 | DSLContext::fetchFromJSON and ::fetchFromXML wrongly assume dialect specific data types in header |
Deprecations
#13005 | Deprecate FieldOrConstraint |
#13071 | Deprecate the org.jooq.Internal annotation |
#13542 | Replace SPI default implementation class (e.g. DefaultExecuteListener) by default methods in interface |
Bug Fixes
#1049 | Better GREATEST() and LEAST() emulations for SQL Server using MAX() or MIN() with VALUES() correlated derived table |
#5612 | Inline enum values should be cast to their enum type just like inline bind variables |
#6133 | Cannot combine CREATE TEMPORARY TABLE .. AS .. with ON COMMIT .. |
#7362 | Excess parentheses generated in NOT operator |
#7783 | Nested row value expressions produce String column types when concrete type information should be available |
#8614 | Passing arrays of generated tableRecords to a stored procedure generates SQL that won't parse due to cast ::any[] |
#8681 | Wrong SQL generated for connectByRoot(minus(one())) |
#9981 | Some BooleanDataKey values should be reset when entering a new scope |
#10277 | CAST to PostgreSQL enum type lacks type qualification |
#10304 | Unnecessary parentheses generated in ConditionAsField |
#11114 | CAST should generate qualified type when casting to Table::getDataType or UDT::getDataType |
#11424 | Improve the alignment of GenerationTool INFO log |
#11441 | Inlining PostgreSQL CHAR(len)[] types produces VARCHAR[] instead |
#11509 | batchStore(), batchInsert(), etc. with StatementType.STATIC_STATEMENT throws java.sql.BatchUpdateException |
#11552 | UpdatableRecord::merge doesn't work in the presence of a unique constraint and in the absence of a primary key value |
#11637 | FilePattern cannot load classpath resource from within jar file |
#11722 | Code generator cannot handle tables from other schemas than PUBLIC referencing H2 enum domain types |
#12036 | Timestamp Arithmetic fails with ConvertedDataType |
#12134 | Support deserialising binary data in MULTISET emulations |
#12269 | Records detached when converting nested multiset |
#12287 | Replace calls to System.currentTimeMillis() by Clock usage |
#12428 | DDL export no longer exports INDEX WHERE clause |
#12525 | Nesting of converters causes unexpected Exception |
#12783 | Feature Comparison on website is different from docs |
#12788 | Support SQLite columns having no data type declaration |
#12794 | Parser and code generator does not recognise H2 2.0's BINARY VARYING and other standard SQL data type synonyms |
#12795 | Upgrade H2 dependency to 2.0.206 |
#12801 | GroupConcat renders string_agg separator argument within wrong parentheses |
#12804 | Add parser support for Teradata's { UPDATE | DELETE } .. ALL syntax |
#12811 | DAOImpl.findOptionalById shouldn't be final |
#12818 | GROUP_CONCAT doesn't work as window function |
#12820 | Parser doesn't support Derby's FOR BIT DATA data type modifier |
#12824 | Parser cannot handle 1. decimal syntax in SELECT |
#12825 | Parser shouldn't parse Teradata cast syntax based on Settings.parseAppendMissingTableReferences, but only based on the parseDialect() |
#12852 | Parser can't handle TRIM (FROM <value>) syntax |
#12854 | jOOQ Open Source Edition code generation doesn't work PostgreSQL 11 or less because of ERROR: column pg_attribute.attgenerated does not exist |
#12855 | Bump spring-core from 5.3.13 to 5.3.14 |
#12858 | Computed column related support annotations claim SQLDialect.POSTGRES instead of SQLDialect.POSTGRES_12 |
#12864 | OSS Edition H2 INSERT .. RETURNING no longer works if columns are qualified with a schema |
#12868 | The DATA_RENDERING_DATA_CHANGE_DELTA_TABLE qualification omission doesn't work correctly in the presence of scalar subqueries |
#12884 | Upgrade jOOQ-checker's error_prone_core's transitive protobuf dependency to mitigate CVE-2021-22569 |
#12888 | Parser should treat AS optional in CREATE TABLE AS SELECT |
#12890 | Parser fails to parse SET SCHEMA 'string-literal' |
#12908 | Select::$replace loses GROUP BY clause |
#12916 | Select.$where(), $having, $qualify(), $connectBy(), $connectByStartWith() don't actually return null in the absence of a predicate |
#12917 | Wrong SQL generated when InlineDerivedTable is transformed using $replace() |
#12922 | Bump h2 from 2.0.206 to 2.1.210 |
#12923 | Upgrade H2 to 2.1.210 |
#12925 | Work around H2 issue 3398 which hangs the process when using FINAL TABLE (MERGE ...) |
#12929 | NullPointerException when mapping NULL nested ROW from scalar subquery |
#12930 | Nested ROW projection emulation doesn't work in scalar subqueries |
#12931 | DAOImpl#deleteById(Collection<T>) ignores Converter |
#12938 | Outdated implementation examples in manual's MULTISET section |
#12939 | maven-deploy.sh should have same description in --repository flag as maven-deploy.bat |
#12944 | Consider improving invalid JDBC URL error messages in class generation |
#12951 | GenerationTool should handle JDBC driver returning null Connection on Driver::connect |
#12954 | Typo in manual section "codegen-ddl" |
#12955 | Wrong code generated for identity columns in H2 1.4 |
#12956 | Can no longer store/retrieve blob data exceeding 1M in H2 2.0 |
#12966 | NullPointerException in MetaDataFieldProvider when reading plain SQL column without a name in MySQL |
#12970 | jOOQ Open Source Edition does not generate routine with long name |
#12976 | Bump postgresql from 42.3.0 to 42.3.2 |
#12977 | Jooq holds onto connections when using r2dbc |
#12979 | Upgrade the pgjdbc dependency to 42.3.2 due to CVE-2022-21724 |
#12982 | Bump postgresql from 42.2.8 to 42.2.25 in /jOOQ-examples/jOOQ-spark-chart-example |
#12983 | Outdated JAXB dependency in manual tutorial |
#12991 | Typo in manual section "codegen-tables" |
#12992 | Code generation <indexes/> flag should turn on <tables/> as a dependency |
#12993 | [jOOQ/jOOQ#12992] Automatically enable table generation if indexes are enabled |
#12994 | Typo in manual section "fetching" |
#13008 | Compilation error in KotlinGenerator output when implicit join path cache conflicts with keyword |
#13010 | [#13008] Unquote keyword when mapping one to many relation |
#13013 | Interpreter does not correctly interpret CREATE INDEX .. WHERE |
#13023 | Record.formatJSON(Writer) and Record.formatXML(Writer) should flush the writer |
#13029 | SQLDataType.XYZ.getArrayDataType().getTypeName() and getCastTypeName() should produce standard SQL XYZ ARRAY type |
#13033 | DSL.function not replacing schema for function call in generated SQL |
#13034 | SchemaMapping should apply Settings.defaultCatalog even if Settings.defaultSchema doesn't apply |
#13035 | SchemaMapping should cache result of Settings.defaultCatalog or Settings.defaultSchema application |
#13040 | AbstractRecord.from(String[], TableField[]) no longer works as expected |
#13043 | Avoid generating H2 NUMBER type alias for NUMERIC types |
#13048 | Settings.parseRetainCommentsBetweenQueries doesn't work for the last comment |
#13054 | java.lang.IllegalArgumentException: Cannot create a VALUES() constructor with an empty set of rows when using JSON_ARRAY(ABSENT ON NULL) in PostgreSQL |
#13058 | NullPointerException when using CAST(x AS user-defined-type) with SQLDialect.JAVA |
#13060 | Typo in Records.intoArray(Class) Javadoc |
#13073 | Order of calling DataType.asConvertedDataType(Converter) and DataType.getArrayDataType() should not matter |
#13076 | Bump postgresql from 42.2.25 to 42.3.3 in /jOOQ-examples/jOOQ-spark-chart-example |
#13081 | Cannot use H2 enum values in JSON documents |
#13085 | Field.sortAsc() should not hard wire NULLS FIRST behaviour |
#13089 | MySQL's BIT(1) type doesn't map correctly in MULTISET subqueries |
#13107 | Register array types of built-in types in internal static type registry |
#13113 | Manual dialects translations for nested records emulations is wrong |
#13117 | Bad deserialisation of UDT TIMESTAMP value in the presence of a Converter in PostgreSQL |
#13119 | Nested record projection should generate ROW constructor keyword for rows of degree 1 in PostgreSQL's RETURNING clauses |
#13120 | Cannot use RETURNING with 2-level nested ROW expressions in SQL Server |
#13124 | Sequence.nextvals() doesn't work with DSLContext.selectFrom() |
#13138 | Bad JSONFormat rendering of nested records |
#13144 | ClobBinding shouldn't call Clob.length() in Firebird |
#13147 | Context::scopeMapping should return @NotNull QueryPart |
#13148 | Prevent Context::scopeMapping to apply when wrapperFor(X) is equal to X |
#13156 | Work around Oracle / ojdbc bug where JSON_ARRAY() can't combine bind parameter marker with FORMAT JSON |
#13163 | Compilation error when PostgreSQL stored function has an ANY[] data type reference |
#13169 | Incorrect parsing of (NULL) row literal in PostgreSQL for nested records, UDTs, etc. |
#13170 | NPE in INSERT .. ON DUPLICATE KEY emulation when defaulted PRIMARY KEY value isn't supplied in Oracle |
#13174 | ERROR: could not determine data type of parameter when projecting PostgreSQL UDT bind value |
#13184 | UNNEST table expression does not maintain derived column list |
#13189 | Feedback about manual section "codegen-ddl" |
#13196 | Db2 RowAsField emulation using JSON_OBJECT is lacking RETURNING BLOB when using the JSONB emulation |
#13200 | MULTISET nested record as JSON_OBJECT() emulation (Db2, SQL Server) doesn't work for records with more than 10 fields |
#13202 | SQL Server CREATE TABLE statement should generate VARBINARY(MAX) for BLOB |
#13204 | Boolean values aren't serialised correctly in SQL Server JSON documents |
#13211 | KotlinGenerator cannot read existing catalog/schema version |
#13212 | [#13211] Use square brackets for KotlinGenerator |
#13216 | Change Sakila database such that all ID types are INTEGER |
#13217 | Work around xerial SQLite driver's Clob behaviour when data is null |
#13220 | SQLite's JSON operators don't retain boolean three-valued logic |
#13226 | Wrong escaping of string literals in doubly nested EXECUTE IMMEDIATE blocks for DDL emulations |
#13230 | UNNEST with array argument doesn't work in Oracle when used with derived column list |
#13237 | ORA-03001: unimplemented feature when nested row emulation produces double quotes in Oracle identifiers |
#13240 | Code generation fails with H2 2.1.210 when using MySQL execution mode |
#13245 | Bump liquibase-core from 4.4.3 to 4.8.0 |
#13251 | Error when nesting ROW() expressions with values instead of with fields, with degree > 22 |
#13252 | Cannot insert data into PostgreSQL XML column due to missing cast |
#13273 | INSERT .. ON DUPLICATE KEY { IGNORE | UPDATE } emulation should consider all UNIQUE keys on SQLite |
#13276 | Wrong code generated for SQLite table with unnamed primary key and unique constraints |
#13290 | NullPointerException in Result.formatJSON(), formatXML(), formatCSV(), formatHTML() when a Record is null |
#13302 | H2TableDefinition with H2 2.0+ produces wrong code generation output when the run mode is Oracle |
#13311 | QOM API mutators on Select type don't copy OFFSET .. LIMIT and a few other clauses |
#13315 | Compilation error in generated UDTRecord's POJO constructor if the UDT contains arrays of table records |
#13319 | Generated records shouldn't have a @ConstructorProperties annotation on their POJO constructor |
#13340 | Wrong precision documented in forceIntegerTypesOnZeroScaleDecimals manual section |
#13341 | jOOQ internals shouldn't create unnamed derived tables |
#13348 | Internal deprecation note on FieldsTrait::field leaks into generated code |
#13349 | Select.asTable() should delay slow call to Tools::autoAlias |
#13355 | Invalid code generated when pojosEqualsAndHashCode option is enabled and column name is 'other' |
#13364 | Result::formatXML does not escape type names |
#13379 | Generated SQL Server code uses `sp_executeSQL`, which fails for binary (case sensitive) collations |
#13383 | Invalid SQL generated in Oracle 11g when query has LIMIT clause and scalar subqueries without explicit aliases |
#13392 | Generated column name for binary bind values shouldn't use Java's byte[].toString() |
#13395 | Bump spring-core from 5.3.16 to 5.3.18 |
#13396 | Update spring-core dependency to 5.3.18 to mitigate CVE-2022-22965 |
#13403 | MULTISET and ROW generated nested records should not have their changed flags set to true |
#13415 | GroupConcat renders string_agg separator argument within wrong parentheses in EXASOL |
#13422 | Dead links in manual for nested class Javadocs |
#13424 | Duplicate headers in manual where there exist redirects |
#13429 | DSL.noCondition() isn't applied correctly to aggregate FILTER WHERE clause |
#13439 | No warning is logged when readonly columns or rowids are not used |
#13447 | Upgrade to org.postgresql:postgresql:42.3.3 to mitigate CVE-2022-26520 |
#13454 | ARRAY_AGG cannot aggregate array columns in H2 |
#13465 | Expressions based on computed columns must not retain computation reference |
#13468 | Work around SQLite INSERT .. SELECT .. ON CONFLICT bug |
#13473 | SQLException when calling oracle.jdbc.driver.ArrayDataResultSet.getMetaData() |
#13479 | Bump spring-core from 5.3.18 to 5.3.19 |
#13488 | org.jooq.SQL and manual should document plain SQL templating's capability of recognising :named parameters |
#13489 | ArrayIndexOutOfBoundsException when rendering PostgreSQL plain SQL template containing ?@ |
#13499 | Improve implementation of QualifiedName.hashCode() |
#13503 | Parser meta lookups don't work for INSERT .. SELECT .. RETURNING |
#13509 | MariaDB, MySQL, Oracle, SQL Server may ignore MULTISET subquery ORDER BY clause |
#13513 | LoaderLoadStep.execute() shouldn't have @CheckReturnValue annotation |
#13536 | Wrong documentation for <printMarginForBlockComment/> |
#13543 | NullPointerException when rendering CTE without a top level context |
#13545 | DSL.quotedName(String[]) should produce QualifiedName only if argument array length != 1 |
#13555 | Field::likeIgnoreCase should cast lhs operand just like Field::like and Field::similarTo |
#13557 | MySQL / MariaDB generated columns with enum type are not generated as readonly |
#13560 | Invalid SQL generated for Oracle when selecting multiple unaliased rows |
#13563 | INSERT .. RETURNING emulations shouldn't acquire multiple connections from ConnectionProvider when using ThreadLocalTransactionProvider |
#13574 | UpdatableRecord::merge might produce wrong update count if generated keys can't be fetched |
#13581 | Excess parentheses generated in unary ~ (QOM.BitNot) or - (QOM.Neg) operators |
#13600 | Bump spring-core from 5.3.19 to 5.3.20 |
#13601 | Derby boolean expressions have to be wrapped in parentheses when passed to COALESCE |
#13608 | Distribute jOOQ-postgres-extensions also with the commercial distributions |
#13611 | UnsupportedOperationException when selecting single nested row with JSON column |
#13624 | Manual documents wrong artifactId for |
#13625 | Wrong code generated for Oracle package procedure SYS.DBMS_STATS.GATHER_DATABASE_STATS |
#13635 | Test container does not close in example |
#13636 | Close testcontainer in example |
#13643 | Wrong result column type for requested conversion when reading JSONB_ARRAY and JSONB_OBJECT nested in ROW in DB2 |
#13647 | DefaultRecordUnmapper should cache AbstractRow and record type |
#13660 | PostgreSQL ON CONFLICT .. WHERE .. DO NOTHING generates not valid SQL |
#13663 | Remove the "modern IDEs" section from the manual |
#13664 | Avoid ambiguous reference when using Table<R> as SelectField<R> for table conflicting with column |
#13667 | Link.$schema() is Nullable |
#13671 | Oracle doesn't support ORDER BY in UPDATE .. SET correlated subquery |
#13673 | Settings.returnAllOnUpdatableRecord doesn't work for UPDATE queries in HSQLDB |
#13676 | Improve <inputCatalog/> warning message in code generator |
#13681 | Cannot use scalar subquery originating from MULTISET in JSON_OBJECT() VALUE clause in Db2 |
#13691 | Manual should link JDBC types to Javadoc |
Version 3.16.0 - January 5, 2022
This release tackles two long standing and complex feature requests that users have asked us to offer for a long time: a public API for manipulating jOOQ's query object model (QOM), and spatial support.
New Query Object Model (QOM)
Every jOOQ query is modeled as an expression tree constructed via our intuitive DSL. For some use-cases there exist historic model API versions (e.g. SelectQuery), but those models aren't readable or transformable. We're now starting to offer most of our expression tree model as a public API for users to consume and manipulate. Every expression tree element has a corresponding type in org.jooq.impl.QOM. Every type provides access to its components using "$" prefixed method names, e.g.:
// Create an expression using the DSL API: Field<String> field = substring(BOOK.TITLE, 2, 4); // Access the expression's internals using the model API if (field instanceof QOM.Substring substring) { Field<String> string = substring.$string(); Field<? extends Number> startingPosition = substring.$startingPosition(); Field<? extends Number> length = substring.$length(); }
The new API is experimental and might change in the next minor release.
Licensed power users will get auxiliary APIs to traverse and transform the expression tree, e.g. traversal:
// Contains 7 query parts long count2 = BOOK.ID.eq(1).or(BOOK.ID.eq(2)) .$traverse(Traversers.collecting(Collectors.counting());
Or replacement:
// Contains redundant operators Condition c = not(not(BOOK.ID.eq(1))); System.out.println(c.$replace(q -> q instanceof QOM.Not n1 && n1.$arg1() instanceof QOM.Not n2 ? n2.$arg1() : q ));
The above prints the following, having removed the redundant NOT operators:
"BOOK"."ID" = 1
This new API is very powerful for even more sophisticated dynamic SQL use-cases, such as:
- Optimising SQL expressions as the above NOT NOT example
- Row level security
- Soft deletion
- Shared schema multi tenancy
- Audit column support
- And much more (stay tuned for future blogs and out-of-the-box transformations)
For more info, see:
- https://www.jooq.org/doc/dev/manual/sql-building/model-api/model-api-design/
- https://www.jooq.org/doc/dev/manual/sql-building/model-api/model-api-traversal/
- https://www.jooq.org/doc/dev/manual/sql-building/model-api/model-api-replacement/
Spatial support
A long awaited feature that starts shipping to our commercially licensed customers is spatial support. Many dialects support the ISO/IEC 13249-3:2016 SQL standard extension, and finally, so do we.
jOOQ introduces new auxiliary data types for GEOMETRY and GEOGRAPHY data to use as standardised bind variables, containing WKB or WKT data, as well as a variety of out of the box functions and predicates.
Future versions will add more support for other functions and dialects.
New dialect and versions
Another new officially supported SQL dialect has been added to all jOOQ editions including the jOOQ Open Source Edition: YugabyteDB. This was a sponsored integration, thank you very much Yugabyte!
Other dialects have upgraded versions, meaning:
- We support this version in all editions now
- The jOOQ Open Source Edition now requires this version if applicable
The versions are:
- Firebird 4.0
- H2 2.0.202
- MariaDB 10.6
- PostgreSQL 14
- Oracle 21c
Computed and readonly columns including ROWID
A lot of dialects support computed columns ("generated" columns), and we now support those as well in jOOQ. For most use-cases, this does not affect jOOQ usage, but especially when writing CRUD code, the new readonly column feature can be very helpful to avoid having to exclude computed columns manually from the CRUD operation.
This also includes a new, improved ROWID support, where users can choose to work with a synthetic ROWID column instead of the primary key, when performing CRUD operations.
All of these features are available in the commercial jOOQ editions.
Jakarta EE
We've moved on from Java EE to Jakarta EE dependencies. This change is currently backwards incompatible because:
- It greatly facilitates maintaining the related code
- It prevents tons of user problems resulting from having both dependencies
- We're not actually integrating tightly with Java EE / Jakarta EE
The following Jakarta EE modules are affected:
- JAXB, which we're using to load our configuration objects.
- Validation, whose annotations can be generated by the code generator.
- JPA, which is used by the DefaultRecordMapper and the JPADatabase
If this breaking change causes issues, please get in touch at https://github.com/jOOQ/jOOQ/issues/9641
Various improvements
As with every minor release, a lot of smaller improvements have been implemented. Some highlights include:
- PostgreSQL procedures are now supported in code generation and at runtime.
- SQLite JSON support has been added, which includes the MULTISET emulation!
- A lot of MULTISET / ROW improvements have been implemented
- R2DBC 0.9 has been released, and we've upgraded our dependency
- The Java 17 distribution now requires Java 17 instead of Java 16
- Pre jOOQ 3.6 deprecations have been removed
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.15-3.16
Features and Improvements
#982 | Add support for spatial extensions |
#4764 | Reduce log level of most DefaultRelations messages from INFO to DEBUG |
#4845 | Add support for additional Firebird 3.0 features |
#5306 | Add support for the standard SQL <data change delta table> |
#6492 | Add support for computed columns |
#7425 | Integration test jOOQ also on the module path |
#7965 | Review manual for places to explain that in jOOQ, views = tables |
#8388 | Add code generation option to generate a synthetic, readonly ROWID column |
#8431 | Add support for PostgreSQL 11 procedures |
#8543 | Support FILTER for GROUP_CONCAT |
#9310 | Add support for MariaDB 10.3 PERCENTILE_DISC, PERCENTILE_CONT, MEDIAN functions |
#9367 | Create a SQL dialect version support manual page |
#9542 | Remove deprecated reference to org.sonatype.oss:oss-parent |
#9609 | Add SQLDialect.H2_2_0_202 |
#9864 | Add support for readonly columns |
#9931 | Add a new DSL.systemName type |
#10022 | Remove Alias.SUPPORT_DERIVED_COLUMN_NAMES_SPECIAL3 on SQLDialect.H2_2_0_202 |
#10039 | Add support for the Oracle 21c WINDOW clause |
#10051 | UpdatableRecord.merge() should support fetching generated keys, where possible |
#10149 | Modularise jOOQ-meta, jOOQ-codegen and others |
#10710 | Make org.jooq.impl.CombinedCondition a binary expression |
#10881 | Enum literals should be defined by generator strategies |
#10935 | Add documentation for formatChart() |
#11109 | Add SQLDialect.ORACLE21C |
#11120 | Add DSLContext.fetchMap(ResultQuery<? extends Record2<K, V>>) and fetchGroups(ResultQuery<? extends Record2<K, V>>) |
#11415 | Support parsing the JDBC escape syntax { call ... } |
#11465 | Add JSON support for SQLite via the JSON1 extension |
#11627 | Add ParseListener.parseStart() and parseEnd() events |
#11670 | Add support for GROUP BY DISTINCT |
#11834 | Let Table<?> extend GroupField |
#11864 | Add more startup tips to be logged with the jOOQ logo |
#12005 | Emulate DML in WITH using data change delta tables |
#12021 | Address known limitations of MULTISET support |
#12102 | Add support for MariaDB 10.6 |
#12116 | Support nesting ROW in MULTISET |
#12120 | Spring Boot example should use `@SpringBootApplication(exclude = { R2dbcAutoConfiguration.class })` |
#12128 | Document lack of correlated MULTISET support in Db2, H2, MariaDB, MySQL 5.7 |
#12146 | Split MCVE template into 3 modules for Java, Scala, and Kotlin |
#12151 | Add a cache for Tools.fieldName() and fieldNameString() |
#12163 | Add support for TO_CHAR in Db2 |
#12177 | Remove "These are currently generated" from single page manual and PDF manual |
#12193 | Upgrade R2DBC dependency to 0.9.0.RELEASE |
#12195 | Improve formatting of XMLELEMENT() |
#12206 | Add an R2DBC example project to our examples |
#12222 | Avoid reflection with ParserImpl.IGNORE |
#12231 | Add support for enums in PostgreSQL R2DBC |
#12235 | Avoid maven per-execution configuration in manual, if unnecessary |
#12236 | Add missing DSL.dateSub() overloads |
#12249 | Support parsing Oracle 21c's JSON construction convenience syntax |
#12255 | Let RowIdImpl implement toString(), equals(), hashCode() |
#12304 | Add Configuration::formattingProvider to offer various formatting related SPIs |
#12305 | Add missing @NotNull annotations to TXTFormat, CSVFormat, JSONFormat, XMLFormat, ChartFormat |
#12322 | Add support for SQLDialect.POSTGRES_14 |
#12344 | Add DMLQuery<R> as a common super type for Insert<R>, Update<R>, Delete<R>, Merge<R> |
#12348 | Add parser support for DML in CTEs |
#12367 | Add another jOOQ testcontainers example that includes using Flyway |
#12371 | Add ParseContext.characters() to access and replace the SQL char[] |
#12385 | Upgrade ojdbc dependency to 21.3.0.0 and require its module name com.oracle.database.jdbc |
#12394 | Parser should accept 1 and 0 as boolean literals in MySQL |
#12405 | CLI programs should set java.util.loggin.SimpleFormatter.format if not already set |
#12407 | Add a SQLDialect.YUGABYTEDB dialect |
#12408 | Make the OSGi imports for jackson and gson modules optional |
#12415 | Add native support for BIT_AND_AGG() and BIT_OR_AGG() in PostgreSQL |
#12423 | Offer alternative EnumConverter constructor accepting Function<U, T> as a Converter::to implementation |
#12425 | Add public query object model API draft |
#12427 | Extract bitwise operations into their own classes |
#12431 | Extract arithmetic operations into their own classes |
#12432 | Extract CompareCondition and CombinedCondition into their own classes |
#12457 | Generate some Javadoc on implicit join path navigation methods |
#12470 | Add better Javadoc documentation about what Class<T> literals can be passed to DSL.val(Object, Class), etc. |
#12476 | Change source, target, and release level to 17 for Java 17 distribution |
#12484 | Manual should point to JDK 17 Javadoc |
#12488 | Log warning in code generator when wrong runtime version is used |
#12501 | Offer more Settings flag in ParserCLI and TranslationService |
#12506 | SQLDialect.supportedBy() and supportedUntil() should specify that they're inclusive in their Javadoc |
#12507 | Improve some internal Nullable / NotNull annotation usage |
#12509 | DefaultConverterProvider should be able to convert from JSON(B) to the usual JSON types and back |
#12513 | Add new Functions.nullOnAllNull(FunctionN) and nullOnAnyNull(FunctionN) |
#12528 | Add ExecuteScope, a Scope that knows about an ExecuteContext |
#12529 | Add nullability annotations to BindingXYZContext types |
#12530 | Let Function1 <: Function and Function2 <: BiFunction |
#12538 | Add Settings.parseRetainCommentsBetweenQueries |
#12539 | Better seek clause examples |
#12566 | JDBCUtils::safeClose methods should debug log stack traces |
#12574 | Add ExecuteContext::resultLevel and ::recordLevel to indicate the Result and Record nesting level |
#12582 | ControlFlowSignal should use Throwable(String, Throwable, boolean, boolean) super constructor |
#12583 | Add DAO.findOptionalById() |
#12585 | Use INFO level instead of WARNING level for routines with more than 254 parameters |
#12592 | JPADatabase should log a WARNING message if it cannot find any entities on the classpath |
#12601 | Produce compilation error if code generator version doesn't match runtime version |
#12604 | Add SQLDialect.FIREBIRD_4_0 |
#12620 | Document that the asterisk may lead to column order mismatches |
#12625 | Manual examples shouldn't re-create Gson or ObjectMapper instances all the time |
#12630 | The JavaGenerator.printDeprecationIfUnknownType should hint at a UDT being in a different schema |
#12644 | Upgrade Spring Boot example to Spring Boot 2.6 |
#12658 | Add HANA support for ON DUPLICATE KEY UPDATE et al |
#12662 | Add H2 support for ON CONFLICT ON CONSTRAINT |
#12663 | Add EnumType.<E extends EnumType>lookupLiteral(Class<E>, String) and generate E.lookupLiteral(String) methods |
#12664 | Support distinguishing between STORED and VIRTUAL computed columns |
#12667 | Add Source.of(InputStream, int) and Source.of(Reader, int) to create length limited sources |
#12681 | Add JooqLogger.getLogger(Class<?>, int) to create a logger whose number of messages are limited to some number |
#12691 | Support parsing single element IN predicate without parentheses |
#12692 | Development version of the manual should include a disclaimer in the header |
#12720 | Split manual section about CREATE TABLE into multiple subsections |
#12725 | Manual section "daos" should link to "codegen-daos" |
#12728 | Add support for Informix stored procedures |
#12737 | Add DataType.isSpatial() |
#12758 | Bump log4j-core from 2.16.0 to 2.17.0 |
#12759 | Additional SQL statements after JDBC connection |
#12766 | Mention fetchSingle() in the manual section about fetching |
Breaking changes
#9641 | Migrate Java EE dependencies to Jakarta EE |
#9676 | Add support for H2's data change delta tables |
#12109 | Remove pre 3.6 deprecated API and pre 3.6 documentation |
#12127 | R2DBC execution should wrap R2dbcException in DataAccessException |
#12212 | Unnecessary generic type parameter in localDateAdd and other date time arithmetic functions |
#12586 | Remove DB2DataType.ROWID |
#12633 | Move XSDs from jOOQ and jOOQ-meta to subpackages to avoid split xsd packages |
#12757 | Experiment with sealed classes |
Deprecations
#12238 | Deprecate Internal.fieldsRow(TableField) |
#12420 | Deprecate PostgresDSL.oid() and replace its usage by actual OID columns |
#12465 | Deprecate IGNITE dialect again |
Bug Fixes
#3035 | INSERT .. RETURNING does not return any value in H2, when no AUTO_INCREMENT column is involved |
#3398 | Avoid generating new SQL statements for every bind variable length in Firebird 3 |
#4311 | Usage of jOOQ API inside of ConnectionProvider.acquire() causes issues with Oracle cross-schema OBJECT type bindings |
#8205 | Use JDK 9 Matcher.replaceAll(Function) instead of Matcher.replaceAll(String) where possible |
#9129 | Support parsing ALTER TABLE ... ADD ... AUTO_INCREMENT |
#9136 | Wrong SQL generated in DB2's NTH_VALUE() IGNORE NULLS window function |
#9162 | Parser missing type information for Enum fields |
#9917 | Codegeneration fails with case sensitive data types in postgres 9.0 or less |
#10423 | Bad translation of identity to CockroachDB |
#10866 | Generator produces an invalid enum with an underscore "_" as the name |
#11386 | Avoid streaming SQL Server FOR JSON or FOR XML in chunked results |
#11401 | Improve JSON_VALUE formatting |
#11659 | Upgrade Liquibase dependency of jooq-meta-extensions-liquibase to 4.x |
#11703 | Parser can't parse functions receiving operator based string expressions |
#12025 | Parsed DATE_ADD and DATE_SUB don't translate correctly when lacking column meta data |
#12104 | R2DBC nested subscription loops forever when nesting or sequencing INSERT .. RETURNING run on r2dbc-pool |
#12108 | Operator called default onErrorDropped: PostgresConnectionClosedException when chaining queries |
#12117 | ORA-06550 when calling a PL/SQL procedure with a %ROWTYPE parameter that has DATE fields when dateAsTimestamp=true and javaTimeTypes=true |
#12118 | Regression in SQLite code generation for unnamed composite pkeys on JDK 9+ with the jOOQ Open Source Edition |
#12123 | Regression in ResultQuery.fetchMap(Field, Field) with null values |
#12125 | Wrong Support annotation: HSQLDB doesn't support MULTISET or MULTISET_AGG |
#12130 | Wrong deserialisation of temporal data types in MULTISET XML emulation |
#12131 | DefaultConverterProvider should be able to convert both ISO timestamp formats to Timestamp and LocalDateTime |
#12135 | MULTISET emulation doesn't correctly deserialise single column record containing only a NULL value in SQL Server |
#12136 | IndexOutOfBoundsException when deserialising MULTISET as XML emulation with NULLs |
#12139 | MULTISET as JSON emulation using JSON_ARRAY must use NULL ON NULL clause |
#12141 | Data conversion error converting "TIMESTAMP to JSON" in H2 |
#12144 | Regression when binding JSONB value containing a JSONB string in PostgreSQL |
#12148 | Setter return type must be Unit & '@set:' annotations could be applied only to mutable properties |
#12149 | DSL.using(String, String, String) based R2DBC Connection does not use provided username and password |
#12150 | [jOOQ/jOOQ#12149] Use username and password properties for r2dbc connection |
#12155 | Nested multiset record mapping fails at the 3rd level of nesting |
#12158 | MULTISET/JSON emulation can't read TIME type in Db2 |
#12160 | Error when embedding a timestamp in Db2 XMLELEMENT |
#12168 | Deeply nested MULTISET produce quoted JSON in MariaDB |
#12174 | Unnecessary finalizer registration in DefaultConnectionProvider |
#12181 | SQL Server doesn't correctly serialize TIME bind values in FOR XML and FOR JSON usage |
#12183 | An R2dbcException wrapping DataAccessException should properly produce sqlState() and other properties |
#12187 | The XML MULTISET_AGG emulation doesn't work with unnamed bind values in Db2 |
#12189 | Db2 cannot handle scalar subqueries in JSON_OBJECT in the presence of a MULTISET ad-hoc converter |
#12192 | INSERT .. RETURNING doesn't work in H2 when a composite key does not have the identity as its first column |
#12194 | MySQL DELETE .. USING with JOIN produces duplicate table declarations in USING clause |
#12197 | The DataKey.DATA_PREPEND_SQL and DATA_APPEND_SQL feature must work on Query only, not other QueryParts |
#12200 | SelectOnStep::onKey returns wrong type, preventing combinations of join predicates |
#12201 | Error when embedding a timestamp in Db2 XMLATTRIBUTES |
#12208 | Deeply nested MULTISET mappings with ad-hoc conversion doesn't work when using reflection |
#12210 | Aliasing implicit join paths produces invalid queries |
#12216 | Remove references to javax.annotation.Generated from jooq-codegen Javadoc |
#12225 | DefaultConverterProvider truncates timestamps to milliseconds precision when converting from Timestamp to LocalDateTime |
#12237 | Embeddables cannot be placed in MULTISET |
#12240 | NullPointerException in MetaImpl.MetaTable.getReferences() when there are catalog conflicts in SQL Server |
#12244 | Inconsistent formatting of table list when using generated or non-generated aliased tables |
#12247 | Replace remaining reflective call to OracleConnection.createARRAY from DefaultBinding |
#12253 | Long lists are no longer wrapped when rendering formatted SQL |
#12260 | NullPointerException when reading empty results for MULTISET_AGG / JSON emulation |
#12262 | Delay initialisation of Jackson, Gson, JAXB classes in Convert |
#12265 | Custom data type binding example in manual works only on JDBC, not R2DBC |
#12267 | jOOQ 3.15.0 XSD is not published? |
#12277 | Wrong method name used in manual section schema-diff |
#12278 | Empty subsection in manual section codegen-config-generator |
#12281 | IllegalArgumentException: Minimum abbreviation width is 4 when TXTFormat::minColWidth is less than 4 |
#12286 | java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema when running examples from manual tutorial |
#12289 | In manual section jooq-in-7-steps-step3, fix multi line shell syntax |
#12291 | Reference to database and/or server name in 'master.sys.schemas' is not supported in this version of SQL Server. |
#12306 | Wrong table list to ANSI join transformation when tables are qualified and aliased |
#12307 | Wrong result for Table or Field.getQualifiedName() on aliased table(Name) or field(Name) |
#12308 | MockDataProvider cannot handle MULTISET fields |
#12315 | Wrong procedure declaration generated in MySQL when using IN parameters with VARCHAR(length) types |
#12316 | ParseListener example doesn't compile, should use onParseCondition(), not onParseField() |
#12324 | Wrong (+) to LEFT JOIN transformation in join tree A⟕B, A⟕C, A⋈D |
#12327 | ImmutablePOJOMapper cannot map more than one nested POJO on the same level |
#12328 | Empty select() should not project asterisk if unknown table is used with leftSemiJoin() or leftAntiJoin() |
#12332 | Result.formatChart() produces bad default formatting for Display.HUNDRED_PERCENT_STACKED |
#12333 | IndexOutOfBoundsException when calling Result.formatChart() on an empty result |
#12340 | Improve <dialects/> to display correct number of dialects for operators |
#12345 | Inline floating point formatting shouldn't depend on default Locale |
#12357 | Wrong SQL example in manual section multiset-value-constructor |
#12363 | Nested Block generates top-level anonymous block behaviour when top level Statement is not a Block |
#12364 | Spelling mistake in manual section "jooq-with-flyway" |
#12373 | ClassCastException when using returning() with R2DBC |
#12375 | NullPointerException in OracleDatabase.getArrays0() |
#12379 | Wrong type documented in INSERT .. RETURNING section of the manual |
#12381 | DSLContext.explain(Query) doesn't work with bind values in Oracle |
#12386 | Positional window functions without ORDER BY should generate ORDER BY 1 in Oracle |
#12399 | FOR JSON emulation must use RETURNING CLOB in Oracle |
#12413 | DataTypeException in multiset with a mapped nested row |
#12417 | BIT_AND_AGG(), BIT_OR_AGG() emulations shouldn't use bind values |
#12434 | CVE-2021-26291 via maven-core-3.6.3 dependency |
#12437 | Avoid generating overloaded table valued functions with compilation errors, until they are supported |
#12440 | Compilation error in KotlinGenerator generated code when @set:JvmName is applied to overriding property |
#12441 | Fix generating multi-key DAOs with Java records |
#12442 | Compilation errors in generated code when using <daos/> with <pojosAsJavaRecordClasses/> |
#12446 | Unnecessary cast in Db2 when comparing value with concatenation |
#12459 | KotlinGenerator setter return type must be Unit also for records |
#12463 | H2 enum values which contain brackets are not generated as Java literals |
#12468 | MockFileDatabase example doesn't compile |
#12469 | InlineDerivedTable shouldn't inline when used in outer joins |
#12480 | DSL.arrayGet() does not generate required parentheses |
#12491 | api-diff generates wrong nested class Javadoc links |
#12492 | Clarify whether .offset(..) starts from 0 or 1 |
#12495 | Ignored COMMENT ON CONSTRAINT syntax should support qualified object identifiers |
#12498 | Meta does not produce correct DataType::nullable information when data type isn't supported |
#12499 | Wrong documentation in section "codegen-database-regex-flags" |
#12500 | Unable to fetch Instant field within a multiset |
#12502 | NPE in Query.equals() when Query isn't attached |
#12508 | Cannot map JSON(B) in MULTISET when mapping with Jackson from DefaultConverterProvider |
#12516 | Field with Converter<String, Boolean> inside multiset causes JSON parsing error on Oracle |
#12520 | Parser should support PERCENTILE_CONT / PERCENTILE_DISC with expressions as percentiles |
#12527 | DefaultExecuteContext.LOCAL_SCOPE is reset to null when nesting lazy executions |
#12537 | ParserCLI interactive mode ignores setting booleans to false |
#12543 | ParserCLI interactive mode can't handle leading /* comment block |
#12544 | Field<Instant>.div(int) regression for Instant fields that have a converter |
#12545 | Lenient support for H2's time zone format when using the Instant type |
#12549 | Wrong JSON_MERGE_PRESERVE function generated when embedding JSON in MULTISET in MariaDB and MySQL |
#12557 | Add support for unwrapping Optional types in DefaultConverterProvider |
#12561 | ROWNUM transformation doesn't work when projecting an expression containing ROWNUM |
#12564 | Exception in LoggerListener when projecting top level row(...).mapping() |
#12568 | Connection leak when ExecuteListener::fetchEnd throws an exception |
#12589 | CockroachDB IDENTITY column recognition is broken |
#12596 | ParamType.INLINED produces wrong behaviour for Settings.cacheParsingConnection |
#12599 | Incorrect MERGE statement syntax generated in FIREBIRD when aliasing USING derived table |
#12602 | Parser cannot parse INSERT .. SELECT without column list |
#12611 | SQLDataType.null generated when using XMLDatabase with lower case array type |
#12612 | Generated column in table valued function of type TIMESTAMP without precision is generated using precision zero |
#12638 | OracleDatabase::sequences produces query that doesn't work on older ojdbc driver versions |
#12639 | typo in jOOQ-academy setup script |
#12640 | OracleDatabase doesn't produce correct CYCLE sequence flag information in code generation |
#12645 | Parser should support PostgreSQL date part syntaxes with explicit type casts |
#12649 | Parser parses and ignores NOT keyword after column expression |
#12655 | Fix Firebird Support annotations on INSERT .. ON DUPLICATE KEY UPDATE as well as UpdatableRecord.merge |
#12659 | Wrong SQL generated for PostgreSQL functions returning single UDT OUT parameters |
#12666 | Restore streaming bind value method behaviour on ParsingStatement |
#12669 | Blob.length() and Clob.length() calls shouldn't be silently downcast to int |
#12674 | HanaTableDefinition reports all computed columns as identities |
#12675 | MariaDBDatabase no longer generates check constraints |
#12678 | Potential resource leak in SettingsTools static initialiser |
#12683 | Regression in code generation catalog mapping |
#12697 | Mapped JSON in multiset causes multiple ad-hoc conversions |
#12700 | Single element IN predicate without parentheses uses wrong operator precedence |
#12704 | DefaultRecordUnmapper.IterableUnmapper uses name based field access instead of index based ones, leading to ambiguities |
#12706 | Cannot nest MULTISET in top level ROW in PostgreSQL |
#12712 | Parser mis-interprets KEY columns as MySQL KEY (INDEX) specification if unquoted and of type VARCHAR(n) |
#12713 | Debug log output causes exceptions when data type converter is re-applied incompatibly |
#12718 | Some manual "previous" and "next" links use wrong URL |
#12731 | DB2Database should order routine overloads by signature, not specificname |
#12733 | Update log4j to 2.15.0 because of CVE-2021-44228 |
#12741 | Loader.onDuplicateKeyIgnore doesn't work on tables that don't have a PRIMARY KEY |
#12742 | ListAgg not working with filter clause. |
#12751 | Bump h2 from 1.4.199 to 2.0.202 in /jOOQ-examples/jOOQ-javafx-example |
#12752 | DDLDatabase defaultNameCase property shouldn't affect built in functions in view definitions |
#12753 | SQLDialect.JAVA produces wrong output for quotedName() |
#12755 | DSL.unquotedName() has wrong Javadoc |
#12776 | Compilation errors in generated code when enabling <pojosAsJavaRecordClasses> and <embeddables> |
#12780 | Support generating the PostGIS GEOMETRY type as SQLDataType.GEOMETRY |
Version 3.15.0 - July 6, 2021
R2DBC
What a lot of users have been waiting for: jOOQ 3.15 is reactive, thanks to the new native R2DBC integration. Recent versions already implemented the reactive streams Publisher SPI, but now we're not cheating anymore. We're not longer blocking. Just wrap your R2DBC ConnectionFactory configured jOOQ query in a Flux (or any reactive streams API of your choice), and see what happens.
Flux.from(ctx.select(BOOK.TITLE).from(BOOK));
Both blocking (via JDBC) and non-blocking (via R2DBC) can work side-by-side, allowing users to quickly a query between the two execution models without any changes to the query building logic.
Projecting ROW types, ARRAY of ROW Types, and MULTISETS
After having implemented standard SQL/XML and SQL/JSON support in jOOQ 3.14, another major milestone in taking SQL to the next level is now available as an experimental feature: Nesting collections using the standard SQL MULTISET operator.
The operator is currently emulated using SQL/XML or SQL/JSON. The resulting documents are parsed again when fetching them from JDBC. Future versions will also provide native support (Informix, Oracle), and emulations using ARRAY (various dialects, including PostgreSQL).
Imagine this query against the Sakila database (https://www.jooq.org/sakila):
var result = ctx.select( FILM.TITLE, multiset( select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME) .from(ACTOR) .join(FILM_ACTOR).using(ACTOR.ACTOR_ID) .where(FILM_ACTOR.FILM_ID.eq(FILM.FILM_ID)) ).as("actors"), multiset( select(CATEGORY.NAME) .from(CATEGORY) .join(FILM_CATEGORY).using(CATEGORY.CATEGORY_ID) .where(FILM_CATEGORY.FILM_ID.eq(FILM.FILM_ID)) ).as("films") ) .from(FILM) .orderBy(FILM.TITLE) .fetch();
You're really going to love Java 10's var keyword for these purposes. What's the type of result? Exactly:
Result<Record3<String, Result<Record2<String, String>>, Result<Record1<String>>>>
It contains:
+---------------------------+--------------------------------------------------+---------------+ |title |actors |films | +---------------------------+--------------------------------------------------+---------------+ |ACADEMY DINOSAUR |[(PENELOPE, GUINESS), (CHRISTIAN, GABLE), (LUCI...|[(Documentary)]| |ACE GOLDFINGER |[(BOB, FAWCETT), (MINNIE, ZELLWEGER), (SEAN, GU...|[(Horror)] | |ADAPTATION HOLES |[(NICK, WAHLBERG), (BOB, FAWCETT), (CAMERON, ST...|[(Documentary)]| ...
Two collections were nested in a single query without producing any unwanted cartesian products and duplication of data. And stay tuned, we've added more goodies! See this article on how to map the above structural type to your nominal types (e.g. Java 16 records) in a type safe way, without reflection!
More info here:
- https://www.jooq.org/doc/3.15/manual/sql-building/column-expressions/multiset-value-constructor/
- https://www.jooq.org/doc/3.15/manual/sql-building/column-expressions/aggregate-functions/multiset-agg-function/
New Dialects
We've added support for 5 (!) new SQLDialect's. That's unprecedented for any previous minor release. The new dialects are:
- BIGQUERY
- EXASOL
- IGNITE
- JAVA
- SNOWFLAKE
Yes, there's an experimental "JAVA" dialect. It's mostly useful if you want to translate your native SQL queries to jOOQ using https://www.jooq.org/translate, and it cannot be executed. In the near future, we might add SCALA and KOTLIN as well, depending on demand.
BigQuery and Snowflake were long overdue by popular vote. The expedited EXASOL support has been sponsored by a customer, which is a great reminder that this is always an option. You need something more quickly? We can make it happen, even if the feature isn't very popular on the roadmap.
Many other dialects have been brought up to date, including REDSHIFT, HANA, VERTICA, and two have been deprecated: INGRES and ORACLE10G, as these grow less and less popular.
Drop Java 6/7 support for Enterprise Edition, require Java 11 in OSS Edition
We're cleaning up our support for old dependencies and features. Starting with jOOQ 3.12, we offered Java 6 and 7 support only to jOOQ Enterprise Edition customers. With jOOQ 3.15, this support has now been removed, and Java 8 is the new baseline for commercial editions, Java 11 for the jOOQ Open Source Edition, meaning the OSS Edition is now finally modular, and we get access to little things like the Flow API (see R2DBC) and @Deprecate(forRemoval, since).
Upgrading to Java 8 allows for exciting new improvements to our internals, as we can finally use default methods, lambdas, generalised target type inference, effectively final, diamond operators, try-with-resources, string switches, and what not. Improving our code base leads to dogfooding, and that again leads to new features for you. For example, we've put a lot of emphasis on ResultQuery.collect(), refactoring internals: https://blog.jooq.org/use-resultquery-collect-to-implement-powerful-mappings/
There are new auxiliary types, like org.jooq.Rows and org.jooq.Records for more functional transformation convenience. More functions mean less loops, and also less ArrayList allocations.
At the same time, we've started building a Java 17 ready distribution for the commercial editions, which unlocks better record type support.
Refactoring of ResultQuery to work with DML
With all the above goodies related to Java 8, and a more functional usage of jOOQ, we've also finally refactored our DML statement type hierarchy (INSERT, UPDATE, DELETE), to let their respective RETURNING clauses return an actual ResultQuery. That means you can now stream(), collect(), fetchMap() and subscribe() (via R2DBC) to your DML statements, and even put them in the WITH clause (in PostgreSQL).
Massive improvements to the parser / translator use case
jOOQ's secondary value proposition is to use its parser and translator, instead of the DSL API, which is also available for free on our website: https://www.jooq.org/translate
With increasing demand for this product, we've greatly improved the experience:
- The ParsingConnection no longer experimental
- Batch is now possible
- We've added a cache for input/output SQL string pairs to heavily speed up the integration
- We're now delaying bind variable type inference to use actual PreparedStatement information. This produces more accurate results, especially when data types are not known to the parser.
- A new ParseListener SPI allows for hooking into the parser and extend it with custom syntax support for column, table, and predicate expressions.
CREATE PROCEDURE, FUNCTION, TRIGGER and more procedural instructions
Over the recent releases, we've started working on procedural language extensions for the commercial distributions. In addition to creating anonymous blocks, we now also support all lifecycle management DDL for procedures, functions, and triggers, which can contain procedural language logic.
This is great news if you're supporting multiple RDBMS and want to move some more data processing logic to the server side in a vendor agnostic way.
Explicit JDBC driver dependencies to avoid reflection
To get AOP ready, we're slowly removing internal reflection usage, meaning we're experimenting with an explicit JDBC driver build-time dependency. This currently affects:
- Oracle
- PostgreSQL
- SQL Server
Only drivers available from Maven Central have been added as dependency so far.
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.14-3.15
Features and Improvements
#1729 | Add DSL.aggregate() and DSL.aggregateDistinct() as plain SQL AggregateFunctions |
#1985 | Add support for the EXASOL database |
#2620 | Add support for Google BigQuery |
#3884 | Add support for the MULTISET operator |
#4474 | Allow to form CTE from plain SQL or from ResultQuery |
#4876 | Add Firebird 3.0 support for IDENTITY columns |
#5179 | Add support for returning unique constraints from Meta Table<R>.getKeys() |
#5310 | DataType.toString() should generate DDL type declaration fragment |
#5507 | Add a new jooq-postgres-extensions module for PostgreSQL specific extension |
#5757 | Support batch in DSLContext.parsingConnection() |
#5810 | Emulate Teradata's QUALIFY clause for window function filtering |
#6080 | Add support for multiple ROW nesting |
#6277 | Add SQLDialect.JAVA to generate Java code from a SQL statement |
#6347 | Add TableLike.get(X) kotlin operators as aliases for Table.field(X) |
#6562 | Add a recursive CTE example to the manual |
#6604 | Add multi Row[N] or Record[N] VALUES support |
#6956 | Add support for { CREATE | DROP } TRIGGER commands |
#7100 | Add <U> Field<T>.convert(Binding<T, U>), convert(Converter<T, U>), convert(Class<U>, Function<T, U>, Function<U, T>) |
#7290 | Add DSL.chr(int) |
#7421 | Stop rendering "FROM dual" in MySQL 8+ and MariaDB 10.4+ |
#7520 | Add code generator support for foreign keys in Teradata |
#7536 | Implicit JOIN improvements |
#7789 | Support Java 8 only in Professional and Enterprise Edition |
#7900 | Add support for SQL Server style DATEDIFF(datepart, date, date) |
#8166 | Add support for SELECT .. INTO <variables> for use inside statement blocks |
#8230 | Add support for RAISE or SIGNAL in the procedural API |
#8263 | Add syntax highlighting to /translate |
#8284 | Emulate label-less iterate and leave in DB2, HSQLDB, MariaDB, MySQL |
#8334 | ParsingConnection should cache frequent input / output SQL string pairs |
#8469 | org.jooq.Meta should try parsing default expressions |
#8495 | Avoid copying around lists and arrays in jOOQ's internals |
#8500 | Review callers of Tools#field(T) in AbstractField |
#8521 | Transform MySQL IN (SELECT .. LIMIT) to derived table |
#8714 | Support SQL Server function SQUARE() |
#8715 | Add support for the LOG10 function |
#8775 | Record.get(n) etc, Javadoc could state if n starts from 0 or 1 |
#8821 | Add Settings.parseNamedParamPrefix to support dialect specific named parameter placeholders |
#8888 | Improve HSQLDB Dual table implementation |
#8973 | Create a troubleshooting page in the manual |
#9038 | Add support for the PostgreSQL SPLIT_PART function |
#9087 | Document CallbackExecuteListener |
#9190 | Add support for CREATE FUNCTION and CREATE PROCEDURE |
#9191 | Add support for DROP FUNCTION and DROP PROCEDURE |
#9376 | Document <fluentSetters/> in the manual |
#9472 | Add support for UUID generator functions, such as NEWID() or GEN_RANDOM_UUID() |
#9627 | Add Settings.metaIncludeSystemIndexes |
#9650 | Add support for the Snowflake database |
#9728 | Add <comments/> configuration to allow for generating custom Javadoc on generated code |
#9753 | Change DEFAULT rendering of CURRENT_DATE, CURRENT_TIME, and CURRENT_TIMESTAMP |
#9767 | Built in SQL transformations |
#9804 | Make TableOptions available through code generation to remaining dialects |
#9854 | Add support for DB2 DIGITS() function |
#9945 | Implement generated TIMESTAMP precision in code generation |
#9953 | Add support for nested declarations in Firebird procedural logic |
#10030 | Add a type annotation to all jOOQ API that accepts explicit string types |
#10036 | Add support for BIT_AND_AGG(), BIT_OR_AGG(), BIT_XOR_AGG() |
#10048 | Add logging to BatchCRUD when the number of generated SQL queries is too high |
#10080 | Add a manual section about LATERAL and APPLY |
#10118 | Add support for CockroachDB CREATE OR REPLACE VIEW |
#10150 | Support JDK 14, 15, 16 |
#10175 | Add support for H2 and PostgreSQL array functions |
#10181 | Improve parser performance |
#10229 | Convert should be able to convert types into any type with a single argument constructor |
#10243 | Add ParseListener SPI to parse custom syntax |
#10287 | Add <pojosAsJavaRecordClasses/> to allow for generating Java POJOs as JDK records instead |
#10349 | Add more Settings to enable / disable DefaultRecordMapper mapping algorithms |
#10437 | Get HANA dialect support up to date |
#10505 | Split up manual's JOIN section into different subsections |
#10514 | Improve Settings.parseWithMetaLookups |
#10522 | Emulate UPDATE .. SET row = (SELECT ...) using UPDATE .. FROM for uncorrelated subqueries |
#10528 | Improve procedural language abstraction API |
#10546 | Add { Schema, Meta } . { getUniqueKeys(), getForeignKeys(), getIndexes() } |
#10551 | Add support for Apache Ignite |
#10572 | Various parser bugs / missing features |
#10626 | Add support for CockroachDB CREATE SCHEMA et. al |
#10645 | Add SQLDialect.POSTGRES_13 |
#10690 | Use some newer JDK API when creating a distribution for JDK 17 |
#10724 | Get Redshift dialect support up to date |
#10745 | SQLDialect Javadoc should explain the distinction between commercial and OSS dialects |
#10775 | Add Rows.toRowList() and Rows.toRowArray() methods to create Row[N] arrays and lists |
#10801 | Add JavaGenerator.printDaoConstructorAnnotations() to allow for custom annotations in generated DAO constructors |
#10807 | Meta.migrateTo(Meta) should not produce any diff when timestamp default precision is specified |
#10827 | Add a DSL.currentCatalog() function |
#10829 | Exclude synthetic fields and keys from diff |
#10844 | Implement MetaImpl.getSequences() |
#10851 | Add <visibilityModifier/> to allow for generating explicit / implicit public visibility, as well as internal in KotlinGenerator |
#10873 | Add alternative DSL.key(...).value(...) syntax to produce JSONEntry |
#10883 | Add Table.getUniqueKeys() |
#10893 | Add Javadoc link from SQLDialect to the new version support matrix page |
#10898 | Add Settings.metaIncludeSystemSequences |
#10899 | Add <includeSystemSequences/> to code generator configuration |
#10909 | Enhance MCVE template to also include KotlinGenerator and ScalaGenerator out-of-the-box |
#10913 | Add Database.getPrimaryKeys() and overloads to jOOQ-meta |
#10927 | Add code generator support for SQLite CHECK constraints |
#10932 | Support MySQL 8.0.16 CHECK constraints |
#10936 | Add DataType.null_() and notNull() as synonyms for nullable(boolean) |
#10952 | Add a DDL textarea to /translate |
#10953 | Add additional JSONFormat options to optimise formatting of JSON in the presence of SQL/JSON result set content |
#10962 | Remove Disqus from manual |
#10963 | Parse DEFAULT nextval('<id>_seq'::regclass) as Serial data type |
#10990 | Add support for MERGE in Informix |
#10998 | Add <enumsAsScalaSealedTraits/> to let ScalaGenerator generate Java enums |
#11002 | Remove the outdated manual section about dependencies |
#11009 | Add support for the MySQL FIELD() function |
#11023 | Throw more explicit DataTypeException when Convert fails to convert between JSON/JSONB/XML and a user-defined type |
#11031 | Extract common API from Cursor | Record | RecordType | Result | Row | TableLike | UDT to new Fields type |
#11061 | Parser should look up data types for bind variables from context |
#11063 | Add TableOptions.function(String) |
#11070 | Propagate type nullability through API |
#11074 | Parser should be able to replace expressions for bind variables |
#11076 | Add support for SQLDialect.MYSQL_5_6 |
#11082 | DSL.currentTimestamp(int) is missing |
#11089 | Add parser support for COERCE(x AS <data type>) |
#11091 | Avoid calling DSL.nullSafe() and similar all over the DSL API, move the calls to QueryPart constructors |
#11093 | Use instance methods in parser implementation |
#11097 | Add single argument DSL.function() overload |
#11107 | Parser should parse 3-argument Oracle INSTR function |
#11123 | Add Settings.mapConstructorProperties to allow for opting out of reading the ConstructorProperties annotation in DefaultRecordMapper |
#11125 | Let AbstractQueryPart::configuration return Tools.CTX::configuration |
#11131 | Make functional interfaces F0, F1, F2 public, internal, deprecated |
#11136 | Add Name.qualifierQualified() to check if a Name's qualifier (if any) is qualified as well |
#11154 | Add Javadoc to Map producing API (fetchMap(), fetchGroups()) about map iteration order guarantees |
#11155 | Add documentation for using LiquibaseDatabase with Liquibase's YAML or JSON formats |
#11157 | Add support for COVAR_SAMP and COVAR_POP aggregate and window functions |
#11161 | Add formal support for SQL Server PIVOT clause |
#11172 | Add support for SQLite's fts3 and fts4 virtual tables |
#11176 | Add <includeSystemTables/> to exclude SQLite virtual table implementation tables from code generation |
#11177 | Add further vendor-specific <includeSystemTables/> implementations |
#11180 | Clarify unused logger warning message about what is obsolete |
#11182 | Generate DAO.fetchByXYZ() methods for embeddable types |
#11183 | Generate a record constructor taking a generated POJO |
#11187 | Add DAO.fetch(Field<Z>, Collection<? extends Z>) overload |
#11189 | Improve generated Javadoc formatting |
#11190 | UPDATE .. RETURNING cannot be used Reactively |
#11192 | Add Javadoc remark to code generation flags available to commercial editions only |
#11194 | Add code generation configuration for Javadoc line wrapping |
#11202 | Add documentation for the QUALIFY clause |
#11231 | Support parsing Access ASC() or Firebird ASCII_VAL() functions |
#11237 | Add SafeVarargs annotation to DSL.greatest() and DSL.least() |
#11243 | Emulate FOR UPDATE .. WAIT n using SET LOCAL LOCK_TIMEOUT in PostgreSQL dialects |
#11246 | Add support for TRIGGER pseudo columns DELETING, INSERTING, UPDATING |
#11250 | Add a language context to the ParserContext and RenderContext |
#11252 | Add support for SET LOCAL statements |
#11253 | Add some convenience API for locally overriding Context.paramType(), Context.qualify(), and other flags |
#11254 | Add lambda constructor in CustomField, CustomCondition, CustomQueryPart |
#11269 | Add CreateTableConstraintStep.primaryKey(), unique(), check() convenience methods |
#11279 | Support ALTER TABLE .. RENAME INDEX .. TO .. in SQL Server |
#11318 | Add native support for the standard JSON function RETURNING clause |
#11323 | Add HSQLDB procedural language support |
#11333 | Add parser support for hash style comments (#) in MariaDB, MySQL |
#11336 | Emulate CREATE OR REPLACE in MySQL using compound statements |
#11338 | Add convenience for common bracing / formatting / indenting SQL rendering |
#11344 | Add Context.declareParameters() |
#11356 | Add support for CALL in procedural languages |
#11358 | Add some CSS syntax highlighting to all content in the manual
|
#11359 | Add support for INFORMIX procedural language |
#11360 | Add CustomStatement |
#11367 | Refactor internal ScopeMarkers functionality |
#11369 | Emulate using expressions in Db2 DECLARE .. DEFAULT statements |
#11373 | Add ParamOrVariable<T>, a common super type of Param<T> and Variable<T> |
#11374 | Wrong algorithm to aggregate local variable declarations at the beginning of a block |
#11379 | Update RecordListener documentation to explain this is about UpdatableRecords only, not bulk DML |
#11382 | Add parser support for <explicit table> |
#11383 | Add Configuration.commercial() |
#11389 | Add parser support for PL/SQL style variable declarations in function / procedure headers |
#11390 | Support parsing RETURN statement |
#11393 | Add CockroachDB ENUM type support |
#11394 | Support parsing Teradata's zeroifnull() |
#11402 | Support parsing Teradata's UPDATE .. FROM .. SET syntax |
#11403 | Support parsing Teradata's undocumented SELECT .. GROUP BY .. WHERE clause ordering |
#11405 | Emulate procedural SELECT .. INTO variables in T-SQL |
#11406 | Field.as(unquotedName("@i")) should produce T-SQL aliasing syntax |
#11408 | Procedural DECLARE should support declaring multiple variables, for convenience |
#11410 | Support HSQLDB's procedural destructuring assignment |
#11420 | Support Parsing the MySQL version of the VALUES constructor |
#11421 | Parser should throw exception if not all rows have the same degree in a VALUES constructor |
#11422 | Add parser support for JSON_ARRAYAGG() and JSON_OBJECTAGG() as window functions |
#11429 | Add missing parser support for EXECUTE IMMEDIATE |
#11430 | Add parser support for ALTER TABLE .. DROP .. DROP syntax |
#11432 | Support parsing Db2 style LISTAGG() without WITHIN GROUP clause |
#11433 | Add parser support for ALTER TABLE .. ADD .. ADD syntax |
#11436 | Support parsing UPDATE .. SET (row) = (row | subquery) |
#11449 | Support parsing SQLite MIN() and MAX() functions |
#11450 | Support parsing SQLite's IS [ NOT ] predicate |
#11452 | Add parser support for MySQL's DATE_ADD and DATE_SUB functions |
#11458 | Add support for the ANY_VALUE() aggregate function |
#11461 | MetaTable does not contain table COMMENT (REMARKS) |
#11470 | Add support for the CORR aggregate functions |
#11472 | Document immutability of CSVFormat and related types |
#11481 | Stop using the deprecated JSON_MERGE function in MariaDB 10.4+ and MySQL 8.0.19+ |
#11491 | Add a Settings.forceIntegerTypesOnZeroScaleDecimals |
#11492 | Add jbang example to the manual |
#11494 | Add parser support for OCTET_LENGTH alternative names |
#11499 | [jOOQ/jOOQ#11492] Add jbang catalog |
#11502 | Unknown table identifier when trying to look up CustomTable or TableImpl whose Schema doesn't reference its tables |
#11504 | Default[UnsignedType]Bindings should delegate to integer bindings, rather than implement their own |
#11507 | Add Log.isWarnEnabled() |
#11508 | Emulate procedural RETURN (SELECT ..) statement where not supported |
#11512 | ParsingConnection should infer bind variable type from PreparedStatement calls |
#11520 | Add CallbackXYZListener implementations, and static convenience API on XYZListener |
#11525 | Upgrade scala version to 2.13.5 |
#11530 | Add Configuration.setAppending() and Configuration.deriveAppending() methods to create derived configurations by appending listeners |
#11531 | Add jsonEntry(X, Select<?>) overloads |
#11536 | Document pom.xml plugin inheritance mechanism |
#11543 | Emulate FOR UPDATE .. WAIT n using SET SESSION innodb_lock_wait_timeout in MySQL dialects |
#11547 | Emulate statistical aggregate functions |
#11549 | Add startup tips to be logged with the jOOQ logo |
#11559 | Add parser support for ADD_YEARS, ADD_MONTHS, ADD_DAYS, ADD_HOURS, ADD_MINUTES, ADD_SECONDS |
#11567 | Add Database.getSources(): Map<Definition, String> as an alternative way to produce source code for generated objects |
#11572 | Add versioned dialects for COCKROACHDB 20, 21 |
#11578 | Add DSL.inlined(Field<T>): Field<T> |
#11585 | Remove unnecessary restriction from sequences and domains "Must provide a qualified name of length 1 or 2" |
#11587 | Fix ordering of TOP_LEVEL_CTE |
#11601 | Add a manual section for trueCondition(), falseCondition(), and noCondition() |
#11602 | Support parsing WITH in derived tables or scalar subqueries |
#11603 | Add parser support for WITH nested inside WITH |
#11606 | DefaultRenderContext(RenderContext) constructor should only copy flags |
#11616 | Missing DB2 and Derby @Support on DROP SCHEMA .. RESTRICT |
#11623 | Refactor a few internal checked exception throwing functional interfaces |
#11626 | Add DefaultDataType.getDataType(SQLDialect, int) to lookup JDBC types |
#11633 | ParsingConnection should batch translated statements without having to re-translate the statement several times |
#11640 | Use ojdbc8 API internally |
#11641 | Emulate SPLIT_PART |
#11642 | Emulate OVERLAY in H2 using INSERT |
#11645 | Add procedure support in the VerticaDatabase |
#11647 | Add MySQL SUBSTRING_INDEX() support |
#11648 | Add Db2, Derby, H2 support for POSITION(in, search, startIndex) via LOCATE |
#11649 | Add parser support for Db2's LOCATE_IN_STRING function |
#11650 | Get SQLDialect.VERTICA up to date |
#11654 | Add code generation support for CHECK constraints in Vertica |
#11655 | Emulate statistical window functions in Vertica |
#11656 | Add support for a TO_HEX(number) function |
#11660 | Emulate CONNECT BY LEVEL < x and CONNECT BY ROWNUM < x |
#11666 | Expand unqualified asterisk when combined with other projection expressions and when not supported |
#11672 | Function and QueryPartCollectionView formatting improvements |
#11674 | Add native support for NVL2 where supported |
#11684 | Add a CacheProvider SPI to allow for overriding the default ConcurrentHashMap |
#11688 | Remove experimental remarks from all parser related API |
#11694 | Support parsing TO_DATE(string) and TO_TIMESTAMP(string) |
#11699 | Support parsing Oracle comparison operators with whitespace in between |
#11700 | Add R2DBC support |
#11707 | SQUARE() should be emulated using POWER() if the argument is not a SimpleQueryPart |
#11711 | Use floating point literals for inline DOUBLE, FLOAT, and REAL literals |
#11712 | Support parsing the ** exponentiation operator |
#11718 | Annotate DSL API with @CheckReturnValue to help detect when calling execute() etc is forgotten |
#11719 | Add support for TO_DATE() in SQL Server |
#11729 | Create a Java 17 distribution |
#11737 | Add dialect version support for H2 |
#11738 | Add optional, provided dependency on mssql-jdbc, ojdbc, pgjdbc to avoid reflection |
#11743 | Support parsing Teradata cast syntax |
#11744 | Support the Teradata DATE function |
#11755 | Extract AttachableQueryPart from Query |
#11757 | Add Settings.renderCoalesceToEmptyStringInConcat |
#11763 | Upgrade shaded jOOR dependency to 0.9.14 |
#11772 | Convert should support conversions between ByteBuffer and byte[] |
#11774 | Add a <priority/> to <forcedType/> |
#11778 | DefaultRecordMapper should reflect on Class.getRecordComponents() |
#11779 | Upgrade XJC to com.sun.xml.bind:jaxb-xjc:2.3.4 |
#11780 | Include identity-generated system sequences in PostgreSQL generated code |
#11784 | Add code generation support for Firebird 3.0 stored functions |
#11787 | Add an <includeSystemUDTs/> flag to turn on/off the generation of system UDTs |
#11788 | Add QualifiedRecord and RecordQualifier to unify the Table|UDT and TableRecord|UDTRecord type hierarchy |
#11794 | Improve MappingException message when no RecordMapper implementation could be found |
#11799 | Refactor some internals to re-use a new functional mapping method |
#11800 | Fields.field() methods should add better documentation about what it means when null is returned |
#11801 | Move some Tools content such as Tools.Cache to the top level |
#11803 | Support = ANY and != ALL quantified comparison predicates of degree > 1 for MySQL |
#11804 | Add Records class with common record mapping utilities |
#11808 | Make sure the SQL in MetaSQL is dialect version specific |
#11809 | Add SQLDialect.isVersioned() |
#11810 | RecordMapper<R, E> should extend Function<R, E> |
#11812 | Let Row[N]<T1, T2, ..., TN> extend SelectField<Record[N]<T1, T2, ..., TN>> |
#11813 | Add Row[N]<T1, T2, ..., TN>.mapping(Class<R>, Function[N]<T1, T2, ..., TN, R>) to create a SelectField<R> reference |
#11815 | Change DSLContext.fetchValue(Field<T>) to DSLContext.fetchValue(SelectField<T>) |
#11816 | Add missing ConstraintTypeStep.primaryKey(Collection<? extends Field<?>>) and related overloads |
#11817 | Add Converter.from(Class<T>, Class<U>, Function<T, U>) and Converter.to(Class<T>, Class<U>, Function<U, T>) to create one-way converters |
#11821 | Support parsing Teradata INSERT without VALUES |
#11822 | Translator should offer specifying a default schema / search path |
#11826 | Remove serialVersionUID from jOOQ's internals |
#11829 | Add DataType.row() to track nested ROW types and allow access to their Field<?>[] |
#11831 | Support parsing array(select) |
#11838 | Add Settings.namePathSeparator |
#11843 | Add parser / render support for COUNTIF() |
#11844 | Support parsing Teradata eq, ne, gt, ge, lt, le operators |
#11845 | Transform Teradata style implicit join syntax in the parser |
#11850 | Get SQLDialect.TERADATA up to date |
#11851 | Add Settings.renderImplicitWindowRange handling different default window RANGE clause defaults |
#11854 | Generate identity column information in Teradata |
#11855 | Support parsing CT as Teradata alias for CREATE TABLE |
#11860 | Generate FOREIGN KEY meta data in Teradata |
#11861 | Emulate LISTAGG in Teradata using XMLAGG |
#11863 | Add SingleStore native support for multi row inserts |
#11871 | Document missing ExecuteListener::resultEnd event when ResultQuery::collect and other methods are used |
#11879 | Define rawtype API compatibility strategy |
#11880 | Implement improved INSERT .. ON DUPLICATE KEY UPDATE emulation via MERGE |
#11884 | Refer to DSL.val() in Javadoc to raise awareness |
#11897 | ClassCastException when calling Convert.convert(Object, Class) with a collection |
#11905 | Update Hibernate dependency in jooq-meta-extensions-hibernate |
#11908 | Use the @Deprecate(forRemoval = true, since = "...") flags in the API |
#11925 | Emulate DELETE .. USING where some equivalent native syntax is available |
#11926 | Add parser support for DELETE .. JOIN and UPDATE .. JOIN |
#11927 | Add a Javadoc remark about performance to all the fetch() methods that map results |
#11931 | Support translating DATEADD from Snowflake to BigQuery |
#11932 | CLI APIs should log more helpful error messages on NoClassDefFoundError |
#11938 | Support parsing Snowflake style DATEADD() function with date part as string literal |
#11943 | Add native OFFSET support to Db2 11.1 |
#11960 | Add support for Redshift YEAR TO MONTH interval literals |
#11961 | Get Redshift dialect up to date |
#11964 | Add new DefaultBinding(Binding<T, U>) constructor |
#11979 | Add Configuration.deriveSettings(Function<Settings, Settings>) |
#11985 | Add HANA support for REGEXP_REPLACE |
#11992 | Pull up Fields super type declaration from Select<R> to ResultQuery<R> |
#12002 | Support parsing HSQLDB CALL <expression> statement |
#12011 | BindingGetResultSetContext<T> should offer field(): Field<T> methods |
#12028 | Add MULTISET_AGG aggregate and window function support |
#12030 | Support creating MULTISET predicates |
#12035 | Upgrade kotlin dependency to 1.5 |
#12042 | Improve error message in MockFileDatabase from "Invalid SQL" to something more descriptive |
#12043 | Add DataType.isMultiset() |
#12046 | Add support for XMLSERIALIZE |
#12053 | Add disclaimers about mocking also to Javadoc |
#12055 | Highlight new manual menu items in each version |
#12061 | Improve XML path notation in section jooq-in-7-steps-step3 |
#12065 | Add manual section about scalar subqueries |
#12071 | Add an internal means of ad-hoc table mapping |
#12079 | Avoid auxiliary in-memory table when emulating DML RETURNING in SQL Server, if not strictly necessary |
#12092 | MySQL queries running GROUP_CONCAT() or JSON_ARRAYAGG() should auto-increase the default group_concat_max_len |
#12093 | Add <includeExcludePackageRoutines/> to let code generator <includes/> and <excludes/> match package procedures and functions |
#12110 | Move Sakila database to own repository |
Breaking changes
#3185 | Let InsertResultStep<R>, UpdateResultStep<R>, DeleteResultStep<R> extend ResultQuery<R> |
#7863 | Link Oracle %ROWTYPE references to their corresponding table types |
#9280 | Unsupport Scala 2.10 |
#9288 | Offer Result.intoMap(), intoGroups(), intoSet() functionality as Collector |
#9715 | Render DSL.currentDate() as TRUNC(CURRENT_DATE) in Oracle |
#10803 | Remove jOOQ-refaster from distributions |
#10809 | Dialect specific data type is reported from Meta, instead of SQLDataType |
#10884 | Change jOOQ-meta Relations.getUniqueKeys() to return unique keys only |
#10918 | XMLasDOMBinding and AbstractXMLasObjectBinding should implement Binding<XML, T>, not Binding<String, T> |
#10937 | Add Settings.renderDefaultNullability |
#11053 | Pull up PostgresDSL.array() to DSL.array() |
#11115 | Table.getSchema() should not return the generated schema for aliased generated tables |
#11164 | Remove ResultQuery::fetchLater and ResultQuery.fetchLazy(int) |
#11196 | Drop support for Java 6 and 7 in jOOQ Enterprise Edition |
#11207 | AbstractBinding empty base implementations should throw exception |
#11218 | KotlinGenerator generates Record[N]<T1, T2, ..., TN> for PK types in DAOs, instead of Record[N]<T1?, T2?, ..., TN?> |
#11242 | Remove deprecated on(Boolean), where(Boolean), having(Boolean), etc |
#11286 | Use org.jooq.Meta to discover SQLite primary key, unique key, and foreign key names in code generator |
#11495 | Remove pre 3.5 deprecated API |
#11498 | DSLContext.connection() and connectionResult() shouldn't produce null Connection when detached |
#11511 | Stop casting SQLDataType.OTHER to VARCHAR |
#11625 | GeneratorStrategy references package-private AbstractGenerator.Language class |
#11720 | XResultStep<R> should not extend X<R> for X<R> = Insert<R> | Update<R> | Delete<R> |
#11802 | Add new Transformation enum for Settings with values ALWAYS, WHEN_NEEDED, NEVER |
#11892 | Add Settings.fetchIntermediateResult |
#11901 | Implement more optimal ResultQuery.forEach() method |
#11980 | MockConfiguration set() and derive() calls return delegate instead of MockConfiguration |
#12023 | JSONB equals, hashCode, toString() should be formatting agnostic |
Deprecations
#8611 | Some MySQL encryption functions were removed in MySQL 8.0.x |
#10796 | Deprecate the empty dialect specific DSL classes |
#11092 | Deprecate DSL.nullSafe() and related protected methods, and move them to Tools |
#11129 | Log a warning when users call deprecated Param.setValue(), setConverted(), setInline() |
#11329 | Deprecate XYZFinalStep types |
#11505 | Deprecate DateToLocalDateConverter, TimeToLocalTimeConverter, TimestampToLocalDateTimeConverter |
#11506 | Log deprecation warning when Serialization of jOOQ API is triggered |
#11515 | Deprecate INGRES dialect |
#11618 | Deprecate JDBC41Connection, JDBC41Statement, JDBC41ResultSet |
#11797 | Deprecate Oracle 10g support |
#11898 | Deprecate org.jooq.tools.Convert, the public API |
#11902 | Deprecate RecordHandler |
Bug Fixes
#2815 | Bad SQL rendered in MySQL, when selecting from DUAL with ORDER BY |
#3619 | Result.intoGroups() and intoMap() do not run through RecordListener |
#5851 | VALUES constructor generates wrong SQL if one row contains a null bind variable |
#5865 | Avoid allocation of new internal ConvertAll instances |
#6252 | Infinity values not correctly escaped with PostgreSQL |
#7201 | Incorrect emulation of SELECT DISTINCT .. FETCH NEXT .. ROWS WITH TIES |
#7648 | Issue with insertion with DEFAULT value with H2 and onDuplicateKeyIgnore |
#7721 | OFFSET .. FETCH should not be emulated in Oracle 18c anymore even when projection has duplicate column names |
#8509 | Equals on fields not symmetric |
#8554 | Improve documentation regarding nullable forced types |
#8762 | Improve performance of implicit join algorithm |
#8875 | Field.getDataType().defaultValue() value is 'null' instead of actual value. |
#8917 | INSERT .. RETURNING emulation doesn't work on SQL Server when returning expressions or aliases |
#9067 | StackOverflowError generating code from Postgresql XML schema with ARRAY columns |
#9206 | Wrong implementation of DayToSecond#equals() and YearToMonth#equals() |
#9475 | Support parsing number literals with exponent |
#9553 | Parser cannot parse WITH in EXISTS() and other subqueries |
#10019 | Fetched result is not logged when using collect(), only with fetch() |
#10245 | Blocking subscriber.onComplete called after subscriber.onError |
#10527 | Fix known limitations of embeddable types |
#10529 | Ignore <records>false</records> for UDTRecords |
#10668 | Parser should ignore TRUNC() call when parsing TRUNC(CURRENT_DATE) or TRUNC(SYSDATE) |
#10697 | Address known issues of Settings.transformTableListsToAnsiJoin |
#10699 | Parser cannot parse set operations combining SELECT * with SELECT <column list> |
#10716 | Fix known issues of Settings.transformRownum |
#10760 | Wrong emulation of INSERT .. RETURNING for embeddables on SQL Server |
#10761 | KotlinGenerator produces invalid syntax for PostgreSQL enum types |
#10762 | Wrong XSD schema in org.jooq.Constants#XSD_CODEGEN in version 3.14.0 |
#10767 | Kotlin code generator generates Record with invalid kotlin syntax when a column is named "value" and <recordsImplementingRecordN/> is true |
#10768 | Compilation errors in KotlinGenerator generated classes when tables have array types |
#10769 | Cannot convert from UUID to JSON in H2's JSON_OBJECT() and related functions |
#10771 | KotlinGenerator creates incorrect @Generated annotation |
#10774 | Remove @Nullable annotation from ResultQuery.fetchSingleInto(Class) and Record.into(Class) |
#10778 | Fix compilation errors for Oracle Packages, UDTs, ArrayRecords, Queues, Links in KotlinGenerator |
#10779 | Compilation error in KotlinGenerator generated DAOs for data type TINYINT |
#10782 | Wrong code generated for <jpaAnnotations/> Table annotations with KotlinGenerator |
#10783 | KotlinGenerator does not annotate properties with <jpaAnnotations/> |
#10787 | KotlinGenerator and ScalaGenerator don't produce correct POJO.toString(), equals(), hashCode() methods for array types |
#10788 | DSL.jsonbArray() generates json_build_array() call in PostgreSQL, instead of jsonb_build_array() |
#10793 | Most package-info Javadocs refer to Sybase ASE |
#10797 | Applying a forcedType prevents identity(true) from being generated |
#10804 | NullPointerException when calling MetaImpl.snapshot() on a PostgreSQL schema with function based indexes |
#10805 | Kotlin POJOs with array properties must implement equals() and hashCode() |
#10808 | Converter using primitive types fails when used in UDT array in PostgreSQL |
#10812 | Compilation error in KotlinGenerator generated code when <enumConverter/> flag is turned on |
#10813 | Meta.migrateTo(Meta) produces constraint rename operations for MySQL PRIMARY KEY constraints |
#10817 | MetaImpl should not produce explicit DEFAULT NULL value |
#10821 | Code generation fails in PostgreSQL when grants for enum types are missing |
#10822 | Meta.migrateTo(Meta) should not produce DROP SCHEMA "" calls |
#10824 | Stop using information_schema.table_constraints in PostgresDatabase |
#10825 | Missing INFORMIX dialect in CTE support annotations |
#10828 | Record.get(Field) doesn't work for embeddable table fields when non field-replacing embeddables are projected explicitly |
#10830 | There should be no diff between implicit and explicit ASC ordering in index definitions |
#10834 | Wrong columns requested from Connection.prepareStatement(String, String[]) when running INSERT .. RETURNING with embeddables in HSQLDB and Oracle |
#10835 | KotlinGenerator should produce open classes |
#10837 | KotlinGenerator produces invalid syntax for enums with special characters |
#10839 | DefaultConverterProvider should be Serializable |
#10849 | Deadlock on lazy initialisation of Tables in Scala |
#10852 | Parser fails to parse schema qualified type in CREATE TYPE .. AS ENUM commands |
#10856 | Avoid querying information_schema.columns.datetime_precision in older versions of MySQL 5.7 |
#10858 | <includeSystemIndexes/> doesn't work correctly on MySQL 8.0.22 |
#10864 | Don't create a diff between DECIMAL and NUMERIC types, where they are just aliases |
#10867 | KotlinGenerator should quote identifiers containing $ |
#10869 | KotlinGenerator should escape $ in string literals |
#10871 | Add `yield` to kotlin keywords for use in KotlinGenerator |
#10877 | Compilation error in ScalaGenerator generated code when table has column "CLASS" |
#10882 | Code examples contain excess or missing semi colons |
#10887 | ALTER TABLE code examples shows wrong multi column addition syntax |
#10889 | Meta.filterPrimaryKeys() is not implemented correctly |
#10895 | Attaching configuration to unbound ResultQuery does not work when executed async |
#10900 | Compilation error in KotlinGenerator generated code, when OTHER data type columns have a default value |
#10904 | KotlinGenerator produces compilation error in generated interfaces when <jpaAnnotations/> is set |
#10910 | java.lang.ClassCastException: class java.lang.Class cannot be cast to class java.lang.reflect.ParameterizedType when custom data type extends List |
#10915 | Wrong code generated by KotlinGenerator for <validationAnnotations/> |
#10920 | PostgreSQL supports XMLTABLE only after version 10 |
#10923 | KotlinGenerator produces compilation errors in UDT Records when <recordsImplementingRecordN/> is true |
#10931 | LIMIT without OFFSET is emulated using window functions when value is not a bind variable |
#10934 | Unnecessary ORDER BY (SELECT 0) clause generated in SQL Server when using TOP |
#10939 | Wrong SQL generated for IIF() emulation in MySQL |
#10940 | <includeSystemCheckConstraints/> fails with missing FROM-clause entry for table "alias_18649163" on PostgreSQL |
#10944 | Code generator warning message should refer to deprecated <customType/> only if customType configuration is present |
#10949 | Missing data type display in ParserCLI help listing |
#10951 | JPAConverter may cause DataTypeException if it does not detect the proper <T, U> types using reflection |
#10954 | Unqualified field lookup in ON DUPLICATE KEY UPDATE clause doesn't work |
#10956 | Add missing documentation about throwing of DataDefinitionException in relevant API |
#10964 | Parser should support plural form of DatePart where applicable |
#10968 | Ambiguous field identifier when parsing unions with unqualified columns and parseWithMetaLookups |
#10970 | Unknown field identifier when parsing ORDER BY clauses referencing field aliases with parseWithMetaLookups |
#10972 | jOOQ-checker does not work with error prone 2.4.0 |
#10974 | Support ARRAY_AGG in H2 |
#10979 | XMLDatabase does not produce parameters for overloaded routines |
#10983 | Wrong Oracle style to ANSI JOIN transformation result, depending on predicate order |
#10989 | Wrong SQL generated for INSERT .. SELECT .. ON DUPLICATE KEY IGNORE emulation using NOT EXISTS |
#10992 | Wrong SQL generated when outer and correlated subquery share implicit join path |
#10997 | Compilation error in KotlinGenerator generated code when enum literals conflict with modifier keywords |
#11000 | Parser cannot look up column from tables by same name from different schemas |
#11011 | Subquery IS [ NOT ] NULL predicate should avoid RVE emulation for degree = 1 |
#11014 | JSON_TABLE emulation in PostgreSQL broken |
#11016 | Kotlin POJO generator produces wrong equals/hashCode for binary types |
#11017 | KotlinGenerator should generate equals(other: Any?), not equals(obj: Any?) on pojos |
#11021 | Avoid synthetic ORDER BY clause in window functions if not strictly necessary |
#11022 | The NAME keyword in XMLELEMENT(NAME <name>) should be optional for the parser |
#11025 | Wrong variable binding for boolean values in Oracle and Db2 JSON_OBJECT(), JSON_ARRAY() and others |
#11032 | Compilation errors for <implicitJoinPathsToOne/> when referenced table is called RECORD_TYPE |
#11041 | Bug in documentation for JSON_TABLE |
#11042 | Add support for parsing INSERT .. WITH .. SELECT |
#11043 | NullPointerException when parsing WITH .. INSERT .. SELECT without explicit INSERT column list |
#11045 | Support parsing table aliases in DELETE statements |
#11047 | Code generator does not produce indexes for quoted identifiers in PostgreSQL |
#11050 | Parser doesn't support derived column lists in MERGE |
#11051 | DSL.array(Select) produces bad formatting |
#11055 | RenderQuotedNames.ALWAYS does not work correctly for stored functions |
#11056 | Wrong nullability annotations on Parser.parseSelect() and others, when parsing blank strings |
#11057 | KotlinGenerator should generate kotlin.Deprecated annotation instead of java.lang.Deprecated |
#11062 | Remove deprecated Param.setValue(), setConverted(), setInline() calls from manual |
#11066 | Tests failed for jooq-spring-boot-example |
#11078 | Override CatalogImpl.equals() |
#11086 | Wrong SQL generated when DomainDataType is loaded before base SQLDataType for SQLDialect.DEFAULT |
#11095 | KotlinGenerator should take ParameterDefinition nullability into consideration |
#11101 | Misleading error message when something goes wrong in the code generator |
#11103 | NullPointerException when custom JavaGenerator subclasses don't call JavaWriter.printPackageSpecification() |
#11105 | NullPointerException when GenerationTool is not properly initialised |
#11116 | Cache implicit join path references |
#11118 | Nested records produced by DefaultRecordMapper do not pass through RecordListener lifecycle |
#11132 | ParseWithMetaLookups produces wrong projection on self join |
#11134 | ParseWithMetaLookups looks up columns in Meta that cannot possibly appear in query |
#11139 | ParseWithMetaLookups propagates wrong type from derived table |
#11143 | ParserWithMetaLookups reports ambiguous column in correlated subquery, when there is none |
#11148 | Regression calling Record1<JSON>.into(OtherTableRecord) |
#11150 | Omitting parts of the foreign key in onKey(TableField…) doesn't produce the expected result |
#11165 | Converter should use Jackson kotlin module if available when mapping JSON to kotlin data classes |
#11166 | Wrong SQL generated for Informix STDDEV_SAMP and VAR_SAMP |
#11168 | DataType.convert(Object...) and convert(Collection<?>) don't work for converted data types |
#11179 | Compilation errors in generated DAOs when embeddables use <replacesFields/> |
#11185 | Compilation errors in generated embeddable pojos if the embeddable is located in a "synthetic" schema |
#11191 | Generated code of a routine with TIMESTAMP parameter has too little precision |
#11200 | Multithread deadlock: org.jooq.impl.AbstractField references subclass org.jooq.impl.Val in static initializer |
#11201 | MetaTable::getReferences and MetaUniqueKey::getReferences do not take into account inverseSchemaCatalog |
#11213 | Error mapping a jsonObject field: Cannot convert from LinkedHashMap |
#11216 | JDBCUtils.dialect() should recognise MariaDB versioned SQLDialect |
#11220 | Manual produces wrong Javadoc link for java.beans package |
#11223 | Prevent parsing the same flag twice in CREATE SEQUENCE and ALTER SEQUENCE |
#11224 | DROP TEMPORARY TABLE doesn't generate TEMPORARY keyword in MariaDB |
#11226 | Broken JDK Javadoc links in the PDF version of the manual |
#11228 | Settings.isMapConstructorParameterNamesInKotlin doesn't work for kotlin inline classes |
#11233 | Parser throws IllegalArgumentException instead of ParserException when date_trunc() is parsed with invalid DatePart |
#11235 | Parser fails when union subquery contains correlated subquery |
#11238 | FILTER or OVER clause does not work on JSON_ARRAYAGG() or JSON_OBJECTAGG() functions in H2, MySQL, and PostgreSQL style dialects |
#11239 | Generated order of check constraints does not respect Database::getOrderProvider |
#11244 | SelectQuery.setForUpdate and similar methods do not clear flag when value is false |
#11247 | VariableImpl should render qualified name |
#11255 | Meta.getTables() does not include PostgreSQL foreign data wrapper tables |
#11258 | NullPointerException in MetaImpl.snapshot() when foreign key column order doesn't match unique key column order |
#11259 | NullPointerException when using table valued function without explicit parameters |
#11261 | Interpreter cannot find unique key if foreign key references columns in different order |
#11265 | Internal DataKey.DATA_PREPEND_SQL functionality should be cumulative |
#11270 | Wrong support annotation for FIREBIRD ALTER TABLE .. RENAME |
#11273 | Behavior of MockResultSet.close() differs from ResultSet.close() javadoc |
#11275 | NullPointerException when using InsertSetStep.set(Map) on plain SQL table with plain SQL field names |
#11277 | Wrong Support annotation for Derby DROP { INDEX | TABLE } IF EXISTS |
#11280 | Add native support for CREATE INDEX .. INCLUDE in Db2 |
#11281 | Wrong SQLSTATE handled in Db2's CREATE INDEX IF NOT EXISTS |
#11284 | Wrong emulation of CREATE UNIQUE INDEX .. INCLUDE |
#11287 | NullPointerException in AbstractMeta.copyFK for SQLite when a foreign key references a unique key |
#11290 | Parser parses PRIMARYKEY as PRIMARY KEY |
#11292 | AbstractMeta.getForeignKeys() and other key / index producing methods don't handle namespacing correctly for named keys |
#11295 | POSITION(in, search, startIndex) emulation returns wrong result when search was not found |
#11299 | SQLite's DSL.extract() emulation should render an explicit CAST(STRFTIME(...) AS INT) |
#11302 | Wrong Support annotation on ALTER TABLE .. RENAME CONSTRAINT |
#11304 | ExecuteContext.exception() should accept null exceptions and translate them to an unspecified DataAccessException |
#11307 | PostgreSQL MetaImpl based DataTypes are missing length of array element type |
#11309 | ArrayDataType.toString() should indicate that it's an array type |
#11317 | Wrong documentation of RenderQuotedNames.EXPLICIT_DEFAULT_UNQUOTED |
#11319 | JDBCDatabase produces empty string as default value everywhere |
#11325 | PostgreSQL routines with long names are excluded by code generator |
#11334 | Field.getDataType(Configuration) resets nullability |
#11341 | intoXML() throws NPE exception |
#11343 | Simplify JSONConverterProvider example in the manual |
#11345 | Memory leak regression in DefaultDataType cache |
#11347 | Wrong syntax generated when WITH clause is empty in DSL |
#11348 | BooleanDataKey.DATA_FORCE_STATIC_STATEMENT only forces inlining of bind values, not static statement execution |
#11350 | Missing H2 support on WithStep::selectOne and similar methods |
#11361 | Wrong emulation of the procedural FOR loop with index |
#11366 | Collect nested DECLARE statements in Firebird and pull them up to the top level block |
#11370 | Occasionally repeated BEGIN BEGIN blocks from emulations around DECLARE |
#11376 | Implicit joins don't work inside of procedural logic |
#11377 | DML statements should enter a ScopeStack scope |
#11387 | NullPointerException when using Enums |
#11388 | java.lang.IllegalStateException: Cannot create a DerivedColumnList from a qualified name |
#11398 | Wrong emulation of JSON_OBJECTAGG in Db2 and other dialects for String values |
#11417 | Parser::parseStatements parses DECLARE <decl> BEGIN <stmt> END; into bad structure |
#11427 | Parser doesn't accept INSERT .. SELECT .. ON CONFLICT |
#11435 | Support parsing quoted identifiers containing escaped quotes |
#11437 | Passing an empty array or collection to returningResult() does not match the behaviour of returning() |
#11442 | Plain SQL templates improperly recognise "?<>" as a PostgreSQL operator |
#11443 | BatchedPreparedStatement doesn't work if statement is re-used |
#11446 | Bad formatting for UPDATE .. ROW = ROW statements |
#11447 | Missing CockroachDB support on WITH RECURSIVE method Support annotations |
#11462 | LoaderOptionsStep.commitAfter() is not implemented correctly |
#11466 | DataType::identity Support annotation should list dialects that support identity types |
#11468 | CustomTable.getUniqueKeys() should return super.getUniqueKeys() not super.getKeys() |
#11474 | Cannot parse JSON[B]_AGG() FILTER or OVER clause |
#11475 | Translator should avoid bind variable casts in the absence of schema information |
#11477 | Missing ABSENT ON NULL declarations in JSON_OBJECT emulated by FOR JSON |
#11484 | FILTER clause does not work on JSON_ARRAYAGG() or JSON_OBJECTAGG() functions in Db2 and Oracle dialects |
#11486 | Bad extra derived table generated when INSERT .. SELECT references target table from correlated subquery in MariaDB, MySQL |
#11517 | Support annotation wrong for Derby on DROP VIEW IF EXISTS |
#11521 | ClassCastException when ResultQuery.fetchArray() returns no rows |
#11522 | Wrong precision generated for SQL Server SMALLDATETIME data type |
#11535 | Parser parses incorrect FOR UPDATE OF syntax, depending on dialect |
#11560 | java.lang.ClassCastException: class org.jooq.impl.ResultImpl cannot be cast to class java.sql.ResultSet when mocking Oracle SYS_REFCURSOR procedure |
#11564 | Add a way for emulated table expressions to auto-alias themselves |
#11566 | JDBCDatabase doesn't yet distinguish between TableType.TABLE and VIEW and others |
#11576 | DefaultMetaTableDefinition doesn't consider DataType.identity() flag |
#11579 | Add internal Cascade enum type |
#11580 | fetchParent() doesn't work properly with foreign key referencing just a part from a composed primary key |
#11582 | Avoid auxiliary derived table in SQLite GENERATE_SERIES emulation |
#11586 | Put TOP_LEVEL_CTE marker at DML statement beginning, not SELECT, in SQL Server |
#11591 | Misleading Javadoc about Settings.isInsertUnchangedRecords |
#11596 | ArrayTable doesn't pass derived column list to ArrayTableEmulation |
#11605 | DropTableStep.cascade() and restrict() have wrong dialects in Support annotation |
#11614 | Fix @Support on ALTER TABLE .. RENAME INDEX |
#11621 | Parser wrongly recognises VERSIONS table alias as keyword |
#11629 | Cannot parse MariaDB FOR LOOP syntax |
#11630 | Cannot parse empty blocks |
#11631 | Boolean field expected when parsing NOT(?) |
#11632 | Parser fails when parsing nested not unary operator without parentheses |
#11634 | XMLFormat.quoteNested() is not being considered in Result.intoXML() |
#11638 | Missing DERBY @Support on DSL.date(), DSL.time(), DSL.timestamp() methods |
#11639 | Support parsing DROP SEQUENCE .. RESTRICT |
#11644 | Invert defaults for internal Tools.visitSubquery() parentheses flag |
#11651 | Add parser support for VERTICA IDENTITY column type |
#11652 | Vertica has native support for DECODE |
#11658 | PostgresDatabase doesn't produce CHAR type length for CHAR(n)[] array types |
#11661 | ROWNUM transformation doesn't work in the presence of DISTINCT |
#11663 | Wrong order of WINDOW / QUALIFY clauses |
#11667 | Oracle MetaTable fields do not have identity information |
#11673 | Emulate NVL using COALESCE instead of CASE, where possible |
#11683 | REPLACE should inline empty string parameter, not use val |
#11689 | Code generator regression for SQL Server defaulted parameters |
#11695 | Support parsing "! =" and "< >" and other operators containing white space in Oracle |
#11701 | Bad inlining of Infinity or NaN in PostgreSQL |
#11704 | Support floating point NaN and (-)Infinity values in other dialects |
#11705 | Add parser support for Firebird's BLOB SUB_TYPE syntax |
#11709 | Oracle typed REF CURSOR produce wrong code |
#11721 | Wrong precision for H2 timestamp when using domains |
#11732 | PostgreSQL ON CONFLICT .. WHERE <index_predicate> generates not valid SQL |
#11733 | Column "INFORMATION_SCHEMA.COLUMNS.INTERVAL_TYPE" not found in H2 1.4.197 |
#11740 | Stop using deprecated ojdbc API |
#11747 | TO_CHAR(x) without format is not natively supported in PostgreSQL |
#11749 | Oracle UPDATE .. RETURNING emulation doesn't work for boolean data type rewrites |
#11760 | NullPointerException instead of DetachedException when executing a detached Routine |
#11762 | Regression when using plain SQL H2 array types |
#11767 | ROWNUM transformation should avoid creating derived tables if possible |
#11769 | NPE when ParsingConnection is not attached to an actual connection |
#11783 | Named parameter mapping doesn't work with missing or excess source column values |
#11790 | Oracle DUAL table incorrectly quoted by RenderQuotedNames.ALWAYS |
#11791 | <recordsImplementingRecordN/> no longer works in Scala |
#11818 | Avoid new Integer(...) calls in JSON Parser |
#11819 | Coerce should delegate all QueryPartInternal calls to the wrapped field |
#11832 | Typo in AggregateFunction.keepDenseRankLastOrderBy() Javadoc |
#11841 | Work around Simba for BigQuery's lack of NULL bind variable support |
#11847 | Regression in Teradata where DUAL is no longer quoted |
#11852 | DUAL emulation in Teradata MERGE .. USING DUAL doesn't work |
#11857 | Emulate CASE WHEN EXISTS in Teradata |
#11866 | MemSQL computed columns of type int aren't generated correctly |
#11870 | MiniJAXB cannot read code generation's regexFlags content (an xs:list type) |
#11873 | Code generation error when generating code for Redshift |
#11876 | Regression in OracleDatabase for sequences with large MAXVALUE |
#11883 | jOOQ 3.13 manual refers to not-yet existing jsonEntry(String, Field) |
#11893 | DefaultConverterProvider isn't able to look up value to single-arg constructor conversions |
#11895 | ResultQuery.fetchStream() fetches entire resultset at once |
#11904 | ORDER BY <field index> should resolve nested record emulation |
#11912 | KotlinGenerator generates invalid code when column names X and isX clash |
#11918 | Add Settings.renderOptionalXYZ support to ParserCLI |
#11921 | Wrong position reported for parser meta lookup failures |
#11924 | Incorrect SQL generated for multi table DELETE with JOIN in MySQL |
#11930 | Wrong result displayed for SQRT(4) function call in the manual |
#11934 | Constants.MINOR_VERSION was not updated in 3.14 |
#11936 | Manual section using-jooq-with-jdbctemplate shouldn't use deprecated JdbcTemplate method |
#11953 | Parser grammar does not reflect both possible positions of FROM FIRST / LAST and IGNORE / RESPECT NULLS |
#11954 | Date Add and Date Sub conversion not working for Redshift dialect |
#11958 | BOOL_AND() and BOOL_OR() emulation does not correctly implement FILTER clause |
#11973 | JDBCUtils.dialect(Connection) recognises MYSQL_8_0, not MYSQL_8_0_19 |
#11977 | PostgresDatabase should ignore unknown functions when parsing index column expressions |
#11987 | Parser doesn't support date time arithmetic in DATE_TRUNC arguments |
#12007 | Column "INFORMATION_SCHEMA.COLUMNS.DOMAIN_SCHEMA" and "INFORMATION_SCHEMA.COLUMNS.DOMAIN_NAME" not found in H2 1.4.197 |
#12013 | Support parsing HSQLDB post-fix IF EXISTS in DROP statements |
#12019 | ORA-06550 when calling a PL/SQL procedure with a %ROWTYPE parameter that has DATE fields when dateAsTimestamp=true |
#12020 | Result.formatXML() and formatJSON() do not correctly format nested records |
#12026 | Result.formatXML() re-declares xmlns on each level for nested results |
#12044 | Correctly emulate XMLAGG(...) FILTER (WHERE ...) in Db2, Oracle, Teradata |
#12050 | CAST must not generate length, precision, scale in Oracle PL/SQL context |
#12054 | Wrong comment in manual meta section about the manual |
#12064 | Informix can't handle bind values as arguments to NVL() or COALESCE() |
#12070 | JSON_OBJECT and JSON_ARRAY functions should generate a Name, not a Keyword |
#12072 | Work around Oracle bug where a CASE expression without ELSE clause in JSON_ARRAYAGG causes ORA-40590: invalid format |
#12078 | SQL Server UpdatableRecord.refresh() is unnecessary when calling UpdatableRecord.store() |
#12080 | Generate a FORMAT JSON clause in Oracle's JSON_OBJECT if contents are of type JSON |
#12085 | Work around Oracle's JSON_ARRAYAGG() bugs when aggregate inputs should be DISTINCT |
#12086 | Nested JSON_OBJECT() emulation is wrong in SQL Server |
#12088 | UDT.getQualifiedName() does not produce package qualification for a package UDT |
#12091 | Manual section data-types-oracle-date uses deprecated API |
#12094 | Meta.ddl() produces TIMESTAMP instead of DATE for columns with dateAsTimestamp=true active |
#12105 | Work around Db2 Reply.fill() - insufficient data (-1). Message: Insufficient data. when fetching JSON_ARRAY |
#12106 | Manual section about limit-clause contains broken link about Oracle ROWNUM filtering performance |
Version 3.14.0 - October 19, 2020
In this release, we've sorted our github issues according to user feedback and finally implemented some of the most wanted features, which include better Kotlin support, embeddable types, and domain type support.
In addition to this, we believe that our newly added XML and JSON operation support will be a leading game changer in how ORMs interact with SQL databases in the future.
XML and JSON
Standard SQL has long supported SQL/XML, and since recently, most RDBMS also support standard SQL/JSON or vendor specific variants thereof. While ORDBMS extensions have never seen the adoption they deserve, XML and JSON do. It makes sense to occasionally denormalise data and store documents in the database directly. However, this is not what we're most excited about.
We're excited about our support for all the fancy operators like:
- JSON_TABLE to turn JSON values into SQL tables
- JSON_ARRAY, JSON_OBJECT, JSON_VALUE to construct JSON data from values
- JSON_ARRAYAGG, JSON_OBJECTAGG to aggregate data into nested JSON documents
- JSON_EXISTS to query documents with JSON path
Similar functions are available for XML, like XMLTABLE, XMLELEMENT, XMLAGG, etc. All editions of jOOQ 3.14 support standard SQL XML and JSON operators, and emulate them where non-standard support is available (e.g. PostgreSQL and SQL Server).
The commercial editions also support SQL Server's very convenient FOR XML and FOR JSON APIs, emulating that syntax using standard operators elsewhere. See:
But that's not all of it! If you have Gson, Jackson, or JAXB on the classpath, we can use that to map org.jooq.XML, org.jooq.JSON, org.jooq.JSONB types from your query results to your nested data structures, automatically. See:
These approaches are extremely powerful. In many cases, you might just skip most of your middleware layer and bind a REST or similar endpoint directly to a jOOQ / SQL query, producing JSON for your frontend:
Kotlin support
We've long supported some Scala extensions and a ScalaGenerator. Kotlin is an additional very promising JVM language where a new jOOQ-kotlin module as well as a KotlinGenerator will add a lot of value for your jOOQ/Kotlin integration.
The KotlinGenerator offers, among other things:
- Data class support for generated POJOs
- Property support for generated POJOs, interfaces and records
- Better nullability support
The jOOQ-kotlin module offers some useful extension functions to further improve the experience of the jOOQ/Kotlin integration.
In addition to the above, we've annotated the entire jOOQ API with nullability annotations from JetBrains:
- org.jetbrains.annotations.Nullable
- org.jetbrains.annotations.NotNull
This will remove many of the annoying T! types in your Kotlin/jOOQ code, turning them into T or T? types instead, giving you more confidence.
With these improvements, we've also critically reviewed our existing ScalaGenerator, fixing a lot of bugs.
Embeddable types
One of the biggest new features in jOOQ 3.14 is inspired by JPA, which ships with embeddable types. An embeddable type is an emulation of a database user- defined type (UDT), which are supported natively only in Oracle and PostgreSQL. The biggest gain of such types is to create more semantic, composite data types in your database schema, and profit from the additional type safety.
Our interpretation of the feature is mostly in the source code generator, whose output now becomes even more valuable. All jOOQ editions support the basic infrastructure to pattern-match column sets and turn them into synthetic embeddable types.
In addition to the above, our commercial editions offer some auto configuration of embeddable types in cases where they really shine:
- For primary/unique constraints and their matching foreign keys
- For DOMAIN types (see below)
- Handling overlapping embeddable types
- Allowing for embeddable types to replace their underlying columns
We took the concept a step further than JPA. In jOOQ, embeddable types can act as views on the underlying columns, without replacing them, or as a replacement like in JPA. jOOQ respects all levels of relational modelling, including overlapping constraints and thus allowing for two embeddable types to overlap.
For more information, please refer to:
DOMAIN types
Speaking of types, some database dialects support standard SQL DOMAIN types, which are a simpler form of UDTs. Instead of working with low level technical types like VARCHAR(10), why not give your single-column types a name, and add a few re-usable CHECK constraints to them?
That's what a DOMAIN type is:
- A named type
- Aliasing a technical type, like VARCHAR(10)
- Possibly adding a DEFAULT expression
- Possibly adding a NOT NULL constraint
- Possibly adding a set of CHECK constraints
All of the above is reusable across your schema and if you're commercially licensed, you can even have the code generator auto-generate embeddable types for all of your domains to profit from the additional type safety in Java.
For more information, please refer to:
- https://www.jooq.org/doc/3.14/manual/code-generation/codegen-domains/
- https://www.jooq.org/doc/3.14/manual/code-generation/codegen-embeddable-types/codegen-embedded-domains/
Synthetic constraints
Related to the above improved code generator output are synthetic objects, such as the previously supported synthetic primary keys, and now also synthetic unique and foreign keys.
If you invest heavily in security and re-usable components within your database, you will make heavy use of SQL views. Unfortunately, views do not have any meta data like foreign key constraints - despite the meta data being "obvious" to you the database designer. With synthetic constraints, you can tell jOOQ about your knowledge of underlying constraints.
The main benefits of meta data being available to jOOQ being:
- You can now use implicit joins on views as well
- You can now use the JOIN .. ON KEY syntax on views as well
- You can use embeddable key types from before on views just like on tables
For more information, please refer to:
- https://www.jooq.org/doc/3.14/manual/sql-building/sql-statements/select-statement/implicit-join/
- https://www.jooq.org/doc/3.14/manual/code-generation/codegen-advanced/codegen-config-database/codegen-database-synthetic-objects/
Better MERGE support
We've finally tackled support for more advanced MERGE statement clauses and now support:
- Multiple WHEN MATCHED AND condition THEN UPDATE clauses
- Multiple WHEN MATCHED AND condition THEN DELETE clauses
- UpdatableRecord.merge() and all the related goodies to simplify record merging
Transformations
With the parser and our translator tool https://www.jooq.org/translate, we'll invest more and more in new use-cases for putting jOOQ to use other than as an embeddable DSL in Java.
Our translation capabilities have already been strong, and with a new set of SQL transformations, they become even stronger helping customers migrate off RDBMS A towards RDBMS B (and back, if they made a mistake).
While our website translator is free of charge, the jOOQ library can always be used programmatically, or as a command line utility: https://www.jooq.org/doc/3.14/manual/sql-building/sql-parser/sql-parser-cli/
To make this use-case even more useful, new transformation features have been added, including:
- ROWNUM to LIMIT or to ROW_NUMBER()
- Table lists to ANSI JOIN (including Oracle (+) support)
- Unnecessary arithmetic expressions
This is an exciting area that we'll be exploring for our commercially licensed customers in the future, while even the jOOQ Open Source Edition profits from these improvements. For example, the infrastructure created for transformations finally enabled emulating PostgreSQL's DISTINCT ON clause, elsewhere.
For more information, please refer to:
- https://www.jooq.org/doc/3.14/manual/sql-building/queryparts/sql-transformation/
- https://github.com/jOOQ/jOOQ/issues/10054 (future work)
Better manual
We've taken a step back and reviewed a few important parts of our documentation. We're now offering:
- Sticky tabs for code generator techniques (XML, Programmatic, Gradle): If you're using Gradle with jOOQ's code generator, you don't want to look at the XML configuration again, in the manual. These tabs finally hide unneeded information.
- Subsections for each function: We've started documenting each SQL function individually, explaining how it works in SQL, and providing some examples and example results.
- Generate example vendor specific rendering of SQL: We're using jOOQ when generating the manual, translating some jOOQ API usage to all of our supported dialects, and displaying how the function renders in each dialect.
- Show imports button and display context sensitive imports: All the examples in the manual can be overwhelming. We're assuming a lot of (static) imports, which we're finally documenting in an expandable "show imports" section of each code fragment.
- We've rewritten some sections to be much more complete with examples, such as the data import section.
- A new API diff page displays what has changed between each minor release in terms of list of Javadoc links: https://www.jooq.org/api-diff
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.13-3.14
Features and Improvements
#229 | Enhance API to provide access to ARRAY elements |
#681 | Add support for type DOMAINs |
#1571 | Add support for REGEXP_REPLACE() |
#1962 | Improve formatting of SQL rendered by window functions |
#2230 | Add support for INTERVAL data types in code generator |
#2530 | Add support for "fetch groups" or "embedded record types", where a group of fields is defined as a reusable RowN type across various tables |
#2961 | Add UpdatableRecord.merge() |
#3419 | Add support for intercepting PreparedStatements, collecting individual bind value sets into larger batch sets |
#3505 | Emulate quantified comparison predicates for row value expressions, if not natively supported |
#3564 | Emulate PostgreSQL's DISTINCT ON clause |
#3713 | Add <pojosAsScalaCaseClasses/> to the code generator to generate case classes |
#3774 | Move Configuration thread safety content to new section |
#3896 | Add Configuration.converterProvider() to allow for implementing default converters between <T> and <U> types |
#4528 | Add manual section about DSLContext.connection() |
#4941 | Add LoaderListenerStep.onRowStart() for preprocessing input data |
#5216 | Add UpdatableRecord<R>.children(ForeignKey<O, R>): Table<O> |
#5218 | Add support for FOR SHARE OF in Postgres dialect |
#6124 | Add code generator option to generate an embeddable record per primary / unique key |
#6183 | Add GeneratorStrategy.getGlobalReferencesFile(Class.class) and getGlobalReferencesJavaClassName(Class.class) etc. to allow for overriding the files that contain global references |
#6187 | Add Schema.getTable(Name), getSequence(Name), getUDT(Name), getDomain(Name) |
#6188 | Add Catalog.getSchema(Name) |
#6248 | Implement KotlinGenerator |
#6256 | Add Kotlin infix and extension functions to a new jOOQ-kotlin extensions module |
#6345 | Generate Kotlin data classes |
#6456 | Generate comments also on POJOs |
#6501 | Can we profit from Kotlin's named and defaulted parameters for procedure calls, record constructors etc? |
#6598 | Support mapping into nested immutable POJOs |
#6736 | Add support for PostgreSQL ON CONFLICT .. WHERE <index_predicate> |
#7067 | Specify jOOQ's lack of Serializable backwards compatibility in the manual |
#7155 | Add support for synthetic foreign keys |
#7168 | Maven, Gradle, programmatic configuration code should be toggled using tabs |
#7253 | Add support for Loader.batchAll() with onDuplicateKeyIgnore() |
#7262 | Improve formatting of dual emulations |
#7291 | Add support for multiple MERGE .. WHEN MATCHED AND { condition } |
#7312 | Add Setting to transform table lists to ansi join |
#7507 | Implicit Joins should produce inner joins when possible |
#7553 | Add more and better DDL examples to the manual |
#7681 | Add programmatic and Gradle examples on how to configure generator strategies in the manual |
#7711 | Support recent features for Sybase ASE |
#7860 | Add support for synthetic unique keys |
#7997 | Emulate DISTINCT predicate using DECODE in Db2, H2, Oracle |
#8054 | Support `NO WAIT` with FOR SHARE on MySQL/Postgres |
#8254 | Publish an API version diff in the manual |
#8353 | Fix known limitations of embeddable types |
#8381 | Pull up OracleDSL.toChar() to DSL |
#8384 | Emulate support for INSERT INTO t [ AS alias ] |
#8450 | Improve procedural language abstraction API |
#8492 | DSL.row(Collection<?>) should also accept Select in argument collection |
#8519 | Add native support for H2 JOIN .. USING syntax |
#8548 | Add support for SQLite window function extensions from version 3.28 |
#8553 | Add support for foreign keys referencing unique key columns in different order than in the unique key definition |
#8575 | Implement native support for H2 RATIO_TO_REPORT() |
#8592 | Emulate PERCENT_RANK and CUME_DIST where not natively supported |
#8719 | Use native support for H2 <rve> IS [ NOT ] NULL predicate |
#8732 | Add native support for H2's new UNIQUE predicate |
#8805 | Support OVERLAY() function |
#8841 | Redshift: Support ILIKE |
#8844 | Emulate FOR UPDATE SKIP LOCKED using READPAST table hint |
#8949 | Add CharsetProvider SPI |
#8950 | Add support for standard JSON functions - continued |
#9017 | Add Settings.transformRownum |
#9044 | Add support for parsing single parameter numeric TRUNC() function |
#9054 | Manual headers should offer a link to the "latest" version |
#9061 | Improve Settings.parseWithMetaLookups |
#9131 | Support parsing MySQL BIT(1) value literals |
#9212 | Add support for MariaDB INSERT and DELETE RETURNING |
#9351 | Let DataType extend QueryPart |
#9404 | AbstractKey and subtypes should accept Name instead of string in constructors |
#9492 | Deprecate static data type registry lookups for user defined data types |
#9496 | Improve formatting of CREATE TABLE and derived column lists |
#9639 | Apply Database::getOrderProvider to Keys.java content as well |
#9744 | Add <locale/> to code generator <target/> specification |
#9764 | Rework formatting of SQL |
#9775 | Various parser bugs / missing features |
#9798 | Make the names in org.jooq.impl.Names unquoted |
#9825 | Document new jOOQ-refaster module |
#9833 | Add missing @Support annotation to DSLContext#fetch*() methods |
#9839 | Remove manual version 3.2, unsupport 3.7 |
#9841 | Update documentation to refer to org.jooq.trial-java-8 Maven groupId |
#9851 | Rewrite ResultQuery Javadoc |
#9861 | Add covariant overrides Record[N].with(Field, T) for fluent setting of values on a Record |
#9866 | Liquibase imports should use ClassLoaderResourceAccessor |
#9868 | SQL Server: Support STRING_AGG() function |
#9872 | LiquibaseDatabase should use configured changeLogParameters.contexts when updating |
#9874 | [#9872] LiquibaseDatabase should use provided contexts on update |
#9881 | DB2: Support ALTER TABLE ... DROP PRIMARY KEY |
#9882 | Deprecate SQLDialect#supports(Collection<SQLDialect>) method |
#9885 | Add support for DSL.execute() in Oracle |
#9888 | Support parsing some PostgreSQL specific matching operators |
#9889 | Add support for native ILIKE in H2 |
#9891 | Change Pro annotation retention to class |
#9894 | DB2: New aggregate functions in version 11 |
#9898 | Implement native support for LIKE ANY et al in PostgreSQL |
#9899 | Programmatic code generator configuration documentation should fully qualify org.jooq.meta.jaxb.Configuration |
#9900 | Add TransactionalRunnable.of(TransactionalRunnable...) to compose nested transactions |
#9902 | Add Settings to apply native JSR 310 data type binding |
#9911 | Deprecate Comparator.supportsQuantifier() and supportsSubselect() |
#9921 | Offer additional settings as dropdowns in /translate |
#9923 | Add support for FOR XML and FOR JSON |
#9924 | Emulate SQL Server FOR XML (single table) in other dialects |
#9925 | Add support for standard XML functions |
#9926 | Emulate SQL Server FOR JSON (single table) in other dialects |
#9927 | Add support for JSON_ARRAYAGG |
#9928 | Add support for JSON_OBJECT <JSON constructor null clause> |
#9930 | Add internal DefaultAggregateFunction and DefaultWindowFunction |
#9932 | Add DSL.jsonEntry(String, Field) and jsonObject(String, Field) |
#9936 | Add support for JSON_OBJECTAGG |
#9938 | Emulate SQL Server FOR JSON PATH and FOR XML PATH with dot / slash notation in other dialects |
#9939 | Emulate SQL Server FOR JSON AUTO nested collections from to-many joins |
#9950 | Improve support for EXECUTE for use in procedural blocks |
#9952 | Implement procedural language support for Firebird |
#9958 | Add DataType.precisionDefined(), scaleDefined(), lengthDefined() |
#9959 | Code generator should produce TIMESTAMP(precision) calls instead of TIMESTAMP.precision(precision) |
#9967 | Add support for HSQLDB temporal tables |
#9971 | Support parsing BETWEEN ASYMMETRIC where the SQL standard supports it |
#9973 | Remove internal AbstractFunction |
#9976 | Deprecate also CUBRIDDSL |
#9977 | Add more thread safety documentation around DSLContext and Configuration |
#9979 | Add DSL.val(), value(), and inline() overloads for JSON, JSONB, and XML types |
#9985 | Refactor some rendering logic to make better reuse of QueryPartList |
#9986 | Add an internal QueryPartListView class |
#9990 | Add some convenience API to SQLDialect, delegating to JDBCUtils |
#9991 | Offer an org.jooq.impl.AbstractBinding base implementation for the common case |
#9994 | Add missing with(Collection<? extends CommonTableExpression<?>>) overloads |
#9995 | Add SQLDialect.POSTGRES_12 |
#10000 | Add DSL.tau() to support τ, which is a better π |
#10008 | Add a configuration flag to DDLDatabase to specify whether queries should be logged |
#10010 | Rename Loader { CSV | JSON | Rows } Step.fieldsFromSource() to fieldsCorresponding() |
#10013 | Add <constructorPropertiesAnnotation/> to generate @ConstructorProperties on pojos and records |
#10015 | Replace internal usages of QueryPartList by QueryPartListView |
#10016 | Improve H2's derived column list support |
#10023 | Add Table.with(SQL) to allow for plain SQL templating in T-SQL style table hints |
#10024 | Upgrade dependencies |
#10025 | Move Keywords.F_XYZ to Names.N_XYZ and make them unquotedName |
#10032 | Add a /doc/dev URL mapping to the manual |
#10038 | Add SQLDialect.ORACLE20C |
#10040 | Add support for Oracle 20c EXCEPT ALL and INTERSECT ALL |
#10041 | Add support for Oracle 20c window function GROUPS and EXCLUDE clauses |
#10042 | Add RecordListener.mergeStart() and RecordListener.mergeEnd() lifecycle events |
#10043 | Add Support annotations to TableRecord.insert(), UpdatableRecord.store(), DAO.update(), etc. |
#10045 | Deprecate the H2 style MERGE statement |
#10046 | Add DSLContext.batchMerge() |
#10049 | Add DAO.merge() |
#10050 | Add support for optimistic locking with UpdatableRecord.merge() |
#10052 | Add support for standard SQL MERGE .. WHEN MATCHED [ AND .. ] THEN DELETE |
#10053 | Improve tutorial "jOOQ as a SQL builder" explaining the resulting bind parameter markers |
#10060 | Emulate JSON_ARRAYAGG() in older MariaDB versions |
#10061 | Add native support for DISTINCT predicate in Db2 |
#10064 | trueCondition(), noCondition() and falseCondition() should generate TRUE and FALSE, where BOOLEAN types are supported |
#10068 | Add native support for the DB2 11.1 OVERLAPS predicate |
#10070 | jOOQ should allow empty JOIN .. USING clauses |
#10071 | DefaultRecordMapper should apply ConverterProvider for Record1.into(...) calls |
#10072 | Out of the box support mapping between XML/JSON and POJOs using JAXB or Jackson/Gson |
#10074 | Provide default implementation of AbstractTable.as(Name) |
#10075 | Support unqualified column lookups in parser |
#10078 | Create manual subsections for each function |
#10079 | Create subsections in the manual for aggregate function features |
#10082 | Add JSON.json(), JSONB.jsonb(), XML.xml() methods |
#10085 | Add DataType.isJSON() and isXML() |
#10089 | Emulate JSON_OBJECTAGG where unavailable |
#10090 | Add a <generatedAnnotationDate/> flag to allow for turning off generating @Generated.date() |
#10094 | Emulate FOR XML AUTO with joins in other dialects |
#10097 | Add support for DB2 CREATE INDEX .. EXCLUDE NULL KEYS clause |
#10099 | Emulate XMLTABLE in SQL Server with NODES() and VALUE() |
#10100 | Emulate JSON_TABLE in SQL Server with OPENJSON |
#10104 | Add synthetic FOR JSONB syntax that produces JSONB instead of JSON |
#10105 | Support parsing ALTER { SEQUENCE | TABLE | TYPE | VIEW } .. OWNER TO .. |
#10111 | FOR JSON WITHOUT_ARRAY_WRAPPER emulation should use REGEXP_REPLACE, not SUBSTRING |
#10112 | Add QueryPartInternal.rendersContent(Context<?>) |
#10127 | Generate dialect specific rendering information in manual |
#10128 | Add support for Postgres 12 materialized CTEs |
#10131 | Emulate NVL2 using IIF in SQL Server |
#10133 | Add Javadoc and manual documentation for WIDTH_BUCKET |
#10137 | RPAD() and LPAD() should no longer need to cast |
#10152 | Add support for SAP HANA's BOOLEAN data type |
#10153 | Get HANA dialect support up to date |
#10156 | Deprecate createView(X, Function), Table.as(X, Function), and DSLContext.with(X, Function) |
#10160 | Add support for MySQL's IF() function |
#10162 | Add parser support for named NOT NULL constraints in DDL |
#10164 | Support parsing statement batches without delimiter |
#10165 | Add support for MySQL's INSERT() function via OVERLAY() |
#10171 | Parse a few known syntaxes and throw an exception about them not being supported |
#10178 | Add Field.is[Not]DistinctFrom(Select) and RowN.is[Not]DistinctFrom(Select) |
#10179 | Boolean field emulation should be NOT NULL aware |
#10180 | Add native support for DECODE where it is supported |
#10184 | Add missing TableLike.asTable(Name) and asTable(Table) overloads |
#10188 | Add Tools.visitSubquery(Context<?>, Select) |
#10193 | Support precision on LOCALTIME and LOCALDATETIME data types |
#10196 | GeneratorWriter should auto-indent generated code |
#10204 | Add a way to filter out objects from org.jooq.Meta instances |
#10210 | Add support for CREATE, ALTER, and DROP DATABASE statements |
#10215 | Stop emulating GROUP BY () in PostgreSQL 9.5+ |
#10216 | Add code generation support for HANA ARRAY type parameters |
#10220 | Support parsing CHECK constraints without parentheses |
#10230 | Let DataType extend Named |
#10235 | jOOQ-kotlin-example should use new KotlinGenerator |
#10246 | Add missing <includeXYZ/> flag documentation to manual |
#10250 | Add Db2 11.1 support for more EXTRACT DateParts |
#10258 | Improve PostgreSQL dateAdd() implementation |
#10264 | Support \s in the code generation config's indentation configuration |
#10278 | Add Named.getCommentPart() |
#10280 | Add Meta.snapshot() to create an in-memory copy of a Meta implementation |
#10284 | Add UDT.getPackage() in the OSS edition API |
#10288 | Add <pojosAsKotlinDataClasses/> to the code generator to generate data classes |
#10291 | Add support for CITEXT and VARCHAR_IGNORECASE types in parser |
#10292 | Add org.jooq.Qualified |
#10294 | Remove unnecessary covariant overrides from RenderContext and BindContext |
#10299 | Improve ParserImpl code reuse for single arg functions |
#10300 | Add DataType.getArrayComponentType() and getArrayComponentDataType() |
#10309 | Add code generation support for arrays of domain types |
#10317 | Deprecate Context.formatIndentLockStart() and formatIndentLockEnd() |
#10321 | Add support for JSON / JSONB types in H2 |
#10322 | Add parser support for JSON, JSONB, and XML types |
#10353 | Add a new internal InlineDerivedTable implementation |
#10354 | Retrofit Table.where() implementation to use new InlineDerivedTable |
#10360 | Support parsing NOT DEFERRABLE INITIALLY IMMEDIATE on foreign key constraints |
#10361 | Add JSONFormat.quoteNested() and XMLFormat.quoteNested() flags |
#10362 | Refactor DefaultBinding to reference DataType<T>, not Class<T> |
#10368 | Add DataType.isNString() |
#10372 | Refactor internal org.jooq.impl.Cast.Native for better reuse |
#10377 | Inline internal AbstractContext.visit0() to reduce stack trace size |
#10382 | Add support for CockroachDB 20.1 features |
#10383 | Add support for CockroachDB WITH RECURSIVE |
#10384 | Add support for CockroachDB TEMPORARY tables |
#10388 | Add parser support for Oracle's INTERVAL YEAR TO MONTH and INTERVAL DAY TO SECOND types |
#10389 | Support INFORMATION_SCHEMA.COLUMNS.INTERVAL_TYPE in H2 |
#10391 | Implement TableOptions equals() and hashCode() |
#10397 | Default implementation of AbstractTable.getIdentity() should check Table.fields() for any Field with DataType.identity() |
#10400 | Use DataType.identity() information in the absence of Table.getIdentity() in INSERT .. RETURNING emulation |
#10402 | Add when(Field<Boolean>) overloads to CASE expression API |
#10404 | Add SQLDialect.ASE_12_5, ASE_15_5, ASE_15_7, ASE_16_0 dialects |
#10406 | Get ASE dialect support up to date |
#10420 | Add Context.methodIf(Arg, boolean) for an "internal if" implementation |
#10422 | Let User and Role extend Named to give access to quoted / unquoted and qualified / unqualified names |
#10428 | Improve manual section "importing" |
#10429 | Make LoaderRowListener a FunctionalInterface |
#10432 | Add Settings.cachePreparedStatementsInLoader to keeping open PreparedStatements in Loader API |
#10438 | Support lazy DataType lookups in DSL.val() and DSL.inline() |
#10447 | Refactor some internal duplicate logic |
#10451 | Use H2, HSQLDB native interval arithmetic instead of DATEADD emulation |
#10453 | Support parsing additional standard interval literals |
#10456 | Add static YearToMonth and DayToSecond.<intervalType>(String) constructor methods |
#10460 | Use MERGE to emulate INSERT .. ON DUPLICATE KEY IGNORE in H2 |
#10472 | Add LazySchema and LazyCatalog to allow for lazy referencing a schema or catalog in generated code |
#10478 | Add Matchers for catalogs |
#10481 | Add <replacesFields/> to embeddable configuration |
#10483 | Add Database.getUniqueKeys(), getForeignKeys() to look up constraints without a specific schema |
#10489 | Add parser support for qualified data types in DDL and casts |
#10491 | Add conditional-expressions subsection about Field<Boolean> |
#10493 | Add TemplatingException for errors that occur with plain SQL templating |
#10495 | Add a "show imports" button to all manual code sections |
#10497 | Add parser support for the PostgreSQL CREATE INDEX .. ON .. USING syntax |
#10499 | Support overlapping embeddables |
#10511 | Add <embeddableDomains/> to allow for wrapping all DOMAIN types in embeddables |
#10518 | /learn should clearly distinguish between unreleased and released versions in the docs |
#10524 | Add DataType.isEmbeddable() |
#10532 | Add new <lambdaConverter/> configuration in <forcedType/> to further simplify programmatic converters |
#10535 | Generated code should import org.jooq.impl.SQLDataType if possible |
#10540 | Implement new internal syntax to create derived column lists only if necessary |
#10542 | Add Comparator.inverse() |
#10543 | Manual should discourage using jOOQ without the code generator |
#10550 | Remove the Derby SelectQueryImpl.UNION_PARENTHESIS_IN_DERIVED_TABLES emulation |
#10554 | Avoid workaround for too large initialisers when unnecessary |
#10568 | ParserCLI should offer configuration of RenderQuotedNames |
#10569 | ParserCLI should display individual flags when not providing a new value in interactive mode |
#10575 | Add some empty protected methods to generate custom class footers in reference classes |
#10578 | Add PackageDefinition.getUDTs() |
#10583 | Loader API should pad input rows if more target fields are provided than source fields |
#10588 | Add new <syntheticObjects/> configuration, and deprecate / replace existing functionality |
#10592 | Add DDLExportConfiguration.includeConstraintsOnViews to prevent Meta::ddl from exporting synthetic constraints on views |
#10600 | Gradle example in the manual should not use MarkupBuilder to avoid issues with name |
#10613 | Add Key.nullable() to indicate that a key is (partially) nullable |
#10616 | Add Settings.implicitJoinType to govern whether an INNER or LEFT JOIN is generated |
#10625 | Static import all SQLDataType types in the manual |
#10631 | Display context sensitive imports in manual |
#10632 | Log all column and parameter types in DEBUG level in JavaGenerator |
#10633 | Add DataTypeDefinition.getMatchNames() |
#10636 | Link to SEEK clause from OFFSET clause in the manual |
#10638 | Add parser support for arbitrary CONNECT BY .. START WITH .. GROUP BY .. HAVING ordering |
#10640 | Remove unneeded private DSL constructors |
#10641 | Support and emulate Oracle's TO_CHAR() function |
#10646 | Document that import-on-demand cannot be used with org.jooq.Record |
#10648 | Log info when code generation run doesn't produce any difference |
#10651 | Manual section about like should document example of concatenating "%" to a bind value |
#10653 | Make the JavaGenerator::INITIALISER_SIZE configurable through <maxMembersPerInitialiser/> |
#10654 | Make the generation of the serialVersionUID configurable |
#10658 | Add Sequence.nextvals(int):Select<Record1<T>> and DSLContext.nextvals(Sequence<T>, int):List<T> to fetch a number of sequence values in one go |
#10659 | Add Informix emulation for GENERATE_SERIES |
#10660 | Add WITH RECURSIVE emulations for GENERATE_SERIES, where available |
#10665 | Change org.jooq.impl.Expression implementation to be binary only |
#10682 | Add Collection overload for CatalogMetaProvider, SchemaMetaProvider, TableMetaProvider constructors |
#10688 | Add Converter.forArrays() to turn a Converter<T, U> into a Converter<T[], U[]> |
#10689 | Deprecate zero-args and one-arg Converters.of() methods |
#10692 | Address known issues of BatchedConnection |
#10693 | Add Settings.batchSize to transparently specify a maximum batch size for BatchedConnection |
#10694 | Add DataType.asConvertedDataType(Class<U>, Function<-T, +U>, Function<-U, +T>) |
#10705 | MockResultSet::toString should visually display current row |
#10707 | Add Routine.getInValue(Parameter) to allow for retrieving IN parameter values |
#10711 | Emulate using WITH in UNION subqueries by wrapping the subquery in a derived table in dialects where this isn't supported |
#10713 | Upgrade SQLite JDBC dependency from 3.30 to 3.32 |
#10728 | Add DSL.jsonEntry(Field) and DSL.jsonObject(Field...) overloads that derive key value(s) from field name(s) |
#10731 | Bump junit from 4.13 to 4.13.1 in /jOOQ-examples/jOOQ-spark-example |
#10732 | Bump junit from 4.13 to 4.13.1 in /jOOQ-examples/jOOQ-academy |
#10733 | Bump junit from 4.13 to 4.13.1 in /jOOQ-examples/jOOQ-javafx-example |
#10735 | Bump junit from 4.13 to 4.13.1 |
#10750 | Deprecate some internal field(String) and field(Name) implementations |
#10753 | Add support for ALTER TABLE .. SET NOT NULL in Oracle |
Breaking changes
#3285 | Add support for HSQLDB table-valued functions |
#4695 | Create separate Row[N] and Record[N] implementations for each N |
#4703 | The underscore "_" is a reserved token in Java 9. The jOOQ code generator should avoid generating it |
#6612 | Modularise jOOQ |
#7328 | Replace cursor-based FOR UPDATE emulation in SQL Server by table hints |
#7342 | Field.as(Field) and Table.as(Table) should inherit alias-defining Named's quoted flag |
#8576 | Regenerate jOOQ-meta code with <instanceFields>true</instanceFields> |
#8829 | Loader should decode binary data as base64, not with new String(byte[]) |
#8945 | Add org.jooq.XML |
#9754 | Unstable routine name suffix generation with overloaded names |
#9840 | Remove DSL.groupingId() from jOOQ Open Source Edition, as no OSS dialect supports it |
#9933 | Optimistic locking does not work when recordTimestamp column has precision less than TIMESTAMP(3) |
#10081 | Make accidentally public classes package private again |
#10129 | SQLite's SIGN() emulation does not produce the correct value on NULL |
#10146 | Let SQLDataType.TIMESTAMP map to DATETIME2 instead of DATETIME in SQL Server |
#10187 | Remove CONNECT BY support from OSS Edition |
#10276 | DSLContext.ddl() should not produce foreign keys that point outside of the argument schema |
#10283 | Stop generating singleton Identity declarations and move logic into TableImpl |
#10331 | Split jOOQ-meta-extensions into jOOQ-meta-extensions-hibernate and jOOQ-meta-extensions-liquibase |
#10338 | XMLGenerator should produce 1-based <ordinal_position/> in <key_column_usage/> |
#10343 | Make JSON::data, JSONB::data, and XML::data NotNull |
#10355 | Change JavaGenerator.printClassAnnotations() to (JavaWriter, Definition, Mode) |
#10418 | GrantOnStep.on(String) and RevokeOnStep.on(String) should wrap String argument in Name |
#10435 | DSLContext.connection() and similar methods should not wrap RuntimeException in DataAccessException |
#10512 | Add a CloseableDSLContext and stop subtyping AutoCloseable from DSLContext directly |
#10534 | <enumConverter/> and <lambdaConverter/> don't work in ScalaGenerator and KotlinGenerator |
#10566 | Wrong DDL generated in Oracle when translating integer types |
#10576 | Compilation error when 2 Oracle packages both contain the same record type name |
#10686 | ConnectionRunnable and ConnectionCallable should accept throwing Throwable |
Bug Fixes
#3379 | Table-valued function aliasing is confusing as the order of .call() and .as() is relevant |
#3479 | Awkward formatting of "short" functions |
#4691 | Add an unused forced type hint about Pattern.COMMENTS being turned on to help debug regexes with whitespace |
#5200 | Loader API onDuplicateKeyIgnore() doesn't work when primary key is an identity |
#5422 | ScalaGenerator should follow Scala Style Guide in generated code |
#5488 | Excess newline in formatted SELECT without FROM clause |
#6004 | DSL.values(Row[N]...) and DSL.table(Record) should emulate simpler SQL |
#6186 | Log warning if standalone <outputSchema/> element is not paired with <inputSchema/> |
#6266 | JoinTable.join(...).onKey() does not work |
#6278 | Wrong DDL generated when using SQLDataType.TINYINT on SQL Server |
#6356 | H2 row expression IN predicate with subquery doesn't work when subquery columns are aliased |
#6385 | Derby emulation of all(T...) is incorrect |
#6793 | Avoid allocating (and iterating) the MutablePOJOMapper's nestedFields HashMap |
#6819 | PostgreSQL UDT not working when used as stored procedure return type |
#6935 | insert queries having auto-generated ids are not executed |
#7070 | Add code generation support for PostgreSQL types referencing domains |
#7334 | DataAccessException.sqlStateClass() always returns OTHER for SQLite |
#7411 | `returning` statement does not work in MySQL even with primary key and auto increment |
#7489 | Datetime arithmetic generates bind values when input uses inline values |
#7626 | join(...).onKey(TableField) doesn't work with aliased tables |
#7667 | Generated SQL is missing aliasing for Stored Procedure |
#7673 | Cannot call SQL Server stored procedure on HSQLDB |
#7679 | Cannot use Meta.getSchema() for DROP SCHEMA statement |
#7682 | KeepNamesGeneratorStrategy doesn't work with ScalaGenerator |
#7867 | DSLContext.fetchCount(Select) should rename the select statement's column names to prevent ambiguities |
#7917 | Use H2 1.4.198 domain qualification for enums stored as domains |
#8029 | Cast expressions on TIMESTAMP data types should use explicit precision |
#8045 | EnumConverter doesn't work when fromType is Kotlin Int |
#8089 | Compilation error in generated Scala code for single letter schema names |
#8139 | scala.UninitializedFieldError in runtime using generated data objects |
#8220 | Row[N] predicates should wrap T argument values in Tools.field() to allow for raw type scalar subqueries |
#8278 | Code generation for SQLite doesn't pick up view column types correctly |
#8589 | Unstable code generation in PostgreSQL regexp_split_to_table function |
#8869 | jOOQ-scala modules no longer compile under JDK 13 |
#8965 | Wrong DDL generated when using precision on TIMESTAMPTZ type |
#9103 | Remove EPUB manual from website |
#9164 | Consistently show SQL code to the left and Java code to the right in manual |
#9188 | Cannot use DayToSecond intervals in Oracle, for intervals bigger than 99 days |
#9246 | ALTER TABLE .. ADD UNIQUE INDEX syntax cannot be parsed |
#9337 | DDLDatabase does not support JSON or JSONB columns |
#9396 | Too many tables produced from DSLContext.meta(Tables).getSchemas() |
#9540 | SQL Server NVARCHAR literal is not rendered correctly |
#9554 | not(unique(c)) / notUnique(c) and not(exists(c)) / notExists(c) should generate the same SQL |
#9590 | JDBC DatabaseMetaData backed Meta implementation should read DECIMAL_DIGITS for timestamp precision, not COLUMN_SIZE |
#9647 | Dead links to javax.validation |
#9832 | jOOQ Open Source Edition code generation fails on MySQL 5.7 and MariaDB 10.3 |
#9834 | jOOQ-meta Database implementations should dynamically detect server version and use appropriate dialect version |
#9835 | NPE when using AbstractDatabase instance without explicit configuredCustomTypes |
#9842 | Update error messages to refer to org.jooq.trial-java-8 Maven groupId |
#9849 | Compilation error in generated code for check constraints containing bad escape sequences |
#9856 | Parser cannot handle double quotes in string literals |
#9865 | Fix a few REDSHIFT support annotations and DDL statements |
#9870 | OracleDatabase produces wrong query when tableValuedFunctions is active |
#9873 | LiquibaseDatabase should use actual changeLog database table names |
#9875 | [#9873] LiquibaseDatabase should use actual changeLog table names |
#9896 | DB2: Wrong rendering of DSL#stddevSamp() and DSL#varSamp() |
#9897 | CockroachDB does not yet implement STDDEV_SAMP() and VAR_SAMP() |
#9903 | Changing getJavaClassName() for Mode.ENUM in DefaultGeneratorStrategy generates invalid code |
#9907 | NullPointerException in ByteArrayClassLoader, when it is asked to load an external class |
#9914 | PostgreSQL UNION requires parentheses if subquery has WITH clause |
#9916 | NullPointerException in XMLDatabase when new <enforced> element is missing |
#9922 | INSERT .. RETURNING with aliased target table generates wrong SQL in Oracle |
#9934 | Fix Sakila install scripts for Oracle Database |
#9935 | Oracle Database 11g: Column SEARCH_CONDITION_VC does not exist in table SYS.ALL_CONSTRAINTS |
#9940 | AS keyword is mandatory when aliasing DML target tables in SQLite |
#9946 | INSERT .. RETURNING emulation produces wrong follow up SELECT query when target table is aliased |
#9954 | Incorrect SQL generated in DB2's INSERT INTO t .. RETURNING t.* emulation |
#9961 | Wrong SQL generated when using implicit joins in union subquery |
#9968 | Error when reading or writing timestamps of year 10000+ in HSQLDB |
#9975 | Fix generated imports in RowN types |
#9980 | Wrong Javadoc link in DSL.value() methods |
#9992 | Firebird batch statements can produce java.sql.DataTruncation |
#9996 | INSERT ... RETURNING documentation in chapter 4.3.4.6 is lacking further explanation about returningResult |
#9998 | DSL.and(noCondition()) and DSL.or(noCondition()) generates a "1 = 1" or "1 = 0" predicate |
#9999 | Work around CockroachDB's wrong implementation of <row> IS NULL predicate |
#10007 | "constant string too long" in generated code when view source code exceeds 64KB |
#10029 | Manual documentation about RenderQuotedNames is not up to date |
#10033 | Stop casting bind values in INSERT .. VALUES() |
#10034 | Stop casting bind values in UPDATE .. SET |
#10056 | Again ORA-38104 on newer versions of Oracle |
#10066 | The FOR LOOP is supported only by MariaDB 10.3 |
#10093 | Sqlserver datetime2 precision not respected in batch insert |
#10098 | Support parsing SQL Server multi-column ADD syntax |
#10121 | Compiler regression on CI |
#10130 | Remove reference to ADBA from docs |
#10134 | Bad formatting of nullif() |
#10135 | Improve SPACE(n) emulation where possible |
#10136 | DSL.repeat().getName() is "rpad" |
#10139 | Unknown columns in code generator queries for Firebird 2.5 |
#10143 | java.nio.file.InvalidPathException: Illegal char <*> when using FilePattern on module path |
#10144 | Runtime compilation error when compiling enum types on module path |
#10145 | NoClassDefFoundError when trying to load JAXB from a modularised jOOQ |
#10158 | The default ParseNameCase for MariaDB should be AS_IS |
#10169 | Improve parser error message for 2 expected tokens |
#10172 | Wrong Javadoc: There are also DSLContext.fetchSingle() methods that return null |
#10183 | Bad record type returned for selectFrom(T) when T contains LEFT SEMI JOIN or LEFT ANTI JOIN |
#10189 | Bad formatting when selecting NULL |
#10191 | Fix several ScalaGenerator issues |
#10192 | Optimistic locking does not work when recordTimestamp column has precision less than LOCALDATETIME(3) |
#10194 | DefaultRecordMapper incorrectly maps immutable Kotlin classes with defaulted properties |
#10195 | GenerationTool should execute SHUTDOWN on HSQLDB connections |
#10197 | Implicit join constructor shouldn't be generated on table valued functions |
#10203 | Bad Javadoc generated for Tables.java in the default schema |
#10205 | NullPointerException when calling Meta.apply() on an H2 database with views |
#10207 | DataDefinitionException: Table can only have one identity when using Meta.apply() on PostgreSQL |
#10211 | Syntax errors in manual's SQL snippets |
#10223 | AUTO_INCREMENT columns fail to parse if they are preceded by a column with DEFAULT |
#10226 | DSLContext.fetchValue(field(name("t", "i"))) should select "i" from "t" |
#10227 | Global UDT, Index, Identity, references are generated as static, not static final |
#10248 | Wrong emulation of EXTRACT() with DECADE, CENTURY, MILLENIUM date parts |
#10252 | Add empty comment after stmt in trigger in Db2 Sakila scripts |
#10254 | Derby date time arithmetic uses unsupported sql_tsi_milli_second |
#10256 | HSQLDB cannot handle negative DAY intervals when using expression syntax |
#10262 | Newline configuration doesn't work |
#10267 | ImmutablePOJOMapperWithParameterNames throws InaccessibleObjectException on module path |
#10268 | Unrelated Liquibase error when using jooq-meta-extensions with Spring Boot |
#10269 | Settings.renderQuotedNames does not work with Routine |
#10271 | Cannot create or drop catalog-qualified schema in SQL Server |
#10272 | NPE in Interpreter when foreign key references table from other schema that does not exist |
#10279 | Missing implementations in DetachedMeta |
#10281 | AbstractKey.equals doesn't work for MetaPrimaryKey |
#10282 | Creating a Record, setting no fields explicitly, doing .insert(), PK is not set into Record object |
#10289 | Tutorial documentation - Incorrectly suggests installing XAMPP to get MySQL |
#10295 | Configuration.transactionProvider() is null after deserialisation |
#10296 | Reflect branch renaming from master to main in CONTRIBUTING.md |
#10301 | Columns are aliased by default to their own name, when using SQL Server parse dialect |
#10305 | Excluded schema is still included in code generation of foreign keys in PostgreSQL |
#10311 | Javadoc of SQLDataType.INTERVAL is incorrect |
#10312 | Converted datatype not using type from dialect after calling nullable |
#10313 | SQLDialect.supportedBy() sets should be used with contains(dialect()), not contains(family()) |
#10315 | Bad formatting of single WHEN simple CASE expression |
#10318 | Long source code workaround allocates substrings twice |
#10326 | Derby binary literals don't work with BLOB types |
#10334 | MySQLRoutineDefinition uses HSQLDB's INFORMATION_SCHEMA.PARAMETERS table, not MySQL's |
#10335 | NullPointerException when Database.setOnError(null) is called |
#10336 | jooq-meta.xsd shouldn't require table_type |
#10339 | orderProvider is not applied to AbstractDatabase.getSchemata0() |
#10345 | NON_BIND_VARIABLE_SUFFIXES should only be used in PostgreSQL dialect |
#10350 | Document Kotlin meta data usage by the DefaultRecordMapper in Javadoc |
#10364 | Mistake in the "FOR clause" documentation |
#10365 | DSL.currentTimestamp() should generate GETDATE() instead of CURRENT_BIGDATETIME() in Sybase ASE 12.5 |
#10370 | General exception error has occurred in the optimizer in Informix code generation, when generating only one schema and <includeSystemIndexes/> is turned on |
#10373 | Db2 and Derby CHAR casts erroneously casts to VARCHAR |
#10374 | YearToSecond interval not correctly supported in Oracle |
#10381 | CockroachDB FOR UPDATE must now specify unqualified names |
#10387 | XMLGenerator should quote source code from views, check constraints, and default expressions in generated output |
#10390 | <sources/> and <sourcesOnViews/> are not implemented in XMLGenerator |
#10394 | <comments/> and related flags implemented incorrectly in JavaGenerator |
#10398 | <syntheticIdentities/> doesn't set DataType.identity(true) in generated code |
#10399 | DataType.defaultValue() and DataType.identity() shouldn't be mutually exclusive |
#10408 | Error in Sybase ASE INSERT .. DEFAULT VALUES emulation when used with identity column |
#10410 | Excess derived table generated when putting unions in derived tables in Sybase ASE |
#10413 | maven-deploy.sh and maven-install.sh should use #!/bin/bash |
#10415 | Wrong Support annotations on INTERSECT and EXCEPT for MySQL |
#10417 | Sybase ASE cannot cast from numbers to TEXT directly |
#10421 | Sybase ASE TEXT columns get generated as LONGVARCHAR rather than CLOB |
#10425 | ImmutablePOJOMapperWithParameterNames no longer injects default values for unmapped primitive arguments |
#10426 | Use standard SQL for identity columns in H2 DDL |
#10442 | Wrong Javadoc on Settings.renderKeywordStyle |
#10444 | PostgreSQL code generation is incorrect when two tables share check constraint name |
#10445 | Manual redirects don't produce anchors in manual-single-page |
#10448 | Firebird arithmetic exception, numeric overflow, or string truncation; numeric value is out of range, when using Field.add(DayToSecond) with large millisecond numbers |
#10459 | Empty GROUP BY emulation stops working in HSQLDB 2.5.1 |
#10461 | INSERT .. ON DUPLICATE KEY IGNORE emulation using MERGE should support multi value inserts |
#10463 | Configuration log level is ignored by GenerationTool for first log statements |
#10466 | Code generator fails with ArrayIndexOutOfBoundsException for Index..Include statements |
#10467 | PostgresUtils.toPGArray does not handle escaped quotes |
#10474 | Manual refers to wrong <nonnnullannotation/> code generation configuration element |
#10479 | Manual section about custom code section doesn't document the possibility of overriding catalog related methods |
#10480 | Avoid generating empty header comments in Keys.java |
#10494 | Avoid querying ALL_JSON_COLUMNS on Oracle 12.1.0.1.0 |
#10498 | Compilation error in generated code when there is a table called OVERRIDE |
#10508 | DSLContext.meta(Table) may contain sequences |
#10538 | Improve emulation of (a, b) >= (x, y) |
#10548 | Unnecessary stack elements when SelectQueryImpl doesn't have both semi join and where clause predicates |
#10558 | Mention mapping into Record types in DefaultRecordMapper Javadoc |
#10561 | Various compilation errors when schema, table, key names conflict |
#10565 | Known issues with new FOR XML, FOR JSON features |
#10567 | Translator doesn't correctly quote identifiers in FOR XML and FOR JSON emulations |
#10579 | JavaWriter::beforeClose shouldn't search for package using a regex |
#10586 | Some missing nullable annotations in generated code |
#10587 | NullPointerException when misconfiguring code generator, lacking a <database/> |
#10594 | Meta::ddl does not correctly export view contents from generated code |
#10595 | Error when fully qualifying a view with catalog name in CREATE/DROP VIEW in SQL Server |
#10602 | Missing NOT NULL constraint in generated DDL for some dialects |
#10603 | Ambiguous match found when using complex implicit join graphs |
#10605 | offset(0) is ignored |
#10608 | Apply URL rewrite in /latest and /dev manuals also to internal links |
#10614 | Avoid ClassCastException when comparing two column values without natural order in Record::compareTo |
#10624 | Failing constraint exclusion with partitioned tables in Postgres 12.4 - 10.2 |
#10628 | BackslashEscaping.DEFAULT should implement ON behaviour in Redshift, not OFF |
#10635 | AbstractQueryPart::equals might not work when one QueryPart has a different Configuration than the other |
#10644 | Add Settings.transformUnneededArithmeticExpressions to optimise arithmetic prior to SQL generation |
#10655 | Support empty INSERT .. VALUES() clause via DEFAULT VALUES |
#10663 | Improve formatting of CONNECT BY emulation of GENERATE_SERIES |
#10664 | DataType.getArrayDataType() should wrap custom Converter<T, U> implementations into Converter<T[], U[]> automatically |
#10669 | Parser should parse DATE - DATE to dateDiff() and TIMESTAMP - TIMESTAMP to timestampDiff() |
#10670 | Error when parsing Oracle (+) operator with ParseUnknownFunctions.IGNORE |
#10674 | jOOQ Translator - Maria DB Version are missing |
#10675 | Parser doesn't recognise Oracle ( + ) operator, if it contains whitespace |
#10678 | Unsafe re-use of object in Expression math causes incorrect SQL generation |
#10679 | Parser incorrectly parses IN predicate of degree > 1 with extra parentheses around SELECT subquery |
#10680 | Translator should ignore unknown functions |
#10704 | ClassCastException when using MockDataProvider with Oracle ArrayRecord types |
#10718 | Error when mocking Oracle routines that have VARRAY or TABLE parameters |
#10720 | MockConnection must not produce first ResultSet when calling stored procedures with OUT parameters |
#10736 | NullPointerExceptions when calling DSLContext.informationSchema() with DSL.schema(Name) and similar meta data |
#10738 | NullPointerException in Meta.migrateTo() when using DatabaseMetaData backed Meta containing views |
#10741 | NullPointerException in SQLite Meta.migrateTo() when using DatabaseMetaData backed Meta containing FK referencing wrong identifier case |
#10743 | Fix emulations of nested FOR JSON and FOR XML queries |
#10751 | Code generator can't handle SQL Server database names with dash |
Version 3.13.0 - February 13, 2020
Starting with this release, we will further embrace our support for parsing, translating, executing, and now also interpreting DDL statements. The driving force is better code generation support, but in the future, also better integration with database change management systems like Flyway or Liquibase.
We've added support for a very promising new dialect: CockroachDB.
We're starting to support one of SQL:2011's most interesting features: temporal tables for system and application time versioning, and we've generally improved the way we build and distribute jOOQ to our paying customers.
SQL Dialects
We've worked together with a team of great engineers at CockroachDB to speed up our newly added, formal CockroachDB support in the jOOQ Professional and Enterprise Editions. While many users have successfully used the POSTGRES dialect with CockroachDB for simple integrations, this new dialect is now fully integration tested and supported for future jOOQ and CockroachDB versions. The integration fixed a variety of issues and minor differences that we have encountered in the code generator and the runtime library.
We've added support for a variety of features now available in Firebird 3.0+, MariaDB 10.3+, MySQL 8+, and PostgreSQL 10+.
DDL interpretation
Our biggest investment has been made in the area of DDL interpretation. Since jOOQ 3.9, we can parse more and more SQL syntax. A logical next step is to allow for interpreting parsed (or ordinary, DSL constructed) DDL statements in order to maintain an incremental, in-memory meta model of a database. This has a variety of benefits, which we will take advantage of in this release and in the future.
The main out of the box benefits in this version include:
- Being able to create a diff between two versions of a schema, programmatically through Meta.migrateTo(Meta), on the command line through DiffCLI (https://www.jooq.org/doc/latest/manual/sql-building/schema-diff-cli), or online, through our website: https://www.jooq.org/diff
- Such a diff or the meta model itself can be used for ad-hoc introspections, or formally, for automated migrations by tools built on top of jOOQ. Future versions will offer such migrations out of the box.
- Unfortunately, we have not yet replaced our H2 backed DDLDatabase by our new DDL interpretation capabilities. This is a high priority for jOOQ 3.14, though
In the context of these investments, we have improved a variety of infrastructure that were needed for these features and that users can benefit as well. These improvements include:
- A new LiquibaseDatabase, which uses Liquibase behind the scenes to simulate a schema migration in memory (similar to the DDLDatabase for Flyway), to reverse engineer that for the code generator. If you're using Liquibase, chances are that you no longer need to connect to an actual database to use jOOQ's code generator. More info here: https://blog.jooq.org/how-to-simulate-a-liquibase-migration-using-h2/
- We now support the inclusion of SQL text in generated code and other parts of the runtime meta model, including for CHECK constraints and views
- A lot of improvements to the JDBC DatabaseMetaData backed org.jooq.Meta API have been implemented.
- A lot of additional DDL statement and syntax support has been added throughout the API, parser, and other tooling.
- The runtime meta model has been enhanced with new information, such as sequence flags, check constraints, table type information, and more.
Temporal table support
Perhaps the SQL:2011 standard's most exciting "new" feature are temporal tables, an enhancement on top of Oracle's historic flashback query feature, and much more.
In many systems, single, or bi temporal versioning of data is essential. The two dimensions of versioning that are now supported in jOOQ are:
- System versioning, useful for backups and auditing, where every mutating operation results in a backup copy of the data in a managed backup table.
- Application versioning, useful for data that has a timely limited validity, such as a price for a product, which could have a temporary discount.
jOOQ 3.13 supports org.jooq.Period and related API in Select, Update, and Delete to manipulate and query temporal tables in dialects that ship with native support for these features. To different degrees, these dialects include:
- DB2
- MariaDB
- Oracle
- SQL Server
Emulations of incompletely supported syntax in the above dialects, as well as in all other dialects will be added in future jOOQ versions, making temporal validity a problem of the past.
More details here: https://www.jooq.org/doc/3.13/manual/sql-building/table-expressions/temporal-tables/
This is a commercially licensed only feature.
Build improvements
We've invested a lot of time in improving our build automation using newer Jenkins features that allow us to publish builds more frequently, especially snapshot builds of upcoming minor releases for early adopters, as well as patch releases for customers needing urgent fixes:
https://www.jooq.org/download/versions
These new releases also include trial versions for Java 6, 8, 11, without the need to register for extended trials.
In addition to the above, we've improved and continue to improve our documentation of features per edition, in the future.
Procedural API improvement
In jOOQ 3.12, we've introduced support for procedural languages, which we are improving in every new release. jOOQ 3.13 adds support for additional procedural statements, including:
- EXECUTE for dynamic SQL execution embedded in procedural blocks
- RETURN to return from functions
- Plain SQL statement support
In the future, we're planning to support also the generation of functions, procedures, and triggers through standard jOOQ API.
More details here: https://www.jooq.org/doc/3.13/manual/sql-building/procedural-statements/
This is a commercially licensed only feature.
jOOQ-Refaster
Some of our users have had a lot of success using our checker-framework or ErrorProne integrations, which allow for some static API usage analysis in client code (e.g. plain SQL / SQLi risk, dialect compatiblity, etc.)
Starting from jOOQ 3.13, we're also adding support for ErrorProne's sub project "refaster", which allows for automatically rewriting bad API usage to something better, such as for example:
- Migrate deprecated API usage like field.trim(), to its replacement trim(field)
- Migrate inefficient SQL usage like ctx.fetchCount(select) != 0 to ctx.fetchExists(select)
More details here: https://www.jooq.org/doc/3.13/manual/tools/refaster/
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.12-3.13
Features and Improvements
#2286 | Add LiquibaseDatabase to support interpreting the liquibase XML format in the code generator |
#2370 | Add org.jooq.TableOptions to describe the various storage and other options of a table in the meta model |
#3521 | Implement JDBCDatabase.loadForeignKeys() |
#3676 | Treat identical UNION [ ALL ] and INTERSECT set operations as associative avoiding unnecessary parentheses |
#4245 | Add support for PostgreSQL's DELETE .. USING syntax |
#4454 | Implement Table.getIdentity() for tables obtained via org.jooq.Meta |
#4793 | Add support for Catalog in runtime schema mapping |
#5181 | Add additional runtime meta information for indexes |
#5317 | Add support for ALTER TABLE .. ADD [ COLUMN ] .. [ { PRIMARY KEY | UNIQUE } ] [ REFERENCES | CHECK .. ] |
#6314 | Add Meta.getIndexes() |
#6412 | DSLContext.ddl() should distinguish between table types (table, temporary table, view, etc.) |
#6659 | Add support for PostgreSQL 10 IDENTITY columns |
#7004 | Add support for MariaDB sequences |
#7006 | Add support for MariaDB 10.3 Features |
#7241 | Add support for ALTER TABLE .. ADD .. [ FIRST | BEFORE | AFTER ] |
#7293 | Generate OFFSET .. FETCH for Firebird 3.0 |
#7421 | Stop rendering "FROM dual" in MySQL 8+ and MariaDB 10.4+ |
#7511 | Add support [ NOT ] ENFORCED in constraints |
#7629 | Add support for exporting CHECK constraints through DSLContext.ddl() |
#7639 | Add code generation support for CHECK constraints |
#7752 | Add support for Sequence flags in meta model |
#7775 | Add support for ALTER TYPE to modify enum types in PostgreSQL |
#8104 | Add support for ALTER DATABASE with DDLDatabase |
#8105 | Interpreter should have an option to disable foreign key checks |
#8194 | Add a Configuration.systemConnectionProvider() SPI |
#8201 | Add support for EXECUTE for use in procedural blocks |
#8252 | Add build integration test verifying if all pro API is annotated with the org.jooq.Pro annotation |
#8323 | Publish existing jOOQ-xtend project as a Maven module |
#8345 | Add an org.jooq.Typed<T> marker interface |
#8507 | Add a parent pom.xml for all examples |
#8524 | Add support for CREATE TEMPORARY TABLE IF NOT EXISTS |
#8528 | Add org.jooq.Meta implementation that is based on DDL interpretation |
#8541 | Use MySQL's native derived column lists support |
#8545 | Add support for CockroachDB |
#8621 | Add support for exception syntax in MockFileDatabase |
#8642 | Separate section for jOOQ's SQL extensions |
#8755 | Make Loader(CSV|JSON|Rows)Step.fields() calls optional |
#8787 | Support DSL#alterIndexIfExists() for SQL Server |
#8800 | Add Settings.transformAnsiJoinToTableLists to support pre-ANSI join syntax |
#8807 | Add setting to specify whether INNER and OUTER keywords should be generated in joins |
#8870 | Support Scala 2.13 |
#8901 | Cannot use INSERT .. RETURNING in Oracle to fetch back a UDT |
#8923 | Consider using jaxb2-annotate-plugin in XJC compiler |
#8953 | Use Internal API for generated code of Queues and Sequences |
#8995 | Add Javadoc to XJC generated with-methods |
#9019 | Render DROP TEMPORARY TABLE in MySQL |
#9043 | Add org.jooq.Source API |
#9053 | Offer a SNAPSHOT repository |
#9086 | Add tags to the manual documenting what editions support a given feature |
#9096 | Document the procedural language API |
#9101 | Improve method Javadoc of JAXB generated classes |
#9109 | Emulate multi column COUNT (DISTINCT col1, col2) in H2 using row value expressions |
#9127 | Update jOOQ-mcve dependency versions |
#9130 | Support MySQL FOREIGN KEY [ index_name ] syntax |
#9132 | Support parsing MySQL's USING [ BTREE | HASH ] index type syntax everywhere where it is supported |
#9138 | Parser errors from DDLDatabase should hint at jOOQ's parser ignore comment syntax |
#9141 | DDLDatabase should output query results to log output |
#9155 | Various third party dependency updates |
#9161 | Add support for parsing MySQL FULLTEXT KEY inline declaration in CREATE TABLE |
#9166 | Deprecate loading settings from /jooq-settings.xml or from -Dorg.jooq.settings |
#9168 | Add a DSL.execute(Query) convenience method |
#9171 | Add Javadoc to DSL::execute |
#9183 | Add support for DISTINCT ON in H2 |
#9186 | Correct various @Support annotations for MariaDB |
#9192 | Add DSL.statement(String), a plain SQL procedural Statement API |
#9194 | Add support for RETURN in the procedural API |
#9200 | Avoid unnecessary warning when there are multiple nextval default values (not caused by serial types) in PostgreSQL |
#9209 | Add support for exceptions in MockResult |
#9213 | Introduce versioned MARIADB dialects |
#9217 | Support parsing MySQL's USING HASH index_type in CREATE INDEX |
#9221 | Postgres supports DateParts MILLISECOND and MICROSECOND |
#9222 | Align @Support annotation of DatePart enum constants with DSL methods |
#9233 | Use new Source API throughout the jOOQ API |
#9238 | Add a new Settings.parseNameCase |
#9240 | Constraint with empty name rendered as CONSTRAINT "" |
#9244 | Add support for DROP TEMPORARY TABLE IF EXISTS |
#9252 | H2: Omit OFFSET clause if offset is 0 |
#9255 | Upgrade Maven version to 3.6.2 in Travis |
#9263 | Better support for fields with boolean converter |
#9265 | Add JSON.data() and JSONB.data() |
#9272 | Slightly improved code generation pattern |
#9273 | Update Gradle example to use newer version of H2 |
#9276 | Java generator always uses LF line terminator for import statements |
#9285 | Add a link from the dialect family to the latest dialect version in each SQLDialect |
#9289 | Add Javadoc to Configuration.dsl() explaining that it is just convenience |
#9294 | Add support for MariaDB FOR UPDATE .. [ WAIT n | NOWAIT ] |
#9295 | Use Settings.getQueryTimeout() consistently |
#9305 | Support parsing Vertica's TEMP table syntax |
#9307 | Add Mock.of(SQLException) |
#9312 | Add SQLDialect.supportedBy(SQLDialect...) to produce a set of supported dialects from an input |
#9313 | Add SQLDialect.predecessors() to produce a set of all preceding versions of a given dialect |
#9316 | Also support STRAIGHT_JOIN for MariaDB and MemSQL |
#9317 | Synchronize @Support annotations on JoinType and Table methods |
#9318 | H2: Support WITH clause for MERGE statement |
#9320 | Add a new DataDefinitionException to be thrown by DDLInterpreter |
#9325 | Add Name.empty() to check if a name consists only of the empty string "" |
#9327 | Add DDLFlag.SEQUENCE to allow for exporting CREATE SEQUENCE statements from DSLContext.ddl() |
#9329 | Add reactive streams in published ZIP file as a dependency, for convenience |
#9344 | Fix Support annotations for CREATE SEQUENCE flags |
#9352 | Only render CREATE SEQUENCE ... NO CYCLE clause where supported |
#9353 | Support parsing ALTER TABLE .. ALTER .. SET DEFAULT |
#9354 | Add support for ALTER TABLE .. ALTER .. DROP DEFAULT |
#9358 | Add support for parsing the H2 SCHEMA() function |
#9359 | Refactor common meta extensions code to new InterpretingDatabase |
#9361 | Upgrade H2 dependency to 1.4.200 |
#9362 | Add Settings.interpreterDialect |
#9364 | Add DDLFlag.INDEX to allow for exporting CREATE INDEX statements |
#9371 | H2: DSL#currentTime() should render as CURRENT_TIME |
#9372 | Improve SEMI / ANTI JOIN documentation |
#9374 | Support various H2 ALTER .. IF EXISTS statements |
#9375 | Add code generation and runtime flags to include/exclude automatic indexes on PK/UK/FK |
#9380 | Add support for ALTER TABLE .. DROP CONSTRAINT .. [ CASCADE | RESTRICT ] |
#9382 | Add support for Oracle's ALTER TABLE .. DROP UNIQUE (<columns>) syntax |
#9384 | DataType.getDataType(Configuration) turns this on dialect specific data types |
#9394 | Move DSLContext.ddl() API to Meta |
#9395 | Let Meta extend Scope |
#9399 | Move DSLContext.informationSchema() to Meta |
#9403 | Deprecate CUBRID dialect |
#9407 | Deprecate remaining Field.xyz() convenience API |
#9410 | Various Firebird DDL improvements |
#9413 | Add support for RDB$DESCRIPTION in Firebird code generation |
#9421 | Add Firebird code generation support for indexes |
#9426 | DSLContext.meta(Source...) should be able to read InformationSchema from sources |
#9427 | Let Name extend Comparable |
#9428 | Meta.toString() should call Meta.ddl() |
#9429 | Add DSLContext.meta(Query...) as a shortcut for meta(Source...) |
#9431 | Add a /diff tool to the website |
#9432 | Add Queries.concat(Queries) |
#9433 | Implement Meta.equals() and hashCode() based on Meta.ddl() |
#9434 | Add DDLExportConfiguration.respectOrder flags |
#9435 | Let Key extend Named |
#9436 | Add Meta.apply(Queries) |
#9437 | Add support for ALTER SEQUENCE [ sequence flags ] |
#9438 | ALTER SEQUENCE .. RESTART emulation should use Sequence.startWith() flag, if available |
#9441 | Add DSLContext.meta(String...) for convenience |
#9442 | Add code generation support for sequence flags |
#9445 | Various Sybase ASE DDL improvements |
#9460 | Support additional Settings.interpreterDialects and add an InterpreterConnectionProvider SPI |
#9476 | Add parser support for MySQL [ INNER ] JOIN without ON clause |
#9478 | Support parsing ALTER TABLE .. ALTER COLUMN .. SET NULL syntax |
#9482 | Add new internal org.jooq.impl.Names class for commonly used DSL.name() references |
#9490 | Create an FAQ on the website, and link to it from the issue template |
#9491 | Add 301 redirects for non-modular Javadoc |
#9502 | Add Settings.renderOptionalAsKeywordForTableAliases and ...ForFieldAliases |
#9504 | Add DDLExportConfiguration.createViewIfNotExists and DDLExportConfiguration.createOrReplaceView |
#9505 | Add org.jooq.Version to describe a database version |
#9508 | Add Settings.interpreterDelayForeignKeyDeclarations |
#9511 | Avoid quoted identifiers in jOOQ-meta queries |
#9514 | LiquibaseDatabase should allow for passing parameters to the Liquibase |
#9520 | Log info message when a forcedType never matches |
#9533 | Add support for DROP INDEX .. [ CASCADE | RESTRICT ] |
#9534 | Add support ALTER TABLE .. DROP UNIQUE <name> |
#9536 | Add DataType.isInteger() |
#9558 | Clarify in Javadoc of selectFrom() and related methods that all Table.fields() will be fetched, not DSL.asterisk() |
#9562 | Add Table.getChecks() to return a list of check constraints |
#9565 | Add CheckConstraint XSD type to jooq-meta.xsd |
#9570 | Generate single ADD or DROP ALTER TABLE statements when a list of length 1 is passed |
#9578 | Upgrade Hibernate dependency to 5.4.9.Final |
#9580 | Add DDLExportConfiguration.defaultSequenceFlags |
#9584 | Add Source.readString() |
#9588 | Use H2's native BITNOT() |
#9589 | Use H2's native LSHIFT() and RSHIFT() |
#9591 | Let DefaultRecordContext and DefaultExecuteContext extend AbstractScope |
#9595 | Regenerate HSQLDB information schema against 2.5.0 |
#9600 | Add code generation flag <includeSystemCheckConstraints/> |
#9603 | Add sequence flag support on jooq-meta.xsd |
#9604 | Implement a default OrderProvider in the code generator |
#9610 | Add code generation support for Derby indexes |
#9611 | Add code generation support for Informix indexes |
#9612 | Document JSON and JSONB NULL semantics |
#9613 | Update Configuration Javadoc |
#9614 | Clarify that SQL Data Warehouse = Azure Synapse Analytics |
#9616 | Support parsing ALTER TABLE .. ADD, .. ADD |
#9624 | Add a DiffCLI command line tool |
#9629 | Add new <sequenceFlags/> flag to allow for turning off sequence flag generation |
#9630 | Add more ErrorProne and Refaster checks / refactorings |
#9633 | Add a new Settings.interpreterNameLookupCaseSensitivity |
#9636 | Add Settings.locale() as a default for renderLocale() and other locales |
#9646 | Document <generatedAnnotation/> |
#9651 | Support parsing // as a single line comment token |
#9657 | Publish 3.12 snapshots on website |
#9660 | Update dependency to Derby 10.15 |
#9661 | Support parsing MySQL's unnamed constraint syntax |
#9667 | Ignore changes to sun-jaxb.episode files |
#9668 | Offer Java 11 and 6 trial downloads from website |
#9669 | Move xjb files out of artifacts |
#9670 | Make slf4j-api version backwards compatible to OSGi consumers |
#9672 | Add new ConstraintDefinition type |
#9675 | Postgres: Support MD5() function |
#9677 | Add Settings.interpreterSearchPath |
#9681 | Synchronize @Support annotations on MergeUsingStep#columns() methods |
#9682 | Add SQLDialect.SQLITE_3_30 |
#9692 | Add InsertQuery.setSelect(Collection, Select) overload |
#9696 | Add a new <generateGlobalIndexReferences/> flag |
#9698 | How to alter a table to add a column of Enum/Set type in MySQL. |
#9700 | Sakila/PostgreSQL: Don't fail if language plpgsql already exists |
#9703 | Document the requirement of matching versions between code generator and runtime library |
#9719 | Support MySQL ISNULL() function in the parser |
#9727 | Add configuration/basedir to resolve relative paths in code generator |
#9733 | Add <nonnullAnnotationType/> and <nullableAnnotationType/> |
#9734 | Add <nonnullAnnotation/> and <nullableAnnotation/> |
#9741 | Add org.jooq.Period for temporal validity |
#9747 | JSON and JSONB should implement Serializable |
#9762 | Add support for DB2 SET SCHEMA command |
#9772 | Add SQLDialect.MYSQL_8_0_19 |
#9776 | Add support for MySQL 8.0.19 VALUES clause |
#9777 | Add SQLDialect.supportedUntil() |
#9778 | Support NULLS [ FIRST | LAST ] in SQLite 3.30 |
#9779 | Add native support for aggregate and window function FILTER clause in SQLite 3.30 |
#9780 | Add Settings.parseSetCommands |
#9781 | Add DSLContext.set(Name, Param<?>) for arbitrary set commands |
#9790 | Add internal functional interfaces F0, F1, F2 |
#9796 | Generated annotation should produce HTTPS link to jOOQ website |
#9799 | Make TableOptions available through code generation |
#9800 | Make TableOptions available through org.jooq.Meta |
#9801 | Make TableOptions available through InformationSchema |
#9805 | Generate view source code with generated views |
#9806 | Add Batch.executeAsync() methods |
#9807 | Apply Configuration.onError flag also to SQL errors from AbstractDatabase |
#9808 | Add JooqLogger.log(Level) overloads |
#9811 | Document that CustomRecord subclasses need a no-arg constructor |
#9816 | Add Definition.getSource() |
#9819 | Add support for INFORMATION_SCHEMA.VIEWS in jooq-meta.xsd |
#9822 | Firebird support for ALTER TABLE ... ALTER ... [ DROP | SET ] NOT NULL |
#9827 | Remove SQL 2 jOOQ section from the manual |
Breaking changes
#4934 | Delay query execution until a Stream terminal op is called |
#5714 | Change <javaTimeTypes/> default value to "true" |
#9031 | Remove unnecessary AlterSequenceRestartStep |
#9235 | Remove checked exceptions from LoaderSourceStep methods |
#9237 | Remove checked exceptions from MockFileDatabaseConfiguration::source methods |
#9241 | Change <varargSetters/> to default to false |
#9283 | DefaultBinding should return null on null JSON values, instead of JSON[B].valueOf(null) |
#9365 | Support H2's standard LOG() function |
#9470 | FilePatter.Loader should accept Source, instead of InputStream |
#9479 | Remove internal, deprecated DefaultConfiguration constructors |
#9596 | Regenerate MySQL information schema against 8.0.18 |
#9601 | Add code generation flag <includeSystemIndexes/> |
#9725 | Move org.jooq.meta.tools.FilePattern API to core library |
#9732 | Change default value of <generatedAnnotation/> to "false" |
#9737 | Wrong generics on DSLContext.selectFrom(Name) and similar methods |
#9758 | Generated constraint names should not be table prefixed in meta data in DB2 and PostgreSQL |
Bug Fixes
#2967 | Impossible to inline "decimals" parameter of ROUND() function |
#4856 | UNION generates bad SQL for MySQL, when UNION subqueries contain duplicate column names from JOIN operations |
#6497 | Add LocalDateAsLocalDateTimeBinding to make <javaTimeTypes/> and <dateAsTimestamp/> work together |
#7377 | When using org.jooq.Meta, UniqueKey.getReferences throws NPE in Firebird |
#7962 | ORA-04043 on INSERT when using qualified, quoted table name and fetching generated keys |
#8335 | DDLDatabase loads too many files when using relative path |
#8508 | Fix Javadoc warnings |
#8555 | Parser cannot handle enum literals that are invalid java identifiers |
#8580 | LikeEscapeStep#escape() also supported by Teradata |
#8677 | Log warning when file based databases have invalid <jdbc/> configurations |
#8721 | Enum type with '-' character does not compile |
#8824 | DDLDatabase can not handle multiple constraints with the same name |
#8966 | Invalid SQL rendered for recursive query |
#8967 | Generator outputs duplicate method (not compilable) |
#8968 | An exception in ExecuteListener#start is not routed to ExecuteListener#exception |
#8991 | DSL.field(Name) fields should support schema mapping |
#9099 | Cannot build Javadoc in jOOQ-checker under Java 11 |
#9100 | Fix Javadoc links starting from jOOQ 3.12, which is built with JDK 11 |
#9104 | JooQ 3.12.0 codegen fails with an incorrect query where 3.11 worked correctly (PostgreSQL) |
#9110 | Wrong SQL generated by DSL.countDistinct() without arguments |
#9111 | Allow parsing of COUNT(DISTINCT <row-value-expression>) |
#9121 | Generator does not report file in which invalid SQL was found |
#9122 | java 8+ distribution of 3.12.0 broken |
#9133 | 404s on /latest Javadoc |
#9134 | Wrong rendering of [ FROM { FIRST | LAST } ] clause for NTH_VALUE() |
#9140 | Translation of USE command should result in SET SCHEMA command in dialects that do not support catalogs |
#9144 | ParserCLI "-f" flag does not work as shortcut for "--from-dialect" |
#9145 | Manual page about ParserCLI misses reactive-streams in classpath |
#9146 | ParserCLI --from-dialect is not case insensitive |
#9147 | ParserCLI -h parameter throws a RuntimeException |
#9150 | Compilation error in generated code when Oracle OBJECT type contains index_of(varchar2) member procedure |
#9157 | Prevent "Illegal reflective access operation" warning in jOOQ Open Source Edition |
#9158 | Review and fix a few formatting issues in the manual |
#9165 | Quantified LIKE predicate (LIKE ANY) is not documented correctly |
#9177 | H2: SelectLimitPercentStep#percent() not working properly |
#9187 | Bad parenthesis in UNION under HSQLDB |
#9193 | Consecutive RenderContext.formatSeparator() calls ignored when formatIndentStart() is called in between |
#9196 | Only first value added to date time appears in rendered SQL |
#9201 | Negative intervals not rendered properly for PostgreSQL |
#9205 | Fix DefaultYearToMonthBinding and DefaultYearToSecondBinding for Aurora Postgres |
#9214 | SQLDialect.MEMSQL lacks Pro annotation |
#9219 | Regression in Extract(QUARTER) on Postgres in 3.12.1 |
#9223 | MySQL: Support date parts MICROSECOND and WEEK |
#9224 | Regression for "= ANY(?::int[])" no longer produces array bind variable |
#9225 | Postgres: FILTER clause no longer rendered |
#9231 | Wrong Javadoc on org.jooq.Source |
#9242 | AbstractKey#equals() assumes name is unique |
#9248 | Regression: DSLContext#nextval() broken for H2 |
#9250 | LEFT [ ANTI | SEMI ] JOIN ... USING not implemented |
#9251 | H2's WITH TIES support broken in OSS edition |
#9266 | Consistently document all commercial SQLDialects |
#9274 | AttributeConverterExtractor should receive custom Hibernate configuration properties |
#9277 | Improve error message when AttributeConverters cannot be loaded due to NoClassDefFoundError |
#9291 | Sequences are generated as tables in MariaDB |
#9296 | withRenderSchema(false) does render schema in order by clause |
#9311 | Incomplete @Support annotations on UpdateQuery.addValues(Row[N], Select) |
#9315 | Remove unnecessary generic type variable on CreateSchemaImpl |
#9324 | Name.append(Name) should not produce a QualifiedName when one of the parts is empty |
#9331 | Postgres 12 exception in code generation output: "column c.consrc does not exist" |
#9338 | Parse ignore comments not parsed correctly if stop comment is last token of file, prior to a newline |
#9343 | Wrong SQL generation for PostgreSQL function calls having arguments with custom data types. |
#9355 | LoggingConnection does not log static statements |
#9368 | Outdated comment in manual about H2 supporting window functions |
#9386 | RenderMapping is not applied to DSL.schema(Name) |
#9389 | CREATE INDEX commands created from DSLContext.ddl() based on Meta contain illegal WHERE clause |
#9411 | Firebird generated code contains "DEFAULT" keyword in default expressions |
#9414 | Unable to create index with qualified index name on Oracle dialect |
#9415 | Emulate RETURNING * in Firebird |
#9418 | Regression in Firebird's SUBSTRING() implementation |
#9420 | Incorrect emulation of unnamed indexes |
#9424 | Add line breaks to a few parser grammar diagrams |
#9443 | Regression in Sybase ASE source code generation: Cannot generate tables |
#9457 | UDT.getQualifiedName() doesn't return schema qualification for generated tables |
#9461 | Missing @PlainSQL annotation on some DSLContext#batch() methods |
#9462 | Missing @Support annotations on BatchBindStep methods |
#9463 | Add missing @Support annotations to methods of LoaderSourceStep |
#9468 | SQLDialect.ASE cannot be used with a MockConnection |
#9471 | JDBCDatabase does not order objects alphabetically |
#9473 | Creating tables using DSLContext.ddl() converts VARBINARY columns to TEXT in MySQL |
#9480 | CREATE SEQUENCE implementation should reuse Sequence.getDataType() in various flags |
#9493 | JoinStep#crossApply() throws IllegalArgumentException |
#9497 | NullPointerException when calling methods on DAO that is not attached to a Configuration |
#9498 | DDLDatabase: Flyway's repatable migrations are executed to early |
#9513 | Oracle: PIVOT ... FOR always rendered as quoted |
#9516 | Cannot use MERGE .. DELETE WHERE without UPDATE WHERE |
#9528 | Some ConstraintForeignKeyReferencesStep.references() methods are missing Support annotations |
#9531 | Open Source version references dual license |
#9545 | Parser cannot parse views with WITH |
#9547 | Query ALL_MVIEWS instead of ALL_MVIEW_COMMENTS in Oracle |
#9551 | Bad code generated when using SQL Server user defined types |
#9567 | Cosmetic exceptions caused by JPADatabase when using attribute converters |
#9571 | Multi column ALTER TABLE .. ADD statement shouldn't qualify column names |
#9582 | Generator's <globalObjectReferences/> does not prevent the generation of Indexes.java |
#9597 | DefaultRelations#getCheckConstraints() returns all checks on first call |
#9598 | Static class initialisation deadlock race between DefaultDSLContext.java:388 and DefaultDSLContext.java:505 |
#9620 | No DiagnosticsListener.missingWasNullCall() when nullability is unknown |
#9621 | NullPointerException in DefaultRecordMapperProvider when setting a new instance to a Configuration |
#9648 | ArrayIndexOutOfBoundsException if query has a single or double quote char in vendor specific comment |
#9653 | Meta.ddl() loses Schema and Constraint Name.quoted() information |
#9658 | Parser settings repeat available flag documentation |
#9659 | Missing documentation for Settings.inListPadBase |
#9664 | Parser should reject duplicate identities |
#9671 | Fixes #9670 to make jooq OSGi backwards compatible for slf4j and also… |
#9674 | Bad SQL generated from implicit join from within subqueries |
#9685 | Generate.globalTableReferences should not impact what is returned by Schema#getTables() |
#9690 | All links in FAQ are broken |
#9697 | Full identifier qualification in generated code when <globalObjectReferences> is turned off |
#9708 | Mapping schema with RegEx generates invalid output name after upgrade to 3.12 |
#9718 | Wrong type returned by LoaderCSVStep#fields(LoaderFieldMapper) |
#9726 | FilePattern matches too many files when wildcards are being used |
#9751 | MySQL 5.7: Invalid SQL for set operations in subqueries |
#9756 | Regression in IGNORE NULLS clause for DB2 |
#9782 | Add missing @Support annotation to PivotForStep#for_(Field) |
#9791 | Meta.getTables() returns the same table for each catalog in SQL Server |
#9792 | Meta doesn't produce correct data type in SQL Server for identity columns |
#9793 | BLOB SUBTYPE not supported in dialect FIREBIRD when using plain SQL |
#9797 | XMLDatabase cannot read INT type |
#9823 | WITH TIES emulation not used for FIREBIRD dialect |
#9824 | Informix check constraint and view generated SQL code is not trimmed |
Version 3.12.0 - August 29, 2019
In this release, we've focused on a lot of minor infrastructure tasks, greatly improving the overall quality of jOOQ. We've reworked some of our automated integration tests, which has helped us fix a big number of not yet discovered issues, including a much better coverage of our 26 supported RDBMS dialects.
We're excited about these internal changes, as they will help us implement a lot of features that have been requested by many for a long time, including an immutable query object model, with all the secondary benefits like caching of generated SQL, and much more powerful dynamic SQL construction and transformation in the future.
Major new features include the new procedural language API shipped with our commercial distributions, new data types including native JSON support, MemSQL support, formal Java 11+ support, a much better parser, and reactive stream API support.
Procedural languages
Following up on jOOQ 3.11's support for anonymous blocks, the jOOQ 3.12 Professional and Enterprise Editions now include support for a variety of procedural language features, including
- Variable declarations
- Variable assignments
- Loops (WHILE, REPEAT, FOR, LOOP)
- If Then Else
- Labels
- Exit, Continue, Goto
- Execute
This feature set is part of our ongoing efforts to continue supporting more advanced vendor specific functionality, including our planned definition and translation of stored procedures, triggers, and other, ad-hoc procedural logic that helps move data processing logic into the database server.
New Databases Supported
The jOOQ Professional Edition now supports the MemSQL dialect. MemSQL is derived from MySQL, although our integration tests have shown that there are numerous differences, such that supporting MemSQL formally will add a lot of value to our customers by providing much increased syntactic correctness.
Reactive streams
The reactive programming model is gaining traction in some environments as new, useful streaming APIs emerge, such as e.g. Reactor. These APIs have agreed to work with a common SPI: reactive streams, and since JDK 9 the new java.util.concurrent.Flow SPI. jOOQ 3.12 now implements these paradigms on an API level, such that an integration with APIs like Reactor becomes much more easy. The implementation still binds to JDBC, and is thus blocking. Future versions of jOOQ will abstract over JDBC to allow for running queries against ADBA (by Oracle) or R2DBC (by Spring)
New data types
We've introduced native support for a few new data types, which are often very useful in specific situations. These include:
- JSON / JSONB: A native string wrapper for textual and binary JSON data. While users will still want to bind more specific JSON to maps and lists using custom data type Bindings, in a lot of cases, being able to just serialise and deserialise JSON content as strings is sufficient. jOOQ now provides out of the box support for this approach for various SQL dialects.
- INSTANT: RDBMS do not agree on the meaning of the SQL standard TIMESTAMP WITH TIME ZONE. PostgreSQL, for example, interprets it as a unix timestamp, just like java.time.Instant. For an optimal PostgreSQL experience, this new INSTANT type will be much more useful than the standard JDBC java.time.OffsetDateTime binding.
- ROWID: Most RDBMS have a native ROWID / OID / CTID / physloc identity value that physically identifies a row on the underlying storage system, irrespective of any logical primary key. These ROWIDs can be leveraged to run more performant, vendor specific queries. Supporting this type allows for easily using this feature in arbitrary queries.
Parser
Our parser is seeing a lot of continued improvements over the releases as we gather feedback from our users. Our main drivers for feedback are:
- The DDLDatabase which allows for generating code from DDL scripts rather than live JDBC connections to your database
- The https://www.jooq.org/translate website, which translates any kind of SQL between database dialects.
SQL dialect translation will evolve into an independent product in the future. DDL parsing is already very powerful, and a lot of customers rely on it for their production systems.
In the next versions, we will be able to simulate DDL on our own, without H2, which will open up a variety of possible use cases, including better schema management.
Specific jOOQ 3.12 parser improvements include:
- Being able to access schema meta information (column types, constraints) to better emulate SQL features / translate SQL syntax between dialects
- A parse search path, similar to PostgreSQL's search_path, or other dialects' current_schema, allowing support for unqualified object references.
- The DDL simulation from the DDLDatabase is now moved into the core library, supporting it also out of the box as a DDL script based meta data source
- A new special comment syntax that helps ignoring SQL fragments in the jOOQ parser only, while executing it in your ordinary SQL execution.
- A new interactive mode in the ParserCLI
- Support for nested block comments
- And much more
Formal Java 11 Support
While we have been supporting Java 11 for a while through our integration tests, jOOQ 3.12 now fully supports Java 11 to help improve the experience around the transitive JAXB dependency, which we now removed entirely out of jOOQ.
The commercial editions ship with a Java 11+ supporting distribution, which includes more optimal API usage, depending on new Java 9-11 APIs. All editions, including the jOOQ Open Source Edition, have a Java 8+ distribution that supports any Java version starting from Java 8.
Commercial Editions
Dual licensing is at the core of our business, helping us to provide continued value to our customers.
In the past, the main distinction between the different jOOQ editions was the number of database products each edition supported. In the future, we want to provide even more value to our customers with commercial subscriptions. This is why, starting from jOOQ 3.12, we are now offering some new, advanced features only in our commercial distributions. Such features include:
- The procedural language API, which is available with the jOOQ Professional and Enterprise Editions
- While the jOOQ 3.12 Open Source Edition supports Java 8+, the jOOQ 3.12 Professional Edition also ships with a Java 11+ distribution, leveraging some newer JDK APIs, and the jOOQ 3.12 Enterprise Edition continues supporting Java 6 and 7.
- Since Java 8 still sees very substantial market adoption, compared to Java 11, we still support Java 8 in the jOOQ 3.12 Open Source Edition.
- Starting from jOOQ 3.12, formal support for older RDBMS dialect versions in the runtime libraries is reserved to the jOOQ Professional and Enterprise Editions. The jOOQ Open Source Edition will ship with support for the latest version of an RDBMS dialect, only. The code generator is not affected by this change.
By offering more value to our paying customers, we believe that we can continue our successful business model, which in turn allows us to continue the free jOOQ Open Source Edition for free. Our strategy is:
- To implement new, advanced, commercial only features.
- To offer legacy support (legacy Java versions, legacy database versions) to paying customers only.
- To continue supporting a rich set of features to Open Source Edition users.
H2 and SQLite integration
Over the past year, both H2 and SQLite have seen a lot of improvements, which we have now supported in jOOQ as well. Specifically, H2 is moving at a very fast pace, and our traditional close cooperation got even better as we're helping the H2 team with our insights into the SQL standards, while the H2 team is helping us with our own implementations.
Other improvements
The complete list of changes can be found on our website: https://www.jooq.org/notes
A few improvements are worth summarising here explicitly
- We've added support for a few new SQL predicates, such as the standard UNIQUE and SIMILAR TO predicates, as well as the synthetic, but very useful LIKE ANY predicate.
- The JAXB implementation dependency has been removed and replaced by our own simplified implementation for a better Java 9+ experience.
- The historic log4j (1.x) dependency has been removed. We're now logging only via the optional slf4j dependency (which supports log4j bridges), or java.util.logging, if slf4j cannot be found on the classpath.
- The shaded jOOR dependency has been upgraded to 0.9.12.
- We've greatly improved our @Support annotation usage for better use with jOOQ-checker.
- jOOQ-checker can now run with ErrorProne as well as with the checker framework as the latter still does not support Java 9+.
- We've added support for a lot of new DDL statements and clauses.
- There is now a synthetic PRODUCT() aggregate and window function.
- We added support for the very useful window functions GROUPS mode.
- Formatting CSV, JSON, XML now supports nested formatting.
- UPDATE / DELETE statements now support (and emulate) ORDER BY and LIMIT.
- When constructing advanced code generation configuration, users had to resort to using programmatic configuration. It is now possible to use SQL statements to dynamically construct regular expression matching tables, columns, etc.
- Configuration has a new UnwrapperProvider SPI.
- MockFileDatabase can now handle regular expressions and update statements.
- Settings can cleanly separate the configuration of name case and quotation.
- MySQL DDL character sets are now supported, just like collations.
- A new Table.where() API simplifies the construction of simple derived tables. This feature will be very useful in the future, for improved row level security support.
- A nice BigQuery and H2 feature is the "* EXCEPT (...)" syntax, which allows for removing columns from an asterisked expression. We now have Asterisk.except() and QualifiedAsterisk.except().
- A lot of improvements in date time arithmetic were added, including support for vendor specific DateParts, like WEEK.
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.11-3.12
Features and Improvements
#714 | Add support for non-standard ORDER BY .. LIMIT clauses in UPDATE, DELETE statements |
#1699 | Add support for the SQL standard UNIQUE predicate |
#1725 | Add support for SQL standard SIMILAR TO predicate |
#2026 | Add a new @Internal annotation to annotate API parts that are not supposed to be used |
#2059 | Add support for the MemSQL database for the jOOQ Professional Edition |
#2132 | Add support for non-standard date-time fields in the EXTRACT() function |
#2208 | Implement a MockFileDatabase |
#2233 | Add Result<?> DSLContext.fetchFromXML() to allow for loading results that were exported using Result.formatXML() |
#2731 | Add some sections to the manual helping users migrate from other popular ORMs |
#3606 | Emulate INSERT/UPDATE/DELETE (SELECT ...) by WITH v AS (SELECT ...) INSERT/UPDATE/DELETE v on SQL Server |
#3607 | Allow for emitting common table expression declarations to RenderContext |
#4371 | Let ResultQuery<R> extend Publisher<R> |
#4473 | Add ResultQuery<R1>.coerce(Field<?>[]), coerce(Table<R>), that coerce a new Record type on a ResultQuery |
#4498 | Emulate INSERT .. RETURNING via SQL Server OUTPUT clause |
#5110 | Add support for Derby's MERGE statement |
#5576 | Add support for SQLite 3.15's row value expression support |
#5601 | IN list padding setting should also apply to row IN predicates |
#5640 | MockFileDatabase should support all jOOQ import formats, including JSON, XML |
#5700 | Add support for Oracle's STATS_MODE() aggregate function |
#5781 | Add support for ALTER TABLE .. RENAME COLUMN in MySQL 8 |
#5895 | Add support for TIME[STAMP] WITH TIME ZONE in HSQLDB |
#5899 | jOOQ-checker should provide both checker-framework and ErrorProne checks |
#5909 | Deprecate RenderNameStyle.QUOTED and replace feature by renderQuotedNames |
#5939 | Add PRODUCT() aggregate and window function |
#5966 | Add support for NATURAL FULL [ OUTER ] JOIN |
#5969 | Add <includeInvisibleColumns/> to code generator configuration to allow for hiding Oracle's and H2's INVISIBLE columns |
#6234 | Add newline configuration to code generator |
#6260 | Support loading multiple files in XMLDatabase |
#6450 | Javadoc should reference JDK 11 Javadoc |
#6475 | Add procedural language abstraction API |
#6486 | Add a JDK 11 build |
#6548 | Support multiple external configuration files through <configurationFiles/> |
#6583 | Work around MySQL's self-reference-in-DML-subquery restriction |
#6709 | Support custom Hibernate properties in JPADatabase |
#6778 | Support parsing PostgreSQL's dollar quoted string constants |
#6944 | Add a way to specify what object type a <forcedType/> should match |
#6971 | Allow Maven plugin to succeed in absence of valid DB connection if schema is up to date |
#7005 | Add support for MariaDB INTERSECT and EXCEPT |
#7048 | Document the FILTER clause |
#7143 | Support merging external <configurationFile/> into Maven configuration |
#7153 | Allow for configuring a locale to be used for upper/lower casing inside of jOOQ |
#7163 | Add Settings.parseWithMetaLookups |
#7216 | Add RecordN<T1, ..., TN> fetchSingle(Field<T1>, ..., Field<TN>) |
#7235 | DDLDatabase fails with ParserException on JSON field |
#7268 | Add support for MySQL's UNIQUE [ index_name ] syntax |
#7297 | Support deriving a WindowDefinition from another WindowDefinition |
#7305 | Add support for DECLARE statements inside of statement blocks |
#7306 | Add support for the SET command to assign values to variables |
#7331 | Add reference to <forcedType/> configuration in DataType, Converter, Binding |
#7336 | Add new flags to Settings to govern parser behaviour |
#7337 | Add Settings.parseDialect |
#7361 | Improve formatting of nested joins |
#7397 | Add a section to the manual about SELECT * |
#7426 | Add support for Teradata QUALIFY |
#7445 | Support parsing PostgreSQL-specific interval literals |
#7470 | Add indexOf() methods to all TableLike types |
#7485 | Document jOOQ's auto-conversion utility |
#7490 | Upgrade jOOQ-meta-extensions dependency to Hibernate 5.4 |
#7545 | ForcedType configurations should have include / exclude expressions |
#7570 | Add support for CREATE TYPE .. AS ENUM |
#7587 | Use --release flag in JDK 9+ based builds |
#7591 | Add new ResourceManagingScope which allows for Binding implementations to register resources which are freed after execution |
#7595 | Add support for Java 11 |
#7598 | Add search box to Javadocs |
#7599 | Print row count in LoggerListener for ResultQuery |
#7602 | Upgrade jOOR dependency's Java 9 functionality |
#7609 | Add Setting to turn off ORDER BY clause in emulated OFFSET .. FETCH pagination |
#7612 | Add configuration to DDLDatabase to indicate whether unquoted names are reported in lower case, upper case or as-is |
#7619 | Don't ship old XSDs in binaries |
#7628 | Add support for PostgreSQL 11 |
#7633 | ALTER TABLE .. ADD FOREIGN KEY .. REFERENCES references unqualified table name |
#7646 | Support for window functions GROUPS mode |
#7647 | Support window function EXCLUDE clause |
#7678 | Mention more ways to inline parameters in manual |
#7705 | Add support for PostgreSQL FOR NO KEY UPDATE and FOR KEY SHARE |
#7712 | Add support for Catalogs in JDBCDatabase |
#7719 | Add code generation flag to treat MySQL TINYINT(1) as BOOLEAN |
#7727 | Support parsing DEGREES() as a synonym for DEGREE() and DEG(), and RADIANS() for RADIAN(), RAD() |
#7734 | Make the JAXB implementation dependency optional with a custom fallback implementation |
#7748 | Add support for CREATE SEQUENCE flags |
#7749 | Support parsing CREATE INDEX .. ON .. USING btree (..) |
#7751 | Add support for ALTER TABLE ONLY |
#7755 | Add an integration test to discover all DSL API that is not covered by the parser |
#7756 | Improve SQLite repeat() emulation |
#7757 | Improve SQLite LPAD() and RPAD() emulation |
#7759 | Add DDLDatabase property unqualifiedSchema to specify what the unqualifiedSchema is |
#7760 | Upgrade SybDriver version in JDBCUtils.driver(String) |
#7774 | Add support for DROP TYPE |
#7776 | Add support for parsing custom data types |
#7782 | Record.formatJSON() should format nested records recursively |
#7788 | Support Java 6 and 7 only in Enterprise Edition |
#7792 | Support DatePart.DAY_OF_WEEK and DatePart.ISO_DAY_OF_WEEK |
#7793 | Support DatePart.DAY_OF_YEAR |
#7794 | Support DatePart.EPOCH |
#7796 | Support DatePart.QUARTER |
#7799 | jOOQ manual about Gradle code generation should not make explicit use of JAXB |
#7800 | Let Record extend Formattable |
#7801 | Record.formatXML() should format nested records recursively |
#7802 | Record.formatCSV() should format nested records recursively |
#7809 | Generate overridden Table.fieldsRow() method in generated tables |
#7810 | Add DSL.rowField(RowN) |
#7839 | Emulate { UPDATE | DELETE } ORDER BY and LIMIT |
#7856 | Upgrade maven-scala-plugin to scala-maven-plugin |
#7862 | Add SQLDialect.ORACLE18C |
#7865 | Add support for SQLite window functions |
#7866 | Add support for SQLite ALTER TABLE .. RENAME COLUMN |
#7870 | Add support for Java 11 |
#7872 | Add support for HSQLDB EXPLAIN PLAN FOR |
#7873 | Add HSQLDB support for Sequence.currval() |
#7882 | Add Field.startsWithIgnoreCase() and Field.endsWithIgnoreCase() |
#7885 | Add Table.rowid() |
#7902 | Add parser support for negative numeric scales |
#7904 | Apply optimistic locking logic also for non-updatable TableRecords on insert() |
#7905 | Add a new org.jooq.RowId type that corresponds to java.sql.RowId |
#7906 | Add support for H2 window functions |
#7907 | Support parsing vendor-specific RESPECT NULLS / IGNORE NULLS syntax |
#7909 | ExecuteContext.sqlException(SQLException) should accept null |
#7913 | Add support for H2 standard MERGE statement |
#7914 | Overload fetchXYZ(T, Collection<? extends Condition>) and fetchXYZ(T, Condition...) |
#7915 | Add Query.poolable(boolean) to govern the JDBC Statement.setPoolable() behaviour |
#7921 | Add support for Asterisk.except(Field...) and QualifiedAsterisk.except(Field...) |
#7922 | Upgrade org.checkerframework:checker dependency in jOOQ-checker |
#7924 | Add a CompileOptions argument object to pass annotation processors and other things to Reflect.compile() |
#7947 | Let code generation patterns match also partially qualified object names |
#7948 | Use the new H2 1.4.198 INFORMATION_SCHEMA.COLUMNS.IS_VISIBLE column |
#7952 | Add SQLDataType.INSTANT |
#7954 | Document in Javadoc that JDBCUtils.dialect() and similar methods return DEFAULT, not null |
#7956 | Deprecate DSL.groupConcat(Field<?>, String) |
#7966 | Add Setting to turn off fetching generated keys from UpdatableRecord |
#7971 | Add delegation support to JDBC 4.3 methods in DefaultConnection and similar types |
#7974 | Add Reflect.initValue(Class) |
#7999 | Overload AbstractTable.createField(Name, ...) methods |
#8000 | Deprecate AbstractTable.createField(String, ...) methods |
#8001 | Overload all date time arithmetic API with Instant arguments |
#8004 | Handle edgecase with Kotlin boolean types |
#8005 | Improve the manual's section about serializability to disclaim any backwards compatible format |
#8010 | Add Table.where(Condition) and overloads |
#8022 | Support passing java.util.Date as a Field<Object> bind value |
#8030 | Remove the unnecessary Schema.getComment() override |
#8034 | Add DataType.isDate() |
#8036 | Add DataType.isTime() |
#8041 | Add support for DataType.characterSet() |
#8061 | Add functions xyz(date) for each extract(xyz from date) datepart |
#8074 | Support parsing nested block comments |
#8075 | Support parsing nested block comments in plain SQL |
#8076 | Allow for chaining DataType.asConvertedDataType(Converter) calls |
#8077 | Add org.jooq.types.YearToSecond to support PostgreSQL mixed interval values |
#8083 | Add Interval.toDuration() |
#8087 | Add support for overloaded functions in H2 |
#8093 | Add support for result less statements in MockFileDatabase |
#8102 | Add RenderNameCase.LOWER_IF_UNQUOTED and UPPER_IF_UNQUOTED |
#8103 | Add RenderQuotedNames.EXPLICIT_DEFAULT_QUOTED and EXPLICIT_DEFAULT_UNQUOTED |
#8107 | Add Name.Quoted Name.quoted() |
#8108 | Add a CriteriaQuery vs jOOQ Example |
#8109 | Add org.jooq.tools.jdbc.LoggingConnection |
#8114 | [#8004] Handle edgecase for Kotlin boolean type |
#8115 | XMLDatabase configuration properties should be in camel case for consistency |
#8124 | Support regular expressions in MockFileDatabase |
#8126 | Add an external MockFileDatabaseConfiguration object |
#8135 | Add support for IF statements inside of statement blocks |
#8138 | Add indentation configuration to code generator |
#8145 | Add an UnwrapProvider SPI that allows for unwrapping underlying JDBC types through proprietary APIs |
#8163 | Deprecate synonym keywords and use suffix underscore instead |
#8168 | Add support for procedural blocks that do not generate BEGIN .. END |
#8174 | Add support for WHILE loops in procedural blocks |
#8175 | Add support for LOOP in procedural blocks |
#8176 | Add support for indexed FOR loops in procedural blocks |
#8179 | Provide empty base implementation for QueryPartInternal.clauses() |
#8186 | Add support for EXIT [ WHEN ] in procedural blocks |
#8187 | Add support for CONTINUE [ WHEN ] in procedural blocks |
#8188 | Add support for labels in procedural blocks |
#8189 | Add support for GOTO in procedural blocks |
#8190 | Remove private DSL.field(Row[N]) methods |
#8206 | Add new Settings.inlineThreshold |
#8213 | Move some DataKey values to a new BooleanDataKey enum |
#8217 | Add an annotation for commercial only API |
#8219 | Add additional documentation that explains DefaultGeneratorStrategy's role in disambiguating names |
#8233 | YearToSecond should be equal to YearToMonth or DayToSecond, if same interval is represented |
#8235 | Improve Sakila database example scripts |
#8236 | Add DataType.isTimestamp() |
#8238 | Add DSL.convert(DataType<?>, Field<?>, int) to support SQL Server CONVERT() function |
#8240 | Add a Javadoc link from all org.jooq.XYZ types to their respective DSL.xyz() constructor method |
#8247 | Add DSL.truncate(String) overload for consistency |
#8249 | Support configuring ParamType in /translate service |
#8255 | Add more Javadoc to common org.jooq.XYZ types |
#8256 | DefaultExecuteContext should contain only a single ThreadLocal list with resources |
#8261 | Add trim(String, char), rtrim(String, char), ltrim(String, char) |
#8262 | Add support for SQL Server 2017 TRIM() |
#8264 | Expose new Settings.parseDialect in ParserCLI |
#8275 | Improve SQLite's CEIL and FLOOR emulation |
#8276 | Add overloads CreateTableColumnStep.columns(Name...) and columns(String...) |
#8280 | Add CTE support for SQLite |
#8285 | Add support for REPEAT statements in procedural blocks |
#8290 | Add Parser.parseStatement() to parse procedural code |
#8291 | Create bug report / feature request / question issue templates |
#8294 | Add interactive mode to ParserCLI |
#8297 | Support inverse distribution functions in H2 |
#8298 | Support hypothetical set functions in H2 |
#8299 | Support FILTER clause on aggregate functions in H2 |
#8300 | Support MODE() and MEDIAN() in H2 |
#8302 | Emulate procedural languages in H2 |
#8308 | Support ALTER TABLE .. ADD with multiple columns in PostgreSQL |
#8309 | Add parser support for declaring multiple variables in one procedural statement |
#8317 | Improve manual railroad diagrams for repetitions with comma |
#8324 | Parser should ignore { CREATE | DROP } EXTENSION statement |
#8325 | Add a special comment syntax to the Parser and DDLDatabase that allows for ignoring certain statements |
#8331 | Add DSLContext.truncateTable() as an alias for truncate() |
#8333 | Support INSERT .. ON ( DUPLICATE KEY | CONFLICT ) in Derby |
#8346 | Improve Javadoc on DSLContext.meta(Table...) etc. |
#8360 | Add new MatcherTransformType.LOWER_FIRST_LETTER and UPPER_FIRST_LETTER |
#8383 | Emulate { UPDATE | DELETE } table AS alias in SQL Server |
#8386 | Support inline constraint names in CREATE TABLE statements |
#8390 | Add support for unmapping Iterable |
#8391 | DSLContext.fetchFromJSON() should be able to read JSON without header information |
#8407 | Add code generation configuration flag to set Connection.setAutoCommit() |
#8409 | Add support for plain SQL CREATE VIEW statements |
#8412 | Add DSL.neg(Field<?>) as an alias for Field.neg() |
#8415 | Support PERCENT and WITH TIES in H2 |
#8421 | Support various DDL statements in Informix |
#8424 | Better VALUES() emulation in Informix using TABLE(MULTISET) |
#8430 | Ignore ON { DELETE | UPDATE } NO ACTION in dialects that do not support the syntax |
#8433 | Add support for SQLite ON CONFLICT |
#8438 | Add support for CREATE SCHEMA in MySQL |
#8446 | Add <sql> to <forcedType> to allow for matching columns with SQL |
#8447 | Add <sqlMatchesPartialQualification> |
#8451 | Add SQL parser support for PostgreSQL ILIKE |
#8463 | Add <includeCheckConstraints/> flag to code generator |
#8464 | Log slow result set fetching in code generator |
#8465 | Add a new <logSlowResultsAfterSeconds/> code generation flag |
#8471 | Add a link in the manual from simple-crud to settings-return-all-on-store |
#8477 | Support views with renamed columns in SQLite's CREATE VIEW statement |
#8479 | Emulate INSERT .. ON DUPLICATE KEY UPDATE .. WHERE on MySQL |
#8486 | Add Settings.renderNamedParamPrefix to support dialect specific named parameter placeholders |
#8498 | Add more documentation to the RETURNING clause |
#8504 | Remove manual from OSS repository |
#8505 | Modules should reference managed H2 dependency |
#8522 | Emulate the PL/SQL BOOLEAN type in SQL functions in Oracle 12c |
#8529 | Improve documentation of INSERT ... ON CONFLICT related APIs |
#8539 | Add alias DSL.default_() for DSL.defaultValue() |
#8542 | Add support for LATERAL to MySQL |
#8547 | Add SQLDialect.SQLITE_3_28 and SQLDialect.SQLITE_3_25 |
#8551 | Support old SQLDialects only in commercial distributions |
#8552 | Add SQLDialect.supports(Collection<SQLDialect>) |
#8556 | Support GROUP BY ROLLUP on SQL Data Warehouse |
#8560 | Add support for calling stored functions with defaulted parameters from SQL in Oracle |
#8577 | Add synthetic [NOT] LIKE ANY and [NOT] LIKE ALL operators |
#8579 | Support parsing the UNIQUE predicate |
#8588 | Add support for SQLite partial indexes |
#8590 | Add support for SQLite EXPLAIN |
#8591 | DSL#table(Object[]) calls DSL#table(Field) with incompatible @Support annotation |
#8595 | Support more DDL for MySQL |
#8596 | Support more DML for MySQL |
#8600 | Emulate CREATE TABLE (...) COMMENT syntax in DB2 |
#8601 | Add code generator support for DB2 table and column comments |
#8602 | Add support for DB2 translate |
#8604 | Add support for DB2 multi ALTER TABLE ADD / DROP statements |
#8616 | Add Settings.parseSearchPath |
#8619 | Let Query subtypes extends RowCountQuery, which extends Publisher<Integer> |
#8620 | Replace Query references by RowCountQuery where appropriate |
#8623 | Add parser support for TOP (n) in DML |
#8639 | Improve documentation about custom syntax elements |
#8646 | Apply Settings.fetchSize also to other statements than ResultQuery |
#8649 | Add support for MySQL's ALTER TABLE .. DROP FOREIGN KEY syntax |
#8650 | Add support for MySQL's ALTER TABLE .. DROP PRIMARY KEY syntax |
#8656 | Add org.jooq.DDLExportConfiguration |
#8657 | Add DDLExportConfiguration.createSchemaIfNotExists and createTableIfNotExists flags |
#8658 | Improve manual's parser grammar and make better reuse of keywords in DDL |
#8660 | Add support for synthetic ALTER TABLE .. DROP PRIMARY KEY <name> syntax |
#8671 | Some @Support annotations have duplicated dialects |
#8674 | Complete parser test suite with tests for all supported built-in functions |
#8675 | Parse CONNECT_BY_ROOT expressions |
#8678 | Enable Settings.parseUnknownFunctions in DDLDatabase |
#8685 | Avoid generating unnecessary {@inheritDoc} |
#8689 | Generate LN function in H2, instead of LOG |
#8693 | Add support for generation of comments on HSQLDB schema objects |
#8695 | Use Configuration#family() convenience |
#8696 | Use SQL Server 2012's LOG() with base parameter |
#8703 | Add DSL#log(Field, Field) overload |
#8704 | Add support for MERGE in Vertica |
#8710 | Add support for generating comments on tables in Vertica |
#8716 | Support DSL#md5() for SQL Server |
#8724 | Add UpdateSetStep.setNull(Field<?>) for convenience |
#8728 | Parser cannot handle double quoted string literals in dialects that support them |
#8735 | Support DSL#offset[Date]Time() and DSL#instant() for SQLite |
#8736 | Avoid catching NumberFormatException when parsing potential numbers |
#8739 | H2: Support ALTER SCHEMA |
#8742 | H2: Support DROP SCHEMA ... [CASCADE | RESTRICT] |
#8744 | H2: Support INSERT ... ON CONFLICT DO UPDATE |
#8745 | Add Guava to the documented list of shaded dependencies |
#8746 | Add Settings.(execute|record|transaction|visit)Listener(Start|End)InvocationOrder to support REVERSE ordering on end() events |
#8751 | Improve rendering performance of SQL templates |
#8753 | Add additional Context.sql(long), sql(float), sql(double) |
#8754 | Avoid using plain SQL templating, internally |
#8759 | Add support for SET SCHEMA in Teradata |
#8764 | Add comments in old manual versions about the jooq-meta and jooq-codegen package renames |
#8766 | Add missing dialects to DSLContext#mergeInto(Table) |
#8767 | Complete @Support annotation on DSL#alterView() to include `DB2` and `FIREBIRD` |
#8768 | Complete @Support annotation on DSL#alterIndexIfExists() to include SQLDATAWAREHOUSE and TERADATA |
#8769 | Methods on TableOuterJoinStep should for now only support ORACLE |
#8770 | Align @Support annotations of SelectLimitAfterOffsetStep#limit() methods |
#8771 | Add LIMIT ... OFFSET ... WITH TIES support for Redshift |
#8772 | Fix @Support annotations of CreateIndexIncludeStep |
#8774 | Remove SQLITE from @Support annotations on AlterTableAlterStep |
#8780 | SQL Server: Support AlterIndexStep#renameTo() |
#8781 | Improve error message when org.jooq.util class cannot be found in code generator configuration |
#8782 | WindowRowsAndStep methods should declare VERTICA support |
#8783 | MergeNotMatchedSetStep methods should declare VERTICA support |
#8784 | MergeValuesStepN methods should declare MARIADB and AURORA_MYSQL support |
#8789 | Add support for parsing MySQL numeric interval literals |
#8793 | Add missing dialects to MergeValuesStepN#values() |
#8794 | Add missing dialects to OrderedAggregateFunction |
#8795 | Support AlterTableAlterStep#set() with SQLDATAWAREHOUSE |
#8796 | Implement InsertOnDuplicateSetStep#set() for FIREBIRD_3_0 |
#8797 | Add Javadoc to StopWatchListener explaining that it should be wrapped in an ExecuteListenerProvider |
#8803 | Improve performance of StringUtils#replace() |
#8825 | Add support for additional DB2 and SQLDATAWAREHOUSE DateParts |
#8827 | SQLServerDatabase should read tables also from sys.all_objects |
#8833 | Oracle: Support DatePart WEEK |
#8837 | Add missing @Support annotations to Operator enum |
#8850 | Informix: Support LikeEscapeStep#escape() |
#8852 | Support parsing empty IN lists |
#8853 | Add support for [NOT] LIKE ANY (subquery) and [NOT] LIKE ALL (subquery) |
#8854 | Add more internal type safety by making Tools.fields() methods generic |
#8856 | Generate empty IN lists in SQL for H2 and SQLite |
#8857 | Spring Boot example should reference custom jOOQ version |
#8863 | Use imported class name in Tables.java to dereference singleton table instance |
#8867 | Add SQLDialect.supported() |
#8883 | Use noCondition() in fetchXYZ(Table), fetchXYZ(Table, Condition) overloads |
#8887 | Add SQLDataType.DECIMAL_INTEGER(int) as a shortcut for DataType.precision(int) |
#8889 | Upgrade scala 2.12 dependency to 2.12.8 |
#8899 | Implement specialised emulation for Oracle single row INSERT .. RETURNING with expressions |
#8900 | Release 3.12: Make current master branch Java 6 compatible |
#8903 | Add Support annotations to DataType methods |
#8905 | GeneratorWriter should check the file size prior to opening existing files to compare contents |
#8909 | Upgrade jOOR dependency to 0.9.12 |
#8912 | Add reference to noCondition(), trueCondition(), and falseCondition() |
#8914 | Always use MiniJAXB |
#8918 | MiniJAXB should warn about unknown XML elements |
#8919 | MiniJAXB#marshal() should output formatted XML |
#8920 | Implement UPDATE / DELETE .. RETURNING in SQL Server using OUTPUT |
#8924 | Add Settings.updateRecordVersion and Settings.updateRecordTimestamp |
#8925 | Add DAO.fetchRangeOf(Field<Z>, Z, Z) |
#8932 | Use diamond operator in jOOQ code |
#8939 | Support Flyway file ordering in DDLDatabase |
#8943 | Add org.jooq.JSON and org.jooq.JSONB |
#8944 | Add support for standard JSON functions |
#8959 | Add Settings.mapConstructorParameterNamesInKotlin |
#8963 | Manual page about SELECT should use DSL.inline() and DSL.val() in addition to selectZero() and selectOne() |
#8972 | jOOQ-meta should query dictionary views for column existence rather than the column itself |
#8975 | Log warning when user uses <inputSchema/> on a database that does not support schemas |
#8976 | [jOOQ/jOOQ#8939] Support Flyway file ordering in DDLDatabase |
#8982 | Add a SingleConnectionDataSource |
#8985 | Create a new jOOQ-extensions module |
#8986 | Move DDLDatabase DDL simulation via H2 to jOOQ-extensions and implement it through org.jooq.Meta |
#8987 | Improve MockResult Javadoc |
#9001 | DefaultRecordMapper should internally also use the RecordMapperProvider |
#9006 | Document logger name for SQL logging |
#9009 | AbstractMeta should consistently cache all information |
#9011 | DDLDatabase failed to parse MySQL NOW(6) |
#9015 | Add support for unqualifiedSchema in JPADatabase to prevent generating the H2 PUBLIC schema |
#9018 | Update Scala compiler to 2.12.9 |
#9022 | Mention fetch sizes on the topic of lazy fetching |
#9030 | Add AlterSequenceStep.restartWith(Field<? extends T>) overload |
#9032 | Add a documentation example for usage of transactionResult() |
#9035 | Teradata support for InsertOnDuplicateStep#onDuplicateKeyUpdate() |
#9036 | Missing @Support annotations on SelectSeekStep<N> methods |
#9037 | Missing @Support annotations on CaseWhenStep#map[Fields|Values]() methods |
#9048 | Delete module-info.java.invalid files |
#9051 | Add section titles to multi page manual |
#9058 | Undocument use-attribute-converters in favour of useAttributeConverters |
#9062 | AlterTableImpl#dropColumn() should not use #dropColumns() |
#9063 | Support for ALTER TABLE ... DROP PRIMARY KEY for Derby and HSQLDB |
#9064 | HSQLDB: Support WEEK() function |
#9070 | Add Constants.CP_RUNTIME and other values |
#9078 | Improve MockFileDatabase error message "Invalid SQL" |
#9082 | ResultQuery.fetchStream() and similar overloads should add an explicit statement about resulting streams being resourceful |
Breaking changes
#5309 | Add support for CREATE TABLE t(c1, c2, ..., cn) AS SELECT ... |
#5538 | Compilation error in Keys.java when two tables contain the same (unique) index name in SQL Server |
#7242 | Add support for JSON / JSONB types |
#7565 | Remove @javax.annotation.Generated annotation from jOOQ code |
#7583 | Add new <generatedAnnotationType/> flag to specify Generated annotation |
#7643 | Use slf4j directly for logging, remove log4j dependency |
#7659 | Support any Number type for LIMIT .. OFFSET |
#7737 | Remove the org.jooq.api.annotation package |
#7747 | Rename jooq-codegen.xsd Schema, Schemata, Catalog, Catalogs types to have a Type suffix |
#7826 | Constraints referencing columns that are not generated should not be generated either |
#7851 | DSL.coerce() should use argument field's qualified name |
#7874 | Pull up DAOImpl.getId() to DAO.getId() |
#7925 | Make org.jooq.impl classes Iif, NullIf, KeywordImpl package-private |
#7953 | Discover JPA annotations also from overridden super class methods |
#8033 | Relax generic constraint on DSLContext.executeInsert(), executeUpdate() and similar methods |
#8173 | SelectIntoStep.into() should return SelectFromStep, not SelectIntoStep |
#8231 | Negative YearToMonth() intervals are not correctly normalised |
#8232 | Negative DayToSecond() intervals are not correctly normalised |
#8234 | "Unnecessary" casts should no longer be ignored |
#8362 | <regexFlags/> is not applied to matcher strategy |
#8434 | Support H2 v1.4.198 array syntax |
#8502 | Add support for H2 1.4.198 row value expression subquery syntax |
#8682 | Parsing of LOG() function |
#8877 | fetchSingle() failure does not trigger ExecuteListener#exception() event |
Bug Fixes
#1535 | Generate dummy ORDER BY clause for ranking functions on databases that require them |
#5215 | Companion object for routine classes generated by ScalaGenerator cause java.lang.IllegalAccessError at runtime |
#6382 | Fix Derby Support annotations |
#6745 | DDL statements on MySQL create CHAR column instead of VARCHAR column on unknown lengths |
#6754 | Significant amount of Object[] allocations due to internal EnumMap |
#6920 | Update API with Vertica Support annotations |
#6932 | Document <enumConverter/> in manual |
#7161 | Slow ROWTYPE discovery queries on large Oracle schemas |
#7295 | SQL Translation Error with MONEY data type |
#7319 | SQLDialectNotSupportedException: The ON DUPLICATE KEY UPDATE clause cannot be emulated for DEFAULT when using the Batch API with named parameters |
#7389 | UniqueKey.getReferences returns unnamed foreign keys |
#7418 | Error when using <matchers/> with <schemas/> in Maven code generation |
#7429 | Flawed Custom Logging ExecuteListener example in the manual |
#7434 | ORA-01861 when casting string as date |
#7496 | UDT data types are unqualified in PostgreSQL, when there is more than one UDT data type per schema |
#7518 | Various parser bugs / missing features |
#7525 | Support parsing DAYOFMONTH() function |
#7551 | Wrong type information associated to Row[N].operator(T1, ..., TN) predicates |
#7554 | UpdatableRecordImpl no longer work when globalObjectReferences is set to false |
#7556 | Add a specific error message if org.jooq.util packages are being used in 3.11+ |
#7562 | Incomplete Support annotation on some of the H2 style mergeInto overloads |
#7567 | Support mixing constraint definitions and columns in the parser |
#7568 | Cannot parse CREATE INDEX statement on a field called "field" |
#7569 | Regression in UpdatableRecord.store() and update() methods when used with connection pools |
#7571 | Support alternative PostgreSQL array syntax in parser |
#7573 | Code generator should generate implicit join constructors in absence of inbound foreign keys |
#7578 | Spring boot example test repeats identical assertion |
#7579 | org.jooq.meta.xml.XMLDatabase does not generate target classes when project is compiled on JDK 9 or 10 |
#7584 | Regression in DSL.or(Collection) when passing empty collection |
#7589 | Cannot bind double types to prepared statements when using Oracle and DBCP |
#7594 | Illegal reflective access when running jOOQ on Java 10 |
#7597 | CREATE TABLE with enum types generates CHECK constraint rather than enum type reference in PostgreSQL |
#7600 | NullPointerException on Query.getBindValues |
#7616 | Support CREATE OR REPLACE VIEW in H2 |
#7622 | Typo in manual, additional DDLDatabase and JPADatabase reference |
#7627 | Cannot parse comma separated identity specification elements |
#7630 | Close the Maven Plugin's URLClassLoader after code generation |
#7634 | Add remark to the Javadoc of <SQLDialect>DataType classes indicating what the deprecation replacement is |
#7637 | Manual refers to non-existent "configuration" element in Gradle code generation configuration |
#7641 | java.lang.NoSuchMethodException when calling createARRAY on JBoss WrappedConnectionJDK8 |
#7644 | Code generator uses H2 TIMESTAMP precision instead of scale |
#7649 | jOOQ 3.11+ transitive dependency prevents it from being loaded on WebLogic 12.1.3 |
#7650 | Issues with codegen generating PUBLIC always |
#7651 | Error Parsing Script for DDLDatabase when column name is called "index" |
#7652 | Upgrade to maven-compiler-plugin 3.7.1-SNAPSHOT |
#7655 | ResultImpl#intoMap produces an incorrect error message on duplicate key |
#7660 | EVERY() aggregate function emulation doesn't yield NULL when aggregating empty sets |
#7663 | Referenced WindowDefinitions should not be inlined in MySQL, Sybase SQL Anywhere |
#7672 | NPE in DefaultRecordMapper when returning it from custom RecordMapperProvider |
#7680 | Allow for overriding the order of generated import statements |
#7688 | NPE in MockResultSet.withTZ() methods |
#7691 | NullPointerException when aggregating row value expressions using ARRAY_AGG() |
#7692 | Compilation errors in generated code for PostgreSQL's pg_catalog schema |
#7693 | Compilation error in generated code when generated Javadoc contains unicode escape sequences |
#7694 | Cannot parse OTHER data type |
#7696 | Cannot parse H2 style ARRAY data type |
#7706 | ArrayIndexOutOfBoundsException when using double quotes in plain SQL as string delimiters |
#7707 | Dead link to MySQL manual on group by page |
#7713 | ASEDatabase doesn't work with older Sybase ASE versions |
#7714 | Meta.getCatalogs() should not return catalogs in databases that do not support them |
#7724 | Parser should support parsing pi() function |
#7725 | Support parsing unknown, parameterless functions |
#7731 | DAO methods do not profit from reflection cache when Settings.returnRecordToPojo = true |
#7732 | XJC generated classes should compare Pattern.pattern() in generated equals() and hashCode() methods |
#7735 | XJC generated classes should generate XmlElementWrapper element for Lists |
#7741 | Unclear code example in 'Sequence and serials' doc |
#7742 | Potential NullPointerException in custom Converter when running INSERT statement |
#7761 | JZ0NK: Generated keys are not available in Sybase ASE when calling UpdatableRecord.store() on a table without identity |
#7764 | Race condition in cached ImmutablePOJOMapperWithParameterNames |
#7765 | [#7764] Race condition in DefaultRecordMapper |
#7767 | DDLDatabase scripts path wild cards do not work correctly |
#7769 | Parser cannot parse MySQL's DEFAULT CHARSET clause |
#7771 | DDLDatabase should ignore storage clauses |
#7785 | Column pg_prog.proisagg does not exist in PostgreSQL 11 |
#7811 | Array types cannot change nullability when generating DDL |
#7813 | Error during code generation when using DDLDatabase on a table with a MySQL enum type |
#7814 | DDLDatabase does not generate enum types when parsing MySQL ENUM syntax |
#7816 | Implement <includeUniqueKeys/>, <includePrimaryKeys/> and <includeForeignKeys/> |
#7824 | NPE when generating code for an index whose column(s) are not generated |
#7827 | InformationSchema.toString() methods generate empty <comment> elements |
#7830 | Manual section about CRUD should not display an N+1 example |
#7834 | AbstractMeta::get never returns an unqualified result |
#7835 | name("").append(name("a")) produces wrong result |
#7846 | Document the fact that <forcedType/> converters can be Java code |
#7853 | Code generator fails to parse partial index when using DDLDatabase |
#7861 | Oracle 18c ALL_ARGUMENTS.DATA_LEVEL no longer lists nested data types |
#7864 | Misleading example about bindings in manual |
#7867 | DSLContext.fetchCount(Select) should rename the select statement's column names to prevent ambiguities |
#7878 | Single element array expressions must generate trailing comma in H2 |
#7886 | Parser doesn't correctly recognise Oracle MINUS operation |
#7889 | Typo in manual reading SQLiteDatabaes |
#7892 | Missing information_schema.routines table error when running code generator on CockroachDB |
#7893 | Invalid javadoc created for deprecated data types |
#7894 | [#7893] Generate valid javadoc for deprecated data types |
#7908 | Add documentation about UPDATE .. FROM |
#7918 | Bad formatting of constraints in CREATE TABLE statements |
#7920 | Missing implementation of AbstractRecord.formatCSV() |
#7923 | jOOQ checker fails with InternalUtils.symbol: tree is null error when checked code has no enclosing method |
#7926 | jOOQ-checker does not type check in absence of Require annotation |
#7929 | jOOQ-checker should not allow any jOOQ API usage in the absence of an Allow annotation |
#7930 | Missing Support annotation on various DSL.val(), value(), inline() overloads |
#7937 | Documentation examples using jOOQ with JPA show wrong Query.getParams() usage |
#7938 | Incorrect Javadoc entry for Field#containsIgnoreCase |
#7939 | Fix Javadoc entry for Field#containsIgnoreCase |
#7942 | Excess SELECT statement run on UpdatableRecord.store(), insert(), update() on MySQL |
#7950 | Illegal reflective access operation on JDK 11 |
#7959 | Internal CursorResultSet does not implement JDBC 4.1 and 4.2 methods |
#7961 | CREATE INDEX IF NOT EXISTS should intercept error code 1913 in SQL Server |
#7968 | Document behaviour of unnamed expressions in the SELECT clause |
#7982 | Unnecessary alias generation in parser for derived tables |
#7986 | Significant time spent in OffsetDateTime.parse() when reading OffsetDateTime fields |
#7991 | NullPointerException in QueryPartList.removeNulls with Java 11 and immutable collections |
#8006 | INSERT .. RETURNING produces records with wrong attached Configuration |
#8011 | DDLDatabase cannot handle tables containing COLLATE clauses |
#8013 | Regression in OffsetDateTime parser when PostgreSQL timestamps have fractional seconds of 1, 2, 4, 5 digit precision |
#8017 | Oracle TIMESTAMP WITH TIME ZONE default binding truncates microseconds |
#8024 | Missing ORACLE Support on DSL.offsetDateTime() overload |
#8026 | Wrong SQL generated when H2 OffsetDateTime values are inlined |
#8035 | PostgreSQL DateAdd doesn't work correctly with LocalDate |
#8037 | DSL.localDate() and DSL.localTime() don't work correctly on SQLite |
#8040 | Avoid unnecessary loop in Fields.indexOf() |
#8044 | Code generation fails on JDK9+ with javax.xml.bind.UnmarshalException: unexpected element when using external <configurationFile/> |
#8047 | Error Importing Sakila database in Oracle Express 11g |
#8048 | CustomQueryPart manual section should explain how to implement accept() |
#8063 | Bad inlining of Double.NaN in HSQLDB |
#8065 | HSQLDB implementation of Field.add(Interval) cannot handle fractional seconds |
#8067 | Code generator doesn't generate length on VARCHAR(n) ARRAY types |
#8070 | Cannot create tables with VARCHAR(n) ARRAY types in HSQLDB |
#8072 | Code generator fails on PostgreSQL 9.3.9 because of unsupported not in predicate on row value expressions |
#8086 | Resolve relative paths in target directory in Maven plugin |
#8096 | Manual page about ParserCLI uses wrong classpath |
#8110 | Embedded UNIQUE INDEX specification in CREATE TABLE statement does not get generated |
#8113 | Cannot call MockStatement.getGeneratedKeys() |
#8116 | XMLDatabase should not distinguish between empty catalog and absent catalog |
#8118 | NullPointerException in XMLDatabase, when no schemas could be loaded |
#8123 | java.lang.ClassCastException: java.base/java.lang.String cannot be cast to java.base/java.util.UUID when using UUID types with MockFileDatabase |
#8125 | Incorrect implementation of MockFileDatabase.nullLiteral() |
#8128 | returningResult() returns generated record type when returning only the identity |
#8131 | ClassCastException in H2 when calling returningResult() to fetch an identity when the generated record does not implement Record1 |
#8143 | java.lang.NoSuchMethodException when calling setBinaryDouble on org.jboss.jca.adapters.jdbc.WrappedStatement |
#8149 | No-arg DefaultConfiguration.derive() does not correctly derive |
#8150 | DefaultConfiguration is missing some JavaBeans setters |
#8151 | ClassCastException in ClobBinding when ConnectionProvider provides wrapped Connection |
#8156 | Wrong Javadoc on LoaderOptionsStep.onDuplicateKeyUpdate() |
#8158 | ORA-38104 when using ON DUPLICATE KEY UPDATE in Oracle |
#8172 | Document <includeIndexes/> in the manual |
#8178 | DefaultOffsetDateTimeBinding fails when year field is negative |
#8181 | Timezone Offset parser doesn't correctly parse offset seconds |
#8197 | Row[N].isDistinctFrom(T1, ..., TN) and others do not work correctly when passing null values |
#8203 | ORA-01745 executing a SELECT * FROM WHERE column IN (large collection) |
#8210 | Fix a variety of compiler warnings when building jOOQ |
#8221 | StringIndexOutOfBoundsException when parsing a PostgreSQL TIMESTAMPTZ with microseconds precision |
#8222 | Resolves 8221: StringIndexOutOfBoundsException parsing PSQL Timestamp |
#8241 | Wrong results from field when forcedType references both converter and binding |
#8243 | Spelling in CONTRIBUTING.md |
#8244 | Outdated Javadoc on WindowDefinition referring WINDOW clause support |
#8251 | Documentation references inexistent org.util package |
#8265 | ParamType not supported: FORCE_INDEXED when calling Query.getSQL() |
#8270 | Wrong foreign key specification generated in MySQL, when foreign key shares name with unique key in different table |
#8279 | Emulate inline window specifications based on other window definitions in SQLite |
#8281 | PDF manual is missing content contained in tags |
#8287 | Change message "Please report this bug here" for cases which are not bugs |
#8293 | Wrong Javadoc on SelectQuery.addHaving(Operator, Condition...) |
#8295 | RenderKeywordStyle.PASCAL doesn't work when keywords contain whitespace |
#8328 | { UPDATE | DELETE } .. LIMIT isn't emulated correctly in the absence of unique key meta information |
#8329 | Lacking formatting for WITH [ NO ] DATA clause |
#8332 | Wrong documentation for forceIntegerTypesOnZeroScaleDecimals |
#8336 | DDLDatabase cannot load relative paths in Maven modules that do not contain wildcards |
#8338 | Redundant QualifiedField.name and AbstractNamed.name fields |
#8339 | RemovingPrefixMapper is not implemented correctly |
#8342 | Array of enums whose literals contain special characters cannot be bound in PostgreSQL |
#8350 | Parser parses (a, b) IS NULL as (a, b) IS NOT NULL |
#8355 | NullPointerException on Routine.toString() when routine is not attached to a Configuration |
#8361 | Cache Patterns in MatcherStrategy |
#8363 | Slow check for similar generated files that differ by case |
#8368 | Compilation errors in generated code for DB2 overloaded procedures |
#8372 | DB2 array types get generated as routines |
#8375 | DB2 array types get generated as UDTRecord types |
#8393 | Replace static field references in manual by instance references |
#8394 | Manual CAST() example shouldn't reference PostgresDataType.TEXT |
#8397 | Parser doesn't recognise BOOL data type |
#8401 | Add support for parsing REGEXP, RLIKE, and LIKE_REGEX operator |
#8402 | Bad SQL generated when setting data type and nullability in PostgreSQL's ALTER TABLE .. ALTER .. SET statement |
#8413 | Rollback should not be called when TransactionListener.commitEnd() throws exception |
#8414 | Don't emulate empty ORDER BY clause in H2's ROW_NUMBER() function |
#8417 | Syntax error when generating code on Informix 12.10 without DELIMIDENT=y |
#8423 | Typo in manual example code for dynamic SQL |
#8429 | Field.endsWith() and similar methods should escape argument lazily |
#8454 | <inputSchema/> doesn't work on Informix code generation |
#8456 | Calling Record.get(0, int.class) returns null if value is not convertible to int |
#8460 | Regression calling POJO setters twice from DefaultRecordMapper.MutablePOJOMapper |
#8468 | DataTypeException when org.jooq.Meta accesses PostgreSQL array column with default expression |
#8478 | ERROR: conflicting ColumnTypes while executing meta query on CockroachDB |
#8484 | 3.11 vs. 3.12 version mismatches between Constants.java and XSD files |
#8488 | Manual page about matcher strategies should use "see MatcherRule", not "--> MatcherRule" |
#8489 | Overrides of AbstractTable#fieldsRow() in Scala don't work due to compiler bug |
#8491 | Remove unnecessary marker tokens in source code |
#8493 | Support JSR 310 types as <name/> in <forcedType/> data type rewriting feature |
#8496 | Regression in DefaultRecordMapper, calling matching setter for JPA annotated getter |
#8503 | Make SET clause in ON DUPLICATE KEY UPDATE optional in parser |
#8511 | Update SQLite identifier list in DefaultRenderContext#SQLITE_KEYWORDS |
#8512 | JPADatabase may not be able to properly detect AttributeConverter |
#8513 | Generator may fail with NPE for CUBRID enums with some <forcedType> definitions |
#8515 | InsertOnConflictWhereStep#where() should return InsertOnConflictConditionStep |
#8527 | MiniJAXB#append() doesn't work for enum types |
#8531 | Wrong Context.subqueryLevel() when emulating derived column lists |
#8535 | Generate @UniqueConstraint annotation instead of @Column(unique = true) |
#8536 | Missing constraint name in generated @UniqueConstraint annotation |
#8537 | Parsing CREATE SEQUENCE always leads to quoted sequence names |
#8544 | ExecuteListener#end() not last lifecycle event when using DSLContext#fetchOne() |
#8550 | Improve formatting of generated table-level JPA annotations |
#8557 | StackOverflowError when using same query instance on both sides of a set operation |
#8561 | Wrong cast generated for Informix and others when casting a LocalDateTime value |
#8570 | Wrong Javadoc on Record.setValue() |
#8572 | Add parser support for RATIO_TO_REPORT |
#8573 | Outdated Javadoc on ExecuteType.DDL |
#8578 | DefaultRecordMapper cannot map into generic type variable in Kotlin |
#8581 | Generator can fail picking up default values using SQLite 3.27.2.1 driver |
#8582 | MySQLDSL should support Aurora MySQL |
#8584 | SQLiteDatabase#loadPrimaryKeys() should use DSLContext#fetch(String, Object...) |
#8593 | DB2 ranking functions require an ORDER BY clause |
#8603 | DB2 CREATE TABLE IF EXISTS emulation should ignore SQLState 42710, not 42704 |
#8606 | Bad SQL generated when writing multi row insert query with unknown column names (plain SQL table) |
#8615 | Missing NOTICE file from commons-lang |
#8625 | Missing DB2 dialect versions in SelectQueryImpl#WRAP_EXP_BODY_IN_DERIVED_TABLE |
#8627 | Some Support annotation mismatches between DSLContext and DSL methods |
#8634 | MySQL does not support DROP INDEX IF EXISTS |
#8636 | Missing PlainSQL annotations on some API |
#8637 | Support annotation mismatch between overloaded methods |
#8645 | Sakila/PostgreSQL: Replace nonexisting IF with CASE |
#8686 | jOOQ generation tool produces Vertica composite unique key columns in wrong order |
#8691 | Serialization fails when table contains SQLDataType.INSTANT columns or when using Converter.ofNullable() converters |
#8694 | Floor switch inconsistent wrt SQL dialects |
#8697 | Add missing MySQL dialects to switch in MD5#getFunction0() |
#8698 | Sign switch inconsistent wrt SQL dialects |
#8699 | Trim switch inconsistent wrt SQL dialects |
#8700 | No foreign key information generated in Vertica |
#8701 | Code generator produces empty strings as default expressions in Vertica |
#8706 | Error when translating a query with OFFSET only (no LIMIT) to Vertica |
#8707 | FunctionTable switch inconsistent wrt SQL dialects |
#8708 | Ranking functions without ORDER BY are not correctly emulated in Vertica |
#8709 | Work around Vertica's incorrect IS NOT NULL implementation |
#8717 | Support parsing SQL Server's UNIQUEIDENTIFIER data type |
#8723 | Wrong SQL generated when using qualified index references with H2 CREATE or DROP INDEX statements |
#8727 | Bad Support annotation on Row[N].op(QuantifiedSelect) |
#8729 | Translator loses quoted names |
#8730 | DSL#localDateTime(LocalDateTime) drops fractional seconds on SQLite |
#8737 | SQLite: Date arithmetic does not support fractional seconds |
#8756 | DSL.timestampAdd() produces wrong cast for teradata |
#8758 | Parse DEFAULT keyword in UPDATE |
#8761 | Fix missing Support annotations for Teradata |
#8777 | Formattable String formatCSV(boolean header, char delimiter) header value is always ignored |
#8785 | Remove DSL#alterIndex() support for TERADATA |
#8786 | Remove execution time from logging output in manual |
#8791 | Remove AlterTableStep#alter() support for TERADATA |
#8806 | Parser doesn't correctly parse identifiers that can conflict with keywords |
#8808 | Compilation error in generated code when sequence has the same name as its containing schema |
#8810 | Emulated ENUM types produce check constraint with bind variables |
#8815 | Add missing Javadoc to Configuration.visitListenerProviders() |
#8817 | Remove unnecessary {@inheritDoc} Javadoc tags in jOOQ's internals |
#8820 | Bad SQL generated in PostgreSQL when calling nextval on a sequence with apostrophes in its name |
#8832 | Wrong rendering of Oracle's CREATE SEQUENCE `NO` clauses |
#8835 | No ALTER SCHEMA ... IF EXISTS clause in Postgres |
#8836 | Correct CreateSequenceFlagsStep#noCache() for Postgres |
#8859 | Generator does not generate anything for schemas only containing sequences |
#8862 | Manual code doesn't compile for derived table and correlated subquery examples |
#8876 | Bad example in CSV import manual section |
#8891 | Bad code generated when an Oracle table valued function name exists both as a standalone function and as a package function |
#8897 | INSERT .. RETURNING emulation doesn't work on Oracle for single row inserts when returning expressions |
#8898 | INSERT .. RETURNING emulation doesn't work on Oracle when returned columns are aliased |
#8902 | Add missing Support annotation to DSL.collation |
#8904 | Add Support annotations to DSL.name() and DSL.keyword() |
#8908 | Statements ignored by the parser do not implement QueryPartInternal |
#8910 | Parse pg_catalog.set_config('search_path') as SET SCHEMA in DDLDatabase |
#8913 | TeradataDataType is missing type mapping for SQLDataType.UUID |
#8915 | COMMENT ON VIEW doesn't work on SQL Server |
#8921 | Wrong Support annotation on UpdateReturningStep and DeleteReturningStep methods |
#8929 | DAOImpl should short circuit Result.map(RecordMapper) calls |
#8931 | Oracle doesn't support asterisks in the RETURNING clause |
#8933 | DSL.unnest(Collection) doesn't work on PostgreSQL |
#8954 | NPE in code generator when generating Oracle UDTs |
#8956 | Document <includePrimaryKeys/> as being a flag influencing generated records |
#8957 | Parser.parseStatements() fails to parse empty block |
#8960 | DELETE .. LIMIT 1 generates a bind variable even if input is inlined |
#8961 | Parser doesn't support bind variables in LIMIT clauses |
#8964 | Bulk insert of BigDecimals with different scale get truncated to first rows scale |
#8978 | Make generatePojoMultiConstructor in JavaGenerator protected |
#8979 | Dead links for generator strategy examples |
#8984 | Potential NumberFormatException in FilenameComparator |
#8993 | NullPointerException when JDBC driver returns null on getGeneratedKeys call using ZDAL5 driver on MySQL |
#9014 | Fix typo in documentation |
#9024 | ExecuteListener documentation typo |
#9028 | Translated sequence flags in CREATE SEQUENCE statement get turned into bind variables |
#9034 | JDBCUtils.driver(String) returns deprecated "com.mysql.jdbc.Driver" |
#9041 | Manual typo: "catlogs" |
#9049 | Stop shipping the Sakila database over the zip files downloaded from the website |
#9052 | Some dead internal links in old manual versions |
#9059 | DSLContext.ddl(Catalog) does not correctly create cross schema foreign key constraints. |
#9065 | Parser does not support NVARCHAR2 |
#9072 | Remove outdated information in manual's logging section |
#9073 | Manual section about custom query parts should not document internal API |
#9088 | Pro Oracle oracleTSTZ doesn't unwrap connection from pool prior to TZ constructor |
#9090 | CREATE TABLE fails with ParseWithMetaLookups.THROW_ON_FAILURE |
Version 3.11.0 - June 7, 2018
New Databases Supported
At last, 4 new SQL dialects have been added to jOOQ! These are:
jOOQ Professional Edition
- Aurora MySQL Edition
- Aurora PostgreSQL Edition
- Azure SQL Data Warehouse
jOOQ Enterprise Edition
- Teradata
Implicit Joins
One of the really cool features in ORMs like Hibernate, Doctrine, and others, is the capability of using a relationship graph notation to access another entity's columns through what is often called "implicit joins".
Instead of explicitly joining a to-one relationship to access its columns:
SELECT author.first_name, author.last_name, book.title FROM book JOIN author ON book.author_id = author.id
We would like to be able to access those columns directly, using this notation:
SELECT book.author.first_name, book.author.last_name, book.title FROM book
The join is implied and should be added implicitly. jOOQ now allows for this to happen when you use the code generator:
ctx.select(BOOK.author().FIRST_NAME, BOOK.author().LAST_NAME, BOOK.TITLE) .from(BOOK) .fetch();
When rendering this query, the implicit join graph will be calculated on the fly and added behind the scenes to the BOOK table. This works for queries of arbitrary complexity and on any level of nested SELECT.
More details in this blog post: https://blog.jooq.org/type-safe-implicit-join-through-path-navigation-in-jooq-3-11/
DiagnosticsListener SPI
A new DiagnosticsListener SPI has been added to jOOQ: https://github.com/jOOQ/jOOQ/issues/5960
The purpose of this SPI is to sanitise your SQL language, JDBC and jOOQ API usage. Listeners can listen to events such as:
- duplicateStatements (similar SQL is executed, bind variables should be used)
- repeatedStatements (identical SQL is executed, should be batched or rewritten)
- tooManyColumnsFetched (not all projected columns were needed)
- tooManyRowsFetched (not all fetched rows were needed)
The great thing about this SPI is that it can be exposed to clients through the JDBC API, in case of which the diagnostics feature can reverse engineer your JDBC or even JPA generated SQL. Ever wanted to detect N+1 queries from Hibernate? Pass those Hibernate-generated queries through this SPI.
Want to find missing bind variables leading to cursor cache contention or SQLi? Let jOOQ find similar SQL statements and report them. E.g.
- SELECT name FROM person WHERE id = 1
- SELECT name FROM person WHERE id = 2
Or also:
- SELECT name FROM person WHERE id IN (?, ?)
- SELECT name FROM person WHERE id IN (?, ?, ?)
Anonymous blocks
Many databases support anonymous blocks to run several statements in a single block scope. For example, Oracle:
DECLARE l_var NUMBER(10); BEGIN l_var := 10; dbms_output.put_line(l_var); END;
jOOQ now supports the new org.jooq.Block API to allow for wrapping DDL and DML statements in such a block. This is a first step towards a future jOOQ providing support for:
- Abstractions over procedural languages
- CREATE PROCEDURE and CREATE FUNCTION statements
- Trigger support
- And much more
Parser
jOOQ's parser support is an ongoing effort. This release has added support for a lot of new SQL clauses and functions from various vendors and in various DDL and DML statements.
The parser is now also exposed through a public website and API, where SQL can be translated from one dialect to another: https://www.jooq.org/translate
This website will help further drive jOOQ API development by helping to find missing functionality that is used in real-world SQL.
Another way to access this API is through the new org.jooq.ParserCLI command line tool. For example, run:
$ java -cp jooq-3.11.0.jar org.jooq.ParserCLI -f -t ORACLE -s "SELECT * FROM (VALUES(1),(2)) AS t(a)"
To get:
select * from ( ( select null a from dual where 1 = 0 ) union all ( select * from ( ( select 1 from dual ) union all ( select 2 from dual ) ) t ) ) t;
Formal Java 10 Support
jOOQ 3.11 is the first release that is formally integration tested with Java 10. To use jOOQ with Java 10, use the Java 8 distribution which has not yet been modularised, but contains Automatic-Module-Name specification to be forward compatible with future, modularised jOOQ distributions.
Additionally, package names between jOOQ, jOOQ-meta, and jOOQ-codegen have been cleaned up to prevent duplicate package names, and the JAXB dependency has been added explicitly to the various artefacts. See https://github.com/jOOQ/jOOQ/issues/7419 for more details
End of Scala 2.11 support in the jOOQ Open Source Edition
Scala 2.10 and 2.11 are now only supported in the commercial distributions
Other great improvements
- Finally, asterisks (SELECT * or SELECT t.*) are formally supported in the API.
- Collations can now be specified on a variety of syntax elements
- The org.jooq.Comment type has been added, and DDL statements for it
- The DefaultBinding implementation has been rewritten for better peformance
- Several performance improvements in jOOQ's internals
- Many more DDL statements are supported including GRANT and REVOKE
- Support for the EXPLAIN statement
- FETCH n PERCENT ROWS and TOP n PERCENT clauses are supported
- Better org.jooq.Name and org.jooq.Named API for identifier handling
- Support for PostgreSQL 10
- Support for SQL Server 2017
- Support for DB2 11
- Upgraded MariaDB support for window functions, inv dist functions, WITH
- jOOU dependency updated to 0.9.3
- jOOR dependency updated to 0.9.8
- Server output (e.g. DBMS_OUTPUT) can now be fetched automatically, by jOOQ
- Code generation support for PL/SQL TABLE types
- SQL Keywords Can Now Be Rendered In Pascal Style If You Must
- Emulate PostgreSQL's ON CONFLICT clause using MERGE
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.10-3.11
Features and Improvements
#629 | Add support for the Teradata database |
#717 | Add support for SQLite unique columns |
#1053 | Add syntax railroad diagram to the manual |
#1502 | Add support for implicit join over to-one relationships |
#1677 | Add SelectFieldOrAsterisk type to support Table.asterisk() (t.*) and DSL.asterisk() |
#2051 | Add is[Not]DistinctFrom() to Row[N] types |
#2508 | Support ON DUPLICATE KEY UPDATE in H2 |
#2637 | Add a section to the manual about the MockFileDatabase, change its experimental status |
#2769 | Add DSL.asterisk() to allow for explicitly issuing SELECT * statements |
#2791 | Add a Context data map scoped to the outer scope of a subquery |
#2908 | Add support for COLLATIONS |
#3686 | Add support for default parameter values in SQL Server |
#3930 | Improve code generation manual sections explaining each flag individually with XML / programmatic examples |
#4015 | Add support for LATERAL to DB2 |
#4059 | Add <link rel="canonical"/> references from older Javadocs/manuals to the latest versions |
#4627 | Support Java 8 constructor parameter reflection in DefaultRecordMapper |
#4888 | Add <serializablePojos/> to allow for POJOs not to be Serializable |
#4930 | Create one DefaultXYZBinding type per DataType, internally |
#5196 | Add support for Amazon Aurora MySQL Edition |
#5296 | Add a MetaProvider Configuration.metaProvider() SPI |
#5314 | Add support for ALTER TABLE .. ADD IF NOT EXISTS |
#5315 | Add support for ALTER TABLE .. DROP IF EXISTS |
#5318 | Add support for ALTER TABLE .. ADD (...) to add multiple objects to a table at once |
#5319 | Add support for ALTER TABLE .. DROP (...) to allow for dropping multiple objects at once |
#5491 | Provide maven-deploy script to install artifacts on remote repository |
#5594 | Add support for Oracle 12c FETCH N PERCENT ROWS and SQL Server TOP n PERCENT clauses |
#5703 | Add option to disable code generation of comments |
#5863 | Support multi-row INSERT .. RETURNING for Oracle using PL/SQL FORALL .. INSERT .. RETURNING .. BULK COLLECT INTO |
#5874 | Add support for H2's new enum types |
#5917 | Add Settings.parseUnsupportedSyntax to define behaviour when a parser error occurs |
#5925 | Replace asList(SQLDialect ...).contains() by EnumSet.of(SQLDialect ...).contains() in internals |
#5960 | Add a DiagnosticsListener SPI |
#5988 | Add Javadoc to DSL.table(String) and Table.field(String) explaining the lack of field references in plain SQL tables |
#6071 | Add Name Sequence.getQualifiedName() and getUnqualifiedName() |
#6131 | Add plain SQL storage() clause to CREATE TABLE statements |
#6140 | Add <clean/> to <target/> in code generator configuration |
#6145 | Add Queries.block() |
#6220 | Add DSL.localDateTimeAdd() localDateTimeSub(), localDateTimeDiff() |
#6240 | Add support for SQL Server's ALTER TABLE .. RENAME INDEX emulation |
#6261 | Support loading multiple files in DDLDatabase |
#6265 | Add org.jooq.Named API for all types containing a getName() method |
#6324 | Add support for COMMENT ON statements |
#6328 | Add SQLDialect.SQLSERVER2017 |
#6358 | Add ResultQuery.fetchSet(RecordMapper) |
#6371 | Add support for DROP TEMPORARY TABLE |
#6474 | Add org.jooq.Block to wrap several statements in an anonymous block |
#6482 | Document in the manual: SQL and JDBC are one-based, jOOQ is zero-based |
#6554 | Mark Maven plugin as @ThreadSafe |
#6577 | Add documentation about the <fullyQualifiedTypes/> flag |
#6580 | Add Settings.fetchServerOutputSize to fetch server output |
#6606 | End of Scala 2.11 support for jOOQ Open Source Edition |
#6627 | Add DateToLocalDateConverter, TimeToLocalTimeConverter, TimestampToLocalDateTimeConverter |
#6630 | Support Oracle TIMESTAMP WITH TIME ZONE data type in UDT |
#6631 | Deprecate public DefaultBinding constructor |
#6632 | Generate DAO.fetchOneByXYZ(T value) for unique columns on SQLite |
#6642 | DefaultBinding should check Settings.executeLogging to decide whether to log |
#6644 | Improve "no catalogs were loaded" error message |
#6654 | Improve code generator's INFO message when objects have no name |
#6660 | Add <catalogs/> to <information_schema> |
#6661 | Add support for catalogs in the XMLGenerator |
#6662 | Support new <catalogs/> element in DSLContext.meta() |
#6663 | Support new <catalogs/> element in DSLContext.informationSchema() |
#6676 | Add markdown to error message about slow SQL |
#6694 | Overload SelectWhereStep.where(Condition...) and similar methods to avoid Condition[] allocation |
#6704 | Support PostgreSQL's escape string constants |
#6715 | Add { Insert | Update | Delete }ReturningStep.returningResult(Field<T1>, ..., Field<TN>) |
#6718 | Add missing overload DSLContext.newResult(Collection<? extends Field<?>>) |
#6720 | Refactor some internals to use Scope.dsl() or Configuration.dsl() |
#6721 | Deprecate AbstractStore.create() |
#6722 | Deprecate AbstractQueryPart.create() methods |
#6765 | Add SQLDialect.POSTGRES_10 |
#6771 | Add a Setting to prevent UPDATE and DELETE statements that lack a WHERE clause |
#6772 | Add a <jpaVersion/> code generator configuration |
#6776 | Add MockResult() and MockResult(int) convenience constructors |
#6781 | Clarify DSL.currentDate() Javadoc: It creates ANSI SQL DATE values, not Oracle DATE |
#6783 | Add explicit unit of time specification to Query.queryTimeout() |
#6796 | [#4627] Support parameter info compiled into bytecode |
#6798 | Add Settings.mapConstructorParameterNames |
#6812 | Add support for GRANT and REVOKE statements |
#6817 | Add DSL.noCondition() |
#6823 | Add DSLContext.explain(Query) |
#6832 | Enhance DSLContext.fetchFromTXT() to support Oracle DBMS_XPLAN format |
#6833 | Add TXTFormat to allow for additional text formatting options |
#6835 | Add new TXTFormat options to generate different table styles |
#6836 | Add Record.format() |
#6838 | Add org.jooq.User |
#6839 | Add org.jooq.Role |
#6853 | [#6838] The User type for GRANT statement |
#6862 | [#6839] The Role type for GRANT statement |
#6867 | Add DSLContext.ddl(Table[]) and ddl(Collection<? extends Table<?>>) |
#6872 | [#4627] Support using first available constructor with **different** number of arguments as the last resort |
#6876 | Add DSL.localDateTimeDiff() and localDateTimeAdd() |
#6878 | [#6812] Added GRANT statement and its implementation. |
#6879 | Add javax.xml.bind:jaxb-api dependency and avoid using the implementation |
#6883 | Add support for loading default values and comments for org.jooq.Meta columns |
#6884 | Emulate SET [ ROW ] = [ ROW ] syntax on all databases |
#6885 | [#6867] Added a possibility to export several DDL of tables |
#6897 | [#6868] Prefer public constructors |
#6899 | Log a link to GitHub when DDLDatabase runs into a ParserException |
#6903 | Add ExecuteContext.statementExecutionCount() to count the number of executions of a statement |
#6906 | Add support for PostgreSQL ON CONFLICT .. ON CONSTRAINT .. |
#6911 | Add support for GRANT .. TO PUBLIC and REVOKE .. FROM PUBLIC |
#6913 | Add support for WITH GRANT OPTION clause to GRANT statement |
#6919 | [#6906] Added support for PostgreSQL ON CONFLICT .. ON CONSTRAINT .. |
#6921 | Optimization of {ULong,UInteger,UShort}.toBigInteger |
#6922 | Upgrade the jOOU dependency to version 0.9.3 |
#6927 | Add ExecuteListener.serverOutput() |
#6928 | Add AlterTableStep.add(Field) taking the data type from the field directly |
#6931 | Add support for REVOKE GRANT OPTION FOR |
#6933 | Add org.jooq.Statement for procedural statements inside of org.jooq.Block |
#6934 | [#6913] Added a support for GRANT .. WITH GRANT OPTION |
#6936 | Parse empty INSERT .. VALUES () clause as an emulated DEFAULT VALUES clause |
#6938 | [#6931] Added a support for REVOKE GRANT OPTION FOR .. clause |
#6940 | [#6913] Added parser support for WITH GRANT OPTION clause |
#6941 | [#6931] Added parser support for GRANT OPTION FOR clause |
#6943 | Add integration test for <forcedType/> applied to table valued function result |
#6951 | Add <includeTriggerRoutines/> flag to exclude the generation of PostgreSQL trigger routines |
#6955 | [#6772] Added a new flag `jpaVersion` to code generator. |
#6958 | Generate hint about <deprecationOnUnknownType/> in Javadoc |
#6962 | Add code generator flags for <globalKeyReferences/> |
#6963 | Add section to the manual about the <globalXYZReferences/> code generation flags |
#6968 | Implement IdentityConverter.toString() |
#6969 | Support various DDL statements in Firebird |
#6977 | Add native support for SQL Server 2017 TRIM() |
#6978 | Add support for TRANSLATE() function |
#6982 | Make jooq-meta's org.jooq.util.Database AutoCloseable |
#6985 | Add an org.jooq.Comment type |
#6986 | Emulate COMMENT ON in SQL Server using sp_updateextendedproperty |
#6987 | Add DDLFlag.COMMENT to extract COMMENT statements from DSLContext.ddl() |
#6990 | When DDLFlag.TABLE is inactive, constraints should produce ALTER TABLE statements on DSLContext.ddl() |
#6991 | Add comments to jooq-meta.xsd |
#6992 | Add Catalog.getComment() |
#6993 | Add Schema.getComment() |
#6994 | Emulate COMMENT ON TABLE in MySQL |
#6997 | Support system properties in Maven code generation |
#7000 | Document the possibility of skipping code generation via a Maven command line argument |
#7008 | Support various DDL statements in MariaDB |
#7016 | Add option to disable the generation of all Javadoc |
#7027 | Add DSL.field(Name, DataType<T>, Comment) and DSL.table(Name, Comment), etc. |
#7028 | Add support for CREATE TABLE .. COMMENT |
#7039 | DDLDatabase should auto-create missing schemas |
#7040 | Add DataAccessException.getCause(Class<? extends Throwable>) |
#7043 | Emulate MySQL's CREATE TABLE .. COMMENT on other databases |
#7044 | Add support for ALTER TABLE .. COMMENT |
#7055 | POJO copy constructor should use interface when codegen of <interfaces/> = true |
#7069 | Add ParserException.sql(), position(), line(), column() |
#7073 | Add <nullability/> to <forcedType/> to allow for matching nullable / non-nullable / all columns |
#7075 | Generate equals(), hashCode(), and toString() on XJC generated classes |
#7082 | Generate comments in SQL Server |
#7086 | Add support for COMMENT ON VIEW |
#7087 | Add support for SET SCHEMA and SET CATALOG |
#7094 | Add ParamType.FORCE_INDEXED |
#7095 | Add Settings.inListPadBase |
#7097 | Expose jOOQ Connection proxies also as DataSource |
#7101 | Add T DSLContext.fetchValue(Field<T>) |
#7107 | Add support for CREATE INDEX ON (unnamed indexes) |
#7112 | Support WITH clause for H2 |
#7115 | Allow usage of derived table as aliased parameter of TableImpl constructor |
#7116 | Add Field.collate(Collation) and collate(String) to support COLLATE clauses |
#7117 | Add DataType.collate(Collation) |
#7120 | Add org.jooq.Collation and DSL.collation(String) |
#7123 | Add CREATE TABLE and ALTER TABLE support for explicit column collations |
#7125 | Add code generation support for PL/SQL TABLE types |
#7131 | Wrap the Table type in an implicit Scala class to allow for writing t.* |
#7134 | Add ArrayRecord.isSQLUsable() and ArrayRecord.getPackage() |
#7139 | Add support for CREATE TABLE AS SELECT .. WITH [ NO ] DATA |
#7140 | Add support for converting java.sql.Struct to UDTRecord |
#7148 | Add code generation support for to-one implicit join relationships |
#7152 | Add Context.scopeStart() and scopeEnd() |
#7154 | Add TableDefinition.getForeignKeys(TableDefinition) |
#7158 | Add public internal API for use by code generator (to work around Scala issues) |
#7162 | Add DSLContext.meta(DatabaseMetaData) and meta(Catalog...), meta(Schema...), meta(Table...) |
#7164 | Add Meta.getXYZ(String), getXYZ(Name) accessors for all object types |
#7166 | Change DSL.unnest(List) and table(List) to unnest(Collection) and table(Collection) |
#7173 | Add documentation for the new DiagnosticsListener SPI |
#7174 | Add support for PostgreSQL ROWTYPE function parameters |
#7185 | Emulate CREATE VIEW IF NOT EXISTS in PostgreSQL |
#7187 | Add List<T> DSLContext.fetchValues(Table<? extends Record1<T>>) |
#7188 | Upgrade Hibernate dependency in jOOQ-meta-extensions to 5.2.13 |
#7210 | Add <serializableInterfaces/> to allow for interfaces not to be Serializable |
#7211 | Upgrade Scala 2.10 dependency to 2.10.7 |
#7217 | DDLDatabase should sort SQL files |
#7219 | XMLDatabase should support reading files from classpath |
#7229 | Add <forceIntegerTypesOnZeroScaleDecimals/> configuration to allow for treating DECIMAL types as BigDecimal |
#7237 | Add DSL.now() as a synonym for DSL.currentTimestamp() |
#7258 | Deprecate org.jooq.Clause |
#7261 | Add more error messages to the parser |
#7264 | Add Parser.parseSelect() |
#7266 | Support parsing column references as predicates |
#7269 | Expose Parser as a CLI tool |
#7275 | Add DSL.iif(Condition, Field<T>, Field<T>) |
#7276 | Add support for SQL Server's CHOOSE() function |
#7277 | Add DSL.with(Name) and DSL.withRecursive(Name) |
#7279 | Add RenderKeywordStyle.PASCAL |
#7280 | Add ConstraintForeignKeyReferencesStep[N].references(Table<?>) |
#7286 | Add CREATE OR REPLACE VIEW |
#7288 | Add DSL.count(SelectFieldOrAsterisk) and countDistinct(SelectFieldOrAsterisk) |
#7296 | Add Name.as() to create empty window specifications |
#7300 | SQL Translation Error - Transact-SQL outer joins |
#7310 | Document <javaTimeTypes> in the manual |
#7311 | Add support for (+) outer join in DB2 |
#7314 | [#5873] Add Setting.quoteEscaping to allow for alternative escaping of single quote |
#7320 | Support parsing Oracle TO_DATE() and TO_TIMESTAMP() functions |
#7324 | Support Kotlin metadata in DefaultRecordMapper |
#7329 | [#7324] Support Kotlin data classes in DefaultRecordMapper |
#7340 | <validationAnnotations/> should generate Size annotations also for (VAR)BINARY types |
#7343 | Add <includePackageConstants>, <includePackageRoutines>, <includePackageUDTs> code generation configuration flags |
#7344 | Add Settings.parseUnknownFunctions to turn off failing on unknown functions |
#7345 | Add section to the manual explaining annotation generation flags |
#7346 | #7301: Allow customization of LoggerListener |
#7347 | Support parsing KEY/INDEX specifications in MySQL CREATE TABLE statements |
#7348 | Add possibility of adding an INDEX (or KEY) as a "constraint" to DDL statements |
#7353 | Let Cursor extend Formattable |
#7355 | Add org.jooq.Formattable |
#7356 | Emulate MySQL's CREATE TABLE (... INDEX) clause using anonymous blocks |
#7357 | Overload CreateIndexStep.on() clauses with Collection accepting version |
#7358 | Add support for SQL Data Warehouse |
#7365 | Emulate PostgreSQL's ON CONFLICT clause with MERGE |
#7374 | Add DSL.timestampSub() and localDateTimeSub() |
#7375 | Deprecate <SQLDialect>DataType classes |
#7379 | Translate MySQL / PostgreSQL ENUM type to check constraint in other databases |
#7385 | Upgrade jOOR dependency to 0.9.8 |
#7386 | org.jooq.Parser should generate in-memory enum types |
#7387 | Add DataType.isEnum() |
#7388 | Make EnumType.getCatalog() and getSchema() default methods |
#7407 | Add support for ALTER INDEX .. RENAME in MySQL by using ALTER TABLE .. RENAME INDEX |
#7409 | Emulate PostgreSQL's ON CONFLICT .. ON CONSTRAINT clause with MERGE |
#7412 | Add support for the CREATE INDEX .. INCLUDE syntax |
#7415 | Add ability for MatcherStrategy to allow for customizing enum class names |
#7420 | Code generation XML config snippets should refer to XMLNS in manual |
#7431 | Document the fact that fetchOne() needs to fetch the second record |
#7433 | Add support for Amazon Aurora PostgreSQL Edition |
#7437 | Add support for generate_series() with step parameter |
#7439 | Add ORACLE12C support for the STANDARD_HASH function |
#7440 | Add support for the NTH_VALUE(..) [ FROM { FIRST | LAST } ] clause |
#7441 | JavaGenerator should allow for overriding POJO constructor generation |
#7446 | Support parsing ISO_8601 interval literals |
#7447 | Add DayToSecond.valueOf(Duration) |
#7452 | Support multi-row INSERT .. SELECT .. RETURNING for Oracle using PL/SQL FORALL .. INSERT .. RETURNING .. BULK COLLECT INTO |
#7453 | Update docs: SQL Azure is now called Azure SQL Database |
#7454 | Add SQLDialect.DB2_11 |
#7461 | Deprecate SEEK BEFORE |
#7469 | Add { ResultQuery | Cursor }.collect(Collector<? super T, A, R>) |
#7474 | Make number of seconds that are considered "slow" in jOOQ-meta configurable |
#7475 | Add { Insert | Update | Delete }ReturningStep.returningResult(...) methods |
#7477 | Add Field.concat(char...) |
#7478 | Add Javadoc to XYZ..Step API to hint at users they should never need to reference it |
#7479 | Log warning when { Insert | Update | Delete }ReturningStep.returning() is used with arbitrary column expressions |
#7480 | Add DSLContext.newRecord(Collection<? extends Field<?>>) |
#7483 | Deprecate DSL.getDataType() |
#7484 | Add DSLContext.selectFrom(Name) and selectFrom(String) overloads |
#7491 | Emulate ON CONFLICT .. DO UPDATE .. WHERE <p> on SQL Server using WHEN MATCHED AND <p> |
#7493 | Emulate { OUTER | CROSS } APPLY on DB2 |
#7498 | Improve RenderMapping to allow for adding a schema to unqualified objects |
#7514 | Add MariaDB support for window functions |
#7522 | Add MariaDB support for inverse distribution functions |
#7523 | Add MariaDB support for WITH |
#7524 | Add support for MariaDB WITH TIES |
#7538 | Deprecate some Field.xyz() convenience API |
Breaking changes
#6462 | INSERT .. ON DUPLICATE KEY { IGNORE | UPDATE } emulation should consider all UNIQUE keys |
#6814 | JDBCUtils.dialect(Connection) should recognise database version |
#6818 | [#6814] overload the JDBCUtils.dialect method |
#6852 | Remove PostgresDataType.MONEY |
#6868 | DefaultRecordMapper should prefer calling public constructors over private ones |
#6961 | Remove generated Sequences classes from jOOQ-meta |
#7167 | Errors should also roll back a transaction |
#7322 | Trailing newRecord() results in NULL insert statement |
#7341 | Change SQLServerDataType.TIMESTAMP to be of type VARBINARY / byte[] |
#7419 | Rename jooq-meta and jooq-codegen packages to avoid conflicts in JPMS |
#7504 | DefaultDataType.getDataType(SQLDialect) should use family |
Bug Fixes
#3045 | DSL.groupConcat() without orderBy() is incorrectly emulated for Oracle |
#3777 | Deadlock when loading DataType classes |
#4277 | INSERT .. RETURNING acquires two different Connections for MySQL |
#4556 | Converter or Binding is not applied to standalone bind values that are passed to functions like DECODE(), COALESCE(), NVL(), etc. |
#5127 | Remove the DATA_LOCALLY_SCOPED_DATA_MAP in SelectQueryImpl |
#5537 | Keys.java shouldn't be generated when <globalObjectReferences/> is set to false |
#5574 | In MySQL, an incorrect column default is generated when the default is CURRENT_TIMESTAMP |
#5688 | PostgreSQL RETURNING <col> AS <alias> is not rendered correctly |
#5692 | jOOQ website CSS is broken on Android |
#6241 | DataType.nullable() and defaultValue() are not generated for enum types |
#6431 | Recursive CTE doesn't work on MySQL because of automatic UNION nesting |
#6485 | Various parser bugs / missing features |
#6607 | MockResultSet.getTimestamp(int, Calendar) ignores Calendar |
#6620 | NPE "Error while fetching indexes" while generating code for function based indexes |
#6621 | Manual should not display "Unsupported versions" header when there are none |
#6625 | Copyright statement in PDF manual is outdated |
#6626 | Manual does not list all contributors from ABOUT.txt |
#6635 | Limit.numberOfRowsOrMax should be initalised from static value |
#6638 | Avoid creating a new DefaultConfiguration in DSLContext.select() and similar methods |
#6640 | QualifiedName.nonEmpty() shouldn't clone argument |
#6643 | Error while generating classes from Record Types and Oracle Types in Oracle 11g |
#6657 | Error in maven-install.bat and .sh scripts when installing cross released Scala deliverables |
#6666 | Costly null check in CombinedCondition constructor |
#6669 | Lazy initialise thread local ArrayLists in DefaultExecuteContext |
#6672 | DefaultBinding.escape() uses String.replace() rather than StringUtils.replace() |
#6679 | Reduce GC pressure through lazy QueryPartList initialisation in SelectQueryImpl |
#6680 | Typo in ResultQuery Javadoc: thorws should be throws |
#6684 | Avoid allocation of CursorImpl.intern array |
#6691 | Prevent calling DSL.name() with empty arguments |
#6696 | Lazy allocate DefaultExecuteContext.batchXYZ arrays if not batching |
#6699 | DSL.trueCondition() and DSL.falseCondition() should return constants |
#6706 | [#6705] Avoid generating code with a redundant cast |
#6707 | Parser.parse() fails on trailing whitespace |
#6708 | DDLDatabase fails when engine=InnoDB is specified |
#6712 | Redundant Javadoc generated when deprecation for unknown types is generated |
#6726 | Support precision on TIME and TIMESTAMP data types |
#6727 | XMLDatabase should be lenient about XML namespace |
#6730 | Typo in Cursor.fetchOne() Javadoc's deprecation hint |
#6733 | jOOQ-scala 2.11 cannot be built with JDK 9 |
#6742 | Oracle OBJECT type declarations inside generated RECORD declarations are not bound correctly, if NULL |
#6746 | Avoid allocating a fresh "ExecuteListeners" instance in the absence of actual ExecuteListeners |
#6747 | Avoid adding the LoggerListener if the log level is more than DEBUG |
#6752 | Avoid various array allocations due to unnecessary varargs |
#6755 | Avoid unnecessary UnqualifiedName[] allocations in QualifiedField etc. |
#6758 | Avoid allocation of AbstractContext.visitListeners if unneeded |
#6763 | PostgreSQL 10 multi column update expressions should use ROW() |
#6766 | Sakila example database: staff.picture column data is too long for mysql |
#6774 | Improve MockDataProvider Javadoc about null or empty return values |
#6779 | Oracle's quoted string literals start with case-insensitive Q letter |
#6785 | Result.format() breaks when there is a tabulator in the content |
#6787 | Inefficient ProxyMapper allocates a new MutablePOJOMapper delegate every time |
#6790 | ConvertAll inefficiently unboxes and boxes primitive types |
#6794 | Custom type converters ignored for table-valued (set-returning) function parameters. |
#6797 | Code generator doesn't work when Derby database uses non-standard collation |
#6800 | Optimise internal reflection cache by avoiding cache key arrays where possible |
#6803 | Cache RecordMapper instances in DefaultRecordMapperProvider |
#6804 | Override equals() and hashCode() in org.jooq.impl.Fields |
#6807 | Improve DefaultRecordMapper::init MappingException message |
#6820 | DayToSecond generates nanosecond precision for DAY_MICROSECOND interval |
#6825 | Error when passing java.util.Date to DSL.year(), month(), day(), hour(), minute(), second() |
#6841 | SQLDataType.INTEGER.identity(true) not working for SQLLite |
#6845 | <deprecationOnUnknownTypes/> has no effect |
#6854 | sqlite_sequence is not a reliable way to discover identities |
#6855 | SQLiteTableDefinition.toString() prints "." after empty schema |
#6860 | Code generator doesn't work in Java 6 build, which calls java.lang.reflect.Method.getParameterCount() |
#6873 | Line numbers not aligned correctly between OSS and Pro edition |
#6875 | scala AbstractKeys cannot be accessed |
#6880 | ALTER COLUMN .. SET with identity type generates wrong query in MySQL and MariaDB |
#6881 | maven-deploy.bat's help options do not work (cannot be discovered easily) |
#6887 | org.jooq.Meta ignores foreign key names |
#6893 | Scala generated code for Oracle queues does not compile |
#6898 | Parser API doesn't document thrown ParserException |
#6904 | Javadoc warnings in ExecuteListener |
#6912 | Bad inlining of Double.NaN in H2 |
#6918 | Generated file headers comment is ill formatted |
#6923 | Clarify the meaning of MockResult.data == null |
#6930 | Compilation error in generated code when <enumConverter/> is applied to an enum column |
#6949 | Video on "learn" page is missing |
#6966 | In JavaGenerator printed overview, add missing flags |
#6967 | Oracle array of object containing date mapped to LocalDate cannot be bound as a variable |
#6972 | Manual examples for code generation includes / excludes contain wrong regular expressions |
#6973 | Firebird IF [ NOT ] EXISTS clause emulations broken |
#6979 | Wrong Javadoc on DropIndexOnStep |
#6980 | DDLDatabase and JPADatabase should use unique in-memory database name |
#6988 | DDLFlag.TABLE does not work correctly on DSLContext.ddl() |
#7001 | Confusing debug log output when fetchOptional or fetchOne throw TooManyRowsException |
#7009 | Invalid SQL rendered for inlined named parameters |
#7017 | DDLDatabase fails with MySQL ENUM columns |
#7019 | DDLDatabase fails with MySQL ON UPDATE |
#7020 | DDLDatabase fails with MySQL TINYINT(1) type columns |
#7021 | DDLDatabase fails with MySQL DATETIME columns |
#7022 | DDLDatabase fails with MySQL UNIQUE INDEX clause |
#7032 | Remove broken Parser "Expected Tokens" error message |
#7035 | Plain SQL API should recognise multi-character PostgreSQL ltree operators |
#7037 | Plain SQL API should recognise multi-character PostgreSQL geometry operators |
#7049 | Generated Tables.scala has unused imports |
#7051 | Generated scala code contains deprecation warning for TableImpl |
#7052 | [7051] Fix generated scala deprecation warning |
#7054 | [#7021] Add parser support for DATETIME data type. |
#7061 | Programmatic code generator Database configuration doesn't default to <includes>.*</includes> |
#7062 | NotSerializableException when Record references reflection cache |
#7068 | Compilation error in generated DAOs when primary key is a composite type |
#7074 | Support PostgreSQL SMALLSERIAL and BIGSERIAL types in parser / DDLDatabase |
#7078 | Excess whitespace in generated Scala case classes |
#7079 | Excess semi colon generated in Scala code |
#7084 | DDLDatabase not working with PostgresSQL database dump |
#7089 | Parser and DDLDatabase cannot parse certain PostgreSQL types |
#7091 | ParsingStatement is not overriding all methods from DefaultStatement |
#7102 | Inaccurate Javadoc for DSLContext.fetchValue() and fetchValues() |
#7114 | DSLContext.transactionXYZ() methods throw ConfigurationException with wrong message |
#7127 | NPE while fetching certain indexes during code generation |
#7135 | Bad ArrayRecord.toString() rendering for nested arrays in Oracle |
#7157 | Queries generates trailing separator / newline character |
#7171 | Various parser bugs / missing features |
#7176 | Regression in PostgreSQL MODE function implementation |
#7177 | Flawed implementation of SET SCHEMA for PostgreSQL |
#7179 | PostgresUtils.toPGXYZString() methods (and others) should avoid using String.replace() pre JDK 9 |
#7183 | Cannot ORDER BY null in PostgreSQL, when Field.sortAsc() has no parameters |
#7186 | NullPointerException when MetaTable.getIndexes() call retrieves a function-based index expression |
#7189 | NullPointerException when DSL.name(Name...) contains a null Name argument |
#7191 | Using VARBINARY type with length on Oracle fails in DDL statements |
#7194 | H2 MetaTable's string column default values are wrong |
#7203 | DDLDatabase fails with order in Index statements |
#7206 | DDLDatabase reports DECIMAL(65535, 32767) for precision/scale-less decimals |
#7222 | IN (SELECT .. UNION SELECT ..) doesn't work on Derby |
#7224 | Do not emulate nested set operators if not strictly needed |
#7231 | Not all columns are fetched when plain SQL tables are mixed with generated ones |
#7243 | Vertica generated sequences are of type Byte instead of Long |
#7248 | Error when running "SELECT 1" query from AbstractDatabase in unsupported SQLDialect |
#7270 | Generating JOOQ-classes for CockroachDB fails when using PostgreSQLDatabase |
#7271 | Generator doesn't select appropriate DataType for Columns using an enum from another schema |
#7282 | Oracle LIMIT always generates OFFSET clause, even if not required |
#7292 | SQL Translation Error |
#7294 | SQL Translation Error |
#7298 | Internal Tools.peek() methods should not operate on strings, but on char[] |
#7299 | Missing whitespace between USING and ( |
#7303 | Nondeterministic ordering in generated schemas in PostgreSQL |
#7315 | SQLDataType.CLOB translates to TINYTEXT rather than TEXT in MySQL |
#7321 | Make visiting a window actually conditional on its nullity. |
#7325 | Error when fetching SQLite timestamps in ISO format (including the letter T) |
#7330 | Workaround for regression in H2 generator where primary keys are no longer found |
#7335 | Optimise SelectLimitStep.limit(Param) for inline parameters |
#7338 | jOOQ 3.10.6 download fail |
#7351 | Error when binding null values to UUID types in PostgreSQL |
#7359 | IndexOutOfBounds when trying to do a MERGE with SELECT in Postgres |
#7370 | Regression in jOOQ 3.11 when binding unknown data types |
#7373 | Undocument <customType/> in jOOQ 3.10+ documentation |
#7376 | Internal FieldMapsForInsert.empty behaves incorrectly |
#7380 | Error in PLSQL procedure if CLOB OUT PARAMETER is > 32kb |
#7381 | 3.11 code generator for H2 throws "Error while fetching enums" exception |
#7392 | Do not use HSQLDB's undocumented NULL keyword for the absence of NOT NULL constraints in CREATE TABLE |
#7394 | InsertQuery.newRecord() without any values produces wrong SQL |
#7396 | Optimistic locking should run deep equality checks on arrays |
#7400 | ORA-01843: not a valid month binding JSR 310 to prepared statements |
#7402 | Regression on Oracle DATE IN OUT parameters |
#7404 | Oracle code generator does not recognise TIMESTAMP WITH TZ type in object types |
#7405 | DSL.inline(UDTRecord) does not work |
#7414 | XMLDatabase should use XML file's encoding, not default Charset |
#7416 | Misleading warning message when using external configurationFile with <matchers/> |
#7427 | Excess ORDER BY "rn" generated in ORACLE11G dialect when LIMIT is used without ORDER BY |
#7430 | ResultQuery.fetchOne() should not fetch second record on a LIMIT 1 query |
#7442 | ORA-00932 when running CAST(.. AS CLOB) in Oracle |
#7455 | ArrayIndexOutOfBoundsException on terminal operation of sorted ResultQuery.stream() |
#7456 | [#7455] Create spliterator correctly |
#7459 | SEEK with UNION doesn't work correctly |
#7460 | SEEK without WHERE produces excess 1 = 1 predicate |
#7463 | Statements provided by delegate should not close underlying connection |
#7488 | Wrong SQL generated in SQL Server when adding nanoseconds to a Timestamp |
#7492 | Clarify meaning of <name/> in data type rewriting in manual |
#7494 | Regression on DB2's INSERT .. RETURNING emulation |
#7497 | Specify capacity for internal ArrayLists whose size is known |
#7500 | Nullability is not correctly generated for Postgres JSONB columns |
#7501 | Binding ARRAY of jsonb in Postgres function results in SQLDialectNotSupportedException |
#7505 | JDBCDatabase doesn't recognise vendor-specific data types |
#7515 | SEEK operations do not auto-convert bind variables to appropriate type |
#7526 | Clean up Support annotations |
#7535 | Missing Meta Database references in the manual |
#7547 | Code generator should not generate "USER-DEFINED" for unknown data types |
#7548 | Underflow when binding small Double values to Oracle JDBC |
Version 3.10.0 - September 29, 2017
Formal Java 9 Support
jOOQ 3.10 is the first release that is formally integration tested with Java 9 along with the existing integration tests for Java 6/7 and for Java 8. To use jOOQ with Java 9 use the Java 8 distribution which has not yet been modularised, but contains Automatic-Module-Name specification to be forward compatible with future, modularised jOOQ distributions.
Cross release for Scala 2.10, 2.11, 2.12
We've been offering cross releases for Java 6/7 and Java 8 in the past and we're now doing the same for Scala. In jOOQ 3.10, Scala 2.11+ will be supported by the jOOQ Open Source Edition and Scala 2.10+ by the commercial editions.
More and better stored procedure support for Oracle and SQL Server
We've finally supported SQL Server's table-valued parameters (TVP), which are a great way of passing data sets to procedures in SQL Server.
In Oracle, we're now supporting a variety of cool PL/SQL features that are not supported directly by ojdbc, among which:
- UPDATE RETURNING and DELETE RETURNING
- Oracle 12c implicit result sets
- PL/SQL RECORD Types passed to and returned from stored procedures
- PL/SQL %ROWTYPE references
- SYS_REFCURSOR IN parameters (we have always supported them as OUT parameters)
- Combinations of PL/SQL BOOLEAN and PL/SQL RECORD types
We believe that those excellent T-SQL and PL/SQL features would be used much more often by Java developers, if the serialisation was made easier. That's why jOOQ 3.10 greatly helps here.
New parser now fully supported
In jOOQ 3.9, we've introduced an interesting new feature that will allow jOOQ to be used in non-classic jOOQ contexts, e.g. as a JDBC proxy to translate SQL from dialect to dialect, or as a formatting tool.
Users who have been using jOOQ's plain SQL API will be happy to hear that using the parser, they will be able to validate their plain SQL already in the client, and possibly normalise / transform it using the entire jOOQ tool chain including the VisitListener SPI.
One immediate benefit of having a parser is the new DDLDatabase, which can reverse engineer your DDL scripts to generate jOOQ code out of them, without any connection to a database!
Support for index types
While we've supported DDL operations to create / drop indexes for a while, we haven't supported indexes in our meta model. We finally do with jOOQ 3.10. They can now be used:
- In code generation output
- As plain SQL meta objects
- As InformationSchema import / exports
- And much more
Other great improvements
- We're now supporting MySQL 8.0 and its WITH clause and window functions.
- Support for the SQL Server 2016 dialect
- Better support for PostgreSQL's ON CONFLICT clause
- Support for FETCH .. WITH TIES: Native and emulated using RANK() OVER (...)
- More improvements for JSR-310 type support
- Many improvements to the org.jooq.Name API for manipulating qualified names
- More DDL support and emulations for DB2, Oracle, and SQL Server
- Many improvements to the org.jooq.Queries API (batches of org.jooq.Query)
- A new RecordUnmapper SPI - the inverse of the existing RecordMapper
- Record unstructuring in Kotlin
- Results can now be formatted as ASCII charts
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.9-3.10
Features and Improvements
#1735 | Add Setting to indicate that bind values should not be cast |
#2520 | Add RecordUnmapper<E, R extends Record> to allow for the inverse operations of RecordMapper |
#2830 | Add JavaDoc on Settings classes |
#3062 | Add support for conversion into Collection types |
#3593 | Add support for packages and routines in XMLDatabase |
#4111 | Cross-release several jooq-scala deliverables |
#4846 | Add <orderProvider/> SPI to allow for injecting meta data ordering |
#4900 | Add support for LIMIT .. WITH TIES |
#4990 | Deprecate Context.keyword() and Context.literal() |
#5149 | Pull up AttachableInternal.configuration() to Attachable. Remove AttachableInternal |
#5171 | Support SQL Server table valued parameters |
#5189 | Generate synthetic ArrayRecord and UDTs for SQL Server table types |
#5191 | Support multi-row UPDATE and DELETE RETURNING for Oracle using PL/SQL RETURNING .. BULK COLLECT INTO |
#5231 | Add a subsection to the manual explaining each setting from the Settings.xml |
#5361 | Add ResultQuery.fetchStreamInto() |
#5411 | Add support for ResultQuery.fetchSingle(), which returns exactly one record |
#5493 | [#2123] Combining INSERT..RETURNING and ON DUPLICATE KEY |
#5551 | Add support for MySQL 8.0 CTE |
#5552 | Add a MySQL 8 SQLDialect version |
#5568 | #3062 Work on adding ability to convert between collections and arrays. |
#5619 | Add Field.containsIgnoreCase() to support Postgres' ILIKE operator |
#5637 | Add support for PostgreSQL ON CONFLICT DO UPDATE WHERE |
#5638 | Add org.jooq.Index |
#5645 | Add DSL.localDateAdd() localDateSub(), localDateDiff() |
#5666 | Add support for Oracle 12c implicit result sets returned from procedures |
#5667 | Review jOOQ's reflection usage for JDK 9 / Jigsaw compatibility |
#5724 | Add support for MySQL's ALTER TABLE .. RENAME INDEX |
#5732 | Emulate { ALTER | DROP } .. IF EXISTS in Oracle using a PL/SQL block |
#5733 | Add a configuration option for varargs setters |
#5738 | Add DSLContext.parsingConnection() to expose the new Parser API through the JDBC API |
#5742 | Stop distributing third party dependencies through zip distribution |
#5745 | Make JDBC driver configuration optional in code generator configuration |
#5746 | The <database/> element in the code generator configuration should be optional |
#5747 | Mention JPADatabase in jooq-codegen.xsd |
#5750 | Deprecate and undocument the <customTypes/> element |
#5754 | Remove copyright (and dates) from file headers |
#5762 | Add DataType.getSQLType(Configuration) |
#5764 | Add support for inlining SQL Server table valued parameters in SQL |
#5767 | Add a comment to the manual's section about MatcherRules regarding unqualified / qualified identifier matching |
#5770 | Add Field.notContains() |
#5772 | Implement Converter.toString() of Converter.of() and ofNullable() results |
#5790 | Add Setting.returnRecordToPojo to disable copying record values back into inserted / updated POJOs |
#5791 | Implement DefaultRecordContext.toString() |
#5806 | Add support for H2's TIMESTAMP WITH TIME ZONE data type |
#5809 | Add code generation support for %ROWTYPE references in Oracle |
#5823 | Add native support for HSQLDB UUID type |
#5824 | Add Convert support for converting UUID to byte[] and vice versa |
#5826 | Add Settings.delimiter to specify the standard delimiter for batches |
#5828 | Add Queries.fetchMany() |
#5829 | Enhance jooq-meta.xsd to include INFORMATION_SCHEMA.ROUTINES and PARAMETERS dictionary views |
#5833 | Add support for routines in XMLGenerator |
#5834 | Improve formatting of multi-argument named parameter procedure calls |
#5850 | Add support for Oracle SYS_REFCURSOR IN parameters |
#5853 | Add XMLFormat, an XML export / import formatting configuration |
#5854 | Support indented XML output in formatXML() |
#5862 | Rename Generator.fluentSetters() to Generator.generateFluentSetters() for API naming consistency |
#5877 | Add <enumConverter/> flag in <forcedType/> to auto-generate EnumConverter |
#5878 | Add DelegatingConverter<T, U> |
#5884 | Allow for specifying Java expressions as Converter / Binding configurations |
#5885 | Document the fact that only the first matching <forcedType/> is a applied to a data type definition |
#5894 | Add Record.formatXML(), formatJSON() |
#5904 | Improve Javadoc on ExecuteContext.rows() |
#5920 | Add several Binding.of() convenience constructors |
#5924 | Add the Table.fullJoin() and SelectJoinStep.fullJoin() aliases |
#5927 | Undeprecate Parser |
#5942 | [5619] Add Field.containsIgnoreCase() to support Postgres' ILIKE operator |
#5947 | Add TypedElementDefinition.getDefinedType() |
#5956 | Add DSL.{rank|denseRank|percentRank|cumeDist}(Collection<? extends Field<?>>) |
#5968 | Add JavaGenerator.printPackageComment() to allow for overriding this |
#5973 | Allow for formatting / indenting JSON output through JSONFormat |
#5987 | Add DSLContext.map(Schema) and map(Table) to expose the schema mapping feature |
#5993 | Add Name DSL.quotedName() and unquotedName() |
#5995 | Add Context.quote() |
#5996 | Add Field.as(Name) and Table.as(Name), Table.as(Name, Name...) |
#5997 | Field.as(Field) and Table.as(Table) should retain quotation flag from Name |
#5998 | Add DSL.name(Name...) to construct a Name from Name.last() elements |
#6000 | Add TableImpl.rename(Name) |
#6005 | Add DDLDatabase to reverse engineer DDL files |
#6006 | Add DSL.primaryKey(Name...), unique(Name...), foreignKey(Name...) |
#6009 | Add support for CREATE INDEX ON with on(Name, Name...) arguments |
#6011 | Add better documentation for the JPADatabase |
#6012 | Implement specialised Name for unqualified Names |
#6013 | Add Name Name.qualifier() |
#6014 | Implement QualifiedTable.getSchema() and QualifiedSchema.getCatalog() |
#6021 | Add DSLContext.with(Name, Name...) |
#6022 | Add Name.fields(Name, ...) |
#6035 | Detect third-party JDBC URL plugins in JDBCUtils |
#6044 | Add DSLContext.currval(Name) and nextval(Name) |
#6052 | Create an internal Keyword cache |
#6053 | KeywordImpl should cache the AS_IS, UPPER, LOWER renderings |
#6056 | Upgrade optional logger dependencies |
#6063 | Use eq / ne / etc in manual, rather than equal / notEqual / etc |
#6068 | Add Name { Field | Table | Schema | Catalog }.getQualifiedName() |
#6070 | Add Name Name.unqualifiedName() |
#6072 | Add code generation flag <recordsImplementingRecordN/> to configure whether generated Records should implement Record[N] |
#6073 | Add Name[] Name.parts() |
#6074 | Implement QueriesImpl.equals() and hashCode() |
#6079 | Add JoinType.qualified() |
#6082 | DSL.condition(Field) and field(Condition) should unwrap previously wrapped QueryPart |
#6084 | Let { Update | Delete }ReturningStep extend { Update | Delete }FinalStep |
#6086 | Add Row Parser.parseRow(String) |
#6087 | Make ParserException public |
#6088 | InsertSetStep.select() should return InsertOnDuplicateStep |
#6093 | Add Field.pow[er](Field) |
#6094 | Support Oracle's PARTITION BY prefixed OUTER JOIN |
#6099 | Document Parser's BNF |
#6104 | Improve VALUES constructor formatting |
#6105 | Add Name { Field | Table | Schema | Catalog }.getUnqualifiedName() |
#6108 | Add PostgresDSL.arrayOverlap() |
#6114 | [#6063] change Field.equal() and Field.notEqual() to Field.eq() and Field.ne() in manual pages |
#6120 | Add support for DB2 RENAME INDEX statement |
#6121 | Add support for DB2 RENAME TABLE statement |
#6123 | Emulate CREATE TABLE AS for DB2 using CREATE TABLE and INSERT |
#6125 | Support different DB2 sqlstates when emulating IF NOT EXISTS |
#6128 | Add more Javadoc to JPADatabase |
#6136 | [#6022] add Name.fields(Name...) method along with the generated ones |
#6139 | Put XJC generated sources under version control |
#6143 | Rename Queries.stream() to Queries.queryStream() |
#6144 | Let Queries extend QueryPart |
#6146 | Add DSLContext.queries(Query...) |
#6147 | Let Queries extend Attachable |
#6148 | Add Queries.executeBatch() |
#6154 | Remove test dependencies from OSS distribution |
#6155 | Remove unneeded javax.validation dependency |
#6156 | Add Configuration.recordUnmapperProvider() |
#6162 | Deprecate plain SQL DSL.sequence(String) constructors |
#6167 | GenerationTool should debug-log input Configuration as XML |
#6169 | Document exception propagation in transaction API Javadoc |
#6194 | Add a section to the manual about the Query By Example API |
#6195 | Add DSLContext.fetchByExample(TableRecord) |
#6196 | Override Iterable.forEach(Consumer) in ResultQuery to provide Javadoc |
#6212 | Generate deprecation for all objects referencing DataType<Object> (unknown type) |
#6214 | Pull up jOOQ-meta's AbstractDatabase.getProperties() to Database |
#6215 | Add localDateAdd() localDateSub(), localDateDiff() support to DSL |
#6217 | Add more details to QueryPart.toString() Javadoc |
#6218 | Add a section to the manual about the plain SQL templating part |
#6219 | Add Parser.parseResultQuery() |
#6222 | Generate IDENTITY information on data type |
#6239 | Add SQLServer2016 dialect |
#6245 | Add Record[N].component[1-N]() methods for better Kotlin interoperability |
#6246 | Add Kotlin operators on Field |
#6247 | Add more Kotlin examples |
#6253 | Add a jOOQ / JPA example to GitHub |
#6254 | Deprecate the ResultQuery.intern() and Result.intern() features |
#6255 | Add better Enum to Enum conversion support in org.jooq.tools.Convert |
#6258 | Emulate MySQL / T-SQL DROP INDEX .. ON for other databases |
#6268 | Support DROP SCHEMA IF EXISTS for SQL Server |
#6269 | Support CREATE SCHEMA IF NOT EXISTS in SQL Server |
#6271 | Improve onKey() join error messages, when join expression is ambiguous |
#6273 | Document <configurationFile/> Maven plugin property |
#6275 | Add SQL Server support for ALTER VIEW .. RENAME |
#6276 | Add SQL Server support for ALTER TABLE IF EXISTS |
#6280 | Deprecate DSLContext.bindContext() and renderContext() |
#6281 | Add DSL.arrayAggDistinct() |
#6285 | Add Javadoc to code generator Configuration classes |
#6287 | Upgrade Spring Boot example to version 1.5.3 |
#6296 | Update Hibernate Dependency in jooq-meta-extensions and examples |
#6297 | Add "development versions" link to the manual |
#6299 | Remove unneeded config files in spring-boot-example |
#6300 | Remove unneeded config files in spring-boot-example |
#6304 | Improve internal TableAlias discovery |
#6306 | Add org.jooq.True and org.jooq.False |
#6307 | Add code generation support for indexes |
#6312 | Document DISTINCT predicate emulation using INTERSECT |
#6313 | Add List<Index> Table.getIndexes() |
#6315 | Add SortField Field.sortDefault() |
#6319 | Add INDEXES and INDEX_COLUMN_USAGES views to jooq-meta.xsd |
#6320 | Import / Export index information with DSLContext.meta(InformationSchema) / DSLContext.informationSchema() |
#6321 | Export indexes using XMLGenerator |
#6322 | Import indexes using XMLDatabase |
#6323 | Generate javax.persistence.Index annotation |
#6325 | Add ResultQuery.fetchGroups(Field[], Field[]) and similar overloads |
#6336 | Add another Kotlin example using apply |
#6352 | Add Result.formatChart() to produce ASCII text charts |
#6355 | Improve Kotlin example in manual |
#6362 | Auto-wrap Select as Field in overloaded API like DSL.least() |
#6363 | Rename Cursor.fetchXXX() methods to fetchNextXXX() |
#6368 | Port Sakila database to DB2 |
#6372 | Add DSLContext Configuration.dsl() |
#6374 | In jOOQ-spring-boot-example, use jooq starter instead of jdbc starter |
#6381 | Add Derby support for RENAME { TABLE | COLUMN | INDEX } |
#6386 | Add Scope.dsl() |
#6391 | Add ResultOrRows.exception() to improve support for SQL Server's RAISERROR |
#6410 | Don't generate empty Keys.java or Indexes.java files |
#6411 | Code generator should generate VARCHAR(length) and NUMBER(precision, scale) method |
#6413 | Add Setting.throwExceptions to define how SQLException should be propagated out of jOOQ |
#6416 | Add Name.unquotedName() and Name.quotedName() |
#6418 | Change SQLite's VALUES constructor implementation to support standard multi-row VALUES() clause |
#6422 | Add support for MySQL 8.0 window functions |
#6426 | Add support for MySQL 8.0 FOR UPDATE { NOWAIT | SKIP LOCKED } |
#6427 | Deprecate partitionByOne() API |
#6428 | Add missing overload WindowPartitionByStep.partitionBy(Collection<? extends Field<?>>) |
#6430 | Add support for MySQL 8.0 FOR UPDATE OF [ tables ] |
#6434 | Enhance "Forcing type" INFO message with the full <forcedType/> specification |
#6441 | Improve TableLike.field(Field) Javadoc |
#6443 | Explain in TooManyRowsException Javadoc that the exception has no impact on the statement causing it |
#6445 | Allow for overriding timestamps used for optimistic locking |
#6447 | Add Clock Configuration.clock() |
#6451 | Add a JdbcTemplate example to the manual |
#6463 | Add bind variable capability to Parser API |
#6465 | Add no-args constructor to some exceptions |
#6466 | Support fetching HSQLDB arrays from plain SQL results |
#6468 | Add DSLContext.fetchSingle() to return exactly one record |
#6471 | Improve manual section about LOBs |
#6472 | Add support for ALTER TABLE .. ALTER COLUMN .. { SET | DROP } NOT NULL |
#6473 | Add DataType.nullable(Nullability) to support a three valued nullable flag |
#6487 | Add DSL.groupId() |
#6488 | Add support for Oracle's WIDTH_BUCKET() function |
#6517 | JPADatabase should map JPA AttributeConverter types to generated jOOQ Converter |
#6519 | Improve JPA example by reusing a JPA AttributeConverter in jOOQ |
#6522 | Add JPAConverter to bridge between Converter and JPA's AttributeConverter |
#6525 | Add Setting for formatting options |
#6527 | Support START WITH .. CONNECT BY (reverse syntax order) |
#6530 | Add runtime support for procedure calls with top-level %ROWTYPE parameter types in Oracle |
#6531 | Add support for Oracle OBJECT types nested in PL/SQL RECORD types |
#6532 | Add UDT.isSynthetic() and UDTDefinition.isSynthetic() |
#6533 | Add support for PL/SQL BOOLEAN types inside of PL/SQL RECORD types |
#6534 | Add Name.append(String) and append(Name) |
#6545 | Support formatting of multi dimensional arrays in Result.format() |
#6567 | Support using org.jooq.impl.EnumConverter as a <converter> configuration |
#6575 | Enhance plain SQL templating language documentation with parsing rules |
#6584 | Improve DSLContext.batchStore() Javadoc, indicating that it does not execute MERGE / UPSERT semantics |
#6599 | In manual ExecuteListeners example, use ConcurrentHashMap.computeIfAbsent |
#6611 | Add Automatic-Module-Name to MANIFEST.MF |
#6617 | Specify <pluginManagement> in parent pom.xml |
Breaking changes
#5734 | Bad type mapping for PostgreSQL TIME[STAMP] WITH TIME ZONE and SQL Server DATETIMEOFFSET types |
#5818 | Plain SQL fetch() methods should return update count in Result |
#5921 | MockFileDatabase shouldn't trim lines |
#5990 | Allow for case-sensitive OWNERs in Oracle's code generation |
#6020 | values(RowN...) columns are named c0, c1, ... c[N-1] instead of c1, c2, ... cN |
#6051 | Don't include StopWatchListener with Settings.isExecuteLogging() |
#6327 | Add OrderField as a common super type of Field and SortField and accept that in ORDER BY clauses |
#6342 | No-args call to Field.sortAsc(), sortDesc() and empty Map call to Field.sortMap() should not return null |
#6373 | InsertQuery.newRecord() doesn't generate additional record unless values are set |
#6388 | Relax type constraints on various set(Map<Field<?>, ?>) to set(Map<?, ?>) |
#6440 | Throw TooManyRowsException in { Insert | Update | Delete }ResultStep.fetchOne() and fetchOptional() |
#6521 | Upgrade the optional/provided JPA API dependency to 2.2 |
#6523 | JPADatabase, H2Database, and OracleDatabase should not generate any system sequences |
#6529 | Move generated PL/SQL RECORD types in a udt subpackage |
#6613 | Add TransactionContext.causeThrowable() to allow for Throwable causes for transaction rollbacks |
#6615 | Allow for TransactionRunnable and TransactionCallable to throw Throwable |
Bug Fixes
#2123 | Cannot combine INSERT .. RETURNING with INSERT .. ON DUPLICATE KEY .. due to DSL API flaw |
#2738 | Bad inlining, setting, and registering of LocalDate, LocalTime, LocalDateTime, OffsetTime, OffsetDateTime bind values |
#3704 | Emit warning on conflict between <customType/> and type rewriting when <forcedType/> name is "Boolean" |
#3805 | Emulate ALTER TABLE .. ALTER TYPE .. NULL / NOT NULL with anonymous blocks, where supported |
#3823 | Regression: Date <-> Timestamp converter ignored after upgrading from 3.4.2 to 3.5 |
#4402 | Bulk insert fails when records have different sets of changed columns |
#4629 | Support INSERT INTO t VALUES with plain SQL tables |
#5213 | NullPointerException when generating code in single-uppercase-named-database setup on MariaDB and MySQL |
#5299 | MySQL enum type doesn't generate correct DDL via DSLContext.ddl() |
#5344 | SchemaMapping and TableMapping are not applied for table(Name) |
#5354 | Add <javaBeansGettersAndSetters/> to the code generator to support JavaBeans |
#5403 | IF EXISTS emulation using THROW doesn't work for SQL Server 2008 |
#5451 | Oracle 12c support for OFFSET .. FETCH causes ORA-00918 regression on queries with ambiguous column names |
#5453 | Work around Oracle 12c issue with INSERT .. SELECT into tables with IDENTITY column |
#5587 | Oracle's quoted string literals aren't parsed correctly |
#5720 | Convert doesn't correctly convert Strings to EnumType |
#5735 | jOOQ-checker is not deployed to Maven Central |
#5744 | Log WARN if users combine nested catalog configurations with top-level inputSchema configuration |
#5755 | Parser cannot parse bind variables |
#5763 | Generated TableValuedFunction.call() methods should wrap arguments with DSL.val(T, DataType) |
#5765 | Compilation error in generated schema when table-valued function literal clashes with class name |
#5771 | MockResultSet should call Converter to transform MockResult's <U> back to <T> |
#5776 | DefaultBinding cannot parse +HH timezone offset |
#5779 | DataType.getSQLType() doesn't return the right value for java.time types |
#5783 | KeepNamesGeneratorStrategy generates wrong Keys.java |
#5794 | git push tag |
#5804 | Various Javadoc warnings |
#5807 | Exception thrown when creating table with SQLDataType.UUID in MySQL |
#5812 | InformationSchema export contains wrong column name |
#5820 | Missing @Support annotations for PostgreSQL on InsertOnDuplicateSetStep.set() |
#5840 | Shouldn't DEBUG log OUT parameters on procedures that don't have any |
#5845 | ClassNotFoundException occures when generate codes form JPA entity by maven plugin |
#5848 | [#5845] Use the correct ClassLoader to load the jpa entity classes de… |
#5855 | Outdated link to jooq-export.xsd in Result.formatXML() Javadoc |
#5858 | Data loader unable to decode Base64 encoding binary types |
#5872 | <types/> cannot match user-defined types (e.g. PostGIS GEOMETRY) |
#5879 | Schema version check does not work with Scala |
#5881 | NullPointerException when running Maven code generator plugin without <target/> specification |
#5886 | Manual typo: >U> should be <U> |
#5888 | <expressions/> deprecation message is logged several times by the code generator |
#5890 | H2Database orders tables by ID instead of NAME |
#5892 | File does not get renamed on Windows when TABLE_A is renamed to TABLEA |
#5901 | Bind variable index should be logged in stack trace when there is a JDBC data type problem |
#5922 | Parser doesn't accept FULL JOIN |
#5929 | java.util.impl.Contains should check both sides of the expression for array types |
#5936 | Ignore strategy/name when strategy/matchers is present, in code generator |
#5938 | Fix typo in manual's having example java code |
#5940 | Do not return ID on Record.update() when updatablePrimaryKeys is set to false |
#5943 | Boolean data type rewrites on Oracle procedures conflict with PL/SQL BOOLEAN data type logic |
#5946 | Compilation error in generated code when applying converter to Oracle NUMBER procedure parameter |
#5954 | Support JTDS limit of 2000 bind variables also for SQL Server |
#5955 | Various parser bugs / missing features |
#5967 | Improve performance of Result.formatJSON() by avoiding List and Map allocation |
#5971 | Do not throw UnsupportedOperationException in DefaultResultSet etc |
#5979 | ArrayIndexOutOfBoundsException when generating DSLContext.ddl() for DefaultSchema |
#5981 | LIMIT examples in manual are not consistent |
#5989 | Case insensitive OWNER search in Oracle code generator causes slow execution for large schemas |
#5994 | DSL.name() Javadoc points to wrong DSL.field() methods |
#6007 | Bad formatting of CASE WHEN EXISTS expressions |
#6019 | Wrong SQL generated on Query.toString() on SELECT .. OFFSET (no LIMIT) |
#6025 | Unstable alias generation for derived tables |
#6031 | DefaultBinding.pgFromString() doesn't support TIMESTAMP WITH TIME ZONE data type |
#6033 | Manual documents incorrect restriction on ConnectionProvider.acquire() method |
#6034 | Param.equals() doesn't work for binary data |
#6038 | Possible leaking JDBC Arrays in DefaultExecuteContext.ARRAYS |
#6042 | DefaultBinding should register java.sql.Array for later freeing |
#6048 | UDTRecordImpl.readSQL(SQLInput) and writeSQL(SQLOutput) optimisations |
#6055 | NullPointerException thrown when calling Oracle Function with BOOLEAN parameter |
#6058 | StackOverflowError when DefaultBinding.pgFromString() encounters unknown type |
#6064 | SQL Server doesn't generate any code when top-level inputSchema is specified, but not inputCatalog |
#6065 | JOIN .. USING emulation doesn't work with plain SQL |
#6069 | Bad Javadoc on Catalog.getName() |
#6077 | Replace usage of String.split() by Pattern.split() |
#6078 | NullPointerException in GenerationUtil with Postgres CITEXT extension applied |
#6081 | Jsr310 LocalDateTime fail on batch insert queries but works in standard queries |
#6083 | Cannot combine INSERT .. DEFAULT VALUES with ON DUPLICATE / ON CONFLICT |
#6085 | Bad Javadoc on DeleteResultStep |
#6103 | Excess whitespace in formatted MySQL WITH ROLLUP clause |
#6106 | Bad formatting when combining constraints in CREATE TABLE statement |
#6109 | Prefer Java 8 syntax (method references, lambda expressions) in manual example |
#6110 | Broken code in docs |
#6117 | DB2 doesn't support qualified column references in FOR UPDATE OF |
#6118 | RESTRICT is a mandatory keyword in DB2's DROP SCHEMA command |
#6122 | Fix DDL Support annotations for DB2 |
#6127 | DELETE RETURNING must be emulated on DB2 with OLD TABLE() not FINAL TABLE() |
#6129 | ConstraintForeignKeyReferencesStepN.references() should return ConstraintForeignKeyOnStep |
#6130 | Cannot combine ON DELETE and ON UPDATE actions on foreign key specifications |
#6141 | Add identity column support to XMLGenerator |
#6150 | Oracle LocalDate bind variables aren't cast to DATE |
#6163 | XMLGenerator doesn't export <is_nullable/> for columns |
#6165 | XMLDatabase doesn't correctly load UNIQUE keys |
#6171 | DefaultTransactionProvider should not roll back to savepoint in top transaction |
#6173 | Dead link in Oracle examples |
#6189 | JPADatabase doesn't correctly generate tables for multi-schema entities |
#6191 | Compilation error in generated code when column is called RESULT or PRIME |
#6198 | Manual incorrectly refers to term "paging" rather than "pagination" |
#6204 | PL/SQL Records not generated depending on the order of procedures in a package |
#6207 | Compatibility issues in Sakila database for SQL Server 2016 |
#6213 | Document XMLGenerator |
#6221 | DSLContext.ddl() doesn't generate identity correctly |
#6223 | Field.contains(T) doesn't delegate to Field.contains(Field<T>) when using plain SQL |
#6226 | NoSuchFieldError when using commercial dialect with open source edition in Maven code generation |
#6235 | Manual does not correctly order versions > 3.9 |
#6236 | Improve inListPadding implementation |
#6238 | Typo in AlterTableRenameConstraintToStep Javadoc |
#6249 | Null batchSQL when running a batch with a single query |
#6251 | XMLGenerator: UniqueConstraintCatalog set to referenced key instead of catalog |
#6267 | Missing SQLDialect.SQLSERVER annotation on CREATE SCHEMA and DROP SCHEMA |
#6274 | Configuration.dialect() should return SQLDialect.DEFAULT when null |
#6289 | Don't generate type length modifier for PostgreSQL bytea types in DDL |
#6292 | Improve support for SQL Server date time literals |
#6303 | Oracle flashback query for aliased table results in invalid sql |
#6316 | ALTER TABLE .. ADD COLUMN ignores column type's DEFAULT clause |
#6329 | Clarify in the manual that INSERT .. SET is emulated for all dialects |
#6330 | Exception thrown when creating table with converted VARCHAR type |
#6331 | DataType.hasLength(), hasPrecision(), hasScale(), and others should depend on Binding's <T> type |
#6332 | JPADatabase with GeneratedValue does not account for dialect |
#6333 | Error when passing java.util.Date to DSL.timestamp() |
#6339 | Recognise H2 SYSTEM_SEQUENCE in INFORMATION_SCHEMA.COLUMNS.COLUMN_DEFAULT as an Identity column |
#6357 | Remove outdated section about Oracle not supporting IDENTITY columns |
#6367 | PostgreSQL enums aren't linked correctly from generated tables when <outputSchemaToDefault/> is true |
#6370 | Improve misleading MockDataProvider example in the manual |
#6375 | INSERT .. SELECT .. ON DUPLICATE KEY emulations using MERGE don't work |
#6377 | Remove outdated jOOQ-codegen-gradle example |
#6383 | Derby requires RESTRICT on DROP SCHEMA statement |
#6390 | SQL Server multiple errors are not propagated if an update count precedes them |
#6394 | SQL Server Sequence.currval() regression |
#6395 | Definition.getQualifiedName() is wrong when <outputSchemaToDefault/> is set to true |
#6399 | Spring Boot example should use official documentation recommendation to configure dialect |
#6401 | Don't generate javax.validation.NotNull for identity columns |
#6404 | NullPointerException when fetching unnamed nested records in plain SQL with PostgreSQL |
#6406 | NullPointerException when trying to get mvn help on goal generate |
#6423 | Compilation error in generated code when both SchemaVersionProvider and CatalogVersionProvider are applied |
#6444 | Fix some slightly out of date links in README.md |
#6453 | Code generation regression for <dateAsTimestamp> |
#6467 | Manual erroneously claims that routine / udt / table / sequence generation cannot be deactivated |
#6478 | Typo in DSLContext.fetchCount() and error in DSLContext.fetchExists() Javadoc |
#6491 | Add support for Oracle SYS_REFCURSOR IN OUT parameters |
#6493 | XMLDatabase doesn't work when dialect is not a SQLDialect.family() |
#6495 | Update manual's list of supported databases |
#6498 | "Invalid column index" on Oracle stored procedure call when return type is converted to boolean and argument type is defaulted |
#6513 | ClobBinding and BlobBinding don't correctly inline their bind values |
#6536 | Generated deprecation doesn't work on function / procedure convenience methods |
#6537 | NullPointerException in AbstractRecord.intern0() |
#6540 | Oracle IDENTITY columns aren't recognised correctly by code generator |
#6557 | Error in Record.compareTo(...) Javadoc |
#6561 | Manual section about optimistic locking has invalid code |
#6563 | Result.formatJSON() does not correctly format array types |
#6571 | Trigger generated errors are not fetched through jOOQ's plain SQL API |
#6574 | "A constant expression was encountered in the ORDER BY list" when calling Field.sortAsc() with empty parameter list on SQL Server |
#6593 | Incorrect handling of Oracle quoted string literals in plain SQL |
#6602 | Code generation for routines fails on MySQL 8 |
#6608 | Transaction API does not roll back on Throwable, but Exception only |
#6609 | Manual section about ForcedTypes uses <converter> instead of <binding> |
#6614 | Typo in manual section about dynamic SQL |
Version 3.9.0 - December 23, 2016
This is another very exciting release
Experimental Parser
This is an extremely exciting strategic feature for jOOQ. jOOQ users are used to creating SQL statements by "manually" creating a SQL expression tree through the jOOQ API. But nothing should prevent us from parsing string-based (and vendor- specific!) SQL statements into jOOQ expression trees. In the future this can be used, for instance, to translate (and format) one SQL dialect into another, making jOOQ not only an excellent SQL client API for Java, but a general-purpose SQL API.
The new Parser API is available from DSLContext.parser() and is currently deprecated as "experimental" (and incomplete). We're including it in jOOQ 3.9 for public review, so we're looking forward for any feedback you may have!
Checker framework integration
We've annotated all of our API with the @Support annotation for quite a while. This annotation allows for documenting what SQL clause or function is available in what SQLDialect (and version). If that's not enough for you, do check out our new JSR 308 / Checker Framework integration, which allows jOOQ API consumers to "type check" their API usage for a given SQL dialect. For instance, using MySQL, you can now get compilation errors if you're accidentally using Oracle-specific API.
More info in this blog post here: https://blog.jooq.org/jsr-308-and-the-checker-framework-add-even-more-typesafety-to-jooq-3-9/
Better Oracle 12c and PL/SQL integration
Oracle 12c introduced a variety of new features that we finally support in jOOQ as well, including the new IDENTITY column type or the OFFSET FETCH clause, which was emulated using ROWNUM filtering, thus far.
In addition to the above, we're continuing our extended PL/SQL support by offering an emulation for the (de)serialisation of PL/SQL RECORD types. This is particularly interesting for everyone who used Oracle's now deprecated (12cR1) and removed (12cR2) JPublisher for PL/SQL bindings.
More info about this here: https://blog.jooq.org/use-jooq-to-read-write-oracle-plsql-record-types/
JSR-310 Java Time API support
We're now confident that we can support the "old" JDBC date time types and the "new" JSR-310 Java Time API types in parallel in a single API. With this in place, jOOQ now includes a <javaTimeTypes/> code generator configuration, that replaces the "old" JDBC date time types in generated code.
The upcoming patch releases for jOOQ 3.9.x will further improve the situation for TIME[STAMP] WITH TIME ZONE types in databases that do support them. Your continued feedback in this area is very welcome.
New DDL statements and clauses
As in every release, we've added support for tons of new DDL statements and clauses, including:
- A variety of RENAME statements
- The { CREATE | ALTER | DROP } SCHEMA statements
- The useful IF EXISTS clause for ALTER and DROP statements
- The useful IF NOT EXISTS clause for CREATE statements
- Support for partial indexes (CREATE INDEX .. WHERE)
- Support for ASC | DESC ordering in CREATE INDEX statements
- Support for Oracle's CONSTRAINT .. USING INDEX .. clause
- Support for IDENTITY columns
- Better support for constraint construction
Improved transactions API
The existing transactions API creates a new "scope" for each transaction, with a new, derived Configuration that contains that transactional scope (and a custom ConnectionProvider, not the user one). This was necessary from a design perspective to allow also for asynchronous transactions, which were introduced in jOOQ 3.8.
But if users can safely rely on ThreadLocal transaction semantics, the existing API that creates a new Configuration is too confusing. This is why jOOQ 3.9 now introduces the ThreadLocalTransactionProvider implementation that allows for the simpler transaction API to be used:
ctx.transaction(() -> { // Safe to re-use the "global" ctx here: ctx.insertInto(TABLE_A); ctx.update(TABLE_B); });
Besides, we now support a new TransactionListener SPI, which allows for hooking into the transaction lifecycle and execute stuff prior to beginning / committing or rolling back a transaction.
InformationSchema import and export
For a while now, we've supported the XMLDatabase in jooq-meta to generate code based on a SQL standard inspired XML format of your database schema: https://www.jooq.org/xsd/jooq-meta-3.5.4.xsd
This format is now also available to the jOOQ runtime library for importing and exporting schema meta information at runtime. In combination with the DSLContext.ddl() command, which was introduced in jOOQ 3.8, this makes for a very powerful schema import / export tool, which we're going to further improve in future versions.
Other minor improvements
- We've finally added support for PostgreSQL 9.5's ON CONFLICT clause.
- A new XMLGenerator allows for exporting a database schema to an XML document.
- A variety of new Java 8 style APIs, including "functional aliasing" and converter construction, and streaming.
- Mocking API improvements
- Lots of code generator and API improvements
Enjoy this exciting new milestone of jOOQ goodness!
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.8-3.9
Features and Improvements
#330 | Add code generation support for PL/SQL RECORD types |
#2303 | Implement a SQL parser |
#2607 | Add support for Oracle 12c's OFFSET .. FETCH clause |
#3146 | Add support for Oracle 12c IDENTITY types |
#3315 | Add code generation hooks to override Record, Pojo, and Interface getters and setters |
#3358 | Add the manual XML to GitHub |
#3906 | Allow for customising generated file headers |
#4164 | Generate varargs setters for array types on interfaces / records / pojos, etc. |
#4429 | Add <javaTimeTypes/> to code generator configuration to generate Java 8 java.time types instead of java.sql types |
#4512 | Add Table.as(String, Function<? super Field<?>, ? extends String>) to allow for "functional aliasing" |
#4794 | Add support for Catalog in code generation schema mapping |
#4919 | Add support for CREATE INDEX .. WHERE in PostgreSQL and SQL Server (filtered indexes) |
#5062 | Add support for IDENTITY columns in CREATE TABLE statements |
#5063 | Improve DSLContext.batchStore() Javadoc |
#5083 | Add support for ALTER SEQUENCE .. RENAME TO .. |
#5084 | Add support for ALTER VIEW .. RENAME TO .. |
#5085 | Add support for ALTER INDEX .. RENAME TO .. |
#5087 | Add support for ALTER TABLE, SEQUENCE, VIEW, INDEX IF EXISTS .. |
#5162 | Use DSLContext.connection() in internal code, rather than calling ConnectionProvider.acquire() directly |
#5238 | Format timestamp when formatting java.sql.Date, if time component is non-zero |
#5239 | Read and write the time component as well in Oracle's DATE type |
#5243 | Manual section showing jOOQ+JPA usage should take into account Binding and Converter |
#5244 | Add support for CREATE SCHEMA |
#5245 | Add org.jooq.Allow and org.jooq.Require annotation and a SQLDialectChecker using JSR-308 and the checker framework |
#5246 | Add an org.jooq.Allow.PlainSQL annotation and a PlainSQLChecker using JSR-308 and the checker framework |
#5247 | Deprecate SQLDialect.POSTGRESPLUS |
#5253 | Add support for Oracle COLLECT() |
#5255 | Add Dao.delete(P) overload (no varargs) to avoid potential generic warnings at the call site |
#5271 | Add SQLDialect.isFamily() |
#5276 | Add ParamMode, an enum to specify if a parameter is IN, OUT, or INOUT |
#5277 | Add support for CREATE SCHEMA IF NOT EXISTS |
#5278 | Add support for ALTER SCHEMA [ IF EXISTS ] .. RENAME TO |
#5279 | Add support for DROP SCHEMA [ IF EXISTS ] .. [ CASCADE | RESTRICT ] |
#5286 | Add more meaningful error handling when Maven code generator is not configured correctly |
#5289 | In the doc, part " 4.4.2. The CREATE statement " add a "nullable(false)" example |
#5295 | Implement Queries.toString() |
#5297 | Add InsertOnDuplicateStep.onConflict() for native PostgreSQL 9.5 ON CONFLICT support |
#5298 | Queries should extend Iterable<Query> and implement stream() |
#5301 | Display a warning in the generator logs for regexes that never match |
#5305 | Add support for CREATE INDEX .. ON (<expr> { ASC | DESC }, ...) |
#5311 | Add DSL.constraint() to create an unnamed (system named) constraint |
#5312 | Add SQLDataType.VARCHAR(length) and other methods for convenience |
#5313 | Add DSL.check() foreignKey(), primaryKey(), unique() to create unnamed (system named) constraints |
#5321 | Add support for POSITION(in, search, startIndex) |
#5327 | Allow for generating immutable interfaces (independently of POJOs) |
#5335 | Log a warning in the code generator if a table is reported to have two identity columns |
#5342 | Add nullable(false) in "The CREATE statement" part |
#5347 | Add XMLGenerator to produce an XML file containing meta information according to jooq-meta.xsd |
#5358 | Add support for INTERSECT ALL, EXCEPT ALL also in DB2 |
#5360 | Add <syntheticIdentities> regular expression to code generator configuration |
#5371 | Add an example project using Spark Java and Chart.js |
#5372 | Add Result.formatJSON(JSONFormat) to allow for different JSON formats |
#5373 | Add <syntheticIdentities> regular expression to code generator configuration |
#5377 | Add alternative TransactionProvider that implements ThreadLocal semantics |
#5378 | Add new TransactionListener SPI that hooks into the TransactionProvider lifecycle |
#5379 | Add convenience API in Configuration.set() and derive() to bypass the *Provider types |
#5384 | Add Settings.executeWithOptimisticLockingExcludeUnversioned |
#5389 | Enhance DSLContext.fetchFromJSON() to support new formats |
#5396 | Add Converter.andThen(Converter) and Converter.inverse() default methods |
#5398 | Add converter constructor Converter.of(Class<T>, Class<U>, Function<? super T, ? extends U>, Function<? super U, ? extends T>) |
#5413 | Add support for Oracle's RATIO_TO_REPORT() analytic function |
#5415 | Recommend using third party Gradle plugin for jOOQ instead of hand-written Groovy code |
#5418 | Add support for ALTER TABLE .. ADD CONSTRAINT .. USING INDEX (...) |
#5437 | Add support for loading the jooq-meta.xsd into org.jooq.Catalog / Schema / Table / etc. |
#5439 | Add Mock.of(Record), Mock.of(Result), Mock.of(MockResult...), Mock.of(int) |
#5443 | Document jOOQ 3.8 <forcedType/> configuration changes |
#5445 | Add support for Oracle 12c TRUNCATE .. CASCADE |
#5449 | Add Table.as(Table) to be consistent with Field.as(Field) |
#5452 | Add a big disclaimer to the Mock API not to mock an entire database |
#5460 | Add DSLContext.informationSchema(Catalog...), informationSchema(Schema...), informationSchema(Table...) to export jooq-meta.xsd format |
#5461 | Add DSLContext.ddl(Catalog) |
#5463 | Add org.jooq.Meta.getSequences() |
#5467 | Add Sequence.getCatalog() and Table.getCatalog() for convenience |
#5472 | Add <emptyCatalogs/> and <emptySchemas/> to the code generator configuration, to prevent generating of empty catalogs / schemas |
#5477 | Add <configurationFile> element to Maven code generation plugin, for external configuration |
#5485 | Add createView(String, Function<? super Field<?>, ? extends String>) where the Function receives Select columns as input |
#5487 | Add Table.as(String, BiFunction<? super Field<?>, ? super Integer, ? extends String>) to allow for "functional aliasing" (with column index) |
#5494 | Improve section of the manual explaining the plain SQL templating logic |
#5501 | Add Record.with(Field, T) for fluent setting of values on a Record |
#5508 | Add Record.intoStream() |
#5517 | Make JavaWriter.ref() methods public |
#5518 | Add inverse Type.xxx(Record) operations for Record.xxx(Type) methods |
#5522 | Add support for derived column lists with unnest() operator |
#5525 | Add code generator flag to turn off generation of tables |
#5526 | Add code generator flag to turn off generation of UDTs |
#5527 | Add code generator flag to turn off the generation of routines |
#5528 | Add code generator flag to turn off generation of sequences |
#5533 | Mention the possibility of running SELECT * by keeping an empty select() field list |
#5545 | Improve manual to explain Binding implementation in the context of static statements |
#5556 | Code generator should delete catalog and schema directories when no longer configured |
#5561 | Log warnings when users misconfigure forceType / customType elements |
#5562 | Add org.jooq.Log, an API that can be implemented by loggers, such as JooqLogger |
#5567 | Add Javadoc warnings on Field.in(Collection) and Field.in(T...) about cursor cache contention problems |
#5570 | Add debug information on exception stack traces |
#5575 | Add support for H2's TO_DATE() and TO_TIMESTAMP() function |
#5585 | Generated file header should read "this file is generated", not "this class is generated" |
#5600 | Add setting to enable IN list padding |
#5603 | Add TableLike.fieldStream() and other metadata Streaming methods |
#5616 | Added hint for m2e to behave |
#5618 | Further improve select() Javadoc for empty argument lists |
#5621 | Add FieldEscapeStep as a return type for Field.like(), such that the ESCAPE keyword can be used explicitly |
#5623 | Add Name.first() and Name.last() |
#5624 | Add Name.qualified() |
#5625 | Add Name.equalsIgnoreCase() |
#5626 | Add DSL.name(Collection<String>) |
#5627 | Add runtime support for PL/SQL RECORD types |
#5629 | Add DataType.isUDT() |
#5630 | DefaultBinding should TRACE log registered OUT parameters |
#5639 | MockFileDatabase ignores erroneous rows specification |
#5642 | Add DSL.localDate(), offsetDateTime(), offsetTime() to construct JSR-310 expressions |
#5643 | Add DSL.currentLocalDate() currentLocalTime() currentLocalDateTime() currentOffsetTime() currentOffsetDateTime() |
#5646 | Add DSL.trunc(LocalDate) etc |
#5647 | Add DSL.extract (LocalDate) etc. |
#5648 | Add DSL.toLocalDate () etc. |
#5657 | Explain the different org.jooq.Scope types in its Javadoc |
#5659 | Add clarification to OFFSET[DATE]TIME Javadoc that the behaviour is defined by the JDBC driver/database |
#5664 | Implement DefaultBinding.toString() |
#5681 | Add MockFileDatabase.nullLiteral() allowing to override the null literal in DSLContext.fetchFromTXT() |
#5690 | Document that only the Open Source Edition is hosted on Maven Central |
#5702 | Add support for PostgreSQL ON CONFLICT .. DO NOTHING |
#5706 | Code generator's <recordVersionFields/> setting does not match column |
#5709 | Add a DataType.identity() flag to specify that a data type is meant to be used as a SERIAL / IDENTITY type |
Breaking changes
#2684 | Rename org.jooq.scala package to org.jooq.scalaextensions because of potential collisions with the scala package |
#3943 | Custom Bindings cannot be applied on record version or timestamp columns |
#4168 | <outputSchemaToDefault/> generates "_" package name when generating multiple schemata |
#5233 | Remove DSL.field(Row[N]) to speed up client side compilation time |
#5320 | DSL.orderBy(Field...) returns WindowSpecificationOrderByStep instead of WindowSpecificationRowsStep |
#5395 | Fix covariance and contravariance on various Converter API usages |
#5589 | java.math.BigInteger should be generated for Oracle INTEGER columns |
Bug Fixes
#4965 | DateTimeParseException when parsing "lenient" OffsetDateTime format |
#5094 | StatementType.STATIC_STATEMENT is not applied to DSLContext.render(QueryPart) |
#5232 | Regression: Cannot select null values for enums |
#5249 | Bad inlining of Double.NaN in PostgreSQL |
#5251 | Oracle PIPELINED functions in packages are erroneously reported as AGGREGATE functions by the code generator |
#5256 | DAO.delete() should delete via UpdatableRecord.delete(), not via a bulk delete |
#5260 | Wrong update count when running UPDATE .. RETURNING in PostgreSQL and Firebird |
#5264 | PostgreSQL SMALLINT function arguments should always be cast explicitly |
#5268 | Compile error when a schema has the same name as a table within that schema |
#5280 | Bad Javadoc on dropTable() statements |
#5290 | Internal Cache$Key is not Serializable |
#5291 | Bad DataType.defaultValue() call generated for MySQL tables |
#5302 | Unmarshal warning : cvc-complex-type.2.4.b: The content of element 'target' is not complete. One of '{"jooq-codegen-3.8.0.xsd":encoding}' is expected. |
#5303 | Code generator aborts catalog browsing on SQL Server as soon as user is denied access to a single catalog |
#5307 | Avoid parsing ? in plain SQL if followed immediately by another operator-like character in PostgreSQL |
#5322 | Create constant empty arrays Field[0] and String[0] for faster toArray() calls |
#5323 | Wrong precision generated in automatic CAST for DB2 and other databases |
#5331 | Column default expressions using sequences are not treated as identity columns in H2 |
#5334 | Nested record generated when TABLE.COLUMN "overlaps" with a table called TABLE_COLUMN for MySQL |
#5349 | Wrong defaults for <tableValuedFunctions/> in jOOQ Open Source Edition |
#5356 | Incorrect order of HSQL column definition tokens: "DEFAULT" and "NULL" |
#5362 | Plain SQL batches produce wrong INFO messages about bind value count mismatches |
#5366 | Record.update() produces wrong update counts in HSQLDB |
#5368 | In HSQLDB, ALTER VIEW .. RENAME is not supported. Use ALTER TABLE .. RENAME instead |
#5380 | MySQL STRAIGHT_JOIN is not implemented correctly |
#5385 | Excessive WARN log level when a generated object has no name |
#5393 | Cannot apply Binding to PostgreSQL UDT arrays |
#5399 | Conversions.scala returns Option[_] instead of Option[T] or Option[U] where this is possible |
#5404 | Exceptions when calling Oracle functions / procedures with TABLE of TABLE type arguments |
#5408 | Optimistic locking doesn't work for PostgreSQL, Firebird |
#5416 | Bad update count on Oracle UPDATE .. RETURNING emulation |
#5424 | Don't escape Scala-style setter names produced by naming strategies in ScalaGenerator |
#5430 | Cumulative Earnings example in jOOQ-spark-chart-example is wrong |
#5432 | Fix the type-erasure issue for scala vararg helpers in org.jooq.scala.Conversions using scala.predef.DummyImplicit |
#5442 | Support default methods in DefaultRecordMapper.ProxyMapper |
#5446 | Unnecessarily costly query to check for Oracle version in code generation |
#5457 | "overriding method fields in class AbstractRecord" compilation error when using ScalaGenerator on tables containing columns like "fields", "configuration", etc. |
#5464 | Wrong @Support annotations on DSL.sequence() constructors |
#5470 | 3.8 manual is wrong about UPDATE .. RETURNING not being emulated |
#5481 | ResultImpl#intoMap produces an incorrect error message on duplicate key |
#5483 | Documentation of DSL#sql(String, QueryPart ...) does not mention parsing bind value placeholders ("?") |
#5495 | NotSerializableException thrown when AbstractXMLasObjectBinding is applied on a column |
#5509 | Cannot combine INSERT .. SELECT .. RETURNING with an arbitrary number of columns |
#5521 | Bad SQL generated for PostgreSQL when inlining arrays |
#5524 | Don't System.exit(-1) from within GenerationTool. Throw an exception instead |
#5536 | Missing reference to ResultQuery.fetchSize() in the manual |
#5540 | Bad predicate generated for INSERT .. ON DUPLICATE KEY IGNORE emulation in PostgreSQL 9.3 dialect |
#5547 | Work around an ojdbc7 driver bug producing a NPE for Oracle 12c INSERT .. RETURNING statements |
#5557 | Compilation error when generated catalog and one of its contained schemas have the same name |
#5559 | Add missing documentation for the <catalogVersionProvider/> configuration element |
#5569 | DataTypeException: Cannot convert from String to class [B when generated code contains VARBINARY type with default value |
#5573 | NullPointerException when generating Oracle AQs with payload types outside of the included schemas |
#5578 | Incorrect ambiguity warning when column name appears in 3+ joined tables |
#5583 | For generated code, change file header style from JavaDoc to regular comment |
#5584 | Fix all file headers to be regular comments, not Javadoc |
#5595 | Be more clear about excludes having priority over includes in code generation config manual section |
#5596 | Error on code generation when schema name is a Windows reserved name like CON, AUX |
#5597 | Code generator IOExceptions are not logged when error appears during closing of file |
#5607 | JPADatabase causes warnings |
#5608 | JPADatabase includes undesired INFORMATION_SCHEMA by default |
#5609 | Regression: Unspecified inputSchema no longer generates all schemata |
#5613 | Incorrect deserialisation of deeply nested PostgreSQL ARRAYs / UDTs |
#5614 | SchemaVersionProvider might cause deletion of schemas that were not updated |
#5617 | NullPointerException on fetchLazy().stream() / MockStatement.execute() returns false on empty results |
#5633 | Regression when reading PostgreSQL bytea[] type |
#5644 | DSL.currentDate() produces field name current_user |
#5649 | Trailing comma from ScalaGenerator when using schemaVersionProvider |
#5661 | Casting to SQLDataType.OFFSETTIME puts ojdbc connection in illegal state |
#5676 | [#5639] Fix MockFileDatabase ignores erroneous rows specification |
#5697 | jOOQ generated code contains deprecated calls |
#5701 | Work around PostgreSQL's limit of 32767 bind variables per statement |
#5704 | Escape HTML characters in generated JavaDoc |
#5707 | Fix typo for setting WindowSpecification |
#5708 | Function delegates window RANGE calls to ROWS |
#5715 | ArrayIndexOutOfBoundsException when fetching an unnamed column from SQL Server with plain SQL |
#5717 | CREATE SEQUENCE doesn't work in Derby, SQL Server, when names aren't quoted |
#5721 | jooq-codegen.xsd wrongly makes forcedType/name a mandatory element |
#5725 | Regression in MySQL's code generation prevents linking column types to enum classes |
#5727 | INSERT INTO table SELECT ... UNION ... renders bad SQL when column names are omitted and a plain SQL table is given |
#5728 | Emulate SELECT .. INTO .. also for HSQLDB using CREATE TABLE .. AS SELECT .. |
Version 3.8.0 - May 03, 2016
Version 3.8 is a collection of very useful little features and improvements that have been sitting on our roadmap for a long time:
More Java 8 and asynchronicity support:
One of Java 8's interesting new features is the monadic support for asynchronous operation composition: CompletionStage. jOOQ now features a variety of methods like DSLContext.transactionAsync(), ResultQuery.fetchAsync(), Query.executeAsync(), but also DBMS_AQ.dequeueAsync(), which allow for leveraging this new Java 8 API. In order to inject custom Executors into jOOQ, a new ExecutorProvider SPI has been added, defaulting to an implementation that uses the ForkJoinPool.
Kotlin integration:
While we were working on jOOQ 3.8, Kotlin 1.0 was released, a very exciting new JVM language by JetBrains. We've started experimenting with the jOOQ / Kotlin integration, and we've already added new methods to leverage Kotlin's syntax sugar: Record.get() and Record.set() (as synonmys for getValue() and setValue())
With these new methods, it is possible to use Kotlin's square bracket syntax to access and modify fields in a record:
val rec = fetchOne(BOOK); println(rec[BOOK.TITLE]); rec[BOOK.TITLE] = "10 SQL Tricks";
Stay tuned for more exciting Kotlin integration features in the near future!
The SQL Catalog type:
Most databases group objects in three hierarchy levels:
- Catalogs, which have several...
- Schemas, which have several...
- Tables (and other objects)
Specifically, in SQL Server, it is possible to select data from objects across several catalogs. jOOQ 3.8 finally formally supports the org.jooq.Catalog type both in the code generator as well as in the runtime.
New DDL features:
Schema migrations and initial database setups become an increasingly useful feature for many jOOQ users. In each release, we're adding support for additional statements and clauses of existing statements. jOOQ 3.8 now supports:
- DEFAULT column values in CREATE TABLE or ALTER TABLE statements
- IF EXISTS in DROP statements
- IF NOT EXISTS in CREATE statements
- ALTER TABLE .. { RENAME | RENAME COLUMN | RENAME CONSTRAINT } statements
In addition to the above statements, we now allow for generating a set of DDL commands from a Schema or Table reference. This is very useful e.g. to recreate an Oracle schema on an H2 in-memory test database.
Code generator improvements:
Among many other improvements, we've simplified data type conversion and binding configurations. This essentially means: Much less XML for the same feature set!
Also, we've added additional flags that help maintaining more fine-grained control over which artefacts you really want to generate.
General notes:
We have once more postponed thorough JSR 310 (java.time) API support. This feature addition is one of our users' most wanted. We're aware of this and sorry we still couldn't deliver it. The risks of getting things wrong in terms of backwards-compatibility are high, and we don't want to get this wrong.
We have changed some internals, which may affect those of you who heavily extend jOOQ. In particular, the deprecated QueryPartInternal.toSQL() and bind() are no longer overridable. Please move your implementation to the accept() method, which was added in jOOQ 3.4. Our main benefit from this incompatible change is a substantial performance improvement, as we can now traverse the jOOQ QueryPart expression tree only once in order to collect the SQL string and the bind variables, which leads to a roughly 40% faster SQL rendering in benchmarks!
All in all, this is an exciting and big new release with tons of little new features that you won't want to miss once you have upgraded! Details below.
Enjoy!
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.7-3.8
Features and Improvements
#1068 | Add integration tests for DSLContext.loadInto() when using only plain SQL objects |
#1859 | Add Setting to always fetch all record data after INSERT or UPDATE |
#2032 | Add code generation support for the new org.jooq.Catalog type |
#2211 | Change Record.getValue() and setValue() to get() and set() |
#2438 | Add ParamType Param.paramType() to indicate whether a parameter is INDEXED, NAMED, INLINED |
#2928 | Mapping tables based on regular expressions |
#3065 | Add performance regression tests |
#3073 | Distribute commercial jOOQ artifacts under a different groupId to avoid conflicts |
#3160 | Add Queries DSLContext.ddl(Schema), ddl(Table) and others to re-generate known artefacts |
#3254 | Add support for PostgreSQL materialized views |
#3330 | Allow custom quote character/no quote character when exporting to CSV |
#3482 | Add flags to the code generator to turn on / off generation for tables, views, packages, procedures, udts, etc. |
#3570 | Add KeepNamesGeneratorStrategy to keep generated identifiers as they are in the database |
#3691 | Improve API to create CASE expressions with arbitrary numbers of arguments |
#3761 | Add code generator configuration to specify a log level threshold |
#3852 | Add DataType.defaultValue(Field<T>) to allow for setting DEFAULTs in DDL statements |
#3942 | Add support for PostgreSQL functions returning single table records |
#4050 | Allow for specifying constraints with CREATE TABLE statements |
#4124 | Add <username/> as a synonym for <user/> in the code generation configuration |
#4155 | Add support for PL/SQL BOOLEAN types |
#4375 | Add support for CREATE TEMPORARY TABLE also in MySQL / MariaDB |
#4435 | Add DSLContext.transactionAsync(TransactionRunnable) and transactionResultAsync(TransactionCallable) |
#4480 | Emulate H2's MERGE statement for MySQL, MariaDB, and PostgreSQL 9.5 |
#4500 | Add a short section to the manual explaining how to configure jOOQ with JPA or Vertabelo |
#4501 | Add .fetch() and .execute() also to historic manual versions |
#4517 | Allow to configure the output file encoding in the code generator |
#4550 | Add support for property expressions in the code generator's standalone configuration |
#4568 | Add support for the PostgreSQL MODE() ordered-set aggregate function |
#4598 | Add <userType/>, <converter/>, <binding/> in <forcedType/>, to allow for working without <customType/> |
#4619 | Let SQLTable constructor pass SQL string to AbstractTable parent constructor |
#4620 | Change error message when jOOQ-meta database type could not be found |
#4663 | Add DSL.val(X), value(X), and inline(X) overloads for all common types |
#4676 | Add SelectFromStep.from(Name) and similar convenience methods |
#4677 | Add type safe overloads DSL.with(String, String, String) that will expect Select<? extends Record2<?, ?>> |
#4687 | Add ResultQuery.fetchStream() as a alias for stream() |
#4688 | Add a Javadoc comment to DataType#convert() linking to Convert#convert() for details |
#4693 | Add DSL.toDate(value, format) and DSL.toTimestamp(value, format) |
#4696 | Relax API contracts on DAOImpl by removing final keyword on methods |
#4715 | Allow to specify the newline character for Result.formatCSV() |
#4721 | Add Javadoc examples to DSL.using(String), showing proper use with try-with-resources |
#4724 | Add Table.eq(Table<R>) and Table.ne(Table<R>) |
#4729 | Emulate DSL.count(Table) and countDistinct(Table) for all other dialects |
#4730 | Recognise pgjdbc-ng JDBC URL in JDBCUtils.dialect(String) |
#4731 | Add Javadoc warning to Table.equals() to help prevent accidental usage |
#4735 | Add DSL.condition(Record) for Query By Example (QBE) predicate building support |
#4746 | Allow for specifying empty string as formatCSV()'s nullString / emptyString |
#4752 | Improve documentation of using jOOQ's code generator with ant |
#4753 | Add Settings for default naxRows, fetchSize, queryTimeout and other values |
#4756 | Add section to the manual documenting how to include the commercial jOOQ distribution in a Maven build |
#4761 | Add MySQL IFNULL() support as a synonym for NVL() |
#4763 | Deprecate on(Boolean), where(Boolean), having(Boolean), etc. |
#4769 | Improve TableLike.field(Field) Javadoc |
#4784 | Add support for OFFSET .. LIMIT in addition to LIMIT .. OFFSET |
#4785 | Add support for OFFSET without LIMIT |
#4791 | Upgrade scala dependency to 2.10.6 |
#4792 | Add Schema.getCatalog() and render the catalog in SQL |
#4795 | Add Setting to turn off rendering catalog at runtime |
#4796 | Add Context.qualifyCatalog() to allow for locally qualifying names without catalog |
#4797 | Document caveat when using Gradle XML Markup generator with some elements |
#4799 | Add a note to the manual about the Gradle / Groovy MarkupBuilder caveat related to some elements |
#4801 | Add DEQUEUE_OPTIONS_T.wait(int) to support timeout-based waits on Oracle AQ |
#4811 | Add source code in original form to .zip, such that users can build jOOQ right away |
#4818 | Add org.jooq.CSVFormat: A parameter object to replace the existing formatCSV overloads |
#4825 | Add support for Oracle table-valued functions |
#4827 | Add CatalogVersionProvider |
#4833 | Generate standalone function call for table-valued functions |
#4834 | Add Context.declareAliases as a flag to indicate whether alias declaration generating QueryParts are allowed to do so |
#4837 | Add DefaultConnectionProvider.setReadOnly() and isReadOnly() |
#4838 | Add code generation flag <tableValuedFunctions/> to turn off generation of table-valued functions |
#4839 | Rename Generator.fullyQualifiedTypes() to generateFullyQualifiedTypes() for naming consistency |
#4841 | Add code generation support for column DEFAULT values |
#4842 | Add support for RANGE clause in window functions |
#4847 | Improve Javadoc's of Loader API's various fields() methods |
#4848 | Add internal API to configure indentation of generated code |
#4855 | Remove final keyword on JavaGenerator methods |
#4857 | Add a chapter to the manual about in-memory importing |
#4858 | Add a section to the manual about importing JSON |
#4859 | Deprecate LoaderJSONOptionsStep.ignoreRows() |
#4868 | Generate 4 spaces in Java or 2 spaces in Scala instead of tabs in generated code by default |
#4869 | Generate schema and catalog references in order to fully qualify tables |
#4873 | Add Firebird 3.0 support for MERGE |
#4874 | Add Firebird 3.0 support for window functions |
#4879 | Add generateGlobalCatalogReferences() and generateGlobalSchemaReferences() flags to code generator |
#4889 | Update copyright to 2016 |
#4891 | Accept DataSource in GenerationTool, in addition to Connection |
#4892 | Add sections to the manual explaining how to use JPADatabase |
#4893 | Add a tutorial section to the manual showing how to use jOOQ with Kotlin |
#4897 | Add sections to the manual explaining how to use XMLDatabase |
#4901 | Add UniqueKey.getName() and ForeignKey.getName(), and generate this info in Keys.java |
#4903 | Emulate EVERY() with MAX() rather than with COUNT() |
#4904 | Add DataAccessException.sqlStateClass() and sqlStateSubclass() |
#4906 | Add manual and Javadoc URL mapping for /current/ = /latest/ |
#4907 | Add DSLContext.fetchFromHTML() to convert an HTML table into a jOOQ Result |
#4914 | Add support for CREATE UNIQUE INDEX |
#4915 | Add UniqueKey.isPrimary() |
#4916 | Implement Key.equals() and hashCode() for all Key types |
#4918 | Add Key.constraint() and improve Key.toString() accordingly |
#4931 | Add a section to the manual explaining the use of dynamic SQL |
#4936 | Add support for CREATE TABLE IF NOT EXISTS |
#4952 | Add flag to turn off generation of database links |
#4954 | Add flag to turn off generation of queues |
#4967 | Add support for CREATE VIEW IF NOT EXISTS |
#4968 | Add support for CREATE [ UNIQUE ] INDEX IF NOT EXISTS |
#4969 | Add support for CREATE SEQUENCE IF NOT EXISTS |
#4974 | Add ExecuteListener to jOOQ-meta logging a warning when queries take longer than 5s |
#4991 | Deprecate Param.setValue(), setConverted(), setInline() |
#4997 | Add DSL.recordType(Field<?>[]) |
#4999 | Add StopWatch.splitXXX(message, threshold) to log a message only if a threshold has been passed |
#5009 | Generate the JPA GeneratedValue annotation on identity columns |
#5011 | Add mergeInto(Table).columns(...).values(...) as an alternative syntax for H2's MERGE |
#5012 | Add CompletionStage<Result<R>> ResultQuery.fetchAsync() and fetchAsync(Executor) |
#5014 | Add Query.executeAsync() and executeAsync(Executor) |
#5015 | Add DBMS_AQ.dequeueStream() to create an Oracle AQ Stream |
#5016 | Add DBMS_AQ.dequeueIterable() to create an Oracle AQ Iterable |
#5021 | Add DBMS_AQ.dequeueAsync() to create an Oracle AQ CompletionStage |
#5022 | Clarify fetch() Javadoc with respect to nullable results |
#5038 | Add an example to the manual showing how to use the maven ant plugin |
#5040 | Add a new ExecutorProvider Configuration.executorProvider() SPI for asynchronous tasks |
#5046 | Issue a warning when Record.field(String) runs into ambiguous columns |
#5055 | Add CreateTableColumnStep.column(Field<?>) for convenience |
#5056 | Add org.jooq.Queries, a wrapper for Query[] |
#5057 | Replace Collection.toArray(new T[size]) calls by Collection.toArray(new T[0]) calls |
#5058 | Add DSLContext.batch(Queries) and other overloads where Query[] or Collection<? extends Query> are accepted |
#5059 | Add CreateTableColumnStep.columns(Field<?>...) |
#5061 | Improve formatting of DDL statements |
#5064 | Improve formatting for MySQL's ON DUPLICATE KEY UPDATE clause |
#5065 | Make all internal classes final if they're not intended for extension |
#5066 | Add CreateTableColumnStep.column(Name, DataType<?>) |
#5067 | Add AlterTableStep.alter[Column](Name), add[Column](Name), drop[Column](Name) |
#5072 | Add default implementations for SPIs, accepting functional event handlers |
#5077 | Add more examples for using RVE IN predicates |
#5081 | Add support for ALTER TABLE .. RENAME TO .. |
#5082 | Add support for ALTER TABLE .. RENAME COLUMN .. TO .. |
#5086 | Add support for ALTER TABLE .. RENAME CONSTRAINT .. TO .. |
#5093 | Implement INSERT .. ON DUPLICATE KEY IGNORE using INSERT .. ON CONFLICT in PostgreSQL 9.5 also when using SQLDialect.POSTGRES |
#5105 | DEBUG-Log exceptions in LoggerListener |
#5113 | Remove Vertabelo Plugin from jOOQ-meta-extensions |
#5117 | Overload internal Tools.field(T) method with concrete T types |
#5118 | Log error in JDBCUtils.safeFree() methods, in case of ignored exception |
#5122 | Improve Javadoc for Loader.loadArrays() |
#5123 | Add LoaderSourceStep.loadArrays(Stream<? extends Object[]>) and loadRecords(Stream<? extends Record>) |
#5124 | Add a chapter to the manual about case-insensitivity (e.g. in filtering, grouping, sorting) |
#5144 | Improve CASE expression formatting |
#5145 | Add LoaderXXXStep.fields(FieldMapper) for better mapping between source and target fields |
#5154 | Add support for mapping Record1<String> to Enum by Enum.valueOf() in DefaultRecordMapper |
#5161 | Add logback.xml file to jOOQ-spring-boot-example to enable DEBUG logging per default |
#5163 | Add UpdatableRecord.refresh(Collection<? extends Field<?>>), store(Collection), insert(Collection), update(Collection) |
#5164 | Implement BindingSetStatementContext.toString() for improved debugging |
#5190 | Support UPDATE and DELETE RETURNING for Oracle using PL/SQL RETURNING .. INTO |
#5192 | Add SafeVarargs annotation to DSL.values() constructor methods |
Breaking changes
#3323 | Make QueryPartInternal.toSQL() and bind() final in favour of the new accept() method |
#4388 | Compilation errors when applying <customType/> for PostgreSQL array types |
#4650 | Collect bind variables while generating SQL, instead of traversing the AST twice |
#4658 | Let DSL.zero(), one(), two() return Param instead of Field |
#4815 | Relax bound from <R extends TableRecord<R>> to <R extends Record> for DSLContext.loadInto() |
Bug Fixes
#2549 | SQLDialectNotSupportedException when calling DSL.val(EnumType) |
#2995 | INSERT INTO table SELECT ... renders bad SQL when column names are omitted and a plain SQL table is given |
#3225 | Performance bottleneck in MetaFieldProvider when fetching unknown plain SQL fields |
#3354 | Fix manual's sections about plain SQL. Avoid referencing to toSQL() and bind() directly |
#3935 | InternalVisitListener accounts for a lot of CPU load |
#4131 | DSLContext.extractBindValues(QueryPart) doesn't report the implicit bind values from plain SQL QueryParts |
#4427 | ScalaGenerator generates Java code for MySQL / PostgreSQL enum types |
#4624 | Compilation error in generated code when column is of type "TIMESTAMP WITH TIME ZONE" in Oracle |
#4626 | Zero-length DAO source files generated for non-updatable tables |
#4634 | Significant CPU overhead in CursorImpl$CursorIterator#fetchOne() due to frequent HashMap access |
#4637 | Regression in Table.onKey(ForeignKey) with multiple joins |
#4638 | Misleading ReferenceImpl.toString() implementation |
#4642 | Significant schema mapping initialisation overhead when schema mapping isn't even used |
#4646 | Significant overhead from Scope.data() Map access |
#4651 | Significant overhead caused by AbstractContext's internal ArrayDeque stacks that created even if there are no VisitListeners |
#4659 | Significant overhead caused by type lookup when using DSL.val(T) or DSL.inline(T) in org.jooq.impl.Limit |
#4664 | Inefficent initialisation of SortFieldList and other QueryPartLists |
#4668 | Significant overhead caused by check if FROM clause is needed |
#4672 | Too many context objects are created when generating SQL |
#4678 | Plain SQL version SelectJoinStep.straightJoin() is missing @PlainSQL annotation |
#4680 | Manual 3.6+ makes use of deprecated fieldByName() and tableByName() methods |
#4682 | Code generation for Postgres DBs assumes column data type to be in same schema as table |
#4685 | Manual's "More info about how to read this manual" always refers to 3.4 version of the manual |
#4686 | Incomplete overloading of SelectJoinStep.straightJoin() |
#4692 | Use correct term for "ordered-set aggregate function" in Javadoc and manual |
#4708 | Wrong enum type referenced from UDT, when the same enum type exists in different schemas in PostgreSQL |
#4712 | Cannot call standalone PostgreSQL function with enum array return type in non-public schema |
#4737 | Documentation bug: Deprecation remark on fieldByName(Class, String...) points to wrong substitute |
#4740 | ClassCastException when using DSL.any() in a Condition Field |
#4744 | Record getter and setter names are generated with Mode.DEFAULT rather than Mode.Record |
#4749 | Regression in AbstractParam throwing StackOverflowError when calling UDTRecord.toString() |
#4755 | Manual typo. Manual still referring to "T_" prefix in tables |
#4762 | org.jooq.Meta must not cache DatabaseMetaData in order not to violate the ConnectionProvider contract |
#4771 | Confusing SQLDialectNotSupportedException when passing wrong arguments to DSL.nvl() function, and others |
#4772 | Extremely slow mapping Record.into(ProxyableInterface.class) |
#4773 | DefaultRecordMapper is not thread safe when mapping proxyable interface |
#4780 | OracleDSL.DBMS_AQ.enqueue() and dequeue() produce wrong syntax depending on parameters that are passed |
#4782 | OracleDSL.DBMS_AQ.dequeue() does not return any MESSAGE_PROPERTIES_T values |
#4783 | Unnecessary SQL exception logged in code generator |
#4798 | Manual typo: Update returning doesn't return update count |
#4800 | Oracle Functions accepting returning PL/SQL-only types are not "SQL usable" |
#4802 | Oracle views with dollar sign '$' in them are not generated |
#4806 | CREATE VIEW statement fails when it contains bind variables |
#4820 | Oracle LONG and LONG RAW columns cause "Stream has already been closed" exception when not placed in first position |
#4829 | Generated convenience methods Routines.f() have misleading Javadoc |
#4840 | <types/> is a regular expression. The manual should make an indication about this |
#4843 | Missing @Support annotations for Vertica and window functions and other API elements |
#4849 | Wrong emulation of SINH() and other hyperbolic functions for Vertica |
#4851 | Wrong emulation of bitwise XOR for Vertica |
#4863 | Manual section about importing CSV erroneously refers to AUTHOR table rather than BOOK table |
#4870 | SQLDialect.POSTGRES_x_x Javadoc is wrong |
#4880 | Escaped block comment inside of Scaladoc causes compilation error |
#4883 | Table valued functions generate bad Scala code |
#4890 | Typo in doc, part "3.4.4. Using jOOQ with Flyway" |
#4910 | Bad SQL generated for CREATE TABLE AS SELECT .. FROM (SELECT ..) in SQL Server |
#4920 | Generated functions without parameter names produce malformed SQL |
#4922 | A negligible amount of CPU is spent in String.indexOf() because of identifier escaping |
#4926 | A small amount of CPU time is wasted on Operator.name().toLowerCase() |
#4935 | Convert.convert(long, Instant.class) shouldn't pass by LocalDateTime |
#4939 | SQLFeatureNotSupportedException thrown in some (unsupported) SQLDialects when initalizing MetaDataFieldProvider |
#4953 | Very slow code generation in Oracle when existing DB Links are not available |
#4955 | ClassCastException when applying schema mapping on procedures and types in Oracle |
#4957 | NullPointerException in ArrayRecord.toString() when ArrayRecord is not attached |
#4964 | Type handling issue when using a custom type with a Postgres UDT field |
#4966 | Standalone calls to Oracle pipelined functions aren't possible |
#4970 | PostgreSQL code generation does not stably order overloaded routines |
#4976 | jOOQ's internals should not call QueryPartInternal.accept(Context), but Context.visit(QueryPart) instead. |
#4977 | HSQLDB does not support bind variables in DDL statements |
#4981 | Wrong SQL generated for CREATE TABLE .. AS SELECT in HSQLDB |
#4985 | Utils.executeImmediate() doesn't work when inlined SQL contains apostrophes |
#4992 | Support for emulating VALUES clauses in H2 is inefficient |
#4996 | DateAsTimestampBinding doesn't work as documented in the manual |
#5004 | Misleading Javadoc on DSL.table(String) |
#5010 | Remove push tag from repository |
#5017 | NullPointerException when using MockConnection with DSLContext.transaction() |
#5024 | Wrong implementation of internal SortFieldList.nulls() |
#5028 | Slow routine overload index calculation in PostgreSQL's code generator |
#5042 | Record[N].values(T1, T2, ..., TN) is not implemented |
#5051 | TableAlias does not delegate getIdentity(), getPrimaryKey(), getKeys(), getRecordVersion(), getRecordTimestamp() calls to aliased table |
#5068 | SQL Server 2008 SELECT DISTINCT .. LIMIT .. OFFSET emulation does not keep ORDER BY semantics in complex queries |
#5088 | Bad deserialisation of PostgreSQL UDTs that contain boolean attributes |
#5089 | Wrong SQL generated for multi row INSERT when ON DUPLICATE KEY IGNORE is emulated |
#5095 | ScalaGenerator produces an invalid import expression for SQL array types |
#5097 | Table.getPrimaryKey() does not work with SQLite's Xerial JDBC driver, when primary key column contains upper-case characters |
#5103 | Tables referencing object arrays generate Record array in POJOs, rather than POJO array |
#5104 | Bad HTML in ExecuteListener.outStart() Javadoc |
#5106 | Result.formatXXX() methods should flush Writers to prevent data loss |
#5128 | Don't generate javax.validation.NotNull for defaulted columns |
#5134 | OracleConnection Class not found when jOOQ runs in OSGi and ARRAY types are bound |
#5140 | DSL.currentTimestamp() cannot be used as a default value for a column, via alterTable |
#5150 | Settings.backslashEscaping is not applied to LIKE .. ESCAPE clause |
#5158 | FILTER (WHERE ...) and OVER() is not applied to PostgreSQL ARRAY_AGG() |
#5167 | Possible NPE when calling InsertImpl.set(Field, Select) with a null Select |
#5174 | NullPointerException when calling Query.getSQL() on an unattached Query |
#5180 | DefaultBindings for OffsetTime and OffsetDateTime handle negative offsets |
#5182 | Meta Table.getKeys() returns an empty list containing "null", if a table has no primary key |
#5186 | Excessive log level when ignoring foreign key referencing an out-of-scope schema |
#5193 | PostgreSQL timestamp deserialisation loses millisecond precision, when timestamp is contained in an array of composite types |
#5202 | MySQL unsigned data types in stored procedures and functions are not captured correctly by jOOQ's code generator |
#5212 | MetaDataFieldProvider should not catch SQLFeatureNotSupportedException from ResultSetMetaData calls |
#5225 | Results.clear() does not remove update counts |
Version 3.7.0 - October 8, 2015
jOOQ 3.7 means Java 8
This release is great news for all of you working with Java 8. From jOOQ 3.7 onwards, we officially support Java 8 and its new APIs, including Stream, Optional, FunctionalInterface, as well as Java 7 features like AutoCloseable, SafeVarargs, and many more. The newly introduced Stream type is a very suitable match for a JDBC ResultSet, or a jOOQ Cursor, given that jOOQ already knows all the type information on individual streaming elements.The new paradigm that has reached the JDK with Java 8 is functional programming. SQL and functional programming are a perfect match for data-driven algorithms that aim for transforming values with functions. We've blogged about this in the past:
- https://blog.jooq.org/java-8-friday-no-more-need-for-orms/
- https://blog.jooq.org/java-8-friday-more-functional-relational-transformation/
If you're still on an older version of Java, we'll continue supporting Java 6 for our commercial customers, where we offer a Java 6 build and a Java 8 build.
jOOQ 3.7 means even more Big Data: Azure, Redshift, Vertica
SQL is the language of Big Data. When you have billions of rows in your table, a column store might seem more suitable than a row store ("NewSQL"), and with SQL, you can optimally query, transform, and aggregate your data. jOOQ fits this model perfectly!jOOQ 3.6 added support for SAP HANA. jOOQ 3.7 now also adds support for SQL Azure, Redshift, and Vertica. With these additions, jOOQ is the best choic for your Java / Big Data application.
jOOQ 3.7 adds support for PostgreSQL 9.5
PostgreSQL is advancing fast. We've now added support for their next major release, which includes GROUPING SETS, UPSERT, SKIP LOCKED, ROW UPDATES and many other featuresOther minor improvements
As always, the convenience of the jOOQ API has greatly increased, having added new overloads for popular methods as well as new access paths to existing functionality.We've also added support for new JOIN types, such as LEFT SEMI JOIN (EXISTS), LEFT ANTI JOIN (NOT EXISTS), or MySQL's STRAIGHT_JOIN syntax.
Writing PL/SQL? Working with TABLE and OBJECT types has now gotten even simpler, and we've also added support for Oracle database links.
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.6-3.7
Features and Improvements
#659 | Add support for SQL Azure |
#1206 | Add Table.leftAntiJoin(Table).on(...) and Table.leftSemiJoin(Table).on(...) to simplify usage of [NOT] EXISTS / IN |
#1350 | Add support for the VERTICA database |
#1364 | Generate toString() on POJOs |
#1503 | Emulate INSERT .. ON DUPLICATE KEY IGNORE in remaining dialects, using INSERT .. SELECT WHERE NOT EXISTS |
#1711 | Add <K, V> Map<K, List<V>> ResultQuery.fetchGroups(Class<K>, Class<V>) and many others |
#1843 | Add section to the manual showing how to use jOOQ with JPA native query |
#2728 | Add support for Amazon Redshift |
#2920 | Emulate CROSS APPLY as LATERAL JOIN for PostgreSQL |
#3082 | Let generated POJOs reference Java array types, instead of ArrayRecords |
#3645 | Let jOOQ require Java 8 - Keep supporting Java 6 in commercial editions |
#3772 | Publish manual also in EPUB format |
#3783 | Add Field<String> DSL.currentSchema() |
#3887 | Support SAP HANA UPSERT |
#3955 | Add a flag to DefaultTransactionProvider to disable the support for nested transactions via savepoints |
#4006 | Add <T> Field<T[]> array(Field<T>...) |
#4016 | Add support for the SQL Standard NTH_VALUE window function |
#4113 | Add Field<?>[] { Cursor | Record | RecordType | Result | Row | TableLike | UDT }.fields( { Field<?>... | int... | String... } ) for convenience |
#4133 | Add table name to formatJSON(), formatXML() export formats |
#4212 | Add LoaderSourceStep.loadRecords(Iterable<? extends Record>) |
#4218 | Add LoaderSourceStep.loadArrays(Iterable<? extends Object[]>) |
#4222 | Generate a Links.java file containing org.jooq.Link references |
#4239 | Add Result.formatCSV(boolean) (and related convenience methods) to avoid header |
#4252 | Provide an out-of-the-box mapping between jOOQ's SQLDialect and Spring dialect names |
#4253 | Provide an out-of-the-box mapping between jOOQ's SQLDialect and Hibernate dialect names |
#4254 | Add support for default routine parameters in PostgreSQL |
#4255 | Add the PostgreSQL VOID data type |
#4271 | Add implicit ScalaResultQuery type to add additional functionality to ResultQuery for Scala users |
#4272 | Add missing <E> E ResultQuery.fetchAny(RecordMapper<? super R, E>) |
#4273 | Add implicit ScalaDSLContext type to add additional functionality to DSLContext for Scala users |
#4275 | Remove VisitListener's "experimental" disclaimer from Javadocs |
#4281 | Add support for MySQL's STRAIGHT_JOIN |
#4283 | Plain SQL queries should read the ResultSetMetaData.getTableName() property if it is available, and produce DSL.field(Name) for better disambiguation |
#4284 | Add { Cursor | Record | RecordType | Result | Row | TableLike | UDT }.field(Name) to extract qualified fields from a row type |
#4299 | Add support for PostgreSQL 9.5 |
#4304 | Add support for INTERSECT ALL, EXCEPT ALL clauses |
#4305 | Add support for the PostgreSQL ROWS FROM () clause |
#4307 | Add an example using the Spark Framework |
#4312 | Add various fetchOptional() methods |
#4336 | Let Cursor and Query extend AutoCloseable |
#4337 | Add Stream<R> ResultQuery.stream() |
#4338 | Add support for java.time |
#4339 | Add DSLContext.fetchStream(...) similar to the existing DSLContext.fetchLazy(...) API |
#4340 | Add Cursor.stream() |
#4363 | Replace using the term "simulate" by "emulate" in all documentation |
#4365 | Document ALTER TABLE .. ADD CONSTRAINT statement in the manual |
#4366 | Add on(Boolean), where(Boolean), having(Boolean), etc. |
#4376 | Translate INSERT .. ON DUPLICATE KEY IGNORE to SQLite's INSERT OR IGNORE |
#4379 | Upgrade Scala dependency from 2.10.4 to 2.10.5 |
#4380 | Make dialect-specific DSL constructors protected to allow further subtyping |
#4398 | Add "t" and "f" to org.jooq.tools.Convert's TRUE_VALUES and FALSE_VALUES |
#4407 | Moved jOOQ Spring Boot to dedicated configuration class. |
#4408 | Document escaping of curly braces in plain SQL templates |
#4413 | Explain in the manual why LIMIT .. OFFSET emulation for Oracle uses ROWNUM instead of ROW_NUMBER() OVER() |
#4416 | Add a remark to the VisitListener Javadoc that implementors should be wary of performance implications |
#4421 | Create sample data for manual sample database |
#4422 | Update jOOQ 3.7 manual and use try-with-resources statements instead of explicit close() calls |
#4424 | Use ArrayDeque as a stack, internally, instead of java.util.Stack |
#4426 | Add <T> T DSLContext.fetchValue(TableField<?, T> field) |
#4431 | Add an about file to the deliverable and to the manual, as specified in the transfer of rights agreement |
#4432 | Add support for java.time in Convert |
#4438 | Add support for CUBRID's { CREATE | DROP } SERIAL statement |
#4443 | Add support for DROP { TABLE | VIEW } IF EXISTS in CUBRID |
#4450 | Add support for ALTER TABLE MODIFY in CUBRID |
#4451 | Add DSLContext.fetchFromCSV(boolean) to allow for fetching header-less CSV data |
#4456 | Implement Table.field(x).getDataType().nullable() for tables obtained via org.jooq.Meta |
#4458 | Add support for Oracle DB links via Table.at(Link), Table.at(Name), Table.at(String) |
#4463 | Add support for passing ROW value expressions to ROLLUP(), CUBE(), and GROUPING SETS() |
#4464 | Emulate H2's MERGE statement for PostgreSQL 9.5 |
#4465 | Add new FieldOrRow type to provide a common super-type for Field<?> and Row |
#4470 | Add <springAnnotations/> code generation configuration to generate Spring annotations on select objects |
#4475 | Add UpdateSetFirstStep.set(RowN, Select<?>) |
#4476 | Issue a warning when Record.field(Field) runs into ambiguous columns |
#4479 | DSLContext should implement AutoCloseable, in case it was constructed via DSL.using(String) |
#4489 | Upgrade Hibernate dependency in jOOQ-meta-extensions to 5.0 |
#4502 | Add org.jooq.Results extends List<Result<Record>> and return this type on fetchMany() calls |
#4505 | Add Maven plugin skip property |
#4508 | Add DSL.condition(Map<Field<?>, ?>) to construct a predicate from a field=>value map |
#4511 | Log a warning when a user accidentally sets the fetchSize with autoCommit == true in PostgreSQL |
#4515 | Emulate POSITION() with INSTR() in SQLite |
#4523 | Add the @SafeVarargs annotation to all methods taking Field<T>... and similar arguments |
#4524 | Add missing DSL.field(String, DataType, QueryPart...) method |
#4530 | Add support for boolAnd(Condition), boolAnd(Field<Boolean>), boolOr(Condition), boolOr(Field<Boolean>) |
#4535 | Make existing join() a synonym for a new innerJoin() method |
#4536 | Make existing { left | right } OuterJoin() a synonym for a new { left | right }Join() method |
#4537 | Let GenerationTool accept multiple argument configurations |
#4538 | Add Constants.XSD_EXPORT and NS_EXPORT |
#4552 | Add DSLContext.connection(ConnectionRunnable) |
#4553 | Add @FunctionalInterface annotation to all relevant callback types |
#4555 | Ensure batches are sent |
#4562 | Do not escape dot in table names during code generation, but use capital case after it |
#4565 | Add Optional support to org.jooq.tools.Convert |
#4566 | Let ArrayRecord<E> extend List<E> |
#4587 | Add Schema ArrayRecord.getSchema() |
#4591 | .zip deliverable should contain a project folder inside of the .zip file |
#4594 | Add DSLContext.query(SQL) etc |
#4597 | Log warning when <forcedType/> doesn't have any matching SQLDataType or <customType/> |
#4600 | Add support for plain SQL APIs via Scala string interpolation |
Breaking changes
#4326 | CREATE SEQUENCE statement lets sequences start with MIN_VALUE, not 1 in Derby |
#4423 | Relax type constraint of DSL.shl() and DSL.shr() |
#4459 | Result.formatHTML() doesn't escape HTML content, which might produce XSS vulnerabilities |
#4488 | Relax bound on <T> for Table.getIdentity() from <? extends Number> to <?> |
Bug Fixes
#2364 | Multi-Result queries may mix ResultSets with update counts. jOOQ doesn't correctly check both in fetchMany() |
#2529 | Cannot combine INSERT .. SELECT with INSERT .. ON DUPLICATE KEY .. due to DSL API flaw |
#2870 | TableOnStep.onKey() generates wrong join condition when left-hand side contains aliases |
#3707 | UDTRecord.toString() doesn't correctly serialise attribute values |
#3779 | Cannot combine INSERT ... SELECT with RETURNING |
#4162 | Malformed record literal when using PostgreSQL array of user-defined types |
#4224 | ORA-00904: "SYS"."ALL_PROCEDURES"."OBJECT_ID": invalid identifier when using the code generator with Oracle 10g |
#4225 | ScalaGenerator logs that it generates XXX.java files |
#4227 | ScalaGenerator should have its own list of reserved words |
#4229 | ScalaGenerator generates unneeded imports |
#4235 | JDBCDatabase calls Meta.getPrimaryKeys() for all schemas, not just for input schemas |
#4236 | Compilation error in compiled code when column is called "null" |
#4240 | JDBCDatabase fetches tables from all schemas, not just from input schemas |
#4246 | HANADataType isn't initialised in SQLDataType's static initialiser block |
#4248 | daoImplements option in MatcherStrategy not generating an implements statement in DAO class |
#4258 | Bad SQL generated for quantified row value expression predicates in Oracle |
#4262 | Manual tutorial should import java.sql.*; |
#4268 | INSERT .. VALUES clause should be rendered on a new line when rendering formatted SQL |
#4269 | No columns generated for PostgreSQL SETOF [ scalar type ] |
#4280 | Document MySQL connector's fetchSize behaviour in ResultQuery.fetchSize() |
#4286 | Manual SQL vs. jOOQ code example are not equivalent |
#4287 | Remove unused import org.jooq.Row in generated records |
#4290 | DefaultTransactionProvider should not cache Connection instance |
#4291 | Add HANA to manual documentation page about DUAL |
#4292 | Wrong emulation of "grand total" GROUP BY () clause in dialects that do not natively support them |
#4295 | Common Table Expression declarations don't set the Context.subquery() flag |
#4300 | DROP SEQUENCE IF EXISTS implemented incorrectly in Sybase SQL Anywhere |
#4306 | ArrayRecord doesn't correctly implement runtime schema mapping for Oracle |
#4308 | SQLSERVER2014 dialect doesn't generate correct LIMIT .. OFFSET clause |
#4313 | NullPointerException in code generator when bypassing GenerationTool without initialising all Lists and String[] to empty objects in Database |
#4314 | SQL Server UPDATE .. FROM illegally declares aliased tables in UPDATE clause |
#4321 | Invalid SQL generated when using nullable data types in Derby CREATE TABLE and ALTER TABLE statements |
#4324 | DROP SEQUENCE statement has a mandatory RESTRICT keyword in Derby |
#4328 | Bad implementation of ALTER TABLE .. ALTER COLUMN .. SET DATA TYPE in Derby |
#4331 | REFERENCES .. ON { DELETE | UPDATE } SET DEFAULT is currently not supported by Derby |
#4333 | Firebird CREATE TABLE regression when columns are nullable |
#4335 | Missing @Support for Firebird for CREATE TABLE statements |
#4341 | No Results are fetched from SQL Server procedures that contain update counts |
#4344 | MockStatement returns wrong update counts |
#4347 | Bad code generated for OBJECT type referencing OBJECT type from different schema |
#4348 | Missing documentation for <schemaVersionProvider/> |
#4349 | The trial / pro license is accidentally delivered with the Open Source Edition |
#4354 | Javadoc warning generated for Result.into(Field<T1>, Field<T2>, ..., Field<TN>) |
#4355 | Regression with <schemaVersionProvider/> caused by formatting of @Generated annotation |
#4358 | Wrong @Support value for SQLite which doesn't support ALTER TABLE .. DROP, SET, ADD CONSTRAINT, etc. |
#4360 | DSL.timestamp() generates wrong output in SQLite |
#4367 | Wrong implementation of MergeImpl.andNot(Field<Boolean>) and orNot(Field<Boolean>) |
#4372 | UDTRecord is not "attached" when fetched from standalone stored function call |
#4381 | No enums generated in MySQL when <forcedType/> contains <types/> matcher |
#4385 | Missing @Support annotation in MySQLDSL |
#4391 | Example exception translator should only translate SQLException |
#4399 | DSLContext.meta().getTables() returns empty fields list for table that are not in the current schema in MySQL |
#4406 | Manual refers to bad list of supported RDBMS |
#4409 | Bad syntax generated for MySQL's ALTER TABLE .. SET DEFAULT statement |
#4412 | Manual section about custom data type binding contains bad link |
#4417 | Typo in some plain SQL query part Javadocs |
#4428 | DELETE .. RETURNING is unavailable without WHERE |
#4430 | Fix routine parameter code generation for types with a binding |
#4437 | Row value expression IN predicate fails with empty rows collection |
#4440 | fetchMany() doesn't work with CUBRID |
#4447 | Empty GROUP BY () clause emulation fails in CUBRID |
#4466 | Missing CAST() in DSL.dateAdd() when the whole expression is wrapped in a cast |
#4471 | Record.getValue(Field) returns wrong value if ambiguous column names are contained in the record, and the schema name is not present in the argument |
#4481 | Missing parentheses when DSL.dateDiff(d1, d2) or timestampDiff(d1, d2) renders "d1 - d2" |
#4490 | Record not attached to Configuration yet, when RecordListener.exception() is called. |
#4494 | getSQL() method not available in CustomField.bind() as documented in the manual |
#4506 | Wrapping condition as field should produce parentheses |
#4510 | Manual typo. Local variable does not exist |
#4526 | ScalaGenerator generates broken code when using xxxImplements |
#4531 | Generated schema and generated Sequences classes import each other, which generates warnings (unused import) |
#4540 | Performance of org.jooq.impl.Fields.field(Field) could be improved heavily, if checking for identity first |
#4545 | Error generating code for Oracle Package in Oracle 10g |
#4547 | Package is not generated when an exception is thrown |
#4554 | DSLContext#batch(Query) silently discards queries |
#4557 | ExceptionTranslator in spring examples shouldn't use dialect.name() for SQLErrorCodeSQLExceptionTranslator |
#4563 | Incorrect Javadoc on DefaultRecordMapper claims that only public members / methods are considered |
#4569 | Manual refers to deprecated DefaultGenerator |
#4575 | SQL comments with javadoc terminators break generated code |
#4576 | JavaWriter uses regex syntax unsupported in Java <1.8 |
#4579 | Unnecessary log messages when a PostgreSQL database contains tables with multiple inheritance |
#4582 | Ensure that jOOQ internally uses regular expressions that are Java 6 compatible |
#4588 | NullPointerException when a TABLE OF OBJECT contains a NULL object |
#4592 | Improper Restriction of XML External Entity References ('XXE') in XMLasDOMBinding |
#4593 | Improper Resource Shutdown or Release in LoaderImpl |
#4614 | Wrong data type reported on org.jooq.Meta by dialect of a family with multiple dialects |
#4617 | NullPointerException when calling UniqueKey.getReferences() in MySQL |
Version 3.6.0 - April 22, 2015
jOOQ goes Big Data with HANA
We've been working hard to add support for our 18th database dialect: SAP HANA, which is now officially supported by the jOOQ Enterprise Edition. HANA is SAP's excellent Big Data offering, supporting column stores combined with the power of SQL standard OLAP functionality, such as window functions. Integrate HANA into your Java or Scala applications with ease, using jOOQ!
Let's talk Scala
We're glad to welcome an increasingly big jOOQ-for-Scala community, an integration where jOOQ really shines thanks to some advanced Scala language features. In order to help you integrate even better, we've now added the new ScalaGenerator that generates jOOQ meta data classes in Scala, instead of Java
Integrate your code generation with JPA
In the previous release, we've implemented a new XMLDatabase that can load arbitrary XML schema metadata formats (via XSLT). We've taken this a step further using our new jOOQ-meta-extensions artefact, which hosts alternative meta data sources, such as your JPA-annotated classes, or ERD exports.
Speaking of XML
Our XML-in-the-database integration just got better! We're showing you in a couple of example Bindings how to get the most out of your vendor-specific data types, such as XML or JSON - which can be integrated into your jOOQ queries effortlessly!
Let's talk some more DDL
This release also adds support for a couple of additional DDL statements that help you standardise your schema migrations for our 18 RDBMS. The newly supported statements are:
- ALTER TABLE ADD CONSTRAINT (with UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK)
- ALTER TABLE DROP CONSTRAINT
- CREATE TEMPORARY TABLE
SQL 2 jOOQ parser
One year ago, we've added the GUDU Software SQL 2 jOOQ parser with our deliverables. While we still believe that this is an excellent product, we have seen little demand from our users and customers - which is why we no longer ship the parser. You can still download it from GUDU Software.
MULTISET and nested records
While we have published (as promised) some API for nested record support, we're not quite convinced of its design yet. This is why this API is still marked as "experimental". Stay tuned for future releases when we'll take these advanced ORDBMS features one step further.
Tons of new convenience API and bugfixes
jOOQ wouldn't be jOOQ if it wasn't for the myriad convenience methods that make your SQL integration lives so much easier. We've listened to our users and customers and added another bulk of useful fetch(), execute(), map() and many other convenience methods that make your SQL integration fun and efficient.
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.5-3.6
Features and improvements
#231 | Add BlobBinding and ClobBinding to use java.sql.Blob and java.sql.Clob on a JDBC level |
#584 | Add a XMLasDOMBinding that can be used to bind SQLXML data types to org.w3c.dom.Node |
#1363 | Generate a copy constructor for POJOs |
#1391 | Add support for the Postgres "every" aggregate function |
#1464 | Allow for a plugin architecture in jooq-meta, jooq-codegen, for custom schema-sources and generation-targets |
#2221 | The manual's section about "Reusing a Query's PreparedStatement" does not mention what the behaviour is, when the underlying Connection is closed |
#2498 | Add support for SQL Standard PERCENTILE_CONT() and PERCENTILE_DISC() inverse distribution functions |
#2626 | Add org.jooq.SQL as a plain SQL type (for templating) |
#2639 | Add stored procedure OUT values to DEBUG log output |
#2664 | Add flag to Loader API to enable batch execution |
#2686 | Add Result.fetchParents(ForeignKey) and Result.fetchChildren(ForeignKey) to fetch relations in a single query |
#2899 | Support generating code based on JPA annotations |
#2905 | Add support for named parameters in BatchBindStep.bind() |
#2919 | Distinguish various PostgreSQL versions in the PostgreSQL family: 9.3, 9.4 |
#2936 | Move .settings, and other Eclipse-related artefacts in a separate place |
#3052 | Add a section to the manual explaining table-valued functions |
#3188 | Add support for LEAD() / LAG() with Row[N] arguments |
#3329 | Support the SQL standard array_agg function |
#3336 | Add code generation flag to enable / disable imports in generated code |
#3338 | Add support for ALTER TABLE ADD CONSTRAINT .. UNIQUE, PRIMARY KEY statements |
#3376 | Add support for PostgreSQL SETOF functions |
#3614 | DefaultRecordMapper only sets declared fields of the target type, no inherited fields |
#3620 | Add section to the manual explaining how to use jOOQ with Nashorn |
#3643 | Ensure that JPA annotations on private members are considered correctly |
#3649 | Support DELETE FROM ... RETURNING |
#3706 | Add a paragraph to the manual explaining how to manually unmarshal code generation Configuration via JAXB |
#3708 | Emit a newline character when performing formatted logging |
#3712 | Add Oracle Spatial examples |
#3717 | Use try-with-resources in manual and tutorial |
#3734 | Implement "$0" as a default expression in matcher strategy rules |
#3744 | Add more precise subtypes for InvalidResultException |
#3748 | Add public Routine T getValue(Parameter<T>) and setValue(Parameter, T) methods |
#3765 | Add support for HANA |
#3781 | Add support for DSL.trunc(date, DatePart) for H2 |
#3784 | Add additional <global[XXX]References/> flags to prevent generation of individual reference classes |
#3797 | For table-valued functions, generate also a static method in Tables.java |
#3800 | jOOQ-Meta should log formatted queries on exception |
#3801 | Add Result#intoMap and Result#intoGroups variants that take field index or field name |
#3808 | Improve manual's section about batching by making it clear that bind() binds records, not individual values |
#3810 | Add fetchOne(RecordMapper) shortcut method to ResultQuery |
#3816 | Use char literals instead of single-character String constants where applicable |
#3819 | Add Constants.XSD_META and Constants.NS_META to describe the new jooq-meta-x.x.xsd |
#3830 | Add support for XSL transformation to XMLDatabase |
#3840 | Add a JavaEE example project with EJB and JSF |
#3842 | Add DSL.field(Name), DSL.table(Name), DSL.schema(Name), DSL.sequence(Name) methods |
#3843 | Deprecate DSL.fieldByName(), DSL.tableByName(), DSL.schemaByName(), DSL.sequenceByName() |
#3844 | Add a new SQLDialect.DEFAULT instead of SQL99 |
#3846 | Let examples work with latest release, not with SNAPSHOTs |
#3847 | Document the fact that Collection<? extends Condition> or Condition[] arguments are always and-connected |
#3848 | Add DSL.dateSub() as a convenience for adding negative dates via DATE_ADD() |
#3849 | Add PostgresDSL.stringToArray(X, Y, Z) support |
#3851 | Add a @PlainSQL annotation to all methods that produce plain SQL objects |
#3853 | Add support for CREATE TEMPORARY TABLE and all related flags |
#3854 | Deprecate DSL.queryPart() in favour of DSL.sql() |
#3865 | Add an example project showing how to use jOOQ with JavaFX |
#3870 | Add support for aggregate FILTER clause |
#3871 | Add support for PostgreSQL 9.4 |
#3872 | Emulate MEDIAN(x) via PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY x) in PostgreSQL 9.4 |
#3873 | Add SQLDialect.predecessor() to establish historic dependencies between SQLDialects |
#3874 | Add a AbstractXMLasObjectBinding that can be used to bind SQLXML data types to JAXB-annotated types |
#3875 | Add support for PostgreSQL 9.4 ordered-set aggregate functions |
#3876 | Add support for SQL Server 2014 |
#3878 | Add R[] ResultQuery.fetchArray() |
#3879 | Rename Result.intoArray() into Result.intoArrays() |
#3882 | Overload JavaGenerator.generateXXX() methods to contain a JavaWriter argument |
#3886 | Add Field<Record[N]> DSL.field(Row[N]) to allow for nesting rows in SELECT clauses |
#3889 | Add DataType.getBinding() |
#3891 | Cache Record Constructor in CursorImpl |
#3894 | Clarify Record.getValue() behaviour in Javadoc |
#3897 | Add support for nested "to-one" POJOs in DefaultRecordMapper |
#3900 | Implement better formatting for nested Records |
#3904 | Add DSL.and(Condition...) / DSL.or(Condition...) |
#3907 | Upgrade Spring version in tutorials / manuals |
#3915 | Calls to Configuration.derive() create a Configuration that indirectly references the previous Configuration instance |
#3928 | Add support for ORA_ROWSCN, SCN_TO_TIMESTAMP() to OracleDSL |
#3931 | Add RenderKeywordStyle.AS_IS |
#3934 | Add StopWatch.split() to get current time |
#3941 | Add additional DSL.param() methods to create unnamed bind value placeholders |
#3956 | Add Configuration set(DataSource) and set(Connection) for convenience |
#3961 | Apply Base64 encoding to binary types when formatting them to XML, JSON, etc. |
#3975 | Add support for bulk insertion in the Loader API |
#3981 | Implement Meta.getTables()[x].getPrimaryKey().getReferences() |
#3983 | Add <T> List DSLContext.fetchValues(TableField) |
#3984 | Implement Meta.getTables()[x].getReferences() |
#3985 | Add support for more PostgreSQL array functions |
#3986 | Add DSL.choose() as a synonym for DSL.decode(), and DSL.when(Field), DSL.when(Condition) as shortcuts |
#3992 | Add <T> DSL.coalesce(Field, T) |
#4004 | Make the manual's version bar at the top a coloured bar |
#4009 | Add <R extends Record> Table DSL.table(R...) |
#4012 | Add new LoaderConfigurationException to indicate bad configurations in Loader API |
#4013 | Add int Loader.executed(), a new counter that counts the number of executed statements |
#4019 | Add system property to remove the logo from the log output |
#4021 | Add a ScalaGenerator |
#4027 | Let INSERT statements default to using DEFAULT VALUES when no values are specified |
#4044 | Add support for ALTER TABLE DROP CONSTRAINT statements |
#4045 | Add AlterTableStep.addColumn() and dropColumn() methods as synonyms for add() and drop() |
#4046 | Add support for ALTER TABLE ADD CONSTRAINT .. FOREIGN KEY statements |
#4047 | Add DSL.deleteFrom() alias for DSL.delete() |
#4048 | Add support for ALTER TABLE ADD CONSTRAINT .. CHECK statements |
#4058 | Mention SimpleFlatMapper from the jOOQ manual |
#4063 | Add DSLContext.truncate(String) convenience method |
#4064 | Add PostgreSQL support for DSLContext.lastId() |
#4071 | Emit a warning when a batch statement doesn't receive the right number of bind values |
#4085 | Add DSL.list(QueryPart...) to allow for creating lists in SQL templates |
#4086 | Add a manual section about Record.into(Table<?>) |
#4097 | Use SQL standard EXTRACT() function also in Oracle |
#4099 | Document how to use Converter and Binding without the code generator |
#4105 | Add an optional, synthetic COLUMNS clause to the INSERT API for convenience |
#4107 | Add Routine.getReturnParameter() |
#4108 | Add ExecuteListener.outStart(ExecuteContext) and outEnd(ExecuteContext) to capture fetching of Routine OUT parameters |
#4110 | Overload DDL API to accept Name instead of String arguments |
#4122 | Log code generation configuration XML only in DEBUG level |
#4125 | Add MockConnectionProvider and MockConfiguration for convenience |
#4126 | Add void DSLContext.mock(MockDataProvider, MockRunnable) and <T> T mockResult(MockDataProvider, MockCallable) |
#4127 | Upgrade embedded jOOR dependency to 0.9.5 |
#4129 | Add support for @javax.persistence.Id |
#4140 | Recognize SQLDroid JDBC URLs in JDBCUtils.dialect(String) |
#4141 | Add support for specifying the encoding when loading CSV or JSON with the Loader API |
#4143 | Add onRow(LoaderRowListener) to the Loader API |
#4144 | Explain the rationale of the transaction examples in the manual |
#4146 | Generate PL/SQL constants |
#4152 | Add <T> Field TableLike.field( { String | int }, { Class, DataType, Field } ) |
#4154 | Link to source code from https://www.jooq.org/java-8-and-sql |
#4174 | Split the manual's section about the INSERT statement in several sections |
#4179 | Add support for MySQL's mandatory ON clause in the DROP INDEX statement |
#4198 | Improve manual section about SQL injection |
#4206 | Add Converter<T, T> Converters.identity(Class) to produce an identity converter |
#4207 | Upgrade Spring Boot version in example to 1.2.3. |
#4215 | Remove Gudu Software's SQL 2 jOOQ Parser from deliverable |
#4216 | Remove obsolete "release" profile from pom.xml files |
#4219 | Implement an instance toString() method on JSONObject |
API changes (backwards-compatible)
API changes (backwards-incompatible)
#3855 | Oracle REAL and FLOAT types cause code generator to produce BigInteger instead of Double types |
#3885 | Add a SelectField marker interface that allows for alternative column expressions in the SELECT clause |
#4106 | Add support for T-SQL optional INTEGER return values from stored procedures |
#4196 | UpdateResultStep is erroneously declared as a subtype of Insert |
Behavioural changes (backwards-incompatible)
#3860 | Allow to specify defaults for all regular expression flags in the code generation configuration. Add CASE_INSENSITIVE to defaults |
#3982 | Empty, OR-connected CombinedConditions should return FALSE, not TRUE |
#4161 | { INSERT | UPDATE | MERGE } .. SET [ Record ] doesn't take changed flags into account |
Bug fixes
#2522 | Codegen Schema mapping doesn't work for UDT |
#2647 | Code generation error when Postgres stored function contains several parameters with the same name |
#3170 | Improve manual's jOOQ examples by always using fetch() or execute() where applicable |
#3255 | DataTypeException: Cannot convert from "" (class java.lang.String) to class [B when casting to MySQL BINARY types |
#3341 | Cannot use ALTER TABLE ADD or CHANGE statements on MySQL for all column data types |
#3378 | Error when fully qualifying PostgreSQL table-valued functions in SELECT clauses |
#3417 | Add documentation about DEFAULT and DEFAULT VALUES to INSERT and UPDATE manual pages |
#3727 | Invalid SQL generated when window definitions from WINDOW clause contain frame clauses |
#3745 | NullPointerException when <jdbc/> is not provided and isn't provided either |
#3778 | PostgreSQL enum array types have to be cast with their fully qualified name |
#3803 | CREATE TABLE statement does not generate NOT NULL constraint |
#3809 | Fix typo in Javadoc in ResultQuery |
#3811 | Potential NullPointerException in Cursor.fetchOne(RecordMapper) and other methods |
#3817 | When used with set operations, ORDER BY must not contain any qualified fields |
#3822 | Invalid SQL for Postgres created with values(Row1...) |
#3824 | PostgreSQL dateAdd() erroneously returns a TIMESTAMP value |
#3831 | <dateAsTimestamp/> deprecation warning is displayed even if the flag is not active |
#3833 | org.jooq.CreateTableAsStep.column(Field<T> field, DataType type) SQLite |
#3835 | SQLite's CREATE VIEW statement doesn't allow to rename columns |
#3838 | Bad @Support annotations on ALTER TABLE statements, which are not supported by SQLite |
#3845 | NullPointerException in code generator when there is an empty <inputSchema/> element in Oracle |
#3850 | Broken link towards 3.5 documentation in 2.6 documentation |
#3861 | Minor manual typo |
#3863 | CSV-Export with delimiter only does not work properly |
#3877 | Generated "fetchBy[ColumnName]" methods in DAOs shouldn't Mode.POJO |
#3880 | Cannot access private JavaGenerator.newJavaWriter() method |
#3888 | Data type conversion fails when using a Binding<byte[], Serializable> and passing a byte[] as user input |
#3899 | Compilation error in generated code when a sequence name ends with $ |
#3905 | LoggerListener and StopWatchListener should be placed after user listeners |
#3909 | Inefficient number to number conversion in org.jooq.tools.Convert |
#3911 | DefaultRecordMapper ignores @ConstructorProperties for property names that don't have a matching getter |
#3919 | Bad caching of JPA-annotated getters leads to wrong mapping into POJOs that have @ConstructorProperties |
#3932 | jooq-runtime-3.5.0.xsd declares wrong namespace |
#3936 | AbstractQuery unnecessarily creates two DefaultRenderContext instances. |
#3940 | Batch statements do not work when queries contain inlined bind variables |
#3944 | AbstractScope creates an excessive amount of HashMaps, internally |
#3946 | Replace ArrayList<ExecuteListener> by ExecuteListener[] in ExecuteListeners to avoid excessive Iterator creation |
#3947 | Avoid creating unnecessary Iterators and ArrayLists in AbstractStore.getAttachables() |
#3954 | Avoid wrapping Field[] in a new RowImpl every time a Record is created |
#3957 | java.lang.NoSuchMethodException: createARRAY when using Oracle arrays with BoneCP |
#3962 | The H2 emulation of SHR might produce rounding errors |
#3966 | Inefficient BIT_COUNT() function for those dialects that do not natively support SHR() |
#3977 | Meta.getTables() also returns entries for indexes for PostgreSQL |
#3987 | The manual refers to a non-existing DSLContent.decode() function, which is really contained in DSL |
#3988 | Incorrect IntelliJ directory listings in .gitignore |
#3993 | ResultQuery.fetchAny() methods Javadoc erroneously claims throwing of InvalidResultException |
#3998 | Cache internal BindingGetResultSetContext instance across a single Cursor |
#4000 | Avoid {ResultSet | CallableStatement | SQLInput).wasNull() calls if not necessary, as they're somewhat expensive on some JDBC drivers |
#4010 | Confusing wording in manual section about org.jooq.Binding |
#4011 | Loader does not call release() when acquiring connections to commit transactions |
#4017 | jooq-meta-3.5.0.xsd is not valid XSD 1.0 |
#4022 | NullPointerException when generating SQLite table with composite primary key |
#4026 | Add a "USE library" command to the manual's tutorial |
#4028 | Loader API's "onDuplicateKeyIgnore()" executes inefficient SELECT |
#4036 | Obsolete remark in RecordListener Javadoc about batch semantics |
#4041 | Bad unnesting of UDT arrays in PostgreSQL |
#4052 | NullPointerException when generating source code for PostgreSQL table-valued function that returns nested arrays |
#4056 | Query.bind(String, Object) binds only to the first occurrence of a named bind value |
#4065 | Exception when loading array results from plain SQL queries into a Record |
#4075 | Bad result from Query.getBindValues() when named Params are repeated |
#4079 | Boolean datatype not handled with MySQL dialect |
#4091 | ORA-01461: can bind a LONG value only for insert into a LONG column, RC=5100 |
#4093 | Typo in Javadoc on DataType.asConvertedDataType() |
#4096 | jooq-meta-3.5.2.xsd doesn't specify the right namespaces |
#4100 | Use "<" for "<" and ">" for ">" in javadoc |
#4101 | Wrong DSL.currentTimestamp() and currentTime() implementations in Oracle |
#4114 | Compilation error when a stored procedure has a parameter named "value" and the generator strategy generates lower case literals |
#4117 | Invalid SQL generated when using UNSIGNED data types with MySQL DDL statements |
#4120 | Invalid SQL generated when using TINYTEXT with MySQL DDL statements |
#4121 | Row value expression IN predicates with subqueries are not formatted correctly |
#4128 | @javax.persistence.Column.name() is case-insensitive |
#4132 | GeneratorStrategy.instanceFields should be true by default |
#4134 | No milliseconds value when reading Timestamp values from SQLite |
#4147 | SQLDialectNotSupportedException: ARRAY TABLE is not supported for SQL99 |
#4151 | FOR UPDATE .. OF doesn't allow qualified column names |
#4156 | Cannot fetch REF CURSOR OUT parameters from Oracle stored procedures when using SQLDialect.ORACLE11G |
#4157 | Package procedures without arguments are not generated in Oracle 12c |
#4160 | SQL generated by DSL.dateAdd() is invalid for certain dates in Oracle |
#4170 | Schema name rendered twice when calling static member procedure in Oracle |
#4173 | NullPointerException when using SQL99 dialect with XMLDatabase for code generation |
#4176 | Wrong @Support value for SQLite which doesn't support DEFAULT in INSERT or UPDATE statements |
#4182 | ArrayIndexOutOfBoundsException in org.jooq.impl.Utils.renderAndBind |
#4185 | ExecuteType.BATCH JavaDoc: not yet supported |
#4187 | SQLite timestamps with trailing fractional zeros are misinterpreted |
#4190 | Generated Record.values() does nothing |
#4193 | Wrong H2 routines generated since recent H2 version |
#4197 | Incomplete Javadoc and @Support annotation on UPDATE .. RETURNING with respect to DB2 emulation |
#4204 | Broken JavaFX example |
Version 3.5.0 - November 21, 2014
The new Binding SPI
The main improvement of this exciting release is the new org.jooq.Binding SPI which can be used to fully control all aspects of a user-type's JDBC interaction. This goes much further than the existing org.jooq.Converter SPI that can be used to map standard JDBC types to user-types. With the new Binding SPI, virtually *ALL* vendor-specific types can be supported now. Examples include PostgreSQL's JSON or HSTORE types, or Oracle's DATE type - which is really incorrectly represented via java.sql.Timestamp, which is why we have retrofitted the existing <dateAsTimestamp/> feature to use such bindings, now.
Stored procedures are everywhere
Stored procedure support was generally improved in this release. This includes lots of new little features and conveniences for use with PL/SQL or Transact-SQL. For instance, jOOQ 3.5.0 now supports cross-schema references of PL/SQL OBJECT and TABLE types, which allows for binding directly to Oracle Spatial. We've blogged about this exciting improvement here: https://blog.jooq.org/painless-access-from-java-to-plsql-procedures-with-jooq/
And while we were at it, we've also added basic support for Oracle AQ, which integrates very nicely with our OBJECT type support!
In Transact-SQL and MySQL, we now support fetching arbitrary numbers of Results from stored procedures, and we've also implemented support for Firebird PSQL, including Firebird's very interesting syntax for table-valued functions.
By the way, we support user-defined aggregate functions for a variety of databases, including Oracle, PostgreSQL, and HSQLDB. Definitely something you should look into!
SQL improvements
In this release, we've finally got support for UNION, INTERSECT, and EXCEPT right with respect to nesting such operations, as well as combining them with ORDER BY and LIMIT .. OFFSET.
Let's talk some more DDL
We've continued to add support for DDL statements, including
- CREATE TABLE
- CREATE TABLE AS SELECT
- CREATE VIEW and DROP VIEW
- CREATE INDEX and DROP INDEX
- CREATE SEQUENCE and DROP SEQUENCE
- DROP .. IF EXISTS
We'll continue to add support for more DDL statements also in the future.
Code generation improvements
We've added support for the new XMLDatabase, a code generation configuration that allows to read meta information from XML formats, e.g. from a standard INFORMATION_SCHEMA.xml, or from an ERD's XML export format: https://blog.jooq.org/importing-your-erd-export-into-jooq/
Future versions of jOOQ will include built-in support for a variety of XML formats.
We've had an awesome contribution by Etienne Studer from Gradleware to help our users integrate the jOOQ code generation with their Gradle builds.
Last but not least: Informix!
Oh, and by the way, we now also support IBM's second most popular database: Informix. Support for this database will be included in the jOOQ Enterprise Edition.
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.4-3.5
Features and improvements
#561 | Add support for the Informix database |
#994 | Add support for the Postgres "hstore" data type |
#1341 | Add DSL.using(String url) and other methods that mimick DriverManager.getConnection() |
#1380 | Generate equals(), hashCode() on POJOs |
#1392 | Add formatInsert() to render insert statements from a Result |
#1410 | Add support for the Postgres "DISTINCT ON" clause |
#1658 | Add support for SQL standard UNION syntax. jOOQ's current understanding of UNION is just convenience |
#1761 | Reference manual versions between each other |
#2054 | Implement quantified comparison predicates for Row[N] row value expressions |
#2155 | Add Converter support to Routines and UDTs |
#2209 | Add <T1, T2, .., T[N]> Result<Record[N]<T1, T2, .., T[N]>> Result.into(Field<T1>, Field<T2>, .., Field<T[N]>) in order to transform Results / Records into another type |
#2289 | Add jOOQ-flyway-example, a documentation module to show how to integrate with Flyway |
#2604 | Add section to the manual explaining how asynchronous querying can be achieved |
#2674 | Add support for stored procedures in MockConnection / MockDataProvider / MockExecuteContext |
#2788 | Add support for the PostgreSQL "json" data type |
#2886 | jooq-codegen-maven should look into project dependencies for jdbc driver |
#2907 | Emulate UPDATE .. RETURNING through SELECT FROM FINAL TABLE (UPDATE ...) in DB2 |
#2925 | Add support for Firebird stored procedures |
#3121 | Skip code re-generation when schema is known to be the same |
#3151 | Add "question mark" with tool-tip to the manual to allow for jumping to the "how to read this manual" section |
#3248 | Add support for Binding (i.e. "Type Providers") |
#3337 | Add support for the CREATE TABLE statement |
#3339 | Add support for CREATE INDEX and DROP INDEX statements |
#3340 | Add support for CREATE VIEW and DROP VIEW statements |
#3346 | Allow for omitting the JDBC driver property in the code generator |
#3355 | Add support for CREATE SEQUENCE and DROP SEQUENCE statements |
#3370 | Allow for overriding the class Javadocs for generated objects |
#3375 | Add support for PostgreSQL table-valued functions |
#3381 | Add support for CREATE TABLE AS statements |
#3386 | Add some test cases using Java 8 Streams for functional-relational transformation |
#3388 | Replace SQL Server's ROW_NUMBER() OVER(ORDER BY @@version) by ORDER BY (SELECT 0) |
#3389 | Add DSLContext.currval(String) and nextval(String) for convenience |
#3412 | Add List DSLContext.fetchValues(...) similar to the existing fetchValue(...) methods |
#3418 | Add DSL.defaultValue(Field<T>) for convenience |
#3425 | Add support for Oracle AQ |
#3431 | Add support for MySQL index hints |
#3435 | Add support for SQL Server's SELECT .. INTO [new table] syntax |
#3442 | Implement MockResultSet.getArray() methods |
#3443 | Add support for conversion of values / arrays to the JDBC Array type in Convert |
#3444 | Add MockArray, a mock implementation of JDBC's Array type |
#3451 | Add XMLDatabase to generate a database schema from an XML file |
#3477 | Add Field.as(Field) to rename a field to another field's name |
#3480 | Add XXXContext.dialect() and XXXContext.family() for convenience |
#3483 | Let <forcedType/>'s <expression/> match both fully qualified column names as well as unqualified column names |
#3495 | Add an example project showing how to use jOOQ's code generator with Gradle |
#3496 | Log a DEBUG message when a Query is executed which returns Query.isExecutable() == false |
#3501 | Add ResultQuery.fetchSet() and Result.intoSet() methods to return LinkedHashSets |
#3506 | Instrument the jOOQ API during integration tests to verify correct application of @Support annotations |
#3511 | Improve DISTINCT predicate emulation through INTERSECT |
#3512 | Add DSL.count(Table<?>) and DSL.countDistinct(Table<?>) to support the PostgreSQL-specific COUNT() extension |
#3513 | Streaming version of formatCSV/formatXML |
#3519 | Document the PostgreSQL JDBC's limitations with respect to large cursors when using Connection.autoCommit = true |
#3525 | Implement more verbose DEBUG logging for jOOQ-meta's include / exclude mechanism |
#3532 | Add support for DROP ... IF EXISTS clauses in DDL |
#3551 | Copy plain SQL query construction API to DSL from DSLContext |
#3557 | Add support for PostgreSQL user-defined aggregate functions |
#3558 | Add Setting to enable / disable fetching of warnings |
#3559 | Propagate jOOQ-codegen's relations flag also to jOOQ-meta, to prevent (possibly expensive) queries to fetch relations |
#3565 | Add XXXContext.settings() for convenience |
#3566 | Add GenerationTool.generate(String) to generate code from an XML string |
#3569 | The <database/> tag is no longer mandatory in the code generator configuration |
#3579 | Emulate nested set operators in databases that don't support them natively |
#3592 | Add Setting to enable Oracle scalar subquery caching for stored function calls |
#3595 | Add MockResult<init>(Record data) convenience constructor |
#3596 | Let code generator empty generated packages on a per-schema basis |
#3597 | Generate table and column comments also for PostgreSQL |
#3598 | If tables define their own comments, don't generate "This class is generated by jOOQ." in Javadocs |
#3599 | Implement nicer formatting of @Generated annotation |
#3600 | Add support for SQL standard SELECT .. WITH CHECK OPTION |
#3610 | Explain the differences between keeping generated sources under version control or not |
#3611 | Add a jOOQ / Nashorn example to the repository |
#3612 | Add an example project showing how to import an ERD export format to the code generator |
#3622 | Add support for Field.in(Result<Record1<T>>) and Row[N].in(Result<RecordN<T1, ..., TN>>) |
#3623 | Add ParamType.NAMED_OR_INLINED to render named parameters only if a name is given |
#3626 | Add Map<S, Result<R>> Result.intoGroups(Table<S>) |
#3627 | Add simplified API for CASE WHEN [ condition ] THEN [ select ] expressions |
#3628 | Add <T> Field<T> DSL.field(Select<? extends Record1<T>>) |
#3633 | Add a section to the manual about jOOQ and NoSQL |
#3638 | Let ResultQuery<R> extend Iterable<R> |
#3644 | Enhance DSL API to work around Nashorn interoperability issue with overloading and varargs |
#3661 | Log some info about the type being matched by a <forcedType/> configuration |
#3667 | <types/> configuration doesn't work for Derby DATE types |
#3668 | Let GenerationTool also search absolute and relative paths |
#3669 | Make the code generator's <database/> element optional |
#3670 | Add DSL.coerce(Object, ...<T>) for convenience |
#3671 | Add alternative DSL.concat() syntax for convenience |
#3672 | Add OracleDSL.toNumber() |
#3677 | Add a paragraph to the manual indicating that the manual is licensed CC-BY-SA 4.0 |
#3678 | Add some JavaBeans-style setters to the DefaultConfiguration to simplify configuration via Spring |
#3680 | Remove all unit tests that make assumptions on how exactly the SQL is rendered |
#3681 | Fetch all result sets from executed stored procedures |
#3688 | Remove the confusing CO_AUTHOR_ID column from the manual |
#3690 | Add a manual page header indicating that a version has gone "end of life" |
#3702 | Add Configuration.family() for convenience and API consistency |
#3740 | Add Table.newRecord() and UDT.newRecord() to construct new records with DefaultConfiguration |
#3746 | Add DSLContext.fetchExists(Select<?>) |
#3752 | Make <jdbc/> element optional in code generation configuration |
#3754 | Explain primitive type conversion in Convert.convert() Javadoc |
#3756 | Regenerate files only if there is a difference |
#3760 | Add Record.intoList() |
#3769 | Add org.jooq.Converters, a chained Converter implementation |
#3773 | Explain jOOQ's understanding of Configuration thread safety in the Configuration Javadoc |
#3775 | Let QueryPart.toString() generate formatted SQL |
#3782 | Add a method to create a org.jooq.util.Database by SQLDialect |
API changes (backwards-compatible)
#3345 | Deprecate org.jooq.api.annotation.State and Transition annotations |
#3356 | Deprecate Select.fetchCount() |
#3703 | Deprecate CastMode.SOME and RenderContext.cast() |
#3770 | Deprecate <dateAsTimestamp/> |
API changes (backwards-incompatible)
Behavioural changes (backwards-incompatible)
#2486 | Allow to specify precision, scale, length for type-rewrites in <forcedType/> |
#3000 | Add Setting to enable MySQL backslash escaping |
#3407 | DDL statements accepting String names should generate quoted names, not plain SQL |
#3541 | Change DSLContext.nextval(String) and currval(String) to internally call DSL.sequenceByName() instead of DSL.sequence() |
Bug fixes
#2080 | Syntax error in rendered SQL when using limit().offset() with aliased projections in SQL Server |
#3206 | DSL.field(Condition) doesn't correctly handle NULLs when emulating boolean fields with a CASE expression |
#3347 | Field.in(T...) should defend against Collection arguments |
#3353 | Manual Javadoc anchors are no longer correct with the recent changes of JDK 8 Javadocs |
#3359 | store() after copy() executes an UPDATE instead of an INSERT, when Settings.updatablePrimaryKeys is set |
#3360 | SQLite regression when using special characters in identifiers |
#3362 | DSLContext.batchStore() executes INSERT if records are batch stores are executed two times in a row on new records, if Settings.updatablePrimaryKeys is set to true |
#3363 | UpdatableRecord.store() executes UPDATE instead of INSERT after delete(), if Settings.updatablePrimaryKeys is set to true |
#3369 | Render CAST(? AS DATE) for java.sql.Timestamp bind values that are bound to Oracle DATE columns |
#3372 | The syntheticPrimaryKeys code generation option is currently undocumented |
#3373 | The manual's page about the DUAL table does not list all the supported databases |
#3382 | NOT NULL constraints and type information are incorrectly generated when using Firebird DOMAINs for data types |
#3390 | Add missing documentation about the new jOOQ 3.4 transaction API |
#3392 | Call setAccessible(true) only if really needed |
#3400 | ALTER TABLE generates invalid syntax on Firebird when data types are nullable |
#3402 | Wrong character length generated by jOOQ for Firebird |
#3408 | Remove the default log4j.xml configuration file from the maven plugin again |
#3413 | Oracle generated ArrayRecords cannot be constructed through reflection if deprecated flag is set to off |
#3420 | NullPointerException when generating code for Oracle AQ Tables |
#3427 | Internal QueryCollectorSignal exception escapes into user code when not dealt with in ExecuteListener |
#3430 | JDBC escape syntax is not correctly rendered from plain SQL when plain SQL contains newlines |
#3436 | Manual sections about transactions documents ctx to be a DSLContext instead of Configuration |
#3437 | QualifiedField does not respect RenderContext.qualify() |
#3445 | Cannot run Maven code generator with professional edition |
#3450 | Backslashes in SQL comments don't get escaped |
#3455 | UPDATE .. FROM statement renders incorrect SQL for derived tables or aliased tables |
#3456 | Name clash in generated code when Routine argument is called "f" (functions) or "p" (procedures) |
#3462 | Field<Object>.in(Object...) can be called with Select<?> arguments, accidentally |
#3463 | Field.in(...) methods shouldn't return trueCondition() or falseCondition() |
#3473 | java.lang.IllegalArgumentException: Field (null) is not contained in Row |
#3488 | Compilation error in generated code, when a similar tables T_A and TA exist |
#3489 | DefaultTransactionProvider does not call Connection.releaseSavepoint(Savepoint) after commit |
#3507 | Bad @Support annotation on Select.intersect() and Select.except() |
#3514 | ResultQuery.fetchLazy() ignores fetchSize() |
#3520 | Duplicate column information in foreign key references for foreign keys that share the same name in different tables |
#3526 | Unnecessary warning logs introduced in code generation |
#3533 | Avoid using named parameters for Oracle, if not really needed |
#3537 | Incorrect call to releaseSavepoint() |
#3542 | Oracle DDL statements do not allow for using bind variables |
#3544 | Add a DDLQuery marker interface, which all DDL Query types should extend |
#3545 | Error when using qualified, case-sensitive sequence names in H2 |
#3547 | DSLContext.batch(String) doesn't accept bind variables |
#3552 | Oracle Stored procedures using type synonyms in signatures cannot be used through jOOQ |
#3556 | Generated Oracle Stored procedures do not reference types from other schemas |
#3560 | Slow discovery of primary keys in very large MySQL databases |
#3567 | Code generator error message refers to wrong XSD |
#3577 | Don't render "empty" OFFSET 0 clauses |
#3578 | Slight manual bug referring to inexistent ExecuteContext.dialect() method |
#3582 | Record.from(Object) does not consider DataType.nullable() which may lead to constraint violations when inserting |
#3586 | Context.paramType() is initially null instead of INDEXED |
#3590 | Manual erroneously claims that the SQL standard allows SELECT without FROM |
#3591 | Compilation error generated in manual's tutorial code |
#3602 | Cannot INSERT into view |
#3608 | Typo in documentation of transaction method |
#3624 | Compilation errors when Converters are applied to generated Routines and UDTs |
#3630 | ArrayOutOfBoundsException when using backslash escaping in MySQL with jOOQ plain SQL |
#3634 | Record.into(Table) maps to the wrong table when passing an aliased table after a self-join |
#3639 | java.lang.NoSuchMethodException: createARRAY when using Oracle arrays with Spring TransactionAwareDataSourceProxy |
#3648 | Use JDBC Escape syntax for MySQL Date / Time literals to circumvent a known MySQL bug |
#3650 | NullPointerException on TableRecord.insert() when primary key information is not present |
#3664 | UNION ALL, ORDER BY, and LIMIT regression |
#3665 | Typos in Javadocs |
#3673 | OracleDSL.toChar() methods shouldn't require String types |
#3682 | PostgreSQL INSERT .. RETURNING doesn't work with plain SQL table |
#3696 | OutOfMemoryError with SQL Azure, caused by long-running loop of consuming further exceptions |
#3705 | The jOOQ "flash log" doesn't display nicely when using java.util.logging |
#3711 | Incorrect code generated for cross-schema OBJECT type references |
#3718 | Exceptions on rollback hide the original exceptions causing the rollback |
#3723 | Add org.jooq.Scope to unify all Configuration, Settings, and data map access in a single API |
#3730 | Cannot use regex COMMENTS in <forcedType/>'s <expression/> |
#3732 | Improve performance of <forcedType/> regex evaluation |
#3733 | Code generator should use CHAR_LENGTH columns for Oracle, instead of DATA_LENGTH |
#3741 | MySQL ResultSet streaming conflicts with internal SHOW WARNINGS call |
#3758 | ExecuteListener.warning() is not listed as a method in the Javadoc |
#3762 | Bad emulation of DUAL table in HSQLDB when connecting with a DBA user on a database with more than one user |
#3792 | Code generator erroneously refers to "singleton instances" of tables in generated Javadoc |
Version 3.4.0 - June 20, 2014
With this awesome new minor release version, we have finally started supporting a couple of very important aspects of the SQL language:
- Common table expressions
- Transactions
- DDL
Common table expressions have been missing from jOOQ for a long time, and they're now finally part of our DSL API, both for recursive or regular usage.
Transactions are handled very nicely in JavaEE or through Spring TX. But if you're running small standalone programs with JDBC (and jOOQ) only, you have to resort to a transaction API that is no longer contemporay. With jOOQ 3.4, we're now shipping a Java-8 ready transaction API and a default implementation backed by JDBC transactions. Our manual also contains an example implementation that is backed by Spring TX. While we do not want to compete with popular transaction models, we do want to provide a simple, functional-interface oriented API to apply transactions in client code.
DDL is very hard to standardise across databases, and with jOOQ 3.4, we have now started adding type safe support for some DDL statements, including thus far:
- ALTER SEQUENCE
- ALTER TABLE
We're going to be adding support for more DDL statements in jOOQ 3.5 as part of our more general DDL support strategy.
Apart from that, there is a tremendous amount of minor improvements. See below for details:
API Diff:
See what's changed in terms of an API diff here: https://www.jooq.org/api-diff/3.3-3.4
Features and improvements
#454 | Add support for CTE (Common Table Expressions / WITH-clause) |
#682 | Mavenise jooq-test |
#883 | Add support for DDL statements |
#1061 | Support "DEFAULT" keyword in INSERT and UPDATE statements |
#2573 | Generate DAOs for tables with composite primary keys |
#2646 | SQL Server error "The text, ntext, and image data types cannot be compared or sorted" when using LIMIT with a SELECT [text, image] statement |
#2675 | Add test to verify if jOOQ correctly binds NULL values with the right JDBC type in batch INSERT operations |
#2694 | Unify RenderContext and BindContext traversal |
#3010 | Generate POJOs for Oracle and PostgreSQL UDTs |
#3016 | Adapt manual to recommend also other popular connection pools |
#3030 | Add support for ALTER SEQUENCE ... RESTART [ WITH ... ] |
#3075 | Add support for Oracle TEMPORARY tables |
#3076 | Add ExecuteListener.warning(ExecuteContext) to allow for listening to SQLWarnings |
#3077 | Let Sequence implement QueryPart |
#3080 | Generate Interfaces for Oracle and PostgreSQL UDTs |
#3081 | Let generated POJOs reference generated UDT POJOs instead of UDT Records |
#3084 | SQL Server unique indexes are not loaded by jOOQ-meta |
#3093 | Add code-generation configuration to treat UNIQUE keys as primary keys to generate UpdatableTables |
#3094 | Add Relations.getUniqueKeys(SchemaDefinition), getUniqueKeys() |
#3095 | Add SchemaDefinition.getTables() |
#3096 | Add Constants.XSD_RUNTIME, NS_RUNTIME, XSD_CODEGEN, NS_CODEGEN |
#3111 | Support multiple Converters for the same <U> type in the code generator |
#3115 | Support hypothetical set function syntax (for CUME_DIST, RANK, DENSE_RANK, PERCENT_RANK) |
#3116 | The jOOQ Scala manual examples use T_BOOK instead of BOOK |
#3125 | Generate default ArrayRecord constructors that don't need a Configuration |
#3130 | Generated UDTRecords should be more similar to generated TableRecords |
#3139 | Add <T1, ..., T[N]> Result<Record[N]<T1, ..., T[N]>> DSLContext.newResult(Field<T1>, ..., Field<T[N]>) |
#3153 | Add a paragraph to the manual explaining classpath behaviour of the standalone code generator |
#3154 | Add code-generation configuration to generate synthetic primary keys for updatable views |
#3169 | Add more ResultQuery.fetchAnyXXX() convenience methods |
#3180 | Add a Java 8 example to the documentation |
#3181 | Update external manual links to point to the JavaSE 8 Javadoc |
#3189 | Add DSL.sequenceByName(String...) |
#3199 | Add some Javadoc to Result.attach() and Result.detach() to explain the semantics |
#3202 | Allow for Pattern.COMMENTS in code generation configuration's regexes |
#3203 | Add DSL.not(Field<Boolean>) as a convenience for DSL.not(Condition) and condition(Field<Boolean>) |
#3204 | Clarify what "fully qualified" means in the context of <include/> and <exclude/> in the code generator configuration |
#3205 | Add DSL.condition(Boolean) as a convenience for condition(Field<Boolean>) |
#3212 | Add support for value types in DefaultRecordMapper, when mapping Record1 types |
#3229 | Add DSLContext.transaction() to implement nested transaction semantics through functional interfaces |
#3230 | Implement TransactionProvider for use with DataSourceConnectionProvider |
#3232 | Add optional <type/> configuration to <customType/> in order to specify different converters for the same Java type |
#3233 | Add DataTypeDefinition.getConverter() |
#3240 | Add DSL.sequence() methods for plain SQL sequence construction |
#3252 | Relax bounds on <R> for DSLContext.batchInsert() |
#3253 | Pull up TableRecord.insert() |
#3264 | Use try-with-resources statements in the manual |
#3265 | Add manual examples for include / exclude that explicitly use schemas (and other fully qualified object names) |
#3275 | Use maven-plugin-annotations in jOOQ-codegen-maven instead of Javadoc tags |
#3286 | Add MySQLDSL.encode(byte[]) and decode(byte[]) |
#3288 | Add DSL.date(String), DSL.time(String), and DSL.timestamp(String), as shortcuts for respective valueOf() methods |
#3305 | Add SQLDialect.families() to access all SQLDialect families |
#3307 | Change internal representation of AbstractRecord to use Object[] and BitSet instead of Value[] |
#3319 | Update the jOOQ LIMIT .. OFFSET manual page |
#3316 | Add RecordContext.recordType() to allow for introspecting record types when implementing RecordListeners |
#3321 | Add support for Oracle's (+) JOIN syntax |
#3322 | Add UpdatableRecord.store(Field<?>...), insert(Field<?>...), update(Field<?>...) |
API changes (backwards-compatible)
#3126 | Deprecate generated ArrayRecord constructors that take a Configuration argument |
#3127 | Deprecate ArrayRecord.set(Array) |
#3128 | Change ArrayRecord.setList(List<? extends E>) into ArrayRecord.set(Collection<? extends E>) |
API changes (backwards-incompatible)
#3247 | InsertSetMoreStep must not extend InsertSetStep |
Behavioural changes (backwards-incompatible)
#3131 | Query.getBindValues() should not return inlined bind values |
#3132 | Quoting identifiers that contain "special characters" may lead to unexpected results when using RenderNameStyle.AS_IS |
#3306 | Let Record.key() return a "copy record", instead of a view to the original record |
Bug fixes
#2335 | SQL syntax error when projecting two columns of the same name along with a LIMIT clause in Oracle |
#2700 | DAO.insert() and other DAO operations do not respect DEFAULT values |
#2973 | Field.in(Collection) should accept wildcard instead of T |
#3011 | Routines do not propagate errors raised from T-SQL with sqljdbc_4.0 |
#3018 | Add <outputSchemaToDefault/> to support "default schemas" during code generation |
#3055 | Add missing MariaDB and MS Access support to the manual |
#3057 | Wrong paths in maven-install.sh and maven-install.bat |
#3060 | Conversion fails for Oracle VARRAY / TABLE types, nested in UDTs |
#3069 | jOOQ calls Clob.free(), which is available only in JDBC 4.0 / Java 1.6 |
#3090 | Bad predicates generated from nullable keys on refresh(), update(), delete() |
#3099 | UpdatableRecord.store() executes INSERT instead of UPDATE when used with nullable composite primary keys |
#3101 | MutablePOJOMapper doesn't work with annotated boolean getters |
#3108 | Local Fields' Converters should be preferred over globally registered Converters |
#3117 | jOOQ illegally generates covariant setters on UDTRecords and UDT Pojos when <pojos/> and <interfaces/> are activated |
#3119 | Upgrade to JUnit 4.11 and omit using deprecated junit.framework.Assert in tests |
#3120 | Outdated link to Spring TX in the manual |
#3122 | Runtime Schema mapping doesn't work for UDT |
#3131 | Query.getBindValues() should not return inlined bind values |
#3133 | Code generation marks all PostgreSQL Fields as having a default value |
#3143 | Bad Javadoc in the org.jooq.tools.json package: JSON tools are not "JSONAware" |
#3147 | Field.sortAsc() and sortDesc() should generate inlined values for sort indirection |
#3155 | Improve documentation of <forcedType>'s <types/> element |
#3156 | "Column ambiguously defined" when emulating derived column lists with duplicate column names |
#3159 | Replace BoneCP with Apache DBCP in examples and manual |
#3161 | Bad XSD version number referenced from jOOQ 3.3 manual |
#3162 | NullPointerException when referencing window name that was not declared |
#3164 | Missing formatting when rendering formatted MERGE statement's SET clause |
#3168 | Bad download link in documentation |
#3176 | Don't generate "assignment-constructors" for POJOs and Records with more than 255 columns |
#3179 | PDF manual's white-on-black code sections are hard to read with Kindle |
#3183 | Add some clarification to the manual's section about the H2 MERGE statement |
#3186 | Bad SQL rendered for FOR UPDATE clause in Firebird |
#3187 | Manual section about Groovy has a couple of Scala references in them |
#3191 | ResultQuery.keepStatement(true) doesn't work correctly with DataSourceConnectionProvider |
#3194 | Avoid using deprecated Maven mojo descriptor @parameter expression="${property}" |
#3195 | IN predicate with subquery cannot have LIMIT .. OFFSET clause in Oracle |
#3200 | Converter does not work when loading CSV files |
#3211 | Dead codegen example POM link in manual |
#3214 | Error when inserting PostgreSQL enum array |
#3217 | Manual was not updated after fixing #2910 |
#3218 | Fix the manual and suggest using DSL.field() instead of DSL.fieldByName() |
#3226 | DefaultConnectionProvider shouldn't use DSL class for DEBUG logging |
#3234 | Connection Leak With BatchCRUD operations |
#3237 | UpdatableRecord.store() executes INSERT instead of UPDATE when nullable primary keys are NULL |
#3241 | Cursor.iterator() does not correctly implement Iterator.next() contract with respect to NoSuchElementException |
#3244 | InsertQuery.setDefaultValues() is not supported by the ACCESS dialect |
#3249 | DSL.selectZero() and DSL.selectOne() should alias column names |
#3267 | Misleading DSLContext.batch() Javadoc. It should be clear that an additional call to execute() is needed. |
#3277 | SQLite DECIMAL(p, s) types are not correctly recognised |
#3282 | inputSchema / outputSchema codegen configuration has no effect in Oracle, if inputSchema is lower-cased |
#3293 | Bad composite foreign key references generated for H2 |
#3294 | DSLContext.renderNamedParameters() doesn't replace ?, ? by :1, :2 in plain SQL QueryParts |
#3297 | Bind variables are erroneously inlined into quoted identifiers, if identifiers contain question marks |
#3300 | UpdatableRecord.store() executes INSERT instead of UPDATE when nullable primary keys are NULL, and the updatablePrimaryKeys setting is active |
#3309 | Don't use "deploy" as Maven <defaultGoal/> |
#3328 | Re-create old DefaultConfiguration constructors for backwards- compatibility |
#3333 | maven-compiler-plugin configuration in jooq-parent pom file uses the deprecated compilerArguments parameter |
#3342 | Cannot INSERT into tables with Firebird BLOB types |
Version 3.3.0 - February 14, 2014
Finally, a new awesome jOOQ release is ready for you to download! The most important feature first:
The SEEK method
We've been blogging about keyset paging before:
- https://blog.jooq.org/faster-sql-paging-with-jooq-using-the-seek-method/
- https://blog.jooq.org/faster-sql-pagination-with-keysets-continued/
Every SQL developer should have this tool in their toolchain. And now, with jOOQ 3.3, we natively support a synthetic SQL clause for you to express keyset paging very easily. jOOQ is the only database software out there to do so!
Gudu Software's SQL 2 jOOQ Parser
We're very happy to announce our collaboration with Gudu Software Ltd who have implemented a very powerful SQL parser and transformer for enterprise databases.
Together with Gudu Software, we have created an Open Source SQL 2 jOOQ parser that takes native SQL statements as input and generates jOOQ code as output.
The source code can be found here:
And our manual features a tutorial here:
We will ship, test and maintain this awesome new addition with our own deliverables. So far, SQL 2 jOOQ supports the MySQL and PostgreSQL dialects and it is in an alpha stadium. Please, community, provide as much feedback as possible to make this great tool rock even more!
Please take note of the fact that the sql2jooq library is Open Source, but it depends on the commercial gsp.jar parser, whose trial licensing terms can be seen here:
Great new SQL Feature Support
We've been looking around for SQL standard and vendor-specific features, such as the WINDOW clause (standard!), CROSS APPLY, OUTER APPLY, LATERAL join, DEFAULTs for inserts, and nice datetime arithmetic functions and emulations thereof.
As always, we've also blogged about all these features. See the following links for more details:
- https://blog.jooq.org/probably-the-coolest-sql-feature-window-functions/
- https://blog.jooq.org/add-lateral-joins-or-cross-apply-to-your-sql-tool-chain/
- https://blog.jooq.org/lesser-known-sql-features-default-values/
- https://blog.jooq.org/youre-very-likely-to-have-gotten-sql-date-time-arithmetic-wrong/
Formal Spring integration support
Spring is one of the most popular frameworks to handle transactions, and it does so very well. With the help of our community, we've established new standards and examples of how to get started very quickly with jOOQ and Spring. See the following resources for details:
- https://www.jooq.org/doc/latest/manual/getting-started/tutorials/jooq-with-spring/
- https://github.com/jOOQ/jOOQ/tree/main/jOOQ-examples/jOOQ-spring-example
Features and improvements
#531 | Add support for the WINDOW clause |
#845 | Add support for the T-SQL and Oracle 12c CROSS APPLY clause |
#846 | Add support for the T-SQL and Oracle 12c OUTER APPLY clause |
#1018 | Add support for PostgreSQL and SQL Server non-standard UPDATE .. FROM clause |
#1070 | Add support for SQL Server table-valued functions |
#1506 | Allow for inserting empty records through INSERT INTO .. DEFAULT VALUES |
#2093 | Add comment functionality from DISQUS to website |
#2246 | Add <T> T DSLContext.fetchValue(Select<Record1<T>>) to support more typesafety when fetching single values |
#2576 | Integrate with Travis-CI to run automated builds |
#2657 | Add support for ORDER BY .. SEEK .. LIMIT to implement the "seek method" for faster offsets |
#2709 | Add Record[N].value1(xx), value2(xx) setter methods |
#2734 | Add support for lateral derived tables |
#2744 | Emulate INSERT .. RETURNING through SELECT FROM FINAL TABLE (INSERT ...) in DB2 |
#2767 | Add support for CUBRID 9.2 features |
#2776 | Add support for the PostgreSQL ONLY clause |
#2778 | Add detailed section to the manual about settings.xml |
#2779 | Add support for LEFT(), RIGHT() functions |
#2780 | Add PostgresDSL.oid(Table<?>) to produce table.oid references |
#2784 | Add DSL.row(Collection<?>) to allow for interacting with collections of values or Fields |
#2790 | Add a Context data map scoped to the current subquery |
#2801 | Mention licensing options from the manual, add help message to jOOQ-Codegen when OSS users try using commercial databases |
#2805 | Add seekAfter() and seekBefore() to allow for paging in both directions |
#2806 | Add ResultQuery.fetchSize() to influence the JDBC Statement's fetch size |
#2809 | Add support for MySQL's MID() function, which is a synonym for SUBSTRING() |
#2810 | Add support for the REVERSE() function, where it is supported |
#2824 | Log 500 records on TRACE level, instead of just 5 |
#2828 | Use a default Database for code generation, in the absence of an explicit database |
#2829 | Enhance Loader API to allow for importing JSON data in addition to CSV data |
#2832 | Add OracleDSL.toChar() |
#2838 | Add more sophisticated CustomField example to the manual |
#2840 | Add DSL.date(), DSL.time(), and DSL.timestamp() to extract date, time, timestamp parts from a TIMESTAMP |
#2844 | Let JAXB emit more warnings when loading the code generation configuration |
#2848 | Add support for infix-notation for bitwise operations |
#2851 | Add some documentation to the manual about custom code sections in generated code |
#2853 | Add DSLContext.fetchFromJSON() |
#2854 | Add a JAX-RS (with Spring) and jOOQ example to the manual |
#2860 | Add manual section about using jOOQ with Groovy |
#2876 | Add some Javadoc about the fact that some SQLDialects are available in commercial distributions only. |
#2883 | Add support for PostgreSQL COUNT(DISTINCT(a, b, ...)) through DSL.countDistinct() |
#2885 | Generated enum values contain extra comma |
#2891 | Add a jOOQ / Spring-TX example to GitHub under jOOQ-examples |
#2894 | Enable automated CI on github |
#2898 | Add DSL.generateSeries(int, Field<Integer>) and (Field<Integer>, int) overloads |
#2900 | Overload MockFileDatabase constructor to allow for Readers, InputStreams, and Strings |
#2909 | Improve manual's jOOQ syntax highlighting: Highlight SQL keywords |
#2912 | Add convenience methods set(Connection), set(DataSource), derive(Connection), derive(DataSource) to DefaultConfiguration |
#2915 | Log JDBC URL in code generator configuration log |
#2921 | Add support for ad-hoc table renaming |
#2931 | Add DSLContext.fetchCount(Table<?>) and fetchCount(Table<?>, Condition) |
#2932 | Retry loading the GenerationTool configuration file with a / prepended if it fails |
#2933 | Add {Result.into|ResultQuery.fetch}{Map|Group}({Field<?>|Field[]}, RecordMapper<R, E>) |
#2944 | Add support for GROUP_CONCAT in SQLite |
#2945 | Deprecate the <generateInstanceFields/> code generation flag |
#2946 | Add a section to the manual explaining how to programmatically configure the code generator |
#2950 | Add Table.getComment() and Field.getComment() to access comment meta information from the schema |
#2969 | Add support for SQL Server SOUNDEX() and DIFFERENCE() functions |
#2970 | Add DSL.isnull() as a synonym for NVL() for the SQL Server dialect |
#2971 | Add DSL.space() to support the SQL Server specific SPACE() function |
#2976 | Add bookmarks to the PDF manual |
#2979 | Add Maven install scripts (.bat and .sh) to deliverables |
#2981 | Add an official Spring / Guice example |
#2984 | Add <R extends Record> Table<R> table(Result<R>) to allow to fetch from / join / etc in-memory tables |
#2985 | Add DSL.values(RowN...) |
#3001 | Add VisitContext.clausesLength() and queryPartsLength() to indicate the depth of the currently visited QueryPart tree |
#3002 | Add the BindVariableAbbreviator VisitListener example to the manual |
#3009 | Add DSL.dateAdd(Field<Date>, Field<? extends Number>, DatePart) and timestampAdd(Field<Timestamp>, Field<? extends Number>, DatePart) for better cross-database datetime arithmetic |
#3015 | Add support for HSQLDB user-defined aggregate functions |
#3044 | Integrate SQL 2 jOOQ beta in deliverable |
API changes (backwards-compatible)
#2811 | Deprecate ResultQuery.fetchLazy(int) - fetchSize is now passed to ResultQuery.fetchSize() not only for lazy fetching |
#2837 | Deprecate code generation configuration's <expressions/> in favour of <expression/> |
#2878 | Deprecate Record.getValue() and Result.getValue() methods that take a defaultValue argument |
#3007 | Add API guarantee to ResultQuery.fetch() methods indicating that all JDBC resources are freed |
API changes (backwards-incompatible)
#2910 | The new matchers configuration cannot be used with Maven |
#3038 | Add RecordListener.exception(RecordContext) and RecordContext.exception() |
Behavioural changes (backwards-incompatible)
#2863 | Remove unnecessarily cached Connection in DataSourceConnectionProvider |
Bug fixes
#2016 | Bad parsing of MySQL ENUM literals by jooq-meta, if they contain special characters |
#2152 | Invalid column type: 16, when binding null as java.lang.Boolean onto a NUMBER(..) column in Oracle |
#2633 | Fix manual to link to appropriate Javadoc |
#2655 | Improve ArrayIndexOutOfBoundsException: -1 error message when unknown field is accessed from a record |
#2658 | Inefficient emulation of row value expression comparison predicates <, <=, >, >=. Factor out predicates for improved index usage |
#2773 | Confusion of Unix vs Windows style line terminators in source code |
#2781 | Disambiguate collisions between enum literals and package names |
#2792 | data(Object, Object) methods do not unset the value if null is passed |
#2795 | Bad Javadoc on DSLContext.fetchOne(String) method |
#2798 | Inconsistent logic executed between Record.setValue(Field<T>, T) and BookRecord.setId(Integer) (generated) |
#2816 | Manual shows wrong DefaultConfiguration constructor call for use with Spring |
#2819 | Invalid SQL rendered for Ingres row value expression predicates |
#2820 | Invalid SQL rendered for Ingres derived column lists |
#2825 | IngresDatabase treats unique keys as primary keys |
#2831 | Bad Javadoc formatting on MySQLDSL's and MariaDBDSL's enumType() method |
#2835 | UpdatableRecord.store() and DSLContext.executeInsert() show different behaviour with respect to NULL value insertion |
#2842 | Sybase CAST(? AS LONG VARCHAR) must not contain a length |
#2845 | AbstractStoreQuery.prepare() does not apply RenderKeywordStyle when specifying column names for return after INSERT |
#2857 | Unnecessary whitespace rendered in USING() clause |
#2858 | Bad example in manual related to stored procedure call |
#2864 | Check if ALL_MVIEW_COMMENTS exists before using it (e.g. against an Oracle 9i database) |
#2866 | Wrong implementation for check if ALL_COLUMNS.DEFAULTED exists |
#2869 | DefaultRecordMapper should attach resulting records according to Settings.attachRecords, if target type implements Attachable |
#2872 | Possible StackOverflowError when using plain SQL tables with inlined QueryParts |
#2879 | An exception in the check constraint loader can cause all constraint loading to fail |
#2881 | Throw IllegalArgumentException when calling SelectQuery.addJoinOnKey() and addJoinUsing() with bad JoinType |
#2887 | jooq-codegen-maven should use a target directory relative to the module |
#2913 | Improve code generator compatibility with PostgreSQL 8.x by removing the selection of INFORMATION_SCHEMA.COLUMNS.IDENTITY_GENERATION |
#2916 | Improve code generator compatibility with PostgreSQL 8.x by avoiding the use of window functions |
#2917 | Improve code generator compatibility with PostgreSQL 8.x by avoiding casting to enum types |
#2922 | Manual Bug: SQL Builder example does not compile |
#2923 | Manual Bug: It is not clear where FK_BOOK_AUTHOR is imported from |
#2926 | Add code-generation support for the MySQL / MariaDB TINYTEXT data type |
#2937 | Fix trailing whitespaces in generated code |
#2942 | Error in the manual: Wrong class linked |
#2956 | Field.isFalse() / isTrue() result in extra parameters |
#2958 | Error when the code-generation database user has insufficient grants to read the "mysql" meta schema |
#2963 | Lower log level for warnings about unknown SQL data types from MetaDataFieldProvider (plain SQL) |
#2977 | Missing parent pom.xml file in deliverables |
#2982 | Variable binding doesn't work in vendor-specific UPDATE t1 JOIN t2 queries, when joined tables are subqueries with bind values |
#2987 | Bind values are not debug-logged for standalone stored procedure or function calls |
#2989 | Inherit complete Record state when calling Record.into(Class<? extends Record>) |
#2994 | Manual Bug: The jOOQ 2.x Table.getFields() method is used, which doesn't exist |
#3013 | The Configuration's RecordMapperProvider is not used when mapping UDTRecords |
#3019 | Bad SQL rendered from HSQLDBDatabase when loading check constraints |
#3023 | DefaultRecordMapper does not map nested UDTs onto nested POJOs |
#3027 | Missing whitespace / newline on emulated multi-value INSERT |
#3036 | RecordListeners don't receive "end" events when exceptions occur |
#3039 | Cannot bind NULL with JDBC Types.BOOLEAN in DB2 |
#3042 | Work around flaws in H2's INFORMATION_SCHEMA.CONSTRAINTS.COLUMN_LIST |
#3046 | UDTRecordImpl.toString() may throw NullPointerException, if custom RecordMapperProvider maps Record to null |
#3048 | Nested UDTs are no longer attached when fetched from queries (as opposed to procedures) |
#3050 | DefaultRecordMapperProvider should implement Serializable |
Version 3.2.0 - October 9, 2013
With the new jOOQ 3.2, apart from introducing great new features, we are changing quite a few things on how we operate. At Data Geekery GmbH, we believe in Open Source. But we also believe in the creative power enabled by commercial software. This is why we have chosen to implement a dual-licensing strategy. Read more about this strategy here:
https://blog.jooq.org/jooq-3-2-offering-commercial-licensing-and-support
But jOOQ 3.2 also ships with great new features! They include:
A new RecordListener SPI which can be hooked into the Configuration in order to control ActiveRecord lifecycle events. This is very useful if you want to initialise some database records prior to inserting new data, or if you want to implement a central ID generation strategy, e.g. by generating Java UUIDs.
A new, experimental VisitListener SPI which can be hooked into the Configuration in order to control jOOQ's complete QueryPart rendering and variable binding lifecycle. Use this powerful SPI to perform custom SQL transformation, e.g. to implement shared-schema multi-tenancy, or a security layer centrally preventing access to certain data.
With this release, the Oracle and DB2 SQL dialect families will now be able to distinguish Oracle 10g, 11g, 12c features, as well as DB2 9.x, 10.x features. This is important as more and more databases start supporting the SQL standard OFFSET .. FETCH clause and other clauses that are emulated by jOOQ.
The code generator has experienced a lot of improvements, mainly including a new MatcherStrategy, which can be configured through Maven or XML code generator configurations. This generator strategy will allow you to implement several regular-expression based naming pattern replacements for all sorts of generated artefacts. This is extremely useful to generate table, record, pojo class name prefixes, suffixes in particular, or to just completely redesign the way the jOOQ code generator generates things.
Features and improvements
#674 | Add <fluentSetters/> code generation flag to let generated setters return this |
#996 | Add support for various Postgres ARRAY operations |
#1079 | Add support for Oracle's FLASHBACK QUERY clause |
#1171 | Add a MatcherStrategy GeneratorStrategy to allow for configurative regex pattern matching and replacement |
#1644 | Add DSL.dual() to explicitly create a DUAL table that works with any dialect |
#1903 | Duplicate Query construction API between DSLContext and DSL |
#2010 | Add listener API to Record / UpdatableRecord |
#2352 | Enhance <ForcedType/> to allow for forcing a type upon all columns / parameters / attributes of a given data type |
#2542 | Add a Keyword type and DSL.keyword(String) to construct it |
#2593 | Add Meta.getPrimaryKeys() |
#2594 | Add primary key and foreign key navigation support in JDBCDatabase |
#2595 | Add implicit conversions from Scala functions to RecordMapper |
#2603 | Add <includeExcludeColumns/> flag to code generation configuration to indicate that <includes/> and <excludes/> shall also match column names |
#2606 | Distinguish ORACLE10G, ORACLE11G, ORACLE12C SQLDialects within the ORACLE family |
#2618 | Document the fact that different packages are generated for different schemas |
#2619 | Add an example ExecuteListener to the manual, showing how UPDATE and DELETE statements without WHERE clause can be aborted |
#2630 | Add DSL.queryPart(String, Object...) and similar methods to create simple plain SQL query parts |
#2652 | Change tutorial to use the common AUTHOR table, instead of POSTS |
#2660 | Add some documentation about jOOQ not supporting operator precedence |
#2665 | Implement SPI for RenderContext listening to allow for custom SQL transformation |
#2666 | Pull up RenderContext.sql(QueryPart) and BindContext.bind(QueryPart) to Context.visit(QueryPart) |
#2667 | Add org.jooq.Clause and let org.jooq.Context listen on start(Clause) and end(Clause) events |
#2676 | Add QueryPartInternal.clause() to allow for QueryParts to return Clause information to org.jooq.Context |
#2689 | Expose a DAO's internal RecordMapper through DAO.mapper() |
#2696 | Provide default implementation for CustomQueryPart.bind() (for all Custom QueryParts) |
#2699 | Generate DEFAULT and NULL metadata information on generated DataTypes |
#2701 | Document the fact that jOOQ sets changed flags to true, even if Record.setValue() sets the value already present in the record |
#2702 | Add DataType.defaulted() and DataType.nullable() |
#2706 | Generate "full" constructors in records, allowing to construct a record with all values set |
#2713 | Add support for custom code sections in generated code |
#2722 | Add DSLContext.newRecord(Field<?>...) to support the creation of custom record types |
#2723 | Add example VisitListener implementation that prevents UPDATE, DELETE statement execution without explicit WHERE clause |
#2724 | The default logger should log the number of affected records, if applicable |
#2725 | Add ExecuteContext.rows() to indicate the number of affected rows in the last executed statement |
#2726 | Add Attachable.detach() |
#2729 | Emulate IS DISTINCT FROM through IS / IS NOT in SQLite |
#2733 | Add the default log4j.xml configuration file to the maven plugin |
#2745 | Generate default constructor and "assignment-constructor" in POJOs |
#2757 | Add support for DB2 10.5 |
#2761 | Add some documentation to the manual showing how GeneratorStrategy SPI is used by jOOQ-codegen |
#2764 | Let CRUD operations be able to perform UPDATEs on primary keys |
#2765 | Add support for a database-agnostic GENERATE_SERIES(FROM, TO) table function |
API changes (backwards-compatible)
#2581 | Deprecate fetchLater() and FutureResult<R> |
#2662 | Deprecate the internal method DSLContext.bind(QueryPart, PreparedStatement) |
#2719 | Change various method(Collection<SortField<?>>) into method(Collection<? extends SortField<?>>) |
Bug fixes
#1908 | Compilation error in generated code when a MySQL procedure and function share the same name and signature |
#2534 | Correctly handle Oracle BLOB and CLOB data types, when fetched through plain SQL |
#2580 | Bad SQL rendered when combining DISTINCT with LIMIT .. OFFSET in DB2, SQL Server |
#2584 | ORA-00904: "SYS"."ALL_PROCEDURES"."OBJECT_TYPE": invalid identifier when running code generation with Oracle 10gR1 |
#2586 | Bad SQL dialect referenced from ASE's and CUBRID's package-info.java |
#2591 | Result.intoGroups() and similar methods create key Records with changed=true |
#2592 | Qualified names created using DSL.name(String...) should not render null or empty string parts |
#2596 | Scala tests don't run with Maven |
#2597 | f1.concat(f2).toString() seems to render unnecessary cast expression |
#2608 | Error in code generator when the sqlite_sequence table is missing |
#2613 | The batch INSERT query example in the manual is no longer correct with jOOQ 3.x |
#2624 | Wrong SQL Server 2012 detection in jOOQ-Meta |
#2628 | Add missing Javadoc to DefaultDSLContext |
#2634 | Minor documentation bug: The MockDataProvider uses toLowerCase() but upper-case SQL keywords |
#2643 | Routine.execute(Configuration) should restore the original routine state after execution |
#2681 | "Type NULL is not supported in dialect MYSQL" when calling Meta.getTables() with MySQL or MariaDB JDBC drivers |
#2690 | Inaccurate runtime xsd versions in 3.1 manual |
#2703 | SQLDialect.getNameLC() and getNameUC() are not NPE-safe |
#2707 | PostgreSQL ENUM ordering is inconsistent with the database |
#2708 | Wrong SQL rendered for CAST(x AS DECIMAL(y, z)). Precision and scale are lost. |
#2712 | Field.equalIgnoreCase(String) method broken for SQL Server |
#2714 | Documentation bug in INSERT statements. Cannot combine Field<?> with String arguments in VALUES() clause |
#2717 | DefaultResultSet compile-time depends on Java 1.7 / JDBC 4.1 |
#2718 | NullPointerException in code generator when a primary key (or foreign key) column is excluded from code generation |
#2720 | Fix the manual's claim that <includes/> accepts comma-separated regular expressions |
#2730 | Immutable Pojo+Interface code generation produces uncompilable pojo |
#2736 | Improve code generator compatibility with PostgreSQL 8.x by testing if pg_catalog.pg_enum and information_schema.attributes exist |
#2753 | DATE_DIFF() with CURRENT_DATE() returns wrong precision in Oracle |
#2755 | Incomplete @Support annotations on OrderedAggregateFunction methods |
#2758 | Duplicate primary key column references generated for DB2 |
#2759 | DSLContext.fetchCount() fails when argument SELECT statement does not explicitly provide column names in SQL Server |
#2760 | org.jooq.Meta should treat MySQL databases as Schema, not as Catalog |
#2766 | Javadoc typo on DSLContext.batchDelete() |
Version 3.1.0 - June 30, 2013
With this release, MariaDB is now finally officially supported by jOOQ! MariaDB is a MySQL fork, which currently has a very similar feature set as its parent. As such forks tend to evolve into different directions very quickly, it makes sense to add formal support in jOOQ.
SQL Server 2012 is another SQL dialect that is now officially supported in jOOQ, allowing to make use of the newly supported ROWS UNBOUNDED PRECEDING and similar windowing clauses, as well as the long awaited OFFSET .. FETCH clause. From now on, jOOQ SQLDialect.family() allows to define a super-set of SQL dialects by the same vendors with only subtle differences.
POJO mapping is taken to the next level. jOOQ opened up its internal DefaultRecordMapper providing useful Record to POJO mapping algorithms. But your custom domain model might be more complex. Instead of creating the next impedance mismatch, trying to foresee your own mapping algorithm needs, jOOQ allows you to inject a RecordMapperProvider into your Configuration, allowing to override record mapping with arbitrary behaviour.
This minor release is also a strong step forward towards a more unified SQL experience, where row value expression IN predicates and comparison predicates are simulated with an equivalent EXISTS predicate. See this blog post for more details: https://blog.jooq.org/sql-query-transformation-fun-predicates-with-row-value-expressions
Note, that for technical reasons, jOOQ 3.0.0 could not yet be integration tested with DB2, Ingres, and Sybase ASE. Consider using jOOQ 2.6, instead
Features and improvements
#552 | Add SQLDialect.family() to group several SQLDialect versions of the same RDBMS |
#742 | Improve MySQL Stored Procedure support using MySQL 5.5's INFORMATION_SCHEMA.PARAMETERS dictionary table |
#833 | Add integration tests for both jconn3 and jTDS JDBC drivers for Sybase and SQL Server |
#963 | Map SQL Server TINYINT to UByte |
#965 | Add support for Sybase SQL Anywhere unsigned number types |
#1373 | Add <T> Field<T> DSL.coerce(Field<?>, DataType<T>) and similar methods, to coerce a field to a given data type (as opposed to casting it) |
#1836 | Document using jOOQ with Spring for transaction support |
#1885 | Add test to count opening and closing of Statements and ResultSets by jOOQ |
#2022 | Add support for SQL Server 2012 windowing clauses in window functions |
#2058 | Add support for the MariaDB database |
#2095 | Document <forcedType/>'s feature of forcing a column onto a SQL type |
#2235 | Add Result<?> DSLContext.fetchFromTXT() to allow for loading results that were exported using Result.format() |
#2236 | Add DSLContext.batch(String...) and batch(String, Object[]...) to easily create batch statements from SQL strings |
#2291 | Add DSLContext.fetchAny(Table, Condition) method and others |
#2299 | Allow for setting ResultSet flags (e.g. ResultSet.TYPE_SCROLL_INSENSITIVE through ResultQuery.resultSetConcurrency(), resultSetType(), resultSetHoldability() |
#2310 | Add DSL.using(Connection) and DSL.using(Connection, Settings) which auto-detect the SQLDialect from the jdbc url |
#2311 | Add Configuration.recordMapperProvider() to override jOOQ's internal default ReflectionMapper |
#2339 | Support CUBRID 9.1's new features |
#2344 | Add a new ControlFlowSignal that is used to explicitly jump out of a control flow |
#2355 | Add support for Postgres / HSQLDB's TRUNCATE [...] RESTART / CONTINUE IDENTITY |
#2357 | Add support for Postgres' TRUNCATE [...] CASCADE statement |
#2395 | Simulate row value expression IN predicate using EXISTS |
#2414 | Add Setting to influence parameter rendering (indexed, named, inlined) |
#2416 | Add Result.intoXML(org.xml.sax.ContentHandler) to generate a SAX event stream from a jOOQ result |
#2423 | Add support for SQL Server 2012 native OFFSET .. FETCH clause |
#2424 | Integration-test jOOQ with the SQLite xerial driver |
#2426 | Add DSLContext.batch(Query, Object[]...) as a convenience for calling batch(Query).bind(Object...).bind(Object...) |
#2427 | Add more Javadoc to ResultQuery.fetchResultSet() explaining that underlying PreparedStatements are closed with ResultSet.close() |
#2428 | Simulate row value expression comparison predicates using EXISTS |
#2430 | Add CustomQueryPart for use with plain SQL and other places |
#2434 | Add Field.compare(Comparator, Select) and Field.compare(Comparator, QuantifiedSelect) to allow for more dynamic SQL |
#2437 | Add RenderContext.paramType() and deprecate RenderContext.inline() and .namedParams() |
#2440 | Expose the DataSource contained in the DataSourceConnectionProvider |
#2441 | Add DSL.cast(Field<?>, XXX) for increased API consistency |
#2446 | Add JDBCUtils.dialect(Connection) to "guess" the jOOQ SQLDialect from a JDBC Connection |
#2466 | Add a public DefaultDSLContext implementation that can be used by users to override the default behaviour |
#2485 | Allow for treating Field<Boolean> as Condition |
#2496 | Add support for SQL Server 2012 sequences |
#2499 | Add JDBCUtils.safeClose(Connection) |
#2509 | Expose CHECK constraints in jOOQ-meta |
#2519 | Add Record.from(Object, Field<?>...) from(Object, String...), from(Object, int...) to copy only a select set of values from a POJO, Array, Map |
#2521 | Add {Row|Record}.fields(Field<?>...), {Row|Record}.fields(String...), {Row|Record}.fields(int...) to extract Field<?>[] from a row or record |
#2527 | Add org.jooq.tools.jdbc.DefaultResultSet to provide a default ResultSet delegation implementation |
#2531 | Add integration tests mapping binary(16) to java.util.UUID |
#2532 | Let batch executions debug-log executed queries |
#2535 | Convert.convert(Object, Class) should support simple casting |
#2547 | Document some SQL language to jOOQ DSL API mapping rules in the manual |
#2566 | Upgrade integration test jTDS version to 1.3.1 |
#2571 | Add a new RecordType<R extends Record> type to make up for the missing recursive type definition on Record |
API changes (backwards-incompatible)
#2468 | API bug: MergeNotMatchedSetStep.set(Field, Select) returns MergeMatchedSetMoreStep instead of MergeNotMatchedSetMoreStep |
Bug fixes
#1520 | Handle Ingres', SQLite, SQL Server's, Sybase ASE's limitations of 1024, 999, 2100 or 2000 maximum bind values per query |
#2135 | Postgres ENUM data type isn't supported correctly, if the ENUM needs full qualification |
#2323 | NullPointerException when calling Schema.getTables() on a meta schema with SQLite |
#2401 | Bad package name generated when <packageName/> contents are not trimmed |
#2404 | Cannot combine <dateAsTimestamp/> with <forcedType/> if both match |
#2412 | jOOQ Meta does not recognise non-uppercase IN, OUT, INOUT keywords in MySQL stored procedures |
#2413 | Suppress warnings in generated code (@SuppressWarnings("all") doesn't suppress "rawtypes" warnings with javac) |
#2418 | RenderContext.data() is not passed on to QueryParts when being rendered |
#2422 | Upgrade RSyntaxTextArea to 2.0.7 |
#2432 | Manual refers to a package-private DefaultConfiguration constructor |
#2443 | AbstractStoreQuery.execute() doesn't correctly operate on the Configuration's ConnectionProvider in SQLite IDENTITY fetching queries |
#2445 | JDBCDatabase doesn't recognise Oracle's VARCHAR2 data type (and other vendor-specific data types) |
#2447 | Tables collected through DSLContext.meta() return duplicate columns if multi-schema environments contain identical tables |
#2449 | JDBCDatabase doesn't use DataType.length(), precision(), and scale() |
#2450 | Cannot set precision on TINYINT, SMALLINT, INT, BIGINT data types |
#2461 | Generator Encoding Error for Database-Objects with Unicode-Names |
#2464 | Bad SQL rendered from DELETE statements with aliased tables |
#2469 | NullPointerException in AbstractResultQuery.fetchOneMap() |
#2477 | MySQL's unsigned types cannot be used in other dialects |
#2478 | IngresDatabase erroneously joins IIINDEXES to get constraint columns, rather than using IIKEYS |
#2494 | Possible null pointer passed to ConnectionProvider.release() |
#2502 | Code generation fails to generate valid java for stored procedures that accept parameters named configuration. |
#2506 | SQLDialectNotSupportedException on DSL.inline(T, Class), when jOOQ's internals are not (yet) properly initialised |
#2515 | Compilation errors when generating code for artefacts that differ only by a trailing underscore(s): A and A_ and A__ |
#2523 | Statement.close() may be called upon previously closed statements |
#2528 | Combining renderFormatted with inlined bind variables will change bind$ values when they contain newlines |
#2562 | Bad SQLDialect reference in Oracle and MySQL package-info.java |
#2569 | Error when rendering SQL Server procedures with Settings.renderSchema == false |
Version 3.0.0 - April 28, 2013
This major release is a great move towards better integration of SQL as a language in Java. Unlike any other database abstraction framework, jOOQ now formally supports the notion of "row value expressions". The jOOQ API uses Xtend-generated API types from Row1 .. Row22, as well as Record1 .. Record22 to bring you even more compile-time typesafety on a record-level.
In SQL, you can typesafely write
SELECT * FROM t WHERE (t.a, t.b) = (1, 2) SELECT * FROM t WHERE (t.a, t.b) OVERLAPS (date1, date2) SELECT * FROM t WHERE (t.a, t.b) IN (SELECT x, y FROM t2) UPDATE t SET (a, b) = (SELECT x, y FROM t2 WHERE ...) INSERT INTO t (a, b) VALUES (1, 2)
In jOOQ, you can now (also typesafely!) write
select().from(t).where(row(t.a, t.b).eq(1, 2)); // Type-check here: -----------------> ^^^^ select().from(t).where(row(t.a, t.b).overlaps(date1, date2)); // Type-check here: ------------------------> ^^^^^^^^^^^^ select().from(t).where(row(t.a, t.b).in(select(t2.x, t2.y).from(t2))); // Type-check here: -------------------------> ^^^^^^^^^^ update(t).set(row(t.a, t.b), select(t2.x, t2.y).where(...)); // Type-check here: --------------> ^^^^^^^^^^ insertInto(t, t.a, t.b).values(1, 2); // Type-check here: ---------> ^^^^
This also applies for existing API, which doesn't involve row value expressions:
select().from(t).where(t.a.eq(select(t2.x).from(t2)); // Type-check here: ---------------> ^^^^ select().from(t).where(t.a.eq(any(select(t2.x).from(t2))); // Type-check here: -------------------> ^^^^ select().from(t).where(t.a.in(select(t2.x).from(t2)); // Type-check here: ---------------> ^^^^
And for UNIONs
select(t1.a, t1.b).from(t1).union(select(t2.a, t2.b).from(t2)); // Type-check here: -------------------> ^^^^^^^^^^
These type-checks are preformed by your Java compiler, considering the generic type information of your SQL statement's Record data types. These include:
- Record1<T1>
- Record2<T1, T2>
- Record3<T1, T2, T3>
- ...
- Record22<T1, T2, T3, .., T22>
The highest degree of typesafety was chosen to be 22, to match Scala's Tuple22, Product22 and Function22 types. Higher degree records are still supported by jOOQ, just without the additional typesafety.
This Record typesafety is applied to
- SELECT statements
- INSERT and MERGE statements: the VALUES() clause
- UPDATE statements: SET A = (SELECT...)
- UPDATE statements with row value expressions: SET (A, B) = (SELECT...)
- Quantified comparison predicates: ANY(SELECT...) and ALL(SELECT...)
- Comparison predicates: = (SELECT...)
- IN predicates: IN (SELECT...)
- BETWEEN predicates: BETWEEN (SELECT...) AND (SELECT...)
- Generated records
- The new VALUES() constructor
- Scala integration for conversion of jOOQ Record[N] to Scala's Tuple[N]
Apart from this major improvement, there had been many minor changes throughout the jOOQ API. Here are some important ones:
- Factory has been split into DSL (static QueryPart construction) and DSLContext (Query execution, "attached" QueryPart construction). This greatly improves the overall DSL experience while allowing for more fine-grained Executor lifecycle control.
- A ConnectionProvider has been introduced as an abstraction of the JDBC Connection lifecycle. The standalone Connection and pooled DataSource modes are still supported, but you can now inject your own ConnectionProvider for more control.
- A lot of performance improvements have been implemented within the jOOQ API removing most of the overhead caused by jOOQ when fetching data from JDBC
- A JDBC Mock API has been added to help you create simple unit tests for your application built on top of jOOQ.
- A VALUES() constructor is now supported, and derived column lists to alias tables and columns in one go.
- The data type API has been greatly simplified. This allowed for the introduction of runtime precision, scale, and length information.
- CRUD has been improved through many more CRUD batch operations, explicit INSERT and UPDATE (in addition to store()), and explicit handling of jOOQ's internal changed flags.
As this is a major release, some backwards-incompatibilities were inevitable. For those users among you, migrating from jOOQ 2.x to 3.0, here are a couple of useful hints: https://www.jooq.org/doc/latest/manual/reference/migrating-to-3.0/
Note, that for technical reasons, jOOQ 3.0.0 could not yet be integration tested with DB2, Ingres, and Sybase ASE. Consider using jOOQ 2.6, instead
Note, that further code generation and model API improvements were postponed to a later release
Note, previous release candidates contained more features, improvements and bug fixes. See their respective sections for details.
Features and improvements
#2410 | Add some more API usage examples to the section about ResultSet fetching |
#2415 | Add Constants.MINOR_VERSION and Constants.FULL_VERSION for internal and external reuse |
Bug fixes
#1998 | Wrong screenshots in the manual's section about code generation. jooq-meta.jar is missing |
#2407 | Fix bad references to pre-3.0 Factory in Javadoc |
Version 3.0.0 (RC3) - April 12, 2013
This major release is a great move towards better integration of SQL as a language in Java. Unlike any other database abstraction framework, jOOQ now formally supports the notion of "row value expressions". The jOOQ API uses Xtend-generated API types from Row1 .. Row22, as well as Record1 .. Record22 to bring you even more compile-time typesafety on a record-level.
See release 3.0.0 for more information.
Features and improvements
#2195 | Remove the standalone tutorial, link to the manual |
#2321 | Implement various Key.toString() methods |
#2329 | Add Javadoc to Configuration.executeListenerProviders() |
#2331 | Add hint to the manual about mvn eclipse:clean and eclipse:eclipse when building jOOQ |
#2363 | Change the readme file to use Markdown |
#2366 | Add org.jooq.util.example package to jOOQ-codegen with some example GeneratorStrategies |
#2372 | Add aliases for arithmetic operators to be able to use Groovy default operator overloading |
#2389 | Make org.jooq.impl.DefaultConfiguration public |
#2392 | Add Configuration.set() methods. They should allow for modifying a Configuration |
#2396 | Add DSL.function(Name, Class, Field...) and DSL.function(Name, DataType, Field...) to allow for custom, fully-qualified function references |
API changes (backwards-compatible)
#2378 | Allow for overriding getIdentity() and getReferences() in CustomTable |
API changes (backwards-incompatible)
#2328 | Remove UpdatableTable marker interface, pulling up methods to Table |
#2342 | Change Configuration.data() to return Map<Object, Object> |
#2343 | Decouple lifecycle of Configuration and ExecuteContext |
#2350 | Do not statically reference a Connection from GenerationTool |
#2353 | Decouple org.jooq.Context from Configuration. Choose composition over inheritance |
#2362 | Decouple org.jooq.DSLContext from Configuration. Choose composition over inheritance |
#2379 | Replace 3.0-RC1 Executor type by a contextual DSL type constructed from DSL.using() |
#2380 | Rename org.jooq.impl.Factory to org.jooq.impl.DSL |
#2382 | Let DAO reference a Configuration instead of a DSLContext |
#2388 | Replace Configuration's List<ExecuteListener> with ExecuteListenerProvider[] to simplify correct and thread-safe client implementations |
#2390 | Change Configuration API to reflect jOOQ-style getter / setter naming |
#2391 | Rename dialect-specific Factories [Dialect]Factory to [Dialect]DSL |
#2399 | Remove support for the USE statement |
Behaviour changes (backwards-incompatible)
#2351 | Relax ConnectionProvider contract, allowing acquire() to return new Connections even before release() is called |
Bug fixes
#1868 | Cursor.close() doesn't terminate the ExecuteListener life cycle |
#2325 | "HsqlException: incompatible data type in conversion" when binding a UUID[] to an HSQLDB prepared statement |
#2327 | Compilation error in generated tables, when a table contains a UNIQUE key but no PRIMARY key |
#2332 | Documentation example regarding DSL.concat() does not compile |
#2336 | jOOQ 3.0 regression: NoClassDefFoundError caused by missing log4j dependency |
#2338 | Tutorial example unclear: There are three artefacts in Maven, not one |
#2346 | org.jooq.Meta's generated Schema and other objects are Serializable, but their enclosed Meta instance is not |
#2347 | Let equals() implementations succeed early on identity |
#2354 | Single page manual display errors on Firefox |
#2361 | Inaccurate Configuration Javadoc explaining wrong ExecuteListener lifecycle |
#2367 | SQLite identifiers that collide with keywords should be quoted |
#2381 | Do not add TableFieldImpl to table in constructor of TableFieldImpl |
#2385 | fetchOne() and fetchLazy() don't terminate the ExecuteListener life cycle when an exception occurs |
#2393 | Fully qualified name not used for user-defined aggregate function |
Version 3.0.0 (RC2) - March 8, 2013
This major release is a great move towards better integration of SQL as a language in Java. Unlike any other database abstraction framework, jOOQ now formally supports the notion of "row value expressions". The jOOQ API uses Xtend-generated API types from Row1 .. Row22, as well as Record1 .. Record22 to bring you even more compile-time typesafety on a record-level.
See subsequent release candidates or release 3.0.0 for more information.
Features and improvements
#2200 | Add Executor.fetchCount(Select<?>) and Select.fetchCount() to replace the projection by a COUNT(*) query |
#2244 | Add section to the manual indicating that the jOOQ generator can only handle schemas of a certain size |
#2255 | Add code generation option to avoid the generation of "global object references" |
#2257 | Add List<IdentityDefinition> Database.getIdentities(SchemaDefinition) for convenience to jooq-meta |
#2258 | Restore private and deprecated versions of the Factory constructors, adding some Javadoc about the changes between jOOQ 2.x and 3.0 |
#2270 | Add section to the manual indicating how to build jOOQ with Maven |
#2272 | Add a paragraph to the manual's preface, explaining "why not just use SQL"? |
#2281 | Add Result<Record> Executor.fetchFromStringData(List<String[]>) in order to reuse logic from fetchFromCSV |
#2285 | Add more verbosity to the code generator, when configured badly |
#2290 | Add Database.getUniqueKeys() and getForeignKeys to jOOQ-meta |
#2297 | Add section to the manual indicating how the various generator flags depend on each other |
#2308 | Do not generate "final" Tables.java, UniqueKeys.java, etc. |
Bug fixes
#2212 | "code size too large" in generated SchemaImpl, when the number of tables exceeds 15k |
#2238 | Code generation runs extremely slow for large schemas (Inefficient DefaultRelations.getUniqueKeys() and getForeignKeys() methods) |
#2239 | Code generation runs extremely slow for large schemas (Inefficient AbstractDatabase.filterSchema() methods) |
#2252 | ArrayIndexOutOfBoundsException, when rendering plain SQL that is terminated by a comment |
#2259 | RenderMapping has no effect, if not supplied to the Executor constructor |
#2262 | RenderSchema has no effect, if not supplied to the Executor constructor |
#2267 | SQLDialectNotSupportedException: Type class org.postgis.PGgeometry is not supported in dialect null, when binding PG* objects |
#2271 | jOOQ Unit tests fail when not run in CET / CEST |
#2273 | Tutorial bug, referencing wrong Maven dependency. jOOQ 3.0.0 is not yet released, only RC1 |
#2276 | Wrong MockDataProvider manual example |
#2278 | Postgres (UUID and other) ARRAY types aren't correctly inlined as string literals |
#2279 | UUIDs aren't correctly deserialised from Postgres UDTs |
#2280 | Improve supported formats for MockFileDatabase |
#2283 | Class loading issues in GenerationTool when called by Gradle |
#2294 | Compilation errors when code generator is configured with <daos>true</daos> and <relations>false</relations> |
#2298 | Suppress warnings in generated code (@SuppressWarnings("all") doesn't work with javac) |
#2312 | Annotate org.jooq.Support with java.lang.annotation.Documented to make it part of the public API (in Javadoc) |
#2314 | Outdated GenerationTool Javadoc |
Version 3.0.0 (RC1) - February 16, 2013
This major release is a great move towards better integration of SQL as a language in Java. Unlike any other database abstraction framework, jOOQ now formally supports the notion of "row value expressions". The jOOQ API uses Xtend-generated API types from Row1 .. Row22, as well as Record1 .. Record22 to bring you even more compile-time typesafety on a record-level.
See subsequent release candidates or release 3.0.0 for more information.
Features and improvements
#456 | Add runtime support for PRECISION, SCALE, and LENGTH attributes |
#834 | Add support for the Firebird / Postgres UPDATE .. RETURNING clause |
#915 | Add <T1, T2, ..., T[N]> Table<Record[N]<T1, T2, ..., T[N]>> Factory.values(Row[N]<T1, T2, ..., T[N]>...), to create ad-hoc tables from data |
#1038 | Introduce new type GroupField for cube(), rollup() and groupingSets() functions. Accept only GroupField... in groupBy() clauses |
#1097 | Add org.jooq.Catalog, a type modelling an entity combining several org.jooq.Schema |
#1144 | Overload Executor.fetch[One|Lazy](ResultSet, X...) with X being Field<?>, DataType<?>, Class<?> |
#1178 | Allow for treating Condition as Field<Boolean> |
#1583 | Add support for row value expressions in UPDATE statements: UPDATE .. SET (A, B, C) = (SELECT X, Y, Z) |
#1624 | Add support for java.util.UUID as a <T> type |
#1663 | Document RenderContext and make it part of the public API |
#1686 | Add UpdatableRecord.insert() and update() |
#1689 | Generate <E> E into(E) and <E> R from(E) methods to generated records |
#1690 | Add UpdatableRecord.key() returning a Record holding PK values |
#1695 | Add Factory.all() and Factory.any() to create quantified expressions |
#1703 | Add Executor.batchDelete(UpdatableRecord<?>...) to mass-delete a set of UpdatableRecords |
#1801 | Add Table.as(String, String...) to allow for creating a table aliases (correlation names) with derived column lists |
#1874 | Add Record1, Record2, ... Record[N] similar to Row1, Row2, ... Row[N] to support record type-safety |
#1897 | Add a section to the manual about the migration to jOOQ 3.0 |
#1899 | Make some JDBC-related utility methods publicly available in org.jooq.tools.jdbc.JDBCUtils |
#1902 | Duplicate SELECT API between Executor and Factory |
#1904 | Add Executor.fetch(ResultQuery), Executor.execute(Query), and similar methods |
#1905 | Add Row[N].equal(Select<? extends Record[N]>) and similar methods |
#1906 | Use Xtend to generate Row[N], Record[N] and other [N]-related API code artefacts |
#1914 | Document the fact that SELECT * is performed by leaving the SELECT list empty |
#1917 | Add support for CUBRID 9.0's window functions and MERGE statement |
#1918 | Let generated Records implement Record[N] if applicable |
#1919 | Support higher degrees of Row[N] and Record[N] types. Match Scala's max degree of 22 |
#1920 | Add more implicit defs in order to treat Record[N] as Scala's Tuple[N] |
#1923 | Add Record.intoResultSet() to create a single-record JDBC ResultSet from a Record |
#1924 | Add support for CUBRID 9.0's ENUM data type |
#1932 | Generate Javadocs for Table constructors |
#1934 | Improve generated Record Javadoc |
#1951 | Add support for the SQL Server WITH (...) table hints |
#1966 | Add Row[N].equal(Record[N]) and similar convenience methods |
#1967 | Document using MySQL's SQL_CALC_FOUND_ROWS as an Oracle hint |
#1968 | Add org.jooq.Meta returned from Executor.meta() to return a wrapped JDBC DatabaseMetaData object |
#1972 | Move MySQLFactory.md5() to Factory and simulate it for Oracle |
#1973 | Add Executor.fetchOne(ResultSet) |
#1975 | Add Result.sort{Asc|Desc}(int) and (String) to order by field index / name |
#1981 | Add support for DB2 CGTT and MQT |
#1983 | Improve the Javadoc on Table.as() and Field.as() to hint at case-sensitivity and RenderNameStyle |
#1984 | Add ResultQuery.fetchOneInto() |
#1986 | Add Record.fromMap() as the inverse operation of Record.intoMap() |
#1987 | Allow for reading data from arrays, Maps through Record.from() |
#1988 | Add Record.fromArray() as the inverse operation of Record.intoArray() |
#1989 | Add Record.changed(Field<?>), changed(int), changed(String) to check whether a single field's value has changed |
#1990 | Add <T> T Record.original(Field<T>), original(int), original(String) to get a Field's original value |
#1991 | Reflect changed flag in Result.toString() (and thus also Record.toString()) |
#1999 | Add Record.changed(boolean) changed(Field<?>, boolean) changed(int, boolean) changed(String, boolean) as setters for the changed flag |
#2000 | Add Record.reset(), reset(Field<?>), reset(int), reset(String) to restore original values in a record |
#2008 | Add elementFormDefault="qualified" to XSD specifications to allow for XML validation of jOOQ configuration files |
#2020 | Let org.jooq.ExecuteListener extend java.util.EventListener |
#2021 | Add UpdatableRecord.refresh(Field<?>...) to allow for refreshing a subset of the Record's values |
#2027 | Document semantic versioning rules as understood by jOOQ |
#2028 | Add Batch.size() to indicate the number of queries that will be executed by a batch operation |
#2030 | Add reusable wrapper types for JDBC Connection, Statement, ResultSet, etc. |
#2044 | Add various TableRecord.fetchParent(...), fetchChild(...) and fetchChildren(...) methods to follow foreign key relationships |
#2049 | Add gt() / ge() / lt() / le() to Row[N] types |
#2052 | Add [not]Between[Symmetric]() to Row[N] types |
#2053 | Add is[Not]Null() to Row[N] types |
#2066 | Add Executor.extractBindValues(QueryPart), extractParams(QueryPart) to extract bind values in the context of an Executor (i.e. Configuration) |
#2072 | Let UDTRecordImpl and ArrayRecordImpl.toString() return a valid constructor expression |
#2078 | Add Postgres to @Support annotation of SelectForUpdateWaitStep.wait() |
#2079 | Support generation of bean validation annotations on records and interfaces |
#2089 | Generate an "empty" DefaultSchema for those databases that do not have any schema (CUBRID, Firebird, SQLite) |
#2094 | Add unit tests for org.jooq.tools.Convert |
#2107 | Let Record implement Comparable |
#2111 | Improve org.jooq.Record Javadoc, to explain the various Record subtypes |
#2112 | Add Row.types() and Row.dataTypes() as a convenience |
#2113 | Document Record.hashCode() and equals() through Javadoc |
#2133 | Allow for mapping <outputSchema/> to "" (empty) in order to avoid the generation of a schema |
#2156 | Add Row.type(int), type(String), dataType(int), dataType(String) for convenience |
#2158 | Add Executor.fetchLazy(Table) and fetchLazy(Table, Condition) for convenience |
#2159 | Let ExecuteListener extend Serializable |
#2160 | Add Executor.batchUpdate(UpdatableRecord<?>...) to mass-update a set of UpdatableRecords |
#2161 | Add Executor.batchInsert(UpdatableRecord<?>...) to mass-insert a set of UpdatableRecords |
#2162 | Add some more Javadoc to JooqLogger |
#2170 | Add 0.0 and 1.0 to Convert.FALSE_VALUES and Convert.TRUE_VALUES |
#2171 | Allow for converting booleans to numbers through org.jooq.tools.Convert: TRUE => 1, FALSE => 0 |
#2172 | Add <T> set(Field<T>, Select<? extends Record1<T>>) methods to UPDATE, MERGE and INSERT statements |
#2176 | Add hint in code generation, when an unsupported, old database version is being used (e.g. MS SQL Server 2000) |
#2177 | Add ResultQuery.intern() and Result.intern() for string interning in result sets |
#2179 | Add Javadoc to QueryPart.hashCode() and equals() |
#2199 | Allow for INSERT and UPDATE of pre-existing records through SET [ Record ] clauses |
#2202 | Add Mock JDBC objects for unit testing with jOOQ |
#2203 | Add Executor.map(Schema) and Executor.map(Table) as a convenience to apply runtime schema mapping |
#2204 | Add BatchBindStep.bind(Object[][]) to bind lots of bind values at a time |
#2205 | Add <R> Result<R> Executor.newResult(Table<R>) to generate custom results |
API changes (backwards-compatible)
#1309 | Let Factory.val() return Param<T> instead of Field<T> |
#2031 | Change union(Select<R>) and similar methods to union(Select<? extends R>) |
#2157 | Change the bounds of various <H extends RecordHandler<R>> H fetchInto(H handler) methods to RecordHandler<? super R> |
#2197 | Relax bounds on Factory.groupingSets(Collection<Field<?>>...) to Collection<? extends Field<?>>... |
#2206 | Relax bounds of R on Executor.newRecord() from TableRecord<R> to Record |
API changes (backwards-incompatible)
#1118 | Remove support for the code generation ant task |
#1254 | Move org.jooq.tools.unsigned contents to org.jooq.types (along with the INTERVAL types) |
#1374 | Relax usage of generic <? extends T>. Replace by <T> where data types are involved. |
#1533 | Extract Executor API from Factory. Let Factory contain only static QueryPart factory methods |
#1549 | Externalise connection lifecycle through new ConnectionProvider |
#1649 | Remove support for code generation from pre-jOOQ 2.0 .properties file |
#1740 | Remove support for generated master data enums |
#1875 | Add generic <R extends Record> type to SelectXXXStep DSL type hierarchy for increased tuple type-safety |
#1887 | Remove all deprecated code |
#1894 | Remove constructors from dialect-specific factories |
#1907 | Remove FactoryOperations, push its API down to org.jooq.impl.Executor |
#1921 | Add <T1, T2, ..., T[N]> InsertValuesStep[N]<R, T1, T2, ..., T[N]> Executor.insertInto(Table<R>, Field<T1>, Field<T2>, ..., Field<TN>) |
#1926 | Add <T1, T2, ..., T[N]> MergeXXXStep<R, T1, T2, ..., T[N]> Executor.mergeInto(Table<?>, Field<T1>, Field<T2>, ..., Field<TN>) |
#1977 | Remove the confusing concept of having a "main key" as opposed to a "primary key" |
#2042 | Remove generated setters, setting foreign key values from records |
#2043 | Remove generated navigation methods |
#2060 | Remove redundant SimpleSelectXXX API |
#2117 | Remove the FieldProvider marker interface. Simplify the FieldProvider API |
#2119 | Rename Row.getDegree() to Row.size() |
Behaviour changes (backwards-incompatible)
#1235 | SQLite BIGINT data type erroneously maps to java.math.BigInteger |
#1578 | Change configuration of ExecuteListeners in Configuration. Listeners instances should be provided, not classes |
#2076 | Stop "supporting" comma-separated regular expressions in the code generator configuration |
#2088 | Do not treat CUBRID "owner" as schema in generated code |
Bug fixes
#1170 | Improve performance on jOOQ's reflection usage |
#1626 | Explicitly implement hashCode() and equals() in some additional QueryParts |
#1886 | Query.bind() has no effect when Query.keepStatement(true) and StatementType.STATIC_STATEMENT are combined |
#1890 | Bad Postgres array serialisation when " or \ characters are contained in a String[] |
#1938 | Improve AbstractField.hashCode() and AbstractTable.hashCode() and similar, as these two are called very often |
#1942 | Inefficient call to String.split() in StringUtils.toCamelCase() leads to non-negligible performance overhead in POJO transformation calls |
#1937 | Inefficient implementations of AbstractDataType.equals() and hashCode() |
#1954 | Bad SQL rendered when combining ORDER BY [ some-function ] with LIMIT .. OFFSET in DB2, SQL Server |
#1958 | Bad SQL rendered for OVER (ORDER BY [ some-function ]) for SQL Server and Sybase |
#1974 | Optimise various Executor.fetchOne() methods, which consume the whole ResultSet before throwing an InvalidResultException |
#1979 | Thread safety issue in org.jooq.impl.FieldList |
#1982 | Change RenderNameStyle.UPPER, LOWER, AS_IS to quote literals if needed |
#1992 | Bad reference to org.jooq.debug.[impl].DebugListener in the manual |
#1993 | Bad code generated when the same table name exists in multiple schemas in SQL Server |
#1995 | Record.original() values aren't updated after a Record.store() operation |
#1997 | Review the manual's tutorial for integrity |
#2001 | Named Params are treated as null literals on right sides of comparisons |
#2007 | Bad type coercion on the right hand side of a comparison predicate, when the left hand side is Field<Object> |
#2011 | Implement some micro-optimisations in DefaultRenderContext |
#2025 | Correctly handle multiple foreign keys defined on the same column |
#2045 | Bad hashCode calculation when Records contain arrays or byte[] |
#2055 | MySQL's UPDATE [t1] JOIN [t2] syntax can cause syntax errors as column references are not fully qualified |
#2057 | Cannot properly extract bind values for LIMIT .. OFFSET clause from a SELECT statement |
#2063 | jOOQ-meta loads Firebird composite unique key columns in wrong order |
#2073 | The code generator's <dateAsTimestamp/> flag doesn't affect Oracle VARRAY and TABLE types |
#2082 | Oracle PIVOT expression doesn't bind any variables of a derived table being pivoted |
#2085 | java.lang.NoSuchMethodError: org.apache.log4j.Logger.isTraceEnabled()Z when logger dependency is missing |
#2086 | SQL syntax error when aliasing outcome of a relational division |
#2091 | CUBRID doesn't really have a NVARCHAR data type |
#2098 | NullPointerException when org.jooq.impl.EnumConverter converts null |
#2104 | SQLite code generation treats multi-column primary keys like multiple single-column unique keys |
#2108 | SQLite returns NULL for val(new Date(0)).add(-1) and some other date time arithmetic expressions |
#2128 | Misleading Javadoc in Factory / Executor.selectCount() |
#2137 | Failure to assign a value to a record pojo for a column with a composite type when using select into. |
#2139 | batchStore with Postgres composite types incorrectly reuses values from the first record. |
#2140 | No table java mapping generated using maven plugin - missing inputSchema in postgres |
#2143 | UnsupportedOperationException when binding UDTRecord in batchStore() for Oracle |
#2144 | Improve AbstractField.equals() and AbstractTable.equals() and similar, as these two are called very often |
#2145 | Improve QueryPartList.removeNulls() as this is called very often |
#2154 | Generated Records should access values by index, not by field, for performance reasons |
#2165 | Add H2 database definitions to the jOOQ-scala module (to prevent compilation errors) |
#2167 | Convert.convert("xx", boolean.class) returns null, instead of false |
#2178 | Improve FieldList. Avoid creating excessive array lists, where simple (immutable) Field<?>[] are sufficient |
#2180 | Optimise DAOImpl by using the new ReflectionMapper instead of calling Record.into() all the time |
#2187 | Change all Javadoc <h3/> tags to <h5/> (To fix Java 7 standard Javadoc style layout issues) |
#2210 | Executor.fetchFromCSV() shouldn't mark resulting records as "changed" |
#2215 | Improve example in the "jOOQ for CRUD" section. Use only columns from the sample database |
#2223 | SQL injection is possible in org.jooq.impl.Val, if client code doesn't correctly enforce generic typesafety, and bind variables are inlined |
#2227 | Field.in(T...) doesn't convert argument values to the Field's type |
Version 2.6.0 - October 26, 2012
This release has a new main feature: the type-safe support for row value expressions also known as tuples - up to a degree of 8. The API is formed in a similar way as pre-existing tuple support in languages like C# or Scala.
jOOQ's Scala integration has also been improved through the new jOOQ-Scala module, which provides some useful implicit defs for operator overloading. Future versions of jOOQ-Scala may experiment with Scala 2.10's Macros
This release also ships with a lot of new deprecation to help you prepare for the upcoming major release.
Minor feature improvements include:
- Lots of new fetchGroups() and intoGroups() methods, thanks to Ivan Dugic
- JDBC execution control support, such as cancel(), maxRows(), queryTimeout()
- Allowing for re-using JDBC PreparedStatement between Query executions
- Support for the SQL standard OVERLAPS predicate
- A new RecordMapper, similar to the existing RecordHandler
Features and improvements
#385 | Allow for keeping open statements in a Query |
#600 | Add support for Oracle / SQL Standard linear regression functions |
#1058 | Add <T1, T2, .. TN> Factory.row(T1, T2, .. TN) and Factory.row( Field<T1>, Field<T2> ... Field<TN>) to allow for creating tuples / rows |
#1077 | Add support for the SQL standard OVERLAPS predicate |
#1245 | Improve formatting for DECIMAL data types in Result.format(). Nicely align the decimal point and reserve space on both sides |
#1484 | Let XJC-generated artefacts implement Cloneable |
#1527 | Support for converting String to java.net.URL, java.net.URI, and java.io.File |
#1674 | Export data types with Result.formatXML() and Result.formatJSON() exports |
#1679 | Add Factory.table(String, QueryPart...) |
#1708 | Add <T, E> Map<T, List<E>> ResultQuery.fetchGroups(Field<T>, Class<E>) |
#1709 | Add Map<Record, Result<R>> ResultQuery.fetchGroups(Field<?>[]) |
#1710 | Add <E> Map<Record, List<E>> ResultQuery.fetchGroups(Field<?>[], Class<E>) |
#1719 | Make logic from ResultQuery.fetchArray() available in Result.intoArray() |
#1728 | Add support for the MySQL COUNT(DISTINCT expr, expr...) aggregate function syntax |
#1744 | Add support for the CUBRID DECR() function |
#1756 | Add RecordMapper<E>, similar to RecordHandler<R>, mapping records to custom types |
#1762 | Add package-info.java to add Javadoc documentation to all packages |
#1766 | Simulate row comparisons where they are not supported |
#1773 | Add a new jOOQ-Scala project and jooq-scala artefactId, to contain jOOQ extensions in the Scala language |
#1782 | Move JAXB bindings out of XSD, in order to support more advanced bindings |
#1783 | Generate @SuppressWarnings("all") in jOOQ-generated artefacts |
#1784 | Enhance the BETWEEN predicate, introducing the AND keyword |
#1810 | Add <T, E> Map<T, E> ResultQuery.fetchMap(Field<T>, Class<E>) and Result.intoMap(Field<T>, Class<E>) |
#1816 | Add support for materialized views in Oracle's code generator |
#1828 | Reduce log level for Factory deserialisation to TRACE |
#1837 | Add support for @java.beans.ConstructorProperties when fetching into immutable POJOs |
#1841 | Add SortField Field.sort(SortOrder) to allow for dynamic sorting |
#1842 | Add Condition Field.compare(Comparator, Field<T>) to allow for dynamic comparisons |
#1844 | Add Table<Record> Table.join(TableLike<?>, JoinType) to allow for dynamic joining |
#1845 | Add Factory.schemaByName(String) for plain SQL schemata |
#1848 | Add Record.changed() to indicate whether a Record contains "dirty" values |
#1849 | Add Record.original() to obtain the originally fetched values from a Record |
#1854 | Add ResultQuery.maxRows(int) to limit the number of actually fetched records |
#1855 | Add Query.cancel() to support for interrupting statements prematurely |
#1856 | Add Query.queryTimeout(int) to support for JDBC's Statement.setQueryTimeout() |
API changes (backwards-compatible)
#1800 | Deprecate AliasProvider |
#1807 | Result.intoArray() declares "throws MappingException", which isn't true |
#1839 | Deprecate the various Result.getValuesAs[Type] and Record.getValueAs[Type] methods |
#1840 | Deprecate org.jooq.Store |
#1866 | Deprecate [Schema-Name]Factory, remove reference to it from the tutorials |
#1869 | Deprecate org.jooq.NamedQueryPart |
#1870 | Deprecate org.jooq.NamedTypeProviderQueryPart |
#1872 | Improve jOOQ's RenderContext pretty printing behaviour |
#1881 | Deprecate ConditionProvider, OrderProvider, LockProvider types |
Bug fixes
#1593 | Factory.field("{1} + {0} + {0}", val(1), val(2)) doesn't work. Cannot re-use / re-order placeholders |
#1720 | Improve performance by using Record.getValue(int) instead of Record.getValue(Field) internally, where more than one value is retrieved from a record |
#1751 | Result.intoResultSet() generates wrong ResultSetMetaData if runtime schema mapping is applied |
#1764 | Add missing @Support({ ... FIREBIRD ... }) annotations |
#1768 | NullPointerException when DAO.fetchOne() returns no record |
#1774 | QueryPart.toString() does not load default settings from classpath |
#1786 | Fix SEQUENCE support for Firebird |
#1791 | Log a table's input/output names, and PK name when generating code |
#1792 | Factory.fieldByName() and tableByName() do not correctly escape quotes |
#1797 | SQL syntax errors when plain SQL contains comments with question marks and SQL is executed as StatementType.STATIC_STATEMENT |
#1802 | Result.into(Table) doesn't work correctly, if the same field name appears twice in Result |
#1806 | Let Record.toString() wrap the record in a temporary Result and call Result.toString() instead |
#1819 | MappingException in Record.into(Class), when POJO setters have applicable names but non-applicable argument types |
#1820 | Cannot fetch into non-public POJO classes. Their members / getters / setters should be made accessible |
#1829 | Factory.execute(String) may cause errors when plain SQL returns results |
#1830 | Allow for passing null or empty arrays to intoMap(Field[]) and intoGroups(Field[]) |
#1850 | Record.equals() returns true as soon as both records hold a "null" value for a given field |
#1860 | Bad Results returned from plain SQL "select *" queries, if several selected columns share the same name |
#1876 | NULL constraint violation when storing a copied record |
Version 2.5.0 - August 26, 2012
Welcome to another great database integration in jOOQ: Firebird! This is one of the more popular open source SQL databases out there, with a rich feature set, including the SQL standard MERGE statement.
Apart from this, the main new features are:
- Optimistic locking. jOOQ's UpdatableRecord API transparently implements optimistic locking on its store() and delete() methods. By default, the in-memory record is compared with the one in the database at write time. But you can also let jOOQ handle incremented VERSION or TIMESTAMP columns for you.
- Oracle feature increment. Many nice Oracle features are now supported: user-defined aggregates, regular expressions, Oracle Text, CONNECT_BY_ROOT and ORDER SIBLINGS BY clausess, partitioned outer joins and more
- jOOQ's convenience API has been greatly enhanced. This includes many improved fetch methods and new short forms for equal=eq, notEqual=ne, greaterThan=gt, etc. to better align jOOQ with JPA, XSL, QueryDSL and many other tools that abbreviate these keywords
- Many types and methods have been deprecated to help you foresee the upcoming changes in jOOQ 3.0
Please consider also the updated manual with its new, more user-friendly structure
Features and improvements
#430 | Add support for the Firebird database |
#457 | Add support for Oracle user-defined AGGREGATE functions |
#620 | Add support for the SQL:2008 standard LIKE_REGEX operator |
#722 | Remove casting of bind values in Ingres |
#727 | Simulate RPAD and LPAD in SQLite |
#816 | Add support for Oracle Text functions |
#1339 | Add option to generate immutable pojos |
#1547 | Support "optimistic locking" in UpdatableRecord.store() and delete() |
#1552 | Generate fetchBy[ColumnName] methods in generated DAO classes |
#1553 | Add some Javadoc to document the difference between using a Factory with a Connection or with a DataSource |
#1556 | Add javax.validation API to full deliverable |
#1565 | Add Factory.connectByRoot(Field<?>) to support the Oracle CONNECT_BY_ROOT pseudo column |
#1570 | Add Factory.condition(String, QueryPart...) similar to Factory.field(String, QueryPart...) |
#1582 | Add support for Oracle's ORDER SIBLINGS BY clause, in combination with CONNECT BY |
#1586 | Add missing constructors taking DataSource to dialect-specific factories |
#1587 | Generate missing constructors taking DataSource in schema-specific factories |
#1595 | Simulate REPEAT() in SQLite |
#1596 | Add support for optimistic locking using generated information about "timestamp" or "version" columns |
#1627 | Handle NULL in CSV imports/exports |
#1645 | Add support for Oracle's PARTITION BY clause in OUTER JOINs |
#1657 | Reorganise the manual |
#1664 | By default, activate <relations/> in the code generator |
#1665 | Add support for the empty GROUP BY () clause |
#1675 | Add support for the SQL standard IS [NOT] DISTINCT FROM predicate |
#1680 | Overload all plain SQL DSL methods to also accept QueryPart arguments |
#1681 | Simulate empty GROUP BY () clause in Sybase ASE and Ingres, joining a dummy table and grouping by a constant field |
#1684 | Add <attachRecords/> Setting to indicate that fetched records shouldn't be automatically "attached" |
#1685 | Improve Javadoc of Attachable.attach(). Document how "detaching" works |
#1688 | Add <E> E Record.into(E) as a complement to <E> E Record.into(Class<E>) |
#1692 | Replace Factory.executeInsert(), Factory.executeUpdate() and similar methods with more succinct variants |
#1696 | Add short versions of comparison predicate methods, such as eq, ne, gt, ge, lt, le |
#1698 | Add support for the SQL standard BETWEEN SYMMETRIC predicate |
#1701 | Add Factory.not(Condition) as a synonym for Condition.not() |
#1704 | Document the behaviour of Factory.newRecord(Table<?>, Object) and Record.from(Object) with respect to UpdatableRecord.store() |
#1707 | Add <K> Map<K, Result<R>> ResultQuery.fetchGroups(Field<K>) and Result.intoGroups(Field<K>) |
#1712 | Add <T extends Comparable<? super T>> Result.sortAsc .sortDesc(Field<T>) |
#1713 | Add <T> Result.sortAsc, .sortDesc(Field<T>, Comparator<? super T>) |
#1714 | Add Result.sortAsc, .sortDesc(Comparator<? super R>) |
#1718 | Document usage of InvalidResultException on the ResultQuery.fetchXXX() Javadocs |
#1721 | Add <K, V> Map<K, List<V>> ResultQuery.fetchGroups(Field<K>, Field<V>) and Result.intoGroups(Field<K>, Field<V>) |
#1722 | ResultQuery.fetchArray(int) and .fetchArray(String) should return a typed array, even if this cannot be checked by the compiler |
#1723 | Add Factory.fetchLazy(ResultSet) |
API changes (backwards-compatible)
#1544 | Remove Attachable interface from QueryPart hierarchy |
#1579 | Deprecate org.jooq.Type |
#1580 | Deprecate org.jooq.SchemaProvider |
#1638 | Deprecate org.jooq.ArrayRecord.createArray() |
#1639 | Deprecate org.jooq.Adapter |
#1687 | Let Cursor.fetchInto(Table<Z>) return Result<Z> instead of List<Z> |
#1736 | Deprecate TableRecord.{store|refresh|delete}Using() methods as being part of jOOQ's internal API |
#1741 | Deprecate org.jooq.MasterDataType |
Bug fixes
#1572 | Use Thread.currentThread().getContextClassLoader() to load ExecuteListener classes as a workaround for experienced class loading problems when using OSGi |
#1584 | Code generation error with Oracle UDT static functions |
#1632 | Improve the performance of various DefaultRenderContext methods, by locally caching Settings values |
#1633 | Improve the performance of CursorImpl.CursorIterator by setting Record values by index rather than by Field |
#1635 | Improve the performance of Factory.fetch(ResultSet) by caching data type normalisation regex in FieldTypeHelper |
#1650 | jOOR Fix #16: Can't call Reflect.create(A, B, null) |
#1660 | Factory.renderContext().castMode(CastMode.NEVER).render(query) doesn't work. CastMode is not applied |
#1667 | Bad variable binding when NULLS FIRST, NULLS LAST is simulated in SQL Server and other databases |
#1673 | Result.formatXML() and Result.intoXML() do not render namespaces correctly |
#1683 | Oracle code generation regression for 10g. No such column ALL_PROCEDURES.OBJECT_ID |
#1693 | Cannot bind UDT values from other schemata to stored procedures |
#1730 | Compilation errors in SQLite generated code when flag <instanceFields/> is set to true |
Version 2.4.0 - July 8, 2012
This release's main new feature is jOOQ's added convenience in Factory initialisation for those users who get their database connectivity through JDBC DataSources. If supplied with a DataSource, a jOOQ Factory will handle the Connection lifecycle internally, closing the Connection when no longer needed.
The H2 MERGE statement syntax is now supported and simulated in other databases, for those users that prefer its more intuitive syntax over the SQL standard.
The code generator now also allows for generating interfaces and DAOs per table. DAO generation was previous discussed on the user group and seen in a competitor product called OneWebSQL.
The jOOQ Console now supports breakpoints for even more effective SQL development
Features and improvements
#1141 | Add Result.intoResultSet() to wrap a Result in a JDBC ResultSet |
#1253 | Avoid JDBC escape syntax for date/time literals |
#1280 | Generate DAO classes and interfaces for POJOs |
#1404 | Document the lifecycle of an ExecuteListener in the Javadoc |
#1411 | Add support for Postgres "any" data type (with quotes!). This seems to map well to java.lang.Object |
#1418 | Support case-insensitive schema names in code generation |
#1419 | Add some WARN-level logging when the source-code generator doesn't generate any artefacts |
#1423 | Add Field.likeIgnoreCase() to support Postgres' ILIKE operator |
#1424 | Add Factory(DataSource) and similar constructors |
#1427 | Add Factory.batchStore(Collection<? extends UpdatableRecord<?>>) for convenience |
#1428 | Add DataType.convert(Object...) and DataType.convert(Collection<?>) for convenience |
#1431 | Add org.jooq.Name Factory.name(String) to contruct QueryParts that are escaped according to Settings.getRenderNameStyle() |
#1432 | Add Factory.fetch(String, QueryPart...) and Factory.execute(String, QueryPart...) and similar methods to support arbitrary QueryParts in plain SQL |
#1434 | Add UniqueKeyDefinition.isPrimaryKey() for completeness |
#1438 | Add Result<Record> Factory.fetchFromCSV(String) |
#1440 | Add top-level pom.xml for jooq-parent artefact (GitHub Issue #14) |
#1446 | Converting arbitrary strings to Number / Date should return null, instead of throwing an exception |
#1449 | Generate some meaningful Javadoc into the generated [schema-name]Factory classes |
#1454 | Add line breaks to generated Javadoc where appropriate |
#1463 | Add option to let generated Record / POJO objects implement a common generated interface |
#1470 | Support interface types in ResultQuery.fetchInto(Class), Result.into(Class), and Record.into(Class) methods, returning a proxy |
#1471 | Upgrade internal jOOR dependency to jOOR 0.9.4 |
#1473 | Add IdentityDefinition to jooq-meta |
#1501 | Add support for conversion of String to java.sql.{Date, Time, Timestamp}. GitHub issue #22 |
#1504 | Document behaviour of fetch() and fetchOne() in case jOOQ cannot fetch actual records |
#1509 | Minor improvements in the generator source code. GitHub pull request #23 |
#1510 | Generate additional setters for foreign keys, accepting records as arguments |
#1521 | Expose Connection methods, such as commit(), rollback() and similar transaction-related methods in Factory |
#1523 | Support ROW_NUMBER() OVER() for the latest version of Derby and H2, which support it |
#1524 | Simulate ROW_NUMBER() OVER() in HSQLDB using ROWNUM() |
#1528 | Let generated interfaces extend Serializable |
#1532 | Clarify the lifecycle of Configuration.data in the Javadoc |
#1534 | Generate more meaningful Javadoc where "an uncommented item" stands now |
#1536 | Add documentation to the FOR UPDATE OF clause, indicating that DB2 may have stricter requirements regarding updatability of fields |
#1541 | Add support for the H2 MERGE syntax - GitHub Issue #18 |
#1542 | Simulate the H2 MERGE syntax in other dialects supporting the SQL standard MERGE statement - GitHub Issue #18 |
#1545 | Website and Documentation anchors should be links to themselves, visually recognisable |
Features and improvements (jOOQ Console)
#1398 | Allow for adding breakpoints in jOOQ Console |
API changes (backwards-compatible)
#1408 | Relax bounds of <R> in Factory.truncate() to Record, instead of TableRecord |
#1429 | Change Convert.convert(List, XXX) to accept Collection instead of List |
Bug fixes
#1020 | Improve Oracle's LIMIT .. OFFSET clause simulation. GitHub Issue #16 |
#1358 | Compilation errors in generated source code when Oracle overloaded procedures collide with procedures that end with numbers |
#1437 | Error in Javadoc of FactoryOperations.fetchOne(). This method may return null |
#1441 | Performance issue with AbstractDataType.convert(Object). Avoid conversions when they're obviously unneeded |
#1448 | Handle String to Enum conversion (when Java Enums are stored as Strings in the database) - GitHub issue #15 |
#1459 | Generated Keys.java static class too large (static initialiser can become bigger than 64kb) |
#1460 | Table.getReferencesTo(Table) doesn't work correctly for aliased tables |
#1461 | Exception when rendering of {fn datetimeadd(...)} for HSQLDB and Derby |
#1462 | Document missing GeneratorStrategy features, such as getJavaClassImplements() |
#1465 | Custom generator strategy's printImplements() is called with Mode == RECORD for tables |
#1478 | Caching SQLDialect in AbstractDatabase heavily improves code generation performance |
#1483 | Inefficient cloning of default settings using JAXB unmarshalling leads to non-negligible overall overhead. Use serialisation instead (short of a useful XJC clone plugin) |
#1489 | Fix manual where it claims to throw SQLExceptions |
#1490 | Compilation error when a SQL Server stored procedure has a parameter named "value" |
#1493 | Bad syntax for SELECT /*+hint*/ DISTINCT ... in Oracle |
#1498 | jOOQ does not compile using JDK 7 / JDBC 4.1. GitHub Issue #24 |
#1499 | Generated members of Tables.java are not final |
#1505 | Bad exception message when ON DUPLICATE KEY IGNORE cannot be simulated |
#1515 | Splitting of large NOT IN conditions is wrong. The parts should be connected with AND, not with OR |
#1522 | fetch().into(Table) doesn't initialise records correctly, such that subsequent calls to store() will execute an INSERT, rather than an UPDATE |
#1525 | Generate missing Javadoc to getters for procedure OUT parameters |
#1529 | Factory.batchStore() logs all single statements to DEBUG output. Find a more accurate log output |
#1537 | Factory.batchStore() renders bad SQL for Postgres. The RETURNING clause is not allowed in batch INSERTs |
Version 2.3.1 - May 11, 2012
This is an important patch release fixing some regressions in the code generator for the Postgres dialect. With 2.3.0, it was no longer possible to generate schemata of which the database user was not the owner.Bug fixes
#1334 | Fix inaccurate simulation of TRUNC(number, decimals) for Derby |
#1403 | Documentation bug: ctx.statement() can be replaced in executeStart(). This is not documented |
#1406 | Compilation errors in generated source code when Postgres stored procedure parameter is called "NAME" |
#1407 | Compilation errors in generated source code when Postgres data-type is "any" (with quotes!) |
#1409 | Postgres code generation broken when not connecting with the owner of a schema |
Version 2.3.0 - May 6, 2012
This is a minor feature increment release, featuring many useful API enhancements, some new functions, some new syntax support elements, improved source code generation and a lot of improvements on the jOOQ Console, thanks to Christopher Deckers.
The updated jOOQ Console now allows for filtering incoming statements directly on the server side, using regular expression filters on statement text and other features. These improvements are a part of a general strategy to introduce breakpoints and more sophisticated debugging capability to the jOOQ Console.
Features and improvements
#597 | Add support for Oracle KEEP (DENSE_RANK FIRST...) aggregate function clause |
#910 | Add ExecuteListener extension to allow for overriding exception translator to handle vendor-specific error codes |
#1286 | Add "renderSchema" flag to Settings, to completely disable rendering of schema names |
#1293 | Generate setter methods for JAXB annotated configuration properties |
#1295 | Add support for MySQL's INSERT IGNORE clause |
#1296 | Simulate the FOR UPDATE clause for SQL Server, CUBRID, using JDBC's ResultSet.CONCUR_UPDATABLE |
#1302 | Add Factory.inline() to allow for flagging inline-only "bind values" |
#1303 | Add connection-less Factory constructors for convenience, when jOOQ is only used as a SQL query builder |
#1304 | Add option to generate JSR-303 @NotNull and @Size annotations to generated POJO's |
#1307 | Let HSQLDB dialect render NVL2() as NVL2() instead of CASE expression |
#1312 | Allow for omitting <inputSchema/>, and generate all available schemata in that case |
#1315 | Let generated factories use their associated Schema as the Settings' RenderMapping's defaultSchema |
#1319 | Move jooq-spring's FactoryProxy to the core jooq project |
#1322 | Add Factory.dateAdd() and timestampAdd() for convenience |
#1327 | Add DataType.isLob() |
#1328 | Add Field<String> inline(char), inline(Character), inline(CharSequence) for convenience |
#1333 | Add support for the Oracle TRUNC function, for numeric arithmetic |
#1336 | Let Record.into(Class<?>) and similar methods accept "immutable" classes, i.e. setter-less classes that take several constructor arguments |
#1340 | Use Constructor.setAccessible(true), if no default constructor is available on the target type of Record.into(Class<?>) |
#1342 | Improve Javadoc on Factory.function(). Document arguments |
#1349 | Add support for the CUBRID Click-Counter INCR() |
#1352 | Allow for creating syntax-error and SQL-injection safe qualifiers for org.jooq.Field and org.jooq.Table |
#1361 | Add Factory.batchStore(TableRecord<?>...), to allow for batch UPDATE/INSERTs of many records |
#1367 | Make configured ExecuteListeners default constructors accessible |
#1366 | Let org.jooq.Batch extend Serializable |
#1378 | Upgrade internal jOOR dependency to jOOR 0.9.3 |
#1379 | Upgrade internal jOOU dependency to jOOU 0.9.1 |
#1390 | Add RenderContext.qualify() to indicate whether QueryParts should render qualified versions of themselves or not |
Features and improvements (jOOQ Console)
#1242 | Upgrade jOOQ Console dependency on RSyntaxTextArea from 1.5 to 2.0.2 |
#1249 | Allow for filtering incoming statements in jOOQ Console |
#1393 | Implement a communication protocol between Console server types and Console client types to allow for more sophisticated functionality |
API changes (backwards-compatible)
#1310 | Deprecate Factory.literal() in favor of Factory.inline(), and Factory.field() |
#1368 | Promote AbstractQuery.isExecutable() to the public API |
Bug fixes
#989 | INSERT and UPDATE statements always render non-qualified, escaped field names. This may cause trouble when using plain SQL fields |
#1109 | Standalone TABLE or VARRAY types are not correctly initialised before referencing tables load them |
#1279 | NullPointerException when leaving <inputSchema/> empty |
#1283 | The LIKE escape character needs escaping, too, in contains(), startsWith(), endsWith() |
#1306 | Add missing INTERVAL data types to HSQLDBDataType |
#1308 | Oracle's DataTypeDefinition reports the length of a BLOB / CLOB data type to be 4000 |
#1313 | <includes/> and <excludes/> match only table names, not fully qualified names |
#1323 | Add support for byte[] in Postgres UDTs |
#1324 | Code generation error in Oracle 10g when generating stored procedures |
#1326 | Error when deserialising BLOBs from Oracle UDTs |
#1329 | NullPointerException when passing null to timestampDiff(Field, Field) |
#1343 | Regression in insertInto(...).values(...). Cannot pass Field<?> to values() |
#1344 | Initialise Result ArrayLists to their expected size, if that size is known. |
#1360 | jOOR issue 12: "Don't reset the accessible flag to false, if setting it to true is required, to avoid race conditions in concurrency contexts" |
#1371 | Missing conversion when using unsafe Field<?> types in BATCH statements |
#1376 | Oracle UDTs in REF CURSORs are not deserialised correctly from procedure OUT parameters |
#1377 | Oracle UDTs are not deserialised correctly when the same UDT name is present in multiple schemata |
#1394 | NullPointerException when omitting <generate/> element in code generation configuration |
Version 2.2.1 - April 12, 2012
This is a minor patch release, fixing some issues related to the code generation of the new CUBRID integration as well as other, minor issues. Upgrade if you're using CUBRID
Bug fixes
#1287 | Remove oracle.sql dependency also from OSGi information in pom.xml |
#1288 | SQL syntax errors from sequences when using RenderMapping with defaultSchema |
#1289 | DefaultBindContext logs as Util.class |
#1297 | Compilation error in CUBRID generated artefacts referencing OBJECT types |
#1298 | Avoid source code generation errors when generating code for unknown, dialect-specific data types |
Version 2.2.0 - April 09, 2012
Finally, jOOQ has added support for another database, and a very promising one, that is. https://www.cubrid.org is a surprisingly original mixture of a relational and object-oriented database where tables and classes are synonyms, so are records and instances. The CUBRID database has a high level of compatibility with MySQL and is aimed at MySQL users wanting more performance for their web applications. For details, see the slides here:
https://www.slideshare.net/cubrid/growing-in-the-wild-the-story-by-cubrid-database-developers
jOOQ is proud to have become a CUBRID partner, looking forward to further cooperation with CUBRID in the near future.
Apart from that, jOOQ now fully supports SQL standard INTERVAL data types. With JDBC and JPA lacking official support for this, jOOQ aims for becoming the tool of choice for vendor-specific date time arithmetic. True INTERVAL data type support is given in HSQLDB, Ingres, Oracle, Postgres databases. Besides that, CUBRID and MySQL support INTERVAL data type arguments in functions. In other dialects, jOOQ simulates DATEADD(), TIMESTAMPADD(), DATEDIFF(), TIMESTAMPDIFF().
For jOOQ's OLAP friends, there is now also support for the Oracle LISTAGG function (LIST() in Sybase, XMLAGG() in DB2, STRING_AGG() in Postgres, GROUP_CONCAT() in CUBRID, H2, HSQLDB, MySQL). LISTAGG is an "ordered aggregate function", meaning that the aggregation is done using a specific ordering. Keep an eye out for more such function support in future versions.
Features and improvements
#566 | Add support for INTERVAL data types |
#585 | Add support for DATE, TIME and INTERVAL arithmetic |
#1183 | Add support for DEFAULT values in Oracle stored procedure parameters |
#1243 | Let generated POJOs (and Records) extend base classes and implement interfaces |
#1252 | Avoid JDBC escape syntax for Oracle stored procedure calls. Generate PL/SQL syntax, instead |
#1255 | Let generated Tables contain a public default constructor to be able to extend those classes - Github issue #12 |
#1257 | Add CUBRID support |
#1268 | Add Factory.field(String, QueryPart...) to generate custom clauses |
#1269 | Add YEAR(), MONTH(), DAY(), HOUR(), MINUTE(), SECOND() function support as shortcuts for EXTRACT() |
#1273 | Simulate GROUP_CONCAT() aggregate function using Oracle's LISTAGG() function, where available |
#1274 | Add support for the Oracle LISTAGG(...) WITHIN GROUP (ORDER BY ..) [ OVER (..) ] aggregate / analytic function |
#1275 | Simulate Sybase LIST() aggregate function using Oracle's LISTAGG() function |
#1276 | Simulate Oracle's LISTAGG() in DB2 using XMLAGG(), SUBSTR() and CONCAT() |
#1278 | DEBUG log both executed SQL and SQL with inlined bind values |
API changes (backwards-compatible)
#1262 | Pull up OracleFactory.prior() and other CONNECT BY related methods to Factory |
Bug fixes
#1241 | Wrong variable binding when comparing CHAR columns in Derby and DB2 without explicit casting to VARCHAR |
#1244 | Cannot override class name in GeneratorStrategy in Mode.POJO |
#1248 | Setting both <records>false</records> and <relations>true</relations> leads to compilation errors |
#1256 | Fixed code generation issue with H2 user defined functions returning VARCHAR |
#1263 | Pass fetchsizes <= 0 to the JDBC driver (for vendor- specific MySQL compatibility) |
#1270 | Most databases allow for multiple identical foreign keys. This leads to compilation errors in generated source code |
Version 2.1.0 - March 18, 2012
With this version, jOOQ attempts to follow versioning rules imposed by semantic versioning: https://semver.org/ There will be 1 minor release per month, and a couple of patch releases per year, depending on popular demand
The main improvements for this release include
- The possibility of providing jOOQ with a custom type mapping. You can now define your own Converter types that are used by jOOQ to map a database's SQLDataTypes to your custom types. This is particularly useful for Java's enums. Read more about custom converters in the manual: https://www.jooq.org/manual/ADVANCED/CustomTypes/
- There are a lot of new runtime configuration options to control the SQL style of SQL rendered by jOOQ. You can now specify whether table/column names should be quoted / capitalised / lower-cased, whether SQL keywords should be capitalised or not, etc...
- The handling of NULL has been improved in favour of using jOOQ as a SQL builder library (e.g. along with Spring for execution) NULL is no longer inlined, but bound as a variable.
- jOOQ now supports simulation of the relational division operation using an intuitive syntax. Read more about the relational division here: https://en.wikipedia.org/wiki/Relational_algebra#Division
Features and improvements
#161 | Add runtime configuration to pretty print rendered SQL |
#349 | Add SQLite relations support |
#491 | Add runtime configuration for SQL keyword style (upper case, lower case) |
#521 | Add runtime configuration for SQL reference style (upper case, lower case, as-is, quoted) |
#1150 | Add code generation option to disable generation of records |
#1181 | Add support for SQL Server data types timestamp and rowversion |
#1188 | Load default Settings from the classpath at /jooq-settings.xml, or from -Dorg.jooq.settings |
#1193 | Specify main-class in jOOQ Console's manifest.mf and include dependency in jar file |
#1194 | Add ColumnDefinition.isNullable() |
#1202 | Add support for the relational division operation: A.divideBy(B).on(A.ID.equal(B.A_ID)).returning(A.X, ...) |
#1207 | Add Factory.batch(Collection<? extends Query>) for convenience |
#1208 | Render @javax.persistence.Column(nullable = false) property, if available |
#1209 | Render @javax.persistence.Column(length, precision, scale) properties, if available |
#1215 | Add org.jooq.Converter<T, U> for custom type mapping |
#1216 | Overload Record, Result.getValue() and .setValue() methods to accept a Converter |
#1217 | Add EnumConverter as a base type for custom enum converters |
#1218 | Add code generation options to generate <customTypes/> referencing a Java type and a Converter |
#1224 | Add DataTypeDefinition.getLength() to jooq-meta's type system |
#1233 | Support custom JDBC properties for jooq-codegen |
#1234 | Add Database.getTable(SchemaDefinition, String, boolean) to fetch tables case-insensitively |
#1239 | Add Factory.fetchLazy(String, Object...) |
API changes (backwards-compatible)
#1191 | Deprecate ConfigurationRegistry and replace by equivalent ExecuteListener feature |
#1219 | API Bug: Cannot use LIMIT .. OFFSET along with FOR UPDATE |
Bug fixes
#625 | Remove dependency from generated Routines to the generator's SQLDialect |
#1128 | NULL is inlined in INSERT statement instead of binding it as a variable. This can cause issues when using jOOQ with Spring |
#1137 | Exclude MySQL column-level enum types when that column is overridden by a <forcedType/> |
#1158 | Derby cannot handle inlined NULL literals in some contexts |
#1180 | Execute BatchMultiple (multi-query batch query), when executing BatchSimple (single-query, multi-bind-value query) with StatementType == STATIC_STATEMENT |
#1189 | TableMapping regression for SQLite database |
#1190 | Cannot store SQLite records when using StatementType.STATIC_STATEMENT |
#1199 | Table.getFields() returns an internal representation of a table's field list. Make generated tables immutable! |
#1200 | Internal API leak exposed through covariance in AbstractType.getFields() |
#1211 | Enforce method name disambiguation also when using custom strategies in jooq-codegen |
#1212 | Enforce identifier disambiguation also when using custom strategies in jooq-codegen |
#1221 | Incorrect ExecuteListener invocation for INSERT .. RETURNING. executeStart() and executeEnd() are omitted |
#1223 | Cache ExecuteListener classes for performance |
#1225 | Bind NULL byte[] as java.sql.Types.BINARY instead of BLOB in Postgres, to avoid errors |
#1226 | Bind NULL UDTs with their associated type name in Oracle |
#1232 | SQLException when Factory.fetch() does not return a ResultSet |
#1237 | Don't generate enum classes for columns in MySQL tables that are excluded from code generation |
Version 2.0.5 - February 26, 2012
This release finally introduced basic runtime configuration features for the jOOQ Factory. This configuration now includes:
- Execute listener and SQL tracing support. jOOQ allows you to hook your own listeners into jOOQ's query execution engine to be notified of all sorts of events
- The existing SchemaMapping features. They are now part of the runtime configuration
- StatementType settings. Specify whether a Factory should execute java.sql.PreparedStatements (with bind variables) or static java.sql.Statements with inlined variables.
The runtime configuration is documented here:
https://www.jooq.org/manual/JOOQ/Factory/
The listener and tracing support has been requested by Christopher Deckers, a new jOOQ user who has had the courtesy to contribute the new jOOQ Console, which is documented here:
https://www.jooq.org/manual/ADVANCED/ExecuteListener/
Apart from that, another long-requested feature is now fully implemented: The GeneratorStrategy, allowing for custom naming strategies in generated source code. This will allow for generating custom table / record class name prefixes / suffixes, as well as overriding the default behaviour for rendering UPPER, lower and CamelCase artefacts. See the manual for details:
https://www.jooq.org/manual/META/Configuration/
Features and improvements
#93 | Add Field.equalIgnoreCase(), Field.notEqualIgnoreCase() |
#408 | Add class prefixes, suffixes and other options to the code generator |
#492 | Add runtime configuration |
#1107 | Let Field.contains() support the Postgres ARRAY @> ARRAY operator |
#1140 | Add ResultQuery.fetchResultSet() to return the underlying JDBC result set |
#1143 | Add Result.isNotEmpty() for convenience |
#1145 | Add runtime configuration to specify whether jOOQ should execute java.sql.PreparedStatement (with bind variables) or a java.sql.Statement (with inlined parameters) |
#1146 | Add Query.getSQL(boolean) to indicate that bind values should be inlined (as a convenience for Factory.renderInlined(QueryPart)) |
#1148 | Add Cursor.resultSet() to expose the underlying ResultSet |
#1149 | Allow for optional https://www.jooq.org/xsd/jooq-codegen-2.0.4.xsd namespace in jooq-codegen configuration |
#1152 | Add <E extends java.lang.Enum<E> & org.jooq.EnumType> E MySQLFactory.enumType(Class<E>, int) for enum reverse lookups of MySQL-specific enums |
#1159 | Support matching numbers with LIKE, e.g. ID LIKE '%33%' |
#1160 | Implement Field.contains(), .startsWith(), .endsWith() for numeric values, too |
#1161 | Use reflection to remove compile-time dependency on ojdbc for creating ARRAYs |
#1162 | Integrate jOOR into jOOQ for simpler reflection |
#1164 | Distinguish between Definition.getInputName(), .getOutputName() |
#1165 | Add constraint name to generated javadoc |
#1167 | Trivial issue with org.jooq.Factory.exists Javadoc - GitHub issue #10 |
#1169 | Add Configuration.setData(), getData() to convey custom data in a configuration's lifecycle |
#1172 | Add runtime configuration to deactivate JooqLogger |
#1177 | Add jOOQ-Console module to jOOQ |
#1184 | Add DataType.isArray() |
API changes (backwards-compatible)
#1142 | Rename Result.exportXML() to Result.intoXML() to stay more consistent |
#1151 | Deprecate SchemaMapping in favour of new runtime configuration |
Bug fixes
#978 | Schema.getTables() and similar methods return empty lists when Schema is mapped with SchemaMapping |
#1153 | Bad inlining of booleans in Sybase ASE / DB2 / Oracle SQL Server / SQLite |
#1154 | Bad inlining of byte[] in most dialects |
#1155 | byte[] are erroneously converted to String when using Record.intoArray() |
#1156 | Bad inlining of DATE / TIME / TIMESTAMP data types in Ingres (and other dialects, when the setting differs from the default) |
#1166 | Some generated Javadoc uses naming strategy or plain output name, instead of qualified output name |
#1168 | Oracle packages are generated as static, instead of static final |
#1175 | Factory.use() seems to render SQL with the Schema name still present |
#1179 | Oracle-generated ArrayRecords need a reference to org.jooq.Schema to read TABLE of OBJECT from stored procedures |
Test cases
#1147 | Add integration tests for executing SQL generated using Factory.renderInlined() |
Version 2.0.4 - February 12, 2012
This release introduced many improvements to source code generation. These improvements include:
- Maven and standalone code generation now use the same XML configuration, which is read by jOOQ-codegen using JAXB. This allows for more complex configuration elements in the future
- jOOQ-codegen can now handle multi-schema databases and generate code for tables referencing tables from other schemata. This is integration tested against the SQL Server AdventureWorks database
- jOOQ now allows to generate simple POJOs in addition to Records and to annotate both POJOs and Records with JPA annotations such as @Entity, @Table, @Id, @Column, @UniqueConstraint, etc.
You can migrate your existing .properties configuration by running > org.jooq.util.GenerationTool /your.properties migrate
Besides that, there is a lot of ongoing work to improve the integration of Oracle's TABLE and VARRAY types.
Features and improvements
#8 | Add JPA annotations to generated POJOs / Records |
#282 | Add support for multi-schema databases |
#287 | Add support for Oracle TABLE types |
#395 | Use XML configuration file instead of properties file |
#1089 | Add Field.contains(), .startsWith(), .endsWith() as a convenience for Field.like() (including escaping) |
#1092 | Move master data table configuration from generator.generate to generator.database namespace |
#1093 | Add support for generator.strategy in Maven source code generation |
#1094 | Add support for generator.database.date-as-timestamp in Maven source code generation |
#1095 | Move generator.generate.unsigned-types to generator.database namespace |
#1096 | Add support for generator.generate.unsigned-types in Maven source code generation |
#1103 | Add support for SQL Server data type uniqueidentifier |
#1106 | Add Factory.escape(Field<String>, char) for use with LIKE |
#1108 | Add support for multi-schema databases using Maven code generation |
#1115 | Add support for Oracle VARRAY/TABLE of OBJECT types |
#1127 | Add support for POJO classes generation |
#1129 | Allow for using Param in LIMIT .. OFFSET clauses |
#1132 | Add RenderContext.castMode() to allow for avoiding casts where this is not really needed |
#1136 | Add generation option to enable/disable generating navigation methods |
Bug fixes
#1099 | Derby generated artefacts are not sorted alphabetically |
#1101 | Internal API leak exposed through covariance in AbstractTable.joinXXX() methods |
#1110 | VARRAY element type information is lost when unnesting VARRAY's in Oracle |
#1111 | VARRAY element type information is lost when unnesting VARRAY's returned from functions in Oracle |
#1114 | Syntax error when unnesting TABLE of OBJECT in Oracle. The unnested table contains several columns but jOOQ only unnests "COLUMN_VALUE" |
#1117 | NullPointerException when passing an ArrayRecord containing a null array to a stored function in Oracle |
#1125 | Postgres needs casting for date time data types in queries like SELECT ? FROM DUAL |
#1131 | DB2: [Noauthorized routine named "LIKE" of type "FUNCTION" having compatible arguments was found] when using Field.like(concat(x, y)) |
#1133 | Compilation errors in generated source code if the same constraint name exists in several schemata |
#1134 | NullPointerException in code generation when a foreign key constraint references a table from another schema that is not being generated |
#1135 | Generated Javadoc references inputSchema instead of outputSchema |
Test cases
#1009 | Add more integration tests for proper handling of java.sql.Date, Time, Timestamp |
#1090 | Run jOOQ tests against AdventureWorks SQL Server sample database |
#1105 | Add integration tests for multi-schema source code generation and querying |
#1122 | The 10k lines of integration test code are too heavy for the compiler. Create test modules with fewer lines of code, each. |
Version 2.0.3 - January 29, 2012
This release focuses on increased compatibility between various SQL dialect integrations as far as ARRAY and JOIN support is concerned:
- ARRAY types are only available in H2, HSQLDB, Oracle, Postgres. Nevertheless, they can be somewhat simulated in other dialects using nested selects with UNION ALL. Increased compatibility leads to a nicer API, where ARRAYs are used along with ALL/ANY quantifiers, for instance.
- JOIN syntaxes can be quite powerful in SQL. Apart from simulating NATURAL JOIN, JOIN USING clauses, as well as a synthetic "KEY JOIN" syntax, jOOQ now also supports nesting JOIN expressions to create more complex table sources. See a recent blog post on the subject here:
https://blog.jooq.org/lets-revise-the-sql-from-clause/
Features and improvements
#578 | Add KEY JOIN syntax to simulate joining using generated foreign keys |
#577 | Simulate NATURAL JOIN syntax, where this is unavailable |
#582 | Simulate JOIN USING syntax, where this is unavailable |
#671 | Allow for nesting JOIN clauses |
#676 | Add Table.join() methods to create more flexible table sources |
#993 | Add Field.equalAny(T[]), .equalAny(Field<T[]>) methods |
#1048 | Simulate <op> <quantifier> (array) syntax for dialects that do not support arrays |
#1051 | Add Factory.execute(String, Object...) as a convenience method for Factory.query(...).execute() |
#1055 | Simulate Factory.table(Object[]) and table(List<?>) using UNION ALL in dialects that do not support arrays |
#1060 | Improve debug logging of H2 arrays. The syntax is not ARRAY[1, 2], but (1, 2) |
#1065 | Add OracleFactory.sysContext(String, String) to support Oracle's SYS_CONTEXT function |
#1069 | Add support for INSERT INTO table(field1, field2, ...) SELECT syntax - as opposed to the existing INSERT INTO table SELECT |
#1072 | Add support for LIKE .. ESCAPE .. syntax |
#1074 | Add Field.notBetween(T, T) for convenience |
#1080 | Add support for JDBC's Statement.setFetchSize() in ResultQuery.fetchLazy() |
#1082 | Add some more DEBUG logging in AbstractResultQuery |
API changes (backwards-compatible)
#1059 | Change SelectFromStep.from(Collection<TableLike<?>>) to from(Collection<? extends TableLike<?>>) |
API changes (backwards-incompatible)
#1087 | Change the NTILE function to return Field<Integer> instead of Field<BigDecimal> |
Bug fixes
#1071 | Make Sequence Serializable |
#1081 | Derby error in NULL handling when simulating unnested arrays that contain NULL values |
#1084 | Bind index mismatch in val(null).equal(null) and in val(null).notEqual(null) |
#1091 | Add missing @Support annotations on Table.crossJoin() methods |
Test cases
#1026 | Add integration tests for NTILE window function and document compatibility |
#1073 | Add integration tests for NOT IN queries holding NULL arguments |
Version 2.0.2 - January 8, 2012
This is a maintenance release for jOOQ 2.0. The main improvements include
- The whole jOOQ API is now annotated with a new org.jooq.Support annotation to help you assess whether a certain SQL clause is available in your database or not. This is particularly useful when your application should support several databases at once (e.g. MySQL, Postgres, Oracle)
- The Oracle PIVOT clause is now formally supported for advanced statistical queries in Oracle. This clause will be simulated in other dialects in the future.
- The DATE data type can be mapped to TIMESTAMP. This important when you query a legacy Oracle database, where DATE columns can also contain time information
- Several convenience methods have been added for more fluent syntax, when using plain SQL result queries, subqueries as tables, or when unnesting arrays in ANY() and ALL() quantifiers
Features and improvements
#595 | Add support for Oracle's PIVOT clause |
#869 | Add support for using ANY, ALL with arrays, not just with subselects |
#1007 | Formally document the API methods to indicate whether something is supported by any given SQL dialect |
#1011 | Add code generation configuration parameter to avoid generating @Generated annotation |
#1019 | Render LIMIT x OFFSET y also for MySQL, instead of LIMIT y, x |
#1022 | Add missing Sybase ASE implementation for Factory.use() |
#1024 | Add Factory.resultQuery(String, Object...) to allow for arbitrary execution modes of plain SQL queries (lazy, later, into, array, etc) |
#1025 | Add missing SQLite implementation for Factory.deg() and Factory.rad() |
#1033 | Generate table comments into generated Tables.java as Javadoc |
#1040 | Add Object[][] Result.intoArray() and Object[] Record.intoArray() for convenience. Let <E> E Record.into(Class<E>) also support array types. |
#1041 | Add <R> Table<R> Factory.table(Select<R>) convenience method for more fluency |
#1042 | Add support for DISTINCT keyword in SUM, AVG, MIN, MAX aggregate functions |
#1046 | Generate Ingres table and column comments in generated source code (only Ingres 10) |
API changes (backwards-compatible)
#1050 | Deprecate usage of SOME quantifier in predicates, such as equalSome() |
API changes (backwards-incompatible)
#1036 | Fixed API typo in WindowsRowsStep.rowsBetweenUnboundedFollwing() |
#1037 | The fluent API allows for JOIN clauses without FROM clause |
Bug fixes
#1010 | The MERGE INTO .. WHEN NOT MATCHED THEN INSERT .. syntax may cause type-safety issues in some databases. VALUES should be converted before binding |
#1014 | FindBugs: Latent risk of infinite recursion due to typo in QueryPartList.retainAll(); |
#1015 | FindBugs: 7 occurrences of "Bad attempt to compute absolute value of signed 32-bit hashcode". In extreme cases, this could lead to SQL syntax errors |
#1016 | The Oracle CONNECT BY cond1 AND cond2 syntax erroneously creates a WHERE cond2 CONNECT BY cond1 statement |
#1028 | Syntax errors when using untyped param() in HSQLDB (and other strongly typed dialects) |
#1029 | Postgres can't bind NULL values in cases, where bind type is Object.class and bind value was created with Factory.param() |
#1030 | UnsupportedOperationException when calling Query.bind(int, Object) on a query containing plain SQL fields |
#1031 | Incorrect debug logging when plain SQL QueryParts like field("?") bind null values |
#1032 | Incorrect debug logging when plain SQL QueryParts contain String literals, such as 'Hello? Anyobody out there?' |
#1047 | Field.notEqualAny() erroneously renders <> ALL() |
Test cases
#1021 | Add explicit integration tests for LEFT|RIGHT|FULL OUTER JOIN |
Version 2.0.1 - December 23, 2011
This is a maintenance release for jOOQ 2.0. The main improvements include
- Better integration for using jOOQ with Spring Data. This includes support for named parameters, as well as allowing to change bind values on previously constructed Query objects
- The MERGE statement has been enhanced for better integration with Oracle.
- jOOQ is now ready to use with Scala / Groovy
For more information about using jOOQ with Scala, see this blog post: https://blog.jooq.org/the-ultimate-sql-dsl-jooq-in-scala/
There is now also experimental support for a custom type mapping. This mapping allows to rewrite data types at code generation time as well as to specify custom enum data types (e.g. boolean Y/N). Not all integration tests run smoothly for custom data types, hence, this feature is not yet fully supported.
Features and improvements
#691 | Add support for Oracle CURSOR REF IN / INOUT parameters |
#677 | Add type-mapping configuration, enforcing types for columns |
#947 | Add custom type mapping support (experimental) |
#968 | Allow for custom enum types, configured in the code generator (experimental) |
#974 | Add Schema.getTable(String), getSequence(String), getUDT(String) for better runtime Schema meta-navigation |
#975 | Add Sequence.getName(), getSchema(), getDataType() |
#980 | Add support for named parameters, to better interact with Spring |
#991 | Add Query.bind(String, Object) and bind(int, Object) to easily modify existing bind values |
#992 | Document thrown DataTypeException in Convert methods |
#998 | Enhance MERGE statement for Oracle extensions: WHEN MATCHED THEN UPDATE .. WHERE .. DELETE WHERE .. WHEN NOT MATCHED THEN INSERT .. WHERE .. |
#1000 | Add support for MySQL's INSERT INTO .. SET .. syntax in MERGE statement's WHEN NOT MATCHED THEN INSERT clause |
API changes (backwards-compatible)
#981 | Cannot insertInto(table("my_table")), as plain SQL tables return Table<Record>, not Table<TableRecord>. Relax bound on R |
#988 | Change Factory.field(String) to return Field<Object> instead of Field<?> |
#999 | Make MERGE's WHEN MATCHED .. and WHEN NOT MATCHED .. clauses optional |
#1001 | Identity.getField() should return TableField<R, T> instead of Field<T> |
#1006 | Add Factory.value(...) as a synonym for Factory.val(...) for increased Scala / Groovy compatibility |
Bug fixes
#973 | EnumType renders name() instead of getLiteral() in formatXXX() methods |
#977 | EnumType renders name() instead of getLiteral() in Convert.convert() method |
#979 | Record.from() sets all changed flags to true. That's not necessarily correct in the event of storing the record back to the DB |
#985 | AbstractRecord.equals() does not correctly compare arrays. Compare them using Arrays.asList() |
#986 | Postgres / DB2 / Sybase ASE foreign-key namespace is unique-per-table. jOOQ forces all foreign keys from all tables into the same namespace |
#990 | Problems when encoding arbitrary byte[] as String(byte[]) in inlined SQL. This can cause issues when DEBUG-level logging is activated |
#995 | Routines don't respect SchemaMapping - Github issue #8 |
#1002 | TableRecord.storeUsing() doesn't update IDENTITY column values, if the column is not part of the main unique key |
#1003 | Sybase / SQL Server / MySQL / Ingres / H2 / Derby's INSERT .. RETURNING simulation returns null if a table has an IDENTITY column, but no primary/unique key |
#1005 | The INSERT INTO .. VALUES .. syntax may cause type-safety issues in some databases. VALUES should be converted before binding |
Test cases
#984 | Detach IDENTITY column tests from UNIQUE KEY tests, create a dedicated test suite instead |
Version 2.0.0 - November 25, 2011
This release is a fresh start in many areas of jOOQ, adressing issues that have been requested by users for a long time. These release notes docment the most important changes, a detailed upgrade guide, as well as the detailed list of improvements.Most important changes
- The API became more static. This applies to many Factory methods, such as val(), literal(), as well as to many Field methods that have been moved over to the Factory. For example, when before, you wrote this using "postfix function notation":
NAME.replace(" ", "_").trim()
you will now write (just as in SQL):
trim(replace(NAME, " ", "_"))
Using static imports of Factory.*, jOOQ makes SQL look even more like SQL. The current "postfix notation" is maintained for backwards compatibility.
- By default, jooq-codegen will now generate a "dynamic" meta model as opposed to the existing static one. Generated tables covariantly override the as(String) aliasing method, leading to a much more convenient aliasing style. When before, you wrote:
Table<TRecord> parent = T.as("parent"); Table<TRecord> child = T.as("child"); Condition join = parent.getField("ID").equal(child.getField("PARENT_ID"))
You can now write:
T parent = T.as("parent"); T child = T.as("child"); Condition join = parent.ID.equal(child.PARENT_ID)
Of course, the existing notation still works
- Exceptions are no longer checked. When previously, the DB's SQLException was propagated to client code, there is now an unchecked DataAccessException hierarchy, similar to that of Spring. This will eventually give way to a standardised error handling abstraction, in future developments.
- Window functions are now constructed from their underlying aggregate functions just like in SQL. For example:
sum(AMOUNT) sum(AMOUNT).over().partitionBy(ACCOUNT)
This makes for a more concise API, especially when considering future extensions, such as Oracle's KEEP (DENSE_RANK FIRST...) syntax.
- More type safety has been introduced regarding various places where generic <R extends Record> and <T> types are involved. This is especially true for INSERT / UPDATE / DELETE statements
- Sequences now also have a <T> type
- Unsigned number types are now supported in those databases that use them. Unsigned numbers are implemented in jOOU, a spin-off open source project. For convenience, this library is "internalised" into jOOQ, to avoid adding a dependency
http://code.google.com/p/joou/
Upgrade instructions:
Various of the above changes are incompatible with jOOQ 1.x. In order to upgrade, please be aware of the following pitfalls:- The schema needs to be re-generated.
- Much of the post-fix function notation is replaced by static methods in the Factory. Today's org.jooq.Field API is maintained in jOOQ 2.0, for backwards compatibility. It will be removed, eventually, though. Expect some incompatible changes, where window functions are involved
- Some Factory instance methods (such as val(), literal()) are now static. They are compatible, but may cause compiler warnings.
- The meta model is now an instance model by default. If you prefer the static meta model, you can configure this in your jooq-codegen configuration.
- The additional typesafety involving <R> and <T> types may cause compiler warnings and errors.
- SQLException is no longer part of the API. This can cause compiler issues, in particular when extending jOOQ
- Some utility classes have moved to org.jooq.tools
Should these incompatibilities be too significant for your project, you can still stay on the 1.x branch, which will be maintained for a while. Be aware that upgrading might be more difficult, later, though.
Features and improvements
#55 | Implement improved exception handling |
#117 | Improve DSL support for field and table aliasing (decrease verbosity) |
#519 | Add support for MySQL UNSIGNED numeric types |
#626 | Create static function access |
#661 | Add support for bitwise operators |
#718 | Sequences should be mapped to appropriate type (e.g. SMALLINT, INT, BIGINT, etc) |
#734 | Add support for Oracle / SQL Server CUBE() and ROLLUP() grouping functions |
#751 | Add support for Oracle / SQL Server GROUPING SETS() function |
#799 | Add support for Oracle PL/SQL's object-oriented MEMBER PROCEDURES and MEMBER FUNCTIONS |
#804 | Add <R extends Record> to Insert, Update, Delete |
#835 | Review API typesafety for <T> InsertSetMoreStep set(Field<T>, T) and similar methods |
#890 | Add Factory.selectCount() convenience method |
#891 | Let min() max(), etc functions return a new type AggregateFunction. This type can then be used as an entry- point for window functions |
#892 | Add support for Oracle / SQL Server GROUPING() and GROUPING_ID() functions to be used along with CUBE() and ROLLUP() |
#893 | Simulate ROLLUP() function for MySQL, using the WITH ROLLUP grouping modifier |
#894 | Move functions from Field<?> to org.jooq.impl.Factory and make them static |
#895 | Add power(..., Field<? extends Number>) |
#897 | Add (experimental) Spring integration project |
#898 | Replace usage of checked SQLException by an unchecked DataAccessException, similar to that of Spring |
#899 | Build jOOQ .jar files as bundles to be deployed into OSGI environments |
#900 | Purge deprecated API - Prior to 2.0 |
#901 | Introduce InvalidResultException as a subtype of DataAccessException for integrity checks in methods like ResultQuery#fetchOne(), ResultQuery#fetchMap(), etc. |
#902 | Make AggregateFunction the base type for constructing window functions |
#904 | Move SQLDialectNotSupportedException into org.jooq.exception package |
#905 | Introduce MappingException as a subtype of DataAccessException for integrity checks in methods like ResultQuery#fetchInto(), etc. |
#907 | Add missing Field.like(Field<T>), notLike(Field<T>) methods to overload the existing Field.like(T), notLike(T) |
#908 | Change rpad / lpad functions to accept String instead of char |
#912 | Add <R extends Record> R newRecord(Table<R>, Object) as the inverse of various into(Class<?>) methods |
#916 | Add <R extends TableRecord<R>> {Record.into(Table<R>) | Result.into(Table<R>) | ResultQuery.fetchInto(Table<R>) | Cursor.fetchInto(Table<R>)} |
#917 | Add various Cursor.fetchOneInto() convenience methods |
#918 | Add CustomTable, CustomRecord as base classes for more convenience when used with various into(Table) methods |
#919 | Allow for accessing non-public constructors of Record subtypes |
#923 | Move some utilities to org.jooq.tools |
#924 | Generate a reference to every table in a new Tables.java class for improved static access |
#928 | Add DataTypeException extending DataAccessException in case something went wrong when converting data types |
#930 | Support converting date time types to java.util.Calendar. This applies to various into(Class<?>) methods, as well as Result.getValue(xx, Class<?>) |
#931 | Allow for conversion between Long and date/time types, and vice versa |
#932 | Let the bound of R in TableRecord extend TableRecord<R>, in UpdatableRecord to extend UpdatableRecord<R> |
#933 | Add support for type Character in Record.into(Class<?>) methods and similar |
#936 | Accept primitive types, such as int.class for type conversion |
#938 | CODEGEN: Add static/instance table field configuration |
#939 | Include license.txt and readme.txt in .jar files' META-INF directory |
#953 | Make DefaultGeneratorStrategy methods non-final to allow for overriding |
#954 | Add examples for source code generation of multiple schemata with Maven |
#955 | Generate a reference to every type in a new UDTs.java class |
#957 | Add <R> R Factory.newRecord(UDT<R>) for constructing attached UDTRecords |
#958 | CODEGEN: Add generation-time schema mapping, allowing for re-writing schemata in jooq-codegen |
#960 | CODEGEN: Add code generation configuration parameter to avoid using the new UByte, UShort, UInteger, ULong wrappers for UNSIGNED number types |
#961 | Use Oracle's SYS.ALL_SEQUENCES.MAX_VALUE to determine the type of a sequence. |
#969 | Add <T> List<T> ResultQuery.fetch(Field<?>, Class<? extends T>) convenience method |
Bug fixes
#686 | Reduce the internal API leak by preventing access to TableFieldImpl, UDTFieldImpl, ParameterImpl |
#903 | lag(Field, int, T) erroneously delegates to lead() |
#906 | Add more NullPointerException safety to API |
#913 | NoClassDefFoundError in JooqUtil.isJPAAvailable() |
#920 | Generic type is lost in Cursor.fetchInto(RecordHandler) |
#925 | SelectConditionStep should extend SelectConnectByStep, not SelectGroupByStep |
#926 | AbstractRecord.into() fails to convert java.sql.Date into java.util.Date |
#934 | Don't consider static members in reflection utilities when used with Record.into(Class<?>) and similar methods |
#935 | Don't consider final member fields in reflection utilities when used with Record.into(Class<?>) and similar methods |
#937 | In the event of name clash (same name for table and field) generated code has errors |
#945 | Calling UpdatableRecord.setValue() twice with the same argument causes the changed flag to be reset to false |
#948 | Always set the changed flag to true in Record.setValue() |
#959 | Compilation errors in generated source code if MySQL enum values match Java reserved words, such as 'true', 'false', 'new', etc... |
#962 | Postgres ordering of generated enum literals is unstable |
#967 | Better document type conversion |
Version 1.7.0 - November 25, 2011
This is a maintenance release for the 1.x branch. Some important bug fixes are merged from version 2.0. These include:Bug fixes
#925 | SelectConditionStep should extend SelectConnectByStep, not SelectGroupByStep |
#926 | AbstractRecord.into() fails to convert java.sql.Date into java.util.Date |
#937 | In the event of name clash (same name for table and field) generated code has errors |
#945 | Calling UpdatableRecord.setValue() twice with the same argument causes the changed flag to be reset to false |
#948 | Always set the changed flag to true in Record.setValue() |
#951 | Empty Password for jooq-codegen-maven causes NPE |
Version 1.6.9 - November 7, 2011
This is a maintenance release for the 1.x branch. Developments on this branch will stop after version 1.6.9. Only important bug fixes are merged to this branch. Developments for release 2.0 have started.The most important functionality in release 1.6.9 is the newly added support for JDBC batch operations. You can now batch execute several queries.
See the official blog for more information: https://blog.jooq.org/jdbc-batch-operations-with-jooq/
Features and improvements
#621 | Add support for JDBC batch operations |
#794 | Add support for ORDER BY [int value] in order to reference a column index for sorting |
#882 | Optimise Field.isTrue() and isFalse(). Take Field's data type into consideration. |
#885 | Add support for INSERT INTO .. VALUES (..) syntax, omitting explicit field declarations |
#887 | Add <E> List<E> Cursor.fetchInto(Class<E>) |
Bug fixes
#748 | H2 regression in 1.3.158 regarding stored functions, which return a ResultSet (this was fixed in H2) |
#859 | Derby casting of numeric types to BOOLEAN doesn't work |
#886 | Regression in date extract function when used in a subselect |
#888 | Derby casting of VARCHAR to FLOAT (and similar) doesn't work |
Version 1.6.8 - October 22, 2011
The main improvement of this release is the re-design of the stored procedure / function API. With 12 supported RDBMS, which all have their own idea about what is a stored procedure and what is a stored function, it has proven to be a better design, to unite them in one single type: org.jooq.Routine. A routine can have a return value as well as OUT parameters. It can be embedded in SQL and used as a field or a table.This means, you will need to re-generate your database schema, when upgrading to jOOQ 1.6.8. After re-generation, you'll need to fix your client code. These are the package changes:
- [generated.package].procedures > [generated.package].routines
- [generated.package].functions > [generated.package].routines
- [generated.package].Procedures > [generated.package].Routines
- [generated.package].Functions > [generated.package].Routines
Oracle generated packages are not re-located. With these improvements, using stored procedures and functions becomes even more reliable, especially when cursor types are involved. Read more about the rationale behind this change:
https://blog.jooq.org/what-are-procedures-and-functions-after-all/
Apart from that, important improvements have been made in the area of plain SQL tables. Also, consider a demo integration of jOOQ with Google Cloud SQL:
https://blog.jooq.org/jooq-and-google-cloud-sql-example/
Features and improvements
#271 | Don't pre-fetch table meta data when selecting from plain SQL tables |
#489 | Add support for SELECT * (i.e. render SELECT * where applicable) |
#596 | Add support for VARIANCE() and STDDEV() OVER() window functions |
#608 | Add jOOQ version number in generated source code |
#670 | Add more Javadoc to Field.xxx() functions |
#692 | Add support for ResultSet type returned from HSQLDB stored functions |
#850 | Use https://www.jooq.org as URL for the @Generated annotation |
#854 | Add convenience methods Fields.isTrue(), isFalse() for conversion of "Y", "YES", "1", "true", "on", etc into a boolean condition |
#870 | Add support for MEDIAN aggregate function |
#872 | Add support for STDDEV_POP(), STDDEV_SAMP(), VAR_POP(), VAR_SAMP() aggregate functions |
#874 | Reduce the number of internal classes for dialect-specific function aliases |
#878 | Implement DataType.equals() and hashCode() |
API changes (backwards-compatible)
#851 | Change Field.{sortAsc|sortDesc}(List<T> sortList) into Field.{sortAsc|sortDesc}(Collection<T> sortList) |
API changes (backwards-incompatible)
#848 | Purge deprecated API - Prior to 1.6.1 |
#849 | Replace Cursor.fetchResult() by Cursor.fetch() |
#852 | Review stored procedures / functions concept. Merge them all into a single "Routine" type |
Bug fixes
#756 | Error when aliasing HSQLDB and Postgres unnested tables |
#761 | Exception when TRACE logging execution with plain SQL tables involved |
#773 | Execute standalone stored functions as CallableStatement to prevent issues with transactions |
#847 | Query.getSQL() doesn't render dialect-specific SQL when Query is constructed using the fluent API |
#853 | DB2 generated convenience methods for stored functions have unstable ordering |
#857 | Derby casting of numeric types to String / VARCHAR does not work |
#858 | SQLDataType.getSQLDataType() should return itself, instead of null |
#860 | SQLite CEIL function is incorrectly simulated. CEIL(2.0) returns 3.0 instead of 2.0 |
#861 | Field.replace(String) generates bad SQL for various RDBMS. Field.replace(String, String) works, though |
#863 | Ingres integration generates illegal SQL when selecting things like SELECT 1 WHERE 1 = 1 |
#866 | Sybase ASE Field.replace(String) function incorrectly removes the argument string |
#873 | Error when selecting two times the same aggregate field |
#877 | Compilation error in generated source code when a table without a primary key has an identity column |
#879 | Add Google Cloud SQL Example |
#880 | Query.getSQL() does not consider SchemaMapping |
Test cases
#811 | Loader integration tests fail for SQLite |
#812 | CSV Loader test leaves Postgres JDBC connection in an inconsistent transactional state on error |
#856 | Add integration tests for Field.abs() |
#865 | Add integration tests for Field.ascii() |
#867 | Add integration tests for Field.sum(), avg(), max(), min() |
#881 | Re-design H2 stored functions to be pre-compiled, in order to speed up integration tests |
Version 1.6.7 - September 25, 2011
This release coincides with the launch of the new website at https://www.jooq.org. Hence, it ships with little additions to the deliverable itself.
Apart from new convenience methods, the main addition is a Maven plugin for jooq-codegen contributed by Sander Plas.
Features and improvements
#797 | Create Maven plugin for source code generation |
#825 | Add List<Result<Record>> Factory.fetchMany(String) to allow for fetching several result sets from stored procedures, such as Sybase ASE's "sp_help" |
#838 | Implement MetaDataFieldProvider.toString() |
#841 | Add <T> List<T> Result.getValues(Field<?>, Class<T>) |
#842 | Add Query.getBindValues() method to allow for extracting bind values in the correct order |
#843 | Add Factory.fetch(ResultSet) to transform a JDBC ResultSet into a jOOQ Result |
API changes (backwards-compatible)
#837 | Avoid final keyword on Object methods, such as .equals(), .hashCode(), etc |
Bug fixes
#836 | Bad syntax when selecting from aliased plain SQL tables |
#839 | Boolean conversion in getValueAsBoolean() should trim String values first |
#840 | Numeric conversions in getValueAsXXX() should trim String values first |
#844 | NullPointerException when selecting a column from a Result, that does not exist |
Version 1.6.6 - September 11, 2011
Finally, support for another RDBMS has been added. Sybase's other important product Sybase Adaptive Server Enterprise (or simply Sybase ASE) is now officially supported by jOOQ
Apart from this, there had been important improvements with the recently added INSERT .. RETURNING clause, as well as some fixes related to DECIMAL / NUMERIC data types
Features and improvements
#796 | Complete missing public org.jooq.impl Javadoc |
#800 | Add support for Sybase Adaptive Server Enterprise |
#808 | Add support for INSERT .. RETURNING for Ingres |
#809 | Add support for INSERT .. RETURNING for Sybase SQL Anywhere using SELECT @@identity |
#810 | Add support for INSERT .. RETURNING for SQLite using last_inserted_rowid() |
#813 | Add DSL support for INSERT .. RETURNING |
#814 | Change TableRecord to reload its trigger-initialised main key in Oracle and other RDBMS that don't support IDENTITY columns |
#818 | Add SQLiteFactory.rowid() |
#819 | Support SQLite AUTOINCREMENT columns as IDENTITY |
#820 | Add Factory.fetchOne(String) for executing plain SQL queries that return single records |
#826 | Allow for returning several records in the INSERT .. RETURNING clause. This now works for DB2, HSQLDB, MySQL, and Postgres |
#827 | Support Sybase SQL Anywhere's TOP n START AT m clause instead of simulating it with nested SELECT's |
API changes (previous API now deprecated)
#817 | Deprecate Factory.lastID(Identity) |
Bug fixes
#815 | SQL Server fetching of IDENTITY value is broken |
#821 | Optimise ResultQuery.fetchAny() executing fetchLazy() internally, and only fetching one record from the cursor |
#822 | Let Constant cast to more precise NUMERIC/DECIMAL types in those RDBMS where casting is necessary |
#823 | Cannot bind SQLite BigDecimal, BigInteger types - bind them as String instead |
#824 | BigInteger values cannot be bound in DB2, Derby |
#828 | Document inefficient implementation for GREATEST and LEAST in some RDBMS |
Version 1.6.5 - August 28, 2011
This release finally adds a loader for CSV data to jOOQ. You can now load CSV data using a simple fluent API, configuring error handling, duplicate behaviour and transaction handling, as well as various CSV parameters.
This release also changes the way generated keys are retrieved after INSERT's. Instead of (potentially inconsistently) running SELECT MAX(pk) immediately after the INSERT, Postgres' INSERT.. RETURNING clause is used (or simulated), in a single statement.
Features and improvements
#784 | Add Result.exportXML() to retrieve a DOM document similar to that of .formatXML() |
#792 | Add support for loading of CSV data into tables |
#795 | Add <T> List<T> fetch(int, Class<T>) and fetch(String, Class<T>) convenience methods |
#803 | Add support for INSERT .. RETURNING or simulate it where not available |
#805 | Add <T> T[] fetchArray(int, Class<T>) and fetchArray(String, Class<T>) convenience methods |
#806 | Add <T> T fetchOne(int, Class<T>) and fetchOne(String, Class<T>) convenience methods |
Bug fixes
#798 | Oracle IN (...) clause with more than 1000 arguments does not work |
#802 | Use "INSERT .. RETURNING" instead of "SELECT MAX(pk)" to retrieve the primary key of a new record |
Version 1.6.4 - August 07, 2011
This release ships with a couple of useful concepts inspired by other frameworks. These are:
- selecting into custom POJO's. Results can be mapped to POJO's by convention or using JPA @Column annotations
- selecting into custom callbacks. This is already a wide-spread practice in Spring JdbcTemplates.
- selecting long-running queries asynchronously. This idea has been inspired by the Avaje Ebean framework
Apart from these changes and some bugfixes, the internal API has been completely re-designed. The idea here is that query rendering and variable binding are even faster (less String objects), more extensible and more accurate. This is a pre- requisite for many future developments with even more complex SQL statements, such as for instance CTE's (Common Table Expressions)
Features and improvements
#137 | Add support for asynchronous query execution using FutureResult<R> ResultQuery.fetchLater() similar to Avaje Ebean |
#198 | Add SELECT INTO functionality into POJO's using <T> T ResultQuery.fetchInto(Class<T>) similar to JPA CriteriaQuery |
#728 | Add .fetchInto(RecordHandler<R>) to ResultQuery, Result, and Cursor to allow for callbacks similar to Spring's JdbcTemplate/Ollin Framework |
#774 | Add more TRACE logging to .fetchLazy() |
#777 | CURSOR: Add function alias: UNNEST for TABLE |
#781 | Add E function (Euler number) |
#782 | Add <T> T Record.getValue(..., Class<? extends T>) methods for convenient type conversion |
#785 | Allow for storing TableRecord with a provided Field<?>[] indicating the primary key |
#786 | Document thread-safety facts in Factory Javadoc |
#788 | Add Key.getFieldsArray() convenience method |
#793 | Add support for Oracle's SYS_CONNECT_BY_PATH function |
API changes (backwards-incompatible)
#758 | Change internal QueryPart rendering and binding API to use Configuration and Context as callback parameters. If you use CustomField or CustomCondition, please correct your implementations accordingly. Other parts of the API should not be affected |
#778 | Purge deprecated API, deprecation prior to jOOQ 1.5.7 |
#790 | Purge deprecated generated code, deprecation prior to jOOQ 1.5.7 |
API changes (previous API now deprecated)
#776 | Deprecate QueryPart.getSQL(), add Query.getSQL() |
#789 | Deprecate Record constructors with Configuration parameter |
Test cases
#636 | Add integration tests for more advanced CONNECT BY example |
#772 | Add integration tests for selecting cartesian products (several tables in FROM clause) |
Bug fixes
#730 | Sybase cannot bind null values in plain SQL |
#759 | Omit the TOP 100 PERCENT clause in SQL Server ordered top-level queries |
#767 | An empty Java package is generated for PL/SQL packages containing underscores |
#771 | Some exotic literals are not properly escaped with quotes yet, e.g. UDT identifiers, VARRAY types, etc. |
#775 | Automatic re-attaching after deserialisation does not work when used with .fetchLazy() |
#787 | The UpdatableRecord's internal changed flags are not updated after INSERTs / UPDATEs |
Version 1.6.3 - July 31, 2011
This is mainly a maintenance release with lots of bugfixes, mostly around code generation, plain SQL tables, and data types. Please note that generated source code may contain incompatible changes due to #639 (see below for details)!
Apart from that, project CURSOR is advancing and it is now possible to unnest arrays into tables. See this article for details about where jOOQ is heading with project CURSOR:
https://blog.jooq.org/the-power-of-ref-cursor-types/
Features and improvements
#679 | Improve H2 NVL2 support as of H2 1.3.156 |
#680 | Improve H2 ROUND support as of H2 1.3.156 |
#735 | Add README documentation to GitHub |
#736 | Add more info regarding number of generated artefacts in jooq-codegen logging |
#750 | Add DataType.isNumeric(), .isString(), .isTemporal(), .isBinary() |
#754 | Log query as executed by JDBC PreparedStatement when TRACE logging (without inlining variables) |
#752 | CURSOR: Add support for selecting from ARRAY types |
#762 | Use H2's native support of NVL, instead of COALESCE |
#764 | CURSOR: Add support for selecting from ARRAY types returned from stored functions |
API changes (backwards-incompatible)
#639 | Map DECIMAL(n, 0) and NUMBER/NUMERIC(n, 0) data types to Byte/Short/Integer/Long/BigInteger instead of BigDecimal in generated source code. Re-generated code will not be compatible! |
API changes (previous API now deprecated)
#731 | Inconsistent API with Field.lessOrEqualToXXX(). Removed "To" from method name |
#757 | Deprecate Factory.constant() methods |
Test cases
#731 | Add missing integration tests for equalAll(), equalSome() and similar methods |
#747 | Upgrade H2 to 1.3.158 |
Bug fixes
#632 | Sybase error : column @p0 not found in nested SELECT |
#700 | Restore HSQLDB ARRAY support with INFORMATION_SCHEMA change in HSQLDB 2.2.3, and some fixes in 2.2.5 |
#725 | Cannot insert byte[] data with plain SQL |
#733 | H2 changed JDBC type for ResultSet/CURSOR from 0 to -10, like Oracle |
#737 | Compilation errors in generated source code if table fields contain spaces |
#738 | Compilation errors in generated source code if MySQL procedure parameter type contains two comma-separated arguments (like DECIMAL(10,2)) |
#739 | Postgres navigator methods and keys are not re-generated in the same order |
#740 | Formatting is broken on Result.format() with some special newline characters |
#743 | Make SQL Server INFORMATION_SCHEMA independent from HSQLDB again, to prevent incompatibility issues |
#744 | Ingres REAL and FLOAT4 types are generated as FLOAT/FLOAT8 which maps to java.lang.Double, instead of java.lang.Float |
#753 | Postgres error when binding array that contains null values |
#755 | NullPointerException when converting an array containing a null value |
#766 | Bad decoding of JDBC Types BIGINT (to BigInteger instead of Long) and REAL (to BigDecimal instead of Float) when plain SQL tables are involved |
Version 1.6.2 - July 10, 2011
This release mainly introduces three new projects.
Project CURSOR where jOOQ finally supports various RDBMS's TABLE, CURSOR, and REF CURSOR data types. This is especially useful when those types are returned from stored procedures and functions. Cursors are simply mapped to jOOQ Result<Record> types and can thus be used like regular table results
Project EXPORT aims at exporting data from the database in various serialisable formats, such as XML, CSV, HTML, Text, JSON. This project will be continued in the future, to also deserialise from (some of) these data streams. This will allow for easy transport of jOOQ Result<?> types over the net.
Project CODEGEN has finally been started. Many improvements suggested by jOOQ users will be implemented in the next releases. In this release, important fixes have been made to prevent compilation errors in generated artefacts.
Features and improvements
#61 | EXPORT: Add Result.formatXML() |
#166 | CURSOR: Add support for ResultSet type returned from Oracle stored procedures / functions |
#411 | Allow for fetching Map<String, Object> (instead of Record) and List<Map<String, Object>> (instead of Result) |
#549 | Add Factory.function() for plain SQL functions |
#611 | Simulate RPAD and LPAD in SQL Server, Sybase |
#627 | Add support for Postgres FOR UPDATE OF [table-name] clause |
#628 | Add support for REPEAT (SQL Server: REPLICATE) function |
#637 | Nicely format time in StopWatch logging output |
#640 | Simulate Postgres FOR UPDATE OF [table-name] clause in other dialects |
#649 | CURSOR: Add Cursor.fetch(int) .fetchOne() .fetchResult(int) .fetchResult() |
#653 | Add support for MySQL encryption and compression functions |
#660 | Clarify Javadoc of UpdatableRecord to explain its behaviour when changing the main unique key |
#669 | EXPORT: Add Result.formatHTML() |
#672 | Add convenience method UpdatableRecord.copy() in order to reset primary key values for a subsequent INSERT |
#675 | EXPORT: Add Result.formatCSV() |
#683 | Implement ResultImpl.equals() and .hashCode() |
#684 | Implement AbstractStore.equals() and .hashCode() |
#685 | Add Store.size() to indicate the maximum index of the Store |
#687 | EXPORT: Add result.formatJSON() |
#689 | Create separate builds: jooq-core.zip and jooq-with-dependencies.zip |
#690 | CURSOR: Add support for ResultSet type returned from H2 stored functions |
#695 | CURSOR: Add support for ResultSet type returned from Postgres stored functions |
#697 | Add Factory.fetch(String) for executing plain SQL queries that return results |
#701 | Add ResultQuery.fetchArray() and .fetchOneArray to return Object[][] and Object[] |
#704 | Always add top and bottom line in Result.format() |
#705 | Right-align numeric values in Result.format() |
#716 | Add SUBSTRING function Field.substring(Field, Field) taking fields as arguments |
#719 | Document risk of SQL injection in plain SQL and literal factory methods |
#726 | Add LENGTH function as a synonym for CHAR_LENGTH |
API changes (backwards-compatible)
#698 | Inconsistent API with Factory.fetch(Table<R> [,Condition]) Let method return Result<R> instead of List<R> |
#699 | Let Result<R extends Record> extend List<R> |
API changes (previous API now deprecated)
#656 | Decrease verbosity of plain SQL methods. They will just be called Factory.field() .condition() .table() .query() |
Test cases
#643 | Add integration test for code generation of invalid and incomplete types in Oracle |
#654 | Add integration tests for master data tables with PK types other than NUMBER/INT |
#655 | Add missing integration tests for TRIM function |
Bug fixes
#450 | Improve plain SQL integrity checks for bind variables |
#610 | CODEGEN: Compilation error in generated source code for databases with table named 'system' |
#646 | An empty Java package is generated for an empty PL/SQL package. This is unnecessary |
#651 | CODEGEN: Avoid importing datatypes in generated source code to prevent collisions |
#657 | NullPointerException when creating a Factory with a null SchemaMapping |
#658 | Master data table code generation is broken for tables with more or less than 3 columns |
#662 | Add support for the missing Postgres data type "bpchar" |
#663 | Add support for the missing Sybase data type "int" |
#664 | Ingres INTEGER data types are not correctly generated |
#665 | HSQLDB Datatype CLOB and BLOB are not supported, when selecting from plain SQL tables |
#666 | The evil bug: Ingres TRIM function only executes RTRIM |
#673 | UpdatableRecord.store() doesn't work if called after .delete() |
#702 | Add support for the missing SQLite data type "NULL" |
#706 | CURSOR: Ensure that Query.execute() runs in a single transaction when Postgres refcursor is involved in the query (this fixes a Postgres JDBC driver flaw) |
#724 | NullPointerException when passing a single literal null bind value to plain SQL methods without casting to Object |
#729 | DB2, Derby, Ingres, Oracle cannot bind null values in plain SQL |
Version 1.6.1 - June 19, 2011
In this release, the PORTABILITY project has been implemented. Finally, the SQLDialect has been removed from most generated artefacts (Schema, Table, Field, Sequence, etc). Also, the constructing Factory is not referenced by its created QueryParts anymore, unless this is really necessary (Query objects, UDT's, ARRAY types). This leads to higher compatibility between schemata of different databases, e.g. if users want to use an HSQLDB development and Oracle productive database.
Unfortunately, this means that the way stored procedures are called had to be changed. This is an API break that could not be avoided. The pre-1.6.1 StoredObject.execute(Connection) method is deprecated and will be removed in the future. It has been replaced by StoredObject.execute(Configuration)
In addition to this project, many more window functions are now supported, as well as the Oracle-specific CONNECT BY clause for recursive queries.
Features
#351 | Add support for Oracle ROWID data type |
#452 | PORTABILITY: Create a super-set of RDBMS data types |
#453 | PORTABILITY: Don't create dialect-specific QueryParts |
#455 | Add support for the Oracle CONNECT BY clause |
#587 | Add optional OFFSET clause to form LIMIT .. OFFSET constructs |
#589 | Add extended FOR UDPATE [OF ...] [{WAIT n | NOWAIT | SKIP LOCKED }] support |
#591 | Add support for LEAD() OVER() and LAG() OVER() window functions |
#592 | Add support for the CUME_DIST() OVER() window function |
#601 | Add Factory.literal() convenience methods |
#602 | Add Factory.val() methods to decrease .constant() verbosity |
#604 | Add support for RESPECT NULLS clause in some window functions |
#605 | Add Factory.use(String) for non-generated schemata |
#613 | Add PI function |
#616 | Add Factory.two() literal convenience method |
#630 | Add support for Oracle CONNECT BY pseudo-columns LEVEL, CONNECT_BY_ISCYCLE, CONNECT_BY_ISLEAF |
API changes
#299 | PORTABILITY: Create a dialect-independent meta-model |
#588 | Add OVER() keyword to FIRST_VALUE() and LAST_VALUE() API |
Test cases
#368 | Add integration test for use with schema mapping |
#586 | Upgrade H2 to 1.3.155 |
#607 | Add integration tests for CRUD / SP's / UDT's / ARRAY's with SchemaMapping |
#612 | Add integration tests for LPAD and RPAD functions |
#624 | Add integration test for code generation of invalid/ incomplete views in Oracle |
#631 | PORTABILITY: Add integration tests for using Oracle- generated schema against an HSQLDB database |
#638 | Add missing integration test for DECIMAL data type |
Bugfixes
#176 | Stored procedures / functions in EQUIVALENT schemata cannot be called |
#493 | Bind variable mismatch when constructing bad SQL |
#594 | Confusing Javadoc in SELECT DSL API |
#603 | Fix DB2 'IGNORE NULLS' clause |
#619 | SUBSTRING() function is broken in DB2, Ingres, SQL Server |
#623 | SQL syntax error for some MERGE queries in SQL Server and Sybase |
#633 | SchemaMapping is not applied to sequences |
#634 | Sequences are not escaped in generated SQL |
Version 1.6.0 - June 05, 2011
Apart from supporting various additional standard and non- standard JOIN constructs, there is now also full support for the SQL standard MERGE statement and MySQL's ON DUPLICATE KEY variant thereof. A great number of API enhancements have been added, which improve the usability of jOOQ. The Ingres database is now also supported.
Features
#301 | Add support for Oracle execution hints |
#409 | Add support for NATURAL JOIN syntax, where RDBMS allows it |
#415 | Make fluent API's underlying SelectQuery objects publicly available |
#429 | Add Ingres support |
#475 | Document class-level generic types <R> and <T> in Javadoc |
#486 | Add support for SQL MERGE clause |
#494 | Allow for omitting schema name in generated SQL |
#496 | Automatically update IDENTITY values in UpdatableRecord, after storing them |
#520 | Add support for JOIN ... USING syntax |
#524 | Upgrade HSQLDB to 2.2 |
#533 | Add ORDER BY [Map] or BY [List] functionality |
#534 | Add Result.isEmpty() |
#535 | Call upon ConfigurationRegistry.provideFor() before throwing a DetachedException |
#536 | Simulate CASE [value] WHEN [value] THEN [result] END syntax in Derby |
#538 | Add some logging to ConfigurationProvider |
#539 | Add possibility to negate numeric values with Field.neg() |
#541 | Add support for MySQL ON DUPLICATE KEY clause |
#542 | Allow for Collection arguments in INSERT's DSL API |
#543 | Allow for creating FUNCTION() OVER() without PARTITION BY or ORDER BY clause |
#546 | Add Factory.use(Schema) |
#548 | Add new internal type FieldMap |
#550 | Simulate ON DUPLICATE KEY INSERT clause in dialects other than MySQL |
#551 | Add TableMapping, similar to SchemaMapping for mapping tables |
#553 | Add Factory.plainSQLQuery |
#554 | Add Factory.plainSQLField with a DataType parameter |
#555 | Add UpdateXXX.set(Map) convenience methods to DSL API |
#557 | Enhance INSERT DSL API to allow for adding VALUES clause with InsertXXX.set() syntax |
#570 | Add support for the RAND() function |
#567 | Add support for Ingres Sequences |
#572 | Add support for the ATAN2() function |
#573 | Add possibility for additional select() clauses for convenience |
#575 | Add support for the FULL OUTER JOIN syntax, where RDBMS supports it |
#576 | Add support for the CROSS JOIN syntax, where RDBMS supports it |
#581 | Enhance API and allow Collection<? extends Field<?>> instead of Collection<Field<?>> |
API changes
#397 | Purge deprecated API |
Bugfixes
#481 | Handle case where an empty record is stored |
#522 | Misleading Javadoc in generated stored procedures and function constructors |
#532 | Restore Postgres INFORMATION_SCHEMA |
#537 | Prevent null from being added to QueryPartList |
#540 | Error when TRACE logging Limit |
#544 | Aliased elements are not bound correctly when rendered with toSQLReference() |
#559 | Loosen type safety on overloaded methods to prevent compilation errors with javac/Netbeans |
#560 | HSQLDB DataType REAL is configured incorrectly |
#565 | Add integration tests for current_user() function |
#569 | ORA-01427 when generating foreign key relations |
#571 | Field.trim() not correctly implemented for SQL Server |
#583 | Accelerate integration tests: Reset schema only if necessary |
Version 1.5.9 - May 15, 2011
This version ships with lots of new functionality. Finally, the DSL-style API has been extended to CRUD operations (INSERT, UPDATE, DELETE)! Also, support for the TRUNCATE TABLE statement has been added.
The most important new features include the support for SQL:2003 standard window functions, which are available in most major RDBMS. Additionally, basic function support has been widely extended.
Features
#148 | Added support for window functions |
#204 | Add support for multi-record INSERT's |
#416 | Added support for retrieval of IDENTITY values |
#433 | Use bind variables for LIMIT and OFFSET |
#441 | Added foreign key relationship meta information to the generated source code |
#446 | Beautify ResultImpl.toString() method |
#461 | Automatically cast CONCAT parameters to Field<String> if necessary |
#463 | Added support for trigonometric functions |
#471 | Added support for the sign function |
#472 | Added support for GREATEST/LEAST functions |
#474 | Added support for "hyperbolic" functions SINH, COSH, TANH, and COTH |
#482 | Added DSL API for INSERT statements |
#483 | Added DSL API for UPDATE statements |
#484 | Added DSL API for DELETE statements |
#485 | Added "Registry" for client code to provide Configurations to jOOQ Attachables |
#490 | Added support for the TRUNCATE TABLE statement |
#495 | Generate source code for IDENTITY columns |
#501 | Added support for boolean conversion to Result, Record, and Store |
#503 | Allow for schema navigation via generated artefacts |
#518 | Let stored procedures reference owner package if applicable |
#525 | Added NULLS {FIRST | LAST} clause to ORDER BY constructs |
#528 | Added Factory.getDataType() convenience method |
#530 | Added Factory.zero() and Factory.one() convenience methods |
API changes (jooq)
#527 | Weakened type-safety on Field.nvl2() |
#529 | Deprecated Factory.select(Object...), added .selectOne() and .selectZero() instead |
API changes (jooq-meta)
#30 | Add ParameterDefinition for stored procedures, instead of reusing ColumnDefinition |
#499 | Add reference to TableDefinition in ColumnDefinition |
#500 | Add AttributeDefinition for UDTDefinition, instead of reusing ColumnDefinition |
Bug fixes
#369 | Adapt H2 relations generation to H2's correction of information_schema.cross_references |
#435 | Added integration tests for NESTED SELECTs holding LIMIT clauses |
#460 | Syntax error when using a field with a reserved name |
#462 | Fixed Javadoc broken links |
#473 | Don't cast when cast is unnecessary |
#479 | INSERT statement should not set all fields for a table |
#497 | Derby referential code generation is broken, for named foreign keys |
#498 | Oracle package content is generated in arbitrary order |
#502 | Syntax error when creating an empty IN condition |
#526 | Corrected Javadoc in Field.coalesce() |
Version 1.5.8 - April 29, 2011
Finally, jOOQ now supports two important new RDBMS: SQL Server and Sybase!
Apart from this great enhancement, there is now also full support for the non-SQL standard LIMIT clause, even in dialects where the LIMIT clause is not supported natively (especially Oracle, but also DB2, SQL Server and Sybase, which have limitations). jOOQ simulates LIMITs by rendering nested selects filtering on ROWNUM (Oracle) or on ROW_NUMBER() (DB2, SQL Server and Sybase).
Other interesting additions are an increasing support for native mathematical functions. More function support will be added in future versions.
Features
#16 | Added support for SQL Server |
#21 | Uniform implementation of the LIMIT clause. Implemented LIMIT clause simulation through analytic functions, where LIMIT is not supported natively |
#97 | Added support for Sybase |
#418 | Measure time of various steps in source code generation |
#420 | Added support for proprietary SQL extensions "FOR UPDATE" and "FOR SHARE" |
#431 | Added additional statistics to generation log files |
#432 | Unified the various "standard" ANSI INFORMATION_SCHEMA implementations in the jooq-meta artefact |
#436 | Added support for the modulo function |
#438 | Added floor and ceil functions |
#439 | Added support for mathematical functions (logarithms, exponentials, sqrt) |
#447 | Enhanced Field.add() and Field.subtract() to work for date time fields, also |
API changes
#428 | Created new Maven artefact jooq-meta to cleanly separate database meta-data navigation from code generation |
#458 | Decreased DSL verbosity for arithmetic operations and for ordering |
Bug fixes
#417 | Restored warning when unknown column type is encountered in source code generation |
#419 | Corrected misleading Select.fetchOne(...) Javadoc |
#421 | Optimised AbstractRecord's memory consumption |
#448 | Corrected some Javadoc @see links |
#449 | Changed Field.concatenate() to accept Field<?> parameters to avoid generic varargs warnings |
Version 1.5.7 - April 17, 2011
This is the first release built with support of Maven thanks to the help of some jOOQ users!
The main new features in this release are the improved support for serialisation/deserialisation of jOOQ objects through use of the newly introduced "Attachable" interface.
If using log4j or the newly supported slf4j logging framework in debug/trace mode, there is the possibility to log query building/execution time statistics.
Apart from these new features, fixes were mainly done in the fields of type casting, HSQLDB 2.1 upgrade support, stored procedures with OUT, IN/OUT parameters. Please upgrade, if you are using any of those features.
If you extend jOOQ as a base implementation for source code generation, be aware of the fact, that the jOOQ-codegen is currently undergoing major changes. Expect the code generation API to stabilise again in one of the next releases.
Features
#104 | Added maven dependency |
#248 | Integrate UDT types with ARRAYs |
#295 | Allow for attaching/detaching UpdatableRecords to/from Configurations |
#359 | Added statistics measurement to Query execution for debug log level |
#362 | Added deprecation configuration flag |
#364 | Document unknown type in generated source code |
#373 | Improve exception handling in code generation |
#378 | Added support for Oracle stored functions with OUT parameters |
#382 | Added Factory.attach() methods to re-attach deserialised Attachables |
#394 | Add logging support for SLF4J |
#398 | Allow to provide a DataType in Factory.constant() |
#399 | Provide access to TypeUtils.convert() methods via DataType |
#404 | Added trace logging for measuring the speed of various query execution steps |
API changes
#358 | Enhanced DSL API to allow for HAVING clauses without GROUP BY clauses |
#367 | Make Store, Result, QueryPart "Attachable" |
#374 | Introduce strategy pattern to code generation for future support for advanced naming schemes |
#375 | Decouple Database from Generator |
#381 | Made DataType Serializable |
#384 | Deprecated singleton QueryParts |
#388 | Unify "internal" API using an Adapter pattern |
Bug fixes
#187 | Protect generated Record navigation methods against name clashes |
#266 | Added more thorough integration tests for dialect-specific casting (including some fixes related to varchar types) |
#360 | Added more integration tests for the DISTINCT clause |
#361 | Add more checks in testInsertUpdateDelete() |
#366 | Warn only once per ColumnDefinition, if a data type is unknown |
#377 | NullPointerException when generating invalid stored function |
#380 | Added integration tests to check for proper serialisability |
#386 | Fixed incompatibilities with HSQLDB 2.1.0 |
#387 | Fixed unnecessary imports in some Oracle generated Records |
#389 | Fixed javac compiler warning in AbstractStoredObject |
#391 | Cannot properly call stored procedures when IN/OUT parameter is bound to NULL |
#392 | Procedures with several OUT parameters may not register OUT parameters correctly |
#410 | Passing null VARRAY values to Oracle stored procedures causes issues |
#412 | limit(int) sets default offset incorrectly in some dialects |
Version 1.5.6 - March 31, 2011
This release consists mainly of code generation bug fixes and minor API improvements and enhancements.
The most important improvement is ticket #90, by which lazy fetching and iteration over data is now supported. jOOQ lets you keep a reference to a Cursor that has an open JDBC ResultSet, to fetch data from on-the-fly.
A few major code generation bugs were reported where the generated code may cause ambiguity due to an inconsistent API. This means that you will have to re-generate your schema after upgrading to version 1.5.6. Some of your code may not compile anymore, after this upgrade.
Features
#90 | Added possibility for lazy fetching of data |
#208 | Added convenience methods for direct invocation of sequences' currval() and nextval() attributes |
#212 | Created one factory per dialect for better separation of dialect-specific support |
#213 | Generate a factory for each schema |
#251 | Opened up base implementations for Field<?> and Condition to allow for custom implementations by client code |
#274 | Integrate H2 ARRAY types with stored procedures |
#292 | Documented usage of log4j and java.util.logging |
#306 | Added support for the NULLIF function |
#319 | Added Field.between(Field<T>, Field<T>) method |
#320 | Added trace logging for variable binding and SQL generation methods |
#323 | Added Field.in(Field<?>...) method |
#325 | Include release version number in delivered .jar files |
#328 | Improved configuration setup documentation page |
#333 | Let Result implement Serializable |
#334 | Added fetchMap() convenience methods |
#335 | Added more functions and aggregate functions examples to documentation |
#338 | Visually improve code generation logging |
#339 | Removed skipping of unreferenced UDT's, ENUM's and ARRAY's |
#342 | Improved generated referential code by using fetch() and fetchOne() API |
#356 | Let UpdatableRecord.store() and delete() return an int to indicate whether the record was actually modified |
API changes
#233 | Allow for joining TableLike instead of Table |
#337 | Added generic type <R extends TableRecord<R>> to InsertSelectQuery |
#341 | Fixed API flaw where SelectOnConditionStep.and() methods and similar ones returned SelectConditionStep, instead of SelectOnConditionStep |
Bugfixes
#69 | Corrected referential code generation for foreign keys that reference non-primary unique keys |
#85 | Corrected referential code generation for multi-field foreign keys |
#121 | Covered more Factory.executeXXX() methods with integration tests |
#318 | Fixed NullPointerException when executing SELECT * from aliased tables |
#321 | BetweenCondition does not bind left hand side Field correctly |
#322 | InCondition does not bind left hand side Field correctly |
#326 | Avoid method overloading where binding <T> to Object may lead to compile-time ambiguities (with javac) |
#343 | Add more foreign key navigation method integration tests |
#347 | Add explicit integration tests for schema artefacts excluded from code generation |
#350 | Disambiguate navigation methods if several foreign keys reference the same entity |
#352 | Disambiguate navigation methods if a table ending on S references itself |
#353 | Added integration test for compilation of generated artefacts with javac (as opposed to the Eclipse compiler) |
#355 | Error when storing an UpdatableRecord that has no changed values |
Version 1.5.5.2 - March 15, 2011
A critical bug was reported from the 1.5 release stream where stored functions did not render their parameters in correct order
Features
#302 | Map Oracle's NUMBER data type to java.lang.Number in stored procedures, stored functions |
Bugfixes
#317 | StoredFunctionImpl.asField() renders parameters in wrong order |
Version 1.5.5.1 - March 13, 2011
In version 1.5.5, there was a fatal bug breaking Derby source code generation. Only the Derby dialect is affected. Please update immediately, if you are using jOOQ's Derby integration
Bugfixes
#315 | Generated master data records are not sorted by PK |
#316 | Derby code generation fatally broken |
Version 1.5.5 - March 12, 2011
This version is released early as there are some important bugfixes. Additional improvements include:
- Improved DSL related to conditions in HAVING and JOIN clauses
- Support for Oracle-style functions, such as NVL, NVL2, COALESCE DECODE, etc
Features
#304 | Add support for Oracle NVL function |
#305 | Add support for COALESCE function |
#308 | Add support for Oracle NVL2 function |
#311 | Add support for Oracle DECODE function |
API changes
#223 | Enhance DSL to accept and(), or() and similar methods in JOIN steps |
#224 | Enhance DSL to accept and(), or() and similar methods in HAVING steps |
Bugfixes
#297 | Fixed Factory.concatenate() function |
#298 | Added integration tests for nested selects in HAVING clause |
#300 | Added integration tests for nested selects in JOIN clause |
#303 | Javadoc correction |
#307 | Accelerated integration tests |
#309 | Fixed JDBC variable binding issue related to Conditions where the lhs is a function (e.g. stored function) and the rhs is a constant |
#310 | Fixed issue where fetchOne() methods throw NullPointerException if no result record is available |
#312 | Fixed issue where Field.equal(...) methods rendered unexpected SQL when rhs null is cast to a type |
#313 | Fixed Derby cast type for VARCHAR |
#304 | Let the DerbyDataType default for java.lang.String be VARCHAR, not LONG VARCHAR |
Version 1.5.4 - March 04, 2011
Feature #243 required a minor API change in the base classes of generated source code. This means you have to re-generate all your jOOQ artifacts in order to migrate to 1.5.4. The artifacts themselves should be regenerated in a compatible way, such that your client code should not be affected. If this is not the case, please report a ticket here:
https://sourceforge.net/apps/trac/jooq/newticket
Apart from the Derby RDMBS and some new data type support, there have been many new convenience methods added all over the API. For instance, if type-safety is not really a requirement, there are lots of possibilities to use plain SQL directly in the DSL. In that case, data can be accessed from Record, Results, not only through Field<?>, but also through field names or indexes.
Check out the updated documentation (soon) here:
https://sourceforge.net/apps/trac/jooq/wiki/Examples
- Support for the Derby RDBMS
- Support for casting. This allows for even greater flexibility in cases where jOOQ cannot 100% ensure type-safety
- Support for ARRAY types. Oracle, Postgres, HSQLDB and H2 ARRAY types are now supported natively as regular <T> bindings in jOOQ's Field<T>
- Support for dialect-specific data types. CHAR, VARCHAR, CLOB are no longer treated equally as java.lang.String. Their type heritage is also generated
- More sequence support
- Lots and lots of bug fixes
Features
#95 | Support for the Derby RDMBS |
#163 | Add support for JDBC type ARRAY (with Postgres) |
#209 | Add support for DB2 sequences |
#210 | Add support for H2 sequences |
#211 | Add support for HSQLDB sequences |
#215 | Support for SQL casting using <T> as cast type |
#246 | Support for SQL casting using dialect-specific data types |
#254 | Add HSQLDB support for ARRAY types |
#256 | Add Oracle support for VARRAY types |
#257 | Integrate ARRAY types with stored procedures |
#261 | Add a global type mapping to the generated Schema object |
#267 | Add DataTypeDefinition for further abstraction of data types in code generation |
#269 | Add H2 support for ARRAY types |
#290 | If log4j is not on the classpath, use java.util.logging instead, as fallback |
API Changes
#156 | Allow for results to be accessed by index, not by field |
#218 | Corrected bad method signature: Record.getValueAsLong(Field<?>, Integer) |
#219 | Extended Result and Select API's to be more similar to that of Record |
#232 | Add more convenience plain SQL support to the API |
#235 | Add convenience methods to Record, Result and Select for access of data via field name |
#243 | Refactor DataType implementations in order to allow for the use of generics |
#259 | Add field type to database meta data (ColumnDefinition) |
#260 | Add field type to database meta data (Field<?>) |
#262 | Add default behaviour for Record.getValue(Field<?>) |
#276 | Add Javadoc as a ZIP file to the jOOQ distribution |
Bugfixes
#125 | Add more plain SQL integration tests |
#191 | Add more integration tests for nested unions |
#205 | Implemented workaround for handling Postgres stored functions with UDT OUT parameters |
#214 | Fixed NPE when generating a stored function with an unknown parameter type |
#216 | Fixed some cases where binding of BigInteger is not done correctly |
#220 | Syntax error when using select statement in a CASE clause |
#221 | Corrected integration tests for combined update and select statements |
#222 | Added integration test for INSERT statements having nested SELECT statements for their fields |
#225 | Correctly cast array types in Postgres |
#230 | Potential misuse of Blob and Clob in H2's JDBC types |
#239 | Factory.fetchAny() is not implemented for SQLite |
#244 | Fixed peculiar MySQL casting support where cast types do not match any data types |
#245 | Fixed NPE when reading null dates in SQLite |
#249 | Added ARRAY type integration tests |
#255 | Stored procedure bind variables get mixed up when any argument is null |
#263 | Correctly handle Postgres function overloading |
#264 | Ambiguous funciton calls when calling overloaded functions with null parameter |
#281 | Handle compilation errors when generating stored procedures with > 254 parameters |
#283 | Fixed compilation errors in generated source code for Oracle's UDT table type |
#284 | Fixed compilation errors in generated source code for Oracle procedures in packages, when they have no parameters |
#285 | Fixed compilation errors in generated source code for Oracle tables with the same name in different schemata |
#286 | Fixed name collisions in generated objects with the java.lang.* package |
#288 | Prevent the creation of UNION queries with bad syntax in MySQL |
#289 | Correctly alias fields within UNION queries for some dialects, which then only require the "AS" keyword |
#291 | Cannot create an aliased field called "year" in Postgres |
Version 1.5.3 - January 13, 2011
- Lots of stored procedure support was implemented
- Support for sequences was added
- The final decision to postpone support for DB2 UDT's was made
- Some code generation bugfixes
Features
#36 | Added stored procedure / stored function support for HSQLDB |
#140 | Added support for Oracle sequences |
#147 | Added support for H2 stored functions |
#162 | Correctly integrate UDTs with stored procedures |
#170 | Added support for Postgres stored functions |
#186 | Added support for more Oracle PL/SQL simple data types |
#193 | Simulate support for H2 "stored procedures" |
#195 | Simulate support for Postgres "stored procedures" |
#206 | Added support for Postgres sequences |
API changes
#180 | Improved DSL for constant values |
#181 | Allow for referencing Field<?> in function argument list |
#189 | Renamed convenience methods in org.jooq.Record |
#207 | Add fetchOne(Field) method to org.jooq.Select API |
Bugfixes
#182 | Protected generated Record classes against clashes with inherited methods |
#183 | Fixed NullPointerException, when generating master data tables with NULL fields |
#184 | Fixed IllegalArgumentException, when a data type is present in the schema, but unavailable in code generation logic |
#185 | Code generation should not fail when single elements cannot be generated |
#188 | Improved integration tests for stored procedures / functions / packages |
#196 | Increase RDMBS version compatibility by avoiding "SELECT *" in code generation logic |
#199 | Added integration tests for stored procedures in RDBMS that do not support OUT parameters |
#201 | Fixed issue in DB2 where stored procedures without parameters were not generated. |
#202 | Added integration tests for stored procedures / functions without parameters |
Version 1.5.2 - December 27, 2010
- Improved support for stored procedures, also in packages
- A minor API change was inevitable to implement #173. The API change only concerns the INTERNAL API. Deprecation marks are added and deprecated items will be removed in 1.6.0
- Experimental SQLite database support
- Some important bug fixes
Features
#25 | Added support for Oracle packages |
#114 | Added support for Oracle UDTs |
#145 | Added support for the SQLite database |
#150 | Generate static convenience methods for stored procedures / functions |
#151 | Generate static convenience methods for stored function fields |
#152 | Generate meaningful serialVersionUID in generated classes |
#173 | Added support for EQUIVALENT schemata |
API changes
#159 | Added convenience method List<T> getValues(Field) to Result |
#165 | Added convenience methods for creating EXISTS clauses |
#169 | Improved DSL for WHERE clauses |
Bugfixes
#68 | Prevent issues originating from overloaded stored procedure names, generating identical Java class names |
#153 | Fixed issue with generated code for DB2 stored functions |
#154 | Fixed issue with generated code for DB2 stored functions |
#155 | Fixed issues with database NULL not being mapped correctly to Java NULL when selecting values that have a primitive type (int, long, etc) |
#158 | Potential ClassCastException when using Field<BigInteger> |
#171 | Corrected issue related to selection of default schema in DB2 |
#177 | Fixed issue related to generated code for tables or UDTs without columns |
Version 1.5.1 - December 13, 2010
- H2 database support thanks to Espen Stromsnes
- Improved stored procedure support
Features
#96 | Added H2 database support |
#101 | Added stored procedure / stored function support for Oracle |
#138 | Added stored procedure support for DB2 |
#146 | Added support for DB2 functions |
API changes
#143 | Added convenience methods to Record |
Bugfixes
#84 | Implemented referential code generation for foreign keys that do not match their primary keys' types |
#141 | Encoding problem in generated master data classes |
Version 1.5.0 - November 22, 2010
- A big one. Major API changes / improvements
- Added lots of convenience methods
- UDT support
- Enum support
- DB2 support thanks to Espen Stromsnes
- "Light" dependency to log4j added. jOOQ will still run without it
Features
#1 | Create support for UDTs (so far only for PostgreSQL) |
#15 | Added DB2 support |
#60 | Added support for nested selects in INSERT and UPDATE statements |
#83 | Added log4j logging to code generation and runtime |
#87 | Add support for arithmetic expressions |
#105 | Added support for ENUM data types, where applicable (MySQL and PostgreSQL so far) |
#110 | Added execute and fetch convenience methods |
#111 | Added missing "select distinct" support |
#122 | Annotate generated classes with javax.annotation.Generated |
#123 | Generate user enum fields from data values (master data) |
#124 | Added PlainSQLTable |
#127 | Added not() operator to Condition |
#135 | Added convenience methods andNot() and orNot() in Condition |
API changes
#89 | Removed support for DataSource. jOOQ is not a transaction manager |
#92 | Added SortField type to be used for sorting |
#99 | Provide better access to functions (No more FunctionFactory) |
#116 | Merge Manager functionality into Factory |
#118 | Improve API of org.jooq.Field |
#119 | Improve subquery condition API |
#132 | Reduced much of the select query API |
#134 | Better separation of SelectQuery and SimpleSelectQuery |
Bugfixes
#109 | Error when executing select * if generated schema does not match actual schema |
#115 | Fix various "null" pseudo field issues |
#126 | Error when selecting a single field from a union nested select |
#129 | Fixed performance issue in Oracle code generation for very large databases |
Version 1.4.4 - November 22, 2010
Unreleased version, fixes included in 1.5.0
Bugfixes
#133 | JoinCondition does not take comparison operator |
Version 1.4.3 - October 25, 2010
Some more bugfixes
Bugfixes
#71 | Generated code does not compile, when foreign key and primary key have a data type mismatch |
#73 | In Oracle generated code, multi-field foreign keys may generated bad relations code |
#82 | Conversion of literals to camelcase fails if numbers are involved |
Version 1.4.2 - October 22, 2010
Various bugfixes and minor improvements
Features
#66 | Add support for CASE or DECODE expression |
API changes
#77 | Functions should not extend FieldImpl, but a new AbstractField |
#78 | QueryPart pollutes declared method space of its implementations. Hide it by indirection |
Bugfixes
#64 | Code generation fails when foreign key references a unique key that is not the primary key. Code generation for these cases is omitted |
#67 | When loading properties files, a leading / seems to be mandatory. This is preventing users from correctly setting up jOOQ the first time |
#70 | Add support for Oracle datatype TIMESTAMP(6) |
#72 | Name clashes in generated Tables |
#75 | Constant does not bind its values. |
#76 | Constant should not render strings all the time |
#79 | Constants are not properly escaped |
#80 | Position function does not bind any variables |
#81 | Add cast function to Constants in HSQL |
Version 1.4.1 - October 18, 2010
Oracle patch release
Features
#63 | Generate referential functionality for Oracle |
Version 1.4.0 - October 17, 2010
Support for PostGreSQL was added. Added lots of OR-mapping functionality. There is a general API change due to various new features.
Features
#14 | Add PostGreSQL support |
#40 | Resolve foreign keys. Allow for navigation between objects. |
#42 | Add PlainSQLField |
#45 | Add "dirty" flag to Record's values. This allows for updating only relevant data. |
#47 | Complete implementation for UPDATE, INSERT, DELETE statements. Added some missing functionality. |
#48 | Add more support for Date, Time, Timestamp fields. |
#51 | Add a org.jooq.impl.Manager class that provides common utility methods for CRUD operations |
API changes
#10 | Add second generic type <R extends Record>. This is a prerequisite for many OR-mapping features |
#18 | Use org.jooq.Record in InsertQuery and UpdateQuery |
#46 | Create UpdatableRecords as a prerequisite for JPA and true OR-mapping. These records support store() and delete() methods |
#52 | Add default constructor in generated Records. |
#53 | Add refresh functionality to UpdatableRecords. See also #46 |
#54 | Add a state to the factory class |
#56 | Reduce API, remove unnecessary Condition subinterfaces |
#57 | Reduce API, remove unnecessary QueryPart interfaces |
Bugfixes
#49 | NullPointerException when generating relations on schema subset |
#58 | Count function renders bad SQL in various dialects |
#59 | Exception when selecting unaliased functions in queries |
Version 1.3.0 - August 24, 2010
Support for HSQLDB was added. There is a major API change due to #44.
Features
#29 | Generate primary keys and foreign keys in Oracle code generation |
#34 | Add support for HSQLDB |
#39 | Generate primary keys and foreign keys in HSQLDB code generation |
#41 | Add documentation to QueryFactory and Functions |
API changes
#23 | Add support for more advanced joins |
#32 | Merge SelectQuery and ResultProviderQuery interfaces |
#44 | Let Query methods return "this" |
Bugfixes
#35 | Add unit tests for HSQLDB support |
#37 | Syntax error in combined select queries! The usage of combined queries in MySQL may still be a bit awkward. Keep an eye out for further fixes |
#43 | Join with aliased tables doesn't work |
Version 1.2.0 - August 21, 2010
The added Oracle support is now unit tested and more stable. The Oracle NUMBER data type is mapped more precisely to Java types.
Features
#12 | Model primary keys and foreign keys in generated code |
#22 | Improve mapping of Oracle NUMBER data type |
#26 | Add Plain SQL QueryParts |
#27 | Add support for HAVING clause |
Bugfixes
#24 | Add Unit tests for oracle database (and fixed bugs) |
#31 | Pull up addOrderBy() methods from SelectQuery to ResultProviderQuery |
Version 1.1.0 - August 17, 2010
The main new feature is the Oracle support. Wait for Version 1.1.1 for that support to be stabilised, as there are no Oracle unit tests running against an Oracle database yet.
Features
#2 | Add support for inner / nested selects |
#3 | Add more function support |
#4 | Implement filtering functionality for code generation |
#6 | Add Oracle Support |
#9 | Create true POJO's (implementing org.jooq.Record) with getters and setters |
#17 | Make org.jooq.impl.Parameter independent of Field |
Bugfixes
#11 | Code generation does not remove files |
Version 1.0.1 - August 14, 2010
Features
#5 | Prevent code regeneration, if no changes were made |
#7 | Implement ant task for code generation |