diff --git a/backend/v3/domain/instance.go b/backend/v3/domain/instance.go index acbee10c1b..82e6ac451f 100644 --- a/backend/v3/domain/instance.go +++ b/backend/v3/domain/instance.go @@ -87,7 +87,7 @@ type InstanceRepository interface { // Member() MemberRepository Get(ctx context.Context, opts ...database.Condition) (*Instance, error) - List(ctx context.Context, opts ...database.Condition) ([]*Instance, error) + List(ctx context.Context, opts ...database.Condition) ([]Instance, error) Create(ctx context.Context, instance *Instance) error Update(ctx context.Context, condition database.Condition, changes ...database.Change) (int64, error) diff --git a/backend/v3/storage/database/database.go b/backend/v3/storage/database/database.go index f962132fa0..f94037eaa5 100644 --- a/backend/v3/storage/database/database.go +++ b/backend/v3/storage/database/database.go @@ -2,6 +2,8 @@ package database import ( "context" + + "github.com/jackc/pgx/v5" ) // Pool is a connection pool. e.g. pgxpool @@ -57,8 +59,5 @@ type Row interface { // Rows is an abstraction of sql.Rows. type Rows interface { - Row - Next() bool - Close() error - Err() error + pgx.Rows } diff --git a/backend/v3/storage/database/dialect/postgres/rows.go b/backend/v3/storage/database/dialect/postgres/rows.go index 891a2a3f46..7a36979a5e 100644 --- a/backend/v3/storage/database/dialect/postgres/rows.go +++ b/backend/v3/storage/database/dialect/postgres/rows.go @@ -9,10 +9,3 @@ import ( var _ database.Rows = (*Rows)(nil) type Rows struct{ pgx.Rows } - -// Close implements [database.Rows]. -// Subtle: this method shadows the method (Rows).Close of Rows.Rows. -func (r *Rows) Close() error { - r.Rows.Close() - return nil -} diff --git a/backend/v3/storage/database/repository/instance.go b/backend/v3/storage/database/repository/instance.go index 8278eeb24e..3037bbd112 100644 --- a/backend/v3/storage/database/repository/instance.go +++ b/backend/v3/storage/database/repository/instance.go @@ -5,6 +5,7 @@ import ( "errors" "time" + "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgconn" "github.com/zitadel/zitadel/backend/v3/domain" "github.com/zitadel/zitadel/backend/v3/storage/database" @@ -42,11 +43,17 @@ func (i *instance) Get(ctx context.Context, opts ...database.Condition) (*domain andCondition := database.And(opts...) i.writeCondition(&builder, andCondition) - return scanInstance(i.client.QueryRow(ctx, builder.String(), builder.Args()...)) + rows, err := i.client.Query(ctx, builder.String(), builder.Args()...) + if err != nil { + return nil, err + } + defer rows.Close() + + return scanInstance(rows) } // List implements [domain.InstanceRepository]. -func (i *instance) List(ctx context.Context, opts ...database.Condition) ([]*domain.Instance, error) { +func (i *instance) List(ctx context.Context, opts ...database.Condition) ([]domain.Instance, error) { builder := database.StatementBuilder{} builder.WriteString(queryInstanceStmt) @@ -214,20 +221,8 @@ func (i *instance) writeCondition( condition.Write(builder) } -func scanInstance(scanner database.Scanner) (*domain.Instance, error) { - var instance domain.Instance - err := scanner.Scan( - &instance.ID, - &instance.Name, - &instance.DefaultOrgID, - &instance.IAMProjectID, - &instance.ConsoleClientID, - &instance.ConsoleAppID, - &instance.DefaultLanguage, - &instance.CreatedAt, - &instance.UpdatedAt, - &instance.DeletedAt, - ) +func scanInstance(rows database.Rows) (*domain.Instance, error) { + instance, err := pgx.CollectOneRow[domain.Instance](rows, pgx.RowToStructByNameLax[domain.Instance]) if err != nil { // if no results returned, this is not a error // it just means the instance was not found @@ -241,29 +236,16 @@ func scanInstance(scanner database.Scanner) (*domain.Instance, error) { return &instance, nil } -func scanInstances(rows database.Rows) ([]*domain.Instance, error) { - instances := make([]*domain.Instance, 0) - for rows.Next() { - - var instance domain.Instance - err := rows.Scan( - &instance.ID, - &instance.Name, - &instance.DefaultOrgID, - &instance.IAMProjectID, - &instance.ConsoleClientID, - &instance.ConsoleAppID, - &instance.DefaultLanguage, - &instance.CreatedAt, - &instance.UpdatedAt, - &instance.DeletedAt, - ) - if err != nil { - return nil, err +func scanInstances(rows database.Rows) ([]domain.Instance, error) { + instances, err := pgx.CollectRows[domain.Instance](rows, pgx.RowToStructByNameLax[domain.Instance]) + if err != nil { + // if no results returned, this is not a error + // it just means the instance was not found + // the caller should check if the returned instance is nil + if err.Error() == "no rows in result set" { + return nil, nil } - - instances = append(instances, &instance) - + return nil, err } return instances, nil } diff --git a/backend/v3/storage/database/repository/user.go b/backend/v3/storage/database/repository/user.go index 1adc22c3d6..a20e6283a1 100644 --- a/backend/v3/storage/database/repository/user.go +++ b/backend/v3/storage/database/repository/user.go @@ -58,13 +58,8 @@ func (u *user) List(ctx context.Context, opts ...database.QueryOption) (users [] if err != nil { return nil, err } - defer func() { - closeErr := rows.Close() - if err != nil { - return - } - err = closeErr - }() + defer rows.Close() + for rows.Next() { user, err := scanUser(rows) if err != nil {