@@ -400,14 +400,18 @@ func (c *SQLiteConn) AutoCommit() bool {
400
400
}
401
401
402
402
func (c * SQLiteConn ) lastError () error {
403
- rv := C .sqlite3_errcode (c .db )
403
+ return lastError (c .db )
404
+ }
405
+
406
+ func lastError (db * C.sqlite3 ) error {
407
+ rv := C .sqlite3_errcode (db )
404
408
if rv == C .SQLITE_OK {
405
409
return nil
406
410
}
407
411
return Error {
408
412
Code : ErrNo (rv ),
409
- ExtendedCode : ErrNoExtended (C .sqlite3_extended_errcode (c . db )),
410
- err : C .GoString (C .sqlite3_errmsg (c . db )),
413
+ ExtendedCode : ErrNoExtended (C .sqlite3_extended_errcode (db )),
414
+ err : C .GoString (C .sqlite3_errmsg (db )),
411
415
}
412
416
}
413
417
@@ -537,6 +541,8 @@ func errorString(err Error) string {
537
541
// _txlock=XXX
538
542
// Specify locking behavior for transactions. XXX can be "immediate",
539
543
// "deferred", "exclusive".
544
+ // _foreign_keys=X
545
+ // Enable or disable enforcement of foreign keys. X can be 1 or 0.
540
546
func (d * SQLiteDriver ) Open (dsn string ) (driver.Conn , error ) {
541
547
if C .sqlite3_threadsafe () == 0 {
542
548
return nil , errors .New ("sqlite library was not compiled for thread-safe operation" )
@@ -545,6 +551,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
545
551
var loc * time.Location
546
552
txlock := "BEGIN"
547
553
busyTimeout := 5000
554
+ foreignKeys := - 1
548
555
pos := strings .IndexRune (dsn , '?' )
549
556
if pos >= 1 {
550
557
params , err := url .ParseQuery (dsn [pos + 1 :])
@@ -587,6 +594,18 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
587
594
}
588
595
}
589
596
597
+ // _foreign_keys
598
+ if val := params .Get ("_foreign_keys" ); val != "" {
599
+ switch val {
600
+ case "1" :
601
+ foreignKeys = 1
602
+ case "0" :
603
+ foreignKeys = 0
604
+ default :
605
+ return nil , fmt .Errorf ("Invalid _foreign_keys: %v" , val )
606
+ }
607
+ }
608
+
590
609
if ! strings .HasPrefix (dsn , "file:" ) {
591
610
dsn = dsn [:pos ]
592
611
}
@@ -613,6 +632,27 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
613
632
return nil , Error {Code : ErrNo (rv )}
614
633
}
615
634
635
+ exec := func (s string ) error {
636
+ cs := C .CString (s )
637
+ rv := C .sqlite3_exec (db , cs , nil , nil , nil )
638
+ C .free (unsafe .Pointer (cs ))
639
+ if rv != C .SQLITE_OK {
640
+ return lastError (db )
641
+ }
642
+ return nil
643
+ }
644
+ if foreignKeys == 0 {
645
+ if err := exec ("PRAGMA foreign_keys = OFF;" ); err != nil {
646
+ C .sqlite3_close_v2 (db )
647
+ return nil , err
648
+ }
649
+ } else if foreignKeys == 1 {
650
+ if err := exec ("PRAGMA foreign_keys = ON;" ); err != nil {
651
+ C .sqlite3_close_v2 (db )
652
+ return nil , err
653
+ }
654
+ }
655
+
616
656
conn := & SQLiteConn {db : db , loc : loc , txlock : txlock }
617
657
618
658
if len (d .Extensions ) > 0 {
0 commit comments