All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jooq.impl.AbstractField Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2009-2016, Data Geekery GmbH (http://www.datageekery.com)
 * All rights reserved.
 *
 * 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.Clause.FIELD;
import static org.jooq.Comparator.EQUALS;
import static org.jooq.Comparator.GREATER;
import static org.jooq.Comparator.GREATER_OR_EQUAL;
import static org.jooq.Comparator.IN;
import static org.jooq.Comparator.IS_DISTINCT_FROM;
import static org.jooq.Comparator.IS_NOT_DISTINCT_FROM;
import static org.jooq.Comparator.LESS;
import static org.jooq.Comparator.LESS_OR_EQUAL;
import static org.jooq.Comparator.LIKE;
import static org.jooq.Comparator.LIKE_IGNORE_CASE;
import static org.jooq.Comparator.NOT_EQUALS;
import static org.jooq.Comparator.NOT_IN;
import static org.jooq.Comparator.NOT_LIKE;
import static org.jooq.Comparator.NOT_LIKE_IGNORE_CASE;
import static org.jooq.impl.DSL.inline;
import static org.jooq.impl.DSL.nullSafe;
import static org.jooq.impl.DSL.val;
import static org.jooq.impl.ExpressionOperator.ADD;
import static org.jooq.impl.ExpressionOperator.DIVIDE;
import static org.jooq.impl.ExpressionOperator.MULTIPLY;
import static org.jooq.impl.ExpressionOperator.SUBTRACT;
import static org.jooq.impl.Tools.EMPTY_FIELD;
import static org.jooq.impl.Tools.EMPTY_STRING;
import static org.jooq.tools.Convert.FALSE_VALUES;
import static org.jooq.tools.Convert.TRUE_VALUES;
import static org.jooq.tools.StringUtils.defaultString;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;

import org.jooq.BetweenAndStep;
import org.jooq.Binding;
import org.jooq.CaseValueStep;
import org.jooq.CaseWhenStep;
import org.jooq.Clause;
import org.jooq.Comparator;
import org.jooq.Condition;
import org.jooq.Configuration;
import org.jooq.Context;
import org.jooq.Converter;
import org.jooq.DataType;
import org.jooq.DatePart;
import org.jooq.Field;
import org.jooq.LikeEscapeStep;
import org.jooq.QuantifiedSelect;
import org.jooq.Record;
import org.jooq.Record1;
import org.jooq.Result;
import org.jooq.Select;
import org.jooq.SortField;
import org.jooq.SortOrder;
import org.jooq.WindowIgnoreNullsStep;
import org.jooq.WindowPartitionByStep;
import org.jooq.tools.StringUtils;

/**
 * @author Lukas Eder
 */
abstract class AbstractField extends AbstractQueryPart implements Field {

    /**
     * Generated UID
     */
    private static final long     serialVersionUID = 2884811923648354905L;
    private static final Clause[] CLAUSES          = { FIELD };

    private final String          name;
    private final String          comment;
    private final DataType     dataType;

    AbstractField(String name, DataType type) {
        this(name, type, null, type.getBinding());
    }

    @SuppressWarnings("unchecked")
    AbstractField(String name, DataType type, String comment, Binding binding) {
        super();

        this.name = name;
        this.comment = defaultString(comment);
        this.dataType = type.asConvertedDataType((Binding) binding);
    }

    // ------------------------------------------------------------------------
    // XXX: API (not implemented)
    // ------------------------------------------------------------------------

    @Override
    public abstract void accept(Context ctx);

    @Override
    public Clause[] clauses(Context ctx) {
        return CLAUSES;
    }

    // ------------------------------------------------------------------------
    // [#5518] Record method inversions, e.g. for use as method references
    // ------------------------------------------------------------------------

    @Override
    public final Field field(Record record) {
        return record.field(this);
    }

    @Override
    public final T get(Record record) {
        return record.get(this);
    }

    @Override
    public final T getValue(Record record) {
        return record.getValue(this);
    }

    @Override
    public final T original(Record record) {
        return record.original(this);
    }

    @Override
    public final boolean changed(Record record) {
        return record.changed(this);
    }

    @Override
    public final void reset(Record record) {
        record.reset(this);
    }

    @Override
    public final Record1 from(Record record) {
        return record.into(this);
    }

    // ------------------------------------------------------------------------
    // XXX: API
    // ------------------------------------------------------------------------

    @Override
    public Field as(String alias) {
        return new FieldAlias(this, alias);
    }

    @Override
    public final Field as(Field otherField) {
        return as(otherField.getName());
    }



    @Override
    public final Field as(Function, ? extends String> aliasFunction) {
        return as(aliasFunction.apply(this));
    }



    @Override
    public final String getName() {
        return name;
    }

    @Override
    public final String getComment() {
        return comment;
    }

    @Override
    public final Converter getConverter() {
        return getBinding().converter();
    }

    @Override
    public final Binding getBinding() {
        return dataType.getBinding();
    }

    @Override
    public final DataType getDataType() {
        return dataType;
    }

    @Override
    public final DataType getDataType(Configuration configuration) {
        return dataType.getDataType(configuration);
    }

    @Override
    public final Class getType() {
        return dataType.getType();
    }

    // ------------------------------------------------------------------------
    // XXX: Type casts
    // ------------------------------------------------------------------------

    @Override
    public final  Field cast(Field field) {
        return cast(field.getDataType());
    }

    @SuppressWarnings("unchecked")
    @Override
    public final  Field cast(DataType type) {

        // [#473] Prevent unnecessary casts
        if (getDataType().equals(type)) {
            return (Field) this;
        }
        else {
            return new Cast(this, type);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public final  Field cast(Class type) {

        // [#2597] Prevent unnecessary casts
        if (getType() == type) {
            return (Field) this;
        }
        else {
            return cast(DefaultDataType.getDataType(null, type));
        }
    }

    // ------------------------------------------------------------------------
    // XXX: Type coercions
    // ------------------------------------------------------------------------

    @Override
    public final  Field coerce(Field field) {
        return coerce(field.getDataType());
    }

    @SuppressWarnings("unchecked")
    @Override
    public final  Field coerce(DataType type) {

        // [#473] Prevent unnecessary coercions
        if (getDataType().equals(type)) {
            return (Field) this;
        }
        else {
            return new Coerce(this, type);
        }
    }

    @Override
    public final  Field coerce(Class type) {
        return coerce(DefaultDataType.getDataType(null, type));
    }

    // ------------------------------------------------------------------------
    // XXX: Conversion of field into a sort field
    // ------------------------------------------------------------------------

    @Override
    public final SortField asc() {
        return sort(SortOrder.ASC);
    }

    @Override
    public final SortField desc() {
        return sort(SortOrder.DESC);
    }

    @Override
    public final SortField sort(SortOrder order) {
        return new SortFieldImpl(this, order);
    }

    @Override
    public final SortField sortAsc(Collection sortList) {
        Map map = new LinkedHashMap();

        int i = 0;
        for (T value : sortList) {
            map.put(value, i++);
        }

        return sort(map);
    }

    @Override

    @SafeVarargs

    public final SortField sortAsc(T... sortList) {
        return sortAsc(Arrays.asList(sortList));
    }

    @Override
    public final SortField sortDesc(Collection sortList) {
        Map map = new LinkedHashMap();

        int i = 0;
        for (T value : sortList) {
            map.put(value, i--);
        }

        return sort(map);
    }

    @Override

    @SafeVarargs

    public final SortField sortDesc(T... sortList) {
        return sortDesc(Arrays.asList(sortList));
    }

    @Override
    public final  SortField sort(Map sortMap) {
        CaseValueStep decode = DSL.choose(this);
        CaseWhenStep result = null;

        for (Entry entry : sortMap.entrySet()) {
            if (result == null) {
                result = decode.when(entry.getKey(), inline(entry.getValue()));
            }
            else {
                result.when(entry.getKey(), inline(entry.getValue()));
            }
        }

        if (result == null) {
            return null;
        }
        else {
            return result.asc();
        }
    }

    // ------------------------------------------------------------------------
    // XXX: Arithmetic operations
    // ------------------------------------------------------------------------

    @Override
    public final Field neg() {
        return new Neg(this, ExpressionOperator.SUBTRACT);
    }

    @Override
    public final Field add(Number value) {
        return add(Tools.field(value));
    }

    /*
     * This default implementation is known to be overridden by
     * Expression to generate neater expressions
     */
    @Override
    public Field add(Field value) {
        return new Expression(ADD, this, nullSafe(value, getDataType()));
    }

    @Override
    public final Field sub(Number value) {
        return sub(Tools.field(value));
    }

    @Override
    public final Field sub(Field value) {
        return new Expression(SUBTRACT, this, nullSafe(value, getDataType()));
    }

    @Override
    public final Field mul(Number value) {
        return mul(Tools.field(value));
    }

    /**
     * This default implementation is known to be overridden by
     * Expression to generate neater expressions
     */
    @Override
    public Field mul(Field value) {
        return new Expression(MULTIPLY, this, nullSafe(value, getDataType()));
    }

    @Override
    public final Field div(Number value) {
        return div(Tools.field(value));
    }

    @Override
    public final Field div(Field value) {
        return new Expression(DIVIDE, this, nullSafe(value, getDataType()));
    }

    @Override
    public final Field mod(Number value) {
        return mod(Tools.field(value));
    }

    @Override
    public final Field mod(Field value) {
        return new Mod(this, nullSafe(value, getDataType()));
    }

    // ------------------------------------------------------------------------
    // XXX: Arithmetic operation aliases
    // ------------------------------------------------------------------------

    @Override
    public final Field plus(Number value) {
        return add(value);
    }

    @Override
    public final Field plus(Field value) {
        return add(value);
    }

    @Override
    public final Field subtract(Number value) {
        return sub(value);
    }

    @Override
    public final Field subtract(Field value) {
        return sub(value);
    }

    @Override
    public final Field minus(Number value) {
        return sub(value);
    }

    @Override
    public final Field minus(Field value) {
        return sub(value);
    }

    @Override
    public final Field multiply(Number value) {
        return mul(value);
    }

    @Override
    public final Field multiply(Field value) {
        return mul(value);
    }

    @Override
    public final Field divide(Number value) {
        return div(value);
    }

    @Override
    public final Field divide(Field value) {
        return div(value);
    }

    @Override
    public final Field modulo(Number value) {
        return mod(value);
    }

    @Override
    public final Field modulo(Field value) {
        return mod(value);
    }

    // ------------------------------------------------------------------------
    // XXX: Bitwise operations
    // ------------------------------------------------------------------------
    // Unsafe casting is needed here, as bitwise operations only work on
    // numeric values...

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitNot() {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitNot((Field) this);
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitAnd(T value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitAnd((Field) this, (Field) val(value, this));
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitAnd(Field value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitAnd((Field) this, (Field) value);
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitNand(T value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitNand((Field) this, (Field) val(value, this));
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitNand(Field value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitNand((Field) this, (Field) value);
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitOr(T value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitOr((Field) this, (Field) val(value, this));
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitOr(Field value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitOr((Field) this, (Field) value);
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitNor(T value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitNor((Field) this, (Field) val(value, this));
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitNor(Field value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitNor((Field) this, (Field) value);
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitXor(T value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitXor((Field) this, (Field) val(value, this));
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitXor(Field value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitXor((Field) this, (Field) value);
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitXNor(T value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitXNor((Field) this, (Field) val(value, this));
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field bitXNor(Field value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.bitXNor((Field) this, (Field) value);
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field shl(Number value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.shl((Field) this, (Field) Tools.field(value));
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field shl(Field value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.shl((Field) this, value);
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field shr(Number value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.shr((Field) this, (Field) Tools.field(value));
        return result;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public final Field shr(Field value) {
        // Workaround assignment for https://bugs.eclipse.org/bugs/show_bug.cgi?id=473657
        final Field result = DSL.shr((Field) this, (Field) value);
        return result;
    }

    // ------------------------------------------------------------------------
    // XXX: Conditions created from this field
    // ------------------------------------------------------------------------

    @Override
    public final Condition isNull() {
        return new IsNull(this, true);
    }

    @Override
    public final Condition isNotNull() {
        return new IsNull(this, false);
    }

    @Override
    public final Condition isDistinctFrom(T value) {
        return isDistinctFrom(Tools.field(value, this));
    }

    @Override
    public final Condition isDistinctFrom(Field field) {
        return compare(IS_DISTINCT_FROM, field);
    }

    @Override
    public final Condition isNotDistinctFrom(T value) {
        return isNotDistinctFrom(Tools.field(value, this));
    }

    @Override
    public final Condition isNotDistinctFrom(Field field) {
        return compare(IS_NOT_DISTINCT_FROM, field);
    }

    @SuppressWarnings({ "unchecked" })
    @Override
    public final Condition isTrue() {
        Class type = getType();

        if (type == String.class)
            return ((Field) this).in(Tools.inline(TRUE_VALUES.toArray(EMPTY_STRING)));
        else if (Number.class.isAssignableFrom(type))
            return ((Field) this).equal(inline((Number) getDataType().convert(1)));
        else if (Boolean.class.isAssignableFrom(type))
            return ((Field) this).equal(inline(true));
        else
            return cast(String.class).in(TRUE_VALUES);
    }

    @SuppressWarnings({ "unchecked" })
    @Override
    public final Condition isFalse() {
        Class type = getType();

        if (type == String.class)
            return ((Field) this).in(Tools.inline(FALSE_VALUES.toArray(EMPTY_STRING)));
        else if (Number.class.isAssignableFrom(type))
            return ((Field) this).equal(inline((Number) getDataType().convert(0)));
        else if (Boolean.class.isAssignableFrom(type))
            return ((Field) this).equal(inline(false));
        else
            return cast(String.class).in(Tools.inline(FALSE_VALUES.toArray(EMPTY_STRING)));
    }

    @Override
    public final LikeEscapeStep like(String value) {
        return like(Tools.field(value, String.class));
    }

    @Override
    public final Condition like(String value, char escape) {
        return like(Tools.field(value, String.class), escape);
    }

    @Override
    public final LikeEscapeStep like(Field field) {
        return new CompareCondition(this, nullSafe(field, getDataType()), LIKE);
    }

    @Override
    public final Condition like(Field field, char escape) {
        return like(field).escape(escape);
    }

    @Override
    public final LikeEscapeStep likeIgnoreCase(String value) {
        return likeIgnoreCase(Tools.field(value, String.class));
    }

    @Override
    public final Condition likeIgnoreCase(String value, char escape) {
        return likeIgnoreCase(Tools.field(value, String.class), escape);
    }

    @Override
    public final LikeEscapeStep likeIgnoreCase(Field field) {
        return new CompareCondition(this, nullSafe(field, getDataType()), LIKE_IGNORE_CASE);
    }

    @Override
    public final Condition likeIgnoreCase(Field field, char escape) {
        return likeIgnoreCase(field).escape(escape);
    }

    @Override
    public final Condition likeRegex(String pattern) {
        return likeRegex(Tools.field(pattern, String.class));
    }

    @Override
    public final Condition likeRegex(Field pattern) {
        return new RegexpLike(this, nullSafe(pattern, getDataType()));
    }

    @Override
    public final LikeEscapeStep notLike(String value) {
        return notLike(Tools.field(value, String.class));
    }

    @Override
    public final Condition notLike(String value, char escape) {
        return notLike(Tools.field(value, String.class), escape);
    }

    @Override
    public final LikeEscapeStep notLike(Field field) {
        return new CompareCondition(this, nullSafe(field, getDataType()), NOT_LIKE);
    }

    @Override
    public final Condition notLike(Field field, char escape) {
        return notLike(field).escape(escape);
    }

    @Override
    public final LikeEscapeStep notLikeIgnoreCase(String value) {
        return notLikeIgnoreCase(Tools.field(value, String.class));
    }

    @Override
    public final Condition notLikeIgnoreCase(String value, char escape) {
        return notLikeIgnoreCase(Tools.field(value, String.class), escape);
    }

    @Override
    public final LikeEscapeStep notLikeIgnoreCase(Field field) {
        return new CompareCondition(this, nullSafe(field, getDataType()), NOT_LIKE_IGNORE_CASE);
    }

    @Override
    public final Condition notLikeIgnoreCase(Field field, char escape) {
        return notLikeIgnoreCase(field).escape(escape);
    }

    @Override
    public final Condition notLikeRegex(String pattern) {
        return likeRegex(pattern).not();
    }

    @Override
    public final Condition notLikeRegex(Field pattern) {
        return likeRegex(pattern).not();
    }

    @Override
    public final Condition contains(T value) {
        return new Contains(this, value);
    }

    @Override
    public final Condition contains(Field value) {
        return new Contains(this, value);
    }

    @Override
    public final Condition startsWith(T value) {
        Field concat = DSL.concat(Tools.escapeForLike(value), inline("%"));
        return like(concat, Tools.ESCAPE);
    }

    @Override
    public final Condition startsWith(Field value) {
        Field concat = DSL.concat(Tools.escapeForLike(value), inline("%"));
        return like(concat, Tools.ESCAPE);
    }

    @Override
    public final Condition endsWith(T value) {
        Field concat = DSL.concat(inline("%"), Tools.escapeForLike(value));
        return like(concat, Tools.ESCAPE);
    }

    @Override
    public final Condition endsWith(Field value) {
        Field concat = DSL.concat(inline("%"), Tools.escapeForLike(value));
        return like(concat, Tools.ESCAPE);
    }

    private final boolean isAccidentalSelect(T[] values) {
        return (values != null && values.length == 1 && values[0] instanceof Select);
    }

    private final boolean isAccidentalCollection(T[] values) {
        return (values != null && values.length == 1 && values[0] instanceof Collection);
    }

    @SuppressWarnings("unchecked")
    @Override
    public final Condition in(T... values) {

        // [#3362] Prevent "rogue" API usage when using Field.in(Object... values)
        if (isAccidentalSelect(values))
            return in((Select>) values[0]);

        // [#3347] Prevent "rogue" API usage when using Field.in(Object... values)
        if (isAccidentalCollection(values))
            return in((Collection) values[0]);

        return in(Tools.fields(values, this).toArray(EMPTY_FIELD));
    }

    @Override
    public final Condition in(Field... values) {
        return new InCondition(this, nullSafe(values), IN);
    }

    @Override
    public final Condition in(Collection values) {
        List> fields = new ArrayList>();

        for (Object value : values)
            fields.add(Tools.field(value, this));

        return in(fields.toArray(EMPTY_FIELD));
    }

    @Override
    public final Condition in(Result> result) {
        return in(result.getValues(0, getType()));
    }

    @Override
    public final Condition in(Select> query) {
        return compare(IN, query);
    }

    @SuppressWarnings("unchecked")
    @Override
    public final Condition notIn(T... values) {

        // [#3362] Prevent "rogue" API usage when using Field.in(Object... values)
        if (isAccidentalSelect(values))
            return notIn((Select>) values[0]);

        // [#3347] Prevent "rogue" API usage when using Field.in(Object... values)
        if (isAccidentalCollection(values))
            return notIn((Collection) values[0]);

        return notIn(Tools.fields(values, this).toArray(EMPTY_FIELD));
    }

    @Override
    public final Condition notIn(Field... values) {
        return new InCondition(this, nullSafe(values), NOT_IN);
    }

    @Override
    public final Condition notIn(Collection values) {
        List> fields = new ArrayList>();

        for (Object value : values)
            fields.add(Tools.field(value, this));

        return notIn(fields.toArray(EMPTY_FIELD));
    }

    @Override
    public final Condition notIn(Result> result) {
        return notIn(result.getValues(0, getType()));
    }

    @Override
    public final Condition notIn(Select> query) {
        return compare(NOT_IN, query);
    }

    @Override
    public final Condition between(T minValue, T maxValue) {
        return between(Tools.field(minValue, this), Tools.field(maxValue, this));
    }

    @Override
    public final Condition between(Field minValue, Field maxValue) {
        return between(nullSafe(minValue, getDataType())).and(nullSafe(maxValue, getDataType()));
    }

    @Override
    public final Condition betweenSymmetric(T minValue, T maxValue) {
        return betweenSymmetric(Tools.field(minValue, this), Tools.field(maxValue, this));
    }

    @Override
    public final Condition betweenSymmetric(Field minValue, Field maxValue) {
        return betweenSymmetric(nullSafe(minValue, getDataType())).and(nullSafe(maxValue, getDataType()));
    }

    @Override
    public final Condition notBetween(T minValue, T maxValue) {
        return notBetween(Tools.field(minValue, this), Tools.field(maxValue, this));
    }

    @Override
    public final Condition notBetween(Field minValue, Field maxValue) {
        return notBetween(nullSafe(minValue, getDataType())).and(nullSafe(maxValue, getDataType()));
    }

    @Override
    public final Condition notBetweenSymmetric(T minValue, T maxValue) {
        return notBetweenSymmetric(Tools.field(minValue, this), Tools.field(maxValue, this));
    }

    @Override
    public final Condition notBetweenSymmetric(Field minValue, Field maxValue) {
        return notBetweenSymmetric(nullSafe(minValue, getDataType())).and(nullSafe(maxValue, getDataType()));
    }

    @Override
    public final BetweenAndStep between(T minValue) {
        return between(Tools.field(minValue, this));
    }

    @Override
    public final BetweenAndStep between(Field minValue) {
        return new BetweenCondition(this, nullSafe(minValue, getDataType()), false, false);
    }

    @Override
    public final BetweenAndStep betweenSymmetric(T minValue) {
        return betweenSymmetric(Tools.field(minValue, this));
    }

    @Override
    public final BetweenAndStep betweenSymmetric(Field minValue) {
        return new BetweenCondition(this, nullSafe(minValue, getDataType()), false, true);
    }

    @Override
    public final BetweenAndStep notBetween(T minValue) {
        return notBetween(Tools.field(minValue, this));
    }

    @Override
    public final BetweenAndStep notBetween(Field minValue) {
        return new BetweenCondition(this, nullSafe(minValue, getDataType()), true, false);
    }

    @Override
    public final BetweenAndStep notBetweenSymmetric(T minValue) {
        return notBetweenSymmetric(Tools.field(minValue, this));
    }

    @Override
    public final BetweenAndStep notBetweenSymmetric(Field minValue) {
        return new BetweenCondition(this, nullSafe(minValue, getDataType()), true, true);
    }

    @Override
    public final Condition eq(T value) {
        return equal(value);
    }

    @Override
    public final Condition eq(Field field) {
        return equal(field);
    }

    @Override
    public final Condition eq(Select> query) {
        return equal(query);
    }

    @Override
    public final Condition eq(QuantifiedSelect> query) {
        return equal(query);
    }

    @Override
    public final Condition ne(T value) {
        return notEqual(value);
    }

    @Override
    public final Condition ne(Field field) {
        return notEqual(field);
    }

    @Override
    public final Condition ne(Select> query) {
        return notEqual(query);
    }

    @Override
    public final Condition ne(QuantifiedSelect> query) {
        return notEqual(query);
    }

    @Override
    public final Condition lt(T value) {
        return lessThan(value);
    }

    @Override
    public final Condition lt(Field field) {
        return lessThan(field);
    }

    @Override
    public final Condition lt(Select> query) {
        return lessThan(query);
    }

    @Override
    public final Condition lt(QuantifiedSelect> query) {
        return lessThan(query);
    }

    @Override
    public final Condition le(T value) {
        return lessOrEqual(value);
    }

    @Override
    public final Condition le(Field field) {
        return lessOrEqual(field);
    }

    @Override
    public final Condition le(Select> query) {
        return lessOrEqual(query);
    }

    @Override
    public final Condition le(QuantifiedSelect> query) {
        return lessOrEqual(query);
    }

    @Override
    public final Condition gt(T value) {
        return greaterThan(value);
    }

    @Override
    public final Condition gt(Field field) {
        return greaterThan(field);
    }

    @Override
    public final Condition gt(Select> query) {
        return greaterThan(query);
    }

    @Override
    public final Condition gt(QuantifiedSelect> query) {
        return greaterThan(query);
    }

    @Override
    public final Condition ge(T value) {
        return greaterOrEqual(value);
    }

    @Override
    public final Condition ge(Field field) {
        return greaterOrEqual(field);
    }

    @Override
    public final Condition ge(Select> query) {
        return greaterOrEqual(query);
    }

    @Override
    public final Condition ge(QuantifiedSelect> query) {
        return greaterOrEqual(query);
    }

    @Override
    public final Condition equal(T value) {
        return equal(Tools.field(value, this));
    }

    @Override
    public final Condition equal(Field field) {
        return compare(EQUALS, nullSafe(field, getDataType()));
    }

    @Override
    public final Condition equalIgnoreCase(String value) {
        return equalIgnoreCase(Tools.field(value, String.class));
    }

    @Override
    public final Condition equalIgnoreCase(Field value) {
        return DSL.lower(cast(String.class)).equal(DSL.lower(value));
    }

    @Override
    public final Condition equal(Select> query) {
        return compare(EQUALS, query);
    }

    @Override
    public final Condition equal(QuantifiedSelect> query) {
        return compare(EQUALS, query);
    }

    @Override
    public final Condition notEqual(T value) {
        return notEqual(Tools.field(value, this));
    }

    @Override
    public final Condition notEqual(Field field) {
        return compare(NOT_EQUALS, nullSafe(field, getDataType()));
    }

    @Override
    public final Condition notEqualIgnoreCase(String value) {
        return notEqualIgnoreCase(Tools.field(value, String.class));
    }

    @Override
    public final Condition notEqualIgnoreCase(Field value) {
        return DSL.lower(cast(String.class)).notEqual(DSL.lower(value));
    }

    @Override
    public final Condition notEqual(Select> query) {
        return compare(NOT_EQUALS, query);
    }

    @Override
    public final Condition notEqual(QuantifiedSelect> query) {
        return compare(NOT_EQUALS, query);
    }

    @Override
    public final Condition lessThan(T value) {
        return lessThan(Tools.field(value, this));
    }

    @Override
    public final Condition lessThan(Field field) {
        return compare(LESS, nullSafe(field, getDataType()));
    }

    @Override
    public final Condition lessThan(Select> query) {
        return compare(LESS, query);
    }

    @Override
    public final Condition lessThan(QuantifiedSelect> query) {
        return compare(LESS, query);
    }

    @Override
    public final Condition lessOrEqual(T value) {
        return lessOrEqual(Tools.field(value, this));
    }

    @Override
    public final Condition lessOrEqual(Field field) {
        return compare(LESS_OR_EQUAL, nullSafe(field, getDataType()));
    }

    @Override
    public final Condition lessOrEqual(Select> query) {
        return compare(LESS_OR_EQUAL, query);
    }

    @Override
    public final Condition lessOrEqual(QuantifiedSelect> query) {
        return compare(LESS_OR_EQUAL, query);
    }

    @Override
    public final Condition greaterThan(T value) {
        return greaterThan(Tools.field(value, this));
    }

    @Override
    public final Condition greaterThan(Field field) {
        return compare(GREATER, nullSafe(field, getDataType()));
    }

    @Override
    public final Condition greaterThan(Select> query) {
        return compare(GREATER, query);
    }

    @Override
    public final Condition greaterThan(QuantifiedSelect> query) {
        return compare(GREATER, query);
    }

    @Override
    public final Condition greaterOrEqual(T value) {
        return greaterOrEqual(Tools.field(value, this));
    }

    @Override
    public final Condition greaterOrEqual(Field field) {
        return compare(GREATER_OR_EQUAL, nullSafe(field, getDataType()));
    }

    @Override
    public final Condition greaterOrEqual(Select> query) {
        return compare(GREATER_OR_EQUAL, query);
    }

    @Override
    public final Condition greaterOrEqual(QuantifiedSelect> query) {
        return compare(GREATER_OR_EQUAL, query);
    }

    @Override
    public final Condition compare(Comparator comparator, T value) {
        return compare(comparator, Tools.field(value, this));
    }

    @Override
    public final Condition compare(Comparator comparator, Field field) {
        switch (comparator) {
            case IS_DISTINCT_FROM:
            case IS_NOT_DISTINCT_FROM:
                return new IsDistinctFrom(this, nullSafe(field, getDataType()), comparator);

            default:
                return new CompareCondition(this, nullSafe(field, getDataType()), comparator);
        }
    }

    @Override
    public final Condition compare(Comparator comparator, Select> query) {
        return compare(comparator, new ScalarSubquery(query, getDataType()));
    }

    @Override
    public final Condition compare(Comparator comparator, QuantifiedSelect> query) {
        return new QuantifiedComparisonCondition(query, this, comparator);
    }








    // ------------------------------------------------------------------------
    // XXX: Pre-2.0 API. This API is maintained for backwards-compatibility. It
    // will be removed in the future. Consider using equivalent methods from
    // org.jooq.impl.DSL
    // ------------------------------------------------------------------------

    @SuppressWarnings("unchecked")
    private final  Field numeric() {
        if (getDataType().isNumeric()) {
            return (Field) this;
        }
        else {
            return (Field) cast(BigDecimal.class);
        }
    }

    @SuppressWarnings("unchecked")
    private final Field varchar() {
        if (getDataType().isString()) {
            return (Field) this;
        }
        else {
            return cast(String.class);
        }
    }

    @SuppressWarnings("unchecked")
    private final  Field date() {
        if (getDataType().isTemporal()) {
            return (Field) this;
        }
        else {
            return (Field) cast(Timestamp.class);
        }
    }

    @Override
    @Deprecated
    public final Field sign() {
        return DSL.sign(numeric());
    }

    @SuppressWarnings("unchecked")
    @Override
    @Deprecated
    public final Field abs() {
        return (Field) DSL.abs(numeric());
    }

    @SuppressWarnings("unchecked")
    @Override
    @Deprecated
    public final Field round() {
        return (Field) DSL.round(numeric());
    }

    @SuppressWarnings("unchecked")
    @Override
    @Deprecated
    public final Field round(int decimals) {
        return (Field) DSL.round(numeric(), decimals);
    }

    @SuppressWarnings("unchecked")
    @Override
    @Deprecated
    public final Field floor() {
        return (Field) DSL.floor(numeric());
    }

    @SuppressWarnings("unchecked")
    @Override
    @Deprecated
    public final Field ceil() {
        return (Field) DSL.ceil(numeric());
    }

    @Override
    @Deprecated
    public final Field sqrt() {
        return DSL.sqrt(numeric());
    }

    @Override
    @Deprecated
    public final Field exp() {
        return DSL.exp(numeric());
    }

    @Override
    @Deprecated
    public final Field ln() {
        return DSL.ln(numeric());
    }

    @Override
    @Deprecated
    public final Field log(int base) {
        return DSL.log(numeric(), base);
    }

    @Override
    public final Field pow(Number exponent) {
        return DSL.power(numeric(), exponent);
    }

    @Override
    @Deprecated
    public final Field power(Number exponent) {
        return pow(exponent);
    }

    @Override
    @Deprecated
    public final Field acos() {
        return DSL.acos(numeric());
    }

    @Override
    @Deprecated
    public final Field asin() {
        return DSL.asin(numeric());
    }

    @Override
    @Deprecated
    public final Field atan() {
        return DSL.atan(numeric());
    }

    @Override
    @Deprecated
    public final Field atan2(Number y) {
        return DSL.atan2(numeric(), y);
    }

    @Override
    @Deprecated
    public final Field atan2(Field y) {
        return DSL.atan2(numeric(), y);
    }

    @Override
    @Deprecated
    public final Field cos() {
        return DSL.cos(numeric());
    }

    @Override
    @Deprecated
    public final Field sin() {
        return DSL.sin(numeric());
    }

    @Override
    @Deprecated
    public final Field tan() {
        return DSL.tan(numeric());
    }

    @Override
    @Deprecated
    public final Field cot() {
        return DSL.cot(numeric());
    }

    @Override
    @Deprecated
    public final Field sinh() {
        return DSL.sinh(numeric());
    }

    @Override
    @Deprecated
    public final Field cosh() {
        return DSL.cosh(numeric());
    }

    @Override
    @Deprecated
    public final Field tanh() {
        return DSL.tanh(numeric());
    }

    @Override
    @Deprecated
    public final Field coth() {
        return DSL.coth(numeric());
    }

    @Override
    @Deprecated
    public final Field deg() {
        return DSL.deg(numeric());
    }

    @Override
    @Deprecated
    public final Field rad() {
        return DSL.rad(numeric());
    }

    @Override
    @Deprecated
    public final Field count() {
        return DSL.count(this);
    }

    @Override
    @Deprecated
    public final Field countDistinct() {
        return DSL.countDistinct(this);
    }

    @Override
    @Deprecated
    public final Field max() {
        return DSL.max(this);
    }

    @Override
    @Deprecated
    public final Field min() {
        return DSL.min(this);
    }

    @Override
    @Deprecated
    public final Field sum() {
        return DSL.sum(numeric());
    }

    @Override
    @Deprecated
    public final Field avg() {
        return DSL.avg(numeric());
    }

    @Override
    @Deprecated
    public final Field median() {
        return DSL.median(numeric());
    }

    @Override
    @Deprecated
    public final Field stddevPop() {
        return DSL.stddevPop(numeric());
    }

    @Override
    @Deprecated
    public final Field stddevSamp() {
        return DSL.stddevSamp(numeric());
    }

    @Override
    @Deprecated
    public final Field varPop() {
        return DSL.varPop(numeric());
    }

    @Override
    @Deprecated
    public final Field varSamp() {
        return DSL.varSamp(numeric());
    }

    @Override
    @Deprecated
    public final WindowPartitionByStep countOver() {
        return DSL.count(this).over();
    }

    @Override
    @Deprecated
    public final WindowPartitionByStep maxOver() {
        return DSL.max(this).over();
    }

    @Override
    @Deprecated
    public final WindowPartitionByStep minOver() {
        return DSL.min(this).over();
    }

    @Override
    @Deprecated
    public final WindowPartitionByStep sumOver() {
        return DSL.sum(numeric()).over();
    }

    @Override
    @Deprecated
    public final WindowPartitionByStep avgOver() {
        return DSL.avg(numeric()).over();
    }

    @Override
    @Deprecated
    public final WindowIgnoreNullsStep firstValue() {
        return DSL.firstValue(this);
    }

    @Override
    @Deprecated
    public final WindowIgnoreNullsStep lastValue() {
        return DSL.lastValue(this);
    }

    @Override
    @Deprecated
    public final WindowIgnoreNullsStep lead() {
        return DSL.lead(this);
    }

    @Override
    @Deprecated
    public final WindowIgnoreNullsStep lead(int offset) {
        return DSL.lead(this, offset);
    }

    @Override
    @Deprecated
    public final WindowIgnoreNullsStep lead(int offset, T defaultValue) {
        return DSL.lead(this, offset, defaultValue);
    }

    @Override
    @Deprecated
    public final WindowIgnoreNullsStep lead(int offset, Field defaultValue) {
        return DSL.lead(this, offset, defaultValue);
    }

    @Override
    @Deprecated
    public final WindowIgnoreNullsStep lag() {
        return DSL.lag(this);
    }

    @Override
    @Deprecated
    public final WindowIgnoreNullsStep lag(int offset) {
        return DSL.lag(this, offset);
    }

    @Override
    @Deprecated
    public final WindowIgnoreNullsStep lag(int offset, T defaultValue) {
        return DSL.lag(this, offset, defaultValue);
    }

    @Override
    @Deprecated
    public final WindowIgnoreNullsStep lag(int offset, Field defaultValue) {
        return DSL.lag(this, offset, defaultValue);
    }

    @Override
    @Deprecated
    public final WindowPartitionByStep stddevPopOver() {
        return DSL.stddevPop(numeric()).over();
    }

    @Override
    @Deprecated
    public final WindowPartitionByStep stddevSampOver() {
        return DSL.stddevSamp(numeric()).over();
    }

    @Override
    @Deprecated
    public final WindowPartitionByStep varPopOver() {
        return DSL.varPop(numeric()).over();
    }

    @Override
    @Deprecated
    public final WindowPartitionByStep varSampOver() {
        return DSL.varSamp(numeric()).over();
    }

    @Override
    @Deprecated
    public final Field upper() {
        return DSL.upper(varchar());
    }

    @Override
    @Deprecated
    public final Field lower() {
        return DSL.lower(varchar());
    }

    @Override
    @Deprecated
    public final Field trim() {
        return DSL.trim(varchar());
    }

    @Override
    @Deprecated
    public final Field rtrim() {
        return DSL.rtrim(varchar());
    }

    @Override
    @Deprecated
    public final Field ltrim() {
        return DSL.ltrim(varchar());
    }

    @Override
    @Deprecated
    public final Field rpad(Field length) {
        return DSL.rpad(varchar(), length);
    }

    @Override
    @Deprecated
    public final Field rpad(int length) {
        return DSL.rpad(varchar(), length);
    }

    @Override
    @Deprecated
    public final Field rpad(Field length, Field character) {
        return DSL.rpad(varchar(), length, character);
    }

    @Override
    @Deprecated
    public final Field rpad(int length, char character) {
        return DSL.rpad(varchar(), length, character);
    }

    @Override
    @Deprecated
    public final Field lpad(Field length) {
        return DSL.lpad(varchar(), length);
    }

    @Override
    @Deprecated
    public final Field lpad(int length) {
        return DSL.lpad(varchar(), length);
    }

    @Override
    @Deprecated
    public final Field lpad(Field length, Field character) {
        return DSL.lpad(varchar(), length, character);
    }

    @Override
    @Deprecated
    public final Field lpad(int length, char character) {
        return DSL.lpad(varchar(), length, character);
    }

    @Override
    @Deprecated
    public final Field repeat(Number count) {
        return DSL.repeat(varchar(), count == null ? 0 : count.intValue());
    }

    @Override
    @Deprecated
    public final Field repeat(Field count) {
        return DSL.repeat(varchar(), count);
    }

    @Override
    @Deprecated
    public final Field replace(Field search) {
        return DSL.replace(varchar(), search);
    }

    @Override
    @Deprecated
    public final Field replace(String search) {
        return DSL.replace(varchar(), search);
    }

    @Override
    @Deprecated
    public final Field replace(Field search, Field replace) {
        return DSL.replace(varchar(), search, replace);
    }

    @Override
    @Deprecated
    public final Field replace(String search, String replace) {
        return DSL.replace(varchar(), search, replace);
    }

    @Override
    @Deprecated
    public final Field position(String search) {
        return DSL.position(varchar(), search);
    }

    @Override
    @Deprecated
    public final Field position(Field search) {
        return DSL.position(varchar(), search);
    }

    @Override
    @Deprecated
    public final Field ascii() {
        return DSL.ascii(varchar());
    }

    @Override
    @Deprecated
    public final Field concat(Field... fields) {
        return DSL.concat(Tools.combine(this, fields));
    }

    @Override
    @Deprecated
    public final Field concat(String... values) {
        return DSL.concat(Tools.combine(this, Tools.fields(values).toArray(EMPTY_FIELD)));
    }

    @Override
    @Deprecated
    public final Field substring(int startingPosition) {
        return DSL.substring(varchar(), startingPosition);
    }

    @Override
    @Deprecated
    public final Field substring(Field startingPosition) {
        return DSL.substring(varchar(), startingPosition);
    }

    @Override
    @Deprecated
    public final Field substring(int startingPosition, int length) {
        return DSL.substring(varchar(), startingPosition, length);
    }

    @Override
    @Deprecated
    public final Field substring(Field startingPosition, Field length) {
        return DSL.substring(varchar(), startingPosition, length);
    }

    @Override
    @Deprecated
    public final Field length() {
        return DSL.length(varchar());
    }

    @Override
    @Deprecated
    public final Field charLength() {
        return DSL.charLength(varchar());
    }

    @Override
    @Deprecated
    public final Field bitLength() {
        return DSL.bitLength(varchar());
    }

    @Override
    @Deprecated
    public final Field octetLength() {
        return DSL.octetLength(varchar());
    }

    @Override
    @Deprecated
    public final Field extract(DatePart datePart) {
        return DSL.extract(date(), datePart);
    }

    @Override
    @Deprecated

    @SafeVarargs

    public final Field greatest(T... others) {
        return DSL.greatest(this, Tools.fields(others).toArray(EMPTY_FIELD));
    }

    @Override
    @Deprecated
    public final Field greatest(Field... others) {
        return DSL.greatest(this, others);
    }

    @Override
    @Deprecated

    @SafeVarargs

    public final Field least(T... others) {
        return DSL.least(this, Tools.fields(others).toArray(EMPTY_FIELD));
    }

    @Override
    @Deprecated
    public final Field least(Field... others) {
        return DSL.least(this, others);
    }

    @Override
    @Deprecated
    public final Field nvl(T defaultValue) {
        return DSL.nvl(this, defaultValue);
    }

    @Override
    @Deprecated
    public final Field nvl(Field defaultValue) {
        return DSL.nvl(this, defaultValue);
    }

    @Override
    @Deprecated
    public final  Field nvl2(Z valueIfNotNull, Z valueIfNull) {
        return DSL.nvl2(this, valueIfNotNull, valueIfNull);
    }

    @Override
    @Deprecated
    public final  Field nvl2(Field valueIfNotNull, Field valueIfNull) {
        return DSL.nvl2(this, valueIfNotNull, valueIfNull);
    }

    @Override
    @Deprecated
    public final Field nullif(T other) {
        return DSL.nullif(this, other);
    }

    @Override
    @Deprecated
    public final Field nullif(Field other) {
        return DSL.nullif(this, other);
    }

    @Override
    @Deprecated
    public final  Field decode(T search, Z result) {
        return DSL.decode(this, search, result);
    }

    @Override
    @Deprecated
    public final  Field decode(T search, Z result, Object... more) {
        return DSL.decode(this, search, result, more);
    }

    @Override
    @Deprecated
    public final  Field decode(Field search, Field result) {
        return DSL.decode(this, search, result);
    }

    @Override
    @Deprecated
    public final  Field decode(Field search, Field result, Field... more) {
        return DSL.decode(this, search, result, more);
    }

    @Override
    @Deprecated

    @SafeVarargs

    public final Field coalesce(T option, T... options) {
        return DSL.coalesce(this, Tools.combine(Tools.field(option), Tools.fields(options).toArray(EMPTY_FIELD)));
    }

    @Override
    @Deprecated
    public final Field coalesce(Field option, Field... options) {
        return DSL.coalesce(this, Tools.combine(option, options));
    }

    // ------------------------------------------------------------------------
    // XXX: Object API
    // ------------------------------------------------------------------------

    @Override
    public boolean equals(Object that) {
        if (this == that) {
            return true;
        }

        // [#2144] Non-equality can be decided early, without executing the
        // rather expensive implementation of AbstractQueryPart.equals()
        if (that instanceof AbstractField) {
            if (StringUtils.equals(name, (((AbstractField) that).name))) {
                return super.equals(that);
            }

            return false;
        }

        return false;
    }

    @Override
    public int hashCode() {

        // [#1938] This is a much more efficient hashCode() implementation
        // compared to that of standard QueryParts
        return name.hashCode();
    }
}