/// <summary> /// The simple part: converts an expression to SQL /// This is not used for FROM clause /// </summary> /// <param name="expression"></param> /// <param name="queryContext"></param> /// <returns></returns> protected virtual SqlStatement BuildExpression(Expression expression, QueryContext queryContext) { var sqlProvider = queryContext.DataContext.Vendor.SqlProvider; var currentPrecedence = ExpressionQualifier.GetPrecedence(expression); // first convert operands var operands = expression.GetOperands(); var literalOperands = new List <SqlStatement>(); foreach (var operand in operands) { var operandPrecedence = ExpressionQualifier.GetPrecedence(operand); var literalOperand = BuildExpression(operand, queryContext); if (operandPrecedence > currentPrecedence) { literalOperand = sqlProvider.GetParenthesis(literalOperand); } literalOperands.Add(literalOperand); } // then converts expression if (expression is SpecialExpression) { return(sqlProvider.GetLiteral(((SpecialExpression)expression).SpecialNodeType, literalOperands)); } if (expression is EntitySetExpression) { expression = ((EntitySetExpression)expression).TableExpression; } if (expression is TableExpression) { var tableExpression = (TableExpression)expression; if (tableExpression.Alias != null) // if we have an alias, use it { return(sqlProvider.GetColumn(sqlProvider.GetTableAlias(tableExpression.Alias), sqlProvider.GetColumns())); } return(sqlProvider.GetColumns()); } if (expression is ColumnExpression) { var columnExpression = (ColumnExpression)expression; if (columnExpression.Table.Alias != null) { return(sqlProvider.GetColumn(sqlProvider.GetTableAlias(columnExpression.Table.Alias), columnExpression.Name)); } return(sqlProvider.GetColumn(columnExpression.Name)); } if (expression is InputParameterExpression) { var inputParameterExpression = (InputParameterExpression)expression; if (expression.Type.IsArray) { int i = 0; List <SqlStatement> inputParameters = new List <SqlStatement>(); foreach (object p in (Array)inputParameterExpression.GetValue()) { inputParameters.Add(new SqlStatement(new SqlParameterPart(sqlProvider.GetParameterName(inputParameterExpression.Alias + i.ToString()), inputParameterExpression.Alias + i.ToString()))); ++i; } return(new SqlStatement(sqlProvider.GetLiteral(inputParameters.ToArray()))); } return (new SqlStatement(new SqlParameterPart(sqlProvider.GetParameterName(inputParameterExpression.Alias), inputParameterExpression.Alias))); } if (expression is SelectExpression) { return(Build((SelectExpression)expression, queryContext)); } if (expression is ConstantExpression) { return(sqlProvider.GetLiteral(((ConstantExpression)expression).Value)); } if (expression is GroupExpression) { return(BuildExpression(((GroupExpression)expression).GroupedExpression, queryContext)); } StartIndexOffsetExpression indexExpression = expression as StartIndexOffsetExpression; if (indexExpression != null) { if (indexExpression.StartsAtOne) { literalOperands.Add(BuildExpression(Expression.Constant(1), queryContext)); return(sqlProvider.GetLiteral(ExpressionType.Add, literalOperands)); } else { return(literalOperands.First()); } } if (expression.NodeType == ExpressionType.Convert || expression.NodeType == ExpressionType.ConvertChecked) { var unaryExpression = (UnaryExpression)expression; var firstOperand = literalOperands.First(); if (IsConversionRequired(unaryExpression)) { return(sqlProvider.GetLiteralConvert(firstOperand, unaryExpression.Type)); } return(firstOperand); } return(sqlProvider.GetLiteral(expression.NodeType, literalOperands)); }
protected virtual SqlStatement BuildExpression(Expression expression, bool allowNull = false) { if (expression == null) { Util.Check(allowNull, "Expression argument may not be null."); return(null); } if (expression is ConstantExpression) { return(_sqlProvider.GetLiteral(((ConstantExpression)expression).Value)); } var currentPrecedence = ExpressionUtil.GetPrecedence(expression); // first convert operands var operands = expression.GetOperands(); var literalOperands = new List <SqlStatement>(); foreach (var operand in operands) { var operandPrecedence = ExpressionUtil.GetPrecedence(operand); var literalOperand = BuildExpression(operand); if (operandPrecedence > currentPrecedence) { literalOperand = _sqlProvider.GetParenthesis(literalOperand); } literalOperands.Add(literalOperand); } if (expression is AliasedExpression) { var aliasExpr = (AliasedExpression)expression; return(BuildExpression(aliasExpr.Expression)); //Alias will be added later } // then converts expression if (expression is SqlFunctionExpression) { var specExpr = (SqlFunctionExpression)expression; //RI: Special case for multiple "*" operands if (specExpr.FunctionType == SqlFunctionType.Count && literalOperands.Count > 0) { literalOperands.Clear(); literalOperands.Add("*"); } return(_sqlProvider.GetSqlFunction(specExpr.FunctionType, specExpr.ForceIgnoreCase, literalOperands)); } if (expression is TableExpression) { var tableExpression = (TableExpression)expression; if (tableExpression.Alias != null) // if we have an alias, use it { return(_sqlProvider.GetColumn(_sqlProvider.GetTableAlias(tableExpression.Alias), _sqlProvider.GetColumns())); } return(_sqlProvider.GetColumns()); } //RI: We might have NewExpression here! Query: (from b in books select new {b.Title}).Count(); // in this case the NewExpression is 'hidden' inside subquery and it is not visible to CutOutOperands // We just return list of arguments (columns) of New expression if (expression is NewExpression) { return(new SqlStatement(literalOperands)); } //RI: adding this if (expression is MetaTableExpression) { var metaTable = (MetaTableExpression)expression; return(_sqlProvider.GetColumns()); } if (expression is ColumnExpression) { var columnExpression = (ColumnExpression)expression; if (columnExpression.Table.Alias != null) { return(_sqlProvider.GetColumn(_sqlProvider.GetTableAlias(columnExpression.Table.Alias), columnExpression.Name)); } //RI: changed this to keep output type var sqlPart = new SqlLiteralPart(_sqlProvider.GetColumn(columnExpression.Name), expression.Type); return(new SqlStatement(sqlPart)); //return _sqlProvider.GetColumn(columnExpression.Name); } if (expression is ExternalValueExpression) { var extValue = (ExternalValueExpression)expression; switch (extValue.SqlUse) { case ExternalValueSqlUse.Literal: var sql = _sqlProvider.GetLiteral(extValue.LiteralValue); return(sql); case ExternalValueSqlUse.Parameter: // In SQL templates the first 2 args are reserved for { and } symbols return(_sqlProvider.GetParameter(extValue)); default: // we should never get here Util.Throw("LINQ engine error: encountered ExternalValueExpression with invalid Usage type: {0}, Expression: {1}", extValue.SqlUse, extValue.SourceExpression); return(null); //never happens } } if (expression is SelectExpression) { return(BuildSelectSql((SelectExpression)expression)); } if (expression is GroupExpression) { return(BuildExpression(((GroupExpression)expression).GroupedExpression)); } StartIndexOffsetExpression indexExpression = expression as StartIndexOffsetExpression; if (indexExpression != null) { if (indexExpression.StartsAtOne) { literalOperands.Add(BuildExpression(Expression.Constant(1))); return(_sqlProvider.GetLiteral(ExpressionType.Add, literalOperands)); } else { return(literalOperands.First()); } } if (expression.NodeType == ExpressionType.Convert || expression.NodeType == ExpressionType.ConvertChecked) { var unaryExpression = (UnaryExpression)expression; var firstOperand = literalOperands.First(); if (IsConversionRequired(unaryExpression)) { return(_sqlProvider.GetLiteralConvert(firstOperand, unaryExpression.Type)); } return(firstOperand); } if (expression is BinaryExpression || expression is UnaryExpression) { return(_sqlProvider.GetLiteral(expression.NodeType, literalOperands)); } if (expression is TableFilterExpression) { return(_sqlProvider.GetTableFilter((TableFilterExpression)expression)); } return(_sqlProvider.GetLiteral(expression.NodeType, literalOperands)); }