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.17.31 - November 4, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#17473 | Add <description/> to all pom.xml files |
Bug Fixes
#17469 | IndexOutOfBoundsException when calling PostgreSQL table valued function returning empty result, with <tableValuedFunction/> turned off |
#17480 | Bad code generated when activating <springDao/> but not <springAnnotations/> |
#17486 | Parser should support SQL Server's NTEXT type and parse it into NCLOB |
#17492 | 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 |
#17501 | GenerationTool should be more clear about commercial dependencies, when lookups don't work |
#17511 | ORA-00904: invalid identifier when trying to insert into tables with lower case identifier in Oracle |
#17524 | Suppressed NoSuchElementException from ThreadLocalTransactionProvider.rollback prevents rollback when commit fails |
Version 3.17.30 - October 21, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Bug Fixes
#17396 | Meta.ddl() includes synonyms or aliases as tables for some dialects |
#17400 | IN-list padding truncates row IN lists to 1000 elements in Oracle pre 23ai |
#17417 | NUMERIC bind values passed to SQL Server VALUES constructor may lose scale if not explicit DataType is supplied |
#17424 | VALUES types decimal and int cannot be matched when inlining NUMERIC types in CockroachDB |
#17432 | DSLContext::fetchCount for selects with nested records causes DataAccessException |
#17438 | Cannot call Record.reset(Field), Record.original(Field), Record.changed(Field) with embeddable field arguments |
#17444 | ClassCastException during invocation of double-wrapped ConvertedDataType |
#17447 | Wrong field indexes in code generated in record getters and setters for non-replacing embeddables when database reports non-consecutive column ordinals |
#17450 | CREATE TABLE and other DDL statements don't qualify tables in BigQuery |
#17458 | Converter<byte[], U> for binary columns doesn't work from within MULTISET expressions |
Version 3.17.29 - September 26, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#17336 | MetaImpl exceptions should indicate table and column if applicable, which caused the exception |
#17379 | Add a link to DSL::coerce from DSL::cast and Field::cast |
Bug Fixes
#17301 | SQLite's binding of BigDecimal through PreparedStatement.setString() doesn't work for predicates |
#17326 | Upgrade Spring dependency from jOOQ-meta-extensions-hibernate to 5.3.39 due to CVE-2024-38808 |
#17329 | Upgrade jOOQ-checker's transitive guava dependency to 32.1.3-jre due to CVE-2023-2976 |
#17332 | R2DBC Connection leak when cancelling pending connection with ConnectionPool |
#17340 | ORA-17068: Invalid arguments in call when calling OracleDatabaseMetaData.getIndexInfo() with quoted object names |
#17347 | MetaImpl and code generator should ignore MySQL's dummy REMARKS column on DatabaseMetaData::getTables for views |
#17358 | Regression when generating DDL from certain generated views |
#17362 | DDL::applyAsPlainSQL should trim plain SQL string to check if it starts with CREATE |
#17368 | UserImpl::$replace produces a RoleImpl instance |
#17373 | Oracle PL/SQL %ROWTYPE references should be declared as such in anonymous blocks when calling procedures |
Version 3.17.28 - September 23, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#17103 | Add DataType.isTimestampWithTimeZone() for INSTANT and OFFSETDATETIME and isTimeWithTimeZone() for OffsetTime |
#17211 | Revert deprecation of serialization support |
#17297 | Document the fact that org.jooq.Binding does not necessarily have to implement a complete org.jooq.Converter |
#17304 | Add new DataType.isDecimal() method to check if DataType.isNumeric() and it has a decimal representation |
Bug Fixes
#17051 | Upgrade pgjdbc dependency to 42.7.3 to mitigate CVE-2024-1597 |
#17066 | Update DataType.isXYZ() Javadoc with new types |
#17073 | TIME(0), LOCALTIME(0), OFFSETDATETIME(0), and INSTANT(0) don't work in DDL statements as the datetime precision is simply omitted |
#17078 | Redundant unique index on primary key makes foreign keys disappear in PostgreSQL |
#17086 | HANA's WITH ORDINALITY emulation doesn't maintain correct ordering of ORDINALITY |
#17090 | Fix R2DBC support for TIMESTAMP WITH TIME ZONE types |
#17098 | Fix support for special float values NaN, Infinity in MULTISET usage |
#17111 | Invalid SQL generated for INSERT .. ON DUPLICATE KEY IGNORE or ON DUPLICATE KEY UPDATE emulations using MERGE |
#17116 | KotlinGenerator contains incomplete list of Kotlin forbidden identifier characters |
#17120 | Bad code generated for enum values containing backslash character |
#17123 | CASE expression on BOOLEAN type emulation in JSON constructor causes ORA-40590: invalid format on Oracle XE 18 |
#17129 | MySQL boolean type information isn't maintained across expressions when embedded into JSON |
#17138 | <unsignedTypes/> flag doesn't work outside of MySQLDatabase |
#17153 | Join paths don't work when embeddable keys or domains on keys are present |
#17162 | Meta::ddl produces incorrect DDL for SQLite, when there are FOREIGN KEY constraints |
#17168 | Using embedded domains with POJO generation results in duplicate getters |
#17174 | Overload resolution ambiguity in KotlinGenerator generated code for embeddable domains |
#17193 | Multiset Result and Records are attached to derived configuration, not original one |
#17199 | ScalaGenerator produces wrong code when generated interfaces (traits) extend multiple other interfaces |
#17206 | IllegalAccessException when creating DSL.table(R...) from list of Kotlin generated TableRecords |
#17215 | NPE while reading timestamp data type value for SAP SQL Anywhere 17 with jconn4 |
#17219 | Error in SybaseDatabase when generating code for routines |
#17230 | Missing Support and NotNull annotations in ConstraintForeignKeyReferencesStepN |
#17239 | Improve error message in GeneratorWriter when brackets mismatch, including the offending file |
#17250 | Log warnings when Java record constructor has more than 254 parameters |
#17258 | Parser should accept qualified field references in MERGE .. INSERT statement |
#17262 | Meta::filterCatalogs is applied too late for internal MetaImpl queries executed by Meta::ddl |
#17266 | NullPointerException in MetaImpl::lookupTable when Schema isn't available for lookup of cross-schema foreign keys |
#17269 | Exception when accessing MetaImpl::ddl with a user that lacks privileges to access certain databasese in SQL Server |
#17283 | Work around DERBY-7170 when fetching sources for tables in MetaImpl or DerbyDatabase |
#17287 | Cannot parse default expression in Derby using MetaImpl when computed column is reported as DEFAULT |
#17291 | NullPointerException in MetaImpl.getUniqueKeys() query when unique key cannot look up column references due to missing privileges |
#17307 | Records.mapping() implementations should handle null records |
#17314 | JPADatabase should throw Hibernate's exceptions when there is anything going wrong with the SchemaExport |
#17318 | Upgrade jOOQ-checker's protobuf-java transitive dependency due to CVE-2024-7254 |
Version 3.17.27 - August 13, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#16887 | Improve DataTypeException error message when encountering internal UnknownType |
#16921 | Clarify in manual and Javadoc that NoXYZ QueryParts are to be used only with the DSL API, not with the QOM API |
Bug Fixes
#16848 | Correctly implement numerous Oracle specific ST_Geometry spatial functions |
#16856 | MySQL error "BLOB, TEXT, GEOMETRY or JSON column can't have a default value" when running DDL from generated code |
#16860 | SQLite's MetaImpl can't distinguish between multiple unnamed UNIQUE constraints |
#16863 | Avoid static members in jOOQ-meta Definition classes to avoid stale build caching |
#16881 | Wrong cast syntax used for BigQuery ARRAY types |
#16895 | Invalid link in Fields javadoc |
#16899 | TIMESTAMP(0) doens't work in DDL statements as the datetime precision is simply omitted |
#16905 | Wrong replacement output when emulating data change delta tables in CockroachDB |
#16915 | Wrong syntax rendered for SQL Server UNION queries with LIMIT in their subqueries |
#16931 | Wrong SQL generated in SQL Server when using UNION .. LIMIT without OFFSET |
#16937 | SQL Server MULTISET subquery ORDER BY clause doesn't work with UNION |
#16941 | Work around SQL Server's peculiar UNION with ORDER BY .. OFFSET .. FETCH implementation in derived tables |
#16945 | Bad OFFSET emulation in UNION queries when OFFSET contains an expression |
#16949 | Wrong emulation of DISTINCT ON with UNION |
#16952 | Wrong combination of emulations: DISTINCT ON with UNION and LIMIT with expressions |
#16957 | Empty window definition in WINDOW clause isn't emulated correctly in SQLDialect.ORACLE18C |
#16960 | Wrong WITH TIES emulation when combined with QUALIFY if QUALIFY is supported natively |
#16971 | Force inline bind values after 2536 in Teradata |
#16991 | Correctly name Apache-2.0 everywhere |
#17002 | Code generation order provider isn't being applied to TableDefinition.getXYZ() methods |
#17008 | Error when trying to delay DataType inference for scalar SQL type converted to user array type |
#17012 | SQLite unnamed unique constraints are listed in a non-deterministic order by code generator |
#17016 | Exception when doing Meta.ddl() export with tables that have USE or GO or similar field or table aliases |
#17029 | Repeated WHERE FALSE clause in CREATE TABLE AS SELECT .. WITH NO DATA emulation, when query is nested |
#17033 | JDBCUtils.dialect() detects wrong MySQL dialect for versions > 8.1 |
#17043 | SQLDialect.JAVA warning message about derived tables not being supported is misleading |
Version 3.17.26 - June 14, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#16808 | Clarify EmbeddableRecord Javadoc |
Bug Fixes
#16742 | Internal SelectQueryImpl::copy behaviour may produce inconsistent copy of WINDOW clause |
#16748 | Wrong SQL rendered for MS Access CONCAT function with more than 2 arguments |
#16758 | Work around BigQuery's SELECT without FROM clause cannot use aggregation limitation |
#16765 | Parser meta lookup fails for DUAL table |
#16772 | Work around BigQuery ORDER BY clause limitation where identifiers cannot be resolved if the table and the column share the same name |
#16776 | Work around BigQuery limitation of using: HAVING clause on a non-aggregate query |
#16780 | Support BigQuery's QUALIFY .. WINDOW keyword order |
#16789 | Fix null treatment syntax of window functions in BigQuery |
#16795 | Inconsistent formatting of HSQLDB DUAL table emulation |
#16800 | Parser error when trying to parse hypothetical set function with FILTER clause |
Version 3.17.25 - May 30, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Bug Fixes
#16654 | TableRecords should refresh() themselves for HANA dialect, when any non-identity value should be fetched after an insert |
#16665 | Wrong source code generated when newline escape sequence of long view source is split into two |
#16674 | Update using multi-column set clause with DSL.row and custom type logs warn on deprecated static type registry |
#16678 | SQLite "Cannot parse or interpret sql for table" error with both unique columns and foreign key constraints |
#16689 | Error in CockroachDBDatabase when running SHOW INDEXES for table valued function |
#16694 | Work around KT-68407 compiler error in generated AbstractSpringDAOImpl class in kotlin 2.0 |
#16699 | Memory leak in DefaultCacheProvider when large amounts of arbitrary projections are mapped with DefaultRecordMapper |
#16724 | Confusing error message when reading a non-existing Field from a Record containing accidentally nested row types |
#16728 | Avoid operator associativity rendering logic if operator isn't nested |
Version 3.17.24 - May 2, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Bug Fixes
#16550 | Auto wrap Field arguments to a Routine's Object typed parameter in Field<Object> |
#16555 | Work around lack of support for INSERT .. SELECT .. UNION [ ALL ] SELECT in SingleStore |
#16574 | DELETE .. ORDER BY .. LIMIT on partitioned tables without unique constraint uses non-unique ctid for self joins |
#16584 | Time zone information lost when fetching TIMETZ[] value in PostgreSQL |
#16588 | Work around HSQLDB bug where wrong LocalTime value is fetched when using bind values of type LocalTime[] |
#16605 | Wrong cast type name when casting value to NCLOB in Firebird |
#16619 | Fix order of NOT NULL and DEFAULT clauses in BigQuery CREATE TABLE statements |
Version 3.17.23 - April 4, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#16491 | Add DataType.isFloat() |
Bug Fixes
#16464 | SEEK doesn't work correctly when there are multiple noField() arguments and ORDER BY is uniform and Settings.renderRowConditionForSeekClause is true |
#16473 | Work around CockroachDB's lack of support for the POWER() function accepting integer arguments |
#16476 | jOOQ parser parses indexed parameters as named |
#16482 | SQL Server's CREATE cannot fully qualify a sequence name |
#16497 | Intercept SQLFeatureNotSupportedException caused by DatabaseMetaData::getImportedKeys and other calls |
#16506 | Improve compilation speeds of generated QOM types |
#16513 | Avoid PostgreSQL empty array cast when explicit cast is given |
#16538 | Parser fails to parse TIME[STAMP] WITH TIME ZONE literals |
#16542 | Incorrect conversion of LocalDateTime to LocalDate during daylight saving time |
Version 3.17.22 - March 8, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Bug Fixes
#16350 | Parser fails with StringIndexOutOfBoundsException when encountering invalid PostgreSQL unicode literal |
#16353 | Parser shouldn't fail with NumberFormatException |
#16359 | ParsingConnection doesn't correctly execute batches when using ParamType.INLINED or StatementType.STATIC_STATEMENT |
#16366 | UUID bind values should be auto-cast to avoid issues with lack of auto-conversion support in PostgreSQL |
#16373 | Parser always parses NULL literal of type BOOLEAN |
#16384 | DataType should cache null_() and notNull() variants |
#16388 | Add some WARN logs when synthetic key objects aren't matched |
#16391 | Add arity check to synthetic foreign key configuration to avoid wrong generated code when FK / UK columns mismatch |
#16396 | Empty derived column lists generate wrong SQL syntax |
#16399 | Regression in fetchCount execution when argument query uses plain SQL tables |
#16408 | Parser doesn't support GROUPING SETS with <ordinary grouping set> specification |
#16413 | Code generator and MetaImpl return CREATE DEFAULT statement instead of just the default expression |
Version 3.17.21 - February 27, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Bug Fixes
#16322 | Wrong SQL generated when nesting predicates on subqueries projecting embeddables within MULTISET |
#16325 | SelectIsNull renders invalid SQL when SELECT projection is embeddable |
#16329 | DSLContext.fetchCount(Select) produces wrong SQL when query projects embeddables |
#16339 | NumberFormatException in parser when encountering double value with implicit 0 exponent |
#16343 | DefaultRenderContext::peekIndex doesn't contain correct bind index |
Version 3.17.20 - February 20, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Bug Fixes
#16131 | Maximum consumed results reached when Hikari close a SQL Server connection, leading to excessive logging |
#16183 | %ROWTYPE UDT types generate invalid system columns when underlying table references object types |
#16198 | Overall performance improvement in AbstractNamed.hashCode() specialisations by avoiding Name::append |
#16206 | Remove internal AbstractContext::toggle utilities |
#16212 | AbstractScope::dsl, ::settings, ::dialect, and ::family should avoid unnecessary null-checks on Configuration |
#16235 | Wrong Support annotation on CREATE TRIGGER for INFORMIX |
#16240 | IndexOutOfBoundsException in DerbyDatabase when <includeExcludeColumns/> excludes a column from an index |
#16249 | Avoid allocating DataMap in short lived Scope implementations |
#16252 | Cache TableRecord Constructor in TableImpl for use in Tools.recordFactory() |
#16261 | Avoid allocating Collections.nCopies in ScopeStack |
#16265 | Avoid allocating JoinNode in scope registration of tables if unnecessary |
#16269 | Avoid constructing DSL.name() for constant internal names |
#16273 | Refactor QualifiedName to improve performance |
#16278 | name(null, "") should equal to name("") |
#16282 | Result::formatXML should omit type attribute on columns whose type is unknown |
#16286 | Meta::ddl generates incorrect queries for SQL Server (max) lengths |
#16305 | Can't parse MySQL ALTER TABLE .. DROP .., DROP .. syntax |
Version 3.17.19 - January 19, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Bug Fixes
#16078 | Compilation error in ScalaGenerator generated code of generated DAOs when using scalac 3 |
#16097 | Compilation error in ScalaGenerator generated Keys.scala class when using GeneratorStrategy |
#16108 | Wrong Javadoc in RTRIM() and LTRIM() |
Version 3.17.18 - January 12, 2024
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#16025 | 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) |
#16047 | org.jooq.tools.Convert should delegate to org.jooq.impl.Convert, instead of duplicating implementations |
Bug Fixes
#16016 | Compilation error in KotlinGenerator generated code when GeneratorStrategy produces identifiers conflicting with property access syntax of AbstractRoutine getters |
#16028 | Cannot project TableAsField if table contains embeddables in PostgreSQL |
#16034 | SQLPerformanceWarning should log hint about gathering dictionary statistics in OracleDatabase |
#16042 | Compilation error in JavaGenerator generated code when <pojosAsJavaRecordClasses> is active and a table references a UDT |
#16051 | DATE column in Oracle is null when fetched through multiset |
#16062 | MetaSQL lookups are done with SQLDialect.family(), not SQLDialect |
#16068 | Add Javadoc to all XJC-generated "withers" and setters of boolean types |
Version 3.17.17 - December 20, 2023
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#15794 | Offer a public Maven repository for commercial distributions (maven-install.sh and maven-deploy.sh hints) |
#15858 | Deprecation log warning about <dateAsTimestamp/> should link to relevant manual section |
Bug Fixes
#15705 | Reactive transaction hangs when exception thrown in lambda constructing reactive flow |
#15716 | Possible compilation errors in generated code when column names contain double quotes |
#15726 | BindingSetStatementContext should reference actual ExecuteContext, if available |
#15729 | DefaultStringBinding should bind java.sql.Clob for CLOB types in Oracle MERGE statements |
#15737 | Ill-formed Javadoc causes JDK 21 javadoc tool to crash |
#15740 | BatchCRUD does not update optimistic locking version and timestamp values in UpdatableRecord |
#15748 | Syntax error when from current_timestamp when precision bind value is specified for Postgres |
#15758 | Implicit JOIN implementation for DML is incorrect if paths navigate self joins |
#15764 | Compile errors of generated classes using scala 3 |
#15769 | JSONB inline values should be rendered using JSONB.data() not JSONB.toString() |
#15772 | MiniJAXB::marshal(XMLAppendable, OutputStream) does not flush decorating writer |
#15785 | Add Javadoc to the Query::bind methods indicating that they bind values in the rendered order, not the input order |
#15801 | LazyVal::generatesCast should return true |
#15806 | MetaImpl reports system indexes for Derby 10.16 |
#15841 | Support overlapping embeddables when enabling <embeddablePrimaryKeys/> |
#15852 | Compilation error in KotlinGenerator generated code for tables containing a FROM column, when <interfaces> is activated |
#15855 | Accidental override when enabling <interfaces> for tables with columns X and IS_X in Kotlin |
#15878 | Internal RecordDataType.getDataType() should be non-nullable for records consisting of all non-null fields |
#15881 | IllegalArgumentException when calling UpdatableRecord methods on tables with embedded domains that replace their underlying fields |
#15885 | Compilation error in generated code when using <embeddableDomains/> and the domain is part of a composite key |
#15896 | NullPointerException when using plain SQL identity and additional column in INSERT .. RETURNING |
#15903 | Incorrect ExecuteListener Javadoc regarding ExecuteListener lifecycle |
#15920 | AbstractDatabase::markUsed doesn't work in some edge cases |
#15929 | SnowflakeDataType is missing references to Snowflake's JDBC-internal spellings of TIMESTAMPNTZ, TIMESTAMPLTZ, TIMESTAMPTZ |
#15950 | Compilation error in KotlinGenerator generated code with KeepNamesGeneratorStrategy and generated implicit join paths |
#15956 | SQLite requires parenthesised DEFAULT expressions in DDL |
#15961 | YugabyteDB doesn't support ALTER TABLE .. DROP CONSTRAINT IF EXISTS |
Version 3.17.16 - October 10, 2023
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#15522 | Add a log message whenever an exception occurs with the SQLDialect.DEFAULT |
Bug Fixes
#15480 | AutoConverter should be lenient about TIME type fractional seconds |
#15484 | Can't invoke default methods on proxied types returned by DefaultRecordMapper in JDK 9 or more |
#15493 | Code generation fails on BigQuery when querying INFORMATION_SCHEMA without a DefaultDataset being specified |
#15501 | Work around SQL Server's 1000 row value limitation for INSERT statements |
#15526 | Missing Stringly annotation on String... varargs parameters |
#15541 | Meta.ddl() should export tables first, then views |
#15561 | Datetime precision isn't maintained by code generator for domain types |
#15566 | DefaultRecordMapper should skip most mappers when an instance is provided |
#15571 | Record.into(recordInstance) should modify argument record |
#15577 | DefaultOtherBinding shouldn't create string literals for inline values for numeric data types |
#15580 | MutablePOJOMapper should be able to map to instance, even if there isn't a default constructor |
#15586 | Install shell/batch scripts should be clearer about Java 17+ support |
#15600 | Fix DefaultRecordMapper Javadoc to reflect actual behaviour |
#15604 | Plain SQL Javadoc disclaimer is absent on api generator generated step methods |
#15616 | Wrong Support annotation on COMMENT ON COLUMN for MariaDB |
#15648 | On JDK 21, generated code should apply "this-escape" warning suppression |
#15652 | DefaultConfiguration doesn't serialize AuditProvider or TransformProvider |
#15660 | KotlinGenerator - isKotlinNotNullPojoAttributes setting prevents generated DAO to set serial ID to pojo |
#15663 | Copy paste errors in likeIgnoreCase and containsIgnoreCase Javadoc |
#15666 | Query::isExecutable should be checked in the R2DBC implementation, allowing no-ops for non-executable queries |
#15670 | INSERT .. ON DUPLICATE KEY UPDATE emulation mustn't silently insert the last row only in Derby multi row inserts |
#15675 | Domains aren't generated if they don't have a CHECK constraint associated with them, in HSQLDB |
#15680 | Code generator doesn't generate multiple check constraints for DOMAIN types |
#15689 | HANA sort indirection doesn't work with bind values |
Version 3.17.15 - August 10, 2023
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#15288 | Add Javadoc to discourage using any m(Class<T>) method if there's an m(DataType<T>) overload |
#15312 | Builds should log their build date with the logo |
#15417 | "Ambiguous match found" warning log should reference qualified field name, if available |
#15450 | Add Javadoc hints about Record.changed() values to InsertValuesStep[N].valuesOfRecords(...) |
Bug Fixes
#15295 | Meta.ddl() export generates wrong DDL for constraints with USING INDEX clause in Oracle |
#15305 | Meta.ddl() generates broken DDL for smallserial columns |
#15329 | Error when generating code from a MariaDB database containing packages |
#15338 | Parser error when using SET new.x = y syntax in triggers |
#15343 | Bad syntax in Firebird when creating triggers for unquoted table names |
#15361 | Block::$replace doesn't replace anything |
#15368 | Avoid generating sort specification in indexes in dialects that don't support it |
#15377 | Table with 255 columns generates record and POJO objects whose constructors have too many parameters |
#15380 | Batch::executeAsync throws NullPointerException when executed with R2DBC driver |
#15386 | Compilation error in generated code when global object references conflict with schema names |
#15390 | Settings.metaIncludeSystemIndexes doesn't work for system indexes of unnamed constraints in HSQLDB |
#15397 | MetaImpl is missing view source code or unique constraints for objects in other catalogs |
#15404 | Bad formatting of hints at the end of maven-install.sh scripts |
#15421 | Can't generate code using CockroachDB materialized view |
#15425 | Table list to ANSI JOIN transformation doesn't work if table declarations are fully qualified, but references are not |
#15445 | Exception when MockResult contains UDTRecord |
#15457 | AutoConverter loses nanosecond precision when converting from Instant to LocalDateTime or OffsetDateTime |
Version 3.17.14 - June 23, 2023
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#15077 | maven-install and maven-deploy shell scripts should use -e flag to report more error info |
#15119 | Add a jooq.codegen.propertyOverride system property to GenerationTool |
#15132 | Add DSLContext.transactionCoroutine overload accepting CoroutineContext |
#15140 | Improve Javadoc on DSLContext.executeInsert(), executeUpdate(), and executeDelete() about optimistic locking not applying |
#15233 | Add support for MySQL DECIMAL/FLOAT/DOUBLE/REAL UNSIGNED types in Meta and code generation |
Deprecations
#15199 | Deprecate inconsistent DSL.jsonObject(Field...) and DSL.jsonbObject(Field...) overloads |
Bug Fixes
#15063 | DDLDatabase defaultNameCase=lower doesn't work with ENUM types |
#15067 | Unable to rename table with qualified target table name |
#15080 | Add error message to maven-install.sh which doesn't work with Maven 3.9.0 due to MNG-7679 |
#15083 | Parser meta lookup fails when using qualified asterisk on a table alias |
#15090 | Misleading error message when ON KEY finds ambiguous keys |
#15110 | Compilation error in Oracle generated code for package type in PL/SQL RECORD constructor |
#15112 | Ambiguous type name warning for non-ambiguous type name in OracleDatabase |
#15123 | Wrong warning logged regarding CockroachDB version support |
#15129 | DefaultConfiguration::toString logs wrong flags in R2DBC context |
#15134 | Use awaitSingle instead of awaitFirstOrNull in transactionCoroutine to correctly sequence transaction script |
#15137 | Improve error message when unversioned, row based optimistic locking doesn't work with DAOs and POJOs |
#15151 | PostgresDatabase and subtypes may produce wrong table comments in presence of stored functions |
#15170 | NullPointerException in code generator when omitting <target> directory |
#15185 | Compilation error in generated DAO code when visibility of a field is changed to private |
#15193 | PostgreSQL: array(<domain over UUID>) causes exception |
#15204 | Add missing Experimental annotation to migrations API types |
#15216 | H2 dialect should cast binary data of unknown length as VARBINARY, not as BINARY |
#15220 | NullPointerException in AbstractMeta::lookupTable and other methods, when there is no DefaultCatalog |
#15241 | MetaImpl::ddl() should produce plain SQL CREATE VIEW statements if it can't parse the view contents |
#15244 | Ambiguous match found when using aliases with implicit join and joining the same table twice |
#15255 | ScalaGenerator produces wrong code when generator strategy adds multiple interfaces to legacy enum type |
#15263 | Add Javadoc to plain SQL DSL.field() constructors recommending to use code generation or at least pass a DataType |
#15268 | LoggerListener logs some batch queries twice, when using BatchMultiple |
#15273 | Wrong implementation of SelectQueryImpl::wrapQueryExpressionBodyInDerivedTable in jOOQ Open Source Edition |
Version 3.17.13 - May 11, 2023
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#14956 | Add Javadoc hints about implementation of JSONB::toString, JSONB::hashCode, and JSONB::equals |
#14969 | Reactive batch implementations should throw UnsupportedOperationException with a message |
#15010 | Cannot pass Table reference to row() constructor in array or list |
Bug Fixes
#14940 | Unstable ordering of Derby generated foreign keys |
#14951 | Upgrade spring-core dependency to mitigate CVE-2023-20863 |
#14962 | No-arg DefaultConfiguration() constructor clones default settings twice |
#15000 | OffsetDateTimeRange javadoc should reference tstzrange not tsrange |
#15017 | A few MySQL 5.6 related fixes |
#15030 | Support NULL bind values of type Interval in R2DBC integration |
#15033 | R2DBC bind value related exceptions produce misleading error message |
#15044 | Support NULL bind values of type UUID in R2DBC integration |
Version 3.17.12 - April 11, 2023
This is a 3.17 patch release with minor improvements and bug fixes
Bug Fixes
#14886 | Regression: KotlinGenerator produces superfluous public keyword for overriding methods |
#14888 | Generate nullable annotations also on record constructor, when <pojosAsJavaRecordClasses/> is set |
#14892 | QUALIFY transformation should unalias columns again |
#14897 | Add Javadoc to DAO::insert and DAO::update regarding Settings.returnRecordToPojo |
#14910 | Missing parentheses when second subquery in set operation contains deep nesting |
#14918 | ERROR: type "blob" does not exist when casting NULL as a domain converted as user defined type using class literal |
#14921 | Compilation error with embedded domains and postgres types |
#14926 | Explicitly set locale to English in maven-javadoc-plugin |
Version 3.17.11 - March 29, 2023
This is a 3.17 patch release with minor improvements and bug fixes
Bug Fixes
#14835 | Version support check shouldn't log error message for MockConnection |
#14847 | Upgrade Spring to mitigate CVE-2023-20861 |
#14851 | ROLLUP, CUBE should generate Keyword, not Name |
#14857 | Compilation error in generated code for embeddable properties when reducing visibility to internal, and generating interfaces |
#14860 | Kotlin Code generator generates invalid code for embeddables in POJOs when immutable interfaces is activated |
#14863 | Kotlin Code generator generates invalid code for embeddables in POJOs when immutable interfaces is activated |
#14878 | Add warnings to manual and Javadoc about ON KEY ambiguity caveats |
Version 3.17.10 - March 21, 2023
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#14820 | Add a remark on the Converter Javadoc that implementations must be able to handle NULL |
Bug Fixes
#14766 | Avoid dialect version lookup in AbstractDatabase, if unnecessary |
#14782 | Correctly annotate SIMILAR TO operator |
#14793 | SQLDialect version check throws NumberFormatException in Percona DB |
#14826 | <clinit> race conditions in jOOQ internals |
Version 3.17.9 - March 8, 2023
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#14638 | Log warning when unsupported dialect version is being used |
#14691 | Add parser support for SQLite's WITHOUT ROWID tables |
#14709 | PostgreSQL interval parser handle fractional seconds with interval style iso_8601 |
#14714 | Add support for interval types in DefaultConverterProvider |
Bug Fixes
#14619 | SQL Server nullability information isn't generated correctly for domains |
#14622 | Work around a YugabyteDB regression querying the INFORMATION_SCHEMA.ATTRIBUTES table |
#14625 | Missing nullability information on nullable DOMAIN types that are made non-null by CREATE TABLE |
#14629 | Missing default information on DOMAIN types that get an overridden DEFAULT by CREATE TABLE |
#14632 | Add parser support for SQLite's STRICT tables |
#14636 | Single message JooqLogger doesn't work |
#14645 | LoggerListener::fetchEnd should check if DEBUG logging is enabled |
#14651 | Wrong emulation of GENERATE_SERIES with STEP parameter for Snowflake |
#14669 | Wrong ON KEY JOIN generated when aliased table appears twice in the JOIN tree |
#14673 | Wrong column resolved by JoinTable.field(Field), when JoinTable contains aliased tables and lookup uses unaliased tables |
#14678 | JoinTable.onKey(ForeignKey) does not work when tables are aliased |
#14688 | Translator duplicates comment only content when retaining comments |
#14697 | Wrapping SQLException must copy SQLState and other info from wrapped SQLException |
#14704 | SQL Server RETURNING clause emulation for fetching server side computed columns generates incorrect SQL if only computed columns are fetched |
#14705 | INSERT statement does not apply types to bind values in VALUES clause when using valuesOfRows() |
#14715 | UnsupportedOperationException when selecting row with YearToSecond |
#14732 | Use LazyName in AbstractParam |
#14734 | Push down ScopeMappable marker interface from AbstractField to AbstractWindowFunction and TableFieldImpl |
#14740 | PostgreSQL Numeric array type with precision/scale too large in generated code |
#14745 | Slow TableAlias::equals implementation, when argument type is TableImpl |
#14748 | Speed up AbstractRow.equals() and hashCode() when comparing with other AbstractRow |
#14753 | Nesting MULTISET/ROW/MULTISET/ROW with ad-hoc converters and JSON emulation results in ClassCastException |
#14758 | VALUES() must cast NULL literals in the first row, if the type is known and the RDBMS cannot infer it |
Version 3.17.8 - February 9, 2023
This is a 3.17 patch release with minor improvements and bug fixes
Bug Fixes
#14520 | Building jOOQ on Java 19 fails in xtend |
#14525 | Compilation error due to missing import in generated code when using <lambdaConverter/> on a routine |
#14531 | NullPointerException in DB2Database when constraint schema is unavailable |
#14536 | Fix org.jooq.Null Javadoc |
#14542 | Add support for top level nested records in R2DBC queries |
#14575 | Regression: Meta::getTables returns tables of type TableType.TABLE when they're actually system views |
#14587 | Use ? as parameter marker on MySQL, MariaDB when using R2DBC |
#14589 | KotlinGenerator generates invalid code in equals() and hashCode() methods for inline value class fields |
#14596 | Regression: UpdateQuery.execute() with RETURNING clause returns 1 even when no records were updated |
#14600 | setAllToExcluded also sets fields not specified in insert to excluded when using INSERT .. SET syntax |
#14601 | Exception while executing meta query on MySQL 5.6: Unknown column 'information_schema.COLUMNS.GENERATION_EXPRESSION' |
#14603 | CockroachDBDatabase doesn't report enum types on columns correctly anymore |
Version 3.17.7 - January 17, 2023
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#14401 | Code generator should properly qualify H2 domain enums |
#14500 | Add an R2DBC LoggingConnection |
Bug Fixes
#14384 | Broken link in a logging statement and Javadoc |
#14390 | Table::useIndex and similar table wrapping methods break joins using onKey() |
#14396 | DSL::noField doesn't work in SEEK clause |
#14399 | java.lang.StackOverflowError at org.jooq.impl.Expression.acceptAssociative |
#14404 | "You can't specify target table '...' for update in FROM clause" when target table has index hint in MySQL |
#14415 | DDLDatabase cannot handle qualified enum types in CREATE TABLE |
#14422 | Update error reporting URL in log messages |
#14427 | Code generation for sequences fails for SQL Server 2014 |
#14434 | Generated TableImpl::getSchema override should be annotated Nullable |
#14460 | Work around Db2 error "The string constant beginning with ... is too long" |
#14467 | Wrong result column type for requested conversion when reading JSONB_ARRAYAGG and JSONB_OBJECTAGG in DB2 |
#14480 | SQL Server RETURNING clause emulation for fetching trigger generated values generates incorrect SQL if no columns are fetched |
#14484 | Wrong SQL generated in SQL Server when virtual client side computed columns are referenced in RETURNING clause |
#14493 | Syntax errors lead to unclosed R2DBC connection in SQL Server |
#14497 | TransactionPublisher does not commit transaction when wrapped in reactor's Mono |
Version 3.17.6 - December 8, 2022
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#14243 | Add support for DB2 ROWNUMBER and DENSERANK window function in parser |
Bug Fixes
#14177 | ParserCLI in interactive mode should use Settings defaults for its SQL transformation flags |
#14183 | MANIFEST.MF contains unnecessary javax.persistence dependency |
#14188 | StackOverflowError in transformPatternsArithmeticExpressions when commutative operator has 2 inline arguments |
#14192 | DefaultDiagnosticsContext should cache resultSetFetchedRows |
#14197 | Bad syntax generated when using the Field.collate() clause in CREATE TABLE statements |
#14211 | Regression in MS Access CONCAT implementation |
#14219 | Plain SQL INSERT .. RETURNING doesn't work with unqualified field templates in SQL Server |
#14221 | Update blog links from Javadoc and comments |
#14227 | Outdated Javadoc on DSL.array() for how jOOQ renders H2 array constructors |
#14233 | ORA-00904: "v0"."GET_WKT": invalid identifier |
#14234 | Cannot query geometry value in a nested ROW |
#14235 | Cannot query geometry value in a multiset |
#14237 | DefaultDiagnosticsContext shouldn't call ResultSet::getMetaData on already closed ResultSet |
#14240 | Work around SQLite's error: HAVING clause on a non-aggregate query |
#14259 | ClassCastException in WithImpl::$replace |
#14265 | Improve generated unknown data type javadoc when forcedTypes match return type, but there are still unknown parameter types |
#14277 | Median emulation ignores FILTER and OVER clauses |
#14281 | AbstractToJacksonConverter does not work when userType is array |
#14284 | Kotlin Value Classes in Constructor lead to name based mapping failure |
#14287 | Upgrade pgjdbc to 42.4.3 to mitigate CVE-2022-41946 |
#14290 | ScalaGenerator generated code should avoid "procedure syntax" |
#14292 | ForcedType enum with no matching value being converted to last enum value |
#14295 | ON CONFLICT DO NOTHING emulation should continue to be applied for PostgreSQL 9.3 and 9.4 |
#14304 | In MySQL, withReturnAllOnUpdatableRecord(true) causes two SELECT statements |
#14314 | Informix DDL statements generate invalid SQL for timestamp columns |
#14317 | Informix CURRENT_TIMESTAMP emulation doesn't work as DDL DEFAULT expression |
#14322 | Wrong NULL behaviour of BitAndAgg, BitOrAgg, and related aggregate function emulations |
#14326 | Informix BOOLEAN literals 't' and 'f' need to be cast to BOOLEAN explicitly |
#14329 | Excess query executed against SQLite when emulating INSERT .. RETURNING |
#14334 | ArrayIndexOutOfBoundsException when parsing ill formed SQL ending with a comment and a semicolon |
#14340 | Exception in Teradata code generation: Unknown column TVName |
#14344 | StackOverflowError in parser with Settings.parseWithMetaLookups == IGNORE_ON_FAILURE |
#14347 | Error: Invalid Top N Value: N is too big for Teradata OFFSET emulation |
#14350 | Teradata TOP expression or DISTINCT TOP don't work |
#14354 | Parser meta lookups don't work correctly when using DELETE .. FROM with aliased tables |
#14369 | Meta::getTables should list also PARTITIONED TABLE |
#14374 | Parser produces wrong projection data type when parsing doubly nested derived table |
#14376 | Parser reports wrong Ambiguous field identifier error when derived tables share column names |
Version 3.17.5 - November 4, 2022
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#13997 | Improve documentation on Fields lookup methods |
#14072 | Add parser support for undocumented AS keyword in SQL Server procedure parameter list |
Bug Fixes
#13966 | HSQLDB arrays can't be projected from nested rows |
#13983 | ParsingConnection doesn't correctly relay Statement::getResultSet, Statement::getUpdateCount, or Statement::getMoreResults on static Statement |
#13994 | Wrong value returned from NullCondition::isNullable |
#14015 | Slow query against SYS.ALL_INDEXES in OracleDatabase |
#14018 | Moderately slow query on ALL_TAB_COLS due to cartesian product in OracleTableDefinition |
#14022 | Moderately slow query on ALL_ARGUMENTS due to EXTENDED DATA LINK FULL in OracleTableDefinition |
#14024 | Postgres array of single-field UDT reads UDT's field as null instead of actual value |
#14028 | ClobBinding and BlobBinding shouldn't delegate sql() generation to internal DefaultStringBinding or DefaultBytesBinding |
#14031 | ORA-01704 when generating large CLOB inline values in Oracle |
#14035 | Upgrade to Scala 2.13.9 to mitigate CVE-2022-36944 |
#14037 | KotlinGenerator produces directory names with backticks when catalog names contain special characters |
#14054 | Upgrade jackson-databind dependency to 2.13.4 to mitigate CVE-2022-42004 |
#14056 | Upgrade protobuf-java to 3.16.3 to mitigate CVE-2021-22569 |
#14061 | Work around Derby's Error [30000] [54002]: A string constant starting with '...' is too long |
#14068 | ClobBinding and BlobBinding shouldn't bind a null value on PreparedStatement::setClob and ::setBlob in Firebird, HSQLDB |
#14087 | Support parsing SELECT .. INTO <qualified table> FROM .. |
#14101 | Table as SelectField native support relies on actual column order, not generated order |
#14109 | Upgrade jackson-databind dependency to 2.13.4.2 to mitigate CVE-2022-42003 |
#14117 | ClassCastException when nesting array(select row) projections in PostgreSQL |
#14134 | Code generator shouldn't generate JPA Column precision on non-decimal types |
#14142 | Generated text blocks for view sources should escape \ |
#14164 | Wrong transformation for transformPatternsTrivialPredicates when DISTINCT predicate operand is NULL |
Version 3.17.4 - September 6, 2022
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#13886 | Parse length on unknown data types |
#13888 | Parse and ignore SQLite DDL conflict-clause |
#13931 | Show deprecation warning for javax.persistence annotations also for method and field annotations |
Bug Fixes
#13874 | PostgreSQL arrays don't deserialise correctly when using XML MULTISET emulation |
#13877 | ArrayGet should not produce parentheses when used as a store assignment target, e.g. in UPDATE |
#13883 | Parser should parse and ignore PRIMARY KEY UNIQUE |
#13899 | The maven codegen plugin does not load syntheticObjects from external configurationFile |
#13908 | Logger name repeated twice |
#13909 | Code generation fails with H2 2.1.214 when using CASE_INSENSITIVE_IDENTIFIERS |
#13921 | PostgreSQL generated code doesn't maintain precision / scale on NUMERIC or TIME, TIMETZ, TIMESTAMP, TIMESTAMPTZ types |
#13923 | Convert truncates microseconds from OffsetDateTime when converting to Instant |
#13929 | NullPointerException thrown instead of DetachedException, when executing detached query |
#13943 | Cannot use Table as SelectField from derived table where nesting records is supported natively |
#13953 | IsNotDistinctFrom predicate doesn't declare non-nullability |
Version 3.17.3 - August 16, 2022
This is a 3.17 patch release with minor improvements and bug fixes
Bug Fixes
#13792 | Data type rewrites to BOOLEAN don't work in Oracle JSON_OBJECT |
#13797 | Virtual client side computed columns must be excluded from generated DDL statements |
#13799 | GenerationOption.DEFAULT should act as STORED in client side computed columns |
#13819 | MySQL DEFAULT CURRENT_TIMESTAMP column is generated as computed column |
#13831 | NullPointerException when calling DBMS_AQ.dequeue |
#13852 | Wrong DDL generated for computed columns in MEMSQL |
#13855 | Syntax error in MemSQL code generation |
#13858 | Upgrade pgjdbc to mitigate CVE-2022-31197 |
#13861 | Fix typo in code generation log message |
#13863 | AbstractSpringDAOImpl imported from wrong package when generating multiple schemas |
#13864 | Wrong kotlin code generated for SQL Server stored procedures |
#13868 | MemSQL doesn't support the SET @@var = @other_var syntax |
Version 3.17.2 - July 7, 2022
This is a 3.17 patch release with minor improvements and bug fixes
Bug Fixes
#13731 | Generated sources emits "reference not accessible" warning for `org.jooq.impl.AbstractTable#convertFrom` |
#13733 | Wrong Javadoc in generated AbstractSpringDAOImpl |
#13735 | Work around JDK-8289221, where javadoc aren't allowed to contain ellipses in a tag in a method header
|
#13739 | Reactive transactions don't call Connection::close |
#13740 | Connection::close call is skipped when R2DBC query fails |
#13743 | R2DBC implementation may hang when there's an exception in the rendering logic |
#13754 | GROUP BY <table> does not use table alias |
#13757 | Returning null from transactionCoroutine throws NoSuchElementException |
#13765 | DefaultRecordBinding.pgRenderRecordCast and others don't apply schema mapping |
#13767 | Upgrade log4j to 2.18.0 to mitigate CVE-2022-33915 |
#13772 | Parser doesn't support parsing parenthesised GROUP BY expression |
#13777 | maven-deploy and maven-install bash and batch scripts should terminate on mvn command error |
#13782 | ERROR: unknown function: nameconcatoid() in CockroachDBDatabase on CockroachDB 22 |
Version 3.17.1 - June 27, 2022
This is a 3.17 patch release with minor improvements and bug fixes
Features and Improvements
#13707 | OnError.FAIL should log a message about the user's option how to handle the problem |
#13719 | Log warning should show jOOQ-meta type to help disambiguate objects that share the same name |
Bug Fixes
#13710 | Ill formatted Javadoc in DSLContext |
#13714 | Cannot parse computed columns in the presence of identity column |
#13724 | Regression: Zero-length delimited identifier is generated for enum columns when using <outputSchemaToDefault/> |
#13726 | Regression: Client code no longer compiles when calling DSLContext.fetchSingle(Table, Condition...) |
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. |
#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-de |