Add postgres support (#135)
Revert fixture fixes for postgres Use postgres connection string with spaces instead of url Fix label order Make postgres tests in ci less verbose Add sequence update script Skip resets in postgres Remove option to skip resets in postgres Make postgres tests in ci verboseq Update test fixtures database Fix file tests on postgres Add postgres options to sample config Make sure tests init test fixtures before running the actual tests Fix issues with IDs too big to fit in an int Fix duplicate auto incremented IDs Refactor / Fix team tests Refactor team member tests Fix team member create Fix label test Fix getting labels Fix test fixtures for postgresql Fix connection string params Disable ssl mode on postgres integration tests Disable ssl mode on postgres tests Use sprintf to create the connection string for postgresql fixup! Add postgres support Add postgres support Added generate as a make dependency for make build Clarify docs on building Co-authored-by: kolaente <k@knt.li> Co-authored-by: Jan Tojnar <jtojnar@gmail.com> Reviewed-on: https://kolaente.dev/vikunja/api/pulls/135
This commit is contained in:
15
vendor/gopkg.in/testfixtures.v2/.editorconfig
generated
vendored
15
vendor/gopkg.in/testfixtures.v2/.editorconfig
generated
vendored
@ -1,15 +0,0 @@
|
||||
# http://editorconfig.org/
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
||||
[*.{yml,md}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
1
vendor/gopkg.in/testfixtures.v2/.gitattributes
generated
vendored
1
vendor/gopkg.in/testfixtures.v2/.gitattributes
generated
vendored
@ -1 +0,0 @@
|
||||
* text eol=lf
|
29
vendor/gopkg.in/testfixtures.v2/.gitignore
generated
vendored
29
vendor/gopkg.in/testfixtures.v2/.gitignore
generated
vendored
@ -1,29 +0,0 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
|
||||
# SQLite databases
|
||||
*.sqlite3
|
||||
|
||||
.env
|
5
vendor/gopkg.in/testfixtures.v2/.sample.env
generated
vendored
5
vendor/gopkg.in/testfixtures.v2/.sample.env
generated
vendored
@ -1,5 +0,0 @@
|
||||
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"
|
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.10'
|
||||
- '1.11'
|
||||
|
||||
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
|
21
vendor/gopkg.in/testfixtures.v2/LICENSE
generated
vendored
21
vendor/gopkg.in/testfixtures.v2/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Andrey Nering
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
388
vendor/gopkg.in/testfixtures.v2/README.md
generated
vendored
388
vendor/gopkg.in/testfixtures.v2/README.md
generated
vendored
@ -1,388 +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}
|
||||
```
|
||||
|
||||
#### Skipping reset of sequences
|
||||
|
||||
You can skip the reset of PostgreSQL sequences if you're debugging a problem
|
||||
with it, but most of the time you shouldn't do it:
|
||||
|
||||
```go
|
||||
&testfixtures.PostgreSQL{SkipResetSequences: 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.
|
||||
|
||||
## 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.
|
||||
|
||||
See [#40](https://github.com/go-testfixtures/testfixtures/issues/40)
|
||||
and [golang/go#11521](https://github.com/golang/go/issues/11521) for more information.
|
||||
|
||||
We're also planning to implement transactional tests to allow running tests
|
||||
in parallel (see [#24](https://github.com/go-testfixtures/testfixtures/issues/24)).
|
||||
Running each test package in a separated database would also allow you to do that.
|
||||
Open issues for other ideas :slightly_smiling_face:.
|
||||
|
||||
## 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 @@
|
||||
# https://taskfile.org
|
||||
|
||||
version: '2'
|
||||
|
||||
tasks:
|
||||
dl-deps:
|
||||
desc: Download cli deps
|
||||
cmds:
|
||||
- go get -u golang.org/x/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.11.2
|
||||
|
||||
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
|
||||
}
|
17
vendor/gopkg.in/testfixtures.v2/go.mod
generated
vendored
17
vendor/gopkg.in/testfixtures.v2/go.mod
generated
vendored
@ -1,17 +0,0 @@
|
||||
module gopkg.in/testfixtures.v2
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.33.1 // indirect
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f
|
||||
github.com/go-sql-driver/mysql v1.4.1
|
||||
github.com/google/go-cmp v0.2.0 // indirect
|
||||
github.com/joho/godotenv v1.3.0
|
||||
github.com/lib/pq v1.0.0
|
||||
github.com/mattn/go-oci8 v0.0.0-20181115070430-6eefff3c767c
|
||||
github.com/mattn/go-sqlite3 v1.10.0
|
||||
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869 // indirect
|
||||
google.golang.org/appengine v1.3.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.2.1
|
||||
)
|
||||
|
||||
go 1.13
|
27
vendor/gopkg.in/testfixtures.v2/go.sum
generated
vendored
27
vendor/gopkg.in/testfixtures.v2/go.sum
generated
vendored
@ -1,27 +0,0 @@
|
||||
cloud.google.com/go v0.33.1 h1:fmJQWZ1w9PGkHR1YL/P7HloDvqlmKQ4Vpb7PC2e+aCk=
|
||||
cloud.google.com/go v0.33.1/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f h1:WH0w/R4Yoey+04HhFxqZ6VX6I0d7RMyw5aXQ9UTvQPs=
|
||||
github.com/denisenkom/go-mssqldb v0.0.0-20181014144952-4e0d7dc8888f/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
|
||||
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/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
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.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/mattn/go-oci8 v0.0.0-20181115070430-6eefff3c767c h1:RkC3vqmJwowDCqtL7d8cFEMNdoGHBcqoR4jKO9/mWuA=
|
||||
github.com/mattn/go-oci8 v0.0.0-20181115070430-6eefff3c767c/go.mod h1:/M9VLO+lUPmxvoOK2PfWRZ8mTtB4q1Hy9lEGijv9Nr8=
|
||||
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
|
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869 h1:kkXA53yGe04D0adEYJwEVQjeBppL01Exg+fnMjfUraU=
|
||||
golang.org/x/crypto v0.0.0-20181112202954-3d3f9f413869/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
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.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
73
vendor/gopkg.in/testfixtures.v2/helper.go
generated
vendored
73
vendor/gopkg.in/testfixtures.v2/helper.go
generated
vendored
@ -1,73 +0,0 @@
|
||||
package testfixtures
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
paramTypeDollar = iota + 1
|
||||
paramTypeQuestion
|
||||
paramTypeColon
|
||||
)
|
||||
|
||||
type loadFunction func(tx *sql.Tx) error
|
||||
|
||||
// Helper is the generic interface for the database helper
|
||||
type Helper interface {
|
||||
init(*sql.DB) error
|
||||
disableReferentialIntegrity(*sql.DB, loadFunction) error
|
||||
paramType() int
|
||||
databaseName(queryable) (string, error)
|
||||
tableNames(queryable) ([]string, error)
|
||||
isTableModified(queryable, string) (bool, error)
|
||||
afterLoad(queryable) error
|
||||
quoteKeyword(string) string
|
||||
whileInsertOnTable(*sql.Tx, string, func() error) error
|
||||
}
|
||||
|
||||
type queryable interface {
|
||||
Exec(string, ...interface{}) (sql.Result, error)
|
||||
Query(string, ...interface{}) (*sql.Rows, error)
|
||||
QueryRow(string, ...interface{}) *sql.Row
|
||||
}
|
||||
|
||||
// batchSplitter is an interface with method which returns byte slice for
|
||||
// splitting SQL batches. This need to split sql statements and run its
|
||||
// separately.
|
||||
//
|
||||
// For Microsoft SQL Server batch splitter is "GO". For details see
|
||||
// https://docs.microsoft.com/en-us/sql/t-sql/language-elements/sql-server-utilities-statements-go
|
||||
type batchSplitter interface {
|
||||
splitter() []byte
|
||||
}
|
||||
|
||||
var (
|
||||
_ Helper = &MySQL{}
|
||||
_ Helper = &PostgreSQL{}
|
||||
_ Helper = &SQLite{}
|
||||
_ Helper = &Oracle{}
|
||||
_ Helper = &SQLServer{}
|
||||
)
|
||||
|
||||
type baseHelper struct{}
|
||||
|
||||
func (baseHelper) init(_ *sql.DB) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (baseHelper) quoteKeyword(str string) string {
|
||||
return fmt.Sprintf(`"%s"`, str)
|
||||
}
|
||||
|
||||
func (baseHelper) whileInsertOnTable(_ *sql.Tx, _ string, fn func() error) error {
|
||||
return fn()
|
||||
}
|
||||
|
||||
func (baseHelper) isTableModified(_ queryable, _ string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (baseHelper) afterLoad(_ queryable) error {
|
||||
return nil
|
||||
}
|
44
vendor/gopkg.in/testfixtures.v2/json.go
generated
vendored
44
vendor/gopkg.in/testfixtures.v2/json.go
generated
vendored
@ -1,44 +0,0 @@
|
||||
package testfixtures
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
var (
|
||||
_ driver.Valuer = jsonArray{}
|
||||
_ driver.Valuer = jsonMap{}
|
||||
)
|
||||
|
||||
type jsonArray []interface{}
|
||||
|
||||
func (a jsonArray) Value() (driver.Value, error) {
|
||||
return json.Marshal(a)
|
||||
}
|
||||
|
||||
type jsonMap map[string]interface{}
|
||||
|
||||
func (m jsonMap) Value() (driver.Value, error) {
|
||||
return json.Marshal(m)
|
||||
}
|
||||
|
||||
// Go refuses to convert map[interface{}]interface{} to JSON because JSON only support string keys
|
||||
// So it's necessary to recursively convert all map[interface]interface{} to map[string]interface{}
|
||||
func recursiveToJSON(v interface{}) (r interface{}) {
|
||||
switch v := v.(type) {
|
||||
case []interface{}:
|
||||
for i, e := range v {
|
||||
v[i] = recursiveToJSON(e)
|
||||
}
|
||||
r = jsonArray(v)
|
||||
case map[interface{}]interface{}:
|
||||
newMap := make(map[string]interface{}, len(v))
|
||||
for k, e := range v {
|
||||
newMap[k.(string)] = recursiveToJSON(e)
|
||||
}
|
||||
r = jsonMap(newMap)
|
||||
default:
|
||||
r = v
|
||||
}
|
||||
return
|
||||
}
|
132
vendor/gopkg.in/testfixtures.v2/mysql.go
generated
vendored
132
vendor/gopkg.in/testfixtures.v2/mysql.go
generated
vendored
@ -1,132 +0,0 @@
|
||||
package testfixtures
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// MySQL is the MySQL helper for this package
|
||||
type MySQL struct {
|
||||
baseHelper
|
||||
tables []string
|
||||
tablesChecksum map[string]int64
|
||||
}
|
||||
|
||||
func (h *MySQL) init(db *sql.DB) error {
|
||||
var err error
|
||||
h.tables, err = h.tableNames(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*MySQL) paramType() int {
|
||||
return paramTypeQuestion
|
||||
}
|
||||
|
||||
func (*MySQL) quoteKeyword(str string) string {
|
||||
return fmt.Sprintf("`%s`", str)
|
||||
}
|
||||
|
||||
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) {
|
||||
query := `
|
||||
SELECT table_name
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = ?
|
||||
AND table_type = 'BASE TABLE';
|
||||
`
|
||||
dbName, err := h.databaseName(q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := q.Query(query, dbName)
|
||||
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 (h *MySQL) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (err error) {
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
if _, err = tx.Exec("SET FOREIGN_KEY_CHECKS = 0"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
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) {
|
||||
checksum, err := h.getChecksum(q, tableName)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
oldChecksum := h.tablesChecksum[tableName]
|
||||
|
||||
return oldChecksum == 0 || checksum != oldChecksum, nil
|
||||
}
|
||||
|
||||
func (h *MySQL) afterLoad(q queryable) error {
|
||||
if h.tablesChecksum != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
h.tablesChecksum = make(map[string]int64, len(h.tables))
|
||||
for _, t := range h.tables {
|
||||
checksum, err := h.getChecksum(q, t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.tablesChecksum[t] = checksum
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *MySQL) getChecksum(q queryable, tableName string) (int64, error) {
|
||||
sql := fmt.Sprintf("CHECKSUM TABLE %s", h.quoteKeyword(tableName))
|
||||
var (
|
||||
table string
|
||||
checksum int64
|
||||
)
|
||||
if err := q.QueryRow(sql).Scan(&table, &checksum); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return checksum, nil
|
||||
}
|
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)
|
||||
}
|
295
vendor/gopkg.in/testfixtures.v2/postgresql.go
generated
vendored
295
vendor/gopkg.in/testfixtures.v2/postgresql.go
generated
vendored
@ -1,295 +0,0 @@
|
||||
package testfixtures
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PostgreSQL is the PG helper for this package
|
||||
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
|
||||
|
||||
// SkipResetSequences prevents the reset of the databases
|
||||
// sequences after load fixtures time
|
||||
SkipResetSequences bool
|
||||
|
||||
tables []string
|
||||
sequences []string
|
||||
nonDeferrableConstraints []pgConstraint
|
||||
tablesChecksum map[string]string
|
||||
}
|
||||
|
||||
type pgConstraint struct {
|
||||
tableName string
|
||||
constraintName string
|
||||
}
|
||||
|
||||
func (h *PostgreSQL) init(db *sql.DB) error {
|
||||
var err error
|
||||
|
||||
h.tables, err = h.tableNames(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h.sequences, err = h.getSequences(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h.nonDeferrableConstraints, err = h.getNonDeferrableConstraints(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*PostgreSQL) paramType() int {
|
||||
return paramTypeDollar
|
||||
}
|
||||
|
||||
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) {
|
||||
var tables []string
|
||||
|
||||
sql := `
|
||||
SELECT pg_namespace.nspname || '.' || pg_class.relname
|
||||
FROM pg_class
|
||||
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%';
|
||||
`
|
||||
rows, err := q.Query(sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
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 (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'
|
||||
`
|
||||
|
||||
rows, err := q.Query(sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var sequences []string
|
||||
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 (*PostgreSQL) getNonDeferrableConstraints(q queryable) ([]pgConstraint, error) {
|
||||
var constraints []pgConstraint
|
||||
|
||||
sql := `
|
||||
SELECT table_schema || '.' || table_name, constraint_name
|
||||
FROM information_schema.table_constraints
|
||||
WHERE constraint_type = 'FOREIGN KEY'
|
||||
AND is_deferrable = 'NO'
|
||||
`
|
||||
rows, err := q.Query(sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var constraint pgConstraint
|
||||
if err = rows.Scan(&constraint.tableName, &constraint.constraintName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
constraints = append(constraints, constraint)
|
||||
}
|
||||
if err = rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return constraints, nil
|
||||
}
|
||||
|
||||
func (h *PostgreSQL) disableTriggers(db *sql.DB, loadFn loadFunction) (err error) {
|
||||
defer func() {
|
||||
// re-enable triggers after load
|
||||
var sql string
|
||||
for _, table := range h.tables {
|
||||
sql += fmt.Sprintf("ALTER TABLE %s ENABLE TRIGGER ALL;", h.quoteKeyword(table))
|
||||
}
|
||||
if _, err2 := db.Exec(sql); err2 != nil && err == nil {
|
||||
err = err2
|
||||
}
|
||||
}()
|
||||
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var sql string
|
||||
for _, table := range h.tables {
|
||||
sql += fmt.Sprintf("ALTER TABLE %s DISABLE TRIGGER ALL;", h.quoteKeyword(table))
|
||||
}
|
||||
if _, err = tx.Exec(sql); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = loadFn(tx); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (h *PostgreSQL) makeConstraintsDeferrable(db *sql.DB, loadFn loadFunction) (err error) {
|
||||
defer func() {
|
||||
// ensure constraint being not deferrable again after load
|
||||
var sql string
|
||||
for _, constraint := range h.nonDeferrableConstraints {
|
||||
sql += fmt.Sprintf("ALTER TABLE %s ALTER CONSTRAINT %s NOT DEFERRABLE;", h.quoteKeyword(constraint.tableName), h.quoteKeyword(constraint.constraintName))
|
||||
}
|
||||
if _, err2 := db.Exec(sql); err2 != nil && err == nil {
|
||||
err = err2
|
||||
}
|
||||
}()
|
||||
|
||||
var sql string
|
||||
for _, constraint := range h.nonDeferrableConstraints {
|
||||
sql += fmt.Sprintf("ALTER TABLE %s ALTER CONSTRAINT %s DEFERRABLE;", h.quoteKeyword(constraint.tableName), h.quoteKeyword(constraint.constraintName))
|
||||
}
|
||||
if _, err := db.Exec(sql); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
if _, err = tx.Exec("SET CONSTRAINTS ALL DEFERRED"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = loadFn(tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (h *PostgreSQL) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (err error) {
|
||||
// ensure sequences being reset after load
|
||||
if !h.SkipResetSequences {
|
||||
defer func() {
|
||||
if err2 := h.resetSequences(db); err2 != nil && err == nil {
|
||||
err = err2
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
if h.UseAlterConstraint {
|
||||
return h.makeConstraintsDeferrable(db, loadFn)
|
||||
}
|
||||
return h.disableTriggers(db, loadFn)
|
||||
}
|
||||
|
||||
func (h *PostgreSQL) resetSequences(db *sql.DB) error {
|
||||
for _, sequence := range h.sequences {
|
||||
_, err := db.Exec(fmt.Sprintf("SELECT SETVAL('%s', %d)", sequence, resetSequencesTo))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *PostgreSQL) isTableModified(q queryable, tableName string) (bool, error) {
|
||||
checksum, err := h.getChecksum(q, tableName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
oldChecksum := h.tablesChecksum[tableName]
|
||||
|
||||
return oldChecksum == "" || checksum != oldChecksum, nil
|
||||
}
|
||||
|
||||
func (h *PostgreSQL) afterLoad(q queryable) error {
|
||||
if h.tablesChecksum != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
h.tablesChecksum = make(map[string]string, len(h.tables))
|
||||
for _, t := range h.tables {
|
||||
checksum, err := h.getChecksum(q, t)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h.tablesChecksum[t] = checksum
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
`,
|
||||
h.quoteKeyword(tableName),
|
||||
)
|
||||
|
||||
var checksum sql.NullString
|
||||
if err := q.QueryRow(sqlStr).Scan(&checksum); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return checksum.String, nil
|
||||
}
|
||||
|
||||
func (*PostgreSQL) quoteKeyword(s string) string {
|
||||
parts := strings.Split(s, ".")
|
||||
for i, p := range parts {
|
||||
parts[i] = fmt.Sprintf(`"%s"`, p)
|
||||
}
|
||||
return strings.Join(parts, ".")
|
||||
}
|
76
vendor/gopkg.in/testfixtures.v2/sqlite.go
generated
vendored
76
vendor/gopkg.in/testfixtures.v2/sqlite.go
generated
vendored
@ -1,76 +0,0 @@
|
||||
package testfixtures
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// SQLite is the SQLite Helper for this package
|
||||
type SQLite struct {
|
||||
baseHelper
|
||||
}
|
||||
|
||||
func (*SQLite) paramType() int {
|
||||
return paramTypeQuestion
|
||||
}
|
||||
|
||||
func (*SQLite) databaseName(q queryable) (string, error) {
|
||||
var seq int
|
||||
var main, dbName string
|
||||
err := q.QueryRow("PRAGMA database_list").Scan(&seq, &main, &dbName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
dbName = filepath.Base(dbName)
|
||||
return dbName, nil
|
||||
}
|
||||
|
||||
func (*SQLite) tableNames(q queryable) ([]string, error) {
|
||||
query := `
|
||||
SELECT name
|
||||
FROM sqlite_master
|
||||
WHERE type = 'table';
|
||||
`
|
||||
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 (*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
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err = db.Exec("PRAGMA defer_foreign_keys = ON"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
if err = loadFn(tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
135
vendor/gopkg.in/testfixtures.v2/sqlserver.go
generated
vendored
135
vendor/gopkg.in/testfixtures.v2/sqlserver.go
generated
vendored
@ -1,135 +0,0 @@
|
||||
package testfixtures
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SQLServer is the helper for SQL Server for this package.
|
||||
// SQL Server >= 2008 is required.
|
||||
type SQLServer struct {
|
||||
baseHelper
|
||||
|
||||
tables []string
|
||||
}
|
||||
|
||||
func (h *SQLServer) init(db *sql.DB) error {
|
||||
var err error
|
||||
|
||||
h.tables, err = h.tableNames(db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*SQLServer) paramType() int {
|
||||
return paramTypeQuestion
|
||||
}
|
||||
|
||||
func (*SQLServer) quoteKeyword(s string) string {
|
||||
parts := strings.Split(s, ".")
|
||||
for i, p := range parts {
|
||||
parts[i] = fmt.Sprintf(`[%s]`, p)
|
||||
}
|
||||
return strings.Join(parts, ".")
|
||||
}
|
||||
|
||||
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")
|
||||
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 (h *SQLServer) tableHasIdentityColumn(q queryable, tableName string) bool {
|
||||
sql := `
|
||||
SELECT COUNT(*)
|
||||
FROM SYS.IDENTITY_COLUMNS
|
||||
WHERE OBJECT_ID = OBJECT_ID(?)
|
||||
`
|
||||
var count int
|
||||
q.QueryRow(sql, h.quoteKeyword(tableName)).Scan(&count)
|
||||
return count > 0
|
||||
|
||||
}
|
||||
|
||||
func (h *SQLServer) whileInsertOnTable(tx *sql.Tx, tableName string, fn func() error) (err error) {
|
||||
if h.tableHasIdentityColumn(tx, tableName) {
|
||||
defer func() {
|
||||
_, err2 := tx.Exec(fmt.Sprintf("SET IDENTITY_INSERT %s OFF", h.quoteKeyword(tableName)))
|
||||
if err2 != nil && err == nil {
|
||||
err = err2
|
||||
}
|
||||
}()
|
||||
|
||||
_, err := tx.Exec(fmt.Sprintf("SET IDENTITY_INSERT %s ON", h.quoteKeyword(tableName)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return fn()
|
||||
}
|
||||
|
||||
func (h *SQLServer) disableReferentialIntegrity(db *sql.DB, loadFn loadFunction) (err error) {
|
||||
// ensure the triggers are re-enable after all
|
||||
defer func() {
|
||||
var sql string
|
||||
for _, table := range h.tables {
|
||||
sql += fmt.Sprintf("ALTER TABLE %s WITH CHECK CHECK CONSTRAINT ALL;", h.quoteKeyword(table))
|
||||
}
|
||||
if _, err2 := db.Exec(sql); err2 != nil && err == nil {
|
||||
err = err2
|
||||
}
|
||||
}()
|
||||
|
||||
var sql string
|
||||
for _, table := range h.tables {
|
||||
sql += fmt.Sprintf("ALTER TABLE %s NOCHECK CONSTRAINT ALL;", h.quoteKeyword(table))
|
||||
}
|
||||
if _, err := db.Exec(sql); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tx, err := db.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
if err = loadFn(tx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
// splitter is a batchSplitter interface implementation. We need it for
|
||||
// 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 {
|
||||
return []byte("GO\n")
|
||||
}
|
306
vendor/gopkg.in/testfixtures.v2/testfixtures.go
generated
vendored
306
vendor/gopkg.in/testfixtures.v2/testfixtures.go
generated
vendored
@ -1,306 +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 {
|
||||
fileExt := filepath.Ext(fileinfo.Name())
|
||||
if !fileinfo.IsDir() && (fileExt == ".yml" || fileExt == ".yaml") {
|
||||
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
|
||||
}
|
Reference in New Issue
Block a user