private QueryUnderConstruction PackageQuery(HashSet <ParameterExpression> inScope) { QueryUnderConstruction result = new QueryUnderConstruction(); var inputParam = result.fromParameters.SetInputParameter(typeof(object), ParameterSubstitution.InputParameterName, inScope); inScope.Add(inputParam); result.inputQuery = this; if (this.selectClause == null) { var star = new SqlSelectStarSpec(); this.selectClause = new SqlSelectClause(star, null); } return(result); }
public override void Visit(SqlSelectClause sqlSelectClause) { this.writer.Write("SELECT "); if (sqlSelectClause.HasDistinct) { this.writer.Write("DISTINCT "); } if (sqlSelectClause.TopSpec != null) { sqlSelectClause.TopSpec.Accept(this); this.writer.Write(" "); } sqlSelectClause.SelectSpec.Accept(this); }
public override int Visit(SqlSelectClause sqlSelectClause) { int hashCode = SqlSelectClauseHashCode; if (sqlSelectClause.HasDistinct) { hashCode = CombineHashes(hashCode, SqlSelectClauseDistinctHashCode); } if (sqlSelectClause.TopSpec != null) { hashCode = CombineHashes(hashCode, sqlSelectClause.TopSpec.Accept(this)); } hashCode = CombineHashes(hashCode, sqlSelectClause.SelectSpec.Accept(this)); return(hashCode); }
/// <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); }
public override SqlObject VisitSelect_clause([NotNull] sqlParser.Select_clauseContext context) { SqlSelectSpec sqlSelectSpec = (SqlSelectSpec)this.Visit(context.selection()); SqlTopSpec sqlTopSpec; if (context.top_spec() != default) { sqlTopSpec = (SqlTopSpec)this.Visit(context.top_spec()); } else { sqlTopSpec = default; } bool distinct = context.K_DISTINCT() != default; return(SqlSelectClause.Create(sqlSelectSpec, sqlTopSpec, distinct)); }
/// <summary> /// Add a Select clause to a query; may need to create a new subquery. /// </summary> /// <param name="select">Select clause to add.</param> /// <param name="context">The translation context.</param> /// <returns>A new query containing a select clause.</returns> public QueryUnderConstruction AddSelectClause(SqlSelectClause select, TranslationContext context) { QueryUnderConstruction result = context.PackageCurrentQueryIfNeccessary(); // If result SelectClause is not null, or both result selectClause and select has Distinct // then it is unexpected since the SelectClause will be overwritten. if (!((result.selectClause != null && result.selectClause.HasDistinct && selectClause.HasDistinct) || result.selectClause == null)) { throw new DocumentQueryException("Internal error: attempting to overwrite SELECT clause"); } result.selectClause = select; foreach (Binding binding in context.CurrentSubqueryBinding.TakeBindings()) { result.AddBinding(binding); } return(result); }
private static IEnumerable <CosmosElement> ProjectOnGroupings( IEnumerable <IGrouping <GroupByKey, CosmosElement> > groupings, SqlSelectClause sqlSelectClause) { foreach (IGrouping <GroupByKey, CosmosElement> grouping in groupings) { IEnumerable <CosmosElement> dataSource = grouping; if (AggregateProjectionDector.HasAggregate(sqlSelectClause.SelectSpec)) { // If there is an aggregate then we need to just project out the one document // But we need to transform the query to first evaluate the aggregate on all the documents AggregateProjectionTransformer aggregateProjectionTransformer = new AggregateProjectionTransformer(dataSource); SqlSelectSpec transformedSpec = aggregateProjectionTransformer .TransformAggregatesInProjection(sqlSelectClause.SelectSpec); CosmosElement aggregationResult = transformedSpec.Accept( Projector.Singleton, dataSource.FirstOrDefault()); if (aggregationResult != null) { dataSource = new CosmosElement[] { aggregationResult }; } else { dataSource = Array.Empty <CosmosElement>(); } } else { dataSource = dataSource .Select(element => sqlSelectClause.SelectSpec.Accept( Projector.Singleton, element)) .Where(projection => projection != Undefined); } if (dataSource.Any()) { yield return(dataSource.First()); } } }
/// <summary> /// Add a Select clause to a query; may need to create a new subquery. /// </summary> /// <param name="select">Select clause to add.</param> /// <param name="inputElementType">Type of element in the input collection.</param> /// <param name="outputElementType">Type of element in output collection.</param> /// <param name="inScope">Set of parameter names in scope.</param> /// <returns>A new query containing a select clause.</returns> public QueryUnderConstruction AddSelectClause(SqlSelectClause select, Type inputElementType, Type outputElementType, HashSet <ParameterExpression> inScope) { if (select.HasDistinct) { QueryUnderConstruction.ValidateNonSubquerySupport(this); } QueryUnderConstruction result = this; if (this.selectClause != null) { result = this.PackageQuery(inScope); } if (result.selectClause != null) { throw new DocumentQueryException("Internal error: attempting to overwrite SELECT clause"); } result.selectClause = select; return(result); }
public void SqlSubqueryScalarExpressionTest() { SqlLiteralScalarExpression five = SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(5)); SqlLiteralScalarExpression three = SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(3)); // (SELECT VALUE 5 + 3) SqlSubqueryScalarExpression subqueryScalarExpression = SqlSubqueryScalarExpression.Create( SqlQuery.Create( SqlSelectClause.Create( SqlSelectValueSpec.Create( SqlBinaryScalarExpression.Create( SqlBinaryScalarOperatorKind.Add, five, three))), fromClause: null, whereClause: null, groupByClause: null, orderByClause: null, offsetLimitClause: null)); AssertEvaluation(CosmosNumber64.Create(5 + 3), subqueryScalarExpression); }
private SqlSelectClause Substitute(SqlSelectClause inputSelectClause, SqlTopSpec topSpec, SqlIdentifier inputParam, SqlSelectClause selectClause) { SqlSelectSpec selectSpec = inputSelectClause.SelectSpec; if (selectClause == null) { return(selectSpec != null?SqlSelectClause.Create(selectSpec, topSpec, inputSelectClause.HasDistinct) : null); } if (selectSpec is SqlSelectStarSpec) { return(SqlSelectClause.Create(selectSpec, topSpec, inputSelectClause.HasDistinct)); } SqlSelectValueSpec selValue = selectSpec as SqlSelectValueSpec; if (selValue != null) { SqlSelectSpec intoSpec = selectClause.SelectSpec; if (intoSpec is SqlSelectStarSpec) { return(SqlSelectClause.Create(selectSpec, topSpec, selectClause.HasDistinct || inputSelectClause.HasDistinct)); } SqlSelectValueSpec intoSelValue = intoSpec as SqlSelectValueSpec; if (intoSelValue != null) { SqlScalarExpression replacement = SqlExpressionManipulation.Substitute(selValue.Expression, inputParam, intoSelValue.Expression); SqlSelectValueSpec selValueReplacement = SqlSelectValueSpec.Create(replacement); return(SqlSelectClause.Create(selValueReplacement, topSpec, selectClause.HasDistinct || inputSelectClause.HasDistinct)); } throw new DocumentQueryException("Unexpected SQL select clause type: " + intoSpec.Kind); } throw new DocumentQueryException("Unexpected SQL select clause type: " + selectSpec.Kind); }
private static IEnumerable <CosmosElement> ExecuteSelectClause( IEnumerable <IGrouping <GroupByKey, CosmosElement> > groupings, SqlSelectClause sqlSelectClause) { IEnumerable <CosmosElement> dataSource = ProjectOnGroupings( groupings, sqlSelectClause); if (sqlSelectClause.HasDistinct) { dataSource = dataSource.Distinct(); } if (sqlSelectClause.TopSpec != null) { CosmosNumber cosmosTopValue = (CosmosNumber)sqlSelectClause.TopSpec.TopExpresion.Accept( ScalarExpressionEvaluator.Singleton, input: null); long topCount = Number64.ToLong(cosmosTopValue.Value); dataSource = dataSource.Take((int)topCount); } return(dataSource); }
public override bool Visit(SqlSelectClause first, SqlObject secondAsObject) { if (!(secondAsObject is SqlSelectClause second)) { return(false); } if (first.HasDistinct != second.HasDistinct) { return(false); } if (!Equals(first.SelectSpec, second.SelectSpec)) { return(false); } if (!Equals(first.TopSpec, second.TopSpec)) { return(false); } return(true); }
public override SqlObject VisitSql_query([NotNull] sqlParser.Sql_queryContext context) { Contract.Requires(context != null); SqlSelectClause sqlSelectClause = (SqlSelectClause)this.Visit(context.select_clause()); SqlFromClause sqlFromClause; if (context.from_clause() != null) { sqlFromClause = (SqlFromClause)this.Visit(context.from_clause()); } else { sqlFromClause = default; } SqlWhereClause sqlWhereClause; if (context.where_clause() != null) { sqlWhereClause = (SqlWhereClause)this.Visit(context.where_clause()); } else { sqlWhereClause = default; } SqlOrderByClause sqlOrderByClause; if (context.order_by_clause() != null) { sqlOrderByClause = (SqlOrderByClause)this.Visit(context.order_by_clause()); } else { sqlOrderByClause = default; } SqlGroupByClause sqlGroupByClause; if (context.group_by_clause() != default) { sqlGroupByClause = (SqlGroupByClause)this.Visit(context.group_by_clause()); } else { sqlGroupByClause = default; } SqlOffsetLimitClause sqlOffsetLimitClause; if (context.offset_limit_clause() != default) { sqlOffsetLimitClause = (SqlOffsetLimitClause)this.Visit(context.offset_limit_clause()); } else { sqlOffsetLimitClause = default; } return(SqlQuery.Create( sqlSelectClause, sqlFromClause, sqlWhereClause, sqlGroupByClause, sqlOrderByClause, sqlOffsetLimitClause)); }
/// <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); }
public void AliasedCollectionExpressionTest() { // FROM c SqlAliasedCollectionExpression fromC = SqlAliasedCollectionExpression.Create( SqlInputPathCollection.Create( SqlIdentifier.Create("c"), relativePath: null), alias: null); CosmosObject andersenWrapped = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["c"] = AndersenFamily, ["_rid"] = AndersenFamily["_rid"] }); CosmosObject wakeFieldWrapped = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["c"] = WakefieldFamily, ["_rid"] = WakefieldFamily["_rid"] }); AssertEvaluation(new CosmosElement[] { andersenWrapped, wakeFieldWrapped }, fromC, DataSource); // FROM c.id SqlAliasedCollectionExpression fromCDotId = SqlAliasedCollectionExpression.Create( SqlInputPathCollection.Create( SqlIdentifier.Create("c"), SqlIdentifierPathExpression.Create( null, SqlIdentifier.Create("id"))), alias: null); CosmosObject andersenId = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["id"] = CosmosString.Create("AndersenFamily"), ["_rid"] = AndersenFamily["_rid"] }); CosmosObject wakefieldId = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["id"] = CosmosString.Create("WakefieldFamily"), ["_rid"] = WakefieldFamily["_rid"] }); AssertEvaluation(new CosmosElement[] { andersenId, wakefieldId }, fromCDotId, DataSource); // FROM c.id AS familyId SqlAliasedCollectionExpression fromCDotIdAsFamilyId = SqlAliasedCollectionExpression.Create( SqlInputPathCollection.Create( SqlIdentifier.Create("c"), SqlIdentifierPathExpression.Create( null, SqlIdentifier.Create("id"))), SqlIdentifier.Create("familyId")); CosmosObject andersenIdAsFamilyId = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["familyId"] = CosmosString.Create("AndersenFamily"), ["_rid"] = AndersenFamily["_rid"] }); CosmosObject wakefieldIdAsFamilyId = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["familyId"] = CosmosString.Create("WakefieldFamily"), ["_rid"] = WakefieldFamily["_rid"] }); AssertEvaluation(new CosmosElement[] { andersenIdAsFamilyId, wakefieldIdAsFamilyId }, fromCDotIdAsFamilyId, DataSource); // FROM (SELECT VALUE child["grade"] FROM child IN c.children) grade SqlAliasedCollectionExpression fromSubqueryGrades = SqlAliasedCollectionExpression.Create( SqlSubqueryCollection.Create( SqlQuery.Create( SqlSelectClause.Create( SqlSelectValueSpec.Create( TestUtils.CreatePathExpression("child", "grade"))), SqlFromClause.Create( SqlArrayIteratorCollectionExpression.Create( SqlIdentifier.Create("child"), SqlInputPathCollection.Create( SqlIdentifier.Create("c"), SqlStringPathExpression.Create( null, SqlStringLiteral.Create("children"))))), whereClause: null, groupByClause: null, orderByClause: null, offsetLimitClause: null)), SqlIdentifier.Create("grade")); CosmosObject henrietteWrapped = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["grade"] = CosmosNumber64.Create(5), ["_rid"] = AndersenFamily["_rid"] }); CosmosObject jesseWrapped = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["grade"] = CosmosNumber64.Create(1), ["_rid"] = WakefieldFamily["_rid"] }); CosmosObject lisaWrapped = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["grade"] = CosmosNumber64.Create(8), ["_rid"] = WakefieldFamily["_rid"] }); AssertEvaluation( new CosmosElement[] { henrietteWrapped, jesseWrapped, lisaWrapped }, fromSubqueryGrades, DataSource); }
internal SqlSelectClauseFormatter(FormatterVisitor visitor, SqlSelectClause codeObject) : base(visitor, codeObject, visitor.Context.FormatOptions.PlaceEachReferenceOnNewLineInQueryStatements) { NewLineSeparatedListFormatter = new NewLineSeparatedListFormatter(visitor, codeObject, true); }
public abstract TOutput Visit(SqlSelectClause sqlObject, TArg input);
public virtual void Visiting(SqlSelectClause selectClause) { }
/// <summary> /// Add a Select clause to a query; may need to create a new subquery. /// </summary> /// <param name="select">Select clause to add.</param> /// <param name="context">The translation context.</param> /// <returns>A new query containing a select clause.</returns> public QueryUnderConstruction AddSelectClause(SqlSelectClause select, TranslationContext context) { return(AddSelectClause(select, context.InScope, context.PeekCollection(), context.CurrentSubqueryBinding)); }
public abstract TResult Visit(SqlSelectClause sqlObject);
public void SqlExistsScalarExpressionTest() { CosmosObject tag = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["name"] = CosmosString.Create("asdf") }); CosmosObject tags = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["tags"] = CosmosArray.Create(new List <CosmosElement>() { tag }), ["_rid"] = CosmosString.Create("AYIMAMmFOw8YAAAAAAAAAA==") }); CosmosObject tagsWrapped = CosmosObject.Create(new Dictionary <string, CosmosElement> { ["c"] = tags, ["_rid"] = CosmosString.Create("AYIMAMmFOw8YAAAAAAAAAA==") }); // EXISTS(SELECT VALUE t.name FROM t in c.tags where t.name = "asdf") SqlExistsScalarExpression existsScalarExpressionMatched = SqlExistsScalarExpression.Create( SqlQuery.Create( SqlSelectClause.Create( SqlSelectValueSpec.Create( TestUtils.CreatePathExpression("t", "name"))), SqlFromClause.Create( SqlArrayIteratorCollectionExpression.Create( SqlIdentifier.Create("t"), SqlInputPathCollection.Create( SqlIdentifier.Create("c"), SqlStringPathExpression.Create( null, SqlStringLiteral.Create("tags"))))), SqlWhereClause.Create( SqlBinaryScalarExpression.Create( SqlBinaryScalarOperatorKind.Equal, TestUtils.CreatePathExpression("t", "name"), SqlLiteralScalarExpression.Create(SqlStringLiteral.Create("asdf")))), groupByClause: null, orderByClause: null, offsetLimitClause: null)); AssertEvaluation(CosmosBoolean.Create(true), existsScalarExpressionMatched, tagsWrapped); SqlExistsScalarExpression existsScalarExpressionNotMatched = SqlExistsScalarExpression.Create( SqlQuery.Create( SqlSelectClause.Create( SqlSelectValueSpec.Create( TestUtils.CreatePathExpression("t", "name"))), SqlFromClause.Create( SqlArrayIteratorCollectionExpression.Create( SqlIdentifier.Create("t"), SqlInputPathCollection.Create( SqlIdentifier.Create("c"), SqlStringPathExpression.Create( null, SqlStringLiteral.Create("tags"))))), SqlWhereClause.Create( SqlBinaryScalarExpression.Create( SqlBinaryScalarOperatorKind.NotEqual, TestUtils.CreatePathExpression("t", "name"), SqlLiteralScalarExpression.Create(SqlStringLiteral.Create("asdf")))), groupByClause: null, orderByClause: null, offsetLimitClause: null)); AssertEvaluation(CosmosBoolean.Create(false), existsScalarExpressionNotMatched, tagsWrapped); }
public abstract void Visit(SqlSelectClause sqlObject);
public override void Visit(SqlSelectClause codeObject) { Format(codeObject); }