internal string[] FormatBlock(SqlBlock block, bool isDebug) { List<string> results = new List<string>(block.Statements.Count); for(int i = 0, n = block.Statements.Count; i < n; i++) { SqlStatement stmt = block.Statements[i]; SqlSelect select = stmt as SqlSelect; if(select != null && select.DoNotOutput) { continue; } results.Add(this.Format(stmt, isDebug)); } return results.ToArray(); }
internal ReadOnlyCollection<ReadOnlyCollection<SqlParameterInfo>> ParameterizeBlock(SqlBlock block) { SqlParameterInfo rowStatus = new SqlParameterInfo( new SqlParameter(typeof(int), _typeProvider.From(typeof(int)), "@ROWCOUNT", block.SourceExpression) ); List<ReadOnlyCollection<SqlParameterInfo>> list = new List<ReadOnlyCollection<SqlParameterInfo>>(); for(int i = 0, n = block.Statements.Count; i < n; i++) { SqlNode statement = block.Statements[i]; List<SqlParameterInfo> parameters = this.ParameterizeInternal(statement); if(i > 0) { parameters.Add(rowStatus); } list.Add(parameters.AsReadOnly()); } return list.AsReadOnly(); }
internal virtual SqlBlock VisitBlock(SqlBlock b) { for (int i = 0, n = b.Statements.Count; i < n; i++) { b.Statements[i] = (SqlStatement)this.Visit(b.Statements[i]); } return b; }
private SqlStatement VisitUpdate(Expression item, LambdaExpression check, LambdaExpression resultSelector) { if(item == null) { throw Error.ArgumentNull("item"); } MetaTable metaTable = _services.Model.GetTable(item.Type); Expression source = _services.Context.GetTable(metaTable.RowType.Type).Expression; Type rowType = metaTable.RowType.Type; bool saveAllowDeferred = _allowDeferred; _allowDeferred = false; try { Expression seq = source; // construct identity predicate based on supplied item ParameterExpression p = Expression.Parameter(rowType, "p"); LambdaExpression idPredicate = Expression.Lambda(Expression.Equal(p, item), p); // combine predicate and check expression into single find predicate LambdaExpression findPredicate = idPredicate; if(check != null) { findPredicate = Expression.Lambda(Expression.And(Expression.Invoke(findPredicate, p), Expression.Invoke(check, p)), p); } seq = Expression.Call(typeof(Enumerable), "Where", new Type[] { rowType }, seq, findPredicate); // source 'query' is based on table + find predicate SqlSelect ss = new RetypeCheckClause().VisitSelect(this.VisitSequence(seq)); // construct update assignments from 'item' info List<SqlAssign> assignments = new List<SqlAssign>(); ConstantExpression conItem = item as ConstantExpression; if(conItem == null) { throw Error.UpdateItemMustBeConstant(); } if(conItem.Value == null) { throw Error.ArgumentNull("item"); } // get changes from data services to construct update command Type entityType = conItem.Value.GetType(); MetaType metaType = _services.Model.GetMetaType(entityType); ITable table = _services.Context.GetTable(metaType.InheritanceRoot.Type); foreach(ModifiedMemberInfo mmi in table.GetModifiedMembers(conItem.Value)) { MetaDataMember mdm = metaType.GetDataMember(mmi.Member); assignments.Add( new SqlAssign( _nodeFactory.Member(ss.Selection, mmi.Member), new SqlValue(mdm.Type, _typeProvider.From(mdm.Type), mmi.CurrentValue, true, source), source )); } SqlUpdate upd = new SqlUpdate(ss, assignments, source); if(resultSelector == null) { return upd; } SqlSelect select = null; // build select to return result seq = source; seq = Expression.Call(typeof(Enumerable), "Where", new Type[] { rowType }, seq, idPredicate); seq = Expression.Call(typeof(Enumerable), "Select", new Type[] { rowType, resultSelector.Body.Type }, seq, resultSelector); select = this.VisitSequence(seq); select.Where = _nodeFactory.AndAccumulate( _nodeFactory.Binary(SqlNodeType.GT, this.GetRowCountExpression(), _nodeFactory.ValueFromObject(0, false, _dominatingExpression)), select.Where ); // combine update & select into statement block SqlBlock block = new SqlBlock(source); block.Statements.Add(upd); block.Statements.Add(select); return block; } finally { _allowDeferred = saveAllowDeferred; } }
private SqlStatement VisitInsert(Expression item, LambdaExpression resultSelector) { if(item == null) { throw Error.ArgumentNull("item"); } _dominatingExpression = item; MetaTable metaTable = _services.Model.GetTable(item.Type); Expression source = _services.Context.GetTable(metaTable.RowType.Type).Expression; MetaType itemMetaType = null; SqlNew sqlItem = null; // construct insert assignments from 'item' info ConstantExpression conItem = item as ConstantExpression; if(conItem == null) { throw Error.InsertItemMustBeConstant(); } if(conItem.Value == null) { throw Error.ArgumentNull("item"); } // construct insert based on constant value List<SqlMemberAssign> bindings = new List<SqlMemberAssign>(); itemMetaType = metaTable.RowType.GetInheritanceType(conItem.Value.GetType()); SqlExpression sqlExprItem = _nodeFactory.ValueFromObject(conItem.Value, true, source); foreach(MetaDataMember mm in itemMetaType.PersistentDataMembers) { if(!mm.IsAssociation && !mm.IsDbGenerated && !mm.IsVersion) { bindings.Add(new SqlMemberAssign(mm.Member, _nodeFactory.Member(sqlExprItem, mm.Member))); } } ConstructorInfo cons = itemMetaType.Type.GetConstructor(Type.EmptyTypes); System.Diagnostics.Debug.Assert(cons != null); sqlItem = _nodeFactory.New(itemMetaType, cons, null, null, bindings, item); SqlTable tab = _nodeFactory.Table(metaTable, metaTable.RowType, _dominatingExpression); SqlInsert sin = new SqlInsert(tab, sqlItem, item); if(resultSelector == null) { return sin; } else { MetaDataMember id = itemMetaType.DBGeneratedIdentityMember; bool isDbGenOnly = false; if(id != null) { isDbGenOnly = this.IsDbGeneratedKeyProjectionOnly(resultSelector.Body, id); if(id.Type == typeof(Guid) && (_converterStrategy & ConverterStrategy.CanOutputFromInsert) != 0) { sin.OutputKey = new SqlColumn(id.Type, _nodeFactory.Default(id), id.Name, id, null, _dominatingExpression); if(!isDbGenOnly) { sin.OutputToLocal = true; } } } SqlSelect result = null; SqlSelect preResult = null; SqlAlias tableAlias = new SqlAlias(tab); SqlAliasRef tableAliasRef = new SqlAliasRef(tableAlias); System.Diagnostics.Debug.Assert(resultSelector.Parameters.Count == 1); _parameterExpressionToSqlExpression.Add(resultSelector.Parameters[0], tableAliasRef); SqlExpression projection = this.VisitExpression(resultSelector.Body); // build select to return result SqlExpression pred = null; if(id != null) { pred = _nodeFactory.Binary( SqlNodeType.EQ, _nodeFactory.Member(tableAliasRef, id.Member), this.GetIdentityExpression(id, sin.OutputKey != null) ); } else { SqlExpression itemExpression = this.VisitExpression(item); pred = _nodeFactory.Binary(SqlNodeType.EQ2V, tableAliasRef, itemExpression); } result = new SqlSelect(projection, tableAlias, resultSelector); result.Where = pred; // Since we're only projecting back a single generated key, we can // optimize the query to a simple selection (e.g. SELECT @@IDENTITY) // rather than selecting back from the table. if(id != null && isDbGenOnly) { if(sin.OutputKey == null) { SqlExpression exp = this.GetIdentityExpression(id, false); if(exp.ClrType != id.Type) { ProviderType sqlType = _nodeFactory.Default(id); exp = _nodeFactory.ConvertTo(id.Type, sqlType, exp); } // The result selector passed in was bound to the table - // we need to rebind to the single result as an array projection ParameterExpression p = Expression.Parameter(id.Type, "p"); Expression[] init = new Expression[1] { Expression.Convert(p, typeof(object)) }; NewArrayExpression arrExp = Expression.NewArrayInit(typeof(object), init); LambdaExpression rs = Expression.Lambda(arrExp, p); _parameterExpressionToSqlExpression.Add(p, exp); SqlExpression proj = this.VisitExpression(rs.Body); preResult = new SqlSelect(proj, null, rs); } else { // case handled in formatter automatically } result.DoNotOutput = true; } // combine insert & result into block SqlBlock block = new SqlBlock(_dominatingExpression); block.Statements.Add(sin); if(preResult != null) { block.Statements.Add(preResult); } block.Statements.Add(result); return block; } }
internal override SqlBlock VisitBlock(SqlBlock block) { for(int i = 0, n = block.Statements.Count; i < n; i++) { this.Visit(block.Statements[i]); if(i < n - 1) { SqlSelect select = block.Statements[i + 1] as SqlSelect; if(@select == null || [email protected]) { this.NewLine(); this.NewLine(); } } } return block; }
internal override SqlBlock VisitBlock(SqlBlock block) { SqlBlock nb = new SqlBlock(block.SourceExpression); foreach(SqlStatement stmt in block.Statements) { nb.Statements.Add((SqlStatement)this.Visit(stmt)); } return nb; }