public virtual ISqlQueryGenerator CreateRawCommandGenerator( SelectExpression selectExpression, string sql, object[] parameters) => new RawSqlQueryGenerator( _sqlCommandBuilder, Check.NotNull(selectExpression, nameof(selectExpression)), Check.NotNull(sql, nameof(sql)), Check.NotNull(parameters, nameof(parameters)));
protected override void GenerateLimitOffset(SelectExpression selectExpression) { if (selectExpression.Offset != null && !selectExpression.OrderBy.Any()) { Sql.AppendLine().Append("ORDER BY @@ROWCOUNT"); } base.GenerateLimitOffset(selectExpression); }
protected override void GenerateLimitOffset(SelectExpression selectExpression) { if (selectExpression.Projection.OfType<RowNumberExpression>().Any()) { return; } if (selectExpression.Offset != null && !selectExpression.OrderBy.Any()) { Sql.AppendLine().Append("ORDER BY @@ROWCOUNT"); } base.GenerateLimitOffset(selectExpression); }
public RawSqlQueryGenerator( [NotNull] ISqlCommandBuilder sqlCommandBuilder, [NotNull] SelectExpression selectExpression, [NotNull] string sql, [NotNull] object[] parameters) { Check.NotNull(sqlCommandBuilder, nameof(sqlCommandBuilder)); Check.NotNull(selectExpression, nameof(selectExpression)); Check.NotNull(sql, nameof(sql)); Check.NotNull(parameters, nameof(parameters)); _sqlCommandBuilder = sqlCommandBuilder; _selectExpression = selectExpression; _sql = sql; _inputParameters = parameters; }
public RawSqlQueryGenerator( [NotNull] SelectExpression selectExpression, [NotNull] string sql, [NotNull] object[] parameters, [NotNull] IRelationalTypeMapper typeMapper) { Check.NotNull(typeMapper, nameof(typeMapper)); Check.NotNull(selectExpression, nameof(selectExpression)); Check.NotNull(sql, nameof(sql)); Check.NotNull(parameters, nameof(parameters)); _selectExpression = selectExpression; _sql = sql; _inputParameters = parameters; _commandParameters = new List<CommandParameter>(); TypeMapper = typeMapper; }
protected override void GenerateLimitOffset(SelectExpression selectExpression) { Check.NotNull(selectExpression, nameof(selectExpression)); if (selectExpression.Limit != null || selectExpression.Offset != null) { Sql.AppendLine() .Append("LIMIT ") .Append(selectExpression.Limit ?? -1); if (selectExpression.Offset != null) { Sql.Append(" OFFSET ") .Append(selectExpression.Offset); } } }
public RawSqlQueryGenerator( [NotNull] IRelationalCommandBuilderFactory commandBuilderFactory, [NotNull] IParameterNameGeneratorFactory parameterNameGeneratorFactory, [NotNull] SelectExpression selectExpression, [NotNull] string sql, [NotNull] object[] parameters) { Check.NotNull(commandBuilderFactory, nameof(commandBuilderFactory)); Check.NotNull(parameterNameGeneratorFactory, nameof(parameterNameGeneratorFactory)); Check.NotNull(selectExpression, nameof(selectExpression)); Check.NotNull(sql, nameof(sql)); Check.NotNull(parameters, nameof(parameters)); _commandBuilderFactory = commandBuilderFactory; _parameterNameGeneratorFactory = parameterNameGeneratorFactory; _selectExpression = selectExpression; _sql = sql; _inputParameters = parameters; }
public virtual SelectExpression Clone([NotNull] string alias) { Check.NotEmpty(alias, nameof(alias)); var selectExpression = new SelectExpression(_sqlQueryGeneratorFactory, alias) { _limit = _limit, _offset = _offset, _isDistinct = _isDistinct, _subqueryDepth = _subqueryDepth, IsProjectStar = IsProjectStar, Predicate = Predicate }; selectExpression._projection.AddRange(_projection); selectExpression.AddTables(_tables); selectExpression.AddToOrderBy(_orderBy); return selectExpression; }
public bool IsCorrelated(SelectExpression selectExpression) { _selectExpression = selectExpression; Visit(_selectExpression); return _correlated; }
public virtual SelectExpression PushDownSubquery() { _subqueryDepth++; var subquery = new SelectExpression(_sqlQueryGeneratorFactory, SystemAliasPrefix + _subqueryDepth); var columnAliasCounter = 0; foreach (var expression in _projection) { var aliasExpression = expression as AliasExpression; if (aliasExpression != null) { var columnExpression = aliasExpression.TryGetColumnExpression(); if (columnExpression != null && subquery._projection.OfType<AliasExpression>() .Any(ae => ae.TryGetColumnExpression()?.Name == columnExpression.Name)) { aliasExpression.Alias = "c" + columnAliasCounter++; } } else { aliasExpression = new AliasExpression("c" + columnAliasCounter++, expression); } subquery._projection.Add(aliasExpression); } subquery.AddTables(_tables); subquery.AddToOrderBy(_orderBy); subquery.Predicate = Predicate; subquery._limit = _limit; subquery._offset = _offset; subquery._isDistinct = _isDistinct; subquery._subqueryDepth = _subqueryDepth; subquery.IsProjectStar = IsProjectStar || !subquery._projection.Any(); _limit = null; _offset = null; _isDistinct = false; Predicate = null; ClearTables(); ClearProjection(); ClearOrderBy(); AddTable(subquery); return subquery; }
public virtual SelectExpression PushDownSubquery() { _subqueryDepth++; var subquery = new SelectExpression(SystemAliasPrefix + _subqueryDepth); var columnAliasCounter = 0; // TODO: Only AliasExpressions? Don't unique-ify here. foreach (var aliasExpression in _projection.OfType<AliasExpression>()) { var columnExpression = aliasExpression.TryGetColumnExpression(); if (columnExpression != null && subquery._projection.OfType<AliasExpression>().Any(ae => ae.TryGetColumnExpression()?.Name == columnExpression.Name)) { aliasExpression.Alias = "c" + columnAliasCounter++; } subquery._projection.Add(aliasExpression); } subquery.AddTables(_tables); subquery.AddToOrderBy(_orderBy); subquery.Predicate = Predicate; subquery._limit = _limit; subquery._offset = _offset; subquery._isDistinct = _isDistinct; subquery._subqueryDepth = _subqueryDepth; subquery._projectStar = _projectStar || !subquery._projection.Any(); _limit = null; _offset = null; _isDistinct = false; Predicate = null; ClearTables(); ClearProjection(); ClearOrderBy(); _projectStar = true; AddTable(subquery); return subquery; }
public override ISqlQueryGenerator CreateSqlQueryGenerator(SelectExpression selectExpression) => new SqliteQuerySqlGenerator(selectExpression, TypeMapper);
private JoinExpressionBase AdjustJoinExpression(SelectExpression selectExpression, JoinExpressionBase joinExpression) { var subquery = new SelectExpression(_sqlQueryGeneratorFactory, joinExpression.Alias); subquery.AddTable(joinExpression.TableExpression); subquery.IsProjectStar = true; subquery.Predicate = selectExpression.Predicate; var newJoinExpression = joinExpression is LeftOuterJoinExpression ? (JoinExpressionBase)new LeftOuterJoinExpression(subquery) : new InnerJoinExpression(subquery); newJoinExpression.QuerySource = joinExpression.QuerySource; newJoinExpression.Alias = joinExpression.Alias; return newJoinExpression; }
private static void LiftOrderBy( SelectExpression innerJoinSelectExpression, SelectExpression targetSelectExpression, TableExpressionBase innerJoinExpression) { foreach (var ordering in innerJoinSelectExpression.OrderBy) { var orderingExpression = ordering.Expression; var aliasExpression = ordering.Expression as AliasExpression; if (aliasExpression?.Alias != null) { var columnExpression = aliasExpression.TryGetColumnExpression(); if (columnExpression != null) { orderingExpression = new ColumnExpression( aliasExpression.Alias, columnExpression.Property, columnExpression.Table); } } var index = innerJoinSelectExpression.AddToProjection(orderingExpression); var expression = innerJoinSelectExpression.Projection[index]; var newExpression = targetSelectExpression.UpdateColumnExpression(expression, innerJoinExpression); targetSelectExpression.AddToOrderBy(new Ordering(newExpression, ordering.OrderingDirection)); } innerJoinSelectExpression.ClearOrderBy(); }
private IEnumerable<Expression> CreateIncludeRelatedValuesStrategyFactories( IQuerySource querySource, IEnumerable<INavigation> navigationPath) { var selectExpression = _queryCompilationContext.FindSelectExpression(querySource); var targetTableExpression = selectExpression.GetTableForQuerySource(querySource); var canProduceInnerJoin = true; var includeReferenceCount = 0; foreach (var navigation in navigationPath) { var targetEntityType = navigation.GetTargetType(); var targetTableName = _queryCompilationContext.GetTableName(targetEntityType); var targetTableAlias = targetTableName[0].ToString().ToLower(); if (!navigation.IsCollection()) { var joinedTableExpression = new TableExpression( targetTableName, _queryCompilationContext.GetSchema(targetEntityType), targetTableAlias, querySource); var valueBufferOffset = selectExpression.Projection.Count; canProduceInnerJoin = canProduceInnerJoin && (navigation.ForeignKey.IsRequired && navigation.PointsToPrincipal()); var joinExpression = canProduceInnerJoin ? selectExpression .AddInnerJoin(joinedTableExpression) : selectExpression .AddOuterJoin(joinedTableExpression); var materializer = new MaterializerFactory( _queryCompilationContext.EntityMaterializerSource) .CreateMaterializer( targetEntityType, selectExpression, projectionAdder: (p, se) => se.AddToProjection( new AliasExpression( new ColumnExpression( _queryCompilationContext.GetColumnName(p), p, joinedTableExpression))) - valueBufferOffset, querySource: null); joinExpression.Predicate = BuildJoinEqualityExpression( navigation, navigation.PointsToPrincipal() ? targetTableExpression : joinExpression, navigation.PointsToPrincipal() ? joinExpression : targetTableExpression, querySource); targetTableExpression = joinedTableExpression; var readerIndex = _readerIndexes[includeReferenceCount]; includeReferenceCount++; yield return Expression.Lambda( Expression.Call( _queryCompilationContext.QueryMethodProvider .CreateReferenceIncludeRelatedValuesStrategyMethod, Expression.Convert( EntityQueryModelVisitor.QueryContextParameter, typeof(RelationalQueryContext)), Expression.Constant(valueBufferOffset), Expression.Constant(readerIndex), materializer)); } else { var principalTable = selectExpression.Tables.Last(t => t.QuerySource == querySource); foreach (var property in navigation.ForeignKey.PrincipalKey.Properties) { selectExpression .AddToOrderBy( _queryCompilationContext.GetColumnName(property), property, principalTable, OrderingDirection.Asc); } var targetSelectExpression = new SelectExpression(); targetTableExpression = new TableExpression( targetTableName, _queryCompilationContext.GetSchema(targetEntityType), targetTableAlias, querySource); targetSelectExpression.AddTable(targetTableExpression); var materializer = new MaterializerFactory( _queryCompilationContext.EntityMaterializerSource) .CreateMaterializer( targetEntityType, targetSelectExpression, (p, se) => se.AddToProjection( _queryCompilationContext.GetColumnName(p), p, querySource), querySource: null); var innerJoinSelectExpression = selectExpression.Clone( selectExpression.OrderBy .Select(o => o.Expression) .Last(o => o.IsAliasWithColumnExpression()) .TryGetColumnExpression().TableAlias); innerJoinSelectExpression.IsDistinct = true; innerJoinSelectExpression.ClearProjection(); var innerJoinExpression = targetSelectExpression.AddInnerJoin(innerJoinSelectExpression); LiftOrderBy(innerJoinSelectExpression, targetSelectExpression, innerJoinExpression); innerJoinExpression.Predicate = BuildJoinEqualityExpression( navigation, targetTableExpression, innerJoinExpression, querySource); selectExpression = targetSelectExpression; yield return Expression.Lambda( Expression.Call( _queryCompilationContext.QueryMethodProvider .CreateCollectionIncludeRelatedValuesStrategyMethod, Expression.Call( _queryCompilationContext.QueryMethodProvider.QueryMethod, EntityQueryModelVisitor.QueryContextParameter, Expression.Constant( new CommandBuilder( () => _queryCompilationContext.CreateSqlQueryGenerator(targetSelectExpression), _queryCompilationContext.ValueBufferFactoryFactory))), materializer)); } } }
protected override void GenerateTop(SelectExpression selectExpression) { // Handled by GenerateLimitOffset }
public override ISqlQueryGenerator CreateSqlQueryGenerator(SelectExpression selectExpression) => new SqlServerQuerySqlGenerator(Check.NotNull(selectExpression, nameof(selectExpression)), TypeMapper);
public virtual Expression CreateMaterializer( IEntityType entityType, SelectExpression selectExpression, Func<IProperty, SelectExpression, int> projectionAdder, IQuerySource querySource) { Check.NotNull(entityType, nameof(entityType)); Check.NotNull(selectExpression, nameof(selectExpression)); Check.NotNull(projectionAdder, nameof(projectionAdder)); var valueBufferParameter = Expression.Parameter(typeof(ValueBuffer), "valueBuffer"); var concreteEntityTypes = entityType.GetConcreteTypesInHierarchy().ToArray(); var indexMap = new int[concreteEntityTypes[0].GetProperties().Count()]; var propertyIndex = 0; foreach (var property in concreteEntityTypes[0].GetProperties()) { indexMap[propertyIndex++] = projectionAdder(property, selectExpression); } var materializer = _entityMaterializerSource .CreateMaterializeExpression( concreteEntityTypes[0], valueBufferParameter, indexMap); if (concreteEntityTypes.Length == 1 && concreteEntityTypes[0].RootType() == concreteEntityTypes[0]) { return Expression.Lambda<Func<ValueBuffer, object>>(materializer, valueBufferParameter); } var discriminatorProperty = _relationalAnnotationProvider.For(concreteEntityTypes[0]).DiscriminatorProperty; var discriminatorColumn = selectExpression.Projection .OfType<AliasExpression>() .Single(c => c.TryGetColumnExpression()?.Property == discriminatorProperty); var firstDiscriminatorValue = Expression.Constant( _relationalAnnotationProvider.For(concreteEntityTypes[0]).DiscriminatorValue); var discriminatorPredicate = Expression.Equal(discriminatorColumn, firstDiscriminatorValue); if (concreteEntityTypes.Length == 1) { selectExpression.Predicate = new DiscriminatorPredicateExpression(discriminatorPredicate, querySource); return Expression.Lambda<Func<ValueBuffer, object>>(materializer, valueBufferParameter); } var discriminatorValueVariable = Expression.Variable(discriminatorProperty.ClrType); var returnLabelTarget = Expression.Label(typeof(object)); var blockExpressions = new Expression[] { Expression.Assign( discriminatorValueVariable, _entityMaterializerSource .CreateReadValueExpression( valueBufferParameter, discriminatorProperty.ClrType, discriminatorProperty.GetIndex())), Expression.IfThenElse( Expression.Equal(discriminatorValueVariable, firstDiscriminatorValue), Expression.Return(returnLabelTarget, materializer), Expression.Throw( Expression.Call( _createUnableToDiscriminateException, Expression.Constant(concreteEntityTypes[0])))), Expression.Label( returnLabelTarget, Expression.Default(returnLabelTarget.Type)) }; foreach (var concreteEntityType in concreteEntityTypes.Skip(1)) { indexMap = new int[concreteEntityType.GetProperties().Count()]; propertyIndex = 0; foreach (var property in concreteEntityType.GetProperties()) { indexMap[propertyIndex++] = projectionAdder(property, selectExpression); } var discriminatorValue = Expression.Constant( _relationalAnnotationProvider.For(concreteEntityType).DiscriminatorValue); materializer = _entityMaterializerSource .CreateMaterializeExpression(concreteEntityType, valueBufferParameter, indexMap); blockExpressions[1] = Expression.IfThenElse( Expression.Equal(discriminatorValueVariable, discriminatorValue), Expression.Return(returnLabelTarget, materializer), blockExpressions[1]); discriminatorPredicate = Expression.OrElse( Expression.Equal(discriminatorColumn, discriminatorValue), discriminatorPredicate); } selectExpression.Predicate = new DiscriminatorPredicateExpression(discriminatorPredicate, querySource); return Expression.Lambda<Func<ValueBuffer, object>>( Expression.Block(new[] { discriminatorValueVariable }, blockExpressions), valueBufferParameter); }
private Expression VisitSelectExpression(SelectExpression selectExpression) { base.Visit(selectExpression); if (!RequiresRowNumberPaging(selectExpression)) { return selectExpression; } var subQuery = selectExpression.PushDownSubquery(); foreach (var projection in subQuery.Projection) { var alias = projection as AliasExpression; var column = projection as ColumnExpression; if (column != null) { column = new ColumnExpression(column.Name, column.Property, subQuery); selectExpression.AddToProjection(column); continue; } column = alias?.TryGetColumnExpression(); if (column != null) { column = new ColumnExpression(column.Name, column.Property, subQuery); alias = new AliasExpression(alias.Alias, column); selectExpression.AddToProjection(alias); } else { column = new ColumnExpression(alias.Alias, alias.Expression.Type, subQuery); selectExpression.AddToProjection(column); } } if (subQuery.OrderBy.Count == 0) { subQuery.AddToOrderBy( new Ordering(new SqlFunctionExpression("@@RowCount", typeof(int)), OrderingDirection.Asc)); } var columnExpression = new ColumnExpression(RowNumberColumnName, typeof(int), subQuery); var rowNumber = new RowNumberExpression(columnExpression, subQuery.OrderBy); subQuery.ClearOrderBy(); subQuery.AddToProjection(rowNumber, false); Expression predicate = null; var offset = subQuery.Offset ?? 0; if (subQuery.Offset.HasValue) { predicate = Expression.GreaterThan(columnExpression, Expression.Constant(offset)); } if (subQuery.Limit.HasValue) { var exp = Expression.LessThanOrEqual(columnExpression, Expression.Constant(offset + subQuery.Limit.Value)); if (predicate != null) { exp = Expression.AndAlso(predicate, exp); } predicate = exp; } selectExpression.Predicate = predicate; return selectExpression; }
private static bool RequiresRowNumberPaging(SelectExpression selectExpression) => selectExpression.Offset.HasValue && selectExpression.Offset != 0 && !selectExpression.Projection.Any(p => p is RowNumberExpression);
public virtual ISqlQueryGenerator CreateGenerator(SelectExpression selectExpression) => new SqlServerQuerySqlGenerator( _commandBuilderFactory, _sqlGenerator, _parameterNameGeneratorFactory, Check.NotNull(selectExpression, nameof(selectExpression)));