diff --git a/sqlx.go b/sqlx.go index 7435e48..bf067dc 100644 --- a/sqlx.go +++ b/sqlx.go @@ -563,6 +563,10 @@ func (q *qStmt) Queryx(query string, args ...interface{}) (*Rows, error) { return &Rows{Rows: r, unsafe: q.Stmt.unsafe, Mapper: q.Stmt.Mapper}, err } +func (q *qStmt) QueryRow(query string, args ...interface{}) *sql.Row { + return q.Stmt.QueryRow(args...) +} + func (q *qStmt) QueryRowx(query string, args ...interface{}) *Row { rows, err := q.Stmt.Query(args...) return &Row{rows: rows, err: err, unsafe: q.Stmt.unsafe, Mapper: q.Stmt.Mapper} diff --git a/sqlx_context.go b/sqlx_context.go index dc90bc6..59ddf65 100644 --- a/sqlx_context.go +++ b/sqlx_context.go @@ -317,6 +317,12 @@ func (tx *Tx) PrepareNamedContext(ctx context.Context, query string) (*NamedStmt return prepareNamedContext(ctx, tx, query) } +// NamedQueryContext using this Tx. +// Any named placeholder parameters are replaced with fields from arg. +func (tx *Tx) NamedQueryContext(ctx context.Context, query string, arg interface{}) (*Rows, error) { + return NamedQueryContext(ctx, tx, query, arg) +} + // MustExecContext runs MustExecContext within a transaction. // Any placeholder parameters are replaced with supplied args. func (tx *Tx) MustExecContext(ctx context.Context, query string, args ...interface{}) sql.Result { @@ -405,6 +411,10 @@ func (q *qStmt) QueryxContext(ctx context.Context, query string, args ...interfa return &Rows{Rows: r, unsafe: q.Stmt.unsafe, Mapper: q.Stmt.Mapper}, err } +func (q *qStmt) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row { + return q.Stmt.QueryRowContext(ctx, args...) +} + func (q *qStmt) QueryRowxContext(ctx context.Context, query string, args ...interface{}) *Row { rows, err := q.Stmt.QueryContext(ctx, args...) return &Row{rows: rows, err: err, unsafe: q.Stmt.unsafe, Mapper: q.Stmt.Mapper} diff --git a/sqlx_context_test.go b/sqlx_context_test.go index eebbd1a..30126a0 100644 --- a/sqlx_context_test.go +++ b/sqlx_context_test.go @@ -807,6 +807,25 @@ func TestUsageContext(t *testing.T) { if err != nil { t.Fatal(err) } + rows, err := tx.NamedQueryContext(ctx, "SELECT * FROM person WHERE first_name=:first", map[string]interface{}{"first": "Bin"}) + if err != nil { + t.Fatal(err) + } + + ben := &Person{} + for rows.Next() { + err = rows.StructScan(ben) + if err != nil { + t.Fatal(err) + } + if ben.FirstName != "Bin" { + t.Fatal("Expected first name of `Bin`, got " + ben.FirstName) + } + if ben.LastName != "Smuth" { + t.Fatal("Expected first name of `Smuth`, got " + ben.LastName) + } + } + tstmt2 := tx.Stmtx(stmt2) row2 := tstmt2.QueryRowx("Jason") err = row2.StructScan(&jason) @@ -880,7 +899,7 @@ func TestUsageContext(t *testing.T) { t.Errorf("Expected the right telcodes, got %#v", places) } - rows, err := db.QueryxContext(ctx, "SELECT * FROM place") + rows, err = db.QueryxContext(ctx, "SELECT * FROM place") if err != nil { t.Fatal(err) } @@ -940,7 +959,7 @@ func TestUsageContext(t *testing.T) { t.Fatal(err) } - ben := &Person{} + ben = &Person{} for rows.Next() { err = rows.StructScan(ben) if err != nil { diff --git a/stmt_query_row_test.go b/stmt_query_row_test.go new file mode 100644 index 0000000..df36e4a --- /dev/null +++ b/stmt_query_row_test.go @@ -0,0 +1,28 @@ +package sqlx + +import ( + "context" + "testing" +) + +// *Stmt promotes (*sql.Stmt).QueryRowContext(ctx, args...): the first +// variadic argument is a bind argument, not a query. Guards against a method +// on *Stmt shadowing it (the mistake in upstream #941). +func TestStmtQueryRowContextArgs(t *testing.T) { + RunWithSchema(defaultSchema, t, func(db *DB, t *testing.T, now string) { + loadDefaultFixture(db, t) + ctx := context.Background() + stmt, err := db.PreparexContext(ctx, db.Rebind("SELECT last_name FROM person WHERE first_name=?")) + if err != nil { + t.Fatal(err) + } + defer stmt.Close() + var last string + if err := stmt.QueryRowContext(ctx, "Jason").Scan(&last); err != nil || last != "Moiron" { + t.Errorf("stmt.QueryRowContext(ctx, \"Jason\").Scan: err=%v last=%q, want nil and Moiron", err, last) + } + if err := stmt.QueryRow("Jason").Scan(&last); err != nil || last != "Moiron" { + t.Errorf("stmt.QueryRow(\"Jason\").Scan: err=%v last=%q, want nil and Moiron", err, last) + } + }) +}