From 50840e7ed1662d3284d0798b53df0b6a99c46294 Mon Sep 17 00:00:00 2001 From: Yoshiki Shibukawa Date: Fri, 19 Aug 2022 23:34:32 +0900 Subject: [PATCH] accept *[]map[string]interface{} as Select()'s dest (#10) accept *[]map[string]interface{} as Select()'s dest --- Dockerfile | 1 + e2e_test.go | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ twowaysql.go | 29 ++++++++++++++++++++++++++++- 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 51ec0f1..024f185 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,3 +4,4 @@ WORKDIR /go/src/twowaysql COPY . . RUN go install -v ./... +CMD ["go", "test", "-v", "./..."] \ No newline at end of file diff --git a/e2e_test.go b/e2e_test.go index 05a196d..c3c1267 100644 --- a/e2e_test.go +++ b/e2e_test.go @@ -75,6 +75,56 @@ func TestSelect(t *testing.T) { } +func TestSelectMap(t *testing.T) { + //このテストはinit.sqlに依存しています。 + //データベースは/postgres/init以下のsqlファイルを用いて初期化されている。 + db := open(t) + defer db.Close() + tw := New(db) + ctx := context.Background() + + // SELECT + var people []map[string]interface{} + var params = Info{ + MaxEmpNo: 3, + DeptNo: 12, + } + + expected := []map[string]interface{}{ + { + "first_name": "Evan", + "last_name": "MacMans", + "email": "evanmacmans@example.com", + }, + { + "first_name": "Malvina", + "last_name": "FitzSimons", + "email": "malvinafitzsimons@example.com", + }, + } + + sql := `-- comment + SELECT + first_name + , last_name + , email + FROM + persons + WHERE + employee_no < /*maxEmpNo*/1000 -- comment + /* IF deptNo */ + AND dept_no < /*deptNo*/1 + /* END */ + -- comment` + err := tw.Select(ctx, &people, sql, ¶ms) + if err != nil { + t.Errorf("select: failed: %v", err) + } + + assert.Check(t, cmp.DeepEqual(people, expected)) + +} + func TestUpdate(t *testing.T) { //このテストはinit.sqlに依存しています。 //データベースは/postgres/init以下のsqlファイルを用いて初期化されている。 diff --git a/twowaysql.go b/twowaysql.go index 2c3a5b1..2edc0b9 100644 --- a/twowaysql.go +++ b/twowaysql.go @@ -25,7 +25,6 @@ func New(db *sqlx.DB) *Twowaysql { // params takes a tagged struct. The tags format must be `twowaysql:"tag_name"`. // dest takes a pointer to a slice of a struct. The struct tag format must be `db:"tag_name"`. func (t *Twowaysql) Select(ctx context.Context, dest interface{}, query string, params interface{}) error { - eval, bindParams, err := Eval(query, params) if err != nil { return err @@ -33,6 +32,14 @@ func (t *Twowaysql) Select(ctx context.Context, dest interface{}, query string, q := t.db.Rebind(eval) + if destMap, ok := dest.(*[]map[string]interface{}); ok { + rows, err := t.db.QueryxContext(ctx, q, bindParams...) + if err != nil { + return err + } + return convertResultToMap(destMap, rows) + } + return t.db.SelectContext(ctx, dest, q, bindParams...) } @@ -137,6 +144,14 @@ func (t *TwowaysqlTx) Select(ctx context.Context, dest interface{}, query string q := t.tx.Rebind(eval) + if destMap, ok := dest.(*[]map[string]interface{}); ok { + rows, err := t.tx.QueryxContext(ctx, q, bindParams...) + if err != nil { + return err + } + return convertResultToMap(destMap, rows) + } + return t.tx.SelectContext(ctx, dest, q, bindParams...) } @@ -156,6 +171,18 @@ func (t *TwowaysqlTx) Exec(ctx context.Context, query string, params interface{} return t.tx.ExecContext(ctx, q, bindParams...) } +func convertResultToMap(dest *[]map[string]interface{}, rows *sqlx.Rows) error { + defer rows.Close() + for rows.Next() { + row := map[string]interface{}{} + if err := rows.MapScan(row); err != nil { + return err + } + *dest = append(*dest, row) + } + return nil +} + // Tx returns `*sqlx.Tx` func (t *TwowaysqlTx) Tx() *sqlx.Tx { return t.tx