private int Eval(BinaryNode expr, DataRow row, DataRowVersion version)
{
if (expr._op == Operators.And)
{
int lResult = Eval((BinaryNode)expr._left, row, version);
if (lResult != 0)
return lResult;
int rResult = Eval((BinaryNode)expr._right, row, version);
if (rResult != 0)
return rResult;
return 0;
}
long c = 0;
object vLeft = expr._left.Eval(row, version);
if (expr._op != Operators.Is && expr._op != Operators.IsNot)
{
object vRight = expr._right.Eval(row, version);
bool isLConst = (expr._left is ConstNode);
bool isRConst = (expr._right is ConstNode);
if ((vLeft == DBNull.Value) || (expr._left.IsSqlColumn && DataStorage.IsObjectSqlNull(vLeft)))
return -1;
if ((vRight == DBNull.Value) || (expr._right.IsSqlColumn && DataStorage.IsObjectSqlNull(vRight)))
return 1;
StorageType leftType = DataStorage.GetStorageType(vLeft.GetType());
if (StorageType.Char == leftType)
{
if ((isRConst) || (!expr._right.IsSqlColumn))
vRight = Convert.ToChar(vRight, _table.FormatProvider);
else
vRight = SqlConvert.ChangeType2(vRight, StorageType.Char, typeof(char), _table.FormatProvider);
}
StorageType rightType = DataStorage.GetStorageType(vRight.GetType());
StorageType resultType;
if (expr._left.IsSqlColumn || expr._right.IsSqlColumn)
{
resultType = expr.ResultSqlType(leftType, rightType, isLConst, isRConst, expr._op);
}
else
{
resultType = expr.ResultType(leftType, rightType, isLConst, isRConst, expr._op);
}
if (StorageType.Empty == resultType)
{
expr.SetTypeMismatchError(expr._op, vLeft.GetType(), vRight.GetType());
}
// if comparing a Guid column value against a string literal
// use InvariantCulture instead of DataTable.Locale because in the Danish related cultures
// sorting a Guid as a string has different results than in Invariant and English related cultures.
// This fix is restricted to DataTable.Select("GuidColumn = 'string literal'") types of queries
NameNode namedNode = null;
System.Globalization.CompareInfo comparer =
((isLConst && !isRConst && (leftType == StorageType.String) && (rightType == StorageType.Guid) && (null != (namedNode = expr._right as NameNode)) && (namedNode._column.DataType == typeof(Guid))) ||
(isRConst && !isLConst && (rightType == StorageType.String) && (leftType == StorageType.Guid) && (null != (namedNode = expr._left as NameNode)) && (namedNode._column.DataType == typeof(Guid))))
? System.Globalization.CultureInfo.InvariantCulture.CompareInfo : null;
c = expr.BinaryCompare(vLeft, vRight, resultType, expr._op, comparer);
}
switch (expr._op)
{
case Operators.EqualTo: c = (c == 0 ? 0 : c < 0 ? -1 : 1); break;
case Operators.GreaterThen: c = (c > 0 ? 0 : -1); break;
case Operators.LessThen: c = (c < 0 ? 0 : 1); break;
case Operators.GreaterOrEqual: c = (c >= 0 ? 0 : -1); break;
case Operators.LessOrEqual: c = (c <= 0 ? 0 : 1); break;
case Operators.Is: c = (vLeft == DBNull.Value ? 0 : -1); break;
case Operators.IsNot: c = (vLeft != DBNull.Value ? 0 : 1); break;
default: Debug.Assert(true, "Unsupported Binary Search Operator!"); break;
}
return (int)c;
}