From 6d093bc707ad2fd212bb7630e1e77169816b16f0 Mon Sep 17 00:00:00 2001 From: lukaseder Date: Thu, 25 Feb 2016 17:58:31 +0100 Subject: [PATCH] [#3225] Performance bottleneck in MetaFieldProvider when fetching unknown plain SQL fields --- .../java/org/jooq/impl/DefaultDataType.java | 67 +++++++++++++------ .../org/jooq/impl/MetaDataFieldProvider.java | 13 ++-- 2 files changed, 52 insertions(+), 28 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java b/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java index 2c764e9fe6..1caa5245ea 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultDataType.java @@ -272,24 +272,9 @@ public class DefaultDataType implements DataType { this.castTypeBase = TYPE_NAME_PATTERN.matcher(castTypeName).replaceAll("").trim(); this.arrayType = (Class) 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 implements DataType { : new DefaultBinding(Converters.identity(type), this.isLob()); } + /** + * [#3225] Performant constructor for creating derived types. + */ + private DefaultDataType(DefaultDataType 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 nullable(boolean n) { - return new DefaultDataType(dialect, sqlDataType, type, typeName, castTypeName, precision, scale, length, n, defaulted); + return new DefaultDataType(this, precision, scale, length, n, defaulted); } @Override @@ -340,7 +365,7 @@ public class DefaultDataType implements DataType { @Override public final DataType defaulted(boolean d) { - return new DefaultDataType(dialect, sqlDataType, type, typeName, castTypeName, precision, scale, length, nullable, d); + return new DefaultDataType(this, precision, scale, length, nullable, d); } @Override @@ -362,7 +387,7 @@ public class DefaultDataType implements DataType { else if (isLob()) return this; else - return new DefaultDataType(dialect, sqlDataType, type, typeName, castTypeName, p, s, length, nullable, defaulted); + return new DefaultDataType(this, p, s, length, nullable, defaulted); } @Override @@ -384,7 +409,7 @@ public class DefaultDataType implements DataType { if (isLob()) return this; else - return new DefaultDataType(dialect, sqlDataType, type, typeName, castTypeName, precision, s, length, nullable, defaulted); + return new DefaultDataType(this, precision, s, length, nullable, defaulted); } @Override @@ -406,7 +431,7 @@ public class DefaultDataType implements DataType { if (isLob()) return this; else - return new DefaultDataType(dialect, sqlDataType, type, typeName, castTypeName, precision, scale, l, nullable, defaulted); + return new DefaultDataType(this, precision, scale, l, nullable, defaulted); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/MetaDataFieldProvider.java b/jOOQ/src/main/java/org/jooq/impl/MetaDataFieldProvider.java index 937bcede13..55b8413f59 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MetaDataFieldProvider.java +++ b/jOOQ/src/main/java/org/jooq/impl/MetaDataFieldProvider.java @@ -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 init(Configuration configuration, ResultSetMetaData meta) { - List> fieldList = new ArrayList>(); + 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(fieldList); + return new Fields(fields); } final Field[] getFields() {