From 7acb6ebe8c62e7840fe0e25b4ad337ed925ecfa1 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 8 Feb 2013 13:08:41 +0100 Subject: [PATCH] [#2178] Improve FieldList. Avoid creating excessive array lists, where simple (immutable) Field[] are sufficient - Introduced org.jooq.impl.Fields as a wrapper for Field[]. Executor.newRecord() is accelerated by 50%! --- .../java/org/jooq/impl/AbstractRecord.java | 6 +- .../main/java/org/jooq/impl/FieldList.java | 71 --------- jOOQ/src/main/java/org/jooq/impl/Fields.java | 145 ++++++++++++++++++ .../main/java/org/jooq/impl/MergeImpl.java | 18 +-- .../org/jooq/impl/MetaDataFieldProvider.java | 19 ++- jOOQ/src/main/java/org/jooq/impl/RowImpl.java | 71 +++++---- jOOQ/src/main/java/org/jooq/impl/Utils.java | 8 + 7 files changed, 209 insertions(+), 129 deletions(-) create mode 100644 jOOQ/src/main/java/org/jooq/impl/Fields.java diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java b/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java index b9c2cb893c..21b2fa9505 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractRecord.java @@ -333,7 +333,7 @@ abstract class AbstractRecord extends AbstractStore implements Record { */ @Override public Record original() { - AbstractRecord result = Utils.newRecord(getClass(), fields.fields, getConfiguration()); + AbstractRecord result = Utils.newRecord(getClass(), fields.fields.fields, getConfiguration()); Value[] v = getValues(); for (int i = 0; i < v.length; i++) { @@ -520,7 +520,7 @@ abstract class AbstractRecord extends AbstractStore implements Record { @Override public final ResultSet intoResultSet() { - ResultImpl result = new ResultImpl(getConfiguration(), fields.fields); + ResultImpl result = new ResultImpl(getConfiguration(), fields.fields.fields); result.add(this); return result.intoResultSet(); } @@ -663,7 +663,7 @@ abstract class AbstractRecord extends AbstractStore implements Record { @Override public String toString() { - Result result = new ResultImpl(getConfiguration(), fields.fields); + Result result = new ResultImpl(getConfiguration(), fields.fields.fields); result.add(this); return result.toString(); } diff --git a/jOOQ/src/main/java/org/jooq/impl/FieldList.java b/jOOQ/src/main/java/org/jooq/impl/FieldList.java index d6cb0c82d1..a57da3dec4 100644 --- a/jOOQ/src/main/java/org/jooq/impl/FieldList.java +++ b/jOOQ/src/main/java/org/jooq/impl/FieldList.java @@ -58,75 +58,4 @@ class FieldList extends QueryPartList> { FieldList(Field... wrappedList) { super(wrappedList); } - - @SuppressWarnings("unchecked") - final Field field(Field field) { - if (field == null) { - return null; - } - - // [#1802] Try finding an exact match (e.g. exact matching qualified name) - for (Field f : this) { - if (f.equals(field)) { - return (Field) f; - } - } - - // In case no exact match was found, return the first field with matching name - String name = field.getName(); - for (Field f1 : this) { - if (f1.getName().equals(name)) { - return (Field) f1; - } - } - - return null; - } - - final Field field(String name) { - if (name == null) { - return null; - } - - for (Field f : this) { - if (f.getName().equals(name)) { - return f; - } - } - - return null; - } - - final Field field(int index) { - if (index >= 0 && index < size()) { - return get(index); - } - - return null; - } - - final Field[] fields() { - return toArray(new Field[size()]); - } - - final int indexOf(Field field) { - - // Get an exact match, or a field with a similar name - Field compareWith = field(field); - - if (compareWith != null) { - int size = size(); - - for (int i = 0; i < size; i++) { - if (get(i).equals(compareWith)) - return i; - } - } - - return -1; - } - - final int indexOf(String fieldName) { - return indexOf(field(fieldName)); - } } diff --git a/jOOQ/src/main/java/org/jooq/impl/Fields.java b/jOOQ/src/main/java/org/jooq/impl/Fields.java new file mode 100644 index 0000000000..4f5d519499 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/impl/Fields.java @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2009-2013, Lukas Eder, lukas.eder@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jooq.impl; + +import java.util.Collection; + +import org.jooq.BindContext; +import org.jooq.Field; +import org.jooq.RenderContext; + +/** + * A simple wrapper for Field[], providing some useful lookup + * methods + * + * @author Lukas Eder + */ +class Fields extends AbstractQueryPart { + + private static final long serialVersionUID = -6911012275707591576L; + final Field[] fields; + + Fields(Field... fields) { + this.fields = fields; + } + + Fields(Collection> fields) { + this.fields = fields.toArray(new Field[fields.size()]); + } + + @SuppressWarnings("unchecked") + final Field field(Field field) { + if (field == null) { + return null; + } + + // [#1802] Try finding an exact match (e.g. exact matching qualified name) + for (Field f : fields) { + if (f.equals(field)) { + return (Field) f; + } + } + + // In case no exact match was found, return the first field with matching name + String name = field.getName(); + for (Field f1 : fields) { + if (f1.getName().equals(name)) { + return (Field) f1; + } + } + + return null; + } + + final Field field(String name) { + if (name == null) { + return null; + } + + for (Field f : fields) { + if (f.getName().equals(name)) { + return f; + } + } + + return null; + } + + final Field field(int index) { + if (index >= 0 && index < fields.length) { + return fields[index]; + } + + return null; + } + + final Field[] fields() { + return fields; + } + + final int indexOf(Field field) { + + // Get an exact match, or a field with a similar name + Field compareWith = field(field); + + if (compareWith != null) { + int size = fields.length; + + for (int i = 0; i < size; i++) { + if (fields[i].equals(compareWith)) + return i; + } + } + + return -1; + } + + final int indexOf(String fieldName) { + return indexOf(field(fieldName)); + } + + + @Override + public final void toSQL(RenderContext context) { + new FieldList(fields).toSQL(context); + } + + @Override + public final void bind(BindContext context) { + new FieldList(fields).bind(context); + } +} diff --git a/jOOQ/src/main/java/org/jooq/impl/MergeImpl.java b/jOOQ/src/main/java/org/jooq/impl/MergeImpl.java index 24ffdf3b7a..03d9239ac1 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MergeImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/MergeImpl.java @@ -215,7 +215,7 @@ implements // Objects for the H2-specific syntax private boolean h2Style; - private FieldList h2Fields; + private Fields h2Fields; private FieldList h2Keys; private FieldList h2Values; private Select h2Select; @@ -232,7 +232,7 @@ implements if (fields != null) { h2Style = true; - h2Fields = new FieldList(fields); + h2Fields = new Fields(fields); } } @@ -240,9 +240,9 @@ implements // H2-specific MERGE API // ------------------------------------------------------------------------- - FieldList getH2Fields() { + Fields getH2Fields() { if (h2Fields == null) { - h2Fields = new FieldList(table.fields()); + h2Fields = new Fields(table.fields()); } return h2Fields; @@ -518,7 +518,7 @@ implements // syntax, in case of which, the USING() was not added if (using == null) { h2Style = true; - getH2Values().addAll(vals(convert(values, getH2Fields().toArray(new Field[0])))); + getH2Values().addAll(vals(convert(values, getH2Fields().fields()))); } else { Field[] fields = notMatchedInsert.keySet().toArray(new Field[0]); @@ -967,11 +967,11 @@ implements for (int i = 0; i < src.fieldsRow().size(); i++) { // Oracle does not allow to update fields from the ON clause - if (!onFields.contains(getH2Fields().get(i))) { - update.put(getH2Fields().get(i), src.field(i)); + if (!onFields.contains(getH2Fields().field(i))) { + update.put(getH2Fields().field(i), src.field(i)); } - insert.put(getH2Fields().get(i), src.field(i)); + insert.put(getH2Fields().field(i), src.field(i)); } return create(config).mergeInto(table) @@ -1137,7 +1137,7 @@ implements context.declareTables(true) .bind(table) .declareTables(false) - .bind((QueryPart) getH2Fields()) + .bind(getH2Fields()) .bind((QueryPart) getH2Keys()) .bind(h2Select) .bind((QueryPart) getH2Values()); diff --git a/jOOQ/src/main/java/org/jooq/impl/MetaDataFieldProvider.java b/jOOQ/src/main/java/org/jooq/impl/MetaDataFieldProvider.java index 1ac7e68ecc..d1a5b1778c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/MetaDataFieldProvider.java +++ b/jOOQ/src/main/java/org/jooq/impl/MetaDataFieldProvider.java @@ -40,6 +40,8 @@ import static org.jooq.impl.Factory.field; import java.io.Serializable; import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; import org.jooq.Configuration; import org.jooq.DataType; @@ -69,17 +71,14 @@ class MetaDataFieldProvider implements Serializable { private static final long serialVersionUID = -8482521025536063609L; private static final JooqLogger log = JooqLogger.getLogger(MetaDataFieldProvider.class); - private final Configuration configuration; - private final FieldList fields; + private final Fields fields; MetaDataFieldProvider(Configuration configuration, ResultSetMetaData meta) { - this.configuration = configuration; - this.fields = new FieldList(); - - init(meta); + this.fields = init(configuration, meta); } - private final void init(ResultSetMetaData meta) { + private Fields init(Configuration configuration, ResultSetMetaData meta) { + List> fieldList = new ArrayList>(); int columnCount = 0; try { @@ -90,7 +89,7 @@ class MetaDataFieldProvider implements Serializable { // procedures / functions catch (SQLException e) { log.warn("Cannot fetch column count for cursor : " + e.getMessage()); - fields.add(field("dummy")); + fieldList.add(field("dummy")); } try { @@ -123,14 +122,14 @@ class MetaDataFieldProvider implements Serializable { log.warn("Not supported by dialect", ignore.getMessage()); } - fields.add(field(name, dataType)); + fieldList.add(field(name, dataType)); } } catch (SQLException e) { throw Utils.translate(null, e); } - meta = null; + return new Fields(fieldList); } final Field[] getFields() { diff --git a/jOOQ/src/main/java/org/jooq/impl/RowImpl.java b/jOOQ/src/main/java/org/jooq/impl/RowImpl.java index f95c57bf8d..fb7d82dc30 100644 --- a/jOOQ/src/main/java/org/jooq/impl/RowImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/RowImpl.java @@ -45,14 +45,6 @@ import java.util.Iterator; import javax.annotation.Generated; import org.jooq.BetweenAndStep1; -import org.jooq.BetweenAndStep2; -import org.jooq.BetweenAndStep3; -import org.jooq.BetweenAndStep4; -import org.jooq.BetweenAndStep5; -import org.jooq.BetweenAndStep6; -import org.jooq.BetweenAndStep7; -import org.jooq.BetweenAndStep8; -import org.jooq.BetweenAndStep9; import org.jooq.BetweenAndStep10; import org.jooq.BetweenAndStep11; import org.jooq.BetweenAndStep12; @@ -63,26 +55,25 @@ import org.jooq.BetweenAndStep16; import org.jooq.BetweenAndStep17; import org.jooq.BetweenAndStep18; import org.jooq.BetweenAndStep19; +import org.jooq.BetweenAndStep2; import org.jooq.BetweenAndStep20; import org.jooq.BetweenAndStep21; import org.jooq.BetweenAndStep22; +import org.jooq.BetweenAndStep3; +import org.jooq.BetweenAndStep4; +import org.jooq.BetweenAndStep5; +import org.jooq.BetweenAndStep6; +import org.jooq.BetweenAndStep7; +import org.jooq.BetweenAndStep8; +import org.jooq.BetweenAndStep9; import org.jooq.BetweenAndStepN; import org.jooq.BindContext; import org.jooq.Comparator; import org.jooq.Condition; import org.jooq.DataType; import org.jooq.Field; -import org.jooq.QueryPart; import org.jooq.Record; import org.jooq.Record1; -import org.jooq.Record2; -import org.jooq.Record3; -import org.jooq.Record4; -import org.jooq.Record5; -import org.jooq.Record6; -import org.jooq.Record7; -import org.jooq.Record8; -import org.jooq.Record9; import org.jooq.Record10; import org.jooq.Record11; import org.jooq.Record12; @@ -93,20 +84,20 @@ import org.jooq.Record16; import org.jooq.Record17; import org.jooq.Record18; import org.jooq.Record19; +import org.jooq.Record2; import org.jooq.Record20; import org.jooq.Record21; import org.jooq.Record22; +import org.jooq.Record3; +import org.jooq.Record4; +import org.jooq.Record5; +import org.jooq.Record6; +import org.jooq.Record7; +import org.jooq.Record8; +import org.jooq.Record9; import org.jooq.RenderContext; import org.jooq.Row; import org.jooq.Row1; -import org.jooq.Row2; -import org.jooq.Row3; -import org.jooq.Row4; -import org.jooq.Row5; -import org.jooq.Row6; -import org.jooq.Row7; -import org.jooq.Row8; -import org.jooq.Row9; import org.jooq.Row10; import org.jooq.Row11; import org.jooq.Row12; @@ -117,9 +108,17 @@ import org.jooq.Row16; import org.jooq.Row17; import org.jooq.Row18; import org.jooq.Row19; +import org.jooq.Row2; import org.jooq.Row20; import org.jooq.Row21; import org.jooq.Row22; +import org.jooq.Row3; +import org.jooq.Row4; +import org.jooq.Row5; +import org.jooq.Row6; +import org.jooq.Row7; +import org.jooq.Row8; +import org.jooq.Row9; import org.jooq.RowN; import org.jooq.Select; @@ -162,18 +161,18 @@ implements */ private static final long serialVersionUID = -929427349071556318L; - final FieldList fields; + final Fields fields; RowImpl(Field... fields) { super(); - this.fields = new FieldList(fields); + this.fields = new Fields(fields); } RowImpl(Collection> fields) { super(); - this.fields = new FieldList(fields); + this.fields = new Fields(fields.toArray(new Field[fields.size()])); } // ------------------------------------------------------------------------ @@ -185,7 +184,7 @@ implements context.sql("("); String separator = ""; - for (Field field : fields) { + for (Field field : fields.fields) { context.sql(separator); context.sql(field); @@ -197,7 +196,7 @@ implements @Override public final void bind(BindContext context) { - context.bind((QueryPart) fields); + context.bind(fields); } // ------------------------------------------------------------------------ @@ -206,7 +205,7 @@ implements @Override public final int size() { - return fields.size(); + return fields.fields.length; } @Override @@ -241,7 +240,7 @@ implements @Override public final Class[] types() { - int size = fields.size(); + int size = fields.fields.length; Class[] result = new Class[size]; for (int i = 0; i < size; i++) { @@ -263,13 +262,13 @@ implements @Override public final DataType[] dataTypes() { - int size = fields.size(); + int size = fields.fields.length; DataType[] result = new DataType[size]; - + for (int i = 0; i < size; i++) { result[i] = fields.field(i).getDataType(); } - + return result; } @@ -9564,6 +9563,6 @@ implements @Override public final Iterator> iterator() { - return fields.iterator(); + return Arrays.asList(fields.fields).iterator(); } } diff --git a/jOOQ/src/main/java/org/jooq/impl/Utils.java b/jOOQ/src/main/java/org/jooq/impl/Utils.java index e10ed589fe..4bd626577a 100644 --- a/jOOQ/src/main/java/org/jooq/impl/Utils.java +++ b/jOOQ/src/main/java/org/jooq/impl/Utils.java @@ -654,6 +654,14 @@ final class Utils { } } + /** + * Render a list of names of the NamedQueryParts contained in + * this list. + */ + static final void fieldNames(RenderContext context, Fields fields) { + fieldNames(context, list(fields.fields)); + } + /** * Render a list of names of the NamedQueryParts contained in * this list.