From eb126b2ee0f8a378fde6d90e5cec4f30f7804787 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Tue, 2 Nov 2021 14:17:48 +0100 Subject: [PATCH] [jOOQ/jOOQ#8388] Generate Table.rowid() overrides, implement KotlinGenerator and ScalaGenerator, improved configuration --- .../java/org/jooq/codegen/GenerationTool.java | 5 +- .../java/org/jooq/codegen/JavaGenerator.java | 26 ++++++++++ .../java/org/jooq/meta/AbstractDatabase.java | 43 +++++++++------- .../AbstractElementContainerDefinition.java | 27 +++++++++- .../src/main/java/org/jooq/meta/Database.java | 30 +++++------ .../java/org/jooq/meta/jaxb/Database.java | 50 ------------------- .../org/jooq/meta/jaxb/ObjectFactory.java | 8 +++ .../jooq/meta/jaxb/SyntheticObjectsType.java | 46 +++++++++++++++++ .../resources/xsd/jooq-codegen-3.16.0.xsd | 33 +++++++++--- .../java/org/jooq/impl/AbstractTable.java | 2 +- 10 files changed, 176 insertions(+), 94 deletions(-) diff --git a/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationTool.java b/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationTool.java index a3c4ee4d76..29cd83d91a 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationTool.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/GenerationTool.java @@ -576,17 +576,16 @@ public class GenerationTool { database.setEmbeddablePrimaryKeys(d.getEmbeddablePrimaryKeys()); database.setEmbeddableUniqueKeys(d.getEmbeddableUniqueKeys()); database.setEmbeddableDomains(d.getEmbeddableDomains()); - database.setReadonlyRowids(d.getReadonlyRowids()); database.setLogSlowQueriesAfterSeconds(defaultIfNull(d.getLogSlowQueriesAfterSeconds(), 5)); database.setLogSlowResultsAfterSeconds(defaultIfNull(d.getLogSlowResultsAfterSeconds(), 5)); if (d.getRegexFlags() != null) { database.setRegexFlags(d.getRegexFlags()); - if (strategy instanceof MatcherStrategy) { + if (strategy instanceof MatcherStrategy) ((MatcherStrategy) strategy).getPatterns().setRegexFlags(d.getRegexFlags()); - } } + database.setRegexMatchesPartialQualification(!FALSE.equals(d.isRegexMatchesPartialQualification())); database.setSqlMatchesPartialQualification(!FALSE.equals(d.isSqlMatchesPartialQualification())); diff --git a/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java b/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java index 5125567ef3..9132151e35 100644 --- a/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java +++ b/jOOQ-codegen/src/main/java/org/jooq/codegen/JavaGenerator.java @@ -108,6 +108,7 @@ import org.jooq.Parameter; import org.jooq.Record; import org.jooq.Result; import org.jooq.Row; +import org.jooq.RowId; import org.jooq.SQLDialect; import org.jooq.Schema; import org.jooq.Sequence; @@ -6210,6 +6211,31 @@ public class JavaGenerator extends AbstractGenerator { out.println("}"); } + + + + + + + + + + + + + + + + + + + + + + + + + // [#7809] fieldsRow() // [#10481] Use the types from replaced embeddables if applicable List replacingEmbeddablesAndUnreplacedColumns = replacingEmbeddablesAndUnreplacedColumns(table); diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java index 5e530e50e9..c99276d280 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractDatabase.java @@ -123,6 +123,7 @@ import org.jooq.meta.jaxb.SyntheticIdentityType; import org.jooq.meta.jaxb.SyntheticObjectsType; import org.jooq.meta.jaxb.SyntheticPrimaryKeyType; import org.jooq.meta.jaxb.SyntheticReadonlyColumnType; +import org.jooq.meta.jaxb.SyntheticReadonlyRowidType; import org.jooq.meta.jaxb.SyntheticUniqueKeyType; import org.jooq.meta.jaxb.SyntheticViewType; // ... @@ -204,6 +205,8 @@ public abstract class AbstractDatabase implements Database { private Set unusedComments = new HashSet<>(); private List configuredSyntheticReadonlyColumns = new ArrayList<>(); private Set unusedSyntheticReadonlyColumns = new HashSet<>(); + private List configuredSyntheticReadonlyRowids = new ArrayList<>(); + private Set unusedSyntheticReadonlyRowids = new HashSet<>(); private List configuredSyntheticIdentities = new ArrayList<>(); private Set unusedSyntheticIdentities = new HashSet<>(); private List configuredSyntheticPrimaryKeys = new ArrayList<>(); @@ -1996,23 +1999,6 @@ public abstract class AbstractDatabase implements Database { this.embeddableDomains = embeddableDomains; } - @Override - public String readonlyRowids() { - return readonlyRowids; - } - - @SuppressWarnings("unused") - @Override - public void setReadonlyRowids(String readonlyRowids) { - - - - if (!isBlank(readonlyRowids)) - log.info("Commercial feature", "Readonly ROWIDs are a commercial only feature. Please consider upgrading to the jOOQ Professional Edition"); - - this.readonlyRowids = readonlyRowids; - } - @Override public final List getEmbeddables() { if (embeddables == null) { @@ -2838,12 +2824,15 @@ public abstract class AbstractDatabase implements Database { // list but append it. getConfiguredSyntheticReadonlyColumns().addAll(configuredSyntheticObjects.getReadonlyColumns()); + getConfiguredSyntheticReadonlyRowids().addAll(configuredSyntheticObjects.getReadonlyRowids()); getConfiguredSyntheticIdentities().addAll(configuredSyntheticObjects.getIdentities()); getConfiguredSyntheticPrimaryKeys().addAll(configuredSyntheticObjects.getPrimaryKeys()); getConfiguredSyntheticUniqueKeys().addAll(configuredSyntheticObjects.getUniqueKeys()); getConfiguredSyntheticForeignKeys().addAll(configuredSyntheticObjects.getForeignKeys()); getConfiguredSyntheticViews().addAll(configuredSyntheticObjects.getViews()); + unusedSyntheticReadonlyColumns.addAll(configuredSyntheticObjects.getReadonlyColumns()); + unusedSyntheticReadonlyRowids.addAll(configuredSyntheticObjects.getReadonlyRowids()); unusedSyntheticIdentities.addAll(configuredSyntheticObjects.getIdentities()); unusedSyntheticPrimaryKeys.addAll(configuredSyntheticObjects.getPrimaryKeys()); unusedSyntheticUniqueKeys.addAll(configuredSyntheticObjects.getUniqueKeys()); @@ -2857,6 +2846,8 @@ public abstract class AbstractDatabase implements Database { if (!configuredSyntheticObjects.getReadonlyColumns().isEmpty()) log.info("Commercial feature", "Synthetic read only columns are a commercial only feature. Please upgrade to the jOOQ Professional Edition"); + if (!configuredSyntheticObjects.getReadonlyRowids().isEmpty()) + log.info("Commercial feature", "Synthetic read only rowids are a commercial only feature. Please upgrade to the jOOQ Professional Edition"); if (!configuredSyntheticObjects.getUniqueKeys().isEmpty()) log.info("Commercial feature", "Synthetic unique keys are a commercial only feature. Please upgrade to the jOOQ Professional Edition"); if (!configuredSyntheticObjects.getForeignKeys().isEmpty()) @@ -2872,6 +2863,14 @@ public abstract class AbstractDatabase implements Database { return configuredSyntheticReadonlyColumns; } + @Override + public List getConfiguredSyntheticReadonlyRowids() { + if (configuredSyntheticReadonlyRowids == null) + configuredSyntheticReadonlyRowids = new ArrayList<>(); + + return configuredSyntheticReadonlyRowids; + } + @Override public List getConfiguredSyntheticIdentities() { if (configuredSyntheticIdentities == null) @@ -2917,6 +2916,11 @@ public abstract class AbstractDatabase implements Database { unusedSyntheticReadonlyColumns.remove(readonlyColumn); } + @Override + public void markUsed(SyntheticReadonlyRowidType readonlyRowid) { + unusedSyntheticReadonlyRowids.remove(readonlyRowid); + } + @Override public void markUsed(SyntheticIdentityType identity) { unusedSyntheticIdentities.remove(identity); @@ -2947,6 +2951,11 @@ public abstract class AbstractDatabase implements Database { return new ArrayList<>(unusedSyntheticReadonlyColumns); } + @Override + public List getUnusedSyntheticReadonlyRowids() { + return new ArrayList<>(unusedSyntheticReadonlyRowids); + } + @Override public List getUnusedSyntheticIdentities() { return new ArrayList<>(unusedSyntheticIdentities); diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractElementContainerDefinition.java b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractElementContainerDefinition.java index 69982c1685..3138963497 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/AbstractElementContainerDefinition.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/AbstractElementContainerDefinition.java @@ -38,8 +38,10 @@ package org.jooq.meta; +import static java.util.Collections.singletonList; import static org.jooq.meta.AbstractDatabase.fetchedSize; import static org.jooq.meta.AbstractDatabase.getDefinition; +import static org.jooq.tools.StringUtils.defaultIfEmpty; import java.sql.SQLException; import java.util.ArrayList; @@ -47,6 +49,9 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; +// ... +import org.jooq.meta.jaxb.SyntheticReadonlyColumnType; +import org.jooq.meta.jaxb.SyntheticReadonlyRowidType; import org.jooq.tools.JooqLogger; import org.jooq.tools.StringUtils; @@ -89,7 +94,7 @@ extends AbstractDefinition { List e = getElements0(); // [#5335] Warn if a table definition contains several identity columns - if (this instanceof TableDefinition) { + if (this instanceof TableDefinition) { TableDefinition t = (TableDefinition) this; if (e.stream().map(c -> (ColumnDefinition) c).filter(ColumnDefinition::isIdentity).count() > 1) log.warn("Multiple identities", "Table " + getOutputName() + " has multiple identity columns. Only the first one is considered."); @@ -107,6 +112,7 @@ extends AbstractDefinition { + } // [#2603] Filter exclude / include also for table columns @@ -127,6 +133,25 @@ extends AbstractDefinition { return elements; } + + + + + + + + + + + + + + + + + + + protected final E getElement(String name) { return getElement(name, false); } diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/Database.java b/jOOQ-meta/src/main/java/org/jooq/meta/Database.java index d1b2cbf5d4..659fcb93b2 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/Database.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/Database.java @@ -63,6 +63,7 @@ import org.jooq.meta.jaxb.SyntheticIdentityType; import org.jooq.meta.jaxb.SyntheticObjectsType; import org.jooq.meta.jaxb.SyntheticPrimaryKeyType; import org.jooq.meta.jaxb.SyntheticReadonlyColumnType; +import org.jooq.meta.jaxb.SyntheticReadonlyRowidType; import org.jooq.meta.jaxb.SyntheticUniqueKeyType; import org.jooq.meta.jaxb.SyntheticViewType; @@ -1068,20 +1069,6 @@ public interface Database extends AutoCloseable { */ void setEmbeddableDomains(String embeddableDomains); - /** - * A regular expression matching all tables for which a synthetic ROWID column should be generated. - *

- * This feature is available in the commercial distribution only. - */ - String readonlyRowids(); - - /** - * A regular expression matching all tables for which a synthetic ROWID column should be generated. - *

- * This feature is available in the commercial distribution only. - */ - void setReadonlyRowids(String readonlyRowids); - /** * Configure the comments. */ @@ -1112,6 +1099,11 @@ public interface Database extends AutoCloseable { */ List getConfiguredSyntheticReadonlyColumns(); + /** + * Get the configured synthetic readonly rowids. + */ + List getConfiguredSyntheticReadonlyRowids(); + /** * Get the configured synthetic identities. */ @@ -1147,6 +1139,16 @@ public interface Database extends AutoCloseable { */ List getUnusedSyntheticReadonlyColumns(); + /** + * Mark a synthetic readonly rowids as used. + */ + void markUsed(SyntheticReadonlyRowidType readonlyRowid); + + /** + * Retrieve the not-yet used synthetic readonly rowids. + */ + List getUnusedSyntheticReadonlyRowids(); + /** * Mark a synthetic identity as used. */ diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/Database.java b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/Database.java index 906ea0f06e..a8b5925b26 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/Database.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/Database.java @@ -150,8 +150,6 @@ public class Database implements Serializable, XMLAppendable protected String embeddableUniqueKeys; @XmlJavaTypeAdapter(StringAdapter.class) protected String embeddableDomains; - @XmlJavaTypeAdapter(StringAdapter.class) - protected String readonlyRowids; @XmlElement(defaultValue = "true") protected Boolean forceIntegerTypesOnZeroScaleDecimals = true; protected Boolean tableValuedFunctions; @@ -1575,30 +1573,6 @@ public class Database implements Serializable, XMLAppendable this.embeddableDomains = value; } - /** - * A regular expression matching all tables for which a synthetic ROWID column should be generated. - *

- * Use this along with the synthetic primary key feature to replace existing primary key usage by ROWID usage, if this makes sense for your {@link UpdatableRecord}. - *

- * This feature is available in the commercial distribution only. - * - */ - public String getReadonlyRowids() { - return readonlyRowids; - } - - /** - * A regular expression matching all tables for which a synthetic ROWID column should be generated. - *

- * Use this along with the synthetic primary key feature to replace existing primary key usage by ROWID usage, if this makes sense for your {@link UpdatableRecord}. - *

- * This feature is available in the commercial distribution only. - * - */ - public void setReadonlyRowids(String value) { - this.readonlyRowids = value; - } - /** * Historically, zero-scale decimal types are generated as their most appropriate, corresponding integer type (e.g. NUMBER(2, 0) and less: Byte). This allows for turning off this feature. In case of conflict between this rule and actual {@link #getForcedTypes()}, the latter will win. * @@ -2312,19 +2286,6 @@ public class Database implements Serializable, XMLAppendable return this; } - /** - * A regular expression matching all tables for which a synthetic ROWID column should be generated. - *

- * Use this along with the synthetic primary key feature to replace existing primary key usage by ROWID usage, if this makes sense for your {@link UpdatableRecord}. - *

- * This feature is available in the commercial distribution only. - * - */ - public Database withReadonlyRowids(String value) { - setReadonlyRowids(value); - return this; - } - public Database withForceIntegerTypesOnZeroScaleDecimals(Boolean value) { setForceIntegerTypesOnZeroScaleDecimals(value); return this; @@ -2581,7 +2542,6 @@ public class Database implements Serializable, XMLAppendable builder.append("embeddablePrimaryKeys", embeddablePrimaryKeys); builder.append("embeddableUniqueKeys", embeddableUniqueKeys); builder.append("embeddableDomains", embeddableDomains); - builder.append("readonlyRowids", readonlyRowids); builder.append("forceIntegerTypesOnZeroScaleDecimals", forceIntegerTypesOnZeroScaleDecimals); builder.append("tableValuedFunctions", tableValuedFunctions); builder.append("logSlowQueriesAfterSeconds", logSlowQueriesAfterSeconds); @@ -3083,15 +3043,6 @@ public class Database implements Serializable, XMLAppendable return false; } } - if (readonlyRowids == null) { - if (other.readonlyRowids!= null) { - return false; - } - } else { - if (!readonlyRowids.equals(other.readonlyRowids)) { - return false; - } - } if (forceIntegerTypesOnZeroScaleDecimals == null) { if (other.forceIntegerTypesOnZeroScaleDecimals!= null) { return false; @@ -3259,7 +3210,6 @@ public class Database implements Serializable, XMLAppendable result = ((prime*result)+((embeddablePrimaryKeys == null)? 0 :embeddablePrimaryKeys.hashCode())); result = ((prime*result)+((embeddableUniqueKeys == null)? 0 :embeddableUniqueKeys.hashCode())); result = ((prime*result)+((embeddableDomains == null)? 0 :embeddableDomains.hashCode())); - result = ((prime*result)+((readonlyRowids == null)? 0 :readonlyRowids.hashCode())); result = ((prime*result)+((forceIntegerTypesOnZeroScaleDecimals == null)? 0 :forceIntegerTypesOnZeroScaleDecimals.hashCode())); result = ((prime*result)+((tableValuedFunctions == null)? 0 :tableValuedFunctions.hashCode())); result = ((prime*result)+((logSlowQueriesAfterSeconds == null)? 0 :logSlowQueriesAfterSeconds.hashCode())); diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ObjectFactory.java b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ObjectFactory.java index 690da15347..e740391b99 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ObjectFactory.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/ObjectFactory.java @@ -181,6 +181,14 @@ public class ObjectFactory { return new SyntheticReadonlyColumnType(); } + /** + * Create an instance of {@link SyntheticReadonlyRowidType } + * + */ + public SyntheticReadonlyRowidType createSyntheticReadonlyRowidType() { + return new SyntheticReadonlyRowidType(); + } + /** * Create an instance of {@link SyntheticIdentityType } * diff --git a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/SyntheticObjectsType.java b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/SyntheticObjectsType.java index b01b494c12..6970db7fdd 100644 --- a/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/SyntheticObjectsType.java +++ b/jOOQ-meta/src/main/java/org/jooq/meta/jaxb/SyntheticObjectsType.java @@ -34,6 +34,9 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable @XmlElementWrapper(name = "readonlyColumns") @XmlElement(name = "readonlyColumn") protected List readonlyColumns; + @XmlElementWrapper(name = "readonlyRowids") + @XmlElement(name = "readonlyRowid") + protected List readonlyRowids; @XmlElementWrapper(name = "identities") @XmlElement(name = "identity") protected List identities; @@ -61,6 +64,17 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable this.readonlyColumns = readonlyColumns; } + public List getReadonlyRowids() { + if (readonlyRowids == null) { + readonlyRowids = new ArrayList(); + } + return readonlyRowids; + } + + public void setReadonlyRowids(List readonlyRowids) { + this.readonlyRowids = readonlyRowids; + } + public List getIdentities() { if (identities == null) { identities = new ArrayList(); @@ -137,6 +151,27 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable return this; } + public SyntheticObjectsType withReadonlyRowids(SyntheticReadonlyRowidType... values) { + if (values!= null) { + for (SyntheticReadonlyRowidType value: values) { + getReadonlyRowids().add(value); + } + } + return this; + } + + public SyntheticObjectsType withReadonlyRowids(Collection values) { + if (values!= null) { + getReadonlyRowids().addAll(values); + } + return this; + } + + public SyntheticObjectsType withReadonlyRowids(List readonlyRowids) { + setReadonlyRowids(readonlyRowids); + return this; + } + public SyntheticObjectsType withIdentities(SyntheticIdentityType... values) { if (values!= null) { for (SyntheticIdentityType value: values) { @@ -245,6 +280,7 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable @Override public final void appendTo(XMLBuilder builder) { builder.append("readonlyColumns", "readonlyColumn", readonlyColumns); + builder.append("readonlyRowids", "readonlyRowid", readonlyRowids); builder.append("identities", "identity", identities); builder.append("primaryKeys", "primaryKey", primaryKeys); builder.append("uniqueKeys", "uniqueKey", uniqueKeys); @@ -280,6 +316,15 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable return false; } } + if (readonlyRowids == null) { + if (other.readonlyRowids!= null) { + return false; + } + } else { + if (!readonlyRowids.equals(other.readonlyRowids)) { + return false; + } + } if (identities == null) { if (other.identities!= null) { return false; @@ -333,6 +378,7 @@ public class SyntheticObjectsType implements Serializable, XMLAppendable final int prime = 31; int result = 1; result = ((prime*result)+((readonlyColumns == null)? 0 :readonlyColumns.hashCode())); + result = ((prime*result)+((readonlyRowids == null)? 0 :readonlyRowids.hashCode())); result = ((prime*result)+((identities == null)? 0 :identities.hashCode())); result = ((prime*result)+((primaryKeys == null)? 0 :primaryKeys.hashCode())); result = ((prime*result)+((uniqueKeys == null)? 0 :uniqueKeys.hashCode())); diff --git a/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.16.0.xsd b/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.16.0.xsd index ecda8b5f95..b3cdd896bd 100644 --- a/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.16.0.xsd +++ b/jOOQ-meta/src/main/resources/xsd/jooq-codegen-3.16.0.xsd @@ -887,14 +887,6 @@ This feature is available in the commercial distribution only.]]>< -This feature is available in the commercial distribution only.]]> - - - - ROWID column should be generated. -

-Use this along with the synthetic primary key feature to replace existing primary key usage by ROWID usage, if this makes sense for your {@link UpdatableRecord}. -

This feature is available in the commercial distribution only.]]> @@ -987,6 +979,10 @@ This feature is available in the commercial distribution only.]]>< + + + + @@ -1033,6 +1029,27 @@ This feature is available in the commercial distribution only.]]>< + + + + + + + + ROWID column should be generated. +

+Use this along with the synthetic primary key feature to replace existing primary key usage by ROWID usage, if this makes sense for your {@link UpdatableRecord}.]]> + + + + + + + + + + + diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractTable.java b/jOOQ/src/main/java/org/jooq/impl/AbstractTable.java index 630b26a3bf..d72ef4c4fb 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractTable.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractTable.java @@ -784,7 +784,7 @@ abstract class AbstractTable extends AbstractNamed implements // ------------------------------------------------------------------------- @Override - public final Field rowid() { + public /* non-final */ Field rowid() { return new QualifiedRowid(this); }