diff --git a/internal/dbtest/db_test.go b/internal/dbtest/db_test.go index 8460070f3..1b394a3fc 100644 --- a/internal/dbtest/db_test.go +++ b/internal/dbtest/db_test.go @@ -254,6 +254,7 @@ func TestDB(t *testing.T) { {testJSONInterface}, {testJSONValuer}, {testSelectBool}, + {testRawQuery}, {testFKViolation}, {testWithForeignKeysAndRules}, {testWithForeignKeys}, @@ -820,6 +821,14 @@ func testSelectBool(t *testing.T, db *bun.DB) { require.False(t, flag) } +func testRawQuery(t *testing.T, db *bun.DB) { + var num int + err := db.Raw("SELECT ?", 123).Scan(ctx, &num) + + require.NoError(t, err) + require.Equal(t, 123, num) +} + func testFKViolation(t *testing.T, db *bun.DB) { type Deck struct { ID int `bun:",pk,autoincrement"` diff --git a/query_raw.go b/query_raw.go new file mode 100644 index 000000000..1c509f142 --- /dev/null +++ b/query_raw.go @@ -0,0 +1,47 @@ +package bun + +import ( + "context" + "github.com/uptrace/bun/schema" +) + +type RawQuery struct { + baseQuery + + query string + args []interface{} +} + +func (db *DB) Raw(query string, args ...interface{}) *RawQuery { + return &RawQuery{ + baseQuery: baseQuery{ + db: db, + conn: db.DB, + }, + query: query, + args: args, + } +} + +func (q *RawQuery) Scan(ctx context.Context, dest ...interface{}) error { + if q.err != nil { + return q.err + } + + model, err := q.getModel(dest) + if err != nil { + return err + } + + query := q.db.format(q.query, q.args) + _, err = q.scan(ctx, q, query, model, true) + return err +} + +func (q *RawQuery) AppendQuery(fmter schema.Formatter, b []byte) ([]byte, error) { + return fmter.AppendQuery(b, q.query, q.args), nil +} + +func (q *RawQuery) Operation() string { + return "SELECT" +}