internal override SqlSelect VisitSelect(SqlSelect select) { /* * We're travelling through <expression> of something like: * * SELECT <expression> * FROM <alias> * * Inside the expression there may be a reference to <alias> that * represents the dynamic type that we're trying to discover. * * In this case, the type relationship between AliasRef and Alias is * T to IEnumerable<T>. * * We need to remember to 'unpivot' the type of IEnumerable<T> to * get the correct dynamic type. * * Since SELECTs may be nested, we use a stack of pivots. * */ this.UnwrapSequences = new UnwrapStack(this.UnwrapSequences, true); VisitExpression(select.Selection); this.UnwrapSequences = this.UnwrapSequences.Last; return(select); }
internal override SqlSelect VisitSelect(SqlSelect select) { UnwrapSequences = new UnwrapStack(UnwrapSequences, true); VisitExpression(select.Selection); UnwrapSequences = UnwrapSequences.Last; return(select); }
internal override SqlExpression VisitAliasRef(SqlAliasRef aref) { if ((UnwrapSequences != null) && UnwrapSequences.Unwrap) { UnwrapSequences = new UnwrapStack(UnwrapSequences, false); VisitAlias(aref.Alias); UnwrapSequences = UnwrapSequences.Last; return(aref); } VisitAlias(aref.Alias); return(aref); }
internal override SqlExpression VisitAliasRef(SqlAliasRef aref) { if (this.UnwrapSequences != null && this.UnwrapSequences.Unwrap) { this.UnwrapSequences = new UnwrapStack(this.UnwrapSequences, false); this.VisitAlias(aref.Alias); this.UnwrapSequences = this.UnwrapSequences.Last; } else { this.VisitAlias(aref.Alias); } return(aref); }
internal override SqlSelect VisitSelect(SqlSelect select) { /* * We're travelling through <expression> of something like: * * SELECT <expression> * FROM <alias> * * Inside the expression there may be a reference to <alias> that * represents the dynamic type that we're trying to discover. * * In this case, the type relationship between AliasRef and Alias is * T to IEnumerable<T>. * * We need to remember to 'unpivot' the type of IEnumerable<T> to * get the correct dynamic type. * * Since SELECTs may be nested, we use a stack of pivots. * */ this.UnwrapSequences = new UnwrapStack(this.UnwrapSequences, true); VisitExpression(select.Selection); this.UnwrapSequences = this.UnwrapSequences.Last; return select; }
public UnwrapStack(UnwrapStack last, bool unwrap) { Last = last; Unwrap = unwrap; }
internal override SqlExpression VisitAliasRef(SqlAliasRef aref) { if (this.UnwrapSequences != null && this.UnwrapSequences.Unwrap) { this.UnwrapSequences = new UnwrapStack(this.UnwrapSequences, false); this.VisitAlias(aref.Alias); this.UnwrapSequences = this.UnwrapSequences.Last; } else { this.VisitAlias(aref.Alias); } return aref; }
internal override SqlNode Visit(SqlNode node) { if (node == null) { return(null); } sourceExpression = node as SqlExpression; if (sourceExpression != null) { Type type = sourceExpression.ClrType; UnwrapStack unwrap = this.UnwrapSequences; while (unwrap != null) { if (unwrap.Unwrap) { type = TypeSystem.GetElementType(type); } unwrap = unwrap.Last; } sourceType = type; } if (sourceType != null && TypeSystem.GetNonNullableType(sourceType).IsValueType) { return(node); // Value types can't also have a dynamic type. } if (sourceType != null && TypeSystem.HasIEnumerable(sourceType)) { return(node); // Sequences can't be polymorphic. } switch (node.NodeType) { case SqlNodeType.ScalarSubSelect: case SqlNodeType.Multiset: case SqlNodeType.Element: case SqlNodeType.SearchedCase: case SqlNodeType.ClientCase: case SqlNodeType.SimpleCase: case SqlNodeType.Member: case SqlNodeType.DiscriminatedType: case SqlNodeType.New: case SqlNodeType.FunctionCall: case SqlNodeType.MethodCall: case SqlNodeType.Convert: // Object identity does not survive convert. It does survive Cast. // Dig no further. return(node); case SqlNodeType.TypeCase: sourceType = ((SqlTypeCase)node).RowType.Type; return(node); case SqlNodeType.Link: sourceType = ((SqlLink)node).RowType.Type; return(node); case SqlNodeType.Table: sourceType = ((SqlTable)node).RowType.Type; return(node); case SqlNodeType.Value: SqlValue val = (SqlValue)node; if (val.Value != null) { // In some cases the ClrType of a Value node may // differ from the actual runtime type of the value. // Therefore, we ensure here that the correct type is set. sourceType = val.Value.GetType(); } return(node); } return(base.Visit(node)); }
// Methods internal override SqlNode Visit(SqlNode node) { if (node == null) { return(null); } sourceExpression = node as SqlExpression; if (sourceExpression != null) { Type clrType = sourceExpression.ClrType; for (UnwrapStack stack = UnwrapSequences; stack != null; stack = stack.Last) { if (stack.Unwrap) { clrType = TypeSystem.GetElementType(clrType); } } sourceType = clrType; } if ((sourceType != null) && TypeSystem.GetNonNullableType(sourceType).IsValueType) { return(node); } if ((sourceType != null) && TypeSystem.HasIEnumerable(sourceType)) { return(node); } switch (node.NodeType) { case SqlNodeType.ClientCase: case SqlNodeType.Convert: case SqlNodeType.DiscriminatedType: return(node); case SqlNodeType.MethodCall: case SqlNodeType.Member: return(node); case SqlNodeType.Link: sourceType = ((SqlLink)node).RowType.Type; return(node); case SqlNodeType.Element: case SqlNodeType.FunctionCall: return(node); case SqlNodeType.ScalarSubSelect: case SqlNodeType.SearchedCase: return(node); case SqlNodeType.New: return(node); case SqlNodeType.Multiset: return(node); case SqlNodeType.TypeCase: sourceType = ((SqlTypeCase)node).RowType.Type; return(node); case SqlNodeType.Value: { SqlValue value2 = (SqlValue)node; if (value2.Value != null) { sourceType = value2.Value.GetType(); } return(node); } case SqlNodeType.SimpleCase: return(node); case SqlNodeType.Table: sourceType = ((SqlTable)node).RowType.Type; return(node); } return(base.Visit(node)); }