Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions dialect/psql/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,11 @@ func (v *ViewQuery[T, Tslice]) Count(ctx context.Context, exec bob.Executor) (in

// Exists checks if there is any matching row
func (v *ViewQuery[T, Tslice]) Exists(ctx context.Context, exec bob.Executor) (bool, error) {
count, err := v.Count(ctx, exec)
return count > 0, err
ctx, err := v.RunHooks(ctx, exec)
if err != nil {
return false, err
}
return bob.One(ctx, exec, Select(sm.Columns(Exists(v.BaseQuery))), scan.SingleColumnMapper[bool])
}

// asCountQuery clones and rewrites an existing query to a count query
Expand Down
34 changes: 34 additions & 0 deletions dialect/psql/view_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package psql
import (
"bytes"
"context"
"strings"
"testing"

_ "github.com/lib/pq"
Expand Down Expand Up @@ -77,6 +78,39 @@ func TestSomeViewQueryWithoutSchema(t *testing.T) {
}
}

func TestSomeViewExistsUsesExistsExpression(t *testing.T) {
ctx := context.Background()
if _, err := testDB.ExecContext(ctx, `CREATE TABLE exists_view_test (id BIGINT PRIMARY KEY)`); err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
if _, err := testDB.ExecContext(ctx, `DROP TABLE exists_view_test`); err != nil {
t.Error(err)
}
})
if _, err := testDB.ExecContext(ctx, `INSERT INTO exists_view_test (id) VALUES (1)`); err != nil {
t.Fatal(err)
}

view := NewView[int64, bob.Expression]("", "exists_view_test", Quote("id"))
var query strings.Builder
exists, err := view.Query(
sm.With("matching").As(Select(sm.Columns("id"), sm.From("exists_view_test"))),
sm.From("matching"),
sm.Where(Quote("id").EQ(Arg(1))),
).Exists(ctx, bob.DebugToWriter(testDB, &query))
if err != nil {
t.Fatal(err)
}
if !exists {
t.Fatal("expected matching row to exist")
}
got := query.String()
if !strings.Contains(got, "EXISTS ((") || !strings.Contains(got, "WITH") || strings.Contains(got, "count(1)") {
t.Fatalf("expected EXISTS query, got:\n%s", got)
}
}

func selectToString(t *testing.T, query bob.BaseQuery[*dialect.SelectQuery], argsLen int) string {
t.Helper()
ctx := context.Background()
Expand Down
Loading