[#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%!
This commit is contained in:
Lukas Eder 2013-02-08 13:08:41 +01:00
parent 8573e3d0c5
commit 7acb6ebe8c
7 changed files with 209 additions and 129 deletions

View File

@ -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<Record> result = new ResultImpl<Record>(getConfiguration(), fields.fields);
ResultImpl<Record> result = new ResultImpl<Record>(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<AbstractRecord> result = new ResultImpl<AbstractRecord>(getConfiguration(), fields.fields);
Result<AbstractRecord> result = new ResultImpl<AbstractRecord>(getConfiguration(), fields.fields.fields);
result.add(this);
return result.toString();
}

View File

@ -58,75 +58,4 @@ class FieldList extends QueryPartList<Field<?>> {
FieldList(Field<?>... wrappedList) {
super(wrappedList);
}
@SuppressWarnings("unchecked")
final <T> Field<T> field(Field<T> 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<T>) 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<T>) 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));
}
}

View File

@ -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 <code>Field[]</code>, 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<? extends Field<?>> fields) {
this.fields = fields.toArray(new Field[fields.size()]);
}
@SuppressWarnings("unchecked")
final <T> Field<T> field(Field<T> 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<T>) 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<T>) 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);
}
}

View File

@ -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());

View File

@ -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<Field<?>> fieldList = new ArrayList<Field<?>>();
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() {

View File

@ -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<? extends Field<?>> 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<Field<?>> iterator() {
return fields.iterator();
return Arrays.asList(fields.fields).iterator();
}
}

View File

@ -654,6 +654,14 @@ final class Utils {
}
}
/**
* Render a list of names of the <code>NamedQueryParts</code> contained in
* this list.
*/
static final void fieldNames(RenderContext context, Fields fields) {
fieldNames(context, list(fields.fields));
}
/**
* Render a list of names of the <code>NamedQueryParts</code> contained in
* this list.