Skip to content

Commit 47fc4e5

Browse files
authored
Merge pull request #436 from zombiezen/recursivetriggers
Add connection option for recursive triggers
2 parents 9cbb097 + 848386d commit 47fc4e5

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

sqlite3.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,8 @@ func errorString(err Error) string {
599599
// "deferred", "exclusive".
600600
// _foreign_keys=X
601601
// Enable or disable enforcement of foreign keys. X can be 1 or 0.
602+
// _recursive_triggers=X
603+
// Enable or disable recursive triggers. X can be 1 or 0.
602604
func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
603605
if C.sqlite3_threadsafe() == 0 {
604606
return nil, errors.New("sqlite library was not compiled for thread-safe operation")
@@ -608,6 +610,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
608610
txlock := "BEGIN"
609611
busyTimeout := 5000
610612
foreignKeys := -1
613+
recursiveTriggers := -1
611614
pos := strings.IndexRune(dsn, '?')
612615
if pos >= 1 {
613616
params, err := url.ParseQuery(dsn[pos+1:])
@@ -662,6 +665,18 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
662665
}
663666
}
664667

668+
// _recursive_triggers
669+
if val := params.Get("_recursive_triggers"); val != "" {
670+
switch val {
671+
case "1":
672+
recursiveTriggers = 1
673+
case "0":
674+
recursiveTriggers = 0
675+
default:
676+
return nil, fmt.Errorf("Invalid _recursive_triggers: %v", val)
677+
}
678+
}
679+
665680
if !strings.HasPrefix(dsn, "file:") {
666681
dsn = dsn[:pos]
667682
}
@@ -708,6 +723,17 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
708723
return nil, err
709724
}
710725
}
726+
if recursiveTriggers == 0 {
727+
if err := exec("PRAGMA recursive_triggers = OFF;"); err != nil {
728+
C.sqlite3_close_v2(db)
729+
return nil, err
730+
}
731+
} else if recursiveTriggers == 1 {
732+
if err := exec("PRAGMA recursive_triggers = ON;"); err != nil {
733+
C.sqlite3_close_v2(db)
734+
return nil, err
735+
}
736+
}
711737

712738
conn := &SQLiteConn{db: db, loc: loc, txlock: txlock}
713739

sqlite3_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,35 @@ func TestForeignKeys(t *testing.T) {
136136
}
137137
}
138138

139+
func TestRecursiveTriggers(t *testing.T) {
140+
cases := map[string]bool{
141+
"?_recursive_triggers=1": true,
142+
"?_recursive_triggers=0": false,
143+
}
144+
for option, want := range cases {
145+
fname := TempFilename(t)
146+
uri := "file:" + fname + option
147+
db, err := sql.Open("sqlite3", uri)
148+
if err != nil {
149+
os.Remove(fname)
150+
t.Errorf("sql.Open(\"sqlite3\", %q): %v", uri, err)
151+
continue
152+
}
153+
var enabled bool
154+
err = db.QueryRow("PRAGMA recursive_triggers;").Scan(&enabled)
155+
db.Close()
156+
os.Remove(fname)
157+
if err != nil {
158+
t.Errorf("query recursive_triggers for %s: %v", uri, err)
159+
continue
160+
}
161+
if enabled != want {
162+
t.Errorf("\"PRAGMA recursive_triggers;\" for %q = %t; want %t", uri, enabled, want)
163+
continue
164+
}
165+
}
166+
}
167+
139168
func TestClose(t *testing.T) {
140169
tempFilename := TempFilename(t)
141170
defer os.Remove(tempFilename)

0 commit comments

Comments
 (0)