Repository: upper/db
Pull request #610 (2020-12-05 14:53:26)

Add -race option to tests


Patch:
diff --git a/adapter/cockroachdb/Makefile b/adapter/cockroachdb/Makefile
index 291634e..7982984 100644
--- a/adapter/cockroachdb/Makefile
+++ b/adapter/cockroachdb/Makefile
@@ -24,6 +24,9 @@ export DB_USERNAME
 export TEST_FLAGS
 
 test:
+	go test -v -race -timeout 20m $(TEST_FLAGS)
+
+test-no-race:
 	go test -v $(TEST_FLAGS)
 
 server-up: server-down
diff --git a/adapter/mongo/Makefile b/adapter/mongo/Makefile
index e303a29..1a39523 100644
--- a/adapter/mongo/Makefile
+++ b/adapter/mongo/Makefile
@@ -25,6 +25,9 @@ export DB_USERNAME
 export TEST_FLAGS
 
 test:
+	go test -v -race -timeout 20m $(TEST_FLAGS)
+
+test-no-race:
 	go test -v $(TEST_FLAGS)
 
 server-up: server-down
diff --git a/adapter/mssql/Makefile b/adapter/mssql/Makefile
index a7c9842..b7d1d35 100644
--- a/adapter/mssql/Makefile
+++ b/adapter/mssql/Makefile
@@ -25,6 +25,9 @@ export DB_USERNAME
 export TEST_FLAGS
 
 test:
+	go test -v -race -timeout 20m $(TEST_FLAGS)
+
+test-no-race:
 	go test -v $(TEST_FLAGS)
 
 server-up: server-down
diff --git a/adapter/mysql/Makefile b/adapter/mysql/Makefile
index 489dd45..53710a4 100644
--- a/adapter/mysql/Makefile
+++ b/adapter/mysql/Makefile
@@ -25,6 +25,9 @@ export DB_USERNAME
 export TEST_FLAGS
 
 test:
+	go test -v -race -timeout 20m $(TEST_FLAGS)
+
+test-no-race:
 	go test -v $(TEST_FLAGS)
 
 server-up: server-down
diff --git a/adapter/postgresql/Makefile b/adapter/postgresql/Makefile
index 9d48969..3ab44a8 100644
--- a/adapter/postgresql/Makefile
+++ b/adapter/postgresql/Makefile
@@ -25,6 +25,9 @@ export DB_USERNAME
 export TEST_FLAGS
 
 test:
+	go test -v -race -timeout 20m $(TEST_FLAGS)
+
+test-no-race:
 	go test -v $(TEST_FLAGS)
 
 server-up: server-down
diff --git a/adapter/ql/Makefile b/adapter/ql/Makefile
index 7c524fc..ec6c936 100644
--- a/adapter/ql/Makefile
+++ b/adapter/ql/Makefile
@@ -1,6 +1,6 @@
-SHELL ?= bash
+SHELL                 ?= bash
 
-DB_NAME ?= ql-test.db
+DB_NAME               ?= memory://virtual.db
 TEST_FLAGS            ?=
 
 export DB_NAME
@@ -8,16 +8,13 @@ export DB_NAME
 build:
 	go build && go install
 
-require-client:
-	@if [ -z "$$(which ql)" ]; then \
-		echo 'Missing "ql" command. Please install the QL cli tool and try again.' && \
-		exit 1; \
-	fi
+# Temporarily disabled due to https://gitlab.com/cznic/ql/-/issues/225
+#test:
+#	go test -v -race -timeout 20m $(TEST_FLAGS)
 
-reset-db: require-client
-	rm -f $(DB_NAME)
+test: test-no-race
 
-test: reset-db
+test-no-race:
 	go test -v $(TEST_FLAGS)
 
 test-extended: test
diff --git a/adapter/ql/connection.go b/adapter/ql/connection.go
index e613b8c..5881645 100644
--- a/adapter/ql/connection.go
+++ b/adapter/ql/connection.go
@@ -28,10 +28,11 @@ import (
 	"strings"
 )
 
-const connectionScheme = `file`
+const defaultConnectionScheme = `file`
 
 // ConnectionURL implements a QL connection struct.
 type ConnectionURL struct {
+	Scheme   string
 	Database string
 	Options  map[string]string
 }
@@ -60,10 +61,13 @@ func (c ConnectionURL) String() (s string) {
 
 	// Building URL.
 	u := url.URL{
-		Scheme:   connectionScheme,
+		Scheme:   c.Scheme,
 		Path:     c.Database,
 		RawQuery: vv.Encode(),
 	}
+	if u.Scheme == "" {
+		u.Scheme = defaultConnectionScheme
+	}
 
 	return u.String()
 }
@@ -72,23 +76,22 @@ func (c ConnectionURL) String() (s string) {
 func ParseURL(s string) (conn ConnectionURL, err error) {
 	var u *url.URL
 
-	if !strings.HasPrefix(s, connectionScheme+"://") {
-		return conn, fmt.Errorf(`Expecting file:// connection scheme.`)
-	}
-
 	if u, err = url.Parse(s); err != nil {
 		return conn, err
 	}
 
-	conn.Database = u.Host + u.Path
-	conn.Options = map[string]string{}
+	if u.Scheme != "file" && u.Scheme != "memory" && u.Scheme != "" {
+		return conn, fmt.Errorf(`Expecting file:// or memory:// connection scheme.`)
+	}
 
 	var vv url.Values
-
 	if vv, err = url.ParseQuery(u.RawQuery); err != nil {
 		return conn, err
 	}
 
+	conn.Scheme = u.Scheme
+	conn.Database = u.Host + u.Path
+	conn.Options = map[string]string{}
 	for k := range vv {
 		conn.Options[k] = vv.Get(k)
 	}
diff --git a/adapter/ql/database.go b/adapter/ql/database.go
index 754c417..afd5ab6 100644
--- a/adapter/ql/database.go
+++ b/adapter/ql/database.go
@@ -46,7 +46,7 @@ func (*database) Template() *exql.Template {
 }
 
 func (*database) OpenDSN(sess sqladapter.Session, dsn string) (*sql.DB, error) {
-	return sql.Open("ql", dsn)
+	return sql.Open("ql2", dsn)
 }
 
 func (*database) Collections(sess sqladapter.Session) (collections []string, err error) {
diff --git a/adapter/sqlite/Makefile b/adapter/sqlite/Makefile
index 482b858..df2af78 100644
--- a/adapter/sqlite/Makefile
+++ b/adapter/sqlite/Makefile
@@ -3,6 +3,7 @@ DB_NAME               ?= sqlite3-test.db
 TEST_FLAGS            ?=
 
 export DB_NAME
+
 export TEST_FLAGS
 
 build:
@@ -18,6 +19,9 @@ reset-db: require-client
 	rm -f $(DB_NAME)
 
 test: reset-db
+	go test -v -race -timeout 20m $(TEST_FLAGS)
+
+test-no-race:
 	go test -v $(TEST_FLAGS)
 
 test-extended: test
diff --git a/go.mod b/go.mod
index 46645a4..2e73170 100644
--- a/go.mod
+++ b/go.mod
@@ -3,13 +3,31 @@ module github.com/upper/db/v4
 go 1.15
 
 require (
-	github.com/denisenkom/go-mssqldb v0.0.0-20200620013148-b91950f658ec
+	github.com/PuerkitoBio/goquery v1.5.1 // indirect
+	github.com/denisenkom/go-mssqldb v0.9.0
 	github.com/go-sql-driver/mysql v1.5.0
 	github.com/google/uuid v1.1.1
-	github.com/lib/pq v1.8.0
-	github.com/mattn/go-sqlite3 v1.14.1
-	github.com/sirupsen/logrus v1.6.0
+	github.com/ipfs/go-detect-race v0.0.1
+	github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect
+	github.com/lib/pq v1.9.0
+	github.com/mattn/go-sqlite3 v1.14.5
+	github.com/sirupsen/logrus v1.7.0
 	github.com/stretchr/testify v1.6.1
+	gitlab.com/cznic/ebnf2y v1.0.0 // indirect
+	gitlab.com/cznic/golex v1.0.0 // indirect
+	golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 // indirect
+	golang.org/x/exp v0.0.0-20190411193353-0480eff6dd7c // indirect
+	golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
+	golang.org/x/sys v0.0.0-20201218084310-7d0127a74742 // indirect
 	gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
-	modernc.org/ql v1.1.0
+	gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
+	modernc.org/b v1.0.1 // indirect
+	modernc.org/db v1.0.1 // indirect
+	modernc.org/ebnfutil v1.0.0 // indirect
+	modernc.org/file v1.0.2 // indirect
+	modernc.org/golex v1.0.1 // indirect
+	modernc.org/lldb v1.0.1 // indirect
+	modernc.org/mathutil v1.2.1 // indirect
+	modernc.org/ql v1.3.1
+	modernc.org/zappy v1.0.2 // indirect
 )
diff --git a/go.sum b/go.sum
index 7a37312..899d4f4 100644
--- a/go.sum
+++ b/go.sum
@@ -6,26 +6,42 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/denisenkom/go-mssqldb v0.0.0-20200620013148-b91950f658ec h1:NfhRXXFDPxcF5Cwo06DzeIaE7uuJtAUhsDwH3LNsjos=
 github.com/denisenkom/go-mssqldb v0.0.0-20200620013148-b91950f658ec/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
+github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk=
+github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
 github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 h1:aaQcKT9WumO6JEJcRyTqFVq4XUZiUcKR2/GI31TOcz8=
 github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
+github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
+github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
 github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
 github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
 github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
+github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
+github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
 github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
+github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/mattn/go-sqlite3 v1.14.1 h1:AHx9Ra40wIzl+GelgX2X6AWxmT5tfxhI1PL0523HcSw=
 github.com/mattn/go-sqlite3 v1.14.1/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
+github.com/mattn/go-sqlite3 v1.14.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ=
+github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446 h1:/NRJ5vAYoqz+7sG51ubIDHXeWO8DlTSrToPu6q11ziA=
 github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
+github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
+github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
 github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
 github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
@@ -35,18 +51,28 @@ gitlab.com/cznic/golex v1.0.0/go.mod h1:vkWdDgqbbThjRHoOLU7yNPgMxaubAkwnvF/4zeG8
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
 golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20201217014255-9d1352758620 h1:3wPMTskHO3+O6jqTEXyFcsnuxMQOqYSaHsDxcbUXpqA=
+golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
+golang.org/x/exp v0.0.0-20181106170214-d68db9428509/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190411193353-0480eff6dd7c/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
 golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
 golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201218084310-7d0127a74742 h1:+CBz4km/0KPU3RGTwARGh/noP3bEwtHcq+0YcBQM2JQ=
+golang.org/x/sys v0.0.0-20201218084310-7d0127a74742/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -54,30 +80,57 @@ gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3
 gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 modernc.org/b v1.0.0 h1:vpvqeyp17ddcQWF29Czawql4lDdABCDRbXRAS4+aF2o=
 modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg=
+modernc.org/b v1.0.1 h1:8VABT8XSmy5060wa3xlq3DfWkgb/xOWT2Kwd3FLaA6A=
+modernc.org/b v1.0.1/go.mod h1:tDOyuvEozkYjX/zTreV7vX4YzdBVDkTS8JBA2W4y1r8=
 modernc.org/db v1.0.0 h1:2c6NdCfaLnshSvY7OU09cyAY0gYXUZj4lmg5ItHyucg=
 modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8=
+modernc.org/db v1.0.1 h1:BhmMWD64aPvNFuTB0nVZR9TFPG6X9ZmyKhcv+3jIjEs=
+modernc.org/db v1.0.1/go.mod h1:47Lw6e5W/cp7LsOTOFWsxeBY3UU9SpksM+mzvFC6D2Y=
 modernc.org/ebnfutil v1.0.0/go.mod h1:+2n/OnQXoild9pzrPa/2wmVtR+ufWjB/0fYkc0BV9sc=
 modernc.org/file v1.0.0 h1:9/PdvjVxd5+LcWUQIfapAWRGOkDLK90rloa8s/au06A=
 modernc.org/file v1.0.0/go.mod h1:uqEokAEn1u6e+J45e54dsEA/pw4o7zLrA2GwyntZzjw=
+modernc.org/file v1.0.1/go.mod h1:J8VpOGC1yz67lZWlr+JttVsXK5OWQCHLTwdrkejbneE=
+modernc.org/file v1.0.2 h1:KgufszwK4hxad+OvVBp32zSpCl1s4ctrwZESYbFdyEI=
+modernc.org/file v1.0.2/go.mod h1:J8VpOGC1yz67lZWlr+JttVsXK5OWQCHLTwdrkejbneE=
 modernc.org/fileutil v1.0.0 h1:Z1AFLZwl6BO8A5NldQg/xTSjGLetp+1Ubvl4alfGx8w=
 modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8=
 modernc.org/golex v1.0.0 h1:wWpDlbK8ejRfSyi0frMyhilD3JBvtcx2AdGDnU+JtsE=
 modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
+modernc.org/golex v1.0.1 h1:EYKY1a3wStt0RzHaH8mdSRNg78Ub0OHxYfCRWw35YtM=
+modernc.org/golex v1.0.1/go.mod h1:QCA53QtsT1NdGkaZZkF5ezFwk4IXh4BGNafAARTC254=
 modernc.org/internal v1.0.0 h1:XMDsFDcBDsibbBnHB2xzljZ+B1yrOVLEFkKL2u15Glw=
 modernc.org/internal v1.0.0/go.mod h1:VUD/+JAkhCpvkUitlEOnhpVxCgsBI90oTzSCRcqQVSM=
 modernc.org/lex v1.0.0/go.mod h1:G6rxMTy3cH2iA0iXL/HRRv4Znu8MK4higxph/lE7ypk=
 modernc.org/lexer v1.0.0/go.mod h1:F/Dld0YKYdZCLQ7bD0USbWL4YKCyTDRDHiDTOs0q0vk=
 modernc.org/lldb v1.0.0 h1:6vjDJxQEfhlOLwl4bhpwIz00uyFK4EmSYcbwqwbynsc=
 modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8=
+modernc.org/lldb v1.0.1 h1:VtkRpUW/fkzRKdfOJ7aQo8TWOC4A+F+Tl8En7rFS3ow=
+modernc.org/lldb v1.0.1/go.mod h1:+PHMSs/M3AmQyfhU3ArzoiHfJ2pSgH4TCibGbk7Rhpc=
 modernc.org/mathutil v1.0.0 h1:93vKjrJopTPrtTNpZ8XIovER7iCIH1QU7wNbOQXC60I=
 modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
+modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
+modernc.org/mathutil v1.2.0 h1:Tb16fUEZWEe1XaHBkpQmZX91vrAgl7XwWDCswCRfImg=
+modernc.org/mathutil v1.2.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
+modernc.org/mathutil v1.2.1 h1:PSIN4RdyeB6MbFsNLSkFCzDjnEVEMS3H/hFHcJtAJ9g=
+modernc.org/mathutil v1.2.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
 modernc.org/ql v1.1.0 h1:TUkpkmUf6562EZPTB1DH+EhJdE6265maYFS+eemhn08=
 modernc.org/ql v1.1.0/go.mod h1:Fj1ylcVyzcu/fgWZTrvBO9j/aEUg/ixLFnGtmzh7quI=
+modernc.org/ql v1.3.1 h1:gAXr1jn9w/WObUo12A1I5xMx/A8SrbRRBNzoBtCraPI=
+modernc.org/ql v1.3.1/go.mod h1:0su3LZVtXgxr5HnJc3DWIj4tb8Zx08BjZAzs//CUT6o=
 modernc.org/sortutil v1.0.0 h1:SUTM1sCR0Ldpv7dbB/KCPC2zHHsZ1KrSkhmGmmV22CQ=
 modernc.org/sortutil v1.0.0/go.mod h1:1QO0q8IlIlmjBIwm6t/7sof874+xCfZouyqZMLIAtxM=
+modernc.org/sortutil v1.1.0 h1:oP3U4uM+NT/qBQcbg/K2iqAX0Nx7B1b6YZtq3Gk/PjM=
+modernc.org/sortutil v1.1.0/go.mod h1:ZyL98OQHJgH9IEfN71VsamvJgrtRX9Dj2gX+vH86L1k=
 modernc.org/strutil v1.0.0 h1:XVFtQwFVwc02Wk+0L/Z/zDDXO81r5Lhe6iMKmGX3KhE=
 modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
+modernc.org/strutil v1.1.0 h1:+1/yCzZxY2pZwwrsbH+4T7BQMoLQ9QiBshRC9eicYsc=
+modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
 modernc.org/zappy v1.0.0 h1:dPVaP+3ueIUv4guk8PuZ2wiUGcJ1WUVvIheeSSTD0yk=
 modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4=
+modernc.org/zappy v1.0.1/go.mod h1:O0z5BRBwgfXAYDDhMqz9xVj0omSIEpspvGcwsyBe3FM=
+modernc.org/zappy v1.0.2 h1:sMwU2l77s4LKCmJwJ02u+S7t4H1llml4MvQQzGPqjsQ=
+modernc.org/zappy v1.0.2/go.mod h1:O0z5BRBwgfXAYDDhMqz9xVj0omSIEpspvGcwsyBe3FM=


Test patch:
diff --git a/adapter/ql/connection_test.go b/adapter/ql/connection_test.go
index 52fd2a0..cd453e0 100644
--- a/adapter/ql/connection_test.go
+++ b/adapter/ql/connection_test.go
@@ -22,27 +22,21 @@
 package ql
 
 import (
+	"github.com/stretchr/testify/assert"
 	"path/filepath"
 	"testing"
 )
 
 func TestConnectionURL(t *testing.T) {
-
 	c := ConnectionURL{}
 
-	// Default connection string is only the protocol.
-	if c.String() != "" {
-		t.Fatal(`Expecting default connectiong string to be empty, got:`, c.String())
-	}
+	assert.Zero(t, c.String())
 
 	// Adding a database name.
 	c.Database = "file://myfilename"
-
 	absoluteName, _ := filepath.Abs(c.Database)
 
-	if c.String() != "file://"+absoluteName+"" {
-		t.Fatal(`Test failed, got:`, c.String())
-	}
+	assert.Equal(t, "file://"+absoluteName, c.String())
 
 	// Adding an option.
 	c.Options = map[string]string{
@@ -50,17 +44,11 @@ func TestConnectionURL(t *testing.T) {
 		"mode":  "ro",
 	}
 
-	if c.String() != "file://"+absoluteName+"?cache=foobar&mode=ro" {
-		t.Fatal(`Test failed, got:`, c.String())
-	}
+	assert.Equal(t, "file://"+absoluteName+"?cache=foobar&mode=ro", c.String())
 
 	// Setting another database.
 	c.Database = "/another/database"
-
-	if c.String() != `file:///another/database?cache=foobar&mode=ro` {
-		t.Fatal(`Test failed, got:`, c.String())
-	}
-
+	assert.Equal(t, `file:///another/database?cache=foobar&mode=ro`, c.String())
 }
 
 func TestParseConnectionURL(t *testing.T) {
@@ -69,37 +57,25 @@ func TestParseConnectionURL(t *testing.T) {
 	var err error
 
 	s = "file://mydatabase.db"
-
-	if u, err = ParseURL(s); err != nil {
-		t.Fatal(err)
-	}
-
-	if u.Database != "mydatabase.db" {
-		t.Fatal("Failed to parse database.")
-	}
+	u, err = ParseURL(s)
+	assert.NoError(t, err)
+	assert.Equal(t, "mydatabase.db", u.Database)
 
 	s = "file:///path/to/my/database.db?mode=ro&cache=foobar"
+	u, err = ParseURL(s)
+	assert.NoError(t, err)
+	assert.Equal(t, "/path/to/my/database.db", u.Database)
 
-	if u, err = ParseURL(s); err != nil {
-		t.Fatal(err)
-	}
-
-	if u.Database != "/path/to/my/database.db" {
-		t.Fatal("Failed to parse username.")
-	}
-
-	if u.Options["cache"] != "foobar" {
-		t.Fatal("Expecting option.")
-	}
+	s = "memory:///path/to/my/database.db?mode=ro&cache=foobar"
+	u, err = ParseURL(s)
+	assert.NoError(t, err)
+	assert.Equal(t, "/path/to/my/database.db", u.Database)
 
-	if u.Options["mode"] != "ro" {
-		t.Fatal("Expecting option.")
-	}
+	assert.Equal(t, "foobar", u.Options["cache"])
+	assert.Equal(t, "ro", u.Options["mode"])
 
 	s = "http://example.org"
-
-	if _, err = ParseURL(s); err == nil {
-		t.Fatal("Expecting error.")
-	}
-
+	u, err = ParseURL(s)
+	assert.Error(t, err)
+	assert.Zero(t, u.Database)
 }
diff --git a/adapter/ql/helper_test.go b/adapter/ql/helper_test.go
index 37896e6..a8b49c6 100644
--- a/adapter/ql/helper_test.go
+++ b/adapter/ql/helper_test.go
@@ -29,8 +29,12 @@ import (
 	"github.com/upper/db/v4/internal/testsuite"
 )
 
-var settings = ConnectionURL{
-	Database: os.Getenv("DB_NAME"),
+var (
+	settings ConnectionURL
+)
+
+func init() {
+	settings, _ = ParseURL(os.Getenv("DB_NAME"))
 }
 
 type Helper struct {
diff --git a/internal/testsuite/sql_suite.go b/internal/testsuite/sql_suite.go
index 1bc5109..5739960 100644
--- a/internal/testsuite/sql_suite.go
+++ b/internal/testsuite/sql_suite.go
@@ -11,6 +11,7 @@ import (
 	"sync"
 	"time"
 
+	detectrace "github.com/ipfs/go-detect-race"
 	"github.com/sirupsen/logrus"
 	"github.com/stretchr/testify/suite"
 	db "github.com/upper/db/v4"
@@ -104,6 +105,16 @@ func (s *SQLTestSuite) TestPreparedStatementsCache() {
 	// This limit was chosen because, by default, MySQL accepts 16k statements
 	// and dies. See https://github.com/upper/db/issues/287
 	limit := 20000
+
+	if detectrace.WithRace() {
+		// When running this test under the Go race detector we quickly reach the limit
+		// of 8128 alive goroutines it can handle, so we set it to a safer number.
+		//
+		// Note that in order to fully stress this feature you'll have to run this
+		// test without the race detector.
+		limit = 8000
+	}
+
 	var wg sync.WaitGroup
 
 	for i := 0; i < limit; i++ {