/// <summary> /// Appends a single part, including (useless) optimizations /// </summary> /// <param name="parts"></param> /// <param name="index"></param> /// <param name="part"></param> public static void InsertPart(IList<SqlPart> parts, int index, SqlPart part) { // optimization if top part is a literal, and the one we're adding is a literal too // in this case, we combine both // (this is useless, just pretty) if (part is SqlLiteralPart && index > 0 && parts[index - 1] is SqlLiteralPart) { parts[index - 1] = new SqlLiteralPart(parts[index - 1].Sql + part.Sql); } else parts.Insert(index, part); }
/// <summary> /// Appends a single part, including (useless) optimizations /// </summary> /// <param name="parts"></param> /// <param name="index"></param> /// <param name="part"></param> public static void InsertPart(IList <SqlPart> parts, int index, SqlPart part) { // optimization if top part is a literal, and the one we're adding is a literal too // in this case, we combine both // (this is useless, just pretty) if (part is SqlLiteralPart && index > 0 && parts[index - 1] is SqlLiteralPart) { parts[index - 1] = new SqlLiteralPart(parts[index - 1].Sql + part.Sql); } else { parts.Insert(index, part); } }
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)); }
protected virtual SqlStatement BuildExpression(Expression expression) { 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); }