mirror of
https://github.com/ent/ent.git
synced 2026-05-22 09:31:45 +03:00
dialect/sql/sqlgraph: ignore ORDER BY clauses in COUNT queries (#3226)
This commit is contained in:
@@ -2744,6 +2744,12 @@ func (s *Selector) OrderExpr(exprs ...Querier) *Selector {
|
||||
return s
|
||||
}
|
||||
|
||||
// ClearOrder clears the ORDER BY clause to be empty.
|
||||
func (s *Selector) ClearOrder() *Selector {
|
||||
s.order = nil
|
||||
return s
|
||||
}
|
||||
|
||||
// GroupBy appends the `GROUP BY` clause to the `SELECT` statement.
|
||||
func (s *Selector) GroupBy(columns ...string) *Selector {
|
||||
s.group = append(s.group, columns...)
|
||||
|
||||
@@ -1681,6 +1681,17 @@ func TestSelector_OrderByExpr(t *testing.T) {
|
||||
require.Equal(t, []any{28, 1, 2}, args)
|
||||
}
|
||||
|
||||
func TestSelector_ClearOrder(t *testing.T) {
|
||||
query, args := Select("*").
|
||||
From(Table("users")).
|
||||
OrderBy("name").
|
||||
ClearOrder().
|
||||
OrderBy("id").
|
||||
Query()
|
||||
require.Equal(t, "SELECT * FROM `users` ORDER BY `id`", query)
|
||||
require.Empty(t, args)
|
||||
}
|
||||
|
||||
func TestSelector_SelectExpr(t *testing.T) {
|
||||
query, args := SelectExpr(
|
||||
Expr("?", "a"),
|
||||
@@ -1716,93 +1727,93 @@ func TestSelector_SelectExpr(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSelector_Union(t *testing.T) {
|
||||
query, args := Dialect(dialect.Postgres).
|
||||
Select("*").
|
||||
From(Table("users")).
|
||||
Where(EQ("active", true)).
|
||||
Union(
|
||||
Select("*").
|
||||
From(Table("old_users1")).
|
||||
Where(
|
||||
And(
|
||||
EQ("is_active", true),
|
||||
GT("age", 20),
|
||||
),
|
||||
),
|
||||
).
|
||||
UnionAll(
|
||||
Select("*").
|
||||
From(Table("old_users2")).
|
||||
Where(
|
||||
And(
|
||||
EQ("is_active", "true"),
|
||||
LT("age", 18),
|
||||
),
|
||||
),
|
||||
).
|
||||
Query()
|
||||
require.Equal(t, `SELECT * FROM "users" WHERE "active" UNION SELECT * FROM "old_users1" WHERE "is_active" AND "age" > $1 UNION ALL SELECT * FROM "old_users2" WHERE "is_active" = $2 AND "age" < $3`, query)
|
||||
require.Equal(t, []any{20, "true", 18}, args)
|
||||
query, args := Dialect(dialect.Postgres).
|
||||
Select("*").
|
||||
From(Table("users")).
|
||||
Where(EQ("active", true)).
|
||||
Union(
|
||||
Select("*").
|
||||
From(Table("old_users1")).
|
||||
Where(
|
||||
And(
|
||||
EQ("is_active", true),
|
||||
GT("age", 20),
|
||||
),
|
||||
),
|
||||
).
|
||||
UnionAll(
|
||||
Select("*").
|
||||
From(Table("old_users2")).
|
||||
Where(
|
||||
And(
|
||||
EQ("is_active", "true"),
|
||||
LT("age", 18),
|
||||
),
|
||||
),
|
||||
).
|
||||
Query()
|
||||
require.Equal(t, `SELECT * FROM "users" WHERE "active" UNION SELECT * FROM "old_users1" WHERE "is_active" AND "age" > $1 UNION ALL SELECT * FROM "old_users2" WHERE "is_active" = $2 AND "age" < $3`, query)
|
||||
require.Equal(t, []any{20, "true", 18}, args)
|
||||
}
|
||||
|
||||
func TestSelector_Except(t *testing.T) {
|
||||
query, args := Dialect(dialect.Postgres).
|
||||
Select("*").
|
||||
From(Table("users")).
|
||||
Where(EQ("active", true)).
|
||||
Except(
|
||||
Select("*").
|
||||
From(Table("old_users1")).
|
||||
Where(
|
||||
And(
|
||||
EQ("is_active", true),
|
||||
GT("age", 20),
|
||||
),
|
||||
),
|
||||
).
|
||||
ExceptAll(
|
||||
Select("*").
|
||||
From(Table("old_users2")).
|
||||
Where(
|
||||
And(
|
||||
EQ("is_active", "true"),
|
||||
LT("age", 18),
|
||||
),
|
||||
),
|
||||
).
|
||||
Query()
|
||||
require.Equal(t, `SELECT * FROM "users" WHERE "active" EXCEPT SELECT * FROM "old_users1" WHERE "is_active" AND "age" > $1 EXCEPT ALL SELECT * FROM "old_users2" WHERE "is_active" = $2 AND "age" < $3`, query)
|
||||
require.Equal(t, []any{20, "true", 18}, args)
|
||||
query, args := Dialect(dialect.Postgres).
|
||||
Select("*").
|
||||
From(Table("users")).
|
||||
Where(EQ("active", true)).
|
||||
Except(
|
||||
Select("*").
|
||||
From(Table("old_users1")).
|
||||
Where(
|
||||
And(
|
||||
EQ("is_active", true),
|
||||
GT("age", 20),
|
||||
),
|
||||
),
|
||||
).
|
||||
ExceptAll(
|
||||
Select("*").
|
||||
From(Table("old_users2")).
|
||||
Where(
|
||||
And(
|
||||
EQ("is_active", "true"),
|
||||
LT("age", 18),
|
||||
),
|
||||
),
|
||||
).
|
||||
Query()
|
||||
require.Equal(t, `SELECT * FROM "users" WHERE "active" EXCEPT SELECT * FROM "old_users1" WHERE "is_active" AND "age" > $1 EXCEPT ALL SELECT * FROM "old_users2" WHERE "is_active" = $2 AND "age" < $3`, query)
|
||||
require.Equal(t, []any{20, "true", 18}, args)
|
||||
}
|
||||
|
||||
func TestSelector_Intersect(t *testing.T) {
|
||||
query, args := Dialect(dialect.Postgres).
|
||||
Select("*").
|
||||
From(Table("users")).
|
||||
Where(EQ("active", true)).
|
||||
Intersect(
|
||||
Select("*").
|
||||
From(Table("old_users1")).
|
||||
Where(
|
||||
And(
|
||||
EQ("is_active", true),
|
||||
GT("age", 20),
|
||||
),
|
||||
),
|
||||
).
|
||||
IntersectAll(
|
||||
Select("*").
|
||||
From(Table("old_users2")).
|
||||
Where(
|
||||
And(
|
||||
EQ("is_active", "true"),
|
||||
LT("age", 18),
|
||||
),
|
||||
),
|
||||
).
|
||||
Query()
|
||||
require.Equal(t, `SELECT * FROM "users" WHERE "active" INTERSECT SELECT * FROM "old_users1" WHERE "is_active" AND "age" > $1 INTERSECT ALL SELECT * FROM "old_users2" WHERE "is_active" = $2 AND "age" < $3`, query)
|
||||
require.Equal(t, []any{20, "true", 18}, args)
|
||||
query, args := Dialect(dialect.Postgres).
|
||||
Select("*").
|
||||
From(Table("users")).
|
||||
Where(EQ("active", true)).
|
||||
Intersect(
|
||||
Select("*").
|
||||
From(Table("old_users1")).
|
||||
Where(
|
||||
And(
|
||||
EQ("is_active", true),
|
||||
GT("age", 20),
|
||||
),
|
||||
),
|
||||
).
|
||||
IntersectAll(
|
||||
Select("*").
|
||||
From(Table("old_users2")).
|
||||
Where(
|
||||
And(
|
||||
EQ("is_active", "true"),
|
||||
LT("age", 18),
|
||||
),
|
||||
),
|
||||
).
|
||||
Query()
|
||||
require.Equal(t, `SELECT * FROM "users" WHERE "active" INTERSECT SELECT * FROM "old_users1" WHERE "is_active" AND "age" > $1 INTERSECT ALL SELECT * FROM "old_users2" WHERE "is_active" = $2 AND "age" < $3`, query)
|
||||
require.Equal(t, []any{20, "true", 18}, args)
|
||||
}
|
||||
|
||||
func TestSelector_SetOperatorWithRecursive(t *testing.T) {
|
||||
|
||||
@@ -645,6 +645,11 @@ func (q *query) count(ctx context.Context, drv dialect.Driver) (int, error) {
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// Remove any ORDER BY clauses present in the COUNT query as
|
||||
// they are not allowed in some databases, such as PostgreSQL.
|
||||
if q.Order != nil {
|
||||
selector.ClearOrder()
|
||||
}
|
||||
// If no columns were selected in count,
|
||||
// the default selection is by node ids.
|
||||
columns := q.Node.Columns
|
||||
|
||||
@@ -2198,11 +2198,11 @@ func TestQueryNodes(t *testing.T) {
|
||||
AddRow(1, 10, nil, nil, nil).
|
||||
AddRow(2, 20, "", 0, 0).
|
||||
AddRow(3, 30, "a8m", 1, 1))
|
||||
mock.ExpectQuery(escape("SELECT COUNT(DISTINCT `users`.`id`) FROM `users` WHERE `age` < ? ORDER BY `id` LIMIT 3 OFFSET 4 FOR UPDATE NOWAIT")).
|
||||
mock.ExpectQuery(escape("SELECT COUNT(DISTINCT `users`.`id`) FROM `users` WHERE `age` < ? LIMIT 3 OFFSET 4 FOR UPDATE NOWAIT")).
|
||||
WithArgs(40).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"COUNT"}).
|
||||
AddRow(3))
|
||||
mock.ExpectQuery(escape("SELECT COUNT(DISTINCT `users`.`name`) FROM `users` WHERE `age` < ? ORDER BY `id` LIMIT 3 OFFSET 4 FOR UPDATE NOWAIT")).
|
||||
mock.ExpectQuery(escape("SELECT COUNT(DISTINCT `users`.`name`) FROM `users` WHERE `age` < ? LIMIT 3 OFFSET 4 FOR UPDATE NOWAIT")).
|
||||
WithArgs(40).
|
||||
WillReturnRows(sqlmock.NewRows([]string{"COUNT"}).
|
||||
AddRow(3))
|
||||
|
||||
Reference in New Issue
Block a user