예제 #1
0
        protected override Expression VisitBinaryExpression(BinaryExpression expression)
        {
            // handle special cases
            if (expression.NodeType == ExpressionType.Equal)
            {
                if (HandleAddressOrIdEquals(expression.Left, expression.Right))
                {
                    return(expression);
                }
            }
            if (expression.NodeType == ExpressionType.Equal || expression.NodeType == ExpressionType.NotEqual)
            {
                if (HandleEqualsNotEquals(expression))
                {
                    return(expression);
                }
                var leftPropertyHint  = GetPropertyHint(expression.Left);
                var rightPropertyHint = GetPropertyHint(expression.Right);
                var leftIsAddress     = leftPropertyHint != null &&
                                        (leftPropertyHint.MappingType == PropertyMappingType.Address ||
                                         leftPropertyHint.MappingType == PropertyMappingType.Id);
                var rightIsAddress = rightPropertyHint != null &&
                                     (rightPropertyHint.MappingType == PropertyMappingType.Address ||
                                      rightPropertyHint.MappingType == PropertyMappingType.Id);


                //handle checking for nulls (bug 5416)

                /*
                 * if (rightPropertyHint == null && expression.Right.NodeType == ExpressionType.Constant)
                 * {
                 *  var constantExpression = expression.Right as ConstantExpression;
                 *  var value = constantExpression.Value;
                 *  var defValue = expression.Left.Type.GetDefaultValue();
                 *  if ((value == null && defValue == null) || (value != null && value.Equals(defValue)))
                 *  {
                 *      if (leftIsAddress)
                 *      {
                 *          var querySourceReferenceExpression =
                 *              ((MemberExpression) expression.Left).Expression as QuerySourceReferenceExpression;
                 *          var varname = querySourceReferenceExpression.ReferencedQuerySource.ItemName;
                 *
                 *          var filter = expression.NodeType == ExpressionType.NotEqual
                 *                           ? "( bound(?{0}))"
                 *                           : "(!bound(?{0}))";
                 *          _filterWriter.AppendFormat(filter, varname);
                 *          return expression;
                 *      }
                 *      else
                 *      {
                 *          string varname = null;
                 *          QueryBuilder.StartOptional();
                 *          var convertedExpression = VisitExpression(expression.Left);
                 *          QueryBuilder.EndOptional();
                 *          if (convertedExpression is SelectVariableNameExpression)
                 *          {
                 *              varname = (convertedExpression as SelectVariableNameExpression).Name;
                 *          }
                 *          if (varname != null)
                 *          {
                 *              string filter;
                 *              if (expression.Left.Type.IsValueType && defValue != null)
                 *              {
                 *                  filter = expression.NodeType == ExpressionType.NotEqual
                 *                               ? "(bound(?{0}) && (?{0} != {1}))"
                 *                               : "(!bound(?{0}) || (?{0} = {1}))";
                 *              }
                 *              else
                 *              {
                 *                  filter = expression.NodeType == ExpressionType.NotEqual
                 *                               ? "( bound(?{0}))"
                 *                               : "(!bound(?{0}))";
                 *              }
                 *              if (defValue != null)
                 *              {
                 *                  _filterWriter.AppendFormat(filter, varname,
                 *                                             _filterWriter.MakeSparqlConstant(defValue));
                 *              }
                 *              else
                 *              {
                 *                  _filterWriter.AppendFormat(filter, varname);
                 *              }
                 *              return expression;
                 *          }
                 *      }
                 *  }
                 * }
                 *
                 * if (leftIsAddress && expression.Right.NodeType == ExpressionType.Constant)
                 * {
                 *  var querySourceReferenceExpression = ((MemberExpression)expression.Left).Expression as QuerySourceReferenceExpression;
                 *  var varname = querySourceReferenceExpression.ReferencedQuerySource.ItemName;
                 *
                 *  var constantExpression = expression.Right as ConstantExpression;
                 *  var value = constantExpression.Value.ToString();
                 *
                 *  var filter = expression.NodeType == ExpressionType.Equal
                 *                   ? "( sameTerm(?{0}, <{1}>))"
                 *                   : "(!sameTerm(?{0}, <{1}>))";
                 *
                 *  _filterWriter.AppendFormat(filter, varname, MakeResourceAddress(GetPropertyInfo(expression.Right), value));
                 *  return expression;
                 * }
                 *
                 * if (rightIsAddress && expression.Left.NodeType == ExpressionType.Constant)
                 * {
                 *  var querySourceReferenceExpression =
                 *      ((MemberExpression) expression.Right).Expression as QuerySourceReferenceExpression;
                 *  var varname = querySourceReferenceExpression.ReferencedQuerySource.ItemName;
                 *  var constantExpression = expression.Left as ConstantExpression;
                 *  var value = constantExpression.Value.ToString();
                 *  var filter = expression.NodeType == ExpressionType.Equal
                 *                   ? "(sameTerm(<{0}>,?{1}))"
                 *                   : "(!sameTerm(?{0}, <{1}>))";
                 *  _filterWriter.AppendFormat(filter, MakeResourceAddress(GetPropertyInfo(expression.Left), value), varname);
                 * }
                 */
                if (leftIsAddress && rightIsAddress)
                {
                    // Comparing two resource addresses - use the sameTerm function rather then simple equality
                    _filterWriter.Append(expression.NodeType == ExpressionType.Equal
                                                    ? "(sameTerm("
                                                    : "(!sameTerm(");
                    _filterWriter.VisitExpression(expression.Left);
                    _filterWriter.Append(",");
                    _filterWriter.VisitExpression(expression.Right);
                    _filterWriter.Append("))");
                    return(expression);
                }
            }

            var mce = expression.Left as MethodCallExpression;

            if (mce != null && mce.Method.Name.Equals("Compare"))
            {
                //handle compare (bug 5441)
                HandleCompareExpression(mce, expression.NodeType);
                return(expression);
            }

            // Process operators that translate to SPARQL functions
            switch (expression.NodeType)
            {
            case ExpressionType.Or:
                _filterWriter.WriteFunction(BrightstarDB.Query.BrightstarFunctionFactory.BrightstarFunctionsNamespace, BrightstarDB.Query.BrightstarFunctionFactory.BitOr, expression.Left, expression.Right);
                return(expression);

            case ExpressionType.And:
                _filterWriter.WriteFunction(BrightstarDB.Query.BrightstarFunctionFactory.BrightstarFunctionsNamespace, BrightstarDB.Query.BrightstarFunctionFactory.BitAnd, expression.Left, expression.Right);
                return(expression);
            }

            // Process in-fix operator
            _filterWriter.Append('(');
            _filterWriter.VisitExpression(expression.Left);
            switch (expression.NodeType)
            {
            case ExpressionType.Add:
            case ExpressionType.AddChecked:
                _filterWriter.Append(" + ");
                break;

            case ExpressionType.AndAlso:
                _filterWriter.Append(" && ");
                break;

            case ExpressionType.Divide:
                _filterWriter.Append(" / ");
                break;

            case ExpressionType.Equal:
                _filterWriter.Append(" = ");
                break;

            case ExpressionType.GreaterThan:
                _filterWriter.Append(" > ");
                break;

            case ExpressionType.GreaterThanOrEqual:
                _filterWriter.Append(" >= ");
                break;

            case ExpressionType.LessThan:
                _filterWriter.Append(" < ");
                break;

            case ExpressionType.LessThanOrEqual:
                _filterWriter.Append(" <= ");
                break;

            case ExpressionType.Multiply:
            case ExpressionType.MultiplyChecked:
                _filterWriter.Append(" * ");
                break;

            case ExpressionType.NotEqual:
                _filterWriter.Append(" != ");
                break;

            case ExpressionType.OrElse:
                _filterWriter.Append(" || ");
                break;

            case ExpressionType.Subtract:
            case ExpressionType.SubtractChecked:
                _filterWriter.Append(" - ");
                break;

            default:
                base.VisitBinaryExpression(expression);
                break;
            }
            _filterWriter.VisitExpression(expression.Right);
            _filterWriter.Append(')');
            return(expression);
        }
        private Expression HandleBinaryExpression(BinaryExpression expression)
        {
            // handle special cases
            if (expression.NodeType == ExpressionType.Equal)
            {
                if (HandleAddressOrIdEquals(expression.Left, expression.Right))
                {
                    return(expression);
                }
            }
            if (expression.NodeType == ExpressionType.Equal || expression.NodeType == ExpressionType.NotEqual)
            {
                if (HandleEqualsNotEquals(expression))
                {
                    return(expression);
                }
                var leftPropertyHint  = GetPropertyHint(expression.Left);
                var rightPropertyHint = GetPropertyHint(expression.Right);
                var leftIsAddress     = leftPropertyHint != null &&
                                        (leftPropertyHint.MappingType == PropertyMappingType.Address ||
                                         leftPropertyHint.MappingType == PropertyMappingType.Id);
                var rightIsAddress = rightPropertyHint != null &&
                                     (rightPropertyHint.MappingType == PropertyMappingType.Address ||
                                      rightPropertyHint.MappingType == PropertyMappingType.Id);
                if (leftIsAddress && rightIsAddress)
                {
                    // Comparing two resource addresses - use the sameTerm function rather then simple equality
                    _filterWriter.Append(expression.NodeType == ExpressionType.Equal
                        ? "(sameTerm("
                        : "(!sameTerm(");
                    _filterWriter.VisitExpression(expression.Left);
                    _filterWriter.Append(",");
                    _filterWriter.VisitExpression(expression.Right);
                    _filterWriter.Append("))");
                    return(expression);
                }
            }

            var mce = expression.Left as MethodCallExpression;

            if (mce != null && mce.Method.Name.Equals("Compare"))
            {
                //handle compare (bug 5441)
                HandleCompareExpression(mce, expression.NodeType);
                return(expression);
            }

            // Process operators that translate to SPARQL functions
            switch (expression.NodeType)
            {
            case ExpressionType.Or:
                _filterWriter.WriteFunction(BrightstarFunctionFactory.BrightstarFunctionsNamespace,
                                            BrightstarFunctionFactory.BitOr, expression.Left, expression.Right);
                return(expression);

            case ExpressionType.And:
                _filterWriter.WriteFunction(BrightstarFunctionFactory.BrightstarFunctionsNamespace,
                                            BrightstarFunctionFactory.BitAnd, expression.Left, expression.Right);
                return(expression);
            }

            // Process in-fix operator
            if (_optimizeFilter)
            {
                switch (expression.NodeType)
                {
                case ExpressionType.Equal:
                    QueryBuilder.StartBgpGroup();
                    AppendOptimisedEqualityExpression(expression.Left, expression.Right);
                    QueryBuilder.EndBgpGroup();
                    break;

                case ExpressionType.NotEqual:
                    QueryBuilder.StartMinus();
                    AppendOptimisedEqualityExpression(expression.Left, expression.Right);
                    QueryBuilder.EndMinus();
                    break;

                case ExpressionType.OrElse:
                    _inBooleanExpression = true;
                    QueryBuilder.StartBgpGroup();
                    VisitExpression(expression.Left);
                    QueryBuilder.EndBgpGroup();

                    QueryBuilder.Union();

                    QueryBuilder.StartBgpGroup();
                    VisitExpression(expression.Right);
                    QueryBuilder.EndBgpGroup();
                    _inBooleanExpression = false;
                    break;

                case ExpressionType.AndAlso:
                    _inBooleanExpression = true;
                    VisitExpression(expression.Left);
                    VisitExpression(expression.Right);
                    _inBooleanExpression = false;
                    break;

                default:
                    throw new NotSupportedException();
                }
            }
            else
            {
                _filterWriter.Append('(');
                _filterWriter.VisitExpression(expression.Left);
                switch (expression.NodeType)
                {
                case ExpressionType.Add:
                case ExpressionType.AddChecked:
                    _filterWriter.Append(" + ");
                    break;

                case ExpressionType.AndAlso:
                    _filterWriter.Append(" && ");
                    break;

                case ExpressionType.Divide:
                    _filterWriter.Append(" / ");
                    break;

                case ExpressionType.Equal:
                    _filterWriter.Append(" = ");
                    break;

                case ExpressionType.GreaterThan:
                    _filterWriter.Append(" > ");
                    break;

                case ExpressionType.GreaterThanOrEqual:
                    _filterWriter.Append(" >= ");
                    break;

                case ExpressionType.LessThan:
                    _filterWriter.Append(" < ");
                    break;

                case ExpressionType.LessThanOrEqual:
                    _filterWriter.Append(" <= ");
                    break;

                case ExpressionType.Multiply:
                case ExpressionType.MultiplyChecked:
                    _filterWriter.Append(" * ");
                    break;

                case ExpressionType.NotEqual:
                    _filterWriter.Append(" != ");
                    break;

                case ExpressionType.OrElse:
                    _filterWriter.Append(" || ");
                    break;

                case ExpressionType.Subtract:
                case ExpressionType.SubtractChecked:
                    _filterWriter.Append(" - ");
                    break;

                default:
                    base.VisitBinaryExpression(expression);
                    break;
                }
                _filterWriter.VisitExpression(expression.Right);
                _filterWriter.Append(')');
            }
            return(expression);
        }