public string BuildSqlString() { if (Selects.Count == 0) { throw new InvalidOperationException("A query must have a select part"); } foreach (var qs in Simplifications) { if (qs.CanSimplify(this)) { return(qs.Simplify(this)); } } var countOperator = ResultOperators.FirstOrDefault(it => it is CountResultOperator || it is LongCountResultOperator); if (countOperator != null) { return(BuildCountQuery(countOperator)); } var sb = new StringBuilder(); sb.Append("SELECT "); sb.Append(string.Join(@", " , Selects.Select(it => it.Sql))).AppendLine(); sb.Append(GetFromPart()); sb.Append(GetWherePart()); sb.Append(GetOrderPart()); ProcessResultOperators(sb); return(sb.ToString()); }
/// <summary> /// Gets an <see cref="IStreamedDataInfo"/> object describing the data streaming out of this <see cref="QueryModel"/>. If a query ends with /// the <see cref="SelectClause"/>, this corresponds to <see cref="Clauses.SelectClause.GetOutputDataInfo"/>. If a query has /// <see cref="QueryModel.ResultOperators"/>, the data is further modified by those operators. /// </summary> /// <returns>Gets a <see cref="IStreamedDataInfo"/> object describing the data streaming out of this <see cref="QueryModel"/>.</returns> /// <remarks> /// The data streamed from a <see cref="QueryModel"/> is often of type <see cref="IQueryable{T}"/> instantiated /// with a specific item type, unless the /// query ends with a <see cref="ResultOperatorBase"/>. For example, if the query ends with a <see cref="CountResultOperator"/>, the /// result type will be <see cref="int"/>. /// </remarks> /// <exception cref="InvalidOperationException"> /// The <see cref="ResultTypeOverride"/> is not compatible with the calculated <see cref="IStreamedDataInfo"/> calculated from the <see cref="ResultOperators"/>. /// </exception> public IStreamedDataInfo GetOutputDataInfo() { var outputDataInfo = ResultOperators .Aggregate((IStreamedDataInfo)SelectClause.GetOutputDataInfo(), (current, resultOperator) => resultOperator.GetOutputDataInfo(current)); if (ResultTypeOverride == null) { return(outputDataInfo); } try { return(outputDataInfo.AdjustDataType(ResultTypeOverride)); } catch (Exception ex) { var resultTypeOverride = ResultTypeOverride; ResultTypeOverride = null; throw new InvalidOperationException( string.Format( "The query model's result type cannot be changed to '{0}'. The result type may only be overridden and set to values compatible with the ResultOperators' current data type ('{1}').", resultTypeOverride, outputDataInfo.DataType), ex); } }
/// <summary> /// Gets an <see cref="IStreamedDataInfo"/> object describing the data streaming out of this <see cref="QueryModel"/>. If a query ends with /// the <see cref="SelectClause"/>, this corresponds to <see cref="Clauses.SelectClause.GetOutputDataInfo"/>. If a query has /// <see cref="QueryModel.ResultOperators"/>, the data is further modified by those operators. /// </summary> /// <returns>Gets a <see cref="IStreamedDataInfo"/> object describing the data streaming out of this <see cref="QueryModel"/>.</returns> /// <remarks> /// The data streamed from a <see cref="QueryModel"/> is often of type <see cref="IQueryable{T}"/> instantiated /// with a specific item type, unless the /// query ends with a <see cref="ResultOperatorBase"/>. For example, if the query ends with a <see cref="CountResultOperator"/>, the /// result type will be <see cref="int"/>. /// </remarks> public IStreamedDataInfo GetOutputDataInfo() { var outputDataInfo = ResultOperators .Aggregate((IStreamedDataInfo)SelectClause.GetOutputDataInfo(), (current, resultOperator) => resultOperator.GetOutputDataInfo(current)); if (ResultTypeOverride != null) { return(outputDataInfo.AdjustDataType(ResultTypeOverride)); } else { return(outputDataInfo); } }
public string BuildSqlString(bool canUseOperators) { if (MainFrom == null) { throw new ApplicationException("From !?"); } foreach (var qs in Simplifications) { if (qs.CanSimplify(this)) { return(qs.Simplify(this)); } } var sb = new StringBuilder(); sb.Append("SELECT "); var groupOperator = ResultOperators.FirstOrDefault(it => it is GroupResultOperator) as GroupResultOperator; if (groupOperator != null) { if (Selects.Count != 1) { throw new FrameworkException("Select count can only be two when grouping!"); } //TODO fix later... collect sb.AppendFormat( "{0} AS \"Key\", ARRAY_AGG(\"{1}\") AS \"Values\"", GetSqlExpression(groupOperator.KeySelector), Selects[0].QuerySource.ItemName); } else { if (canUseOperators) { var countOperator = ResultOperators.FirstOrDefault(it => it is CountResultOperator || it is LongCountResultOperator); if (countOperator != null) { return(BuildCountQuery(countOperator)); } if (ResultOperators.Any(it => it is AnyResultOperator)) { return(BuildAnyQuery()); } var sumOperator = ResultOperators.FirstOrDefault(it => it is SumResultOperator); if (sumOperator != null) { if (Selects.Count > 1) { //TOOD hack to fix problem with select Selects.Clear(); Selects.Add(new SelectSource { Sql = GetSqlExpression(Selector), ItemType = Selector.Type }); } sb.AppendFormat("COALESCE(SUM({0}), 0)", Selects[0].Sql); //TODO use actual type if (Selects[0].ItemType == typeof(int) || Selects[0].ItemType == typeof(int?)) { sb.Append("::int"); } if (Selects[0].Name != null) { sb.AppendFormat(" AS \"{0}\"", Selects[0].Name); } sb.AppendLine(); sb.Append(GetFromPart()); sb.Append(GetWherePart()); return(sb.ToString()); } var containsOperator = ResultOperators.FirstOrDefault(it => it is ContainsResultOperator); if (containsOperator != null) { if (Selects.Count > 1) { //TOOD hack to fix problem with select Selects.Clear(); Selects.Add(new SelectSource { Sql = GetSqlExpression(Selector) }); } } } sb.Append(string.Join(@", ", Selects.Where(it => it.Sql != null).Select(it => it.Sql))); } sb.AppendLine(); sb.Append(GetFromPart()); sb.Append(GetWherePart()); sb.Append(GetOrderPart()); ProcessResultOperators(sb); return(sb.ToString()); }