From 3c866a0b6f23d64f923b5a24015e8d638edcd62c Mon Sep 17 00:00:00 2001 From: go-jet Date: Tue, 28 Dec 2021 17:18:10 +0100 Subject: [PATCH] Add sub-query column alias bubling tests. --- tests/postgres/chinook_db_test.go | 154 ++++++++++++++++++++++++++++++ tests/postgres/with_test.go | 77 +++++++++++++++ 2 files changed, 231 insertions(+) diff --git a/tests/postgres/chinook_db_test.go b/tests/postgres/chinook_db_test.go index 553f920..0e00019 100644 --- a/tests/postgres/chinook_db_test.go +++ b/tests/postgres/chinook_db_test.go @@ -101,6 +101,96 @@ func TestJoinEverything(t *testing.T) { } } + testutils.AssertStatementSql(t, stmt, ` +SELECT "Artist"."ArtistId" AS "Artist.ArtistId", + "Artist"."Name" AS "Artist.Name", + "Album"."AlbumId" AS "Album.AlbumId", + "Album"."Title" AS "Album.Title", + "Album"."ArtistId" AS "Album.ArtistId", + "Track"."TrackId" AS "Track.TrackId", + "Track"."Name" AS "Track.Name", + "Track"."AlbumId" AS "Track.AlbumId", + "Track"."MediaTypeId" AS "Track.MediaTypeId", + "Track"."GenreId" AS "Track.GenreId", + "Track"."Composer" AS "Track.Composer", + "Track"."Milliseconds" AS "Track.Milliseconds", + "Track"."Bytes" AS "Track.Bytes", + "Track"."UnitPrice" AS "Track.UnitPrice", + "Genre"."GenreId" AS "Genre.GenreId", + "Genre"."Name" AS "Genre.Name", + "MediaType"."MediaTypeId" AS "MediaType.MediaTypeId", + "MediaType"."Name" AS "MediaType.Name", + "PlaylistTrack"."PlaylistId" AS "PlaylistTrack.PlaylistId", + "PlaylistTrack"."TrackId" AS "PlaylistTrack.TrackId", + "Playlist"."PlaylistId" AS "Playlist.PlaylistId", + "Playlist"."Name" AS "Playlist.Name", + "Invoice"."InvoiceId" AS "Invoice.InvoiceId", + "Invoice"."CustomerId" AS "Invoice.CustomerId", + "Invoice"."InvoiceDate" AS "Invoice.InvoiceDate", + "Invoice"."BillingAddress" AS "Invoice.BillingAddress", + "Invoice"."BillingCity" AS "Invoice.BillingCity", + "Invoice"."BillingState" AS "Invoice.BillingState", + "Invoice"."BillingCountry" AS "Invoice.BillingCountry", + "Invoice"."BillingPostalCode" AS "Invoice.BillingPostalCode", + "Invoice"."Total" AS "Invoice.Total", + "Customer"."CustomerId" AS "Customer.CustomerId", + "Customer"."FirstName" AS "Customer.FirstName", + "Customer"."LastName" AS "Customer.LastName", + "Customer"."Company" AS "Customer.Company", + "Customer"."Address" AS "Customer.Address", + "Customer"."City" AS "Customer.City", + "Customer"."State" AS "Customer.State", + "Customer"."Country" AS "Customer.Country", + "Customer"."PostalCode" AS "Customer.PostalCode", + "Customer"."Phone" AS "Customer.Phone", + "Customer"."Fax" AS "Customer.Fax", + "Customer"."Email" AS "Customer.Email", + "Customer"."SupportRepId" AS "Customer.SupportRepId", + "Employee"."EmployeeId" AS "Employee.EmployeeId", + "Employee"."LastName" AS "Employee.LastName", + "Employee"."FirstName" AS "Employee.FirstName", + "Employee"."Title" AS "Employee.Title", + "Employee"."ReportsTo" AS "Employee.ReportsTo", + "Employee"."BirthDate" AS "Employee.BirthDate", + "Employee"."HireDate" AS "Employee.HireDate", + "Employee"."Address" AS "Employee.Address", + "Employee"."City" AS "Employee.City", + "Employee"."State" AS "Employee.State", + "Employee"."Country" AS "Employee.Country", + "Employee"."PostalCode" AS "Employee.PostalCode", + "Employee"."Phone" AS "Employee.Phone", + "Employee"."Fax" AS "Employee.Fax", + "Employee"."Email" AS "Employee.Email", + "Manager"."EmployeeId" AS "Manager.EmployeeId", + "Manager"."LastName" AS "Manager.LastName", + "Manager"."FirstName" AS "Manager.FirstName", + "Manager"."Title" AS "Manager.Title", + "Manager"."ReportsTo" AS "Manager.ReportsTo", + "Manager"."BirthDate" AS "Manager.BirthDate", + "Manager"."HireDate" AS "Manager.HireDate", + "Manager"."Address" AS "Manager.Address", + "Manager"."City" AS "Manager.City", + "Manager"."State" AS "Manager.State", + "Manager"."Country" AS "Manager.Country", + "Manager"."PostalCode" AS "Manager.PostalCode", + "Manager"."Phone" AS "Manager.Phone", + "Manager"."Fax" AS "Manager.Fax", + "Manager"."Email" AS "Manager.Email" +FROM chinook."Artist" + LEFT JOIN chinook."Album" ON ("Artist"."ArtistId" = "Album"."ArtistId") + LEFT JOIN chinook."Track" ON ("Track"."AlbumId" = "Album"."AlbumId") + LEFT JOIN chinook."Genre" ON ("Genre"."GenreId" = "Track"."GenreId") + LEFT JOIN chinook."MediaType" ON ("MediaType"."MediaTypeId" = "Track"."MediaTypeId") + LEFT JOIN chinook."PlaylistTrack" ON ("PlaylistTrack"."TrackId" = "Track"."TrackId") + LEFT JOIN chinook."Playlist" ON ("Playlist"."PlaylistId" = "PlaylistTrack"."PlaylistId") + LEFT JOIN chinook."InvoiceLine" ON ("InvoiceLine"."TrackId" = "Track"."TrackId") + LEFT JOIN chinook."Invoice" ON ("Invoice"."InvoiceId" = "InvoiceLine"."InvoiceId") + LEFT JOIN chinook."Customer" ON ("Customer"."CustomerId" = "Invoice"."CustomerId") + LEFT JOIN chinook."Employee" ON ("Employee"."EmployeeId" = "Customer"."SupportRepId") + LEFT JOIN chinook."Employee" AS "Manager" ON ("Manager"."EmployeeId" = "Employee"."ReportsTo") +ORDER BY "Artist"."ArtistId", "Album"."AlbumId", "Track"."TrackId", "Genre"."GenreId", "MediaType"."MediaTypeId", "Playlist"."PlaylistId", "Invoice"."InvoiceId", "Customer"."CustomerId"; +`) + err := stmt.Query(db, &dest) require.NoError(t, err) @@ -109,6 +199,70 @@ func TestJoinEverything(t *testing.T) { requireLogged(t, stmt) } +// default column aliases from sub-CTEs are bubbled up to the main query, +// cte name does not affect default column alias in main query +func TestSubQueryColumnAliasBubbling(t *testing.T) { + subQuery1 := SELECT( + Artist.AllColumns, + String("custom_column_1").AS("custom_column_1"), + ).FROM( + Artist, + ).ORDER_BY( + Artist.ArtistId.ASC(), + ).AsTable("subQuery1") + + subQuery2 := SELECT( + subQuery1.AllColumns(), + String("custom_column_2").AS("custom_column_2"), + ).FROM( + subQuery1, + ).AsTable("subQuery2") + + mainQuery := SELECT( + subQuery2.AllColumns(), + ).FROM( + subQuery2, + ) + + //fmt.Println(mainQuery.Sql()) + + testutils.AssertStatementSql(t, mainQuery, ` +SELECT "subQuery2"."Artist.ArtistId" AS "Artist.ArtistId", + "subQuery2"."Artist.Name" AS "Artist.Name", + "subQuery2".custom_column_1 AS "custom_column_1", + "subQuery2".custom_column_2 AS "custom_column_2" +FROM ( + SELECT "subQuery1"."Artist.ArtistId" AS "Artist.ArtistId", + "subQuery1"."Artist.Name" AS "Artist.Name", + "subQuery1".custom_column_1 AS "custom_column_1", + $1 AS "custom_column_2" + FROM ( + SELECT "Artist"."ArtistId" AS "Artist.ArtistId", + "Artist"."Name" AS "Artist.Name", + $2 AS "custom_column_1" + FROM chinook."Artist" + ORDER BY "Artist"."ArtistId" ASC + ) AS "subQuery1" + ) AS "subQuery2"; +`) + var dest []struct { + model.Artist + CustomColumn1 string + CustomColumn2 string + } + + err := mainQuery.Query(db, &dest) + require.NoError(t, err) + + require.Len(t, dest, 275) + require.Equal(t, dest[0].Artist, model.Artist{ + ArtistId: 1, + Name: testutils.StringPtr("AC/DC"), + }) + require.Equal(t, dest[0].CustomColumn1, "custom_column_1") + require.Equal(t, dest[0].CustomColumn2, "custom_column_2") +} + func TestSelfJoin(t *testing.T) { var dest []struct { model.Employee diff --git a/tests/postgres/with_test.go b/tests/postgres/with_test.go index 5056256..345320b 100644 --- a/tests/postgres/with_test.go +++ b/tests/postgres/with_test.go @@ -221,6 +221,83 @@ FROM log_discontinued; } +// default column aliases from sub-queries are bubbled up to the main query, +// cte name does not affect default column alias in main query +func TestCTEColumnAliasBubbling(t *testing.T) { + cte1 := CTE("cte1") + cte2 := CTE("cte2") + + stmt := WITH( + cte1.AS( + SELECT( + Territories.AllColumns, + String("custom_column_1").AS("custom_column_1"), + ).FROM( + Territories, + ).ORDER_BY( + Territories.TerritoryID.ASC(), + ), + ), + cte2.AS( + SELECT( + cte1.AllColumns(), + String("custom_column_2").AS("custom_column_2"), + ).FROM( + cte1, + ), + ), + )( + SELECT( + cte2.AllColumns(), + ).FROM( + cte2, + ), + ) + + // fmt.Println(stmt.Sql()) + + testutils.AssertStatementSql(t, stmt, ` +WITH cte1 AS ( + SELECT territories.territory_id AS "territories.territory_id", + territories.territory_description AS "territories.territory_description", + territories.region_id AS "territories.region_id", + $1 AS "custom_column_1" + FROM northwind.territories + ORDER BY territories.territory_id ASC +),cte2 AS ( + SELECT cte1."territories.territory_id" AS "territories.territory_id", + cte1."territories.territory_description" AS "territories.territory_description", + cte1."territories.region_id" AS "territories.region_id", + cte1.custom_column_1 AS "custom_column_1", + $2 AS "custom_column_2" + FROM cte1 +) +SELECT cte2."territories.territory_id" AS "territories.territory_id", + cte2."territories.territory_description" AS "territories.territory_description", + cte2."territories.region_id" AS "territories.region_id", + cte2.custom_column_1 AS "custom_column_1", + cte2.custom_column_2 AS "custom_column_2" +FROM cte2; +`) + + var dest []struct { + model.Territories + CustomColumn1 string + CustomColumn2 string + } + + err := stmt.Query(db, &dest) + require.NoError(t, err) + require.Len(t, dest, 53) + require.Equal(t, dest[0].Territories, model.Territories{ + TerritoryID: "01581", + TerritoryDescription: "Westboro", + RegionID: 1, + }) + require.Equal(t, dest[0].CustomColumn1, "custom_column_1") + require.Equal(t, dest[0].CustomColumn2, "custom_column_2") +} + type EmployeeWrap struct { model.Employees