Skip to content

Commit d2205cb

Browse files
committed
feat(be): sqlite support
1 parent 6da7d0f commit d2205cb

21 files changed

+31929
-31142
lines changed

.dredd/hooks/helpers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func truncateAll() {
7070
case *bolt.BoltDb:
7171
// Do nothing
7272
case *sql.SqlDb:
73-
switch store.(*sql.SqlDb).Sql().Dialect.(type) {
73+
switch store.(*sql.SqlDb).Sql().Dialect().(type) {
7474
case gorp.PostgresDialect:
7575
// Do nothing
7676
case gorp.MySQLDialect:

db/Migration.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package db
33
import (
44
"fmt"
55
"github.com/semaphoreui/semaphore/pkg/tz"
6+
"github.com/semaphoreui/semaphore/util"
67
"slices"
78
"strconv"
89
"strings"
@@ -21,7 +22,14 @@ func (m Migration) HumanoidVersion() string {
2122
return "v" + m.Version
2223
}
2324

24-
func GetMigrations() []Migration {
25+
func GetMigrations(dialect string) []Migration {
26+
if dialect == util.DbDriverSQLite {
27+
return []Migration{
28+
{Version: "2.15.1.sqlite"},
29+
{Version: "2.16.0.sqlite"},
30+
}
31+
}
32+
2533
return []Migration{
2634
{Version: "0.0.0"},
2735
{Version: "1.0.0"},
@@ -187,7 +195,7 @@ func Rollback(d Store, targetVersion string) error {
187195

188196
didRun := false
189197

190-
migrations := GetMigrations()
198+
migrations := GetMigrations(d.GetDialect())
191199
slices.Reverse(migrations)
192200

193201
for _, version := range migrations {
@@ -220,7 +228,7 @@ func Rollback(d Store, targetVersion string) error {
220228
func Migrate(d Store, targetVersion *string) error {
221229
didRun := false
222230

223-
for _, version := range GetMigrations() {
231+
for _, version := range GetMigrations(d.GetDialect()) {
224232

225233
if targetVersion != nil && version.Compare(Migration{Version: *targetVersion}) > 0 {
226234
break

db/Store.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ type ConnectionManager interface {
194194

195195
// MigrationManager handles database migrations
196196
type MigrationManager interface {
197+
GetDialect() string
197198
// IsInitialized indicates is database already initialized, or it is empty.
198199
// The method is useful for creating required entities in database during first run.
199200
IsInitialized() (bool, error)

db/bolt/BoltDb.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ type BoltDb struct {
4444
terraformAlias publicAlias
4545
}
4646

47+
func (d *BoltDb) GetDialect() string {
48+
return util.DbDriverBolt
49+
}
50+
4751
var terraformAliasProps = db.ObjectProps{
4852
TableName: "terraform_alias",
4953
Type: reflect.TypeOf(db.TerraformInventoryAlias{}),

db/factory/store.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ func CreateStore() db.Store {
1414
}
1515
switch config.Dialect {
1616
case util.DbDriverMySQL:
17-
return &sql.SqlDb{}
17+
return sql.CreateDb(config.Dialect)
1818
case util.DbDriverBolt:
1919
return bolt.CreateBoltDB()
2020
case util.DbDriverPostgres:
21-
return &sql.SqlDb{}
21+
return sql.CreateDb(config.Dialect)
22+
case util.DbDriverSQLite:
23+
return sql.CreateDb(config.Dialect)
2224
default:
2325
panic("Unsupported database dialect: " + config.Dialect)
2426
}

db/sql/SqlDb.go

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ import (
1818
"github.com/semaphoreui/semaphore/pkg/task_logger"
1919
"github.com/semaphoreui/semaphore/util"
2020
log "github.com/sirupsen/logrus"
21+
_ "modernc.org/sqlite" // Import the driver
2122
)
2223

2324
type SqlDb struct {
24-
sql *gorp.DbMap
25+
sql Sql
26+
dialect string
2527
}
2628

2729
var initialSQL = `
@@ -35,6 +37,14 @@ create table ` + "`migrations`" + ` (
3537
//go:embed migrations/*.sql
3638
var dbAssets embed.FS
3739

40+
func CreateDb(dialect string) *SqlDb {
41+
return &SqlDb{dialect: dialect}
42+
}
43+
44+
func (d *SqlDb) GetDialect() string {
45+
return d.dialect
46+
}
47+
3848
func getQueryForParams(q squirrel.SelectBuilder, prefix string, props db.ObjectProps, params db.RetrieveQueryParams) (res squirrel.SelectBuilder, err error) {
3949
pp, err := params.Validate(props)
4050
if err != nil {
@@ -114,27 +124,31 @@ func (d *SqlDb) prepareQueryWithDialect(query string, dialect gorp.Dialect) stri
114124
}
115125

116126
func (d *SqlDb) PrepareQuery(query string) string {
117-
return d.prepareQueryWithDialect(query, d.sql.Dialect)
127+
return d.prepareQueryWithDialect(query, d.sql.Dialect())
118128
}
119129

120130
func (d *SqlDb) insert(primaryKeyColumnName string, query string, args ...any) (int, error) {
131+
return d.insertBy(d.sql, primaryKeyColumnName, query, args...)
132+
}
133+
134+
func (d *SqlDb) insertBy(executor gorp.SqlExecutor, primaryKeyColumnName string, query string, args ...any) (int, error) {
121135
var insertId int64
122136

123-
switch d.sql.Dialect.(type) {
137+
switch d.sql.Dialect().(type) {
124138
case gorp.PostgresDialect:
125139
var err error
126140
if primaryKeyColumnName != "" {
127141
query += " returning " + primaryKeyColumnName
128-
err = d.sql.QueryRow(d.PrepareQuery(query), args...).Scan(&insertId)
142+
err = executor.QueryRow(d.PrepareQuery(query), args...).Scan(&insertId)
129143
} else {
130-
_, err = d.sql.Exec(d.PrepareQuery(query), args...)
144+
_, err = executor.Exec(d.PrepareQuery(query), args...)
131145
}
132146

133147
if err != nil {
134148
return 0, err
135149
}
136150
default:
137-
res, err := d.exec(query, args...)
151+
res, err := executor.Exec(d.PrepareQuery(query), args...)
138152
if err != nil {
139153
return 0, err
140154
}
@@ -323,7 +337,7 @@ func (d *SqlDb) deleteObject(projectID int, props db.ObjectProps, objectID any)
323337
}
324338

325339
func (d *SqlDb) Close(token string) {
326-
err := d.sql.Db.Close()
340+
err := d.sql.Close()
327341
if err != nil {
328342
panic(err)
329343
}
@@ -364,16 +378,11 @@ func (d *SqlDb) Connect(_ string) {
364378
panic(err)
365379
}
366380

367-
var dialect gorp.Dialect
368-
369-
switch cfg.Dialect {
370-
case util.DbDriverMySQL:
371-
dialect = gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8"}
372-
case util.DbDriverPostgres:
373-
dialect = gorp.PostgresDialect{}
374-
}
381+
d.sql = Create(cfg.Dialect, sqlDb) //&gorp.DbMap{Db: sqlDb, Dialect: dialect}
375382

376-
d.sql = &gorp.DbMap{Db: sqlDb, Dialect: dialect}
383+
//if d.GetDialect() == util.DbDriverSQLite {
384+
// sqlDb.SetMaxOpenConns(1)
385+
//}
377386

378387
d.sql.AddTableWithName(db.APIToken{}, "user__token").SetKeys(false, "id")
379388
d.sql.AddTableWithName(db.AccessKey{}, "access_key").SetKeys(true, "id")
@@ -486,7 +495,7 @@ func (d *SqlDb) getObjectRefsFrom(
486495
return
487496
}
488497

489-
func (d *SqlDb) Sql() *gorp.DbMap {
498+
func (d *SqlDb) Sql() Sql {
490499
return d.sql
491500
}
492501

db/sql/common_sql.go

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
package sql
2+
3+
import (
4+
"context"
5+
"database/sql"
6+
"github.com/go-gorp/gorp/v3"
7+
"github.com/semaphoreui/semaphore/util"
8+
"sync"
9+
)
10+
11+
type FakeLocker struct {
12+
}
13+
14+
func (f FakeLocker) Lock() {
15+
}
16+
17+
func (f FakeLocker) Unlock() {
18+
}
19+
20+
type CommonSql struct {
21+
db *gorp.DbMap
22+
mutex sync.Locker
23+
}
24+
25+
func Create(dialectStr string, sqlDb *sql.DB) *CommonSql {
26+
var dialect gorp.Dialect
27+
28+
switch dialectStr {
29+
case util.DbDriverMySQL:
30+
dialect = gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8"}
31+
case util.DbDriverPostgres:
32+
dialect = gorp.PostgresDialect{}
33+
case util.DbDriverSQLite:
34+
dialect = gorp.SqliteDialect{}
35+
}
36+
37+
var mutex sync.Locker
38+
if dialectStr == util.DbDriverSQLite {
39+
mutex = &sync.Mutex{}
40+
} else {
41+
mutex = &FakeLocker{}
42+
}
43+
44+
return &CommonSql{db: &gorp.DbMap{Db: sqlDb, Dialect: dialect}, mutex: mutex}
45+
}
46+
47+
func (c CommonSql) Lock() {
48+
c.mutex.Lock()
49+
}
50+
51+
func (c CommonSql) Unlock() {
52+
c.mutex.Unlock()
53+
}
54+
55+
func (c CommonSql) QueryRow(query string, args ...interface{}) *sql.Row {
56+
c.Lock()
57+
defer c.Unlock()
58+
return c.db.QueryRow(query, args...)
59+
}
60+
61+
func (c CommonSql) Insert(list ...interface{}) error {
62+
c.Lock()
63+
defer c.Unlock()
64+
65+
return c.db.Insert(list...)
66+
}
67+
68+
func (c CommonSql) SelectOne(holder interface{}, query string, args ...interface{}) error {
69+
c.Lock()
70+
defer c.Unlock()
71+
72+
return c.db.SelectOne(holder, query, args...)
73+
}
74+
75+
func (c CommonSql) PrepareQuery(query string) string {
76+
return query
77+
}
78+
79+
func (c CommonSql) Exec(query string, args ...interface{}) (sql.Result, error) {
80+
c.Lock()
81+
defer c.Unlock()
82+
83+
return c.db.Exec(query, args...)
84+
}
85+
86+
func (c CommonSql) Select(i interface{}, query string, args ...interface{}) ([]interface{}, error) {
87+
c.Lock()
88+
defer c.Unlock()
89+
90+
return c.db.Select(i, query, args...)
91+
}
92+
93+
func (c CommonSql) SelectInt(query string, args ...interface{}) (int64, error) {
94+
c.Lock()
95+
defer c.Unlock()
96+
97+
return c.db.SelectInt(query, args...)
98+
}
99+
100+
func (c CommonSql) AddTableWithName(i interface{}, name string) *gorp.TableMap {
101+
c.Lock()
102+
defer c.Unlock()
103+
104+
return c.db.AddTableWithName(i, name)
105+
}
106+
107+
func (c CommonSql) Dialect() gorp.Dialect {
108+
return c.db.Dialect
109+
}
110+
111+
func (c CommonSql) Close() error {
112+
c.Lock()
113+
defer c.Unlock()
114+
115+
return c.db.Db.Close()
116+
}
117+
118+
func (c CommonSql) Begin() (*gorp.Transaction, error) {
119+
return c.db.Begin()
120+
}
121+
122+
func (c CommonSql) WithContext(ctx context.Context) gorp.SqlExecutor {
123+
c.Lock()
124+
defer c.Unlock()
125+
126+
return c.db.WithContext(ctx)
127+
}
128+
129+
func (c CommonSql) Get(i interface{}, keys ...interface{}) (interface{}, error) {
130+
c.Lock()
131+
defer c.Unlock()
132+
133+
return c.db.Get(i, keys...)
134+
}
135+
136+
func (c CommonSql) Update(list ...interface{}) (int64, error) {
137+
c.Lock()
138+
defer c.Unlock()
139+
140+
return c.db.Update(list...)
141+
}
142+
143+
func (c CommonSql) Delete(list ...interface{}) (int64, error) {
144+
c.Lock()
145+
defer c.Unlock()
146+
147+
return c.db.Delete(list...)
148+
}
149+
150+
func (c CommonSql) SelectNullInt(query string, args ...interface{}) (sql.NullInt64, error) {
151+
c.Lock()
152+
defer c.Unlock()
153+
154+
return c.db.SelectNullInt(query, args...)
155+
}
156+
157+
func (c CommonSql) SelectFloat(query string, args ...interface{}) (float64, error) {
158+
c.Lock()
159+
defer c.Unlock()
160+
161+
return c.db.SelectFloat(query, args...)
162+
}
163+
164+
func (c CommonSql) SelectNullFloat(query string, args ...interface{}) (sql.NullFloat64, error) {
165+
c.Lock()
166+
defer c.Unlock()
167+
168+
return c.db.SelectNullFloat(query, args...)
169+
}
170+
171+
func (c CommonSql) SelectStr(query string, args ...interface{}) (string, error) {
172+
c.Lock()
173+
defer c.Unlock()
174+
175+
return c.db.SelectStr(query, args...)
176+
}
177+
178+
func (c CommonSql) SelectNullStr(query string, args ...interface{}) (sql.NullString, error) {
179+
c.Lock()
180+
defer c.Unlock()
181+
182+
return c.db.SelectNullStr(query, args...)
183+
}
184+
185+
func (c CommonSql) Query(query string, args ...interface{}) (*sql.Rows, error) {
186+
c.Lock()
187+
defer c.Unlock()
188+
189+
return c.db.Query(query, args...)
190+
}

db/sql/migration.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func getVersionSQL(name string, ignoreErrors bool) (queries []string) {
5555
// prepareMigration converts migration SQLite-query to current dialect.
5656
// Supported MySQL and Postgres dialects.
5757
func (d *SqlDb) prepareMigration(query string) string {
58-
switch d.sql.Dialect.(type) {
58+
switch d.sql.Dialect().(type) {
5959
case gorp.MySQLDialect:
6060
query = autoIncrementRE.ReplaceAllString(query, "auto_increment")
6161
query = ifExistsRE.ReplaceAllString(query, "")

db/sql/migration_2_10_24.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ type migration_2_10_24 struct {
77
}
88

99
func (m migration_2_10_24) PreApply(tx *gorp.Transaction) error {
10-
switch m.db.sql.Dialect.(type) {
10+
switch m.db.sql.Dialect().(type) {
1111
case gorp.MySQLDialect:
1212
_, _ = tx.Exec(m.db.PrepareQuery("alter table `project__template` drop foreign key `project__template_ibfk_6`"))
1313
case gorp.PostgresDialect:

0 commit comments

Comments
 (0)