回答編集履歴

2

typo

2020/06/06 04:02

投稿

d_tutuz
d_tutuz

スコア730

test CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- `LastInsertId` は Postgres のドライバーでは使えない (参照: [no LastInsertId available in Postgresql](https://github.com/jmoiron/sqlx/issues/245)) ため [`RETURNING`](https://www.postgresql.jp/document/11/html/dml-returning.html) 句を用いるのはどうでしょうか?`RETURNING` は `squirrel` のクエリビルダで付与するイメージです。
5
+ `LastInsertId` は PostgreSQL のドライバーでは使えない (参照: [no LastInsertId available in Postgresql](https://github.com/jmoiron/sqlx/issues/245)) ため [`RETURNING`](https://www.postgresql.jp/document/11/html/dml-returning.html) 句を用いるのはどうでしょうか?`RETURNING` は `squirrel` のクエリビルダで付与するイメージです。
6
6
 
7
7
 
8
8
 

1

追記いただいたコードをベースに全体的に書き換え

2020/06/06 04:02

投稿

d_tutuz
d_tutuz

スコア730

test CHANGED
@@ -1,39 +1,195 @@
1
- squirrel のどのメソッドを用いるかよって多少異なると思いますが、たとえば [InsertBuilder.ExecContext](https://godoc.org/github.com/Masterminds/squirrel#InsertBuilder.ExecContext) を用た場合の例を考えてみます
1
+ 追記いただいたコード(InsertHoge メソッド)ベース全体的に書き換えした。ローカルで試際は Docker などを用いて PostgreSQL に接続できる環境でお試しください。
2
+
3
+
4
+
5
+ `LastInsertId` は Postgres のドライバーでは使えない (参照: [no LastInsertId available in Postgresql](https://github.com/jmoiron/sqlx/issues/245)) ため [`RETURNING`](https://www.postgresql.jp/document/11/html/dml-returning.html) 句を用いるのはどうでしょうか?`RETURNING` は `squirrel` のクエリビルダで付与するイメージです。
6
+
7
+
8
+
9
+ ### コード
2
10
 
3
11
 
4
12
 
5
13
  ```go
6
14
 
15
+ package main
16
+
17
+
18
+
19
+ import (
20
+
21
+ "database/sql"
22
+
23
+ "fmt"
24
+
25
+
26
+
27
+ "github.com/jmoiron/sqlx"
28
+
29
+ _ "github.com/lib/pq"
30
+
31
+
32
+
33
+ sq "github.com/Masterminds/squirrel"
34
+
35
+ )
36
+
37
+
38
+
7
- func (b InsertBuilder) ExecContext(ctx context.Context) (sql.Result, error)
39
+ func (p *Postgres) InsertHoge(hoge *Hoge) (*Hoge, error) {
40
+
41
+ query, args, err := sq.StatementBuilder.PlaceholderFormat(sq.Dollar).
42
+
43
+ Insert("hoge").Columns("title").Values(hoge.Title).Suffix("RETURNING *").ToSql()
44
+
45
+
46
+
47
+ if err != nil {
48
+
49
+ return nil, err
50
+
51
+ }
52
+
53
+
54
+
55
+ tx, err := p.Beginx()
56
+
57
+ if err != nil {
58
+
59
+ return nil, err
60
+
61
+ }
62
+
63
+
64
+
65
+ var h Hoge
66
+
67
+ if err := tx.QueryRowx(query, args[0]).StructScan(&h); err != nil {
68
+
69
+ return nil, err
70
+
71
+ }
72
+
73
+
74
+
75
+ tx.Commit()
76
+
77
+
78
+
79
+ // エラーのときのロールバックの処理は割愛
80
+
81
+ return &h, nil
82
+
83
+ }
84
+
85
+
86
+
87
+ // ------------------------------------------------------------------------------------------------
88
+
89
+ // ローカルの Docker の起動
90
+
91
+ // $ docker run --name tmp-postgres -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -d -p 5432:5432 postgres
92
+
93
+ // ------------------------------------------------------------------------------------------------
94
+
95
+
96
+
97
+ func main() {
98
+
99
+ // Docker上のデータベースへの接続
100
+
101
+ db, err := sql.Open("postgres", fmt.Sprintf(
102
+
103
+ "user=%s password=%s host=%s port=%s dbname=%s sslmode=%s",
104
+
105
+ "postgres", "postgres", "localhost", "5432", "postgres", "disable",
106
+
107
+ ))
108
+
109
+ if err != nil {
110
+
111
+ panic(err)
112
+
113
+ }
114
+
115
+
116
+
117
+ // sqlxライブラリの使用
118
+
119
+ x := sqlx.NewDb(db, "postgres")
120
+
121
+
122
+
123
+ // Postgres構造体の値生成
124
+
125
+ p := &Postgres{x}
126
+
127
+
128
+
129
+ // クエリの実行
130
+
131
+ m, err := p.InsertHoge(&Hoge{Title: "gopher"})
132
+
133
+ if err != nil {
134
+
135
+ panic(err)
136
+
137
+ }
138
+
139
+
140
+
141
+ // 結果の表示
142
+
143
+ fmt.Printf("%+v\n", m)
144
+
145
+ }
146
+
147
+
148
+
149
+ /*
150
+
151
+ -- DDLは以下のようなものを想定
152
+
153
+
154
+
155
+ CREATE TABLE hoge (
156
+
157
+ id SERIAL NOT NULL,
158
+
159
+ title VARCHAR(255) NOT NULL,
160
+
161
+ PRIMARY KEY (id)
162
+
163
+ );
164
+
165
+ */
166
+
167
+ type Hoge struct {
168
+
169
+ Id int `db:"id"`
170
+
171
+ Title string `db:"title"`
172
+
173
+ }
174
+
175
+
176
+
177
+ type Postgres struct{ *sqlx.DB }
8
178
 
9
179
  ```
10
180
 
11
181
 
12
182
 
13
- その場合、以下のようにして database/sql の sql.Result を取得できます。なので LastInsertId() で id も取得できと思いますが、どうでしょうか。
183
+ ### 取得できる結果例
14
184
 
15
185
 
16
186
 
17
- ```go
18
-
19
- b := Insert("test").Values(1)
187
+ 以下のように ID と Title の組み合わせでオートインクリメントされた ID の値も取得できます。
20
188
 
21
189
 
22
190
 
23
- ret, err := b.ExecContext(context.TODO())
191
+ ```
24
192
 
25
- if err != nil {
26
-
27
- // handle error
193
+ &{Id:3 Title:gopher}
28
-
29
- }
30
-
31
- id, err = ret.LastInsertId()
32
-
33
- if err != nil {
34
-
35
- // handle error
36
-
37
- }
38
194
 
39
195
  ```