Add support for SELECT_JSON statements.

This commit is contained in:
go-jet 2025-02-21 19:55:01 +01:00
parent 7047de44a9
commit 7b16e432ff
46 changed files with 2732 additions and 307 deletions

View file

@ -35,6 +35,58 @@ func TestAllTypesSelect(t *testing.T) {
testutils.AssertDeepEqual(t, dest[1], allTypesRow1)
}
func TestAllTypesSelectJson(t *testing.T) {
stmt := SELECT_JSON_ARR(
AllTypesAllColumns.Except(
AllTypes.JSON, AllTypes.JSONPtr,
AllTypes.Jsonb, AllTypes.JsonbPtr,
AllTypes.TextArray, AllTypes.TextArrayPtr,
AllTypes.JsonbArray, AllTypes.IntegerArray, AllTypes.IntegerArrayPtr,
AllTypes.TextMultiDimArray, AllTypes.TextMultiDimArrayPtr,
),
CAST(AllTypes.JSONPtr).AS_TEXT().AS("jsonPtr"),
CAST(AllTypes.JSON).AS_TEXT().AS("JSON"),
CAST(AllTypes.JsonbPtr).AS_TEXT().AS("jsonbPtr"),
CAST(AllTypes.Jsonb).AS_TEXT().AS("Jsonb"),
CAST(AllTypes.TextArrayPtr).AS_TEXT().AS("TextArrayPtr"),
CAST(AllTypes.TextArray).AS_TEXT().AS("TextArray"),
CAST(AllTypes.JsonbArray).AS_TEXT().AS("JsonbArray"),
CAST(AllTypes.IntegerArray).AS_TEXT().AS("IntegerArray"),
CAST(AllTypes.IntegerArrayPtr).AS_TEXT().AS("IntegerArrayPtr"),
CAST(AllTypes.TextMultiDimArray).AS_TEXT().AS("TextMultiDimArray"),
CAST(AllTypes.TextMultiDimArrayPtr).AS_TEXT().AS("TextMultiDimArrayPtr"),
).FROM(AllTypes)
//fmt.Println(stmt.DebugSql())
var dest []model.AllTypes
err := stmt.QueryJSON(ctx, db, &dest)
require.NoError(t, err)
// fix inconsistencies between postgres and cockroachdb.
// cockroachdb returns char[N] columns with trailing whitespaces trimmed
if sourceIsCockroachDB() {
dest[0].Char = allTypesRow0.Char
dest[0].CharPtr = allTypesRow0.CharPtr
dest[1].Char = allTypesRow1.Char
dest[1].CharPtr = allTypesRow1.CharPtr
}
// set time local before comparison
dest[0].Timestampz = dest[0].Timestampz.Local()
if dest[0].TimestampzPtr != nil {
dest[0].TimestampzPtr = ptr.Of(dest[0].TimestampzPtr.Local())
}
dest[1].Timestampz = dest[1].Timestampz.Local()
require.Equal(t, dest[0], allTypesRow0)
require.Equal(t, dest[1], allTypesRow1)
}
func TestAllTypesViewSelect(t *testing.T) {
type AllTypesView model.AllTypes
var dest []AllTypesView
@ -146,40 +198,42 @@ RETURNING all_types.bytea AS "all_types.bytea",
all_types.bytea_ptr AS "all_types.bytea_ptr";
`, byteArrHex, byteArrBin)
var inserted model.AllTypes
err := insertStmt.Query(db, &inserted)
require.NoError(t, err)
testutils.ExecuteInTxAndRollback(t, db, func(tx qrm.DB) {
var inserted model.AllTypes
err := insertStmt.Query(tx, &inserted)
require.NoError(t, err)
require.Equal(t, string(*inserted.ByteaPtr), "Hello Gopher!")
// It is not possible to initiate bytea column using hex format '\xDEADBEEF' with pq driver.
// pq driver always encodes parameter string if destination column is of type bytea.
// Probably pq driver error.
// require.Equal(t, string(inserted.Bytea), "Hello Gopher!")
require.Equal(t, string(*inserted.ByteaPtr), "Hello Gopher!")
// It is not possible to initiate bytea column using hex format '\xDEADBEEF' with pq driver.
// pq driver always encodes parameter string if destination column is of type bytea.
// Probably pq driver error.
// require.Equal(t, string(inserted.Bytea), "Hello Gopher!")
stmt := SELECT(
AllTypes.Bytea,
AllTypes.ByteaPtr,
).FROM(
AllTypes,
).WHERE(
AllTypes.ByteaPtr.EQ(Bytea(byteArrBin)),
)
stmt := SELECT(
AllTypes.Bytea,
AllTypes.ByteaPtr,
).FROM(
AllTypes,
).WHERE(
AllTypes.ByteaPtr.EQ(Bytea(byteArrBin)),
)
testutils.AssertStatementSql(t, stmt, `
testutils.AssertStatementSql(t, stmt, `
SELECT all_types.bytea AS "all_types.bytea",
all_types.bytea_ptr AS "all_types.bytea_ptr"
FROM test_sample.all_types
WHERE all_types.bytea_ptr = $1::bytea;
`, byteArrBin)
var dest model.AllTypes
var dest model.AllTypes
err = stmt.Query(db, &dest)
require.NoError(t, err)
err = stmt.Query(tx, &dest)
require.NoError(t, err)
require.Equal(t, string(*dest.ByteaPtr), "Hello Gopher!")
// Probably pq driver error.
// require.Equal(t, string(dest.Bytea), "Hello Gopher!")
require.Equal(t, string(*dest.ByteaPtr), "Hello Gopher!")
// Probably pq driver error.
// require.Equal(t, string(dest.Bytea), "Hello Gopher!")
})
}
func TestAllTypesFromSubQuery(t *testing.T) {

View file

@ -188,7 +188,130 @@ ORDER BY "Artist"."ArtistId", "Album"."AlbumId", "Track"."TrackId";
`)
}
type AllArtistDetails []struct { //list of all artist
model.Artist
Albums []struct { // list of albums per artist
model.Album
Tracks []struct { // list of tracks per album
model.Track
Genre model.Genre // track genre
MediaType model.MediaType // track media type
Playlists []model.Playlist // list of playlist where track is used
Invoices []struct { // list of invoices where track occurs
model.Invoice
Customer struct { // customer data for invoice
model.Customer
Employee *struct { // employee data for customer if exists
model.Employee
Manager *model.Employee `alias:"Manager"`
}
}
}
}
}
}
func BenchmarkJoinEverythingJSON(b *testing.B) {
for i := 0; i < b.N; i++ {
testJoinEverythingJSON(b)
}
}
func TestJoinEverythingJSON(t *testing.T) {
testJoinEverythingJSON(t)
}
func testJoinEverythingJSON(t require.TestingT) {
manager := Employee.AS("Manager")
stmt := SELECT_JSON_ARR(
Artist.AllColumns,
SELECT_JSON_ARR(
Album.AllColumns,
SELECT_JSON_ARR(
Track.AllColumns,
SELECT_JSON_OBJ(Genre.AllColumns).
FROM(Genre).
WHERE(Genre.GenreId.EQ(Track.GenreId)).AS("Genre"),
SELECT_JSON_OBJ(MediaType.AllColumns).
FROM(MediaType).
WHERE(MediaType.MediaTypeId.EQ(Track.MediaTypeId)).AS("MediaType"),
SELECT_JSON_ARR(Playlist.AllColumns).
FROM(Playlist.INNER_JOIN(
PlaylistTrack,
Playlist.PlaylistId.EQ(PlaylistTrack.PlaylistId))).
WHERE(PlaylistTrack.TrackId.EQ(Track.TrackId)).
ORDER_BY(Playlist.PlaylistId).AS("Playlists"),
SELECT_JSON_ARR(
Invoice.AllColumns,
SELECT_JSON_OBJ(
Customer.AllColumns,
SELECT_JSON_OBJ(
Employee.AllColumns,
SELECT_JSON_OBJ(manager.AllColumns).
FROM(manager).
WHERE(manager.EmployeeId.EQ(Employee.ReportsTo)).AS("Manager"),
).FROM(Employee).
WHERE(Employee.EmployeeId.EQ(Customer.SupportRepId)).AS("Employee"),
).FROM(Customer).
WHERE(Customer.CustomerId.EQ(Invoice.CustomerId)).AS("Customer"),
).FROM(Invoice.INNER_JOIN(
InvoiceLine,
InvoiceLine.InvoiceId.EQ(Invoice.InvoiceId)),
).WHERE(InvoiceLine.TrackId.EQ(Track.TrackId)).
ORDER_BY(Invoice.InvoiceId).AS("Invoices"),
).FROM(Track).
WHERE(Track.AlbumId.EQ(Album.AlbumId)).
ORDER_BY(Track.TrackId).AS("Tracks"),
).FROM(Album).
WHERE(Album.ArtistId.EQ(Artist.ArtistId)).
ORDER_BY(Album.AlbumId).AS("Albums"),
).FROM(Artist).
ORDER_BY(Artist.ArtistId)
//fmt.Println(stmt.DebugSql())
var dest AllArtistDetails
err := stmt.QueryJSON(ctx, db, &dest)
require.NoError(t, err)
require.Equal(t, len(dest), 275)
//testutils.SaveJSONFile(dest, "./testdata/results/postgres/joined_everything2.json")
testutils.AssertJSONFile(t, dest, "./testdata/results/postgres/joined_everything.json")
requireLogged(t, stmt)
requireQueryLogged(t, stmt, 1)
}
func BenchmarkJoinEverything(b *testing.B) {
for i := 0; i < b.N; i++ {
testJoinEverything(b)
}
}
func TestJoinEverything(t *testing.T) {
testJoinEverything(t)
}
func testJoinEverything(t require.TestingT) {
manager := Employee.AS("Manager")
@ -223,37 +346,6 @@ func TestJoinEverything(t *testing.T) {
Invoice.InvoiceId, Customer.CustomerId,
)
var dest []struct { //list of all artist
model.Artist
Albums []struct { // list of albums per artist
model.Album
Tracks []struct { // list of tracks per album
model.Track
Genre model.Genre // track genre
MediaType model.MediaType // track media type
Playlists []model.Playlist // list of playlist where track is used
Invoices []struct { // list of invoices where track occurs
model.Invoice
Customer struct { // customer data for invoice
model.Customer
Employee *struct { // employee data for customer if exists
model.Employee
Manager *model.Employee `alias:"Manager"`
}
}
}
}
}
}
testutils.AssertStatementSql(t, stmt, `
SELECT "Artist"."ArtistId" AS "Artist.ArtistId",
"Artist"."Name" AS "Artist.Name",
@ -344,7 +436,7 @@ FROM chinook."Artist"
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";
`)
var dest AllArtistDetails
err := stmt.QueryContext(context.Background(), db, &dest)
require.NoError(t, err)

View file

@ -119,14 +119,22 @@ func init() {
})
}
func requireLogged(t *testing.T, statement postgres.Statement) {
func requireLogged(t require.TestingT, statement postgres.Statement) {
if _, ok := t.(*testing.B); ok {
return // skip assert for benchmarks
}
query, args := statement.Sql()
require.Equal(t, loggedSQL, query)
require.Equal(t, loggedSQLArgs, args)
require.Equal(t, loggedDebugSQL, statement.DebugSql())
}
func requireQueryLogged(t *testing.T, statement postgres.Statement, rowsProcessed int64) {
func requireQueryLogged(t require.TestingT, statement postgres.Statement, rowsProcessed int64) {
if _, ok := t.(*testing.B); ok {
return // skip assert for benchmarks
}
query, args := statement.Sql()
queryLogged, argsLogged := queryInfo.Statement.Sql()

View file

@ -9,7 +9,50 @@ import (
"testing"
)
func TestNorthwindJoinEverything(t *testing.T) {
type Dest []struct {
model.Customers
Demographics model.CustomerDemographics
Orders []struct {
model.Orders
Shipper model.Shippers
Employee struct {
model.Employees
Territories []struct {
model.Territories
Region model.Region
}
}
Details []struct {
model.OrderDetails
Products struct {
model.Products
Category model.Categories
Supplier model.Suppliers
}
}
}
}
func BenchmarkTestNorthwindJoinEverything(b *testing.B) {
for i := 0; i < b.N; i++ {
testNorthwindJoinEverything(b)
}
}
func TestTestNorthwindJoinEverything(t *testing.T) {
testNorthwindJoinEverything(t)
}
func testNorthwindJoinEverything(t require.TestingT) {
stmt :=
SELECT(
@ -21,6 +64,9 @@ func TestNorthwindJoinEverything(t *testing.T) {
Products.AllColumns,
Categories.AllColumns,
Suppliers.AllColumns,
Employees.AllColumns,
Territories.AllColumns,
Region.AllColumns,
).FROM(
Customers.
LEFT_JOIN(CustomerCustomerDemo, Customers.CustomerID.EQ(CustomerCustomerDemo.CustomerID)).
@ -35,35 +81,110 @@ func TestNorthwindJoinEverything(t *testing.T) {
LEFT_JOIN(EmployeeTerritories, EmployeeTerritories.EmployeeID.EQ(Employees.EmployeeID)).
LEFT_JOIN(Territories, EmployeeTerritories.TerritoryID.EQ(Territories.TerritoryID)).
LEFT_JOIN(Region, Territories.RegionID.EQ(Region.RegionID)),
).ORDER_BY(Customers.CustomerID, Orders.OrderID, Products.ProductID)
).ORDER_BY(
Customers.CustomerID,
Orders.OrderID,
Products.ProductID,
Territories.TerritoryID,
)
var dest []struct {
model.Customers
//fmt.Println(stmt.DebugSql())
Demographics model.CustomerDemographics
Orders []struct {
model.Orders
Shipper model.Shippers
Details struct {
model.OrderDetails
Products []struct {
model.Products
Category model.Categories
Supplier model.Suppliers
}
}
}
}
var dest Dest
err := stmt.Query(db, &dest)
require.NoError(t, err)
//jsonSave("./testdata/northwind-all.json", dest)
//testutils.SaveJSONFile(dest, "./testdata/results/postgres/northwind-all.json")
testutils.AssertJSONFile(t, dest, "./testdata/results/postgres/northwind-all.json")
requireLogged(t, stmt)
}
func BenchmarkTestNorthwindJoinEverythingJson(b *testing.B) {
for i := 0; i < b.N; i++ {
testNorthwindJoinEverythingJson(b)
}
}
func TestNorthwindJoinEverythingJson(t *testing.T) {
testNorthwindJoinEverythingJson(t)
}
func testNorthwindJoinEverythingJson(t require.TestingT) {
stmt := SELECT_JSON_ARR(
Customers.AllColumns,
SELECT_JSON_OBJ(CustomerDemographics.AllColumns).
FROM(CustomerDemographics.INNER_JOIN(CustomerCustomerDemo, CustomerCustomerDemo.CustomerTypeID.EQ(CustomerDemographics.CustomerTypeID))).
WHERE(CustomerCustomerDemo.CustomerID.EQ(Customers.CustomerID)).AS("Demographics"),
SELECT_JSON_ARR(
Orders.AllColumns,
SELECT_JSON_OBJ(Shippers.AllColumns).
FROM(Shippers).
WHERE(Shippers.ShipperID.EQ(Orders.ShipVia)).AS("Shipper"),
SELECT_JSON_OBJ(
Employees.AllColumns,
SELECT_JSON_ARR(
Territories.AllColumns,
SELECT_JSON_OBJ(Region.AllColumns).
FROM(Region).
WHERE(Region.RegionID.EQ(Territories.RegionID)).AS("Region"),
).FROM(
EmployeeTerritories.LEFT_JOIN(
Territories,
EmployeeTerritories.TerritoryID.EQ(Territories.TerritoryID)),
).WHERE(
EmployeeTerritories.EmployeeID.EQ(Employees.EmployeeID), // TODO: move to join
).AS("Territories"),
).FROM(Employees).
WHERE(Orders.EmployeeID.EQ(Employees.EmployeeID)).AS("Employee"),
SELECT_JSON_ARR(
OrderDetails.AllColumns,
SELECT_JSON_OBJ(
Products.AllColumns,
SELECT_JSON_OBJ(
Categories.AllColumns,
).FROM(Categories).
WHERE(Categories.CategoryID.EQ(Products.CategoryID)).AS("Category"),
SELECT_JSON_OBJ(Suppliers.AllColumns).
FROM(Suppliers).
WHERE(Suppliers.SupplierID.EQ(Products.SupplierID)).AS("Supplier"),
).FROM(Products).
WHERE(Products.ProductID.EQ(OrderDetails.ProductID)).AS("Products"),
).FROM(
OrderDetails,
).WHERE(
OrderDetails.OrderID.EQ(Orders.OrderID),
).AS("Details"),
).FROM(
Orders,
).WHERE(
Orders.CustomerID.EQ(Customers.CustomerID),
).ORDER_BY(
Orders.OrderID,
).AS("Orders"),
).FROM(
Customers,
).ORDER_BY(
Customers.CustomerID,
)
//fmt.Println(stmt.DebugSql())
var dest Dest
err := stmt.QueryJSON(ctx, db, &dest)
require.NoError(t, err)
//testutils.SaveJSONFile(dest, "./testdata/results/postgres/northwind-all2.json")
testutils.AssertJSONFile(t, dest, "./testdata/results/postgres/northwind-all.json")
}

View file

@ -220,20 +220,7 @@ func TestUUIDComplex(t *testing.T) {
requireLogged(t, query)
})
t.Run("slice of structs left join", func(t *testing.T) {
leftQuery := Person.LEFT_JOIN(PersonPhone, PersonPhone.PersonID.EQ(Person.PersonID)).
SELECT(Person.AllColumns, PersonPhone.AllColumns).
ORDER_BY(Person.PersonID.ASC(), PersonPhone.PhoneID.ASC())
var dest []struct {
model.Person
Phones []struct {
model.PersonPhone
}
}
err := leftQuery.Query(db, &dest)
require.NoError(t, err)
testutils.AssertJSON(t, dest, `
var expectedSliceOfStructsLeftJoin = `
[
{
"PersonID": "b68dbff4-a87d-11e9-a7f2-98ded00c39c6",
@ -274,10 +261,50 @@ func TestUUIDComplex(t *testing.T) {
]
}
]
`)
`
t.Run("slice of structs left join", func(t *testing.T) {
leftQuery := Person.LEFT_JOIN(PersonPhone, PersonPhone.PersonID.EQ(Person.PersonID)).
SELECT(Person.AllColumns, PersonPhone.AllColumns).
ORDER_BY(Person.PersonID.ASC(), PersonPhone.PhoneID.ASC())
var dest []struct {
model.Person
Phones []struct {
model.PersonPhone
}
}
err := leftQuery.Query(db, &dest)
require.NoError(t, err)
testutils.AssertJSON(t, dest, expectedSliceOfStructsLeftJoin)
requireLogged(t, leftQuery)
})
t.Run("select json", func(t *testing.T) {
jsonQuery := SELECT_JSON_ARR(
Person.AllColumns,
SELECT_JSON_ARR(PersonPhone.AllColumns).
FROM(PersonPhone).
WHERE(PersonPhone.PersonID.EQ(Person.PersonID)).
ORDER_BY(PersonPhone.PhoneID).AS("Phones"),
).FROM(
Person,
).ORDER_BY(
Person.PersonID.ASC(),
)
var dest []struct {
model.Person
Phones []struct {
model.PersonPhone
}
}
err := jsonQuery.QueryJSON(ctx, db, &dest)
require.NoError(t, err)
testutils.AssertJSON(t, dest, expectedSliceOfStructsLeftJoin)
})
}
func TestEnumType(t *testing.T) {
query := Person.

View file

@ -209,7 +209,7 @@ func TestScanToStruct(t *testing.T) {
err := query.Query(db, &dest)
require.Error(t, err)
require.EqualError(t, err, "jet: can't scan int64('\\x01') to 'InventoryID uuid.UUID': Scan: unable to scan type int64 into UUID")
require.EqualError(t, err, "jet: can't assign int64('\\x01') to 'InventoryID uuid.UUID': Scan: unable to scan type int64 into UUID")
})
t.Run("type mismatch base type", func(t *testing.T) {

File diff suppressed because one or more lines are too long

View file

@ -21,36 +21,36 @@ import (
)
func TestSelect_ScanToStruct(t *testing.T) {
expectedSQL := `
t.Run("standard", func(t *testing.T) {
stmt := SELECT(Actor.AllColumns).
DISTINCT().
FROM(Actor).
WHERE(Actor.ActorID.EQ(Int(2)))
testutils.AssertDebugStatementSql(t, stmt, `
SELECT DISTINCT actor.actor_id AS "actor.actor_id",
actor.first_name AS "actor.first_name",
actor.last_name AS "actor.last_name",
actor.last_update AS "actor.last_update"
FROM dvds.actor
WHERE actor.actor_id = 2;
`
`, int64(2))
query := SELECT(Actor.AllColumns).
DISTINCT().
FROM(Actor).
WHERE(Actor.ActorID.EQ(Int(2)))
var dest model.Actor
err := stmt.Query(db, &dest)
testutils.AssertDebugStatementSql(t, query, expectedSQL, int64(2))
require.NoError(t, err)
testutils.AssertDeepEqual(t, dest, actor2)
requireLogged(t, stmt)
})
}
actor := model.Actor{}
err := query.Query(db, &actor)
require.NoError(t, err)
expectedActor := model.Actor{
ActorID: 2,
FirstName: "Nick",
LastName: "Wahlberg",
LastUpdate: *testutils.TimestampWithoutTimeZone("2013-05-26 14:47:57.62", 2),
}
testutils.AssertDeepEqual(t, actor, expectedActor)
requireLogged(t, query)
var actor2 = model.Actor{
ActorID: 2,
FirstName: "Nick",
LastName: "Wahlberg",
LastUpdate: *testutils.TimestampWithoutTimeZone("2013-05-26 14:47:57.62", 2),
}
func TestSelectDistinctOn(t *testing.T) {
@ -85,7 +85,6 @@ ORDER BY rental.staff_id ASC, rental.customer_id ASC, rental.rental_id ASC;
err := stmt.Query(db, &dest)
require.NoError(t, err)
testutils.AssertJSON(t, dest, `
[
{
@ -187,6 +186,21 @@ ORDER BY customer.customer_id ASC;
testutils.AssertDeepEqual(t, lastCustomer, customers[598])
requireLogged(t, query)
t.Run("select json", func(t *testing.T) {
stmt := SELECT_JSON_ARR(
Customer.AllColumns,
).FROM(
Customer,
).ORDER_BY(Customer.CustomerID.ASC())
var dest []model.Customer
err := stmt.QueryJSON(ctx, db, &dest)
require.NoError(t, err)
testutils.AssertDeepEqual(t, customers, dest)
})
}
func TestSelectAndUnionInProjection(t *testing.T) {
@ -217,15 +231,14 @@ FROM dvds.payment
LIMIT 12;
`
query := Payment.
SELECT(
Payment.PaymentID,
Customer.SELECT(Customer.CustomerID).LIMIT(1),
UNION(
Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(10),
Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(2),
).LIMIT(1),
).
query := SELECT(
Payment.PaymentID,
Customer.SELECT(Customer.CustomerID).LIMIT(1),
UNION(
Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(10),
Payment.SELECT(Payment.PaymentID).LIMIT(1).OFFSET(2),
).LIMIT(1),
).FROM(Payment).
LIMIT(12)
//fmt.Println(query.DebugSql())
@ -2771,7 +2784,8 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
err := stmt.Query(db, &dest)
require.NoError(t, err)
//jsonSave("./testdata/quick-start-dest.json", dest)
//testutils.SaveJSONFile(dest, "./testdata/results/postgres/quick-start-dest.json")
testutils.AssertJSONFile(t, dest, "./testdata/results/postgres/quick-start-dest.json")
var dest2 []struct {
@ -2784,7 +2798,7 @@ ORDER BY actor.actor_id ASC, film.film_id ASC;
err = stmt.Query(db, &dest2)
require.NoError(t, err)
//jsonSave("./testdata/quick-start-dest2.json", dest2)
//testutils.SaveJSONFile(dest2, "./testdata/results/postgres/quick-start-dest2.json")
testutils.AssertJSONFile(t, dest2, "./testdata/results/postgres/quick-start-dest2.json")
}
@ -2966,7 +2980,7 @@ WHERE payment.payment_id < $1
WINDOW w1 AS (PARTITION BY payment.payment_date), w2 AS (w1), w3 AS (w2 ORDER BY payment.customer_id)
ORDER BY payment.customer_id;
`
query := Payment.SELECT(
query := SELECT(
AVG(Payment.Amount).OVER(),
AVG(Payment.Amount).OVER(Window("w1")),
AVG(Payment.Amount).OVER(
@ -2976,6 +2990,7 @@ ORDER BY payment.customer_id;
),
AVG(Payment.Amount).OVER(Window("w3").RANGE(PRECEDING(UNBOUNDED), FOLLOWING(UNBOUNDED))),
).
FROM(Payment).
WHERE(Payment.PaymentID.LT(Int(10))).
WINDOW("w1").AS(PARTITION_BY(Payment.PaymentDate)).
WINDOW("w2").AS(Window("w1")).