Improvements on sub-query projection reference.
This commit is contained in:
parent
d9ffa86453
commit
565b670188
17 changed files with 512 additions and 134 deletions
|
|
@ -356,6 +356,185 @@ func TestTimeOperators(t *testing.T) {
|
|||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
func TestSubQueryColumnReference(t *testing.T) {
|
||||
|
||||
type expected struct {
|
||||
sql string
|
||||
args []interface{}
|
||||
}
|
||||
|
||||
subQueries := map[ExpressionTable]expected{}
|
||||
|
||||
selectSubQuery := AllTypes.SELECT(
|
||||
AllTypes.Boolean,
|
||||
AllTypes.Integer,
|
||||
AllTypes.Real,
|
||||
AllTypes.Text,
|
||||
AllTypes.Time,
|
||||
AllTypes.Timez,
|
||||
AllTypes.Timestamp,
|
||||
AllTypes.Timestampz,
|
||||
AllTypes.Date,
|
||||
AllTypes.Bytea.AS("aliasedColumn"),
|
||||
).
|
||||
LIMIT(2).
|
||||
AsTable("subQuery")
|
||||
|
||||
var selectExpectedSql = ` (
|
||||
SELECT all_types.boolean AS "all_types.boolean",
|
||||
all_types.integer AS "all_types.integer",
|
||||
all_types.real AS "all_types.real",
|
||||
all_types.text AS "all_types.text",
|
||||
all_types.time AS "all_types.time",
|
||||
all_types.timez AS "all_types.timez",
|
||||
all_types.timestamp AS "all_types.timestamp",
|
||||
all_types.timestampz AS "all_types.timestampz",
|
||||
all_types.date AS "all_types.date",
|
||||
all_types.bytea AS "aliasedColumn"
|
||||
FROM test_sample.all_types
|
||||
LIMIT 2
|
||||
) AS "subQuery"`
|
||||
|
||||
unionSubQuery :=
|
||||
UNION_ALL(
|
||||
AllTypes.SELECT(
|
||||
AllTypes.Boolean,
|
||||
AllTypes.Integer,
|
||||
AllTypes.Real,
|
||||
AllTypes.Text,
|
||||
AllTypes.Time,
|
||||
AllTypes.Timez,
|
||||
AllTypes.Timestamp,
|
||||
AllTypes.Timestampz,
|
||||
AllTypes.Date,
|
||||
AllTypes.Bytea.AS("aliasedColumn"),
|
||||
).
|
||||
LIMIT(1),
|
||||
AllTypes.SELECT(
|
||||
AllTypes.Boolean,
|
||||
AllTypes.Integer,
|
||||
AllTypes.Real,
|
||||
AllTypes.Text,
|
||||
AllTypes.Time,
|
||||
AllTypes.Timez,
|
||||
AllTypes.Timestamp,
|
||||
AllTypes.Timestampz,
|
||||
AllTypes.Date,
|
||||
AllTypes.Bytea.AS("aliasedColumn"),
|
||||
).
|
||||
LIMIT(1).OFFSET(1),
|
||||
).
|
||||
AsTable("subQuery")
|
||||
|
||||
unionExpectedSql := `
|
||||
(
|
||||
(
|
||||
SELECT all_types.boolean AS "all_types.boolean",
|
||||
all_types.integer AS "all_types.integer",
|
||||
all_types.real AS "all_types.real",
|
||||
all_types.text AS "all_types.text",
|
||||
all_types.time AS "all_types.time",
|
||||
all_types.timez AS "all_types.timez",
|
||||
all_types.timestamp AS "all_types.timestamp",
|
||||
all_types.timestampz AS "all_types.timestampz",
|
||||
all_types.date AS "all_types.date",
|
||||
all_types.bytea AS "aliasedColumn"
|
||||
FROM test_sample.all_types
|
||||
LIMIT 1
|
||||
)
|
||||
UNION ALL
|
||||
(
|
||||
SELECT all_types.boolean AS "all_types.boolean",
|
||||
all_types.integer AS "all_types.integer",
|
||||
all_types.real AS "all_types.real",
|
||||
all_types.text AS "all_types.text",
|
||||
all_types.time AS "all_types.time",
|
||||
all_types.timez AS "all_types.timez",
|
||||
all_types.timestamp AS "all_types.timestamp",
|
||||
all_types.timestampz AS "all_types.timestampz",
|
||||
all_types.date AS "all_types.date",
|
||||
all_types.bytea AS "aliasedColumn"
|
||||
FROM test_sample.all_types
|
||||
LIMIT 1
|
||||
OFFSET 1
|
||||
)
|
||||
) AS "subQuery"`
|
||||
|
||||
subQueries[selectSubQuery] = expected{sql: selectExpectedSql, args: []interface{}{int64(2)}}
|
||||
subQueries[unionSubQuery] = expected{sql: unionExpectedSql, args: []interface{}{int64(1), int64(1), int64(1)}}
|
||||
|
||||
for subQuery, expected := range subQueries {
|
||||
boolColumn := AllTypes.Boolean.From(subQuery)
|
||||
intColumn := AllTypes.Integer.From(subQuery)
|
||||
floatColumn := AllTypes.Real.From(subQuery)
|
||||
stringColumn := AllTypes.Text.From(subQuery)
|
||||
timeColumn := AllTypes.Time.From(subQuery)
|
||||
timezColumn := AllTypes.Timez.From(subQuery)
|
||||
timestampColumn := AllTypes.Timestamp.From(subQuery)
|
||||
timestampzColumn := AllTypes.Timestampz.From(subQuery)
|
||||
dateColumn := AllTypes.Date.From(subQuery)
|
||||
aliasedColumn := StringColumn("aliasedColumn").From(subQuery)
|
||||
|
||||
stmt1 := SELECT(
|
||||
boolColumn,
|
||||
intColumn,
|
||||
floatColumn,
|
||||
stringColumn,
|
||||
timeColumn,
|
||||
timezColumn,
|
||||
timestampColumn,
|
||||
timestampzColumn,
|
||||
dateColumn,
|
||||
aliasedColumn,
|
||||
).
|
||||
FROM(subQuery)
|
||||
|
||||
var expectedSql = `
|
||||
SELECT "subQuery"."all_types.boolean" AS "all_types.boolean",
|
||||
"subQuery"."all_types.integer" AS "all_types.integer",
|
||||
"subQuery"."all_types.real" AS "all_types.real",
|
||||
"subQuery"."all_types.text" AS "all_types.text",
|
||||
"subQuery"."all_types.time" AS "all_types.time",
|
||||
"subQuery"."all_types.timez" AS "all_types.timez",
|
||||
"subQuery"."all_types.timestamp" AS "all_types.timestamp",
|
||||
"subQuery"."all_types.timestampz" AS "all_types.timestampz",
|
||||
"subQuery"."all_types.date" AS "all_types.date",
|
||||
"subQuery"."aliasedColumn" AS "aliasedColumn"
|
||||
FROM`
|
||||
|
||||
assertStatementSql(t, stmt1, expectedSql+expected.sql+";\n", expected.args...)
|
||||
|
||||
dest1 := []model.AllTypes{}
|
||||
err := stmt1.Query(db, &dest1)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, len(dest1), 2)
|
||||
assert.Equal(t, dest1[0].Boolean, allTypesRow0.Boolean)
|
||||
assert.Equal(t, dest1[0].Integer, allTypesRow0.Integer)
|
||||
assert.Equal(t, dest1[0].Real, allTypesRow0.Real)
|
||||
assert.Equal(t, dest1[0].Text, allTypesRow0.Text)
|
||||
assert.DeepEqual(t, dest1[0].Time, allTypesRow0.Time)
|
||||
assert.DeepEqual(t, dest1[0].Timez, allTypesRow0.Timez)
|
||||
assert.DeepEqual(t, dest1[0].Timestamp, allTypesRow0.Timestamp)
|
||||
assert.DeepEqual(t, dest1[0].Timestampz, allTypesRow0.Timestampz)
|
||||
assert.DeepEqual(t, dest1[0].Date, allTypesRow0.Date)
|
||||
|
||||
stmt2 := SELECT(
|
||||
subQuery.AllColumns(),
|
||||
).
|
||||
FROM(subQuery)
|
||||
|
||||
fmt.Println(stmt2.DebugSql())
|
||||
|
||||
assertStatementSql(t, stmt2, expectedSql+expected.sql+";\n", expected.args...)
|
||||
|
||||
dest2 := []model.AllTypes{}
|
||||
err = stmt2.Query(db, &dest2)
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, dest1, dest2)
|
||||
}
|
||||
}
|
||||
|
||||
var allTypesRow0 = model.AllTypes{
|
||||
SmallintPtr: int16Ptr(1),
|
||||
Smallint: 1,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package tests
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
. "github.com/go-jet/jet/sqlbuilder"
|
||||
"github.com/go-jet/jet/tests/.test_files/dvd_rental/chinook/model"
|
||||
. "github.com/go-jet/jet/tests/.test_files/dvd_rental/chinook/table"
|
||||
|
|
@ -151,6 +152,65 @@ ORDER BY "Album.AlbumId";
|
|||
assert.DeepEqual(t, dest[1], album2)
|
||||
}
|
||||
|
||||
func TestSubQueriesForQuotedNames(t *testing.T) {
|
||||
first10Artist := Artist.
|
||||
SELECT(Artist.AllColumns).
|
||||
ORDER_BY(Artist.ArtistId).
|
||||
LIMIT(10).
|
||||
AsTable("first10Artist")
|
||||
|
||||
artistId := Artist.ArtistId.From(first10Artist)
|
||||
|
||||
first10Albums := Album.
|
||||
SELECT(Album.AllColumns).
|
||||
ORDER_BY(Album.AlbumId).
|
||||
LIMIT(10).
|
||||
AsTable("first10Albums")
|
||||
|
||||
albumArtistId := Album.ArtistId.From(first10Albums)
|
||||
|
||||
stmt := first10Artist.
|
||||
INNER_JOIN(first10Albums, artistId.EQ(albumArtistId)).
|
||||
SELECT(first10Artist.AllColumns(), first10Albums.AllColumns()).
|
||||
ORDER_BY(artistId)
|
||||
|
||||
assertStatementSql(t, stmt, `
|
||||
SELECT "first10Artist"."Artist.ArtistId" AS "Artist.ArtistId",
|
||||
"first10Artist"."Artist.Name" AS "Artist.Name",
|
||||
"first10Albums"."Album.AlbumId" AS "Album.AlbumId",
|
||||
"first10Albums"."Album.Title" AS "Album.Title",
|
||||
"first10Albums"."Album.ArtistId" AS "Album.ArtistId"
|
||||
FROM (
|
||||
SELECT "Artist"."ArtistId" AS "Artist.ArtistId",
|
||||
"Artist"."Name" AS "Artist.Name"
|
||||
FROM chinook."Artist"
|
||||
ORDER BY "Artist"."ArtistId"
|
||||
LIMIT 10
|
||||
) AS "first10Artist"
|
||||
INNER JOIN (
|
||||
SELECT "Album"."AlbumId" AS "Album.AlbumId",
|
||||
"Album"."Title" AS "Album.Title",
|
||||
"Album"."ArtistId" AS "Album.ArtistId"
|
||||
FROM chinook."Album"
|
||||
ORDER BY "Album"."AlbumId"
|
||||
LIMIT 10
|
||||
) AS "first10Albums" ON ("first10Artist"."Artist.ArtistId" = "first10Albums"."Album.ArtistId")
|
||||
ORDER BY "first10Artist"."Artist.ArtistId";
|
||||
`, int64(10), int64(10))
|
||||
|
||||
var dest []struct {
|
||||
model.Artist
|
||||
|
||||
Album []model.Album
|
||||
}
|
||||
|
||||
err := stmt.Query(db, &dest)
|
||||
|
||||
assert.NilError(t, err)
|
||||
|
||||
spew.Dump(dest)
|
||||
}
|
||||
|
||||
func assertJson(t *testing.T, jsonFilePath string, data interface{}) {
|
||||
fileJsonData, err := ioutil.ReadFile(jsonFilePath)
|
||||
assert.NilError(t, err)
|
||||
|
|
|
|||
|
|
@ -907,7 +907,7 @@ SELECT customer.customer_id AS "customer.customer_id",
|
|||
customer.create_date AS "customer.create_date",
|
||||
customer.last_update AS "customer.last_update",
|
||||
customer.active AS "customer.active",
|
||||
customer_payment_sum.amount_sum AS "customer_with_amounts.amount_sum"
|
||||
customer_payment_sum."amount_sum" AS "CustomerWithAmounts.AmountSum"
|
||||
FROM dvds.customer
|
||||
INNER JOIN (
|
||||
SELECT payment.customer_id AS "payment.customer_id",
|
||||
|
|
@ -915,7 +915,7 @@ FROM dvds.customer
|
|||
FROM dvds.payment
|
||||
GROUP BY payment.customer_id
|
||||
) AS customer_payment_sum ON (customer.customer_id = customer_payment_sum."payment.customer_id")
|
||||
ORDER BY customer_payment_sum.amount_sum ASC;
|
||||
ORDER BY customer_payment_sum."amount_sum" ASC;
|
||||
`
|
||||
|
||||
customersPayments := Payment.
|
||||
|
|
@ -933,7 +933,7 @@ ORDER BY customer_payment_sum.amount_sum ASC;
|
|||
INNER_JOIN(customersPayments, Customer.CustomerID.EQ(customerId)).
|
||||
SELECT(
|
||||
Customer.AllColumns,
|
||||
amountSum.AS("customer_with_amounts.amount_sum"),
|
||||
amountSum.AS("CustomerWithAmounts.AmountSum"),
|
||||
).
|
||||
ORDER_BY(amountSum.ASC())
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ func assertStatementSql(t *testing.T, query sqlbuilder.Statement, expectedQuery
|
|||
assert.DeepEqual(t, args, expectedArgs)
|
||||
|
||||
debuqSql, err := query.DebugSql()
|
||||
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, debuqSql, expectedQuery)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue