[jOOQ/jOOQ#681] Add interpreter support for DOMAINS (WIP)

This change includes:

- DDLExportConfiguration instructions
- DDLFlag.DOMAIN and Meta.ddl() export implementation
- Meta.getDomains() and Schema.getDomains() API
- Interpreter implementation (WIP)
This commit is contained in:
Lukas Eder 2020-05-28 15:36:27 +02:00
parent 8ce30181c5
commit cf993c0b67
10 changed files with 410 additions and 107 deletions

View File

@ -56,6 +56,7 @@ public final class DDLExportConfiguration {
private final boolean createSchemaIfNotExists;
private final boolean createTableIfNotExists;
private final boolean createIndexIfNotExists;
private final boolean createDomainIfNotExists;
private final boolean createSequenceIfNotExists;
private final boolean createViewIfNotExists;
private final boolean createOrReplaceView;
@ -66,6 +67,7 @@ public final class DDLExportConfiguration {
private final boolean respectColumnOrder;
private final boolean respectConstraintOrder;
private final boolean respectIndexOrder;
private final boolean respectDomainOrder;
private final boolean respectSequenceOrder;
private final boolean defaultSequenceFlags;
@ -83,6 +85,7 @@ public final class DDLExportConfiguration {
false,
false,
false,
false,
false,
false,
@ -91,6 +94,7 @@ public final class DDLExportConfiguration {
false,
false,
false,
false,
false
);
@ -102,6 +106,7 @@ public final class DDLExportConfiguration {
boolean createSchemaIfNotExists,
boolean createTableIfNotExists,
boolean createIndexIfNotExists,
boolean createDomainIfNotExists,
boolean createSequenceIfNotExists,
boolean createViewIfNotExists,
boolean createOrReplaceView,
@ -112,6 +117,7 @@ public final class DDLExportConfiguration {
boolean respectColumnOrder,
boolean respectConstraintOrder,
boolean respectIndexOrder,
boolean respectDomainOrder,
boolean respectSequenceOrder,
boolean defaultSequenceFlags
@ -121,6 +127,7 @@ public final class DDLExportConfiguration {
this.createSchemaIfNotExists = createSchemaIfNotExists;
this.createTableIfNotExists = createTableIfNotExists;
this.createIndexIfNotExists = createIndexIfNotExists;
this.createDomainIfNotExists = createDomainIfNotExists;
this.createSequenceIfNotExists = createSequenceIfNotExists;
this.createViewIfNotExists = createViewIfNotExists;
this.createOrReplaceView = createOrReplaceView;
@ -131,7 +138,9 @@ public final class DDLExportConfiguration {
this.respectColumnOrder = respectColumnOrder;
this.respectConstraintOrder = respectConstraintOrder;
this.respectIndexOrder = respectIndexOrder;
this.respectDomainOrder = respectDomainOrder;
this.respectSequenceOrder = respectSequenceOrder;
this.defaultSequenceFlags = defaultSequenceFlags;
}
@ -158,6 +167,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -167,6 +177,7 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -192,6 +203,7 @@ public final class DDLExportConfiguration {
newCreateSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -201,6 +213,7 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -226,6 +239,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
newCreateTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -235,6 +249,7 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -260,6 +275,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
newCreateIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -269,6 +285,43 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
}
/**
* Whether to generate <code>CREATE DOMAIN IF NOT EXISTS</code> statements.
* <p>
* Not all RDBMS support this flag. Check
* {@link DSLContext#createDomainIfNotExists(Domain)} to see if your
* {@link SQLDialect} supports the clause.
*/
public final boolean createDomainIfNotExists() {
return createDomainIfNotExists;
}
/**
* Whether to generate <code>CREATE DOMAIN IF NOT EXISTS</code> statements.
*/
public final DDLExportConfiguration createDomainIfNotExists(boolean newCreateDomainIfNotExists) {
return new DDLExportConfiguration(
flags,
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
newCreateDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
respectCatalogOrder,
respectSchemaOrder,
respectTableOrder,
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -294,6 +347,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
newCreateSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -303,6 +357,7 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -328,6 +383,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
newCreateViewIfNotExists,
createOrReplaceView,
@ -337,6 +393,7 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -362,6 +419,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
newCreateOrReplaceView,
@ -371,6 +429,7 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -394,6 +453,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -403,6 +463,7 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -426,6 +487,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -435,6 +497,7 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -458,6 +521,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -467,6 +531,7 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -490,6 +555,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -499,6 +565,7 @@ public final class DDLExportConfiguration {
newRespectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -522,6 +589,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -531,6 +599,7 @@ public final class DDLExportConfiguration {
respectColumnOrder,
newRespectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -554,6 +623,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -563,6 +633,41 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
newRespectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
}
/**
* Whether to respect the domain order produced by the {@link Meta} source
* when generated domain DDL.
*/
public final boolean respectDomainOrder() {
return respectDomainOrder;
}
/**
* Whether to respect the sequence order produced by the {@link Meta} source
* when generated sequence DDL.
*/
public final DDLExportConfiguration respectDomainOrder(boolean newRespectDomainOrder) {
return new DDLExportConfiguration(
flags,
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
respectCatalogOrder,
respectSchemaOrder,
respectTableOrder,
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
newRespectDomainOrder,
respectSequenceOrder,
defaultSequenceFlags
);
@ -586,6 +691,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -595,6 +701,7 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
newRespectSequenceOrder,
defaultSequenceFlags
);
@ -618,6 +725,7 @@ public final class DDLExportConfiguration {
createSchemaIfNotExists,
createTableIfNotExists,
createIndexIfNotExists,
createDomainIfNotExists,
createSequenceIfNotExists,
createViewIfNotExists,
createOrReplaceView,
@ -627,6 +735,7 @@ public final class DDLExportConfiguration {
respectColumnOrder,
respectConstraintOrder,
respectIndexOrder,
respectDomainOrder,
respectSequenceOrder,
newDefaultSequenceFlags
);

View File

@ -77,6 +77,11 @@ public enum DDLFlag {
*/
INDEX,
/**
* Whether <code>DOMAIN</code> statements should be generated.
*/
DOMAIN,
/**
* Whether <code>SEQUENCE</code> statements should be generated.
*/

View File

@ -52,6 +52,7 @@ import static org.jooq.SQLDialect.HSQLDB;
import static org.jooq.SQLDialect.POSTGRES;
// ...
// ...
// ...
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
@ -169,6 +170,33 @@ public interface Meta extends Scope {
@Support
List<Table<?>> getTables(Name name) throws DataAccessException;
/**
* Get all domain objects from the underlying meta data source.
*
* @throws DataAccessException If something went wrong fetching the meta
* objects
*/
@Support({ H2, POSTGRES })
List<Domain<?>> getDomains() throws DataAccessException;
/**
* Get all domain objects by name from the underlying meta data source.
*
* @throws DataAccessException If something went wrong fetching the meta
* objects
*/
@Support({ H2, POSTGRES })
List<Domain<?>> getDomains(String name) throws DataAccessException;
/**
* Get all domain objects by name from the underlying meta data source.
*
* @throws DataAccessException If something went wrong fetching the meta
* objects
*/
@Support({ H2, POSTGRES })
List<Domain<?>> getDomains(Name name) throws DataAccessException;
/**
* Get all sequence objects from the underlying meta data source.
*

View File

@ -119,6 +119,24 @@ public interface Schema extends Named {
*/
UDT<?> getUDT(String name);
/**
* Stream all domains contained in this schema.
*/
Stream<Domain<?>> domainStream();
/**
* List all domains contained in this schema.
*/
List<Domain<?>> getDomains();
/**
* Get a domain by its name (case-sensitive) in this schema, or
* <code>null</code> if no such domain exists.
*/
Domain<?> getDomain(String name);
/**
* Stream all sequences contained in this schema.
*/

View File

@ -51,6 +51,7 @@ import java.util.Map;
import org.jooq.Catalog;
import org.jooq.Configuration;
import org.jooq.DDLExportConfiguration;
import org.jooq.Domain;
import org.jooq.Index;
import org.jooq.Meta;
import org.jooq.Name;
@ -74,9 +75,11 @@ abstract class AbstractMeta extends AbstractScope implements Meta, Serializable
private Map<Name, Catalog> cachedCatalogs;
private Map<Name, Schema> cachedQualifiedSchemas;
private Map<Name, Table<?>> cachedQualifiedTables;
private Map<Name, Domain<?>> cachedQualifiedDomains;
private Map<Name, Sequence<?>> cachedQualifiedSequences;
private Map<Name, List<Schema>> cachedUnqualifiedSchemas;
private Map<Name, List<Table<?>>> cachedUnqualifiedTables;
private Map<Name, List<Domain<?>>> cachedUnqualifiedDomains;
private Map<Name, List<Sequence<?>>> cachedUnqualifiedSequences;
private List<UniqueKey<?>> cachedPrimaryKeys;
private List<Index> cachedIndexes;
@ -196,6 +199,48 @@ abstract class AbstractMeta extends AbstractScope implements Meta, Serializable
return result;
}
@Override
public final List<Domain<?>> getDomains(String name) {
return getDomains(name(name));
}
@Override
public final List<Domain<?>> getDomains(Name name) {
initDomains();
return get(name, new Iterable<Domain<?>>() {
@Override
public Iterator<Domain<?>> iterator() {
return getDomains().iterator();
}
}, cachedQualifiedDomains, cachedUnqualifiedDomains);
}
@Override
public final List<Domain<?>> getDomains() {
initDomains();
return Collections.unmodifiableList(new ArrayList<>(cachedQualifiedDomains.values()));
}
private final void initDomains() {
if (cachedQualifiedDomains == null) {
cachedQualifiedDomains = new LinkedHashMap<>();
cachedUnqualifiedDomains = new LinkedHashMap<>();
get(name(""), new Iterable<Domain<?>>() {
@Override
public Iterator<Domain<?>> iterator() {
return getDomains0().iterator();
}
}, cachedQualifiedDomains, cachedUnqualifiedDomains);
}
}
protected List<Domain<?>> getDomains0() {
List<Domain<?>> result = new ArrayList<>();
for (Schema schema : getSchemas())
result.addAll(schema.getDomains());
return result;
}
@Override
public final List<Sequence<?>> getSequences(String name) {
return getSequences(name(name));

View File

@ -39,6 +39,7 @@ package org.jooq.impl;
import static org.jooq.DDLFlag.CHECK;
import static org.jooq.DDLFlag.COMMENT;
import static org.jooq.DDLFlag.DOMAIN;
import static org.jooq.DDLFlag.FOREIGN_KEY;
import static org.jooq.DDLFlag.INDEX;
import static org.jooq.DDLFlag.PRIMARY_KEY;
@ -59,11 +60,15 @@ import java.util.List;
import org.jooq.Check;
import org.jooq.Constraint;
import org.jooq.ConstraintEnforcementStep;
import org.jooq.CreateDomainAsStep;
import org.jooq.CreateDomainConstraintStep;
import org.jooq.CreateDomainDefaultStep;
import org.jooq.CreateSequenceFlagsStep;
import org.jooq.CreateTableOnCommitStep;
import org.jooq.DDLExportConfiguration;
import org.jooq.DDLFlag;
import org.jooq.DSLContext;
import org.jooq.Domain;
import org.jooq.Field;
import org.jooq.ForeignKey;
import org.jooq.Index;
@ -171,6 +176,27 @@ final class DDL {
return result;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
final Query createDomain(Domain<?> domain) {
CreateDomainAsStep s1 = configuration.createDomainIfNotExists()
? ctx.createDomainIfNotExists(domain)
: ctx.createDomain(domain);
CreateDomainDefaultStep s2 = s1.as(domain.getDataType());
CreateDomainConstraintStep s3 = domain.getDataType().defaulted()
? s2.default_(domain.getDataType().default_())
: s2;
if (domain.checks().isEmpty())
return s3;
List<Constraint> constraints = new ArrayList<>();
for (Check check : domain.checks())
constraints.add(check.constraint());
return s3.constraints(constraints);
}
private final Query createTable(Table<?> table) {
return createTable(table, constraints(table));
}
@ -345,6 +371,11 @@ final class DDL {
for (Constraint constraint : foreignKeys(table))
queries.add(ctx.alterTable(table).add(constraint));
if (configuration.flags().contains(DOMAIN))
for (Schema schema : schemas)
for (Domain<?> domain : sortIf(schema.getDomains(), !configuration.respectDomainOrder()))
queries.add(createDomain(domain));
if (configuration.flags().contains(SEQUENCE))
for (Schema schema : schemas)
for (Sequence<?> sequence : sortIf(schema.getSequences(), !configuration.respectSequenceOrder()))

View File

@ -52,7 +52,7 @@ import org.jooq.Schema;
/**
* @author Lukas Eder
*/
final class DomainImpl<T> extends AbstractTypedNamed<T> implements Domain<T> {
class DomainImpl<T> extends AbstractTypedNamed<T> implements Domain<T> {
/**
* Generated UID

View File

@ -49,6 +49,7 @@ import static org.jooq.impl.ConstraintType.PRIMARY_KEY;
import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DSL.schema;
import static org.jooq.impl.SQLDataType.BIGINT;
import static org.jooq.impl.Tools.EMPTY_CHECK;
import static org.jooq.impl.Tools.EMPTY_FIELD;
import static org.jooq.impl.Tools.intersect;
import static org.jooq.impl.Tools.normaliseNameCase;
@ -74,6 +75,7 @@ import org.jooq.Configuration;
import org.jooq.Constraint;
import org.jooq.DataType;
import org.jooq.Delete;
import org.jooq.Domain;
import org.jooq.Field;
import org.jooq.FieldOrConstraint;
import org.jooq.ForeignKey;
@ -127,6 +129,7 @@ final class Interpreter {
private final Map<Name, UniqueKeyImpl<Record>> interpretedUniqueKeys = new HashMap<>();
private final Map<Name, ReferenceImpl<Record, ?>> interpretedForeignKeys = new HashMap<>();
private final Map<Name, Index> interpretedIndexes = new HashMap<>();
private final Map<Name, MutableDomain.InterpretedDomain> interpretedDomains = new HashMap<>();
private final Map<Name, MutableSequence.InterpretedSequence> interpretedSequences = new HashMap<>();
Interpreter(Configuration configuration) {
@ -205,6 +208,9 @@ final class Interpreter {
else if (query instanceof DropIndexImpl)
accept0((DropIndexImpl) query);
else if (query instanceof CreateDomainImpl)
accept0((CreateDomainImpl) query);
else if (query instanceof CommentOnImpl)
accept0((CommentOnImpl) query);
@ -248,7 +254,7 @@ final class Interpreter {
if (getSchema(schema, false) != null) {
if (!query.$createSchemaIfNotExists())
throw schemaAlreadyExists(schema);
throw alreadyExists(schema);
return;
}
@ -263,14 +269,14 @@ final class Interpreter {
MutableSchema oldSchema = getSchema(schema);
if (oldSchema == null) {
if (!query.$alterSchemaIfExists())
throw schemaNotExists(schema);
throw notExists(schema);
return;
}
if (renameTo != null) {
if (getSchema(renameTo, false) != null)
throw schemaAlreadyExists(renameTo);
throw alreadyExists(renameTo);
oldSchema.name((UnqualifiedName) renameTo.getUnqualifiedName());
return;
@ -285,7 +291,7 @@ final class Interpreter {
if (mutableSchema == null) {
if (!query.$dropSchemaIfExists())
throw schemaNotExists(schema);
throw notExists(schema);
return;
}
@ -358,7 +364,7 @@ final class Interpreter {
MutableUniqueKey mu = null;
if (mrf == null)
throw tableNotExists(impl.$referencesTable());
throw notExists(impl.$referencesTable());
List<MutableField> mfs = mt.fields(impl.$foreignKey(), true);
List<MutableField> mrfs = mrf.fields(impl.$references(), true);
@ -472,7 +478,7 @@ final class Interpreter {
MutableTable existing = schema.table(table);
if (existing == null) {
if (!query.$ifExists())
throw tableNotExists(table);
throw notExists(table);
return;
}
@ -482,9 +488,9 @@ final class Interpreter {
if (query.$add() != null) {
for (FieldOrConstraint fc : query.$add())
if (fc instanceof Field && find(existing.fields, (Field<?>) fc) != null)
throw fieldAlreadyExists((Field<?>) fc);
throw alreadyExists(fc);
else if (fc instanceof Constraint && !fc.getUnqualifiedName().empty() && existing.constraint((Constraint) fc) != null)
throw constraintAlreadyExists((Constraint) fc);
throw alreadyExists(fc);
// TODO: ReverseIterable is not a viable approach if we also allow constraints to be added this way
if (query.$addFirst()) {
@ -516,7 +522,7 @@ final class Interpreter {
else if (query.$addColumn() != null) {
if (find(existing.fields, query.$addColumn()) != null)
if (!query.$ifNotExistsColumn())
throw fieldAlreadyExists(query.$addColumn());
throw alreadyExists(query.$addColumn());
else
return;
@ -540,7 +546,7 @@ final class Interpreter {
if (existingField == null)
if (!query.$ifExistsColumn())
throw columnNotExists(query.$alterColumn());
throw notExists(query.$alterColumn());
else
return;
@ -566,9 +572,9 @@ final class Interpreter {
MutableField mf = find(existing.fields, query.$renameColumn());
if (mf == null)
throw fieldNotExists(query.$renameColumn());
throw notExists(query.$renameColumn());
else if (find(existing.fields, query.$renameColumnTo()) != null)
throw fieldAlreadyExists(query.$renameColumnTo());
throw alreadyExists(query.$renameColumnTo());
else
mf.name((UnqualifiedName) query.$renameColumnTo().getUnqualifiedName());
}
@ -576,7 +582,7 @@ final class Interpreter {
MutableConstraint mc = existing.constraint(query.$renameConstraint(), true);
if (existing.constraint(query.$renameConstraintTo()) != null)
throw constraintAlreadyExists(query.$renameConstraintTo());
throw alreadyExists(query.$renameConstraintTo());
else
mc.name((UnqualifiedName) query.$renameConstraintTo().getUnqualifiedName());
}
@ -672,7 +678,7 @@ final class Interpreter {
}
if (!query.$ifExistsConstraint())
throw constraintNotExists(query.$dropConstraint());
throw notExists(query.$dropConstraint());
}
else if (query.$dropConstraintType() == PRIMARY_KEY) {
if (existing.primaryKey != null)
@ -732,11 +738,12 @@ final class Interpreter {
private final void addConstraint(Query query, ConstraintImpl impl, MutableTable existing) {
if (!impl.getUnqualifiedName().empty() && existing.constraint(impl) != null)
throw constraintAlreadyExists(impl);
throw alreadyExists(impl);
boolean enforced = true ;
if (impl.$primaryKey() != null)
if (existing.primaryKey != null)
throw constraintAlreadyExists(impl);
throw alreadyExists(impl);
else
existing.primaryKey = new MutableUniqueKey((UnqualifiedName) impl.getUnqualifiedName(), existing, existing.fields(impl.$primaryKey(), true), enforced);
else if (impl.$unique() != null)
@ -756,7 +763,7 @@ final class Interpreter {
MutableTable existing = schema.table(table);
if (existing == null) {
if (!query.$ifExists())
throw tableNotExists(table);
throw notExists(table);
return;
}
@ -775,7 +782,7 @@ final class Interpreter {
MutableTable existing = schema.table(table);
if (existing == null)
throw tableNotExists(table);
throw notExists(table);
else if (!existing.options.type().isTable())
throw objectNotTable(table);
else if (!query.$cascade() && existing.hasReferencingKeys())
@ -850,7 +857,7 @@ final class Interpreter {
MutableSequence existing = schema.sequence(sequence);
if (existing != null) {
if (!query.$createSequenceIfNotExists())
throw sequenceAlreadyExists(sequence);
throw alreadyExists(sequence);
return;
}
@ -872,7 +879,7 @@ final class Interpreter {
MutableSequence existing = schema.sequence(sequence);
if (existing == null) {
if (!query.$ifExists())
throw sequenceNotExists(sequence);
throw notExists(sequence);
return;
}
@ -880,7 +887,7 @@ final class Interpreter {
Sequence<?> renameTo = query.$renameTo();
if (renameTo != null) {
if (schema.sequence(renameTo) != null)
throw sequenceAlreadyExists(renameTo);
throw alreadyExists(renameTo);
existing.name((UnqualifiedName) renameTo.getUnqualifiedName());
}
@ -932,7 +939,7 @@ final class Interpreter {
MutableSequence existing = schema.sequence(sequence);
if (existing == null) {
if (!query.$dropSequenceIfExists())
throw sequenceNotExists(sequence);
throw notExists(sequence);
return;
}
@ -947,14 +954,14 @@ final class Interpreter {
MutableTable mt = schema.table(table);
if (mt == null)
throw tableNotExists(table);
throw notExists(table);
MutableIndex existing = find(mt.indexes, index);
List<MutableSortField> mtf = mt.sortFields(query.$sortFields());
if (existing != null) {
if (!query.$ifNotExists())
throw indexAlreadyExists(index);
throw alreadyExists(index);
return;
}
@ -972,7 +979,7 @@ final class Interpreter {
if (index(query.$renameTo(), table, false, false) == null)
existing.name((UnqualifiedName) query.$renameTo().getUnqualifiedName());
else
throw indexAlreadyExists(query.$renameTo());
throw alreadyExists(query.$renameTo());
else
throw unsupportedQuery(query);
}
@ -987,6 +994,39 @@ final class Interpreter {
existing.table.indexes.remove(existing);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private final void accept0(CreateDomainImpl<?> query) {
Domain<?> domain = query.$domain();
MutableSchema schema = getSchema(domain.getSchema(), true);
MutableDomain existing = schema.domain(domain);
if (existing != null) {
if (!query.$createDomainIfNotExists())
throw alreadyExists(domain);
return;
}
MutableDomain md = new MutableDomain((UnqualifiedName) domain.getUnqualifiedName(), schema, query.$dataType());
if (query.$default_() != null)
md.dataType = md.dataType.default_((Field) query.$default_());
// TODO: Support NOT NULL constraints
if (query.$constraints() != null) {
md.checks = new ArrayList<>();
for (Constraint constraint : query.$constraints())
if (((ConstraintImpl) constraint).$check() != null)
md.checks.add(new CheckImpl(
null,
constraint.getQualifiedName(),
((ConstraintImpl) constraint).$check(),
true
));
}
}
private final void accept0(CommentOnImpl query) {
Table<?> table = query.$table();
Field<?> field = query.$field();
@ -1002,7 +1042,7 @@ final class Interpreter {
private final void accept0(SetSchema query) {
MutableSchema schema = getSchema(query.$schema());
if (schema == null)
throw schemaNotExists(query.$schema());
throw notExists(query.$schema());
currentSchema = schema;
}
@ -1022,27 +1062,14 @@ final class Interpreter {
// Exceptions
// -------------------------------------------------------------------------
// TODO: Surely, these exception utilities can be refactored / improved?
private static final DataDefinitionException unsupportedQuery(Query query) {
return new DataDefinitionException("Unsupported query: " + query.getSQL());
}
private static final DataDefinitionException schemaNotExists(Schema schema) {
return new DataDefinitionException("Schema does not exist: " + schema.getQualifiedName());
}
private static final DataDefinitionException schemaAlreadyExists(Schema schema) {
return new DataDefinitionException("Schema already exists: " + schema.getQualifiedName());
}
private static final DataDefinitionException schemaNotEmpty(Schema schema) {
return new DataDefinitionException("Schema is not empty: " + schema.getQualifiedName());
}
private static final DataDefinitionException tableNotExists(Table<?> table) {
return new DataDefinitionException("Table does not exist: " + table.getQualifiedName());
}
private static final DataDefinitionException objectNotTable(Table<?> table) {
return new DataDefinitionException("Object is not a table: " + table.getQualifiedName());
}
@ -1055,10 +1082,6 @@ final class Interpreter {
return new DataDefinitionException("Object is not a view: " + table.getQualifiedName());
}
private static final DataDefinitionException tableAlreadyExists(Table<?> table) {
return new DataDefinitionException("Table already exists: " + table.getQualifiedName());
}
private static final DataDefinitionException viewNotExists(Table<?> view) {
return new DataDefinitionException("View does not exist: " + view.getQualifiedName());
}
@ -1067,58 +1090,22 @@ final class Interpreter {
return new DataDefinitionException("View already exists: " + view.getQualifiedName());
}
private static final DataDefinitionException columnNotExists(Field<?> field) {
return new DataDefinitionException("Column does not exist: " + field.getQualifiedName());
}
private static final DataDefinitionException columnAlreadyExists(Field<?> field) {
return columnAlreadyExists(field.getQualifiedName());
}
private static final DataDefinitionException columnAlreadyExists(Name name) {
return new DataDefinitionException("Column already exists: " + name);
}
private static final DataDefinitionException sequenceNotExists(Sequence<?> sequence) {
return new DataDefinitionException("Sequence does not exist: " + sequence.getQualifiedName());
private static final DataDefinitionException notExists(Named named) {
return new DataDefinitionException(named.getClass().getSimpleName() + " does not exist: " + named.getQualifiedName());
}
private static final DataDefinitionException sequenceAlreadyExists(Sequence<?> sequence) {
return new DataDefinitionException("Sequence already exists: " + sequence.getQualifiedName());
private static final DataDefinitionException alreadyExists(Named named) {
return new DataDefinitionException(named.getClass().getSimpleName() + " already exists: " + named.getQualifiedName());
}
private static final DataDefinitionException primaryKeyNotExists() {
return new DataDefinitionException("Primary key does not exist");
}
private static final DataDefinitionException constraintAlreadyExists(Constraint constraint) {
return new DataDefinitionException("Constraint already exists: " + constraint.getQualifiedName());
}
private static final DataDefinitionException constraintNotExists(Constraint constraint) {
return new DataDefinitionException("Constraint does not exist: " + constraint.getQualifiedName());
}
private static final DataDefinitionException indexNotExists(Index index) {
return new DataDefinitionException("Index does not exist: " + index.getQualifiedName());
}
private static final DataDefinitionException indexAlreadyExists(Index index) {
return new DataDefinitionException("Index already exists: " + index.getQualifiedName());
}
private static final DataDefinitionException fieldNotExists(Field<?> field) {
return new DataDefinitionException("Field does not exist: " + field.getQualifiedName());
}
private static final DataDefinitionException fieldAlreadyExists(Field<?> field) {
return new DataDefinitionException("Field already exists: " + field.getQualifiedName());
}
private static final DataDefinitionException objectNotExists(Named named) {
return new DataDefinitionException("Object does not exist: " + named.getQualifiedName());
}
// -------------------------------------------------------------------------
// Auxiliary methods
// -------------------------------------------------------------------------
@ -1206,7 +1193,7 @@ final class Interpreter {
private final MutableTable table(Table<?> table, boolean throwIfNotExists) {
MutableTable result = getSchema(table.getSchema()).table(table);
if (result == null && throwIfNotExists)
throw tableNotExists(table);
throw notExists(table);
return result;
}
@ -1233,10 +1220,10 @@ final class Interpreter {
if (mt != null)
mi = find(mt.indexes, index);
else if (table != null && throwIfNotExists)
throw tableNotExists(table);
throw notExists(table);
if (mi == null && !ifExists && throwIfNotExists)
throw indexNotExists(index);
throw notExists(index);
return mi;
}
@ -1254,7 +1241,7 @@ final class Interpreter {
if (mt.options.type().isView())
return viewAlreadyExists(t);
else
return tableAlreadyExists(t);
return alreadyExists(t);
}
private final MutableField field(Field<?> field) {
@ -1270,7 +1257,7 @@ final class Interpreter {
MutableField result = find(table.fields, field);
if (result == null && throwIfNotExists)
throw fieldNotExists(field);
throw notExists(field);
return result;
}
@ -1312,7 +1299,7 @@ final class Interpreter {
}
if (result == -1)
throw objectNotExists(named);
throw notExists(named);
return result;
}
@ -1484,6 +1471,7 @@ final class Interpreter {
private final class MutableSchema extends MutableNamed {
MutableCatalog catalog;
List<MutableTable> tables = new MutableNamedList<>();
List<MutableDomain> domains = new MutableNamedList<>();
List<MutableSequence> sequences = new MutableNamedList<>();
MutableSchema(UnqualifiedName name, MutableCatalog catalog) {
@ -1499,7 +1487,10 @@ final class Interpreter {
for (MutableForeignKey referencingKey : table.referencingKeys())
referencingKey.table.foreignKeys.remove(referencingKey);
// TODO: Cascade domains?
tables.clear();
domains.clear();
sequences.clear();
}
@ -1526,6 +1517,10 @@ final class Interpreter {
return find(tables, t);
}
final MutableDomain domain(Domain<?> d) {
return find(domains, d);
}
final MutableSequence sequence(Sequence<?> s) {
return find(sequences, s);
}
@ -1545,6 +1540,16 @@ final class Interpreter {
return result;
}
@Override
public final List<Domain<?>> getDomains() {
List<Domain<?>> result = new ArrayList<>(domains.size());
for (MutableDomain domain : domains)
result.add(domain.interpretedDomain());
return result;
}
@Override
public final List<Sequence<?>> getSequences() {
List<Sequence<?>> result = new ArrayList<>(sequences.size());
@ -1641,7 +1646,7 @@ final class Interpreter {
return result;
if (failIfNotFound)
throw constraintNotExists(constraint);
throw notExists(constraint);
return null;
}
@ -1754,6 +1759,48 @@ final class Interpreter {
}
}
private final class MutableDomain extends MutableNamed {
MutableSchema schema;
DataType<?> dataType;
List<Check<?>> checks;
MutableDomain(UnqualifiedName name, MutableSchema schema, DataType<?> dataType) {
super(name);
this.schema = schema;
this.dataType = dataType;
schema.domains.add(this);
}
@Override
final void onDrop() {
// TODO: Cascade
}
@Override
final MutableNamed parent() {
return schema;
}
final InterpretedDomain interpretedDomain() {
Name qualifiedName = qualifiedName();
InterpretedDomain result = interpretedDomains.get(qualifiedName);
if (result == null)
interpretedDomains.put(qualifiedName, result = new InterpretedDomain(schema.interpretedSchema()));
return result;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private final class InterpretedDomain extends DomainImpl {
InterpretedDomain(Schema schema) {
super(schema, MutableDomain.this.name(), dataType, checks != null ? checks.toArray(EMPTY_CHECK) : EMPTY_CHECK);
}
}
}
private final class MutableSequence extends MutableNamed {
MutableSchema schema;
Field<? extends Number> startWith;

View File

@ -49,7 +49,9 @@ import org.jooq.Catalog;
import org.jooq.Clause;
import org.jooq.Comment;
import org.jooq.Context;
import org.jooq.Domain;
import org.jooq.Name;
import org.jooq.Named;
import org.jooq.Schema;
import org.jooq.Sequence;
import org.jooq.Table;
@ -126,31 +128,32 @@ public class SchemaImpl extends AbstractNamed implements Schema {
return CLAUSES;
}
@Override
public final Table<?> getTable(String tableName) {
for (Table<?> table : getTables())
if (table.getName().equals(tableName))
return table;
private final <N extends Named> N getNamed(List<N> list, String name) {
for (N named : list)
if (named.getName().equals(name))
return named;
return null;
}
@Override
public final UDT<?> getUDT(String udtName) {
for (UDT<?> udt : getUDTs())
if (udt.getName().equals(udtName))
return udt;
return null;
public final Table<?> getTable(String name) {
return getNamed(getTables(), name);
}
@Override
public final Sequence<?> getSequence(String sequenceName) {
for (Sequence<?> sequence : getSequences())
if (sequence.getName().equals(sequenceName))
return sequence;
public final UDT<?> getUDT(String name) {
return getNamed(getUDTs(), name);
}
return null;
@Override
public final Domain<?> getDomain(String name) {
return getNamed(getDomains(), name);
}
@Override
public final Sequence<?> getSequence(String name) {
return getNamed(getSequences(), name);
}
/**
@ -173,6 +176,16 @@ public class SchemaImpl extends AbstractNamed implements Schema {
return Collections.emptyList();
}
/**
* {@inheritDoc}
* <p>
* Subclasses should override this method
*/
@Override
public List<Domain<?>> getDomains() {
return Collections.emptyList();
}
/**
* {@inheritDoc}
* <p>
@ -194,6 +207,11 @@ public class SchemaImpl extends AbstractNamed implements Schema {
return getUDTs().stream();
}
@Override
public final Stream<Domain<?>> domainStream() {
return getDomains().stream();
}
@Override
public final Stream<Sequence<?>> sequenceStream() {
return getSequences().stream();

View File

@ -217,6 +217,7 @@ import org.jooq.Asterisk;
import org.jooq.Attachable;
import org.jooq.BindContext;
import org.jooq.Catalog;
import org.jooq.Check;
import org.jooq.Clause;
import org.jooq.CommonTableExpression;
import org.jooq.Condition;
@ -298,6 +299,7 @@ final class Tools {
// ------------------------------------------------------------------------
static final byte[] EMPTY_BYTE = {};
static final Check<?>[] EMPTY_CHECK = {};
static final Clause[] EMPTY_CLAUSE = {};
static final Collection<?>[] EMPTY_COLLECTION = {};
static final CommonTableExpression<?>[] EMPTY_COMMON_TABLE_EXPRESSION = {};