/// <summary> /// Add a Where clause to a query; may need to create a new query. /// </summary> /// <param name="whereClause">Clause to add.</param> /// <param name="context">The translation context.</param> /// <returns>A new query containing the specified Where clause.</returns> public QueryUnderConstruction AddWhereClause(SqlWhereClause whereClause, TranslationContext context) { QueryUnderConstruction result = context.PackageCurrentQueryIfNeccessary(); whereClause = QueryUnderConstruction.CombineWithConjunction(result.whereClause, whereClause); result.whereClause = whereClause; foreach (Binding binding in context.CurrentSubqueryBinding.TakeBindings()) { result.AddBinding(binding); } return(result); }
/// <summary> /// Add a Where clause to a query; may need to create a new query. /// </summary> /// <param name="whereClause">Clause to add.</param> /// <param name="elementType">Type of element in input collection.</param> /// <param name="inScope">Set of parameter names in scope.</param> /// <returns>A new query containing the specified Where clause.</returns> public QueryUnderConstruction AddWhereClause(SqlWhereClause whereClause, Type elementType, HashSet <ParameterExpression> inScope) { QueryUnderConstruction.ValidateNonSubquerySupport(this); QueryUnderConstruction result = this; if (this.selectClause != null) { result = this.PackageQuery(inScope); } whereClause = QueryUnderConstruction.CombineWithConjunction(result.whereClause, whereClause); result.whereClause = whereClause; return(result); }
/// <summary> /// Flatten subqueries into a single query by substituting their expressions in the current query. /// </summary> /// <returns>A flattened query.</returns> public QueryUnderConstruction Flatten() { // SELECT fo(y) FROM y IN (SELECT fi(x) FROM x WHERE gi(x)) WHERE go(y) // is translated by substituting fi(x) for y in the outer query // producing // SELECT fo(fi(x)) FROM x WHERE gi(x) AND (go(fi(x)) if (this.inputQuery == null) { // we are flat already if (this.selectClause == null) { this.selectClause = new SqlSelectClause(new SqlSelectStarSpec(), this.topSpec); } else { this.selectClause = new SqlSelectClause(this.selectClause.SelectSpec, this.topSpec, this.selectClause.HasDistinct); } return(this); } if (this.inputQuery.orderByClause != null && this.orderByClause != null) { throw new DocumentQueryException("Multiple OrderBy is not supported."); } var flatInput = this.inputQuery.Flatten(); var inputSelect = flatInput.selectClause; var inputwhere = flatInput.whereClause; SqlIdentifier replacement = new SqlIdentifier(this.InputParameter().Name); var composedSelect = Substitute(inputSelect, inputSelect.TopSpec ?? this.topSpec, replacement, this.selectClause); var composedWhere = Substitute(inputSelect.SelectSpec, replacement, this.whereClause); var composedOrderBy = Substitute(inputSelect.SelectSpec, replacement, this.orderByClause); var and = QueryUnderConstruction.CombineWithConjunction(inputwhere, composedWhere); QueryUnderConstruction result = new QueryUnderConstruction { selectClause = composedSelect, whereClause = and, inputQuery = null, fromParameters = flatInput.fromParameters, orderByClause = composedOrderBy ?? this.inputQuery.orderByClause, }; return(result); }
/// <summary> /// Add a Where clause to a query; may need to create a new query. /// </summary> /// <param name="whereClause">Clause to add.</param> /// <param name="context">The translation context.</param> /// <returns>A new query containing the specified Where clause.</returns> public QueryUnderConstruction AddWhereClause(SqlWhereClause whereClause, TranslationContext context) { QueryUnderConstruction result = this; if (this.ShouldBeOnNewQuery(LinqMethods.Where, 2)) { result = this.PackageQuery(context.InScope, context.PeekCollection()); context.CurrentSubqueryBinding.ShouldBeOnNewQuery = false; } whereClause = QueryUnderConstruction.CombineWithConjunction(result.whereClause, whereClause); result.whereClause = whereClause; foreach (Binding binding in context.CurrentSubqueryBinding.TakeBindings()) { result.AddBinding(binding); } return(result); }
/// <summary> /// Flatten subqueries into a single query by substituting their expressions in the current query. /// </summary> /// <returns>A flattened query.</returns> private QueryUnderConstruction Flatten() { // SELECT fo(y) FROM y IN (SELECT fi(x) FROM x WHERE gi(x)) WHERE go(y) // is translated by substituting fi(x) for y in the outer query // producing // SELECT fo(fi(x)) FROM x WHERE gi(x) AND (go(fi(x)) if (this.inputQuery == null) { // we are flat already if (this.selectClause == null) { // If selectClause doesn't exists, use SELECT v0 where v0 is the input parameter, instead of SELECT *. string parameterName = this.fromParameters.GetInputParameter().Name; SqlScalarExpression parameterExpression = SqlPropertyRefScalarExpression.Create(null, SqlIdentifier.Create(parameterName)); this.selectClause = SqlSelectClause.Create(SqlSelectValueSpec.Create(parameterExpression)); } else { this.selectClause = SqlSelectClause.Create(this.selectClause.SelectSpec, this.topSpec, this.selectClause.HasDistinct); } return(this); } QueryUnderConstruction flatInput = this.inputQuery.Flatten(); SqlSelectClause inputSelect = flatInput.selectClause; SqlWhereClause inputwhere = flatInput.whereClause; // Determine the paramName to be replaced in the current query // It should be the top input parameter name which is not binded in this collection. // That is because if it has been binded before, it has global scope and should not be replaced. string paramName = null; HashSet <string> inputQueryParams = new HashSet <string>(); foreach (Binding binding in this.inputQuery.fromParameters.GetBindings()) { inputQueryParams.Add(binding.Parameter.Name); } foreach (Binding binding in this.fromParameters.GetBindings()) { if (binding.ParameterDefinition == null || inputQueryParams.Contains(binding.Parameter.Name)) { paramName = binding.Parameter.Name; } } SqlIdentifier replacement = SqlIdentifier.Create(paramName); SqlSelectClause composedSelect = Substitute(inputSelect, inputSelect.TopSpec ?? this.topSpec, replacement, this.selectClause); SqlWhereClause composedWhere = Substitute(inputSelect.SelectSpec, replacement, this.whereClause); SqlOrderbyClause composedOrderBy = Substitute(inputSelect.SelectSpec, replacement, this.orderByClause); SqlWhereClause and = QueryUnderConstruction.CombineWithConjunction(inputwhere, composedWhere); FromParameterBindings fromParams = QueryUnderConstruction.CombineInputParameters(flatInput.fromParameters, this.fromParameters); SqlOffsetSpec offsetSpec; SqlLimitSpec limitSpec; if (flatInput.offsetSpec != null) { offsetSpec = flatInput.offsetSpec; limitSpec = flatInput.limitSpec; } else { offsetSpec = this.offsetSpec; limitSpec = this.limitSpec; } QueryUnderConstruction result = new QueryUnderConstruction(this.aliasCreatorFunc) { selectClause = composedSelect, whereClause = and, inputQuery = null, fromParameters = flatInput.fromParameters, orderByClause = composedOrderBy ?? this.inputQuery.orderByClause, offsetSpec = offsetSpec, limitSpec = limitSpec, alias = new Lazy <ParameterExpression>(() => this.Alias) }; return(result); }