コード例 #1
0
        protected virtual Expression AnalyzeProjectionQuery(SqlFunctionType specialExpressionType, IList<Expression> parameters,
            TranslationContext context, bool canHaveFilter = true)
        {
            if (context.IsExternalInExpressionChain)
            {
                var operand0 = Analyze(parameters[0], context);
                Expression functionOperand = null;
                Expression projectionOperand;

                if (    context.CurrentSelect.NextSelectExpression != null
                    ||  context.CurrentSelect.Operands.Count() > 0
                    ||  context.CurrentSelect.Group.Count > 0
                   )
                {
                    // No TableInfo in projection
                    operand0 = new SubSelectExpression(context.CurrentSelect, operand0.Type, "source", null);
                    context.NewParentSelect();

                    // In the new scope we should not have MaximumDatabaseLoad
                    //context.QueryContext.MaximumDatabaseLoad = false;

                    context.CurrentSelect.Tables.Add(operand0 as TableExpression);
                }

                // basically, we have three options for projection methods:
                // - projection on grouped table (1 operand, a GroupExpression)
                // - projection on grouped column (2 operands, GroupExpression and ColumnExpression)
                // - projection on table/column, with optional restriction
                var groupOperand0 = operand0 as GroupExpression;
                if (groupOperand0 != null)
                {
                    if (parameters.Count > 1)
                        projectionOperand = Analyze(parameters[1], groupOperand0.GroupedExpression, context);
                    else
                        projectionOperand = Analyze(groupOperand0.GroupedExpression, context);
                }
                else
                {
                    projectionOperand = operand0;
                    if (parameters.Count > 1)
                      functionOperand = Analyze(parameters[1], operand0, context);
                    int filterIndex = canHaveFilter ? 1 : -1; //special case for Average - its second parameter is NOT filter
                    CheckWhere(projectionOperand, parameters, filterIndex, context);
                }

                if (projectionOperand is TableExpression)
                    projectionOperand = RegisterTable((TableExpression)projectionOperand, context);

                if (groupOperand0 != null) {
                  var childColumns = GetChildColumns(projectionOperand, context);
                  projectionOperand = new GroupExpression(projectionOperand, groupOperand0.KeyExpression, childColumns);
                }

                var opList = new List<Expression>();
                opList.Add(projectionOperand);
                if (functionOperand != null)
                  opList.Add(functionOperand);
                return CreateSqlFunction(specialExpressionType, opList.ToArray());
            }
            else
            {
                var subQueryContext = context.NewSelect();

                var tableExpression = Analyze(parameters[0], subQueryContext);

                //RI: new stuff - handling grouping with aggregates
                //if (IsAggregate(specialExpressionType)) {
                  var grpExpr = tableExpression as GroupExpression;
                  var srcTable = grpExpr == null ? tableExpression : grpExpr.GroupedExpression ;
                  SqlFunctionExpression specialExpr;
                  if (parameters.Count > 1) {
                    var predicate = Analyze(parameters[1], srcTable, subQueryContext);
                    specialExpr = CreateSqlFunction(specialExpressionType, tableExpression, predicate);
                  } else {
                    specialExpr = CreateSqlFunction(specialExpressionType, tableExpression);
                  }
                  // If subQuery context has no tables added, it is not a subquery, it's just an aggregate function over 'main' table
                  var currSelect = subQueryContext.CurrentSelect;
                  if (currSelect.Tables.Count == 0)
                    return specialExpr;
                  //this is a real subquery, so mutate and return the current select from this context
                  currSelect = currSelect.ChangeOperands(new Expression[] { specialExpr }, currSelect.Operands);
                  return currSelect;
                //}
                //RI: end my special code
            }
        }
コード例 #2
0
        /// <summary>
        /// Any() returns true if the given condition satisfies at least one of provided elements
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        protected virtual Expression AnalyzeAny(IList<Expression> parameters, TranslationContext context)
        {
            if (context.IsExternalInExpressionChain)
            {
                var tableExpression = Analyze(parameters[0], context);
                Expression projectionOperand;

                if (context.CurrentSelect.NextSelectExpression != null)
                {
                    TableExpression currentTableExpression = tableExpression as TableExpression;
                    tableExpression = new SubSelectExpression(context.CurrentSelect, currentTableExpression.Type, "source", currentTableExpression.TableInfo);
                    context.NewParentSelect();

                    // In the new scope we should not have MaximumDatabaseLoad
                    //context.QueryContext.MaximumDatabaseLoad = false;

                    context.CurrentSelect.Tables.Add(tableExpression as TableExpression);
                }

                // basically, we have three options for projection methods:
                // - projection on grouped table (1 operand, a GroupExpression)
                // - projection on grouped column (2 operands, GroupExpression and ColumnExpression)
                // - projection on table/column, with optional restriction
                var groupOperand0 = tableExpression as GroupExpression;
                if (groupOperand0 != null)
                {
                    if (parameters.Count > 1)
                    {
                        projectionOperand = Analyze(parameters[1], groupOperand0.GroupedExpression,
                                                    context);
                    }
                    else
                        projectionOperand = Analyze(groupOperand0.GroupedExpression, context);
                }
                else
                {
                    projectionOperand = tableExpression;
                    CheckWhere(projectionOperand, parameters, 1, context);
                }

                if (projectionOperand is TableExpression)
                    projectionOperand = RegisterTable((TableExpression)projectionOperand, context);

                if (groupOperand0 != null) {
                  var childColumns = GetChildColumns(groupOperand0.KeyExpression, context);
                  projectionOperand = new GroupExpression(projectionOperand, groupOperand0.KeyExpression, childColumns);
                }

                return ExpressionUtil.MakeGreaterThanZero(CreateSqlFunction(SqlFunctionType.Count, projectionOperand));
            }
            else
            {
                var anyBuilderContext = context.NewSelect();
                var tableExpression = Analyze(parameters[0], anyBuilderContext);

                if (!(tableExpression is TableExpression))
                    tableExpression = Analyze(tableExpression, anyBuilderContext);

                // from here we build a custom clause:
                // <anyClause> ==> "(select count(*) from <table> where <anyClause>)>0"
                // TODO (later...): see if some vendors support native Any operator and avoid this substitution
                if (parameters.Count > 1)
                {
                    var anyClause = Analyze(parameters[1], tableExpression, anyBuilderContext);
                    RegisterWhere(anyClause, anyBuilderContext);
                }
                var countExpr = CreateSqlFunction(SqlFunctionType.Count, tableExpression);
                var currSelect = anyBuilderContext.CurrentSelect;
                anyBuilderContext.CurrentSelect = currSelect.ChangeOperands(new Expression[] {countExpr}, currSelect.Operands);
                // TODO: see if we need to register the tablePiece here (we probably don't)

                // we now switch back to current context, and compare the result with 0
                // note - we might have count returning int or long, so we must adjust 0 constant (int or long)
                var anyExpression = ExpressionUtil.MakeGreaterThanZero(anyBuilderContext.CurrentSelect);
                return anyExpression;
            }
        }
コード例 #3
0
        protected virtual Expression AnalyzeContains(IList<Expression> parameters, TranslationContext context)
        {
            if (!parameters[1].Type.IsDbPrimitive())
              parameters = ConvertContainsWithObject(parameters, context);

            var t0 = parameters[0].Type;
            if (t0.IsGenericQueryable()) {
              Expression p1 = Analyze(parameters[1], context);
              var newContext = context.NewSelect();
              Expression p0 = AnalyzeSubQuery(parameters[0], newContext);
              var c = p0 as ColumnExpression;
              if (c != null && !newContext.CurrentSelect.Tables.Contains(c.Table))
                newContext.CurrentSelect.Tables.Add(c.Table);
              return CreateSqlFunction(SqlFunctionType.In, p1, newContext.CurrentSelect.Mutate(new Expression[] { p0 }));
            } else if (t0.IsListOrArray()) {
              Expression array = Analyze(parameters[0], context);
              var expression = Analyze(parameters[1], context);
              return CreateSqlFunction(SqlFunctionType.InArray, expression, array);
            }
            throw Util.Throw("{0}.Contains() method is not supported.", t0.GetDisplayName());
        }
コード例 #4
0
        protected virtual Expression AnalyzeAll(IList<Expression> parameters, TranslationContext context)
        {
            var allBuilderContext = context.NewSelect();
            var tableExpression = Analyze(parameters[0], allBuilderContext);
            var allClause = Analyze(parameters[1], tableExpression, allBuilderContext);
            // from here we build a custom clause:
            // <allClause> ==> "(select count(*) from <table> where not <allClause>)==0"
            // TODO (later...): see if some vendors support native All operator and avoid this substitution
            var whereExpression = Expression.Not(allClause);
            RegisterWhere(whereExpression, allBuilderContext);
            var countExpr = CreateSqlFunction(SqlFunctionType.Count, tableExpression);
            var currSelect = allBuilderContext.CurrentSelect;
            allBuilderContext.CurrentSelect = currSelect.ChangeOperands(new Expression[] {countExpr}, currSelect.Operands);
            // TODO: see if we need to register the tablePiece here (we probably don't)

            // we now switch back to current context, and compare the result with 0
            // Note: be careful, result of Count() might be int32 or int64 for different servers, so user CreateConstant helper
            var zero = ExpressionUtil.CreateConstant(0, allBuilderContext.CurrentSelect.Type);
            var allExpression = Expression.Equal(allBuilderContext.CurrentSelect, zero);
            return allExpression;
        }