[#3154] Add code-generation configuration to generate synthetic primary keys for updatable views

This commit is contained in:
Lukas Eder 2014-06-06 14:57:51 +02:00
parent a0bef16560
commit a507d50bc4
12 changed files with 171 additions and 9 deletions

View File

@ -314,6 +314,7 @@ public class GenerationTool {
database.setIncludeExcludeColumns(TRUE.equals(d.isIncludeExcludeColumns()));
database.setRecordVersionFields(new String[] { defaultString(d.getRecordVersionFields()) });
database.setRecordTimestampFields(new String[] { defaultString(d.getRecordTimestampFields()) });
database.setSyntheticPrimaryKeys(new String[] { defaultString(d.getSyntheticPrimaryKeys()) });
database.setOverridePrimaryKeys(new String[] { defaultString(d.getOverridePrimaryKeys()) });
database.setConfiguredCustomTypes(d.getCustomTypes());
database.setConfiguredEnumTypes(d.getEnumTypes());

View File

@ -94,6 +94,7 @@ public abstract class AbstractDatabase implements Database {
private boolean includeExcludeColumns;
private String[] recordVersionFields;
private String[] recordTimestampFields;
private String[] syntheticPrimaryKeys;
private String[] overridePrimaryKeys;
private boolean supportsUnsignedTypes;
private boolean dateAsTimestamp;
@ -332,6 +333,16 @@ public abstract class AbstractDatabase implements Database {
return recordTimestampFields;
}
@Override
public void setSyntheticPrimaryKeys(String[] syntheticPrimaryKeys) {
this.syntheticPrimaryKeys = syntheticPrimaryKeys;
}
@Override
public String[] getSyntheticPrimaryKeys() {
return syntheticPrimaryKeys;
}
@Override
public void setOverridePrimaryKeys(String[] overridePrimaryKeys) {
this.overridePrimaryKeys = overridePrimaryKeys;
@ -883,6 +894,13 @@ public abstract class AbstractDatabase implements Database {
log.error("Error while fetching check constraints", e);
}
try {
syntheticPrimaryKeys(result);
}
catch (Exception e) {
log.error("Error while generating synthetic primary keys", e);
}
try {
overridePrimaryKeys(result);
}
@ -910,6 +928,28 @@ public abstract class AbstractDatabase implements Database {
return fetched.size() + " (" + included.size() + " included, " + (fetched.size() - included.size()) + " excluded)";
}
private final void syntheticPrimaryKeys(DefaultRelations r) {
List<UniqueKeyDefinition> syntheticKeys = new ArrayList<UniqueKeyDefinition>();
for (SchemaDefinition schema : getSchemata()) {
for (TableDefinition table : schema.getTables()) {
List<ColumnDefinition> columns = filterExcludeInclude(table.getColumns(), null, getSyntheticPrimaryKeys());
if (!columns.isEmpty()) {
DefaultUniqueKeyDefinition syntheticKey = new DefaultUniqueKeyDefinition(schema, "SYNTHETIC_PK_" + table.getName(), table, true);
syntheticKey.getKeyColumns().addAll(columns);
syntheticKeys.add(syntheticKey);
}
}
}
log.info("Synthetic primary keys", fetchedSize(syntheticKeys, syntheticKeys));
for (UniqueKeyDefinition key : syntheticKeys) {
r.overridePrimaryKey(key);
}
}
private final void overridePrimaryKeys(DefaultRelations r) {
List<UniqueKeyDefinition> allKeys = r.getUniqueKeys();
List<UniqueKeyDefinition> filteredKeys = filterExcludeInclude(allKeys, null, overridePrimaryKeys);

View File

@ -259,6 +259,18 @@ public interface Database {
*/
String[] getRecordTimestampFields();
/**
* Columns matching these regular expressions will be considered as members
* of synthetic primary keys in generated code.
*/
void setSyntheticPrimaryKeys(String[] primaryKeys);
/**
* Columns matching these regular expressions will be considered as members
* of synthetic primary keys in generated code.
*/
String[] getSyntheticPrimaryKeys();
/**
* Unique keys matching these regular expressions will be considered as
* primary keys in generated code.

View File

@ -105,8 +105,9 @@ public class DefaultRelations implements Relations {
// Remove the existing key from the column -> key mapping
primaryKeysByColumn = null;
uniqueKeysByColumn = null;
// Remove the existing key from the key mapping
// Remove the existing key from the primary key mapping (not from the unique key mapping!)
Iterator<Entry<Key, UniqueKeyDefinition>> it = primaryKeys.entrySet().iterator();
while (it.hasNext()) {
Entry<Key, UniqueKeyDefinition> entry = it.next();
@ -119,7 +120,9 @@ public class DefaultRelations implements Relations {
}
// Add the new primary key
primaryKeys.put(key(key.getTable(), key.getName()), key);
Key mapKey = key(key.getTable(), key.getName());
primaryKeys.put(mapKey, key);
uniqueKeys.put(mapKey, key);
log.info("Overriding primary key", "Table : " + key.getTable() +
", previous key : " + ((old == null) ? "none" : old.getName()) +
", new key : " + key.getName());

View File

@ -371,6 +371,19 @@
-->
<element name="recordTimestampFields" type="string" default="" minOccurs="0" maxOccurs="1" />
<!--
A regular expression matching all columns that participate in "synthetic" primary keys,
which should be placed on generated UpdatableRecords, to be used with
- UpdatableRecord.store()
- UpdatableRecord.update()
- UpdatableRecord.delete()
- UpdatableRecord.refresh()
Synthetic primary keys will override existing primary keys.
-->
<element name="syntheticPrimaryKeys" type="string" default="" minOccurs="0" maxOccurs="1" />
<!--
All (UNIQUE) key names that should be used instead of primary keys on
generated UpdatableRecords, to be used with
@ -381,6 +394,8 @@
- UpdatableRecord.refresh()
If several keys match, a warning is emitted and the first one encountered will be used.
This flag will also replace synthetic primary keys, if it matches.
-->
<element name="overridePrimaryKeys" type="string" default="" minOccurs="0" maxOccurs="1" />

View File

@ -1 +1,9 @@
SET MAVEN_OPTS=-Xdebug -Xnoagent -Djava.compile=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005
@ECHO OFF
IF "%1" == "off" (
SET MAVEN_OPTS=
) ELSE (
SET MAVEN_OPTS=-Xdebug -Xnoagent -Djava.compile=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005
)
SET MAVEN_OPTS

View File

@ -1170,6 +1170,13 @@
| ASDF_ASDF_ASDF # This should not have any effect
| ASDF_ASDF_ASDF # This should not have any effect
</recordTimestampFields>
<syntheticPrimaryKeys>
.*\. # All schemas
(?i:
V_AUTHOR\.ID # Some updatable view columns
| V_BOOK\.ID # Some updatable view columns
)
</syntheticPrimaryKeys>
<dateAsTimestamp>false</dateAsTimestamp>
<unsignedTypes>true</unsignedTypes>
<inputSchema>${db.h2.schema}</inputSchema>

View File

@ -46,6 +46,8 @@ public class Keys {
public static final org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.XTestCase_64_69Record> PK_X_TEST_CASE_64_69 = UniqueKeys0.PK_X_TEST_CASE_64_69;
public static final org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.XTestCase_71Record> PK_X_TEST_CASE_71 = UniqueKeys0.PK_X_TEST_CASE_71;
public static final org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.XTestCase_85Record> PK_X_TEST_CASE_85 = UniqueKeys0.PK_X_TEST_CASE_85;
public static final org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.VAuthorRecord> SYNTHETIC_PK_V_AUTHOR = UniqueKeys0.SYNTHETIC_PK_V_AUTHOR;
public static final org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.VBookRecord> SYNTHETIC_PK_V_BOOK = UniqueKeys0.SYNTHETIC_PK_V_BOOK;
// -------------------------------------------------------------------------
// FOREIGN KEY definitions
@ -98,6 +100,8 @@ public class Keys {
public static final org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.XTestCase_64_69Record> PK_X_TEST_CASE_64_69 = createUniqueKey(org.jooq.test.h2.generatedclasses.tables.XTestCase_64_69.X_TEST_CASE_64_69, org.jooq.test.h2.generatedclasses.tables.XTestCase_64_69.X_TEST_CASE_64_69.ID);
public static final org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.XTestCase_71Record> PK_X_TEST_CASE_71 = createUniqueKey(org.jooq.test.h2.generatedclasses.tables.XTestCase_71.X_TEST_CASE_71, org.jooq.test.h2.generatedclasses.tables.XTestCase_71.X_TEST_CASE_71.ID);
public static final org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.XTestCase_85Record> PK_X_TEST_CASE_85 = createUniqueKey(org.jooq.test.h2.generatedclasses.tables.XTestCase_85.X_TEST_CASE_85, org.jooq.test.h2.generatedclasses.tables.XTestCase_85.X_TEST_CASE_85.ID);
public static final org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.VAuthorRecord> SYNTHETIC_PK_V_AUTHOR = createUniqueKey(org.jooq.test.h2.generatedclasses.tables.VAuthor.V_AUTHOR, org.jooq.test.h2.generatedclasses.tables.VAuthor.V_AUTHOR.ID);
public static final org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.VBookRecord> SYNTHETIC_PK_V_BOOK = createUniqueKey(org.jooq.test.h2.generatedclasses.tables.VBook.V_BOOK, org.jooq.test.h2.generatedclasses.tables.VBook.V_BOOK.ID);
}
private static class ForeignKeys0 extends org.jooq.impl.AbstractKeys {

View File

@ -9,7 +9,7 @@ package org.jooq.test.h2.generatedclasses.tables;
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class VAuthor extends org.jooq.impl.TableImpl<org.jooq.test.h2.generatedclasses.tables.records.VAuthorRecord> {
private static final long serialVersionUID = -1789099087;
private static final long serialVersionUID = 2131959173;
/**
* The singleton instance of <code>PUBLIC.V_AUTHOR</code>
@ -76,6 +76,22 @@ public class VAuthor extends org.jooq.impl.TableImpl<org.jooq.test.h2.generatedc
super(alias, org.jooq.test.h2.generatedclasses.Public.PUBLIC, aliased, parameters, "");
}
/**
* {@inheritDoc}
*/
@Override
public org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.VAuthorRecord> getPrimaryKey() {
return org.jooq.test.h2.generatedclasses.Keys.SYNTHETIC_PK_V_AUTHOR;
}
/**
* {@inheritDoc}
*/
@Override
public java.util.List<org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.VAuthorRecord>> getKeys() {
return java.util.Arrays.<org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.VAuthorRecord>>asList(org.jooq.test.h2.generatedclasses.Keys.SYNTHETIC_PK_V_AUTHOR);
}
/**
* {@inheritDoc}
*/

View File

@ -9,7 +9,7 @@ package org.jooq.test.h2.generatedclasses.tables;
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class VBook extends org.jooq.impl.TableImpl<org.jooq.test.h2.generatedclasses.tables.records.VBookRecord> {
private static final long serialVersionUID = 2008359507;
private static final long serialVersionUID = 424616229;
/**
* The singleton instance of <code>PUBLIC.V_BOOK</code>
@ -101,6 +101,38 @@ public class VBook extends org.jooq.impl.TableImpl<org.jooq.test.h2.generatedcla
super(alias, org.jooq.test.h2.generatedclasses.Public.PUBLIC, aliased, parameters, "");
}
/**
* {@inheritDoc}
*/
@Override
public org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.VBookRecord> getPrimaryKey() {
return org.jooq.test.h2.generatedclasses.Keys.SYNTHETIC_PK_V_BOOK;
}
/**
* {@inheritDoc}
*/
@Override
public java.util.List<org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.VBookRecord>> getKeys() {
return java.util.Arrays.<org.jooq.UniqueKey<org.jooq.test.h2.generatedclasses.tables.records.VBookRecord>>asList(org.jooq.test.h2.generatedclasses.Keys.SYNTHETIC_PK_V_BOOK);
}
/**
* {@inheritDoc}
*/
@Override
public org.jooq.TableField<org.jooq.test.h2.generatedclasses.tables.records.VBookRecord, java.lang.Integer> getRecordVersion() {
return org.jooq.test.h2.generatedclasses.tables.VBook.V_BOOK.REC_VERSION;
}
/**
* {@inheritDoc}
*/
@Override
public org.jooq.TableField<org.jooq.test.h2.generatedclasses.tables.records.VBookRecord, java.sql.Timestamp> getRecordTimestamp() {
return org.jooq.test.h2.generatedclasses.tables.VBook.V_BOOK.REC_TIMESTAMP;
}
/**
* {@inheritDoc}
*/

View File

@ -7,9 +7,9 @@ package org.jooq.test.h2.generatedclasses.tables.records;
* This class is generated by jOOQ.
*/
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class VAuthorRecord extends org.jooq.impl.TableRecordImpl<org.jooq.test.h2.generatedclasses.tables.records.VAuthorRecord> implements org.jooq.Record6<java.lang.Integer, java.lang.String, java.lang.String, java.sql.Date, java.lang.Integer, java.lang.String>, org.jooq.test.h2.generatedclasses.tables.interfaces.IVAuthor {
public class VAuthorRecord extends org.jooq.impl.UpdatableRecordImpl<org.jooq.test.h2.generatedclasses.tables.records.VAuthorRecord> implements org.jooq.Record6<java.lang.Integer, java.lang.String, java.lang.String, java.sql.Date, java.lang.Integer, java.lang.String>, org.jooq.test.h2.generatedclasses.tables.interfaces.IVAuthor {
private static final long serialVersionUID = -1737704365;
private static final long serialVersionUID = 355974962;
/**
* Setter for <code>PUBLIC.V_AUTHOR.ID</code>.
@ -113,6 +113,18 @@ public class VAuthorRecord extends org.jooq.impl.TableRecordImpl<org.jooq.test.h
return (java.lang.String) getValue(5);
}
// -------------------------------------------------------------------------
// Primary key information
// -------------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public org.jooq.Record1<java.lang.Integer> key() {
return (org.jooq.Record1) super.key();
}
// -------------------------------------------------------------------------
// Record6 type implementation
// -------------------------------------------------------------------------

View File

@ -7,9 +7,9 @@ package org.jooq.test.h2.generatedclasses.tables.records;
* This class is generated by jOOQ.
*/
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class VBookRecord extends org.jooq.impl.TableRecordImpl<org.jooq.test.h2.generatedclasses.tables.records.VBookRecord> implements org.jooq.Record11<java.lang.Integer, java.lang.Integer, java.lang.Integer, java.lang.Integer, java.lang.String, java.lang.Integer, java.lang.Integer, java.lang.String, byte[], java.lang.Integer, java.sql.Timestamp>, org.jooq.test.h2.generatedclasses.tables.interfaces.IVBook {
public class VBookRecord extends org.jooq.impl.UpdatableRecordImpl<org.jooq.test.h2.generatedclasses.tables.records.VBookRecord> implements org.jooq.Record11<java.lang.Integer, java.lang.Integer, java.lang.Integer, java.lang.Integer, java.lang.String, java.lang.Integer, java.lang.Integer, java.lang.String, byte[], java.lang.Integer, java.sql.Timestamp>, org.jooq.test.h2.generatedclasses.tables.interfaces.IVBook {
private static final long serialVersionUID = 1399887711;
private static final long serialVersionUID = -1694762730;
/**
* Setter for <code>PUBLIC.V_BOOK.ID</code>.
@ -198,6 +198,18 @@ public class VBookRecord extends org.jooq.impl.TableRecordImpl<org.jooq.test.h2.
return (java.sql.Timestamp) getValue(10);
}
// -------------------------------------------------------------------------
// Primary key information
// -------------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public org.jooq.Record1<java.lang.Integer> key() {
return (org.jooq.Record1) super.key();
}
// -------------------------------------------------------------------------
// Record11 type implementation
// -------------------------------------------------------------------------