2025-12-29 19:23:49 +08:00
|
|
|
|
package repository
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"context"
|
|
|
|
|
|
"database/sql"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type sqlQueryer interface {
|
|
|
|
|
|
QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// scanSingleRow executes a query and scans the first row into dest.
|
|
|
|
|
|
// If no rows are returned, sql.ErrNoRows is returned.
|
|
|
|
|
|
// 设计目的:仅依赖 QueryContext,避免 QueryRowContext 对 *sql.Tx 的强绑定,
|
|
|
|
|
|
// 让 ent.Tx 也能作为 sqlExecutor/Queryer 使用。
|
2025-12-30 16:41:45 +08:00
|
|
|
|
func scanSingleRow(ctx context.Context, q sqlQueryer, query string, args []any, dest ...any) (err error) {
|
2025-12-29 19:23:49 +08:00
|
|
|
|
rows, err := q.QueryContext(ctx, query, args...)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
2025-12-30 16:41:45 +08:00
|
|
|
|
defer func() {
|
|
|
|
|
|
if closeErr := rows.Close(); closeErr != nil && err == nil {
|
|
|
|
|
|
err = closeErr
|
|
|
|
|
|
}
|
|
|
|
|
|
}()
|
2025-12-29 19:23:49 +08:00
|
|
|
|
|
|
|
|
|
|
if !rows.Next() {
|
2025-12-30 16:41:45 +08:00
|
|
|
|
if err = rows.Err(); err != nil {
|
2025-12-29 19:23:49 +08:00
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
return sql.ErrNoRows
|
|
|
|
|
|
}
|
2025-12-30 16:41:45 +08:00
|
|
|
|
if err = rows.Scan(dest...); err != nil {
|
|
|
|
|
|
return err
|
|
|
|
|
|
}
|
|
|
|
|
|
if err = rows.Err(); err != nil {
|
2025-12-29 19:23:49 +08:00
|
|
|
|
return err
|
|
|
|
|
|
}
|
2025-12-30 16:41:45 +08:00
|
|
|
|
return nil
|
2025-12-29 19:23:49 +08:00
|
|
|
|
}
|