Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSSQL: AddJoin not using alias, thus its not usable in some cases #1265

Open
florianendrich opened this issue Oct 24, 2024 · 2 comments
Open

Comments

@florianendrich
Copy link

If you join two tables with the same exposed names from e.g. different Schemas, the Initialize stored procedure does not use an alias, so creation fails.

Example

Here is a short example to illustrate the setup:

var setup = new SyncSetup(new string[] { "Sales.Customers", "Sales.Orders", "HR.Orders" });

var plsFilter = new SetupFilter("Customers", "Sales");
plsFilter.AddJoin(Join.Left, "Orders", "Sales").On("Customers", "CustomerID", "Orders", "CustomerID", "Sales", "Sales");
plsFilter.AddJoin(Join.Left, "Orders", "HR").On("Customers", "CustomerID", "Orders", "CustomerID", "Sales", "HR");

plsFilter.AddParameter("OrderLimit", DbType.Int16);
plsFilter.AddWhere("OrderTotal", "Orders", "OrderLimit", "Sales");

This results in SQL similar to the following:

CREATE PROCEDURE [Sales].[Customers_OrderLimitinitialize]
	@sync_min_timestamp bigint = NULL,
	@OrderLimit smallint
AS
BEGIN
;WITH 
  [Customers_tracking] AS (
	SELECT [CT].[CustomerID], 
	CAST([CT].[SYS_CHANGE_CONTEXT] as uniqueidentifier) AS [sync_update_scope_id], 
	[CT].[SYS_CHANGE_VERSION] as [sync_timestamp],
	CASE WHEN [CT].[SYS_CHANGE_OPERATION] = 'D' THEN 1 ELSE 0 END AS [sync_row_is_tombstone]
	FROM CHANGETABLE(CHANGES [Sales].[Customers], @sync_min_timestamp) AS [CT]
	)
SELECT DISTINCT 
	  [base].[CustomerID]
	, [base].[FirstName]
	, [base].[LastName]
	, [base].[Email]
	, [base].[PhoneNumber]
	, [side].[sync_row_is_tombstone] as [sync_row_is_tombstone]
FROM [Sales].[Customers] [base]
LEFT JOIN [Customers_tracking] [side] ON [base].[CustomerID] = [side].[CustomerID]
LEFT JOIN [Orders] ON [base].[CustomerID] = [Orders].[CustomerID]
LEFT JOIN [Orders] ON [base].[CustomerID] = [Orders].[CustomerID]

WHERE (
(
 (
   ([Sales].[Orders].[OrderTotal] = @OrderLimit)
  )
 OR [side].[sync_row_is_tombstone] = 1
)
AND 
	([side].[sync_timestamp] > @sync_min_timestamp OR @sync_min_timestamp IS NULL)
)
UNION
SELECT
	  [side].[CustomerID]
	, [base].[FirstName]
	, [base].[LastName]
	, [base].[Email]
	, [base].[PhoneNumber]
	, [side].[sync_row_is_tombstone] as [sync_row_is_tombstone]
FROM [Sales].[Customers] [base]
RIGHT JOIN [Customers_tracking] [side] ON [base].[CustomerID] = [side].[CustomerID]
WHERE ([side].[sync_timestamp] > @sync_min_timestamp AND [side].[sync_row_is_tombstone] = 1);

END

As you can see, the JOIN selection does not set an alias.

Error Encountered

As MSSQL can not tell which table to join, this results in:
{"The objects \"Orders\" and \"Orders\" in the FROM clause have the same exposed names. Use correlation names to distinguish them."}

Suggested Fix
Allow setting an alias on AddJoin e.g.

var plsFilter = new SetupFilter("Customers", "Sales");
plsFilter.AddJoin(Join.Left, "Orders", "Sales").Alias("SalesOrders").On("Customers", "CustomerID", "Orders", "CustomerID", "Sales", "Sales");
plsFilter.AddJoin(Join.Left, "Orders", "HR").Alias("HROrders").On("Customers", "CustomerID", "Orders", "CustomerID", "Sales", "HR");
@florianendrich
Copy link
Author

Forgot to mention that to have AddJoin from different schemas, its probably necessary to change from QuotedShortName to QuotedFullName in SqlBuilderProcedure.cs CreateFilterCustomJoins.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
@florianendrich and others