@@ -2,7 +2,6 @@ package database
22
33import (
44 "context"
5- "fmt"
65 "github.com/go-sql-driver/mysql"
76 "github.com/icinga/icinga-go-library/backoff"
87 "github.com/icinga/icinga-go-library/com"
@@ -19,7 +18,6 @@ import (
1918 "golang.org/x/sync/semaphore"
2019 "net/url"
2120 "strconv"
22- "strings"
2321 "sync"
2422 "time"
2523)
@@ -202,143 +200,37 @@ func (db *DB) BuildColumns(subject interface{}) []string {
202200
203201// BuildDeleteStmt returns a DELETE statement for the given struct.
204202func (db * DB ) BuildDeleteStmt (from interface {}) string {
205- return fmt .Sprintf (
206- `DELETE FROM "%s" WHERE id IN (?)` ,
207- TableName (from ),
208- )
203+ return NewQB (from ).Delete ()
209204}
210205
211206// BuildInsertStmt returns an INSERT INTO statement for the given struct.
212207func (db * DB ) BuildInsertStmt (into interface {}) (string , int ) {
213- columns := db .BuildColumns (into )
214-
215- return fmt .Sprintf (
216- `INSERT INTO "%s" ("%s") VALUES (%s)` ,
217- TableName (into ),
218- strings .Join (columns , `", "` ),
219- fmt .Sprintf (":%s" , strings .Join (columns , ", :" )),
220- ), len (columns )
208+ return NewQB (into ).Insert (db )
221209}
222210
223211// BuildInsertIgnoreStmt returns an INSERT statement for the specified struct for
224212// which the database ignores rows that have already been inserted.
225213func (db * DB ) BuildInsertIgnoreStmt (into interface {}) (string , int ) {
226- table := TableName (into )
227- columns := db .BuildColumns (into )
228- var clause string
229-
230- switch db .DriverName () {
231- case driver .MySQL :
232- // MySQL treats UPDATE id = id as a no-op.
233- clause = fmt .Sprintf (`ON DUPLICATE KEY UPDATE "%s" = "%s"` , columns [0 ], columns [0 ])
234- case driver .PostgreSQL :
235- var constraint string
236- if constrainter , ok := into .(PgsqlOnConflictConstrainter ); ok {
237- constraint = constrainter .PgsqlOnConflictConstraint ()
238- } else {
239- constraint = "pk_" + table
240- }
241-
242- clause = fmt .Sprintf ("ON CONFLICT ON CONSTRAINT %s DO NOTHING" , constraint )
243- }
244-
245- return fmt .Sprintf (
246- `INSERT INTO "%s" ("%s") VALUES (%s) %s` ,
247- table ,
248- strings .Join (columns , `", "` ),
249- fmt .Sprintf (":%s" , strings .Join (columns , ", :" )),
250- clause ,
251- ), len (columns )
214+ return NewQB (into ).InsertIgnore (db )
252215}
253216
254217// BuildSelectStmt returns a SELECT query that creates the FROM part from the given table struct
255218// and the column list from the specified columns struct.
256219func (db * DB ) BuildSelectStmt (table interface {}, columns interface {}) string {
257- q := fmt .Sprintf (
258- `SELECT "%s" FROM "%s"` ,
259- strings .Join (db .BuildColumns (columns ), `", "` ),
260- TableName (table ),
261- )
220+ qb := NewQB (table )
221+ qb .SetColumns (db .BuildColumns (columns )... )
262222
263- if scoper , ok := table .(Scoper ); ok {
264- where , _ := db .BuildWhere (scoper .Scope ())
265- q += ` WHERE ` + where
266- }
267-
268- return q
223+ return qb .Select (db )
269224}
270225
271226// BuildUpdateStmt returns an UPDATE statement for the given struct.
272227func (db * DB ) BuildUpdateStmt (update interface {}) (string , int ) {
273- columns := db .BuildColumns (update )
274- set := make ([]string , 0 , len (columns ))
275-
276- for _ , col := range columns {
277- set = append (set , fmt .Sprintf (`"%s" = :%s` , col , col ))
278- }
279-
280- return fmt .Sprintf (
281- `UPDATE "%s" SET %s WHERE id = :id` ,
282- TableName (update ),
283- strings .Join (set , ", " ),
284- ), len (columns ) + 1 // +1 because of WHERE id = :id
228+ return NewQB (update ).Update (db )
285229}
286230
287231// BuildUpsertStmt returns an upsert statement for the given struct.
288232func (db * DB ) BuildUpsertStmt (subject interface {}) (stmt string , placeholders int ) {
289- insertColumns := db .BuildColumns (subject )
290- table := TableName (subject )
291- var updateColumns []string
292-
293- if upserter , ok := subject .(Upserter ); ok {
294- updateColumns = db .BuildColumns (upserter .Upsert ())
295- } else {
296- updateColumns = insertColumns
297- }
298-
299- var clause , setFormat string
300- switch db .DriverName () {
301- case driver .MySQL :
302- clause = "ON DUPLICATE KEY UPDATE"
303- setFormat = `"%[1]s" = VALUES("%[1]s")`
304- case driver .PostgreSQL :
305- var constraint string
306- if constrainter , ok := subject .(PgsqlOnConflictConstrainter ); ok {
307- constraint = constrainter .PgsqlOnConflictConstraint ()
308- } else {
309- constraint = "pk_" + table
310- }
311-
312- clause = fmt .Sprintf ("ON CONFLICT ON CONSTRAINT %s DO UPDATE SET" , constraint )
313- setFormat = `"%[1]s" = EXCLUDED."%[1]s"`
314- }
315-
316- set := make ([]string , 0 , len (updateColumns ))
317-
318- for _ , col := range updateColumns {
319- set = append (set , fmt .Sprintf (setFormat , col ))
320- }
321-
322- return fmt .Sprintf (
323- `INSERT INTO "%s" ("%s") VALUES (%s) %s %s` ,
324- table ,
325- strings .Join (insertColumns , `", "` ),
326- fmt .Sprintf (":%s" , strings .Join (insertColumns , ",:" )),
327- clause ,
328- strings .Join (set , "," ),
329- ), len (insertColumns )
330- }
331-
332- // BuildWhere returns a WHERE clause with named placeholder conditions built from the specified struct
333- // combined with the AND operator.
334- func (db * DB ) BuildWhere (subject interface {}) (string , int ) {
335- columns := db .BuildColumns (subject )
336- where := make ([]string , 0 , len (columns ))
337- for _ , col := range columns {
338- where = append (where , fmt .Sprintf (`"%s" = :%s` , col , col ))
339- }
340-
341- return strings .Join (where , ` AND ` ), len (columns )
233+ return NewQB (subject ).Upsert (db )
342234}
343235
344236// OnSuccess is a callback for successful (bulk) DML operations.
0 commit comments