diff --git a/MarkMpn.Sql4Cds.Engine/ExecutionPlan/FetchXmlScan.cs b/MarkMpn.Sql4Cds.Engine/ExecutionPlan/FetchXmlScan.cs index 16bb762c..5f9c21d3 100644 --- a/MarkMpn.Sql4Cds.Engine/ExecutionPlan/FetchXmlScan.cs +++ b/MarkMpn.Sql4Cds.Engine/ExecutionPlan/FetchXmlScan.cs @@ -468,6 +468,9 @@ private void VerifyFilterValueTypes(string entityName, object[] items, DataSourc if (condition.value == null && (condition.Items == null || condition.Items.Length == 0)) continue; + if (condition.IsVariable) + continue; + var conditionEntity = entityName; if (condition.entityname != null) diff --git a/MarkMpn.Sql4Cds.Engine/NodeContext.cs b/MarkMpn.Sql4Cds.Engine/NodeContext.cs index 68b6c98d..01d16b73 100644 --- a/MarkMpn.Sql4Cds.Engine/NodeContext.cs +++ b/MarkMpn.Sql4Cds.Engine/NodeContext.cs @@ -32,6 +32,20 @@ public NodeCompilationContext( DataSources = dataSources; Options = options; ParameterTypes = parameterTypes; + GlobalCalculations = new NestedLoopNode + { + LeftSource = new ComputeScalarNode + { + Source = new ConstantScanNode + { + Values = + { + new Dictionary() + } + } + }, + OuterReferences = new Dictionary() + }; Log = log ?? (msg => { }); } @@ -47,6 +61,7 @@ public NodeCompilationContext( DataSources = parentContext.DataSources; Options = parentContext.Options; ParameterTypes = parameterTypes; + GlobalCalculations = parentContext.GlobalCalculations; Log = parentContext.Log; _parentContext = parentContext; } @@ -71,6 +86,11 @@ public NodeCompilationContext( /// public DataSource PrimaryDataSource => DataSources[Options.PrimaryDataSource]; + /// + /// Returns a which can be used to calculate global values to be injected into other nodes + /// + public NestedLoopNode GlobalCalculations { get; } + /// /// A callback function to log messages /// @@ -87,6 +107,25 @@ public string GetExpressionName() return $"Expr{++_expressionCounter}"; } + + internal void ResetGlobalCalculations() + { + GlobalCalculations.OuterReferences.Clear(); + ((ComputeScalarNode)GlobalCalculations.LeftSource).Columns.Clear(); + } + + internal IDataExecutionPlanNodeInternal InsertGlobalCalculations(IRootExecutionPlanNodeInternal rootNode, IDataExecutionPlanNodeInternal source) + { + if (GlobalCalculations.OuterReferences.Count == 0) + return source; + + var clone = (NestedLoopNode)GlobalCalculations.Clone(); + clone.RightSource = source; + source.Parent = clone; + clone.Parent = rootNode; + + return clone; + } } ///