[jOOQ/jOOQ#9061] Wrong data types in meta lookups for expressions
When unqualified column names are part of expressions (e.g. ID + 1) then the data type information is lost on both the column reference and the whole expression.
This commit is contained in:
parent
77a3943a65
commit
78f7c67f67
711
jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java
Normal file
711
jOOQ/src/main/java/org/jooq/impl/AbstractDataType.java
Normal file
@ -0,0 +1,711 @@
|
||||
/*
|
||||
* 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.impl;
|
||||
|
||||
import static org.jooq.Nullability.NOT_NULL;
|
||||
import static org.jooq.impl.DSL.unquotedName;
|
||||
import static org.jooq.impl.SQLDataType.BLOB;
|
||||
import static org.jooq.impl.SQLDataType.CLOB;
|
||||
import static org.jooq.impl.SQLDataType.NCLOB;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.Blob;
|
||||
import java.sql.Clob;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
// ...
|
||||
import org.jooq.Binding;
|
||||
import org.jooq.CharacterSet;
|
||||
import org.jooq.Collation;
|
||||
import org.jooq.Comment;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.Converter;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.Domain;
|
||||
import org.jooq.EnumType;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.JSON;
|
||||
import org.jooq.JSONB;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.Nullability;
|
||||
// ...
|
||||
import org.jooq.Result;
|
||||
import org.jooq.UDTRecord;
|
||||
import org.jooq.XML;
|
||||
import org.jooq.tools.Convert;
|
||||
import org.jooq.types.Interval;
|
||||
import org.jooq.types.UNumber;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked", "deprecation" })
|
||||
abstract class AbstractDataType<T> extends AbstractNamed implements DataType<T> {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
*/
|
||||
private static final long serialVersionUID = 4155588654449505119L;
|
||||
|
||||
AbstractDataType(Name name, Comment comment) {
|
||||
super(name, comment);
|
||||
}
|
||||
|
||||
/**
|
||||
* [#7811] Allow for subtypes to override the constructor
|
||||
*/
|
||||
abstract AbstractDataType<T> construct(
|
||||
Integer newPrecision,
|
||||
Integer newScale,
|
||||
Integer newLength,
|
||||
Nullability newNullability,
|
||||
Collation newCollation,
|
||||
CharacterSet newCharacterSet,
|
||||
boolean newIdentity,
|
||||
Field<T> newDefaultValue
|
||||
);
|
||||
|
||||
@Override
|
||||
public final DataType<T> nullability(Nullability n) {
|
||||
return construct(precision0(), scale0(), length0(), n, collation(), characterSet(), n.nullable() ? false : identity(), defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> nullable(boolean n) {
|
||||
return nullability(Nullability.of(n));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean nullable() {
|
||||
return nullability().nullable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> collation(Collation c) {
|
||||
return construct(precision0(), scale0(), length0(), nullability(), c, characterSet(), identity(), defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> characterSet(CharacterSet c) {
|
||||
return construct(precision0(), scale0(), length0(), nullability(), collation(), c, identity(), defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> identity(boolean i) {
|
||||
return construct(precision0(), scale0(), length0(), i ? NOT_NULL : nullability(), collation(), characterSet(), i, i ? null : defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> defaultValue(T d) {
|
||||
return default_(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> defaultValue(Field<T> d) {
|
||||
return default_(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> defaultValue() {
|
||||
return default_();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> default_(T d) {
|
||||
return default_(Tools.field(d, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> default_(Field<T> d) {
|
||||
return construct(precision0(), scale0(), length0(), nullability(), collation(), characterSet(), d != null ? false : identity(), d);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final DataType<T> defaulted(boolean d) {
|
||||
return defaultValue(d ? Tools.field(null, this) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean defaulted() {
|
||||
return defaultValue() != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int precision() {
|
||||
Integer precision = precision0();
|
||||
return precision == null ? 0 : precision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> precision(int p) {
|
||||
return precision0(p, scale());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> precision(int p, int s) {
|
||||
return precision0(p, s);
|
||||
}
|
||||
|
||||
final AbstractDataType<T> precision0(Integer p, Integer s) {
|
||||
if (eq(precision(), p) && eq(scale(), s))
|
||||
return this;
|
||||
|
||||
// [#4120] LOB types are not allowed to have precision
|
||||
else if (isLob())
|
||||
return this;
|
||||
else
|
||||
return construct(p, s, length0(), nullability(), collation(), characterSet(), identity(), defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasPrecision() {
|
||||
Class<?> tType = tType0();
|
||||
|
||||
return tType == BigInteger.class
|
||||
|| tType == BigDecimal.class
|
||||
|| tType == Timestamp.class
|
||||
|| tType == Time.class
|
||||
|
||||
|| tType == LocalDateTime.class
|
||||
|| tType == LocalTime.class
|
||||
|| tType == OffsetDateTime.class
|
||||
|| tType == OffsetTime.class
|
||||
|| tType == Instant.class
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean precisionDefined() {
|
||||
return precision0() != null && hasPrecision();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int scale() {
|
||||
Integer scale = scale0();
|
||||
return scale == null ? 0 : scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> scale(int s) {
|
||||
return scale0(s);
|
||||
}
|
||||
|
||||
final AbstractDataType<T> scale0(Integer s) {
|
||||
if (eq(scale(), s))
|
||||
return this;
|
||||
|
||||
// [#4120] LOB types are not allowed to have scale
|
||||
if (isLob())
|
||||
return this;
|
||||
else
|
||||
return construct(precision0(), s, length0(), nullability(), collation(), characterSet(), identity(), defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasScale() {
|
||||
return tType0() == BigDecimal.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean scaleDefined() {
|
||||
return scale0() != null && hasScale();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> length(int l) {
|
||||
return length0(l);
|
||||
}
|
||||
|
||||
final AbstractDataType<T> length0(Integer l) {
|
||||
if (eq(length0(), l))
|
||||
return this;
|
||||
|
||||
// [#4120] LOB types are not allowed to have length
|
||||
if (isLob())
|
||||
return this;
|
||||
else
|
||||
return construct(precision0(), scale0(), l, nullability(), collation(), characterSet(), identity(), defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int length() {
|
||||
Integer length = length0();
|
||||
return length == null ? 0 : length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasLength() {
|
||||
Class<?> tType = tType0();
|
||||
return (tType == byte[].class || tType == String.class) && !isLob();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean lengthDefined() {
|
||||
return length0() != null && hasLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* final */ int getSQLType() {
|
||||
return getSQLType(DSL.using(getDialect()).configuration());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getSQLType(Configuration configuration) {
|
||||
// TODO [#1227] There is some confusion with these types, especially
|
||||
// when it comes to byte[] which can be mapped to BLOB, BINARY, VARBINARY
|
||||
Class<?> tType = tType0();
|
||||
|
||||
if (tType == Blob.class)
|
||||
return Types.BLOB;
|
||||
else if (tType == Boolean.class)
|
||||
return Types.BOOLEAN;
|
||||
else if (tType == BigInteger.class)
|
||||
return Types.BIGINT;
|
||||
else if (tType == BigDecimal.class)
|
||||
return Types.DECIMAL;
|
||||
else if (tType == Byte.class)
|
||||
return Types.TINYINT;
|
||||
else if (tType == byte[].class)
|
||||
return Types.BLOB;
|
||||
else if (tType == Clob.class)
|
||||
return Types.CLOB;
|
||||
else if (Tools.isDate(tType)) {
|
||||
switch (configuration.family()) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
default:
|
||||
return Types.DATE;
|
||||
}
|
||||
}
|
||||
else if (tType == Double.class)
|
||||
return Types.DOUBLE;
|
||||
else if (tType == Float.class)
|
||||
return Types.FLOAT;
|
||||
else if (tType == Integer.class)
|
||||
return Types.INTEGER;
|
||||
else if (tType == Long.class)
|
||||
return Types.BIGINT;
|
||||
else if (tType == Short.class)
|
||||
return Types.SMALLINT;
|
||||
else if (tType == String.class)
|
||||
return Types.VARCHAR;
|
||||
else if (Tools.isTime(tType))
|
||||
return Types.TIME;
|
||||
else if (Tools.isTimestamp(tType))
|
||||
return Types.TIMESTAMP;
|
||||
|
||||
|
||||
// [#5779] Few JDBC drivers support the JDBC 4.2 TIME[STAMP]_WITH_TIMEZONE types.
|
||||
else if (tType == OffsetTime.class)
|
||||
return Types.VARCHAR;
|
||||
else if (tType == OffsetDateTime.class)
|
||||
return Types.VARCHAR;
|
||||
else if (tType == Instant.class)
|
||||
return Types.VARCHAR;
|
||||
|
||||
|
||||
// The type byte[] is handled earlier.
|
||||
else if (tType.isArray())
|
||||
return Types.ARRAY;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
else if (EnumType.class.isAssignableFrom(tType))
|
||||
return Types.VARCHAR;
|
||||
else if (UDTRecord.class.isAssignableFrom(tType))
|
||||
return Types.STRUCT;
|
||||
else if (Result.class.isAssignableFrom(tType)) {
|
||||
switch (configuration.family()) {
|
||||
|
||||
|
||||
|
||||
case H2:
|
||||
return -10; // OracleTypes.CURSOR;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
case POSTGRES:
|
||||
default:
|
||||
return Types.OTHER;
|
||||
}
|
||||
}
|
||||
else
|
||||
return Types.OTHER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ Domain<T> getDomain() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Converter<?, T> getConverter() {
|
||||
return getBinding().converter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getTypeName() {
|
||||
return typeName0();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getCastTypeName() {
|
||||
|
||||
// [#9958] We should be able to avoid checking for x > 0, but there may
|
||||
// be a lot of data types constructed with a 0 value instead of
|
||||
// a null value, historically, so removing this check would
|
||||
// introduce a lot of regressions!
|
||||
if (lengthDefined() && length() > 0)
|
||||
return castTypeBase0() + "(" + length() + ")";
|
||||
else if (precisionDefined() && precision() > 0)
|
||||
if (scaleDefined() && scale() > 0)
|
||||
return castTypeBase0() + "(" + precision() + ", " + scale() + ")";
|
||||
else
|
||||
return castTypeBase0() + "(" + precision() + ")";
|
||||
else
|
||||
return castTypeName0();
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ String getTypeName(Configuration configuration) {
|
||||
return getDataType(configuration).getTypeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ String getCastTypeName(Configuration configuration) {
|
||||
return getDataType(configuration).getCastTypeName();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public final Class<T[]> getArrayType() {
|
||||
return (Class<T[]>) Array.newInstance(getType(), 0).getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T[]> getArrayDataType() {
|
||||
return new ArrayDataType<>(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ Class<?> getArrayComponentType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ DataType<?> getArrayComponentDataType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final <E extends EnumType> DataType<E> asEnumDataType(Class<E> enumDataType) {
|
||||
// TODO: Make EnumTypes implement Named
|
||||
String enumTypeName = Tools.enums(enumDataType)[0].getName();
|
||||
return new DefaultDataType<>(getDialect(), (DataType<E>) null, enumDataType, unquotedName(enumTypeName), enumTypeName, enumTypeName, precision0(), scale0(), length0(), nullability(), (Field) defaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ <U> DataType<U> asConvertedDataType(Converter<? super T, U> converter) {
|
||||
return asConvertedDataType(DefaultBinding.newBinding(converter, this, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ <U> DataType<U> asConvertedDataType(Binding<? super T, U> newBinding) {
|
||||
if (getBinding() == newBinding)
|
||||
return (DataType<U>) this;
|
||||
|
||||
if (newBinding == null)
|
||||
newBinding = (Binding<? super T, U>) DefaultBinding.binding(getType(), isLob());
|
||||
|
||||
return new ConvertedDataType<>(this, newBinding);
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* final */ T convert(Object object) {
|
||||
|
||||
// [#1441] Avoid unneeded type conversions to improve performance
|
||||
if (object == null)
|
||||
return null;
|
||||
else if (object.getClass() == getType())
|
||||
return (T) object;
|
||||
else
|
||||
return Convert.convert(object, getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final T[] convert(Object... objects) {
|
||||
return (T[]) Convert.convertArray(objects, getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<T> convert(Collection<?> objects) {
|
||||
return Convert.convert(objects, getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isNumeric() {
|
||||
return Number.class.isAssignableFrom(tType0()) && !isInterval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isInteger() {
|
||||
Class<?> tType = tType0();
|
||||
return UNumber.class.isAssignableFrom(tType)
|
||||
|| Byte.class == tType
|
||||
|| Short.class == tType
|
||||
|| Integer.class == tType
|
||||
|| Long.class == tType
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isString() {
|
||||
return tType0() == String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isDateTime() {
|
||||
Class<?> tType = tType0();
|
||||
return java.util.Date.class.isAssignableFrom(tType)
|
||||
|
||||
|| java.time.temporal.Temporal.class.isAssignableFrom(tType)
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isDate() {
|
||||
Class<?> tType = tType0();
|
||||
return java.sql.Date.class.isAssignableFrom(tType)
|
||||
|
||||
|| java.time.LocalDate.class.isAssignableFrom(tType)
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isTimestamp() {
|
||||
Class<?> tType = tType0();
|
||||
return java.sql.Timestamp.class.isAssignableFrom(tType)
|
||||
|
||||
|| java.time.LocalDateTime.class.isAssignableFrom(tType)
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isTime() {
|
||||
Class<?> tType = tType0();
|
||||
return java.sql.Time.class.isAssignableFrom(tType)
|
||||
|
||||
|| java.time.LocalTime.class.isAssignableFrom(tType)
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isTemporal() {
|
||||
return isDateTime() || isInterval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isInterval() {
|
||||
return Interval.class.isAssignableFrom(tType0());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isLob() {
|
||||
DataType<T> t = getSQLDataType();
|
||||
|
||||
if (t == this)
|
||||
return getTypeName().endsWith("lob");
|
||||
else
|
||||
return (t == BLOB || t == CLOB || t == NCLOB);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isBinary() {
|
||||
return tType0() == byte[].class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isArray() {
|
||||
Class<?> tType = tType0();
|
||||
return
|
||||
(!isBinary() && tType.isArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isUDT() {
|
||||
return UDTRecord.class.isAssignableFrom(tType0());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isEnum() {
|
||||
return EnumType.class.isAssignableFrom(tType0());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isJSON() {
|
||||
Class<?> tType = tType0();
|
||||
return tType == JSON.class || tType == JSONB.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isXML() {
|
||||
return tType0() == XML.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void accept(Context<?> ctx) {
|
||||
ctx.visit(getQualifiedName());
|
||||
}
|
||||
|
||||
private static final boolean eq(Integer i1, Integer i2) {
|
||||
return (i1 == i2) || (i1 != null && i2 != null && i1.intValue() == i2.intValue());
|
||||
}
|
||||
|
||||
abstract String typeName0();
|
||||
abstract String castTypeBase0();
|
||||
abstract String castTypeName0();
|
||||
abstract Class<?> tType0();
|
||||
abstract Integer precision0();
|
||||
abstract Integer scale0();
|
||||
abstract Integer length0();
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The Object API
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getCastTypeName() + " (" + getType().getName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((getDialect() == null) ? 0 : getDialect().hashCode());
|
||||
result = prime * result + length();
|
||||
result = prime * result + precision();
|
||||
result = prime * result + scale();
|
||||
result = prime * result + ((getType() == null) ? 0 : getType().hashCode());
|
||||
result = prime * result + ((tType0() == null) ? 0 : tType0().hashCode());
|
||||
result = prime * result + ((typeName0() == null) ? 0 : typeName0().hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (!(obj instanceof AbstractDataType))
|
||||
return false;
|
||||
AbstractDataType<?> other = (AbstractDataType<?>) obj;
|
||||
if (getDialect() != other.getDialect())
|
||||
return false;
|
||||
if (!eq(length0(), other.length0()))
|
||||
return false;
|
||||
if (!eq(precision0(), other.precision0()))
|
||||
return false;
|
||||
if (!eq(scale0(), other.scale0()))
|
||||
return false;
|
||||
if (getType() == null) {
|
||||
if (other.getType() != null)
|
||||
return false;
|
||||
}
|
||||
else if (!getType().equals(other.getType()))
|
||||
return false;
|
||||
if (tType0() == null) {
|
||||
if (other.tType0() != null)
|
||||
return false;
|
||||
}
|
||||
else if (!tType0().equals(other.tType0()))
|
||||
return false;
|
||||
if (typeName0() == null) {
|
||||
if (other.typeName0() != null)
|
||||
return false;
|
||||
}
|
||||
else if (!typeName0().equals(other.typeName0()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -66,17 +66,17 @@ abstract class AbstractTypedNamed<T> extends AbstractNamed implements Typed<T> {
|
||||
|
||||
@Override
|
||||
public final Converter<?, T> getConverter() {
|
||||
return type.getConverter();
|
||||
return getDataType().getConverter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Binding<?, T> getBinding() {
|
||||
return type.getBinding();
|
||||
return getDataType().getBinding();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Class<T> getType() {
|
||||
return type.getType();
|
||||
return getDataType().getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -86,6 +86,6 @@ abstract class AbstractTypedNamed<T> extends AbstractNamed implements Typed<T> {
|
||||
|
||||
@Override
|
||||
public final DataType<T> getDataType(Configuration configuration) {
|
||||
return type.getDataType(configuration);
|
||||
return getDataType().getDataType(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ final class ConvertedDataType<T, U> extends DefaultDataType<U> {
|
||||
private final DataType<T> delegate;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ConvertedDataType(DefaultDataType<T> delegate, Binding<? super T, U> binding) {
|
||||
ConvertedDataType(AbstractDataType<T> delegate, Binding<? super T, U> binding) {
|
||||
super(
|
||||
null,
|
||||
binding.converter().toType(),
|
||||
|
||||
@ -38,34 +38,18 @@
|
||||
package org.jooq.impl;
|
||||
|
||||
import static java.util.Collections.unmodifiableCollection;
|
||||
import static org.jooq.Nullability.NOT_NULL;
|
||||
// ...
|
||||
import static org.jooq.SQLDialect.HSQLDB;
|
||||
import static org.jooq.SQLDialect.POSTGRES;
|
||||
import static org.jooq.impl.CommentImpl.NO_COMMENT;
|
||||
import static org.jooq.impl.DSL.unquotedName;
|
||||
import static org.jooq.impl.DefaultBinding.binding;
|
||||
import static org.jooq.impl.SQLDataType.BLOB;
|
||||
import static org.jooq.impl.SQLDataType.CLOB;
|
||||
import static org.jooq.impl.SQLDataType.NCLOB;
|
||||
import static org.jooq.tools.reflect.Reflect.wrapper;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.Blob;
|
||||
import java.sql.Clob;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -74,30 +58,19 @@ import org.jooq.Binding;
|
||||
import org.jooq.CharacterSet;
|
||||
import org.jooq.Collation;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.Context;
|
||||
import org.jooq.Converter;
|
||||
import org.jooq.DataType;
|
||||
import org.jooq.Domain;
|
||||
import org.jooq.EnumType;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.JSON;
|
||||
import org.jooq.JSONB;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.Nullability;
|
||||
// ...
|
||||
import org.jooq.Result;
|
||||
import org.jooq.SQLDialect;
|
||||
import org.jooq.TableRecord;
|
||||
import org.jooq.UDTRecord;
|
||||
import org.jooq.XML;
|
||||
import org.jooq.exception.MappingException;
|
||||
import org.jooq.exception.SQLDialectNotSupportedException;
|
||||
import org.jooq.tools.Convert;
|
||||
import org.jooq.types.Interval;
|
||||
import org.jooq.types.UByte;
|
||||
import org.jooq.types.UInteger;
|
||||
import org.jooq.types.ULong;
|
||||
import org.jooq.types.UNumber;
|
||||
import org.jooq.types.UShort;
|
||||
|
||||
/**
|
||||
@ -111,7 +84,7 @@ import org.jooq.types.UShort;
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
@org.jooq.Internal
|
||||
public class DefaultDataType<T> extends AbstractNamed implements DataType<T> {
|
||||
public class DefaultDataType<T> extends AbstractDataType<T> {
|
||||
|
||||
/**
|
||||
* Generated UID
|
||||
@ -212,11 +185,6 @@ public class DefaultDataType<T> extends AbstractNamed implements DataType<T> {
|
||||
*/
|
||||
private final Binding<?, T> binding;
|
||||
|
||||
/**
|
||||
* The Java class corresponding to arrays of this data type.
|
||||
*/
|
||||
private final Class<T[]> arrayType;
|
||||
|
||||
/**
|
||||
* The type name used for casting to this type.
|
||||
*/
|
||||
@ -322,7 +290,6 @@ public class DefaultDataType<T> extends AbstractNamed implements DataType<T> {
|
||||
this.typeName = typeName;
|
||||
this.castTypeName = castTypeName;
|
||||
this.castTypeBase = TYPE_NAME_PATTERN.matcher(castTypeName).replaceAll("").trim();
|
||||
this.arrayType = (Class<T[]>) Array.newInstance(type, 0).getClass();
|
||||
|
||||
this.nullability = nullability;
|
||||
this.collation = collation;
|
||||
@ -365,6 +332,7 @@ public class DefaultDataType<T> extends AbstractNamed implements DataType<T> {
|
||||
/**
|
||||
* [#7811] Allow for subtypes to override the constructor
|
||||
*/
|
||||
@Override
|
||||
DefaultDataType<T> construct(
|
||||
Integer newPrecision,
|
||||
Integer newScale,
|
||||
@ -401,7 +369,6 @@ public class DefaultDataType<T> extends AbstractNamed implements DataType<T> {
|
||||
this.typeName = t.typeName;
|
||||
this.castTypeName = t.castTypeName;
|
||||
this.castTypeBase = t.castTypeBase;
|
||||
this.arrayType = t.arrayType;
|
||||
|
||||
this.nullability = nullability;
|
||||
this.collation = collation;
|
||||
@ -429,204 +396,44 @@ public class DefaultDataType<T> extends AbstractNamed implements DataType<T> {
|
||||
return precision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> nullability(Nullability n) {
|
||||
return construct(precision, scale, length, n, collation, characterSet, n.nullable() ? false : identity, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Nullability nullability() {
|
||||
return nullability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> nullable(boolean n) {
|
||||
return nullability(Nullability.of(n));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean nullable() {
|
||||
return nullability.nullable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> collation(Collation c) {
|
||||
return construct(precision, scale, length, nullability, c, characterSet, identity, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Collation collation() {
|
||||
return collation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> characterSet(CharacterSet c) {
|
||||
return construct(precision, scale, length, nullability, collation, c, identity, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final CharacterSet characterSet() {
|
||||
return characterSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> identity(boolean i) {
|
||||
return construct(precision, scale, length, i ? NOT_NULL : nullability, collation, characterSet, i, i ? null : defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean identity() {
|
||||
return identity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> defaultValue(T d) {
|
||||
return default_(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> defaultValue(Field<T> d) {
|
||||
return default_(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> defaultValue() {
|
||||
return default_();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> default_(T d) {
|
||||
return default_(Tools.field(d, this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> default_(Field<T> d) {
|
||||
return construct(precision, scale, length, nullability, collation, characterSet, d != null ? false : identity, d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Field<T> default_() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final DataType<T> defaulted(boolean d) {
|
||||
return defaultValue(d ? Tools.field(null, this) : null);
|
||||
final Integer precision0() {
|
||||
return precision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean defaulted() {
|
||||
return defaultValue != null;
|
||||
final Integer scale0() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> precision(int p) {
|
||||
return precision0(p, scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> precision(int p, int s) {
|
||||
return precision0(p, s);
|
||||
}
|
||||
|
||||
private final DefaultDataType<T> precision0(Integer p, Integer s) {
|
||||
if (eq(precision, p) && eq(scale, s))
|
||||
return this;
|
||||
|
||||
// [#4120] LOB types are not allowed to have precision
|
||||
else if (isLob())
|
||||
return this;
|
||||
else
|
||||
return construct(p, s, length, nullability, collation, characterSet, identity, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int precision() {
|
||||
return precision == null ? 0 : precision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasPrecision() {
|
||||
return tType == BigInteger.class
|
||||
|| tType == BigDecimal.class
|
||||
|| tType == Timestamp.class
|
||||
|| tType == Time.class
|
||||
|
||||
|| tType == LocalDateTime.class
|
||||
|| tType == LocalTime.class
|
||||
|| tType == OffsetDateTime.class
|
||||
|| tType == OffsetTime.class
|
||||
|| tType == Instant.class
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean precisionDefined() {
|
||||
return precision != null && hasPrecision();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> scale(int s) {
|
||||
return scale0(s);
|
||||
}
|
||||
|
||||
private final DefaultDataType<T> scale0(Integer s) {
|
||||
if (eq(scale, s))
|
||||
return this;
|
||||
|
||||
// [#4120] LOB types are not allowed to have scale
|
||||
if (isLob())
|
||||
return this;
|
||||
else
|
||||
return construct(precision, s, length, nullability, collation, characterSet, identity, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int scale() {
|
||||
return scale == null ? 0 : scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasScale() {
|
||||
return tType == BigDecimal.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean scaleDefined() {
|
||||
return scale != null && hasScale();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T> length(int l) {
|
||||
return length0(l);
|
||||
}
|
||||
|
||||
private final DefaultDataType<T> length0(Integer l) {
|
||||
if (eq(length, l))
|
||||
return this;
|
||||
|
||||
// [#4120] LOB types are not allowed to have length
|
||||
if (isLob())
|
||||
return this;
|
||||
else
|
||||
return construct(precision, scale, l, nullability, collation, characterSet, identity, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int length() {
|
||||
return length == null ? 0 : length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasLength() {
|
||||
return (tType == byte[].class || tType == String.class) && !isLob();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean lengthDefined() {
|
||||
return length != null && hasLength();
|
||||
final Integer length0() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -671,216 +478,34 @@ public class DefaultDataType<T> extends AbstractNamed implements DataType<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* final */ int getSQLType() {
|
||||
return getSQLType(DSL.using(dialect).configuration());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getSQLType(Configuration configuration) {
|
||||
// TODO [#1227] There is some confusion with these types, especially
|
||||
// when it comes to byte[] which can be mapped to BLOB, BINARY, VARBINARY
|
||||
|
||||
if (tType == Blob.class)
|
||||
return Types.BLOB;
|
||||
else if (tType == Boolean.class)
|
||||
return Types.BOOLEAN;
|
||||
else if (tType == BigInteger.class)
|
||||
return Types.BIGINT;
|
||||
else if (tType == BigDecimal.class)
|
||||
return Types.DECIMAL;
|
||||
else if (tType == Byte.class)
|
||||
return Types.TINYINT;
|
||||
else if (tType == byte[].class)
|
||||
return Types.BLOB;
|
||||
else if (tType == Clob.class)
|
||||
return Types.CLOB;
|
||||
else if (Tools.isDate(tType)) {
|
||||
switch (configuration.family()) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
default:
|
||||
return Types.DATE;
|
||||
}
|
||||
}
|
||||
else if (tType == Double.class)
|
||||
return Types.DOUBLE;
|
||||
else if (tType == Float.class)
|
||||
return Types.FLOAT;
|
||||
else if (tType == Integer.class)
|
||||
return Types.INTEGER;
|
||||
else if (tType == Long.class)
|
||||
return Types.BIGINT;
|
||||
else if (tType == Short.class)
|
||||
return Types.SMALLINT;
|
||||
else if (tType == String.class)
|
||||
return Types.VARCHAR;
|
||||
else if (Tools.isTime(tType))
|
||||
return Types.TIME;
|
||||
else if (Tools.isTimestamp(tType))
|
||||
return Types.TIMESTAMP;
|
||||
|
||||
|
||||
// [#5779] Few JDBC drivers support the JDBC 4.2 TIME[STAMP]_WITH_TIMEZONE types.
|
||||
else if (tType == OffsetTime.class)
|
||||
return Types.VARCHAR;
|
||||
else if (tType == OffsetDateTime.class)
|
||||
return Types.VARCHAR;
|
||||
else if (tType == Instant.class)
|
||||
return Types.VARCHAR;
|
||||
|
||||
|
||||
// The type byte[] is handled earlier.
|
||||
else if (tType.isArray())
|
||||
return Types.ARRAY;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
else if (EnumType.class.isAssignableFrom(tType))
|
||||
return Types.VARCHAR;
|
||||
else if (UDTRecord.class.isAssignableFrom(tType))
|
||||
return Types.STRUCT;
|
||||
else if (Result.class.isAssignableFrom(tType)) {
|
||||
switch (configuration.family()) {
|
||||
|
||||
|
||||
|
||||
case H2:
|
||||
return -10; // OracleTypes.CURSOR;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
case POSTGRES:
|
||||
default:
|
||||
return Types.OTHER;
|
||||
}
|
||||
}
|
||||
else
|
||||
return Types.OTHER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Class<T> getType() {
|
||||
return uType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ Domain<T> getDomain() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Binding<?, T> getBinding() {
|
||||
return binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Converter<?, T> getConverter() {
|
||||
return binding.converter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getTypeName() {
|
||||
final String typeName0() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ String getTypeName(Configuration configuration) {
|
||||
return getDataType(configuration).getTypeName();
|
||||
final String castTypeBase0() {
|
||||
return castTypeBase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getCastTypeName() {
|
||||
|
||||
// [#9958] We should be able to avoid checking for x > 0, but there may
|
||||
// be a lot of data types constructed with a 0 value instead of
|
||||
// a null value, historically, so removing this check would
|
||||
// introduce a lot of regressions!
|
||||
if (lengthDefined() && length() > 0)
|
||||
return castTypeBase + "(" + length + ")";
|
||||
else if (precisionDefined() && precision() > 0)
|
||||
if (scaleDefined() && scale() > 0)
|
||||
return castTypeBase + "(" + precision + ", " + scale + ")";
|
||||
else
|
||||
return castTypeBase + "(" + precision + ")";
|
||||
else
|
||||
return castTypeName;
|
||||
final String castTypeName0() {
|
||||
return castTypeName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ String getCastTypeName(Configuration configuration) {
|
||||
return getDataType(configuration).getCastTypeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Class<T[]> getArrayType() {
|
||||
return arrayType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final DataType<T[]> getArrayDataType() {
|
||||
return new ArrayDataType<>(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ Class<?> getArrayComponentType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ DataType<?> getArrayComponentDataType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public final <E extends EnumType> DataType<E> asEnumDataType(Class<E> enumDataType) {
|
||||
// TODO: Make EnumTypes implement Named
|
||||
String enumTypeName = Tools.enums(enumDataType)[0].getName();
|
||||
return new DefaultDataType<>(dialect, (DataType<E>) null, enumDataType, unquotedName(enumTypeName), enumTypeName, enumTypeName, precision, scale, length, nullability, (Field) defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* non-final */ <U> DataType<U> asConvertedDataType(Converter<? super T, U> converter) {
|
||||
return asConvertedDataType(DefaultBinding.newBinding(converter, this, null));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public /* non-final */ <U> DataType<U> asConvertedDataType(Binding<? super T, U> newBinding) {
|
||||
if (binding == newBinding)
|
||||
return (DataType<U>) this;
|
||||
|
||||
if (newBinding == null)
|
||||
newBinding = (Binding<? super T, U>) DefaultBinding.binding(getType(), isLob());
|
||||
|
||||
return new ConvertedDataType<>(this, newBinding);
|
||||
final Class<?> tType0() {
|
||||
return tType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -888,28 +513,6 @@ public class DefaultDataType<T> extends AbstractNamed implements DataType<T> {
|
||||
return dialect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public /* final */ T convert(Object object) {
|
||||
|
||||
// [#1441] Avoid unneeded type conversions to improve performance
|
||||
if (object == null)
|
||||
return null;
|
||||
else if (object.getClass() == uType)
|
||||
return (T) object;
|
||||
else
|
||||
return Convert.convert(object, uType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final T[] convert(Object... objects) {
|
||||
return (T[]) Convert.convertArray(objects, uType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<T> convert(Collection<?> objects) {
|
||||
return Convert.convert(objects, uType);
|
||||
}
|
||||
|
||||
public static final DataType<Object> getDefaultDataType(String typeName) {
|
||||
return new DefaultDataType<>(SQLDialect.DEFAULT, Object.class, typeName, typeName);
|
||||
}
|
||||
@ -1029,174 +632,6 @@ public class DefaultDataType<T> extends AbstractNamed implements DataType<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isNumeric() {
|
||||
return Number.class.isAssignableFrom(tType) && !isInterval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isInteger() {
|
||||
return UNumber.class.isAssignableFrom(tType)
|
||||
|| Byte.class == tType
|
||||
|| Short.class == tType
|
||||
|| Integer.class == tType
|
||||
|| Long.class == tType
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isString() {
|
||||
return tType == String.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isDateTime() {
|
||||
return java.util.Date.class.isAssignableFrom(tType)
|
||||
|
||||
|| java.time.temporal.Temporal.class.isAssignableFrom(tType)
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isDate() {
|
||||
return java.sql.Date.class.isAssignableFrom(tType)
|
||||
|
||||
|| java.time.LocalDate.class.isAssignableFrom(tType)
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isTimestamp() {
|
||||
return java.sql.Timestamp.class.isAssignableFrom(tType)
|
||||
|
||||
|| java.time.LocalDateTime.class.isAssignableFrom(tType)
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isTime() {
|
||||
return java.sql.Time.class.isAssignableFrom(tType)
|
||||
|
||||
|| java.time.LocalTime.class.isAssignableFrom(tType)
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isTemporal() {
|
||||
return isDateTime() || isInterval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isInterval() {
|
||||
return Interval.class.isAssignableFrom(tType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isLob() {
|
||||
DataType<T> t = getSQLDataType();
|
||||
|
||||
if (t == this)
|
||||
return getTypeName().endsWith("lob");
|
||||
else
|
||||
return (t == BLOB || t == CLOB || t == NCLOB);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isBinary() {
|
||||
return tType == byte[].class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isArray() {
|
||||
return
|
||||
(!isBinary() && tType.isArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isUDT() {
|
||||
return UDTRecord.class.isAssignableFrom(tType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isEnum() {
|
||||
return EnumType.class.isAssignableFrom(tType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isJSON() {
|
||||
return tType == JSON.class || tType == JSONB.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isXML() {
|
||||
return tType == XML.class;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// The Object API
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getCastTypeName() + " (" + uType.getName() + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((dialect == null) ? 0 : dialect.hashCode());
|
||||
result = prime * result + length();
|
||||
result = prime * result + precision();
|
||||
result = prime * result + scale();
|
||||
result = prime * result + ((uType == null) ? 0 : uType.hashCode());
|
||||
result = prime * result + ((tType == null) ? 0 : tType.hashCode());
|
||||
result = prime * result + ((typeName == null) ? 0 : typeName.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
DefaultDataType<?> other = (DefaultDataType<?>) obj;
|
||||
if (dialect != other.dialect)
|
||||
return false;
|
||||
if (!eq(length, other.length))
|
||||
return false;
|
||||
if (!eq(precision, other.precision))
|
||||
return false;
|
||||
if (!eq(scale, other.scale))
|
||||
return false;
|
||||
if (uType == null) {
|
||||
if (other.uType != null)
|
||||
return false;
|
||||
}
|
||||
else if (!uType.equals(other.uType))
|
||||
return false;
|
||||
if (tType == null) {
|
||||
if (other.tType != null)
|
||||
return false;
|
||||
}
|
||||
else if (!tType.equals(other.tType))
|
||||
return false;
|
||||
if (typeName == null) {
|
||||
if (other.typeName != null)
|
||||
return false;
|
||||
}
|
||||
else if (!typeName.equals(other.typeName))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The type name without all special characters and white spaces
|
||||
*/
|
||||
@ -1268,13 +703,4 @@ public class DefaultDataType<T> extends AbstractNamed implements DataType<T> {
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
private static final boolean eq(Integer i1, Integer i2) {
|
||||
return (i1 == i2) || (i1 != null && i2 != null && i1.intValue() == i2.intValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void accept(Context<?> ctx) {
|
||||
ctx.visit(getQualifiedName());
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -12251,7 +12251,7 @@ final class ParserContext {
|
||||
Field<?> f2;
|
||||
if ((f2 = t.field(f.getName())) != null) {
|
||||
if (f1 != null) {
|
||||
position(f.position);
|
||||
position(f.position());
|
||||
throw exception("Ambiguous field identifier");
|
||||
}
|
||||
|
||||
@ -12259,10 +12259,8 @@ final class ParserContext {
|
||||
}
|
||||
}
|
||||
|
||||
if (f1 != null) {
|
||||
f.delegate = (AbstractField) f1;
|
||||
f.sql = null;
|
||||
}
|
||||
if (f1 != null)
|
||||
f.delegate((AbstractField) f1);
|
||||
else
|
||||
retain.add(f);
|
||||
}
|
||||
@ -12289,7 +12287,7 @@ final class ParserContext {
|
||||
|
||||
void unknownField(FieldProxy<?> field) {
|
||||
if (!scopeClear && !metaLookupsForceIgnore && metaLookups == THROW_ON_FAILURE) {
|
||||
position(field.position);
|
||||
position(field.position());
|
||||
throw exception("Unknown field identifier");
|
||||
}
|
||||
}
|
||||
@ -12335,7 +12333,7 @@ final class ParserContext {
|
||||
|
||||
FieldProxy<?> field = lookupFields.get(name.last());
|
||||
if (field == null)
|
||||
lookupFields.set(name.last(), field = new FieldProxy<>((AbstractField<Object>) field(name), sql, position));
|
||||
lookupFields.set(name.last(), field = new FieldProxy<>((AbstractField<Object>) field(name), position));
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user