private SqlExpression TranslateEqualsOp(SqlNodeType op, SqlExpression left, SqlExpression right, bool allowExpand) { switch (op) { case SqlNodeType.EQ: case SqlNodeType.NE: return(this.sql.Binary(op, left, right)); case SqlNodeType.EQ2V: { if ((SqlExpressionNullability.CanBeNull(left) != false) && (SqlExpressionNullability.CanBeNull(right) != false)) { SqlNodeType type = allowExpand ? SqlNodeType.EQ2V : SqlNodeType.EQ; return(this.sql.Binary(SqlNodeType.Or, this.sql.Binary(SqlNodeType.And, this.sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(left)), this.sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(right))), this.sql.Binary(SqlNodeType.And, this.sql.Binary(SqlNodeType.And, this.sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(left)), this.sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(right))), this.sql.Binary(type, left, right)))); } SqlNodeType nodeType = allowExpand ? SqlNodeType.EQ2V : SqlNodeType.EQ; return(this.sql.Binary(nodeType, left, right)); } case SqlNodeType.NE2V: { if ((SqlExpressionNullability.CanBeNull(left) == false) || (SqlExpressionNullability.CanBeNull(right) == false)) { SqlNodeType type4 = allowExpand ? SqlNodeType.NE2V : SqlNodeType.NE; return(this.sql.Binary(type4, left, right)); } SqlNodeType type3 = allowExpand ? SqlNodeType.EQ2V : SqlNodeType.EQ; return(this.sql.Unary(SqlNodeType.Not, this.sql.Binary(SqlNodeType.Or, this.sql.Binary(SqlNodeType.And, this.sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(left)), this.sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(right))), this.sql.Binary(SqlNodeType.And, this.sql.Binary(SqlNodeType.And, this.sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(left)), this.sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(right))), this.sql.Binary(type3, left, right))))); } } throw Error.UnexpectedNode(op); }
internal SqlExpression TranslateLinkIsNull(SqlUnary expr) { SqlLink operand = expr.Operand as SqlLink; if (((operand == null) || !operand.Member.IsAssociation) || !operand.Member.Association.IsForeignKey) { return(expr); } IList <SqlExpression> keyExpressions = operand.KeyExpressions; SqlExpression left = null; SqlNodeType nodeType = (expr.NodeType == SqlNodeType.IsNull) ? SqlNodeType.Or : SqlNodeType.And; int num = 0; int count = keyExpressions.Count; while (num < count) { SqlExpression right = this.sql.Unary(expr.NodeType, this.sql.DoNotVisitExpression(keyExpressions[num]), expr.SourceExpression); if (left == null) { left = right; } else { left = this.sql.Binary(nodeType, left, right); } num++; } return(left); }
internal SqlBetween(SqlNodeType nodeType, SqlExpression expression, SqlExpression left, SqlExpression right) : base(nodeType) { this.expression = expression; this.left = left; this.right = right; }
internal SqlUnary Unary(SqlNodeType nodeType, SqlExpression expression, MethodInfo method, Expression sourceExpression) { Type type = null; ProviderType providerType = null; switch (nodeType) { case SqlNodeType.Count: type = typeof(int); providerType = TypeProvider.From(typeof(int)); break; case SqlNodeType.LongCount: type = typeof(long); providerType = TypeProvider.From(typeof(long)); break; case SqlNodeType.ClrLength: type = typeof(int); providerType = TypeProvider.From(typeof(int)); break; default: type = ((!nodeType.IsPredicateUnaryOperator()) ? expression.ClrType : (expression.ClrType.Equals(typeof(bool?)) ? typeof(bool?) : typeof(bool))); providerType = TypeProvider.PredictTypeForUnary(nodeType, expression.SqlType); break; } return(new SqlUnary(nodeType, type, providerType, expression, method, sourceExpression)); }
private SqlExpression TranslateEqualsOp(SqlNodeType op, SqlExpression left, SqlExpression right, bool allowExpand) { switch (op) { case SqlNodeType.EQ: case SqlNodeType.NE: return(sql.Binary(op, left, right)); case SqlNodeType.EQ2V: { if (SqlExpressionNullability.CanBeNull(left) != false && SqlExpressionNullability.CanBeNull(right) != false) { var nodeType3 = allowExpand ? SqlNodeType.EQ2V : SqlNodeType.EQ; return(sql.Binary(SqlNodeType.Or, sql.Binary(SqlNodeType.And, sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(left)), sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(right))), sql.Binary(SqlNodeType.And, sql.Binary(SqlNodeType.And, sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(left)), sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(right))), sql.Binary(nodeType3, left, right)))); } var nodeType4 = allowExpand ? SqlNodeType.EQ2V : SqlNodeType.EQ; return(sql.Binary(nodeType4, left, right)); } case SqlNodeType.NE2V: { if (SqlExpressionNullability.CanBeNull(left) != false && SqlExpressionNullability.CanBeNull(right) != false) { var nodeType = allowExpand ? SqlNodeType.EQ2V : SqlNodeType.EQ; return(sql.Unary(SqlNodeType.Not, sql.Binary(SqlNodeType.Or, sql.Binary(SqlNodeType.And, sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(left)), sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(right))), sql.Binary(SqlNodeType.And, sql.Binary(SqlNodeType.And, sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(left)), sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(right))), sql.Binary(nodeType, left, right))))); } var nodeType2 = allowExpand ? SqlNodeType.NE2V : SqlNodeType.NE; return(sql.Binary(nodeType2, left, right)); } default: throw Error.UnexpectedNode(op); } }
internal override SqlExpression VisitUnaryOperator(SqlUnary uo) { SqlNodeType nodeType = uo.NodeType; if (nodeType <= SqlNodeType.LongCount) { switch (nodeType) { case SqlNodeType.Avg: case SqlNodeType.Count: case SqlNodeType.LongCount: goto Label_002B; } goto Label_0034; } if (((nodeType != SqlNodeType.Max) && (nodeType != SqlNodeType.Min)) && (nodeType != SqlNodeType.Sum)) { goto Label_0034; } Label_002B: this.hasAggregates = true; return(uo); Label_0034: return(base.VisitUnaryOperator(uo)); }
internal static bool IsUnaryOperatorExpectingPredicateOperand(this SqlNodeType nodeType) { switch (nodeType) { case SqlNodeType.Not: case SqlNodeType.Not2V: return(true); case SqlNodeType.IsNull: case SqlNodeType.IsNotNull: case SqlNodeType.Negate: case SqlNodeType.BitNot: case SqlNodeType.Count: case SqlNodeType.LongCount: case SqlNodeType.Max: case SqlNodeType.Min: case SqlNodeType.Sum: case SqlNodeType.Avg: case SqlNodeType.Stddev: case SqlNodeType.Convert: case SqlNodeType.ValueOf: case SqlNodeType.OuterJoinedValue: case SqlNodeType.ClrLength: return(false); default: throw Error.UnexpectedNode(nodeType); } }
protected override SqlNode VisitFirst(Expression sequence, LambdaExpression lambda, bool isFirst) { SqlSelect select = this.LockSelect(this.VisitSequence(sequence)); if (lambda != null) { this.map[lambda.Parameters[0]] = select.Selection; select.Where = this.VisitExpression(lambda.Body); } if (isFirst) { var f = sql.FunctionCall(typeof(int), "LIMIT", new[] { sql.ValueFromObject(1, false, dominatingExpression) }, dominatingExpression); f.Brackets = false; f.Comma = false; select.Top = f; } if (this.outerNode) { return(select); } SqlNodeType nt = this.typeProvider.From(select.Selection.ClrType).CanBeColumn ? SqlNodeType.ScalarSubSelect : SqlNodeType.Element; return(this.sql.SubSelect(nt, select, sequence.Type)); }
internal SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right, MethodInfo method) : base(nt, clrType, sqlType, right.SourceExpression) { switch (nt) { case SqlNodeType.Add: case SqlNodeType.Sub: case SqlNodeType.Mul: case SqlNodeType.Div: case SqlNodeType.Mod: case SqlNodeType.BitAnd: case SqlNodeType.BitOr: case SqlNodeType.BitXor: case SqlNodeType.And: case SqlNodeType.Or: case SqlNodeType.GE: case SqlNodeType.GT: case SqlNodeType.LE: case SqlNodeType.LT: case SqlNodeType.EQ: case SqlNodeType.NE: case SqlNodeType.EQ2V: case SqlNodeType.NE2V: case SqlNodeType.Concat: case SqlNodeType.Coalesce: break; default: throw Error.UnexpectedNode(nt); } this.Left = left; this.Right = right; this.method = method; }
internal SqlSubSelect SubSelect(SqlNodeType nt, SqlSelect select, Type clrType) { ProviderType sqlType = null; switch (nt) { case SqlNodeType.ScalarSubSelect: case SqlNodeType.Element: clrType = @select.Selection.ClrType; sqlType = @select.Selection.SqlType; break; case SqlNodeType.Multiset: if (clrType == null) { clrType = typeof(List <>).MakeGenericType(@select.Selection.ClrType); } sqlType = typeProvider.GetApplicationType((int)ConverterSpecialTypes.Table); break; case SqlNodeType.Exists: clrType = typeof(bool); sqlType = typeProvider.From(typeof(bool)); break; } return(new SqlSubSelect(nt, clrType, sqlType, @select)); }
internal SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right, MethodInfo method) : base(nt, clrType, sqlType, right.SourceExpression) { switch (nt) { case SqlNodeType.BitAnd: case SqlNodeType.BitOr: case SqlNodeType.BitXor: case SqlNodeType.And: case SqlNodeType.Add: case SqlNodeType.Coalesce: case SqlNodeType.Concat: case SqlNodeType.Div: case SqlNodeType.EQ: case SqlNodeType.EQ2V: case SqlNodeType.LE: case SqlNodeType.LT: case SqlNodeType.GE: case SqlNodeType.GT: case SqlNodeType.Mod: case SqlNodeType.Mul: case SqlNodeType.NE: case SqlNodeType.NE2V: case SqlNodeType.Or: case SqlNodeType.Sub: this.Left = left; this.Right = right; this.method = method; return; } throw new Exception("Unexpected node: " + nt); }
internal SqlUserQuery(SqlNodeType nt, SqlExpression projection, IEnumerable <SqlExpression> args, Expression source) : base(nt, source) { Projection = projection; this.args = (args != null) ? new List <SqlExpression>(args) : new List <SqlExpression>(); columns = new List <SqlUserColumn>(); }
internal SqlUnary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression expr, MethodInfo method, Expression sourceExpression) : base(nt, clrType, sqlType, sourceExpression) { switch (nt) { case SqlNodeType.Not: case SqlNodeType.Not2V: case SqlNodeType.Negate: case SqlNodeType.BitNot: case SqlNodeType.IsNull: case SqlNodeType.IsNotNull: case SqlNodeType.Count: case SqlNodeType.LongCount: case SqlNodeType.Max: case SqlNodeType.Min: case SqlNodeType.Sum: case SqlNodeType.Avg: case SqlNodeType.Stddev: case SqlNodeType.Convert: case SqlNodeType.ValueOf: case SqlNodeType.Treat: case SqlNodeType.OuterJoinedValue: case SqlNodeType.ClrLength: break; default: throw Error.UnexpectedNode(nt); } this.Operand = expr; this.method = method; }
// Constructor internal SqlQueryExpression(SqlNodeType nodeType, ISqlQueryExpression left, ISqlQueryExpression right, bool all) : base(nodeType) { this.left = left; this.right = right; this.all = all; }
internal static bool IsClientAidedExpression(this SqlExpression expr) { SqlNodeType nodeType = expr.NodeType; if (nodeType <= SqlNodeType.Link) { switch (nodeType) { case SqlNodeType.ClientQuery: case SqlNodeType.Element: case SqlNodeType.Link: goto Label_002C; } goto Label_002E; } if (((nodeType != SqlNodeType.Multiset) && (nodeType != SqlNodeType.New)) && (nodeType != SqlNodeType.TypeCase)) { goto Label_002E; } Label_002C: return(true); Label_002E: return(false); }
protected override SqlNode VisitFirst(Expression sequence, LambdaExpression lambda, bool isFirst) { //var takeExp = VisitExpression(Expression.Constant(1)); //return GenerateSkipTake(VisitSequence(sequence), null, takeExp); SqlSelect select = this.LockSelect(this.VisitSequence(sequence)); if (lambda != null) { this.map[lambda.Parameters[0]] = select.Selection; select.Where = this.VisitExpression(lambda.Body); } if (isFirst) { //select.Top = this.sql.ValueFromObject(1, false, this.dominatingExpression); var skipExp = sql.Value(typeof(int), typeProvider.From(typeof(int)), -1, false, dominatingExpression); var takeExp = sql.Value(typeof(int), typeProvider.From(typeof(int)), 1, false, dominatingExpression); IEnumerable <SqlExpression> expressions = new[] { skipExp, takeExp }; select.Top = new SqlFunctionCall(typeof(int), typeProvider.From(typeof(int)), "SkipTake", expressions, takeExp.SourceExpression); } if (this.outerNode) { return(select); } SqlNodeType nt = this.typeProvider.From(select.Selection.ClrType).CanBeColumn ? SqlNodeType.ScalarSubSelect : SqlNodeType.Element; return(this.sql.SubSelect(nt, select, sequence.Type)); }
internal static bool IsComparisonOperator(this SqlNodeType nodeType) { switch (nodeType) { case SqlNodeType.BitAnd: case SqlNodeType.BitOr: case SqlNodeType.BitXor: case SqlNodeType.And: case SqlNodeType.Add: case SqlNodeType.Coalesce: case SqlNodeType.Concat: case SqlNodeType.Div: case SqlNodeType.Mod: case SqlNodeType.Mul: case SqlNodeType.Or: case SqlNodeType.Sub: return(false); case SqlNodeType.EQ: case SqlNodeType.EQ2V: case SqlNodeType.LE: case SqlNodeType.LT: case SqlNodeType.GE: case SqlNodeType.GT: case SqlNodeType.NE: case SqlNodeType.NE2V: return(true); } throw Error.UnexpectedNode(nodeType); }
internal SqlExpression TranslateLinkIsNull(SqlUnary expr) { System.Diagnostics.Debug.Assert(expr.NodeType == SqlNodeType.IsNull || expr.NodeType == SqlNodeType.IsNotNull); SqlLink link = expr.Operand as SqlLink; if (!(link != null && link.Member.IsAssociation && link.Member.Association.IsForeignKey)) { return(expr); } List <SqlExpression> exprs = link.KeyExpressions; System.Diagnostics.Debug.Assert(exprs.Count > 0); SqlExpression exp = null; SqlNodeType combo = (expr.NodeType == SqlNodeType.IsNull) ? SqlNodeType.Or : SqlNodeType.And; for (int i = 0, n = exprs.Count; i < n; i++) { SqlExpression compare = sql.Unary(expr.NodeType, sql.DoNotVisitExpression(exprs[i]), expr.SourceExpression); if (exp == null) { exp = compare; } else { exp = sql.Binary(combo, exp, compare); } } return(exp); }
internal SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right, MethodInfo method) : base(nt, clrType, sqlType, right.SourceExpression) { switch (nt) { case SqlNodeType.Add: case SqlNodeType.Sub: case SqlNodeType.Mul: case SqlNodeType.Div: case SqlNodeType.Mod: case SqlNodeType.BitAnd: case SqlNodeType.BitOr: case SqlNodeType.BitXor: case SqlNodeType.And: case SqlNodeType.Or: case SqlNodeType.GE: case SqlNodeType.GT: case SqlNodeType.LE: case SqlNodeType.LT: case SqlNodeType.EQ: case SqlNodeType.NE: case SqlNodeType.EQ2V: case SqlNodeType.NE2V: case SqlNodeType.Concat: case SqlNodeType.Coalesce: break; default: throw Error.UnexpectedNode(nt); } Left = left; Right = right; this.method = method; }
protected override SqlNode VisitFirst(Expression sequence, LambdaExpression lambda, bool isFirst) { SqlSelect select = this.LockSelect(this.VisitSequence(sequence)); if (lambda != null) { this.map[lambda.Parameters[0]] = select.Selection; select.Where = this.VisitExpression(lambda.Body); } if (isFirst) { var valueType = typeof(int); var sqlType = typeProvider.From(valueType); var skipExp = sql.ValueFromObject(0, false, dominatingExpression); var takeExp = sql.ValueFromObject(1, false, dominatingExpression); IEnumerable <SqlExpression> expressions = new[] { takeExp, skipExp }; select.Top = new SqlFunctionCall(valueType, sqlType, "Limit", expressions, takeExp.SourceExpression); } if (this.outerNode) { return(select); } SqlNodeType nt = this.typeProvider.From(select.Selection.ClrType).CanBeColumn ? SqlNodeType.ScalarSubSelect : SqlNodeType.Element; return(this.sql.SubSelect(nt, select, sequence.Type)); }
internal static bool IsPredicateBinaryOperator(this SqlNodeType nodeType) { switch (nodeType) { case SqlNodeType.GE: case SqlNodeType.GT: case SqlNodeType.LE: case SqlNodeType.LT: case SqlNodeType.EQ: case SqlNodeType.NE: case SqlNodeType.EQ2V: case SqlNodeType.NE2V: case SqlNodeType.And: case SqlNodeType.Or: return(true); case SqlNodeType.Add: case SqlNodeType.Sub: case SqlNodeType.Mul: case SqlNodeType.Div: case SqlNodeType.Mod: case SqlNodeType.BitAnd: case SqlNodeType.BitOr: case SqlNodeType.BitXor: case SqlNodeType.Concat: case SqlNodeType.Coalesce: return(false); default: throw Error.UnexpectedNode(nodeType); } }
//用来修正日期值为 0000:00:00 的情况 internal override SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right, MethodInfo method, Type clrType, IProviderType sqlType) { var args = new[] { left, right }; if (left.NodeType != right.NodeType) { var m = args.Where(o => o.NodeType != SqlNodeType.Value).FirstOrDefault(); var n = args.OfType <SqlValue>().Select(o => o.Value).FirstOrDefault(); var type = m.ClrType.IsGenericType ? m.ClrType.GetGenericArguments()[0] : m.ClrType; if (type == typeof(DateTime) && n == null) { if (nodeType == SqlNodeType.EQ) { var b1 = new SqlBinary(nodeType, clrType, sqlType, left, right, method); var b2 = new SqlBinary(SqlNodeType.LT, clrType, sqlType, m, ValueFromObject(DateTime.MinValue, m.SourceExpression)); return(new SqlBinary(SqlNodeType.Or, typeof(bool), TypeProvider.From(typeof(bool)), b1, b2)); } if (nodeType == SqlNodeType.NE) { var b1 = new SqlBinary(nodeType, clrType, sqlType, left, right, method); var b2 = new SqlBinary(SqlNodeType.GT, clrType, sqlType, m, ValueFromObject(DateTime.MinValue, m.SourceExpression)); return(new SqlBinary(SqlNodeType.And, typeof(bool), TypeProvider.From(typeof(bool)), b1, b2)); } } } return(base.Binary(nodeType, left, right, method, clrType, sqlType)); }
internal static bool IsUnaryOperatorExpectingPredicateOperand(this SqlNodeType nodeType) { SqlNodeType type = nodeType; if (type <= SqlNodeType.LongCount) { switch (type) { case SqlNodeType.Avg: case SqlNodeType.BitNot: case SqlNodeType.Cast: case SqlNodeType.IsNotNull: case SqlNodeType.IsNull: case SqlNodeType.LongCount: case SqlNodeType.Convert: case SqlNodeType.Count: case SqlNodeType.Covar: case SqlNodeType.ClrLength: goto Label_00A9; } goto Label_00AB; } if (type <= SqlNodeType.Not2V) { switch (type) { case SqlNodeType.Negate: case SqlNodeType.Min: case SqlNodeType.Max: goto Label_00A9; case SqlNodeType.New: goto Label_00AB; case SqlNodeType.Not: case SqlNodeType.Not2V: return(true); } goto Label_00AB; } if (type <= SqlNodeType.Stddev) { switch (type) { case SqlNodeType.OuterJoinedValue: case SqlNodeType.Stddev: goto Label_00A9; } goto Label_00AB; } if ((type != SqlNodeType.Sum) && (type != SqlNodeType.ValueOf)) { goto Label_00AB; } Label_00A9: return(false); Label_00AB: throw Error.UnexpectedNode(nodeType); }
internal override SqlSelect VisitSelect(SqlSelect select) { if (select.IsDistinct) { this.IsDistinct = true; this.AddIdentityMembers(select.Selection.ClrType.GetProperties()); return(select); } select.From = (SqlSource)base.Visit(select.From); if ((this.IdentityMembers == null) || (this.IdentityMembers.Count == 0)) { throw Error.SkipRequiresSingleTableQueryWithPKs(); } SqlNodeType nodeType = select.Selection.NodeType; if (nodeType <= SqlNodeType.ColumnRef) { switch (nodeType) { case SqlNodeType.Column: case SqlNodeType.ColumnRef: goto Label_009E; case SqlNodeType.AliasRef: goto Label_00DD; } goto Label_00F1; } if (nodeType != SqlNodeType.Member) { switch (nodeType) { case SqlNodeType.Treat: case SqlNodeType.TypeCase: return(select); case SqlNodeType.New: goto Label_00DD; } goto Label_00F1; } Label_009E: if (this.IdentityMembers.Count == 1) { MemberInfo column = this.IdentityMembers[0]; this.IsValid &= IsColumnMatch(column, select.Selection); return(select); } this.IsValid = false; return(select); Label_00DD: select.Selection = this.VisitExpression(select.Selection); return(select); Label_00F1: this.IsValid = false; return(select); }
internal SqlFunctionCall(SqlNodeType nodeType, Type clrType, IProviderType sqlType, string name, IEnumerable <SqlExpression> args, Expression source) : base(nodeType, clrType, sqlType, source) { this.Name = name; this.Arguments = new MyList(args); Comma = true; Brackets = true; }
public override string GetOperator(SqlNodeType nt) { if (nt == SqlNodeType.LongCount) { return("COUNT"); } return(base.GetOperator(nt)); }
internal SqlExpression VisitParameter(SqlExpression expr) { SqlExpression expression = VisitExpression(expr); SqlNodeType nodeType = expression.NodeType; if (nodeType != SqlNodeType.Parameter) { return(nodeType == SqlNodeType.Value ? InsertLookup((SqlValue)expression) : expression); } return(expression); }
private static void Traverse(SqlExpression expression, SqlNodeType operatorType, List <SqlExpression> output) { if (expression.NodeType == operatorType) { var binary = (SqlBinary)expression; Traverse(binary.Left, operatorType, output); Traverse(binary.Right, operatorType, output); } else { output.Add(expression); } }
internal SqlSubSelect(SqlNodeType nt , Type clrType, ProviderType sqlType , SqlSelect select) : base(nt, clrType, sqlType, select.SourceExpression) { switch (nt) { case SqlNodeType.Multiset: case SqlNodeType.ScalarSubSelect: case SqlNodeType.Element: case SqlNodeType.Exists: break; default: throw Error.UnexpectedNode(nt); } this.Select = select; }
/// <summary> /// Helper for VisitBinaryOperator. Builds the new case with distributed valueds. /// </summary> private SqlExpression DistributeOperatorIntoCase(SqlNodeType nt, SqlSimpleCase sc, SqlExpression expr) { if (nt!=SqlNodeType.EQ && nt!=SqlNodeType.NE && nt!=SqlNodeType.EQ2V && nt!=SqlNodeType.NE2V) throw Error.ArgumentOutOfRange("nt"); object val = Eval(expr); List<SqlExpression> values = new List<SqlExpression>(); List<SqlExpression> matches = new List<SqlExpression>(); foreach(SqlWhen when in sc.Whens) { matches.Add(when.Match); object whenVal = Eval(when.Value); bool eq = when.Value.SqlType.AreValuesEqual(whenVal, val); values.Add(sql.ValueFromObject((nt==SqlNodeType.EQ || nt==SqlNodeType.EQ2V) == eq, false, sc.SourceExpression)); } return this.VisitExpression(sql.Case(typeof(bool), sc.Expression, matches, values, sc.SourceExpression)); }
// Methods internal SqlSubSelect(SqlNodeType nt, Type clrType, IProviderType sqlType, SqlSelect select) : base(nt, clrType, sqlType, select.SourceExpression) { switch (nt) { case SqlNodeType.Element: case SqlNodeType.Exists: case SqlNodeType.Multiset: case SqlNodeType.ScalarSubSelect: this.Select = select; return; } throw Error.UnexpectedNode(nt); }
internal override SQLTYPE PredictTypeForUnary(SqlNodeType unaryOp, SQLTYPE operandType) { switch (unaryOp) { case SqlNodeType.Avg: case SqlNodeType.Covar: case SqlNodeType.Stddev: case SqlNodeType.Sum: return(MostPreciseTypeInFamily(operandType)); case SqlNodeType.BitNot: return(operandType); case SqlNodeType.ClrLength: if (operandType.IsLargeType) { return(From(typeof(long))); } return(From(typeof(int))); case SqlNodeType.LongCount: return(From(typeof(long))); case SqlNodeType.Max: return(operandType); case SqlNodeType.Count: return(From(typeof(int))); case SqlNodeType.IsNotNull: case SqlNodeType.IsNull: case SqlNodeType.Not: case SqlNodeType.Not2V: return(SqlTypes[TypeCode.Boolean]); //TheBit; case SqlNodeType.Negate: return(operandType); case SqlNodeType.OuterJoinedValue: return(operandType); case SqlNodeType.Min: return(operandType); case SqlNodeType.Treat: case SqlNodeType.ValueOf: return(operandType); } throw Error.UnexpectedNode(unaryOp); }
private static bool IsComparison(SqlNodeType nodeType) { switch (nodeType) { case SqlNodeType.EQ: case SqlNodeType.NE: case SqlNodeType.LT: case SqlNodeType.LE: case SqlNodeType.GT: case SqlNodeType.GE: case SqlNodeType.EQ2V: case SqlNodeType.NE2V: return true; default: return false; } }
public override string Translate(SqlNodeType type) { switch (type) { case SqlNodeType.Count: return("COUNT_BIG"); case SqlNodeType.Concat: return("+"); case SqlNodeType.Overlaps: throw new NotSupportedException(string.Format(Strings.ExOperationXIsNotSupported, type)); } return(base.Translate(type)); }
private SqlBinary MakeCompareTo(SqlExpression left, SqlExpression right, SqlNodeType op, int iValue) { if(iValue == 0) { return sql.Binary(op, left, right); } if(op == SqlNodeType.EQ || op == SqlNodeType.EQ2V) { switch(iValue) { case -1: return sql.Binary(SqlNodeType.LT, left, right); case 1: return sql.Binary(SqlNodeType.GT, left, right); } } return null; }
internal Where(SqlNodeType nodeType, Expression sourceExpression, SqlExpression source, SqlExpression condition) : base(nodeType, source.ClrType, sourceExpression) { Source = source; Condition = condition; }
private SqlExpression TranslateEqualsOp(SqlNodeType op, SqlExpression left, SqlExpression right, bool allowExpand) { switch (op) { case SqlNodeType.EQ: case SqlNodeType.NE: return sql.Binary(op, left, right); case SqlNodeType.EQ2V: if (SqlExpressionNullability.CanBeNull(left) != false && SqlExpressionNullability.CanBeNull(right) != false) { SqlNodeType eqOp = allowExpand ? SqlNodeType.EQ2V : SqlNodeType.EQ; return sql.Binary(SqlNodeType.Or, sql.Binary(SqlNodeType.And, sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(left)), sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(right)) ), sql.Binary(SqlNodeType.And, sql.Binary(SqlNodeType.And, sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(left)), sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(right)) ), sql.Binary(eqOp, left, right) ) ); } else { SqlNodeType eqOp = allowExpand ? SqlNodeType.EQ2V : SqlNodeType.EQ; return sql.Binary(eqOp, left, right); } case SqlNodeType.NE2V: if (SqlExpressionNullability.CanBeNull(left) != false && SqlExpressionNullability.CanBeNull(right) != false) { SqlNodeType eqOp = allowExpand ? SqlNodeType.EQ2V : SqlNodeType.EQ; return sql.Unary(SqlNodeType.Not, sql.Binary(SqlNodeType.Or, sql.Binary(SqlNodeType.And, sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(left)), sql.Unary(SqlNodeType.IsNull, (SqlExpression)SqlDuplicator.Copy(right)) ), sql.Binary(SqlNodeType.And, sql.Binary(SqlNodeType.And, sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(left)), sql.Unary(SqlNodeType.IsNotNull, (SqlExpression)SqlDuplicator.Copy(right)) ), sql.Binary(eqOp, left, right) ) ) ); } else { SqlNodeType neOp = allowExpand ? SqlNodeType.NE2V : SqlNodeType.NE; return sql.Binary(neOp, left, right); } default: throw Error.UnexpectedNode(op); } }
private SqlExpression GetAggregate(SqlNodeType aggType, Type clrType, SqlExpression exp) { ProviderType sqlType = this.typeProvider.From(clrType); return new SqlUnary(aggType, clrType, sqlType, exp, this.dominatingExpression); }
private SqlNode VisitAggregate(Expression sequence, LambdaExpression lambda, SqlNodeType aggType, Type returnType) { // Convert seq.Agg(exp) into // // 1) SELECT Agg(exp) FROM seq // 2) SELECT Agg1 FROM (SELECT Agg(exp) as Agg1 FROM group-seq GROUP BY ...) // 3) SCALAR(SELECT Agg(exp) FROM seq) // bool isCount = aggType == SqlNodeType.Count || aggType == SqlNodeType.LongCount; SqlNode source = this.Visit(sequence); SqlSelect select = this.CoerceToSequence(source); SqlAlias alias = new SqlAlias(select); SqlAliasRef aref = new SqlAliasRef(alias); // If the sequence is of the form x.Select(expr).Agg() and the lambda for the aggregate is null, // or is a no-op parameter expression (like u=>u), clone the group by selection lambda // expression, and use for the aggregate. // Final form should be x.Agg(expr) MethodCallExpression mce = sequence as MethodCallExpression; if (!outerNode && !isCount && (lambda == null || (lambda.Parameters.Count == 1 && lambda.Parameters[0] == lambda.Body)) && (mce != null) && IsSequenceOperatorCall(mce, "Select") && select.From is SqlAlias) { LambdaExpression selectionLambda = GetLambda(mce.Arguments[1]); lambda = Expression.Lambda(selectionLambda.Type, selectionLambda.Body, selectionLambda.Parameters); alias = (SqlAlias)select.From; aref = new SqlAliasRef(alias); } if (lambda != null && !TypeSystem.IsSimpleType(lambda.Body.Type)) { throw Error.CannotAggregateType(lambda.Body.Type); } //Empty parameter aggregates are not allowed on anonymous types //i.e. db.Customers.Select(c=>new{c.Age}).Max() instead it should be // db.Customers.Select(c=>new{c.Age}).Max(c=>c.Age) if (select.Selection.SqlType.IsRuntimeOnlyType && !IsGrouping(sequence.Type) && !isCount && lambda == null) { throw Error.NonCountAggregateFunctionsAreNotValidOnProjections(aggType); } if (lambda != null) this.map[lambda.Parameters[0]] = aref; if (this.outerNode) { // If this aggregate is basically the last/outer-most operator of the query // // produce SELECT Agg(exp) FROM seq // SqlExpression exp = (lambda != null) ? this.VisitExpression(lambda.Body) : null; SqlExpression where = null; if (isCount && exp != null) { where = exp; exp = null; } else if (exp == null && !isCount) { exp = aref; } if (exp != null) { // in case this contains another aggregate exp = new SqlSimpleExpression(exp); } SqlSelect sel = new SqlSelect( this.GetAggregate(aggType, returnType, exp), alias, this.dominatingExpression ); sel.Where = where; sel.OrderingType = SqlOrderingType.Never; return sel; } else if (!isCount || lambda == null) { // Look to optimize aggregate by pushing its evaluation down to the select node that has the // actual group-by operator. // // Produce: SELECT Agg1 FROM (SELECT Agg(exp) as Agg1 FROM seq GROUP BY ...) // GroupInfo info = this.FindGroupInfo(source); if (info != null) { SqlExpression exp = null; if (lambda != null) { // evaluate expression relative to the group-by select node this.map[lambda.Parameters[0]] = (SqlExpression)SqlDuplicator.Copy(info.ElementOnGroupSource); exp = this.VisitExpression(lambda.Body); } else if (!isCount) { // support aggregates w/o an explicit selector specified exp = info.ElementOnGroupSource; } if (exp != null) { // in case this contains another aggregate exp = new SqlSimpleExpression(exp); } SqlExpression agg = this.GetAggregate(aggType, returnType, exp); SqlColumn c = new SqlColumn(agg.ClrType, agg.SqlType, null, null, agg, this.dominatingExpression); info.SelectWithGroup.Row.Columns.Add(c); return new SqlColumnRef(c); } } // Otherwise, if we cannot optimize then fall back to generating a nested aggregate in a correlated sub query // // SCALAR(SELECT Agg(exp) FROM seq) { SqlExpression exp = (lambda != null) ? this.VisitExpression(lambda.Body) : null; if (exp != null) { // in case this contains another aggregate exp = new SqlSimpleExpression(exp); } SqlSelect sel = new SqlSelect( this.GetAggregate(aggType, returnType, isCount ? null : (lambda == null) ? aref : exp), alias, this.dominatingExpression ); sel.Where = isCount ? exp : null; return sql.SubSelect(SqlNodeType.ScalarSubSelect, sel); } }
internal SqlSubSelect SubSelect(SqlNodeType nt, SqlSelect select) { return this.SubSelect(nt, select, null); }
internal SqlNode(SqlNodeType nodeType, Expression sourceExpression) { this.nodeType = nodeType; this.sourceExpression = sourceExpression; }
internal SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right, MethodInfo method, Type clrType) { ProviderType sqlType = null; if (nodeType.IsPredicateBinaryOperator()) { if (clrType == null) { clrType = typeof(bool); } sqlType = typeProvider.From(clrType); } else { ProviderType resultType = this.typeProvider.PredictTypeForBinary(nodeType, left.SqlType, right.SqlType); if (resultType == right.SqlType) { if (clrType == null) { clrType = right.ClrType; } sqlType = right.SqlType; } else if (resultType == left.SqlType) { if (clrType == null) { clrType = left.ClrType; } sqlType = left.SqlType; } else { sqlType = resultType; if (clrType == null) { clrType = resultType.GetClosestRuntimeType(); } } } return new SqlBinary(nodeType, clrType, sqlType, left, right, method); }
internal override ProviderType PredictTypeForBinary(SqlNodeType binaryOp, ProviderType leftType, ProviderType rightType) { SqlType highest; if(leftType.IsSameTypeFamily(this.From(typeof(string))) && rightType.IsSameTypeFamily(this.From(typeof(string)))) { highest = (SqlType)this.GetBestType(leftType, rightType); } else { int coercionPrecedence = leftType.ComparePrecedenceTo(rightType); highest = (SqlType)(coercionPrecedence > 0 ? leftType : rightType); } switch(binaryOp) { case SqlNodeType.Add: case SqlNodeType.Sub: case SqlNodeType.Mul: case SqlNodeType.Div: case SqlNodeType.BitAnd: case SqlNodeType.BitOr: case SqlNodeType.BitXor: case SqlNodeType.Mod: case SqlNodeType.Coalesce: return highest; case SqlNodeType.Concat: // When concatenating two types with size, the result type after // concatenation must have a size equal to the sum of the two sizes. if(highest.HasSizeOrIsLarge) { // get the best type, specifying null for size so we get // the maximum allowable size ProviderType concatType = this.GetBestType(highest.SqlDbType, null); if((!leftType.IsLargeType && leftType.Size.HasValue) && (!rightType.IsLargeType && rightType.Size.HasValue)) { // If both types are not large types and have size, and the // size is less than the default size, return the shortened type. int concatSize = leftType.Size.Value + rightType.Size.Value; if((concatSize < concatType.Size) || concatType.IsLargeType) { return GetBestType(highest.SqlDbType, concatSize); } } return concatType; } return highest; case SqlNodeType.And: case SqlNodeType.Or: case SqlNodeType.LT: case SqlNodeType.LE: case SqlNodeType.GT: case SqlNodeType.GE: case SqlNodeType.EQ: case SqlNodeType.NE: case SqlNodeType.EQ2V: case SqlNodeType.NE2V: return ProviderConstants.IntType; default: throw Error.UnexpectedNode(binaryOp); } }
internal SqlSimpleTypeExpression(SqlNodeType nodeType, Type clrType, ProviderType sqlType, Expression sourceExpression) : base(nodeType, clrType, sourceExpression) { this.sqlType = sqlType; }
internal abstract ProviderType PredictTypeForUnary(SqlNodeType unaryOp, ProviderType operandType);
internal abstract ProviderType PredictTypeForBinary(SqlNodeType binaryOp, ProviderType leftType, ProviderType rightType);
internal SqlUnary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression expr, Expression sourceExpression) : this(nt, clrType, sqlType, expr, null, sourceExpression) { }
internal SqlFunctionCall(SqlNodeType nodeType, Type clrType, ProviderType sqlType, string name , IEnumerable <SqlExpression> args , Expression source) : base(nodeType, clrType, sqlType, source) { this.name = name; this.arguments = new List<SqlExpression>(args); }
internal SqlSubSelect SubSelect(SqlNodeType nt, SqlSelect select, Type clrType) { ProviderType sqlType = null; switch (nt) { case SqlNodeType.ScalarSubSelect: case SqlNodeType.Element: clrType = select.Selection.ClrType; sqlType = select.Selection.SqlType; break; case SqlNodeType.Multiset: if (clrType == null) { clrType = typeof(List<>).MakeGenericType(select.Selection.ClrType); } sqlType = typeProvider.GetApplicationType((int)ConverterSpecialTypes.Table); break; case SqlNodeType.Exists: clrType = typeof(bool); sqlType = typeProvider.From(typeof(bool)); break; } return new SqlSubSelect(nt, clrType, sqlType, select); }
internal override ProviderType PredictTypeForUnary(SqlNodeType unaryOp, ProviderType operandType) { switch(unaryOp) { case SqlNodeType.Not: case SqlNodeType.Not2V: case SqlNodeType.IsNull: case SqlNodeType.IsNotNull: return ProviderConstants.BitType; case SqlNodeType.Negate: case SqlNodeType.BitNot: case SqlNodeType.ValueOf: case SqlNodeType.Treat: case SqlNodeType.OuterJoinedValue: return operandType; case SqlNodeType.Count: return this.From(typeof(int)); case SqlNodeType.LongCount: return this.From(typeof(long)); case SqlNodeType.Min: case SqlNodeType.Max: return operandType; case SqlNodeType.Sum: case SqlNodeType.Avg: case SqlNodeType.Stddev: return this.MostPreciseTypeInFamily(operandType); case SqlNodeType.ClrLength: if(operandType.IsLargeType) { return this.From(typeof(long)); // SqlDbType.BigInt } else { return this.From(typeof(int)); // SqlDbType.Int } default: throw Error.UnexpectedNode(unaryOp); } }
public SqlBinaryExpression(SqlNodeType nodeType, SqlExpression left, SqlExpression right) { this.nodeType = nodeType; this.left = left; this.right = right; }
internal SqlExpression(SqlNodeType nodeType, Type clrType, Expression sourceExpression) : base(nodeType, sourceExpression) { this.clrType = clrType; }
internal SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right, Type clrType) { return Binary(nodeType, left, right, null, clrType); }
// Methods internal SqlStatement(SqlNodeType nodeType, Expression sourceExpression) : base(nodeType, sourceExpression) { }
internal SqlUnary Unary(SqlNodeType nodeType, SqlExpression expression, Expression sourceExpression) { return Unary(nodeType, expression, null, sourceExpression); }
internal SqlUserQuery(SqlNodeType nt, SqlExpression projection, IEnumerable<SqlExpression> args, Expression source) : base(nt, source) { this.Projection = projection; this.args = (args != null) ? new List<SqlExpression>(args) : new List<SqlExpression>(); this.columns = new List<SqlUserColumn>(); }
internal SqlUnary Unary(SqlNodeType nodeType, SqlExpression expression, MethodInfo method, Expression sourceExpression) { Type clrType = null; ProviderType sqlType = null; if (nodeType == SqlNodeType.Count) { clrType = typeof(int); sqlType = typeProvider.From(typeof(int)); } else if (nodeType == SqlNodeType.LongCount) { clrType = typeof(long); sqlType = typeProvider.From(typeof(long)); } else if (nodeType == SqlNodeType.ClrLength) { clrType = typeof(int); sqlType = typeProvider.From(typeof(int)); } else { if (nodeType.IsPredicateUnaryOperator()) { // DevDiv 201730 - Do not ignore nullability of bool type clrType = expression.ClrType.Equals(typeof(bool?)) ? typeof(bool?) : typeof(bool); } else { clrType = expression.ClrType; } sqlType = typeProvider.PredictTypeForUnary(nodeType, expression.SqlType); } return new SqlUnary(nodeType, clrType, sqlType, expression, method, sourceExpression); }
internal virtual string GetOperator(SqlNodeType nt) { switch (nt) { case SqlNodeType.Add: return "+"; case SqlNodeType.Sub: return "-"; case SqlNodeType.Mul: return "*"; case SqlNodeType.Div: return "/"; case SqlNodeType.Mod: return "%"; case SqlNodeType.Concat: return "+"; case SqlNodeType.BitAnd: return "&"; case SqlNodeType.BitOr: return "|"; case SqlNodeType.BitXor: return "^"; case SqlNodeType.And: return "AND"; case SqlNodeType.Or: return "OR"; case SqlNodeType.GE: return ">="; case SqlNodeType.GT: return ">"; case SqlNodeType.LE: return "<="; case SqlNodeType.LT: return "<"; case SqlNodeType.EQ: return "="; case SqlNodeType.EQ2V: return "="; case SqlNodeType.NE: return "<>"; case SqlNodeType.NE2V: return "<>"; case SqlNodeType.Not: return "NOT"; case SqlNodeType.Not2V: return "NOT"; case SqlNodeType.BitNot: return "~"; case SqlNodeType.Negate: return "-"; case SqlNodeType.IsNull: return "IS NULL"; case SqlNodeType.IsNotNull: return "IS NOT NULL"; case SqlNodeType.Count: return "COUNT"; case SqlNodeType.LongCount: return "COUNT_BIG"; case SqlNodeType.Min: return "MIN"; case SqlNodeType.Max: return "MAX"; case SqlNodeType.Sum: return "SUM"; case SqlNodeType.Avg: return "AVG"; case SqlNodeType.Stddev: return "STDEV"; case SqlNodeType.ClrLength: return "CLRLENGTH"; default: throw Error.InvalidFormatNode(nt); } }
internal SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right, MethodInfo method) { return Binary(nodeType, left, right, method, null); }