Add support for NULLS_FIRST and NULLS_LAST sorting order.
This commit is contained in:
parent
0fc51cf402
commit
dab153a739
8 changed files with 882 additions and 19 deletions
|
|
@ -12,6 +12,7 @@ type Dialect interface {
|
||||||
IdentifierQuoteChar() byte
|
IdentifierQuoteChar() byte
|
||||||
ArgumentPlaceholder() QueryPlaceholderFunc
|
ArgumentPlaceholder() QueryPlaceholderFunc
|
||||||
IsReservedWord(name string) bool
|
IsReservedWord(name string) bool
|
||||||
|
SerializeOrderBy() func(expression Expression, ascending, nullsFirst *bool) SerializerFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// SerializerFunc func
|
// SerializerFunc func
|
||||||
|
|
@ -33,6 +34,7 @@ type DialectParams struct {
|
||||||
IdentifierQuoteChar byte
|
IdentifierQuoteChar byte
|
||||||
ArgumentPlaceholder QueryPlaceholderFunc
|
ArgumentPlaceholder QueryPlaceholderFunc
|
||||||
ReservedWords []string
|
ReservedWords []string
|
||||||
|
SerializeOrderBy func(expression Expression, ascending, nullsFirst *bool) SerializerFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDialect creates new dialect with params
|
// NewDialect creates new dialect with params
|
||||||
|
|
@ -46,6 +48,7 @@ func NewDialect(params DialectParams) Dialect {
|
||||||
identifierQuoteChar: params.IdentifierQuoteChar,
|
identifierQuoteChar: params.IdentifierQuoteChar,
|
||||||
argumentPlaceholder: params.ArgumentPlaceholder,
|
argumentPlaceholder: params.ArgumentPlaceholder,
|
||||||
reservedWords: arrayOfStringsToMapOfStrings(params.ReservedWords),
|
reservedWords: arrayOfStringsToMapOfStrings(params.ReservedWords),
|
||||||
|
serializeOrderBy: params.SerializeOrderBy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,8 +61,7 @@ type dialectImpl struct {
|
||||||
identifierQuoteChar byte
|
identifierQuoteChar byte
|
||||||
argumentPlaceholder QueryPlaceholderFunc
|
argumentPlaceholder QueryPlaceholderFunc
|
||||||
reservedWords map[string]bool
|
reservedWords map[string]bool
|
||||||
|
serializeOrderBy func(expression Expression, ascending, nullsFirst *bool) SerializerFunc
|
||||||
supportsReturning bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *dialectImpl) Name() string {
|
func (d *dialectImpl) Name() string {
|
||||||
|
|
@ -101,6 +103,10 @@ func (d *dialectImpl) IsReservedWord(name string) bool {
|
||||||
return isReservedWord
|
return isReservedWord
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *dialectImpl) SerializeOrderBy() func(expression Expression, ascending, nullsFirst *bool) SerializerFunc {
|
||||||
|
return d.serializeOrderBy
|
||||||
|
}
|
||||||
|
|
||||||
func arrayOfStringsToMapOfStrings(arr []string) map[string]bool {
|
func arrayOfStringsToMapOfStrings(arr []string) map[string]bool {
|
||||||
ret := map[string]bool{}
|
ret := map[string]bool{}
|
||||||
for _, elem := range arr {
|
for _, elem := range arr {
|
||||||
|
|
|
||||||
|
|
@ -64,14 +64,24 @@ func (e *ExpressionInterfaceImpl) AS(alias string) Projection {
|
||||||
return newAlias(e.Parent, alias)
|
return newAlias(e.Parent, alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ASC expression will be used to sort query result in ascending order
|
// ASC expression will be used to sort a query result in ascending order
|
||||||
func (e *ExpressionInterfaceImpl) ASC() OrderByClause {
|
func (e *ExpressionInterfaceImpl) ASC() OrderByClause {
|
||||||
return newOrderByClause(e.Parent, true)
|
return newOrderByAscending(e.Parent, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DESC expression will be used to sort query result in descending order
|
// DESC expression will be used to sort a query result in descending order
|
||||||
func (e *ExpressionInterfaceImpl) DESC() OrderByClause {
|
func (e *ExpressionInterfaceImpl) DESC() OrderByClause {
|
||||||
return newOrderByClause(e.Parent, false)
|
return newOrderByAscending(e.Parent, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NULLS_FIRST specifies sort where null values appear before all non-null values
|
||||||
|
func (e *ExpressionInterfaceImpl) NULLS_FIRST() OrderByClause {
|
||||||
|
return newOrderByNullsFirst(e.Parent, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NULLS_LAST specifies sort where null values appear after all non-null values
|
||||||
|
func (e *ExpressionInterfaceImpl) NULLS_LAST() OrderByClause {
|
||||||
|
return newOrderByNullsFirst(e.Parent, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ExpressionInterfaceImpl) serializeForGroupBy(statement StatementType, out *SQLBuilder) {
|
func (e *ExpressionInterfaceImpl) serializeForGroupBy(statement StatementType, out *SQLBuilder) {
|
||||||
|
|
|
||||||
|
|
@ -2,28 +2,78 @@ package jet
|
||||||
|
|
||||||
// OrderByClause interface
|
// OrderByClause interface
|
||||||
type OrderByClause interface {
|
type OrderByClause interface {
|
||||||
|
// NULLS_FIRST specifies sort where null values appear before all non-null values.
|
||||||
|
// For some dialects(mysql,mariadb), which do not support NULL_FIRST, NULL_FIRST is simulated
|
||||||
|
// with additional IS_NOT_NULL expression.
|
||||||
|
// For instance,
|
||||||
|
// Rental.ReturnDate.DESC().NULLS_FIRST()
|
||||||
|
// would translate to,
|
||||||
|
// rental.return_date IS NOT NULL, rental.return_date DESC
|
||||||
|
NULLS_FIRST() OrderByClause
|
||||||
|
|
||||||
|
// NULLS_LAST specifies sort where null values appear after all non-null values.
|
||||||
|
// For some dialects(mysql,mariadb), which do not support NULLS_LAST, NULLS_LAST is simulated
|
||||||
|
// with additional IS_NULL expression.
|
||||||
|
// For instance,
|
||||||
|
// Rental.ReturnDate.ASC().NULLS_LAST()
|
||||||
|
// would translate to,
|
||||||
|
// rental.return_date IS NULL, rental.return_date ASC
|
||||||
|
NULLS_LAST() OrderByClause
|
||||||
|
|
||||||
serializeForOrderBy(statement StatementType, out *SQLBuilder)
|
serializeForOrderBy(statement StatementType, out *SQLBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
type orderByClauseImpl struct {
|
type orderByClauseImpl struct {
|
||||||
expression Expression
|
expression Expression
|
||||||
ascent bool
|
ascending *bool
|
||||||
|
nullsFirst *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *orderByClauseImpl) serializeForOrderBy(statement StatementType, out *SQLBuilder) {
|
func (ord *orderByClauseImpl) NULLS_FIRST() OrderByClause {
|
||||||
if o.expression == nil {
|
nullsFirst := true
|
||||||
|
ord.nullsFirst = &nullsFirst
|
||||||
|
return ord
|
||||||
|
}
|
||||||
|
func (ord *orderByClauseImpl) NULLS_LAST() OrderByClause {
|
||||||
|
nullsFirst := false
|
||||||
|
ord.nullsFirst = &nullsFirst
|
||||||
|
return ord
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ord *orderByClauseImpl) serializeForOrderBy(statement StatementType, out *SQLBuilder) {
|
||||||
|
customSerializer := out.Dialect.SerializeOrderBy()
|
||||||
|
if customSerializer != nil {
|
||||||
|
customSerializer(ord.expression, ord.ascending, ord.nullsFirst)(statement, out)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ord.expression == nil {
|
||||||
panic("jet: nil expression in ORDER BY clause")
|
panic("jet: nil expression in ORDER BY clause")
|
||||||
}
|
}
|
||||||
|
|
||||||
o.expression.serializeForOrderBy(statement, out)
|
ord.expression.serializeForOrderBy(statement, out)
|
||||||
|
|
||||||
if o.ascent {
|
if ord.ascending != nil {
|
||||||
|
if *ord.ascending {
|
||||||
out.WriteString("ASC")
|
out.WriteString("ASC")
|
||||||
} else {
|
} else {
|
||||||
out.WriteString("DESC")
|
out.WriteString("DESC")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ord.nullsFirst != nil {
|
||||||
|
if *ord.nullsFirst {
|
||||||
|
out.WriteString("NULLS FIRST")
|
||||||
|
} else {
|
||||||
|
out.WriteString("NULLS LAST")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newOrderByClause(expression Expression, ascent bool) OrderByClause {
|
func newOrderByAscending(expression Expression, ascending bool) OrderByClause {
|
||||||
return &orderByClauseImpl{expression: expression, ascent: ascent}
|
return &orderByClauseImpl{expression: expression, ascending: &ascending}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newOrderByNullsFirst(expression Expression, nullsFirst bool) OrderByClause {
|
||||||
|
return &orderByClauseImpl{expression: expression, nullsFirst: &nullsFirst}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,10 @@ func Serialize(exp Serializer, statementType StatementType, out *SQLBuilder, opt
|
||||||
exp.serialize(statementType, out, options...)
|
exp.serialize(statementType, out, options...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SerializeForOrderBy(exp Expression, statementType StatementType, out *SQLBuilder) {
|
||||||
|
exp.serializeForOrderBy(statementType, out)
|
||||||
|
}
|
||||||
|
|
||||||
func contains(options []SerializeOption, option SerializeOption) bool {
|
func contains(options []SerializeOption, option SerializeOption) bool {
|
||||||
for _, opt := range options {
|
for _, opt := range options {
|
||||||
if opt == option {
|
if opt == option {
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ func newDialect() jet.Dialect {
|
||||||
return "?"
|
return "?"
|
||||||
},
|
},
|
||||||
ReservedWords: reservedWords,
|
ReservedWords: reservedWords,
|
||||||
|
SerializeOrderBy: serializeOrderBy,
|
||||||
}
|
}
|
||||||
|
|
||||||
return jet.NewDialect(mySQLDialectParams)
|
return jet.NewDialect(mySQLDialectParams)
|
||||||
|
|
@ -162,6 +163,53 @@ func mysqlNOTREGEXPLIKEoperator(expressions ...jet.Serializer) jet.SerializerFun
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func serializeOrderBy(expression Expression, ascending, nullsFirst *bool) jet.SerializerFunc {
|
||||||
|
return func(statement jet.StatementType, out *jet.SQLBuilder, options ...jet.SerializeOption) {
|
||||||
|
|
||||||
|
if nullsFirst == nil {
|
||||||
|
jet.SerializeForOrderBy(expression, statement, out)
|
||||||
|
|
||||||
|
if ascending != nil {
|
||||||
|
serializeAscending(*ascending, out)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
asc := true
|
||||||
|
|
||||||
|
if ascending != nil {
|
||||||
|
asc = *ascending
|
||||||
|
}
|
||||||
|
|
||||||
|
if asc {
|
||||||
|
if !*nullsFirst {
|
||||||
|
jet.SerializeForOrderBy(expression.IS_NULL(), statement, out)
|
||||||
|
out.WriteString(", ")
|
||||||
|
}
|
||||||
|
jet.SerializeForOrderBy(expression, statement, out)
|
||||||
|
if ascending != nil {
|
||||||
|
serializeAscending(asc, out)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if *nullsFirst {
|
||||||
|
jet.SerializeForOrderBy(expression.IS_NOT_NULL(), statement, out)
|
||||||
|
out.WriteString(", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
jet.SerializeForOrderBy(expression, statement, out)
|
||||||
|
serializeAscending(asc, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func serializeAscending(ascending bool, out *jet.SQLBuilder) {
|
||||||
|
if ascending {
|
||||||
|
out.WriteString("ASC")
|
||||||
|
} else {
|
||||||
|
out.WriteString("DESC")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var reservedWords = []string{
|
var reservedWords = []string{
|
||||||
"ACCESSIBLE",
|
"ACCESSIBLE",
|
||||||
"ADD",
|
"ADD",
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package mysql
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"github.com/go-jet/jet/v2/postgres"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -296,6 +297,296 @@ ORDER BY inventory.film_id, inventory.store_id;
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOrderBy(t *testing.T) {
|
||||||
|
// NULLS_FIRST and NULLS_LAST are simulated using IS_NULL, ...
|
||||||
|
|
||||||
|
ensureNullsFirstRentalResult := func(t *testing.T, stmt postgres.Statement, asc bool) {
|
||||||
|
var dest []model.Rental
|
||||||
|
|
||||||
|
err := stmt.Query(db, &dest)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, dest, 200)
|
||||||
|
require.Nil(t, dest[0].ReturnDate)
|
||||||
|
require.NotNil(t, dest[199].ReturnDate)
|
||||||
|
|
||||||
|
if asc {
|
||||||
|
require.True(t, dest[198].ReturnDate.Before(*dest[199].ReturnDate))
|
||||||
|
} else {
|
||||||
|
require.True(t, dest[199].ReturnDate.Before(*dest[198].ReturnDate))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureNullsLastRentalResult := func(t *testing.T, stmt postgres.Statement, asc bool) {
|
||||||
|
var dest []model.Rental
|
||||||
|
|
||||||
|
err := stmt.Query(db, &dest)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, dest, 200)
|
||||||
|
require.NotNil(t, dest[0].ReturnDate)
|
||||||
|
require.Nil(t, dest[199].ReturnDate)
|
||||||
|
|
||||||
|
if asc {
|
||||||
|
require.True(t, dest[0].ReturnDate.Before(*dest[1].ReturnDate))
|
||||||
|
} else {
|
||||||
|
require.True(t, dest[1].ReturnDate.Before(*dest[0].ReturnDate))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("default", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate,
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
ensureNullsFirstRentalResult(t, stmt, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("NULLS FIRST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.NULLS_FIRST(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
ensureNullsFirstRentalResult(t, stmt, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("NULLS LAST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.NULLS_LAST(),
|
||||||
|
).LIMIT(200).OFFSET(15800)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date IS NULL, rental.return_date
|
||||||
|
LIMIT 200
|
||||||
|
OFFSET 15800;
|
||||||
|
`)
|
||||||
|
ensureNullsLastRentalResult(t, stmt, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ASC", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.ASC(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date ASC
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
ensureNullsFirstRentalResult(t, stmt, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ASC NULLS FIRST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.ASC().NULLS_FIRST(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date ASC
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
|
||||||
|
ensureNullsFirstRentalResult(t, stmt, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ASC NULLS LAST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.ASC().NULLS_LAST(),
|
||||||
|
).LIMIT(200).OFFSET(15800)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date IS NULL, rental.return_date ASC
|
||||||
|
LIMIT 200
|
||||||
|
OFFSET 15800;
|
||||||
|
`)
|
||||||
|
|
||||||
|
ensureNullsLastRentalResult(t, stmt, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DESC", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.DESC(),
|
||||||
|
).LIMIT(200).OFFSET(15800)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date DESC
|
||||||
|
LIMIT 200
|
||||||
|
OFFSET 15800;
|
||||||
|
`)
|
||||||
|
|
||||||
|
ensureNullsLastRentalResult(t, stmt, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DESC NULLS LAST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.DESC().NULLS_LAST(),
|
||||||
|
).LIMIT(200).OFFSET(15800)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date DESC
|
||||||
|
LIMIT 200
|
||||||
|
OFFSET 15800;
|
||||||
|
`)
|
||||||
|
|
||||||
|
ensureNullsLastRentalResult(t, stmt, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DESC NULLS FIRST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.DESC().NULLS_FIRST(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date IS NOT NULL, rental.return_date DESC
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
|
||||||
|
ensureNullsFirstRentalResult(t, stmt, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("complex", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.RentalID.DESC(),
|
||||||
|
Rental.ReturnDate.DESC().NULLS_FIRST(),
|
||||||
|
Rental.LastUpdate.ASC(),
|
||||||
|
Rental.InventoryID.ADD(Rental.RentalID).ASC().NULLS_LAST(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.rental_id DESC, rental.return_date IS NOT NULL, rental.return_date DESC, rental.last_update ASC, (rental.inventory_id + rental.rental_id) IS NULL, rental.inventory_id + rental.rental_id ASC
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestSubQuery(t *testing.T) {
|
func TestSubQuery(t *testing.T) {
|
||||||
|
|
||||||
rRatingFilms := SELECT(
|
rRatingFilms := SELECT(
|
||||||
|
|
|
||||||
|
|
@ -1151,7 +1151,7 @@ func TestSelectOrderByAscDesc(t *testing.T) {
|
||||||
firstCustomerAsc := customersAsc[0]
|
firstCustomerAsc := customersAsc[0]
|
||||||
lastCustomerAsc := customersAsc[len(customersAsc)-1]
|
lastCustomerAsc := customersAsc[len(customersAsc)-1]
|
||||||
|
|
||||||
customersDesc := []model.Customer{}
|
var customersDesc []model.Customer
|
||||||
err = Customer.SELECT(Customer.CustomerID, Customer.FirstName, Customer.LastName).
|
err = Customer.SELECT(Customer.CustomerID, Customer.FirstName, Customer.LastName).
|
||||||
ORDER_BY(Customer.FirstName.DESC()).
|
ORDER_BY(Customer.FirstName.DESC()).
|
||||||
Query(db, &customersDesc)
|
Query(db, &customersDesc)
|
||||||
|
|
@ -1164,7 +1164,7 @@ func TestSelectOrderByAscDesc(t *testing.T) {
|
||||||
testutils.AssertDeepEqual(t, firstCustomerAsc, lastCustomerDesc)
|
testutils.AssertDeepEqual(t, firstCustomerAsc, lastCustomerDesc)
|
||||||
testutils.AssertDeepEqual(t, lastCustomerAsc, firstCustomerDesc)
|
testutils.AssertDeepEqual(t, lastCustomerAsc, firstCustomerDesc)
|
||||||
|
|
||||||
customersAscDesc := []model.Customer{}
|
var customersAscDesc []model.Customer
|
||||||
err = Customer.SELECT(Customer.CustomerID, Customer.FirstName, Customer.LastName).
|
err = Customer.SELECT(Customer.CustomerID, Customer.FirstName, Customer.LastName).
|
||||||
ORDER_BY(Customer.FirstName.ASC(), Customer.LastName.DESC()).
|
ORDER_BY(Customer.FirstName.ASC(), Customer.LastName.DESC()).
|
||||||
Query(db, &customersAscDesc)
|
Query(db, &customersAscDesc)
|
||||||
|
|
@ -1187,6 +1187,233 @@ func TestSelectOrderByAscDesc(t *testing.T) {
|
||||||
testutils.AssertDeepEqual(t, customerAscDesc327, customersAscDesc[327])
|
testutils.AssertDeepEqual(t, customerAscDesc327, customersAscDesc[327])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOrderBy(t *testing.T) {
|
||||||
|
|
||||||
|
t.Run("default", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate,
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("NULLS FIRST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.NULLS_FIRST(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date NULLS FIRST
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("NULLS LAST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.NULLS_LAST(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date NULLS LAST
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ASC", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.ASC(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date ASC
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ASC NULLS FIRST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.ASC().NULLS_FIRST(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date ASC NULLS FIRST
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ASC NULLS LAST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.ASC().NULLS_LAST(),
|
||||||
|
).LIMIT(200).OFFSET(15800)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date ASC NULLS LAST
|
||||||
|
LIMIT 200
|
||||||
|
OFFSET 15800;
|
||||||
|
`)
|
||||||
|
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DESC", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.DESC(),
|
||||||
|
).LIMIT(200).OFFSET(15800)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date DESC
|
||||||
|
LIMIT 200
|
||||||
|
OFFSET 15800;
|
||||||
|
`)
|
||||||
|
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DESC NULLS LAST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.DESC().NULLS_LAST(),
|
||||||
|
).LIMIT(200).OFFSET(15800)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date DESC NULLS LAST
|
||||||
|
LIMIT 200
|
||||||
|
OFFSET 15800;
|
||||||
|
`)
|
||||||
|
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DESC NULLS FIRST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.DESC().NULLS_FIRST(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM dvds.rental
|
||||||
|
ORDER BY rental.return_date DESC NULLS FIRST
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestSelectFullJoin(t *testing.T) {
|
func TestSelectFullJoin(t *testing.T) {
|
||||||
expectedSQL := `
|
expectedSQL := `
|
||||||
SELECT customer.customer_id AS "customer.customer_id",
|
SELECT customer.customer_id AS "customer.customer_id",
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,233 @@ ORDER BY payment.customer_id, SUM(payment.amount) ASC;
|
||||||
requireLogged(t, query)
|
requireLogged(t, query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestOrderBy(t *testing.T) {
|
||||||
|
|
||||||
|
t.Run("default", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate,
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM rental
|
||||||
|
ORDER BY rental.return_date
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("NULLS FIRST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.NULLS_FIRST(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM rental
|
||||||
|
ORDER BY rental.return_date NULLS FIRST
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("NULLS LAST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.NULLS_LAST(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM rental
|
||||||
|
ORDER BY rental.return_date NULLS LAST
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ASC", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.ASC(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM rental
|
||||||
|
ORDER BY rental.return_date ASC
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ASC NULLS FIRST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.ASC().NULLS_FIRST(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM rental
|
||||||
|
ORDER BY rental.return_date ASC NULLS FIRST
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("ASC NULLS LAST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.ASC().NULLS_LAST(),
|
||||||
|
).LIMIT(200).OFFSET(15800)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM rental
|
||||||
|
ORDER BY rental.return_date ASC NULLS LAST
|
||||||
|
LIMIT 200
|
||||||
|
OFFSET 15800;
|
||||||
|
`)
|
||||||
|
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DESC", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.DESC(),
|
||||||
|
).LIMIT(200).OFFSET(15800)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM rental
|
||||||
|
ORDER BY rental.return_date DESC
|
||||||
|
LIMIT 200
|
||||||
|
OFFSET 15800;
|
||||||
|
`)
|
||||||
|
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DESC NULLS LAST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.DESC().NULLS_LAST(),
|
||||||
|
).LIMIT(200).OFFSET(15800)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM rental
|
||||||
|
ORDER BY rental.return_date DESC NULLS LAST
|
||||||
|
LIMIT 200
|
||||||
|
OFFSET 15800;
|
||||||
|
`)
|
||||||
|
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("DESC NULLS FIRST", func(t *testing.T) {
|
||||||
|
stmt := SELECT(
|
||||||
|
Rental.AllColumns,
|
||||||
|
).FROM(
|
||||||
|
Rental,
|
||||||
|
).ORDER_BY(
|
||||||
|
Rental.ReturnDate.DESC().NULLS_FIRST(),
|
||||||
|
).LIMIT(200)
|
||||||
|
|
||||||
|
testutils.AssertDebugStatementSql(t, stmt, `
|
||||||
|
SELECT rental.rental_id AS "rental.rental_id",
|
||||||
|
rental.rental_date AS "rental.rental_date",
|
||||||
|
rental.inventory_id AS "rental.inventory_id",
|
||||||
|
rental.customer_id AS "rental.customer_id",
|
||||||
|
rental.return_date AS "rental.return_date",
|
||||||
|
rental.staff_id AS "rental.staff_id",
|
||||||
|
rental.last_update AS "rental.last_update"
|
||||||
|
FROM rental
|
||||||
|
ORDER BY rental.return_date DESC NULLS FIRST
|
||||||
|
LIMIT 200;
|
||||||
|
`)
|
||||||
|
|
||||||
|
require.NoError(t, stmt.Query(db, &struct{}{}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestAggregateFunctionDistinct(t *testing.T) {
|
func TestAggregateFunctionDistinct(t *testing.T) {
|
||||||
stmt := SELECT(
|
stmt := SELECT(
|
||||||
Payment.CustomerID,
|
Payment.CustomerID,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue