protected override void GenerateLimitOffset(SelectExpression expression) { if (expression.Limit != null) { Sql.AppendLine() .Append("LIMIT ") .Append(expression.Limit); } }
public CommandBuilder( [NotNull] SelectExpression selectExpression, [NotNull] RelationalQueryCompilationContext relationalQueryCompilationContext) { Check.NotNull(selectExpression, "selectExpression"); Check.NotNull(relationalQueryCompilationContext, "relationalQueryCompilationContext"); _selectExpression = selectExpression; _relationalQueryCompilationContext = relationalQueryCompilationContext; }
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 virtual SelectExpression Clone([NotNull] string alias) { Check.NotEmpty(alias, nameof(alias)); var selectExpression = new SelectExpression(alias) { _limit = _limit, _offset = _offset, _isDistinct = _isDistinct, _subqueryDepth = _subqueryDepth, _projectStar = _projectStar, Predicate = Predicate }; selectExpression._projection.AddRange(_projection); selectExpression.AddTables(_tables); selectExpression.AddToOrderBy(_orderBy); return selectExpression; }
private IEnumerable<Expression> CreateIncludeRelatedValuesStrategyFactories( IQuerySource querySource, IEnumerable<INavigation> navigationPath) { var selectExpression = _queryCompilationContext.FindSelectExpression(querySource); var targetTableExpression = selectExpression.FindTableForQuerySource(querySource); var readerIndex = 0; var canProduceInnerJoin = true; 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() ? targetEntityType : navigation.EntityType) .GetPrimaryKey().Properties, navigation.PointsToPrincipal() ? targetTableExpression : joinExpression, navigation.PointsToPrincipal() ? joinExpression : targetTableExpression); targetTableExpression = joinedTableExpression; 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.EntityType.GetPrimaryKey().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(); foreach (var expression in innerJoinSelectExpression.OrderBy .Select(o => o.Expression)) { innerJoinSelectExpression.AddToProjection(expression); } innerJoinSelectExpression.ClearOrderBy(); var primaryKeyProperties = navigation.EntityType.GetPrimaryKey().Properties; var innerJoinExpression = targetSelectExpression.AddInnerJoin(innerJoinSelectExpression); targetSelectExpression.UpdateOrderByColumnBinding(selectExpression.OrderBy, innerJoinExpression); innerJoinExpression.Predicate = BuildJoinEqualityExpression( navigation, primaryKeyProperties, targetTableExpression, innerJoinExpression); selectExpression = targetSelectExpression; readerIndex++; 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)); } } }
private SelectExpression PushDownSubquery() { _subqueryDepth = _subqueryDepth != null ? _subqueryDepth + 1 : 0; var subquery = new SelectExpression("t" + _subqueryDepth); var columnAliasCounter = 0; foreach (var aliasExpression in _projection.OfType<AliasExpression>()) { var columnExpression = ((Expression)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._limit = _limit; subquery._offset = _offset; subquery._isDistinct = _isDistinct; subquery._subqueryDepth = _subqueryDepth; subquery._projectStar = _projectStar; _limit = null; _offset = null; _isDistinct = false; ClearTables(); ClearProjection(); ClearOrderBy(); _projectStar = true; AddTable(subquery); return subquery; }
private void PushDownSubquery() { var subquery = new SelectExpression(); var columnAliasCounter = 0; foreach (var columnExpression in _projection) { if (subquery._projection.FindIndex(ce => ce.Name == columnExpression.Name) != -1) { columnExpression.Alias = "c" + columnAliasCounter++; } subquery._projection.Add(columnExpression); } subquery.AddTables(_tables); subquery.AddToOrderBy(_orderBy); subquery._limit = _limit; subquery._isDistinct = _isDistinct; subquery._subquery = _subquery; subquery._projectStar = _projectStar; _limit = null; _isDistinct = false; ClearTables(); ClearProjection(); ClearOrderBy(); _projectStar = true; _subquery = subquery; }
protected override void GenerateTop(SelectExpression selectExpression) { // Handled by GenerateLimitOffset }
public override ISqlQueryGenerator CreateSqlQueryGenerator(SelectExpression selectExpression) { Check.NotNull(selectExpression, nameof(selectExpression)); return new NpgsqlQueryGenerator(selectExpression); }
private CommandBuilder setupCommandBuilder(DbContext context) { var source = new EntityMaterializerSource(new MemberMapper(new FieldMatcher())); var loggerFactory = new LoggerFactory(); var selectExpression = new SelectExpression(); var queryCompilationContext = new RelationalQueryCompilationContext( context.Model, loggerFactory.CreateLogger("new"), new LinqOperatorProvider(), new RelationalResultOperatorHandler(), source, new EntityKeyFactorySource(new BoxedValueReaderSource()), new AsyncQueryMethodProvider(), new CompositeMethodCallTranslator()); return new CommandBuilder(selectExpression, queryCompilationContext); }
protected override void GenerateTop(SelectExpression expression) { // not supported in SQLite }
public override ISqlQueryGenerator CreateSqlQueryGenerator(SelectExpression selectExpression) => new SqliteQuerySqlGenerator(selectExpression);
protected override Expression VisitEntityQueryable([NotNull] Type elementType) { Check.NotNull(elementType, nameof(elementType)); var queryMethodInfo = RelationalQueryModelVisitor.CreateValueReaderMethodInfo; var entityType = QueryModelVisitor.QueryCompilationContext.Model.GetEntityType(elementType); var selectExpression = new SelectExpression(); var tableName = QueryModelVisitor.QueryCompilationContext.GetTableName(entityType); var alias = _querySource.ItemName.StartsWith("<generated>_") ? tableName.First().ToString().ToLower() : _querySource.ItemName; var fromSqlAnnotation = GetAnnotations<FromSqlAnnotation>(_querySource).SingleOrDefault(); selectExpression.AddTable( (fromSqlAnnotation != null) ? (TableExpressionBase)new RawSqlDerivedTableExpression( fromSqlAnnotation.Sql, fromSqlAnnotation.Parameters, alias, _querySource) : new TableExpression( tableName, QueryModelVisitor.QueryCompilationContext.GetSchema(entityType), alias, _querySource)); QueryModelVisitor.AddQuery(_querySource, selectExpression); var queryMethodArguments = new List<Expression> { Expression.Constant(_querySource), EntityQueryModelVisitor.QueryContextParameter, EntityQueryModelVisitor.QuerySourceScopeParameter, _readerParameter }; if (QueryModelVisitor.QuerySourceRequiresMaterialization(_querySource)) { var materializer = new MaterializerFactory( QueryModelVisitor .QueryCompilationContext .EntityMaterializerSource) .CreateMaterializer( entityType, selectExpression, (p, se) => se.AddToProjection( QueryModelVisitor.QueryCompilationContext.GetColumnName(p), p, _querySource), _querySource); queryMethodInfo = RelationalQueryModelVisitor.CreateEntityMethodInfo .MakeGenericMethod(elementType); var keyProperties = entityType.GetPrimaryKey().Properties; var keyFactory = QueryModelVisitor.QueryCompilationContext.EntityKeyFactorySource .GetKeyFactory(keyProperties); queryMethodArguments.AddRange( new[] { Expression.Constant(0), Expression.Constant(entityType), Expression.Constant(QueryModelVisitor.QuerySourceRequiresTracking(_querySource)), Expression.Constant(keyFactory), Expression.Constant(keyProperties), materializer }); } return Expression.Call( QueryModelVisitor.QueryCompilationContext.QueryMethodProvider.QueryMethod .MakeGenericMethod(queryMethodInfo.ReturnType), EntityQueryModelVisitor.QueryContextParameter, Expression.Constant(new CommandBuilder(selectExpression, QueryModelVisitor.QueryCompilationContext)), Expression.Lambda( Expression.Call(queryMethodInfo, queryMethodArguments), _readerParameter)); }
public override ISqlQueryGenerator CreateSqlQueryGenerator(SelectExpression selectExpression) => new SqlServerQuerySqlGenerator(Check.NotNull(selectExpression, nameof(selectExpression)));
protected override Expression VisitEntityQueryable(Type elementType) { Check.NotNull(elementType, nameof(elementType)); var queryMethodInfo = RelationalQueryModelVisitor.CreateValueBufferMethodInfo; var relationalQueryCompilationContext = QueryModelVisitor.QueryCompilationContext; var entityType = relationalQueryCompilationContext.Model.GetEntityType(elementType); var selectExpression = new SelectExpression(); var tableName = relationalQueryCompilationContext.GetTableName(entityType); var tableAlias = _querySource.HasGeneratedItemName() ? tableName[0].ToString().ToLower() : _querySource.ItemName; var fromSqlAnnotation = relationalQueryCompilationContext.QueryAnnotations .OfType<FromSqlQueryAnnotation>() .SingleOrDefault(a => a.QuerySource == _querySource); selectExpression.AddTable( fromSqlAnnotation != null ? (TableExpressionBase) new RawSqlDerivedTableExpression( fromSqlAnnotation.Sql, fromSqlAnnotation.Parameters, tableAlias, _querySource) : new TableExpression( tableName, relationalQueryCompilationContext.GetSchema(entityType), tableAlias, _querySource)); var composable = true; if (fromSqlAnnotation != null) { var sqlStart = fromSqlAnnotation.Sql.Cast<char>().SkipWhile(char.IsWhiteSpace).Take(7).ToArray(); if (sqlStart.Length != 7 || !char.IsWhiteSpace(sqlStart.Last()) || !new string(sqlStart).StartsWith("SELECT", StringComparison.OrdinalIgnoreCase)) { if (relationalQueryCompilationContext.QueryAnnotations .OfType<IncludeQueryAnnotation>().Any()) { throw new InvalidOperationException(Strings.StoredProcedureIncludeNotSupported); } QueryModelVisitor.RequiresClientEval = true; composable = false; } if (!fromSqlAnnotation.QueryModel.BodyClauses.Any() && !fromSqlAnnotation.QueryModel.ResultOperators.Any()) { composable = false; } } QueryModelVisitor.AddQuery(_querySource, selectExpression); var queryMethodArguments = new List<Expression> { Expression.Constant(_querySource), EntityQueryModelVisitor.QueryContextParameter, EntityQueryModelVisitor.QuerySourceScopeParameter, _valueBufferParameter, Expression.Constant(0) }; if (QueryModelVisitor.QuerySourceRequiresMaterialization(_querySource) || QueryModelVisitor.RequiresClientEval) { var materializer = new MaterializerFactory( relationalQueryCompilationContext .EntityMaterializerSource) .CreateMaterializer( entityType, selectExpression, (p, se) => se.AddToProjection( relationalQueryCompilationContext.GetColumnName(p), p, _querySource), _querySource); queryMethodInfo = RelationalQueryModelVisitor.CreateEntityMethodInfo .MakeGenericMethod(elementType); var keyProperties = entityType.GetPrimaryKey().Properties; var keyFactory = relationalQueryCompilationContext.EntityKeyFactorySource .GetKeyFactory(keyProperties); queryMethodArguments.AddRange( new[] { Expression.Constant(entityType), Expression.Constant(QueryModelVisitor.QuerySourceRequiresTracking(_querySource)), Expression.Constant(keyFactory), Expression.Constant(keyProperties), materializer }); } Func<ISqlQueryGenerator> sqlQueryGeneratorFactory; if (composable) { sqlQueryGeneratorFactory = () => relationalQueryCompilationContext.CreateSqlQueryGenerator(selectExpression); } else { sqlQueryGeneratorFactory = () => new RawSqlQueryGenerator(selectExpression, fromSqlAnnotation.Sql, fromSqlAnnotation.Parameters); } return Expression.Call( relationalQueryCompilationContext.QueryMethodProvider.ShapedQueryMethod .MakeGenericMethod(queryMethodInfo.ReturnType), EntityQueryModelVisitor.QueryContextParameter, Expression.Constant( new CommandBuilder( sqlQueryGeneratorFactory, relationalQueryCompilationContext.ValueBufferFactoryFactory)), Expression.Lambda( Expression.Call(queryMethodInfo, queryMethodArguments), _valueBufferParameter)); }