One

クエリを実行し、単一の行を返します。scan.One のラッパーです。

使用方法

type userObj struct {
    ID   int
    Name string
}

ctx := context.Background()
db, err := bob.Open("postgres", "...")
if err != nil {
    // ...
}

q := psql.Select(...)
// user は userObj{} 型
user, err := bob.One(ctx, db, q, scan.StructMapper[userObj]())
if err != nil {
    // ...
}

特徴

  • 単一の結果: 1つの行のみを取得
  • 型安全: 構造体マッピングをサポート
  • エラーハンドリング: 結果が見つからない場合は sql.ErrNoRows を返す

使用例

基本的な使用

type User struct {
    ID    int    `db:"id"`
    Name  string `db:"name"`
    Email string `db:"email"`
}

query := psql.Select("id", "name", "email").
    From("users").
    Where(psql.Quote("id").EQ(psql.Arg(1)))

user, err := bob.One(ctx, db, query, scan.StructMapper[User]())
if err != nil {
    if errors.Is(err, sql.ErrNoRows) {
        // ユーザーが見つからない場合の処理
        return nil, fmt.Errorf("user not found")
    }
    return nil, err
}

fmt.Printf("User: %+v\n", user)

複雑なクエリの場合

type UserProfile struct {
    ID       int    `db:"id"`
    Name     string `db:"name"`
    Email    string `db:"email"`
    Profile  string `db:"profile"`
    PostCount int   `db:"post_count"`
}

query := psql.Select(
    psql.Quote("users", "id"),
    psql.Quote("users", "name"),
    psql.Quote("users", "email"),
    psql.Quote("profiles", "bio").As("profile"),
    psql.F("COUNT", psql.Quote("posts", "id")).As("post_count"),
).From("users").
    LeftJoin("profiles", psql.Quote("profiles", "user_id").EQ(psql.Quote("users", "id"))).
    LeftJoin("posts", psql.Quote("posts", "user_id").EQ(psql.Quote("users", "id"))).
    Where(psql.Quote("users", "id").EQ(psql.Arg(1))).
    GroupBy(psql.Quote("users", "id"), psql.Quote("profiles", "bio"))

userProfile, err := bob.One(ctx, db, query, scan.StructMapper[UserProfile]())
if err != nil {
    return nil, err
}

One は、単一の結果を期待するクエリに最適です。結果が見つからない場合やエラーが発生した場合は、適切なエラーを返します。