internal static bool IsNameMapProjection(DbSelectExpression select) { if (select.From is DbTableExpression) { return(false); } DbSelectExpression fromSelect = select.From as DbSelectExpression; if (fromSelect == null || select.Columns.Count != fromSelect.Columns.Count) { return(false); } ReadOnlyCollection <DbColumnDeclaration> fromColumns = fromSelect.Columns; // test that all columns in 'select' are refering to columns in the same position // in from. for (int i = 0, n = select.Columns.Count; i < n; i++) { DbColumnExpression col = select.Columns[i].Expression as DbColumnExpression; if (col == null || !(col.Name == fromColumns[i].Name)) { return(false); } } return(true); }
protected virtual DbColumnAssignment VisitColumnAssignment(DbColumnAssignment ca) { DbColumnExpression c = (DbColumnExpression)Visit(ca.Column); Expression e = Visit(ca.Expression); return(UpdateColumnAssignment(ca, c, e)); }
/// <summary> /// Add a sequence of order expressions to an accumulated list, prepending so as /// to give precedence to the new expressions over any previous expressions /// </summary> /// <param name="newOrderings"></param> protected void PrependOrderings(IList <DbOrderExpression> newOrderings) { if (newOrderings != null) { if (this.gatheredOrderings == null) { this.gatheredOrderings = new List <DbOrderExpression>(); } for (int i = newOrderings.Count - 1; i >= 0; i--) { this.gatheredOrderings.Insert(0, newOrderings[i]); } // trim off obvious duplicates HashSet <string> unique = new HashSet <string>(); for (int i = 0; i < this.gatheredOrderings.Count;) { DbColumnExpression column = this.gatheredOrderings[i].Expression as DbColumnExpression; if (column != null) { string hash = column.Alias + ":" + column.Name; if (unique.Contains(hash)) { this.gatheredOrderings.RemoveAt(i); // don't increment 'i', just continue continue; } else { unique.Add(hash); } } i++; } } }
protected override Expression VisitColumn(DbColumnExpression column) { if (this.oldAliases.Contains(column.Alias)) { return(new DbColumnExpression(column.Type, column.DbType, this.newAlias, column.Name)); } return(column); }
protected override Expression VisitColumn(DbColumnExpression column) { if (!this.columns.ContainsKey(column.Name)) { this.columns.Add(column.Name, column); } return(column); }
protected override Expression VisitColumn(DbColumnExpression column) { DbTableAlias newAlias; if (this.map.TryGetValue(column.Alias, out newAlias)) { return(new DbColumnExpression(column.Type, column.DbType, newAlias, column.Name)); } return(column); }
protected override Expression VisitColumn(DbColumnExpression column) { DbColumnExpression mapped; if (this.map.TryGetValue(column, out mapped)) { return(mapped); } return(column); }
protected DbColumnAssignment UpdateColumnAssignment( DbColumnAssignment ca, DbColumnExpression c, Expression e) { if (c != ca.Column || e != ca.Expression) { return(new DbColumnAssignment(c, e)); } return(ca); }
bool SameExpression(Expression a, Expression b) { if (a == b) { return(true); } DbColumnExpression ca = a as DbColumnExpression; DbColumnExpression cb = b as DbColumnExpression; return(ca != null && cb != null && ca.Alias == cb.Alias && ca.Name == cb.Name); }
internal static bool IsSimpleProjection(DbSelectExpression select) { foreach (DbColumnDeclaration decl in select.Columns) { DbColumnExpression col = decl.Expression as DbColumnExpression; if (col == null || decl.Name != col.Name) { return(false); } } return(true); }
protected override Expression VisitColumn(DbColumnExpression column) { if (column.Alias == this.outerAlias) { DbNamedValueExpression nv; if (!this.map.TryGetValue(column, out nv)) { nv = new DbNamedValueExpression("n" + (iParam++), column.DbType, column); this.map.Add(column, nv); } return(nv); } return(column); }
internal bool TryGetValue(DbColumnExpression column, out ParameterExpression dbDataReader, out int ordinal) { for (Scope s = this; s != null; s = s.outer) { if (column.Alias == s.Alias && this.nameMap.TryGetValue(column.Name, out ordinal)) { dbDataReader = this.dbDataReader; return(true); } } dbDataReader = null; ordinal = 0; return(false); }
protected override Expression VisitColumn(DbColumnExpression column) { ParameterExpression reader; int iOrdinal; if (this.scope != null && this.scope.TryGetValue(column, out reader, out iOrdinal)) { return(Expression.Call(this.GetType(), "GetValue", new Type[] { column.Type }, this.provider, reader, Expression.Constant(iOrdinal))); } else { System.Diagnostics.Debug.Fail(string.Format("column not in scope: {0}", column)); } return(column); }
protected override Expression VisitColumn(DbColumnExpression column) { Dictionary <string, Expression> nameMap; if (this.map.TryGetValue(column.Alias, out nameMap)) { Expression expr; if (nameMap.TryGetValue(column.Name, out expr)) { return(this.Visit(expr)); } throw new Exception("Reference to undefined column"); } return(column); }
protected override Expression Visit(Expression expression) { if (this.candidates.Contains(expression)) { if (expression.NodeType == (ExpressionType)DbExpressionType.Column) { DbColumnExpression column = (DbColumnExpression)expression; DbColumnExpression mapped; if (this.map.TryGetValue(column, out mapped)) { return(mapped); } // check for column that already refers to this column foreach (DbColumnDeclaration existingColumn in this.columns) { DbColumnExpression cex = existingColumn.Expression as DbColumnExpression; if (cex != null && cex.Alias == column.Alias && cex.Name == column.Name) { // refer to the column already in the column list return(new DbColumnExpression(column.Type, column.DbType, this.newAlias, existingColumn.Name)); } } if (this.existingAliases.Contains(column.Alias)) { int ordinal = this.columns.Count; string columnName = this.GetUniqueColumnName(column.Name); this.columns.Add(new DbColumnDeclaration(columnName, column)); mapped = new DbColumnExpression(column.Type, column.DbType, this.newAlias, columnName); this.map.Add(column, mapped); this.columnNames.Add(columnName); return(mapped); } // must be referring to outer scope return(column); } else { string columnName = this.GetNextColumnName(); this.columns.Add(new DbColumnDeclaration(columnName, expression)); return(new DbColumnExpression(expression.Type, null, this.newAlias, columnName)); } } else { return(base.Visit(expression)); } }
protected override Expression VisitOuterJoined(DbOuterJoinedExpression outer) { Expression expr = this.Visit(outer.Expression); DbColumnExpression column = (DbColumnExpression)outer.Test; ParameterExpression reader; int iOrdinal; if (this.scope.TryGetValue(column, out reader, out iOrdinal)) { return(Expression.Condition( Expression.Call(reader, "IsDbNull", null, Expression.Constant(iOrdinal)), Expression.Constant(outer.Type.CreateInstance(), outer.Type), expr )); } return(expr); }
private bool GetEquiJoinKeyExpressions(Expression predicate, DbTableAlias outerAlias, List <Expression> outerExpressions, List <Expression> innerExpressions) { if (predicate.NodeType == ExpressionType.Equal) { var b = (BinaryExpression)predicate; DbColumnExpression leftCol = this.GetColumnExpression(b.Left); DbColumnExpression rightCol = this.GetColumnExpression(b.Right); if (leftCol != null && rightCol != null) { if (leftCol.Alias == outerAlias) { outerExpressions.Add(b.Left); innerExpressions.Add(b.Right); return(true); } else if (rightCol.Alias == outerAlias) { innerExpressions.Add(b.Left); outerExpressions.Add(b.Right); return(true); } } } bool hadKey = false; var parts = predicate.Split(ExpressionType.And, ExpressionType.AndAlso); if (parts.Length > 1) { foreach (var part in parts) { bool hasOuterAliasReference = ReferencedAliasGatherer.Gather(part).Contains(outerAlias); if (hasOuterAliasReference) { if (!GetEquiJoinKeyExpressions(part, outerAlias, outerExpressions, innerExpressions)) { return(false); } hadKey = true; } } } return(hadKey); }
protected override Expression VisitSelect(DbSelectExpression select) { select = (DbSelectExpression)base.VisitSelect(select); // look for redundant column declarations List <DbColumnDeclaration> cols = select.Columns.OrderBy(c => c.Name).ToList(); BitArray removed = new BitArray(select.Columns.Count); bool anyRemoved = false; for (int i = 0, n = cols.Count; i < n - 1; i++) { DbColumnDeclaration ci = cols[i]; DbColumnExpression cix = ci.Expression as DbColumnExpression; DbDataType qt = cix != null ? cix.DbType : null; DbColumnExpression cxi = new DbColumnExpression(ci.Expression.Type, qt, select.Alias, ci.Name); for (int j = i + 1; j < n; j++) { if (!removed.Get(j)) { DbColumnDeclaration cj = cols[j]; if (SameExpression(ci.Expression, cj.Expression)) { // any reference to 'j' should now just be a reference to 'i' DbColumnExpression cxj = new DbColumnExpression(cj.Expression.Type, qt, select.Alias, cj.Name); this.map.Add(cxj, cxi); removed.Set(j, true); anyRemoved = true; } } } } if (anyRemoved) { List <DbColumnDeclaration> newDecls = new List <DbColumnDeclaration>(); for (int i = 0, n = cols.Count; i < n; i++) { if (!removed.Get(i)) { newDecls.Add(cols[i]); } } select = select.SetColumns(newDecls); } return(select); }
/// <summary> /// Rebind order expressions to reference a new alias and add to column declarations if necessary /// </summary> protected virtual BindResult RebindOrderings(IEnumerable <DbOrderExpression> orderings, DbTableAlias alias, HashSet <DbTableAlias> existingAliases, IEnumerable <DbColumnDeclaration> existingColumns) { List <DbColumnDeclaration> newColumns = null; List <DbOrderExpression> newOrderings = new List <DbOrderExpression>(); foreach (DbOrderExpression ordering in orderings) { Expression expr = ordering.Expression; DbColumnExpression column = expr as DbColumnExpression; if (column == null || (existingAliases != null && existingAliases.Contains(column.Alias))) { // check to see if a declared column already contains a similar expression int iOrdinal = 0; foreach (DbColumnDeclaration decl in existingColumns) { DbColumnExpression declColumn = decl.Expression as DbColumnExpression; if (decl.Expression == ordering.Expression || (column != null && declColumn != null && column.Alias == declColumn.Alias && column.Name == declColumn.Name)) { // found it, so make a reference to this column expr = new DbColumnExpression(column.Type, column.DbType, alias, decl.Name); break; } iOrdinal++; } // if not already projected, add a new column declaration for it if (expr == ordering.Expression) { if (newColumns == null) { newColumns = new List <DbColumnDeclaration>(existingColumns); existingColumns = newColumns; } string colName = column != null ? column.Name : "c" + iOrdinal; newColumns.Add(new DbColumnDeclaration(colName, ordering.Expression)); expr = new DbColumnExpression(expr.Type, null, alias, colName); } newOrderings.Add(new DbOrderExpression(ordering.OrderType, expr)); } } return(new BindResult(existingColumns, newOrderings)); }
protected override Expression VisitBinary(BinaryExpression b) { Expression left = this.Visit(b.Left); Expression right = this.Visit(b.Right); if (left.NodeType == (ExpressionType)DbExpressionType.NamedValue && right.NodeType == (ExpressionType)DbExpressionType.Column) { DbNamedValueExpression nv = (DbNamedValueExpression)left; DbColumnExpression c = (DbColumnExpression)right; left = new DbNamedValueExpression(nv.Name, c.DbType, nv.Value); } else if (b.Right.NodeType == (ExpressionType)DbExpressionType.NamedValue && b.Left.NodeType == (ExpressionType)DbExpressionType.Column) { DbNamedValueExpression nv = (DbNamedValueExpression)right; DbColumnExpression c = (DbColumnExpression)left; right = new DbNamedValueExpression(nv.Name, c.DbType, nv.Value); } return(this.UpdateBinary(b, left, right, b.Conversion, b.IsLiftedToNull, b.Method)); }
private Expression MakeSubquery(Expression expression) { var newAlias = new DbTableAlias(); var aliases = DeclaredAliasGatherer.Gather(expression); var decls = new List <DbColumnDeclaration>(); foreach (var ta in aliases) { foreach (var col in this.columns[ta]) { string name = decls.GetAvailableColumnName(col.Name); var decl = new DbColumnDeclaration(name, col); decls.Add(decl); var newCol = new DbColumnExpression(col.Type, col.DbType, newAlias, col.Name); this.map.Add(col, newCol); } } return(new DbSelectExpression(newAlias, decls, expression, null)); }
protected override Expression VisitSelect(DbSelectExpression select) { select = (DbSelectExpression)base.VisitSelect(select); if (select.Skip != null) { DbSelectExpression newSelect = select.SetSkip(null).SetTake(null); bool canAddColumn = !select.IsDistinct && (select.GroupBy == null || select.GroupBy.Count == 0); if (!canAddColumn) { newSelect = newSelect.AddRedundantSelect(new DbTableAlias()); } newSelect = newSelect.AddColumn(new DbColumnDeclaration("rownum", new DbRowNumberExpression(select.OrderBy))); // add layer for WHERE clause that references new rownum column newSelect = newSelect.AddRedundantSelect(new DbTableAlias()); newSelect = newSelect.RemoveColumn(newSelect.Columns.Single(c => c.Name == "rownum")); var newAlias = ((DbSelectExpression)newSelect.From).Alias; DbColumnExpression rnCol = new DbColumnExpression(typeof(int), null, newAlias, "rownum"); Expression where; if (select.Take != null) { where = new DbBetweenExpression(rnCol, Expression.Add(select.Skip, Expression.Constant(1)), Expression.Add(select.Skip, select.Take)); } else { where = rnCol.GreaterThan(select.Skip); } if (newSelect.Where != null) { where = newSelect.Where.And(where); } newSelect = newSelect.SetWhere(where); select = newSelect; } return(select); }
public DbColumnAssignment( DbColumnExpression column, Expression expression) { _column = column; _expression = expression; }
private Expression BindAnyAll(Expression source, MethodInfo method, LambdaExpression predicate, bool isRoot) { bool isAll = method.Name == "All"; ConstantExpression constSource = source as ConstantExpression; if (constSource != null && !IsQuery(constSource)) { System.Diagnostics.Debug.Assert(!isRoot); Expression where = null; foreach (object value in (IEnumerable)constSource.Value) { Expression expr = Expression.Invoke(predicate, Expression.Constant(value, predicate.Parameters[0].Type)); if (where == null) { where = expr; } else if (isAll) { where = where.And(expr); } else { where = where.Or(expr); } } return(this.Visit(where)); } else { if (isAll) { predicate = Expression.Lambda(Expression.Not(predicate.Body), predicate.Parameters.ToArray()); } if (predicate != null) { source = Expression.Call(typeof(Queryable), "Where", method.GetGenericArguments(), source, predicate); } DbProjectionExpression projection = this.VisitSequence(source); Expression result = new DbExistsExpression(projection.Select); if (isAll) { result = Expression.Not(result); } if (isRoot) { if (this.mapping.Language.AllowSubqueryInSelectWithoutFrom) { return(GetSingletonSequence(result, "SingleOrDefault")); } else { // use count aggregate instead of exists var newSelect = projection.Select.SetColumns( new[] { new DbColumnDeclaration("value", new DbAggregateExpression(typeof(int), DbAggregateType.Count, null, false)) } ); var colx = new DbColumnExpression(typeof(int), null, newSelect.Alias, "value"); var exp = isAll ? colx.Equal(Expression.Constant(0)) : colx.GreaterThan(Expression.Constant(0)); return(new DbProjectionExpression( newSelect, exp, Aggregator.Aggregate(typeof(bool), typeof(IEnumerable <bool>)) )); } } return(result); } }
protected virtual bool CompareColumn(DbColumnExpression a, DbColumnExpression b) { return(CompareAlias(a.Alias, b.Alias) && a.Name == b.Name); }
protected override Expression VisitColumn(DbColumnExpression column) { MarkColumnAsUsed(column.Alias, column.Name); return(column); }
protected override Expression VisitColumn(DbColumnExpression column) { this.aliases.Add(column.Alias); return(column); }
protected override Expression VisitColumn(DbColumnExpression column) { this.columns.Add(column); return(column); }
protected virtual Expression VisitColumn(DbColumnExpression column) { return(column); }