// +build go1.8 package sqlx import ( "context" "database/sql" ) // A union interface of contextPreparer and binder, required to be able to // prepare named statements with context (as the bindtype must be determined). type namedPreparerContext interface { PreparerContext binder } func prepareNamedContext(ctx context.Context, p namedPreparerContext, query string) (*NamedStmt, error) { bindType := BindType(p.DriverName()) q, args, err := compileNamedQuery([]byte(query), bindType) if err != nil { return nil, err } stmt, err := PreparexContext(ctx, p, q) if err != nil { return nil, err } return &NamedStmt{ QueryString: q, Params: args, Stmt: stmt, }, nil } // ExecContext executes a named statement using the struct passed. // Any named placeholder parameters are replaced with fields from arg. func (n *NamedStmt) ExecContext(ctx context.Context, arg interface{}) (sql.Result, error) { args, err := bindAnyArgs(n.Params, arg, n.Stmt.Mapper) if err != nil { return *new(sql.Result), err } return n.Stmt.ExecContext(ctx, args...) } // QueryContext executes a named statement using the struct argument, returning rows. // Any named placeholder parameters are replaced with fields from arg. func (n *NamedStmt) QueryContext(ctx context.Context, arg interface{}) (*sql.Rows, error) { args, err := bindAnyArgs(n.Params, arg, n.Stmt.Mapper) if err != nil { return nil, err } return n.Stmt.QueryContext(ctx, args...) } // QueryRowContext executes a named statement against the database. Because sqlx cannot // create a *sql.Row with an error condition pre-set for binding errors, sqlx // returns a *sqlx.Row instead. // Any named placeholder parameters are replaced with fields from arg. func (n *NamedStmt) QueryRowContext(ctx context.Context, arg interface{}) *Row { args, err := bindAnyArgs(n.Params, arg, n.Stmt.Mapper) if err != nil { return &Row{err: err} } return n.Stmt.QueryRowxContext(ctx, args...) } // MustExecContext execs a NamedStmt, panicing on error // Any named placeholder parameters are replaced with fields from arg. func (n *NamedStmt) MustExecContext(ctx context.Context, arg interface{}) sql.Result { res, err := n.ExecContext(ctx, arg) if err != nil { panic(err) } return res } // QueryxContext using this NamedStmt // Any named placeholder parameters are replaced with fields from arg. func (n *NamedStmt) QueryxContext(ctx context.Context, arg interface{}) (*Rows, error) { r, err := n.QueryContext(ctx, arg) if err != nil { return nil, err } return &Rows{Rows: r, Mapper: n.Stmt.Mapper, unsafe: isUnsafe(n)}, err } // QueryRowxContext this NamedStmt. Because of limitations with QueryRow, this is // an alias for QueryRow. // Any named placeholder parameters are replaced with fields from arg. func (n *NamedStmt) QueryRowxContext(ctx context.Context, arg interface{}) *Row { return n.QueryRowContext(ctx, arg) } // SelectContext using this NamedStmt // Any named placeholder parameters are replaced with fields from arg. func (n *NamedStmt) SelectContext(ctx context.Context, dest interface{}, arg interface{}) error { rows, err := n.QueryxContext(ctx, arg) if err != nil { return err } // if something happens here, we want to make sure the rows are Closed defer rows.Close() return scanAll(rows, dest, false) } // GetContext using this NamedStmt // Any named placeholder parameters are replaced with fields from arg. func (n *NamedStmt) GetContext(ctx context.Context, dest interface{}, arg interface{}) error { r := n.QueryRowxContext(ctx, arg) return r.scanAny(dest, false) } // NamedQueryContext binds a named query and then runs Query on the result using the // provided Ext (sqlx.Tx, sqlx.Db). It works with both structs and with // map[string]interface{} types. func NamedQueryContext(ctx context.Context, e ExtContext, query string, arg interface{}) (*Rows, error) { q, args, err := bindNamedMapper(BindType(e.DriverName()), query, arg, mapperFor(e)) if err != nil { return nil, err } return e.QueryxContext(ctx, q, args...) } // NamedExecContext uses BindStruct to get a query executable by the driver and // then runs Exec on the result. Returns an error from the binding // or the query excution itself. func NamedExecContext(ctx context.Context, e ExtContext, query string, arg interface{}) (sql.Result, error) { q, args, err := bindNamedMapper(BindType(e.DriverName()), query, arg, mapperFor(e)) if err != nil { return nil, err } return e.ExecContext(ctx, q, args...) }