void resolveTypes()

in HSQL/src/org/hsqldb1/Expression.java [2044:2453]


    void resolveTypes(Session session) throws HsqlException {

        if (isParam) {
            return;
        }

        if (eArg != null) {
            eArg.resolveTypes(session);
        }

        if (eArg2 != null) {
            eArg2.resolveTypes(session);
        }

        switch (exprType) {

            case VALUE :
                if (dataType == Types.BOOLEAN && valueData != null) {
                    exprType = ((Boolean) valueData).booleanValue() ? TRUE
                                                                    : FALSE;
                }
                break;

            case COLUMN :
                break;

            case FUNCTION :
                function.resolveType(session);

                dataType = function.getReturnType();
                break;

            case QUERY : {
                subQuery.select.resolveTypes(session);

                dataType = subQuery.select.exprColumns[0].dataType;

                break;
            }
            case NEGATE :
                if (eArg.isParam) {
                    throw Trace.error(Trace.UNRESOLVED_PARAMETER_TYPE,
                                      Trace.Expression_resolveTypes1);
                }

                dataType = eArg.dataType;

                if (isFixedConstant()) {
                    valueData = getValue(session, dataType);
                    eArg      = null;
                    exprType  = VALUE;
                }
                break;

            case ADD :

                // concat using + operator
                // non-standard concat operator to be deprecated
                if (Types.isCharacterType(eArg.dataType)
                        || Types.isCharacterType(eArg2.dataType)) {
                    exprType = Expression.CONCAT;
                    dataType = Types.VARCHAR;

                    if (isFixedConstant()) {
                        valueData = getValue(session, dataType);
                        eArg      = null;
                        eArg2     = null;
                        exprType  = VALUE;
                    } else {
                        if (eArg.isParam) {
                            eArg.dataType = Types.VARCHAR;
                        }

                        if (eArg2.isParam) {
                            eArg2.dataType = Types.VARCHAR;
                        }
                    }

                    break;
                }
            case SUBTRACT :
            case MULTIPLY :
            case DIVIDE :
                if (eArg.isParam && eArg2.isParam) {
                    throw Trace.error(Trace.UNRESOLVED_PARAMETER_TYPE,
                                      Trace.Expression_resolveTypes2);
                }

                if (isFixedConstant()) {
                    dataType = Column.getCombinedNumberType(eArg.dataType,
                            eArg2.dataType, exprType);
                    valueData = getValue(session, dataType);
                    eArg      = null;
                    eArg2     = null;
                    exprType  = VALUE;
                } else {
                    if (eArg.isParam) {
                        eArg.dataType = eArg2.dataType;
                    } else if (eArg2.isParam) {
                        eArg2.dataType = eArg.dataType;
                    }

                    // fredt@users 20011010 - patch 442993 by fredt
                    dataType = Column.getCombinedNumberType(eArg.dataType,
                            eArg2.dataType, exprType);
                }
                break;

            case CONCAT :
                dataType = Types.VARCHAR;

                if (isFixedConstant()) {
                    valueData = getValue(session, dataType);
                    eArg      = null;
                    eArg2     = null;
                    exprType  = VALUE;
                } else {
                    if (eArg.isParam) {
                        eArg.dataType = Types.VARCHAR;
                    }

                    if (eArg2.isParam) {
                        eArg2.dataType = Types.VARCHAR;
                    }
                }
                break;

            case EQUAL :
            case BIGGER_EQUAL :
            case BIGGER :
            case SMALLER :
            case SMALLER_EQUAL :
            case NOT_EQUAL :
                if (eArg.isParam && eArg2.isParam) {
                    throw Trace.error(Trace.UNRESOLVED_PARAMETER_TYPE,
                                      Trace.Expression_resolveTypes3);
                }

                if (isFixedConditional()) {
                    Boolean result = test(session);

                    if (result == null) {
                        setNull();
                    } else if (result.booleanValue()) {
                        exprType = TRUE;
                    } else {
                        exprType = FALSE;
                    }

                    eArg  = null;
                    eArg2 = null;
                } else if (eArg.isParam) {
                    eArg.dataType = eArg2.dataType == Types.NULL
                                    ? Types.VARCHAR
                                    : eArg2.dataType;

                    if (eArg2.exprType == COLUMN) {
                        eArg.setTableColumnAttributes(eArg2);
                    }
                } else if (eArg2.isParam) {
                    eArg2.dataType = eArg.dataType == Types.NULL
                                     ? Types.VARCHAR
                                     : eArg.dataType;

                    if (eArg.exprType == COLUMN) {
                        eArg2.setTableColumnAttributes(eArg);
                    }
                }

                dataType = Types.BOOLEAN;
                break;

            case LIKE :
                resolveTypeForLike(session);

                dataType = Types.BOOLEAN;
                break;

            case AND : {
                boolean argFixed  = eArg.isFixedConditional();
                boolean arg2Fixed = eArg2.isFixedConditional();
                Boolean arg       = argFixed ? (eArg.test(session))
                                             : null;
                Boolean arg2      = arg2Fixed ? eArg2.test(session)
                                              : null;

                if (argFixed && arg2Fixed) {
                    if (arg == null || arg2 == null) {
                        setNull();
                    } else {
                        exprType = arg.booleanValue() && arg2.booleanValue()
                                   ? TRUE
                                   : FALSE;
                        eArg  = null;
                        eArg2 = null;
                    }
                } else if ((argFixed && !Boolean.TRUE.equals(arg))
                           || (arg2Fixed && !Boolean.TRUE.equals(arg2))) {
                    exprType = FALSE;
                    eArg     = null;
                    eArg2    = null;
                } else {
                    if (eArg.isParam) {
                        eArg.dataType = Types.BOOLEAN;
                    }

                    if (eArg2.isParam) {
                        eArg2.dataType = Types.BOOLEAN;
                    }
                }

                dataType = Types.BOOLEAN;

                break;
            }
            case OR : {
                boolean argFixed  = eArg.isFixedConditional();
                boolean arg2Fixed = eArg2.isFixedConditional();
                Boolean arg       = argFixed ? (eArg.test(session))
                                             : null;
                Boolean arg2      = arg2Fixed ? eArg2.test(session)
                                              : null;

                if (argFixed && arg2Fixed) {
                    if (arg == null || arg2 == null) {
                        setNull();
                    } else {
                        exprType = arg.booleanValue() || arg2.booleanValue()
                                   ? TRUE
                                   : FALSE;
                        eArg  = null;
                        eArg2 = null;
                    }
                } else if ((argFixed && Boolean.TRUE.equals(arg))
                           || (arg2Fixed && Boolean.TRUE.equals(arg2))) {
                    exprType = TRUE;
                    eArg     = null;
                    eArg2    = null;
                } else {
                    if (eArg.isParam) {
                        eArg.dataType = Types.BOOLEAN;
                    }

                    if (eArg2.isParam) {
                        eArg2.dataType = Types.BOOLEAN;
                    }
                }

                dataType = Types.BOOLEAN;

                break;
            }
            case IS_NULL :
                if (isFixedConditional()) {
                    exprType = Boolean.TRUE.equals(test(session)) ? TRUE
                                                                  : FALSE;
                    eArg     = null;
                } else if (eArg.dataType == Types.NULL) {
                    eArg.dataType = Types.VARCHAR;
                }

                dataType = Types.BOOLEAN;
                break;

            case NOT :
                if (isFixedConditional()) {
                    Boolean arg = test(session);

                    if (arg == null) {
                        setNull();
                    } else {
                        exprType = arg.booleanValue() ? TRUE
                                                      : FALSE;
                        eArg     = null;
                    }
                } else if (eArg.isParam) {
                    eArg.dataType = Types.BOOLEAN;
                }

                dataType = Types.BOOLEAN;
                break;

            case ALL :
            case ANY :
                dataType = eArg.dataType;
                break;

            case IN :
                resolveTypeForIn(session);

                dataType = Types.BOOLEAN;
                break;

            case EXISTS :

                // NOTE: no such thing as a param arg if expression is EXISTS
                // Also, cannot detect if result is fixed value
                dataType = Types.BOOLEAN;
                break;

            /** @todo fredt - set the correct return type */
            case COUNT :
                if (eArg.isParam) {
                    throw Trace.error(Trace.UNRESOLVED_PARAMETER_TYPE,
                                      Trace.Expression_resolveTypes4);
                }

                dataType = Types.INTEGER;
                break;

            case MAX :
            case MIN :
            case SUM :
            case AVG :
            case EVERY :
            case SOME :
            case STDDEV_POP :
            case STDDEV_SAMP :
            case VAR_POP :
            case VAR_SAMP :
                if (eArg.isParam) {
                    throw Trace.error(Trace.UNRESOLVED_PARAMETER_TYPE,
                                      Trace.Expression_resolveTypes4);
                }

                dataType = SetFunction.getType(exprType, eArg.dataType);
                break;

            case CONVERT :

                // NOTE: both iDataType for this expr and for eArg (if isParm)
                // are already set in Parser during read
                if (eArg.isFixedConstant() || eArg.isFixedConditional()) {
                    valueData = getValue(session);
                    exprType  = VALUE;
                    eArg      = null;
                }
                break;

            case CASEWHEN :

                // We use CASEWHEN as parent type.
                // In the parent, eArg is the condition, and eArg2 is
                // the leaf, tagged as type ALTERNATIVE; its eArg is
                // case 1 (how to get the value when the condition in
                // the parent evaluates to true), while its eArg2 is case 2
                // (how to get the value when the condition in
                // the parent evaluates to false).
                if (eArg.isParam) {

                    // condition is a paramter marker,
                    // as in casewhen(?, v1, v2)
                    eArg.dataType = Types.BOOLEAN;
                }

                dataType = getCaseWhenType(session);
                break;

            case ALTERNATIVE : {
                Expression case1 = eArg;
                Expression case2 = eArg2;

                if (case1.isParam && case2.isParam) {
                    throw Trace.error(Trace.UNRESOLVED_PARAMETER_TYPE,
                                      Trace.Expression_resolveTypes6);
                }

                if (case1.isParam || case1.dataType == Types.NULL) {
                    case1.dataType = case2.dataType;
                } else if (case2.isParam || case2.dataType == Types.NULL) {
                    case2.dataType = case1.dataType;
                }

                if (case1.dataType == Types.NULL
                        && case2.dataType == Types.NULL) {
                    dataType = Types.NULL;
                }

                if (Types.isNumberType(case1.dataType)
                        && Types.isNumberType(case2.dataType)) {
                    dataType = Column.getCombinedNumberType(case1.dataType,
                            case2.dataType, ALTERNATIVE);
                } else if (Types.isCharacterType(case1.dataType)
                           && Types.isCharacterType(case2.dataType)) {
                    dataType = Types.LONGVARCHAR;
                } else if (case1.dataType != case2.dataType) {
                    if (case2.exprType == Expression.VALUE) {
                        dataType = case2.dataType = case1.dataType;
                        case2.valueData = Column.convertObject(case2.valueData,
                                                               dataType);
                    } else if (case1.exprType == Expression.VALUE) {
                        dataType = case1.dataType = case2.dataType;
                        case1.valueData = Column.convertObject(case1.valueData,
                                                               dataType);
                    } else {
                        throw Trace.error(Trace.UNRESOLVED_PARAMETER_TYPE,
                                          Trace.Expression_resolveTypes7,
                                          new String[] {
                            Types.getTypeString(case1.dataType),
                            Types.getTypeString(case2.dataType)
                        });
                    }
                } else {
                    dataType = case1.dataType;
                }

                break;
            }
        }
    }