go-sqlite icon indicating copy to clipboard operation
go-sqlite copied to clipboard

FOREIGN KEY violation when []byte(nil) is used

Open foxcpp opened this issue 1 year ago • 3 comments

When I pass []byte(nil) as an argument to INSERT, unexpected FOREIGN KEY violation happens.

Expected behavior Row is successfully inserted.

Actual behavior Error is returned from INSERT: constraint failed: FOREIGN KEY constraint failed (787)

However:

  1. Using modernc.org/[email protected] as a driver works fine.
  2. Using github.com/mattn/[email protected] as a driver works fine.
  3. Passing nil (not []byte(nil)) works fine.
  4. If foreign key constraints are disabled, the row is inserted successfully and has correct NULL value as parent_id.
Code to reproduce

package main

import (
        "database/sql"
        "log"
        _ "github.com/glebarez/go-sqlite"
)

func main() {
        db, err := sql.Open("sqlite", ":memory:?_pragma=foreign_keys(1)&_pragma=busy_timeout(10000)&_pragma=journal_mode(WAL)")
        if err != nil {
                log.Fatalln(err)
        }
        defer db.Close()
        db.SetMaxOpenConns(1)
        db.SetMaxIdleConns(1)

        _, err = db.Exec(`CREATE TABLE test(id BLOB NOT NULL PRIMARY KEY, parent_id BLOB DEFAULT NULL REFERENCES test(id))`)
        if err != nil {
                log.Fatalln(err)
        }
        log.Println("create table ok")

        _, err = db.Exec(`INSERT INTO test(id, parent_id) VALUES (?, ?)`, []byte("abc"), []byte(nil))
        if err != nil {
                log.Fatalln(err)
        }

        log.Println("insert ok")
}

foxcpp avatar Feb 26 '25 20:02 foxcpp

Judging by how it is interpreted in different query, it is coerced into an empty byte string ("").

foxcpp avatar Mar 02 '25 18:03 foxcpp

Hello @foxcpp . Indeed this project is not bugproof and has been dragging behind the upstream (modernc) due to lack of time to support it. It was only planned to serve as go-driver for GORM.

Is there any reason you choose this over modernc or mattn in your specific case?

glebarez avatar Mar 03 '25 22:03 glebarez

Is there any reason you choose this over modernc or mattn in your specific case?

  1. I wanted to have a non-CGo fallback for my project to make it slightly more portable.
  2. I use gorm and therefore need something with a compatible driver.

If I understand correctly, this repo is modernc fork that fixes some issues to make it more compatible with gorm and to make it more closely match the mattn driver behavior. So to maximize compatibility I choose to use it.

foxcpp avatar Mar 03 '25 22:03 foxcpp