public void Visit(SqlUserColumn node) { if (!node.Expression.IsNullReference()) { Visit(node.Expression); } }
internal override SqlExpression VisitUserColumn(SqlUserColumn suc) { if (this.ingoreExternalRefs && !this.nodeMap.ContainsKey(suc)) { return(suc); } return(new SqlUserColumn(suc.ClrType, suc.SqlType, suc.Query, suc.Name, suc.IsRequired, suc.SourceExpression)); }
internal override SqlExpression VisitUserColumn(SqlUserColumn suc) { SqlExpression result = base.VisitUserColumn(suc); if (result == suc) { // must be external return(ExtractParameter(result)); } return(result); }
public void SqlColumnCloneTest() { { SqlUserColumn c = SqlDml.Column(1); SqlUserColumn cClone = (SqlUserColumn)c.Clone(); Assert.AreNotEqual(c, cClone); Assert.AreNotEqual(c.Expression, cClone.Expression); Assert.AreEqual(c.NodeType, cClone.NodeType); Assert.AreEqual(c.Expression.NodeType, cClone.Expression.NodeType); } Console.WriteLine(); { SqlTableRef t = SqlDml.TableRef(table1); SqlTableColumn c = (SqlTableColumn)t[0]; SqlTableColumn cClone = (SqlTableColumn)c.Clone(); Assert.AreNotEqual(c, cClone); // Assert.AreNotEqual(c.SqlTable, cClone.SqlTable); Assert.AreEqual(c.NodeType, cClone.NodeType); } }
internal override SqlUserQuery VisitUserQuery(SqlUserQuery suq) { List <SqlExpression> args = new List <SqlExpression>(suq.Arguments.Count); foreach (SqlExpression expr in suq.Arguments) { args.Add(this.VisitExpression(expr)); } SqlExpression projection = this.VisitExpression(suq.Projection); SqlUserQuery n = new SqlUserQuery(suq.QueryText, projection, args, suq.SourceExpression); this.nodeMap[suq] = n; foreach (SqlUserColumn suc in suq.Columns) { SqlUserColumn dupSuc = new SqlUserColumn(suc.ClrType, suc.SqlType, suc.Query, suc.Name, suc.IsRequired, suc.SourceExpression); this.nodeMap[suc] = dupSuc; n.Columns.Add(dupSuc); } return(n); }
internal override SqlExpression VisitUserColumn(SqlUserColumn suc) { sb.Append(suc.Name); return suc; }
internal virtual SqlExpression VisitUserColumn(SqlUserColumn suc) { return suc; }
internal override SqlExpression VisitUserColumn(SqlUserColumn suc) { SqlExpression result = base.VisitUserColumn(suc); if (result == suc) { // must be external return ExtractParameter(result); } return result; }
internal override SqlExpression VisitUserColumn(SqlUserColumn suc) { if (this.ingoreExternalRefs && !this.nodeMap.ContainsKey(suc)) { return suc; } return new SqlUserColumn(suc.ClrType, suc.SqlType, suc.Query, suc.Name, suc.IsRequired, suc.SourceExpression); }
internal override SqlUserQuery VisitUserQuery(SqlUserQuery suq) { List<SqlExpression> args = new List<SqlExpression>(suq.Arguments.Count); foreach (SqlExpression expr in suq.Arguments) { args.Add(this.VisitExpression(expr)); } SqlExpression projection = this.VisitExpression(suq.Projection); SqlUserQuery n = new SqlUserQuery(suq.QueryText, projection, args, suq.SourceExpression); this.nodeMap[suq] = n; foreach (SqlUserColumn suc in suq.Columns) { SqlUserColumn dupSuc = new SqlUserColumn(suc.ClrType, suc.SqlType, suc.Query, suc.Name, suc.IsRequired, suc.SourceExpression); this.nodeMap[suc] = dupSuc; n.Columns.Add(dupSuc); } return n; }
private SqlUserQuery VisitUserQuery(string query, Expression[] arguments, Type resultType) { SqlExpression[] args = new SqlExpression[arguments.Length]; for (int i = 0, n = args.Length; i < n; i++) { args[i] = this.VisitExpression(arguments[i]); } SqlUserQuery suq = new SqlUserQuery(query, null, args, this.dominatingExpression); if (resultType != typeof(void)) { Type elementType = TypeSystem.GetElementType(resultType); MetaType mType = this.services.Model.GetMetaType(elementType); // if the element type is a simple type (int, bool, etc.) we create // a single column binding if (TypeSystem.IsSimpleType(elementType)) { SqlUserColumn col = new SqlUserColumn(elementType, typeProvider.From(elementType), suq, "", false, this.dominatingExpression); suq.Columns.Add(col); suq.Projection = col; } else { // ... otherwise we generate a default projection SqlUserRow rowExp = new SqlUserRow(mType.InheritanceRoot, this.typeProvider.GetApplicationType((int)ConverterSpecialTypes.Row), suq, this.dominatingExpression); suq.Projection = this.translator.BuildProjection(rowExp, mType, this.allowDeferred, null, this.dominatingExpression); } } return suq; }
private SqlNode AccessMember(SqlMember m, SqlExpression expo) { SqlExpression exp = expo; switch (exp.NodeType) { case SqlNodeType.ClientCase: { // Distribute into each case. SqlClientCase sc = (SqlClientCase)exp; Type newClrType = null; List<SqlExpression> matches = new List<SqlExpression>(); List<SqlExpression> values = new List<SqlExpression>(); foreach (SqlClientWhen when in sc.Whens) { SqlExpression newValue = (SqlExpression)AccessMember(m, when.Value); if (newClrType == null) { newClrType = newValue.ClrType; } else if (newClrType != newValue.ClrType) { throw Error.ExpectedClrTypesToAgree(newClrType, newValue.ClrType); } matches.Add(when.Match); values.Add(newValue); } SqlExpression result = sql.Case(newClrType, sc.Expression, matches, values, sc.SourceExpression); return result; } case SqlNodeType.SimpleCase: { // Distribute into each case. SqlSimpleCase sc = (SqlSimpleCase)exp; Type newClrType = null; List<SqlExpression> newMatches = new List<SqlExpression>(); List<SqlExpression> newValues = new List<SqlExpression>(); foreach (SqlWhen when in sc.Whens) { SqlExpression newValue = (SqlExpression)AccessMember(m, when.Value); if (newClrType == null) { newClrType = newValue.ClrType; } else if (newClrType != newValue.ClrType) { throw Error.ExpectedClrTypesToAgree(newClrType, newValue.ClrType); } newMatches.Add(when.Match); newValues.Add(newValue); } SqlExpression result = sql.Case(newClrType, sc.Expression, newMatches, newValues, sc.SourceExpression); return result; } case SqlNodeType.SearchedCase: { // Distribute into each case. SqlSearchedCase sc = (SqlSearchedCase)exp; List<SqlWhen> whens = new List<SqlWhen>(sc.Whens.Count); foreach (SqlWhen when in sc.Whens) { SqlExpression value = (SqlExpression)AccessMember(m, when.Value); whens.Add(new SqlWhen(when.Match, value)); } SqlExpression @else = (SqlExpression)AccessMember(m, sc.Else); return sql.SearchedCase(whens.ToArray(), @else, sc.SourceExpression); } case SqlNodeType.TypeCase: { // We don't allow derived types to map members to different database fields. // Therefore, just pick the best SqlNew to call AccessMember on. SqlTypeCase tc = (SqlTypeCase)exp; // Find the best type binding for this member. SqlNew tb = tc.Whens[0].TypeBinding as SqlNew; foreach (SqlTypeCaseWhen when in tc.Whens) { if (when.TypeBinding.NodeType == SqlNodeType.New) { SqlNew sn = (SqlNew)when.TypeBinding; if (m.Member.DeclaringType.IsAssignableFrom(sn.ClrType)) { tb = sn; break; } } } return AccessMember(m, tb); } case SqlNodeType.AliasRef: { // convert alias.Member => column SqlAliasRef aref = (SqlAliasRef)exp; // if its a table, find the matching column SqlTable tab = aref.Alias.Node as SqlTable; if (tab != null) { MetaDataMember mm = GetRequiredInheritanceDataMember(tab.RowType, m.Member); System.Diagnostics.Debug.Assert(mm != null); string name = mm.MappedName; SqlColumn c = tab.Find(name); if (c == null) { ProviderType sqlType = sql.Default(mm); c = new SqlColumn(m.ClrType, sqlType, name, mm, null, m.SourceExpression); c.Alias = aref.Alias; tab.Columns.Add(c); } return new SqlColumnRef(c); } // if it is a table valued function, find the matching result column SqlTableValuedFunctionCall fc = aref.Alias.Node as SqlTableValuedFunctionCall; if (fc != null) { MetaDataMember mm = GetRequiredInheritanceDataMember(fc.RowType, m.Member); System.Diagnostics.Debug.Assert(mm != null); string name = mm.MappedName; SqlColumn c = fc.Find(name); if (c == null) { ProviderType sqlType = sql.Default(mm); c = new SqlColumn(m.ClrType, sqlType, name, mm, null, m.SourceExpression); c.Alias = aref.Alias; fc.Columns.Add(c); } return new SqlColumnRef(c); } break; } case SqlNodeType.OptionalValue: // convert option(exp).Member => exp.Member return this.AccessMember(m, ((SqlOptionalValue)exp).Value); case SqlNodeType.OuterJoinedValue: { SqlNode n = this.AccessMember(m, ((SqlUnary)exp).Operand); SqlExpression e = n as SqlExpression; if (e != null) return sql.Unary(SqlNodeType.OuterJoinedValue, e); return n; } case SqlNodeType.Lift: return this.AccessMember(m, ((SqlLift)exp).Expression); case SqlNodeType.UserRow: { // convert UserRow.Member => UserColumn SqlUserRow row = (SqlUserRow)exp; SqlUserQuery suq = row.Query; MetaDataMember mm = GetRequiredInheritanceDataMember(row.RowType, m.Member); System.Diagnostics.Debug.Assert(mm != null); string name = mm.MappedName; SqlUserColumn c = suq.Find(name); if (c == null) { ProviderType sqlType = sql.Default(mm); c = new SqlUserColumn(m.ClrType, sqlType, suq, name, mm.IsPrimaryKey, m.SourceExpression); suq.Columns.Add(c); } return c; } case SqlNodeType.New: { // convert (new {Member = expr}).Member => expr SqlNew sn = (SqlNew)exp; SqlExpression e = sn.Find(m.Member); if (e != null) { return e; } MetaDataMember mm = sn.MetaType.PersistentDataMembers.FirstOrDefault(p => p.Member == m.Member); if (!sn.SqlType.CanBeColumn && mm != null) { throw Error.MemberNotPartOfProjection(m.Member.DeclaringType, m.Member.Name); } break; } case SqlNodeType.Element: case SqlNodeType.ScalarSubSelect: { // convert Scalar/Element(select exp).Member => Scalar/Element(select exp.Member) / select exp.Member SqlSubSelect sub = (SqlSubSelect)exp; SqlAlias alias = new SqlAlias(sub.Select); SqlAliasRef aref = new SqlAliasRef(alias); SqlSelect saveSelect = this.currentSelect; try { SqlSelect newSelect = new SqlSelect(aref, alias, sub.SourceExpression); this.currentSelect = newSelect; SqlNode result = this.Visit(sql.Member(aref, m.Member)); SqlExpression rexp = result as SqlExpression; if (rexp != null) { // If the expression is still a Member after being visited, but it cannot be a column, then it cannot be collapsed // into the SubSelect because we need to keep track of the fact that this member has to be accessed on the client. // This must be done after the expression has been Visited above, because otherwise we don't have // enough context to know if the member can be a column or not. if (rexp.NodeType == SqlNodeType.Member && !SqlColumnizer.CanBeColumn(rexp)) { // If the original member expression is an Element, optimize it by converting to an OuterApply if possible. // We have to do this here because we are creating a new member expression based on it, and there are no // subsequent visitors that will do this optimization. if (this.canUseOuterApply && exp.NodeType == SqlNodeType.Element && this.currentSelect != null) { // Reset the currentSelect since we are not going to use the previous SqlSelect that was created this.currentSelect = saveSelect; this.currentSelect.From = sql.MakeJoin(SqlJoinType.OuterApply, this.currentSelect.From, alias, null, sub.SourceExpression); exp = this.VisitExpression(aref); } return sql.Member(exp, m.Member); } // Since we are going to make a SubSelect out of this member expression, we need to make // sure it gets columnized before it gets to the PostBindDotNetConverter, otherwise only the // entire SubSelect will be columnized as a whole. Subsequent columnization does not know how to handle // any function calls that may be produced by the PostBindDotNetConverter, but we know how to handle it here. newSelect.Selection = rexp; newSelect.Selection = this.columnizer.ColumnizeSelection(newSelect.Selection); newSelect.Selection = this.ConvertLinks(newSelect.Selection); SqlNodeType subType = (rexp is SqlTypeCase || !rexp.SqlType.CanBeColumn) ? SqlNodeType.Element : SqlNodeType.ScalarSubSelect; SqlSubSelect subSel = sql.SubSelect(subType, newSelect); return this.FoldSubquery(subSel); } SqlSelect rselect = result as SqlSelect; if (rselect != null) { SqlAlias ralias = new SqlAlias(rselect); SqlAliasRef rref = new SqlAliasRef(ralias); newSelect.Selection = this.ConvertLinks(this.VisitExpression(rref)); newSelect.From = new SqlJoin(SqlJoinType.CrossApply, alias, ralias, null, m.SourceExpression); return newSelect; } throw Error.UnexpectedNode(result.NodeType); } finally { this.currentSelect = saveSelect; } } case SqlNodeType.Value: { SqlValue val = (SqlValue)exp; if (val.Value == null) { return sql.Value(m.ClrType, m.SqlType, null, val.IsClientSpecified, m.SourceExpression); } else if (m.Member is PropertyInfo) { PropertyInfo p = (PropertyInfo)m.Member; return sql.Value(m.ClrType, m.SqlType, p.GetValue(val.Value, null), val.IsClientSpecified, m.SourceExpression); } else { FieldInfo f = (FieldInfo)m.Member; return sql.Value(m.ClrType, m.SqlType, f.GetValue(val.Value), val.IsClientSpecified, m.SourceExpression); } } case SqlNodeType.Grouping: { SqlGrouping g = ((SqlGrouping)exp); if (m.Member.Name == "Key") { return g.Key; } break; } case SqlNodeType.ClientParameter: { SqlClientParameter cp = (SqlClientParameter)exp; // create new accessor including this member access LambdaExpression accessor = Expression.Lambda( typeof(Func<,>).MakeGenericType(typeof(object[]), m.ClrType), Expression.MakeMemberAccess(cp.Accessor.Body, m.Member), cp.Accessor.Parameters ); return new SqlClientParameter(m.ClrType, m.SqlType, accessor, cp.SourceExpression); } default: break; } if (m.Expression == exp) { return m; } else { return sql.Member(exp, m.Member); } }
public virtual void Visit(SqlUserColumn node) { VisitInternal(node.Expression); VisitInternal(node.SqlTable); }