/// <summary> /// Takes an expression and replaces all <see cref="QuerySourceReferenceExpression"/> instances, as defined by a given /// <paramref name="querySourceMapping"/>. /// </summary> /// <param name="expression">The expression to be scanned for references.</param> /// <param name="querySourceMapping">The clause mapping to be used for replacing <see cref="QuerySourceReferenceExpression"/> instances.</param> /// <param name="throwOnUnmappedReferences">If <see langword="true"/>, the visitor will throw an exception when /// <see cref="QuerySourceReferenceExpression"/> not mapped in the <paramref name="querySourceMapping"/> is encountered. If <see langword="false"/>, /// the visitor will ignore such expressions.</param> /// <returns>An expression with its <see cref="QuerySourceReferenceExpression"/> instances replaced as defined by the /// <paramref name="querySourceMapping"/>.</returns> public static Expression ReplaceClauseReferences(Expression expression, QuerySourceMapping querySourceMapping, bool throwOnUnmappedReferences) { ArgumentUtility.CheckNotNull("expression", expression); ArgumentUtility.CheckNotNull("querySourceMapping", querySourceMapping); return(new ReferenceReplacingExpressionTreeVisitor(querySourceMapping, throwOnUnmappedReferences).VisitExpression(expression)); }
public PropertyAccessBindingExpressionTreeVisitor( QuerySourceMapping querySourceMapping, EntityQueryModelVisitor queryModelVisitor) : base(querySourceMapping, throwOnUnmappedReferences: false) { _queryModelVisitor = queryModelVisitor; }
protected virtual void FlattenSubQuery( SubQueryExpression subQueryExpression, FromClauseBase fromClause, QueryModel queryModel, int destinationIndex) { ArgumentUtility.CheckNotNull("subQueryExpression", subQueryExpression); ArgumentUtility.CheckNotNull("fromClause", fromClause); ArgumentUtility.CheckNotNull("queryModel", queryModel); CheckFlattenable(subQueryExpression.QueryModel); var innerMainFromClause = subQueryExpression.QueryModel.MainFromClause; CopyFromClauseData(innerMainFromClause, fromClause); var innerSelectorMapping = new QuerySourceMapping(); innerSelectorMapping.AddMapping(fromClause, subQueryExpression.QueryModel.SelectClause.Selector); queryModel.TransformExpressions(ex => ReferenceReplacingExpressionTreeVisitor.ReplaceClauseReferences(ex, innerSelectorMapping, false)); InsertBodyClauses(subQueryExpression.QueryModel.BodyClauses, queryModel, destinationIndex); var innerBodyClauseMapping = new QuerySourceMapping(); innerBodyClauseMapping.AddMapping(innerMainFromClause, new QuerySourceReferenceExpression(fromClause)); queryModel.TransformExpressions(ex => ReferenceReplacingExpressionTreeVisitor.ReplaceClauseReferences(ex, innerBodyClauseMapping, false)); }
public void SetUp() { _mainFromClause = ExpressionHelper.CreateMainFromClause_Int(); _selectClause = ExpressionHelper.CreateSelectClause(); _queryModel = new QueryModel(_mainFromClause, _selectClause); _querySourceMapping = new QuerySourceMapping(); }
private ReferenceReplacingExpressionVisitor(QuerySourceMapping querySourceMapping, bool throwOnUnmappedReferences) { ArgumentUtility.CheckNotNull("querySourceMapping", querySourceMapping); _querySourceMapping = querySourceMapping; _throwOnUnmappedReferences = throwOnUnmappedReferences; }
private void UpdateQuerySourceMapping( QueryModel queryModel, IQuerySource oldQuerySource, Expression newExpression) { var querySourceMapping = new QuerySourceMapping(); querySourceMapping.AddMapping(oldQuerySource, newExpression); queryModel.TransformExpressions( e => ReferenceReplacingExpressionVisitor .ReplaceClauseReferences(e, querySourceMapping, throwOnUnmappedReferences: false)); if (newExpression is QuerySourceReferenceExpression qsre) { var newQuerySource = qsre.ReferencedQuerySource; foreach (var queryAnnotation in _queryCompilationContext.QueryAnnotations.Where(qa => qa.QuerySource == oldQuerySource)) { queryAnnotation.QuerySource = newQuerySource; queryAnnotation.QueryModel = queryModel; if (queryAnnotation is IncludeResultOperator includeAnnotation && includeAnnotation.PathFromQuerySource != null) { includeAnnotation.PathFromQuerySource = ReferenceReplacingExpressionVisitor .ReplaceClauseReferences(includeAnnotation.PathFromQuerySource, querySourceMapping, throwOnUnmappedReferences: false); } } } }
private void UpdateQuerySourceMapping( QueryModel queryModel, IQuerySource oldQuerySource, Expression newExpression) { var querySourceMapping = new QuerySourceMapping(); querySourceMapping.AddMapping(oldQuerySource, newExpression); queryModel.TransformExpressions(e => ReferenceReplacingExpressionVisitor .ReplaceClauseReferences(e, querySourceMapping, throwOnUnmappedReferences: false)); var qsre = newExpression as QuerySourceReferenceExpression; if (qsre != null) { var newQuerySource = qsre.ReferencedQuerySource; foreach (var queryAnnotation in _queryAnnotations.Where(qa => qa.QuerySource == oldQuerySource)) { queryAnnotation.QuerySource = newQuerySource; queryAnnotation.QueryModel = queryModel; } } }
/// <summary> /// Adjusts the given expression for cloning, that is replaces <see cref="QuerySourceReferenceExpression"/> and <see cref="SubQueryExpression"/> /// instances. All referenced clauses must be mapped to clones in the given <paramref name="querySourceMapping"/>, otherwise an exception is thrown. /// </summary> /// <param name="expression">The expression to be adjusted.</param> /// <param name="querySourceMapping">The clause mapping to be used for replacing <see cref="QuerySourceReferenceExpression"/> instances.</param> /// <returns>An expression with all <see cref="QuerySourceReferenceExpression"/> and <see cref="SubQueryExpression"/> instances replaced /// as required by a <see cref="QueryModel.Clone()"/> operation.</returns> public static Expression AdjustExpressionAfterCloning (Expression expression, QuerySourceMapping querySourceMapping) { ArgumentUtility.CheckNotNull ("expression", expression); ArgumentUtility.CheckNotNull ("querySourceMapping", querySourceMapping); return new CloningExpressionTreeVisitor (querySourceMapping, false).VisitExpression (expression); }
public MemberAccessToValueReaderReferenceReplacingExpressionTreeVisitor( QuerySourceMapping querySourceMapping, RelationalQueryModelVisitor queryModelVisitor) : base(querySourceMapping, throwOnUnmappedReferences: false) { _queryModelVisitor = queryModelVisitor; }
protected override Expression VisitQuerySourceReferenceExpression(QuerySourceReferenceExpression expression) { var newExpression = QuerySourceMapping.ContainsMapping(expression.ReferencedQuerySource) ? QuerySourceMapping.GetExpression(expression.ReferencedQuerySource) : base.VisitQuerySourceReferenceExpression(expression); if (_inProjection && newExpression.Type.IsConstructedGenericType) { var genericTypeDefinition = newExpression.Type.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(IOrderedAsyncEnumerable <>)) { newExpression = Expression.Call( _queryModelVisitor.LinqOperatorProvider.ToOrdered .MakeGenericMethod(newExpression.Type.GenericTypeArguments[0]), newExpression); } else if (genericTypeDefinition == typeof(IAsyncEnumerable <>)) { newExpression = Expression.Call( _queryModelVisitor.LinqOperatorProvider.ToEnumerable .MakeGenericMethod(newExpression.Type.GenericTypeArguments[0]), newExpression); } } return(newExpression); }
public IEnumerable <T> ExecuteCollection <T>(QueryModel queryModel) { // Create an expression that returns the current item when invoked Expression currentItemExpression = Expression.Property(Expression.Constant(this), "Current"); // Now replace references like the "i" in "select i" that refers to the "i" in "from i in items" var mapping = new QuerySourceMapping(); mapping.AddMapping(queryModel.MainFromClause, currentItemExpression); queryModel.TransformExpressions(e => ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(e, mapping, true)); // Create a lambda that takes our SampleDataSourceItem and passes it through the select clause // to produce a type of T. (T may be SampleDataSourceItem, in which case this is an identity function). var currentItemProperty = Expression.Parameter(typeof(SampleDataSourceItem)); var projection = Expression.Lambda <Func <SampleDataSourceItem, T> >(queryModel.SelectClause.Selector, currentItemProperty); var projector = projection.Compile(); for (var i = 0; i < 10; i++) { Current = new SampleDataSourceItem { Name = "Name " + i, Description = "This describes the item in position " + i }; yield return(projector(Current)); } }
/// <summary> /// Adjusts the given expression for cloning, that is replaces <see cref="QuerySourceReferenceExpression"/> and <see cref="SubQueryExpression"/> /// instances. All referenced clauses must be mapped to clones in the given <paramref name="querySourceMapping"/>, otherwise an exception is thrown. /// </summary> /// <param name="expression">The expression to be adjusted.</param> /// <param name="querySourceMapping">The clause mapping to be used for replacing <see cref="QuerySourceReferenceExpression"/> instances.</param> /// <returns>An expression with all <see cref="QuerySourceReferenceExpression"/> and <see cref="SubQueryExpression"/> instances replaced /// as required by a <see cref="QueryModel.Clone()"/> operation.</returns> public static Expression AdjustExpressionAfterCloning(Expression expression, QuerySourceMapping querySourceMapping) { ArgumentUtility.CheckNotNull("expression", expression); ArgumentUtility.CheckNotNull("querySourceMapping", querySourceMapping); return(new CloningExpressionTreeVisitor(querySourceMapping, false).VisitExpression(expression)); }
public void SetUp() { _resultOperatorNoDefault = new SingleResultOperator(false); _resultOperatorWithDefault = new SingleResultOperator(true); _querySourceMapping = new QuerySourceMapping(); _cloneContext = new CloneContext(_querySourceMapping); }
/// <summary> /// Creates cloned annotations targeting a new QueryModel. /// </summary> /// <param name="querySourceMapping">A query source mapping.</param> /// <param name="queryModel">A query model.</param> public virtual void CloneAnnotations( [NotNull] QuerySourceMapping querySourceMapping, [NotNull] QueryModel queryModel) { Check.NotNull(querySourceMapping, nameof(querySourceMapping)); Check.NotNull(queryModel, nameof(queryModel)); var clonedAnnotations = new List <IQueryAnnotation>(); // ReSharper disable once LoopCanBeConvertedToQuery foreach (var annotation in QueryAnnotations.OfType <ICloneableQueryAnnotation>()) { if (querySourceMapping.ContainsMapping(annotation.QuerySource) && querySourceMapping.GetExpression(annotation.QuerySource) is QuerySourceReferenceExpression querySourceReferenceExpression) { clonedAnnotations.Add( annotation.Clone( querySourceReferenceExpression.ReferencedQuerySource, queryModel)); } } var newAnnotations = QueryAnnotations.ToList(); newAnnotations.AddRange(clonedAnnotations); QueryAnnotations = newAnnotations; }
/// <summary> /// Takes an expression and replaces all <see cref="QuerySourceReferenceExpression"/> instances, as defined by a given /// <paramref name="querySourceMapping"/>. /// </summary> /// <param name="expression">The expression to be scanned for references.</param> /// <param name="querySourceMapping">The clause mapping to be used for replacing <see cref="QuerySourceReferenceExpression"/> instances.</param> /// <param name="throwOnUnmappedReferences">If <see langword="true"/>, the visitor will throw an exception when /// <see cref="QuerySourceReferenceExpression"/> not mapped in the <paramref name="querySourceMapping"/> is encountered. If <see langword="false"/>, /// the visitor will ignore such expressions.</param> /// <returns>An expression with its <see cref="QuerySourceReferenceExpression"/> instances replaced as defined by the /// <paramref name="querySourceMapping"/>.</returns> public static Expression ReplaceClauseReferences (Expression expression, QuerySourceMapping querySourceMapping, bool throwOnUnmappedReferences) { ArgumentUtility.CheckNotNull ("expression", expression); ArgumentUtility.CheckNotNull ("querySourceMapping", querySourceMapping); return new ReferenceReplacingExpressionVisitor (querySourceMapping, throwOnUnmappedReferences).Visit (expression); }
/// <summary> /// Clones this <see cref="QueryModel"/>, returning a new <see cref="QueryModel"/> equivalent to this instance, but with its clauses being /// clones of this instance's clauses. Any <see cref="QuerySourceReferenceExpression"/> in the cloned clauses that points back to another clause /// in this <see cref="QueryModel"/> (including its subqueries) is adjusted to point to the respective clones in the cloned /// <see cref="QueryModel"/>. Any subquery nested in the <see cref="QueryModel"/> is also cloned. /// </summary> /// <param name="querySourceMapping">The <see cref="QuerySourceMapping"/> defining how to adjust instances of /// <see cref="QuerySourceReferenceExpression"/> in the cloned <see cref="QueryModel"/>. If there is a <see cref="QuerySourceReferenceExpression"/> /// that points out of the <see cref="QueryModel"/> being cloned, specify its replacement via this parameter. At the end of the cloning process, /// this object maps all the clauses in this original <see cref="QueryModel"/> to the clones created in the process. /// </param> public QueryModel Clone(QuerySourceMapping querySourceMapping) { ArgumentUtility.CheckNotNull("querySourceMapping", querySourceMapping); var cloneContext = new CloneContext(querySourceMapping); var queryModelBuilder = new QueryModelBuilder(); queryModelBuilder.AddClause(MainFromClause.Clone(cloneContext)); foreach (var bodyClause in BodyClauses) { queryModelBuilder.AddClause(bodyClause.Clone(cloneContext)); } queryModelBuilder.AddClause(SelectClause.Clone(cloneContext)); foreach (var resultOperator in ResultOperators) { var resultOperatorClone = resultOperator.Clone(cloneContext); queryModelBuilder.AddResultOperator(resultOperatorClone); } var clone = queryModelBuilder.Build(); clone.TransformExpressions(ex => CloningExpressionTreeVisitor.AdjustExpressionAfterCloning(ex, cloneContext.QuerySourceMapping)); clone.ResultTypeOverride = ResultTypeOverride; return(clone); }
public void SetUp() { _oldFromClause = ExpressionHelper.CreateMainFromClause_Int(); _newFromClause = ExpressionHelper.CreateMainFromClause_Int(); _querySourceMapping = new QuerySourceMapping(); _querySourceMapping.AddMapping(_oldFromClause, new QuerySourceReferenceExpression(_newFromClause)); }
public void Clone() { var clonedClauseMapping = new QuerySourceMapping(); var cloneContext = new CloneContext(clonedClauseMapping); var clone = _resultOperator.Clone(cloneContext); Assert.That(clone, Is.InstanceOf(typeof(MaxResultOperator))); }
public void Clone() { var clonedClauseMapping = new QuerySourceMapping(); var cloneContext = new CloneContext(clonedClauseMapping); var clone = _resultOperator.Clone(cloneContext); Assert.That(clone, Is.InstanceOf(typeof(AggregateResultOperator))); Assert.That(((AggregateResultOperator)clone).Func, Is.SameAs(_resultOperator.Func)); }
protected override Expression ReplaceClauseReferences( Expression expression, QuerySourceMapping querySourceMapping) { Check.NotNull(expression, "expression"); Check.NotNull(querySourceMapping, "querySourceMapping"); return(new MemberAccessToValueReaderReferenceReplacingExpressionTreeVisitor(querySourceMapping, this) .VisitExpression(expression)); }
public CosmosMemberAccessBindingExpressionVisitor( QuerySourceMapping querySourceMapping, EntityQueryModelVisitor queryModelVisitor, bool inProjection) { _querySourceMapping = querySourceMapping; _queryModelVisitor = (CosmosQueryModelVisitor)queryModelVisitor; _inProjection = inProjection; }
protected virtual Expression ReplaceClauseReferences( [NotNull] Expression expression, [NotNull] QuerySourceMapping querySourceMapping) { Check.NotNull(expression, "expression"); Check.NotNull(querySourceMapping, "querySourceMapping"); return(ReferenceReplacingExpressionTreeVisitor .ReplaceClauseReferences(expression, querySourceMapping, throwOnUnmappedReferences: false)); }
public void Clone() { var clonedClauseMapping = new QuerySourceMapping(); var cloneContext = new CloneContext(clonedClauseMapping); var clone = _resultOperator.Clone(cloneContext); Assert.That(clone, Is.InstanceOf(typeof(CastResultOperator))); Assert.That(((CastResultOperator)clone).CastItemType, Is.SameAs(_resultOperator.CastItemType)); }
public void Clone() { var clonedClauseMapping = new QuerySourceMapping(); var cloneContext = new CloneContext(clonedClauseMapping); var clone = _resultOperatorWithDefaultValue.Clone(cloneContext); Assert.That(clone, Is.InstanceOf(typeof(DefaultIfEmptyResultOperator))); Assert.That(((DefaultIfEmptyResultOperator)clone).OptionalDefaultValue, Is.SameAs(_resultOperatorWithDefaultValue.OptionalDefaultValue)); }
public void Clone() { var clonedClauseMapping = new QuerySourceMapping(); var cloneContext = new CloneContext(clonedClauseMapping); var clone = _resultOperator.Clone(cloneContext); Assert.That(clone, Is.InstanceOf(typeof(IntersectResultOperator))); Assert.That(((IntersectResultOperator)clone).Source2, Is.SameAs(_source2)); }
public IEnumerable <T> ExecuteCollection <T>(QueryModel queryModel) { var itemHolder = new ItemHolder(); var currentItemExpression = Expression.Property(Expression.Constant(itemHolder), "Current"); var luceneQueryModel = PrepareQuery(queryModel); var mapping = new QuerySourceMapping(); mapping.AddMapping(queryModel.MainFromClause, currentItemExpression); queryModel.TransformExpressions(e => ReferenceReplacingExpressionTreeVisitor.ReplaceClauseReferences(e, mapping, throwOnUnmappedReferences: false)); var projection = GetProjector <T>(queryModel); var projector = projection.Compile(); var searcherHandle = CheckoutSearcher(); using (searcherHandle) { var searcher = searcherHandle.Searcher; var skipResults = luceneQueryModel.SkipResults; var maxResults = Math.Min(luceneQueryModel.MaxResults, searcher.MaxDoc - skipResults); var query = luceneQueryModel.Query; var scoreFunction = luceneQueryModel.GetCustomScoreFunction <TDocument>(); if (scoreFunction != null) { query = new DelegatingCustomScoreQuery <TDocument>(query, ConvertDocumentForCustomBoost, scoreFunction); } var executionContext = new QueryExecutionContext(searcher, query, luceneQueryModel.Filter); PrepareSearchSettings(executionContext); var hits = searcher.Search(executionContext.Query, executionContext.Filter, maxResults + skipResults, luceneQueryModel.Sort); if (luceneQueryModel.Last) { skipResults = hits.ScoreDocs.Length - 1; if (skipResults < 0) { yield break; } } var tracker = luceneQueryModel.DocumentTracker as IRetrievedDocumentTracker <TDocument>; executionContext.Phase = QueryExecutionPhase.ConvertResults; executionContext.Hits = hits; foreach (var p in EnumerateHits(hits, executionContext, searcher, tracker, itemHolder, skipResults, projector)) { yield return(p); } } }
/// <summary> /// This API supports the Entity Framework Core infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> public MemberAccessBindingExpressionVisitor( [NotNull] QuerySourceMapping querySourceMapping, [NotNull] EntityQueryModelVisitor queryModelVisitor, bool inProjection) { _querySourceMapping = querySourceMapping; _queryModelVisitor = queryModelVisitor; _inProjection = inProjection; }
protected override void FlattenSubQuery( [NotNull] SubQueryExpression subQueryExpression, [NotNull] FromClauseBase fromClause, [NotNull] QueryModel queryModel, int destinationIndex) { Check.NotNull(subQueryExpression, nameof(subQueryExpression)); Check.NotNull(fromClause, nameof(fromClause)); Check.NotNull(queryModel, nameof(queryModel)); var subQueryModel = subQueryExpression.QueryModel; VisitQueryModel(subQueryModel); if (subQueryModel.ResultOperators .Any(ro => !(ro is OfTypeResultOperator)) || subQueryModel.BodyClauses.Any(bc => bc is OrderByClause)) { return; } var innerMainFromClause = subQueryExpression.QueryModel.MainFromClause; CopyFromClauseData(innerMainFromClause, fromClause); var innerSelectorMapping = new QuerySourceMapping(); innerSelectorMapping.AddMapping(fromClause, subQueryExpression.QueryModel.SelectClause.Selector); queryModel.TransformExpressions( ex => ReferenceReplacingExpressionTreeVisitor .ReplaceClauseReferences(ex, innerSelectorMapping, false)); InsertBodyClauses(subQueryExpression.QueryModel.BodyClauses, queryModel, destinationIndex); var innerBodyClauseMapping = new QuerySourceMapping(); innerBodyClauseMapping .AddMapping(innerMainFromClause, new QuerySourceReferenceExpression(fromClause)); queryModel.TransformExpressions(ex => ReferenceReplacingExpressionTreeVisitor.ReplaceClauseReferences(ex, innerBodyClauseMapping, false)); foreach (var resultOperator in subQueryModel.ResultOperators.Reverse()) { queryModel.ResultOperators.Insert(0, resultOperator); } foreach (var queryAnnotation in _queryAnnotations .Where(qa => qa.QuerySource == subQueryExpression.QueryModel.MainFromClause)) { queryAnnotation.QuerySource = fromClause; } }
public void Clone_HasCloneForMainFromClause_PassesMapping() { var querySourceMapping = new QuerySourceMapping(); var clone = _queryModel.Clone(querySourceMapping); Assert.That( ((QuerySourceReferenceExpression)querySourceMapping.GetExpression(_queryModel.MainFromClause)).ReferencedQuerySource, Is.SameAs(clone.MainFromClause)); }
public PropertyAccessBindingExpressionTreeVisitor( [NotNull] QuerySourceMapping querySourceMapping, [NotNull] EntityQueryModelVisitor queryModelVisitor) : base( Check.NotNull(querySourceMapping, "querySourceMapping"), throwOnUnmappedReferences: false) { Check.NotNull(queryModelVisitor, "queryModelVisitor"); _queryModelVisitor = queryModelVisitor; }
/// <inheritdoc /> public MongoDbMemberAccessBindingExpressionVisitor( [NotNull] QuerySourceMapping querySourceMapping, [NotNull] MongoDbEntityQueryModelVisitor mongoDbEntityQueryModelVisitor, bool inProjection) : base( Check.NotNull(querySourceMapping, nameof(querySourceMapping)), Check.NotNull(mongoDbEntityQueryModelVisitor, nameof(mongoDbEntityQueryModelVisitor)), inProjection) { _model = mongoDbEntityQueryModelVisitor.QueryCompilationContext.Model; }
public void Clone() { var clonedClauseMapping = new QuerySourceMapping(); var cloneContext = new CloneContext(clonedClauseMapping); var clone = _resultOperator.Clone(cloneContext); Assert.That(clone, Is.InstanceOf(typeof(UnionResultOperator))); Assert.That(((UnionResultOperator)clone).ItemName, Is.EqualTo("itemName")); Assert.That(((UnionResultOperator)clone).Source2, Is.SameAs(_source2)); Assert.That(((UnionResultOperator)clone).ItemType, Is.SameAs(typeof(int))); }
private ReferenceReplacingExpressionVisitor (QuerySourceMapping querySourceMapping, bool throwOnUnmappedReferences) { ArgumentUtility.CheckNotNull ("querySourceMapping", querySourceMapping); _querySourceMapping = querySourceMapping; _throwOnUnmappedReferences = throwOnUnmappedReferences; }
private CloningExpressionVisitor (QuerySourceMapping querySourceMapping) { _querySourceMapping = querySourceMapping; }
private CloningExpressionTreeVisitor (QuerySourceMapping querySourceMapping, bool ignoreUnmappedReferences) : base (querySourceMapping, ignoreUnmappedReferences) { }