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;
}
}
}