Skip to content

Commit

Permalink
[#6473] Add DataType.nullable(Nullability) to support a three valued …
Browse files Browse the repository at this point in the history
…nullable flag
  • Loading branch information
lukaseder committed Jul 31, 2017
1 parent 2ca698a commit 2a2774d
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 24 deletions.
24 changes: 24 additions & 0 deletions jOOQ/src/main/java/org/jooq/DataType.java
Expand Up @@ -194,13 +194,37 @@ public interface DataType<T> extends Serializable {
* <p>
* [#5709] A <code>nullable</code> column cannot have an {@link #identity()}.
*
* @param nullability The new nullability
* @return The new data type
*/
DataType<T> nullability(Nullability nullability);

/**
* Get the nullability of this data type.
*
* @return The nullability
*/
Nullability nullability();

/**
* Return a new data type like this, with a new nullability.
* <p>
* This is the same as calling {@link #nullability(Nullability)} with any of
* {@link Nullability#NULL} or {@link Nullability#NOT_NULL} as an argument.
* <p>
* [#5709] A <code>nullable</code> column cannot have an
* {@link #identity()}.
*
* @param nullable The new nullability
* @return The new data type
*/
DataType<T> nullable(boolean nullable);

/**
* Get the nullability of this data type.
* <p>
* This returns <code>true</code> by default, i.e. if {@link #nullability()}
* is {@link Nullability#DEFAULT}.
*
* @return The nullability
*/
Expand Down
82 changes: 82 additions & 0 deletions jOOQ/src/main/java/org/jooq/Nullability.java
@@ -0,0 +1,82 @@
/*
* 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;

/**
* An enum that specifies the nullability of a {@link DataType}.
*
* @author Lukas Eder
*/
public enum Nullability {

/**
* The data type is explicitly nullable.
*/
NULL,

/**
* The data type is explicitly not nullable.
*/
NOT_NULL,

/**
* Default behaviour for data types.
* <p>
* The interpretation of this value depends on the context in which a
* {@link DataType} is used:
* <ul>
* <li><code>CREATE TABLE</code>: The data type is implicitly nullable (or
* explicitly, if the underlying database does not support implicit
* nullability or defaults to implicit non-nullability).</li>
* <li><code>ALTER TABLE .. ALTER COLUMN .. SET TYPE</code>: The data type's
* nullability will not be modified.</li>
* </ul>
*/
DEFAULT;

/**
* Get the explicit {@link Nullability} corresponding to a boolean value.
*/
public static Nullability of(boolean nullability) {
return nullability ? NULL : NOT_NULL;
}

/**
* Whether this nullability encodes an explicitly or implicitly nullable type.
*/
public boolean nullable() {
return this != NOT_NULL;
}
}
60 changes: 36 additions & 24 deletions jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java
Expand Up @@ -35,6 +35,7 @@
package org.jooq.impl;

import static java.util.Collections.unmodifiableCollection;
import static org.jooq.Nullability.NOT_NULL;
import static org.jooq.impl.SQLDataType.BLOB;
import static org.jooq.impl.SQLDataType.CLOB;
import static org.jooq.impl.SQLDataType.NCLOB;
Expand Down Expand Up @@ -62,6 +63,7 @@
import org.jooq.DataType;
import org.jooq.EnumType;
import org.jooq.Field;
import org.jooq.Nullability;
import org.jooq.Result;
import org.jooq.SQLDialect;
import org.jooq.UDTRecord;
Expand Down Expand Up @@ -204,7 +206,7 @@ public class DefaultDataType<T> implements DataType<T> {
*/
private final String typeName;

private final boolean nullable;
private final Nullability nullability;
private final boolean identity;
private final Field<T> defaultValue;
private final int precision;
Expand Down Expand Up @@ -232,38 +234,38 @@ public class DefaultDataType<T> implements DataType<T> {
}

public DefaultDataType(SQLDialect dialect, DataType<T> sqlDataType, String typeName) {
this(dialect, sqlDataType, sqlDataType.getType(), typeName, typeName, sqlDataType.precision(), sqlDataType.scale(), sqlDataType.length(), sqlDataType.nullable(), sqlDataType.defaultValue());
this(dialect, sqlDataType, sqlDataType.getType(), typeName, typeName, sqlDataType.precision(), sqlDataType.scale(), sqlDataType.length(), sqlDataType.nullability(), sqlDataType.defaultValue());
}

public DefaultDataType(SQLDialect dialect, DataType<T> sqlDataType, String typeName, String castTypeName) {
this(dialect, sqlDataType, sqlDataType.getType(), typeName, castTypeName, sqlDataType.precision(), sqlDataType.scale(), sqlDataType.length(), sqlDataType.nullable(), sqlDataType.defaultValue());
this(dialect, sqlDataType, sqlDataType.getType(), typeName, castTypeName, sqlDataType.precision(), sqlDataType.scale(), sqlDataType.length(), sqlDataType.nullability(), sqlDataType.defaultValue());
}

public DefaultDataType(SQLDialect dialect, Class<T> type, String typeName) {
this(dialect, null, type, typeName, typeName, 0, 0, 0, true, null);
this(dialect, null, type, typeName, typeName, 0, 0, 0, Nullability.DEFAULT, null);
}

public DefaultDataType(SQLDialect dialect, Class<T> type, String typeName, String castTypeName) {
this(dialect, null, type, typeName, castTypeName, 0, 0, 0, true, null);
this(dialect, null, type, typeName, castTypeName, 0, 0, 0, Nullability.DEFAULT, null);
}

DefaultDataType(SQLDialect dialect, Class<T> type, String typeName, String castTypeName, int precision, int scale, int length, boolean nullable, Field<T> defaultValue) {
this(dialect, null, type, typeName, castTypeName, precision, scale, length, nullable, defaultValue);
DefaultDataType(SQLDialect dialect, Class<T> type, String typeName, String castTypeName, int precision, int scale, int length, Nullability nullability, Field<T> defaultValue) {
this(dialect, null, type, typeName, castTypeName, precision, scale, length, nullability, defaultValue);
}

DefaultDataType(SQLDialect dialect, Class<T> type, Binding<?, T> binding, String typeName, String castTypeName, int precision, int scale, int length, boolean nullable, Field<T> defaultValue) {
this(dialect, null, type, binding, typeName, castTypeName, precision, scale, length, nullable, defaultValue);
DefaultDataType(SQLDialect dialect, Class<T> type, Binding<?, T> binding, String typeName, String castTypeName, int precision, int scale, int length, Nullability nullability, Field<T> defaultValue) {
this(dialect, null, type, binding, typeName, castTypeName, precision, scale, length, nullability, defaultValue);
}

DefaultDataType(SQLDialect dialect, DataType<T> sqlDataType, Class<T> type, String typeName, String castTypeName, int precision, int scale, int length, boolean nullable, Field<T> defaultValue) {
this(dialect, sqlDataType, type, null, typeName, castTypeName, precision, scale, length, nullable, defaultValue);
DefaultDataType(SQLDialect dialect, DataType<T> sqlDataType, Class<T> type, String typeName, String castTypeName, int precision, int scale, int length, Nullability nullability, Field<T> defaultValue) {
this(dialect, sqlDataType, type, null, typeName, castTypeName, precision, scale, length, nullability, defaultValue);
}

DefaultDataType(SQLDialect dialect, DataType<T> sqlDataType, Class<T> type, Binding<?, T> binding, String typeName, String castTypeName, int precision, int scale, int length, boolean nullable, Field<T> defaultValue) {
this(dialect, sqlDataType, type, binding, typeName, castTypeName, precision, scale, length, nullable, false, defaultValue);
DefaultDataType(SQLDialect dialect, DataType<T> sqlDataType, Class<T> type, Binding<?, T> binding, String typeName, String castTypeName, int precision, int scale, int length, Nullability nullability, Field<T> defaultValue) {
this(dialect, sqlDataType, type, binding, typeName, castTypeName, precision, scale, length, nullability, false, defaultValue);
}

DefaultDataType(SQLDialect dialect, DataType<T> sqlDataType, Class<T> type, Binding<?, T> binding, String typeName, String castTypeName, int precision, int scale, int length, boolean nullable, boolean identity, Field<T> defaultValue) {
DefaultDataType(SQLDialect dialect, DataType<T> sqlDataType, Class<T> type, Binding<?, T> binding, String typeName, String castTypeName, int precision, int scale, int length, Nullability nullability, boolean identity, Field<T> defaultValue) {

// Initialise final instance members
// ---------------------------------
Expand All @@ -278,7 +280,7 @@ public DefaultDataType(SQLDialect dialect, Class<T> type, String typeName, Strin
this.castTypeBase = TYPE_NAME_PATTERN.matcher(castTypeName).replaceAll("").trim();
this.arrayType = (Class<T[]>) Array.newInstance(type, 0).getClass();

this.nullable = nullable;
this.nullability = nullability;
this.identity = identity;
this.defaultValue = defaultValue;
this.precision = precision0(type, precision);
Expand Down Expand Up @@ -324,7 +326,7 @@ public DefaultDataType(SQLDialect dialect, Class<T> type, String typeName, Strin
/**
* [#3225] Performant constructor for creating derived types.
*/
private DefaultDataType(DefaultDataType<T> t, int precision, int scale, int length, boolean nullable, boolean identity, Field<T> defaultValue) {
private DefaultDataType(DefaultDataType<T> t, int precision, int scale, int length, Nullability nullability, boolean identity, Field<T> defaultValue) {
this.dialect = t.dialect;
this.sqlDataType = t.sqlDataType;
this.uType = t.uType;
Expand All @@ -334,7 +336,7 @@ private DefaultDataType(DefaultDataType<T> t, int precision, int scale, int leng
this.castTypeBase = t.castTypeBase;
this.arrayType = t.arrayType;

this.nullable = nullable;
this.nullability = nullability;
this.identity = identity;
this.defaultValue = defaultValue;
this.precision = precision0(uType, precision);
Expand Down Expand Up @@ -363,19 +365,29 @@ else if (type == Byte.class || type == UByte.class) {
return precision;
}

@Override
public final DataType<T> nullability(Nullability n) {
return new DefaultDataType<T>(this, precision, scale, length, n, n.nullable() ? false : identity, defaultValue);
}

@Override
public final Nullability nullability() {
return nullability;
}

@Override
public final DataType<T> nullable(boolean n) {
return new DefaultDataType<T>(this, precision, scale, length, n, n ? false : identity, defaultValue);
return nullability(Nullability.of(n));
}

@Override
public final boolean nullable() {
return nullable;
return nullability.nullable();
}

@Override
public final DataType<T> identity(boolean i) {
return new DefaultDataType<T>(this, precision, scale, length, i ? false : nullable, i, i ? null : defaultValue);
return new DefaultDataType<T>(this, precision, scale, length, i ? NOT_NULL : nullability, i, i ? null : defaultValue);
}

@Override
Expand All @@ -390,7 +402,7 @@ public final DataType<T> defaultValue(T d) {

@Override
public final DataType<T> defaultValue(Field<T> d) {
return new DefaultDataType<T>(this, precision, scale, length, nullable, d != null ? false : identity, d);
return new DefaultDataType<T>(this, precision, scale, length, nullability, d != null ? false : identity, d);
}

@Override
Expand Down Expand Up @@ -423,7 +435,7 @@ public final DataType<T> precision(int p, int s) {
else if (isLob())
return this;
else
return new DefaultDataType<T>(this, p, s, length, nullable, identity, defaultValue);
return new DefaultDataType<T>(this, p, s, length, nullability, identity, defaultValue);
}

@Override
Expand All @@ -445,7 +457,7 @@ public final DataType<T> scale(int s) {
if (isLob())
return this;
else
return new DefaultDataType<T>(this, precision, s, length, nullable, identity, defaultValue);
return new DefaultDataType<T>(this, precision, s, length, nullability, identity, defaultValue);
}

@Override
Expand All @@ -467,7 +479,7 @@ public final DataType<T> length(int l) {
if (isLob())
return this;
else
return new DefaultDataType<T>(this, precision, scale, l, nullable, identity, defaultValue);
return new DefaultDataType<T>(this, precision, scale, l, nullability, identity, defaultValue);
}

@Override
Expand Down

0 comments on commit 2a2774d

Please sign in to comment.