mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	upgrade to use testfixtures v3 (#11904)
* upgrade to use testfixtures v3 * simplify logic * make vendor * update per @lunny * Update templates/repo/empty.tmpl * Update templates/repo/empty.tmpl Co-authored-by: Lauris BH <lauris@nix.lv>
This commit is contained in:
		@@ -37,7 +37,6 @@ import (
 | 
			
		||||
	"github.com/go-git/go-git/v5/plumbing"
 | 
			
		||||
	context2 "github.com/gorilla/context"
 | 
			
		||||
	"github.com/unknwon/com"
 | 
			
		||||
	"gopkg.in/testfixtures.v2"
 | 
			
		||||
	"xorm.io/xorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -96,14 +95,12 @@ func runPR() {
 | 
			
		||||
	setting.Database.LogSQL = true
 | 
			
		||||
	//x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
 | 
			
		||||
 | 
			
		||||
	var helper testfixtures.Helper = &testfixtures.SQLite{}
 | 
			
		||||
	models.NewEngine(context.Background(), func(_ *xorm.Engine) error {
 | 
			
		||||
		return nil
 | 
			
		||||
	})
 | 
			
		||||
	models.HasEngine = true
 | 
			
		||||
	//x.ShowSQL(true)
 | 
			
		||||
	err = models.InitFixtures(
 | 
			
		||||
		helper,
 | 
			
		||||
		path.Join(curDir, "models/fixtures/"),
 | 
			
		||||
	)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								go.mod
									
									
									
									
									
								
							@@ -44,6 +44,7 @@ require (
 | 
			
		||||
	github.com/go-redis/redis v6.15.2+incompatible
 | 
			
		||||
	github.com/go-sql-driver/mysql v1.4.1
 | 
			
		||||
	github.com/go-swagger/go-swagger v0.21.0
 | 
			
		||||
	github.com/go-testfixtures/testfixtures/v3 v3.2.0
 | 
			
		||||
	github.com/gobwas/glob v0.2.3
 | 
			
		||||
	github.com/gogs/chardet v0.0.0-20191104214054-4b6791f73a28
 | 
			
		||||
	github.com/gogs/cron v0.0.0-20171120032916-9f6c956d3e14
 | 
			
		||||
@@ -56,7 +57,6 @@ require (
 | 
			
		||||
	github.com/issue9/identicon v1.0.1
 | 
			
		||||
	github.com/jaytaylor/html2text v0.0.0-20160923191438-8fb95d837f7d
 | 
			
		||||
	github.com/jmhodges/levigo v1.0.0 // indirect
 | 
			
		||||
	github.com/joho/godotenv v1.3.0 // indirect
 | 
			
		||||
	github.com/kballard/go-shellquote v0.0.0-20170619183022-cd60e84ee657
 | 
			
		||||
	github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
 | 
			
		||||
	github.com/klauspost/compress v1.10.2
 | 
			
		||||
@@ -66,8 +66,7 @@ require (
 | 
			
		||||
	github.com/mailru/easyjson v0.7.0 // indirect
 | 
			
		||||
	github.com/markbates/goth v1.61.2
 | 
			
		||||
	github.com/mattn/go-isatty v0.0.11
 | 
			
		||||
	github.com/mattn/go-oci8 v0.0.0-20190320171441-14ba190cf52d // indirect
 | 
			
		||||
	github.com/mattn/go-sqlite3 v1.11.0
 | 
			
		||||
	github.com/mattn/go-sqlite3 v2.0.2+incompatible
 | 
			
		||||
	github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75
 | 
			
		||||
	github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81
 | 
			
		||||
	github.com/mgechev/revive v1.0.2
 | 
			
		||||
@@ -115,8 +114,7 @@ require (
 | 
			
		||||
	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 | 
			
		||||
	gopkg.in/ini.v1 v1.52.0
 | 
			
		||||
	gopkg.in/ldap.v3 v3.0.2
 | 
			
		||||
	gopkg.in/testfixtures.v2 v2.5.0
 | 
			
		||||
	gopkg.in/yaml.v2 v2.2.8
 | 
			
		||||
	gopkg.in/yaml.v2 v2.3.0
 | 
			
		||||
	mvdan.cc/xurls/v2 v2.1.0
 | 
			
		||||
	strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
 | 
			
		||||
	xorm.io/builder v0.3.7
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								go.sum
									
									
									
									
									
								
							@@ -149,6 +149,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 | 
			
		||||
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
 | 
			
		||||
github.com/denisenkom/go-mssqldb v0.0.0-20190924004331-208c0a498538 h1:bpWCJ5MddHsv4Xtl3azkK89mZzd/vvut32mvAnKbyUA=
 | 
			
		||||
github.com/denisenkom/go-mssqldb v0.0.0-20190924004331-208c0a498538/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
 | 
			
		||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
 | 
			
		||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg=
 | 
			
		||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
 | 
			
		||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 | 
			
		||||
@@ -278,6 +279,8 @@ github.com/go-swagger/go-swagger v0.21.0 h1:AX9mdfzp6eJtUe92nFrWmbK7ocRgkCDPJs0F
 | 
			
		||||
github.com/go-swagger/go-swagger v0.21.0/go.mod h1:tDb8PdDVFcaE8EPXkMOsuxpL3UEPiwu1UDZar9Z/1RY=
 | 
			
		||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0=
 | 
			
		||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0=
 | 
			
		||||
github.com/go-testfixtures/testfixtures/v3 v3.2.0 h1:FGAW3z5UzmrZGjR/dZp1u3Tbld0SDmirLO4RrR5++7Q=
 | 
			
		||||
github.com/go-testfixtures/testfixtures/v3 v3.2.0/go.mod h1:RZctY24ixituGC73XlAV1gkCwYMVwiSwPm26MNlQIhE=
 | 
			
		||||
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=
 | 
			
		||||
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
 | 
			
		||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
 | 
			
		||||
@@ -437,6 +440,7 @@ github.com/lestrrat-go/jwx v0.9.0/go.mod h1:iEoxlYfZjvoGpuWwxUz+eR5e6KTJGsaRcy/Y
 | 
			
		||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 | 
			
		||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
 | 
			
		||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 | 
			
		||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 | 
			
		||||
github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY=
 | 
			
		||||
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 | 
			
		||||
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 h1:uNwtsDp7ci48vBTTxDuwcoTXz4lwtDTe7TjCQ0noaWY=
 | 
			
		||||
@@ -462,13 +466,13 @@ github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc
 | 
			
		||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
 | 
			
		||||
github.com/mattn/go-oci8 v0.0.0-20190320171441-14ba190cf52d h1:m+dSK37rFf2fqppZhg15yI2IwC9BtucBiRwSDm9VL8g=
 | 
			
		||||
github.com/mattn/go-oci8 v0.0.0-20190320171441-14ba190cf52d/go.mod h1:/M9VLO+lUPmxvoOK2PfWRZ8mTtB4q1Hy9lEGijv9Nr8=
 | 
			
		||||
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
 | 
			
		||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 | 
			
		||||
github.com/mattn/go-sqlite3 v2.0.2+incompatible h1:qzw9c2GNT8UFrgWNDhCTqRqYUSmu/Dav/9Z58LGpk7U=
 | 
			
		||||
github.com/mattn/go-sqlite3 v2.0.2+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 | 
			
		||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
 | 
			
		||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 | 
			
		||||
github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 h1:Pijfgr7ZuvX7QIQiEwLdRVr3RoMG+i0SbBO1Qu+7yVk=
 | 
			
		||||
@@ -610,6 +614,8 @@ github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmq
 | 
			
		||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 | 
			
		||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
 | 
			
		||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 | 
			
		||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 | 
			
		||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 | 
			
		||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
 | 
			
		||||
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
 | 
			
		||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
 | 
			
		||||
@@ -890,8 +896,6 @@ gopkg.in/ldap.v3 v3.0.2 h1:R6RBtabK6e1GO0eQKtkyOFbAHO73QesLzI2w2DZ6b9w=
 | 
			
		||||
gopkg.in/ldap.v3 v3.0.2/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw=
 | 
			
		||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 | 
			
		||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
 | 
			
		||||
gopkg.in/testfixtures.v2 v2.5.0 h1:N08B7l2GzFQenyYbzqthDnKAA+cmb17iAZhhFxr7JHw=
 | 
			
		||||
gopkg.in/testfixtures.v2 v2.5.0/go.mod h1:vyAq+MYCgNpR29qitQdLZhdbLFf4mR/2MFJRFoQZZ2M=
 | 
			
		||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
 | 
			
		||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 | 
			
		||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
 | 
			
		||||
@@ -902,8 +906,11 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
 | 
			
		||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,6 @@ import (
 | 
			
		||||
	"github.com/PuerkitoBio/goquery"
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	"github.com/unknwon/com"
 | 
			
		||||
	"gopkg.in/testfixtures.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var mac *macaron.Macaron
 | 
			
		||||
@@ -88,22 +87,7 @@ func TestMain(m *testing.M) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var helper testfixtures.Helper
 | 
			
		||||
	if setting.Database.UseMySQL {
 | 
			
		||||
		helper = &testfixtures.MySQL{}
 | 
			
		||||
	} else if setting.Database.UsePostgreSQL {
 | 
			
		||||
		helper = &testfixtures.PostgreSQL{}
 | 
			
		||||
	} else if setting.Database.UseSQLite3 {
 | 
			
		||||
		helper = &testfixtures.SQLite{}
 | 
			
		||||
	} else if setting.Database.UseMSSQL {
 | 
			
		||||
		helper = &testfixtures.SQLServer{}
 | 
			
		||||
	} else {
 | 
			
		||||
		fmt.Println("Unsupported RDBMS for integration tests")
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := models.InitFixtures(
 | 
			
		||||
		helper,
 | 
			
		||||
		path.Join(filepath.Dir(setting.AppPath), "models/fixtures/"),
 | 
			
		||||
	)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,18 +6,48 @@ package models
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/testfixtures.v2"
 | 
			
		||||
	"github.com/go-testfixtures/testfixtures/v3"
 | 
			
		||||
	"xorm.io/xorm/schemas"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var fixtures *testfixtures.Context
 | 
			
		||||
var fixtures *testfixtures.Loader
 | 
			
		||||
 | 
			
		||||
// InitFixtures initialize test fixtures for a test database
 | 
			
		||||
func InitFixtures(helper testfixtures.Helper, dir string) (err error) {
 | 
			
		||||
	testfixtures.SkipDatabaseNameCheck(true)
 | 
			
		||||
	fixtures, err = testfixtures.NewFolder(x.DB().DB, helper, dir)
 | 
			
		||||
func InitFixtures(dir string) (err error) {
 | 
			
		||||
	testfiles := testfixtures.Directory(dir)
 | 
			
		||||
	dialect := "unknown"
 | 
			
		||||
	switch x.Dialect().URI().DBType {
 | 
			
		||||
	case schemas.POSTGRES:
 | 
			
		||||
		dialect = "postgres"
 | 
			
		||||
	case schemas.MYSQL:
 | 
			
		||||
		dialect = "mysql"
 | 
			
		||||
	case schemas.MSSQL:
 | 
			
		||||
		dialect = "mssql"
 | 
			
		||||
	case schemas.SQLITE:
 | 
			
		||||
		dialect = "sqlite3"
 | 
			
		||||
	default:
 | 
			
		||||
		fmt.Println("Unsupported RDBMS for integration tests")
 | 
			
		||||
		os.Exit(1)
 | 
			
		||||
	}
 | 
			
		||||
	loaderOptions := []func(loader *testfixtures.Loader) error{
 | 
			
		||||
		testfixtures.Database(x.DB().DB),
 | 
			
		||||
		testfixtures.Dialect(dialect),
 | 
			
		||||
		testfixtures.DangerousSkipTestDatabaseCheck(),
 | 
			
		||||
		testfiles,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if x.Dialect().URI().DBType == schemas.POSTGRES {
 | 
			
		||||
		loaderOptions = append(loaderOptions, testfixtures.SkipResetSequences())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fixtures, err = testfixtures.New(loaderOptions...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@ import (
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
	"github.com/unknwon/com"
 | 
			
		||||
	"gopkg.in/testfixtures.v2"
 | 
			
		||||
	"xorm.io/xorm"
 | 
			
		||||
	"xorm.io/xorm/names"
 | 
			
		||||
)
 | 
			
		||||
@@ -101,7 +100,7 @@ func CreateTestEngine(fixturesDir string) error {
 | 
			
		||||
		x.ShowSQL(true)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return InitFixtures(&testfixtures.SQLite{}, fixturesDir)
 | 
			
		||||
	return InitFixtures(fixturesDir)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func removeAllWithRetry(dir string) error {
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ _testmain.go
 | 
			
		||||
*.test
 | 
			
		||||
*.prof
 | 
			
		||||
 | 
			
		||||
# SQLite databases
 | 
			
		||||
*.sqlite3
 | 
			
		||||
 | 
			
		||||
.env
 | 
			
		||||
/testfixtures
 | 
			
		||||
/dist
 | 
			
		||||
							
								
								
									
										41
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/.goreleaser.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/.goreleaser.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
build:
 | 
			
		||||
  binary: testfixtures
 | 
			
		||||
  main: ./cmd/testfixtures
 | 
			
		||||
  goos:
 | 
			
		||||
    - windows
 | 
			
		||||
    - darwin
 | 
			
		||||
    - linux
 | 
			
		||||
  goarch:
 | 
			
		||||
    - 386
 | 
			
		||||
    - amd64
 | 
			
		||||
  ignore:
 | 
			
		||||
    - goos: darwin
 | 
			
		||||
      goarch: 386
 | 
			
		||||
  flags:
 | 
			
		||||
    - -tags=sqlite
 | 
			
		||||
 | 
			
		||||
archives:
 | 
			
		||||
  - name_template: "{{.Binary}}_{{.Os}}_{{.Arch}}"
 | 
			
		||||
    format_overrides:
 | 
			
		||||
      - goos: windows
 | 
			
		||||
        format: zip
 | 
			
		||||
 | 
			
		||||
release:
 | 
			
		||||
  draft: true
 | 
			
		||||
 | 
			
		||||
snapshot:
 | 
			
		||||
  name_template: "{{.Tag}}"
 | 
			
		||||
 | 
			
		||||
checksum:
 | 
			
		||||
  name_template: "testfixtures_checksums.txt"
 | 
			
		||||
 | 
			
		||||
nfpms:
 | 
			
		||||
  - vendor: testfixtures
 | 
			
		||||
    homepage: https://github.com/go-testfixtures/testfixtures
 | 
			
		||||
    maintainer: Andrey Nering <andrey.nering@gmail.com>
 | 
			
		||||
    description: Ruby on Rails like test fixtures for Go.
 | 
			
		||||
    license: MIT
 | 
			
		||||
    formats:
 | 
			
		||||
      - deb
 | 
			
		||||
      - rpm
 | 
			
		||||
    file_name_template: "{{.ProjectName}}_{{.Os}}_{{.Arch}}"
 | 
			
		||||
@@ -2,4 +2,3 @@ PG_CONN_STRING="user=postgres dbname=testfixtures_test sslmode=disable"
 | 
			
		||||
MYSQL_CONN_STRING="root:@/testfixtures_test?multiStatements=true"
 | 
			
		||||
SQLITE_CONN_STRING="testdb.sqlite3"
 | 
			
		||||
SQLSERVER_CONN_STRING="server=localhost\SQLExpress;database=testfixtures_test;user id=sa;password=sqlserver;encrypt=disable"
 | 
			
		||||
ORACLE_CONN_STRING="testfixtures/testfixtures@localhost/XE"
 | 
			
		||||
							
								
								
									
										93
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/CHANGELOG.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
# Changelog
 | 
			
		||||
 | 
			
		||||
## v3.2.0 - 2020-05-10
 | 
			
		||||
 | 
			
		||||
- Add support for loading multiple files and directories
 | 
			
		||||
  ([#65](https://github.com/go-testfixtures/testfixtures/pull/65)).
 | 
			
		||||
 | 
			
		||||
## v3.1.2 - 2020-04-26
 | 
			
		||||
 | 
			
		||||
- Dump: Fix column order in generated YAML files
 | 
			
		||||
  ([#62](https://github.com/go-testfixtures/testfixtures/pull/62)).
 | 
			
		||||
 | 
			
		||||
## v3.1.1 - 2020-01-11
 | 
			
		||||
 | 
			
		||||
- testfixtures now work with both `mssql` and `sqlserver` drivers.
 | 
			
		||||
  Note that [the `mssql` one is deprecated](https://github.com/denisenkom/go-mssqldb#deprecated),
 | 
			
		||||
  though. So try to migrate to `sqlserver` once possible.
 | 
			
		||||
 | 
			
		||||
## v3.1.0 - 2020-01-09
 | 
			
		||||
 | 
			
		||||
- Using `sqlserver` driver instead of the deprecated `mssql`
 | 
			
		||||
  ([#58](https://github.com/go-testfixtures/testfixtures/pull/58)).
 | 
			
		||||
 | 
			
		||||
## v3.0.0 - 2019-12-26
 | 
			
		||||
 | 
			
		||||
### Breaking changes
 | 
			
		||||
 | 
			
		||||
- The import path changed from `gopkg.in/testfixtures.v2` to
 | 
			
		||||
  `github.com/go-testfixtures/testfixtures/v3`.
 | 
			
		||||
- This package no longer support Oracle databases. This decision was
 | 
			
		||||
  taken because too few people actually used this package with Oracle and it
 | 
			
		||||
  was the most difficult to test (we didn't run on CI due the lack of an
 | 
			
		||||
  official Docker image, etc).
 | 
			
		||||
- The public API was totally rewritten to be more flexible and ideomatic.
 | 
			
		||||
  It now uses functional options. It differs from v2, but should be easy
 | 
			
		||||
  enough to upgrade.
 | 
			
		||||
- Some deprecated APIs from v2 were removed as well.
 | 
			
		||||
- This now requires Go >= 1.13.
 | 
			
		||||
 | 
			
		||||
### New features
 | 
			
		||||
 | 
			
		||||
- We now have a CLI so you can easily use testfixtures to load a sample
 | 
			
		||||
  database from fixtures if you want.
 | 
			
		||||
- Templating via [text/template](https://golang.org/pkg/text/template/)
 | 
			
		||||
  is now available. This allows some fancier use cases like generating data
 | 
			
		||||
  or specific columns dynamically.
 | 
			
		||||
- It's now possible to choose which time zone to use when parsing timestamps
 | 
			
		||||
  from fixtures. The default is the same as before, whatever is set on
 | 
			
		||||
  `time.Local`.
 | 
			
		||||
- Errors now use the new `%w` verb only available on Go >= 1.13.
 | 
			
		||||
 | 
			
		||||
### MISC
 | 
			
		||||
 | 
			
		||||
- Travis and AppVeyor are gone. We're using GitHub Actions exclusively now.
 | 
			
		||||
  The whole suite is ran inside Docker (with help of Docker Compose), so it's
 | 
			
		||||
  easy to run tests locally as well.
 | 
			
		||||
 | 
			
		||||
Check the new README for some examples!
 | 
			
		||||
 | 
			
		||||
## v2.6.0 - 2019-10-24
 | 
			
		||||
 | 
			
		||||
- Add support for TimescaleDB
 | 
			
		||||
  ([#53](https://github.com/go-testfixtures/testfixtures/pull/53)).
 | 
			
		||||
 | 
			
		||||
## v2.5.3 - 2018-12-15
 | 
			
		||||
 | 
			
		||||
- Fixes related to use of foreign key pragmas on MySQL (#43).
 | 
			
		||||
 | 
			
		||||
## v2.5.2 - 2018-11-25
 | 
			
		||||
 | 
			
		||||
- This library now supports [Go Modules](https://github.com/golang/go/wiki/Modules);
 | 
			
		||||
- Also allow `.yaml` (as an alternative to `.yml`) as the file extension (#42).
 | 
			
		||||
 | 
			
		||||
## v2.5.1 - 2018-11-04
 | 
			
		||||
 | 
			
		||||
- Allowing disabling reset of PostgreSQL sequences (#38).
 | 
			
		||||
 | 
			
		||||
## v2.5.0 - 2018-09-07
 | 
			
		||||
 | 
			
		||||
- Add public function DetectTestDatabase (#35, #36).
 | 
			
		||||
 | 
			
		||||
## v2.4.5 - 2018-07-07
 | 
			
		||||
 | 
			
		||||
- Fix for MySQL/MariaDB: ignoring views on operations that should be run only on tables (#33).
 | 
			
		||||
 | 
			
		||||
## v2.4.4 - 2018-07-02
 | 
			
		||||
 | 
			
		||||
- Fix for multiple schemas on Microsoft SQL Server (#29 and #30);
 | 
			
		||||
- Configuring AppVeyor CI to also test for Microsoft SQL Server.
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
Sorry, we don't have changelog for older releases 😢.
 | 
			
		||||
							
								
								
									
										9
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/Dockerfile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/Dockerfile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
FROM golang:1.14-alpine
 | 
			
		||||
 | 
			
		||||
RUN apk update
 | 
			
		||||
RUN apk add alpine-sdk
 | 
			
		||||
 | 
			
		||||
WORKDIR /testfixtures
 | 
			
		||||
COPY . .
 | 
			
		||||
 | 
			
		||||
RUN go mod download
 | 
			
		||||
							
								
								
									
										483
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										483
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,483 @@
 | 
			
		||||
# testfixtures
 | 
			
		||||
 | 
			
		||||
[][doc]
 | 
			
		||||
 | 
			
		||||
> ***Warning***: this package will wipe the database data before loading the
 | 
			
		||||
fixtures! It is supposed to be used on a test database. Please, double check
 | 
			
		||||
if you are running it against the correct database.
 | 
			
		||||
 | 
			
		||||
> **TIP**: There are options not described in this README page. It's
 | 
			
		||||
> recommended that you also check [the documentation][doc].
 | 
			
		||||
 | 
			
		||||
Writing tests is hard, even more when you have to deal with an SQL database.
 | 
			
		||||
This package aims to make writing functional tests for web apps written in
 | 
			
		||||
Go easier.
 | 
			
		||||
 | 
			
		||||
Basically this package mimics the ["Ruby on Rails' way"][railstests] of writing tests
 | 
			
		||||
for database applications, where sample data is kept in fixtures files. Before
 | 
			
		||||
the execution of every test, the test database is cleaned and the fixture data
 | 
			
		||||
is loaded into the database.
 | 
			
		||||
 | 
			
		||||
The idea is running tests against a real database, instead of relying in mocks,
 | 
			
		||||
which is boring to setup and may lead to production bugs not being caught in
 | 
			
		||||
the tests.
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
First, import it like this:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
import (
 | 
			
		||||
        "github.com/go-testfixtures/testfixtures/v3"
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
Create a folder for the fixture files. Each file should contain data for a
 | 
			
		||||
single table and have the name `<table_name>.yml`:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
myapp/
 | 
			
		||||
  myapp.go
 | 
			
		||||
  myapp_test.go
 | 
			
		||||
  ...
 | 
			
		||||
  fixtures/
 | 
			
		||||
    posts.yml
 | 
			
		||||
    comments.yml
 | 
			
		||||
    tags.yml
 | 
			
		||||
    posts_tags.yml
 | 
			
		||||
    ...
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The file would look like this (it can have as many record you want):
 | 
			
		||||
 | 
			
		||||
```yml
 | 
			
		||||
# comments.yml
 | 
			
		||||
- id: 1
 | 
			
		||||
  post_id: 1
 | 
			
		||||
  content: A comment...
 | 
			
		||||
  author_name: John Doe
 | 
			
		||||
  author_email: john@doe.com
 | 
			
		||||
  created_at: 2020-12-31 23:59:59
 | 
			
		||||
  updated_at: 2020-12-31 23:59:59
 | 
			
		||||
 | 
			
		||||
- id: 2
 | 
			
		||||
  post_id: 2
 | 
			
		||||
  content: Another comment...
 | 
			
		||||
  author_name: John Doe
 | 
			
		||||
  author_email: john@doe.com
 | 
			
		||||
  created_at: 2020-12-31 23:59:59
 | 
			
		||||
  updated_at: 2020-12-31 23:59:59
 | 
			
		||||
 | 
			
		||||
# ...
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
An YAML object or array will be converted to JSON. It will be stored on a native
 | 
			
		||||
JSON type like JSONB on PostgreSQL or as a TEXT or VARCHAR column on other
 | 
			
		||||
databases.
 | 
			
		||||
 | 
			
		||||
```yml
 | 
			
		||||
- id: 1
 | 
			
		||||
  post_attributes:
 | 
			
		||||
    author: John Due
 | 
			
		||||
    author_email: john@due.com
 | 
			
		||||
    title: "..."
 | 
			
		||||
    tags:
 | 
			
		||||
      - programming
 | 
			
		||||
      - go
 | 
			
		||||
      - testing
 | 
			
		||||
    post: "..."
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
If you need to write raw SQL, probably to call a function, prefix the value
 | 
			
		||||
of the column with `RAW=`:
 | 
			
		||||
 | 
			
		||||
```yml
 | 
			
		||||
- id: 1
 | 
			
		||||
  uuid_column: RAW=uuid_generate_v4()
 | 
			
		||||
  postgis_type_column: RAW=ST_GeomFromText('params...')
 | 
			
		||||
  created_at: RAW=NOW()
 | 
			
		||||
  updated_at: RAW=NOW()
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Your tests would look like this:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
package myapp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
        "database/sql"
 | 
			
		||||
 | 
			
		||||
        _ "github.com/lib/pq"
 | 
			
		||||
        "github.com/go-testfixtures/testfixtures/v3"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
        db *sql.DB
 | 
			
		||||
        fixtures *testfixtures.Loader
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestMain(m *testing.M) {
 | 
			
		||||
        var err error
 | 
			
		||||
 | 
			
		||||
        // Open connection to the test database.
 | 
			
		||||
        // Do NOT import fixtures in a production database!
 | 
			
		||||
        // Existing data would be deleted.
 | 
			
		||||
        db, err = sql.Open("postgres", "dbname=myapp_test")
 | 
			
		||||
        if err != nil {
 | 
			
		||||
                ...
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fixtures, err := testfixtures.New(
 | 
			
		||||
                testfixtures.Database(db), // You database connection
 | 
			
		||||
                testfixtures.Dialect("postgres"), // Available: "postgresql", "timescaledb", "mysql", "mariadb", "sqlite" and "sqlserver"
 | 
			
		||||
                testfixtures.Directory("testdata/fixtures"), // the directory containing the YAML files
 | 
			
		||||
        )
 | 
			
		||||
        if err != nil {
 | 
			
		||||
                ...
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        os.Exit(m.Run())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func prepareTestDatabase() {
 | 
			
		||||
        if err := fixtures.Load(); err != nil {
 | 
			
		||||
                ...
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestX(t *testing.T) {
 | 
			
		||||
        prepareTestDatabase()
 | 
			
		||||
 | 
			
		||||
        // Your test here ...
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestY(t *testing.T) {
 | 
			
		||||
        prepareTestDatabase()
 | 
			
		||||
 | 
			
		||||
        // Your test here ...
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestZ(t *testing.T) {
 | 
			
		||||
        prepareTestDatabase()
 | 
			
		||||
 | 
			
		||||
        // Your test here ...
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Alternatively, you can use the `Files` option, to specify which
 | 
			
		||||
files you want to load into the database:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
fixtures, err := testfixtures.New(
 | 
			
		||||
        testfixtures.Database(db),
 | 
			
		||||
        testfixtures.Dialect("postgres"),
 | 
			
		||||
        testfixtures.Files(
 | 
			
		||||
                "fixtures/orders.yml",
 | 
			
		||||
                "fixtures/customers.yml",
 | 
			
		||||
        ),
 | 
			
		||||
)
 | 
			
		||||
if err != nil {
 | 
			
		||||
        ...
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fixtures, err := testfixtures.NewFiles(db, &testfixtures.PostgreSQL{},
 | 
			
		||||
        "fixtures/orders.yml",
 | 
			
		||||
        "fixtures/customers.yml",
 | 
			
		||||
        // add as many files you want
 | 
			
		||||
)
 | 
			
		||||
if err != nil {
 | 
			
		||||
        ...
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
With `Paths` option, you can specify the paths that fixtures will load
 | 
			
		||||
from. Path can be directory or file. If directory, we will search YAML files
 | 
			
		||||
in it.
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
fixtures, err := testfixtures.New(
 | 
			
		||||
        testfixtures.Database(db),
 | 
			
		||||
        testfixtures.Dialect("postgres"),
 | 
			
		||||
        testfixtures.Paths(
 | 
			
		||||
                "fixtures/orders.yml",
 | 
			
		||||
                "fixtures/customers.yml",
 | 
			
		||||
                "common_fixtures/users"
 | 
			
		||||
        ),
 | 
			
		||||
)
 | 
			
		||||
if err != nil {
 | 
			
		||||
        ...
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Security check
 | 
			
		||||
 | 
			
		||||
In order to prevent you from accidentally wiping the wrong database, this
 | 
			
		||||
package will refuse to load fixtures if the database name (or database
 | 
			
		||||
filename for SQLite) doesn't contains "test". If you want to disable this
 | 
			
		||||
check, use:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
testfixtures.New(
 | 
			
		||||
        ...
 | 
			
		||||
        testfixtures.DangerousSkipTestDatabaseCheck(),
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Sequences
 | 
			
		||||
 | 
			
		||||
For PostgreSQL, this package also resets all sequences to a high
 | 
			
		||||
number to prevent duplicated primary keys while running the tests.
 | 
			
		||||
The default is 10000, but you can change that with:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
testfixtures.New(
 | 
			
		||||
        ...
 | 
			
		||||
        testfixtures.ResetSequencesTo(10000),
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Or, if you want to skip the reset of sequences entirely:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
testfixtures.New(
 | 
			
		||||
        ...
 | 
			
		||||
        testfixtures.SkipResetSequences(),
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Compatible databases
 | 
			
		||||
 | 
			
		||||
### PostgreSQL / TimescaleDB
 | 
			
		||||
 | 
			
		||||
This package has two approaches to disable foreign keys while importing fixtures
 | 
			
		||||
for PostgreSQL databases:
 | 
			
		||||
 | 
			
		||||
#### With `DISABLE TRIGGER`
 | 
			
		||||
 | 
			
		||||
This is the default approach. For that use:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
testfixtures.New(
 | 
			
		||||
        ...
 | 
			
		||||
        testfixtures.Dialect("postgres"), // or "timescaledb"
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
With the above snippet this package will use `DISABLE TRIGGER` to temporarily
 | 
			
		||||
disabling foreign key constraints while loading fixtures. This work with any
 | 
			
		||||
version of PostgreSQL, but it is **required** to be connected in the database
 | 
			
		||||
as a SUPERUSER. You can make a PostgreSQL user a SUPERUSER with:
 | 
			
		||||
 | 
			
		||||
```sql
 | 
			
		||||
ALTER USER your_user SUPERUSER;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### With `ALTER CONSTRAINT`
 | 
			
		||||
 | 
			
		||||
This approach don't require to be connected as a SUPERUSER, but only work with
 | 
			
		||||
PostgreSQL versions >= 9.4. Try this if you are getting foreign key violation
 | 
			
		||||
errors with the previous approach. It is as simple as using:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
testfixtures.New(
 | 
			
		||||
        ...
 | 
			
		||||
        testfixtures.Dialect("postgres"),
 | 
			
		||||
        testfixtures.UseAlterConstraint(),
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Tested using the [github.com/lib/pq](https://github.com/lib/pq) driver.
 | 
			
		||||
 | 
			
		||||
### MySQL / MariaDB
 | 
			
		||||
 | 
			
		||||
Just make sure the connection string have
 | 
			
		||||
[the multistatement parameter](https://github.com/go-sql-driver/mysql#multistatements)
 | 
			
		||||
set to true, and use:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
testfixtures.New(
 | 
			
		||||
        ...
 | 
			
		||||
        testfixtures.Dialect("mysql"), // or "mariadb"
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Tested using the [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) driver.
 | 
			
		||||
 | 
			
		||||
### SQLite
 | 
			
		||||
 | 
			
		||||
SQLite is also supported. It is recommended to create foreign keys as
 | 
			
		||||
`DEFERRABLE` (the default) to prevent problems. See more
 | 
			
		||||
[on the SQLite documentation](https://www.sqlite.org/foreignkeys.html#fk_deferred).
 | 
			
		||||
(Foreign key constraints are no-op by default on SQLite, but enabling it is
 | 
			
		||||
recommended).
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
testfixtures.New(
 | 
			
		||||
        ...
 | 
			
		||||
        testfixtures.Dialect("sqlite"),
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Tested using the [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) driver.
 | 
			
		||||
 | 
			
		||||
### Microsoft SQL Server
 | 
			
		||||
 | 
			
		||||
SQL Server support requires SQL Server >= 2008. Inserting on `IDENTITY` columns
 | 
			
		||||
are handled as well. Just make sure you are logged in with a user with
 | 
			
		||||
`ALTER TABLE` permission.
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
testfixtures.New(
 | 
			
		||||
        ...
 | 
			
		||||
        testfixtures.Dialect("sqlserver"),
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Tested using the `mssql` and `sqlserver` drivers from the
 | 
			
		||||
[github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb) lib.
 | 
			
		||||
 | 
			
		||||
## Templating
 | 
			
		||||
 | 
			
		||||
Testfixtures supports templating, but it's disabled by default. Most people
 | 
			
		||||
won't need it, but it may be useful to dynamically generate data.
 | 
			
		||||
 | 
			
		||||
Enable it by doing:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
testfixtures.New(
 | 
			
		||||
        ...
 | 
			
		||||
        testfixtures.Template(),
 | 
			
		||||
 | 
			
		||||
        // the above options are optional
 | 
			
		||||
        TemplateFuncs(...),
 | 
			
		||||
        TemplateDelims("{{", "}}"),
 | 
			
		||||
        TemplateOptions("missingkey=zero"),
 | 
			
		||||
        TemplateData(...),
 | 
			
		||||
)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The YAML file could look like this:
 | 
			
		||||
 | 
			
		||||
```yaml
 | 
			
		||||
# It's possible generate values...
 | 
			
		||||
- id: {{sha256 "my-awesome-post}}
 | 
			
		||||
  title: My Awesome Post
 | 
			
		||||
  text: {{randomText}}
 | 
			
		||||
 | 
			
		||||
# ... or records
 | 
			
		||||
{{range $post := $.Posts}}
 | 
			
		||||
- id: {{$post.Id}}
 | 
			
		||||
  title: {{$post.Title}}
 | 
			
		||||
  text: {{$post.Text}}
 | 
			
		||||
{{end}}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Generating fixtures for a existing database
 | 
			
		||||
 | 
			
		||||
The following code will generate a YAML file for each table of the database
 | 
			
		||||
into a given folder. It may be useful to boostrap a test scenario from a sample
 | 
			
		||||
database of your app.
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
dumper, err := testfixtures.NewDumper(
 | 
			
		||||
        testfixtures.DumpDatabase(db),
 | 
			
		||||
        testfixtures.DumpDialect("postgres"), // or your database of choice
 | 
			
		||||
        testfixtures.DumpDirectory("tmp/fixtures"),
 | 
			
		||||
        textfixtures.DumpTables( // optional, will dump all table if not given
 | 
			
		||||
          "posts",
 | 
			
		||||
          "comments",
 | 
			
		||||
          "tags",
 | 
			
		||||
        )
 | 
			
		||||
)
 | 
			
		||||
if err != nil {
 | 
			
		||||
        ...
 | 
			
		||||
}
 | 
			
		||||
if err := dumper.Dump(); err != nil {
 | 
			
		||||
        ...
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
> This was intended to run in small sample databases. It will likely break
 | 
			
		||||
if run in a production/big database.
 | 
			
		||||
 | 
			
		||||
## Gotchas
 | 
			
		||||
 | 
			
		||||
### Parallel testing
 | 
			
		||||
 | 
			
		||||
This library doesn't yet support running tests in parallel! Running tests
 | 
			
		||||
in parallel can result in random data being present in the database, which
 | 
			
		||||
will likely cause tests to randomly/intermittently fail.
 | 
			
		||||
 | 
			
		||||
This is specially tricky since it's not immediately clear that `go test ./...`
 | 
			
		||||
run tests for each package in parallel. If more than one package use this
 | 
			
		||||
library, you can face this issue. Please, use `go test -p 1 ./...` or run tests
 | 
			
		||||
for each package in separated commands to fix this issue.
 | 
			
		||||
 | 
			
		||||
If you're looking into being able to run tests in parallel you can try using
 | 
			
		||||
testfixtures together with the [txdb][gotxdb] package, which allows wrapping
 | 
			
		||||
each test run in a transaction.
 | 
			
		||||
 | 
			
		||||
## CLI
 | 
			
		||||
 | 
			
		||||
We also have a CLI to load fixtures in a given database.
 | 
			
		||||
Grab it from the [releases page](https://github.com/go-testfixtures/testfixtures/releases)
 | 
			
		||||
and use it like:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
testfixtures -d postgres -c "postgres://user:password@localhost/database" -D testdata/fixtures
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The connection string changes for each database driver.
 | 
			
		||||
 | 
			
		||||
Use `--help` for all flags.
 | 
			
		||||
 | 
			
		||||
## Contributing
 | 
			
		||||
 | 
			
		||||
We recommend you to [install Task](https://taskfile.dev/#/installation) and
 | 
			
		||||
Docker before contributing to this package, since some stuff is automated
 | 
			
		||||
using these tools.
 | 
			
		||||
 | 
			
		||||
It's recommended to use Docker Compose to run tests, since it runs tests for
 | 
			
		||||
all supported databases once. To do that you just need to run:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
task docker
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
But if you want to run tests locally, copy the `.sample.env` file as `.env`
 | 
			
		||||
and edit it according to your database setup. You'll need to create a database
 | 
			
		||||
(likely names `testfixtures_test`) before continuing. Then run the command
 | 
			
		||||
for the database you want to run tests against:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
task test:pg # PostgreSQL
 | 
			
		||||
task test:mysql # MySQL
 | 
			
		||||
task test:sqlite # SQLite
 | 
			
		||||
task test:sqlserver # Microsoft SQL Server
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
GitHub Actions (CI) runs the same Docker setup available locally.
 | 
			
		||||
 | 
			
		||||
## Alternatives
 | 
			
		||||
 | 
			
		||||
If you don't think using fixtures is a good idea, you can try one of these
 | 
			
		||||
packages instead:
 | 
			
		||||
 | 
			
		||||
- [factory-go][factorygo]: Factory for Go. Inspired by Python's Factory Boy
 | 
			
		||||
and Ruby's Factory Girl
 | 
			
		||||
- [go-txdb (Single transaction SQL driver for Go)][gotxdb]: Use a single
 | 
			
		||||
database transaction for each functional test, so you can rollback to
 | 
			
		||||
previous state between tests to have the same database state in all tests
 | 
			
		||||
- [go-sqlmock][gosqlmock]: A mock for the sql.DB interface. This allow you to
 | 
			
		||||
unit test database code without having to connect to a real database
 | 
			
		||||
- [dbcleaner][dbcleaner] - Clean database for testing, inspired by
 | 
			
		||||
database_cleaner for Ruby
 | 
			
		||||
 | 
			
		||||
[doc]: https://pkg.go.dev/github.com/go-testfixtures/testfixtures/v3?tab=doc
 | 
			
		||||
[railstests]: http://guides.rubyonrails.org/testing.html#the-test-database
 | 
			
		||||
[gotxdb]: https://github.com/DATA-DOG/go-txdb
 | 
			
		||||
[gosqlmock]: https://github.com/DATA-DOG/go-sqlmock
 | 
			
		||||
[factorygo]: https://github.com/bluele/factory-go
 | 
			
		||||
[dbcleaner]: https://github.com/khaiql/dbcleaner
 | 
			
		||||
							
								
								
									
										59
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/Taskfile.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/Taskfile.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
# https://taskfile.org
 | 
			
		||||
 | 
			
		||||
version: '2'
 | 
			
		||||
 | 
			
		||||
tasks:
 | 
			
		||||
  build:
 | 
			
		||||
    cmds:
 | 
			
		||||
      - go build -v -tags sqlite -o ./testfixtures{{exeExt}} ./cmd/testfixtures
 | 
			
		||||
 | 
			
		||||
  test-cli:
 | 
			
		||||
    cmds:
 | 
			
		||||
      - ./testfixtures -d sqlite -c testdb.sqlite3 -D testdata/fixtures
 | 
			
		||||
 | 
			
		||||
  test:pg:
 | 
			
		||||
    desc: Test PostgreSQL
 | 
			
		||||
    cmds:
 | 
			
		||||
      - task: test-db
 | 
			
		||||
        vars: {DATABASE: postgresql}
 | 
			
		||||
 | 
			
		||||
  test:mysql:
 | 
			
		||||
    desc: Test MySQL
 | 
			
		||||
    cmds:
 | 
			
		||||
      - task: test:db
 | 
			
		||||
        vars: {DATABASE: mysql}
 | 
			
		||||
 | 
			
		||||
  test:sqlite:
 | 
			
		||||
    desc: Test SQLite
 | 
			
		||||
    cmds:
 | 
			
		||||
      - task: test-db
 | 
			
		||||
        vars: {DATABASE: sqlite}
 | 
			
		||||
 | 
			
		||||
  test:sqlserver:
 | 
			
		||||
    desc: Test SQLServer
 | 
			
		||||
    cmds:
 | 
			
		||||
      - task: test-db
 | 
			
		||||
        vars: {DATABASE: sqlserver}
 | 
			
		||||
 | 
			
		||||
  test-db:
 | 
			
		||||
    cmds:
 | 
			
		||||
      - go test -v -tags {{.DATABASE}}
 | 
			
		||||
 | 
			
		||||
  goreleaser:test:
 | 
			
		||||
    desc: Tests release process without publishing
 | 
			
		||||
    cmds:
 | 
			
		||||
      - goreleaser --snapshot --rm-dist
 | 
			
		||||
 | 
			
		||||
  docker:
 | 
			
		||||
    cmds:
 | 
			
		||||
      - task: docker:build
 | 
			
		||||
      - task: docker:test
 | 
			
		||||
 | 
			
		||||
  docker:build:
 | 
			
		||||
    cmds:
 | 
			
		||||
      - docker build -t testfixtures .
 | 
			
		||||
 | 
			
		||||
  docker:test:
 | 
			
		||||
    cmds:
 | 
			
		||||
      - docker-compose down -v
 | 
			
		||||
      - docker-compose run testfixtures go test -v -tags 'postgresql sqlite mysql sqlserver'
 | 
			
		||||
							
								
								
									
										37
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/docker-compose.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/docker-compose.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
version: '3'
 | 
			
		||||
 | 
			
		||||
services:
 | 
			
		||||
  testfixtures:
 | 
			
		||||
    image: testfixtures
 | 
			
		||||
    depends_on:
 | 
			
		||||
      - postgresql
 | 
			
		||||
      - mysql
 | 
			
		||||
      - sqlserver
 | 
			
		||||
    environment:
 | 
			
		||||
      PGPASSWORD: postgres
 | 
			
		||||
      PG_CONN_STRING: host=postgresql user=postgres dbname=testfixtures_test port=5432 sslmode=disable
 | 
			
		||||
 | 
			
		||||
      MYSQL_CONN_STRING: root:mysql@tcp(mysql)/testfixtures_test?multiStatements=true
 | 
			
		||||
 | 
			
		||||
      SQLITE_CONN_STRING: testfixtures_test.sqlite3
 | 
			
		||||
 | 
			
		||||
      SQLSERVER_CONN_STRING: server=sqlserver;database=master;user id=sa;password=SQL@1server;encrypt=disable
 | 
			
		||||
 | 
			
		||||
  postgresql:
 | 
			
		||||
    image: postgres:12.1-alpine
 | 
			
		||||
    environment:
 | 
			
		||||
      POSTGRES_DB: testfixtures_test
 | 
			
		||||
      POSTGRES_USER: postgres
 | 
			
		||||
      POSTGRES_PASSWORD: postgres
 | 
			
		||||
 | 
			
		||||
  mysql:
 | 
			
		||||
    image: mysql:8.0
 | 
			
		||||
    environment:
 | 
			
		||||
      MYSQL_DATABASE: testfixtures_test
 | 
			
		||||
      MYSQL_ROOT_PASSWORD: mysql
 | 
			
		||||
 | 
			
		||||
  sqlserver:
 | 
			
		||||
    image: mcr.microsoft.com/mssql/server:2019-latest
 | 
			
		||||
    environment:
 | 
			
		||||
      ACCEPT_EULA: 'Y'
 | 
			
		||||
      SA_PASSWORD: SQL@1server
 | 
			
		||||
							
								
								
									
										165
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/dump.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/dump.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
package testfixtures
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"unicode/utf8"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/yaml.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Dumper is resposible for dumping fixtures from the database into a
 | 
			
		||||
// directory.
 | 
			
		||||
type Dumper struct {
 | 
			
		||||
	db     *sql.DB
 | 
			
		||||
	helper helper
 | 
			
		||||
	dir    string
 | 
			
		||||
 | 
			
		||||
	tables []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDumper creates a new dumper with the given options.
 | 
			
		||||
//
 | 
			
		||||
// The "DumpDatabase", "DumpDialect" and "DumpDirectory" options are required.
 | 
			
		||||
func NewDumper(options ...func(*Dumper) error) (*Dumper, error) {
 | 
			
		||||
	d := &Dumper{}
 | 
			
		||||
 | 
			
		||||
	for _, option := range options {
 | 
			
		||||
		if err := option(d); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return d, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DumpDatabase sets the database to be dumped.
 | 
			
		||||
func DumpDatabase(db *sql.DB) func(*Dumper) error {
 | 
			
		||||
	return func(d *Dumper) error {
 | 
			
		||||
		d.db = db
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DumpDialect informs Loader about which database dialect you're using.
 | 
			
		||||
//
 | 
			
		||||
// Possible options are "postgresql", "timescaledb", "mysql", "mariadb",
 | 
			
		||||
// "sqlite" and "sqlserver".
 | 
			
		||||
func DumpDialect(dialect string) func(*Dumper) error {
 | 
			
		||||
	return func(d *Dumper) error {
 | 
			
		||||
		h, err := helperForDialect(dialect)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		d.helper = h
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DumpDirectory sets the directory where the fixtures files will be created.
 | 
			
		||||
func DumpDirectory(dir string) func(*Dumper) error {
 | 
			
		||||
	return func(d *Dumper) error {
 | 
			
		||||
		d.dir = dir
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DumpTables allows you to choose which tables you want to dump.
 | 
			
		||||
//
 | 
			
		||||
// If not informed, Dumper will dump all tables by default.
 | 
			
		||||
func DumpTables(tables ...string) func(*Dumper) error {
 | 
			
		||||
	return func(d *Dumper) error {
 | 
			
		||||
		d.tables = tables
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Dump dumps the databases as YAML fixtures.
 | 
			
		||||
func (d *Dumper) Dump() error {
 | 
			
		||||
	tables := d.tables
 | 
			
		||||
	if len(tables) == 0 {
 | 
			
		||||
		var err error
 | 
			
		||||
		tables, err = d.helper.tableNames(d.db)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, table := range tables {
 | 
			
		||||
		if err := d.dumpTable(table); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *Dumper) dumpTable(table string) error {
 | 
			
		||||
	query := fmt.Sprintf("SELECT * FROM %s", d.helper.quoteKeyword(table))
 | 
			
		||||
 | 
			
		||||
	stmt, err := d.db.Prepare(query)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer stmt.Close()
 | 
			
		||||
 | 
			
		||||
	rows, err := stmt.Query()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer rows.Close()
 | 
			
		||||
 | 
			
		||||
	columns, err := rows.Columns()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fixtures := make([]yaml.MapSlice, 0, 10)
 | 
			
		||||
	for rows.Next() {
 | 
			
		||||
		entries := make([]interface{}, len(columns))
 | 
			
		||||
		entryPtrs := make([]interface{}, len(entries))
 | 
			
		||||
		for i := range entries {
 | 
			
		||||
			entryPtrs[i] = &entries[i]
 | 
			
		||||
		}
 | 
			
		||||
		if err := rows.Scan(entryPtrs...); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		entryMap := make([]yaml.MapItem, len(entries))
 | 
			
		||||
		for i, column := range columns {
 | 
			
		||||
			entryMap[i] = yaml.MapItem{
 | 
			
		||||
				Key:   column,
 | 
			
		||||
				Value: convertValue(entries[i]),
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		fixtures = append(fixtures, entryMap)
 | 
			
		||||
	}
 | 
			
		||||
	if err = rows.Err(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	filePath := filepath.Join(d.dir, table+".yml")
 | 
			
		||||
	f, err := os.Create(filePath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer f.Close()
 | 
			
		||||
 | 
			
		||||
	data, err := yaml.Marshal(fixtures)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	_, err = f.Write(data)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func convertValue(value interface{}) interface{} {
 | 
			
		||||
	switch v := value.(type) {
 | 
			
		||||
	case []byte:
 | 
			
		||||
		if utf8.Valid(v) {
 | 
			
		||||
			return string(v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return value
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
module github.com/go-testfixtures/testfixtures/v3
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73
 | 
			
		||||
	github.com/go-sql-driver/mysql v1.4.1
 | 
			
		||||
	github.com/joho/godotenv v1.3.0
 | 
			
		||||
	github.com/lib/pq v1.3.0
 | 
			
		||||
	github.com/mattn/go-sqlite3 v2.0.2+incompatible
 | 
			
		||||
	github.com/spf13/pflag v1.0.5
 | 
			
		||||
	google.golang.org/appengine v1.3.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v2 v2.2.7
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
go 1.13
 | 
			
		||||
							
								
								
									
										26
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/go.sum
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/go.sum
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73 h1:OGNva6WhsKst5OZf7eZOklDztV3hwtTHovdrLHV+MsA=
 | 
			
		||||
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 | 
			
		||||
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/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
			
		||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
 | 
			
		||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
 | 
			
		||||
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
 | 
			
		||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 | 
			
		||||
github.com/mattn/go-sqlite3 v2.0.2+incompatible h1:qzw9c2GNT8UFrgWNDhCTqRqYUSmu/Dav/9Z58LGpk7U=
 | 
			
		||||
github.com/mattn/go-sqlite3 v2.0.2+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 | 
			
		||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 | 
			
		||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 | 
			
		||||
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/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
google.golang.org/appengine v1.3.0 h1:FBSsiFRMz3LBeXIomRnVzrQwSDj4ibvcRexLG0LZGQk=
 | 
			
		||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
@@ -8,13 +8,12 @@ import (
 | 
			
		||||
const (
 | 
			
		||||
	paramTypeDollar = iota + 1
 | 
			
		||||
	paramTypeQuestion
 | 
			
		||||
	paramTypeColon
 | 
			
		||||
	paramTypeAtSign
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type loadFunction func(tx *sql.Tx) error
 | 
			
		||||
 | 
			
		||||
// Helper is the generic interface for the database helper
 | 
			
		||||
type Helper interface {
 | 
			
		||||
type helper interface {
 | 
			
		||||
	init(*sql.DB) error
 | 
			
		||||
	disableReferentialIntegrity(*sql.DB, loadFunction) error
 | 
			
		||||
	paramType() int
 | 
			
		||||
@@ -43,11 +42,10 @@ type batchSplitter interface {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	_ Helper = &MySQL{}
 | 
			
		||||
	_ Helper = &PostgreSQL{}
 | 
			
		||||
	_ Helper = &SQLite{}
 | 
			
		||||
	_ Helper = &Oracle{}
 | 
			
		||||
	_ Helper = &SQLServer{}
 | 
			
		||||
	_ helper = &mySQL{}
 | 
			
		||||
	_ helper = &postgreSQL{}
 | 
			
		||||
	_ helper = &sqlite{}
 | 
			
		||||
	_ helper = &sqlserver{}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type baseHelper struct{}
 | 
			
		||||
@@ -5,14 +5,13 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MySQL is the MySQL helper for this package
 | 
			
		||||
type MySQL struct {
 | 
			
		||||
type mySQL struct {
 | 
			
		||||
	baseHelper
 | 
			
		||||
	tables         []string
 | 
			
		||||
	tablesChecksum map[string]int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *MySQL) init(db *sql.DB) error {
 | 
			
		||||
func (h *mySQL) init(db *sql.DB) error {
 | 
			
		||||
	var err error
 | 
			
		||||
	h.tables, err = h.tableNames(db)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -22,21 +21,21 @@ func (h *MySQL) init(db *sql.DB) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*MySQL) paramType() int {
 | 
			
		||||
func (*mySQL) paramType() int {
 | 
			
		||||
	return paramTypeQuestion
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*MySQL) quoteKeyword(str string) string {
 | 
			
		||||
func (*mySQL) quoteKeyword(str string) string {
 | 
			
		||||
	return fmt.Sprintf("`%s`", str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*MySQL) databaseName(q queryable) (string, error) {
 | 
			
		||||
func (*mySQL) databaseName(q queryable) (string, error) {
 | 
			
		||||
	var dbName string
 | 
			
		||||
	err := q.QueryRow("SELECT DATABASE()").Scan(&dbName)
 | 
			
		||||
	return dbName, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *MySQL) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
func (h *mySQL) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
	query := `
 | 
			
		||||
		SELECT table_name
 | 
			
		||||
		FROM information_schema.tables
 | 
			
		||||
@@ -69,14 +68,7 @@ func (h *MySQL) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *MySQL) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
	// re-enable after load
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if _, err2 := db.Exec("SET FOREIGN_KEY_CHECKS = 1"); err2 != nil && err == nil {
 | 
			
		||||
			err = err2
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
func (h *mySQL) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
	tx, err := db.Begin()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
@@ -87,14 +79,19 @@ func (h *MySQL) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (er
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = loadFn(tx); err != nil {
 | 
			
		||||
	err = loadFn(tx)
 | 
			
		||||
	_, err2 := tx.Exec("SET FOREIGN_KEY_CHECKS = 1")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if err2 != nil {
 | 
			
		||||
		return err2
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return tx.Commit()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *MySQL) isTableModified(q queryable, tableName string) (bool, error) {
 | 
			
		||||
func (h *mySQL) isTableModified(q queryable, tableName string) (bool, error) {
 | 
			
		||||
	checksum, err := h.getChecksum(q, tableName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return true, err
 | 
			
		||||
@@ -105,7 +102,7 @@ func (h *MySQL) isTableModified(q queryable, tableName string) (bool, error) {
 | 
			
		||||
	return oldChecksum == 0 || checksum != oldChecksum, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *MySQL) afterLoad(q queryable) error {
 | 
			
		||||
func (h *mySQL) afterLoad(q queryable) error {
 | 
			
		||||
	if h.tablesChecksum != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
@@ -121,7 +118,7 @@ func (h *MySQL) afterLoad(q queryable) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *MySQL) getChecksum(q queryable, tableName string) (int64, error) {
 | 
			
		||||
func (h *mySQL) getChecksum(q queryable, tableName string) (int64, error) {
 | 
			
		||||
	sql := fmt.Sprintf("CHECKSUM TABLE %s", h.quoteKeyword(tableName))
 | 
			
		||||
	var (
 | 
			
		||||
		table    string
 | 
			
		||||
@@ -6,15 +6,12 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PostgreSQL is the PG helper for this package
 | 
			
		||||
type PostgreSQL struct {
 | 
			
		||||
type postgreSQL struct {
 | 
			
		||||
	baseHelper
 | 
			
		||||
 | 
			
		||||
	// UseAlterConstraint If true, the contraint disabling will do
 | 
			
		||||
	// using ALTER CONTRAINT sintax, only allowed in PG >= 9.4.
 | 
			
		||||
	// If false, the constraint disabling will use DISABLE TRIGGER ALL,
 | 
			
		||||
	// which requires SUPERUSER privileges.
 | 
			
		||||
	UseAlterConstraint bool
 | 
			
		||||
	useAlterConstraint bool
 | 
			
		||||
	skipResetSequences bool
 | 
			
		||||
	resetSequencesTo   int64
 | 
			
		||||
 | 
			
		||||
	tables                   []string
 | 
			
		||||
	sequences                []string
 | 
			
		||||
@@ -27,7 +24,7 @@ type pgConstraint struct {
 | 
			
		||||
	constraintName string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *PostgreSQL) init(db *sql.DB) error {
 | 
			
		||||
func (h *postgreSQL) init(db *sql.DB) error {
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	h.tables, err = h.tableNames(db)
 | 
			
		||||
@@ -48,17 +45,17 @@ func (h *PostgreSQL) init(db *sql.DB) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*PostgreSQL) paramType() int {
 | 
			
		||||
func (*postgreSQL) paramType() int {
 | 
			
		||||
	return paramTypeDollar
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*PostgreSQL) databaseName(q queryable) (string, error) {
 | 
			
		||||
func (*postgreSQL) databaseName(q queryable) (string, error) {
 | 
			
		||||
	var dbName string
 | 
			
		||||
	err := q.QueryRow("SELECT current_database()").Scan(&dbName)
 | 
			
		||||
	return dbName, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *PostgreSQL) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
func (h *postgreSQL) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
	var tables []string
 | 
			
		||||
 | 
			
		||||
	sql := `
 | 
			
		||||
@@ -67,7 +64,8 @@ func (h *PostgreSQL) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
		INNER JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
 | 
			
		||||
		WHERE pg_class.relkind = 'r'
 | 
			
		||||
		  AND pg_namespace.nspname NOT IN ('pg_catalog', 'information_schema')
 | 
			
		||||
		  AND pg_namespace.nspname NOT LIKE 'pg_toast%';
 | 
			
		||||
		  AND pg_namespace.nspname NOT LIKE 'pg_toast%'
 | 
			
		||||
		  AND pg_namespace.nspname NOT LIKE '\_timescaledb%';
 | 
			
		||||
	`
 | 
			
		||||
	rows, err := q.Query(sql)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -88,12 +86,13 @@ func (h *PostgreSQL) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
	return tables, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *PostgreSQL) getSequences(q queryable) ([]string, error) {
 | 
			
		||||
func (h *postgreSQL) getSequences(q queryable) ([]string, error) {
 | 
			
		||||
	const sql = `
 | 
			
		||||
		SELECT pg_namespace.nspname || '.' || pg_class.relname AS sequence_name
 | 
			
		||||
		FROM pg_class
 | 
			
		||||
		INNER JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace
 | 
			
		||||
		WHERE pg_class.relkind = 'S'
 | 
			
		||||
		  AND pg_namespace.nspname NOT LIKE '\_timescaledb%'
 | 
			
		||||
	`
 | 
			
		||||
 | 
			
		||||
	rows, err := q.Query(sql)
 | 
			
		||||
@@ -116,7 +115,7 @@ func (h *PostgreSQL) getSequences(q queryable) ([]string, error) {
 | 
			
		||||
	return sequences, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*PostgreSQL) getNonDeferrableConstraints(q queryable) ([]pgConstraint, error) {
 | 
			
		||||
func (*postgreSQL) getNonDeferrableConstraints(q queryable) ([]pgConstraint, error) {
 | 
			
		||||
	var constraints []pgConstraint
 | 
			
		||||
 | 
			
		||||
	sql := `
 | 
			
		||||
@@ -124,6 +123,7 @@ func (*PostgreSQL) getNonDeferrableConstraints(q queryable) ([]pgConstraint, err
 | 
			
		||||
		FROM information_schema.table_constraints
 | 
			
		||||
		WHERE constraint_type = 'FOREIGN KEY'
 | 
			
		||||
		  AND is_deferrable = 'NO'
 | 
			
		||||
		  AND table_schema NOT LIKE '\_timescaledb%'
 | 
			
		||||
  	`
 | 
			
		||||
	rows, err := q.Query(sql)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -144,7 +144,7 @@ func (*PostgreSQL) getNonDeferrableConstraints(q queryable) ([]pgConstraint, err
 | 
			
		||||
	return constraints, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *PostgreSQL) disableTriggers(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
func (h *postgreSQL) disableTriggers(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
	defer func() {
 | 
			
		||||
		// re-enable triggers after load
 | 
			
		||||
		var sql string
 | 
			
		||||
@@ -177,7 +177,7 @@ func (h *PostgreSQL) disableTriggers(db *sql.DB, loadFn loadFunction) (err error
 | 
			
		||||
	return tx.Commit()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *PostgreSQL) makeConstraintsDeferrable(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
func (h *postgreSQL) makeConstraintsDeferrable(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
	defer func() {
 | 
			
		||||
		// ensure constraint being not deferrable again after load
 | 
			
		||||
		var sql string
 | 
			
		||||
@@ -214,21 +214,28 @@ func (h *PostgreSQL) makeConstraintsDeferrable(db *sql.DB, loadFn loadFunction)
 | 
			
		||||
	return tx.Commit()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *PostgreSQL) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
func (h *postgreSQL) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
	// ensure sequences being reset after load
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if err2 := h.resetSequences(db); err2 != nil && err == nil {
 | 
			
		||||
			err = err2
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	if !h.skipResetSequences {
 | 
			
		||||
		defer func() {
 | 
			
		||||
			if err2 := h.resetSequences(db); err2 != nil && err == nil {
 | 
			
		||||
				err = err2
 | 
			
		||||
			}
 | 
			
		||||
		}()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if h.UseAlterConstraint {
 | 
			
		||||
	if h.useAlterConstraint {
 | 
			
		||||
		return h.makeConstraintsDeferrable(db, loadFn)
 | 
			
		||||
	}
 | 
			
		||||
	return h.disableTriggers(db, loadFn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *PostgreSQL) resetSequences(db *sql.DB) error {
 | 
			
		||||
func (h *postgreSQL) resetSequences(db *sql.DB) error {
 | 
			
		||||
	resetSequencesTo := h.resetSequencesTo
 | 
			
		||||
	if resetSequencesTo == 0 {
 | 
			
		||||
		resetSequencesTo = 10000
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, sequence := range h.sequences {
 | 
			
		||||
		_, err := db.Exec(fmt.Sprintf("SELECT SETVAL('%s', %d)", sequence, resetSequencesTo))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
@@ -238,7 +245,7 @@ func (h *PostgreSQL) resetSequences(db *sql.DB) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *PostgreSQL) isTableModified(q queryable, tableName string) (bool, error) {
 | 
			
		||||
func (h *postgreSQL) isTableModified(q queryable, tableName string) (bool, error) {
 | 
			
		||||
	checksum, err := h.getChecksum(q, tableName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
@@ -249,7 +256,7 @@ func (h *PostgreSQL) isTableModified(q queryable, tableName string) (bool, error
 | 
			
		||||
	return oldChecksum == "" || checksum != oldChecksum, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *PostgreSQL) afterLoad(q queryable) error {
 | 
			
		||||
func (h *postgreSQL) afterLoad(q queryable) error {
 | 
			
		||||
	if h.tablesChecksum != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
@@ -265,7 +272,7 @@ func (h *PostgreSQL) afterLoad(q queryable) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *PostgreSQL) getChecksum(q queryable, tableName string) (string, error) {
 | 
			
		||||
func (h *postgreSQL) getChecksum(q queryable, tableName string) (string, error) {
 | 
			
		||||
	sqlStr := fmt.Sprintf(`
 | 
			
		||||
			SELECT md5(CAST((array_agg(t.*)) AS TEXT))
 | 
			
		||||
			FROM %s AS t
 | 
			
		||||
@@ -280,7 +287,7 @@ func (h *PostgreSQL) getChecksum(q queryable, tableName string) (string, error)
 | 
			
		||||
	return checksum.String, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*PostgreSQL) quoteKeyword(s string) string {
 | 
			
		||||
func (*postgreSQL) quoteKeyword(s string) string {
 | 
			
		||||
	parts := strings.Split(s, ".")
 | 
			
		||||
	for i, p := range parts {
 | 
			
		||||
		parts[i] = fmt.Sprintf(`"%s"`, p)
 | 
			
		||||
@@ -5,16 +5,15 @@ import (
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SQLite is the SQLite Helper for this package
 | 
			
		||||
type SQLite struct {
 | 
			
		||||
type sqlite struct {
 | 
			
		||||
	baseHelper
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*SQLite) paramType() int {
 | 
			
		||||
func (*sqlite) paramType() int {
 | 
			
		||||
	return paramTypeQuestion
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*SQLite) databaseName(q queryable) (string, error) {
 | 
			
		||||
func (*sqlite) databaseName(q queryable) (string, error) {
 | 
			
		||||
	var seq int
 | 
			
		||||
	var main, dbName string
 | 
			
		||||
	err := q.QueryRow("PRAGMA database_list").Scan(&seq, &main, &dbName)
 | 
			
		||||
@@ -25,7 +24,7 @@ func (*SQLite) databaseName(q queryable) (string, error) {
 | 
			
		||||
	return dbName, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*SQLite) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
func (*sqlite) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
	query := `
 | 
			
		||||
		SELECT name
 | 
			
		||||
		FROM sqlite_master
 | 
			
		||||
@@ -51,7 +50,7 @@ func (*SQLite) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
	return tables, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*SQLite) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
func (*sqlite) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if _, err2 := db.Exec("PRAGMA defer_foreign_keys = OFF"); err2 != nil && err == nil {
 | 
			
		||||
			err = err2
 | 
			
		||||
@@ -6,17 +6,29 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SQLServer is the helper for SQL Server for this package.
 | 
			
		||||
// SQL Server >= 2008 is required.
 | 
			
		||||
type SQLServer struct {
 | 
			
		||||
type sqlserver struct {
 | 
			
		||||
	baseHelper
 | 
			
		||||
 | 
			
		||||
	tables []string
 | 
			
		||||
	paramTypeCache int
 | 
			
		||||
	tables         []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *SQLServer) init(db *sql.DB) error {
 | 
			
		||||
func (h *sqlserver) init(db *sql.DB) error {
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	// NOTE(@andreynering): The SQL Server lib (github.com/denisenkom/go-mssqldb)
 | 
			
		||||
	// supports both the "?" style (when using the deprecated "mssql" driver)
 | 
			
		||||
	// and the "@p1" style (when using the new "sqlserver" driver).
 | 
			
		||||
	//
 | 
			
		||||
	// Since we don't have a way to know which driver it's been used,
 | 
			
		||||
	// this is a small hack to detect the allowed param style.
 | 
			
		||||
	var v int
 | 
			
		||||
	if err := db.QueryRow("SELECT ?", 1).Scan(&v); err == nil && v == 1 {
 | 
			
		||||
		h.paramTypeCache = paramTypeQuestion
 | 
			
		||||
	} else {
 | 
			
		||||
		h.paramTypeCache = paramTypeAtSign
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	h.tables, err = h.tableNames(db)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
@@ -25,11 +37,11 @@ func (h *SQLServer) init(db *sql.DB) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*SQLServer) paramType() int {
 | 
			
		||||
	return paramTypeQuestion
 | 
			
		||||
func (h *sqlserver) paramType() int {
 | 
			
		||||
	return h.paramTypeCache
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*SQLServer) quoteKeyword(s string) string {
 | 
			
		||||
func (*sqlserver) quoteKeyword(s string) string {
 | 
			
		||||
	parts := strings.Split(s, ".")
 | 
			
		||||
	for i, p := range parts {
 | 
			
		||||
		parts[i] = fmt.Sprintf(`[%s]`, p)
 | 
			
		||||
@@ -37,14 +49,14 @@ func (*SQLServer) quoteKeyword(s string) string {
 | 
			
		||||
	return strings.Join(parts, ".")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*SQLServer) databaseName(q queryable) (string, error) {
 | 
			
		||||
func (*sqlserver) databaseName(q queryable) (string, error) {
 | 
			
		||||
	var dbName string
 | 
			
		||||
	err := q.QueryRow("SELECT DB_NAME()").Scan(&dbName)
 | 
			
		||||
	return dbName, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*SQLServer) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
	rows, err := q.Query("SELECT table_schema + '.' + table_name FROM information_schema.tables")
 | 
			
		||||
func (*sqlserver) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
	rows, err := q.Query("SELECT table_schema + '.' + table_name FROM information_schema.tables WHERE table_name <> 'spt_values'")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -64,36 +76,42 @@ func (*SQLServer) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
	return tables, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *SQLServer) tableHasIdentityColumn(q queryable, tableName string) bool {
 | 
			
		||||
	sql := `
 | 
			
		||||
func (h *sqlserver) tableHasIdentityColumn(q queryable, tableName string) (bool, error) {
 | 
			
		||||
	sql := fmt.Sprintf(`
 | 
			
		||||
		SELECT COUNT(*)
 | 
			
		||||
		FROM SYS.IDENTITY_COLUMNS
 | 
			
		||||
		WHERE OBJECT_ID = OBJECT_ID(?)
 | 
			
		||||
	`
 | 
			
		||||
		WHERE OBJECT_ID = OBJECT_ID('%s')
 | 
			
		||||
	`, tableName)
 | 
			
		||||
	var count int
 | 
			
		||||
	q.QueryRow(sql, h.quoteKeyword(tableName)).Scan(&count)
 | 
			
		||||
	return count > 0
 | 
			
		||||
	if err := q.QueryRow(sql).Scan(&count); err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	return count > 0, nil
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *SQLServer) whileInsertOnTable(tx *sql.Tx, tableName string, fn func() error) (err error) {
 | 
			
		||||
	if h.tableHasIdentityColumn(tx, tableName) {
 | 
			
		||||
func (h *sqlserver) whileInsertOnTable(tx *sql.Tx, tableName string, fn func() error) (err error) {
 | 
			
		||||
	hasIdentityColumn, err := h.tableHasIdentityColumn(tx, tableName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if hasIdentityColumn {
 | 
			
		||||
		defer func() {
 | 
			
		||||
			_, err2 := tx.Exec(fmt.Sprintf("SET IDENTITY_INSERT %s OFF", h.quoteKeyword(tableName)))
 | 
			
		||||
			if err2 != nil && err == nil {
 | 
			
		||||
				err = err2
 | 
			
		||||
				err = fmt.Errorf("testfixtures: could not disable identity insert: %w", err2)
 | 
			
		||||
			}
 | 
			
		||||
		}()
 | 
			
		||||
 | 
			
		||||
		_, err := tx.Exec(fmt.Sprintf("SET IDENTITY_INSERT %s ON", h.quoteKeyword(tableName)))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
			return fmt.Errorf("testfixtures: could not enable identity insert: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return fn()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *SQLServer) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
func (h *sqlserver) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
	// ensure the triggers are re-enable after all
 | 
			
		||||
	defer func() {
 | 
			
		||||
		var sql string
 | 
			
		||||
@@ -130,6 +148,6 @@ func (h *SQLServer) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction)
 | 
			
		||||
// SQL Server because commands like a `CREATE SCHEMA...` and a `CREATE TABLE...`
 | 
			
		||||
// could not be executed in the same batch.
 | 
			
		||||
// See https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms175502(v=sql.105)#rules-for-using-batches
 | 
			
		||||
func (*SQLServer) splitter() []byte {
 | 
			
		||||
func (*sqlserver) splitter() []byte {
 | 
			
		||||
	return []byte("GO\n")
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										599
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/testfixtures.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										599
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/testfixtures.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,599 @@
 | 
			
		||||
package testfixtures // import "github.com/go-testfixtures/testfixtures/v3"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"text/template"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/yaml.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Loader is the responsible to loading fixtures.
 | 
			
		||||
type Loader struct {
 | 
			
		||||
	db            *sql.DB
 | 
			
		||||
	helper        helper
 | 
			
		||||
	fixturesFiles []*fixtureFile
 | 
			
		||||
 | 
			
		||||
	skipTestDatabaseCheck bool
 | 
			
		||||
	location              *time.Location
 | 
			
		||||
 | 
			
		||||
	template           bool
 | 
			
		||||
	templateFuncs      template.FuncMap
 | 
			
		||||
	templateLeftDelim  string
 | 
			
		||||
	templateRightDelim string
 | 
			
		||||
	templateOptions    []string
 | 
			
		||||
	templateData       interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type fixtureFile struct {
 | 
			
		||||
	path       string
 | 
			
		||||
	fileName   string
 | 
			
		||||
	content    []byte
 | 
			
		||||
	insertSQLs []insertSQL
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type insertSQL struct {
 | 
			
		||||
	sql    string
 | 
			
		||||
	params []interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	testDatabaseRegexp = regexp.MustCompile("(?i)test")
 | 
			
		||||
 | 
			
		||||
	errDatabaseIsRequired = fmt.Errorf("testfixtures: database is required")
 | 
			
		||||
	errDialectIsRequired  = fmt.Errorf("testfixtures: dialect is required")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// New instantiates a new Loader instance. The "Database" and "Driver"
 | 
			
		||||
// options are required.
 | 
			
		||||
func New(options ...func(*Loader) error) (*Loader, error) {
 | 
			
		||||
	l := &Loader{
 | 
			
		||||
		templateLeftDelim:  "{{",
 | 
			
		||||
		templateRightDelim: "}}",
 | 
			
		||||
		templateOptions:    []string{"missingkey=zero"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, option := range options {
 | 
			
		||||
		if err := option(l); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l.db == nil {
 | 
			
		||||
		return nil, errDatabaseIsRequired
 | 
			
		||||
	}
 | 
			
		||||
	if l.helper == nil {
 | 
			
		||||
		return nil, errDialectIsRequired
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := l.helper.init(l.db); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if err := l.buildInsertSQLs(); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return l, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Database sets an existing sql.DB instant to Loader.
 | 
			
		||||
func Database(db *sql.DB) func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		l.db = db
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Dialect informs Loader about which database dialect you're using.
 | 
			
		||||
//
 | 
			
		||||
// Possible options are "postgresql", "timescaledb", "mysql", "mariadb",
 | 
			
		||||
// "sqlite" and "sqlserver".
 | 
			
		||||
func Dialect(dialect string) func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		h, err := helperForDialect(dialect)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		l.helper = h
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func helperForDialect(dialect string) (helper, error) {
 | 
			
		||||
	switch dialect {
 | 
			
		||||
	case "postgres", "postgresql", "timescaledb":
 | 
			
		||||
		return &postgreSQL{}, nil
 | 
			
		||||
	case "mysql", "mariadb":
 | 
			
		||||
		return &mySQL{}, nil
 | 
			
		||||
	case "sqlite", "sqlite3":
 | 
			
		||||
		return &sqlite{}, nil
 | 
			
		||||
	case "mssql", "sqlserver":
 | 
			
		||||
		return &sqlserver{}, nil
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, fmt.Errorf(`testfixtures: unrecognized dialect "%s"`, dialect)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UseAlterConstraint If true, the contraint disabling will do
 | 
			
		||||
// using ALTER CONTRAINT sintax, only allowed in PG >= 9.4.
 | 
			
		||||
// If false, the constraint disabling will use DISABLE TRIGGER ALL,
 | 
			
		||||
// which requires SUPERUSER privileges.
 | 
			
		||||
//
 | 
			
		||||
// Only valid for PostgreSQL. Returns an error otherwise.
 | 
			
		||||
func UseAlterConstraint() func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		pgHelper, ok := l.helper.(*postgreSQL)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return fmt.Errorf("testfixtures: UseAlterConstraint is only valid for PostgreSQL databases")
 | 
			
		||||
		}
 | 
			
		||||
		pgHelper.useAlterConstraint = true
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SkipResetSequences prevents Loader from reseting sequences after loading
 | 
			
		||||
// fixtures.
 | 
			
		||||
//
 | 
			
		||||
// Only valid for PostgreSQL. Returns an error otherwise.
 | 
			
		||||
func SkipResetSequences() func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		pgHelper, ok := l.helper.(*postgreSQL)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return fmt.Errorf("testfixtures: SkipResetSequences is only valid for PostgreSQL databases")
 | 
			
		||||
		}
 | 
			
		||||
		pgHelper.skipResetSequences = true
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResetSequencesTo sets the value the sequences will be reset to.
 | 
			
		||||
//
 | 
			
		||||
// Defaults to 10000.
 | 
			
		||||
//
 | 
			
		||||
// Only valid for PostgreSQL. Returns an error otherwise.
 | 
			
		||||
func ResetSequencesTo(value int64) func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		pgHelper, ok := l.helper.(*postgreSQL)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return fmt.Errorf("testfixtures: ResetSequencesTo is only valid for PostgreSQL databases")
 | 
			
		||||
		}
 | 
			
		||||
		pgHelper.resetSequencesTo = value
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DangerousSkipTestDatabaseCheck will make Loader not check if the database
 | 
			
		||||
// name contains "test". Use with caution!
 | 
			
		||||
func DangerousSkipTestDatabaseCheck() func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		l.skipTestDatabaseCheck = true
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Directory informs Loader to load YAML files from a given directory.
 | 
			
		||||
func Directory(dir string) func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		fixtures, err := l.fixturesFromDir(dir)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		l.fixturesFiles = append(l.fixturesFiles, fixtures...)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Files informs Loader to load a given set of YAML files.
 | 
			
		||||
func Files(files ...string) func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		fixtures, err := l.fixturesFromFiles(files...)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		l.fixturesFiles = append(l.fixturesFiles, fixtures...)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Paths inform Loader to load a given set of YAML files and directories.
 | 
			
		||||
func Paths(paths ...string) func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		fixtures, err := l.fixturesFromPaths(paths...)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		l.fixturesFiles = append(l.fixturesFiles, fixtures...)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Location makes Loader use the given location by default when parsing
 | 
			
		||||
// dates. If not given, by default it uses the value of time.Local.
 | 
			
		||||
func Location(location *time.Location) func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		l.location = location
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Template makes loader process each YAML file as an template using the
 | 
			
		||||
// text/template package.
 | 
			
		||||
//
 | 
			
		||||
// For more information on how templates work in Go please read:
 | 
			
		||||
// https://golang.org/pkg/text/template/
 | 
			
		||||
//
 | 
			
		||||
// If not given the YAML files are parsed as is.
 | 
			
		||||
func Template() func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		l.template = true
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TemplateFuncs allow choosing which functions will be available
 | 
			
		||||
// when processing templates.
 | 
			
		||||
//
 | 
			
		||||
// For more information see: https://golang.org/pkg/text/template/#Template.Funcs
 | 
			
		||||
func TemplateFuncs(funcs template.FuncMap) func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		if !l.template {
 | 
			
		||||
			return fmt.Errorf(`testfixtures: the Template() options is required in order to use the TemplateFuns() option`)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		l.templateFuncs = funcs
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TemplateDelims allow choosing which delimiters will be used for templating.
 | 
			
		||||
// This defaults to "{{" and "}}".
 | 
			
		||||
//
 | 
			
		||||
// For more information see https://golang.org/pkg/text/template/#Template.Delims
 | 
			
		||||
func TemplateDelims(left, right string) func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		if !l.template {
 | 
			
		||||
			return fmt.Errorf(`testfixtures: the Template() options is required in order to use the TemplateDelims() option`)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		l.templateLeftDelim = left
 | 
			
		||||
		l.templateRightDelim = right
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TemplateOptions allows you to specific which text/template options will
 | 
			
		||||
// be enabled when processing templates.
 | 
			
		||||
//
 | 
			
		||||
// This defaults to "missingkey=zero". Check the available options here:
 | 
			
		||||
// https://golang.org/pkg/text/template/#Template.Option
 | 
			
		||||
func TemplateOptions(options ...string) func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		if !l.template {
 | 
			
		||||
			return fmt.Errorf(`testfixtures: the Template() options is required in order to use the TemplateOptions() option`)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		l.templateOptions = options
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TemplateData allows you to specify which data will be available
 | 
			
		||||
// when processing templates. Data is accesible by prefixing it with a "."
 | 
			
		||||
// like {{.MyKey}}.
 | 
			
		||||
func TemplateData(data interface{}) func(*Loader) error {
 | 
			
		||||
	return func(l *Loader) error {
 | 
			
		||||
		if !l.template {
 | 
			
		||||
			return fmt.Errorf(`testfixtures: the Template() options is required in order to use the TemplateData() option`)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		l.templateData = data
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnsureTestDatabase returns an error if the database name does not contains
 | 
			
		||||
// "test".
 | 
			
		||||
func (l *Loader) EnsureTestDatabase() error {
 | 
			
		||||
	dbName, err := l.helper.databaseName(l.db)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if !testDatabaseRegexp.MatchString(dbName) {
 | 
			
		||||
		return fmt.Errorf(`testfixtures: database "%s" does not appear to be a test database`, dbName)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Load wipes and after load all fixtures in the database.
 | 
			
		||||
//     if err := fixtures.Load(); err != nil {
 | 
			
		||||
//             ...
 | 
			
		||||
//     }
 | 
			
		||||
func (l *Loader) Load() error {
 | 
			
		||||
	if !l.skipTestDatabaseCheck {
 | 
			
		||||
		if err := l.EnsureTestDatabase(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := l.helper.disableReferentialIntegrity(l.db, func(tx *sql.Tx) error {
 | 
			
		||||
		for _, file := range l.fixturesFiles {
 | 
			
		||||
			modified, err := l.helper.isTableModified(tx, file.fileNameWithoutExtension())
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			if !modified {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if err := file.delete(tx, l.helper); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			err = l.helper.whileInsertOnTable(tx, file.fileNameWithoutExtension(), func() error {
 | 
			
		||||
				for j, i := range file.insertSQLs {
 | 
			
		||||
					if _, err := tx.Exec(i.sql, i.params...); err != nil {
 | 
			
		||||
						return &InsertError{
 | 
			
		||||
							Err:    err,
 | 
			
		||||
							File:   file.fileName,
 | 
			
		||||
							Index:  j,
 | 
			
		||||
							SQL:    i.sql,
 | 
			
		||||
							Params: i.params,
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				return nil
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return l.helper.afterLoad(l.db)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InsertError will be returned if any error happens on database while
 | 
			
		||||
// inserting the record.
 | 
			
		||||
type InsertError struct {
 | 
			
		||||
	Err    error
 | 
			
		||||
	File   string
 | 
			
		||||
	Index  int
 | 
			
		||||
	SQL    string
 | 
			
		||||
	Params []interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *InsertError) Error() string {
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		"testfixtures: error inserting record: %v, on file: %s, index: %d, sql: %s, params: %v",
 | 
			
		||||
		e.Err,
 | 
			
		||||
		e.File,
 | 
			
		||||
		e.Index,
 | 
			
		||||
		e.SQL,
 | 
			
		||||
		e.Params,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *Loader) buildInsertSQLs() error {
 | 
			
		||||
	for _, f := range l.fixturesFiles {
 | 
			
		||||
		var records interface{}
 | 
			
		||||
		if err := yaml.Unmarshal(f.content, &records); err != nil {
 | 
			
		||||
			return fmt.Errorf("testfixtures: could not unmarshal YAML: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch records := records.(type) {
 | 
			
		||||
		case []interface{}:
 | 
			
		||||
			f.insertSQLs = make([]insertSQL, 0, len(records))
 | 
			
		||||
 | 
			
		||||
			for _, record := range records {
 | 
			
		||||
				recordMap, ok := record.(map[interface{}]interface{})
 | 
			
		||||
				if !ok {
 | 
			
		||||
					return fmt.Errorf("testfixtures: could not cast record: not a map[interface{}]interface{}")
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				sql, values, err := l.buildInsertSQL(f, recordMap)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				f.insertSQLs = append(f.insertSQLs, insertSQL{sql, values})
 | 
			
		||||
			}
 | 
			
		||||
		case map[interface{}]interface{}:
 | 
			
		||||
			f.insertSQLs = make([]insertSQL, 0, len(records))
 | 
			
		||||
 | 
			
		||||
			for _, record := range records {
 | 
			
		||||
				recordMap, ok := record.(map[interface{}]interface{})
 | 
			
		||||
				if !ok {
 | 
			
		||||
					return fmt.Errorf("testfixtures: could not cast record: not a map[interface{}]interface{}")
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				sql, values, err := l.buildInsertSQL(f, recordMap)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				f.insertSQLs = append(f.insertSQLs, insertSQL{sql, values})
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			return fmt.Errorf("testfixtures: fixture is not a slice or map")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *fixtureFile) fileNameWithoutExtension() string {
 | 
			
		||||
	return strings.Replace(f.fileName, filepath.Ext(f.fileName), "", 1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *fixtureFile) delete(tx *sql.Tx, h helper) error {
 | 
			
		||||
	if _, err := tx.Exec(fmt.Sprintf("DELETE FROM %s", h.quoteKeyword(f.fileNameWithoutExtension()))); err != nil {
 | 
			
		||||
		return fmt.Errorf(`testfixtures: could not clean table "%s": %w`, f.fileNameWithoutExtension(), err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *Loader) buildInsertSQL(f *fixtureFile, record map[interface{}]interface{}) (sqlStr string, values []interface{}, err error) {
 | 
			
		||||
	var (
 | 
			
		||||
		sqlColumns = make([]string, 0, len(record))
 | 
			
		||||
		sqlValues  = make([]string, 0, len(record))
 | 
			
		||||
		i          = 1
 | 
			
		||||
	)
 | 
			
		||||
	for key, value := range record {
 | 
			
		||||
		keyStr, ok := key.(string)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			err = fmt.Errorf("testfixtures: record map key is not a string")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sqlColumns = append(sqlColumns, l.helper.quoteKeyword(keyStr))
 | 
			
		||||
 | 
			
		||||
		// if string, try convert to SQL or time
 | 
			
		||||
		// if map or array, convert to json
 | 
			
		||||
		switch v := value.(type) {
 | 
			
		||||
		case string:
 | 
			
		||||
			if strings.HasPrefix(v, "RAW=") {
 | 
			
		||||
				sqlValues = append(sqlValues, strings.TrimPrefix(v, "RAW="))
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if t, err := l.tryStrToDate(v); err == nil {
 | 
			
		||||
				value = t
 | 
			
		||||
			}
 | 
			
		||||
		case []interface{}, map[interface{}]interface{}:
 | 
			
		||||
			value = recursiveToJSON(v)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch l.helper.paramType() {
 | 
			
		||||
		case paramTypeDollar:
 | 
			
		||||
			sqlValues = append(sqlValues, fmt.Sprintf("$%d", i))
 | 
			
		||||
		case paramTypeQuestion:
 | 
			
		||||
			sqlValues = append(sqlValues, "?")
 | 
			
		||||
		case paramTypeAtSign:
 | 
			
		||||
			sqlValues = append(sqlValues, fmt.Sprintf("@p%d", i))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		values = append(values, value)
 | 
			
		||||
		i++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sqlStr = fmt.Sprintf(
 | 
			
		||||
		"INSERT INTO %s (%s) VALUES (%s)",
 | 
			
		||||
		l.helper.quoteKeyword(f.fileNameWithoutExtension()),
 | 
			
		||||
		strings.Join(sqlColumns, ", "),
 | 
			
		||||
		strings.Join(sqlValues, ", "),
 | 
			
		||||
	)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *Loader) fixturesFromDir(dir string) ([]*fixtureFile, error) {
 | 
			
		||||
	fileinfos, err := ioutil.ReadDir(dir)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf(`testfixtures: could not stat directory "%s": %w`, dir, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	files := make([]*fixtureFile, 0, len(fileinfos))
 | 
			
		||||
 | 
			
		||||
	for _, fileinfo := range fileinfos {
 | 
			
		||||
		fileExt := filepath.Ext(fileinfo.Name())
 | 
			
		||||
		if !fileinfo.IsDir() && (fileExt == ".yml" || fileExt == ".yaml") {
 | 
			
		||||
			fixture := &fixtureFile{
 | 
			
		||||
				path:     path.Join(dir, fileinfo.Name()),
 | 
			
		||||
				fileName: fileinfo.Name(),
 | 
			
		||||
			}
 | 
			
		||||
			fixture.content, err = ioutil.ReadFile(fixture.path)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, fmt.Errorf(`testfixtures: could not read file "%s": %w`, fixture.path, err)
 | 
			
		||||
			}
 | 
			
		||||
			if err := l.processFileTemplate(fixture); err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			files = append(files, fixture)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return files, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *Loader) fixturesFromFiles(fileNames ...string) ([]*fixtureFile, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		fixtureFiles = make([]*fixtureFile, 0, len(fileNames))
 | 
			
		||||
		err          error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	for _, f := range fileNames {
 | 
			
		||||
		fixture := &fixtureFile{
 | 
			
		||||
			path:     f,
 | 
			
		||||
			fileName: filepath.Base(f),
 | 
			
		||||
		}
 | 
			
		||||
		fixture.content, err = ioutil.ReadFile(fixture.path)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf(`testfixtures: could not read file "%s": %w`, fixture.path, err)
 | 
			
		||||
		}
 | 
			
		||||
		if err := l.processFileTemplate(fixture); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		fixtureFiles = append(fixtureFiles, fixture)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fixtureFiles, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *Loader) fixturesFromPaths(paths ...string) ([]*fixtureFile, error) {
 | 
			
		||||
	fixtureExtractor := func(p string, isDir bool) ([]*fixtureFile, error) {
 | 
			
		||||
		if isDir {
 | 
			
		||||
			return l.fixturesFromDir(p)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return l.fixturesFromFiles(p)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var fixtureFiles []*fixtureFile
 | 
			
		||||
 | 
			
		||||
	for _, p := range paths {
 | 
			
		||||
		f, err := os.Stat(p)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf(`testfixtures: could not stat path "%s": %w`, p, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		fixtures, err := fixtureExtractor(p, f.IsDir())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		fixtureFiles = append(fixtureFiles, fixtures...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fixtureFiles, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *Loader) processFileTemplate(f *fixtureFile) error {
 | 
			
		||||
	if !l.template {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t := template.New("").
 | 
			
		||||
		Funcs(l.templateFuncs).
 | 
			
		||||
		Delims(l.templateLeftDelim, l.templateRightDelim).
 | 
			
		||||
		Option(l.templateOptions...)
 | 
			
		||||
	t, err := t.Parse(string(f.content))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf(`textfixtures: error on parsing template in %s: %w`, f.fileName, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var buffer bytes.Buffer
 | 
			
		||||
	if err := t.Execute(&buffer, l.templateData); err != nil {
 | 
			
		||||
		return fmt.Errorf(`textfixtures: error on executing template in %s: %w`, f.fileName, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f.content = buffer.Bytes()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/time.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								vendor/github.com/go-testfixtures/testfixtures/v3/time.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
package testfixtures
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var timeFormats = [...]string{
 | 
			
		||||
	"2006-01-02",
 | 
			
		||||
	"2006-01-02 15:04",
 | 
			
		||||
	"2006-01-02 15:04:05",
 | 
			
		||||
	"20060102",
 | 
			
		||||
	"20060102 15:04",
 | 
			
		||||
	"20060102 15:04:05",
 | 
			
		||||
	"02/01/2006",
 | 
			
		||||
	"02/01/2006 15:04",
 | 
			
		||||
	"02/01/2006 15:04:05",
 | 
			
		||||
	"2006-01-02T15:04-07:00",
 | 
			
		||||
	"2006-01-02T15:04:05-07:00",
 | 
			
		||||
	"2006-01-02T15:04:05Z07:00",
 | 
			
		||||
	"2006-01-02 15:04:05Z07:00",
 | 
			
		||||
	"2006-01-02T15:04:05Z0700",
 | 
			
		||||
	"2006-01-02 15:04:05Z0700",
 | 
			
		||||
	"2006-01-02T15:04:05Z07",
 | 
			
		||||
	"2006-01-02 15:04:05Z07",
 | 
			
		||||
	"2006-01-02 15:04:05 MST",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (l *Loader) tryStrToDate(s string) (time.Time, error) {
 | 
			
		||||
	loc := l.location
 | 
			
		||||
	if loc == nil {
 | 
			
		||||
		loc = time.Local
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, f := range timeFormats {
 | 
			
		||||
		t, err := time.ParseInLocation(f, s, loc)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		return t, nil
 | 
			
		||||
	}
 | 
			
		||||
	return time.Time{}, fmt.Errorf(`testfixtures: could not convert string "%s" to time`, s)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/mattn/go-sqlite3/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/mattn/go-sqlite3/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -12,6 +12,8 @@ go:
 | 
			
		||||
  - 1.9.x
 | 
			
		||||
  - 1.10.x
 | 
			
		||||
  - 1.11.x
 | 
			
		||||
  - 1.12.x
 | 
			
		||||
  - 1.13.x
 | 
			
		||||
  - master
 | 
			
		||||
 | 
			
		||||
before_install:
 | 
			
		||||
@@ -27,5 +29,5 @@ script:
 | 
			
		||||
  - $HOME/gopath/bin/goveralls -repotoken 3qJVUE0iQwqnCbmNcDsjYu1nh4J4KIFXx
 | 
			
		||||
  - go test -race -v . -tags ""
 | 
			
		||||
  - go test -race -v . -tags "libsqlite3"
 | 
			
		||||
  - go test -race -v . -tags "sqlite_allow_uri_authority sqlite_app_armor sqlite_foreign_keys sqlite_fts5 sqlite_icu sqlite_introspect sqlite_json sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_userauth sqlite_vacuum_incr sqlite_vtable sqlite_unlock_notify"
 | 
			
		||||
  - go test -race -v . -tags "sqlite_allow_uri_authority sqlite_app_armor sqlite_foreign_keys sqlite_fts5 sqlite_icu sqlite_introspect sqlite_json sqlite_preupdate_hook sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_userauth sqlite_vacuum_incr sqlite_vtable sqlite_unlock_notify"
 | 
			
		||||
  - go test -race -v . -tags "sqlite_vacuum_full"
 | 
			
		||||
							
								
								
									
										57
									
								
								vendor/github.com/mattn/go-sqlite3/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										57
									
								
								vendor/github.com/mattn/go-sqlite3/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -3,6 +3,7 @@ go-sqlite3
 | 
			
		||||
 | 
			
		||||
[](http://godoc.org/github.com/mattn/go-sqlite3)
 | 
			
		||||
[](https://travis-ci.org/mattn/go-sqlite3)
 | 
			
		||||
[](https://opencollective.com/mattn-go-sqlite3) 
 | 
			
		||||
[](https://coveralls.io/r/mattn/go-sqlite3?branch=master)
 | 
			
		||||
[](https://goreportcard.com/report/github.com/mattn/go-sqlite3)
 | 
			
		||||
 | 
			
		||||
@@ -16,15 +17,21 @@ Supported Golang version: See .travis.yml
 | 
			
		||||
 | 
			
		||||
### Overview
 | 
			
		||||
 | 
			
		||||
- [go-sqlite3](#go-sqlite3)
 | 
			
		||||
- [Description](#description)
 | 
			
		||||
    - [Overview](#overview)
 | 
			
		||||
- [Installation](#installation)
 | 
			
		||||
- [API Reference](#api-reference)
 | 
			
		||||
- [Connection String](#connection-string)
 | 
			
		||||
  - [DSN Examples](#dsn-examples)
 | 
			
		||||
- [Features](#features)
 | 
			
		||||
    - [Usage](#usage)
 | 
			
		||||
    - [Feature / Extension List](#feature--extension-list)
 | 
			
		||||
- [Compilation](#compilation)
 | 
			
		||||
  - [Android](#android)
 | 
			
		||||
  - [ARM](#arm)
 | 
			
		||||
  - [Cross Compile](#cross-compile)
 | 
			
		||||
  - [Google Cloud Platform](#google-cloud-platform)
 | 
			
		||||
- [ARM](#arm)
 | 
			
		||||
- [Cross Compile](#cross-compile)
 | 
			
		||||
- [Google Cloud Platform](#google-cloud-platform)
 | 
			
		||||
  - [Linux](#linux)
 | 
			
		||||
    - [Alpine](#alpine)
 | 
			
		||||
    - [Fedora](#fedora)
 | 
			
		||||
@@ -34,11 +41,22 @@ Supported Golang version: See .travis.yml
 | 
			
		||||
  - [Errors](#errors)
 | 
			
		||||
- [User Authentication](#user-authentication)
 | 
			
		||||
  - [Compile](#compile)
 | 
			
		||||
  - [Usage](#usage)
 | 
			
		||||
  - [Usage](#usage-1)
 | 
			
		||||
    - [Create protected database](#create-protected-database)
 | 
			
		||||
    - [Password Encoding](#password-encoding)
 | 
			
		||||
      - [Available Encoders](#available-encoders)
 | 
			
		||||
    - [Restrictions](#restrictions)
 | 
			
		||||
    - [Support](#support)
 | 
			
		||||
    - [User Management](#user-management)
 | 
			
		||||
      - [SQL](#sql)
 | 
			
		||||
        - [Examples](#examples)
 | 
			
		||||
      - [*SQLiteConn](#sqliteconn)
 | 
			
		||||
    - [Attached database](#attached-database)
 | 
			
		||||
- [Extensions](#extensions)
 | 
			
		||||
  - [Spatialite](#spatialite)
 | 
			
		||||
- [FAQ](#faq)
 | 
			
		||||
- [License](#license)
 | 
			
		||||
- [Author](#author)
 | 
			
		||||
 | 
			
		||||
# Installation
 | 
			
		||||
 | 
			
		||||
@@ -149,6 +167,7 @@ go build --tags "icu json1 fts5 secure_delete"
 | 
			
		||||
|  International Components for Unicode | sqlite_icu | This option causes the International Components for Unicode or "ICU" extension to SQLite to be added to the build |
 | 
			
		||||
| Introspect PRAGMAS | sqlite_introspect | This option adds some extra PRAGMA statements. <ul><li>PRAGMA function_list</li><li>PRAGMA module_list</li><li>PRAGMA pragma_list</li></ul> |
 | 
			
		||||
| JSON SQL Functions | sqlite_json | When this option is defined in the amalgamation, the JSON SQL functions are added to the build automatically |
 | 
			
		||||
| Pre Update Hook | sqlite_preupdate_hook | Registers a callback function that is invoked prior to each INSERT, UPDATE, and DELETE operation on a database table. |
 | 
			
		||||
| Secure Delete | sqlite_secure_delete | This compile-time option changes the default setting of the secure_delete pragma.<br><br>When this option is not used, secure_delete defaults to off. When this option is present, secure_delete defaults to on.<br><br>The secure_delete setting causes deleted content to be overwritten with zeros. There is a small performance penalty since additional I/O must occur.<br><br>On the other hand, secure_delete can prevent fragments of sensitive information from lingering in unused parts of the database file after it has been deleted. See the documentation on the secure_delete pragma for additional information |
 | 
			
		||||
| Secure Delete (FAST) | sqlite_secure_delete_fast | For more information see [PRAGMA secure_delete](https://www.sqlite.org/pragma.html#pragma_secure_delete) |
 | 
			
		||||
| Tracing / Debug | sqlite_trace | Activate trace functions |
 | 
			
		||||
@@ -504,6 +523,36 @@ For an example see [shaxbee/go-spatialite](https://github.com/shaxbee/go-spatial
 | 
			
		||||
 | 
			
		||||
    More information see [#209](https://github.com/mattn/go-sqlite3/issues/209)
 | 
			
		||||
 | 
			
		||||
## Contributors
 | 
			
		||||
 | 
			
		||||
### Code Contributors
 | 
			
		||||
 | 
			
		||||
This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
 | 
			
		||||
<a href="https://github.com/mattn/go-sqlite3/graphs/contributors"><img src="https://opencollective.com/mattn-go-sqlite3/contributors.svg?width=890&button=false" /></a>
 | 
			
		||||
 | 
			
		||||
### Financial Contributors
 | 
			
		||||
 | 
			
		||||
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/mattn-go-sqlite3/contribute)]
 | 
			
		||||
 | 
			
		||||
#### Individuals
 | 
			
		||||
 | 
			
		||||
<a href="https://opencollective.com/mattn-go-sqlite3"><img src="https://opencollective.com/mattn-go-sqlite3/individuals.svg?width=890"></a>
 | 
			
		||||
 | 
			
		||||
#### Organizations
 | 
			
		||||
 | 
			
		||||
Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/mattn-go-sqlite3/contribute)]
 | 
			
		||||
 | 
			
		||||
<a href="https://opencollective.com/mattn-go-sqlite3/organization/0/website"><img src="https://opencollective.com/mattn-go-sqlite3/organization/0/avatar.svg"></a>
 | 
			
		||||
<a href="https://opencollective.com/mattn-go-sqlite3/organization/1/website"><img src="https://opencollective.com/mattn-go-sqlite3/organization/1/avatar.svg"></a>
 | 
			
		||||
<a href="https://opencollective.com/mattn-go-sqlite3/organization/2/website"><img src="https://opencollective.com/mattn-go-sqlite3/organization/2/avatar.svg"></a>
 | 
			
		||||
<a href="https://opencollective.com/mattn-go-sqlite3/organization/3/website"><img src="https://opencollective.com/mattn-go-sqlite3/organization/3/avatar.svg"></a>
 | 
			
		||||
<a href="https://opencollective.com/mattn-go-sqlite3/organization/4/website"><img src="https://opencollective.com/mattn-go-sqlite3/organization/4/avatar.svg"></a>
 | 
			
		||||
<a href="https://opencollective.com/mattn-go-sqlite3/organization/5/website"><img src="https://opencollective.com/mattn-go-sqlite3/organization/5/avatar.svg"></a>
 | 
			
		||||
<a href="https://opencollective.com/mattn-go-sqlite3/organization/6/website"><img src="https://opencollective.com/mattn-go-sqlite3/organization/6/avatar.svg"></a>
 | 
			
		||||
<a href="https://opencollective.com/mattn-go-sqlite3/organization/7/website"><img src="https://opencollective.com/mattn-go-sqlite3/organization/7/avatar.svg"></a>
 | 
			
		||||
<a href="https://opencollective.com/mattn-go-sqlite3/organization/8/website"><img src="https://opencollective.com/mattn-go-sqlite3/organization/8/avatar.svg"></a>
 | 
			
		||||
<a href="https://opencollective.com/mattn-go-sqlite3/organization/9/website"><img src="https://opencollective.com/mattn-go-sqlite3/organization/9/avatar.svg"></a>
 | 
			
		||||
 | 
			
		||||
# License
 | 
			
		||||
 | 
			
		||||
MIT: http://mattn.mit-license.org/2018
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								vendor/github.com/mattn/go-sqlite3/backup.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/mattn/go-sqlite3/backup.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
@@ -25,18 +25,18 @@ type SQLiteBackup struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Backup make backup from src to dest.
 | 
			
		||||
func (c *SQLiteConn) Backup(dest string, conn *SQLiteConn, src string) (*SQLiteBackup, error) {
 | 
			
		||||
func (destConn *SQLiteConn) Backup(dest string, srcConn *SQLiteConn, src string) (*SQLiteBackup, error) {
 | 
			
		||||
	destptr := C.CString(dest)
 | 
			
		||||
	defer C.free(unsafe.Pointer(destptr))
 | 
			
		||||
	srcptr := C.CString(src)
 | 
			
		||||
	defer C.free(unsafe.Pointer(srcptr))
 | 
			
		||||
 | 
			
		||||
	if b := C.sqlite3_backup_init(c.db, destptr, conn.db, srcptr); b != nil {
 | 
			
		||||
	if b := C.sqlite3_backup_init(destConn.db, destptr, srcConn.db, srcptr); b != nil {
 | 
			
		||||
		bb := &SQLiteBackup{b: b}
 | 
			
		||||
		runtime.SetFinalizer(bb, (*SQLiteBackup).Finish)
 | 
			
		||||
		return bb, nil
 | 
			
		||||
	}
 | 
			
		||||
	return nil, c.lastError()
 | 
			
		||||
	return nil, destConn.lastError()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Step to backs up for one step. Calls the underlying `sqlite3_backup_step`
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								vendor/github.com/mattn/go-sqlite3/callback.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/mattn/go-sqlite3/callback.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
@@ -83,8 +83,22 @@ func authorizerTrampoline(handle uintptr, op int, arg1 *C.char, arg2 *C.char, ar
 | 
			
		||||
	return callback(op, C.GoString(arg1), C.GoString(arg2), C.GoString(arg3))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Use handles to avoid passing Go pointers to C.
 | 
			
		||||
//export preUpdateHookTrampoline
 | 
			
		||||
func preUpdateHookTrampoline(handle uintptr, dbHandle uintptr, op int, db *C.char, table *C.char, oldrowid int64, newrowid int64) {
 | 
			
		||||
	hval := lookupHandleVal(handle)
 | 
			
		||||
	data := SQLitePreUpdateData{
 | 
			
		||||
		Conn:         hval.db,
 | 
			
		||||
		Op:           op,
 | 
			
		||||
		DatabaseName: C.GoString(db),
 | 
			
		||||
		TableName:    C.GoString(table),
 | 
			
		||||
		OldRowID:     oldrowid,
 | 
			
		||||
		NewRowID:     newrowid,
 | 
			
		||||
	}
 | 
			
		||||
	callback := hval.val.(func(SQLitePreUpdateData))
 | 
			
		||||
	callback(data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Use handles to avoid passing Go pointers to C.
 | 
			
		||||
type handleVal struct {
 | 
			
		||||
	db  *SQLiteConn
 | 
			
		||||
	val interface{}
 | 
			
		||||
@@ -103,7 +117,7 @@ func newHandle(db *SQLiteConn, v interface{}) uintptr {
 | 
			
		||||
	return i
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func lookupHandle(handle uintptr) interface{} {
 | 
			
		||||
func lookupHandleVal(handle uintptr) handleVal {
 | 
			
		||||
	handleLock.Lock()
 | 
			
		||||
	defer handleLock.Unlock()
 | 
			
		||||
	r, ok := handleVals[handle]
 | 
			
		||||
@@ -114,7 +128,11 @@ func lookupHandle(handle uintptr) interface{} {
 | 
			
		||||
			panic("invalid handle")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return r.val
 | 
			
		||||
	return r
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func lookupHandle(handle uintptr) interface{} {
 | 
			
		||||
	return lookupHandleVal(handle).val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func deleteHandles(db *SQLiteConn) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										299
									
								
								vendor/github.com/mattn/go-sqlite3/convert.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										299
									
								
								vendor/github.com/mattn/go-sqlite3/convert.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,299 @@
 | 
			
		||||
// Extracted from Go database/sql source code
 | 
			
		||||
 | 
			
		||||
// Copyright 2011 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Type conversions for Scan.
 | 
			
		||||
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"database/sql/driver"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var errNilPtr = errors.New("destination pointer is nil") // embedded in descriptive error
 | 
			
		||||
 | 
			
		||||
// convertAssign copies to dest the value in src, converting it if possible.
 | 
			
		||||
// An error is returned if the copy would result in loss of information.
 | 
			
		||||
// dest should be a pointer type.
 | 
			
		||||
func convertAssign(dest, src interface{}) error {
 | 
			
		||||
	// Common cases, without reflect.
 | 
			
		||||
	switch s := src.(type) {
 | 
			
		||||
	case string:
 | 
			
		||||
		switch d := dest.(type) {
 | 
			
		||||
		case *string:
 | 
			
		||||
			if d == nil {
 | 
			
		||||
				return errNilPtr
 | 
			
		||||
			}
 | 
			
		||||
			*d = s
 | 
			
		||||
			return nil
 | 
			
		||||
		case *[]byte:
 | 
			
		||||
			if d == nil {
 | 
			
		||||
				return errNilPtr
 | 
			
		||||
			}
 | 
			
		||||
			*d = []byte(s)
 | 
			
		||||
			return nil
 | 
			
		||||
		case *sql.RawBytes:
 | 
			
		||||
			if d == nil {
 | 
			
		||||
				return errNilPtr
 | 
			
		||||
			}
 | 
			
		||||
			*d = append((*d)[:0], s...)
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	case []byte:
 | 
			
		||||
		switch d := dest.(type) {
 | 
			
		||||
		case *string:
 | 
			
		||||
			if d == nil {
 | 
			
		||||
				return errNilPtr
 | 
			
		||||
			}
 | 
			
		||||
			*d = string(s)
 | 
			
		||||
			return nil
 | 
			
		||||
		case *interface{}:
 | 
			
		||||
			if d == nil {
 | 
			
		||||
				return errNilPtr
 | 
			
		||||
			}
 | 
			
		||||
			*d = cloneBytes(s)
 | 
			
		||||
			return nil
 | 
			
		||||
		case *[]byte:
 | 
			
		||||
			if d == nil {
 | 
			
		||||
				return errNilPtr
 | 
			
		||||
			}
 | 
			
		||||
			*d = cloneBytes(s)
 | 
			
		||||
			return nil
 | 
			
		||||
		case *sql.RawBytes:
 | 
			
		||||
			if d == nil {
 | 
			
		||||
				return errNilPtr
 | 
			
		||||
			}
 | 
			
		||||
			*d = s
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	case time.Time:
 | 
			
		||||
		switch d := dest.(type) {
 | 
			
		||||
		case *time.Time:
 | 
			
		||||
			*d = s
 | 
			
		||||
			return nil
 | 
			
		||||
		case *string:
 | 
			
		||||
			*d = s.Format(time.RFC3339Nano)
 | 
			
		||||
			return nil
 | 
			
		||||
		case *[]byte:
 | 
			
		||||
			if d == nil {
 | 
			
		||||
				return errNilPtr
 | 
			
		||||
			}
 | 
			
		||||
			*d = []byte(s.Format(time.RFC3339Nano))
 | 
			
		||||
			return nil
 | 
			
		||||
		case *sql.RawBytes:
 | 
			
		||||
			if d == nil {
 | 
			
		||||
				return errNilPtr
 | 
			
		||||
			}
 | 
			
		||||
			*d = s.AppendFormat((*d)[:0], time.RFC3339Nano)
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	case nil:
 | 
			
		||||
		switch d := dest.(type) {
 | 
			
		||||
		case *interface{}:
 | 
			
		||||
			if d == nil {
 | 
			
		||||
				return errNilPtr
 | 
			
		||||
			}
 | 
			
		||||
			*d = nil
 | 
			
		||||
			return nil
 | 
			
		||||
		case *[]byte:
 | 
			
		||||
			if d == nil {
 | 
			
		||||
				return errNilPtr
 | 
			
		||||
			}
 | 
			
		||||
			*d = nil
 | 
			
		||||
			return nil
 | 
			
		||||
		case *sql.RawBytes:
 | 
			
		||||
			if d == nil {
 | 
			
		||||
				return errNilPtr
 | 
			
		||||
			}
 | 
			
		||||
			*d = nil
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var sv reflect.Value
 | 
			
		||||
 | 
			
		||||
	switch d := dest.(type) {
 | 
			
		||||
	case *string:
 | 
			
		||||
		sv = reflect.ValueOf(src)
 | 
			
		||||
		switch sv.Kind() {
 | 
			
		||||
		case reflect.Bool,
 | 
			
		||||
			reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
 | 
			
		||||
			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
 | 
			
		||||
			reflect.Float32, reflect.Float64:
 | 
			
		||||
			*d = asString(src)
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	case *[]byte:
 | 
			
		||||
		sv = reflect.ValueOf(src)
 | 
			
		||||
		if b, ok := asBytes(nil, sv); ok {
 | 
			
		||||
			*d = b
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	case *sql.RawBytes:
 | 
			
		||||
		sv = reflect.ValueOf(src)
 | 
			
		||||
		if b, ok := asBytes([]byte(*d)[:0], sv); ok {
 | 
			
		||||
			*d = sql.RawBytes(b)
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	case *bool:
 | 
			
		||||
		bv, err := driver.Bool.ConvertValue(src)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			*d = bv.(bool)
 | 
			
		||||
		}
 | 
			
		||||
		return err
 | 
			
		||||
	case *interface{}:
 | 
			
		||||
		*d = src
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if scanner, ok := dest.(sql.Scanner); ok {
 | 
			
		||||
		return scanner.Scan(src)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dpv := reflect.ValueOf(dest)
 | 
			
		||||
	if dpv.Kind() != reflect.Ptr {
 | 
			
		||||
		return errors.New("destination not a pointer")
 | 
			
		||||
	}
 | 
			
		||||
	if dpv.IsNil() {
 | 
			
		||||
		return errNilPtr
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !sv.IsValid() {
 | 
			
		||||
		sv = reflect.ValueOf(src)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dv := reflect.Indirect(dpv)
 | 
			
		||||
	if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) {
 | 
			
		||||
		switch b := src.(type) {
 | 
			
		||||
		case []byte:
 | 
			
		||||
			dv.Set(reflect.ValueOf(cloneBytes(b)))
 | 
			
		||||
		default:
 | 
			
		||||
			dv.Set(sv)
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) {
 | 
			
		||||
		dv.Set(sv.Convert(dv.Type()))
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The following conversions use a string value as an intermediate representation
 | 
			
		||||
	// to convert between various numeric types.
 | 
			
		||||
	//
 | 
			
		||||
	// This also allows scanning into user defined types such as "type Int int64".
 | 
			
		||||
	// For symmetry, also check for string destination types.
 | 
			
		||||
	switch dv.Kind() {
 | 
			
		||||
	case reflect.Ptr:
 | 
			
		||||
		if src == nil {
 | 
			
		||||
			dv.Set(reflect.Zero(dv.Type()))
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		dv.Set(reflect.New(dv.Type().Elem()))
 | 
			
		||||
		return convertAssign(dv.Interface(), src)
 | 
			
		||||
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
			
		||||
		s := asString(src)
 | 
			
		||||
		i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			err = strconvErr(err)
 | 
			
		||||
			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
 | 
			
		||||
		}
 | 
			
		||||
		dv.SetInt(i64)
 | 
			
		||||
		return nil
 | 
			
		||||
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 | 
			
		||||
		s := asString(src)
 | 
			
		||||
		u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			err = strconvErr(err)
 | 
			
		||||
			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
 | 
			
		||||
		}
 | 
			
		||||
		dv.SetUint(u64)
 | 
			
		||||
		return nil
 | 
			
		||||
	case reflect.Float32, reflect.Float64:
 | 
			
		||||
		s := asString(src)
 | 
			
		||||
		f64, err := strconv.ParseFloat(s, dv.Type().Bits())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			err = strconvErr(err)
 | 
			
		||||
			return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
 | 
			
		||||
		}
 | 
			
		||||
		dv.SetFloat(f64)
 | 
			
		||||
		return nil
 | 
			
		||||
	case reflect.String:
 | 
			
		||||
		switch v := src.(type) {
 | 
			
		||||
		case string:
 | 
			
		||||
			dv.SetString(v)
 | 
			
		||||
			return nil
 | 
			
		||||
		case []byte:
 | 
			
		||||
			dv.SetString(string(v))
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func strconvErr(err error) error {
 | 
			
		||||
	if ne, ok := err.(*strconv.NumError); ok {
 | 
			
		||||
		return ne.Err
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func cloneBytes(b []byte) []byte {
 | 
			
		||||
	if b == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	c := make([]byte, len(b))
 | 
			
		||||
	copy(c, b)
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func asString(src interface{}) string {
 | 
			
		||||
	switch v := src.(type) {
 | 
			
		||||
	case string:
 | 
			
		||||
		return v
 | 
			
		||||
	case []byte:
 | 
			
		||||
		return string(v)
 | 
			
		||||
	}
 | 
			
		||||
	rv := reflect.ValueOf(src)
 | 
			
		||||
	switch rv.Kind() {
 | 
			
		||||
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
			
		||||
		return strconv.FormatInt(rv.Int(), 10)
 | 
			
		||||
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 | 
			
		||||
		return strconv.FormatUint(rv.Uint(), 10)
 | 
			
		||||
	case reflect.Float64:
 | 
			
		||||
		return strconv.FormatFloat(rv.Float(), 'g', -1, 64)
 | 
			
		||||
	case reflect.Float32:
 | 
			
		||||
		return strconv.FormatFloat(rv.Float(), 'g', -1, 32)
 | 
			
		||||
	case reflect.Bool:
 | 
			
		||||
		return strconv.FormatBool(rv.Bool())
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("%v", src)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) {
 | 
			
		||||
	switch rv.Kind() {
 | 
			
		||||
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 | 
			
		||||
		return strconv.AppendInt(buf, rv.Int(), 10), true
 | 
			
		||||
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
 | 
			
		||||
		return strconv.AppendUint(buf, rv.Uint(), 10), true
 | 
			
		||||
	case reflect.Float32:
 | 
			
		||||
		return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true
 | 
			
		||||
	case reflect.Float64:
 | 
			
		||||
		return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true
 | 
			
		||||
	case reflect.Bool:
 | 
			
		||||
		return strconv.AppendBool(buf, rv.Bool()), true
 | 
			
		||||
	case reflect.String:
 | 
			
		||||
		s := rv.String()
 | 
			
		||||
		return append(buf, s...), true
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								vendor/github.com/mattn/go-sqlite3/error.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/mattn/go-sqlite3/error.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,11 +1,19 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#ifndef USE_LIBSQLITE3
 | 
			
		||||
#include <sqlite3-binding.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <sqlite3.h>
 | 
			
		||||
#endif
 | 
			
		||||
*/
 | 
			
		||||
import "C"
 | 
			
		||||
import "syscall"
 | 
			
		||||
 | 
			
		||||
// ErrNo inherit errno.
 | 
			
		||||
type ErrNo int
 | 
			
		||||
@@ -20,6 +28,7 @@ type ErrNoExtended int
 | 
			
		||||
type Error struct {
 | 
			
		||||
	Code         ErrNo         /* The error code returned by SQLite */
 | 
			
		||||
	ExtendedCode ErrNoExtended /* The extended error code returned by SQLite */
 | 
			
		||||
	SystemErrno  syscall.Errno /* The system errno returned by the OS through SQLite, if applicable */
 | 
			
		||||
	err          string        /* The error string returned by sqlite3_errmsg(),
 | 
			
		||||
	this usually contains more specific details. */
 | 
			
		||||
}
 | 
			
		||||
@@ -72,10 +81,16 @@ func (err ErrNoExtended) Error() string {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err Error) Error() string {
 | 
			
		||||
	var str string
 | 
			
		||||
	if err.err != "" {
 | 
			
		||||
		return err.err
 | 
			
		||||
		str = err.err
 | 
			
		||||
	} else {
 | 
			
		||||
		str = C.GoString(C.sqlite3_errstr(C.int(err.Code)))
 | 
			
		||||
	}
 | 
			
		||||
	return errorString(err)
 | 
			
		||||
	if err.SystemErrno != 0 {
 | 
			
		||||
		str += ": " + err.SystemErrno.Error()
 | 
			
		||||
	}
 | 
			
		||||
	return str
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// result codes from http://www.sqlite.org/c3ref/c_abort_rollback.html
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9185
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										9185
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										81
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										81
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -124,9 +124,9 @@ extern "C" {
 | 
			
		||||
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 | 
			
		||||
** [sqlite_version()] and [sqlite_source_id()].
 | 
			
		||||
*/
 | 
			
		||||
#define SQLITE_VERSION        "3.29.0"
 | 
			
		||||
#define SQLITE_VERSION_NUMBER 3029000
 | 
			
		||||
#define SQLITE_SOURCE_ID      "2019-07-10 17:32:03 fc82b73eaac8b36950e527f12c4b5dc1e147e6f4ad2217ae43ad82882a88bfa6"
 | 
			
		||||
#define SQLITE_VERSION        "3.30.1"
 | 
			
		||||
#define SQLITE_VERSION_NUMBER 3030001
 | 
			
		||||
#define SQLITE_SOURCE_ID      "2019-10-10 20:19:45 18db032d058f1436ce3dea84081f4ee5a0f2259ad97301d43c426bc7f3df1b0b"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
** CAPI3REF: Run-Time Library Version Numbers
 | 
			
		||||
@@ -2094,6 +2094,17 @@ struct sqlite3_mem_methods {
 | 
			
		||||
** following this call.  The second parameter may be a NULL pointer, in
 | 
			
		||||
** which case the trigger setting is not reported back. </dd>
 | 
			
		||||
**
 | 
			
		||||
** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
 | 
			
		||||
** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
 | 
			
		||||
** <dd> ^This option is used to enable or disable [CREATE VIEW | views].
 | 
			
		||||
** There should be two additional arguments.
 | 
			
		||||
** The first argument is an integer which is 0 to disable views,
 | 
			
		||||
** positive to enable views or negative to leave the setting unchanged.
 | 
			
		||||
** The second parameter is a pointer to an integer into which
 | 
			
		||||
** is written 0 or 1 to indicate whether views are disabled or enabled
 | 
			
		||||
** following this call.  The second parameter may be a NULL pointer, in
 | 
			
		||||
** which case the view setting is not reported back. </dd>
 | 
			
		||||
**
 | 
			
		||||
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
 | 
			
		||||
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
 | 
			
		||||
** <dd> ^This option is used to enable or disable the
 | 
			
		||||
@@ -2266,7 +2277,8 @@ struct sqlite3_mem_methods {
 | 
			
		||||
#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE    1012 /* int int* */
 | 
			
		||||
#define SQLITE_DBCONFIG_DQS_DML               1013 /* int int* */
 | 
			
		||||
#define SQLITE_DBCONFIG_DQS_DDL               1014 /* int int* */
 | 
			
		||||
#define SQLITE_DBCONFIG_MAX                   1014 /* Largest DBCONFIG */
 | 
			
		||||
#define SQLITE_DBCONFIG_ENABLE_VIEW           1015 /* int int* */
 | 
			
		||||
#define SQLITE_DBCONFIG_MAX                   1015 /* Largest DBCONFIG */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
** CAPI3REF: Enable Or Disable Extended Result Codes
 | 
			
		||||
@@ -3815,7 +3827,7 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
 | 
			
		||||
** ^The specific value of WHERE-clause [parameter] might influence the 
 | 
			
		||||
** choice of query plan if the parameter is the left-hand side of a [LIKE]
 | 
			
		||||
** or [GLOB] operator or if the parameter is compared to an indexed column
 | 
			
		||||
** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
 | 
			
		||||
** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled.
 | 
			
		||||
** </li>
 | 
			
		||||
** </ol>
 | 
			
		||||
**
 | 
			
		||||
@@ -4850,6 +4862,12 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
 | 
			
		||||
** perform additional optimizations on deterministic functions, so use
 | 
			
		||||
** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
 | 
			
		||||
**
 | 
			
		||||
** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY]
 | 
			
		||||
** flag, which if present prevents the function from being invoked from
 | 
			
		||||
** within VIEWs or TRIGGERs.  For security reasons, the [SQLITE_DIRECTONLY]
 | 
			
		||||
** flag is recommended for any application-defined SQL function that has
 | 
			
		||||
** side-effects.
 | 
			
		||||
**
 | 
			
		||||
** ^(The fifth parameter is an arbitrary pointer.  The implementation of the
 | 
			
		||||
** function can gain access to this pointer using [sqlite3_user_data()].)^
 | 
			
		||||
**
 | 
			
		||||
@@ -4966,8 +4984,30 @@ SQLITE_API int sqlite3_create_window_function(
 | 
			
		||||
** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
 | 
			
		||||
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
 | 
			
		||||
** [sqlite3_create_function_v2()].
 | 
			
		||||
**
 | 
			
		||||
** The SQLITE_DETERMINISTIC flag means that the new function will always
 | 
			
		||||
** maps the same inputs into the same output.  The abs() function is
 | 
			
		||||
** deterministic, for example, but randomblob() is not.
 | 
			
		||||
**
 | 
			
		||||
** The SQLITE_DIRECTONLY flag means that the function may only be invoked
 | 
			
		||||
** from top-level SQL, and cannot be used in VIEWs or TRIGGERs.  This is
 | 
			
		||||
** a security feature which is recommended for all 
 | 
			
		||||
** [application-defined SQL functions] that have side-effects.  This flag 
 | 
			
		||||
** prevents an attacker from adding triggers and views to a schema then 
 | 
			
		||||
** tricking a high-privilege application into causing unintended side-effects
 | 
			
		||||
** while performing ordinary queries.
 | 
			
		||||
**
 | 
			
		||||
** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
 | 
			
		||||
** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
 | 
			
		||||
** Specifying this flag makes no difference for scalar or aggregate user
 | 
			
		||||
** functions. However, if it is not specified for a user-defined window
 | 
			
		||||
** function, then any sub-types belonging to arguments passed to the window
 | 
			
		||||
** function may be discarded before the window function is called (i.e.
 | 
			
		||||
** sqlite3_value_subtype() will always return 0).
 | 
			
		||||
*/
 | 
			
		||||
#define SQLITE_DETERMINISTIC    0x800
 | 
			
		||||
#define SQLITE_DETERMINISTIC    0x000000800
 | 
			
		||||
#define SQLITE_DIRECTONLY       0x000080000
 | 
			
		||||
#define SQLITE_SUBTYPE          0x000100000
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
** CAPI3REF: Deprecated Functions
 | 
			
		||||
@@ -6613,6 +6653,12 @@ struct sqlite3_index_info {
 | 
			
		||||
** ^The sqlite3_create_module()
 | 
			
		||||
** interface is equivalent to sqlite3_create_module_v2() with a NULL
 | 
			
		||||
** destructor.
 | 
			
		||||
**
 | 
			
		||||
** ^If the third parameter (the pointer to the sqlite3_module object) is
 | 
			
		||||
** NULL then no new module is create and any existing modules with the
 | 
			
		||||
** same name are dropped.
 | 
			
		||||
**
 | 
			
		||||
** See also: [sqlite3_drop_modules()]
 | 
			
		||||
*/
 | 
			
		||||
SQLITE_API int sqlite3_create_module(
 | 
			
		||||
  sqlite3 *db,               /* SQLite connection to register module with */
 | 
			
		||||
@@ -6628,6 +6674,23 @@ SQLITE_API int sqlite3_create_module_v2(
 | 
			
		||||
  void(*xDestroy)(void*)     /* Module destructor function */
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
** CAPI3REF: Remove Unnecessary Virtual Table Implementations
 | 
			
		||||
** METHOD: sqlite3
 | 
			
		||||
**
 | 
			
		||||
** ^The sqlite3_drop_modules(D,L) interface removes all virtual
 | 
			
		||||
** table modules from database connection D except those named on list L.
 | 
			
		||||
** The L parameter must be either NULL or a pointer to an array of pointers
 | 
			
		||||
** to strings where the array is terminated by a single NULL pointer.
 | 
			
		||||
** ^If the L parameter is NULL, then all virtual table modules are removed.
 | 
			
		||||
**
 | 
			
		||||
** See also: [sqlite3_create_module()]
 | 
			
		||||
*/
 | 
			
		||||
SQLITE_API int sqlite3_drop_modules(
 | 
			
		||||
  sqlite3 *db,                /* Remove modules from this connection */
 | 
			
		||||
  const char **azKeep         /* Except, do not remove the ones named here */
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
** CAPI3REF: Virtual Table Instance Object
 | 
			
		||||
** KEYWORDS: sqlite3_vtab
 | 
			
		||||
@@ -7336,7 +7399,7 @@ SQLITE_API int sqlite3_test_control(int op, ...);
 | 
			
		||||
#define SQLITE_TESTCTRL_FIRST                    5
 | 
			
		||||
#define SQLITE_TESTCTRL_PRNG_SAVE                5
 | 
			
		||||
#define SQLITE_TESTCTRL_PRNG_RESTORE             6
 | 
			
		||||
#define SQLITE_TESTCTRL_PRNG_RESET               7
 | 
			
		||||
#define SQLITE_TESTCTRL_PRNG_RESET               7  /* NOT USED */
 | 
			
		||||
#define SQLITE_TESTCTRL_BITVEC_TEST              8
 | 
			
		||||
#define SQLITE_TESTCTRL_FAULT_INSTALL            9
 | 
			
		||||
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS     10
 | 
			
		||||
@@ -7359,7 +7422,9 @@ SQLITE_API int sqlite3_test_control(int op, ...);
 | 
			
		||||
#define SQLITE_TESTCTRL_IMPOSTER                25
 | 
			
		||||
#define SQLITE_TESTCTRL_PARSER_COVERAGE         26
 | 
			
		||||
#define SQLITE_TESTCTRL_RESULT_INTREAL          27
 | 
			
		||||
#define SQLITE_TESTCTRL_LAST                    27  /* Largest TESTCTRL */
 | 
			
		||||
#define SQLITE_TESTCTRL_PRNG_SEED               28
 | 
			
		||||
#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS     29
 | 
			
		||||
#define SQLITE_TESTCTRL_LAST                    29  /* Largest TESTCTRL */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
** CAPI3REF: SQL Keyword Checking
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										154
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										154
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
@@ -183,6 +183,12 @@ static int _sqlite3_limit(sqlite3* db, int limitId, int newLimit) {
 | 
			
		||||
  return sqlite3_limit(db, limitId, newLimit);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if SQLITE_VERSION_NUMBER < 3012000
 | 
			
		||||
static int sqlite3_system_errno(sqlite3 *db) {
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
*/
 | 
			
		||||
import "C"
 | 
			
		||||
import (
 | 
			
		||||
@@ -198,6 +204,7 @@ import (
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
@@ -328,7 +335,7 @@ type SQLiteRows struct {
 | 
			
		||||
	decltype []string
 | 
			
		||||
	cls      bool
 | 
			
		||||
	closed   bool
 | 
			
		||||
	done     chan struct{}
 | 
			
		||||
	ctx      context.Context // no better alternative to pass context into Next() method
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type functionInfo struct {
 | 
			
		||||
@@ -749,15 +756,28 @@ func (c *SQLiteConn) lastError() error {
 | 
			
		||||
	return lastError(c.db)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Note: may be called with db == nil
 | 
			
		||||
func lastError(db *C.sqlite3) error {
 | 
			
		||||
	rv := C.sqlite3_errcode(db)
 | 
			
		||||
	rv := C.sqlite3_errcode(db) // returns SQLITE_NOMEM if db == nil
 | 
			
		||||
	if rv == C.SQLITE_OK {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	extrv := C.sqlite3_extended_errcode(db)    // returns SQLITE_NOMEM if db == nil
 | 
			
		||||
	errStr := C.GoString(C.sqlite3_errmsg(db)) // returns "out of memory" if db == nil
 | 
			
		||||
 | 
			
		||||
	// https://www.sqlite.org/c3ref/system_errno.html
 | 
			
		||||
	// sqlite3_system_errno is only meaningful if the error code was SQLITE_CANTOPEN,
 | 
			
		||||
	// or it was SQLITE_IOERR and the extended code was not SQLITE_IOERR_NOMEM
 | 
			
		||||
	var systemErrno syscall.Errno
 | 
			
		||||
	if rv == C.SQLITE_CANTOPEN || (rv == C.SQLITE_IOERR && extrv != C.SQLITE_IOERR_NOMEM) {
 | 
			
		||||
		systemErrno = syscall.Errno(C.sqlite3_system_errno(db))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return Error{
 | 
			
		||||
		Code:         ErrNo(rv),
 | 
			
		||||
		ExtendedCode: ErrNoExtended(C.sqlite3_extended_errcode(db)),
 | 
			
		||||
		err:          C.GoString(C.sqlite3_errmsg(db)),
 | 
			
		||||
		ExtendedCode: ErrNoExtended(extrv),
 | 
			
		||||
		SystemErrno:  systemErrno,
 | 
			
		||||
		err:          errStr,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -869,10 +889,6 @@ func (c *SQLiteConn) begin(ctx context.Context) (driver.Tx, error) {
 | 
			
		||||
	return &SQLiteTx{c}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func errorString(err Error) string {
 | 
			
		||||
	return C.GoString(C.sqlite3_errstr(C.int(err.Code)))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Open database and return a new connection.
 | 
			
		||||
//
 | 
			
		||||
// A pragma can take either zero or one argument.
 | 
			
		||||
@@ -897,7 +913,7 @@ func errorString(err Error) string {
 | 
			
		||||
//      - rwc
 | 
			
		||||
//      - memory
 | 
			
		||||
//
 | 
			
		||||
//   shared
 | 
			
		||||
//   cache
 | 
			
		||||
//     SQLite Shared-Cache Mode
 | 
			
		||||
//     https://www.sqlite.org/sharedcache.html
 | 
			
		||||
//     Values:
 | 
			
		||||
@@ -1000,7 +1016,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
 | 
			
		||||
	deferForeignKeys := -1
 | 
			
		||||
	foreignKeys := -1
 | 
			
		||||
	ignoreCheckConstraints := -1
 | 
			
		||||
	journalMode := "DELETE"
 | 
			
		||||
	var journalMode string
 | 
			
		||||
	lockingMode := "NORMAL"
 | 
			
		||||
	queryOnly := -1
 | 
			
		||||
	recursiveTriggers := -1
 | 
			
		||||
@@ -1232,7 +1248,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
 | 
			
		||||
		if _, ok := params["_locking"]; ok {
 | 
			
		||||
			pkey = "_locking"
 | 
			
		||||
		}
 | 
			
		||||
		if val := params.Get("_locking"); val != "" {
 | 
			
		||||
		if val := params.Get(pkey); val != "" {
 | 
			
		||||
			switch strings.ToUpper(val) {
 | 
			
		||||
			case "NORMAL", "EXCLUSIVE":
 | 
			
		||||
				lockingMode = strings.ToUpper(val)
 | 
			
		||||
@@ -1342,10 +1358,13 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
 | 
			
		||||
		mutex|C.SQLITE_OPEN_READWRITE|C.SQLITE_OPEN_CREATE,
 | 
			
		||||
		nil)
 | 
			
		||||
	if rv != 0 {
 | 
			
		||||
		// Save off the error _before_ closing the database.
 | 
			
		||||
		// This is safe even if db is nil.
 | 
			
		||||
		err := lastError(db)
 | 
			
		||||
		if db != nil {
 | 
			
		||||
			C.sqlite3_close_v2(db)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, Error{Code: ErrNo(rv)}
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if db == nil {
 | 
			
		||||
		return nil, errors.New("sqlite succeeded without returning a database")
 | 
			
		||||
@@ -1522,10 +1541,10 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
 | 
			
		||||
		// Before going any further, we need to check that the user
 | 
			
		||||
		// has provided an username and password within the DSN.
 | 
			
		||||
		// We are not allowed to continue.
 | 
			
		||||
		if len(authUser) < 0 {
 | 
			
		||||
		if len(authUser) == 0 {
 | 
			
		||||
			return nil, fmt.Errorf("Missing '_auth_user' while user authentication was requested with '_auth'")
 | 
			
		||||
		}
 | 
			
		||||
		if len(authPass) < 0 {
 | 
			
		||||
		if len(authPass) == 0 {
 | 
			
		||||
			return nil, fmt.Errorf("Missing '_auth_pass' while user authentication was requested with '_auth'")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -1571,10 +1590,11 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Journal Mode
 | 
			
		||||
	// Because default Journal Mode is DELETE this PRAGMA can always be executed.
 | 
			
		||||
	if err := exec(fmt.Sprintf("PRAGMA journal_mode = %s;", journalMode)); err != nil {
 | 
			
		||||
		C.sqlite3_close_v2(db)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	if journalMode != "" {
 | 
			
		||||
		if err := exec(fmt.Sprintf("PRAGMA journal_mode = %s;", journalMode)); err != nil {
 | 
			
		||||
			C.sqlite3_close_v2(db)
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Locking Mode
 | 
			
		||||
@@ -1846,28 +1866,13 @@ func (s *SQLiteStmt) query(ctx context.Context, args []namedValue) (driver.Rows,
 | 
			
		||||
		decltype: nil,
 | 
			
		||||
		cls:      s.cls,
 | 
			
		||||
		closed:   false,
 | 
			
		||||
		done:     make(chan struct{}),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ctxdone := ctx.Done(); ctxdone != nil {
 | 
			
		||||
		go func(db *C.sqlite3) {
 | 
			
		||||
			select {
 | 
			
		||||
			case <-ctxdone:
 | 
			
		||||
				select {
 | 
			
		||||
				case <-rows.done:
 | 
			
		||||
				default:
 | 
			
		||||
					C.sqlite3_interrupt(db)
 | 
			
		||||
					rows.Close()
 | 
			
		||||
				}
 | 
			
		||||
			case <-rows.done:
 | 
			
		||||
			}
 | 
			
		||||
		}(s.c.db)
 | 
			
		||||
		ctx:      ctx,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return rows, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LastInsertId teturn last inserted ID.
 | 
			
		||||
// LastInsertId return last inserted ID.
 | 
			
		||||
func (r *SQLiteResult) LastInsertId() (int64, error) {
 | 
			
		||||
	return r.id, nil
 | 
			
		||||
}
 | 
			
		||||
@@ -1889,29 +1894,43 @@ func (s *SQLiteStmt) Exec(args []driver.Value) (driver.Result, error) {
 | 
			
		||||
	return s.exec(context.Background(), list)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// exec executes a query that doesn't return rows. Attempts to honor context timeout.
 | 
			
		||||
func (s *SQLiteStmt) exec(ctx context.Context, args []namedValue) (driver.Result, error) {
 | 
			
		||||
	if ctx.Done() == nil {
 | 
			
		||||
		return s.execSync(args)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	type result struct {
 | 
			
		||||
		r   driver.Result
 | 
			
		||||
		err error
 | 
			
		||||
	}
 | 
			
		||||
	resultCh := make(chan result)
 | 
			
		||||
	go func() {
 | 
			
		||||
		r, err := s.execSync(args)
 | 
			
		||||
		resultCh <- result{r, err}
 | 
			
		||||
	}()
 | 
			
		||||
	select {
 | 
			
		||||
	case rv := <-resultCh:
 | 
			
		||||
		return rv.r, rv.err
 | 
			
		||||
	case <-ctx.Done():
 | 
			
		||||
		select {
 | 
			
		||||
		case <-resultCh: // no need to interrupt
 | 
			
		||||
		default:
 | 
			
		||||
			// this is still racy and can be no-op if executed between sqlite3_* calls in execSync.
 | 
			
		||||
			C.sqlite3_interrupt(s.c.db)
 | 
			
		||||
			<-resultCh // ensure goroutine completed
 | 
			
		||||
		}
 | 
			
		||||
		return nil, ctx.Err()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SQLiteStmt) execSync(args []namedValue) (driver.Result, error) {
 | 
			
		||||
	if err := s.bind(args); err != nil {
 | 
			
		||||
		C.sqlite3_reset(s.s)
 | 
			
		||||
		C.sqlite3_clear_bindings(s.s)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ctxdone := ctx.Done(); ctxdone != nil {
 | 
			
		||||
		done := make(chan struct{})
 | 
			
		||||
		defer close(done)
 | 
			
		||||
		go func(db *C.sqlite3) {
 | 
			
		||||
			select {
 | 
			
		||||
			case <-done:
 | 
			
		||||
			case <-ctxdone:
 | 
			
		||||
				select {
 | 
			
		||||
				case <-done:
 | 
			
		||||
				default:
 | 
			
		||||
					C.sqlite3_interrupt(db)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}(s.c.db)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var rowid, changes C.longlong
 | 
			
		||||
	rv := C._sqlite3_step_row_internal(s.s, &rowid, &changes)
 | 
			
		||||
	if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
 | 
			
		||||
@@ -1932,9 +1951,6 @@ func (rc *SQLiteRows) Close() error {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	rc.closed = true
 | 
			
		||||
	if rc.done != nil {
 | 
			
		||||
		close(rc.done)
 | 
			
		||||
	}
 | 
			
		||||
	if rc.cls {
 | 
			
		||||
		rc.s.mu.Unlock()
 | 
			
		||||
		return rc.s.Close()
 | 
			
		||||
@@ -1978,13 +1994,39 @@ func (rc *SQLiteRows) DeclTypes() []string {
 | 
			
		||||
	return rc.declTypes()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Next move cursor to next.
 | 
			
		||||
// Next move cursor to next. Attempts to honor context timeout from QueryContext call.
 | 
			
		||||
func (rc *SQLiteRows) Next(dest []driver.Value) error {
 | 
			
		||||
	rc.s.mu.Lock()
 | 
			
		||||
	defer rc.s.mu.Unlock()
 | 
			
		||||
 | 
			
		||||
	if rc.s.closed {
 | 
			
		||||
		return io.EOF
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if rc.ctx.Done() == nil {
 | 
			
		||||
		return rc.nextSyncLocked(dest)
 | 
			
		||||
	}
 | 
			
		||||
	resultCh := make(chan error)
 | 
			
		||||
	go func() {
 | 
			
		||||
		resultCh <- rc.nextSyncLocked(dest)
 | 
			
		||||
	}()
 | 
			
		||||
	select {
 | 
			
		||||
	case err := <-resultCh:
 | 
			
		||||
		return err
 | 
			
		||||
	case <-rc.ctx.Done():
 | 
			
		||||
		select {
 | 
			
		||||
		case <-resultCh: // no need to interrupt
 | 
			
		||||
		default:
 | 
			
		||||
			// this is still racy and can be no-op if executed between sqlite3_* calls in nextSyncLocked.
 | 
			
		||||
			C.sqlite3_interrupt(rc.s.c.db)
 | 
			
		||||
			<-resultCh // ensure goroutine completed
 | 
			
		||||
		}
 | 
			
		||||
		return rc.ctx.Err()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nextSyncLocked moves cursor to next; must be called with locked mutex.
 | 
			
		||||
func (rc *SQLiteRows) nextSyncLocked(dest []driver.Value) error {
 | 
			
		||||
	rv := C._sqlite3_step_internal(rc.s.s)
 | 
			
		||||
	if rv == C.SQLITE_DONE {
 | 
			
		||||
		return io.EOF
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_context.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_context.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_go18.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_go18.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
@@ -11,6 +11,7 @@ package sqlite3
 | 
			
		||||
#cgo CFLAGS: -DUSE_LIBSQLITE3
 | 
			
		||||
#cgo linux LDFLAGS: -lsqlite3
 | 
			
		||||
#cgo darwin LDFLAGS: -L/usr/local/opt/sqlite/lib -lsqlite3
 | 
			
		||||
#cgo darwin CFLAGS: -I/usr/local/opt/sqlite/include
 | 
			
		||||
#cgo openbsd LDFLAGS: -lsqlite3
 | 
			
		||||
#cgo solaris LDFLAGS: -lsqlite3
 | 
			
		||||
*/
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension_omit.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension_omit.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_allow_uri_authority.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_allow_uri_authority.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_app_armor.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_app_armor.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_foreign_keys.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_foreign_keys.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts5.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_fts5.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_icu.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_icu.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_introspect.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_introspect.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_json1.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_json1.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
// Copyright (C) 2019 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 segment.com <friends@segment.com>
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build cgo
 | 
			
		||||
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
// SQLitePreUpdateData represents all of the data available during a
 | 
			
		||||
// pre-update hook call.
 | 
			
		||||
type SQLitePreUpdateData struct {
 | 
			
		||||
	Conn         *SQLiteConn
 | 
			
		||||
	Op           int
 | 
			
		||||
	DatabaseName string
 | 
			
		||||
	TableName    string
 | 
			
		||||
	OldRowID     int64
 | 
			
		||||
	NewRowID     int64
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										112
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_hook.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_hook.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
			
		||||
// Copyright (C) 2019 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 segment.com <friends@segment.com>
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build sqlite_preupdate_hook
 | 
			
		||||
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
#cgo CFLAGS: -DSQLITE_ENABLE_PREUPDATE_HOOK
 | 
			
		||||
#cgo LDFLAGS: -lm
 | 
			
		||||
 | 
			
		||||
#ifndef USE_LIBSQLITE3
 | 
			
		||||
#include <sqlite3-binding.h>
 | 
			
		||||
#else
 | 
			
		||||
#include <sqlite3.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
void preUpdateHookTrampoline(void*, sqlite3 *, int, char *, char *, sqlite3_int64, sqlite3_int64);
 | 
			
		||||
*/
 | 
			
		||||
import "C"
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RegisterPreUpdateHook sets the pre-update hook for a connection.
 | 
			
		||||
//
 | 
			
		||||
// The callback is passed a SQLitePreUpdateData struct with the data for
 | 
			
		||||
// the update, as well as methods for fetching copies of impacted data.
 | 
			
		||||
//
 | 
			
		||||
// If there is an existing update hook for this connection, it will be
 | 
			
		||||
// removed. If callback is nil the existing hook (if any) will be removed
 | 
			
		||||
// without creating a new one.
 | 
			
		||||
func (c *SQLiteConn) RegisterPreUpdateHook(callback func(SQLitePreUpdateData)) {
 | 
			
		||||
	if callback == nil {
 | 
			
		||||
		C.sqlite3_preupdate_hook(c.db, nil, nil)
 | 
			
		||||
	} else {
 | 
			
		||||
		C.sqlite3_preupdate_hook(c.db, (*[0]byte)(unsafe.Pointer(C.preUpdateHookTrampoline)), unsafe.Pointer(newHandle(c, callback)))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Depth returns the source path of the write, see sqlite3_preupdate_depth()
 | 
			
		||||
func (d *SQLitePreUpdateData) Depth() int {
 | 
			
		||||
	return int(C.sqlite3_preupdate_depth(d.Conn.db))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Count returns the number of columns in the row
 | 
			
		||||
func (d *SQLitePreUpdateData) Count() int {
 | 
			
		||||
	return int(C.sqlite3_preupdate_count(d.Conn.db))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *SQLitePreUpdateData) row(dest []interface{}, new bool) error {
 | 
			
		||||
	for i := 0; i < d.Count() && i < len(dest); i++ {
 | 
			
		||||
		var val *C.sqlite3_value
 | 
			
		||||
		var src interface{}
 | 
			
		||||
 | 
			
		||||
		// Initially I tried making this just a function pointer argument, but
 | 
			
		||||
		// it's absurdly complicated to pass C function pointers.
 | 
			
		||||
		if new {
 | 
			
		||||
			C.sqlite3_preupdate_new(d.Conn.db, C.int(i), &val)
 | 
			
		||||
		} else {
 | 
			
		||||
			C.sqlite3_preupdate_old(d.Conn.db, C.int(i), &val)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch C.sqlite3_value_type(val) {
 | 
			
		||||
		case C.SQLITE_INTEGER:
 | 
			
		||||
			src = int64(C.sqlite3_value_int64(val))
 | 
			
		||||
		case C.SQLITE_FLOAT:
 | 
			
		||||
			src = float64(C.sqlite3_value_double(val))
 | 
			
		||||
		case C.SQLITE_BLOB:
 | 
			
		||||
			len := C.sqlite3_value_bytes(val)
 | 
			
		||||
			blobptr := C.sqlite3_value_blob(val)
 | 
			
		||||
			src = C.GoBytes(blobptr, len)
 | 
			
		||||
		case C.SQLITE_TEXT:
 | 
			
		||||
			len := C.sqlite3_value_bytes(val)
 | 
			
		||||
			cstrptr := unsafe.Pointer(C.sqlite3_value_text(val))
 | 
			
		||||
			src = C.GoBytes(cstrptr, len)
 | 
			
		||||
		case C.SQLITE_NULL:
 | 
			
		||||
			src = nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err := convertAssign(&dest[i], src)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Old populates dest with the row data to be replaced. This works similar to
 | 
			
		||||
// database/sql's Rows.Scan()
 | 
			
		||||
func (d *SQLitePreUpdateData) Old(dest ...interface{}) error {
 | 
			
		||||
	if d.Op == SQLITE_INSERT {
 | 
			
		||||
		return errors.New("There is no old row for INSERT operations")
 | 
			
		||||
	}
 | 
			
		||||
	return d.row(dest, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// New populates dest with the replacement row data. This works similar to
 | 
			
		||||
// database/sql's Rows.Scan()
 | 
			
		||||
func (d *SQLitePreUpdateData) New(dest ...interface{}) error {
 | 
			
		||||
	if d.Op == SQLITE_DELETE {
 | 
			
		||||
		return errors.New("There is no new row for DELETE operations")
 | 
			
		||||
	}
 | 
			
		||||
	return d.row(dest, true)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_omit.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_omit.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
// Copyright (C) 2019 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 segment.com <friends@segment.com>
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build !sqlite_preupdate_hook,cgo
 | 
			
		||||
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
// RegisterPreUpdateHook sets the pre-update hook for a connection.
 | 
			
		||||
//
 | 
			
		||||
// The callback is passed a SQLitePreUpdateData struct with the data for
 | 
			
		||||
// the update, as well as methods for fetching copies of impacted data.
 | 
			
		||||
//
 | 
			
		||||
// If there is an existing update hook for this connection, it will be
 | 
			
		||||
// removed. If callback is nil the existing hook (if any) will be removed
 | 
			
		||||
// without creating a new one.
 | 
			
		||||
func (c *SQLiteConn) RegisterPreUpdateHook(callback func(SQLitePreUpdateData)) {
 | 
			
		||||
	// NOOP
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete_fast.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete_fast.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_stat4.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_stat4.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_unlock_notify.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2018 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_full.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_full.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_incr.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_incr.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_other.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_other.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_solaris.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_solaris.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2018 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_trace.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_trace.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2016 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
@@ -89,6 +89,7 @@ func fillExpandedSQL(info *TraceInfo, db *C.sqlite3, pStmt unsafe.Pointer) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expSQLiteCStr := C.sqlite3_expanded_sql((*C.sqlite3_stmt)(pStmt))
 | 
			
		||||
	defer C.sqlite3_free(unsafe.Pointer(expSQLiteCStr))
 | 
			
		||||
	if expSQLiteCStr == nil {
 | 
			
		||||
		fillDBError(&info.DBError, db)
 | 
			
		||||
		return
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_type.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_type.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,3 +1,8 @@
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package sqlite3
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3ext.h
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/mattn/go-sqlite3/sqlite3ext.h
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -323,6 +323,8 @@ struct sqlite3_api_routines {
 | 
			
		||||
  /* Version 3.28.0 and later */
 | 
			
		||||
  int (*stmt_isexplain)(sqlite3_stmt*);
 | 
			
		||||
  int (*value_frombind)(sqlite3_value*);
 | 
			
		||||
  /* Version 3.30.0 and later */
 | 
			
		||||
  int (*drop_modules)(sqlite3*,const char**);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
@@ -615,6 +617,8 @@ typedef int (*sqlite3_loadext_entry)(
 | 
			
		||||
/* Version 3.28.0 and later */
 | 
			
		||||
#define sqlite3_stmt_isexplain         sqlite3_api->isexplain
 | 
			
		||||
#define sqlite3_value_frombind         sqlite3_api->frombind
 | 
			
		||||
/* Version 3.30.0 and later */
 | 
			
		||||
#define sqlite3_drop_modules           sqlite3_api->drop_modules
 | 
			
		||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
 | 
			
		||||
 | 
			
		||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/github.com/mattn/go-sqlite3/static_mock.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/mattn/go-sqlite3/static_mock.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,3 +1,8 @@
 | 
			
		||||
// Copyright (C) 2019 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
 | 
			
		||||
//
 | 
			
		||||
// Use of this source code is governed by an MIT-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// +build !cgo
 | 
			
		||||
 | 
			
		||||
package sqlite3
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								vendor/github.com/spf13/pflag/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/spf13/pflag/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -3,8 +3,9 @@ sudo: false
 | 
			
		||||
language: go
 | 
			
		||||
 | 
			
		||||
go:
 | 
			
		||||
  - 1.7.3
 | 
			
		||||
  - 1.8.1
 | 
			
		||||
  - 1.9.x
 | 
			
		||||
  - 1.10.x
 | 
			
		||||
  - 1.11.x
 | 
			
		||||
  - tip
 | 
			
		||||
 | 
			
		||||
matrix:
 | 
			
		||||
@@ -12,7 +13,7 @@ matrix:
 | 
			
		||||
    - go: tip
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
  - go get github.com/golang/lint/golint
 | 
			
		||||
  - go get golang.org/x/lint/golint
 | 
			
		||||
  - export PATH=$GOPATH/bin:$PATH
 | 
			
		||||
  - go install ./...
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/spf13/pflag/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/spf13/pflag/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -86,8 +86,8 @@ fmt.Println("ip has value ", *ip)
 | 
			
		||||
fmt.Println("flagvar has value ", flagvar)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
There are helpers function to get values later if you have the FlagSet but
 | 
			
		||||
it was difficult to keep up with all of the flag pointers in your code.
 | 
			
		||||
There are helper functions available to get the value stored in a Flag if you have a FlagSet but find
 | 
			
		||||
it difficult to keep up with all of the pointers in your code.
 | 
			
		||||
If you have a pflag.FlagSet with a flag called 'flagname' of type int you
 | 
			
		||||
can use GetInt() to get the int value. But notice that 'flagname' must exist
 | 
			
		||||
and it must be an int. GetString("flagname") will fail.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								vendor/github.com/spf13/pflag/bool_slice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								vendor/github.com/spf13/pflag/bool_slice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -71,6 +71,44 @@ func (s *boolSliceValue) String() string {
 | 
			
		||||
	return "[" + out + "]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *boolSliceValue) fromString(val string) (bool, error) {
 | 
			
		||||
	return strconv.ParseBool(val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *boolSliceValue) toString(val bool) string {
 | 
			
		||||
	return strconv.FormatBool(val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *boolSliceValue) Append(val string) error {
 | 
			
		||||
	i, err := s.fromString(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = append(*s.value, i)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *boolSliceValue) Replace(val []string) error {
 | 
			
		||||
	out := make([]bool, len(val))
 | 
			
		||||
	for i, d := range val {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = s.fromString(d)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = out
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *boolSliceValue) GetSlice() []string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = s.toString(d)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func boolSliceConv(val string) (interface{}, error) {
 | 
			
		||||
	val = strings.Trim(val, "[]")
 | 
			
		||||
	// Empty string would cause a slice with one (empty) entry
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/spf13/pflag/count.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/spf13/pflag/count.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -46,7 +46,7 @@ func (f *FlagSet) GetCount(name string) (int, error) {
 | 
			
		||||
 | 
			
		||||
// CountVar defines a count flag with specified name, default value, and usage string.
 | 
			
		||||
// The argument p points to an int variable in which to store the value of the flag.
 | 
			
		||||
// A count flag will add 1 to its value evey time it is found on the command line
 | 
			
		||||
// A count flag will add 1 to its value every time it is found on the command line
 | 
			
		||||
func (f *FlagSet) CountVar(p *int, name string, usage string) {
 | 
			
		||||
	f.CountVarP(p, name, "", usage)
 | 
			
		||||
}
 | 
			
		||||
@@ -69,7 +69,7 @@ func CountVarP(p *int, name, shorthand string, usage string) {
 | 
			
		||||
 | 
			
		||||
// Count defines a count flag with specified name, default value, and usage string.
 | 
			
		||||
// The return value is the address of an int variable that stores the value of the flag.
 | 
			
		||||
// A count flag will add 1 to its value evey time it is found on the command line
 | 
			
		||||
// A count flag will add 1 to its value every time it is found on the command line
 | 
			
		||||
func (f *FlagSet) Count(name string, usage string) *int {
 | 
			
		||||
	p := new(int)
 | 
			
		||||
	f.CountVarP(p, name, "", usage)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								vendor/github.com/spf13/pflag/duration_slice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								vendor/github.com/spf13/pflag/duration_slice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -51,6 +51,44 @@ func (s *durationSliceValue) String() string {
 | 
			
		||||
	return "[" + strings.Join(out, ",") + "]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *durationSliceValue) fromString(val string) (time.Duration, error) {
 | 
			
		||||
	return time.ParseDuration(val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *durationSliceValue) toString(val time.Duration) string {
 | 
			
		||||
	return fmt.Sprintf("%s", val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *durationSliceValue) Append(val string) error {
 | 
			
		||||
	i, err := s.fromString(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = append(*s.value, i)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *durationSliceValue) Replace(val []string) error {
 | 
			
		||||
	out := make([]time.Duration, len(val))
 | 
			
		||||
	for i, d := range val {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = s.fromString(d)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = out
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *durationSliceValue) GetSlice() []string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = s.toString(d)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func durationSliceConv(val string) (interface{}, error) {
 | 
			
		||||
	val = strings.Trim(val, "[]")
 | 
			
		||||
	// Empty string would cause a slice with one (empty) entry
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								vendor/github.com/spf13/pflag/flag.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								vendor/github.com/spf13/pflag/flag.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -57,9 +57,9 @@ that give one-letter shorthands for flags. You can use these by appending
 | 
			
		||||
	var ip = flag.IntP("flagname", "f", 1234, "help message")
 | 
			
		||||
	var flagvar bool
 | 
			
		||||
	func init() {
 | 
			
		||||
		flag.BoolVarP("boolname", "b", true, "help message")
 | 
			
		||||
		flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
 | 
			
		||||
	}
 | 
			
		||||
	flag.VarP(&flagVar, "varname", "v", 1234, "help message")
 | 
			
		||||
	flag.VarP(&flagval, "varname", "v", "help message")
 | 
			
		||||
Shorthand letters can be used with single dashes on the command line.
 | 
			
		||||
Boolean shorthand flags can be combined with other shorthand flags.
 | 
			
		||||
 | 
			
		||||
@@ -190,6 +190,18 @@ type Value interface {
 | 
			
		||||
	Type() string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SliceValue is a secondary interface to all flags which hold a list
 | 
			
		||||
// of values.  This allows full control over the value of list flags,
 | 
			
		||||
// and avoids complicated marshalling and unmarshalling to csv.
 | 
			
		||||
type SliceValue interface {
 | 
			
		||||
	// Append adds the specified value to the end of the flag value list.
 | 
			
		||||
	Append(string) error
 | 
			
		||||
	// Replace will fully overwrite any data currently in the flag value list.
 | 
			
		||||
	Replace([]string) error
 | 
			
		||||
	// GetSlice returns the flag value list as an array of strings.
 | 
			
		||||
	GetSlice() []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// sortFlags returns the flags as a slice in lexicographical sorted order.
 | 
			
		||||
func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
 | 
			
		||||
	list := make(sort.StringSlice, len(flags))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										174
									
								
								vendor/github.com/spf13/pflag/float32_slice.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								vendor/github.com/spf13/pflag/float32_slice.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,174 @@
 | 
			
		||||
package pflag
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// -- float32Slice Value
 | 
			
		||||
type float32SliceValue struct {
 | 
			
		||||
	value   *[]float32
 | 
			
		||||
	changed bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newFloat32SliceValue(val []float32, p *[]float32) *float32SliceValue {
 | 
			
		||||
	isv := new(float32SliceValue)
 | 
			
		||||
	isv.value = p
 | 
			
		||||
	*isv.value = val
 | 
			
		||||
	return isv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float32SliceValue) Set(val string) error {
 | 
			
		||||
	ss := strings.Split(val, ",")
 | 
			
		||||
	out := make([]float32, len(ss))
 | 
			
		||||
	for i, d := range ss {
 | 
			
		||||
		var err error
 | 
			
		||||
		var temp64 float64
 | 
			
		||||
		temp64, err = strconv.ParseFloat(d, 32)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		out[i] = float32(temp64)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	if !s.changed {
 | 
			
		||||
		*s.value = out
 | 
			
		||||
	} else {
 | 
			
		||||
		*s.value = append(*s.value, out...)
 | 
			
		||||
	}
 | 
			
		||||
	s.changed = true
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float32SliceValue) Type() string {
 | 
			
		||||
	return "float32Slice"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float32SliceValue) String() string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = fmt.Sprintf("%f", d)
 | 
			
		||||
	}
 | 
			
		||||
	return "[" + strings.Join(out, ",") + "]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float32SliceValue) fromString(val string) (float32, error) {
 | 
			
		||||
	t64, err := strconv.ParseFloat(val, 32)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return float32(t64), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float32SliceValue) toString(val float32) string {
 | 
			
		||||
	return fmt.Sprintf("%f", val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float32SliceValue) Append(val string) error {
 | 
			
		||||
	i, err := s.fromString(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = append(*s.value, i)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float32SliceValue) Replace(val []string) error {
 | 
			
		||||
	out := make([]float32, len(val))
 | 
			
		||||
	for i, d := range val {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = s.fromString(d)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = out
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float32SliceValue) GetSlice() []string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = s.toString(d)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func float32SliceConv(val string) (interface{}, error) {
 | 
			
		||||
	val = strings.Trim(val, "[]")
 | 
			
		||||
	// Empty string would cause a slice with one (empty) entry
 | 
			
		||||
	if len(val) == 0 {
 | 
			
		||||
		return []float32{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	ss := strings.Split(val, ",")
 | 
			
		||||
	out := make([]float32, len(ss))
 | 
			
		||||
	for i, d := range ss {
 | 
			
		||||
		var err error
 | 
			
		||||
		var temp64 float64
 | 
			
		||||
		temp64, err = strconv.ParseFloat(d, 32)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		out[i] = float32(temp64)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetFloat32Slice return the []float32 value of a flag with the given name
 | 
			
		||||
func (f *FlagSet) GetFloat32Slice(name string) ([]float32, error) {
 | 
			
		||||
	val, err := f.getFlagType(name, "float32Slice", float32SliceConv)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []float32{}, err
 | 
			
		||||
	}
 | 
			
		||||
	return val.([]float32), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float32SliceVar defines a float32Slice flag with specified name, default value, and usage string.
 | 
			
		||||
// The argument p points to a []float32 variable in which to store the value of the flag.
 | 
			
		||||
func (f *FlagSet) Float32SliceVar(p *[]float32, name string, value []float32, usage string) {
 | 
			
		||||
	f.VarP(newFloat32SliceValue(value, p), name, "", usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float32SliceVarP is like Float32SliceVar, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func (f *FlagSet) Float32SliceVarP(p *[]float32, name, shorthand string, value []float32, usage string) {
 | 
			
		||||
	f.VarP(newFloat32SliceValue(value, p), name, shorthand, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float32SliceVar defines a float32[] flag with specified name, default value, and usage string.
 | 
			
		||||
// The argument p points to a float32[] variable in which to store the value of the flag.
 | 
			
		||||
func Float32SliceVar(p *[]float32, name string, value []float32, usage string) {
 | 
			
		||||
	CommandLine.VarP(newFloat32SliceValue(value, p), name, "", usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float32SliceVarP is like Float32SliceVar, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func Float32SliceVarP(p *[]float32, name, shorthand string, value []float32, usage string) {
 | 
			
		||||
	CommandLine.VarP(newFloat32SliceValue(value, p), name, shorthand, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float32Slice defines a []float32 flag with specified name, default value, and usage string.
 | 
			
		||||
// The return value is the address of a []float32 variable that stores the value of the flag.
 | 
			
		||||
func (f *FlagSet) Float32Slice(name string, value []float32, usage string) *[]float32 {
 | 
			
		||||
	p := []float32{}
 | 
			
		||||
	f.Float32SliceVarP(&p, name, "", value, usage)
 | 
			
		||||
	return &p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float32SliceP is like Float32Slice, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func (f *FlagSet) Float32SliceP(name, shorthand string, value []float32, usage string) *[]float32 {
 | 
			
		||||
	p := []float32{}
 | 
			
		||||
	f.Float32SliceVarP(&p, name, shorthand, value, usage)
 | 
			
		||||
	return &p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float32Slice defines a []float32 flag with specified name, default value, and usage string.
 | 
			
		||||
// The return value is the address of a []float32 variable that stores the value of the flag.
 | 
			
		||||
func Float32Slice(name string, value []float32, usage string) *[]float32 {
 | 
			
		||||
	return CommandLine.Float32SliceP(name, "", value, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float32SliceP is like Float32Slice, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func Float32SliceP(name, shorthand string, value []float32, usage string) *[]float32 {
 | 
			
		||||
	return CommandLine.Float32SliceP(name, shorthand, value, usage)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										166
									
								
								vendor/github.com/spf13/pflag/float64_slice.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								vendor/github.com/spf13/pflag/float64_slice.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,166 @@
 | 
			
		||||
package pflag
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// -- float64Slice Value
 | 
			
		||||
type float64SliceValue struct {
 | 
			
		||||
	value   *[]float64
 | 
			
		||||
	changed bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newFloat64SliceValue(val []float64, p *[]float64) *float64SliceValue {
 | 
			
		||||
	isv := new(float64SliceValue)
 | 
			
		||||
	isv.value = p
 | 
			
		||||
	*isv.value = val
 | 
			
		||||
	return isv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float64SliceValue) Set(val string) error {
 | 
			
		||||
	ss := strings.Split(val, ",")
 | 
			
		||||
	out := make([]float64, len(ss))
 | 
			
		||||
	for i, d := range ss {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = strconv.ParseFloat(d, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	if !s.changed {
 | 
			
		||||
		*s.value = out
 | 
			
		||||
	} else {
 | 
			
		||||
		*s.value = append(*s.value, out...)
 | 
			
		||||
	}
 | 
			
		||||
	s.changed = true
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float64SliceValue) Type() string {
 | 
			
		||||
	return "float64Slice"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float64SliceValue) String() string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = fmt.Sprintf("%f", d)
 | 
			
		||||
	}
 | 
			
		||||
	return "[" + strings.Join(out, ",") + "]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float64SliceValue) fromString(val string) (float64, error) {
 | 
			
		||||
	return strconv.ParseFloat(val, 64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float64SliceValue) toString(val float64) string {
 | 
			
		||||
	return fmt.Sprintf("%f", val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float64SliceValue) Append(val string) error {
 | 
			
		||||
	i, err := s.fromString(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = append(*s.value, i)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float64SliceValue) Replace(val []string) error {
 | 
			
		||||
	out := make([]float64, len(val))
 | 
			
		||||
	for i, d := range val {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = s.fromString(d)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = out
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *float64SliceValue) GetSlice() []string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = s.toString(d)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func float64SliceConv(val string) (interface{}, error) {
 | 
			
		||||
	val = strings.Trim(val, "[]")
 | 
			
		||||
	// Empty string would cause a slice with one (empty) entry
 | 
			
		||||
	if len(val) == 0 {
 | 
			
		||||
		return []float64{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	ss := strings.Split(val, ",")
 | 
			
		||||
	out := make([]float64, len(ss))
 | 
			
		||||
	for i, d := range ss {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = strconv.ParseFloat(d, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetFloat64Slice return the []float64 value of a flag with the given name
 | 
			
		||||
func (f *FlagSet) GetFloat64Slice(name string) ([]float64, error) {
 | 
			
		||||
	val, err := f.getFlagType(name, "float64Slice", float64SliceConv)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []float64{}, err
 | 
			
		||||
	}
 | 
			
		||||
	return val.([]float64), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float64SliceVar defines a float64Slice flag with specified name, default value, and usage string.
 | 
			
		||||
// The argument p points to a []float64 variable in which to store the value of the flag.
 | 
			
		||||
func (f *FlagSet) Float64SliceVar(p *[]float64, name string, value []float64, usage string) {
 | 
			
		||||
	f.VarP(newFloat64SliceValue(value, p), name, "", usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float64SliceVarP is like Float64SliceVar, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func (f *FlagSet) Float64SliceVarP(p *[]float64, name, shorthand string, value []float64, usage string) {
 | 
			
		||||
	f.VarP(newFloat64SliceValue(value, p), name, shorthand, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float64SliceVar defines a float64[] flag with specified name, default value, and usage string.
 | 
			
		||||
// The argument p points to a float64[] variable in which to store the value of the flag.
 | 
			
		||||
func Float64SliceVar(p *[]float64, name string, value []float64, usage string) {
 | 
			
		||||
	CommandLine.VarP(newFloat64SliceValue(value, p), name, "", usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float64SliceVarP is like Float64SliceVar, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func Float64SliceVarP(p *[]float64, name, shorthand string, value []float64, usage string) {
 | 
			
		||||
	CommandLine.VarP(newFloat64SliceValue(value, p), name, shorthand, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float64Slice defines a []float64 flag with specified name, default value, and usage string.
 | 
			
		||||
// The return value is the address of a []float64 variable that stores the value of the flag.
 | 
			
		||||
func (f *FlagSet) Float64Slice(name string, value []float64, usage string) *[]float64 {
 | 
			
		||||
	p := []float64{}
 | 
			
		||||
	f.Float64SliceVarP(&p, name, "", value, usage)
 | 
			
		||||
	return &p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float64SliceP is like Float64Slice, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func (f *FlagSet) Float64SliceP(name, shorthand string, value []float64, usage string) *[]float64 {
 | 
			
		||||
	p := []float64{}
 | 
			
		||||
	f.Float64SliceVarP(&p, name, shorthand, value, usage)
 | 
			
		||||
	return &p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float64Slice defines a []float64 flag with specified name, default value, and usage string.
 | 
			
		||||
// The return value is the address of a []float64 variable that stores the value of the flag.
 | 
			
		||||
func Float64Slice(name string, value []float64, usage string) *[]float64 {
 | 
			
		||||
	return CommandLine.Float64SliceP(name, "", value, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Float64SliceP is like Float64Slice, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func Float64SliceP(name, shorthand string, value []float64, usage string) *[]float64 {
 | 
			
		||||
	return CommandLine.Float64SliceP(name, shorthand, value, usage)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/spf13/pflag/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/spf13/pflag/go.mod
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
module github.com/spf13/pflag
 | 
			
		||||
 | 
			
		||||
go 1.12
 | 
			
		||||
							
								
								
									
										0
									
								
								vendor/github.com/spf13/pflag/go.sum
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								vendor/github.com/spf13/pflag/go.sum
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										174
									
								
								vendor/github.com/spf13/pflag/int32_slice.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								vendor/github.com/spf13/pflag/int32_slice.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,174 @@
 | 
			
		||||
package pflag
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// -- int32Slice Value
 | 
			
		||||
type int32SliceValue struct {
 | 
			
		||||
	value   *[]int32
 | 
			
		||||
	changed bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newInt32SliceValue(val []int32, p *[]int32) *int32SliceValue {
 | 
			
		||||
	isv := new(int32SliceValue)
 | 
			
		||||
	isv.value = p
 | 
			
		||||
	*isv.value = val
 | 
			
		||||
	return isv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int32SliceValue) Set(val string) error {
 | 
			
		||||
	ss := strings.Split(val, ",")
 | 
			
		||||
	out := make([]int32, len(ss))
 | 
			
		||||
	for i, d := range ss {
 | 
			
		||||
		var err error
 | 
			
		||||
		var temp64 int64
 | 
			
		||||
		temp64, err = strconv.ParseInt(d, 0, 32)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		out[i] = int32(temp64)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	if !s.changed {
 | 
			
		||||
		*s.value = out
 | 
			
		||||
	} else {
 | 
			
		||||
		*s.value = append(*s.value, out...)
 | 
			
		||||
	}
 | 
			
		||||
	s.changed = true
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int32SliceValue) Type() string {
 | 
			
		||||
	return "int32Slice"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int32SliceValue) String() string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = fmt.Sprintf("%d", d)
 | 
			
		||||
	}
 | 
			
		||||
	return "[" + strings.Join(out, ",") + "]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int32SliceValue) fromString(val string) (int32, error) {
 | 
			
		||||
	t64, err := strconv.ParseInt(val, 0, 32)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return int32(t64), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int32SliceValue) toString(val int32) string {
 | 
			
		||||
	return fmt.Sprintf("%d", val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int32SliceValue) Append(val string) error {
 | 
			
		||||
	i, err := s.fromString(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = append(*s.value, i)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int32SliceValue) Replace(val []string) error {
 | 
			
		||||
	out := make([]int32, len(val))
 | 
			
		||||
	for i, d := range val {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = s.fromString(d)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = out
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int32SliceValue) GetSlice() []string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = s.toString(d)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func int32SliceConv(val string) (interface{}, error) {
 | 
			
		||||
	val = strings.Trim(val, "[]")
 | 
			
		||||
	// Empty string would cause a slice with one (empty) entry
 | 
			
		||||
	if len(val) == 0 {
 | 
			
		||||
		return []int32{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	ss := strings.Split(val, ",")
 | 
			
		||||
	out := make([]int32, len(ss))
 | 
			
		||||
	for i, d := range ss {
 | 
			
		||||
		var err error
 | 
			
		||||
		var temp64 int64
 | 
			
		||||
		temp64, err = strconv.ParseInt(d, 0, 32)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		out[i] = int32(temp64)
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetInt32Slice return the []int32 value of a flag with the given name
 | 
			
		||||
func (f *FlagSet) GetInt32Slice(name string) ([]int32, error) {
 | 
			
		||||
	val, err := f.getFlagType(name, "int32Slice", int32SliceConv)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []int32{}, err
 | 
			
		||||
	}
 | 
			
		||||
	return val.([]int32), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int32SliceVar defines a int32Slice flag with specified name, default value, and usage string.
 | 
			
		||||
// The argument p points to a []int32 variable in which to store the value of the flag.
 | 
			
		||||
func (f *FlagSet) Int32SliceVar(p *[]int32, name string, value []int32, usage string) {
 | 
			
		||||
	f.VarP(newInt32SliceValue(value, p), name, "", usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int32SliceVarP is like Int32SliceVar, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func (f *FlagSet) Int32SliceVarP(p *[]int32, name, shorthand string, value []int32, usage string) {
 | 
			
		||||
	f.VarP(newInt32SliceValue(value, p), name, shorthand, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int32SliceVar defines a int32[] flag with specified name, default value, and usage string.
 | 
			
		||||
// The argument p points to a int32[] variable in which to store the value of the flag.
 | 
			
		||||
func Int32SliceVar(p *[]int32, name string, value []int32, usage string) {
 | 
			
		||||
	CommandLine.VarP(newInt32SliceValue(value, p), name, "", usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int32SliceVarP is like Int32SliceVar, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func Int32SliceVarP(p *[]int32, name, shorthand string, value []int32, usage string) {
 | 
			
		||||
	CommandLine.VarP(newInt32SliceValue(value, p), name, shorthand, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int32Slice defines a []int32 flag with specified name, default value, and usage string.
 | 
			
		||||
// The return value is the address of a []int32 variable that stores the value of the flag.
 | 
			
		||||
func (f *FlagSet) Int32Slice(name string, value []int32, usage string) *[]int32 {
 | 
			
		||||
	p := []int32{}
 | 
			
		||||
	f.Int32SliceVarP(&p, name, "", value, usage)
 | 
			
		||||
	return &p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int32SliceP is like Int32Slice, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func (f *FlagSet) Int32SliceP(name, shorthand string, value []int32, usage string) *[]int32 {
 | 
			
		||||
	p := []int32{}
 | 
			
		||||
	f.Int32SliceVarP(&p, name, shorthand, value, usage)
 | 
			
		||||
	return &p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int32Slice defines a []int32 flag with specified name, default value, and usage string.
 | 
			
		||||
// The return value is the address of a []int32 variable that stores the value of the flag.
 | 
			
		||||
func Int32Slice(name string, value []int32, usage string) *[]int32 {
 | 
			
		||||
	return CommandLine.Int32SliceP(name, "", value, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int32SliceP is like Int32Slice, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func Int32SliceP(name, shorthand string, value []int32, usage string) *[]int32 {
 | 
			
		||||
	return CommandLine.Int32SliceP(name, shorthand, value, usage)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										166
									
								
								vendor/github.com/spf13/pflag/int64_slice.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								vendor/github.com/spf13/pflag/int64_slice.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,166 @@
 | 
			
		||||
package pflag
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// -- int64Slice Value
 | 
			
		||||
type int64SliceValue struct {
 | 
			
		||||
	value   *[]int64
 | 
			
		||||
	changed bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newInt64SliceValue(val []int64, p *[]int64) *int64SliceValue {
 | 
			
		||||
	isv := new(int64SliceValue)
 | 
			
		||||
	isv.value = p
 | 
			
		||||
	*isv.value = val
 | 
			
		||||
	return isv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int64SliceValue) Set(val string) error {
 | 
			
		||||
	ss := strings.Split(val, ",")
 | 
			
		||||
	out := make([]int64, len(ss))
 | 
			
		||||
	for i, d := range ss {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = strconv.ParseInt(d, 0, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	if !s.changed {
 | 
			
		||||
		*s.value = out
 | 
			
		||||
	} else {
 | 
			
		||||
		*s.value = append(*s.value, out...)
 | 
			
		||||
	}
 | 
			
		||||
	s.changed = true
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int64SliceValue) Type() string {
 | 
			
		||||
	return "int64Slice"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int64SliceValue) String() string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = fmt.Sprintf("%d", d)
 | 
			
		||||
	}
 | 
			
		||||
	return "[" + strings.Join(out, ",") + "]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int64SliceValue) fromString(val string) (int64, error) {
 | 
			
		||||
	return strconv.ParseInt(val, 0, 64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int64SliceValue) toString(val int64) string {
 | 
			
		||||
	return fmt.Sprintf("%d", val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int64SliceValue) Append(val string) error {
 | 
			
		||||
	i, err := s.fromString(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = append(*s.value, i)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int64SliceValue) Replace(val []string) error {
 | 
			
		||||
	out := make([]int64, len(val))
 | 
			
		||||
	for i, d := range val {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = s.fromString(d)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = out
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *int64SliceValue) GetSlice() []string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = s.toString(d)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func int64SliceConv(val string) (interface{}, error) {
 | 
			
		||||
	val = strings.Trim(val, "[]")
 | 
			
		||||
	// Empty string would cause a slice with one (empty) entry
 | 
			
		||||
	if len(val) == 0 {
 | 
			
		||||
		return []int64{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	ss := strings.Split(val, ",")
 | 
			
		||||
	out := make([]int64, len(ss))
 | 
			
		||||
	for i, d := range ss {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = strconv.ParseInt(d, 0, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetInt64Slice return the []int64 value of a flag with the given name
 | 
			
		||||
func (f *FlagSet) GetInt64Slice(name string) ([]int64, error) {
 | 
			
		||||
	val, err := f.getFlagType(name, "int64Slice", int64SliceConv)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []int64{}, err
 | 
			
		||||
	}
 | 
			
		||||
	return val.([]int64), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int64SliceVar defines a int64Slice flag with specified name, default value, and usage string.
 | 
			
		||||
// The argument p points to a []int64 variable in which to store the value of the flag.
 | 
			
		||||
func (f *FlagSet) Int64SliceVar(p *[]int64, name string, value []int64, usage string) {
 | 
			
		||||
	f.VarP(newInt64SliceValue(value, p), name, "", usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int64SliceVarP is like Int64SliceVar, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func (f *FlagSet) Int64SliceVarP(p *[]int64, name, shorthand string, value []int64, usage string) {
 | 
			
		||||
	f.VarP(newInt64SliceValue(value, p), name, shorthand, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int64SliceVar defines a int64[] flag with specified name, default value, and usage string.
 | 
			
		||||
// The argument p points to a int64[] variable in which to store the value of the flag.
 | 
			
		||||
func Int64SliceVar(p *[]int64, name string, value []int64, usage string) {
 | 
			
		||||
	CommandLine.VarP(newInt64SliceValue(value, p), name, "", usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int64SliceVarP is like Int64SliceVar, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func Int64SliceVarP(p *[]int64, name, shorthand string, value []int64, usage string) {
 | 
			
		||||
	CommandLine.VarP(newInt64SliceValue(value, p), name, shorthand, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int64Slice defines a []int64 flag with specified name, default value, and usage string.
 | 
			
		||||
// The return value is the address of a []int64 variable that stores the value of the flag.
 | 
			
		||||
func (f *FlagSet) Int64Slice(name string, value []int64, usage string) *[]int64 {
 | 
			
		||||
	p := []int64{}
 | 
			
		||||
	f.Int64SliceVarP(&p, name, "", value, usage)
 | 
			
		||||
	return &p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int64SliceP is like Int64Slice, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func (f *FlagSet) Int64SliceP(name, shorthand string, value []int64, usage string) *[]int64 {
 | 
			
		||||
	p := []int64{}
 | 
			
		||||
	f.Int64SliceVarP(&p, name, shorthand, value, usage)
 | 
			
		||||
	return &p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int64Slice defines a []int64 flag with specified name, default value, and usage string.
 | 
			
		||||
// The return value is the address of a []int64 variable that stores the value of the flag.
 | 
			
		||||
func Int64Slice(name string, value []int64, usage string) *[]int64 {
 | 
			
		||||
	return CommandLine.Int64SliceP(name, "", value, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Int64SliceP is like Int64Slice, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func Int64SliceP(name, shorthand string, value []int64, usage string) *[]int64 {
 | 
			
		||||
	return CommandLine.Int64SliceP(name, shorthand, value, usage)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/github.com/spf13/pflag/int_slice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/spf13/pflag/int_slice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -51,6 +51,36 @@ func (s *intSliceValue) String() string {
 | 
			
		||||
	return "[" + strings.Join(out, ",") + "]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *intSliceValue) Append(val string) error {
 | 
			
		||||
	i, err := strconv.Atoi(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = append(*s.value, i)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *intSliceValue) Replace(val []string) error {
 | 
			
		||||
	out := make([]int, len(val))
 | 
			
		||||
	for i, d := range val {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = strconv.Atoi(d)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = out
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *intSliceValue) GetSlice() []string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = strconv.Itoa(d)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func intSliceConv(val string) (interface{}, error) {
 | 
			
		||||
	val = strings.Trim(val, "[]")
 | 
			
		||||
	// Empty string would cause a slice with one (empty) entry
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								vendor/github.com/spf13/pflag/ip_slice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										40
									
								
								vendor/github.com/spf13/pflag/ip_slice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -72,9 +72,47 @@ func (s *ipSliceValue) String() string {
 | 
			
		||||
	return "[" + out + "]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ipSliceValue) fromString(val string) (net.IP, error) {
 | 
			
		||||
	return net.ParseIP(strings.TrimSpace(val)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ipSliceValue) toString(val net.IP) string {
 | 
			
		||||
	return val.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ipSliceValue) Append(val string) error {
 | 
			
		||||
	i, err := s.fromString(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = append(*s.value, i)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ipSliceValue) Replace(val []string) error {
 | 
			
		||||
	out := make([]net.IP, len(val))
 | 
			
		||||
	for i, d := range val {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = s.fromString(d)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = out
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ipSliceValue) GetSlice() []string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = s.toString(d)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ipSliceConv(val string) (interface{}, error) {
 | 
			
		||||
	val = strings.Trim(val, "[]")
 | 
			
		||||
	// Emtpy string would cause a slice with one (empty) entry
 | 
			
		||||
	// Empty string would cause a slice with one (empty) entry
 | 
			
		||||
	if len(val) == 0 {
 | 
			
		||||
		return []net.IP{}, nil
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								vendor/github.com/spf13/pflag/string_array.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/spf13/pflag/string_array.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -23,6 +23,32 @@ func (s *stringArrayValue) Set(val string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stringArrayValue) Append(val string) error {
 | 
			
		||||
	*s.value = append(*s.value, val)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stringArrayValue) Replace(val []string) error {
 | 
			
		||||
	out := make([]string, len(val))
 | 
			
		||||
	for i, d := range val {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i] = d
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = out
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stringArrayValue) GetSlice() []string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = d
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stringArrayValue) Type() string {
 | 
			
		||||
	return "stringArray"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/github.com/spf13/pflag/string_slice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/spf13/pflag/string_slice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -62,6 +62,20 @@ func (s *stringSliceValue) String() string {
 | 
			
		||||
	return "[" + str + "]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stringSliceValue) Append(val string) error {
 | 
			
		||||
	*s.value = append(*s.value, val)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stringSliceValue) Replace(val []string) error {
 | 
			
		||||
	*s.value = val
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stringSliceValue) GetSlice() []string {
 | 
			
		||||
	return *s.value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func stringSliceConv(sval string) (interface{}, error) {
 | 
			
		||||
	sval = sval[1 : len(sval)-1]
 | 
			
		||||
	// An empty string would cause a slice with one (empty) string
 | 
			
		||||
@@ -84,7 +98,7 @@ func (f *FlagSet) GetStringSlice(name string) ([]string, error) {
 | 
			
		||||
// The argument p points to a []string variable in which to store the value of the flag.
 | 
			
		||||
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
 | 
			
		||||
// For example:
 | 
			
		||||
//   --ss="v1,v2" -ss="v3"
 | 
			
		||||
//   --ss="v1,v2" --ss="v3"
 | 
			
		||||
// will result in
 | 
			
		||||
//   []string{"v1", "v2", "v3"}
 | 
			
		||||
func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
 | 
			
		||||
@@ -100,7 +114,7 @@ func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []s
 | 
			
		||||
// The argument p points to a []string variable in which to store the value of the flag.
 | 
			
		||||
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
 | 
			
		||||
// For example:
 | 
			
		||||
//   --ss="v1,v2" -ss="v3"
 | 
			
		||||
//   --ss="v1,v2" --ss="v3"
 | 
			
		||||
// will result in
 | 
			
		||||
//   []string{"v1", "v2", "v3"}
 | 
			
		||||
func StringSliceVar(p *[]string, name string, value []string, usage string) {
 | 
			
		||||
@@ -116,7 +130,7 @@ func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage
 | 
			
		||||
// The return value is the address of a []string variable that stores the value of the flag.
 | 
			
		||||
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
 | 
			
		||||
// For example:
 | 
			
		||||
//   --ss="v1,v2" -ss="v3"
 | 
			
		||||
//   --ss="v1,v2" --ss="v3"
 | 
			
		||||
// will result in
 | 
			
		||||
//   []string{"v1", "v2", "v3"}
 | 
			
		||||
func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
 | 
			
		||||
@@ -136,7 +150,7 @@ func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage str
 | 
			
		||||
// The return value is the address of a []string variable that stores the value of the flag.
 | 
			
		||||
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
 | 
			
		||||
// For example:
 | 
			
		||||
//   --ss="v1,v2" -ss="v3"
 | 
			
		||||
//   --ss="v1,v2" --ss="v3"
 | 
			
		||||
// will result in
 | 
			
		||||
//   []string{"v1", "v2", "v3"}
 | 
			
		||||
func StringSlice(name string, value []string, usage string) *[]string {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										149
									
								
								vendor/github.com/spf13/pflag/string_to_int64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								vendor/github.com/spf13/pflag/string_to_int64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
			
		||||
package pflag
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// -- stringToInt64 Value
 | 
			
		||||
type stringToInt64Value struct {
 | 
			
		||||
	value   *map[string]int64
 | 
			
		||||
	changed bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newStringToInt64Value(val map[string]int64, p *map[string]int64) *stringToInt64Value {
 | 
			
		||||
	ssv := new(stringToInt64Value)
 | 
			
		||||
	ssv.value = p
 | 
			
		||||
	*ssv.value = val
 | 
			
		||||
	return ssv
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Format: a=1,b=2
 | 
			
		||||
func (s *stringToInt64Value) Set(val string) error {
 | 
			
		||||
	ss := strings.Split(val, ",")
 | 
			
		||||
	out := make(map[string]int64, len(ss))
 | 
			
		||||
	for _, pair := range ss {
 | 
			
		||||
		kv := strings.SplitN(pair, "=", 2)
 | 
			
		||||
		if len(kv) != 2 {
 | 
			
		||||
			return fmt.Errorf("%s must be formatted as key=value", pair)
 | 
			
		||||
		}
 | 
			
		||||
		var err error
 | 
			
		||||
		out[kv[0]], err = strconv.ParseInt(kv[1], 10, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !s.changed {
 | 
			
		||||
		*s.value = out
 | 
			
		||||
	} else {
 | 
			
		||||
		for k, v := range out {
 | 
			
		||||
			(*s.value)[k] = v
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	s.changed = true
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stringToInt64Value) Type() string {
 | 
			
		||||
	return "stringToInt64"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *stringToInt64Value) String() string {
 | 
			
		||||
	var buf bytes.Buffer
 | 
			
		||||
	i := 0
 | 
			
		||||
	for k, v := range *s.value {
 | 
			
		||||
		if i > 0 {
 | 
			
		||||
			buf.WriteRune(',')
 | 
			
		||||
		}
 | 
			
		||||
		buf.WriteString(k)
 | 
			
		||||
		buf.WriteRune('=')
 | 
			
		||||
		buf.WriteString(strconv.FormatInt(v, 10))
 | 
			
		||||
		i++
 | 
			
		||||
	}
 | 
			
		||||
	return "[" + buf.String() + "]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func stringToInt64Conv(val string) (interface{}, error) {
 | 
			
		||||
	val = strings.Trim(val, "[]")
 | 
			
		||||
	// An empty string would cause an empty map
 | 
			
		||||
	if len(val) == 0 {
 | 
			
		||||
		return map[string]int64{}, nil
 | 
			
		||||
	}
 | 
			
		||||
	ss := strings.Split(val, ",")
 | 
			
		||||
	out := make(map[string]int64, len(ss))
 | 
			
		||||
	for _, pair := range ss {
 | 
			
		||||
		kv := strings.SplitN(pair, "=", 2)
 | 
			
		||||
		if len(kv) != 2 {
 | 
			
		||||
			return nil, fmt.Errorf("%s must be formatted as key=value", pair)
 | 
			
		||||
		}
 | 
			
		||||
		var err error
 | 
			
		||||
		out[kv[0]], err = strconv.ParseInt(kv[1], 10, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetStringToInt64 return the map[string]int64 value of a flag with the given name
 | 
			
		||||
func (f *FlagSet) GetStringToInt64(name string) (map[string]int64, error) {
 | 
			
		||||
	val, err := f.getFlagType(name, "stringToInt64", stringToInt64Conv)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return map[string]int64{}, err
 | 
			
		||||
	}
 | 
			
		||||
	return val.(map[string]int64), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringToInt64Var defines a string flag with specified name, default value, and usage string.
 | 
			
		||||
// The argument p point64s to a map[string]int64 variable in which to store the values of the multiple flags.
 | 
			
		||||
// The value of each argument will not try to be separated by comma
 | 
			
		||||
func (f *FlagSet) StringToInt64Var(p *map[string]int64, name string, value map[string]int64, usage string) {
 | 
			
		||||
	f.VarP(newStringToInt64Value(value, p), name, "", usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringToInt64VarP is like StringToInt64Var, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func (f *FlagSet) StringToInt64VarP(p *map[string]int64, name, shorthand string, value map[string]int64, usage string) {
 | 
			
		||||
	f.VarP(newStringToInt64Value(value, p), name, shorthand, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringToInt64Var defines a string flag with specified name, default value, and usage string.
 | 
			
		||||
// The argument p point64s to a map[string]int64 variable in which to store the value of the flag.
 | 
			
		||||
// The value of each argument will not try to be separated by comma
 | 
			
		||||
func StringToInt64Var(p *map[string]int64, name string, value map[string]int64, usage string) {
 | 
			
		||||
	CommandLine.VarP(newStringToInt64Value(value, p), name, "", usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringToInt64VarP is like StringToInt64Var, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func StringToInt64VarP(p *map[string]int64, name, shorthand string, value map[string]int64, usage string) {
 | 
			
		||||
	CommandLine.VarP(newStringToInt64Value(value, p), name, shorthand, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringToInt64 defines a string flag with specified name, default value, and usage string.
 | 
			
		||||
// The return value is the address of a map[string]int64 variable that stores the value of the flag.
 | 
			
		||||
// The value of each argument will not try to be separated by comma
 | 
			
		||||
func (f *FlagSet) StringToInt64(name string, value map[string]int64, usage string) *map[string]int64 {
 | 
			
		||||
	p := map[string]int64{}
 | 
			
		||||
	f.StringToInt64VarP(&p, name, "", value, usage)
 | 
			
		||||
	return &p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringToInt64P is like StringToInt64, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func (f *FlagSet) StringToInt64P(name, shorthand string, value map[string]int64, usage string) *map[string]int64 {
 | 
			
		||||
	p := map[string]int64{}
 | 
			
		||||
	f.StringToInt64VarP(&p, name, shorthand, value, usage)
 | 
			
		||||
	return &p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringToInt64 defines a string flag with specified name, default value, and usage string.
 | 
			
		||||
// The return value is the address of a map[string]int64 variable that stores the value of the flag.
 | 
			
		||||
// The value of each argument will not try to be separated by comma
 | 
			
		||||
func StringToInt64(name string, value map[string]int64, usage string) *map[string]int64 {
 | 
			
		||||
	return CommandLine.StringToInt64P(name, "", value, usage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StringToInt64P is like StringToInt64, but accepts a shorthand letter that can be used after a single dash.
 | 
			
		||||
func StringToInt64P(name, shorthand string, value map[string]int64, usage string) *map[string]int64 {
 | 
			
		||||
	return CommandLine.StringToInt64P(name, shorthand, value, usage)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								vendor/github.com/spf13/pflag/uint_slice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/spf13/pflag/uint_slice.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -50,6 +50,48 @@ func (s *uintSliceValue) String() string {
 | 
			
		||||
	return "[" + strings.Join(out, ",") + "]"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *uintSliceValue) fromString(val string) (uint, error) {
 | 
			
		||||
	t, err := strconv.ParseUint(val, 10, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return uint(t), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *uintSliceValue) toString(val uint) string {
 | 
			
		||||
	return fmt.Sprintf("%d", val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *uintSliceValue) Append(val string) error {
 | 
			
		||||
	i, err := s.fromString(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = append(*s.value, i)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *uintSliceValue) Replace(val []string) error {
 | 
			
		||||
	out := make([]uint, len(val))
 | 
			
		||||
	for i, d := range val {
 | 
			
		||||
		var err error
 | 
			
		||||
		out[i], err = s.fromString(d)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*s.value = out
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *uintSliceValue) GetSlice() []string {
 | 
			
		||||
	out := make([]string, len(*s.value))
 | 
			
		||||
	for i, d := range *s.value {
 | 
			
		||||
		out[i] = s.toString(d)
 | 
			
		||||
	}
 | 
			
		||||
	return out
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func uintSliceConv(val string) (interface{}, error) {
 | 
			
		||||
	val = strings.Trim(val, "[]")
 | 
			
		||||
	// Empty string would cause a slice with one (empty) entry
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								vendor/gopkg.in/testfixtures.v2/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/gopkg.in/testfixtures.v2/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,26 +0,0 @@
 | 
			
		||||
language: go
 | 
			
		||||
 | 
			
		||||
go:
 | 
			
		||||
  - '1.9'
 | 
			
		||||
  - '1.10'
 | 
			
		||||
 | 
			
		||||
services:
 | 
			
		||||
  - postgresql
 | 
			
		||||
  - mysql
 | 
			
		||||
 | 
			
		||||
addons:
 | 
			
		||||
  postgresql: "9.4"
 | 
			
		||||
 | 
			
		||||
before_script:
 | 
			
		||||
  - mysql -e 'CREATE DATABASE testfixtures_test;'
 | 
			
		||||
  - psql -c 'CREATE DATABASE testfixtures_test;' -U postgres
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
  - go get -t -tags 'sqlite postgresql mysql' ./...
 | 
			
		||||
  - curl -s https://raw.githubusercontent.com/go-task/task/master/install-task.sh | sh
 | 
			
		||||
  - bin/task dl-deps
 | 
			
		||||
  - cp .sample.env .env
 | 
			
		||||
 | 
			
		||||
script:
 | 
			
		||||
  - bin/task lint
 | 
			
		||||
  - bin/task test-free
 | 
			
		||||
							
								
								
									
										358
									
								
								vendor/gopkg.in/testfixtures.v2/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										358
									
								
								vendor/gopkg.in/testfixtures.v2/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,358 +0,0 @@
 | 
			
		||||
# Go Test Fixtures
 | 
			
		||||
 | 
			
		||||
[](https://godoc.org/gopkg.in/testfixtures.v2)
 | 
			
		||||
[](https://goreportcard.com/report/github.com/go-testfixtures/testfixtures)
 | 
			
		||||
[](https://travis-ci.org/go-testfixtures/testfixtures)
 | 
			
		||||
[](https://ci.appveyor.com/project/andreynering/testfixtures)
 | 
			
		||||
 | 
			
		||||
> ***Warning***: this package will wipe the database data before loading the
 | 
			
		||||
fixtures! It is supposed to be used on a test database. Please, double check
 | 
			
		||||
if you are running it against the correct database.
 | 
			
		||||
 | 
			
		||||
Writing tests is hard, even more when you have to deal with an SQL database.
 | 
			
		||||
This package aims to make writing functional tests for web apps written in
 | 
			
		||||
Go easier.
 | 
			
		||||
 | 
			
		||||
Basically this package mimics the ["Rails' way"][railstests] of writing tests
 | 
			
		||||
for database applications, where sample data is kept in fixtures files. Before
 | 
			
		||||
the execution of every test, the test database is cleaned and the fixture data
 | 
			
		||||
is loaded into the database.
 | 
			
		||||
 | 
			
		||||
The idea is running tests against a real database, instead of relying in mocks,
 | 
			
		||||
which is boring to setup and may lead to production bugs not being caught in
 | 
			
		||||
the tests.
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
 | 
			
		||||
First, get it:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
go get -u -v gopkg.in/testfixtures.v2
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
Create a folder for the fixture files. Each file should contain data for a
 | 
			
		||||
single table and have the name `<table_name>.yml`:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
myapp/
 | 
			
		||||
  myapp.go
 | 
			
		||||
  myapp_test.go
 | 
			
		||||
  ...
 | 
			
		||||
  fixtures/
 | 
			
		||||
    posts.yml
 | 
			
		||||
    comments.yml
 | 
			
		||||
    tags.yml
 | 
			
		||||
    posts_tags.yml
 | 
			
		||||
    ...
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The file would look like this (it can have as many record you want):
 | 
			
		||||
 | 
			
		||||
```yml
 | 
			
		||||
# comments.yml
 | 
			
		||||
- id: 1
 | 
			
		||||
  post_id: 1
 | 
			
		||||
  content: A comment...
 | 
			
		||||
  author_name: John Doe
 | 
			
		||||
  author_email: john@doe.com
 | 
			
		||||
  created_at: 2016-01-01 12:30:12
 | 
			
		||||
  updated_at: 2016-01-01 12:30:12
 | 
			
		||||
 | 
			
		||||
- id: 2
 | 
			
		||||
  post_id: 2
 | 
			
		||||
  content: Another comment...
 | 
			
		||||
  author_name: John Doe
 | 
			
		||||
  author_email: john@doe.com
 | 
			
		||||
  created_at: 2016-01-01 12:30:12
 | 
			
		||||
  updated_at: 2016-01-01 12:30:12
 | 
			
		||||
 | 
			
		||||
# ...
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
An YAML object or array will be converted to JSON. It can be stored on a native
 | 
			
		||||
JSON type like JSONB on PostgreSQL or as a TEXT or VARCHAR column on other
 | 
			
		||||
databases.
 | 
			
		||||
 | 
			
		||||
```yml
 | 
			
		||||
- id: 1
 | 
			
		||||
  post_attributes:
 | 
			
		||||
    author: John Due
 | 
			
		||||
    author_email: john@due.com
 | 
			
		||||
    title: "..."
 | 
			
		||||
    tags:
 | 
			
		||||
      - programming
 | 
			
		||||
      - go
 | 
			
		||||
      - testing
 | 
			
		||||
    post: "..."
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
If you need to write raw SQL, probably to call a function, prefix the value
 | 
			
		||||
of the column with `RAW=`:
 | 
			
		||||
 | 
			
		||||
```yml
 | 
			
		||||
- id: 1
 | 
			
		||||
  uuid_column: RAW=uuid_generate_v4()
 | 
			
		||||
  postgis_type_column: RAW=ST_GeomFromText('params...')
 | 
			
		||||
  created_at: RAW=NOW()
 | 
			
		||||
  updated_at: RAW=NOW()
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Your tests would look like this:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
package myapp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
    "database/sql"
 | 
			
		||||
    "log"
 | 
			
		||||
 | 
			
		||||
    _ "github.com/lib/pq"
 | 
			
		||||
    "gopkg.in/testfixtures.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
    db *sql.DB
 | 
			
		||||
    fixtures *testfixtures.Context
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestMain(m *testing.M) {
 | 
			
		||||
    var err error
 | 
			
		||||
 | 
			
		||||
    // Open connection with the test database.
 | 
			
		||||
    // Do NOT import fixtures in a production database!
 | 
			
		||||
    // Existing data would be deleted
 | 
			
		||||
    db, err = sql.Open("postgres", "dbname=myapp_test")
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        log.Fatal(err)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // creating the context that hold the fixtures
 | 
			
		||||
    // see about all compatible databases in this page below
 | 
			
		||||
    fixtures, err = testfixtures.NewFolder(db, &testfixtures.PostgreSQL{}, "testdata/fixtures")
 | 
			
		||||
    if err != nil {
 | 
			
		||||
        log.Fatal(err)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    os.Exit(m.Run())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func prepareTestDatabase() {
 | 
			
		||||
    if err := fixtures.Load(); err != nil {
 | 
			
		||||
        log.Fatal(err)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestX(t *testing.T) {
 | 
			
		||||
    prepareTestDatabase()
 | 
			
		||||
    // your test here ...
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestY(t *testing.T) {
 | 
			
		||||
    prepareTestDatabase()
 | 
			
		||||
    // your test here ...
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestZ(t *testing.T) {
 | 
			
		||||
    prepareTestDatabase()
 | 
			
		||||
    // your test here ...
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Alternatively, you can use the `NewFiles` function, to specify which
 | 
			
		||||
files you want to load into the database:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
fixtures, err := testfixtures.NewFiles(db, &testfixtures.PostgreSQL{},
 | 
			
		||||
    "fixtures/orders.yml",
 | 
			
		||||
    "fixtures/customers.yml",
 | 
			
		||||
    // add as many files you want
 | 
			
		||||
)
 | 
			
		||||
if err != nil {
 | 
			
		||||
    log.Fatal(err)
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Security check
 | 
			
		||||
 | 
			
		||||
In order to prevent you from accidentally wiping the wrong database, this
 | 
			
		||||
package will refuse to load fixtures if the database name (or database
 | 
			
		||||
filename for SQLite) doesn't contains "test". If you want to disable this
 | 
			
		||||
check, use:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
testfixtures.SkipDatabaseNameCheck(true)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Sequences
 | 
			
		||||
 | 
			
		||||
For PostgreSQL or Oracle, this package also resets all sequences to a high
 | 
			
		||||
number to prevent duplicated primary keys while running the tests.
 | 
			
		||||
The default is 10000, but you can change that with:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
testfixtures.ResetSequencesTo(10000)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Compatible databases
 | 
			
		||||
 | 
			
		||||
### PostgreSQL
 | 
			
		||||
 | 
			
		||||
This package has two approaches to disable foreign keys while importing fixtures
 | 
			
		||||
in PostgreSQL databases:
 | 
			
		||||
 | 
			
		||||
#### With `DISABLE TRIGGER`
 | 
			
		||||
 | 
			
		||||
This is the default approach. For that use:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
&testfixtures.PostgreSQL{}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
With the above snippet this package will use `DISABLE TRIGGER` to temporarily
 | 
			
		||||
disabling foreign key constraints while loading fixtures. This work with any
 | 
			
		||||
version of PostgreSQL, but it is **required** to be connected in the database
 | 
			
		||||
as a SUPERUSER. You can make a PostgreSQL user a SUPERUSER with:
 | 
			
		||||
 | 
			
		||||
```sql
 | 
			
		||||
ALTER USER your_user SUPERUSER;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
#### With `ALTER CONSTRAINT`
 | 
			
		||||
 | 
			
		||||
This approach don't require to be connected as a SUPERUSER, but only work with
 | 
			
		||||
PostgreSQL versions >= 9.4. Try this if you are getting foreign key violation
 | 
			
		||||
errors with the previous approach. It is as simple as using:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
&testfixtures.PostgreSQL{UseAlterConstraint: true}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### MySQL / MariaDB
 | 
			
		||||
 | 
			
		||||
Just make sure the connection string have
 | 
			
		||||
[the multistatement parameter](https://github.com/go-sql-driver/mysql#multistatements)
 | 
			
		||||
set to true, and use:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
&testfixtures.MySQL{}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### SQLite
 | 
			
		||||
 | 
			
		||||
SQLite is also supported. It is recommended to create foreign keys as
 | 
			
		||||
`DEFERRABLE` (the default) to prevent problems. See more
 | 
			
		||||
[on the SQLite documentation](https://www.sqlite.org/foreignkeys.html#fk_deferred).
 | 
			
		||||
(Foreign key constraints are no-op by default on SQLite, but enabling it is
 | 
			
		||||
recommended).
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
&testfixtures.SQLite{}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Microsoft SQL Server
 | 
			
		||||
 | 
			
		||||
SQL Server support requires SQL Server >= 2008. Inserting on `IDENTITY` columns
 | 
			
		||||
are handled as well. Just make sure you are logged in with a user with
 | 
			
		||||
`ALTER TABLE` permission.
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
&testfixtures.SQLServer{}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Oracle
 | 
			
		||||
 | 
			
		||||
Oracle is supported as well. Use:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
&testfixtures.Oracle{}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Generating fixtures for a existing database (experimental)
 | 
			
		||||
 | 
			
		||||
The following code will generate a YAML file for each table of the database in
 | 
			
		||||
the given folder. It may be useful to boostrap a test scenario from a sample
 | 
			
		||||
database of your app.
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
err := testfixtures.GenerateFixtures(db, &testfixtures.PostgreSQL{}, "testdata/fixtures")
 | 
			
		||||
if err != nil {
 | 
			
		||||
    log.Fatalf("Error generating fixtures: %v", err)
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Or
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
err := testfixtures.GenerateFixturesForTables(
 | 
			
		||||
    db,
 | 
			
		||||
    []*TableInfo{
 | 
			
		||||
        &TableInfo{Name: "table_name", Where: "foo = 'bar'"},
 | 
			
		||||
        // ...
 | 
			
		||||
    },
 | 
			
		||||
    &testfixtures.PostgreSQL{},
 | 
			
		||||
    "testdata/fixtures",
 | 
			
		||||
)
 | 
			
		||||
if err != nil {
 | 
			
		||||
    log.Fatalf("Error generating fixtures: %v", err)
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
> This was thought to run in small sample databases. It will likely break
 | 
			
		||||
if run in a production/big database.
 | 
			
		||||
 | 
			
		||||
## Contributing
 | 
			
		||||
 | 
			
		||||
Tests were written to ensure everything work as expected. You can run the tests
 | 
			
		||||
with:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# running tests for PostgreSQL
 | 
			
		||||
go test -tags postgresql
 | 
			
		||||
 | 
			
		||||
# running test for MySQL
 | 
			
		||||
go test -tags mysql
 | 
			
		||||
 | 
			
		||||
# running tests for SQLite
 | 
			
		||||
go test -tags sqlite
 | 
			
		||||
 | 
			
		||||
# running tests for SQL Server
 | 
			
		||||
go test -tags sqlserver
 | 
			
		||||
 | 
			
		||||
# running tests for Oracle
 | 
			
		||||
go test -tags oracle
 | 
			
		||||
 | 
			
		||||
# running test for multiple databases at once
 | 
			
		||||
go test -tags 'sqlite postgresql mysql'
 | 
			
		||||
 | 
			
		||||
# running tests + benchmark
 | 
			
		||||
go test -v -bench=. -tags postgresql
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Travis runs tests for PostgreSQL, MySQL and SQLite. AppVeyor run for all
 | 
			
		||||
these and also Microsoft SQL Server.
 | 
			
		||||
 | 
			
		||||
To set the connection string of tests for each database, copy the `.sample.env`
 | 
			
		||||
file as `.env` and edit it according to your environment.
 | 
			
		||||
 | 
			
		||||
## Alternatives
 | 
			
		||||
 | 
			
		||||
If you don't think using fixtures is a good idea, you can try one of these
 | 
			
		||||
packages instead:
 | 
			
		||||
 | 
			
		||||
- [factory-go][factorygo]: Factory for Go. Inspired by Python's Factory Boy
 | 
			
		||||
and Ruby's Factory Girl
 | 
			
		||||
- [go-txdb (Single transaction SQL driver for Go)][gotxdb]: Use a single
 | 
			
		||||
database transaction for each functional test, so you can rollback to
 | 
			
		||||
previous state between tests to have the same database state in all tests
 | 
			
		||||
- [go-sqlmock][gosqlmock]: A mock for the sql.DB interface. This allow you to
 | 
			
		||||
unit test database code without having to connect to a real database
 | 
			
		||||
- [dbcleaner][dbcleaner] - Clean database for testing, inspired by
 | 
			
		||||
database_cleaner for Ruby
 | 
			
		||||
 | 
			
		||||
[railstests]: http://guides.rubyonrails.org/testing.html#the-test-database
 | 
			
		||||
[gotxdb]: https://github.com/DATA-DOG/go-txdb
 | 
			
		||||
[gosqlmock]: https://github.com/DATA-DOG/go-sqlmock
 | 
			
		||||
[factorygo]: https://github.com/bluele/factory-go
 | 
			
		||||
[dbcleaner]: https://github.com/khaiql/dbcleaner
 | 
			
		||||
							
								
								
									
										64
									
								
								vendor/gopkg.in/testfixtures.v2/Taskfile.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										64
									
								
								vendor/gopkg.in/testfixtures.v2/Taskfile.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,64 +0,0 @@
 | 
			
		||||
# github.com/go-task/task
 | 
			
		||||
 | 
			
		||||
version: '2'
 | 
			
		||||
 | 
			
		||||
tasks:
 | 
			
		||||
  dl-deps:
 | 
			
		||||
    desc: Download cli deps
 | 
			
		||||
    cmds:
 | 
			
		||||
      - go get -u github.com/golang/lint/golint
 | 
			
		||||
 | 
			
		||||
  lint:
 | 
			
		||||
    desc: Runs golint
 | 
			
		||||
    cmds:
 | 
			
		||||
      - golint .
 | 
			
		||||
 | 
			
		||||
  test-free:
 | 
			
		||||
    desc: Test free databases (PG, MySQL and SQLite)
 | 
			
		||||
    cmds:
 | 
			
		||||
      - task: test-pg
 | 
			
		||||
      - task: test-mysql
 | 
			
		||||
      - task: test-sqlite
 | 
			
		||||
 | 
			
		||||
  test-all:
 | 
			
		||||
    desc: Test all databases (PG, MySQL, SQLite, SQLServer and Oracle)
 | 
			
		||||
    cmds:
 | 
			
		||||
      - task: test-pg
 | 
			
		||||
      - task: test-mysql
 | 
			
		||||
      - task: test-sqlite
 | 
			
		||||
      - task: test-sqlserver
 | 
			
		||||
      - task: test-oracle
 | 
			
		||||
 | 
			
		||||
  test-pg:
 | 
			
		||||
    desc: Test PostgreSQL
 | 
			
		||||
    cmds:
 | 
			
		||||
      - task: test-db
 | 
			
		||||
        vars: {DATABASE: postgresql}
 | 
			
		||||
 | 
			
		||||
  test-mysql:
 | 
			
		||||
    desc: Test MySQL
 | 
			
		||||
    cmds:
 | 
			
		||||
      - task: test-db
 | 
			
		||||
        vars: {DATABASE: mysql}
 | 
			
		||||
 | 
			
		||||
  test-sqlite:
 | 
			
		||||
    desc: Test SQLite
 | 
			
		||||
    cmds:
 | 
			
		||||
      - task: test-db
 | 
			
		||||
        vars: {DATABASE: sqlite}
 | 
			
		||||
 | 
			
		||||
  test-sqlserver:
 | 
			
		||||
    desc: Test SQLServer
 | 
			
		||||
    cmds:
 | 
			
		||||
      - task: test-db
 | 
			
		||||
        vars: {DATABASE: sqlserver}
 | 
			
		||||
 | 
			
		||||
  test-oracle:
 | 
			
		||||
    desc: Test Oracle
 | 
			
		||||
    cmds:
 | 
			
		||||
      - task: test-db
 | 
			
		||||
        vars: {DATABASE: oracle}
 | 
			
		||||
 | 
			
		||||
  test-db:
 | 
			
		||||
    cmds:
 | 
			
		||||
      - go test -v -tags {{.DATABASE}}
 | 
			
		||||
							
								
								
									
										51
									
								
								vendor/gopkg.in/testfixtures.v2/appveyor.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										51
									
								
								vendor/gopkg.in/testfixtures.v2/appveyor.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,51 +0,0 @@
 | 
			
		||||
version: '{build}'
 | 
			
		||||
 | 
			
		||||
clone_folder: C:\GOPATH\src\gopkg.in\testfixtures.v2
 | 
			
		||||
 | 
			
		||||
build: false
 | 
			
		||||
deploy: false
 | 
			
		||||
 | 
			
		||||
services:
 | 
			
		||||
  - postgresql96
 | 
			
		||||
  - mysql
 | 
			
		||||
  - mssql2017
 | 
			
		||||
 | 
			
		||||
environment:
 | 
			
		||||
  POSTGRES_PATH: C:\Program Files\PostgreSQL\9.6
 | 
			
		||||
  PGUSER: postgres
 | 
			
		||||
  PGPASSWORD: Password12!
 | 
			
		||||
  PG_CONN_STRING: 'user=postgres password=Password12! dbname=testfixtures_test sslmode=disable'
 | 
			
		||||
 | 
			
		||||
  MYSQL_PATH: C:\Program Files\MySql\MySQL Server 5.7
 | 
			
		||||
  MYSQL_PWD: Password12!
 | 
			
		||||
  MYSQL_CONN_STRING: 'root:Password12!@/testfixtures_test?multiStatements=true'
 | 
			
		||||
 | 
			
		||||
  SQLITE_CONN_STRING: 'testdb.sqlite3'
 | 
			
		||||
 | 
			
		||||
  SQLSERVER_CONN_STRING: 'server=localhost;database=testfixtures_test;user id=sa;password=Password12!;encrypt=disable'
 | 
			
		||||
 | 
			
		||||
  MINGW_PATH: C:\MinGW
 | 
			
		||||
 | 
			
		||||
  GOPATH: C:\GOPATH
 | 
			
		||||
  GOVERSION: 1.10.3
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
  - SET PATH=%POSTGRES_PATH%\bin;%MYSQL_PATH%\bin;%MINGW_PATH%\bin;%PATH%
 | 
			
		||||
 | 
			
		||||
  - rmdir C:\go /s /q
 | 
			
		||||
  - appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-386.msi
 | 
			
		||||
  - msiexec /i go%GOVERSION%.windows-386.msi /q
 | 
			
		||||
  - go version
 | 
			
		||||
 | 
			
		||||
build_script:
 | 
			
		||||
  - createdb testfixtures_test
 | 
			
		||||
  - mysql -e "CREATE DATABASE testfixtures_test;" --user=root
 | 
			
		||||
  - sqlcmd -S localhost,1433 -U sa -P Password12! -Q "CREATE DATABASE testfixtures_test" -d "master"
 | 
			
		||||
 | 
			
		||||
test_script:
 | 
			
		||||
  - go get -t -tags "sqlite postgresql mysql sqlserver" ./...
 | 
			
		||||
  - go install -v ./...
 | 
			
		||||
  - go test -v -tags postgresql
 | 
			
		||||
  - go test -v -tags mysql
 | 
			
		||||
  - go test -v -tags sqlserver
 | 
			
		||||
  - go test -v -tags sqlite
 | 
			
		||||
							
								
								
									
										75
									
								
								vendor/gopkg.in/testfixtures.v2/deprecated.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										75
									
								
								vendor/gopkg.in/testfixtures.v2/deprecated.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,75 +0,0 @@
 | 
			
		||||
package testfixtures
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type (
 | 
			
		||||
	// DataBaseHelper is the helper interface
 | 
			
		||||
	// Deprecated: Use Helper instead
 | 
			
		||||
	DataBaseHelper Helper
 | 
			
		||||
 | 
			
		||||
	// PostgreSQLHelper is the PostgreSQL helper
 | 
			
		||||
	// Deprecated: Use PostgreSQL{} instead
 | 
			
		||||
	PostgreSQLHelper struct {
 | 
			
		||||
		PostgreSQL
 | 
			
		||||
		UseAlterConstraint bool
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// MySQLHelper is the MySQL helper
 | 
			
		||||
	// Deprecated: Use MySQL{} instead
 | 
			
		||||
	MySQLHelper struct {
 | 
			
		||||
		MySQL
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// SQLiteHelper is the SQLite helper
 | 
			
		||||
	// Deprecated: Use SQLite{} instead
 | 
			
		||||
	SQLiteHelper struct {
 | 
			
		||||
		SQLite
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// SQLServerHelper is the SQLServer helper
 | 
			
		||||
	// Deprecated: Use SQLServer{} instead
 | 
			
		||||
	SQLServerHelper struct {
 | 
			
		||||
		SQLServer
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// OracleHelper is the Oracle helper
 | 
			
		||||
	// Deprecated: Use Oracle{} instead
 | 
			
		||||
	OracleHelper struct {
 | 
			
		||||
		Oracle
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (h *PostgreSQLHelper) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) error {
 | 
			
		||||
	h.PostgreSQL.UseAlterConstraint = h.UseAlterConstraint
 | 
			
		||||
	return h.PostgreSQL.disableReferentialIntegrity(db, loadFn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadFixtureFiles load all specified fixtures files into database:
 | 
			
		||||
// 		LoadFixtureFiles(db, &PostgreSQL{},
 | 
			
		||||
// 			"fixtures/customers.yml", "fixtures/orders.yml")
 | 
			
		||||
//			// add as many files you want
 | 
			
		||||
//
 | 
			
		||||
// Deprecated: Use NewFiles() and Load() instead.
 | 
			
		||||
func LoadFixtureFiles(db *sql.DB, helper Helper, files ...string) error {
 | 
			
		||||
	c, err := NewFiles(db, helper, files...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.Load()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadFixtures loads all fixtures in a given folder into the database:
 | 
			
		||||
// 		LoadFixtures("myfixturesfolder", db, &PostgreSQL{})
 | 
			
		||||
//
 | 
			
		||||
// Deprecated: Use NewFolder() and Load() instead.
 | 
			
		||||
func LoadFixtures(folderName string, db *sql.DB, helper Helper) error {
 | 
			
		||||
	c, err := NewFolder(db, helper, folderName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.Load()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								vendor/gopkg.in/testfixtures.v2/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										41
									
								
								vendor/gopkg.in/testfixtures.v2/errors.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,41 +0,0 @@
 | 
			
		||||
package testfixtures
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// ErrWrongCastNotAMap is returned when a map is not a map[interface{}]interface{}
 | 
			
		||||
	ErrWrongCastNotAMap = errors.New("Could not cast record: not a map[interface{}]interface{}")
 | 
			
		||||
 | 
			
		||||
	// ErrFileIsNotSliceOrMap is returned the the fixture file is not a slice or map.
 | 
			
		||||
	ErrFileIsNotSliceOrMap = errors.New("The fixture file is not a slice or map")
 | 
			
		||||
 | 
			
		||||
	// ErrKeyIsNotString is returned when a record is not of type string
 | 
			
		||||
	ErrKeyIsNotString = errors.New("Record map key is not string")
 | 
			
		||||
 | 
			
		||||
	// ErrNotTestDatabase is returned when the database name doesn't contains "test"
 | 
			
		||||
	ErrNotTestDatabase = errors.New(`Loading aborted because the database name does not contains "test"`)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// InsertError will be returned if any error happens on database while
 | 
			
		||||
// inserting the record
 | 
			
		||||
type InsertError struct {
 | 
			
		||||
	Err    error
 | 
			
		||||
	File   string
 | 
			
		||||
	Index  int
 | 
			
		||||
	SQL    string
 | 
			
		||||
	Params []interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *InsertError) Error() string {
 | 
			
		||||
	return fmt.Sprintf(
 | 
			
		||||
		"testfixtures: error inserting record: %v, on file: %s, index: %d, sql: %s, params: %v",
 | 
			
		||||
		e.Err,
 | 
			
		||||
		e.File,
 | 
			
		||||
		e.Index,
 | 
			
		||||
		e.SQL,
 | 
			
		||||
		e.Params,
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										110
									
								
								vendor/gopkg.in/testfixtures.v2/generate.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										110
									
								
								vendor/gopkg.in/testfixtures.v2/generate.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,110 +0,0 @@
 | 
			
		||||
package testfixtures
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path"
 | 
			
		||||
	"unicode/utf8"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/yaml.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TableInfo is settings for generating a fixture for table.
 | 
			
		||||
type TableInfo struct {
 | 
			
		||||
	Name  string // Table name
 | 
			
		||||
	Where string // A condition for extracting records. If this value is empty, extracts all records.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ti *TableInfo) whereClause() string {
 | 
			
		||||
	if ti.Where == "" {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf(" WHERE %s", ti.Where)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GenerateFixtures generates fixtures for the current contents of a database, and saves
 | 
			
		||||
// them to the specified directory
 | 
			
		||||
func GenerateFixtures(db *sql.DB, helper Helper, dir string) error {
 | 
			
		||||
	tables, err := helper.tableNames(db)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	for _, table := range tables {
 | 
			
		||||
		filename := path.Join(dir, table+".yml")
 | 
			
		||||
		if err := generateFixturesForTable(db, helper, &TableInfo{Name: table}, filename); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GenerateFixturesForTables generates fixtures for the current contents of specified tables in a database, and saves
 | 
			
		||||
// them to the specified directory
 | 
			
		||||
func GenerateFixturesForTables(db *sql.DB, tables []*TableInfo, helper Helper, dir string) error {
 | 
			
		||||
	for _, table := range tables {
 | 
			
		||||
		filename := path.Join(dir, table.Name+".yml")
 | 
			
		||||
		if err := generateFixturesForTable(db, helper, table, filename); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func generateFixturesForTable(db *sql.DB, h Helper, table *TableInfo, filename string) error {
 | 
			
		||||
	query := fmt.Sprintf("SELECT * FROM %s%s", h.quoteKeyword(table.Name), table.whereClause())
 | 
			
		||||
	rows, err := db.Query(query)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer rows.Close()
 | 
			
		||||
 | 
			
		||||
	columns, err := rows.Columns()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fixtures := make([]interface{}, 0, 10)
 | 
			
		||||
	for rows.Next() {
 | 
			
		||||
		entries := make([]interface{}, len(columns))
 | 
			
		||||
		entryPtrs := make([]interface{}, len(entries))
 | 
			
		||||
		for i := range entries {
 | 
			
		||||
			entryPtrs[i] = &entries[i]
 | 
			
		||||
		}
 | 
			
		||||
		if err := rows.Scan(entryPtrs...); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		entryMap := make(map[string]interface{}, len(entries))
 | 
			
		||||
		for i, column := range columns {
 | 
			
		||||
			entryMap[column] = convertValue(entries[i])
 | 
			
		||||
		}
 | 
			
		||||
		fixtures = append(fixtures, entryMap)
 | 
			
		||||
	}
 | 
			
		||||
	if err = rows.Err(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f, err := os.Create(filename)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer f.Close()
 | 
			
		||||
 | 
			
		||||
	marshaled, err := yaml.Marshal(fixtures)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	_, err = f.Write(marshaled)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func convertValue(value interface{}) interface{} {
 | 
			
		||||
	switch v := value.(type) {
 | 
			
		||||
	case []byte:
 | 
			
		||||
		if utf8.Valid(v) {
 | 
			
		||||
			return string(v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return value
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								vendor/gopkg.in/testfixtures.v2/options.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								vendor/gopkg.in/testfixtures.v2/options.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,19 +0,0 @@
 | 
			
		||||
package testfixtures
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	skipDatabaseNameCheck bool
 | 
			
		||||
	resetSequencesTo      int64 = 10000
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// SkipDatabaseNameCheck If true, loading fixtures will not check if the database
 | 
			
		||||
// name constaint "test". Use with caution!
 | 
			
		||||
func SkipDatabaseNameCheck(value bool) {
 | 
			
		||||
	skipDatabaseNameCheck = value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResetSequencesTo sets the value the sequences will be reset to.
 | 
			
		||||
// This is used by PostgreSQL and Oracle.
 | 
			
		||||
// Defaults to 10000.
 | 
			
		||||
func ResetSequencesTo(value int64) {
 | 
			
		||||
	resetSequencesTo = value
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										171
									
								
								vendor/gopkg.in/testfixtures.v2/oracle.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										171
									
								
								vendor/gopkg.in/testfixtures.v2/oracle.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,171 +0,0 @@
 | 
			
		||||
package testfixtures
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Oracle is the Oracle database helper for this package
 | 
			
		||||
type Oracle struct {
 | 
			
		||||
	baseHelper
 | 
			
		||||
 | 
			
		||||
	enabledConstraints []oracleConstraint
 | 
			
		||||
	sequences          []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type oracleConstraint struct {
 | 
			
		||||
	tableName      string
 | 
			
		||||
	constraintName string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *Oracle) init(db *sql.DB) error {
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	h.enabledConstraints, err = h.getEnabledConstraints(db)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	h.sequences, err = h.getSequences(db)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*Oracle) paramType() int {
 | 
			
		||||
	return paramTypeColon
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*Oracle) quoteKeyword(str string) string {
 | 
			
		||||
	return fmt.Sprintf("\"%s\"", strings.ToUpper(str))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*Oracle) databaseName(q queryable) (string, error) {
 | 
			
		||||
	var dbName string
 | 
			
		||||
	err := q.QueryRow("SELECT user FROM DUAL").Scan(&dbName)
 | 
			
		||||
	return dbName, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*Oracle) tableNames(q queryable) ([]string, error) {
 | 
			
		||||
	query := `
 | 
			
		||||
		SELECT TABLE_NAME
 | 
			
		||||
		FROM USER_TABLES
 | 
			
		||||
	`
 | 
			
		||||
	rows, err := q.Query(query)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer rows.Close()
 | 
			
		||||
 | 
			
		||||
	var tables []string
 | 
			
		||||
	for rows.Next() {
 | 
			
		||||
		var table string
 | 
			
		||||
		if err = rows.Scan(&table); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		tables = append(tables, table)
 | 
			
		||||
	}
 | 
			
		||||
	if err = rows.Err(); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return tables, nil
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*Oracle) getEnabledConstraints(q queryable) ([]oracleConstraint, error) {
 | 
			
		||||
	var constraints []oracleConstraint
 | 
			
		||||
	rows, err := q.Query(`
 | 
			
		||||
		SELECT table_name, constraint_name
 | 
			
		||||
		FROM user_constraints
 | 
			
		||||
		WHERE constraint_type = 'R'
 | 
			
		||||
		  AND status = 'ENABLED'
 | 
			
		||||
	`)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer rows.Close()
 | 
			
		||||
 | 
			
		||||
	for rows.Next() {
 | 
			
		||||
		var constraint oracleConstraint
 | 
			
		||||
		rows.Scan(&constraint.tableName, &constraint.constraintName)
 | 
			
		||||
		constraints = append(constraints, constraint)
 | 
			
		||||
	}
 | 
			
		||||
	if err = rows.Err(); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return constraints, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (*Oracle) getSequences(q queryable) ([]string, error) {
 | 
			
		||||
	var sequences []string
 | 
			
		||||
	rows, err := q.Query("SELECT sequence_name FROM user_sequences")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer rows.Close()
 | 
			
		||||
 | 
			
		||||
	for rows.Next() {
 | 
			
		||||
		var sequence string
 | 
			
		||||
		if err = rows.Scan(&sequence); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		sequences = append(sequences, sequence)
 | 
			
		||||
	}
 | 
			
		||||
	if err = rows.Err(); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return sequences, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *Oracle) resetSequences(q queryable) error {
 | 
			
		||||
	for _, sequence := range h.sequences {
 | 
			
		||||
		_, err := q.Exec(fmt.Sprintf("DROP SEQUENCE %s", h.quoteKeyword(sequence)))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		_, err = q.Exec(fmt.Sprintf("CREATE SEQUENCE %s START WITH %d", h.quoteKeyword(sequence), resetSequencesTo))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *Oracle) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (err error) {
 | 
			
		||||
	// re-enable after load
 | 
			
		||||
	defer func() {
 | 
			
		||||
		for _, c := range h.enabledConstraints {
 | 
			
		||||
			_, err2 := db.Exec(fmt.Sprintf("ALTER TABLE %s ENABLE CONSTRAINT %s", h.quoteKeyword(c.tableName), h.quoteKeyword(c.constraintName)))
 | 
			
		||||
			if err2 != nil && err == nil {
 | 
			
		||||
				err = err2
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	// disable foreign keys
 | 
			
		||||
	for _, c := range h.enabledConstraints {
 | 
			
		||||
		_, err := db.Exec(fmt.Sprintf("ALTER TABLE %s DISABLE CONSTRAINT %s", h.quoteKeyword(c.tableName), h.quoteKeyword(c.constraintName)))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tx, err := db.Begin()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer tx.Rollback()
 | 
			
		||||
 | 
			
		||||
	if err = loadFn(tx); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = tx.Commit(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return h.resetSequences(db)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										305
									
								
								vendor/gopkg.in/testfixtures.v2/testfixtures.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										305
									
								
								vendor/gopkg.in/testfixtures.v2/testfixtures.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,305 +0,0 @@
 | 
			
		||||
package testfixtures
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"path"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/yaml.v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Context holds the fixtures to be loaded in the database.
 | 
			
		||||
type Context struct {
 | 
			
		||||
	db            *sql.DB
 | 
			
		||||
	helper        Helper
 | 
			
		||||
	fixturesFiles []*fixtureFile
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type fixtureFile struct {
 | 
			
		||||
	path       string
 | 
			
		||||
	fileName   string
 | 
			
		||||
	content    []byte
 | 
			
		||||
	insertSQLs []insertSQL
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type insertSQL struct {
 | 
			
		||||
	sql    string
 | 
			
		||||
	params []interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	dbnameRegexp = regexp.MustCompile("(?i)test")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewFolder creates a context for all fixtures in a given folder into the database:
 | 
			
		||||
//     NewFolder(db, &PostgreSQL{}, "my/fixtures/folder")
 | 
			
		||||
func NewFolder(db *sql.DB, helper Helper, folderName string) (*Context, error) {
 | 
			
		||||
	fixtures, err := fixturesFromFolder(folderName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c, err := newContext(db, helper, fixtures)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewFiles creates a context for all specified fixtures files into database:
 | 
			
		||||
//     NewFiles(db, &PostgreSQL{},
 | 
			
		||||
//         "fixtures/customers.yml",
 | 
			
		||||
//         "fixtures/orders.yml"
 | 
			
		||||
//         // add as many files you want
 | 
			
		||||
//     )
 | 
			
		||||
func NewFiles(db *sql.DB, helper Helper, fileNames ...string) (*Context, error) {
 | 
			
		||||
	fixtures, err := fixturesFromFiles(fileNames...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c, err := newContext(db, helper, fixtures)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newContext(db *sql.DB, helper Helper, fixtures []*fixtureFile) (*Context, error) {
 | 
			
		||||
	c := &Context{
 | 
			
		||||
		db:            db,
 | 
			
		||||
		helper:        helper,
 | 
			
		||||
		fixturesFiles: fixtures,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := c.helper.init(c.db); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := c.buildInsertSQLs(); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DetectTestDatabase returns nil if databaseName matches regexp
 | 
			
		||||
//     if err := fixtures.DetectTestDatabase(); err != nil {
 | 
			
		||||
//         log.Fatal(err)
 | 
			
		||||
//     }
 | 
			
		||||
func (c *Context) DetectTestDatabase() error {
 | 
			
		||||
	dbName, err := c.helper.databaseName(c.db)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if !dbnameRegexp.MatchString(dbName) {
 | 
			
		||||
		return ErrNotTestDatabase
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Load wipes and after load all fixtures in the database.
 | 
			
		||||
//     if err := fixtures.Load(); err != nil {
 | 
			
		||||
//         log.Fatal(err)
 | 
			
		||||
//     }
 | 
			
		||||
func (c *Context) Load() error {
 | 
			
		||||
	if !skipDatabaseNameCheck {
 | 
			
		||||
		if err := c.DetectTestDatabase(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := c.helper.disableReferentialIntegrity(c.db, func(tx *sql.Tx) error {
 | 
			
		||||
		for _, file := range c.fixturesFiles {
 | 
			
		||||
			modified, err := c.helper.isTableModified(tx, file.fileNameWithoutExtension())
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			if !modified {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if err := file.delete(tx, c.helper); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			err = c.helper.whileInsertOnTable(tx, file.fileNameWithoutExtension(), func() error {
 | 
			
		||||
				for j, i := range file.insertSQLs {
 | 
			
		||||
					if _, err := tx.Exec(i.sql, i.params...); err != nil {
 | 
			
		||||
						return &InsertError{
 | 
			
		||||
							Err:    err,
 | 
			
		||||
							File:   file.fileName,
 | 
			
		||||
							Index:  j,
 | 
			
		||||
							SQL:    i.sql,
 | 
			
		||||
							Params: i.params,
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				return nil
 | 
			
		||||
			})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return c.helper.afterLoad(c.db)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Context) buildInsertSQLs() error {
 | 
			
		||||
	for _, f := range c.fixturesFiles {
 | 
			
		||||
		var records interface{}
 | 
			
		||||
		if err := yaml.Unmarshal(f.content, &records); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch records := records.(type) {
 | 
			
		||||
		case []interface{}:
 | 
			
		||||
			for _, record := range records {
 | 
			
		||||
				recordMap, ok := record.(map[interface{}]interface{})
 | 
			
		||||
				if !ok {
 | 
			
		||||
					return ErrWrongCastNotAMap
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				sql, values, err := f.buildInsertSQL(c.helper, recordMap)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				f.insertSQLs = append(f.insertSQLs, insertSQL{sql, values})
 | 
			
		||||
			}
 | 
			
		||||
		case map[interface{}]interface{}:
 | 
			
		||||
			for _, record := range records {
 | 
			
		||||
				recordMap, ok := record.(map[interface{}]interface{})
 | 
			
		||||
				if !ok {
 | 
			
		||||
					return ErrWrongCastNotAMap
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				sql, values, err := f.buildInsertSQL(c.helper, recordMap)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				f.insertSQLs = append(f.insertSQLs, insertSQL{sql, values})
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			return ErrFileIsNotSliceOrMap
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *fixtureFile) fileNameWithoutExtension() string {
 | 
			
		||||
	return strings.Replace(f.fileName, filepath.Ext(f.fileName), "", 1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *fixtureFile) delete(tx *sql.Tx, h Helper) error {
 | 
			
		||||
	_, err := tx.Exec(fmt.Sprintf("DELETE FROM %s", h.quoteKeyword(f.fileNameWithoutExtension())))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *fixtureFile) buildInsertSQL(h Helper, record map[interface{}]interface{}) (sqlStr string, values []interface{}, err error) {
 | 
			
		||||
	var (
 | 
			
		||||
		sqlColumns []string
 | 
			
		||||
		sqlValues  []string
 | 
			
		||||
		i          = 1
 | 
			
		||||
	)
 | 
			
		||||
	for key, value := range record {
 | 
			
		||||
		keyStr, ok := key.(string)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			err = ErrKeyIsNotString
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sqlColumns = append(sqlColumns, h.quoteKeyword(keyStr))
 | 
			
		||||
 | 
			
		||||
		// if string, try convert to SQL or time
 | 
			
		||||
		// if map or array, convert to json
 | 
			
		||||
		switch v := value.(type) {
 | 
			
		||||
		case string:
 | 
			
		||||
			if strings.HasPrefix(v, "RAW=") {
 | 
			
		||||
				sqlValues = append(sqlValues, strings.TrimPrefix(v, "RAW="))
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if t, err := tryStrToDate(v); err == nil {
 | 
			
		||||
				value = t
 | 
			
		||||
			}
 | 
			
		||||
		case []interface{}, map[interface{}]interface{}:
 | 
			
		||||
			value = recursiveToJSON(v)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch h.paramType() {
 | 
			
		||||
		case paramTypeDollar:
 | 
			
		||||
			sqlValues = append(sqlValues, fmt.Sprintf("$%d", i))
 | 
			
		||||
		case paramTypeQuestion:
 | 
			
		||||
			sqlValues = append(sqlValues, "?")
 | 
			
		||||
		case paramTypeColon:
 | 
			
		||||
			sqlValues = append(sqlValues, fmt.Sprintf(":%d", i))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		values = append(values, value)
 | 
			
		||||
		i++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sqlStr = fmt.Sprintf(
 | 
			
		||||
		"INSERT INTO %s (%s) VALUES (%s)",
 | 
			
		||||
		h.quoteKeyword(f.fileNameWithoutExtension()),
 | 
			
		||||
		strings.Join(sqlColumns, ", "),
 | 
			
		||||
		strings.Join(sqlValues, ", "),
 | 
			
		||||
	)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fixturesFromFolder(folderName string) ([]*fixtureFile, error) {
 | 
			
		||||
	var files []*fixtureFile
 | 
			
		||||
	fileinfos, err := ioutil.ReadDir(folderName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, fileinfo := range fileinfos {
 | 
			
		||||
		if !fileinfo.IsDir() && filepath.Ext(fileinfo.Name()) == ".yml" {
 | 
			
		||||
			fixture := &fixtureFile{
 | 
			
		||||
				path:     path.Join(folderName, fileinfo.Name()),
 | 
			
		||||
				fileName: fileinfo.Name(),
 | 
			
		||||
			}
 | 
			
		||||
			fixture.content, err = ioutil.ReadFile(fixture.path)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			files = append(files, fixture)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return files, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fixturesFromFiles(fileNames ...string) ([]*fixtureFile, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		fixtureFiles []*fixtureFile
 | 
			
		||||
		err          error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	for _, f := range fileNames {
 | 
			
		||||
		fixture := &fixtureFile{
 | 
			
		||||
			path:     f,
 | 
			
		||||
			fileName: filepath.Base(f),
 | 
			
		||||
		}
 | 
			
		||||
		fixture.content, err = ioutil.ReadFile(fixture.path)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		fixtureFiles = append(fixtureFiles, fixture)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fixtureFiles, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								vendor/gopkg.in/testfixtures.v2/time.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								vendor/gopkg.in/testfixtures.v2/time.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,34 +0,0 @@
 | 
			
		||||
package testfixtures
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var timeFormats = []string{
 | 
			
		||||
	"2006-01-02",
 | 
			
		||||
	"2006-01-02 15:04",
 | 
			
		||||
	"2006-01-02 15:04:05",
 | 
			
		||||
	"20060102",
 | 
			
		||||
	"20060102 15:04",
 | 
			
		||||
	"20060102 15:04:05",
 | 
			
		||||
	"02/01/2006",
 | 
			
		||||
	"02/01/2006 15:04",
 | 
			
		||||
	"02/01/2006 15:04:05",
 | 
			
		||||
	"2006-01-02T15:04-07:00",
 | 
			
		||||
	"2006-01-02T15:04:05-07:00",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrCouldNotConvertToTime is returns when a string is not a reconizable time format
 | 
			
		||||
var ErrCouldNotConvertToTime = errors.New("Could not convert string to time")
 | 
			
		||||
 | 
			
		||||
func tryStrToDate(s string) (time.Time, error) {
 | 
			
		||||
	for _, f := range timeFormats {
 | 
			
		||||
		t, err := time.ParseInLocation(f, s, time.Local)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		return t, nil
 | 
			
		||||
	}
 | 
			
		||||
	return time.Time{}, ErrCouldNotConvertToTime
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/gopkg.in/yaml.v2/apic.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/gopkg.in/yaml.v2/apic.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -86,6 +86,7 @@ func yaml_emitter_initialize(emitter *yaml_emitter_t) {
 | 
			
		||||
		raw_buffer: make([]byte, 0, output_raw_buffer_size),
 | 
			
		||||
		states:     make([]yaml_emitter_state_t, 0, initial_stack_size),
 | 
			
		||||
		events:     make([]yaml_event_t, 0, initial_queue_size),
 | 
			
		||||
		best_width: -1,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							@@ -333,6 +333,9 @@ github.com/go-swagger/go-swagger/cmd/swagger/commands/initcmd
 | 
			
		||||
github.com/go-swagger/go-swagger/codescan
 | 
			
		||||
github.com/go-swagger/go-swagger/generator
 | 
			
		||||
github.com/go-swagger/go-swagger/scan
 | 
			
		||||
# github.com/go-testfixtures/testfixtures/v3 v3.2.0
 | 
			
		||||
## explicit
 | 
			
		||||
github.com/go-testfixtures/testfixtures/v3
 | 
			
		||||
# github.com/gobwas/glob v0.2.3
 | 
			
		||||
## explicit
 | 
			
		||||
github.com/gobwas/glob
 | 
			
		||||
@@ -410,8 +413,6 @@ github.com/jbenet/go-context/io
 | 
			
		||||
github.com/jessevdk/go-flags
 | 
			
		||||
# github.com/jmhodges/levigo v1.0.0
 | 
			
		||||
## explicit
 | 
			
		||||
# github.com/joho/godotenv v1.3.0
 | 
			
		||||
## explicit
 | 
			
		||||
# github.com/kballard/go-shellquote v0.0.0-20170619183022-cd60e84ee657
 | 
			
		||||
## explicit
 | 
			
		||||
github.com/kballard/go-shellquote
 | 
			
		||||
@@ -496,11 +497,9 @@ github.com/mattn/go-colorable
 | 
			
		||||
# github.com/mattn/go-isatty v0.0.11
 | 
			
		||||
## explicit
 | 
			
		||||
github.com/mattn/go-isatty
 | 
			
		||||
# github.com/mattn/go-oci8 v0.0.0-20190320171441-14ba190cf52d
 | 
			
		||||
## explicit
 | 
			
		||||
# github.com/mattn/go-runewidth v0.0.7
 | 
			
		||||
github.com/mattn/go-runewidth
 | 
			
		||||
# github.com/mattn/go-sqlite3 v1.11.0
 | 
			
		||||
# github.com/mattn/go-sqlite3 v2.0.2+incompatible
 | 
			
		||||
## explicit
 | 
			
		||||
github.com/mattn/go-sqlite3
 | 
			
		||||
# github.com/matttproud/golang_protobuf_extensions v1.0.1
 | 
			
		||||
@@ -613,7 +612,7 @@ github.com/spf13/afero/mem
 | 
			
		||||
github.com/spf13/cast
 | 
			
		||||
# github.com/spf13/jwalterweatherman v1.1.0
 | 
			
		||||
github.com/spf13/jwalterweatherman
 | 
			
		||||
# github.com/spf13/pflag v1.0.3
 | 
			
		||||
# github.com/spf13/pflag v1.0.5
 | 
			
		||||
github.com/spf13/pflag
 | 
			
		||||
# github.com/spf13/viper v1.4.0
 | 
			
		||||
github.com/spf13/viper
 | 
			
		||||
@@ -861,12 +860,9 @@ gopkg.in/ini.v1
 | 
			
		||||
# gopkg.in/ldap.v3 v3.0.2
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/ldap.v3
 | 
			
		||||
# gopkg.in/testfixtures.v2 v2.5.0
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/testfixtures.v2
 | 
			
		||||
# gopkg.in/warnings.v0 v0.1.2
 | 
			
		||||
gopkg.in/warnings.v0
 | 
			
		||||
# gopkg.in/yaml.v2 v2.2.8
 | 
			
		||||
# gopkg.in/yaml.v2 v2.3.0
 | 
			
		||||
## explicit
 | 
			
		||||
gopkg.in/yaml.v2
 | 
			
		||||
# mvdan.cc/xurls/v2 v2.1.0
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user