This commit is contained in:
Lukas Eder 2019-12-11 15:33:09 +01:00
parent a471e023d1
commit 6d000bd55b
22 changed files with 587 additions and 171 deletions

View File

@ -138,6 +138,12 @@

View File

@ -0,0 +1,86 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq;

View File

@ -197,6 +197,20 @@ public interface AlterTableStep {
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
AlterTableRenameConstraintToStep renameConstraint(String oldName);
/**
* Add an <code>ALTER COLUMN</code> clause to the <code>ALTER TABLE</code>
* statement.
@ -245,6 +259,34 @@ public interface AlterTableStep {
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, MYSQL, POSTGRES })
AlterTableAlterStep<Object> alterColumn(String field);
/**
* Add an <code>ADD COLUMN</code> clause to the <code>ALTER TABLE</code>
* statement.

View File

@ -62,4 +62,9 @@ public interface Check<R extends Record> extends Named {
* Get this <code>CHECK</code> as a formal {@link Constraint} specification.
*/
Constraint constraint();
/**
* Whether this check is being enforced.
*/
boolean enforced();
}

View File

@ -0,0 +1,87 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
* database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq;
// ...
// ...
/**
* The step in the {@link Constraint} construction DSL API that allows for
* adding <code>ENFORCED</code> and <code>NOT ENFORCED</code> clauses.
* <p>
* <p>
* <h3>Referencing <code>XYZ*Step</code> types directly from client code</h3>
* <p>
* It is usually not recommended to reference any <code>XYZ*Step</code> types
* directly from client code, or assign them to local variables. When writing
* dynamic SQL, creating a statement's components dynamically, and passing them
* to the DSL API statically is usually a better choice. See the manual's
* section about dynamic SQL for details: <a href=
* "https://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql">https://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql</a>.
* <p>
* Drawbacks of referencing the <code>XYZ*Step</code> types directly:
* <ul>
* <li>They're operating on mutable implementations (as of jOOQ 3.x)</li>
* <li>They're less composable and not easy to get right when dynamic SQL gets
* complex</li>
* <li>They're less readable</li>
* <li>They might have binary incompatible changes between minor releases</li>
* </ul>
*
* @author Lukas Eder
*/
public interface ConstraintEnforcementStep extends ConstraintFinalStep {
}

View File

@ -85,7 +85,7 @@ import static org.jooq.SQLDialect.SQLITE;
*
* @author Lukas Eder
*/
public interface ConstraintForeignKeyOnStep extends ConstraintFinalStep {
public interface ConstraintForeignKeyOnStep extends ConstraintEnforcementStep {
/**
* Add an <code>ON DELETE NO ACTION</code> clause to the

View File

@ -89,19 +89,19 @@ public interface ConstraintTypeStep extends ConstraintFinalStep {
* Create a <code>PRIMARY KEY</code> constraint.
*/
@Support
ConstraintFinalStep primaryKey(String... fields);
ConstraintEnforcementStep primaryKey(String... fields);
/**
* Create a <code>PRIMARY KEY</code> constraint.
*/
@Support
ConstraintFinalStep primaryKey(Name... fields);
ConstraintEnforcementStep primaryKey(Name... fields);
/**
* Create a <code>PRIMARY KEY</code> constraint.
*/
@Support
ConstraintFinalStep primaryKey(Field<?>... fields);
ConstraintEnforcementStep primaryKey(Field<?>... fields);
/**
* Add a <code>FOREIGN KEY</code> clause to the <code>CONSTRAINT</code>.
@ -525,23 +525,23 @@ public interface ConstraintTypeStep extends ConstraintFinalStep {
* Create a <code>UNIQUE</code> constraint.
*/
@Support
ConstraintFinalStep unique(String... fields);
ConstraintEnforcementStep unique(String... fields);
/**
* Create a <code>UNIQUE</code> constraint.
*/
@Support
ConstraintFinalStep unique(Name... fields);
ConstraintEnforcementStep unique(Name... fields);
/**
* Create a <code>UNIQUE</code> constraint.
*/
@Support
ConstraintFinalStep unique(Field<?>... fields);
ConstraintEnforcementStep unique(Field<?>... fields);
/**
* Create a <code>CHECK</code> constraint.
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, MARIADB, POSTGRES, SQLITE })
ConstraintFinalStep check(Condition condition);
ConstraintEnforcementStep check(Condition condition);
}

View File

@ -73,4 +73,9 @@ public interface Key<R extends Record> extends Named {
* Get this <code>KEY</code> as a formal {@link Constraint} specification.
*/
Constraint constraint();
/**
* Whether this key is being enforced.
*/
boolean enforced();
}

View File

@ -60,22 +60,18 @@ abstract class AbstractKey<R extends Record> extends AbstractNamed implements Ke
private final Table<R> table;
private final TableField<R, ?>[] fields;
private final boolean enforced;
@SafeVarargs
AbstractKey(Table<R> table, TableField<R, ?>... fields) {
this(table, null, fields);
AbstractKey(Table<R> table, TableField<R, ?>[] fields, boolean enforced) {
this(table, null, fields, enforced);
}
@SafeVarargs
AbstractKey(Table<R> table, String name, TableField<R, ?>... fields) {
AbstractKey(Table<R> table, String name, TableField<R, ?>[] fields, boolean enforced) {
super(name == null ? null : DSL.name(name), null);
this.table = table;
this.fields = fields;
this.enforced = enforced;
}
@Override
@ -93,6 +89,11 @@ abstract class AbstractKey<R extends Record> extends AbstractNamed implements Ke
return fields;
}
@Override
public final boolean enforced() {
return enforced;
}
@Override
public final void accept(Context<?> ctx) {
ctx.visit(getUnqualifiedName());

View File

@ -164,6 +164,7 @@ import java.util.List;
import java.util.Set;
import org.jooq.AlterTableAddStep;
// ...
import org.jooq.AlterTableAlterStep;
import org.jooq.AlterTableDropStep;
import org.jooq.AlterTableFinalStep;
@ -203,6 +204,7 @@ final class AlterTableImpl extends AbstractRowCountQuery implements
AlterTableAddStep,
AlterTableDropStep,
AlterTableAlterStep,
AlterTableAlterConstraintStep,
AlterTableUsingIndexStep,
AlterTableRenameColumnToStep,
AlterTableRenameIndexToStep,
@ -259,6 +261,10 @@ final class AlterTableImpl extends AbstractRowCountQuery implements
private Field<?> alterColumn;
private Nullability alterColumnNullability;
private DataType<?> alterColumnType;
@ -280,32 +286,38 @@ final class AlterTableImpl extends AbstractRowCountQuery implements
this.ifExists = ifExists;
}
final Table<?> $table() { return table; }
final boolean $ifExists() { return ifExists; }
final boolean $ifExistsColumn() { return ifExistsColumn; }
final boolean $ifExistsConstraint() { return ifExistsConstraint; }
final boolean $ifNotExistsColumn() { return ifNotExistsColumn; }
final List<FieldOrConstraint> $add() { return add; }
final Field<?> $addColumn() { return addColumn; }
final DataType<?> $addColumnType() { return addColumnType; }
final Constraint $addConstraint() { return addConstraint; }
final boolean $addFirst() { return addFirst; }
final Field<?> $addBefore() { return addBefore; }
final Field<?> $addAfter() { return addAfter; }
final Field<?> $alterColumn() { return alterColumn; }
final Nullability $alterColumnNullability() { return alterColumnNullability; }
final DataType<?> $alterColumnType() { return alterColumnType; }
final Field<?> $alterColumnDefault() { return alterColumnDefault; }
final boolean $alterColumnDropDefault() { return alterColumnDropDefault; }
final Table<?> $renameTo() { return renameTo; }
final Field<?> $renameColumn() { return renameColumn; }
final Field<?> $renameColumnTo() { return renameColumnTo; }
final Constraint $renameConstraint() { return renameConstraint; }
final Constraint $renameConstraintTo() { return renameConstraintTo; }
final List<Field<?>> $dropColumns() { return dropColumns; }
final Cascade $dropCascade() { return dropCascade; }
final Constraint $dropConstraint() { return dropConstraint; }
final ConstraintType $dropConstraintType() { return dropConstraintType; }
final Table<?> $table() { return table; }
final boolean $ifExists() { return ifExists; }
final boolean $ifExistsColumn() { return ifExistsColumn; }
final boolean $ifExistsConstraint() { return ifExistsConstraint; }
final boolean $ifNotExistsColumn() { return ifNotExistsColumn; }
final List<FieldOrConstraint> $add() { return add; }
final Field<?> $addColumn() { return addColumn; }
final DataType<?> $addColumnType() { return addColumnType; }
final Constraint $addConstraint() { return addConstraint; }
final boolean $addFirst() { return addFirst; }
final Field<?> $addBefore() { return addBefore; }
final Field<?> $addAfter() { return addAfter; }
final Field<?> $alterColumn() { return alterColumn; }
final Nullability $alterColumnNullability() { return alterColumnNullability; }
final DataType<?> $alterColumnType() { return alterColumnType; }
final Field<?> $alterColumnDefault() { return alterColumnDefault; }
final boolean $alterColumnDropDefault() { return alterColumnDropDefault; }
final Table<?> $renameTo() { return renameTo; }
final Field<?> $renameColumn() { return renameColumn; }
final Field<?> $renameColumnTo() { return renameColumnTo; }
final Constraint $renameConstraint() { return renameConstraint; }
final Constraint $renameConstraintTo() { return renameConstraintTo; }
final List<Field<?>> $dropColumns() { return dropColumns; }
final Cascade $dropCascade() { return dropCascade; }
final Constraint $dropConstraint() { return dropConstraint; }
final ConstraintType $dropConstraintType() { return dropConstraintType; }
// ------------------------------------------------------------------------
// XXX: DSL API
@ -635,6 +647,43 @@ final class AlterTableImpl extends AbstractRowCountQuery implements
return this;
}
@Override
public final AlterTableImpl set(DataType type) {
alterColumnType = type;
@ -1357,6 +1406,30 @@ final class AlterTableImpl extends AbstractRowCountQuery implements
ctx.end(ALTER_TABLE_ADD);
}
else if (alterColumn != null) {
ctx.start(ALTER_TABLE_ALTER);

View File

@ -57,33 +57,40 @@ final class CheckImpl<R extends Record> extends AbstractNamed implements Check<R
final Table<R> table;
final Condition condition;
final boolean enforced;
CheckImpl(Table<R> table, Condition condition) {
this(table, null, condition);
CheckImpl(Table<R> table, Condition condition, boolean enforced) {
this(table, null, condition, enforced);
}
CheckImpl(Table<R> table, Name name, Condition condition) {
CheckImpl(Table<R> table, Name name, Condition condition, boolean enforced) {
super(name, null);
this.table = table;
this.condition = condition;
this.enforced = enforced;
}
@Override
public Table<R> getTable() {
public final Table<R> getTable() {
return table;
}
@Override
public Condition condition() {
public final Condition condition() {
return condition;
}
@Override
public Constraint constraint() {
public final Constraint constraint() {
return DSL.constraint(getName()).check(condition);
}
@Override
public final boolean enforced() {
return enforced;
}
@Override
public final void accept(Context<?> ctx) {
ctx.visit(getUnqualifiedName());

View File

@ -51,8 +51,12 @@ import static org.jooq.impl.DSL.name;
import static org.jooq.impl.DSL.table;
import static org.jooq.impl.Keywords.K_CHECK;
import static org.jooq.impl.Keywords.K_CONSTRAINT;
import static org.jooq.impl.Keywords.K_DISABLE;
import static org.jooq.impl.Keywords.K_ENABLE;
import static org.jooq.impl.Keywords.K_ENFORCED;
import static org.jooq.impl.Keywords.K_FOREIGN_KEY;
import static org.jooq.impl.Keywords.K_NONCLUSTERED;
import static org.jooq.impl.Keywords.K_NOT;
import static org.jooq.impl.Keywords.K_NOT_ENFORCED;
import static org.jooq.impl.Keywords.K_ON_DELETE;
import static org.jooq.impl.Keywords.K_ON_UPDATE;
@ -141,8 +145,8 @@ implements
/**
* Generated UID
*/
private static final long serialVersionUID = 1018023703769802616L;
private static final Clause[] CLAUSES = { CONSTRAINT };
private static final long serialVersionUID = 1018023703769802616L;
private static final Clause[] CLAUSES = { CONSTRAINT };
@ -150,14 +154,18 @@ implements
private Field<?>[] unique;
private Field<?>[] primaryKey;
private Field<?>[] foreignKey;
private Table<?> referencesTable;
private Field<?>[] references;
private Action onDelete;
private Action onUpdate;
private Condition check;
private Field<?>[] unique;
private Field<?>[] primaryKey;
private Field<?>[] foreignKey;
private Table<?> referencesTable;
private Field<?>[] references;
private Action onDelete;
private Action onUpdate;
private Condition check;
ConstraintImpl() {
this(null);
@ -176,6 +184,10 @@ implements
final Action $onUpdate() { return onUpdate; }
final Condition $check() { return check; }
// ------------------------------------------------------------------------
// XXX: QueryPart API
// ------------------------------------------------------------------------
@ -277,6 +289,11 @@ implements
.sql(')');
}
if (named) {
@ -293,6 +310,30 @@ implements
}
}
// ------------------------------------------------------------------------
// XXX: Constraint API
// ------------------------------------------------------------------------
@ -1107,6 +1148,22 @@ implements
enum Action {
NO_ACTION("no action"),
RESTRICT("restrict"),

View File

@ -58,6 +58,7 @@ import java.util.List;
import org.jooq.Check;
import org.jooq.Constraint;
import org.jooq.ConstraintEnforcementStep;
import org.jooq.CreateSequenceFlagsStep;
import org.jooq.CreateTableOnCommitStep;
import org.jooq.DDLExportConfiguration;
@ -220,7 +221,7 @@ final class DDL {
if (configuration.flags().contains(PRIMARY_KEY))
for (UniqueKey<?> key : table.getKeys())
if (key.isPrimary())
result.add(constraint(key.getUnqualifiedName()).primaryKey(key.getFieldsArray()));
result.add(enforced(constraint(key.getUnqualifiedName()).primaryKey(key.getFieldsArray()), key.enforced()));
return result;
}
@ -231,7 +232,7 @@ final class DDL {
if (configuration.flags().contains(UNIQUE))
for (UniqueKey<?> key : sortKeysIf(table.getKeys(), !configuration.respectConstraintOrder()))
if (!key.isPrimary())
result.add(constraint(key.getUnqualifiedName()).unique(key.getFieldsArray()));
result.add(enforced(constraint(key.getUnqualifiedName()).unique(key.getFieldsArray()), key.enforced()));
return result;
}
@ -241,7 +242,7 @@ final class DDL {
if (configuration.flags().contains(FOREIGN_KEY))
for (ForeignKey<?, ?> key : sortKeysIf(table.getReferences(), !configuration.respectConstraintOrder()))
result.add(constraint(key.getUnqualifiedName()).foreignKey(key.getFieldsArray()).references(key.getKey().getTable(), key.getKey().getFieldsArray()));
result.add(enforced(constraint(key.getUnqualifiedName()).foreignKey(key.getFieldsArray()).references(key.getKey().getTable(), key.getKey().getFieldsArray()), key.enforced()));
return result;
}
@ -251,7 +252,7 @@ final class DDL {
if (configuration.flags().contains(CHECK))
for (Check<?> check : sortIf(table.getChecks(), !configuration.respectConstraintOrder()))
result.add(constraint(check.getUnqualifiedName()).check(check.condition()));
result.add(enforced(constraint(check.getUnqualifiedName()).check(check.condition()), check.enforced()));
return result;
}
@ -382,4 +383,13 @@ final class DDL {
return input;
}
private final Constraint enforced(ConstraintEnforcementStep check, boolean enforced) {
return check;
}
}

View File

@ -315,14 +315,14 @@ final class DDLInterpreter {
if (!mrfs.isEmpty())
mu = mrf.uniqueKey(mrfs);
else if (mrf.primaryKey != null && mrf.primaryKey.keyFields.size() == mfs.size())
else if (mrf.primaryKey != null && mrf.primaryKey.fields.size() == mfs.size())
mu = mrf.primaryKey;
if (mu == null)
throw primaryKeyNotExists();
mt.foreignKeys.add(new MutableForeignKey(
(UnqualifiedName) impl.getUnqualifiedName(), mt, mfs, mu, impl.$onDelete(), impl.$onUpdate()
(UnqualifiedName) impl.getUnqualifiedName(), mt, mfs, mu, impl.$onDelete(), impl.$onUpdate(), impl.$enforced()
));
}
@ -349,7 +349,7 @@ final class DDLInterpreter {
for (boolean check : cascade == CASCADE ? new boolean [] { false } : new boolean [] { true, false }) {
if (table.primaryKey != null) {
if (intersect(table.primaryKey.keyFields, fields)) {
if (intersect(table.primaryKey.fields, fields)) {
cascade(table.primaryKey, fields, check ? RESTRICT : CASCADE);
if (!check)
@ -382,7 +382,7 @@ final class DDLInterpreter {
while (it2.hasNext()) {
MutableKey key = it2.next();
if (fields == null || intersect(key.keyFields, fields)) {
if (fields == null || intersect(key.fields, fields)) {
if (key instanceof MutableUniqueKey)
cascade((MutableUniqueKey) key, fields, check ? RESTRICT : CASCADE);
@ -522,14 +522,15 @@ final class DDLInterpreter {
mf.name((UnqualifiedName) query.$renameColumnTo().getUnqualifiedName());
}
else if (query.$renameConstraint() != null) {
MutableNamed mk = existing.constraint(query.$renameConstraint());
MutableConstraint mc = existing.constraint(query.$renameConstraint(), true);
if (mk == null)
throw constraintNotExists(query.$renameConstraint());
else if (existing.constraint(query.$renameConstraintTo()) != null)
if (existing.constraint(query.$renameConstraintTo()) != null)
throw constraintAlreadyExists(query.$renameConstraintTo());
else
mk.name((UnqualifiedName) query.$renameConstraintTo().getUnqualifiedName());
mc.name((UnqualifiedName) query.$renameConstraintTo().getUnqualifiedName());
}
else if (query.$alterConstraint() != null) {
existing.constraint(query.$alterConstraint(), true).enforced = query.$alterConstraintEnforced();
}
else if (query.$dropColumns() != null) {
List<MutableField> fields = existing.fields(query.$dropColumns().toArray(EMPTY_FIELD), false);
@ -671,13 +672,13 @@ final class DDLInterpreter {
if (existing.primaryKey != null)
throw constraintAlreadyExists(impl);
else
existing.primaryKey = new MutableUniqueKey((UnqualifiedName) impl.getUnqualifiedName(), existing, existing.fields(impl.$primaryKey(), true));
existing.primaryKey = new MutableUniqueKey((UnqualifiedName) impl.getUnqualifiedName(), existing, existing.fields(impl.$primaryKey(), true), impl.$enforced());
else if (impl.$unique() != null)
existing.uniqueKeys.add(new MutableUniqueKey((UnqualifiedName) impl.getUnqualifiedName(), existing, existing.fields(impl.$unique(), true)));
existing.uniqueKeys.add(new MutableUniqueKey((UnqualifiedName) impl.getUnqualifiedName(), existing, existing.fields(impl.$unique(), true), impl.$enforced()));
else if (impl.$foreignKey() != null)
addForeignKey(getSchema(impl.$referencesTable().getSchema(), false), existing, impl);
else if (impl.$check() != null)
existing.checks.add(new MutableCheck((UnqualifiedName) impl.getUnqualifiedName(), existing, impl.$check()));
existing.checks.add(new MutableCheck((UnqualifiedName) impl.getUnqualifiedName(), existing, impl.$check(), impl.$enforced()));
else
throw unsupportedQuery(query);
}
@ -1395,7 +1396,7 @@ final class DDLInterpreter {
final void onDrop() {
for (MutableTable table : tables)
for (MutableForeignKey referencingKey : table.referencingKeys())
referencingKey.keyTable.foreignKeys.remove(referencingKey);
referencingKey.table.foreignKeys.remove(referencingKey);
tables.clear();
sequences.clear();
@ -1523,8 +1524,8 @@ final class DDLInterpreter {
return result;
}
final MutableNamed constraint(Constraint constraint) {
MutableNamed result;
final MutableConstraint constraint(Constraint constraint, boolean failIfNotFound) {
MutableConstraint result;
if ((result = find(foreignKeys, constraint)) != null)
return result;
@ -1535,7 +1536,17 @@ final class DDLInterpreter {
if ((result = find(checks, constraint)) != null)
return result;
return find(primaryKey, constraint);
if ((result = find(primaryKey, constraint)) != null)
return result;
if (failIfNotFound)
throw constraintNotExists(constraint);
return null;
}
final MutableNamed constraint(Constraint constraint) {
return constraint(constraint, false);
}
final List<MutableField> fields(Field<?>[] fs, boolean failIfNotFound) {
@ -1571,11 +1582,11 @@ final class DDLInterpreter {
final MutableUniqueKey uniqueKey(List<MutableField> mrfs) {
if (primaryKey != null)
if (primaryKey.keyFields.equals(mrfs))
if (primaryKey.fields.equals(mrfs))
return primaryKey;
for (MutableUniqueKey mu : uniqueKeys)
if (mu.keyFields.equals(mrfs))
if (mu.fields.equals(mrfs))
return mu;
return null;
@ -1625,7 +1636,7 @@ final class DDLInterpreter {
List<Check<Record>> result = new ArrayList<>();
for (MutableCheck c : MutableTable.this.checks)
result.add(new CheckImpl<>(this, c.name(), c.condition));
result.add(new CheckImpl<>(this, c.name(), c.condition, c.enforced));
return result;
}
@ -1690,53 +1701,56 @@ final class DDLInterpreter {
}
}
private abstract class MutableKey extends MutableNamed {
MutableTable keyTable;
List<MutableField> keyFields;
private abstract class MutableConstraint extends MutableNamed {
MutableTable table;
boolean enforced;
MutableKey(UnqualifiedName name, MutableTable table, List<MutableField> fields) {
MutableConstraint(UnqualifiedName name, MutableTable table, boolean enforced) {
super(name);
this.keyTable = table;
this.keyFields = fields;
this.table = table;
this.enforced = enforced;
}
@Override
final MutableNamed parent() {
return keyTable;
return table;
}
}
private abstract class MutableKey extends MutableConstraint {
List<MutableField> fields;
MutableKey(UnqualifiedName name, MutableTable table, List<MutableField> fields, boolean enforced) {
super(name, table, enforced);
this.fields = fields;
}
final boolean fieldsEquals(Field<?>[] fields) {
if (keyFields.size() != fields.length)
final boolean fieldsEquals(Field<?>[] f) {
if (fields.size() != f.length)
return false;
for (int i = 0; i < keyFields.size(); i++)
if (!keyFields.get(i).nameEquals((UnqualifiedName) fields[i].getUnqualifiedName()))
for (int i = 0; i < fields.size(); i++)
if (!fields.get(i).nameEquals((UnqualifiedName) f[i].getUnqualifiedName()))
return false;
return true;
}
}
private final class MutableCheck extends MutableNamed {
MutableTable table;
Condition condition;
private final class MutableCheck extends MutableConstraint {
Condition condition;
MutableCheck(UnqualifiedName name, MutableTable table, Condition condition) {
super(name);
MutableCheck(UnqualifiedName name, MutableTable table, Condition condition, boolean enforced) {
super(name, table, enforced);
this.table = table;
this.condition = condition;
}
@Override
final void onDrop() {}
@Override
final MutableNamed parent() {
return table;
}
@Override
final Name qualifiedName() {
@ -1751,8 +1765,8 @@ final class DDLInterpreter {
private final class MutableUniqueKey extends MutableKey {
List<MutableForeignKey> referencingKeys = new MutableNamedList<>();
MutableUniqueKey(UnqualifiedName name, MutableTable keyTable, List<MutableField> keyFields) {
super(name, keyTable, keyFields);
MutableUniqueKey(UnqualifiedName name, MutableTable table, List<MutableField> fields, boolean enforced) {
super(name, table, fields, enforced);
}
@Override
@ -1766,7 +1780,7 @@ final class DDLInterpreter {
// TODO: Find a better way to identify unnamed constraints.
if (name().empty())
return super.qualifiedName().append(keyFields.toString());
return super.qualifiedName().append(fields.toString());
else
return super.qualifiedName();
}
@ -1777,14 +1791,14 @@ final class DDLInterpreter {
UniqueKeyImpl<Record> result = interpretedUniqueKeys.get(qualifiedName);
if (result == null) {
MutableTable.InterpretedTable t = keyTable.interpretedTable();
TableField<Record, ?>[] f = new TableField[keyFields.size()];
MutableTable.InterpretedTable t = table.interpretedTable();
TableField<Record, ?>[] f = new TableField[fields.size()];
for (int i = 0; i < f.length; i++)
f[i] = (TableField<Record, ?>) t.field(keyFields.get(i).name());
f[i] = (TableField<Record, ?>) t.field(fields.get(i).name());
// Add to map before adding bi-directionality to avoid StackOverflowErrors
interpretedUniqueKeys.put(qualifiedName, result = new UniqueKeyImpl<>(t, name().last(), f));
interpretedUniqueKeys.put(qualifiedName, result = new UniqueKeyImpl<>(t, name().last(), f, enforced));
for (MutableForeignKey referencingKey : referencingKeys)
result.references.add((ForeignKey) referencingKey.interpretedKey());
}
@ -1795,18 +1809,21 @@ final class DDLInterpreter {
private final class MutableForeignKey extends MutableKey {
MutableUniqueKey referencedKey;
// TODO: Support these
Action onDelete;
Action onUpdate;
MutableForeignKey(
UnqualifiedName name,
MutableTable keyTable,
List<MutableField> keyFields,
MutableTable table,
List<MutableField> fields,
MutableUniqueKey referencedKey,
Action onDelete,
Action onUpdate
Action onUpdate,
boolean enforced
) {
super(name, keyTable, keyFields);
super(name, table, fields, enforced);
this.referencedKey = referencedKey;
this.referencedKey.referencingKeys.add(this);
@ -1835,13 +1852,13 @@ final class DDLInterpreter {
ReferenceImpl<Record, ?> result = interpretedForeignKeys.get(qualifiedName);
if (result == null) {
MutableTable.InterpretedTable t = keyTable.interpretedTable();
TableField<Record, ?>[] f = new TableField[keyFields.size()];
MutableTable.InterpretedTable t = table.interpretedTable();
TableField<Record, ?>[] f = new TableField[fields.size()];
for (int i = 0; i < f.length; i++)
f[i] = (TableField<Record, ?>) t.field(keyFields.get(i).name());
f[i] = (TableField<Record, ?>) t.field(fields.get(i).name());
interpretedForeignKeys.put(qualifiedName, result = new ReferenceImpl<>(referencedKey.interpretedKey(), t, name().last(), f));
interpretedForeignKeys.put(qualifiedName, result = new ReferenceImpl<>(referencedKey.interpretedKey(), t, name().last(), f, enforced));
}
return result;

View File

@ -149,7 +149,7 @@ import org.jooq.CommonTableExpression;
import org.jooq.Condition;
import org.jooq.Configuration;
import org.jooq.ConnectionProvider;
import org.jooq.ConstraintFinalStep;
import org.jooq.ConstraintEnforcementStep;
import org.jooq.ConstraintForeignKeyReferencesStep1;
import org.jooq.ConstraintForeignKeyReferencesStep10;
import org.jooq.ConstraintForeignKeyReferencesStep11;
@ -5916,7 +5916,7 @@ public class DSL {
* Create an unnamed (system named) <code>PRIMARY KEY</code> constraint.
*/
@Support
public static ConstraintFinalStep primaryKey(String... fields) {
public static ConstraintEnforcementStep primaryKey(String... fields) {
return constraint().primaryKey(fields);
}
@ -5924,7 +5924,7 @@ public class DSL {
* Create an unnamed (system named) <code>PRIMARY KEY</code> constraint.
*/
@Support
public static ConstraintFinalStep primaryKey(Name... fields) {
public static ConstraintEnforcementStep primaryKey(Name... fields) {
return constraint().primaryKey(fields);
}
@ -5932,7 +5932,7 @@ public class DSL {
* Create an unnamed (system named) <code>PRIMARY KEY</code> constraint.
*/
@Support
public static ConstraintFinalStep primaryKey(Field<?>... fields) {
public static ConstraintEnforcementStep primaryKey(Field<?>... fields) {
return constraint().primaryKey(fields);
}
@ -6496,7 +6496,7 @@ public class DSL {
* Create an unnamed (system named) <code>UNIQUE</code> constraint.
*/
@Support
public static ConstraintFinalStep unique(String... fields) {
public static ConstraintEnforcementStep unique(String... fields) {
return constraint().unique(fields);
}
@ -6504,7 +6504,7 @@ public class DSL {
* Create an unnamed (system named) <code>UNIQUE</code> constraint.
*/
@Support
public static ConstraintFinalStep unique(Name... fields) {
public static ConstraintEnforcementStep unique(Name... fields) {
return constraint().unique(fields);
}
@ -6512,7 +6512,7 @@ public class DSL {
* Create an unnamed (system named) <code>UNIQUE</code> constraint.
*/
@Support
public static ConstraintFinalStep unique(Field<?>... fields) {
public static ConstraintEnforcementStep unique(Field<?>... fields) {
return constraint().unique(fields);
}
@ -6520,7 +6520,7 @@ public class DSL {
* Create an unnamed (system named) <code>CHECK</code> constraint.
*/
@Support({ CUBRID, DERBY, FIREBIRD, H2, HSQLDB, POSTGRES, SQLITE })
public static ConstraintFinalStep check(Condition condition) {
public static ConstraintEnforcementStep check(Condition condition) {
return constraint().check(condition);
}

View File

@ -421,7 +421,7 @@ final class InformationSchemaMetaImpl extends AbstractMeta {
for (CheckConstraint cc : meta.getCheckConstraints()) {
if (constraintName.equals(name(cc.getConstraintCatalog(), cc.getConstraintSchema(), cc.getConstraintName()))) {
table.checks.add(new CheckImpl<>(table, constraintName, DSL.condition(cc.getCheckClause())));
table.checks.add(new CheckImpl<>(table, constraintName, DSL.condition(cc.getCheckClause()), true));
continue tableConstraintLoop;
}
}

View File

@ -100,7 +100,7 @@ public final class Internal {
@SafeVarargs
public static final <R extends Record> UniqueKey<R> createUniqueKey(Table<R> table, TableField<R, ?>... fields) {
return new UniqueKeyImpl<>(table, fields);
return new UniqueKeyImpl<>(table, fields, true);
}
/**
@ -110,7 +110,7 @@ public final class Internal {
@SafeVarargs
public static final <R extends Record> UniqueKey<R> createUniqueKey(Table<R> table, String name, TableField<R, ?>... fields) {
return new UniqueKeyImpl<>(table, name, fields);
return new UniqueKeyImpl<>(table, name, fields, true);
}
/**
@ -130,7 +130,7 @@ public final class Internal {
@SafeVarargs
public static final <R extends Record, U extends Record> ForeignKey<R, U> createForeignKey(UniqueKey<U> key, Table<R> table, String name, TableField<R, ?>... fields) {
ForeignKey<R, U> result = new ReferenceImpl<>(key, table, name, fields);
ForeignKey<R, U> result = new ReferenceImpl<>(key, table, name, fields, true);
if (key instanceof UniqueKeyImpl)
((UniqueKeyImpl<U>) key).references.add(result);
@ -167,7 +167,7 @@ public final class Internal {
* Factory method for check constraints.
*/
public static final <R extends Record> Check<R> createCheck(Table<R> table, Name name, String condition) {
return new CheckImpl<>(table, name, DSL.condition(condition));
return new CheckImpl<>(table, name, DSL.condition(condition), true);
}
/**

View File

@ -120,6 +120,7 @@ final class Keywords {
static final Keyword K_DELETE = keyword("delete");
static final Keyword K_DELETE_WHERE = keyword("delete where");
static final Keyword K_DENSE_RANK = keyword("dense_rank");
static final Keyword K_DISABLE = keyword("disable");
static final Keyword K_DISTINCT = keyword("distinct");
static final Keyword K_DISTINCT_ON = keyword("distinct on");
static final Keyword K_DO = keyword("do");
@ -137,11 +138,13 @@ final class Keywords {
static final Keyword K_ELSE = keyword("else");
static final Keyword K_ELSEIF = keyword("elseif");
static final Keyword K_ELSIF = keyword("elsif");
static final Keyword K_ENABLE = keyword("enable");
static final Keyword K_END = keyword("end");
static final Keyword K_END_CATCH = keyword("end catch");
static final Keyword K_END_IF = keyword("end if");
static final Keyword K_END_LOOP = keyword("end loop");
static final Keyword K_END_TRY = keyword("end try");
static final Keyword K_ENFORCED = keyword("enforced");
static final Keyword K_ENUM = keyword("enum");
static final Keyword K_ESCAPE = keyword("escape");
static final Keyword K_EXCEPT = keyword("except");

View File

@ -654,7 +654,7 @@ final class MetaImpl extends AbstractMeta {
fkFields[i] = (TableField<Record, ?>) field(record.get(7, String.class));
}
references.add(new ReferenceImpl<>(new MetaPrimaryKey(pkTable, pkName, pkFields), this, fkName, fkFields));
references.add(new ReferenceImpl<>(new MetaPrimaryKey(pkTable, pkName, pkFields), this, fkName, fkFields, true));
}
return references;
@ -867,6 +867,11 @@ final class MetaImpl extends AbstractMeta {
return true;
}
@Override
public final boolean enforced() {
return true;
}
@Override
@SuppressWarnings("unchecked")
public final List<ForeignKey<?, Record>> getReferences() {
@ -923,7 +928,7 @@ final class MetaImpl extends AbstractMeta {
for (int i = 0; i < value.size(); i++)
fkFields[i] = (TableField<Record, ?>) fkTable.field(value.get(i).get(7, String.class));
references.add(new ReferenceImpl<>(this, fkTable, fkName, fkFields));
references.add(new ReferenceImpl<>(this, fkTable, fkName, fkFields, true));
}
return references;

View File

@ -361,6 +361,7 @@ import org.jooq.Comparator;
import org.jooq.Condition;
import org.jooq.Configuration;
import org.jooq.Constraint;
import org.jooq.ConstraintEnforcementStep;
import org.jooq.ConstraintForeignKeyOnStep;
import org.jooq.ConstraintTypeStep;
import org.jooq.CreateIndexFinalStep;
@ -3610,9 +3611,9 @@ final class ParserImpl implements Parser {
if (!parseKeywordIf(ctx, "CLUSTERED"))
parseKeywordIf(ctx, "NONCLUSTERED");
constraints.add(inlineConstraint == null
constraints.add(parseConstraintEnforcementIf(ctx, inlineConstraint == null
? primaryKey(fieldName)
: inlineConstraint.primaryKey(fieldName));
: inlineConstraint.primaryKey(fieldName)));
primary = true;
unique = true;
continue;
@ -3621,9 +3622,9 @@ final class ParserImpl implements Parser {
if (!parseKeywordIf(ctx, "KEY"))
parseKeywordIf(ctx, "INDEX");
constraints.add(inlineConstraint == null
constraints.add(parseConstraintEnforcementIf(ctx, inlineConstraint == null
? unique(fieldName)
: inlineConstraint.unique(fieldName));
: inlineConstraint.unique(fieldName)));
unique = true;
continue;
}
@ -3700,35 +3701,36 @@ final class ParserImpl implements Parser {
return Internal.createIndex(name == null ? NO_NAME : name, table, fields, false);
}
private static final boolean parseConstraintStateIf(ParserContext ctx) {
parseKeywordIf(ctx, "ENABLE");
return true;
private static final Constraint parseConstraintEnforcementIf(ParserContext ctx, ConstraintEnforcementStep e) {
if ((parseKeywordIf(ctx, "ENABLE") || parseKeywordIf(ctx, "ENFORCED")) && ctx.requireProEdition())
return e.enforced();
else if ((parseKeywordIf(ctx, "DISABLE") || parseKeywordIf(ctx, "NOT ENFORCED")) && ctx.requireProEdition())
return e.notEnforced();
else return e;
}
private static final Constraint parsePrimaryKeySpecification(ParserContext ctx, ConstraintTypeStep constraint) {
parseUsingBtreeOrHashIf(ctx);
Field<?>[] fieldNames = parseKeyColumnList(ctx);
Constraint e = constraint == null
ConstraintEnforcementStep e = constraint == null
? primaryKey(fieldNames)
: constraint.primaryKey(fieldNames);
parseUsingBtreeOrHashIf(ctx);
parseConstraintStateIf(ctx);
return e;
return parseConstraintEnforcementIf(ctx, e);
}
private static final Constraint parseUniqueSpecification(ParserContext ctx, ConstraintTypeStep constraint) {
parseUsingBtreeOrHashIf(ctx);
Field<?>[] fieldNames = parseKeyColumnList(ctx);
Constraint e = constraint == null
ConstraintEnforcementStep e = constraint == null
? unique(fieldNames)
: constraint.unique(fieldNames);
parseUsingBtreeOrHashIf(ctx);
parseConstraintStateIf(ctx);
return e;
return parseConstraintEnforcementIf(ctx, e);
}
private static Field<?>[] parseKeyColumnList(ParserContext ctx) {
@ -3754,12 +3756,11 @@ final class ParserImpl implements Parser {
Condition condition = parseCondition(ctx);
parse(ctx, ')');
Constraint e = constraint == null
ConstraintEnforcementStep e = constraint == null
? check(condition)
: constraint.check(condition);
parseConstraintStateIf(ctx);
return e;
return parseConstraintEnforcementIf(ctx, e);
}
private static final Constraint parseForeignKeySpecification(ParserContext ctx, ConstraintTypeStep constraint) {
@ -3831,8 +3832,7 @@ final class ParserImpl implements Parser {
throw ctx.expected("DELETE", "UPDATE");
}
parseConstraintStateIf(ctx);
return e;
return parseConstraintEnforcementIf(ctx, e);
}
private static final Set<String> ALTER_KEYWORDS = new HashSet<>(Arrays.asList("ADD", "ALTER", "COMMENT", "DROP", "MODIFY", "RENAME"));
@ -3869,8 +3869,11 @@ final class ParserImpl implements Parser {
case 'A':
if (parseKeywordIf(ctx, "ADD"))
return parseAlterTableAdd(ctx, s1, tableName);
else if (parseKeywordIf(ctx, "ALTER") && (parseKeywordIf(ctx, "COLUMN") || true))
return parseAlterTableAlterColumn(ctx, s1);
else if (parseKeywordIf(ctx, "ALTER"))
if (parseKeywordIf(ctx, "CONSTRAINT"))
return parseAlterTableAlterConstraint(ctx, s1);
else if ((parseKeywordIf(ctx, "COLUMN") || true))
return parseAlterTableAlterColumn(ctx, s1);
break;
@ -3944,8 +3947,11 @@ final class ParserImpl implements Parser {
case 'm':
case 'M':
if (parseKeywordIf(ctx, "MODIFY") && (parseKeywordIf(ctx, "COLUMN") || true))
return parseAlterTableAlterColumn(ctx, s1);
if (parseKeywordIf(ctx, "MODIFY"))
if (parseKeywordIf(ctx, "CONSTRAINT"))
return parseAlterTableAlterConstraint(ctx, s1);
else if ((parseKeywordIf(ctx, "COLUMN") || true))
return parseAlterTableAlterColumn(ctx, s1);
break;
@ -4139,6 +4145,21 @@ final class ParserImpl implements Parser {
return s1.alter(field).set(type);
}
private static final DDLQuery parseAlterTableAlterConstraint(ParserContext ctx, AlterTableStep s1) {
ctx.requireProEdition();
throw ctx.expected("ENABLE", "ENFORCED", "DISABLE", "NOT ENFORCED");
}
private static final DDLQuery parseAlterType(ParserContext ctx) {
AlterTypeStep s1 = ctx.dsl.alterType(parseName(ctx));

View File

@ -70,11 +70,8 @@ final class ReferenceImpl<R extends Record, O extends Record> extends AbstractKe
private final UniqueKey<O> key;
@SafeVarargs
ReferenceImpl(UniqueKey<O> key, Table<R> table, String name, TableField<R, ?>... fields) {
super(table, name, fields);
ReferenceImpl(UniqueKey<O> key, Table<R> table, String name, TableField<R, ?>[] fields, boolean enforced) {
super(table, name, fields, enforced);
this.key = key;
}

View File

@ -60,18 +60,12 @@ final class UniqueKeyImpl<R extends Record> extends AbstractKey<R> implements Un
final List<ForeignKey<?, R>> references;
@SafeVarargs
UniqueKeyImpl(Table<R> table, TableField<R, ?>... fields) {
this(table, null, fields);
UniqueKeyImpl(Table<R> table, TableField<R, ?>[] fields, boolean enforced) {
this(table, null, fields, enforced);
}
@SafeVarargs
UniqueKeyImpl(Table<R> table, String name, TableField<R, ?>... fields) {
super(table, name, fields);
UniqueKeyImpl(Table<R> table, String name, TableField<R, ?>[] fields, boolean enforced) {
super(table, name, fields, enforced);
this.references = new ArrayList<>();
}