[#3225] Performance bottleneck in MetaFieldProvider when fetching unknown plain SQL fields

This commit is contained in:
lukaseder 2016-02-25 17:58:31 +01:00
parent 5e7255b31c
commit 6d093bc707
2 changed files with 52 additions and 28 deletions

View File

@ -272,24 +272,9 @@ public class DefaultDataType<T> implements DataType<T> {
this.castTypeBase = TYPE_NAME_PATTERN.matcher(castTypeName).replaceAll("").trim();
this.arrayType = (Class<T[]>) Array.newInstance(type, 0).getClass();
if (precision == 0) {
if (type == Long.class || type == ULong.class) {
precision = LONG_PRECISION;
}
else if (type == Integer.class || type == UInteger.class) {
precision = INTEGER_PRECISION;
}
else if (type == Short.class || type == UShort.class) {
precision = SHORT_PRECISION;
}
else if (type == Byte.class || type == UByte.class) {
precision = BYTE_PRECISION;
}
}
this.nullable = nullable;
this.defaulted = defaulted;
this.precision = precision;
this.precision = precision0(type, precision);
this.scale = scale;
this.length = length;
@ -328,9 +313,49 @@ public class DefaultDataType<T> implements DataType<T> {
: new DefaultBinding<T, T>(Converters.identity(type), this.isLob());
}
/**
* [#3225] Performant constructor for creating derived types.
*/
private DefaultDataType(DefaultDataType<T> t, int precision, int scale, int length, boolean nullable, boolean defaulted) {
this.dialect = t.dialect;
this.sqlDataType = t.sqlDataType;
this.type = t.type;
this.typeName = t.typeName;
this.castTypeName = t.castTypeName;
this.castTypeBase = t.castTypeBase;
this.arrayType = t.arrayType;
this.nullable = nullable;
this.defaulted = defaulted;
this.precision = precision0(type, precision);
this.scale = scale;
this.length = length;
this.binding = t.binding;
}
private static final int precision0(Class<?> type, int precision) {
if (precision == 0) {
if (type == Long.class || type == ULong.class) {
precision = LONG_PRECISION;
}
else if (type == Integer.class || type == UInteger.class) {
precision = INTEGER_PRECISION;
}
else if (type == Short.class || type == UShort.class) {
precision = SHORT_PRECISION;
}
else if (type == Byte.class || type == UByte.class) {
precision = BYTE_PRECISION;
}
}
return precision;
}
@Override
public final DataType<T> nullable(boolean n) {
return new DefaultDataType<T>(dialect, sqlDataType, type, typeName, castTypeName, precision, scale, length, n, defaulted);
return new DefaultDataType<T>(this, precision, scale, length, n, defaulted);
}
@Override
@ -340,7 +365,7 @@ public class DefaultDataType<T> implements DataType<T> {
@Override
public final DataType<T> defaulted(boolean d) {
return new DefaultDataType<T>(dialect, sqlDataType, type, typeName, castTypeName, precision, scale, length, nullable, d);
return new DefaultDataType<T>(this, precision, scale, length, nullable, d);
}
@Override
@ -362,7 +387,7 @@ public class DefaultDataType<T> implements DataType<T> {
else if (isLob())
return this;
else
return new DefaultDataType<T>(dialect, sqlDataType, type, typeName, castTypeName, p, s, length, nullable, defaulted);
return new DefaultDataType<T>(this, p, s, length, nullable, defaulted);
}
@Override
@ -384,7 +409,7 @@ public class DefaultDataType<T> implements DataType<T> {
if (isLob())
return this;
else
return new DefaultDataType<T>(dialect, sqlDataType, type, typeName, castTypeName, precision, s, length, nullable, defaulted);
return new DefaultDataType<T>(this, precision, s, length, nullable, defaulted);
}
@Override
@ -406,7 +431,7 @@ public class DefaultDataType<T> implements DataType<T> {
if (isLob())
return this;
else
return new DefaultDataType<T>(dialect, sqlDataType, type, typeName, castTypeName, precision, scale, l, nullable, defaulted);
return new DefaultDataType<T>(this, precision, scale, l, nullable, defaulted);
}
@Override

View File

@ -47,8 +47,6 @@ import java.io.Serializable;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.List;
import org.jooq.Configuration;
import org.jooq.DataType;
@ -87,18 +85,19 @@ final class MetaDataFieldProvider implements Serializable {
}
private Fields<Record> init(Configuration configuration, ResultSetMetaData meta) {
List<Field<?>> fieldList = new ArrayList<Field<?>>();
Field<?>[] fields;
int columnCount = 0;
try {
columnCount = meta.getColumnCount();
fields = new Field[columnCount];
}
// This happens in Oracle for empty cursors returned from stored
// procedures / functions
catch (SQLException e) {
log.info("Cannot fetch column count for cursor : " + e.getMessage());
fieldList.add(field("dummy"));
fields = new Field[] { field("dummy") };
}
try {
@ -131,7 +130,7 @@ final class MetaDataFieldProvider implements Serializable {
String type = meta.getColumnTypeName(i);
try {
dataType = DefaultDataType.getDataType(configuration.dialect().family(), type, precision, scale);
dataType = DefaultDataType.getDataType(configuration.family(), type, precision, scale);
if (dataType.hasPrecision()) {
dataType = dataType.precision(precision);
@ -153,14 +152,14 @@ final class MetaDataFieldProvider implements Serializable {
log.debug("Not supported by dialect", ignore.getMessage());
}
fieldList.add(field(name, dataType));
fields[i - 1] = field(name, dataType);
}
}
catch (SQLException e) {
throw Utils.translate(null, e);
}
return new Fields<Record>(fieldList);
return new Fields<Record>(fields);
}
final Field<?>[] getFields() {