diff --git a/MarkMpn.Sql4Cds.Engine.Tests/ExecutionPlanTests.cs b/MarkMpn.Sql4Cds.Engine.Tests/ExecutionPlanTests.cs
index a8dfb011..8170aae4 100644
--- a/MarkMpn.Sql4Cds.Engine.Tests/ExecutionPlanTests.cs
+++ b/MarkMpn.Sql4Cds.Engine.Tests/ExecutionPlanTests.cs
@@ -82,6 +82,8 @@ void IQueryExecutionOptions.RetrievingNextPage()
{
}
+ string IQueryExecutionOptions.PrimaryDataSource => "local";
+
Guid IQueryExecutionOptions.UserId => Guid.NewGuid();
[TestMethod]
@@ -2996,7 +2998,7 @@ public void CrossInstanceJoin()
TableSizeCache = new StubTableSizeCache()
}
};
- var planBuilder = new ExecutionPlanBuilder(datasources, "uat", this);
+ var planBuilder = new ExecutionPlanBuilder(datasources, this);
var query = "SELECT uat.name, prod.name FROM uat.dbo.account AS uat INNER JOIN prod.dbo.account AS prod ON uat.accountid = prod.accountid WHERE uat.name <> prod.name AND uat.name LIKE '%test%'";
diff --git a/MarkMpn.Sql4Cds.Engine.Tests/Sql2FetchXmlTests.cs b/MarkMpn.Sql4Cds.Engine.Tests/Sql2FetchXmlTests.cs
index cc97222b..615a0db6 100644
--- a/MarkMpn.Sql4Cds.Engine.Tests/Sql2FetchXmlTests.cs
+++ b/MarkMpn.Sql4Cds.Engine.Tests/Sql2FetchXmlTests.cs
@@ -52,6 +52,8 @@ void IQueryExecutionOptions.RetrievingNextPage()
{
}
+ string IQueryExecutionOptions.PrimaryDataSource => "local";
+
Guid IQueryExecutionOptions.UserId => Guid.NewGuid();
[TestMethod]
diff --git a/MarkMpn.Sql4Cds.Engine.Tests/StubOptions.cs b/MarkMpn.Sql4Cds.Engine.Tests/StubOptions.cs
index aa814f6d..d851cd11 100644
--- a/MarkMpn.Sql4Cds.Engine.Tests/StubOptions.cs
+++ b/MarkMpn.Sql4Cds.Engine.Tests/StubOptions.cs
@@ -64,6 +64,8 @@ void IQueryExecutionOptions.RetrievingNextPage()
{
}
+ string IQueryExecutionOptions.PrimaryDataSource => "local";
+
Guid IQueryExecutionOptions.UserId => Guid.NewGuid();
}
}
diff --git a/MarkMpn.Sql4Cds.Engine/ExecutionPlan/ExpressionExtensions.cs b/MarkMpn.Sql4Cds.Engine/ExecutionPlan/ExpressionExtensions.cs
index 925928c6..c93bfd3a 100644
--- a/MarkMpn.Sql4Cds.Engine/ExecutionPlan/ExpressionExtensions.cs
+++ b/MarkMpn.Sql4Cds.Engine/ExecutionPlan/ExpressionExtensions.cs
@@ -1197,9 +1197,9 @@ private static SqlDateTime GetCurrentTimestamp(IQueryExecutionOptions options)
return new SqlDateTime(DateTime.UtcNow);
}
- private static SqlGuid GetCurrentUser(IQueryExecutionOptions options)
+ private static SqlEntityReference GetCurrentUser(IQueryExecutionOptions options)
{
- return options.UserId;
+ return new SqlEntityReference(options.PrimaryDataSource, "systemuser", options.UserId);
}
///
diff --git a/MarkMpn.Sql4Cds.Engine/ExecutionPlanBuilder.cs b/MarkMpn.Sql4Cds.Engine/ExecutionPlanBuilder.cs
index 5eaa9304..dade75df 100644
--- a/MarkMpn.Sql4Cds.Engine/ExecutionPlanBuilder.cs
+++ b/MarkMpn.Sql4Cds.Engine/ExecutionPlanBuilder.cs
@@ -21,14 +21,13 @@ public class ExecutionPlanBuilder
private int _colNameCounter;
public ExecutionPlanBuilder(IAttributeMetadataCache metadata, ITableSizeCache tableSize, IQueryExecutionOptions options)
- : this(new[] { new DataSource { Name = "local", Metadata = metadata, TableSizeCache = tableSize } }, "local", options)
+ : this(new[] { new DataSource { Name = "local", Metadata = metadata, TableSizeCache = tableSize } }, options)
{
}
- public ExecutionPlanBuilder(IEnumerable dataSources, string primaryDataSource, IQueryExecutionOptions options)
+ public ExecutionPlanBuilder(IEnumerable dataSources, IQueryExecutionOptions options)
{
DataSources = dataSources.ToDictionary(ds => ds.Name, StringComparer.OrdinalIgnoreCase);
- PrimaryDataSource = primaryDataSource;
Options = options;
}
@@ -37,11 +36,6 @@ public ExecutionPlanBuilder(IEnumerable dataSources, string primaryD
///
public IDictionary DataSources { get; }
- ///
- /// The name of the connection that will be used by default
- ///
- public string PrimaryDataSource { get; set; }
-
///
/// Returns or sets a value indicating if SQL will be parsed using quoted identifiers
///
@@ -212,7 +206,7 @@ private ExecuteAsNode ConvertExecuteAsStatement(ExecuteAsStatement impersonate)
{
UserIdSource = "systemuser.systemuserid",
Source = source,
- DataSource = PrimaryDataSource
+ DataSource = Options.PrimaryDataSource
};
}
@@ -220,7 +214,7 @@ private RevertNode ConvertRevertStatement(RevertStatement revert)
{
return new RevertNode
{
- DataSource = PrimaryDataSource
+ DataSource = Options.PrimaryDataSource
};
}
@@ -301,7 +295,7 @@ private IExecutionPlanNode ConvertInsertSelectSource(SelectInsertSource selectSo
private DataSource SelectDataSource(SchemaObjectName schemaObject)
{
- var databaseName = schemaObject.DatabaseIdentifier?.Value ?? PrimaryDataSource;
+ var databaseName = schemaObject.DatabaseIdentifier?.Value ?? Options.PrimaryDataSource;
if (!DataSources.TryGetValue(databaseName, out var dataSource))
throw new NotSupportedQueryFragmentException("Invalid database name", schemaObject) { Suggestion = $"Available database names:\r\n* {String.Join("\r\n*", DataSources.Keys.OrderBy(k => k))}" };
@@ -526,7 +520,7 @@ private DeleteNode ConvertDeleteStatement(DeleteSpecification delete, IList 0)
diff --git a/MarkMpn.Sql4Cds.Engine/ExpressionFunctions.cs b/MarkMpn.Sql4Cds.Engine/ExpressionFunctions.cs
index bb14145d..7396ae77 100644
--- a/MarkMpn.Sql4Cds.Engine/ExpressionFunctions.cs
+++ b/MarkMpn.Sql4Cds.Engine/ExpressionFunctions.cs
@@ -385,9 +385,9 @@ public static SqlInt32 CharIndex(SqlString find, SqlString search, SqlInt32 star
///
/// The options that provide access to the user details
///
- public static SqlGuid User_Name(IQueryExecutionOptions options)
+ public static SqlEntityReference User_Name(IQueryExecutionOptions options)
{
- return options.UserId;
+ return new SqlEntityReference(options.PrimaryDataSource, "systemuser", options.UserId);
}
///
diff --git a/MarkMpn.Sql4Cds.Engine/IQueryExecutionOptions.cs b/MarkMpn.Sql4Cds.Engine/IQueryExecutionOptions.cs
index c67d95c7..1e1086cf 100644
--- a/MarkMpn.Sql4Cds.Engine/IQueryExecutionOptions.cs
+++ b/MarkMpn.Sql4Cds.Engine/IQueryExecutionOptions.cs
@@ -118,6 +118,11 @@ public interface IQueryExecutionOptions
///
void RetrievingNextPage();
+ ///
+ /// Returns the name of the primary data source the query is being executed in
+ ///
+ string PrimaryDataSource { get; }
+
///
/// Returns the unique identifier of the current user
///
diff --git a/MarkMpn.Sql4Cds.Engine/Sql2FetchXml.cs b/MarkMpn.Sql4Cds.Engine/Sql2FetchXml.cs
index 60ce3bfe..b7660815 100644
--- a/MarkMpn.Sql4Cds.Engine/Sql2FetchXml.cs
+++ b/MarkMpn.Sql4Cds.Engine/Sql2FetchXml.cs
@@ -59,6 +59,8 @@ public QueryExecutionOptions(Sql2FetchXml sql2FetchXml)
public bool UseLocalTimeZone => false;
+ public string PrimaryDataSource => "local";
+
public Guid UserId { get; set; }
public List JoinOperatorsAvailable => new List { JoinOperator.Inner, JoinOperator.LeftOuter };
diff --git a/MarkMpn.Sql4Cds/QueryExecutionOptions.cs b/MarkMpn.Sql4Cds/QueryExecutionOptions.cs
index b80b2644..d72b54d9 100644
--- a/MarkMpn.Sql4Cds/QueryExecutionOptions.cs
+++ b/MarkMpn.Sql4Cds/QueryExecutionOptions.cs
@@ -174,6 +174,8 @@ public void RetrievingNextPage()
throw new QueryExecutionException($"Hit maximum retrieval limit. This limit is in place to protect against excessive API requests. Try restricting the data to retrieve with WHERE clauses or eliminating subqueries.\r\nYour limit of {Settings.Instance.MaxRetrievesPerQuery:N0} retrievals per query can be modified in Settings.");
}
+ public string PrimaryDataSource => _con.ConnectionName;
+
public Guid UserId
{
get
diff --git a/MarkMpn.Sql4Cds/SqlQueryControl.cs b/MarkMpn.Sql4Cds/SqlQueryControl.cs
index f9d83d1e..fefcb906 100644
--- a/MarkMpn.Sql4Cds/SqlQueryControl.cs
+++ b/MarkMpn.Sql4Cds/SqlQueryControl.cs
@@ -854,7 +854,7 @@ private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
backgroundWorker.ReportProgress(0, "Executing query...");
var options = new QueryExecutionOptions(_con, DataSources[_con.ConnectionName].Connection, backgroundWorker, this);
- var converter = new ExecutionPlanBuilder(DataSources.Values, _con.ConnectionName, options);
+ var converter = new ExecutionPlanBuilder(DataSources.Values, options);
if (Settings.Instance.UseTSQLEndpoint &&
args.Execute &&