11package utils
22
33import (
4- "context"
54 "database/sql"
6- "fmt"
7- "github.com/icinga/icinga-go-library/database"
8- "github.com/icinga/icinga-go-library/driver"
95 "github.com/icinga/icinga-go-library/types"
10- "github.com/jmoiron/sqlx"
11- "strings"
126)
137
14- // BuildInsertStmtWithout builds an insert stmt without the provided column.
15- func BuildInsertStmtWithout (db * database.DB , into interface {}, withoutColumn string ) string {
16- columns := db .BuildColumns (into )
17- for i , column := range columns {
18- if column == withoutColumn {
19- // Event id is auto incremented, so just erase it from our insert columns
20- columns = append (columns [:i ], columns [i + 1 :]... )
21- break
22- }
23- }
24-
25- return fmt .Sprintf (
26- `INSERT INTO "%s" ("%s") VALUES (%s)` ,
27- database .TableName (into ), strings .Join (columns , `", "` ),
28- fmt .Sprintf (":%s" , strings .Join (columns , ", :" )),
29- )
30- }
31-
32- // RunInTx allows running a function in a database transaction without requiring manual transaction handling.
33- //
34- // A new transaction is started on db which is then passed to fn. After fn returns, the transaction is
35- // committed unless an error was returned. If fn returns an error, that error is returned, otherwise an
36- // error is returned if a database operation fails.
37- func RunInTx (ctx context.Context , db * database.DB , fn func (tx * sqlx.Tx ) error ) error {
38- tx , err := db .BeginTxx (ctx , nil )
39- if err != nil {
40- return err
41- }
42- defer func () { _ = tx .Rollback () }()
43-
44- err = fn (tx )
45- if err != nil {
46- return err
47- }
48-
49- return tx .Commit ()
50- }
51-
52- // InsertAndFetchId executes the given query and fetches the last inserted ID.
53- func InsertAndFetchId (ctx context.Context , tx * sqlx.Tx , stmt string , args any ) (int64 , error ) {
54- var lastInsertId int64
55- if tx .DriverName () == driver .PostgreSQL {
56- preparedStmt , err := tx .PrepareNamedContext (ctx , stmt + " RETURNING id" )
57- if err != nil {
58- return 0 , err
59- }
60- defer func () { _ = preparedStmt .Close () }()
61-
62- err = preparedStmt .Get (& lastInsertId , args )
63- if err != nil {
64- return 0 , fmt .Errorf ("failed to insert entry for type %T: %s" , args , err )
65- }
66- } else {
67- result , err := tx .NamedExecContext (ctx , stmt , args )
68- if err != nil {
69- return 0 , fmt .Errorf ("failed to insert entry for type %T: %s" , args , err )
70- }
71-
72- lastInsertId , err = result .LastInsertId ()
73- if err != nil {
74- return 0 , fmt .Errorf ("failed to fetch last insert id for type %T: %s" , args , err )
75- }
76- }
77-
78- return lastInsertId , nil
79- }
80-
818// ToDBString transforms the given string to types.String.
829func ToDBString (value string ) types.String {
8310 str := types.String {NullString : sql.NullString {String : value }}
@@ -97,22 +24,3 @@ func ToDBInt(value int64) types.Int {
9724
9825 return val
9926}
100-
101- func RemoveIf [T any ](slice []T , pred func (T ) bool ) []T {
102- n := len (slice )
103-
104- for i := 0 ; i < n ; i ++ {
105- for i < n && pred (slice [i ]) {
106- n --
107- slice [i ], slice [n ] = slice [n ], slice [i ]
108- }
109- }
110-
111- return slice [:n ]
112- }
113-
114- func RemoveNils [T any ](slice []* T ) []* T {
115- return RemoveIf (slice , func (ptr * T ) bool {
116- return ptr == nil
117- })
118- }
0 commit comments