Skip to content

Commit

Permalink
add option to handle nil Valuers
Browse files Browse the repository at this point in the history
  • Loading branch information
sajanalexander committed Apr 22, 2024
1 parent 60a01d0 commit 3fd0221
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 2 deletions.
14 changes: 14 additions & 0 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import (
"github.com/jackc/pgx/v5/pgtype"
)

type AfterPgxConnectFunc func(ctx context.Context, pgxconn *Conn) error

// ConnConfig contains all the options used to establish a connection. It must be created by ParseConfig and
// then it can be modified. A manually initialized ConnConfig will cause ConnectConfig to panic.
type ConnConfig struct {
Expand All @@ -41,6 +43,11 @@ type ConnConfig struct {
// functionality can be controlled on a per query basis by passing a QueryExecMode as the first query argument.
DefaultQueryExecMode QueryExecMode

// AfterPgxConnect is utilized to modify the pgx.Conn value, such as adding options to the TypeMap value. This is
// called after the AfterConnect function is called, if supplied. If this returns an error, the connection attempt
// fails.
AfterPgxConnect AfterPgxConnectFunc

createdByParseConfig bool // Used to enforce created by ParseConfig rule.
}

Expand Down Expand Up @@ -259,6 +266,13 @@ func connect(ctx context.Context, config *ConnConfig) (c *Conn, err error) {
return nil, err
}

if config.AfterPgxConnect != nil {
if err := config.AfterPgxConnect(ctx, c); err != nil {
c.Close(ctx)
return nil, err
}
}

c.preparedStatements = make(map[string]*pgconn.StatementDescription)
c.doneChan = make(chan struct{})
c.closedChan = make(chan error)
Expand Down
15 changes: 15 additions & 0 deletions pgtype/pgtype.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ type Map struct {
// to be built up. There are default functions placed in this slice by NewMap(). In most cases these functions
// should run last. i.e. Additional functions should typically be prepended not appended.
TryWrapScanPlanFuncs []TryWrapScanPlanFunc

// NilHandlers is a slice of functions that is utilized to handle the case where a driver.NamedValue instance is considered
// nil by pgx, but may need to be subsituted for a different value.
NilHandlers []NilHandler
}

func NewMap() *Map {
Expand Down Expand Up @@ -1037,6 +1041,17 @@ func (plan *wrapPtrArrayReflectScanPlan) Scan(src []byte, target any) error {
return plan.next.Scan(src, &anyArrayArrayReflect{array: reflect.ValueOf(target).Elem()})
}

type NilHandler func(*driver.NamedValue) error

func (m *Map) TryNilHandling(nv *driver.NamedValue) error {
for _, f := range m.NilHandlers {
if err := f(nv); err != nil {
return err
}
}
return nil
}

// PlanScan prepares a plan to scan a value into target.
func (m *Map) PlanScan(oid uint32, formatCode int16, target any) ScanPlan {
oidMemo := m.memoizedScanPlans[oid]
Expand Down
12 changes: 10 additions & 2 deletions stdlib/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ import (
"time"

"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/internal/anynil"
"github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgtype"
"github.com/jackc/pgx/v5/pgxpool"
Expand Down Expand Up @@ -533,8 +534,15 @@ func (c *Conn) Ping(ctx context.Context) error {
return nil
}

func (c *Conn) CheckNamedValue(*driver.NamedValue) error {
// Underlying pgx supports sql.Scanner and driver.Valuer interfaces natively. So everything can be passed through directly.
func (c *Conn) CheckNamedValue(nv *driver.NamedValue) error {
// Underlying pgx supports sql.Scanner and driver.Valuer interfaces natively. If the Value itself is not nil, but
// can be considered nil, check to see if an option has been set up to handle it explicitly
if nv.Value != nil && anynil.Is(nv.Value) {
tm := c.conn.TypeMap()
if err := tm.TryNilHandling(nv); err != nil {
return err
}
}
return nil
}

Expand Down

0 comments on commit 3fd0221

Please sign in to comment.