Foreign Key constraint fails strangely

Hello, first of all, thank you for this project,
I honestly think you deserve a lot more starts, and I'm sure those stars will find you!

I'm in process of writing a driver for GORM, and I stumbled upon a strange bug. I managed to narrow it down to the following case:

  • foreign_keys pragma doesn't work when using Query() method with 'RETURNING' clause in query.

From what I found, it doesn't matter whether you set this pragma in connection query parameter, or explicitly with PRAGMA clause.

Here's the fully reproducible tests. The one that fails is Test_PragmaFK_Query_With_Returning

package fk_test

import (
	"database/sql"
	"log"
	"testing"

	"github.com/stretchr/testify/require"
	_ "modernc.org/sqlite"
)

var (
	migrationQ = []string{
		"DROP TABLE IF EXISTS `child`",
		"DROP TABLE IF EXISTS `parent`",
		"CREATE TABLE `parent` (`id` text,PRIMARY KEY (`id`))",
		"CREATE TABLE `child` (`id` integer NOT NULL,`parent_id` text,PRIMARY KEY (`id`),CONSTRAINT `fk_child_parent` FOREIGN KEY (`parent_id`) REFERENCES `parent`(`id`))",
	}

	dsn = "file::memory:?_pragma=foreign_keys(1)"

	db *sql.DB
)

func init() {
	var err error
	// connect
	db, err = sql.Open("sqlite", dsn)
	if err != nil {
		log.Fatal(err)
	}

	// run migration
	for _, q := range migrationQ {
		_, err := db.Exec(q)
		if err != nil {
			log.Fatal(err)
		}
	}
}

func Test_PragmaFK_Exec(t *testing.T) {
	require := require.New(t)

	// violate
	_, err := db.Exec("INSERT INTO `child` (`parent_id`) VALUES (?) RETURNING `id`", "non-existing")
	require.Error(err)
	require.Equal(err.Error(), "constraint failed: FOREIGN KEY constraint failed (787)")
}

// ------ THIS TEST FAILS ------
func Test_PragmaFK_Query_With_Returning(t *testing.T) {
	require := require.New(t)

	// violate
	_, err := db.Query("INSERT INTO `child` (`parent_id`) VALUES (?) RETURNING `id`", "non-existing")
	require.Error(err)
	require.Equal(err.Error(), "constraint failed: FOREIGN KEY constraint failed (787)")
}

func Test_PragmaFK_Query_No_Returning(t *testing.T) {
	require := require.New(t)

	// violate
	_, err := db.Query("INSERT INTO `child` (`parent_id`) VALUES (?)", "non-existing")
	require.Error(err)
	require.Equal(err.Error(), "constraint failed: FOREIGN KEY constraint failed (787)")
}
Edited by glebarez