File: fx\src\data\System\Data\Filter\UnaryNode.cs
Project: ndp\System.Data.csproj (System.Data)
//------------------------------------------------------------------------------
// <copyright file="UnaryNode.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
// <owner current="true" primary="false">Microsoft</owner>
// <owner current="false" primary="false">Microsoft</owner>
//------------------------------------------------------------------------------
 
namespace System.Data {
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Data.Common;
    using System.Data.SqlTypes;
 
 
    internal sealed class UnaryNode : ExpressionNode {
        internal readonly int op;
 
        internal ExpressionNode right;
 
        internal UnaryNode(DataTable table, int op, ExpressionNode right) : base(table) {
            this.op = op;
            this.right = right;
        }
 
        internal override void Bind(DataTable table, List<DataColumn> list) {
            BindTable(table);
            right.Bind(table, list);
        }
 
        internal override object Eval() {
            return Eval(null, DataRowVersion.Default);
        }
 
        internal override object Eval(DataRow row, DataRowVersion version) {
            return EvalUnaryOp(op, right.Eval(row, version));
        }
 
        internal override object Eval(int[] recordNos) {
            return right.Eval(recordNos);
        }
 
        private object EvalUnaryOp(int op, object vl) {
            object value = DBNull.Value;
 
            if (DataExpression.IsUnknown(vl))
                return DBNull.Value;
 
            StorageType storageType;
            switch (op) {
                case Operators.Noop:
                    return vl;
                case Operators.UnaryPlus:
                    storageType = DataStorage.GetStorageType(vl.GetType());
                    if (ExpressionNode.IsNumericSql(storageType)) {
                        return vl;
                    }
                    throw ExprException.TypeMismatch(this.ToString());
 
                case Operators.Negative:
                    // the have to be better way for doing this..
                    storageType = DataStorage.GetStorageType(vl.GetType());
                    if (ExpressionNode.IsNumericSql(storageType)) {
                        switch(storageType) {
                        case StorageType.Byte:
                            value = -(Byte) vl;
                            break;
                        case StorageType.Int16:
                            value = -(Int16) vl;
                            break;
                        case StorageType.Int32:
                            value = -(Int32) vl;
                            break;
                        case StorageType.Int64:
                            value = -(Int64) vl;
                            break;
                        case StorageType.Single:
                            value = -(Single) vl;
                            break;
                        case StorageType.Double:
                            value = -(Double) vl;
                            break;
                        case StorageType.Decimal:
                            value = -(Decimal) vl;
                            break;
                        case StorageType.SqlDecimal:
                            value = -(SqlDecimal) vl;
                            break;
                        case StorageType.SqlDouble:
                            value = -(SqlDouble) vl;
                            break;
                        case StorageType.SqlSingle:
                            value = -(SqlSingle) vl;
                            break;
                        case StorageType.SqlMoney:
                            value = -(SqlMoney) vl;
                            break;
                        case StorageType.SqlInt64:
                            value = -(SqlInt64) vl;
                            break;
                        case StorageType.SqlInt32:
                            value = -(SqlInt32) vl;
                            break;
                        case StorageType.SqlInt16:
                            value = -(SqlInt16) vl;
                            break;
                        default:
                            Debug.Assert(false, "Missing a type conversion");
                            value = DBNull.Value;
                            break;
                        }
                        return value;
                    }
 
                    throw ExprException.TypeMismatch(this.ToString());
 
                case Operators.Not:
                    if (vl is SqlBoolean){
                            if (((SqlBoolean)vl).IsFalse){
                                return SqlBoolean.True;
                            }
                            else if (((SqlBoolean)vl).IsTrue) {
                                      return SqlBoolean.False;
                            }
                            throw ExprException.UnsupportedOperator(op);  // or should the result of not SQLNull  be SqlNull ?
                    }
                    else{
                          if (DataExpression.ToBoolean(vl) != false)
                             return false;
                          return true;
                    }
 
                default:
                    throw ExprException.UnsupportedOperator(op);
            }
        }
 
        internal override bool IsConstant() {
            return(right.IsConstant());
        }
 
        internal override bool IsTableConstant() {
            return(right.IsTableConstant());
        }
 
        internal override bool HasLocalAggregate() {
            return(right.HasLocalAggregate());
        }
        
        internal override bool HasRemoteAggregate() {
            return(right.HasRemoteAggregate());
        }
 
        internal override bool DependsOn(DataColumn column) {
            return(right.DependsOn(column));
        }
 
 
        internal override ExpressionNode Optimize() {
            right = right.Optimize();
 
            if (this.IsConstant()) {
                object val = this.Eval();
 
                return new ConstNode(table, ValueType.Object,  val, false);
            }
            else
                return this;
        }
    }
}