Skip to content

Commit

Permalink
Initial support for CURRENT_TIMESTAMP and CURRENT_USER parameterless …
Browse files Browse the repository at this point in the history
…functions
  • Loading branch information
MarkMpn committed Nov 8, 2021
1 parent bfd8c53 commit e76aa4d
Show file tree
Hide file tree
Showing 38 changed files with 341 additions and 193 deletions.
19 changes: 19 additions & 0 deletions MarkMpn.Sql4Cds.Engine.Tests/ExecutionPlanTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ void IQueryExecutionOptions.RetrievingNextPage()
{
}

Guid IQueryExecutionOptions.UserId => Guid.NewGuid();

[TestMethod]
public void SimpleSelect()
{
Expand Down Expand Up @@ -3077,5 +3079,22 @@ GROUP BY
</entity>
</fetch>");
}

[TestMethod]
public void SystemFunctions()
{
var metadata = new AttributeMetadataCache(_service);
var planBuilder = new ExecutionPlanBuilder(metadata, new StubTableSizeCache(), this);

var query = "SELECT CURRENT_TIMESTAMP, CURRENT_USER, GETDATE(), USER_NAME()";

var plans = planBuilder.Build(query);

Assert.AreEqual(1, plans.Length);

var select = AssertNode<SelectNode>(plans[0]);
var calc = AssertNode<ComputeScalarNode>(select.Source);
var constant = AssertNode<ConstantScanNode>(calc.Source);
}
}
}
2 changes: 2 additions & 0 deletions MarkMpn.Sql4Cds.Engine.Tests/Sql2FetchXmlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ void IQueryExecutionOptions.RetrievingNextPage()
{
}

Guid IQueryExecutionOptions.UserId => Guid.NewGuid();

[TestMethod]
public void SimpleSelect()
{
Expand Down
2 changes: 2 additions & 0 deletions MarkMpn.Sql4Cds.Engine.Tests/StubOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,7 @@ void IQueryExecutionOptions.Progress(double? progress, string message)
void IQueryExecutionOptions.RetrievingNextPage()
{
}

Guid IQueryExecutionOptions.UserId => Guid.NewGuid();
}
}
2 changes: 1 addition & 1 deletion MarkMpn.Sql4Cds.Engine/ExecutionPlan/Aggregate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class Aggregate
/// A compiled version of the <see cref="SqlExpression"/> that takes the row values and parameter values and returns the value to add to the aggregate
/// </summary>
[Browsable(false)]
public Func<Entity, IDictionary<string, object>, object> Expression { get; set; }
public Func<Entity, IDictionary<string, object>, IQueryExecutionOptions, object> Expression { get; set; }

/// <summary>
/// The type of value produced by the aggregate function
Expand Down
4 changes: 2 additions & 2 deletions MarkMpn.Sql4Cds.Engine/ExecutionPlan/AliasNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,9 @@ public override string ToString()
return "Subquery Alias";
}

public override int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IDictionary<string, Type> parameterTypes)
public override int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IQueryExecutionOptions options, IDictionary<string, Type> parameterTypes)
{
return Source.EstimateRowsOut(dataSources, parameterTypes);
return Source.EstimateRowsOut(dataSources, options, parameterTypes);
}

public override IEnumerable<IExecutionPlanNode> GetSources()
Expand Down
4 changes: 2 additions & 2 deletions MarkMpn.Sql4Cds.Engine/ExecutionPlan/AssertNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ public override void AddRequiredColumns(IDictionary<string, DataSource> dataSour
Source.AddRequiredColumns(dataSources, parameterTypes, requiredColumns);
}

public override int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IDictionary<string, Type> parameterTypes)
public override int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IQueryExecutionOptions options, IDictionary<string, Type> parameterTypes)
{
return Source.EstimateRowsOut(dataSources, parameterTypes);
return Source.EstimateRowsOut(dataSources, options, parameterTypes);
}
}
}
6 changes: 3 additions & 3 deletions MarkMpn.Sql4Cds.Engine/ExecutionPlan/BaseDataNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public IEnumerable<Entity> Execute(IDictionary<string, DataSource> dataSources,
/// <param name="parameterTypes">A mapping of parameter names to their related types</param>
/// <param name="tableSize">A cache of the number of records in each table</param>
/// <returns>The number of rows the node is estimated to return</returns>
public abstract int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IDictionary<string, Type> parameterTypes);
public abstract int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IQueryExecutionOptions options, IDictionary<string, Type> parameterTypes);

/// <summary>
/// Returns the number of times the node has been executed
Expand Down Expand Up @@ -270,7 +270,7 @@ private bool TranslateFetchXMLCriteria(IAttributeMetadataCache metadata, IQueryE
}

// If we still couldn't find the column name and value, this isn't a pattern we can support in FetchXML
if (field == null || (literal == null && func == null && variable == null && (field2 == null || !options.ColumnComparisonAvailable) && !expr.IsConstantValueExpression(schema, out literal)))
if (field == null || (literal == null && func == null && variable == null && (field2 == null || !options.ColumnComparisonAvailable) && !expr.IsConstantValueExpression(schema, options, out literal)))
return false;

// Select the correct FetchXML operator
Expand Down Expand Up @@ -371,7 +371,7 @@ private bool TranslateFetchXMLCriteria(IAttributeMetadataCache metadata, IQueryE
}
else if (func != null)
{
if (func.IsConstantValueExpression(schema, out literal))
if (func.IsConstantValueExpression(schema, options, out literal))
values = new[] { literal };
else
throw new NotSupportedQueryFragmentException("Unsupported FetchXML function", func);
Expand Down
6 changes: 3 additions & 3 deletions MarkMpn.Sql4Cds.Engine/ExecutionPlan/ComputeScalarNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ protected override IEnumerable<Entity> ExecuteInternal(IDictionary<string, DataS
foreach (var entity in Source.Execute(dataSources, options, parameterTypes, parameterValues))
{
foreach (var col in columns)
entity[col.Name] = col.Expression(entity, parameterValues);
entity[col.Name] = col.Expression(entity, parameterValues, options);

yield return entity;
}
Expand Down Expand Up @@ -111,9 +111,9 @@ public override void AddRequiredColumns(IDictionary<string, DataSource> dataSour
Source.AddRequiredColumns(dataSources, parameterTypes, requiredColumns);
}

public override int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IDictionary<string, Type> parameterTypes)
public override int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IQueryExecutionOptions options, IDictionary<string, Type> parameterTypes)
{
return Source.EstimateRowsOut(dataSources, parameterTypes);
return Source.EstimateRowsOut(dataSources, options, parameterTypes);
}
}
}
4 changes: 2 additions & 2 deletions MarkMpn.Sql4Cds.Engine/ExecutionPlan/ConcatenateNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ public override void AddRequiredColumns(IDictionary<string, DataSource> dataSour
}
}

public override int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IDictionary<string, Type> parameterTypes)
public override int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IQueryExecutionOptions options, IDictionary<string, Type> parameterTypes)
{
return Sources.Sum(s => s.EstimateRowsOut(dataSources, parameterTypes));
return Sources.Sum(s => s.EstimateRowsOut(dataSources, options, parameterTypes));
}
}

Expand Down
2 changes: 1 addition & 1 deletion MarkMpn.Sql4Cds.Engine/ExecutionPlan/ConstantScanNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public override void AddRequiredColumns(IDictionary<string, DataSource> dataSour
{
}

public override int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IDictionary<string, Type> parameterTypes)
public override int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IQueryExecutionOptions options, IDictionary<string, Type> parameterTypes)
{
return Values.Count;
}
Expand Down
4 changes: 2 additions & 2 deletions MarkMpn.Sql4Cds.Engine/ExecutionPlan/DistinctNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,12 @@ public override void AddRequiredColumns(IDictionary<string, DataSource> dataSour
Source.AddRequiredColumns(dataSources, parameterTypes, requiredColumns);
}

public override int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IDictionary<string, Type> parameterTypes)
public override int EstimateRowsOut(IDictionary<string, DataSource> dataSources, IQueryExecutionOptions options, IDictionary<string, Type> parameterTypes)
{
// TODO: Is there any metadata available that could help give a better estimate for this?
// Maybe get the schema and check if any of the columns included in the DISTINCT list are the
// primary key and if so return the entire count, if some are optionset then there's a known list
var totalCount = Source.EstimateRowsOut(dataSources, parameterTypes);
var totalCount = Source.EstimateRowsOut(dataSources, options, parameterTypes);
return totalCount * 8 / 10;
}
}
Expand Down
Loading

0 comments on commit e76aa4d

Please sign in to comment.