Skip to content

Commit cf26002

Browse files
committed
fix: journal mode
Journal Mode should only be enforced when the user set it. Fixes: #607
1 parent 4049232 commit cf26002

File tree

1 file changed

+133
-120
lines changed

1 file changed

+133
-120
lines changed

driver/config.go

Lines changed: 133 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,12 @@ func (j JournalMode) String() string {
334334
}
335335

336336
const (
337-
// JournalModeDelete is the normal behavior.
337+
// JournalModeAuto is the journal mode in which the Journal is not explicitly set.
338+
// This means that if any other program or connection already has set the journal mode
339+
// the journal mode is automatically read from the database and not forcibly set.
340+
JournalModeAuto = JournalMode("AUTO")
341+
342+
// JournalModeDelete is the normal behavior.
338343
// In the DELETE mode, the rollback journal is deleted at the conclusion
339344
// of each transaction.
340345
// Indeed, the delete operation is the action that causes the transaction to commit.
@@ -585,7 +590,7 @@ func NewConfig() *Config {
585590
DeferForeignKeys: false,
586591
ForeignKeyConstraints: false,
587592
IgnoreCheckConstraints: false,
588-
JournalMode: JournalModeDelete,
593+
JournalMode: JournalModeAuto,
589594
QueryOnly: false,
590595
RecursiveTriggers: false,
591596
SecureDelete: SecureDeleteOff,
@@ -597,121 +602,6 @@ func NewConfig() *Config {
597602
}
598603
}
599604

600-
// FormatDSN formats the given Config into a DSN string which can be passed to
601-
// the driver.
602-
func (cfg *Config) FormatDSN() string {
603-
var buf bytes.Buffer
604-
605-
params := url.Values{}
606-
if len(cfg.Cache.String()) > 0 {
607-
params.Set("cache", cfg.Cache.String())
608-
}
609-
610-
if len(cfg.Mode.String()) > 0 {
611-
params.Set("mode", cfg.Mode.String())
612-
}
613-
614-
if len(cfg.Mutex.String()) > 0 {
615-
params.Set("mutex", cfg.Mutex.String())
616-
}
617-
618-
if cfg.Immutable {
619-
params.Set("immutable", "true")
620-
}
621-
622-
if cfg.TimeZone != nil {
623-
if cfg.TimeZone == time.Local {
624-
params.Set("tz", "auto")
625-
} else {
626-
params.Set("tz", cfg.TimeZone.String())
627-
}
628-
}
629-
630-
if cfg.BusyTimeout > 0 {
631-
params.Set("timeout", cfg.BusyTimeout.String())
632-
}
633-
634-
if len(cfg.TransactionLock.String()) > 0 && cfg.TransactionLock != TxLockDeferred {
635-
params.Set("txlock", cfg.TransactionLock.String())
636-
}
637-
638-
if len(cfg.LockingMode) > 0 && cfg.LockingMode != LockingModeNormal {
639-
params.Set("lock", cfg.LockingMode.String())
640-
}
641-
642-
if len(cfg.AutoVacuum) > 0 && cfg.AutoVacuum != AutoVacuumNone {
643-
params.Set("vacuum", cfg.AutoVacuum.String())
644-
}
645-
646-
if cfg.CaseSensitiveLike {
647-
params.Set("cslike", "true")
648-
}
649-
650-
if cfg.DeferForeignKeys {
651-
params.Set("defer_fk", "true")
652-
}
653-
654-
if cfg.ForeignKeyConstraints {
655-
params.Set("fk", "true")
656-
}
657-
658-
if cfg.IgnoreCheckConstraints {
659-
params.Set("ignore_check_contraints", "true")
660-
}
661-
662-
if len(cfg.JournalMode) > 0 && cfg.JournalMode != JournalModeDelete {
663-
params.Set("journal", cfg.JournalMode.String())
664-
}
665-
666-
if cfg.QueryOnly {
667-
params.Set("query_only", "true")
668-
}
669-
670-
if cfg.RecursiveTriggers {
671-
params.Set("recursive_triggers", "true")
672-
}
673-
674-
if len(cfg.SecureDelete) > 0 && cfg.SecureDelete != SecureDeleteOff {
675-
params.Set("secure_delete", cfg.SecureDelete.String())
676-
}
677-
678-
if len(cfg.Synchronous) > 0 && cfg.Synchronous != SynchronousNormal {
679-
params.Set("sync", cfg.Synchronous.String())
680-
}
681-
682-
if cfg.WriteableSchema {
683-
params.Set("writable_schema", "true")
684-
}
685-
686-
if cfg.Authentication != nil {
687-
if len(cfg.Authentication.Username) > 0 && len(cfg.Authentication.Password) > 0 {
688-
params.Set("user", cfg.Authentication.Username)
689-
params.Set("pass", cfg.Authentication.Password)
690-
691-
if len(cfg.Authentication.Salt) > 0 {
692-
params.Set("salt", cfg.Authentication.Salt)
693-
}
694-
695-
if cfg.Authentication.Encoder != nil {
696-
params.Set("crypt", cfg.Authentication.Encoder.String())
697-
}
698-
}
699-
}
700-
701-
if !strings.HasPrefix(cfg.Database, "file:") {
702-
buf.WriteString("file:")
703-
}
704-
buf.WriteString(cfg.Database)
705-
706-
// Append Options
707-
if len(params) > 0 {
708-
buf.WriteRune('?')
709-
buf.WriteString(params.Encode())
710-
}
711-
712-
return buf.String()
713-
}
714-
715605
// Create connection from Configuration
716606
func (cfg *Config) createConnection() (driver.Conn, error) {
717607
if C.sqlite3_threadsafe() == 0 {
@@ -933,9 +823,11 @@ func (cfg *Config) createConnection() (driver.Conn, error) {
933823
}
934824

935825
// Journal Mode
936-
if err := conn.PRAGMA(PRAGMA_JOURNAL_MODE, cfg.JournalMode.String()); err != nil {
937-
C.sqlite3_close_v2(db)
938-
return nil, err
826+
if cfg.JournalMode != JournalModeAuto {
827+
if err := conn.PRAGMA(PRAGMA_JOURNAL_MODE, cfg.JournalMode.String()); err != nil {
828+
C.sqlite3_close_v2(db)
829+
return nil, err
830+
}
939831
}
940832

941833
// Locking Mode
@@ -1242,6 +1134,8 @@ func ParseDSN(dsn string) (cfg *Config, err error) {
12421134
// For WAL Mode set Synchronous Mode to 'NORMAL'
12431135
// See https://www.sqlite.org/pragma.html#pragma_synchronous
12441136
cfg.Synchronous = SynchronousNormal
1137+
case "AUTO":
1138+
cfg.JournalMode = JournalModeAuto
12451139
default:
12461140
return nil, fmt.Errorf("invalid journal: %v, expecting value of 'DELETE TRUNCATE PERSIST MEMORY WAL OFF'", val)
12471141
}
@@ -1318,6 +1212,125 @@ func ParseDSN(dsn string) (cfg *Config, err error) {
13181212
return cfg, nil
13191213
}
13201214

1215+
// FormatDSN formats the given Config into a DSN string which can be passed to
1216+
// the driver.
1217+
func (cfg *Config) FormatDSN() string {
1218+
var buf bytes.Buffer
1219+
1220+
params := url.Values{}
1221+
if len(cfg.Key) > 0 {
1222+
params.Set("key", cfg.Key)
1223+
}
1224+
1225+
if len(cfg.Cache.String()) > 0 {
1226+
params.Set("cache", cfg.Cache.String())
1227+
}
1228+
1229+
if len(cfg.Mode.String()) > 0 {
1230+
params.Set("mode", cfg.Mode.String())
1231+
}
1232+
1233+
if len(cfg.Mutex.String()) > 0 {
1234+
params.Set("mutex", cfg.Mutex.String())
1235+
}
1236+
1237+
if cfg.Immutable {
1238+
params.Set("immutable", "true")
1239+
}
1240+
1241+
if cfg.TimeZone != nil {
1242+
if cfg.TimeZone == time.Local {
1243+
params.Set("tz", "auto")
1244+
} else {
1245+
params.Set("tz", cfg.TimeZone.String())
1246+
}
1247+
}
1248+
1249+
if cfg.BusyTimeout > 0 {
1250+
params.Set("timeout", cfg.BusyTimeout.String())
1251+
}
1252+
1253+
if len(cfg.TransactionLock.String()) > 0 && cfg.TransactionLock != TxLockDeferred {
1254+
params.Set("txlock", cfg.TransactionLock.String())
1255+
}
1256+
1257+
if len(cfg.LockingMode) > 0 && cfg.LockingMode != LockingModeNormal {
1258+
params.Set("lock", cfg.LockingMode.String())
1259+
}
1260+
1261+
if len(cfg.AutoVacuum) > 0 && cfg.AutoVacuum != AutoVacuumNone {
1262+
params.Set("vacuum", cfg.AutoVacuum.String())
1263+
}
1264+
1265+
if cfg.CaseSensitiveLike {
1266+
params.Set("cslike", "true")
1267+
}
1268+
1269+
if cfg.DeferForeignKeys {
1270+
params.Set("defer_fk", "true")
1271+
}
1272+
1273+
if cfg.ForeignKeyConstraints {
1274+
params.Set("fk", "true")
1275+
}
1276+
1277+
if cfg.IgnoreCheckConstraints {
1278+
params.Set("ignore_check_contraints", "true")
1279+
}
1280+
1281+
if len(cfg.JournalMode) > 0 && cfg.JournalMode != JournalModeDelete {
1282+
params.Set("journal", cfg.JournalMode.String())
1283+
}
1284+
1285+
if cfg.QueryOnly {
1286+
params.Set("query_only", "true")
1287+
}
1288+
1289+
if cfg.RecursiveTriggers {
1290+
params.Set("recursive_triggers", "true")
1291+
}
1292+
1293+
if len(cfg.SecureDelete) > 0 && cfg.SecureDelete != SecureDeleteOff {
1294+
params.Set("secure_delete", cfg.SecureDelete.String())
1295+
}
1296+
1297+
if len(cfg.Synchronous) > 0 && cfg.Synchronous != SynchronousNormal {
1298+
params.Set("sync", cfg.Synchronous.String())
1299+
}
1300+
1301+
if cfg.WriteableSchema {
1302+
params.Set("writable_schema", "true")
1303+
}
1304+
1305+
if cfg.Authentication != nil {
1306+
if len(cfg.Authentication.Username) > 0 && len(cfg.Authentication.Password) > 0 {
1307+
params.Set("user", cfg.Authentication.Username)
1308+
params.Set("pass", cfg.Authentication.Password)
1309+
1310+
if len(cfg.Authentication.Salt) > 0 {
1311+
params.Set("salt", cfg.Authentication.Salt)
1312+
}
1313+
1314+
if cfg.Authentication.Encoder != nil {
1315+
params.Set("crypt", cfg.Authentication.Encoder.String())
1316+
}
1317+
}
1318+
}
1319+
1320+
if !strings.HasPrefix(cfg.Database, "file:") {
1321+
buf.WriteString("file:")
1322+
}
1323+
buf.WriteString(cfg.Database)
1324+
1325+
// Append Options
1326+
if len(params) > 0 {
1327+
buf.WriteRune('?')
1328+
buf.WriteString(params.Encode())
1329+
}
1330+
1331+
return buf.String()
1332+
}
1333+
13211334
func normalizeParams(params url.Values) {
13221335
for k, v := range params {
13231336
params[strings.ToLower(k)] = v

0 commit comments

Comments
 (0)