Skip to content

Commit c7dfddd

Browse files
committed
DB: Make use of the QueryBuilder
1 parent 5253251 commit c7dfddd

File tree

1 file changed

+11
-115
lines changed

1 file changed

+11
-115
lines changed

database/db.go

Lines changed: 11 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -258,150 +258,46 @@ func (db *DB) MarshalLogObject(encoder zapcore.ObjectEncoder) error {
258258
return nil
259259
}
260260

261+
// QueryBuilder returns a fully initialised and ready to use *[QueryBuilder] instance for the given subject/struct.
262+
func (db *DB) QueryBuilder(subject any) *QueryBuilder {
263+
return &QueryBuilder{subject: subject}
264+
}
265+
261266
// BuildColumns returns all columns of the given struct.
262267
func (db *DB) BuildColumns(subject interface{}) []string {
263268
return slices.Clone(db.columnMap.Columns(subject))
264269
}
265270

266271
// BuildDeleteStmt returns a DELETE statement for the given struct.
267272
func (db *DB) BuildDeleteStmt(from interface{}) string {
268-
return fmt.Sprintf(
269-
`DELETE FROM "%s" WHERE id IN (?)`,
270-
TableName(from),
271-
)
273+
return db.QueryBuilder(from).Delete()
272274
}
273275

274276
// BuildInsertStmt returns an INSERT INTO statement for the given struct.
275277
func (db *DB) BuildInsertStmt(into interface{}) (string, int) {
276-
columns := db.columnMap.Columns(into)
277-
278-
return fmt.Sprintf(
279-
`INSERT INTO "%s" ("%s") VALUES (%s)`,
280-
TableName(into),
281-
strings.Join(columns, `", "`),
282-
fmt.Sprintf(":%s", strings.Join(columns, ", :")),
283-
), len(columns)
278+
return db.QueryBuilder(into).Insert(db)
284279
}
285280

286281
// BuildInsertIgnoreStmt returns an INSERT statement for the specified struct for
287282
// which the database ignores rows that have already been inserted.
288283
func (db *DB) BuildInsertIgnoreStmt(into interface{}) (string, int) {
289-
table := TableName(into)
290-
columns := db.columnMap.Columns(into)
291-
var clause string
292-
293-
switch db.DriverName() {
294-
case MySQL:
295-
// MySQL treats UPDATE id = id as a no-op.
296-
clause = fmt.Sprintf(`ON DUPLICATE KEY UPDATE "%s" = "%s"`, columns[0], columns[0])
297-
case PostgreSQL:
298-
var constraint string
299-
if constrainter, ok := into.(PgsqlOnConflictConstrainter); ok {
300-
constraint = constrainter.PgsqlOnConflictConstraint()
301-
} else {
302-
constraint = "pk_" + table
303-
}
304-
305-
clause = fmt.Sprintf("ON CONFLICT ON CONSTRAINT %s DO NOTHING", constraint)
306-
}
307-
308-
return fmt.Sprintf(
309-
`INSERT INTO "%s" ("%s") VALUES (%s) %s`,
310-
table,
311-
strings.Join(columns, `", "`),
312-
fmt.Sprintf(":%s", strings.Join(columns, ", :")),
313-
clause,
314-
), len(columns)
284+
return db.QueryBuilder(into).InsertIgnore(db)
315285
}
316286

317287
// BuildSelectStmt returns a SELECT query that creates the FROM part from the given table struct
318288
// and the column list from the specified columns struct.
319289
func (db *DB) BuildSelectStmt(table interface{}, columns interface{}) string {
320-
q := fmt.Sprintf(
321-
`SELECT "%s" FROM "%s"`,
322-
strings.Join(db.columnMap.Columns(columns), `", "`),
323-
TableName(table),
324-
)
325-
326-
if scoper, ok := table.(Scoper); ok {
327-
where, _ := db.BuildWhere(scoper.Scope())
328-
q += ` WHERE ` + where
329-
}
330-
331-
return q
290+
return db.QueryBuilder(table).SetColumns(db.columnMap.Columns(columns)...).Select(db)
332291
}
333292

334293
// BuildUpdateStmt returns an UPDATE statement for the given struct.
335294
func (db *DB) BuildUpdateStmt(update interface{}) (string, int) {
336-
columns := db.columnMap.Columns(update)
337-
set := make([]string, 0, len(columns))
338-
339-
for _, col := range columns {
340-
set = append(set, fmt.Sprintf(`"%s" = :%s`, col, col))
341-
}
342-
343-
return fmt.Sprintf(
344-
`UPDATE "%s" SET %s WHERE id = :id`,
345-
TableName(update),
346-
strings.Join(set, ", "),
347-
), len(columns) + 1 // +1 because of WHERE id = :id
295+
return db.QueryBuilder(update).Update(db)
348296
}
349297

350298
// BuildUpsertStmt returns an upsert statement for the given struct.
351299
func (db *DB) BuildUpsertStmt(subject interface{}) (stmt string, placeholders int) {
352-
insertColumns := db.columnMap.Columns(subject)
353-
table := TableName(subject)
354-
var updateColumns []string
355-
356-
if upserter, ok := subject.(Upserter); ok {
357-
updateColumns = db.columnMap.Columns(upserter.Upsert())
358-
} else {
359-
updateColumns = insertColumns
360-
}
361-
362-
var clause, setFormat string
363-
switch db.DriverName() {
364-
case MySQL:
365-
clause = "ON DUPLICATE KEY UPDATE"
366-
setFormat = `"%[1]s" = VALUES("%[1]s")`
367-
case PostgreSQL:
368-
var constraint string
369-
if constrainter, ok := subject.(PgsqlOnConflictConstrainter); ok {
370-
constraint = constrainter.PgsqlOnConflictConstraint()
371-
} else {
372-
constraint = "pk_" + table
373-
}
374-
375-
clause = fmt.Sprintf("ON CONFLICT ON CONSTRAINT %s DO UPDATE SET", constraint)
376-
setFormat = `"%[1]s" = EXCLUDED."%[1]s"`
377-
}
378-
379-
set := make([]string, 0, len(updateColumns))
380-
381-
for _, col := range updateColumns {
382-
set = append(set, fmt.Sprintf(setFormat, col))
383-
}
384-
385-
return fmt.Sprintf(
386-
`INSERT INTO "%s" ("%s") VALUES (%s) %s %s`,
387-
table,
388-
strings.Join(insertColumns, `", "`),
389-
fmt.Sprintf(":%s", strings.Join(insertColumns, ",:")),
390-
clause,
391-
strings.Join(set, ","),
392-
), len(insertColumns)
393-
}
394-
395-
// BuildWhere returns a WHERE clause with named placeholder conditions built from the specified struct
396-
// combined with the AND operator.
397-
func (db *DB) BuildWhere(subject interface{}) (string, int) {
398-
columns := db.columnMap.Columns(subject)
399-
where := make([]string, 0, len(columns))
400-
for _, col := range columns {
401-
where = append(where, fmt.Sprintf(`"%s" = :%s`, col, col))
402-
}
403-
404-
return strings.Join(where, ` AND `), len(columns)
300+
return db.QueryBuilder(subject).Upsert(db)
405301
}
406302

407303
// OnSuccess is a callback for successful (bulk) DML operations.

0 commit comments

Comments
 (0)