<commit_before>/*
// $Id$
// Package org.eigenbase is a class library of data management components.
// Copyright (C) 2005-2007 The Eigenbase Project
// Copyright (C) 2002-2007 Disruptive Tech
// Copyright (C) 2005-2007 LucidEra, Inc.
// Portions Copyright (C) 2003-2007 <NAME>
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version approved by The Eigenbase Project.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package org.eigenbase.sql.fun;

import org.eigenbase.reltype.*;
import org.eigenbase.resource.*;
import org.eigenbase.sql.*;
import org.eigenbase.sql.type.*;


/**
 * SqlCastFunction. Note that the std functions are really singleton objects,
 * because they always get fetched via the StdOperatorTable. So you can't story
 * any local info in the class and hence the return type data is maintained in
 * operand[1] through the validation phase.
 *
 * @author lee
 * @version $Id$
 * @since Jun 5, 2004
 */
public class SqlCastFunction
    extends SqlFunction
{
    //~ Constructors -----------------------------------------------------------

    public SqlCastFunction()
    {
        super(
            "CAST",
            SqlKind.Cast,
            null,
            SqlTypeStrategies.otiFirstKnown,
            null,
            SqlFunctionCategory.System);
    }

    //~ Methods ----------------------------------------------------------------

    public RelDataType inferReturnType(
        SqlOperatorBinding opBinding)
    {
        assert (opBinding.getOperandCount() == 2);
        RelDataType ret = opBinding.getOperandType(1);
        RelDataType firstType = opBinding.getOperandType(0);
        ret =
            opBinding.getTypeFactory().createTypeWithNullability(
                ret,
                firstType.isNullable());
        if (opBinding instanceof SqlCallBinding) {
            SqlCallBinding callBinding = (SqlCallBinding) opBinding;
            SqlNode operand0 = callBinding.getCall().operands[0];

            // dynamic parameters and null constants need their types asssigned
            // to them using the type they are casted to.
            if (((operand0 instanceof SqlLiteral)
                    && (((SqlLiteral) operand0).getValue() == null))
                || (operand0 instanceof SqlDynamicParam))
            {
                callBinding.getValidator().setValidatedNodeType(
                    operand0,
                    ret);
            }
        }
        return ret;
    }

    public String getSignatureTemplate(final int operandsCount)
    {
        switch (operandsCount) {
        case 2:
            return "{0}({1} AS {2})";
        }
        assert (false);
        return null;
    }

    public SqlOperandCountRange getOperandCountRange()
    {
        return SqlOperandCountRange.Two;
    }

    /**
     * Makes sure that the number and types of arguments are allowable.
     * Operators (such as "ROW" and "AS") which do not check their arguments can
     * override this method.
     */
    public boolean checkOperandTypes(
        SqlCallBinding callBinding,
        boolean throwOnFailure)
    {
        if (SqlUtil.isNullLiteral(callBinding.getCall().operands[0], false)) {
            return true;
        }
        RelDataType validatedNodeType =
            callBinding.getValidator().getValidatedNodeType(
                callBinding.getCall().operands[0]);
        RelDataType returnType =
            callBinding.getValidator().deriveType(
                callBinding.getScope(),
                callBinding.getCall().operands[1]);
        if (!SqlTypeUtil.canCastFrom(returnType, validatedNodeType, true)) {
            if (throwOnFailure) {
                throw callBinding.newError(
                    EigenbaseResource.instance().CannotCastValue.ex(
                        validatedNodeType.toString(),
                        returnType.toString()));
            }
            return false;
        }
        return true;
    }

    public SqlSyntax getSyntax()
    {
        return SqlSyntax.Special;
    }

    public void unparse(
        SqlWriter writer,
        SqlNode [] operands,
        int leftPrec,
        int rightPrec)
    {
        assert operands.length == 2;
        final SqlWriter.Frame frame = writer.startFunCall(getName());
        operands[0].unparse(writer, 0, 0);
        writer.sep("AS");
        if (operands[1] instanceof SqlIntervalQualifier) {
            writer.sep("INTERVAL");
        }
        operands[1].unparse(writer, 0, 0);
        writer.endFunCall(frame);
    }
}

// End SqlCastFunction.java
<commit_msg>FARRAGO: Check casts for monotonicity<commit_after>/*
// $Id$
// Package org.eigenbase is a class library of data management components.
// Copyright (C) 2005-2007 The Eigenbase Project
// Copyright (C) 2002-2007 Disruptive Tech
// Copyright (C) 2005-2007 LucidEra, Inc.
// Portions Copyright (C) 2003-2007 <NAME>
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version approved by The Eigenbase Project.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package org.eigenbase.sql.fun;

import java.util.HashSet;
import java.util.Set;

import org.eigenbase.reltype.*;
import org.eigenbase.resource.*;
import org.eigenbase.sql.*;
import org.eigenbase.sql.type.*;
import org.eigenbase.sql.validate.SqlMonotonicity;
import org.eigenbase.sql.validate.SqlValidatorScope;


/**
 * SqlCastFunction. Note that the std functions are really singleton objects,
 * because they always get fetched via the StdOperatorTable. So you can't story
 * any local info in the class and hence the return type data is maintained in
 * operand[1] through the validation phase.
 *
 * @author lee
 * @version $Id$
 * @since Jun 5, 2004
 */
public class SqlCastFunction
    extends SqlFunction
{
    private class TypeFamilyCast
    {
        private final RelDataTypeFamily castFrom;
        private final RelDataTypeFamily castTo;

        public TypeFamilyCast(
            RelDataTypeFamily castFrom,
            RelDataTypeFamily castTo)
        {
            this.castFrom = castFrom;
            this.castTo = castTo;
        }
        @Override
        public boolean equals(Object obj)
        {
            // TODO Auto-generated method stub
            if (obj.getClass()!=TypeFamilyCast.class) return false;
            TypeFamilyCast other = (TypeFamilyCast) obj;
            return this.castFrom.equals(other.castFrom)
                && this.castTo.equals(other.castTo);
        }
        @Override
        public int hashCode()
        {
            // TODO Auto-generated method stub
            return castFrom.hashCode()+castTo.hashCode();
        }  
    }
    private final Set<TypeFamilyCast> nonMonotonicPreservingCasts =
        createNonMonotonicPreservingCasts();

    //~ Constructors -----------------------------------------------------------

    public SqlCastFunction()
    {
        super(
            "CAST",
            SqlKind.Cast,
            null,
            SqlTypeStrategies.otiFirstKnown,
            null,
            SqlFunctionCategory.System);
    }

    //~ Methods ----------------------------------------------------------------

    /*
     * List all casts that do not preserve monotonicity
     */
    private Set<TypeFamilyCast> createNonMonotonicPreservingCasts()
    {
        Set<TypeFamilyCast> result = new HashSet<TypeFamilyCast>();
        result.add(new TypeFamilyCast(
            SqlTypeFamily.EXACT_NUMERIC,
            SqlTypeFamily.CHARACTER));
        result.add(new TypeFamilyCast(
            SqlTypeFamily.NUMERIC,
            SqlTypeFamily.CHARACTER));
        result.add(new TypeFamilyCast(
            SqlTypeFamily.APPROXIMATE_NUMERIC,
            SqlTypeFamily.CHARACTER));
        result.add(new TypeFamilyCast(
            SqlTypeFamily.DATETIME_INTERVAL,
            SqlTypeFamily.CHARACTER));
        result.add(new TypeFamilyCast(
            SqlTypeFamily.CHARACTER,
            SqlTypeFamily.EXACT_NUMERIC));
        result.add(new TypeFamilyCast(
            SqlTypeFamily.CHARACTER,
            SqlTypeFamily.NUMERIC));
        result.add(new TypeFamilyCast(
            SqlTypeFamily.CHARACTER,
            SqlTypeFamily.APPROXIMATE_NUMERIC));
        result.add(new TypeFamilyCast(
            SqlTypeFamily.CHARACTER,
            SqlTypeFamily.DATETIME_INTERVAL));
        result.add(new TypeFamilyCast(
            SqlTypeFamily.DATETIME,
            SqlTypeFamily.TIME));
        result.add(new TypeFamilyCast(
            SqlTypeFamily.TIMESTAMP,
            SqlTypeFamily.TIME));
        result.add(new TypeFamilyCast(
            SqlTypeFamily.TIME,
            SqlTypeFamily.DATETIME));
        result.add(new TypeFamilyCast(
            SqlTypeFamily.TIME,
            SqlTypeFamily.TIMESTAMP));
        return result;
    }
    
    private boolean isMonotonicPreservingCast(
        RelDataTypeFamily castFrom,
        RelDataTypeFamily castTo)
    {
        return !nonMonotonicPreservingCasts.contains(
            new TypeFamilyCast(castFrom, castTo));
    }
    
    public RelDataType inferReturnType(
        SqlOperatorBinding opBinding)
    {
        assert (opBinding.getOperandCount() == 2);
        RelDataType ret = opBinding.getOperandType(1);
        RelDataType firstType = opBinding.getOperandType(0);
        ret =
            opBinding.getTypeFactory().createTypeWithNullability(
                ret,
                firstType.isNullable());
        if (opBinding instanceof SqlCallBinding) {
            SqlCallBinding callBinding = (SqlCallBinding) opBinding;
            SqlNode operand0 = callBinding.getCall().operands[0];

            // dynamic parameters and null constants need their types asssigned
            // to them using the type they are casted to.
            if (((operand0 instanceof SqlLiteral)
                    && (((SqlLiteral) operand0).getValue() == null))
                || (operand0 instanceof SqlDynamicParam))
            {
                callBinding.getValidator().setValidatedNodeType(
                    operand0,
                    ret);
            }
        }
        return ret;
    }

    public String getSignatureTemplate(final int operandsCount)
    {
        switch (operandsCount) {
        case 2:
            return "{0}({1} AS {2})";
        }
        assert (false);
        return null;
    }

    public SqlOperandCountRange getOperandCountRange()
    {
        return SqlOperandCountRange.Two;
    }

    /**
     * Makes sure that the number and types of arguments are allowable.
     * Operators (such as "ROW" and "AS") which do not check their arguments can
     * override this method.
     */
    public boolean checkOperandTypes(
        SqlCallBinding callBinding,
        boolean throwOnFailure)
    {
        if (SqlUtil.isNullLiteral(callBinding.getCall().operands[0], false)) {
            return true;
        }
        RelDataType validatedNodeType =
            callBinding.getValidator().getValidatedNodeType(
                callBinding.getCall().operands[0]);
        RelDataType returnType =
            callBinding.getValidator().deriveType(
                callBinding.getScope(),
                callBinding.getCall().operands[1]);
        if (!SqlTypeUtil.canCastFrom(returnType, validatedNodeType, true)) {
            if (throwOnFailure) {
                throw callBinding.newError(
                    EigenbaseResource.instance().CannotCastValue.ex(
                        validatedNodeType.toString(),
                        returnType.toString()));
            }
            return false;
        }
        return true;
    }

    public SqlSyntax getSyntax()
    {
        return SqlSyntax.Special;
    }

    public void unparse(
        SqlWriter writer,
        SqlNode [] operands,
        int leftPrec,
        int rightPrec)
    {
        assert operands.length == 2;
        final SqlWriter.Frame frame = writer.startFunCall(getName());
        operands[0].unparse(writer, 0, 0);
        writer.sep("AS");
        if (operands[1] instanceof SqlIntervalQualifier) {
            writer.sep("INTERVAL");
        }
        operands[1].unparse(writer, 0, 0);
        writer.endFunCall(frame);
    }

    @Override
    public SqlMonotonicity getMonotonicity(SqlCall call, SqlValidatorScope scope)
    {
        RelDataTypeFamily castFrom =
            scope.getValidator().deriveType(scope, call.operands[0]).getFamily();
        RelDataTypeFamily castTo =
            scope.getValidator().deriveType(scope, call.operands[1]).getFamily();
        if (isMonotonicPreservingCast(castFrom, castTo)) {
            return call.operands[0].getMonotonicity(scope);
        } else {
            return SqlMonotonicity.NotMonotonic;
        }
    }
}

// End SqlCastFunction.java

{'fraction_non_alphanumeric': 0.10288627225732337, 'fraction_numerical': 0.011272257323377369, 'mean_word_length': 2.045255793616091, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2364607', 'n_tokens_mistral': 3727, 'n_tokens_neox': 3588, 'n_words': 992}