internal override SqlSelect VisitSelect(SqlSelect select) { bool saveForceReferenceAll = _forceReferenceAll; _forceReferenceAll = false; bool saveIsTopLevel = _isTopLevel; try { if(_isTopLevel) { // top-level projection references columns! @select.Selection = this.VisitExpression(@select.Selection); } _isTopLevel = false; for(int i = @select.Row.Columns.Count - 1; i >= 0; i--) { SqlColumn c = @select.Row.Columns[i]; bool safeToRemove = !saveForceReferenceAll && !_referenceMap.ContainsKey(c) // don't remove anything from a distinct select (except maybe a literal value) since it would change the meaning of the comparison && [email protected] // don't remove an aggregate expression that may be the only expression that forces the grouping (since it would change the cardinality of the results) && !(@select.GroupBy.Count == 0 && _aggregateChecker.HasAggregates(c.Expression)); if(safeToRemove) { @select.Row.Columns.RemoveAt(i); } else { this.VisitExpression(c.Expression); } } @select.Top = this.VisitExpression(@select.Top); for(int i = @select.OrderBy.Count - 1; i >= 0; i--) { @select.OrderBy[i].Expression = this.VisitExpression(@select.OrderBy[i].Expression); } @select.Having = this.VisitExpression(@select.Having); for(int i = @select.GroupBy.Count - 1; i >= 0; i--) { @select.GroupBy[i] = this.VisitExpression(@select.GroupBy[i]); } @select.Where = this.VisitExpression(@select.Where); @select.From = this.VisitSource(@select.From); } finally { _isTopLevel = saveIsTopLevel; _forceReferenceAll = saveForceReferenceAll; } return @select; }
internal override SqlExpression VisitMultiset(SqlSubSelect sms) { // allow one big-join per query? if((this.options & SqlMultiplexerOptionType.EnableBigJoin) != 0 && !this.hasBigJoin && this.canJoin && this.isTopLevel && this.outerSelect != null && !MultisetChecker.HasMultiset(sms.Select.Selection) && BigJoinChecker.CanBigJoin(sms.Select)) { sms.Select = this.VisitSelect(sms.Select); SqlAlias alias = new SqlAlias(sms.Select); SqlJoin join = new SqlJoin(SqlJoinType.OuterApply, this.outerSelect.From, alias, null, sms.SourceExpression); this.outerSelect.From = @join; this.outerSelect.OrderingType = SqlOrderingType.Always; // make joined expression SqlExpression expr = (SqlExpression)SqlDuplicator.Copy(sms.Select.Selection); // make count expression SqlSelect copySelect = (SqlSelect)SqlDuplicator.Copy(sms.Select); SqlAlias copyAlias = new SqlAlias(copySelect); SqlSelect countSelect = new SqlSelect(sql.Unary(SqlNodeType.Count, null, sms.SourceExpression), copyAlias, sms.SourceExpression); countSelect.OrderingType = SqlOrderingType.Never; SqlExpression count = sql.SubSelect(SqlNodeType.ScalarSubSelect, countSelect); // make joined collection SqlJoinedCollection jc = new SqlJoinedCollection(sms.ClrType, sms.SqlType, expr, count, sms.SourceExpression); this.hasBigJoin = true; return jc; } return QueryExtractor.Extract(sms, this.parentParameters); }
private static ProviderType GetSqlType(SqlNode node) { SqlExpression exp = node as SqlExpression; if (exp != null) { return(exp.SqlType); } SqlSelect sel = node as SqlSelect; if (sel != null) { return(sel.Selection.SqlType); } SqlTable tab = node as SqlTable; if (tab != null) { return(tab.SqlRowType); } SqlUnion su = node as SqlUnion; if (su != null) { return(su.GetSqlType()); } throw Error.UnexpectedNode(node.NodeType); }
internal override SqlSelect VisitSelect(SqlSelect select) { Scope save = this.current; this.current = new Scope(select.Where, this.current); SqlSelect result = base.VisitSelect(select); bool stopHoisting = select.IsDistinct || select.GroupBy.Count > 0 || this.aggregateChecker.HasAggregates(select) || select.Top != null || this.rowNumberChecker.HasRowNumber(select); // Shift as much of the current WHERE to the parent as possible. if(this.current != null) { if(this.current.Parent != null && !stopHoisting) { this.current.Parent.Where = sql.AndAccumulate(this.current.Parent.Where, this.current.Where); this.current.Where = null; } select.Where = this.current.Where; } this.current = save; return result; }
internal override SqlSelect VisitSelect(SqlSelect select) { this.Visit(select.Row); this.Visit(select.Where); return select; }
internal override SqlSelect VisitSelect(SqlSelect select) { select.From = (SqlSource)this.Visit(select.From); SqlScope save = this.CurrentScope; this.CurrentScope = new SqlScope(select.From, this.CurrentScope.ContainingScope); select.Where = this.VisitExpression(select.Where); for(int i = 0, n = select.GroupBy.Count; i < n; i++) { select.GroupBy[i] = this.VisitExpression(select.GroupBy[i]); } select.Having = this.VisitExpression(select.Having); for(int i = 0, n = select.OrderBy.Count; i < n; i++) { select.OrderBy[i].Expression = this.VisitExpression(select.OrderBy[i].Expression); } select.Top = this.VisitExpression(select.Top); select.Row = (SqlRow)this.Visit(select.Row); // selection must be able to see its own projection this.CurrentScope = new SqlScope(select, this.CurrentScope.ContainingScope); select.Selection = this.VisitExpression(select.Selection); this.CurrentScope = save; return select; }
internal override SqlSelect VisitSelect(SqlSelect select) { if(_isTopLevel) { @select.Selection = _sDeflator.VisitExpression(@select.Selection); } return @select; }
internal override SqlSelect VisitSelect(SqlSelect select) { foreach(SqlColumn c in @select.Row.Columns) { this.columns.Add(c); } return @select; }
internal override SqlSelect VisitSelect(SqlSelect select) { bool saveTop = this.topLevel; this.topLevel = false; @select = this.VisitSelectCore(@select); this.topLevel = saveTop; @select.Selection = this.VisitExpression(@select.Selection); return @select; }
internal override SqlSelect VisitSelect(SqlSelect select) { base.VisitSelect(@select); if(@select.Where != null) { this.CheckJoinCondition(@select.Where); } return @select; }
internal override SqlSelect VisitSelect(SqlSelect select) { if(select.IsDistinct) { _isDistinct = true; // get all members from selection this.AddIdentityMembers(select.Selection.ClrType.GetProperties()); return select; } // We're not distinct, but let's check our sources... select.From = (SqlSource)base.Visit(select.From); if(_identityMembers == null || _identityMembers.Count == 0) { throw Error.SkipRequiresSingleTableQueryWithPKs(); } switch(select.Selection.NodeType) { case SqlNodeType.Column: case SqlNodeType.ColumnRef: case SqlNodeType.Member: { // we've got a bare member/column node, eg "select c.CustomerId" // find out if it refers to the table's PK, of which there must be only 1 if(_identityMembers.Count == 1) { MemberInfo column = _identityMembers[0]; _isValid &= IsColumnMatch(column, @select.Selection); } else { _isValid = false; } break; } case SqlNodeType.New: case SqlNodeType.AliasRef: { select.Selection = this.VisitExpression(@select.Selection); break; } case SqlNodeType.Treat: case SqlNodeType.TypeCase: { break; } default: { _isValid = false; break; } } return select; }
internal override SqlSelect VisitSelect(SqlSelect select) { // big-joins may need to lift PK's out for default ordering, so don't allow big-join if we see these this.canBigJoin &= select.GroupBy.Count == 0 && select.Top == null && !select.IsDistinct; if(!this.canBigJoin) { return select; } return base.VisitSelect(select); }
private bool IsTrivialSelect(SqlSelect select) { if(@select.OrderBy.Count != 0 || @select.GroupBy.Count != 0 || @select.Having != null || @select.Top != null || @select.IsDistinct || @select.Where != null) return false; return this.HasTrivialSource(@select.From) && this.HasTrivialProjection(@select); }
internal override SqlSelect VisitSelect(SqlSelect select) { SelectScope s = expressionSink; #warning [FB] REFACTOR SQL Server specific (TOP). Change it to reflect limiting but not through the usage of 'Top'. // Don't lift through a TOP. if(select.Top != null) { expressionSink = null; } // Don't lift through a GROUP BY (or implicit GROUP BY). if(select.GroupBy.Count > 0 || this.aggregateChecker.HasAggregates(select)) { expressionSink = null; } // Don't lift through DISTINCT if(select.IsDistinct) { expressionSink = null; } if(expressionSink != null) { List<SqlColumn> keep = new List<SqlColumn>(); List<SqlColumn> lift = new List<SqlColumn>(); foreach(SqlColumn sc in select.Row.Columns) { bool referencesLeftsideAliases = SqlAliasesReferenced.ReferencesAny(sc.Expression, expressionSink.LeftProduction); bool isLockedExpression = expressionSink.ReferencedExpressions.Contains(sc); if(referencesLeftsideAliases && !isLockedExpression) { lift.Add(sc); } else { keep.Add(sc); } } select.Row.Columns.Clear(); select.Row.Columns.AddRange(keep); if(lift.Count > 0) { expressionSink.Lifted.Push(lift); } } SqlSelect sel = base.VisitSelect(select); expressionSink = s; return sel; }
private void ConvertColumnsToMax(SqlSelect select, out bool changed, out bool containsLongExpressions) { SqlRow row = select.Row; changed = false; containsLongExpressions = false; foreach(SqlColumn col in row.Columns) { bool columnChanged; containsLongExpressions = containsLongExpressions || col.SqlType.IsLargeType; col.Expression = ConvertToMax(col.Expression, out columnChanged); changed = changed || columnChanged; } }
internal override SqlSelect VisitSelect(SqlSelect select) { SqlSelect save = this.currentSelect; try { this.currentSelect = @select; return base.VisitSelect(@select); } finally { this.currentSelect = save; } }
internal override SqlSelect VisitSelectCore(SqlSelect select) { bool saveIsTopLevel = this.isTopLevel; this.isTopLevel = false; try { return base.VisitSelectCore(@select); } finally { this.isTopLevel = saveIsTopLevel; } }
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; }
internal override SqlSelect VisitSelect(SqlSelect select) { if(select.IsDistinct) { bool changed; bool containsLongExpressions; ConvertColumnsToMax(select, out changed, out containsLongExpressions); if(containsLongExpressions) { this.annotations.Add(select, new CompatibilityAnnotation( Strings.TextNTextAndImageCannotOccurInDistinct(select.SourceExpression), SqlServerProviderMode.Sql2000, SqlServerProviderMode.SqlCE)); } } return base.VisitSelect(select); }
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; }
internal ProviderType GetSqlType() { SqlExpression exp = this.Left as SqlExpression; if (exp != null) { return(exp.SqlType); } SqlSelect sel = this.Left as SqlSelect; if (sel != null) { return(sel.Selection.SqlType); } throw Error.CouldNotGetSqlType(); }
internal override SqlSelect VisitSelect(SqlSelect select) { select.From = this.VisitSource(select.From); select.Where = this.VisitExpression(select.Where); for(int i = 0, n = select.GroupBy.Count; i < n; i++) { select.GroupBy[i] = this.VisitExpression(select.GroupBy[i]); } // remove duplicate group expressions for(int i = select.GroupBy.Count - 1; i >= 0; i--) { for(int j = i - 1; j >= 0; j--) { if(SqlComparer.AreEqual(select.GroupBy[i], select.GroupBy[j])) { select.GroupBy.RemoveAt(i); break; } } } select.Having = this.VisitExpression(select.Having); for(int i = 0, n = select.OrderBy.Count; i < n; i++) { select.OrderBy[i].Expression = this.VisitExpression(select.OrderBy[i].Expression); } // remove duplicate order expressions if(select.OrderBy.Count > 0) { this.equalizer.BuildEqivalenceMap(select.From); for(int i = select.OrderBy.Count - 1; i >= 0; i--) { for(int j = i - 1; j >= 0; j--) { if(this.equalizer.AreEquivalent(select.OrderBy[i].Expression, select.OrderBy[j].Expression)) { select.OrderBy.RemoveAt(i); break; } } } } select.Top = this.VisitExpression(select.Top); select.Row = (SqlRow)this.Visit(select.Row); select.Selection = this.VisitExpression(select.Selection); return select; }
internal override SqlSelect VisitSelect(SqlSelect select) { base.VisitSelect(@select); // enforce exact ordering of columns in union selects SqlUnion union = this.GetUnion(@select.From); if(union != null) { SqlSelect sleft = union.Left as SqlSelect; SqlSelect sright = union.Right as SqlSelect; if(sleft != null & sright != null) { // preset ordinals to high values (so any unreachable column definition is ordered last) for(int i = 0, n = sleft.Row.Columns.Count; i < n; i++) { sleft.Row.Columns[i].Ordinal = @select.Row.Columns.Count + i; } for(int i = 0, n = sright.Row.Columns.Count; i < n; i++) { sright.Row.Columns[i].Ordinal = @select.Row.Columns.Count + i; } // next assign ordinals to all direct columns in subselects for(int i = 0, n = @select.Row.Columns.Count; i < n; i++) { SqlExprSet es = @select.Row.Columns[i].Expression as SqlExprSet; if(es != null) { for(int e = 0, en = es.Expressions.Count; e < en; e++) { SqlColumnRef cr = es.Expressions[e] as SqlColumnRef; if(cr != null && e >= @select.Row.Columns.Count) { cr.Column.Ordinal = i; } } } } // next sort columns in left & right subselects Comparison<SqlColumn> comp = (x, y) => x.Ordinal - y.Ordinal; sleft.Row.Columns.Sort(comp); sright.Row.Columns.Sort(comp); } } return @select; }
internal override SqlSelect VisitSelect(SqlSelect select) { // DevDiv 179191 if(@select.Where != null && @select.Where.NodeType == SqlNodeType.Coalesce) { SqlBinary bin = (SqlBinary)@select.Where; if(bin.Right.NodeType == SqlNodeType.Value) { SqlValue value = (SqlValue)bin.Right; if(value.Value != null && value.Value.GetType() == typeof(bool) && (bool)value.Value == false) { @select.Where = bin.Left; } } } return base.VisitSelect(@select); }
internal override SqlSelect VisitSelect(SqlSelect select) { select.From = this.VisitSource(select.From); select.Where = this.VisitPredicate(select.Where); for(int i = 0, n = select.GroupBy.Count; i < n; i++) { select.GroupBy[i] = this.VisitExpression(select.GroupBy[i]); } select.Having = this.VisitPredicate(select.Having); for(int i = 0, n = select.OrderBy.Count; i < n; i++) { select.OrderBy[i].Expression = this.VisitExpression(select.OrderBy[i].Expression); } select.Top = this.VisitExpression(select.Top); select.Row = (SqlRow)this.Visit(select.Row); // don't visit selection //select.Selection = this.VisitExpression(select.Selection); return select; }
internal override SqlSelect VisitSelect(SqlSelect select) { @select = base.VisitSelect(@select); string[] names = new string[@select.Row.Columns.Count]; for(int i = 0, n = names.Length; i < n; i++) { SqlColumn c = @select.Row.Columns[i]; string name = c.Name; if(name == null) { name = SqlNamer.DiscoverName(c); } names[i] = name; c.Name = null; } var reservedNames = this.GetColumnNames(@select.OrderBy); for(int i = 0, n = @select.Row.Columns.Count; i < n; i++) { SqlColumn c = @select.Row.Columns[i]; string rootName = names[i]; string name = rootName; if(this.makeUnique) { int iName = 1; while(!this.IsUniqueName(@select.Row.Columns, reservedNames, c, name)) { iName++; name = rootName + iName; } } c.Name = name; c.Ordinal = i; } return @select; }
internal override SqlSelect VisitSelect(SqlSelect select) { if(IsTrivialSelect(@select)) { SqlSelect aselect = (SqlSelect)((SqlAlias)@select.From).Node; // build up a column map, so we can rewrite the top-level selection expression Dictionary<SqlColumn, SqlColumnRef> map = new Dictionary<SqlColumn, SqlColumnRef>(); foreach(SqlColumn c in @select.Row.Columns) { SqlColumnRef cref = (SqlColumnRef)c.Expression; map.Add(c, cref); // push the interesting column names down (non null) if(!String.IsNullOrEmpty(c.Name)) { cref.Column.Name = c.Name; } } aselect.Selection = new ColumnMapper(map).VisitExpression(@select.Selection); return aselect; } return @select; }
internal override SqlSelect VisitSelect(SqlSelect select) { base.VisitSelect(select); if(select.Top != null) { if(select.Top.NodeType == SqlNodeType.Value) { SqlValue val = (SqlValue)select.Top; // convert to literal value for SQL2K compatibility if(val.IsClientSpecified) { select.Top = sql.Value(val.ClrType, val.SqlType, val.Value, false, val.SourceExpression); } } else { // cannot be converted to literal value. note that this select is not SQL2K compatible this.annotations.Add(select.Top, new CompatibilityAnnotation(Strings.SourceExpressionAnnotation(select.Top.SourceExpression), SqlServerProviderMode.Sql2000)); } } return select; }
private static Type GetClrType(SqlNode node) { SqlTableValuedFunctionCall tvf = node as SqlTableValuedFunctionCall; if (tvf != null) { return(tvf.RowType.Type); } SqlExpression exp = node as SqlExpression; if (exp != null) { if (TypeSystem.IsSequenceType(exp.ClrType)) { return(TypeSystem.GetElementType(exp.ClrType)); } return(exp.ClrType); } SqlSelect sel = node as SqlSelect; if (sel != null) { return(sel.Selection.ClrType); } SqlTable tab = node as SqlTable; if (tab != null) { return(tab.RowType.Type); } SqlUnion su = node as SqlUnion; if (su != null) { return(su.GetClrType()); } throw Error.UnexpectedNode(node.NodeType); }
internal override SqlSelect VisitSelect(SqlSelect select) { @select = base.VisitSelect(@select); @select.Selection = this.FlattenSelection(@select.Row, false, @select.Selection); if(@select.GroupBy.Count > 0) { this.FlattenGroupBy(@select.GroupBy); } if(@select.OrderBy.Count > 0) { this.FlattenOrderBy(@select.OrderBy); } if(!this.isTopLevel) { @select.Selection = new SqlNop(@select.Selection.ClrType, @select.Selection.SqlType, @select.SourceExpression); } return @select; }
internal override SqlSelect VisitSelect(SqlSelect select) { // check subqueries first this.VisitSource(@select.From); // don't allow lifting through these operations if(@select.Top != null || @select.GroupBy.Count > 0 || this.aggregateChecker.HasAggregates(@select) || @select.IsDistinct) { this.CanLiftAll = false; } // only lift predicates that actually reference the aliases if(this.CanLiftAll && @select.Where != null) { bool referencesAliases = this.aliases.ReferencesAny(@select.Where); if(referencesAliases) { if(this.liftedExpressions != null) { this.liftedExpressions.Add(@select.Where); } if(this.doLifting) { if(this.Lifted != null) this.Lifted = new SqlBinary(SqlNodeType.And, this.Lifted.ClrType, this.Lifted.SqlType, this.Lifted, @select.Where); else this.Lifted = @select.Where; @select.Where = null; } } } return @select; }
internal override SqlSelect VisitSelect(SqlSelect select) { int i = 0; List<SqlOrderExpression> orders = @select.OrderBy; while(i < orders.Count) { SqlExpression expr = orders[i].Expression; while(expr.NodeType == SqlNodeType.DiscriminatedType) { expr = ((SqlDiscriminatedType)expr).Discriminator; } switch(expr.NodeType) { case SqlNodeType.Value: case SqlNodeType.Parameter: orders.RemoveAt(i); break; default: ++i; break; } } return base.VisitSelect(@select); }
// check everything except selection expressions (which will be client or ignored) internal override SqlSelect VisitSelect(SqlSelect select) { return this.VisitSelectCore(select); }
internal SqlUpdate(SqlSelect select, IEnumerable <SqlAssign> assignments, Expression sourceExpression) : base(SqlNodeType.Update, sourceExpression) { this.Select = select; this.assignments = new List <SqlAssign>(assignments); }
private SqlSource PushSourceDown(SqlSource sqlSource, List<SqlColumn> cols) { SqlSelect ns = new SqlSelect(new SqlNop(cols[0].ClrType, cols[0].SqlType, sqlSource.SourceExpression), sqlSource, sqlSource.SourceExpression); ns.Row.Columns.AddRange(cols); return new SqlAlias(ns); }
internal SqlDelete(SqlSelect select, Expression sourceExpression) : base(SqlNodeType.Delete, sourceExpression) { this.Select = select; }