protected override Expression VisitIn(InExpression expression) { if (!ShouldRewrite(expression)) { return base.VisitIn(expression); } Array array = expression.Values.OfType<ConstantExpression>().Select(item => item.Value).Distinct().ToArray(); var vfpDataXml = new ArrayXmlToCursor(array); var tableAlias = new TableAlias(); var columnType = _language.TypeSystem.GetColumnType(vfpDataXml.ItemType); var columnExpression = new ColumnExpression(vfpDataXml.ItemType, columnType, tableAlias, ArrayXmlToCursor.ColumnName); var columns = new List<ColumnDeclaration> { new ColumnDeclaration(string.Empty, columnExpression, columnType) }; var xml = Expression.Constant(vfpDataXml.Xml); var cursorName = Expression.Constant("curTemp_" + DateTime.Now.ToString("ddHHssmm")); var check = Expression.GreaterThan(new XmlToCursorExpression(xml, cursorName), Expression.Constant(0)); var from = Expression.Condition(check, cursorName, Expression.Constant(string.Empty)); var select = new SelectExpression(tableAlias, columns, from, null); return new InExpression(expression.Expression, select); }
protected void AddAlias(TableAlias alias) { if (!this.aliasMap.ContainsKey(alias)) { this.aliasMap.Add(alias, this.aliasMap.Count); } }
internal static Expression Parameterize(TableAlias outerAlias, Expression expr, int parameterCounter) { OuterParameterizer op = new OuterParameterizer(); op.outerAlias = outerAlias; op.parameterCounter = parameterCounter; return op.Visit(expr); }
protected override Expression VisitSelect(SelectExpression select) { TableAlias newAlias = new TableAlias(); this.map[select.Alias] = newAlias; select = (SelectExpression)base.VisitSelect(select); return new SelectExpression(newAlias, select.Columns, select.From, select.Where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Skip, select.Take, select.IsReverse); }
internal Scope(Scope outer, ParameterExpression fieldReader, TableAlias alias, IEnumerable<ColumnDeclaration> columns) { this.outer = outer; this.fieldReader = fieldReader; this.Alias = alias; this.nameMap = columns.Select((c, i) => new { c, i }).ToDictionary(x => x.c.Name, x => x.i); }
public static SelectExpression AddRedundantSelect(this SelectExpression sel, QueryLanguage language, TableAlias newAlias) { var newColumns = from d in sel.Columns let qt = (d.Expression is ColumnExpression) ? ((ColumnExpression)d.Expression).QueryType : language.TypeSystem.GetColumnType(d.Expression.Type) select new ColumnDeclaration(d.Name, new ColumnExpression(d.Expression.Type, qt, newAlias, d.Name), qt); var newFrom = new SelectExpression(newAlias, sel.Columns, sel.From, sel.Where, sel.OrderBy, sel.GroupBy, sel.IsDistinct, sel.Skip, sel.Take, sel.IsReverse); return new SelectExpression(sel.Alias, newColumns, newFrom, null, null, null, false, null, null, false); }
private void MarkColumnAsUsed(TableAlias alias, string name) { HashSet<string> columns; if (!this.allColumnsUsed.TryGetValue(alias, out columns)) { columns = new HashSet<string>(); this.allColumnsUsed.Add(alias, columns); } columns.Add(name); }
public override TableAlias Visit(TableAlias item) { if (item == null) return null; TableAlias result; if (!aliasesMapping.TryGetValue(item, out result)) if (!aliasesMapping.TryGetValue(TableAlias.All, out result)) return item; return result; }
protected override Expression VisitProjection(ProjectionExpression proj) { SelectExpression save = this.currentSelect; this.currentSelect = proj.Source; try { if (!this.isTopLevel) { if (this.CanJoinOnClient(this.currentSelect)) { // make a query that combines all the constraints from the outer queries into a single select SelectExpression newOuterSelect = (SelectExpression)QueryDuplicator.Duplicate(save); // remap any references to the outer select to the new alias; SelectExpression newInnerSelect = (SelectExpression)ColumnMapper.Map(proj.Source, newOuterSelect.Alias, save.Alias); // add outer-join test ProjectionExpression newInnerProjection = new ProjectionExpression(newInnerSelect, proj.Projector).AddOuterJoinTest(); newInnerSelect = newInnerProjection.Source; Expression newProjector = newInnerProjection.Projector; TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.language.CanBeColumn, newProjector, newOuterSelect.Columns, newAlias, newOuterSelect.Alias, newInnerSelect.Alias); JoinExpression join = new JoinExpression(JoinType.OuterApply, newOuterSelect, newInnerSelect, null); SelectExpression joinedSelect = new SelectExpression(newAlias, pc.Columns, join, null, null, null, proj.IsSingleton, null, null); // apply client-join treatment recursively this.currentSelect = joinedSelect; newProjector = this.Visit(pc.Projector); // compute keys (this only works if join condition was a single column comparison) List<Expression> outerKeys = new List<Expression>(); List<Expression> innerKeys = new List<Expression>(); if (this.GetEquiJoinKeyExpressions(newInnerSelect.Where, newOuterSelect.Alias, outerKeys, innerKeys)) { // outerKey needs to refer to the outer-scope's alias var outerKey = outerKeys.Select(k => ColumnMapper.Map(k, save.Alias, newOuterSelect.Alias)); // innerKey needs to refer to the new alias for the select with the new join var innerKey = innerKeys.Select(k => ColumnMapper.Map(k, joinedSelect.Alias, ((ColumnExpression)k).Alias)); ProjectionExpression newProjection = new ProjectionExpression(joinedSelect, newProjector, proj.Aggregator); return new ClientJoinExpression(newProjection, outerKey, innerKey); } } } else { this.isTopLevel = false; } return base.VisitProjection(proj); } finally { this.currentSelect = save; } }
private bool IsColumnUsed(TableAlias alias, string name) { HashSet<string> columnsUsed; if (this.allColumnsUsed.TryGetValue(alias, out columnsUsed)) { if (columnsUsed != null) { return columnsUsed.Contains(name); } } return false; }
private ColumnProjector(Func <Expression, bool> fnCanBeColumn, Expression expression, IEnumerable <ColumnDeclaration> existingColumns, TableAlias newAlias, IEnumerable <TableAlias> existingAliases) { this.newAlias = newAlias; this.existingAliases = new HashSet <TableAlias>(existingAliases); this.map = new Dictionary <ColumnExpression, ColumnExpression>(); if (existingColumns != null) { this.columns = new List <ColumnDeclaration>(existingColumns); this.columnNames = new HashSet <string>(existingColumns.Select(c => c.Name)); } else { this.columns = new List <ColumnDeclaration>(); this.columnNames = new HashSet <string>(); } this.candidates = Nominator.Nominate(fnCanBeColumn, expression); }
internal static ProjectionExpression GetTableQuery(TranslateContext transContext, EntityMetadata entity, bool isNoTracking, bool isAsync) { var tableAlias = new TableAlias(); var selectAlias = new TableAlias(); var entityType = entity.EntityType; var table = new TableExpression(tableAlias, entity.TableName, entityType); var projector = GetTypeProjection(transContext, table, entity); var pc = ColumnProjector.ProjectColumns(CanBeColumnExpression, projector, null, selectAlias, tableAlias); var proj = new ProjectionExpression( new SelectExpression(selectAlias, pc.Columns, table, null), pc.Projector, isAsync, isNoTracking ); return((ProjectionExpression)transContext.QueryPolicy.ApplyPolicy(proj, entityType, ex => QueryBinder.Bind(transContext, ex))); }
protected override Expression VisitProjection(ProjectionExpression proj) { if (isTopLevel) { isTopLevel = false; currentSelect = proj.Source; Expression projector = Visit(proj.Projector); if (projector != proj.Projector || currentSelect != proj.Source) { return(new ProjectionExpression(currentSelect, projector, proj.Aggregator)); } return(proj); } if (proj.IsSingleton && CanJoinOnServer(currentSelect)) { TableAlias newAlias = new TableAlias(); currentSelect = currentSelect.AddRedundantSelect(newAlias); // remap any references to the outer select to the new alias; SelectExpression source = (SelectExpression)ColumnMapper.Map(proj.Source, newAlias, currentSelect.Alias); // add outer-join test ProjectionExpression pex = new ProjectionExpression(source, proj.Projector).AddOuterJoinTest(); var pc = ColumnProjector.ProjectColumns(language.CanBeColumn, pex.Projector, currentSelect.Columns, currentSelect.Alias, newAlias, proj.Source.Alias); JoinExpression join = new JoinExpression(JoinType.OuterApply, currentSelect.From, pex.Source, null); currentSelect = new SelectExpression(currentSelect.Alias, pc.Columns, join, null); return(Visit(pc.Projector)); } var saveTop = isTopLevel; var saveSelect = currentSelect; isTopLevel = true; currentSelect = null; Expression result = base.VisitProjection(proj); isTopLevel = saveTop; currentSelect = saveSelect; return(result); }
private ColumnProjector(Func<Expression, bool> fnCanBeColumn, Expression expression, IEnumerable<ColumnDeclaration> existingColumns, TableAlias newAlias, IEnumerable<TableAlias> existingAliases) { this.newAlias = newAlias; this.existingAliases = new HashSet<TableAlias>(existingAliases); this.map = new Dictionary<ColumnExpression, ColumnExpression>(); if (existingColumns != null) { this.columns = new List<ColumnDeclaration>(existingColumns); this.columnNames = new HashSet<string>(existingColumns.Select(c => c.Name)); } else { this.columns = new List<ColumnDeclaration>(); this.columnNames = new HashSet<string>(); } this.candidates = Nominator.Nominate(fnCanBeColumn, expression); }
internal static ProjectionExpression GetTableQuery(EntityMetadata entity, bool isNoTracking) { var tableAlias = new TableAlias(); var selectAlias = new TableAlias(); var entityType = entity.EntityType; var table = new TableExpression(tableAlias, entity.TableName, entityType); var projector = GetTypeProjection(table, entity, isNoTracking); var pc = ColumnProjector.ProjectColumns(CanBeColumnExpression, projector, null, selectAlias, tableAlias); var proj = new ProjectionExpression( new SelectExpression(selectAlias, pc.Columns, table, null), pc.Projector ); return((ProjectionExpression)ApplyPolicy(proj, entityType)); }
private ColumnProjector(Expression expression, IEnumerable<ColumnDeclaration> existingColumns, TableAlias newAlias, IEnumerable<TableAlias> existingAliases) { this.newAlias = newAlias; this.existingAliases = new HashSet<TableAlias>(existingAliases, TableAlias.Comparer); this.map = new Dictionary<ColumnExpression, ColumnExpression>(); if (existingColumns != null) { this.columns = new List<ColumnDeclaration>(existingColumns); this.columnNames = new HashSet<string>(existingColumns.Select(c => c.Name), StringComparer.Ordinal); } else { this.columns = new List<ColumnDeclaration>(); this.columnNames = new HashSet<string>(StringComparer.Ordinal); } this.candidates = Nominator.Nominate(expression); }
private bool GetEquiJoinKeyExpressions(Expression predicate, TableAlias outerAlias, List <Expression> outerExpressions, List <Expression> innerExpressions) { if (predicate.NodeType == ExpressionType.Equal) { var b = (BinaryExpression)predicate; ColumnExpression leftCol = this.GetColumnExpression(b.Left); ColumnExpression 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); }
public IWhereClauseBuilder Or <TEntity>(Expression <Func <TEntity, bool> > expression, TableAlias alias, string tableName = null, string tableSchema = null) { if (string.IsNullOrWhiteSpace(Sql())) { return(Where <TEntity>(expression, alias, false, tableName, tableSchema)); } else { return(Or <TEntity>(expression, Utils.Alias(alias), tableName, tableSchema)); } }
public IWhereClauseBuilder Where <TEntity>(Expression <Func <TEntity, bool> > expression, TableAlias alias, bool ClearBeforeWhereeClause = false, string tableName = null, string tableSchema = null) { if (string.IsNullOrWhiteSpace(Sql()) || ClearBeforeWhereeClause == true) { return(Where <TEntity>(expression, Utils.Alias(alias), tableName, tableSchema)); } else { return(And <TEntity>(expression, Utils.Alias(alias), tableName, tableSchema)); } }
public IWhereClauseBuilder AndIn <TEntity, TMember>(Expression <Func <TEntity, TMember> > selector, TMember[] values, TableAlias alias, string tableName = null, string tableSchema = null) { if (string.IsNullOrWhiteSpace(Sql())) { return(WhereIn <TEntity, TMember>(selector, values, alias, false, tableName, tableSchema)); } else { return(AndIn <TEntity, TMember>(selector, values, Utils.Alias(alias), tableName, tableSchema)); } }
public virtual Expression GetMemberExpression(Expression root, IEntityMapping mapping, IMemberMapping mm) { var m = mm.Member; if (mm.IsRelationship) { IEntityMapping relatedEntity = mm.RelatedEntity; ProjectionExpression projection = this.GetQueryExpression(relatedEntity); // make where clause for joining back to 'root' var thisKeyMembers = mm.ThisKeyMembers; var otherKeyMembers = mm.OtherKeyMembers; Expression where = null; for (int i = 0, n = otherKeyMembers.Length; i < n; i++) { Expression equal = this.GetMemberExpression(projection.Projector, relatedEntity, otherKeyMembers[i]).Equal( this.GetMemberExpression(root, mapping, thisKeyMembers[i]) ); where = (where != null) ? where.And(equal) : equal; } TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(projection.Projector, null, newAlias, projection.Select.Alias); LambdaExpression aggregator = Aggregator.GetAggregator(mm.MemberType, typeof(IEnumerable <>).MakeGenericType(pc.Projector.Type)); var result = new ProjectionExpression( new SelectExpression(newAlias, pc.Columns, projection.Select, where), pc.Projector, aggregator ); return(ApplyPolicy(result, m)); } else { AliasedExpression aliasedRoot = root as AliasedExpression; if (aliasedRoot != null && mm.IsColumn) { return(new ColumnExpression(mm.MemberType, mm.SqlType, aliasedRoot.Alias, mm.ColumnName)); } return(QueryBinder.BindMember(root, m)); } }
protected override Expression VisitProjection(ProjectionExpression proj) { if (isTopLevel) { isTopLevel = false; currentSelect = proj.Source; Expression projector = Visit(proj.Projector); if (projector != proj.Projector || currentSelect != proj.Source) { return new ProjectionExpression(currentSelect, projector, proj.Aggregator); } return proj; } if (proj.IsSingleton && CanJoinOnServer(currentSelect)) { TableAlias newAlias = new TableAlias(); currentSelect = currentSelect.AddRedundantSelect(newAlias); // remap any references to the outer select to the new alias; SelectExpression source = (SelectExpression) ColumnMapper.Map(proj.Source, newAlias, currentSelect.Alias); // add outer-join test ProjectionExpression pex = new ProjectionExpression(source, proj.Projector).AddOuterJoinTest(); var pc = ColumnProjector.ProjectColumns(language.CanBeColumn, pex.Projector, currentSelect.Columns, currentSelect.Alias, newAlias, proj.Source.Alias); JoinExpression join = new JoinExpression(JoinType.OuterApply, currentSelect.From, pex.Source, null); currentSelect = new SelectExpression(currentSelect.Alias, pc.Columns, join, null); return Visit(pc.Projector); } var saveTop = isTopLevel; var saveSelect = currentSelect; isTopLevel = true; currentSelect = null; Expression result = base.VisitProjection(proj); isTopLevel = saveTop; currentSelect = saveSelect; return result; }
public override Expression GetInsertExpression(MappingEntity entity, Expression instance, LambdaExpression selector) { var tables = this.mapping.GetTables(entity); if (tables.Count < 2) { return(base.GetInsertExpression(entity, instance, selector)); } var commands = new List <Expression>(); var map = this.GetDependentGeneratedColumns(entity); var vexMap = new Dictionary <MemberInfo, Expression>(); foreach (var table in this.GetDependencyOrderedTables(entity)) { var tableAlias = new TableAlias(); var tex = new TableExpression(tableAlias, entity, this.mapping.GetTableName(table)); var assignments = this.GetColumnAssignments(tex, instance, entity, (e, m) => this.mapping.GetAlias(e, m) == this.mapping.GetAlias(table) && !this.mapping.IsGenerated(e, m), vexMap); var totalAssignments = assignments.Concat( this.GetRelatedColumnAssignments(tex, entity, table, vexMap)); commands.Add(new InsertCommand(tex, totalAssignments)); List <MemberInfo> members; if (map.TryGetValue(this.mapping.GetAlias(table), out members)) { var d = this.GetDependentGeneratedVariableDeclaration(entity, table, members, instance, vexMap); commands.Add(d); } } if (selector != null) { commands.Add(this.GetInsertResult(entity, instance, selector, vexMap)); } return(new BlockCommand(commands)); }
private Expression MakeSubquery(Expression expression) { var newAlias = new TableAlias(); var aliases = TableAliasGatherer.Gather(expression); var decls = new List<ColumnDeclaration>(); foreach (var ta in aliases) { foreach (var col in this.columns[ta]) { string name = decls.GetAvailableColumnName(col.Name); var decl = new ColumnDeclaration(name, col, col.SqlType); decls.Add(decl); var newCol = new ColumnExpression(col.Type, col.SqlType, newAlias, name); this.map.Add(col, newCol); } } return new SelectExpression(newAlias, decls, expression, null); }
public IWhereClauseBuilder OrBetween <TEntity, TMember>(Expression <Func <TEntity, TMember> > selector, TMember start, TMember end, TableAlias alias, string tableName = null, string tableSchema = null) { if (string.IsNullOrWhiteSpace(Sql())) { return(WhereBetween <TEntity, TMember>(selector, start, end, Utils.Alias(alias), tableName, tableSchema)); } else { return(OrBetween <TEntity, TMember>(selector, start, end, Utils.Alias(alias), tableName, tableSchema)); } }
private Expression MakeSubquery(Expression expression) { var newAlias = new TableAlias(); var aliases = DeclaredAliasGatherer.Gather(expression); var decls = new List <ColumnDeclaration>(); foreach (var ta in aliases) { foreach (var col in columns[ta]) { var name = decls.GetAvailableColumnName(col.Name); var decl = new ColumnDeclaration(name, col); decls.Add(decl); var newCol = new ColumnExpression(col.Type, newAlias, name, null); map.Add(col, newCol); } } return(new SelectExpression(newAlias, decls, expression, null)); }
protected override DeclarationCommand GetGeneratedIdCommand(MappingEntity entity, List <MemberInfo> members, Dictionary <MemberInfo, Expression> map) { var columns = new List <ColumnDeclaration>(); var decls = new List <VariableDeclaration>(); var alias = new TableAlias(); var orderBy = new List <OrderExpression> { new OrderExpression(OrderType.Ascending, Expression.Constant(1)) }; foreach (var member in members) { var genId = Translator.Linguist.Language.GetGeneratedIdExpression(member); var colType = GetColumnType(entity, member); columns.Add(new ColumnDeclaration(member.Name, genId, colType)); decls.Add(new VariableDeclaration(member.Name, colType, new ColumnExpression(genId.Type, colType, alias, member.Name))); if (map != null) { var vex = new VariableExpression(member.Name, TypeHelper.GetMemberType(member), colType); map.Add(member, vex); } } var attributeMapping = entity as VfpAttributeMapping.AttributeMappingEntity; var tableId = entity.TableId; if (attributeMapping != null) { tableId = attributeMapping.TableName; } var from = new TableExpression(alias, entity, tableId); Expression take = Expression.Constant(1); var select = new SelectExpression(alias, columns, from, null, new ReadOnlyCollection <OrderExpression>(orderBy), null, false, null, take, false); return(new DeclarationCommand(decls, select)); }
public virtual ProjectionExpression GetQueryExpression(IEntityMapping mapping) { Expression projector; TableAlias selectAlias; ProjectedColumns pc; ProjectionExpression proj; var tableAlias = new TableAlias(); selectAlias = new TableAlias(); var table = new TableExpression(tableAlias, mapping); projector = this.GetEntityExpression(table, mapping); pc = ColumnProjector.ProjectColumns(projector, null, selectAlias, tableAlias); proj = new ProjectionExpression( new SelectExpression(selectAlias, pc.Columns, table, null), pc.Projector ); return((ProjectionExpression)ApplyPolicy(proj, mapping.EntityType)); }
internal DeclarationCommand GetGeneratedIdCommand(IEntityMapping mapping, List <IMemberMapping> members, Dictionary <MemberInfo, Expression> map) { var columns = new List <ColumnDeclaration>(); var decls = new List <VariableDeclaration>(); var alias = new TableAlias(); foreach (var member in members) { Expression genId = this.GetGeneratedIdExpression(member); var name = member.Member.Name; var colType = member.SqlType; columns.Add(new ColumnDeclaration(name, genId, colType)); decls.Add(new VariableDeclaration(name, colType, new ColumnExpression(genId.Type, colType, alias, name))); if (map != null) { var vex = new VariableExpression(name, member.MemberType, colType); map.Add(member.Member, vex); } } var select = new SelectExpression(alias, columns, null, null); return(new DeclarationCommand(decls, select)); }
private bool GetEquiJoinKeyExpressions(Expression predicate, TableAlias outerAlias, List <Expression> outerExpressions, List <Expression> innerExpressions) { // predicate can be AND's and EQUAL's between columns BinaryExpression b = predicate as BinaryExpression; if (b != null) { switch (predicate.NodeType) { case ExpressionType.And: case ExpressionType.AndAlso: return(this.GetEquiJoinKeyExpressions(b.Left, outerAlias, outerExpressions, innerExpressions) && this.GetEquiJoinKeyExpressions(b.Right, outerAlias, outerExpressions, innerExpressions)); case ExpressionType.Equal: ColumnExpression left = b.Left as ColumnExpression; ColumnExpression right = b.Right as ColumnExpression; if (left != null && right != null) { if (left.Alias == outerAlias) { outerExpressions.Add(left); innerExpressions.Add(right); return(true); } else if (right.Alias == outerAlias) { innerExpressions.Add(left); outerExpressions.Add(right); return(true); } } break; } } return(false); }
public IEntityWriter <IdType, EntityType> Update(IList <EntityType> entities) { foreach (var entity in entities) { var task = new ExecuteTask <EntityType>(_tasks.Count) { TaskType = ActionType.Update, Entity = entity, }; task.Queries.Add( new QueryElement() { FieldName = IdColumn, Operator = Operator.Equals, Value = entity.Id, TableAlias = TableAlias.ToString() }); _tasks.Add(task); } return(this); }
public virtual Expression GetInsertExpression(IEntityMapping mapping, Expression instance, LambdaExpression selector) { var tableAlias = new TableAlias(); var table = new TableExpression(tableAlias, mapping); var assignments = this.GetInsertColumnAssignments(table, instance, mapping, m => !m.IsGenerated && !m.IsVersion).ToArray(); object o = null; var c = instance as ConstantExpression; if (c != null) { o = c.Value; } if (selector != null) { return(new BlockCommand( new InsertCommand(table, assignments, o), this.GetInsertResult(mapping, instance, selector, null) )); } return(new InsertCommand(table, assignments, o)); }
private bool GetEquiJoinKeyExpressions(Expression predicate, TableAlias outerAlias, List <Expression> outerExpressions, List <Expression> innerExpressions) { var b = predicate as BinaryExpression; if (b != null) { switch (predicate.NodeType) { case ExpressionType.And: case ExpressionType.AndAlso: return(GetEquiJoinKeyExpressions(b.Left, outerAlias, outerExpressions, innerExpressions) && GetEquiJoinKeyExpressions(b.Right, outerAlias, outerExpressions, innerExpressions)); case ExpressionType.Equal: var left = b.Left as ColumnExpression; var right = b.Right as ColumnExpression; if (left != null && right != null) { if (left.Alias == outerAlias) { outerExpressions.Add(left); innerExpressions.Add(right); return(true); } else if (right.Alias == outerAlias) { innerExpressions.Add(left); outerExpressions.Add(right); return(true); } } break; } } return(false); }
/// <summary> /// 创建 INSRT 命令 /// </summary> /// <param name="dbQuery">查询语义</param> /// <param name="token">解析上下文</param> /// <returns></returns> protected override RawCommand ResolveInsertCommand <T>(IDbQueryableInfo_Insert dbQuery, ResolveToken token) { TableAlias aliases = new TableAlias(); ISqlBuilder builder = this.CreateSqlBuilder(token); var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); if (dbQuery.Entity != null) { object entity = dbQuery.Entity; ISqlBuilder seg_Columns = this.CreateSqlBuilder(token); ISqlBuilder seg_Values = this.CreateSqlBuilder(token); // 指定插入列 MemberAccessorCollection memberAccessors = typeRuntime.Members; if (dbQuery.EntityColumns != null && dbQuery.EntityColumns.Count > 0) { memberAccessors = new MemberAccessorCollection(); for (int i = 0; i < dbQuery.EntityColumns.Count; i++) { Expression curExpr = dbQuery.EntityColumns[i]; if (curExpr.NodeType == ExpressionType.Lambda) { curExpr = (curExpr as LambdaExpression).Body.ReduceUnary(); } if (curExpr.NodeType != ExpressionType.MemberAccess) { throw new XFrameworkException("Can't read field name from expression {0}", dbQuery.EntityColumns[i]); } MemberExpression member = curExpr as MemberExpression; string name = member.Member.Name; memberAccessors[name] = typeRuntime.Members[name]; } } foreach (var m in memberAccessors) { var column = m.Column; if (column != null && column.NoMapped) { continue; } if (m.ForeignKey != null) { continue; } if (m.Member.MemberType == System.Reflection.MemberTypes.Method) { continue; } if (m != typeRuntime.Identity) { seg_Columns.AppendMember(m.Member.Name); seg_Columns.Append(','); var value = m.Invoke(entity); string seg = this.DbValue.GetSqlValueWidthDefault(value, token, column); seg_Values.Append(seg); seg_Values.Append(','); } } seg_Columns.Length -= 1; seg_Values.Length -= 1; if (dbQuery.Bulk == null || !dbQuery.Bulk.OnlyValue) { builder.Append("INSERT INTO "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.Append('('); builder.Append(seg_Columns); builder.Append(')'); builder.AppendNewLine(); builder.AppendTab(); builder.Append("VALUES"); } builder.Append('('); builder.Append(seg_Values); builder.Append(')'); if (dbQuery.Bulk != null && !dbQuery.Bulk.IsEndPos) { builder.Append(","); } if (dbQuery.Bulk == null && typeRuntime.Identity != null) { builder.Append(';'); builder.AppendNewLine(); builder.AppendFormat("SELECT LAST_INSERT_ROWID()"); builder.Append(" AS "); builder.Append(this.QuotePrefix); builder.Append(Constant.AUTO_INCREMENT_NAME); builder.Append(this.QuoteSuffix); } } else if (dbQuery.Query != null) { builder.Append("INSERT INTO "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.Append('('); int i = 0; MappingCommand cmd = this.ResolveSelectCommandImpl(dbQuery.Query, 0, false, token) as MappingCommand; //for (int i = 0; i < seg.Columns.Count; i++) foreach (var column in cmd.PickColumns) { builder.AppendMember(column.Name); if (i < cmd.PickColumns.Count - 1) { builder.Append(','); } i++; } builder.Append(')'); builder.AppendNewLine(); builder.Append(cmd.CommandText); } if (dbQuery.Bulk == null || dbQuery.Bulk.IsEndPos) { builder.Append(';'); } return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text)); }
protected override Expression VisitTable(TableExpression table) { TableAlias newAlias = new TableAlias(); this.map[table.Alias] = newAlias; return new TableExpression(newAlias, table.Entity, table.Name); }
// make a variable declaration / initialization for dependent generated values private CommandExpression GetDependentGeneratedVariableDeclaration(MappingEntity entity, MappingTable table, List<MemberInfo> members, Expression instance, Dictionary<MemberInfo, Expression> map) { // first make command that retrieves the generated ids if any DeclarationCommand genIdCommand = null; var generatedIds = this.mapping.GetMappedMembers(entity).Where(m => this.mapping.IsPrimaryKey(entity, m) && this.mapping.IsGenerated(entity, m)).ToList(); if (generatedIds.Count > 0) { genIdCommand = this.GetGeneratedIdCommand(entity, members, map); // if that's all there is then just return the generated ids if (members.Count == generatedIds.Count) { return genIdCommand; } } // next make command that retrieves the generated members // only consider members that were not generated ids members = members.Except(generatedIds).ToList(); var tableAlias = new TableAlias(); var tex = new TableExpression(tableAlias, entity, this.mapping.GetTableName(table)); Expression where = null; if (generatedIds.Count > 0) { where = generatedIds.Select((m, i) => this.GetMemberExpression(tex, entity, m).Equal(map[m]) ).Aggregate((x, y) => x.And(y)); } else { where = this.GetIdentityCheck(tex, entity, instance); } TableAlias selectAlias = new TableAlias(); var columns = new List<ColumnDeclaration>(); var variables = new List<VariableDeclaration>(); foreach (var mi in members) { ColumnExpression col = (ColumnExpression)this.GetMemberExpression(tex, entity, mi); columns.Add(new ColumnDeclaration(this.mapping.GetColumnName(entity, mi), col, col.QueryType)); ColumnExpression vcol = new ColumnExpression(col.Type, col.QueryType, selectAlias, col.Name); variables.Add(new VariableDeclaration(mi.Name, col.QueryType, vcol)); map.Add(mi, new VariableExpression(mi.Name, col.Type, col.QueryType)); } var genMembersCommand = new DeclarationCommand(variables, new SelectExpression(selectAlias, columns, tex, where)); if (genIdCommand != null) { return new BlockCommand(genIdCommand, genMembersCommand); } return genMembersCommand; }
public override Expression GetInsertExpression(MappingEntity entity, Expression instance, LambdaExpression selector) { var tables = this.mapping.GetTables(entity); if (tables.Count < 2) { return base.GetInsertExpression(entity, instance, selector); } var commands = new List<Expression>(); var map = this.GetDependentGeneratedColumns(entity); var vexMap = new Dictionary<MemberInfo, Expression>(); foreach (var table in this.GetDependencyOrderedTables(entity)) { var tableAlias = new TableAlias(); var tex = new TableExpression(tableAlias, entity, this.mapping.GetTableName(table)); var assignments = this.GetColumnAssignments(tex, instance, entity, (e, m) => this.mapping.GetAlias(e, m) == this.mapping.GetAlias(table) && !this.mapping.IsGenerated(e, m), vexMap ); var totalAssignments = assignments.Concat( this.GetRelatedColumnAssignments(tex, entity, table, vexMap) ); commands.Add(new InsertCommand(tex, totalAssignments)); List<MemberInfo> members; if (map.TryGetValue(this.mapping.GetAlias(table), out members)) { var d = this.GetDependentGeneratedVariableDeclaration(entity, table, members, instance, vexMap); commands.Add(d); } } if (selector != null) { commands.Add(this.GetInsertResult(entity, instance, selector, vexMap)); } return new BlockCommand(commands); }
protected virtual bool CompareAlias(TableAlias a, TableAlias b) { if (this.aliasScope != null) { TableAlias mapped; if (this.aliasScope.TryGetValue(a, out mapped)) return mapped == b; } return a == b; }
public override ProjectionExpression GetQueryExpression(MappingEntity entity) { var tables = this.mapping.GetTables(entity); if (tables.Count <= 1) { return base.GetQueryExpression(entity); } var aliases = new Dictionary<string, TableAlias>(); MappingTable rootTable = tables.Single(ta => !this.mapping.IsExtensionTable(ta)); var tex = new TableExpression(new TableAlias(), entity, this.mapping.GetTableName(rootTable)); aliases.Add(this.mapping.GetAlias(rootTable), tex.Alias); Expression source = tex; foreach (MappingTable table in tables.Where(t => this.mapping.IsExtensionTable(t))) { TableAlias joinedTableAlias = new TableAlias(); string extensionAlias = this.mapping.GetAlias(table); aliases.Add(extensionAlias, joinedTableAlias); List<string> keyColumns = this.mapping.GetExtensionKeyColumnNames(table).ToList(); List<MemberInfo> relatedMembers = this.mapping.GetExtensionRelatedMembers(table).ToList(); string relatedAlias = this.mapping.GetExtensionRelatedAlias(table); TableAlias relatedTableAlias; aliases.TryGetValue(relatedAlias, out relatedTableAlias); TableExpression joinedTex = new TableExpression(joinedTableAlias, entity, this.mapping.GetTableName(table)); Expression cond = null; for (int i = 0, n = keyColumns.Count; i < n; i++) { var memberType = TypeHelper.GetMemberType(relatedMembers[i]); var colType = this.GetColumnType(entity, relatedMembers[i]); var relatedColumn = new ColumnExpression(memberType, colType, relatedTableAlias, this.mapping.GetColumnName(entity, relatedMembers[i])); var joinedColumn = new ColumnExpression(memberType, colType, joinedTableAlias, keyColumns[i]); var eq = joinedColumn.Equal(relatedColumn); cond = (cond != null) ? cond.And(eq) : eq; } source = new JoinExpression(JoinType.SingletonLeftOuter, source, joinedTex, cond); } var columns = new List<ColumnDeclaration>(); this.GetColumns(entity, aliases, columns); SelectExpression root = new SelectExpression(new TableAlias(), columns, source, null); var existingAliases = aliases.Values.ToArray(); Expression projector = this.GetEntityExpression(root, entity); var selectAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.Translator.Linguist.Language, projector, null, selectAlias, root.Alias); var proj = new ProjectionExpression( new SelectExpression(selectAlias, pc.Columns, root, null), pc.Projector ); return (ProjectionExpression)this.Translator.Police.ApplyPolicy(proj, entity.ElementType); }
private ColumnMapper(IEnumerable <TableAlias> oldAliases, TableAlias newAlias) { _oldAliases = new HashSet <TableAlias>(oldAliases); _newAlias = newAlias; }
private void ClearColumnsUsed(TableAlias alias) { this.allColumnsUsed[alias] = new HashSet<string>(); }
protected virtual string GetAliasName(TableAlias alias) { string name; if (!this.aliases.TryGetValue(alias, out name)) { name = "t" + this.aliases.Count; this.aliases.Add(alias, name); } return name; }
/// <summary> /// 创建 UPDATE 命令 /// </summary> /// <param name="dbQuery">查询语义</param> /// <param name="token">解析上下文</param> /// <returns></returns> protected override RawCommand ResolveUpdateCommand <T>(IDbQueryableInfo_Update dbQuery, ResolveToken token) { var context = (SqlServerDbContext)token.DbContext; ISqlBuilder builder = this.CreateSqlBuilder(token); var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); builder.Append("UPDATE t0 SET"); builder.AppendNewLine(); if (dbQuery.Entity != null) { object entity = dbQuery.Entity; ISqlBuilder seg_Where = this.CreateSqlBuilder(token); bool useKey = false; int length = 0; foreach (var m in typeRuntime.Members) { var column = m.Column; if (column != null && column.IsIdentity) { goto gotoLabel; // Fix issue# 自增列同时又是主键 } if (column != null && column.NoMapped) { continue; } if (m.Column != null && column.DbType is SqlDbType && (SqlDbType)column.DbType == SqlDbType.Timestamp) { continue; // 行版本号 } if (m.ForeignKey != null) { continue; } if (m.Member.MemberType == System.Reflection.MemberTypes.Method) { continue; } builder.AppendMember("t0", m.Member.Name); builder.Append(" = "); gotoLabel: var value = m.Invoke(entity); var seg = this.DbValue.GetSqlValueWidthDefault(value, token, column); if (column == null || !column.IsIdentity) { builder.Append(seg); length = builder.Length; builder.Append(','); builder.AppendNewLine(); } if (column != null && column.IsKey) { useKey = true; seg_Where.AppendMember("t0", m.Member.Name); seg_Where.Append(" = "); seg_Where.Append(seg); seg_Where.Append(" AND "); } } if (!useKey) { throw new XFrameworkException("Update<T>(T value) require entity must have key column."); } builder.Length = length; seg_Where.Length -= 5; builder.AppendNewLine(); builder.Append("FROM "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.Append(" t0"); builder.AppendNewLine(); builder.Append("WHERE "); builder.Append(seg_Where); } else if (dbQuery.Expression != null) { TableAlias aliases = this.PrepareTableAlias(dbQuery.Query, token); ExpressionVisitorBase visitor = null; visitor = new UpdateExpressionVisitor(this, aliases, dbQuery.Expression); visitor.Write(builder); builder.AppendNewLine(); builder.Append("FROM "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.AppendAs("t0"); var cmd = new SqlServerMappingCommand(context, aliases, token) { HasMany = dbQuery.Query.HasMany }; visitor = new SqlServerJoinExpressionVisitor(context, aliases, dbQuery.Query.Joins); visitor.Write(cmd.JoinFragment); visitor = new WhereExpressionVisitor(this, aliases, dbQuery.Query.Where); visitor.Write(cmd.WhereFragment); cmd.AddNavMembers(visitor.NavMembers); builder.Append(cmd.CommandText); } return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text)); }
/// <summary> /// 创建 UPDATE 命令 /// </summary> /// <param name="dbQuery">查询语义</param> /// <param name="token">解析上下文</param> /// <returns></returns> protected override RawCommand ResolveUpdateCommand <T>(IDbQueryableInfo_Update dbQuery, ResolveToken token) { ISqlBuilder builder = this.CreateSqlBuilder(token); var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); builder.Append("UPDATE "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.Append(" SET"); builder.AppendNewLine(); if (dbQuery.Entity != null) { object entity = dbQuery.Entity; ISqlBuilder seg_Where = this.CreateSqlBuilder(token); bool useKey = false; int length = 0; foreach (var m in typeRuntime.Members) { var column = m.Column; if (column != null && column.IsIdentity) { goto gotoLabel; // Fix issue# 自增列同时又是主键 } if (column != null && column.NoMapped) { continue; } if (m.Column != null && column.DbType is SqlDbType && (SqlDbType)column.DbType == SqlDbType.Timestamp) { continue; // 行版本号 } if (m.ForeignKey != null) { continue; } if (m.Member.MemberType == System.Reflection.MemberTypes.Method) { continue; } builder.AppendMember(m.Member.Name); builder.Append(" = "); gotoLabel: var value = m.Invoke(entity); var seg = this.DbValue.GetSqlValueWidthDefault(value, token, column); if (column == null || !column.IsIdentity) { builder.Append(seg); length = builder.Length; builder.Append(','); builder.AppendNewLine(); } if (column != null && column.IsKey) { useKey = true; seg_Where.AppendMember(m.Member.Name); seg_Where.Append(" = "); seg_Where.Append(seg); seg_Where.Append(" AND "); } } if (!useKey) { throw new XFrameworkException("Update<T>(T value) require entity must have key column."); } builder.Length = length; seg_Where.Length -= 5; builder.AppendNewLine(); builder.Append("WHERE "); builder.Append(seg_Where); } else if (dbQuery.Expression != null) { // SELECT 表达式 LambdaExpression lambda = dbQuery.Expression as LambdaExpression; var body = lambda.Body; Expression expression = null; if (body.NodeType == ExpressionType.MemberInit) { var memberInit = body as MemberInitExpression; var bindings = new List <MemberBinding>(memberInit.Bindings); foreach (var m in typeRuntime.KeyMembers) { var member = Expression.MakeMemberAccess(lambda.Parameters[0], m.Member); var binding = Expression.Bind(m.Member, member); if (!bindings.Any(x => x.Member == m.Member)) { bindings.Add(binding); } } expression = Expression.MemberInit(memberInit.NewExpression, bindings); } else if (body.NodeType == ExpressionType.New) { var newExpression = body as NewExpression; var bindings = new List <MemberBinding>(); for (int i = 0; i < newExpression.Members.Count; i++) { var m = typeRuntime.GetMember(newExpression.Members[i].Name); var binding = Expression.Bind(m.Member, newExpression.Arguments[i].Type != m.DataType ? Expression.Convert(newExpression.Arguments[i], m.DataType) : newExpression.Arguments[i]); bindings.Add(binding); } foreach (var m in typeRuntime.KeyMembers) { var member = Expression.MakeMemberAccess(lambda.Parameters[0], m.Member); var binding = Expression.Bind(m.Member, member); if (!bindings.Any(x => x.Member == m.Member)) { bindings.Add(binding); } } var newExpression2 = Expression.New(typeRuntime.Constructor.Constructor); expression = Expression.MemberInit(newExpression2, bindings); } // 解析查询以确定是否需要嵌套 dbQuery.Query.Select = new DbExpression(DbExpressionType.Select, expression); var cmd = (MappingCommand)this.ResolveSelectCommand(dbQuery.Query, 1, false, null); if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || dbQuery.Query.Joins.Count > 0) { if (typeRuntime.KeyMembers == null || typeRuntime.KeyMembers.Count == 0) { throw new XFrameworkException("Update<T>(Expression<Func<T, object>> updateExpression) require entity must have key column."); } // SET 字段 var visitor = new SQLiteUpdateExpressionVisitor(this, null, dbQuery, null); visitor.ParseCommand = this.ResolveSelectCommand; visitor.Write(builder); // WHERE部分 builder.AppendNewLine(); builder.Append("WHERE EXISTS"); visitor.VisitArgument(dbQuery.Query.Select.Expressions[0], true); } else { // 直接 SQL 的 UPDATE 语法 TableAlias aliases = this.PrepareTableAlias(dbQuery.Query, token); var visitor = new SQLiteUpdateExpressionVisitor(this, aliases, dbQuery, null); visitor.ParseCommand = this.ResolveSelectCommand; visitor.Write(builder); var visitor2 = new WhereExpressionVisitor(this, null, dbQuery.Query.Where); visitor2.Write(builder); } } builder.Append(';'); return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text)); }
public static Expression Map(Expression expression, TableAlias newAlias, IEnumerable<TableAlias> oldAliases) { return new ColumnMapper(oldAliases, newAlias).Visit(expression); }
private ColumnMapper(IEnumerable<TableAlias> oldAliases, TableAlias newAlias) { this.oldAliases = new HashSet<TableAlias>(oldAliases, TableAlias.Comparer); this.newAlias = newAlias; }
// 创建 SELECT 命令 RawCommand ResolveSelectCommandImpl(IDbQueryableInfo_Select dbQuery, int indent, bool isOuter, ResolveToken token) { // 说明: // 1.OFFSET 前必须要有 'ORDER BY',即 'Skip' 子句前必须使用 'OrderBy' 子句 // 2.在有聚合函数的<MAX,MIN...>情况下,如果有 'Distinct' 'GroupBy' 'Skip' 'Take' 子句,则需要使用嵌套查询 // 3.'Any' 子句将翻译成 IF EXISTS... // 4.分组再分页时需要使用嵌套查询,此时子查询不需要 'OrderBy' 子句,但最外层则需要 // 5.'Skip' 'Take' 子句视为语义结束符,在其之后的子句将使用嵌套查询 // 6.导航属性中有 1:n 关系的,需要使用嵌套查询,否则分页查询会有问题 // 导航属性中有1:n关系,只统计主表 // 例:AccountList = a.Client.AccountList, var subQuery = dbQuery.Subquery as IDbQueryableInfo_Select; if (dbQuery.HasMany && subQuery != null && subQuery.Aggregate != null) { dbQuery = subQuery; } bool useStatis = dbQuery.Aggregate != null; bool useNesting = dbQuery.HasDistinct || dbQuery.GroupBy != null || dbQuery.Skip > 0 || dbQuery.Take > 0; string alias0 = token != null && !string.IsNullOrEmpty(token.AliasPrefix) ? (token.AliasPrefix + "0") : "t0"; // 没有聚合函数或者使用 'Skip' 子句,则解析OrderBy // 导航属性如果使用嵌套,除非有 TOP 或者 OFFSET 子句,否则不能用ORDER BY bool useOrderBy = (!useStatis || dbQuery.Skip > 0) && !dbQuery.HasAny && (!dbQuery.IsParsedByMany || (dbQuery.Skip > 0 || dbQuery.Take > 0)); TableAlias aliases = this.PrepareTableAlias(dbQuery, token); var result = new MappingCommand(this, aliases, token) { HasMany = dbQuery.HasMany }; ISqlBuilder jf = result.JoinFragment; ISqlBuilder wf = result.WhereFragment; jf.Indent = indent; #region 嵌套查询 if (useStatis && useNesting) { // SELECT jf.Append("SELECT "); jf.AppendNewLine(); // SELECT COUNT(1) var visitor_ = new AggregateExpressionVisitor(this, aliases, dbQuery.Aggregate, dbQuery.GroupBy, alias0); visitor_.Write(jf); result.AddNavMembers(visitor_.NavMembers); // SELECT COUNT(1) FROM jf.AppendNewLine(); jf.Append("FROM ( "); indent += 1; jf.Indent = indent; } #endregion #region 择子句 // SELECT 子句 if (jf.Indent > 0) { jf.AppendNewLine(); } jf.Append("SELECT "); if (dbQuery.HasAny) { jf.Append("CASE WHEN COUNT(1) = 1 THEN 1 ELSE 0 END FROM ("); indent += 1; jf.Indent = indent; jf.AppendNewLine(); jf.Append("SELECT 1 "); } if (useStatis && !useNesting) { // 如果有聚合函数,并且不是嵌套的话,则直接使用SELECT <MAX,MIN...>,不需要解析选择的字段 jf.AppendNewLine(); var visitor_ = new AggregateExpressionVisitor(this, aliases, dbQuery.Aggregate, dbQuery.GroupBy); visitor_.Write(jf); result.AddNavMembers(visitor_.NavMembers); } else { // DISTINCT 子句 if (dbQuery.HasDistinct) { jf.Append("DISTINCT "); } #region 择字段 if (!dbQuery.HasAny) { // SELECT 范围 var visitor2 = new SQLiteColumnExpressionVisitor(this, aliases, dbQuery); visitor2.Write(jf); result.PickColumns = visitor2.PickColumns; result.PickColumnText = visitor2.PickColumnText; result.PickNavDescriptors = visitor2.PickNavDescriptors; result.AddNavMembers(visitor2.NavMembers); } #endregion } #endregion #region 顺序解析 // FROM 子句 jf.AppendNewLine(); jf.Append("FROM "); if (dbQuery.Subquery != null) { // 子查询 jf.Append('('); RawCommand cmd = this.ResolveSelectCommandImpl(dbQuery.Subquery, indent + 1, false, token); jf.Append(cmd.CommandText); jf.AppendNewLine(); jf.Append(") "); jf.Append(alias0); jf.Append(' '); } else { var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(dbQuery.FromType); jf.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); jf.Append(' '); jf.Append(alias0); jf.Append(' '); } // LEFT<INNER> JOIN 子句 ExpressionVisitorBase visitor = new JoinExpressionVisitor(this, aliases, dbQuery.Joins); visitor.Write(jf); wf.Indent = jf.Indent; // WHERE 子句 visitor = new WhereExpressionVisitor(this, aliases, dbQuery.Where); visitor.Write(wf); result.AddNavMembers(visitor.NavMembers); // GROUP BY 子句 visitor = new GroupByExpressionVisitor(this, aliases, dbQuery.GroupBy); visitor.Write(wf); result.AddNavMembers(visitor.NavMembers); // HAVING 子句 visitor = new HavingExpressionVisitor(this, aliases, dbQuery.Having, dbQuery.GroupBy); visitor.Write(wf); result.AddNavMembers(visitor.NavMembers); // ORDER 子句 if (dbQuery.OrderBys.Count > 0 && useOrderBy) { visitor = new OrderByExpressionVisitor(this, aliases, dbQuery.OrderBys, dbQuery.GroupBy); visitor.Write(wf); result.AddNavMembers(visitor.NavMembers); } #endregion #region 分页查询 if (dbQuery.Take > 0) { wf.AppendNewLine().AppendFormat("LIMIT {0}", this.DbValue.GetSqlValue(dbQuery.Take, token)); } else if (dbQuery.Take == 0 && dbQuery.Skip > 0) { wf.AppendNewLine().AppendFormat("LIMIT {0}", this.DbValue.GetSqlValue(-1, token)); } if (dbQuery.Skip > 0) { wf.AppendFormat(" OFFSET {0}", this.DbValue.GetSqlValue(dbQuery.Skip, token)); } #endregion #region 嵌套查询 if (useStatis && useNesting) { result.CombineFragments(); indent -= 1; jf.Indent = indent; jf.AppendNewLine(); jf.Append(") "); jf.Append(alias0); } #endregion #region 嵌套导航 // TODO Include 从表,没分页,OrderBy 报错 if (dbQuery.HasMany && subQuery != null && subQuery.OrderBys.Count > 0 && subQuery.Aggregate == null && !(subQuery.Skip > 0 || subQuery.Take > 0)) { result.CombineFragments(); visitor = new OrderByExpressionVisitor(this, aliases, subQuery.OrderBys);//, null, "t0"); visitor.Write(jf); } #endregion #region 并集查询 // UNION 子句 if (dbQuery.Unions != null && dbQuery.Unions.Count > 0) { result.CombineFragments(); for (int index = 0; index < dbQuery.Unions.Count; index++) { jf.AppendNewLine(); jf.Append("UNION ALL"); if (indent == 0) { jf.AppendNewLine(); } RawCommand cmd = this.ResolveSelectCommand(dbQuery.Unions[index], indent, isOuter, token); jf.Append(cmd.CommandText); } } #endregion #region Any 子句 // 'Any' 子句 if (dbQuery.HasAny) { // 产生 WHERE 子句 result.CombineFragments(); // 如果没有分页,则显式指定只查一笔记录 if (dbQuery.Take == 0 && dbQuery.Skip == 0) { jf.AppendNewLine(); jf.Append("LIMIT 1"); } indent -= 1; jf.Indent = indent; jf.AppendNewLine(); jf.Append(") "); jf.Append(alias0); } #endregion return(result); }
internal static Expression Map(Expression expression, TableAlias newAlias, params TableAlias[] oldAliases) { return(new ColumnMapper((IEnumerable <TableAlias>)oldAliases, newAlias).Visit(expression)); }
public void Visit(TableAlias alias) { }
/// <summary> /// 创建 DELETE 命令 /// </summary> /// <param name="dbQuery">查询语义</param> /// <param name="token">解析上下文</param> /// <returns></returns> protected override RawCommand ResolveDeleteCommand <T>(IDbQueryableInfo_Delete dbQuery, ResolveToken token) { ISqlBuilder builder = this.CreateSqlBuilder(token); var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); builder.Append("DELETE FROM "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.Append(" "); if (dbQuery.Entity != null) { if (typeRuntime.KeyMembers == null || typeRuntime.KeyMembers.Count == 0) { throw new XFrameworkException("Delete<T>(T value) require entity must have key column."); } object entity = dbQuery.Entity; builder.AppendNewLine(); builder.Append("WHERE "); foreach (var m in typeRuntime.KeyMembers) { var column = m.Column; var value = m.Invoke(entity); var seg = this.DbValue.GetSqlValue(value, token, column); builder.AppendMember(m.Member.Name); builder.Append(" = "); builder.Append(seg); builder.Append(" AND "); } builder.Length -= 5; } else if (dbQuery.Query != null) { // 解析查询用来确定是否需要嵌套 var cmd = this.ResolveSelectCommand(dbQuery.Query, 1, false, null) as MappingCommand; if (token != null && token.Extendsions == null) { token.Extendsions = new Dictionary <string, object>(); if (!token.Extendsions.ContainsKey("SQLiteDelete")) { token.Extendsions.Add("SQLiteDelete", null); } } if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || dbQuery.Query.Joins.Count > 0) { // 最外层仅选择 RowID 列 var outQuery = dbQuery.Query; outQuery.Select = new DbExpression(DbExpressionType.Select, Expression.Constant("t0.RowId", typeof(string))); var iterator = outQuery; while (iterator.Subquery != null) { var subQuery = new SQLiteDbQueryableInfo_Select(iterator.Subquery); iterator.Subquery = subQuery; iterator = subQuery; } // 解析成 RowId IN 结构 cmd = (MappingCommand)this.ResolveSelectCommand(dbQuery.Query, 1, false, token); builder.Append("WHERE "); builder.AppendMember("RowID"); builder.Append(" IN("); builder.AppendNewLine(cmd.CommandText); builder.Append(')'); } else { TableAlias aliases = this.PrepareTableAlias(dbQuery.Query, token); ExpressionVisitorBase visitor = null; visitor = new JoinExpressionVisitor(this, aliases, dbQuery.Query.Joins); visitor.Write(builder); visitor = new WhereExpressionVisitor(this, null, dbQuery.Query.Where); visitor.Write(builder); } } builder.Append(';'); return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text)); }
public static Expression Map(Expression expression, TableAlias newAlias, params TableAlias[] oldAliases) { return Map(expression, newAlias, (IEnumerable<TableAlias>)oldAliases); }
protected virtual Expression GetUpdateResult(MappingEntity entity, Expression instance, LambdaExpression selector) { var tq = this.GetQueryExpression(entity); Expression where = this.GetIdentityCheck(tq.Select, entity, instance); Expression selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], tq.Projector); TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.translator.Linguist.Language, selection, null, newAlias, tq.Select.Alias); return new ProjectionExpression( new SelectExpression(newAlias, pc.Columns, tq.Select, where), pc.Projector, Aggregator.GetAggregator(selector.Body.Type, typeof(IEnumerable<>).MakeGenericType(selector.Body.Type)) ); }
protected void AddAlias(TableAlias alias) { string name; if (!this.aliases.TryGetValue(alias, out name)) { name = "t" + this.aliases.Count; this.aliases.Add(alias, name); } }
public static Expression Map(Expression expression, TableAlias newAlias, IEnumerable <TableAlias> oldAliases) { return(new ColumnMapper(oldAliases, newAlias).Visit(expression)); }
protected virtual DeclarationCommand GetGeneratedIdCommand(MappingEntity entity, List<MemberInfo> members, Dictionary<MemberInfo, Expression> map) { var columns = new List<ColumnDeclaration>(); var decls = new List<VariableDeclaration>(); var alias = new TableAlias(); foreach (var member in members) { Expression genId = this.translator.Linguist.Language.GetGeneratedIdExpression(member); var name = member.Name; var colType = this.GetColumnType(entity, member); columns.Add(new ColumnDeclaration(member.Name, genId, colType)); decls.Add(new VariableDeclaration(member.Name, colType, new ColumnExpression(genId.Type, colType, alias, member.Name))); if (map != null) { var vex = new VariableExpression(member.Name, TypeHelper.GetMemberType(member), colType); map.Add(member, vex); } } var select = new SelectExpression(alias, columns, null, null); return new DeclarationCommand(decls, select); }
public static Expression Map(Expression expression, TableAlias newAlias, params TableAlias[] oldAliases) { return(Map(expression, newAlias, (IEnumerable <TableAlias>)oldAliases)); }
public override Expression GetInsertExpression(MappingEntity entity, Expression instance, LambdaExpression selector) { var tableAlias = new TableAlias(); var table = new TableExpression(tableAlias, entity, this.mapping.GetTableName(entity)); var assignments = this.GetColumnAssignments(table, instance, entity, (e, m) => !this.mapping.IsGenerated(e, m)); if (selector != null) { return new BlockCommand( new InsertCommand(table, assignments), this.GetInsertResult(entity, instance, selector, null) ); } return new InsertCommand(table, assignments); }
public override Expression GetUpdateExpression(MappingEntity entity, Expression instance, LambdaExpression updateCheck, LambdaExpression selector, Expression @else) { var tableAlias = new TableAlias(); var table = new TableExpression(tableAlias, entity, this.mapping.GetTableName(entity)); var where = this.GetIdentityCheck(table, entity, instance); if (updateCheck != null) { Expression typeProjector = this.GetEntityExpression(table, entity); Expression pred = DbExpressionReplacer.Replace(updateCheck.Body, updateCheck.Parameters[0], typeProjector); where = where.And(pred); } var assignments = this.GetColumnAssignments(table, instance, entity, (e, m) => this.mapping.IsUpdatable(e, m)); Expression update = new UpdateCommand(table, where, assignments); if (selector != null) { return new BlockCommand( update, new IFCommand( this.translator.Linguist.Language.GetRowsAffectedExpression(update).GreaterThan(Expression.Constant(0)), this.GetUpdateResult(entity, instance, selector), @else ) ); } else if (@else != null) { return new BlockCommand( update, new IFCommand( this.translator.Linguist.Language.GetRowsAffectedExpression(update).LessThanOrEqual(Expression.Constant(0)), @else, null ) ); } else { return update; } }
private void ClearColumnsUsed(TableAlias alias) { this.allColumnsUsed[alias] = new HashSet <string>(); }
protected virtual Expression GetInsertResult(MappingEntity entity, Expression instance, LambdaExpression selector, Dictionary<MemberInfo, Expression> map) { var tableAlias = new TableAlias(); var tex = new TableExpression(tableAlias, entity, this.mapping.GetTableName(entity)); var aggregator = Aggregator.GetAggregator(selector.Body.Type, typeof(IEnumerable<>).MakeGenericType(selector.Body.Type)); Expression where; DeclarationCommand genIdCommand = null; var generatedIds = this.mapping.GetMappedMembers(entity).Where(m => this.mapping.IsPrimaryKey(entity, m) && this.mapping.IsGenerated(entity, m)).ToList(); if (generatedIds.Count > 0) { if (map == null || !generatedIds.Any(m => map.ContainsKey(m))) { var localMap = new Dictionary<MemberInfo, Expression>(); genIdCommand = this.GetGeneratedIdCommand(entity, generatedIds.ToList(), localMap); map = localMap; } // is this just a retrieval of one generated id member? var mex = selector.Body as MemberExpression; if (mex != null && this.mapping.IsPrimaryKey(entity, mex.Member) && this.mapping.IsGenerated(entity, mex.Member)) { if (genIdCommand != null) { // just use the select from the genIdCommand return new ProjectionExpression( genIdCommand.Source, new ColumnExpression(mex.Type, genIdCommand.Variables[0].QueryType, genIdCommand.Source.Alias, genIdCommand.Source.Columns[0].Name), aggregator ); } else { TableAlias alias = new TableAlias(); var colType = this.GetColumnType(entity, mex.Member); return new ProjectionExpression( new SelectExpression(alias, new[] { new ColumnDeclaration("", map[mex.Member], colType) }, null, null), new ColumnExpression(TypeHelper.GetMemberType(mex.Member), colType, alias, ""), aggregator ); } } where = generatedIds.Select((m, i) => this.GetMemberExpression(tex, entity, m).Equal(map[m]) ).Aggregate((x, y) => x.And(y)); } else { where = this.GetIdentityCheck(tex, entity, instance); } Expression typeProjector = this.GetEntityExpression(tex, entity); Expression selection = DbExpressionReplacer.Replace(selector.Body, selector.Parameters[0], typeProjector); TableAlias newAlias = new TableAlias(); var pc = ColumnProjector.ProjectColumns(this.translator.Linguist.Language, selection, null, newAlias, tableAlias); var pe = new ProjectionExpression( new SelectExpression(newAlias, pc.Columns, tex, where), pc.Projector, aggregator ); if (genIdCommand != null) { return new BlockCommand(genIdCommand, pe); } return pe; }