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

org.hsqldb.FunctionSQL Maven / Gradle / Ivy

There is a newer version: 2.7.4
Show newest version
/* Copyright (c) 2001-2021, The HSQL Development Group
 * All rights reserved.
 *
 * 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 of the HSQL Development Group 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 HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * 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.hsqldb;

import org.hsqldb.ParserDQL.CompileContext;
import org.hsqldb.error.Error;
import org.hsqldb.error.ErrorCode;
import org.hsqldb.lib.IntValueHashMap;
import org.hsqldb.lib.OrderedIntHashSet;
import org.hsqldb.map.ValuePool;
import org.hsqldb.types.BinaryData;
import org.hsqldb.types.BinaryType;
import org.hsqldb.types.BlobData;
import org.hsqldb.types.CharacterType;
import org.hsqldb.types.DTIType;
import org.hsqldb.types.DateTimeType;
import org.hsqldb.types.IntervalType;
import org.hsqldb.types.NumberType;
import org.hsqldb.types.Type;
import org.hsqldb.types.Types;

/**
 * Implementation of SQL standard function calls
 *
 * @author Fred Toussi (fredt@users dot sourceforge.net)
 * @version 2.6.0
 * @since 1.9.0
 */
public class FunctionSQL extends Expression {

    protected static final int FUNC_POSITION_CHAR                    = 1;     // numeric
    private static final int   FUNC_POSITION_BINARY                  = 2;
    private static final int   FUNC_OCCURENCES_REGEX                 = 3;
    private static final int   FUNC_POSITION_REGEX                   = 4;
    protected static final int FUNC_EXTRACT                          = 5;
    protected static final int FUNC_BIT_LENGTH                       = 6;
    protected static final int FUNC_CHAR_LENGTH                      = 7;
    protected static final int FUNC_OCTET_LENGTH                     = 8;
    private static final int   FUNC_CARDINALITY                      = 9;
    private static final int   FUNC_MAX_CARDINALITY                  = 10;
    private static final int   FUNC_TRIM_ARRAY                       = 11;
    private static final int   FUNC_ABS                              = 12;
    private static final int   FUNC_MOD                              = 13;
    protected static final int FUNC_LN                               = 14;
    private static final int   FUNC_EXP                              = 15;
    private static final int   FUNC_POWER                            = 16;
    private static final int   FUNC_SQRT                             = 17;
    private static final int   FUNC_FLOOR                            = 20;
    private static final int   FUNC_CEILING                          = 21;
    private static final int   FUNC_WIDTH_BUCKET                     = 22;
    protected static final int FUNC_SUBSTRING_CHAR                   = 23;    // string
    private static final int   FUNC_SUBSTRING_REG_EXPR               = 24;
    private static final int   FUNC_SUBSTRING_REGEX                  = 25;
    protected static final int FUNC_FOLD_LOWER                       = 26;
    protected static final int FUNC_FOLD_UPPER                       = 27;
    private static final int   FUNC_TRANSCODING                      = 28;
    private static final int   FUNC_TRANSLITERATION                  = 29;
    private static final int   FUNC_REGEX_TRANSLITERATION            = 30;
    protected static final int FUNC_TRIM_CHAR                        = 31;
    static final int           FUNC_OVERLAY_CHAR                     = 32;
    private static final int   FUNC_CHAR_NORMALIZE                   = 33;
    private static final int   FUNC_SUBSTRING_BINARY                 = 40;
    private static final int   FUNC_TRIM_BINARY                      = 41;
    private static final int   FUNC_OVERLAY_BINARY                   = 42;
    protected static final int FUNC_CURRENT_DATE                     = 43;    // datetime
    protected static final int FUNC_CURRENT_TIME                     = 44;
    protected static final int FUNC_CURRENT_TIMESTAMP                = 50;
    protected static final int FUNC_LOCALTIME                        = 51;
    protected static final int FUNC_LOCALTIMESTAMP                   = 52;
    private static final int   FUNC_CURRENT_CATALOG                  = 53;    // general
    private static final int   FUNC_CURRENT_DEFAULT_TRANSFORM_GROUP  = 54;
    private static final int   FUNC_CURRENT_PATH                     = 55;
    private static final int   FUNC_CURRENT_ROLE                     = 56;
    private static final int   FUNC_CURRENT_SCHEMA                   = 57;
    private static final int   FUNC_CURRENT_TRANSFORM_GROUP_FOR_TYPE = 58;
    private static final int   FUNC_CURRENT_USER                     = 59;
    private static final int   FUNC_SESSION_USER                     = 60;
    private static final int   FUNC_SYSTEM_USER                      = 61;
    protected static final int FUNC_USER                             = 62;
    private static final int   FUNC_VALUE                            = 63;

    //
    static final short[] noParamList             = new short[]{};
    static final short[] emptyParamList          = new short[] {
        Tokens.OPENBRACKET, Tokens.CLOSEBRACKET
    };
    static final short[] optionalNoParamList     = new short[] {
        Tokens.X_OPTION, 2, Tokens.OPENBRACKET, Tokens.CLOSEBRACKET
    };
    static final short[] optionalSingleParamList = new short[] {
        Tokens.OPENBRACKET, Tokens.X_OPTION, 1, Tokens.QUESTION,
        Tokens.CLOSEBRACKET
    };
    static final short[] singleParamList          = new short[] {
        Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.CLOSEBRACKET
    };
    static final short[] optionalIntegerParamList = new short[] {
        Tokens.X_OPTION, 3, Tokens.OPENBRACKET, Tokens.X_POS_INTEGER,
        Tokens.CLOSEBRACKET
    };
    static final short[] optionalDoubleParamList = new short[] {
        Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.X_OPTION, 2, Tokens.COMMA,
        Tokens.QUESTION, Tokens.CLOSEBRACKET
    };
    static final short[] doubleParamList = new short[] {
        Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.COMMA, Tokens.QUESTION,
        Tokens.CLOSEBRACKET
    };
    static final short[] tripleParamList = new short[] {
        Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.COMMA, Tokens.QUESTION,
        Tokens.COMMA, Tokens.QUESTION, Tokens.CLOSEBRACKET
    };
    static final short[] quadParamList = new short[] {
        Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.COMMA, Tokens.QUESTION,
        Tokens.COMMA, Tokens.QUESTION, Tokens.COMMA, Tokens.QUESTION,
        Tokens.CLOSEBRACKET
    };

    //
    static IntValueHashMap   valueFuncMap            = new IntValueHashMap();
    static IntValueHashMap   regularFuncMap          = new IntValueHashMap();
    static OrderedIntHashSet nonDeterministicFuncSet = new OrderedIntHashSet();

    static {
        regularFuncMap.put(Tokens.T_POSITION, FUNC_POSITION_CHAR);
        /*
        regularFuncMap.put(Token.T_OCCURENCES_REGEX, FUNC_OCCURENCES_REGEX);
        */
        regularFuncMap.put(Tokens.T_POSITION_REGEX, FUNC_POSITION_REGEX);
        regularFuncMap.put(Tokens.T_EXTRACT, FUNC_EXTRACT);
        regularFuncMap.put(Tokens.T_BIT_LENGTH, FUNC_BIT_LENGTH);
        regularFuncMap.put(Tokens.T_CHAR_LENGTH, FUNC_CHAR_LENGTH);
        regularFuncMap.put(Tokens.T_CHARACTER_LENGTH, FUNC_CHAR_LENGTH);
        regularFuncMap.put(Tokens.T_OCTET_LENGTH, FUNC_OCTET_LENGTH);
        regularFuncMap.put(Tokens.T_CARDINALITY, FUNC_CARDINALITY);
        regularFuncMap.put(Tokens.T_ARRAY_MAX_CARDINALITY,
                           FUNC_MAX_CARDINALITY);
        regularFuncMap.put(Tokens.T_MAX_CARDINALITY, FUNC_MAX_CARDINALITY);
        regularFuncMap.put(Tokens.T_TRIM_ARRAY, FUNC_TRIM_ARRAY);
        regularFuncMap.put(Tokens.T_ABS, FUNC_ABS);
        regularFuncMap.put(Tokens.T_MOD, FUNC_MOD);
        regularFuncMap.put(Tokens.T_LN, FUNC_LN);
        regularFuncMap.put(Tokens.T_EXP, FUNC_EXP);
        regularFuncMap.put(Tokens.T_POWER, FUNC_POWER);
        regularFuncMap.put(Tokens.T_SQRT, FUNC_SQRT);
        regularFuncMap.put(Tokens.T_FLOOR, FUNC_FLOOR);
        regularFuncMap.put(Tokens.T_CEILING, FUNC_CEILING);
        regularFuncMap.put(Tokens.T_CEIL, FUNC_CEILING);
        regularFuncMap.put(Tokens.T_WIDTH_BUCKET, FUNC_WIDTH_BUCKET);
        regularFuncMap.put(Tokens.T_SUBSTRING, FUNC_SUBSTRING_CHAR);
        /*
        regularFuncMap.put(Token.T_SUBSTRING_REG_EXPR,
                           FUNC_SUBSTRING_REG_EXPR);
        */
        regularFuncMap.put(Tokens.T_SUBSTRING_REGEX, FUNC_SUBSTRING_REGEX);
        regularFuncMap.put(Tokens.T_LOWER, FUNC_FOLD_LOWER);
        regularFuncMap.put(Tokens.T_UPPER, FUNC_FOLD_UPPER);
        /*
        regularFuncMap.put(Token.T_TRANSCODING, FUNC_TRANSCODING);
        regularFuncMap.put(Token.T_TRANSLITERATION, FUNC_TRANSLITERATION);
        regularFuncMap.put(Token.T_TRASLATION,
                           FUNC_REGEX_TRANSLITERATION);
        */
        regularFuncMap.put(Tokens.T_TRIM, FUNC_TRIM_CHAR);
        regularFuncMap.put(Tokens.T_OVERLAY, FUNC_OVERLAY_CHAR);
        /*
        regularFuncMap.put(Token.T_NORMALIZE, FUNC_CHAR_NORMALIZE);
        */
        regularFuncMap.put(Tokens.T_TRIM, FUNC_TRIM_BINARY);
    }

    static {
        valueFuncMap.put(Tokens.T_CURRENT_DATE, FUNC_CURRENT_DATE);
        valueFuncMap.put(Tokens.T_CURRENT_TIME, FUNC_CURRENT_TIME);
        valueFuncMap.put(Tokens.T_CURRENT_TIMESTAMP, FUNC_CURRENT_TIMESTAMP);
        valueFuncMap.put(Tokens.T_LOCALTIME, FUNC_LOCALTIME);
        valueFuncMap.put(Tokens.T_LOCALTIMESTAMP, FUNC_LOCALTIMESTAMP);
        valueFuncMap.put(Tokens.T_CURRENT_CATALOG, FUNC_CURRENT_CATALOG);
        /*
        valueFuncMap.put(Token.T_CURRENT_DEFAULT_TRANSFORM_GROUP,
                FUNC_CURRENT_DEFAULT_TRANSFORM_GROUP);
        */
        valueFuncMap.put(Tokens.T_CURRENT_PATH, FUNC_CURRENT_PATH);
        valueFuncMap.put(Tokens.T_CURRENT_ROLE, FUNC_CURRENT_ROLE);
        valueFuncMap.put(Tokens.T_CURRENT_SCHEMA, FUNC_CURRENT_SCHEMA);
        /*
        valueFuncMap.put(Token.T_CURRENT_TRANSFORM_GROUP_FOR_TYPE,
                FUNC_CURRENT_TRANSFORM_GROUP_FOR_TYPE);
        */
        valueFuncMap.put(Tokens.T_CURRENT_USER, FUNC_CURRENT_USER);
        valueFuncMap.put(Tokens.T_SESSION_USER, FUNC_SESSION_USER);
        valueFuncMap.put(Tokens.T_SYSTEM_USER, FUNC_SYSTEM_USER);
        valueFuncMap.put(Tokens.T_USER, FUNC_USER);
        valueFuncMap.put(Tokens.T_VALUE, FUNC_VALUE);

        //
        nonDeterministicFuncSet.addAll(valueFuncMap.values());
    }

    //
    int     funcType;
    boolean isDeterministic;
    String  name;
    short[] parseList;
    short[] parseListAlt;
    boolean isSQLValueFunction;

    public static FunctionSQL newSQLFunction(String token,
            CompileContext context) {

        int     id              = regularFuncMap.get(token, -1);
        boolean isValueFunction = false;

        if (id == -1) {
            id              = valueFuncMap.get(token, -1);
            isValueFunction = true;
        }

        if (id == -1) {
            return null;
        }

        FunctionSQL function = new FunctionSQL(id);

        if (id == FUNC_VALUE) {
            if (context.currentDomain == null) {
                return null;
            }

            function.dataType = context.currentDomain;
        } else {
            function.isSQLValueFunction = isValueFunction;
        }

        return function;
    }

    protected FunctionSQL() {
        super(OpTypes.SQL_FUNCTION);
    }

    protected FunctionSQL(int id) {

        this();

        this.funcType   = id;
        isDeterministic = !nonDeterministicFuncSet.contains(id);

        switch (id) {

            case FUNC_POSITION_CHAR :
            case FUNC_POSITION_BINARY :
                name      = Tokens.T_POSITION;
                parseList = new short[] {
                    Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.IN,
                    Tokens.QUESTION, Tokens.X_OPTION, 5, Tokens.USING,
                    Tokens.X_KEYSET, 2, Tokens.CHARACTERS, Tokens.OCTETS,
                    Tokens.CLOSEBRACKET
                };
                break;

            case FUNC_OCCURENCES_REGEX :
            case FUNC_POSITION_REGEX :
                break;

            case FUNC_EXTRACT :
                name      = Tokens.T_EXTRACT;
                parseList = new short[] {
                    Tokens.OPENBRACKET, Tokens.X_KEYSET, 20, Tokens.YEAR,
                    Tokens.MONTH, Tokens.DAY, Tokens.HOUR, Tokens.MINUTE,
                    Tokens.SECOND, Tokens.DAY_OF_WEEK, Tokens.WEEK_OF_YEAR,
                    Tokens.QUARTER, Tokens.DAY_OF_YEAR, Tokens.DAY_OF_MONTH,
                    Tokens.ISO_WEEK_OF_YEAR, Tokens.DAY_NAME,
                    Tokens.MONTH_NAME, Tokens.SECONDS_MIDNIGHT,
                    Tokens.TIMEZONE_HOUR, Tokens.TIMEZONE_MINUTE,
                    Tokens.MILLISECOND, Tokens.MICROSECOND, Tokens.NANOSECOND,
                    Tokens.FROM, Tokens.QUESTION, Tokens.CLOSEBRACKET
                };
                break;

            case FUNC_CHAR_LENGTH :
                name      = Tokens.T_CHAR_LENGTH;
                parseList = new short[] {
                    Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.X_OPTION, 5,
                    Tokens.USING, Tokens.X_KEYSET, 2, Tokens.CHARACTERS,
                    Tokens.OCTETS, Tokens.CLOSEBRACKET
                };
                break;

            case FUNC_BIT_LENGTH :
                name      = Tokens.T_BIT_LENGTH;
                parseList = singleParamList;
                break;

            case FUNC_OCTET_LENGTH :
                name      = Tokens.T_OCTET_LENGTH;
                parseList = singleParamList;
                break;

            case FUNC_CARDINALITY :
                name      = Tokens.T_CARDINALITY;
                parseList = singleParamList;
                break;

            case FUNC_MAX_CARDINALITY :
                name      = Tokens.T_MAX_CARDINALITY;
                parseList = singleParamList;
                break;

            case FUNC_TRIM_ARRAY :
                name      = Tokens.T_TRIM_ARRAY;
                parseList = doubleParamList;
                break;

            case FUNC_ABS :
                name      = Tokens.T_ABS;
                parseList = singleParamList;
                break;

            case FUNC_MOD :
                name      = Tokens.T_MOD;
                parseList = doubleParamList;
                break;

            case FUNC_LN :
                name      = Tokens.T_LN;
                parseList = singleParamList;
                break;

            case FUNC_EXP :
                name      = Tokens.T_EXP;
                parseList = singleParamList;
                break;

            case FUNC_POWER :
                name      = Tokens.T_POWER;
                parseList = doubleParamList;
                break;

            case FUNC_SQRT :
                name      = Tokens.T_SQRT;
                parseList = singleParamList;
                break;

            case FUNC_FLOOR :
                name      = Tokens.T_FLOOR;
                parseList = singleParamList;
                break;

            case FUNC_CEILING :
                name      = Tokens.T_CEILING;
                parseList = singleParamList;
                break;

            case FUNC_WIDTH_BUCKET :
                name      = Tokens.T_WIDTH_BUCKET;
                parseList = quadParamList;
                break;

            case FUNC_SUBSTRING_CHAR :
            case FUNC_SUBSTRING_BINARY :
                name      = Tokens.T_SUBSTRING;
                parseList = new short[] {
                    Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.FROM,
                    Tokens.QUESTION, Tokens.X_OPTION, 2, Tokens.FOR,
                    Tokens.QUESTION, Tokens.X_OPTION, 5, Tokens.USING,
                    Tokens.X_KEYSET, 2, Tokens.CHARACTERS, Tokens.OCTETS,
                    Tokens.CLOSEBRACKET
                };
                parseListAlt = new short[] {
                    Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.COMMA,
                    Tokens.QUESTION, Tokens.X_OPTION, 2, Tokens.COMMA,
                    Tokens.QUESTION, Tokens.CLOSEBRACKET
                };
                break;

            /*
            case FUNCTION_SUBSTRING_REG_EXPR :
                break;
            case FUNCTION_SUBSTRING_REGEX :
                break;
            */
            case FUNC_FOLD_LOWER :
                name      = Tokens.T_LOWER;
                parseList = singleParamList;
                break;

            case FUNC_FOLD_UPPER :
                name      = Tokens.T_UPPER;
                parseList = singleParamList;
                break;

            /*
            case FUNCTION_TRANSCODING :
                break;
            case FUNCTION_TRANSLITERATION :
                break;
            case FUNCTION_REGEX_TRANSLITERATION :
                break;
             */
            case FUNC_TRIM_CHAR :
            case FUNC_TRIM_BINARY :
                name      = Tokens.T_TRIM;
                parseList = new short[] {
                    Tokens.OPENBRACKET, Tokens.X_OPTION, 11,    //
                    Tokens.X_OPTION, 5,                         //
                    Tokens.X_KEYSET, 3, Tokens.LEADING, Tokens.TRAILING,
                    Tokens.BOTH,                                //
                    Tokens.X_OPTION, 1, Tokens.QUESTION,        //
                    Tokens.FROM, Tokens.QUESTION, Tokens.CLOSEBRACKET
                };
                break;

            /*
            case FUNCTION_CHAR_NORMALIZE :
                break;
            */
            case FUNC_OVERLAY_CHAR :
            case FUNC_OVERLAY_BINARY :
                name      = Tokens.T_OVERLAY;
                parseList = new short[] {
                    Tokens.OPENBRACKET, Tokens.QUESTION, Tokens.PLACING,
                    Tokens.QUESTION, Tokens.FROM, Tokens.QUESTION,
                    Tokens.X_OPTION, 2, Tokens.FOR, Tokens.QUESTION,
                    Tokens.X_OPTION, 2, Tokens.USING, Tokens.CHARACTERS,
                    Tokens.CLOSEBRACKET
                };
                break;

            case FUNC_CURRENT_CATALOG :
                name      = Tokens.T_CURRENT_CATALOG;
                parseList = noParamList;
                break;

            /*
            case FUNC_CURRENT_DEFAULT_TRANSFORM_GROUP :
                break;
            case FUNC_CURRENT_PATH :
                break;
            */
            case FUNC_CURRENT_ROLE :
                name      = Tokens.T_CURRENT_ROLE;
                parseList = noParamList;
                break;

            case FUNC_CURRENT_SCHEMA :
                name      = Tokens.T_CURRENT_SCHEMA;
                parseList = noParamList;
                break;

            /*
            case FUNC_CURRENT_TRANSFORM_GROUP_FOR_TYPE :
                break;
            */
            case FUNC_CURRENT_USER :
                name      = Tokens.T_CURRENT_USER;
                parseList = noParamList;
                break;

            case FUNC_SESSION_USER :
                name      = Tokens.T_SESSION_USER;
                parseList = noParamList;
                break;

            case FUNC_SYSTEM_USER :
                name      = Tokens.T_SYSTEM_USER;
                parseList = noParamList;
                break;

            case FUNC_USER :
                name      = Tokens.T_USER;
                parseList = optionalNoParamList;
                break;

            case FUNC_VALUE :
                name      = Tokens.T_VALUE;
                parseList = noParamList;
                break;

            case FUNC_CURRENT_DATE :
                name      = Tokens.T_CURRENT_DATE;
                parseList = noParamList;
                break;

            case FUNC_CURRENT_TIME :
                name      = Tokens.T_CURRENT_TIME;
                parseList = optionalIntegerParamList;
                break;

            case FUNC_CURRENT_TIMESTAMP :
                name      = Tokens.T_CURRENT_TIMESTAMP;
                parseList = optionalIntegerParamList;
                break;

            case FUNC_LOCALTIME :
                name      = Tokens.T_LOCALTIME;
                parseList = optionalIntegerParamList;
                break;

            case FUNC_LOCALTIMESTAMP :
                name      = Tokens.T_LOCALTIMESTAMP;
                parseList = optionalIntegerParamList;
                break;

            default :
                throw Error.runtimeError(ErrorCode.U_S0500, "FunctionSQL");
        }
    }

    public void setArguments(Expression[] newNodes) {
        this.nodes = newNodes;
    }

    public Expression getFunctionExpression() {
        return this;
    }

    /**
     * Evaluates and returns this Function in the context of the session.

*/ public Object getValue(Session session) { Object[] data = ValuePool.emptyObjectArray; if (nodes.length > 0) { data = new Object[nodes.length]; for (int i = 0; i < nodes.length; i++) { Expression e = nodes[i]; if (e != null) { data[i] = e.getValue(session, e.dataType); } } } return getValue(session, data); } Object getValue(Session session, Object[] data) { switch (funcType) { case FUNC_POSITION_CHAR : { if (data[0] == null || data[1] == null) { return null; } long offset = 0; if (nodes.length > 3 && nodes[3] != null) { Object value = nodes[3].getValue(session); offset = ((Number) value).longValue() - 1; if (offset < 0) { offset = 0; } } long result = ((CharacterType) nodes[1].dataType).position( session, data[1], data[0], nodes[0].dataType, offset) + 1; if (nodes[2] != null && ((Number) nodes[2].valueData).intValue() == Tokens.OCTETS) { result *= 2; } return ValuePool.getLong(result); } case FUNC_POSITION_BINARY : { if (data[0] == null || data[1] == null) { return null; } long result = ((BinaryType) nodes[1].dataType).position( session, (BlobData) data[1], (BlobData) data[0], nodes[0].dataType, 0) + 1; if (nodes[2] != null && ((Number) nodes[2].valueData).intValue() == Tokens.OCTETS) { result *= 2; } return ValuePool.getLong(result); } /* case FUNC_OCCURENCES_REGEX : case FUNC_POSITION_REGEX : */ case FUNC_EXTRACT : { return getExtractValue(session, data); } case FUNC_CHAR_LENGTH : { if (data[0] == null) { return null; } long result = ((CharacterType) nodes[0].dataType).size(session, data[0]); return ValuePool.getLong(result); } case FUNC_BIT_LENGTH : { if (data[0] == null) { return null; } long result; if (nodes[0].dataType.isBinaryType()) { result = ((BlobData) data[0]).bitLength(session); } else { result = 16 * ((CharacterType) nodes[0].dataType).size(session, data[0]); } return ValuePool.getLong(result); } case FUNC_OCTET_LENGTH : { if (data[0] == null) { return null; } long result; if (nodes[0].dataType.isBinaryType()) { result = ((BlobData) data[0]).length(session); } else { result = 2 * ((CharacterType) nodes[0].dataType).size(session, data[0]); } return ValuePool.getLong(result); } case FUNC_CARDINALITY : { if (data[0] == null) { return null; } int result = nodes[0].dataType.cardinality(session, data[0]); return ValuePool.getInt(result); } case FUNC_MAX_CARDINALITY : { if (data[0] == null) { return null; } int result = nodes[0].dataType.arrayLimitCardinality(); return ValuePool.getInt(result); } case FUNC_TRIM_ARRAY : { if (data[0] == null) { return null; } if (data[1] == null) { return null; } Object[] array = (Object[]) data[0]; int length = ((Number) data[1]).intValue(); if (length < 0 || length > array.length) { throw Error.error(ErrorCode.X_2202E); } Object[] newArray = new Object[array.length - length]; System.arraycopy(array, 0, newArray, 0, newArray.length); return newArray; } case FUNC_ABS : { if (data[0] == null) { return null; } return dataType.absolute(data[0]); } case FUNC_MOD : { if (data[0] == null || data[1] == null) { return null; } data[0] = nodeDataTypes[0].convertToType(session, data[0], nodes[0].dataType); data[1] = nodeDataTypes[1].convertToType(session, data[1], nodes[1].dataType); // result type is the same as nodes[1] Object value = ((NumberType) nodeDataTypes[0]).modulo(session, data[0], data[1], nodeDataTypes[1]); return value; } case FUNC_LN : { if (data[0] == null) { return null; } double d = ((Number) data[0]).doubleValue(); if (d <= 0) { if (session.database.sqlDoubleNaN) { throw Error.error(ErrorCode.X_2201E); } } d = Math.log(d); return ValuePool.getDouble(Double.doubleToLongBits(d)); } case FUNC_EXP : { if (data[0] == null) { return null; } double val = Math.exp(((Number) data[0]).doubleValue()); return ValuePool.getDouble(Double.doubleToLongBits(val)); } case FUNC_POWER : { if (data[0] == null || data[1] == null) { return null; } double base = ((Number) data[0]).doubleValue(); double exponent = ((Number) data[1]).doubleValue(); double val; if (base == 0) { if (exponent < 0) { throw Error.error(ErrorCode.X_2201F); } else if (exponent == 0) { val = 1; } else { val = 0; } } else { val = Math.pow(base, exponent); } return ValuePool.getDouble(Double.doubleToLongBits(val)); } case FUNC_SQRT : { if (data[0] == null) { return null; } double d = ((Number) data[0]).doubleValue(); if (d < 0) { if (session.database.sqlDoubleNaN) { throw Error.error(ErrorCode.X_2201E); } } double val = Math.sqrt(((Number) data[0]).doubleValue()); return ValuePool.getDouble(Double.doubleToLongBits(val)); } case FUNC_FLOOR : { if (data[0] == null) { return null; } return ((NumberType) dataType).floor(data[0]); } case FUNC_CEILING : { if (data[0] == null) { return null; } return ((NumberType) dataType).ceiling(data[0]); } case FUNC_WIDTH_BUCKET : { for (int i = 0; i < data.length; i++) { if (data[i] == null) { return null; } data[i] = nodeDataTypes[i].convertToType(session, data[i], nodes[i].dataType); } if (nodeDataTypes[3].isNegative(data[3])) { throw Error.error(ErrorCode.X_2201G); } int compare = nodeDataTypes[1].compare(session, data[1], data[2]); Type subType; Object temp; Object temp2; if (nodeDataTypes[0].isNumberType()) { subType = nodeDataTypes[0]; } else { subType = nodeDataTypes[0].getCombinedType(session, nodeDataTypes[0], OpTypes.SUBTRACT); } switch (compare) { case 0 : throw Error.error(ErrorCode.X_2201G); case -1 : { if (nodeDataTypes[0].compare(session, data[0], data[1]) < 0) { return ValuePool.INTEGER_0; } if (nodeDataTypes[0].compare(session, data[0], data[2]) >= 0) { return dataType.add(session, data[3], ValuePool.INTEGER_1, Type.SQL_INTEGER); } temp = subType.subtract(session, data[0], data[1], nodeDataTypes[1]); temp2 = subType.subtract(session, data[2], data[1], nodeDataTypes[1]); break; } case 1 : { if (nodeDataTypes[0].compare(session, data[0], data[1]) > 0) { return ValuePool.INTEGER_0; } if (nodeDataTypes[0].compare(session, data[0], data[2]) <= 0) { return dataType.add(session, data[3], ValuePool.INTEGER_1, Type.SQL_INTEGER); } temp = subType.subtract(session, data[1], data[0], nodeDataTypes[0]); temp2 = subType.subtract(session, data[1], data[2], nodeDataTypes[2]); break; } default : throw Error.runtimeError(ErrorCode.U_S0500, ""); } Type opType; if (subType.typeCode == Types.SQL_DOUBLE) { opType = subType; } else { opType = IntervalType.factorType; temp = opType.convertToType(session, temp, subType); temp2 = opType.convertToType(session, temp2, subType); } temp = opType.multiply(temp, data[3]); temp = opType.divide(session, temp, temp2); temp = dataType.convertToDefaultType(session, temp); return dataType.add(session, temp, ValuePool.INTEGER_1, Type.SQL_INTEGER); } case FUNC_SUBSTRING_CHAR : { if (data[0] == null || data[1] == null) { return null; } Object value; value = Type.SQL_BIGINT.convertToType(session, data[1], nodes[1].dataType); long offset = ((Number) value).longValue() - 1; long length = 0; if (nodes[2] != null) { if (data[2] == null) { return null; } value = Type.SQL_BIGINT.convertToType(session, data[2], nodes[2].dataType); length = ((Number) value).longValue(); } if (nodes.length > 3 && nodes[3] != null && ((Number) nodes[2].valueData).intValue() == Tokens.OCTETS) { // not clear what the rules on USING OCTECTS are with UTF } return ((CharacterType) dataType).substring(session, data[0], offset, length, nodes[2] != null, false); } /* case FUNCTION_SUBSTRING_REG_EXPR : break; case FUNCTION_SUBSTRING_REGEX : break; */ case FUNC_FOLD_LOWER : if (data[0] == null) { return null; } return ((CharacterType) dataType).lower(session, data[0]); case FUNC_FOLD_UPPER : if (data[0] == null) { return null; } return ((CharacterType) dataType).upper(session, data[0]); /* case FUNCTION_TRANSCODING : break; case FUNCTION_TRANSLITERATION : break; case FUNCTION_REGEX_TRANSLITERATION : break; */ case FUNC_TRIM_CHAR : { if (data[1] == null || data[2] == null) { return null; } boolean leading = false; boolean trailing = false; switch (((Number) nodes[0].valueData).intValue()) { case Tokens.BOTH : leading = trailing = true; break; case Tokens.LEADING : leading = true; break; case Tokens.TRAILING : trailing = true; break; default : throw Error.runtimeError(ErrorCode.U_S0500, "FunctionSQL"); } String string = (String) data[1]; if (string.length() != 1) { throw Error.error(ErrorCode.X_22027); } char character = string.charAt(0); return ((CharacterType) dataType).trim(session, data[2], character, leading, trailing); } case FUNC_OVERLAY_CHAR : { if (data[0] == null || data[1] == null || data[2] == null) { return null; } Object value; value = Type.SQL_BIGINT.convertToType(session, data[2], nodes[2].dataType); long offset = ((Number) value).longValue() - 1; long length = 0; if (nodes[3] != null) { if (data[3] == null) { return null; } value = Type.SQL_BIGINT.convertToType(session, data[3], nodes[3].dataType); length = ((Number) value).longValue(); } return ((CharacterType) dataType).overlay(null, data[0], data[1], offset, length, nodes[3] != null); } /* case FUNCTION_CHAR_NORMALIZE : break; */ case FUNC_SUBSTRING_BINARY : { if (data[0] == null || data[1] == null) { return null; } Object value; value = Type.SQL_BIGINT.convertToType(session, data[1], nodes[1].dataType); long offset = ((Number) value).longValue() - 1; long length = 0; if (nodes[2] != null) { if (data[2] == null) { return null; } value = Type.SQL_BIGINT.convertToType(session, data[2], nodes[2].dataType); length = ((Number) value).intValue(); } return ((BinaryType) dataType).substring(session, (BlobData) data[0], offset, length, nodes[2] != null); } case FUNC_TRIM_BINARY : { if (data[1] == null || data[2] == null) { return null; } boolean leading = false; boolean trailing = false; int spec = ((Number) nodes[0].valueData).intValue(); switch (spec) { case Tokens.BOTH : leading = trailing = true; break; case Tokens.LEADING : leading = true; break; case Tokens.TRAILING : trailing = true; break; default : throw Error.runtimeError(ErrorCode.U_S0500, "FunctionSQL"); } BlobData string = (BlobData) data[1]; if (string.length(session) != 1) { throw Error.error(ErrorCode.X_22027); } byte[] bytes = string.getBytes(); return ((BinaryType) dataType).trim(session, (BlobData) data[2], bytes[0], leading, trailing); } case FUNC_OVERLAY_BINARY : { if (data[0] == null || data[1] == null || data[2] == null) { return null; } Object value; value = Type.SQL_BIGINT.convertToType(session, data[2], nodes[2].dataType); long offset = ((Number) value).longValue() - 1; long length = 0; if (nodes[3] != null) { if (data[3] == null) { return null; } value = Type.SQL_BIGINT.convertToType(session, data[3], nodes[3].dataType); length = ((Number) value).longValue(); } return ((BinaryType) dataType).overlay(session, (BlobData) data[0], (BlobData) data[1], offset, length, nodes[3] != null); } case FUNC_CURRENT_CATALOG : return session.database.getCatalogName().name; /* case FUNC_CURRENT_DEFAULT_TRANSFORM_GROUP : case FUNC_CURRENT_PATH : */ case FUNC_CURRENT_ROLE : return session.getRole() == null ? null : session.getRole().getName() .getNameString(); case FUNC_CURRENT_SCHEMA : return session.getCurrentSchemaHsqlName().name; /* case FUNC_CURRENT_TRANSFORM_GROUP_FOR_TYPE : */ case FUNC_CURRENT_USER : return session.getUser().getName().getNameString(); case FUNC_SESSION_USER : return session.getUser().getName().getNameString(); case FUNC_SYSTEM_USER : return session.getUser().getName().getNameString(); case FUNC_USER : return session.getUser().getName().getNameString(); case FUNC_VALUE : return session.sessionData.currentValue; case FUNC_CURRENT_DATE : if (session.database.sqlSyntaxOra) { return dataType.convertToTypeLimits( session, session.getCurrentTimestamp(false)); } return session.getCurrentDate(); case FUNC_CURRENT_TIME : return dataType.convertToTypeLimits( session, session.getCurrentTime(true)); case FUNC_CURRENT_TIMESTAMP : return dataType.convertToTypeLimits( session, session.getCurrentTimestamp(true)); case FUNC_LOCALTIME : return dataType.convertToTypeLimits( session, session.getCurrentTime(false)); case FUNC_LOCALTIMESTAMP : return dataType.convertToTypeLimits( session, session.getCurrentTimestamp(false)); default : throw Error.runtimeError(ErrorCode.U_S0500, "FunctionSQL"); } } public void resolveTypes(Session session, Expression parent) { for (int i = 0; i < nodes.length; i++) { if (nodes[i] != null) { nodes[i].resolveTypes(session, this); } } switch (funcType) { case FUNC_POSITION_CHAR : case FUNC_POSITION_BINARY : { if (nodes[0].dataType == null) { if (nodes[1].dataType == null) { throw Error.error(ErrorCode.X_42567); } if (nodes[1].dataType.typeCode == Types.SQL_CLOB || nodes[1].dataType.isBinaryType()) { nodes[0].dataType = nodes[1].dataType; } else { nodes[0].dataType = Type.SQL_VARCHAR; } } if (nodes[1].dataType == null) { if (nodes[0].dataType.typeCode == Types.SQL_CLOB || nodes[0].dataType.isBinaryType()) { nodes[1].dataType = nodes[0].dataType; } else { nodes[1].dataType = Type.SQL_VARCHAR; } } if (nodes[0].dataType.isCharacterType() && nodes[1].dataType.isCharacterType()) { funcType = FUNC_POSITION_CHAR; } else if (nodes[0].dataType.isBinaryType() && nodes[1].dataType.isBinaryType()) { if (nodes[0].dataType.isBitType() || nodes[1].dataType.isBitType()) { throw Error.error(ErrorCode.X_42563); } funcType = FUNC_POSITION_BINARY; } else { throw Error.error(ErrorCode.X_42563); } if (nodes.length > 3 && nodes[3] != null) { if (nodes[3].isDynamicParam()) { nodes[3].dataType = Type.SQL_BIGINT; } if (!nodes[3].dataType.isNumberType()) { throw Error.error(ErrorCode.X_42563); } } dataType = Type.SQL_BIGINT; break; } /* case FUNC_OCCURENCES_REGEX : case FUNC_POSITION_REGEX : */ case FUNC_EXTRACT : { if (nodes[1].dataType == null) { throw Error.error(ErrorCode.X_42567); } if (!nodes[1].dataType.isDateTimeType() && !nodes[1].dataType.isIntervalType()) { throw Error.error(ErrorCode.X_42563); } int part = ((Number) nodes[0].valueData).intValue(); DTIType type = (DTIType) nodes[1].dataType; part = DTIType.getFieldNameTypeForToken(part); dataType = type.getExtractType(part); break; } case FUNC_BIT_LENGTH : { if (nodes[0].dataType == null) { nodes[0].dataType = Type.SQL_BIT_VARYING_MAX_LENGTH; } if (!nodes[0].dataType.isCharacterType() && !nodes[0].dataType.isBinaryType()) { throw Error.error(ErrorCode.X_42563); } dataType = Type.SQL_BIGINT; break; } case FUNC_CHAR_LENGTH : if (nodes[0].dataType == null) { nodes[0].dataType = Type.SQL_VARCHAR; } if (!nodes[0].dataType.isCharacterType()) { throw Error.error(ErrorCode.X_42563); } // fall through case FUNC_OCTET_LENGTH : { if (nodes[0].dataType == null) { nodes[0].dataType = Type.SQL_VARCHAR; } if (!nodes[0].dataType.isCharacterType() && !nodes[0].dataType.isBinaryType()) { throw Error.error(ErrorCode.X_42563); } dataType = Type.SQL_BIGINT; break; } case FUNC_CARDINALITY : { if (nodes[0].dataType == null) { throw Error.error(ErrorCode.X_42567); } if (!nodes[0].dataType.isArrayType()) { throw Error.error(ErrorCode.X_42563); } dataType = Type.SQL_INTEGER; break; } case FUNC_MAX_CARDINALITY : { if (nodes[0].dataType == null) { throw Error.error(ErrorCode.X_42567); } if (!nodes[0].dataType.isArrayType()) { throw Error.error(ErrorCode.X_42563); } dataType = Type.SQL_INTEGER; break; } case FUNC_TRIM_ARRAY : { if (nodes[0].dataType == null) { throw Error.error(ErrorCode.X_42567); } if (!nodes[0].dataType.isArrayType()) { throw Error.error(ErrorCode.X_42563); } if (nodes[1].dataType == null) { nodes[1].dataType = Type.SQL_INTEGER; } if (!nodes[1].dataType.isIntegralType()) { throw Error.error(ErrorCode.X_42563); } dataType = nodes[0].dataType; break; } case FUNC_MOD : { if (nodes[0].dataType == null) { nodes[0].dataType = nodes[1].dataType; } if (nodes[1].dataType == null) { nodes[1].dataType = nodes[0].dataType; } if (nodes[0].dataType == null) { throw Error.error(ErrorCode.X_42567); } if (!nodes[0].dataType.isNumberType() || !nodes[1].dataType.isNumberType()) { throw Error.error(ErrorCode.X_42563); } nodeDataTypes = new Type[2]; if (session.database.sqlSyntaxOra) { nodeDataTypes[0] = nodes[0].dataType.getAggregateType(nodes[1].dataType); nodeDataTypes[1] = nodes[1].dataType; } else { nodeDataTypes[0] = ((NumberType) nodes[0].dataType).getIntegralType(); nodeDataTypes[1] = ((NumberType) nodes[1].dataType).getIntegralType(); } dataType = nodeDataTypes[1]; break; } case FUNC_POWER : { if (nodes[0].dataType == null) { nodes[0].dataType = nodes[1].dataType; } if (nodes[1].dataType == null) { nodes[1].dataType = nodes[0].dataType; } if (nodes[0].dataType == null) { throw Error.error(ErrorCode.X_42567); } if (!nodes[0].dataType.isNumberType() || !nodes[1].dataType.isNumberType()) { throw Error.error(ErrorCode.X_42563); } dataType = Type.SQL_DOUBLE; break; } case FUNC_LN : case FUNC_EXP : case FUNC_SQRT : { if (nodes[0].dataType == null) { nodes[0].dataType = Type.SQL_DOUBLE; } if (!nodes[0].dataType.isNumberType()) { throw Error.error(ErrorCode.X_42563); } dataType = Type.SQL_DOUBLE; break; } case FUNC_ABS : if (nodes[0].dataType != null && nodes[0].dataType.isIntervalType()) { dataType = nodes[0].dataType; break; } // fall through case FUNC_FLOOR : case FUNC_CEILING : { if (nodes[0].dataType == null) { nodes[0].dataType = Type.SQL_DOUBLE; } if (!nodes[0].dataType.isNumberType()) { throw Error.error(ErrorCode.X_42563); } dataType = nodes[0].dataType; if (dataType.typeCode == Types.SQL_DECIMAL || dataType.typeCode == Types.SQL_NUMERIC) { if (dataType.scale > 0) { dataType = NumberType.getNumberType(dataType.typeCode, dataType.precision + 1, 0); } } break; } case FUNC_WIDTH_BUCKET : { nodeDataTypes = new Type[4]; nodeDataTypes[0] = Type.getAggregateType(nodes[0].dataType, nodes[1].dataType); nodeDataTypes[0] = Type.getAggregateType(nodeDataTypes[0], nodes[2].dataType); if (nodeDataTypes[0] == null) { throw Error.error(ErrorCode.X_42567); } if (!nodeDataTypes[0].isNumberType() && !nodeDataTypes[0].isDateTimeType()) { throw Error.error(ErrorCode.X_42563); } nodeDataTypes[1] = nodeDataTypes[0]; nodeDataTypes[2] = nodeDataTypes[0]; if (nodes[1].dataType == null) { nodes[1].dataType = nodeDataTypes[1]; } if (nodes[2].dataType == null) { nodes[2].dataType = nodeDataTypes[2]; } if (nodes[3].dataType == null) { nodes[3].dataType = Type.SQL_INTEGER; } if (!nodes[3].dataType.isIntegralType()) { throw Error.error(ErrorCode.X_42563); } nodeDataTypes[3] = nodes[3].dataType; dataType = nodes[3].dataType; break; } case FUNC_SUBSTRING_CHAR : case FUNC_SUBSTRING_BINARY : { if (nodes[0].dataType == null) { // in 20.6 parameter not allowed as type cannot be determined as binary or char // throw Error.error(ErrorCode.X_42567); nodes[0].dataType = Type.SQL_VARCHAR_DEFAULT; } if (nodes[1].dataType == null) { nodes[1].dataType = Type.SQL_NUMERIC; } if (!nodes[1].dataType.isNumberType()) { throw Error.error(ErrorCode.X_42563); } if (nodes[2] != null) { if (nodes[2].dataType == null) { nodes[2].dataType = Type.SQL_NUMERIC; } if (!nodes[2].dataType.isNumberType()) { throw Error.error(ErrorCode.X_42563); } } dataType = nodes[0].dataType; if (dataType.isCharacterType()) { funcType = FUNC_SUBSTRING_CHAR; if (dataType.typeCode == Types.SQL_CHAR) { dataType = CharacterType.getCharacterType( Types.SQL_VARCHAR, dataType.precision, dataType.getCollation()); } } else if (dataType.isBinaryType()) { funcType = FUNC_SUBSTRING_BINARY; } else { throw Error.error(ErrorCode.X_42563); } if (nodes.length > 3 && nodes[3] != null) { // always boolean constant if defined } break; } /* case FUNCTION_SUBSTRING_REG_EXPR : break; case FUNCTION_SUBSTRING_REGEX : break; */ case FUNC_FOLD_LOWER : case FUNC_FOLD_UPPER : if (nodes[0].dataType == null) { nodes[0].dataType = Type.SQL_VARCHAR_DEFAULT; } dataType = nodes[0].dataType; if (!dataType.isCharacterType()) { throw Error.error(ErrorCode.X_42563); } break; /* case FUNCTION_TRANSCODING : break; case FUNCTION_TRANSLITERATION : break; case FUNCTION_REGEX_TRANSLITERATION : break; */ case FUNC_TRIM_CHAR : case FUNC_TRIM_BINARY : if (nodes[0] == null) { nodes[0] = new ExpressionValue(ValuePool.getInt(Tokens.BOTH), Type.SQL_INTEGER); } if (nodes[2].dataType == null) { nodes[2].dataType = Type.SQL_VARCHAR_DEFAULT; } dataType = nodes[2].dataType; if (dataType.isCharacterType()) { funcType = FUNC_TRIM_CHAR; if (dataType.typeCode == Types.SQL_CHAR) { dataType = CharacterType.getCharacterType( Types.SQL_VARCHAR, dataType.precision, dataType.getCollation()); } if (nodes[1] == null) { nodes[1] = new ExpressionValue(" ", Type.SQL_CHAR); } } else if (dataType.isBinaryType()) { funcType = FUNC_TRIM_BINARY; if (nodes[1] == null) { nodes[1] = new ExpressionValue( new BinaryData(new byte[]{ 0 }, false), Type.SQL_BINARY); } } else { throw Error.error(ErrorCode.X_42563); } break; case FUNC_OVERLAY_CHAR : case FUNC_OVERLAY_BINARY : { if (nodes[0].dataType == null) { if (nodes[1].dataType == null) { nodes[0].dataType = Type.SQL_VARCHAR_DEFAULT; nodes[1].dataType = Type.SQL_VARCHAR_DEFAULT; // throw Error.error(ErrorCode.X_42567); } if (nodes[1].dataType.typeCode == Types.SQL_CLOB || nodes[1].dataType.isBinaryType()) { nodes[0].dataType = nodes[1].dataType; } else { nodes[0].dataType = Type.SQL_VARCHAR_DEFAULT; } } if (nodes[1].dataType == null) { if (nodes[0].dataType.typeCode == Types.SQL_CLOB || nodes[0].dataType.isBinaryType()) { nodes[1].dataType = nodes[0].dataType; } else { nodes[1].dataType = Type.SQL_VARCHAR_DEFAULT; } } if (nodes[0].dataType.isCharacterType() && nodes[1].dataType.isCharacterType()) { funcType = FUNC_OVERLAY_CHAR; if (nodes[0].dataType.typeCode == Types.SQL_CLOB || nodes[1].dataType.typeCode == Types.SQL_CLOB) { dataType = CharacterType .getCharacterType(Types.SQL_CLOB, nodes[0].dataType.precision + nodes[1].dataType .precision, nodes[0] .dataType .getCollation()); } else { dataType = CharacterType .getCharacterType(Types.SQL_VARCHAR, nodes[0].dataType.precision + nodes[1].dataType .precision, nodes[0] .dataType .getCollation()); } } else if (nodes[0].dataType.isBinaryType() && nodes[1].dataType.isBinaryType()) { funcType = FUNC_OVERLAY_BINARY; if (nodes[0].dataType.typeCode == Types.SQL_BLOB || nodes[1].dataType.typeCode == Types.SQL_BLOB) { dataType = BinaryType.getBinaryType( Types.SQL_BLOB, nodes[0].dataType.precision + nodes[1].dataType.precision); } else { dataType = BinaryType.getBinaryType( Types.SQL_VARBINARY, nodes[0].dataType.precision + nodes[1].dataType.precision); } } else { throw Error.error(ErrorCode.X_42563); } if (nodes[2].dataType == null) { nodes[2].dataType = Type.SQL_NUMERIC; } if (!nodes[2].dataType.isNumberType()) { throw Error.error(ErrorCode.X_42563); } if (nodes[3] != null) { if (nodes[3].dataType == null) { nodes[3].dataType = Type.SQL_NUMERIC; } if (!nodes[3].dataType.isNumberType()) { throw Error.error(ErrorCode.X_42563); } } break; } /* case FUNCTION_CHAR_NORMALIZE : break; */ case FUNC_CURRENT_CATALOG : case FUNC_CURRENT_DEFAULT_TRANSFORM_GROUP : case FUNC_CURRENT_PATH : case FUNC_CURRENT_ROLE : case FUNC_CURRENT_SCHEMA : case FUNC_CURRENT_TRANSFORM_GROUP_FOR_TYPE : case FUNC_CURRENT_USER : case FUNC_SESSION_USER : case FUNC_SYSTEM_USER : case FUNC_USER : dataType = TypeInvariants.SQL_IDENTIFIER; break; case FUNC_VALUE : break; case FUNC_CURRENT_DATE : if (session.database.sqlSyntaxOra) { dataType = Type.SQL_TIMESTAMP_NO_FRACTION; break; } dataType = Type.SQL_DATE; break; case FUNC_CURRENT_TIME : { int precision = DateTimeType.defaultTimeFractionPrecision; if (nodes.length > 0 && nodes[0] != null) { precision = ((Integer) nodes[0].valueData).intValue(); } dataType = DateTimeType.getDateTimeType(Types.SQL_TIME_WITH_TIME_ZONE, precision); break; } case FUNC_CURRENT_TIMESTAMP : { int precision = DateTimeType.defaultTimestampFractionPrecision; if (nodes.length > 0 && nodes[0] != null) { precision = ((Integer) nodes[0].valueData).intValue(); } dataType = DateTimeType.getDateTimeType( Types.SQL_TIMESTAMP_WITH_TIME_ZONE, precision); break; } case FUNC_LOCALTIME : { int precision = DateTimeType.defaultTimeFractionPrecision; if (nodes.length > 0 && nodes[0] != null) { precision = ((Integer) nodes[0].valueData).intValue(); } dataType = DateTimeType.getDateTimeType(Types.SQL_TIME, precision); break; } case FUNC_LOCALTIMESTAMP : { int precision = DateTimeType.defaultTimestampFractionPrecision; if (nodes.length > 0 && nodes[0] != null) { precision = ((Integer) nodes[0].valueData).intValue(); } dataType = DateTimeType.getDateTimeType(Types.SQL_TIMESTAMP, precision); break; } default : throw Error.runtimeError(ErrorCode.U_S0500, "FunctionSQL"); } } Object getExtractValue(Session session, Object[] data) { if (data[1] == null) { return null; } int part = ((Number) nodes[0].valueData).intValue(); part = DTIType.getFieldNameTypeForToken(part); switch (part) { case Types.SQL_INTERVAL_SECOND : { return ((DTIType) nodes[1].dataType).getSecondPart(session, data[1]); } case Types.DTI_MONTH_NAME : case Types.DTI_DAY_NAME : { return ((DateTimeType) nodes[1].dataType).getPartString( session, data[1], part); } default : { int value = ((DTIType) nodes[1].dataType).getPart(session, data[1], part); return ValuePool.getInt(value); } } } public String getSQL() { StringBuilder sb = new StringBuilder(); switch (funcType) { case FUNC_POSITION_CHAR : case FUNC_POSITION_BINARY : { sb.append(Tokens.T_POSITION).append('(') // .append(nodes[0].getSQL()).append(' ') // .append(Tokens.T_IN).append(' ') // .append(nodes[1].getSQL()); if (nodes[2] != null && Boolean.TRUE.equals(nodes[2].valueData)) { sb.append(' ').append(Tokens.T_USING).append(' ').append( Tokens.T_OCTETS); } sb.append(')'); break; } case FUNC_OCCURENCES_REGEX : break; case FUNC_POSITION_REGEX : break; case FUNC_EXTRACT : { int type = ((Integer) nodes[0].valueData).intValue(); type = DTIType.getFieldNameTypeForToken(type); String token = DTIType.getFieldNameTokenForType(type); sb.append(Tokens.T_EXTRACT).append('(').append(token) // .append(' ').append(Tokens.T_FROM).append(' ') // .append(nodes[1].getSQL()).append(')'); break; } case FUNC_CHAR_LENGTH : { sb.append(Tokens.T_CHAR_LENGTH).append('(') // .append(nodes[0].getSQL()).append(')'); break; } case FUNC_BIT_LENGTH : { sb.append(Tokens.T_BIT_LENGTH).append('(') // .append(nodes[0].getSQL()).append(')'); break; } case FUNC_OCTET_LENGTH : { sb.append(Tokens.T_OCTET_LENGTH).append('(') // .append(nodes[0].getSQL()).append(')'); break; } case FUNC_CARDINALITY : { sb.append(Tokens.T_CARDINALITY).append('(') // .append(nodes[0].getSQL()).append(')'); break; } case FUNC_MAX_CARDINALITY : { sb.append(Tokens.T_MAX_CARDINALITY).append('(') // .append(nodes[0].getSQL()).append(')'); break; } case FUNC_TRIM_ARRAY : { sb.append(Tokens.T_TRIM_ARRAY).append('(') // .append(nodes[0].getSQL()).append(',') // .append(nodes[1].getSQL()).append(')'); // break; } case FUNC_ABS : { sb.append(Tokens.T_ABS).append('(') // .append(nodes[0].getSQL()).append(')'); break; } case FUNC_MOD : { sb.append(Tokens.T_MOD).append('(') // .append(nodes[0].getSQL()).append(',') // .append(nodes[1].getSQL()).append(')'); break; } case FUNC_LN : { sb.append(Tokens.T_LN).append('(') // .append(nodes[0].getSQL()).append(')'); break; } case FUNC_EXP : { sb.append(Tokens.T_EXP).append('(') // .append(nodes[0].getSQL()).append(')'); break; } case FUNC_POWER : { sb.append(Tokens.T_POWER).append('(') // .append(nodes[0].getSQL()).append(',') // .append(nodes[1].getSQL()).append(')'); break; } case FUNC_SQRT : { sb.append(Tokens.T_SQRT).append('(') // .append(nodes[0].getSQL()).append(')'); break; } case FUNC_FLOOR : { sb.append(Tokens.T_FLOOR).append('(') // .append(nodes[0].getSQL()).append(')'); break; } case FUNC_CEILING : { sb.append(Tokens.T_CEILING).append('(') // .append(nodes[0].getSQL()).append(')'); break; } case FUNC_WIDTH_BUCKET : { sb.append(Tokens.T_WIDTH_BUCKET).append('(') // .append(nodes[0].getSQL()).append(',') // .append(nodes[1].getSQL()).append(',') // .append(nodes[2].getSQL()).append(',') // .append(nodes[3].getSQL()).append(')'); break; } case FUNC_SUBSTRING_CHAR : case FUNC_SUBSTRING_BINARY : sb.append(Tokens.T_SUBSTRING).append('(') // .append(nodes[0].getSQL()).append(' ') // .append(Tokens.T_FROM).append(' ') // .append(nodes[1].getSQL()); if (nodes[2] != null) { sb.append(' ').append(Tokens.T_FOR).append(' ') // .append(nodes[2].getSQL()); } if (nodes.length > 3 && nodes[3] != null) { if (Boolean.TRUE.equals(nodes[3].valueData)) { sb.append(' ').append(Tokens.T_USING).append( ' ').append(Tokens.T_OCTETS); } } sb.append(')'); break; /* case FUNCTION_SUBSTRING_REGEX : break; */ case FUNC_FOLD_LOWER : sb.append(Tokens.T_LOWER).append('(').append( nodes[0].getSQL()).append(')'); break; case FUNC_FOLD_UPPER : sb.append(Tokens.T_UPPER).append('(').append( nodes[0].getSQL()).append(')'); break; /* case FUNCTION_TRANSCODING : break; case FUNCTION_TRANSLITERATION : break; case FUNCTION_REGEX_TRANSLITERATION : break; */ case FUNC_OVERLAY_CHAR : case FUNC_OVERLAY_BINARY : sb.append(Tokens.T_OVERLAY).append('(') // .append(nodes[0].getSQL()).append(' ') // .append(Tokens.T_PLACING).append(' ') // .append(nodes[1].getSQL()).append(' ') // .append(Tokens.T_FROM).append(' ') // .append(nodes[2].getSQL()); if (nodes[3] != null) { sb.append(' ').append(Tokens.T_FOR).append(' ').append( nodes[3].getSQL()); } if (nodes[4] != null) { if (Boolean.TRUE.equals(nodes[4].valueData)) { sb.append(' ').append(Tokens.T_USING).append( ' ').append(Tokens.T_OCTETS); } } sb.append(')'); break; /* case FUNCTION_NORMALIZE : break; */ case FUNC_TRIM_CHAR : case FUNC_TRIM_BINARY : String spec = null; switch (((Number) nodes[0].valueData).intValue()) { case Tokens.BOTH : spec = Tokens.T_BOTH; break; case Tokens.LEADING : spec = Tokens.T_LEADING; break; case Tokens.TRAILING : spec = Tokens.T_TRAILING; break; default : } sb.append(Tokens.T_TRIM).append('(') // .append(spec).append(' ') // .append(nodes[1].getSQL()).append(' ') // .append(Tokens.T_FROM).append(' ') // .append(nodes[2].getSQL()).append(')'); break; case FUNC_CURRENT_CATALOG : case FUNC_CURRENT_DEFAULT_TRANSFORM_GROUP : case FUNC_CURRENT_PATH : case FUNC_CURRENT_ROLE : case FUNC_CURRENT_SCHEMA : case FUNC_CURRENT_TRANSFORM_GROUP_FOR_TYPE : case FUNC_CURRENT_USER : case FUNC_SESSION_USER : case FUNC_SYSTEM_USER : case FUNC_USER : case FUNC_CURRENT_DATE : case FUNC_VALUE : return name; case FUNC_LOCALTIME : case FUNC_CURRENT_TIME : { int precision = DateTimeType.defaultTimeFractionPrecision; if (nodes.length > 0 && nodes[0] != null) { precision = ((Number) nodes[0].valueData).intValue(); } if (precision == DateTimeType.defaultTimeFractionPrecision) { return name; } sb.append(name).append(Tokens.T_OPENBRACKET).append(precision); sb.append(Tokens.T_CLOSEBRACKET); return sb.toString(); } case FUNC_LOCALTIMESTAMP : case FUNC_CURRENT_TIMESTAMP : { int precision = DateTimeType.defaultTimestampFractionPrecision; if (nodes.length > 0 && nodes[0] != null) { precision = ((Number) nodes[0].valueData).intValue(); } if (precision == DateTimeType.defaultTimestampFractionPrecision) { return name; } sb.append(name).append(Tokens.T_OPENBRACKET).append(precision); sb.append(Tokens.T_CLOSEBRACKET); return sb.toString(); } default : throw Error.runtimeError(ErrorCode.U_S0500, "FunctionSQL"); } return sb.toString(); } boolean equals(Expression other) { if (other instanceof FunctionSQL) { FunctionSQL o = (FunctionSQL) other; return super.equals(other) && funcType == o.funcType; } return false; } public int hashCode() { return opType + funcType; } /** * Returns a String representation of this object.

*/ public String describe(Session session, int blanks) { StringBuilder sb = new StringBuilder(); sb.append('\n'); for (int i = 0; i < blanks; i++) { sb.append(' '); } sb.append("FUNCTION ").append("=[\n"); sb.append(name).append("("); for (int i = 0; i < nodes.length; i++) { if (nodes[i] == null) { continue; } sb.append("[").append(nodes[i].describe(session, blanks)).append("]"); } sb.append(") returns ").append(dataType.getNameString()); sb.append("]\n"); return sb.toString(); } public boolean isDeterministic() { return isDeterministic; } public boolean isValueFunction() { return isSQLValueFunction; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy