summaryrefslogtreecommitdiffstats
path: root/vendor
diff options
context:
space:
mode:
authorJoram Wilander <jwawilander@gmail.com>2017-05-29 15:46:35 -0400
committerGitHub <noreply@github.com>2017-05-29 15:46:35 -0400
commit860e5d483cd952ec833c40312a2141bb3e4ef579 (patch)
treea854943f1f008f9b0f607f486de4b117b98e08e4 /vendor
parentf9843b380074cc6082566a2752c5482210f912bb (diff)
downloadchat-860e5d483cd952ec833c40312a2141bb3e4ef579.tar.gz
chat-860e5d483cd952ec833c40312a2141bb3e4ef579.tar.bz2
chat-860e5d483cd952ec833c40312a2141bb3e4ef579.zip
PLT-6341/PLT-6342 Update gorp to mattermost fork and add connection timeout setting (#6410)
* Update gorp to mattermost fork and add connection timeout setting * Add go dependency * Rename from connection timeout to query timeout * Properly add gorp dependency
Diffstat (limited to 'vendor')
-rw-r--r--vendor/github.com/mattermost/gorp/.gitignore (renamed from vendor/github.com/go-gorp/gorp/.gitignore)1
-rw-r--r--vendor/github.com/mattermost/gorp/.travis.yml (renamed from vendor/github.com/go-gorp/gorp/.travis.yml)9
-rw-r--r--vendor/github.com/mattermost/gorp/CONTRIBUTING.md34
-rw-r--r--vendor/github.com/mattermost/gorp/LICENSE (renamed from vendor/github.com/go-gorp/gorp/LICENSE)0
-rw-r--r--vendor/github.com/mattermost/gorp/README.md (renamed from vendor/github.com/go-gorp/gorp/README.md)248
-rw-r--r--vendor/github.com/mattermost/gorp/column.go (renamed from vendor/github.com/go-gorp/gorp/column.go)0
-rw-r--r--vendor/github.com/mattermost/gorp/db.go (renamed from vendor/github.com/go-gorp/gorp/db.go)264
-rw-r--r--vendor/github.com/mattermost/gorp/dialect.go (renamed from vendor/github.com/go-gorp/gorp/dialect.go)3
-rw-r--r--vendor/github.com/mattermost/gorp/dialect_mysql.go (renamed from vendor/github.com/go-gorp/gorp/dialect_mysql.go)2
-rw-r--r--vendor/github.com/mattermost/gorp/dialect_mysql_test.go204
-rw-r--r--vendor/github.com/mattermost/gorp/dialect_oracle.go (renamed from vendor/github.com/go-gorp/gorp/dialect_oracle.go)2
-rw-r--r--vendor/github.com/mattermost/gorp/dialect_postgres.go (renamed from vendor/github.com/go-gorp/gorp/dialect_postgres.go)6
-rw-r--r--vendor/github.com/mattermost/gorp/dialect_sqlite.go (renamed from vendor/github.com/go-gorp/gorp/dialect_sqlite.go)2
-rw-r--r--vendor/github.com/mattermost/gorp/dialect_sqlserver.go (renamed from vendor/github.com/go-gorp/gorp/dialect_sqlserver.go)2
-rw-r--r--vendor/github.com/mattermost/gorp/errors.go (renamed from vendor/github.com/go-gorp/gorp/errors.go)0
-rw-r--r--vendor/github.com/mattermost/gorp/gorp.go (renamed from vendor/github.com/go-gorp/gorp/gorp.go)73
-rw-r--r--vendor/github.com/mattermost/gorp/gorp_suite_test.go13
-rw-r--r--vendor/github.com/mattermost/gorp/gorp_test.go (renamed from vendor/github.com/go-gorp/gorp/gorp_test.go)637
-rw-r--r--vendor/github.com/mattermost/gorp/hooks.go (renamed from vendor/github.com/go-gorp/gorp/hooks.go)0
-rw-r--r--vendor/github.com/mattermost/gorp/index.go (renamed from vendor/github.com/go-gorp/gorp/index.go)0
-rw-r--r--vendor/github.com/mattermost/gorp/lockerror.go (renamed from vendor/github.com/go-gorp/gorp/lockerror.go)0
-rw-r--r--vendor/github.com/mattermost/gorp/logging.go (renamed from vendor/github.com/go-gorp/gorp/logging.go)0
-rw-r--r--vendor/github.com/mattermost/gorp/nulltypes.go (renamed from vendor/github.com/go-gorp/gorp/nulltypes.go)0
-rw-r--r--vendor/github.com/mattermost/gorp/select.go (renamed from vendor/github.com/go-gorp/gorp/select.go)58
-rw-r--r--vendor/github.com/mattermost/gorp/table.go (renamed from vendor/github.com/go-gorp/gorp/table.go)0
-rw-r--r--vendor/github.com/mattermost/gorp/table_bindings.go (renamed from vendor/github.com/go-gorp/gorp/table_bindings.go)0
-rwxr-xr-xvendor/github.com/mattermost/gorp/test_all.sh (renamed from vendor/github.com/go-gorp/gorp/test_all.sh)3
-rw-r--r--vendor/github.com/mattermost/gorp/transaction.go (renamed from vendor/github.com/go-gorp/gorp/transaction.go)32
28 files changed, 1271 insertions, 322 deletions
diff --git a/vendor/github.com/go-gorp/gorp/.gitignore b/vendor/github.com/mattermost/gorp/.gitignore
index 8a06adea5..d18c8ca70 100644
--- a/vendor/github.com/go-gorp/gorp/.gitignore
+++ b/vendor/github.com/mattermost/gorp/.gitignore
@@ -1,4 +1,5 @@
_test
+*.test
_testmain.go
_obj
*~
diff --git a/vendor/github.com/go-gorp/gorp/.travis.yml b/vendor/github.com/mattermost/gorp/.travis.yml
index ce4602884..d35c77e71 100644
--- a/vendor/github.com/go-gorp/gorp/.travis.yml
+++ b/vendor/github.com/mattermost/gorp/.travis.yml
@@ -1,9 +1,13 @@
language: go
go:
-- 1.3
-- 1.4
+- 1.6
+- 1.7
- tip
+matrix:
+ allow_failures:
+ - go: tip
+
services:
- mysql
- postgres
@@ -24,5 +28,6 @@ before_script:
- go get github.com/go-sql-driver/mysql
- go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls
+- go get github.com/onsi/ginkgo/ginkgo
script: ./test_all.sh
diff --git a/vendor/github.com/mattermost/gorp/CONTRIBUTING.md b/vendor/github.com/mattermost/gorp/CONTRIBUTING.md
new file mode 100644
index 000000000..7bc145fd7
--- /dev/null
+++ b/vendor/github.com/mattermost/gorp/CONTRIBUTING.md
@@ -0,0 +1,34 @@
+# Contributions are very welcome!
+
+## First: Create an Issue
+
+Even if your fix is simple, we'd like to have an issue to relate to
+the PR. Discussion about the architecture and value can go on the
+issue, leaving PR comments exclusively for coding style.
+
+## Second: Make Your PR
+
+- Fork the `master` branch
+- Make your change
+- Make a PR against the `master` branch
+
+You don't need to wait for comments on the issue before making your
+PR. If you do wait for comments, you'll have a better chance of
+getting your PR accepted the first time around, but it's not
+necessary.
+
+## Third: Be Patient
+
+- If your change breaks backward compatibility, this becomes
+ especially true.
+
+We all have lives and jobs, and many of us are no longer on projects
+that make use of `gorp`. We will get back to you, but it might take a
+while.
+
+## Fourth: Consider Becoming a Maintainer
+
+We really do need help. We will likely ask you for help after a good
+PR, but if we don't, please create an issue requesting maintainership.
+Considering how few of us are currently active, we are unlikely to
+refuse good help.
diff --git a/vendor/github.com/go-gorp/gorp/LICENSE b/vendor/github.com/mattermost/gorp/LICENSE
index b661111d0..b661111d0 100644
--- a/vendor/github.com/go-gorp/gorp/LICENSE
+++ b/vendor/github.com/mattermost/gorp/LICENSE
diff --git a/vendor/github.com/go-gorp/gorp/README.md b/vendor/github.com/mattermost/gorp/README.md
index 8b9277805..53ee245d3 100644
--- a/vendor/github.com/go-gorp/gorp/README.md
+++ b/vendor/github.com/mattermost/gorp/README.md
@@ -4,23 +4,40 @@
[![code coverage](https://img.shields.io/coveralls/go-gorp/gorp.svg)](https://coveralls.io/r/go-gorp/gorp)
[![issues](https://img.shields.io/github/issues/go-gorp/gorp.svg)](https://github.com/go-gorp/gorp/issues)
[![godoc v1](https://img.shields.io/badge/godoc-v1-375EAB.svg)](https://godoc.org/gopkg.in/gorp.v1)
+[![godoc v2](https://img.shields.io/badge/godoc-v2-375EAB.svg)](https://godoc.org/gopkg.in/gorp.v2)
[![godoc bleeding edge](https://img.shields.io/badge/godoc-bleeding--edge-375EAB.svg)](https://godoc.org/github.com/go-gorp/gorp)
-### Update 2015-07-01 Cleanup & feature freeze ([#270](https://github.com/go-gorp/gorp/issues/270))
+### Update 2016-11-13: Future versions
-We are currently cleaning up the backlog of issues and PR's. When this is done the codebase will be split into separate files and there will be breaking changes to the API's. We're also adding better tests and documentation. As a result of these changes the `master` branch will be unstable. Please use `gopkg.in/gorp.v1`. When the cleanup and changes are done, we will release `v2.0`.
+As many of the maintainers have become busy with other projects,
+progress toward the ever-elusive v2 has slowed to the point that we're
+only occasionally making progress outside of merging pull requests.
+In the interest of continuing to release, I'd like to lean toward a
+more maintainable path forward.
-At this time we won't accept new feature-related pull-requests because of changes to the codebase. Please create an issue for your feature and wait until `v2.0` has been released.
-
-For more information, please read [#270](https://github.com/go-gorp/gorp/issues/270).
+For the moment, I am releasing a v2 tag with the current feature set
+from master, as some of those features have been actively used and
+relied on by more than one project. Our next goal is to continue
+cleaning up the code base with non-breaking changes as much as
+possible, but if/when a breaking change is needed, we'll just release
+new versions. This allows us to continue development at whatever pace
+we're capable of, without delaying the release of features or refusing
+PRs.
## Introduction
-I hesitate to call gorp an ORM. Go doesn't really have objects, at least not in the classic Smalltalk/Java sense. There goes the "O". gorp doesn't know anything about the relationships between your structs (at least not yet). So the "R" is questionable too (but I use it in the name because, well, it seemed more clever).
+I hesitate to call gorp an ORM. Go doesn't really have objects, at
+least not in the classic Smalltalk/Java sense. There goes the "O".
+gorp doesn't know anything about the relationships between your
+structs (at least not yet). So the "R" is questionable too (but I use
+it in the name because, well, it seemed more clever).
-The "M" is alive and well. Given some Go structs and a database, gorp should remove a fair amount of boilerplate busy-work from your code.
+The "M" is alive and well. Given some Go structs and a database, gorp
+should remove a fair amount of boilerplate busy-work from your code.
-I hope that gorp saves you time, minimizes the drudgery of getting data in and out of your database, and helps your code focus on algorithms, not infrastructure.
+I hope that gorp saves you time, minimizes the drudgery of getting
+data in and out of your database, and helps your code focus on
+algorithms, not infrastructure.
* Bind struct fields to table columns via API or tag
* Support for embedded structs
@@ -35,42 +52,59 @@ I hope that gorp saves you time, minimizes the drudgery of getting data in and o
* Bind arbitrary SQL queries to a struct
* Bind slice to SELECT query results without type assertions
* Use positional or named bind parameters in custom SELECT queries
-* Optional optimistic locking using a version column (for update/deletes)
+* Optional optimistic locking using a version column (for
+ update/deletes)
## Installation
- # install the library:
- go get gopkg.in/gorp.v1
-
- // use in your .go code:
- import (
- "gopkg.in/gorp.v1"
- )
+Use `go get` or your favorite vendoring tool, using whichever import
+path you'd like.
## Versioning
-This project provides a stable release (v1.x tags) and a bleeding edge codebase (master).
+We use semantic version tags. Feel free to import through `gopkg.in`
+(e.g. `gopkg.in/gorp.v2`) to get the latest tag for a major version,
+or check out the tag using your favorite vendoring tool.
-`gopkg.in/gorp.v1` points to the latest v1.x tag. The API's for v1 are stable and shouldn't change. Development takes place at the master branch. Althought the code in master should always compile and test successfully, it might break API's. We aim to maintain backwards compatibility, but API's and behaviour might be changed to fix a bug. Also note that API's that are new in the master branch can change until released as v2.
+Development is not very active right now, but we have plans to
+restructure `gorp` as we continue to move toward a more extensible
+system. Whenever a breaking change is needed, the major version will
+be bumped.
-If you want to use bleeding edge, use `github.com/go-gorp/gorp` as import path.
+The `master` branch is where all development is done, and breaking
+changes may happen from time to time. That said, if you want to live
+on the bleeding edge and are comfortable updating your code when we
+make a breaking change, you may use `github.com/go-gorp/gorp` as your
+import path.
-## API Documentation
+Check the version tags to see what's available. We'll make a good
+faith effort to add badges for new versions, but we make no
+guarantees.
-Full godoc output from the latest v1 release is available here:
+## Supported Go versions
-https://godoc.org/gopkg.in/gorp.v1
+This package is guaranteed to be compatible with the latest 2 major
+versions of Go.
-For the latest code in master:
+Any earlier versions are only supported on a best effort basis and can
+be dropped any time. Go has a great compatibility promise. Upgrading
+your program to a newer version of Go should never really be a
+problem.
-https://godoc.org/github.com/go-gorp/gorp
+## Migration guide
-## Supported Go versions
+#### Pre-v2 to v2
+Automatic mapping of the version column used in optimistic locking has
+been removed as it could cause problems if the type was not int. The
+version column must now explicitly be set with
+`tablemap.SetVersionCol()`.
-This package is compatible with the last 2 major versions of Go, at this time `1.3` and `1.4`.
+## Help/Support
-Any earlier versions are only supported on a best effort basis and can be dropped any time.
-Go has a great compatibility promise. Upgrading your program to a newer version of Go should never really be a problem.
+Use our [`gitter` channel](https://gitter.im/go-gorp/gorp). We used
+to use IRC, but with most of us being pulled in many directions, we
+often need the email notifications from `gitter` to yell at us to sign
+in.
## Quickstart
@@ -530,10 +564,11 @@ Full list of hooks that you can implement:
#### Note that this behaviour has changed in v2. See [Migration Guide](#migration-guide).
-gorp provides a simple optimistic locking feature, similar to Java's JPA, that
-will raise an error if you try to update/delete a row whose `version` column
-has a value different than the one in memory. This provides a safe way to do
-"select then update" style operations without explicit read and write locks.
+gorp provides a simple optimistic locking feature, similar to Java's
+JPA, that will raise an error if you try to update/delete a row whose
+`version` column has a value different than the one in memory. This
+provides a safe way to do "select then update" style operations
+without explicit read and write locks.
```go
// Version is an auto-incremented number, managed by gorp
@@ -582,13 +617,15 @@ if ok {
```
### Adding INDEX(es) on column(s) beyond the primary key ###
-Indexes are frequently critical for performance. Here is how to add them to your tables.
+Indexes are frequently critical for performance. Here is how to add
+them to your tables.
-NB: SqlServer and Oracle need testing and possible adjustment to the
+NB: SqlServer and Oracle need testing and possible adjustment to the
CreateIndexSuffix() and DropIndexSuffix() methods to make AddIndex()
work for them.
-In the example below we put an index both on the Id field, and on the AcctId field.
+In the example below we put an index both on the Id field, and on the
+AcctId field.
```
type Account struct {
@@ -626,76 +663,111 @@ MariaDB [test]> show create table Account;
## Database Drivers
-gorp uses the Go 1 `database/sql` package. A full list of compliant drivers is available here:
+gorp uses the Go 1 `database/sql` package. A full list of compliant
+drivers is available here:
http://code.google.com/p/go-wiki/wiki/SQLDrivers
-Sadly, SQL databases differ on various issues. gorp provides a Dialect interface that should be
-implemented per database vendor. Dialects are provided for:
+Sadly, SQL databases differ on various issues. gorp provides a Dialect
+interface that should be implemented per database vendor. Dialects
+are provided for:
* MySQL
* PostgreSQL
* sqlite3
-Each of these three databases pass the test suite. See `gorp_test.go` for example
-DSNs for these three databases.
+Each of these three databases pass the test suite. See `gorp_test.go`
+for example DSNs for these three databases.
Support is also provided for:
* Oracle (contributed by @klaidliadon)
-* SQL Server (contributed by @qrawl) - use driver: github.com/denisenkom/go-mssqldb
+* SQL Server (contributed by @qrawl) - use driver:
+ github.com/denisenkom/go-mssqldb
+
+Note that these databases are not covered by CI and I (@coopernurse)
+have no good way to test them locally. So please try them and send
+patches as needed, but expect a bit more unpredicability.
+
+## Sqlite3 Extensions
-Note that these databases are not covered by CI and I (@coopernurse) have no good way to
-test them locally. So please try them and send patches as needed, but expect a bit more
-unpredicability.
+In order to use sqlite3 extensions you need to first register a custom driver:
+
+```go
+import (
+ "database/sql"
+
+ // use whatever database/sql driver you wish
+ sqlite "github.com/mattn/go-sqlite3"
+)
+
+func customDriver() (*sql.DB, error) {
+
+ // create custom driver with extensions defined
+ sql.Register("sqlite3-custom", &sqlite.SQLiteDriver{
+ Extensions: []string{
+ "mod_spatialite",
+ },
+ })
+
+ // now you can then connect using the 'sqlite3-custom' driver instead of 'sqlite3'
+ return sql.Open("sqlite3-custom", "/tmp/post_db.bin")
+}
+```
## Known Issues
### SQL placeholder portability
-Different databases use different strings to indicate variable placeholders in
-prepared SQL statements. Unlike some database abstraction layers (such as JDBC),
-Go's `database/sql` does not standardize this.
+Different databases use different strings to indicate variable
+placeholders in prepared SQL statements. Unlike some database
+abstraction layers (such as JDBC), Go's `database/sql` does not
+standardize this.
-SQL generated by gorp in the `Insert`, `Update`, `Delete`, and `Get` methods delegates
-to a Dialect implementation for each database, and will generate portable SQL.
+SQL generated by gorp in the `Insert`, `Update`, `Delete`, and `Get`
+methods delegates to a Dialect implementation for each database, and
+will generate portable SQL.
-Raw SQL strings passed to `Exec`, `Select`, `SelectOne`, `SelectInt`, etc will not be
-parsed. Consequently you may have portability issues if you write a query like this:
+Raw SQL strings passed to `Exec`, `Select`, `SelectOne`, `SelectInt`,
+etc will not be parsed. Consequently you may have portability issues
+if you write a query like this:
-```go
-// works on MySQL and Sqlite3, but not with Postgresql
-err := dbmap.SelectOne(&val, "select * from foo where id = ?", 30)
-```
+```go // works on MySQL and Sqlite3, but not with Postgresql err :=
+dbmap.SelectOne(&val, "select * from foo where id = ?", 30) ```
-In `Select` and `SelectOne` you can use named parameters to work around this.
-The following is portable:
+In `Select` and `SelectOne` you can use named parameters to work
+around this. The following is portable:
-```go
-err := dbmap.SelectOne(&val, "select * from foo where id = :id",
- map[string]interface{} { "id": 30})
-```
+```go err := dbmap.SelectOne(&val, "select * from foo where id = :id",
+map[string]interface{} { "id": 30}) ```
-Additionally, when using Postgres as your database, you should utilize `$1` instead
-of `?` placeholders as utilizing `?` placeholders when querying Postgres will result
-in `pq: operator does not exist` errors. Alternatively, use
-`dbMap.Dialect.BindVar(varIdx)` to get the proper variable binding for your dialect.
+Additionally, when using Postgres as your database, you should utilize
+`$1` instead of `?` placeholders as utilizing `?` placeholders when
+querying Postgres will result in `pq: operator does not exist`
+errors. Alternatively, use `dbMap.Dialect.BindVar(varIdx)` to get the
+proper variable binding for your dialect.
### time.Time and time zones
-gorp will pass `time.Time` fields through to the `database/sql` driver, but note that
-the behavior of this type varies across database drivers.
+gorp will pass `time.Time` fields through to the `database/sql`
+driver, but note that the behavior of this type varies across database
+drivers.
-MySQL users should be especially cautious. See: https://github.com/ziutek/mymysql/pull/77
+MySQL users should be especially cautious. See:
+https://github.com/ziutek/mymysql/pull/77
-To avoid any potential issues with timezone/DST, consider using an integer field for time
-data and storing UNIX time.
+To avoid any potential issues with timezone/DST, consider:
+
+- Using an integer field for time data and storing UNIX time.
+- Using a custom time type that implements some SQL types:
+ - [`"database/sql".Scanner`](https://golang.org/pkg/database/sql/#Scanner)
+ - [`"database/sql/driver".Valuer`](https://golang.org/pkg/database/sql/driver/#Valuer)
## Running the tests
The included tests may be run against MySQL, Postgresql, or sqlite3.
-You must set two environment variables so the test code knows which driver to
-use, and how to connect to your database.
+You must set two environment variables so the test code knows which
+driver to use, and how to connect to your database.
```sh
# MySQL example:
@@ -709,34 +781,18 @@ go test
go test -bench="Bench" -benchtime 10
```
-Valid `GORP_TEST_DIALECT` values are: "mysql"(for mymysql), "gomysql"(for go-sql-driver), "postgres", "sqlite"
-See the `test_all.sh` script for examples of all 3 databases. This is the script I run
-locally to test the library.
+Valid `GORP_TEST_DIALECT` values are: "mysql"(for mymysql),
+"gomysql"(for go-sql-driver), "postgres", "sqlite" See the
+`test_all.sh` script for examples of all 3 databases. This is the
+script I run locally to test the library.
## Performance
-gorp uses reflection to construct SQL queries and bind parameters. See the BenchmarkNativeCrud vs BenchmarkGorpCrud in gorp_test.go for a simple perf test. On my MacBook Pro gorp is about 2-3% slower than hand written SQL.
-
-## Migration guide
-#### Pre-v2 to v2
-Automatic mapping of the version column used in optimistic locking has been removed as it could cause problems if the type was not int. The version column must now explicitly be set with tablemap.SetVersionCol().
-
-## Help/Support
-
-IRC: #gorp
-Mailing list: gorp-dev@googlegroups.com
-Bugs/Enhancements: Create a github issue
-
-## Pull requests / Contributions
-
-Contributions are very welcome. Please follow these guidelines:
-
-* Fork the `master` branch and issue pull requests targeting the `master` branch
-* If you are adding an enhancement, please open an issue first with your proposed change.
-* Changes that break backwards compatibility in the public API are only accepted after we
- discuss on a GitHub issue for a while.
+gorp uses reflection to construct SQL queries and bind parameters.
+See the BenchmarkNativeCrud vs BenchmarkGorpCrud in gorp_test.go for a
+simple perf test. On my MacBook Pro gorp is about 2-3% slower than
+hand written SQL.
-Thanks!
## Contributors
diff --git a/vendor/github.com/go-gorp/gorp/column.go b/vendor/github.com/mattermost/gorp/column.go
index 99d4fd555..99d4fd555 100644
--- a/vendor/github.com/go-gorp/gorp/column.go
+++ b/vendor/github.com/mattermost/gorp/column.go
diff --git a/vendor/github.com/go-gorp/gorp/db.go b/vendor/github.com/mattermost/gorp/db.go
index 5ce68fdfd..8a65fbe49 100644
--- a/vendor/github.com/go-gorp/gorp/db.go
+++ b/vendor/github.com/mattermost/gorp/db.go
@@ -13,6 +13,7 @@ package gorp
import (
"bytes"
+ "context"
"database/sql"
"database/sql/driver"
"errors"
@@ -41,9 +42,34 @@ type DbMap struct {
TypeConverter TypeConverter
- tables []*TableMap
- logger GorpLogger
- logPrefix string
+ QueryTimeout time.Duration
+
+ tables []*TableMap
+ tablesDynamic map[string]*TableMap // tables that use same go-struct and different db table names
+ logger GorpLogger
+ logPrefix string
+}
+
+func (m *DbMap) dynamicTableAdd(tableName string, tbl *TableMap) {
+ if m.tablesDynamic == nil {
+ m.tablesDynamic = make(map[string]*TableMap)
+ }
+ m.tablesDynamic[tableName] = tbl
+}
+
+func (m *DbMap) dynamicTableFind(tableName string) (*TableMap, bool) {
+ if m.tablesDynamic == nil {
+ return nil, false
+ }
+ tbl, found := m.tablesDynamic[tableName]
+ return tbl, found
+}
+
+func (m *DbMap) dynamicTableMap() map[string]*TableMap {
+ if m.tablesDynamic == nil {
+ m.tablesDynamic = make(map[string]*TableMap)
+ }
+ return m.tablesDynamic
}
func (m *DbMap) CreateIndex() error {
@@ -52,36 +78,52 @@ func (m *DbMap) CreateIndex() error {
dialect := reflect.TypeOf(m.Dialect)
for _, table := range m.tables {
for _, index := range table.indexes {
-
- s := bytes.Buffer{}
- s.WriteString("create")
- if index.Unique {
- s.WriteString(" unique")
- }
- s.WriteString(" index")
- s.WriteString(fmt.Sprintf(" %s on %s", index.IndexName, table.TableName))
- if dname := dialect.Name(); dname == "PostgresDialect" && index.IndexType != "" {
- s.WriteString(fmt.Sprintf(" %s %s", m.Dialect.CreateIndexSuffix(), index.IndexType))
- }
- s.WriteString(" (")
- for x, col := range index.columns {
- if x > 0 {
- s.WriteString(", ")
- }
- s.WriteString(m.Dialect.QuoteField(col))
+ err = m.createIndexImpl(dialect, table, index)
+ if err != nil {
+ break
}
- s.WriteString(")")
+ }
+ }
- if dname := dialect.Name(); dname == "MySQLDialect" && index.IndexType != "" {
- s.WriteString(fmt.Sprintf(" %s %s", m.Dialect.CreateIndexSuffix(), index.IndexType))
- }
- s.WriteString(";")
- _, err = m.Exec(s.String())
+ for _, table := range m.dynamicTableMap() {
+ for _, index := range table.indexes {
+ err = m.createIndexImpl(dialect, table, index)
if err != nil {
break
}
}
}
+
+ return err
+}
+
+func (m *DbMap) createIndexImpl(dialect reflect.Type,
+ table *TableMap,
+ index *IndexMap) error {
+ s := bytes.Buffer{}
+ s.WriteString("create")
+ if index.Unique {
+ s.WriteString(" unique")
+ }
+ s.WriteString(" index")
+ s.WriteString(fmt.Sprintf(" %s on %s", index.IndexName, table.TableName))
+ if dname := dialect.Name(); dname == "PostgresDialect" && index.IndexType != "" {
+ s.WriteString(fmt.Sprintf(" %s %s", m.Dialect.CreateIndexSuffix(), index.IndexType))
+ }
+ s.WriteString(" (")
+ for x, col := range index.columns {
+ if x > 0 {
+ s.WriteString(", ")
+ }
+ s.WriteString(m.Dialect.QuoteField(col))
+ }
+ s.WriteString(")")
+
+ if dname := dialect.Name(); dname == "MySQLDialect" && index.IndexType != "" {
+ s.WriteString(fmt.Sprintf(" %s %s", m.Dialect.CreateIndexSuffix(), index.IndexType))
+ }
+ s.WriteString(";")
+ _, err := m.ExecNoTimeout(s.String())
return err
}
@@ -98,7 +140,7 @@ func (t *TableMap) DropIndex(name string) error {
s.WriteString(fmt.Sprintf(" %s %s", t.dbmap.Dialect.DropIndexSuffix(), t.TableName))
}
s.WriteString(";")
- _, e := t.dbmap.Exec(s.String())
+ _, e := t.dbmap.ExecNoTimeout(s.String())
if e != nil {
err = e
}
@@ -155,6 +197,36 @@ func (m *DbMap) AddTableWithNameAndSchema(i interface{}, schema string, name str
return tmap
}
+// AddTableDynamic registers the given interface type with gorp.
+// The table name will be dynamically determined at runtime by
+// using the GetTableName method on DynamicTable interface
+func (m *DbMap) AddTableDynamic(inp DynamicTable, schema string) *TableMap {
+
+ val := reflect.ValueOf(inp)
+ elm := val.Elem()
+ t := elm.Type()
+ name := inp.TableName()
+ if name == "" {
+ panic("Missing table name in DynamicTable instance")
+ }
+
+ // Check if there is another dynamic table with the same name
+ if _, found := m.dynamicTableFind(name); found {
+ panic(fmt.Sprintf("A table with the same name %v already exists", name))
+ }
+
+ tmap := &TableMap{gotype: t, TableName: name, SchemaName: schema, dbmap: m}
+ var primaryKey []*ColumnMap
+ tmap.Columns, primaryKey = m.readStructColumns(t)
+ if len(primaryKey) > 0 {
+ tmap.keys = append(tmap.keys, primaryKey...)
+ }
+
+ m.dynamicTableAdd(name, tmap)
+
+ return tmap
+}
+
func (m *DbMap) readStructColumns(t reflect.Type) (cols []*ColumnMap, primaryKey []*ColumnMap) {
primaryKey = make([]*ColumnMap, 0)
n := t.NumField()
@@ -189,6 +261,7 @@ func (m *DbMap) readStructColumns(t reflect.Type) (cols []*ColumnMap, primaryKey
var defaultValue string
var isAuto bool
var isPK bool
+ var isNotNull bool
for _, argString := range cArguments[1:] {
argString = strings.TrimSpace(argString)
arg := strings.SplitN(argString, ":", 2)
@@ -216,6 +289,8 @@ func (m *DbMap) readStructColumns(t reflect.Type) (cols []*ColumnMap, primaryKey
isPK = true
case "autoincrement":
isAuto = true
+ case "notnull":
+ isNotNull = true
default:
panic(fmt.Sprintf("Unrecognized tag option for field %v: %v", f.Name, arg))
}
@@ -259,6 +334,7 @@ func (m *DbMap) readStructColumns(t reflect.Type) (cols []*ColumnMap, primaryKey
gotype: gotype,
isPK: isPK,
isAutoIncr: isAuto,
+ isNotNull: isNotNull,
MaxSize: maxSize,
}
if isPK {
@@ -304,11 +380,20 @@ func (m *DbMap) createTables(ifNotExists bool) error {
for i := range m.tables {
table := m.tables[i]
sql := table.SqlForCreate(ifNotExists)
- _, err = m.Exec(sql)
+ _, err = m.ExecNoTimeout(sql)
if err != nil {
- break
+ return err
+ }
+ }
+
+ for _, tbl := range m.dynamicTableMap() {
+ sql := tbl.SqlForCreate(ifNotExists)
+ _, err = m.ExecNoTimeout(sql)
+ if err != nil {
+ return err
}
}
+
return err
}
@@ -316,13 +401,25 @@ func (m *DbMap) createTables(ifNotExists bool) error {
// Returns an error when the table does not exist.
func (m *DbMap) DropTable(table interface{}) error {
t := reflect.TypeOf(table)
- return m.dropTable(t, false)
+
+ tableName := ""
+ if dyn, ok := table.(DynamicTable); ok {
+ tableName = dyn.TableName()
+ }
+
+ return m.dropTable(t, tableName, false)
}
// DropTableIfExists drops an individual table when the table exists.
func (m *DbMap) DropTableIfExists(table interface{}) error {
t := reflect.TypeOf(table)
- return m.dropTable(t, true)
+
+ tableName := ""
+ if dyn, ok := table.(DynamicTable); ok {
+ tableName = dyn.TableName()
+ }
+
+ return m.dropTable(t, tableName, true)
}
// DropTables iterates through TableMaps registered to this DbMap and
@@ -347,12 +444,20 @@ func (m *DbMap) dropTables(addIfExists bool) (err error) {
return err
}
}
+
+ for _, table := range m.dynamicTableMap() {
+ err = m.dropTableImpl(table, addIfExists)
+ if err != nil {
+ return err
+ }
+ }
+
return err
}
// Implementation of dropping a single table.
-func (m *DbMap) dropTable(t reflect.Type, addIfExists bool) error {
- table := tableOrNil(m, t)
+func (m *DbMap) dropTable(t reflect.Type, name string, addIfExists bool) error {
+ table := tableOrNil(m, t, name)
if table == nil {
return fmt.Errorf("table %s was not registered", table.TableName)
}
@@ -365,7 +470,7 @@ func (m *DbMap) dropTableImpl(table *TableMap, ifExists bool) (err error) {
if ifExists {
tableDrop = m.Dialect.IfTableExists(tableDrop, table.SchemaName, table.TableName)
}
- _, err = m.Exec(fmt.Sprintf("%s %s;", tableDrop, m.Dialect.QuotedTableForQuery(table.SchemaName, table.TableName)))
+ _, err = m.ExecNoTimeout(fmt.Sprintf("%s %s;", tableDrop, m.Dialect.QuotedTableForQuery(table.SchemaName, table.TableName)))
return err
}
@@ -377,11 +482,19 @@ func (m *DbMap) TruncateTables() error {
var err error
for i := range m.tables {
table := m.tables[i]
- _, e := m.Exec(fmt.Sprintf("%s %s;", m.Dialect.TruncateClause(), m.Dialect.QuotedTableForQuery(table.SchemaName, table.TableName)))
+ _, e := m.ExecNoTimeout(fmt.Sprintf("%s %s;", m.Dialect.TruncateClause(), m.Dialect.QuotedTableForQuery(table.SchemaName, table.TableName)))
if e != nil {
err = e
}
}
+
+ for _, table := range m.dynamicTableMap() {
+ _, e := m.ExecNoTimeout(fmt.Sprintf("%s %s;", m.Dialect.TruncateClause(), m.Dialect.QuotedTableForQuery(table.SchemaName, table.TableName)))
+ if e != nil {
+ err = e
+ }
+ }
+
return err
}
@@ -487,12 +600,22 @@ func (m *DbMap) Select(i interface{}, query string, args ...interface{}) ([]inte
// Exec runs an arbitrary SQL statement. args represent the bind parameters.
// This is equivalent to running: Exec() using database/sql
+// Times out based on the DbMap.QueryTimeout field
func (m *DbMap) Exec(query string, args ...interface{}) (sql.Result, error) {
if m.logger != nil {
now := time.Now()
defer m.trace(now, query, args...)
}
- return exec(m, query, args...)
+ return exec(m, query, true, args...)
+}
+
+// ExecNoTimeout is the same as Exec except it will not time out
+func (m *DbMap) ExecNoTimeout(query string, args ...interface{}) (sql.Result, error) {
+ if m.logger != nil {
+ now := time.Now()
+ defer m.trace(now, query, args...)
+ }
+ return exec(m, query, false, args...)
}
// SelectInt is a convenience wrapper around the gorp.SelectInt function
@@ -547,7 +670,7 @@ func (m *DbMap) Begin() (*Transaction, error) {
// If no table is mapped to that type an error is returned.
// If checkPK is true and the mapped table has no registered PKs, an error is returned.
func (m *DbMap) TableFor(t reflect.Type, checkPK bool) (*TableMap, error) {
- table := tableOrNil(m, t)
+ table := tableOrNil(m, t, "")
if table == nil {
return nil, fmt.Errorf("no table found for type: %v", t.Name())
}
@@ -561,6 +684,25 @@ func (m *DbMap) TableFor(t reflect.Type, checkPK bool) (*TableMap, error) {
return table, nil
}
+// DynamicTableFor returns the *TableMap for the dynamic table corresponding
+// to the input tablename
+// If no table is mapped to that tablename an error is returned.
+// If checkPK is true and the mapped table has no registered PKs, an error is returned.
+func (m *DbMap) DynamicTableFor(tableName string, checkPK bool) (*TableMap, error) {
+ table, found := m.dynamicTableFind(tableName)
+ if !found {
+ return nil, fmt.Errorf("gorp: no table found for name: %v", tableName)
+ }
+
+ if checkPK && len(table.keys) < 1 {
+ e := fmt.Sprintf("gorp: no keys defined for table: %s",
+ table.TableName)
+ return nil, errors.New(e)
+ }
+
+ return table, nil
+}
+
// Prepare creates a prepared statement for later queries or executions.
// Multiple queries or executions may be run concurrently from the returned statement.
// This is equivalent to running: Prepare() using database/sql
@@ -572,7 +714,15 @@ func (m *DbMap) Prepare(query string) (*sql.Stmt, error) {
return m.Db.Prepare(query)
}
-func tableOrNil(m *DbMap, t reflect.Type) *TableMap {
+func tableOrNil(m *DbMap, t reflect.Type, name string) *TableMap {
+ if name != "" {
+ // Search by table name (dynamic tables)
+ if table, found := m.dynamicTableFind(name); found {
+ return table
+ }
+ return nil
+ }
+
for i := range m.tables {
table := m.tables[i]
if table.gotype == t {
@@ -590,8 +740,18 @@ func (m *DbMap) tableForPointer(ptr interface{}, checkPK bool) (*TableMap, refle
return nil, reflect.Value{}, errors.New(e)
}
elem := ptrv.Elem()
- etype := reflect.TypeOf(elem.Interface())
- t, err := m.TableFor(etype, checkPK)
+ ifc := elem.Interface()
+ var t *TableMap
+ var err error
+ tableName := ""
+ if dyn, isDyn := ptr.(DynamicTable); isDyn {
+ tableName = dyn.TableName()
+ t, err = m.DynamicTableFor(tableName, checkPK)
+ } else {
+ etype := reflect.TypeOf(ifc)
+ t, err = m.TableFor(etype, checkPK)
+ }
+
if err != nil {
return nil, reflect.Value{}, err
}
@@ -599,22 +759,42 @@ func (m *DbMap) tableForPointer(ptr interface{}, checkPK bool) (*TableMap, refle
return t, elem, nil
}
-func (m *DbMap) queryRow(query string, args ...interface{}) *sql.Row {
+func (m *DbMap) QueryRow(query string, args ...interface{}) *sql.Row {
if m.logger != nil {
now := time.Now()
defer m.trace(now, query, args...)
}
+
return m.Db.QueryRow(query, args...)
}
-func (m *DbMap) query(query string, args ...interface{}) (*sql.Rows, error) {
+func (m *DbMap) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
if m.logger != nil {
now := time.Now()
defer m.trace(now, query, args...)
}
+
+ return m.Db.QueryRowContext(ctx, query, args...)
+}
+
+func (m *DbMap) Query(query string, args ...interface{}) (*sql.Rows, error) {
+ if m.logger != nil {
+ now := time.Now()
+ defer m.trace(now, query, args...)
+ }
+
return m.Db.Query(query, args...)
}
+func (m *DbMap) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
+ if m.logger != nil {
+ now := time.Now()
+ defer m.trace(now, query, args...)
+ }
+
+ return m.Db.QueryContext(ctx, query, args...)
+}
+
func (m *DbMap) trace(started time.Time, query string, args ...interface{}) {
if m.logger != nil {
var margs = argsString(args...)
diff --git a/vendor/github.com/go-gorp/gorp/dialect.go b/vendor/github.com/mattermost/gorp/dialect.go
index 203bc62b5..922212640 100644
--- a/vendor/github.com/go-gorp/gorp/dialect.go
+++ b/vendor/github.com/mattermost/gorp/dialect.go
@@ -18,6 +18,9 @@ import "reflect"
// but this could change in the future
type Dialect interface {
+ // dialect name
+ Name() string
+
// adds a suffix to any query, usually ";"
QuerySuffix() string
diff --git a/vendor/github.com/go-gorp/gorp/dialect_mysql.go b/vendor/github.com/mattermost/gorp/dialect_mysql.go
index 3d7d34027..b263c3308 100644
--- a/vendor/github.com/go-gorp/gorp/dialect_mysql.go
+++ b/vendor/github.com/mattermost/gorp/dialect_mysql.go
@@ -27,6 +27,8 @@ type MySQLDialect struct {
Encoding string
}
+func (d MySQLDialect) Name() string { return "MySQLDialect" }
+
func (d MySQLDialect) QuerySuffix() string { return ";" }
func (d MySQLDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
diff --git a/vendor/github.com/mattermost/gorp/dialect_mysql_test.go b/vendor/github.com/mattermost/gorp/dialect_mysql_test.go
new file mode 100644
index 000000000..d1018cf69
--- /dev/null
+++ b/vendor/github.com/mattermost/gorp/dialect_mysql_test.go
@@ -0,0 +1,204 @@
+// Copyright 2012 James Cooper. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+// Package gorp provides a simple way to marshal Go structs to and from
+// SQL databases. It uses the database/sql package, and should work with any
+// compliant database/sql driver.
+//
+// Source code and project home:
+// https://github.com/go-gorp/gorp
+
+package gorp_test
+
+import (
+ "database/sql"
+ "reflect"
+ "time"
+
+ // ginkgo/gomega functions read better as dot-imports.
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/ginkgo/extensions/table"
+ . "github.com/onsi/gomega"
+
+ "github.com/go-gorp/gorp"
+)
+
+var _ = Describe("MySQLDialect", func() {
+ var (
+ engine, encoding string
+ dialect gorp.MySQLDialect
+ )
+
+ JustBeforeEach(func() {
+ dialect = gorp.MySQLDialect{
+ Engine: engine,
+ Encoding: encoding,
+ }
+ })
+
+ DescribeTable("ToSqlType",
+ func(value interface{}, maxsize int, autoIncr bool, expected string) {
+ typ := reflect.TypeOf(value)
+ sqlType := dialect.ToSqlType(typ, maxsize, autoIncr)
+ Expect(sqlType).To(Equal(expected))
+ },
+ Entry("bool", true, 0, false, "boolean"),
+ Entry("int8", int8(1), 0, false, "tinyint"),
+ Entry("uint8", uint8(1), 0, false, "tinyint unsigned"),
+ Entry("int16", int16(1), 0, false, "smallint"),
+ Entry("uint16", uint16(1), 0, false, "smallint unsigned"),
+ Entry("int32", int32(1), 0, false, "int"),
+ Entry("int (treated as int32)", int(1), 0, false, "int"),
+ Entry("uint32", uint32(1), 0, false, "int unsigned"),
+ Entry("uint (treated as uint32)", uint(1), 0, false, "int unsigned"),
+ Entry("int64", int64(1), 0, false, "bigint"),
+ Entry("uint64", uint64(1), 0, false, "bigint unsigned"),
+ Entry("float32", float32(1), 0, false, "double"),
+ Entry("float64", float64(1), 0, false, "double"),
+ Entry("[]uint8", []uint8{1}, 0, false, "mediumblob"),
+ Entry("NullInt64", sql.NullInt64{}, 0, false, "bigint"),
+ Entry("NullFloat64", sql.NullFloat64{}, 0, false, "double"),
+ Entry("NullBool", sql.NullBool{}, 0, false, "tinyint"),
+ Entry("Time", time.Time{}, 0, false, "datetime"),
+ Entry("default-size string", "", 0, false, "varchar(255)"),
+ Entry("sized string", "", 50, false, "varchar(50)"),
+ Entry("large string", "", 1024, false, "text"),
+ )
+
+ Describe("AutoIncrStr", func() {
+ It("returns the auto increment string", func() {
+ Expect(dialect.AutoIncrStr()).To(Equal("auto_increment"))
+ })
+ })
+
+ Describe("AutoIncrBindValue", func() {
+ It("returns the value used to bind the auto-increment value", func() {
+ Expect(dialect.AutoIncrBindValue()).To(Equal("null"))
+ })
+ })
+
+ Describe("AutoIncrInsertSuffix", func() {
+ It("returns the suffix needed for auto-incrementing", func() {
+ Expect(dialect.AutoIncrInsertSuffix(nil)).To(BeEmpty())
+ })
+ })
+
+ Describe("CreateTableSuffix", func() {
+ Context("with an empty engine", func() {
+ BeforeEach(func() {
+ engine = ""
+ encoding = "foo"
+ })
+ It("panics", func() {
+ Expect(func() {
+ dialect.CreateTableSuffix()
+ }).To(Panic())
+ })
+ })
+
+ Context("with an empty encoding", func() {
+ BeforeEach(func() {
+ engine = "foo"
+ encoding = ""
+ })
+ It("panics", func() {
+ Expect(func() {
+ dialect.CreateTableSuffix()
+ }).To(Panic())
+ })
+ })
+
+ Context("with an engine and an encoding", func() {
+ BeforeEach(func() {
+ engine = "foo"
+ encoding = "bar"
+ })
+ It("returns a valid suffix", func() {
+ Expect(dialect.CreateTableSuffix()).To(Equal(" engine=foo charset=bar"))
+ })
+ })
+ })
+
+ Describe("CreateIndexSuffix", func() {
+ It("returns the suffix for creating indexes", func() {
+ Expect(dialect.CreateIndexSuffix()).To(Equal("using"))
+ })
+ })
+
+ Describe("DropIndexSuffix", func() {
+ It("returns the suffix for deleting indexes", func() {
+ Expect(dialect.DropIndexSuffix()).To(Equal("on"))
+ })
+ })
+
+ Describe("TruncateClause", func() {
+ It("returns the clause for truncating a table", func() {
+ Expect(dialect.TruncateClause()).To(Equal("truncate"))
+ })
+ })
+
+ Describe("BindVar", func() {
+ It("returns the variable binding sequence", func() {
+ Expect(dialect.BindVar(0)).To(Equal("?"))
+ })
+ })
+
+ PDescribe("InsertAutoIncr", func() {})
+
+ Describe("QuoteField", func() {
+ It("returns the argument quoted as a field", func() {
+ Expect(dialect.QuoteField("foo")).To(Equal("`foo`"))
+ })
+ })
+
+ Describe("QuotedTableForQuery", func() {
+ var (
+ schema, table string
+
+ quotedTable string
+ )
+
+ JustBeforeEach(func() {
+ quotedTable = dialect.QuotedTableForQuery(schema, table)
+ })
+
+ Context("using the default schema", func() {
+ BeforeEach(func() {
+ schema = ""
+ table = "foo"
+ })
+ It("returns just the table", func() {
+ Expect(quotedTable).To(Equal("`foo`"))
+ })
+ })
+
+ Context("with a supplied schema", func() {
+ BeforeEach(func() {
+ schema = "foo"
+ table = "bar"
+ })
+ It("returns the schema and table", func() {
+ Expect(quotedTable).To(Equal("foo.`bar`"))
+ })
+ })
+ })
+
+ Describe("IfSchemaNotExists", func() {
+ It("appends 'if not exists' to the command", func() {
+ Expect(dialect.IfSchemaNotExists("foo", "bar")).To(Equal("foo if not exists"))
+ })
+ })
+
+ Describe("IfTableExists", func() {
+ It("appends 'if exists' to the command", func() {
+ Expect(dialect.IfTableExists("foo", "bar", "baz")).To(Equal("foo if exists"))
+ })
+ })
+
+ Describe("IfTableNotExists", func() {
+ It("appends 'if not exists' to the command", func() {
+ Expect(dialect.IfTableNotExists("foo", "bar", "baz")).To(Equal("foo if not exists"))
+ })
+ })
+})
diff --git a/vendor/github.com/go-gorp/gorp/dialect_oracle.go b/vendor/github.com/mattermost/gorp/dialect_oracle.go
index c381380f9..b1cee0a0a 100644
--- a/vendor/github.com/go-gorp/gorp/dialect_oracle.go
+++ b/vendor/github.com/mattermost/gorp/dialect_oracle.go
@@ -20,6 +20,8 @@ import (
// Implementation of Dialect for Oracle databases.
type OracleDialect struct{}
+func (d OracleDialect) Name() string { return "OracleDialect" }
+
func (d OracleDialect) QuerySuffix() string { return "" }
func (d OracleDialect) CreateIndexSuffix() string { return "" }
diff --git a/vendor/github.com/go-gorp/gorp/dialect_postgres.go b/vendor/github.com/mattermost/gorp/dialect_postgres.go
index a086381a8..aa7f34cba 100644
--- a/vendor/github.com/go-gorp/gorp/dialect_postgres.go
+++ b/vendor/github.com/mattermost/gorp/dialect_postgres.go
@@ -21,6 +21,8 @@ type PostgresDialect struct {
suffix string
}
+func (d PostgresDialect) Name() string { return "PostgresDialect" }
+
func (d PostgresDialect) QuerySuffix() string { return ";" }
func (d PostgresDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
@@ -78,7 +80,7 @@ func (d PostgresDialect) AutoIncrBindValue() string {
}
func (d PostgresDialect) AutoIncrInsertSuffix(col *ColumnMap) string {
- return " returning " + col.ColumnName
+ return " returning " + d.QuoteField(col.ColumnName)
}
// Returns suffix
@@ -104,7 +106,7 @@ func (d PostgresDialect) BindVar(i int) string {
}
func (d PostgresDialect) InsertAutoIncrToTarget(exec SqlExecutor, insertSql string, target interface{}, params ...interface{}) error {
- rows, err := exec.query(insertSql, params...)
+ rows, err := exec.Query(insertSql, params...)
if err != nil {
return err
}
diff --git a/vendor/github.com/go-gorp/gorp/dialect_sqlite.go b/vendor/github.com/mattermost/gorp/dialect_sqlite.go
index 7d9b29757..e78605983 100644
--- a/vendor/github.com/go-gorp/gorp/dialect_sqlite.go
+++ b/vendor/github.com/mattermost/gorp/dialect_sqlite.go
@@ -20,6 +20,8 @@ type SqliteDialect struct {
suffix string
}
+func (d SqliteDialect) Name() string { return "SQLiteDialect" }
+
func (d SqliteDialect) QuerySuffix() string { return ";" }
func (d SqliteDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
diff --git a/vendor/github.com/go-gorp/gorp/dialect_sqlserver.go b/vendor/github.com/mattermost/gorp/dialect_sqlserver.go
index 8808af598..904110e35 100644
--- a/vendor/github.com/go-gorp/gorp/dialect_sqlserver.go
+++ b/vendor/github.com/mattermost/gorp/dialect_sqlserver.go
@@ -27,6 +27,8 @@ type SqlServerDialect struct {
Version string
}
+func (d SqlServerDialect) Name() string { return "SQLServerDialect" }
+
func (d SqlServerDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
switch val.Kind() {
case reflect.Ptr:
diff --git a/vendor/github.com/go-gorp/gorp/errors.go b/vendor/github.com/mattermost/gorp/errors.go
index d13f03fc3..d13f03fc3 100644
--- a/vendor/github.com/go-gorp/gorp/errors.go
+++ b/vendor/github.com/mattermost/gorp/errors.go
diff --git a/vendor/github.com/go-gorp/gorp/gorp.go b/vendor/github.com/mattermost/gorp/gorp.go
index 1f32283f5..728971e48 100644
--- a/vendor/github.com/go-gorp/gorp/gorp.go
+++ b/vendor/github.com/mattermost/gorp/gorp.go
@@ -12,6 +12,7 @@
package gorp
import (
+ "context"
"database/sql"
"database/sql/driver"
"fmt"
@@ -87,6 +88,7 @@ type TypeConverter interface {
// on internal functions that convert named parameters for the Exec function.
type executor interface {
Exec(query string, args ...interface{}) (sql.Result, error)
+ ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
}
// SqlExecutor exposes gorp operations that can be run from Pre/Post
@@ -101,6 +103,7 @@ type SqlExecutor interface {
Update(list ...interface{}) (int64, error)
Delete(list ...interface{}) (int64, error)
Exec(query string, args ...interface{}) (sql.Result, error)
+ ExecNoTimeout(query string, args ...interface{}) (sql.Result, error)
Select(i interface{}, query string,
args ...interface{}) ([]interface{}, error)
SelectInt(query string, args ...interface{}) (int64, error)
@@ -110,8 +113,18 @@ type SqlExecutor interface {
SelectStr(query string, args ...interface{}) (string, error)
SelectNullStr(query string, args ...interface{}) (sql.NullString, error)
SelectOne(holder interface{}, query string, args ...interface{}) error
- query(query string, args ...interface{}) (*sql.Rows, error)
- queryRow(query string, args ...interface{}) *sql.Row
+ Query(query string, args ...interface{}) (*sql.Rows, error)
+ QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
+ QueryRow(query string, args ...interface{}) *sql.Row
+ QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
+}
+
+// DynamicTable allows the users of gorp to dynamically
+// use different database table names during runtime
+// while sharing the same golang struct for in-memory data
+type DynamicTable interface {
+ TableName() string
+ SetTableName(string)
}
// Compile-time check that DbMap and Transaction implement the SqlExecutor
@@ -144,7 +157,7 @@ func argsString(args ...interface{}) string {
// Calls the Exec function on the executor, but attempts to expand any eligible named
// query arguments first.
-func exec(e SqlExecutor, query string, args ...interface{}) (sql.Result, error) {
+func exec(e SqlExecutor, query string, doTimeout bool, args ...interface{}) (sql.Result, error) {
var dbMap *DbMap
var executor executor
switch m := e.(type) {
@@ -160,7 +173,13 @@ func exec(e SqlExecutor, query string, args ...interface{}) (sql.Result, error)
query, args = maybeExpandNamedQuery(dbMap, query, args)
}
- return executor.Exec(query, args...)
+ if doTimeout && dbMap.Dialect.Name() != "PostgresDialect" {
+ ctx, cancel := context.WithTimeout(context.Background(), dbMap.QueryTimeout)
+ defer cancel()
+ return executor.ExecContext(ctx, query, args...)
+ } else {
+ return executor.Exec(query, args...)
+ }
}
// maybeExpandNamedQuery checks the given arg to see if it's eligible to be used
@@ -220,13 +239,13 @@ func expandNamedQuery(m *DbMap, query string, keyGetter func(key string) reflect
}), args
}
-func columnToFieldIndex(m *DbMap, t reflect.Type, cols []string) ([][]int, error) {
+func columnToFieldIndex(m *DbMap, t reflect.Type, name string, cols []string) ([][]int, error) {
colToFieldIndex := make([][]int, len(cols))
// check if type t is a mapped table - if so we'll
// check the table for column aliasing below
tableMapped := false
- table := tableOrNil(m, t)
+ table := tableOrNil(m, t, name)
if table != nil {
tableMapped = true
}
@@ -327,6 +346,30 @@ func toType(i interface{}) (reflect.Type, error) {
return t, nil
}
+type foundTable struct {
+ table *TableMap
+ dynName *string
+}
+
+func tableFor(m *DbMap, t reflect.Type, i interface{}) (*foundTable, error) {
+ if dyn, isDynamic := i.(DynamicTable); isDynamic {
+ tableName := dyn.TableName()
+ table, err := m.DynamicTableFor(tableName, true)
+ if err != nil {
+ return nil, err
+ }
+ return &foundTable{
+ table: table,
+ dynName: &tableName,
+ }, nil
+ }
+ table, err := m.TableFor(t, true)
+ if err != nil {
+ return nil, err
+ }
+ return &foundTable{table: table}, nil
+}
+
func get(m *DbMap, exec SqlExecutor, i interface{},
keys ...interface{}) (interface{}, error) {
@@ -335,14 +378,20 @@ func get(m *DbMap, exec SqlExecutor, i interface{},
return nil, err
}
- table, err := m.TableFor(t, true)
+ foundTable, err := tableFor(m, t, i)
if err != nil {
return nil, err
}
+ table := foundTable.table
plan := table.bindGet()
v := reflect.New(t)
+ if foundTable.dynName != nil {
+ retDyn := v.Interface().(DynamicTable)
+ retDyn.SetTableName(*foundTable.dynName)
+ }
+
dest := make([]interface{}, len(plan.argFields))
conv := m.TypeConverter
@@ -361,7 +410,15 @@ func get(m *DbMap, exec SqlExecutor, i interface{},
dest[x] = target
}
- row := exec.queryRow(plan.query, keys...)
+ var row *sql.Row
+ if m.Dialect.Name() != "PostgresDialect" {
+ ctx, cancel := context.WithTimeout(context.Background(), m.QueryTimeout)
+ defer cancel()
+ row = exec.QueryRowContext(ctx, plan.query, keys...)
+ } else {
+ row = exec.QueryRow(plan.query, keys...)
+ }
+
err = row.Scan(dest...)
if err != nil {
if err == sql.ErrNoRows {
diff --git a/vendor/github.com/mattermost/gorp/gorp_suite_test.go b/vendor/github.com/mattermost/gorp/gorp_suite_test.go
new file mode 100644
index 000000000..2abcaaf71
--- /dev/null
+++ b/vendor/github.com/mattermost/gorp/gorp_suite_test.go
@@ -0,0 +1,13 @@
+package gorp_test
+
+import (
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+
+ "testing"
+)
+
+func TestGorp(t *testing.T) {
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "Gorp Suite")
+}
diff --git a/vendor/github.com/go-gorp/gorp/gorp_test.go b/vendor/github.com/mattermost/gorp/gorp_test.go
index 895ab450e..98ea4d3e4 100644
--- a/vendor/github.com/go-gorp/gorp/gorp_test.go
+++ b/vendor/github.com/mattermost/gorp/gorp_test.go
@@ -9,7 +9,7 @@
// Source code and project home:
// https://github.com/go-gorp/gorp
-package gorp
+package gorp_test
import (
"bytes"
@@ -28,6 +28,8 @@ import (
"testing"
"time"
+ "github.com/go-gorp/gorp"
+
_ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
@@ -36,12 +38,12 @@ import (
var (
// verify interface compliance
- _ = []Dialect{
- SqliteDialect{},
- PostgresDialect{},
- MySQLDialect{},
- SqlServerDialect{},
- OracleDialect{},
+ _ = []gorp.Dialect{
+ gorp.SqliteDialect{},
+ gorp.PostgresDialect{},
+ gorp.MySQLDialect{},
+ gorp.SqlServerDialect{},
+ gorp.OracleDialect{},
}
debug bool
@@ -124,26 +126,36 @@ type Person struct {
Version int64
}
+// PersonValuerScanner is used as a field in test types to ensure that we
+// make use of "database/sql/driver".Valuer for choosing column types when
+// creating tables and that we don't get in the way of the underlying
+// database libraries when they make use of either Valuer or
+// "database/sql".Scanner.
type PersonValuerScanner struct {
Person
}
+// Value implements "database/sql/driver".Valuer. It will be automatically
+// run by the "database/sql" package when inserting/updating data.
func (p PersonValuerScanner) Value() (driver.Value, error) {
return p.Id, nil
}
-// FIXME: this Scan is never actually used in the tests?
-// Also: if the comments below on the mysql driver are true, then that should be fixed by the dialect when scanning values into structs.
+// Scan implements "database/sql".Scanner. It will be automatically run
+// by the "database/sql" package when reading column data into a field
+// of type PersonValuerScanner.
func (p *PersonValuerScanner) Scan(value interface{}) (err error) {
switch src := value.(type) {
case []byte:
- // The mysql driver seems to return a []byte, even though the
- // type in the database is bigint. Note that this case is
- // *only* used by the mysql driver.
+ // TODO: this case is here for mysql only. For some reason,
+ // one (both?) of the mysql libraries opt to pass us a []byte
+ // instead of an int64 for the bigint column. We should add
+ // table tests around valuers/scanners and try to solve these
+ // types of odd discrepencies to make it easier for users of
+ // gorp to migrate to other database engines.
p.Id, err = strconv.ParseInt(string(src), 10, 64)
case int64:
- // postgres, gomysql, and sqlite drivers all return an int64,
- // as you'd expect.
+ // Most libraries pass in the type we'd expect.
p.Id = src
default:
typ := reflect.TypeOf(value)
@@ -279,7 +291,7 @@ type WithCustomDate struct {
type WithNullTime struct {
Id int64
- Time NullTime
+ Time gorp.NullTime
}
type testTypeConverter struct{}
@@ -302,7 +314,7 @@ func (me testTypeConverter) ToDb(val interface{}) (interface{}, error) {
return val, nil
}
-func (me testTypeConverter) FromDb(target interface{}) (CustomScanner, bool) {
+func (me testTypeConverter) FromDb(target interface{}) (gorp.CustomScanner, bool) {
switch target.(type) {
case *Person:
binder := func(holder, target interface{}) error {
@@ -313,7 +325,7 @@ func (me testTypeConverter) FromDb(target interface{}) (CustomScanner, bool) {
b := []byte(*s)
return json.Unmarshal(b, target)
}
- return CustomScanner{new(string), target, binder}, true
+ return gorp.CustomScanner{new(string), target, binder}, true
case *CustomStringType:
binder := func(holder, target interface{}) error {
s, ok := holder.(*string)
@@ -327,7 +339,7 @@ func (me testTypeConverter) FromDb(target interface{}) (CustomScanner, bool) {
*st = CustomStringType(*s)
return nil
}
- return CustomScanner{new(string), target, binder}, true
+ return gorp.CustomScanner{new(string), target, binder}, true
case *CustomDate:
binder := func(holder, target interface{}) error {
t, ok := holder.(*time.Time)
@@ -341,13 +353,13 @@ func (me testTypeConverter) FromDb(target interface{}) (CustomScanner, bool) {
dateTarget.Time = *t
return nil
}
- return CustomScanner{new(time.Time), target, binder}, true
+ return gorp.CustomScanner{new(time.Time), target, binder}, true
}
- return CustomScanner{}, false
+ return gorp.CustomScanner{}, false
}
-func (p *Person) PreInsert(s SqlExecutor) error {
+func (p *Person) PreInsert(s gorp.SqlExecutor) error {
p.Created = time.Now().UnixNano()
p.Updated = p.Created
if p.FName == "badname" {
@@ -356,32 +368,32 @@ func (p *Person) PreInsert(s SqlExecutor) error {
return nil
}
-func (p *Person) PostInsert(s SqlExecutor) error {
+func (p *Person) PostInsert(s gorp.SqlExecutor) error {
p.LName = "postinsert"
return nil
}
-func (p *Person) PreUpdate(s SqlExecutor) error {
+func (p *Person) PreUpdate(s gorp.SqlExecutor) error {
p.FName = "preupdate"
return nil
}
-func (p *Person) PostUpdate(s SqlExecutor) error {
+func (p *Person) PostUpdate(s gorp.SqlExecutor) error {
p.LName = "postupdate"
return nil
}
-func (p *Person) PreDelete(s SqlExecutor) error {
+func (p *Person) PreDelete(s gorp.SqlExecutor) error {
p.FName = "predelete"
return nil
}
-func (p *Person) PostDelete(s SqlExecutor) error {
+func (p *Person) PostDelete(s gorp.SqlExecutor) error {
p.LName = "postdelete"
return nil
}
-func (p *Person) PostGet(s SqlExecutor) error {
+func (p *Person) PostGet(s gorp.SqlExecutor) error {
p.LName = "postget"
return nil
}
@@ -392,6 +404,281 @@ type PersistentUser struct {
PassedTraining bool
}
+type TenantDynamic struct {
+ Id int64 `db:"id"`
+ Name string
+ Address string
+ curTable string `db:"-"`
+}
+
+func (curObj *TenantDynamic) TableName() string {
+ return curObj.curTable
+}
+func (curObj *TenantDynamic) SetTableName(tblName string) {
+ curObj.curTable = tblName
+}
+
+var dynTableInst1 = TenantDynamic{curTable: "t_1_tenant_dynamic"}
+var dynTableInst2 = TenantDynamic{curTable: "t_2_tenant_dynamic"}
+
+func dynamicTablesTest(t *testing.T, dbmap *gorp.DbMap) {
+
+ dynamicTablesTestTableMap(t, dbmap, &dynTableInst1)
+ dynamicTablesTestTableMap(t, dbmap, &dynTableInst2)
+
+ // TEST - dbmap.Insert using dynTableInst1
+ dynTableInst1.Name = "Test Name 1"
+ dynTableInst1.Address = "Test Address 1"
+ err := dbmap.Insert(&dynTableInst1)
+ if err != nil {
+ t.Errorf("Errow while saving dynTableInst1. Details: %v", err)
+ }
+
+ // TEST - dbmap.Insert using dynTableInst2
+ dynTableInst2.Name = "Test Name 2"
+ dynTableInst2.Address = "Test Address 2"
+ err = dbmap.Insert(&dynTableInst2)
+ if err != nil {
+ t.Errorf("Errow while saving dynTableInst2. Details: %v", err)
+ }
+
+ dynamicTablesTestSelect(t, dbmap, &dynTableInst1)
+ dynamicTablesTestSelect(t, dbmap, &dynTableInst2)
+ dynamicTablesTestSelectOne(t, dbmap, &dynTableInst1)
+ dynamicTablesTestSelectOne(t, dbmap, &dynTableInst2)
+ dynamicTablesTestGetUpdateGet(t, dbmap, &dynTableInst1)
+ dynamicTablesTestGetUpdateGet(t, dbmap, &dynTableInst2)
+ dynamicTablesTestDelete(t, dbmap, &dynTableInst1)
+ dynamicTablesTestDelete(t, dbmap, &dynTableInst2)
+
+}
+
+func dynamicTablesTestTableMap(t *testing.T,
+ dbmap *gorp.DbMap,
+ inpInst *TenantDynamic) {
+
+ tableName := inpInst.TableName()
+
+ tblMap, err := dbmap.DynamicTableFor(tableName, true)
+ if err != nil {
+ t.Errorf("Error while searching for tablemap for tableName: %v, Error:%v", tableName, err)
+ }
+ if tblMap == nil {
+ t.Errorf("Unable to find tablemap for tableName:%v", tableName)
+ }
+}
+
+func dynamicTablesTestSelect(t *testing.T,
+ dbmap *gorp.DbMap,
+ inpInst *TenantDynamic) {
+
+ // TEST - dbmap.Select using inpInst
+
+ // read the data back from dynInst to see if the
+ // table mapping is correct
+ var dbTenantInst1 = TenantDynamic{curTable: inpInst.curTable}
+ selectSQL1 := "select * from " + inpInst.curTable
+ dbObjs, err := dbmap.Select(&dbTenantInst1, selectSQL1)
+ if err != nil {
+ t.Errorf("Errow in dbmap.Select. SQL: %v, Details: %v", selectSQL1, err)
+ }
+ if dbObjs == nil {
+ t.Fatalf("Nil return from dbmap.Select")
+ }
+ rwCnt := len(dbObjs)
+ if rwCnt != 1 {
+ t.Errorf("Unexpected row count for tenantInst:%v", rwCnt)
+ }
+
+ dbInst := dbObjs[0].(*TenantDynamic)
+
+ inpTableName := inpInst.TableName()
+ resTableName := dbInst.TableName()
+ if inpTableName != resTableName {
+ t.Errorf("Mismatched table names %v != %v ",
+ inpTableName, resTableName)
+ }
+
+ if inpInst.Id != dbInst.Id {
+ t.Errorf("Mismatched Id values %v != %v ",
+ inpInst.Id, dbInst.Id)
+ }
+
+ if inpInst.Name != dbInst.Name {
+ t.Errorf("Mismatched Name values %v != %v ",
+ inpInst.Name, dbInst.Name)
+ }
+
+ if inpInst.Address != dbInst.Address {
+ t.Errorf("Mismatched Address values %v != %v ",
+ inpInst.Address, dbInst.Address)
+ }
+}
+
+func dynamicTablesTestGetUpdateGet(t *testing.T,
+ dbmap *gorp.DbMap,
+ inpInst *TenantDynamic) {
+
+ // TEST - dbmap.Get, dbmap.Update, dbmap.Get sequence
+
+ // read and update one of the instances to make sure
+ // that the common gorp APIs are working well with dynamic table
+ var inpIface2 = TenantDynamic{curTable: inpInst.curTable}
+ dbObj, err := dbmap.Get(&inpIface2, inpInst.Id)
+ if err != nil {
+ t.Errorf("Errow in dbmap.Get. id: %v, Details: %v", inpInst.Id, err)
+ }
+ if dbObj == nil {
+ t.Errorf("Nil return from dbmap.Get")
+ }
+
+ dbInst := dbObj.(*TenantDynamic)
+
+ {
+ inpTableName := inpInst.TableName()
+ resTableName := dbInst.TableName()
+ if inpTableName != resTableName {
+ t.Errorf("Mismatched table names %v != %v ",
+ inpTableName, resTableName)
+ }
+
+ if inpInst.Id != dbInst.Id {
+ t.Errorf("Mismatched Id values %v != %v ",
+ inpInst.Id, dbInst.Id)
+ }
+
+ if inpInst.Name != dbInst.Name {
+ t.Errorf("Mismatched Name values %v != %v ",
+ inpInst.Name, dbInst.Name)
+ }
+
+ if inpInst.Address != dbInst.Address {
+ t.Errorf("Mismatched Address values %v != %v ",
+ inpInst.Address, dbInst.Address)
+ }
+ }
+
+ {
+ updatedName := "Testing Updated Name2"
+ dbInst.Name = updatedName
+ cnt, err := dbmap.Update(dbInst)
+ if err != nil {
+ t.Errorf("Error from dbmap.Update: %v", err.Error())
+ }
+ if cnt != 1 {
+ t.Errorf("Update count must be 1, got %v", cnt)
+ }
+
+ // Read the object again to make sure that the
+ // data was updated in db
+ dbObj2, err := dbmap.Get(&inpIface2, inpInst.Id)
+ if err != nil {
+ t.Errorf("Errow in dbmap.Get. id: %v, Details: %v", inpInst.Id, err)
+ }
+ if dbObj2 == nil {
+ t.Errorf("Nil return from dbmap.Get")
+ }
+
+ dbInst2 := dbObj2.(*TenantDynamic)
+
+ inpTableName := inpInst.TableName()
+ resTableName := dbInst2.TableName()
+ if inpTableName != resTableName {
+ t.Errorf("Mismatched table names %v != %v ",
+ inpTableName, resTableName)
+ }
+
+ if inpInst.Id != dbInst2.Id {
+ t.Errorf("Mismatched Id values %v != %v ",
+ inpInst.Id, dbInst2.Id)
+ }
+
+ if updatedName != dbInst2.Name {
+ t.Errorf("Mismatched Name values %v != %v ",
+ updatedName, dbInst2.Name)
+ }
+
+ if inpInst.Address != dbInst.Address {
+ t.Errorf("Mismatched Address values %v != %v ",
+ inpInst.Address, dbInst.Address)
+ }
+
+ }
+}
+
+func dynamicTablesTestSelectOne(t *testing.T,
+ dbmap *gorp.DbMap,
+ inpInst *TenantDynamic) {
+
+ // TEST - dbmap.SelectOne
+
+ // read the data back from inpInst to see if the
+ // table mapping is correct
+ var dbTenantInst1 = TenantDynamic{curTable: inpInst.curTable}
+ selectSQL1 := "select * from " + dbTenantInst1.curTable + " where id = :idKey"
+ params := map[string]interface{}{"idKey": inpInst.Id}
+ err := dbmap.SelectOne(&dbTenantInst1, selectSQL1, params)
+ if err != nil {
+ t.Errorf("Errow in dbmap.SelectOne. SQL: %v, Details: %v", selectSQL1, err)
+ }
+
+ inpTableName := inpInst.curTable
+ resTableName := dbTenantInst1.TableName()
+ if inpTableName != resTableName {
+ t.Errorf("Mismatched table names %v != %v ",
+ inpTableName, resTableName)
+ }
+
+ if inpInst.Id != dbTenantInst1.Id {
+ t.Errorf("Mismatched Id values %v != %v ",
+ inpInst.Id, dbTenantInst1.Id)
+ }
+
+ if inpInst.Name != dbTenantInst1.Name {
+ t.Errorf("Mismatched Name values %v != %v ",
+ inpInst.Name, dbTenantInst1.Name)
+ }
+
+ if inpInst.Address != dbTenantInst1.Address {
+ t.Errorf("Mismatched Address values %v != %v ",
+ inpInst.Address, dbTenantInst1.Address)
+ }
+}
+
+func dynamicTablesTestDelete(t *testing.T,
+ dbmap *gorp.DbMap,
+ inpInst *TenantDynamic) {
+
+ // TEST - dbmap.Delete
+ cnt, err := dbmap.Delete(inpInst)
+ if err != nil {
+ t.Errorf("Errow in dbmap.Delete. Details: %v", err)
+ }
+ if cnt != 1 {
+ t.Errorf("Expected delete count for %v : 1, found count:%v",
+ inpInst.TableName(), cnt)
+ }
+
+ // Try reading again to make sure instance is gone from db
+ getInst := TenantDynamic{curTable: inpInst.TableName()}
+ dbInst, err := dbmap.Get(&getInst, inpInst.Id)
+ if err != nil {
+ t.Errorf("Error while trying to read deleted %v object using id: %v",
+ inpInst.TableName(), inpInst.Id)
+ }
+
+ if dbInst != nil {
+ t.Errorf("Found deleted %v instance using id: %v",
+ inpInst.TableName(), inpInst.Id)
+ }
+
+ if getInst.Name != "" {
+ t.Errorf("Found data from deleted %v instance using id: %v",
+ inpInst.TableName(), inpInst.Id)
+ }
+
+}
+
func TestCreateTablesIfNotExists(t *testing.T) {
dbmap := initDbMap()
defer dropAndClose(dbmap)
@@ -569,7 +856,7 @@ func TestPersistentUser(t *testing.T) {
t.Errorf("%v!=%v", pu, pu2)
}
- arr, err := dbmap.Select(pu, "select * from PersistentUser")
+ arr, err := dbmap.Select(pu, "select * from "+tableName(dbmap, PersistentUser{}))
if err != nil {
panic(err)
}
@@ -579,7 +866,7 @@ func TestPersistentUser(t *testing.T) {
// prove we can get the results back in a slice
var puArr []*PersistentUser
- _, err = dbmap.Select(&puArr, "select * from PersistentUser")
+ _, err = dbmap.Select(&puArr, "select * from "+tableName(dbmap, PersistentUser{}))
if err != nil {
panic(err)
}
@@ -592,7 +879,7 @@ func TestPersistentUser(t *testing.T) {
// prove we can get the results back in a non-pointer slice
var puValues []PersistentUser
- _, err = dbmap.Select(&puValues, "select * from PersistentUser")
+ _, err = dbmap.Select(&puValues, "select * from "+tableName(dbmap, PersistentUser{}))
if err != nil {
panic(err)
}
@@ -605,7 +892,7 @@ func TestPersistentUser(t *testing.T) {
// prove we can get the results back in a string slice
var idArr []*string
- _, err = dbmap.Select(&idArr, "select Id from PersistentUser")
+ _, err = dbmap.Select(&idArr, "select "+columnName(dbmap, PersistentUser{}, "Id")+" from "+tableName(dbmap, PersistentUser{}))
if err != nil {
panic(err)
}
@@ -618,7 +905,7 @@ func TestPersistentUser(t *testing.T) {
// prove we can get the results back in an int slice
var keyArr []*int32
- _, err = dbmap.Select(&keyArr, "select mykey from PersistentUser")
+ _, err = dbmap.Select(&keyArr, "select mykey from "+tableName(dbmap, PersistentUser{}))
if err != nil {
panic(err)
}
@@ -631,7 +918,7 @@ func TestPersistentUser(t *testing.T) {
// prove we can get the results back in a bool slice
var passedArr []*bool
- _, err = dbmap.Select(&passedArr, "select PassedTraining from PersistentUser")
+ _, err = dbmap.Select(&passedArr, "select "+columnName(dbmap, PersistentUser{}, "PassedTraining")+" from "+tableName(dbmap, PersistentUser{}))
if err != nil {
panic(err)
}
@@ -644,7 +931,7 @@ func TestPersistentUser(t *testing.T) {
// prove we can get the results back in a non-pointer slice
var stringArr []string
- _, err = dbmap.Select(&stringArr, "select Id from PersistentUser")
+ _, err = dbmap.Select(&stringArr, "select "+columnName(dbmap, PersistentUser{}, "Id")+" from "+tableName(dbmap, PersistentUser{}))
if err != nil {
panic(err)
}
@@ -675,7 +962,7 @@ func TestNamedQueryMap(t *testing.T) {
// Test simple case
var puArr []*PersistentUser
- _, err = dbmap.Select(&puArr, "select * from PersistentUser where mykey = :Key", map[string]interface{}{
+ _, err = dbmap.Select(&puArr, "select * from "+tableName(dbmap, PersistentUser{})+" where mykey = :Key", map[string]interface{}{
"Key": 43,
})
if err != nil {
@@ -691,7 +978,7 @@ func TestNamedQueryMap(t *testing.T) {
// Test more specific map value type is ok
puArr = nil
- _, err = dbmap.Select(&puArr, "select * from PersistentUser where mykey = :Key", map[string]int{
+ _, err = dbmap.Select(&puArr, "select * from "+tableName(dbmap, PersistentUser{})+" where mykey = :Key", map[string]int{
"Key": 43,
})
if err != nil {
@@ -705,10 +992,10 @@ func TestNamedQueryMap(t *testing.T) {
// Test multiple parameters set.
puArr = nil
_, err = dbmap.Select(&puArr, `
-select * from PersistentUser
+select * from `+tableName(dbmap, PersistentUser{})+`
where mykey = :Key
- and PassedTraining = :PassedTraining
- and Id = :Id`, map[string]interface{}{
+ and `+columnName(dbmap, PersistentUser{}, "PassedTraining")+` = :PassedTraining
+ and `+columnName(dbmap, PersistentUser{}, "Id")+` = :Id`, map[string]interface{}{
"Key": 43,
"PassedTraining": false,
"Id": "33r",
@@ -725,9 +1012,9 @@ select * from PersistentUser
// Test having extra, unused properties in the map.
puArr = nil
_, err = dbmap.Select(&puArr, `
-select * from PersistentUser
+select * from `+tableName(dbmap, PersistentUser{})+`
where mykey = :Key
- and Id != 'abc:def'`, map[string]interface{}{
+ and `+columnName(dbmap, PersistentUser{}, "Id")+` != 'abc:def'`, map[string]interface{}{
"Key": 43,
"PassedTraining": false,
})
@@ -740,7 +1027,7 @@ select * from PersistentUser
}
// Test to delete with Exec and named params.
- result, err := dbmap.Exec("delete from PersistentUser where mykey = :Key", map[string]interface{}{
+ result, err := dbmap.Exec("delete from "+tableName(dbmap, PersistentUser{})+" where mykey = :Key", map[string]interface{}{
"Key": 43,
})
count, err := result.RowsAffected()
@@ -773,10 +1060,10 @@ func TestNamedQueryStruct(t *testing.T) {
// Test select self
var puArr []*PersistentUser
_, err = dbmap.Select(&puArr, `
-select * from PersistentUser
+select * from `+tableName(dbmap, PersistentUser{})+`
where mykey = :Key
- and PassedTraining = :PassedTraining
- and Id = :Id`, pu)
+ and `+columnName(dbmap, PersistentUser{}, "PassedTraining")+` = :PassedTraining
+ and `+columnName(dbmap, PersistentUser{}, "Id")+` = :Id`, pu)
if err != nil {
t.Errorf("Failed to select: %s", err)
t.FailNow()
@@ -790,10 +1077,10 @@ select * from PersistentUser
// Test delete self.
result, err := dbmap.Exec(`
-delete from PersistentUser
+delete from `+tableName(dbmap, PersistentUser{})+`
where mykey = :Key
- and PassedTraining = :PassedTraining
- and Id = :Id`, pu)
+ and `+columnName(dbmap, PersistentUser{}, "PassedTraining")+` = :PassedTraining
+ and `+columnName(dbmap, PersistentUser{}, "Id")+` = :Id`, pu)
count, err := result.RowsAffected()
if err != nil {
t.Errorf("Failed to exec: %s", err)
@@ -808,14 +1095,14 @@ delete from PersistentUser
func TestReturnsNonNilSlice(t *testing.T) {
dbmap := initDbMap()
defer dropAndClose(dbmap)
- noResultsSQL := "select * from invoice_test where id=99999"
+ noResultsSQL := "select * from invoice_test where " + columnName(dbmap, Invoice{}, "Id") + "=99999"
var r1 []*Invoice
- _rawselect(dbmap, &r1, noResultsSQL)
+ rawSelect(dbmap, &r1, noResultsSQL)
if r1 == nil {
t.Errorf("r1==nil")
}
- r2 := _rawselect(dbmap, Invoice{}, noResultsSQL)
+ r2 := rawSelect(dbmap, Invoice{}, noResultsSQL)
if r2 == nil {
t.Errorf("r2==nil")
}
@@ -869,16 +1156,16 @@ func TestOptimisticLocking(t *testing.T) {
p1.LName = "Howard"
count, err := dbmap.Update(p1)
- if _, ok := err.(OptimisticLockError); !ok {
- t.Errorf("update - Expected OptimisticLockError, got: %v", err)
+ if _, ok := err.(gorp.OptimisticLockError); !ok {
+ t.Errorf("update - Expected gorp.OptimisticLockError, got: %v", err)
}
if count != -1 {
t.Errorf("update - Expected -1 count, got: %d", count)
}
count, err = dbmap.Delete(p1)
- if _, ok := err.(OptimisticLockError); !ok {
- t.Errorf("delete - Expected OptimisticLockError, got: %v", err)
+ if _, ok := err.(gorp.OptimisticLockError); !ok {
+ t.Errorf("delete - Expected gorp.OptimisticLockError, got: %v", err)
}
if count != -1 {
t.Errorf("delete - Expected -1 count, got: %d", count)
@@ -901,7 +1188,7 @@ func TestNullValues(t *testing.T) {
defer dropAndClose(dbmap)
// insert a row directly
- _rawexec(dbmap, "insert into TableWithNull values (10, null, "+
+ rawExec(dbmap, "insert into "+tableName(dbmap, TableWithNull{})+" values (10, null, "+
"null, null, null, null)")
// try to load it
@@ -1025,10 +1312,10 @@ func TestRawSelect(t *testing.T) {
expected := &InvoicePersonView{inv1.Id, p1.Id, inv1.Memo, p1.FName, 0}
- query := "select i.Id InvoiceId, p.Id PersonId, i.Memo, p.FName " +
+ query := "select i." + columnName(dbmap, Invoice{}, "Id") + " InvoiceId, p." + columnName(dbmap, Person{}, "Id") + " PersonId, i." + columnName(dbmap, Invoice{}, "Memo") + ", p." + columnName(dbmap, Person{}, "FName") + " " +
"from invoice_test i, person_test p " +
- "where i.PersonId = p.Id"
- list := _rawselect(dbmap, InvoicePersonView{}, query)
+ "where i." + columnName(dbmap, Invoice{}, "PersonId") + " = p." + columnName(dbmap, Person{}, "Id")
+ list := rawSelect(dbmap, InvoicePersonView{}, query)
if len(list) != 1 {
t.Errorf("len(list) != 1: %d", len(list))
} else if !reflect.DeepEqual(expected, list[0]) {
@@ -1063,7 +1350,7 @@ func TestHooks(t *testing.T) {
var persons []*Person
bindVar := dbmap.Dialect.BindVar(0)
- _rawselect(dbmap, &persons, "select * from person_test where id = "+bindVar, p1.Id)
+ rawSelect(dbmap, &persons, "select * from person_test where "+columnName(dbmap, Person{}, "Id")+" = "+bindVar, p1.Id)
if persons[0].LName != "postget" {
t.Errorf("p1.PostGet() didn't run after select: %v", p1)
}
@@ -1129,7 +1416,7 @@ func TestSavepoint(t *testing.T) {
trans.Insert(inv1)
var checkMemo = func(want string) {
- memo, err := trans.SelectStr("select memo from invoice_test")
+ memo, err := trans.SelectStr("select " + columnName(dbmap, Invoice{}, "Memo") + " from invoice_test")
if err != nil {
panic(err)
}
@@ -1194,10 +1481,12 @@ func TestCrud(t *testing.T) {
foo := &AliasTransientField{BarStr: "some bar"}
testCrudInternal(t, dbmap, foo)
+
+ dynamicTablesTest(t, dbmap)
}
-func testCrudInternal(t *testing.T, dbmap *DbMap, val testable) {
- table, _, err := dbmap.tableForPointer(val, false)
+func testCrudInternal(t *testing.T, dbmap *gorp.DbMap, val testable) {
+ table, err := dbmap.TableFor(reflect.TypeOf(val).Elem(), false)
if err != nil {
t.Errorf("couldn't call TableFor: val=%v err=%v", val, err)
}
@@ -1232,11 +1521,11 @@ func testCrudInternal(t *testing.T, dbmap *DbMap, val testable) {
}
// Select *
- rows, err := dbmap.Select(val, "select * from "+table.TableName)
+ rows, err := dbmap.Select(val, "select * from "+dbmap.Dialect.QuoteField(table.TableName))
if err != nil {
- t.Errorf("couldn't select * from %s err=%v", table.TableName, err)
+ t.Errorf("couldn't select * from %s err=%v", dbmap.Dialect.QuoteField(table.TableName), err)
} else if len(rows) != 1 {
- t.Errorf("unexpected row count in %s: %d", table.TableName, len(rows))
+ t.Errorf("unexpected row count in %s: %d", dbmap.Dialect.QuoteField(table.TableName), len(rows))
} else if !reflect.DeepEqual(val, rows[0]) {
t.Errorf("select * result: %v != %v", val, rows[0])
}
@@ -1285,7 +1574,7 @@ func TestColumnFilter(t *testing.T) {
inv1.Memo = "c"
inv1.IsPaid = true
- _updateColumns(dbmap, func(col *ColumnMap) bool {
+ _updateColumns(dbmap, func(col *gorp.ColumnMap) bool {
return col.ColumnName == "Memo"
}, inv1)
@@ -1349,7 +1638,7 @@ func TestWithEmbeddedStruct(t *testing.T) {
t.Errorf("%v != %v", expected, es2)
}
- ess := _rawselect(dbmap, WithEmbeddedStruct{}, "select * from embedded_struct_test")
+ ess := rawSelect(dbmap, WithEmbeddedStruct{}, "select * from embedded_struct_test")
if !reflect.DeepEqual(es2, ess[0]) {
t.Errorf("%v != %v", es2, ess[0])
}
@@ -1376,7 +1665,7 @@ func TestWithEmbeddedStructConflictingEmbeddedMemberNames(t *testing.T) {
t.Errorf("%v != %v", expected, es2)
}
- ess := _rawselect(dbmap, WithEmbeddedStructConflictingEmbeddedMemberNames{}, "select * from embedded_struct_conflict_name_test")
+ ess := rawSelect(dbmap, WithEmbeddedStructConflictingEmbeddedMemberNames{}, "select * from embedded_struct_conflict_name_test")
if !reflect.DeepEqual(es2, ess[0]) {
t.Errorf("%v != %v", es2, ess[0])
}
@@ -1402,7 +1691,7 @@ func TestWithEmbeddedStructSameMemberName(t *testing.T) {
t.Errorf("%v != %v", expected, es2)
}
- ess := _rawselect(dbmap, WithEmbeddedStructSameMemberName{}, "select * from embedded_struct_same_member_name_test")
+ ess := rawSelect(dbmap, WithEmbeddedStructSameMemberName{}, "select * from embedded_struct_same_member_name_test")
if !reflect.DeepEqual(es2, ess[0]) {
t.Errorf("%v != %v", es2, ess[0])
}
@@ -1450,81 +1739,81 @@ func TestSelectVal(t *testing.T) {
_insert(dbmap, &t1)
// SelectInt
- i64 := selectInt(dbmap, "select Int64 from TableWithNull where Str='abc'")
+ i64 := selectInt(dbmap, "select "+columnName(dbmap, TableWithNull{}, "Int64")+" from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Str")+"='abc'")
if i64 != 78 {
t.Errorf("int64 %d != 78", i64)
}
- i64 = selectInt(dbmap, "select count(*) from TableWithNull")
+ i64 = selectInt(dbmap, "select count(*) from "+tableName(dbmap, TableWithNull{}))
if i64 != 1 {
t.Errorf("int64 count %d != 1", i64)
}
- i64 = selectInt(dbmap, "select count(*) from TableWithNull where Str="+bindVar, "asdfasdf")
+ i64 = selectInt(dbmap, "select count(*) from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Str")+"="+bindVar, "asdfasdf")
if i64 != 0 {
t.Errorf("int64 no rows %d != 0", i64)
}
// SelectNullInt
- n := selectNullInt(dbmap, "select Int64 from TableWithNull where Str='notfound'")
+ n := selectNullInt(dbmap, "select "+columnName(dbmap, TableWithNull{}, "Int64")+" from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Str")+"='notfound'")
if !reflect.DeepEqual(n, sql.NullInt64{0, false}) {
t.Errorf("nullint %v != 0,false", n)
}
- n = selectNullInt(dbmap, "select Int64 from TableWithNull where Str='abc'")
+ n = selectNullInt(dbmap, "select "+columnName(dbmap, TableWithNull{}, "Int64")+" from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Str")+"='abc'")
if !reflect.DeepEqual(n, sql.NullInt64{78, true}) {
t.Errorf("nullint %v != 78, true", n)
}
// SelectFloat
- f64 := selectFloat(dbmap, "select Float64 from TableWithNull where Str='abc'")
+ f64 := selectFloat(dbmap, "select "+columnName(dbmap, TableWithNull{}, "Float64")+" from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Str")+"='abc'")
if f64 != 32.2 {
t.Errorf("float64 %d != 32.2", f64)
}
- f64 = selectFloat(dbmap, "select min(Float64) from TableWithNull")
+ f64 = selectFloat(dbmap, "select min("+columnName(dbmap, TableWithNull{}, "Float64")+") from "+tableName(dbmap, TableWithNull{}))
if f64 != 32.2 {
t.Errorf("float64 min %d != 32.2", f64)
}
- f64 = selectFloat(dbmap, "select count(*) from TableWithNull where Str="+bindVar, "asdfasdf")
+ f64 = selectFloat(dbmap, "select count(*) from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Str")+"="+bindVar, "asdfasdf")
if f64 != 0 {
t.Errorf("float64 no rows %d != 0", f64)
}
// SelectNullFloat
- nf := selectNullFloat(dbmap, "select Float64 from TableWithNull where Str='notfound'")
+ nf := selectNullFloat(dbmap, "select "+columnName(dbmap, TableWithNull{}, "Float64")+" from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Str")+"='notfound'")
if !reflect.DeepEqual(nf, sql.NullFloat64{0, false}) {
t.Errorf("nullfloat %v != 0,false", nf)
}
- nf = selectNullFloat(dbmap, "select Float64 from TableWithNull where Str='abc'")
+ nf = selectNullFloat(dbmap, "select "+columnName(dbmap, TableWithNull{}, "Float64")+" from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Str")+"='abc'")
if !reflect.DeepEqual(nf, sql.NullFloat64{32.2, true}) {
t.Errorf("nullfloat %v != 32.2, true", nf)
}
// SelectStr
- s := selectStr(dbmap, "select Str from TableWithNull where Int64="+bindVar, 78)
+ s := selectStr(dbmap, "select "+columnName(dbmap, TableWithNull{}, "Str")+" from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Int64")+"="+bindVar, 78)
if s != "abc" {
t.Errorf("s %s != abc", s)
}
- s = selectStr(dbmap, "select Str from TableWithNull where Str='asdfasdf'")
+ s = selectStr(dbmap, "select "+columnName(dbmap, TableWithNull{}, "Str")+" from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Str")+"='asdfasdf'")
if s != "" {
t.Errorf("s no rows %s != ''", s)
}
// SelectNullStr
- ns := selectNullStr(dbmap, "select Str from TableWithNull where Int64="+bindVar, 78)
+ ns := selectNullStr(dbmap, "select "+columnName(dbmap, TableWithNull{}, "Str")+" from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Int64")+"="+bindVar, 78)
if !reflect.DeepEqual(ns, sql.NullString{"abc", true}) {
t.Errorf("nullstr %v != abc,true", ns)
}
- ns = selectNullStr(dbmap, "select Str from TableWithNull where Str='asdfasdf'")
+ ns = selectNullStr(dbmap, "select "+columnName(dbmap, TableWithNull{}, "Str")+" from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Str")+"='asdfasdf'")
if !reflect.DeepEqual(ns, sql.NullString{"", false}) {
t.Errorf("nullstr no rows %v != '',false", ns)
}
// SelectInt/Str with named parameters
- i64 = selectInt(dbmap, "select Int64 from TableWithNull where Str=:abc", map[string]string{"abc": "abc"})
+ i64 = selectInt(dbmap, "select "+columnName(dbmap, TableWithNull{}, "Int64")+" from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Str")+"=:abc", map[string]string{"abc": "abc"})
if i64 != 78 {
t.Errorf("int64 %d != 78", i64)
}
- ns = selectNullStr(dbmap, "select Str from TableWithNull where Int64=:num", map[string]int{"num": 78})
+ ns = selectNullStr(dbmap, "select "+columnName(dbmap, TableWithNull{}, "Str")+" from "+tableName(dbmap, TableWithNull{})+" where "+columnName(dbmap, TableWithNull{}, "Int64")+"=:num", map[string]int{"num": 78})
if !reflect.DeepEqual(ns, sql.NullString{"abc", true}) {
t.Errorf("nullstr %v != abc,true", ns)
}
@@ -1565,12 +1854,12 @@ func TestWithStringPk(t *testing.T) {
}
}
-// TestSqlExecutorInterfaceSelects ensures that all DbMap methods starting with Select...
-// are also exposed in the SqlExecutor interface. Select... functions can always
+// TestSqlExecutorInterfaceSelects ensures that all gorp.DbMap methods starting with Select...
+// are also exposed in the gorp.SqlExecutor interface. Select... functions can always
// run on Pre/Post hooks.
func TestSqlExecutorInterfaceSelects(t *testing.T) {
- dbMapType := reflect.TypeOf(&DbMap{})
- sqlExecutorType := reflect.TypeOf((*SqlExecutor)(nil)).Elem()
+ dbMapType := reflect.TypeOf(&gorp.DbMap{})
+ sqlExecutorType := reflect.TypeOf((*gorp.SqlExecutor)(nil)).Elem()
numDbMapMethods := dbMapType.NumMethod()
for i := 0; i < numDbMapMethods; i += 1 {
dbMapMethod := dbMapType.Method(i)
@@ -1578,7 +1867,7 @@ func TestSqlExecutorInterfaceSelects(t *testing.T) {
continue
}
if _, found := sqlExecutorType.MethodByName(dbMapMethod.Name); !found {
- t.Errorf("Method %s is defined on DbMap but not implemented in SqlExecutor",
+ t.Errorf("Method %s is defined on gorp.DbMap but not implemented in gorp.SqlExecutor",
dbMapMethod.Name)
}
}
@@ -1591,28 +1880,28 @@ func TestNullTime(t *testing.T) {
// if time is null
ent := &WithNullTime{
Id: 0,
- Time: NullTime{
+ Time: gorp.NullTime{
Valid: false,
}}
err := dbmap.Insert(ent)
if err != nil {
t.Error("failed insert on %s", err.Error())
}
- err = dbmap.SelectOne(ent, `select * from nulltime_test where Id=:Id`, map[string]interface{}{
+ err = dbmap.SelectOne(ent, `select * from nulltime_test where `+columnName(dbmap, WithNullTime{}, "Id")+`=:Id`, map[string]interface{}{
"Id": ent.Id,
})
if err != nil {
t.Error("failed select on %s", err.Error())
}
if ent.Time.Valid {
- t.Error("NullTime returns valid but expected null.")
+ t.Error("gorp.NullTime returns valid but expected null.")
}
// if time is not null
ts, err := time.Parse(time.Stamp, "Jan 2 15:04:05")
ent = &WithNullTime{
Id: 1,
- Time: NullTime{
+ Time: gorp.NullTime{
Valid: true,
Time: ts,
}}
@@ -1620,14 +1909,14 @@ func TestNullTime(t *testing.T) {
if err != nil {
t.Error("failed insert on %s", err.Error())
}
- err = dbmap.SelectOne(ent, `select * from nulltime_test where Id=:Id`, map[string]interface{}{
+ err = dbmap.SelectOne(ent, `select * from nulltime_test where `+columnName(dbmap, WithNullTime{}, "Id")+`=:Id`, map[string]interface{}{
"Id": ent.Id,
})
if err != nil {
t.Error("failed select on %s", err.Error())
}
if !ent.Time.Valid {
- t.Error("NullTime returns invalid but expected valid.")
+ t.Error("gorp.NullTime returns invalid but expected valid.")
}
if ent.Time.Time.UTC() != ts.UTC() {
t.Errorf("expect %v but got %v.", ts, ent.Time.Time)
@@ -1712,7 +2001,7 @@ func TestWithTimeSelect(t *testing.T) {
_insert(dbmap, &w1, &w2)
var caseIds []int64
- _, err := dbmap.Select(&caseIds, "SELECT id FROM time_test WHERE Time < "+dbmap.Dialect.BindVar(0), halfhourago)
+ _, err := dbmap.Select(&caseIds, "SELECT "+columnName(dbmap, WithTime{}, "Id")+" FROM time_test WHERE "+columnName(dbmap, WithTime{}, "Time")+" < "+dbmap.Dialect.BindVar(0), halfhourago)
if err != nil {
t.Error(err)
@@ -1738,9 +2027,9 @@ func TestInvoicePersonView(t *testing.T) {
dbmap.Insert(inv1)
// Run your query
- query := "select i.Id InvoiceId, p.Id PersonId, i.Memo, p.FName " +
+ query := "select i." + columnName(dbmap, Invoice{}, "Id") + " InvoiceId, p." + columnName(dbmap, Person{}, "Id") + " PersonId, i." + columnName(dbmap, Invoice{}, "Memo") + ", p." + columnName(dbmap, Person{}, "FName") + " " +
"from invoice_test i, person_test p " +
- "where i.PersonId = p.Id"
+ "where i." + columnName(dbmap, Invoice{}, "PersonId") + " = p." + columnName(dbmap, Person{}, "Id")
// pass a slice of pointers to Select()
// this avoids the need to type assert after the query is run
@@ -1805,9 +2094,9 @@ func TestSelectTooManyCols(t *testing.T) {
}
var p3 FNameOnly
- err := dbmap.SelectOne(&p3, "select * from person_test where Id=:Id", params)
+ err := dbmap.SelectOne(&p3, "select * from person_test where "+columnName(dbmap, Person{}, "Id")+"=:Id", params)
if err != nil {
- if !NonFatalError(err) {
+ if !gorp.NonFatalError(err) {
t.Error(err)
}
} else {
@@ -1819,9 +2108,9 @@ func TestSelectTooManyCols(t *testing.T) {
}
var pSlice []FNameOnly
- _, err = dbmap.Select(&pSlice, "select * from person_test order by fname asc")
+ _, err = dbmap.Select(&pSlice, "select * from person_test order by "+columnName(dbmap, Person{}, "FName")+" asc")
if err != nil {
- if !NonFatalError(err) {
+ if !gorp.NonFatalError(err) {
t.Error(err)
}
} else {
@@ -1851,7 +2140,7 @@ func TestSelectSingleVal(t *testing.T) {
}
var p2 Person
- err := dbmap.SelectOne(&p2, "select * from person_test where Id=:Id", params)
+ err := dbmap.SelectOne(&p2, "select * from person_test where "+columnName(dbmap, Person{}, "Id")+"=:Id", params)
if err != nil {
t.Error(err)
}
@@ -1862,7 +2151,7 @@ func TestSelectSingleVal(t *testing.T) {
// verify SelectOne allows non-struct holders
var s string
- err = dbmap.SelectOne(&s, "select FName from person_test where Id=:Id", params)
+ err = dbmap.SelectOne(&s, "select "+columnName(dbmap, Person{}, "FName")+" from person_test where "+columnName(dbmap, Person{}, "Id")+"=:Id", params)
if err != nil {
t.Error(err)
}
@@ -1871,14 +2160,14 @@ func TestSelectSingleVal(t *testing.T) {
}
// verify SelectOne requires pointer receiver
- err = dbmap.SelectOne(s, "select FName from person_test where Id=:Id", params)
+ err = dbmap.SelectOne(s, "select "+columnName(dbmap, Person{}, "FName")+" from person_test where "+columnName(dbmap, Person{}, "Id")+"=:Id", params)
if err == nil {
t.Error("SelectOne should have returned error for non-pointer holder")
}
// verify SelectOne works with uninitialized pointers
var p3 *Person
- err = dbmap.SelectOne(&p3, "select * from person_test where Id=:Id", params)
+ err = dbmap.SelectOne(&p3, "select * from person_test where "+columnName(dbmap, Person{}, "Id")+"=:Id", params)
if err != nil {
t.Error(err)
}
@@ -1889,13 +2178,13 @@ func TestSelectSingleVal(t *testing.T) {
// verify that the receiver is still nil if nothing was found
var p4 *Person
- dbmap.SelectOne(&p3, "select * from person_test where 2<1 AND Id=:Id", params)
+ dbmap.SelectOne(&p3, "select * from person_test where 2<1 AND "+columnName(dbmap, Person{}, "Id")+"=:Id", params)
if p4 != nil {
t.Error("SelectOne should not have changed a nil receiver when no rows were found")
}
// verify that the error is set to sql.ErrNoRows if not found
- err = dbmap.SelectOne(&p2, "select * from person_test where Id=:Id", map[string]interface{}{
+ err = dbmap.SelectOne(&p2, "select * from person_test where "+columnName(dbmap, Person{}, "Id")+"=:Id", map[string]interface{}{
"Id": -2222,
})
if err == nil || err != sql.ErrNoRows {
@@ -1903,7 +2192,7 @@ func TestSelectSingleVal(t *testing.T) {
}
_insert(dbmap, &Person{0, 0, 0, "bob", "smith", 0})
- err = dbmap.SelectOne(&p2, "select * from person_test where Fname='bob'")
+ err = dbmap.SelectOne(&p2, "select * from person_test where "+columnName(dbmap, Person{}, "FName")+"='bob'")
if err == nil {
t.Error("Expected error when two rows found")
}
@@ -1915,7 +2204,7 @@ func TestSelectSingleVal(t *testing.T) {
var tFloat float64
primVals := []interface{}{tInt, tStr, tBool, tFloat}
for _, prim := range primVals {
- err = dbmap.SelectOne(&prim, "select * from person_test where Id=-123")
+ err = dbmap.SelectOne(&prim, "select * from person_test where "+columnName(dbmap, Person{}, "Id")+"=-123")
if err == nil || err != sql.ErrNoRows {
t.Error("primVals: SelectOne should have returned sql.ErrNoRows")
}
@@ -1934,7 +2223,7 @@ func TestSelectAlias(t *testing.T) {
// Select into IdCreatedExternal type, which includes some fields not present
// in id_created_test
var p2 IdCreatedExternal
- err := dbmap.SelectOne(&p2, "select * from id_created_test where Id=1")
+ err := dbmap.SelectOne(&p2, "select * from id_created_test where "+columnName(dbmap, IdCreatedExternal{}, "Id")+"=1")
if err != nil {
t.Error(err)
}
@@ -1973,13 +2262,13 @@ func TestMysqlPanicIfDialectNotInitialized(t *testing.T) {
defer func() {
r := recover()
if r == nil {
- t.Error("db.CreateTables() should panic if db is initialized with an incorrect MySQLDialect")
+ t.Error("db.CreateTables() should panic if db is initialized with an incorrect gorp.MySQLDialect")
}
}()
// invalid MySQLDialect : does not contain Engine or Encoding specification
- dialect := MySQLDialect{}
- db := &DbMap{Db: connect(driver), Dialect: dialect}
+ dialect := gorp.MySQLDialect{}
+ db := &gorp.DbMap{Db: connect(driver), Dialect: dialect}
db.AddTableWithName(Invoice{}, "invoice")
// the following call should panic :
db.CreateTables()
@@ -2026,7 +2315,7 @@ func TestPrepare(t *testing.T) {
bindVar0 := dbmap.Dialect.BindVar(0)
bindVar1 := dbmap.Dialect.BindVar(1)
- stmt, err := dbmap.Prepare(fmt.Sprintf("UPDATE invoice_test SET Memo=%s WHERE Id=%s", bindVar0, bindVar1))
+ stmt, err := dbmap.Prepare(fmt.Sprintf("UPDATE invoice_test SET "+columnName(dbmap, Invoice{}, "Memo")+"=%s WHERE "+columnName(dbmap, Invoice{}, "Id")+"=%s", bindVar0, bindVar1))
if err != nil {
t.Error(err)
}
@@ -2035,7 +2324,7 @@ func TestPrepare(t *testing.T) {
if err != nil {
t.Error(err)
}
- err = dbmap.SelectOne(inv1, "SELECT * from invoice_test WHERE Memo='prepare-baz'")
+ err = dbmap.SelectOne(inv1, "SELECT * from invoice_test WHERE "+columnName(dbmap, Invoice{}, "Memo")+"='prepare-baz'")
if err != nil {
t.Error(err)
}
@@ -2044,7 +2333,7 @@ func TestPrepare(t *testing.T) {
if err != nil {
t.Error(err)
}
- transStmt, err := trans.Prepare(fmt.Sprintf("UPDATE invoice_test SET IsPaid=%s WHERE Id=%s", bindVar0, bindVar1))
+ transStmt, err := trans.Prepare(fmt.Sprintf("UPDATE invoice_test SET "+columnName(dbmap, Invoice{}, "IsPaid")+"=%s WHERE "+columnName(dbmap, Invoice{}, "Id")+"=%s", bindVar0, bindVar1))
if err != nil {
t.Error(err)
}
@@ -2053,11 +2342,11 @@ func TestPrepare(t *testing.T) {
if err != nil {
t.Error(err)
}
- err = dbmap.SelectOne(inv2, fmt.Sprintf("SELECT * from invoice_test WHERE IsPaid=%s", bindVar0), true)
+ err = dbmap.SelectOne(inv2, fmt.Sprintf("SELECT * from invoice_test WHERE "+columnName(dbmap, Invoice{}, "IsPaid")+"=%s", bindVar0), true)
if err == nil || err != sql.ErrNoRows {
t.Error("SelectOne should have returned an sql.ErrNoRows")
}
- err = trans.SelectOne(inv2, fmt.Sprintf("SELECT * from invoice_test WHERE IsPaid=%s", bindVar0), true)
+ err = trans.SelectOne(inv2, fmt.Sprintf("SELECT * from invoice_test WHERE "+columnName(dbmap, Invoice{}, "IsPaid")+"=%s", bindVar0), true)
if err != nil {
t.Error(err)
}
@@ -2065,7 +2354,7 @@ func TestPrepare(t *testing.T) {
if err != nil {
t.Error(err)
}
- err = dbmap.SelectOne(inv2, fmt.Sprintf("SELECT * from invoice_test WHERE IsPaid=%s", bindVar0), true)
+ err = dbmap.SelectOne(inv2, fmt.Sprintf("SELECT * from invoice_test WHERE "+columnName(dbmap, Invoice{}, "IsPaid")+"=%s", bindVar0), true)
if err != nil {
t.Error(err)
}
@@ -2075,12 +2364,25 @@ func BenchmarkNativeCrud(b *testing.B) {
b.StopTimer()
dbmap := initDbMapBench()
defer dropAndClose(dbmap)
+ columnId := columnName(dbmap, Invoice{}, "Id")
+ columnCreated := columnName(dbmap, Invoice{}, "Created")
+ columnUpdated := columnName(dbmap, Invoice{}, "Updated")
+ columnMemo := columnName(dbmap, Invoice{}, "Memo")
+ columnPersonId := columnName(dbmap, Invoice{}, "PersonId")
b.StartTimer()
- insert := "insert into invoice_test (Created, Updated, Memo, PersonId) values (?, ?, ?, ?)"
- sel := "select Id, Created, Updated, Memo, PersonId from invoice_test where Id=?"
- update := "update invoice_test set Created=?, Updated=?, Memo=?, PersonId=? where Id=?"
- delete := "delete from invoice_test where Id=?"
+ var insert, sel, update, delete string
+ if os.Getenv("GORP_TEST_DIALECT") != "postgres" {
+ insert = "insert into invoice_test (" + columnCreated + ", " + columnUpdated + ", " + columnMemo + ", " + columnPersonId + ") values (?, ?, ?, ?)"
+ sel = "select " + columnId + ", " + columnCreated + ", " + columnUpdated + ", " + columnMemo + ", " + columnPersonId + " from invoice_test where " + columnId + "=?"
+ update = "update invoice_test set " + columnCreated + "=?, " + columnUpdated + "=?, " + columnMemo + "=?, " + columnPersonId + "=? where " + columnId + "=?"
+ delete = "delete from invoice_test where " + columnId + "=?"
+ } else {
+ insert = "insert into invoice_test (" + columnCreated + ", " + columnUpdated + ", " + columnMemo + ", " + columnPersonId + ") values ($1, $2, $3, $4)"
+ sel = "select " + columnId + ", " + columnCreated + ", " + columnUpdated + ", " + columnMemo + ", " + columnPersonId + " from invoice_test where " + columnId + "=$1"
+ update = "update invoice_test set " + columnCreated + "=$1, " + columnUpdated + "=$2, " + columnMemo + "=$3, " + columnPersonId + "=$4 where " + columnId + "=$5"
+ delete = "delete from invoice_test where " + columnId + "=$1"
+ }
inv := &Invoice{0, 100, 200, "my memo", 0, false}
@@ -2163,7 +2465,7 @@ func BenchmarkGorpCrud(b *testing.B) {
}
}
-func initDbMapBench() *DbMap {
+func initDbMapBench() *gorp.DbMap {
dbmap := newDbMap()
dbmap.Db.Exec("drop table if exists invoice_test")
dbmap.AddTableWithName(Invoice{}, "invoice_test").SetKeys(true, "Id")
@@ -2174,7 +2476,7 @@ func initDbMapBench() *DbMap {
return dbmap
}
-func initDbMap() *DbMap {
+func initDbMap() *gorp.DbMap {
dbmap := newDbMap()
dbmap.AddTableWithName(Invoice{}, "invoice_test").SetKeys(true, "Id")
dbmap.AddTableWithName(InvoiceTag{}, "invoice_tag_test") //key is set via primarykey attribute
@@ -2188,6 +2490,8 @@ func initDbMap() *DbMap {
//dbmap.AddTableWithName(WithEmbeddedStructConflictingEmbeddedMemberNames{}, "embedded_struct_conflict_name_test").SetKeys(true, "Id")
//dbmap.AddTableWithName(WithEmbeddedStructSameMemberName{}, "embedded_struct_same_member_name_test").SetKeys(true, "Id")
dbmap.AddTableWithName(WithEmbeddedStructBeforeAutoincrField{}, "embedded_struct_before_autoincr_test").SetKeys(true, "Id")
+ dbmap.AddTableDynamic(&dynTableInst1, "").SetKeys(true, "Id").AddIndex("TenantInst1Index", "Btree", []string{"Name"}).SetUnique(true)
+ dbmap.AddTableDynamic(&dynTableInst2, "").SetKeys(true, "Id").AddIndex("TenantInst2Index", "Btree", []string{"Name"}).SetUnique(true)
dbmap.AddTableWithName(WithEmbeddedAutoincr{}, "embedded_autoincr_test").SetKeys(true, "Id")
dbmap.AddTableWithName(WithTime{}, "time_test").SetKeys(true, "Id")
dbmap.AddTableWithName(WithNullTime{}, "nulltime_test").SetKeys(false, "Id")
@@ -2201,6 +2505,11 @@ func initDbMap() *DbMap {
panic(err)
}
+ err = dbmap.CreateIndex()
+ if err != nil {
+ panic(err)
+ }
+
// See #146 and TestSelectAlias - this type is mapped to the same
// table as IdCreated, but includes an extra field that isn't in the table
dbmap.AddTableWithName(IdCreatedExternal{}, "id_created_test").SetKeys(true, "Id")
@@ -2208,7 +2517,7 @@ func initDbMap() *DbMap {
return dbmap
}
-func initDbMapNulls() *DbMap {
+func initDbMapNulls() *gorp.DbMap {
dbmap := newDbMap()
dbmap.AddTable(TableWithNull{}).SetKeys(false, "Id")
err := dbmap.CreateTables()
@@ -2218,16 +2527,16 @@ func initDbMapNulls() *DbMap {
return dbmap
}
-func newDbMap() *DbMap {
+func newDbMap() *gorp.DbMap {
dialect, driver := dialectAndDriver()
- dbmap := &DbMap{Db: connect(driver), Dialect: dialect}
+ dbmap := &gorp.DbMap{Db: connect(driver), Dialect: dialect}
if debug {
dbmap.TraceOn("", log.New(os.Stdout, "gorptest: ", log.Lmicroseconds))
}
return dbmap
}
-func dropAndClose(dbmap *DbMap) {
+func dropAndClose(dbmap *gorp.DbMap) {
dbmap.DropTablesIfExists()
dbmap.Db.Close()
}
@@ -2245,28 +2554,28 @@ func connect(driver string) *sql.DB {
return db
}
-func dialectAndDriver() (Dialect, string) {
+func dialectAndDriver() (gorp.Dialect, string) {
switch os.Getenv("GORP_TEST_DIALECT") {
case "mysql":
- return MySQLDialect{"InnoDB", "UTF8"}, "mymysql"
+ return gorp.MySQLDialect{"InnoDB", "UTF8"}, "mymysql"
case "gomysql":
- return MySQLDialect{"InnoDB", "UTF8"}, "mysql"
+ return gorp.MySQLDialect{"InnoDB", "UTF8"}, "mysql"
case "postgres":
- return PostgresDialect{}, "postgres"
+ return gorp.PostgresDialect{}, "postgres"
case "sqlite":
- return SqliteDialect{}, "sqlite3"
+ return gorp.SqliteDialect{}, "sqlite3"
}
panic("GORP_TEST_DIALECT env variable is not set or is invalid. Please see README.md")
}
-func _insert(dbmap *DbMap, list ...interface{}) {
+func _insert(dbmap *gorp.DbMap, list ...interface{}) {
err := dbmap.Insert(list...)
if err != nil {
panic(err)
}
}
-func _update(dbmap *DbMap, list ...interface{}) int64 {
+func _update(dbmap *gorp.DbMap, list ...interface{}) int64 {
count, err := dbmap.Update(list...)
if err != nil {
panic(err)
@@ -2274,7 +2583,7 @@ func _update(dbmap *DbMap, list ...interface{}) int64 {
return count
}
-func _updateColumns(dbmap *DbMap, filter ColumnFilter, list ...interface{}) int64 {
+func _updateColumns(dbmap *gorp.DbMap, filter gorp.ColumnFilter, list ...interface{}) int64 {
count, err := dbmap.UpdateColumns(filter, list...)
if err != nil {
panic(err)
@@ -2282,7 +2591,7 @@ func _updateColumns(dbmap *DbMap, filter ColumnFilter, list ...interface{}) int6
return count
}
-func _del(dbmap *DbMap, list ...interface{}) int64 {
+func _del(dbmap *gorp.DbMap, list ...interface{}) int64 {
count, err := dbmap.Delete(list...)
if err != nil {
panic(err)
@@ -2291,7 +2600,7 @@ func _del(dbmap *DbMap, list ...interface{}) int64 {
return count
}
-func _get(dbmap *DbMap, i interface{}, keys ...interface{}) interface{} {
+func _get(dbmap *gorp.DbMap, i interface{}, keys ...interface{}) interface{} {
obj, err := dbmap.Get(i, keys...)
if err != nil {
panic(err)
@@ -2300,8 +2609,8 @@ func _get(dbmap *DbMap, i interface{}, keys ...interface{}) interface{} {
return obj
}
-func selectInt(dbmap *DbMap, query string, args ...interface{}) int64 {
- i64, err := SelectInt(dbmap, query, args...)
+func selectInt(dbmap *gorp.DbMap, query string, args ...interface{}) int64 {
+ i64, err := gorp.SelectInt(dbmap, query, args...)
if err != nil {
panic(err)
}
@@ -2309,8 +2618,8 @@ func selectInt(dbmap *DbMap, query string, args ...interface{}) int64 {
return i64
}
-func selectNullInt(dbmap *DbMap, query string, args ...interface{}) sql.NullInt64 {
- i64, err := SelectNullInt(dbmap, query, args...)
+func selectNullInt(dbmap *gorp.DbMap, query string, args ...interface{}) sql.NullInt64 {
+ i64, err := gorp.SelectNullInt(dbmap, query, args...)
if err != nil {
panic(err)
}
@@ -2318,8 +2627,8 @@ func selectNullInt(dbmap *DbMap, query string, args ...interface{}) sql.NullInt6
return i64
}
-func selectFloat(dbmap *DbMap, query string, args ...interface{}) float64 {
- f64, err := SelectFloat(dbmap, query, args...)
+func selectFloat(dbmap *gorp.DbMap, query string, args ...interface{}) float64 {
+ f64, err := gorp.SelectFloat(dbmap, query, args...)
if err != nil {
panic(err)
}
@@ -2327,8 +2636,8 @@ func selectFloat(dbmap *DbMap, query string, args ...interface{}) float64 {
return f64
}
-func selectNullFloat(dbmap *DbMap, query string, args ...interface{}) sql.NullFloat64 {
- f64, err := SelectNullFloat(dbmap, query, args...)
+func selectNullFloat(dbmap *gorp.DbMap, query string, args ...interface{}) sql.NullFloat64 {
+ f64, err := gorp.SelectNullFloat(dbmap, query, args...)
if err != nil {
panic(err)
}
@@ -2336,8 +2645,8 @@ func selectNullFloat(dbmap *DbMap, query string, args ...interface{}) sql.NullFl
return f64
}
-func selectStr(dbmap *DbMap, query string, args ...interface{}) string {
- s, err := SelectStr(dbmap, query, args...)
+func selectStr(dbmap *gorp.DbMap, query string, args ...interface{}) string {
+ s, err := gorp.SelectStr(dbmap, query, args...)
if err != nil {
panic(err)
}
@@ -2345,8 +2654,8 @@ func selectStr(dbmap *DbMap, query string, args ...interface{}) string {
return s
}
-func selectNullStr(dbmap *DbMap, query string, args ...interface{}) sql.NullString {
- s, err := SelectNullStr(dbmap, query, args...)
+func selectNullStr(dbmap *gorp.DbMap, query string, args ...interface{}) sql.NullString {
+ s, err := gorp.SelectNullStr(dbmap, query, args...)
if err != nil {
panic(err)
}
@@ -2354,7 +2663,7 @@ func selectNullStr(dbmap *DbMap, query string, args ...interface{}) sql.NullStri
return s
}
-func _rawexec(dbmap *DbMap, query string, args ...interface{}) sql.Result {
+func rawExec(dbmap *gorp.DbMap, query string, args ...interface{}) sql.Result {
res, err := dbmap.Exec(query, args...)
if err != nil {
panic(err)
@@ -2362,10 +2671,26 @@ func _rawexec(dbmap *DbMap, query string, args ...interface{}) sql.Result {
return res
}
-func _rawselect(dbmap *DbMap, i interface{}, query string, args ...interface{}) []interface{} {
+func rawSelect(dbmap *gorp.DbMap, i interface{}, query string, args ...interface{}) []interface{} {
list, err := dbmap.Select(i, query, args...)
if err != nil {
panic(err)
}
return list
}
+
+func tableName(dbmap *gorp.DbMap, i interface{}) string {
+ t := reflect.TypeOf(i)
+ if table, err := dbmap.TableFor(t, false); table != nil && err == nil {
+ return dbmap.Dialect.QuoteField(table.TableName)
+ }
+ return t.Name()
+}
+
+func columnName(dbmap *gorp.DbMap, i interface{}, fieldName string) string {
+ t := reflect.TypeOf(i)
+ if table, err := dbmap.TableFor(t, false); table != nil && err == nil {
+ return dbmap.Dialect.QuoteField(table.ColMap(fieldName).ColumnName)
+ }
+ return fieldName
+}
diff --git a/vendor/github.com/go-gorp/gorp/hooks.go b/vendor/github.com/mattermost/gorp/hooks.go
index 192b51f00..192b51f00 100644
--- a/vendor/github.com/go-gorp/gorp/hooks.go
+++ b/vendor/github.com/mattermost/gorp/hooks.go
diff --git a/vendor/github.com/go-gorp/gorp/index.go b/vendor/github.com/mattermost/gorp/index.go
index 01ecd9eca..01ecd9eca 100644
--- a/vendor/github.com/go-gorp/gorp/index.go
+++ b/vendor/github.com/mattermost/gorp/index.go
diff --git a/vendor/github.com/go-gorp/gorp/lockerror.go b/vendor/github.com/mattermost/gorp/lockerror.go
index 07b3047ae..07b3047ae 100644
--- a/vendor/github.com/go-gorp/gorp/lockerror.go
+++ b/vendor/github.com/mattermost/gorp/lockerror.go
diff --git a/vendor/github.com/go-gorp/gorp/logging.go b/vendor/github.com/mattermost/gorp/logging.go
index 89d6c0e79..89d6c0e79 100644
--- a/vendor/github.com/go-gorp/gorp/logging.go
+++ b/vendor/github.com/mattermost/gorp/logging.go
diff --git a/vendor/github.com/go-gorp/gorp/nulltypes.go b/vendor/github.com/mattermost/gorp/nulltypes.go
index 870770372..870770372 100644
--- a/vendor/github.com/go-gorp/gorp/nulltypes.go
+++ b/vendor/github.com/mattermost/gorp/nulltypes.go
diff --git a/vendor/github.com/go-gorp/gorp/select.go b/vendor/github.com/mattermost/gorp/select.go
index d6ff92ee3..1967b0246 100644
--- a/vendor/github.com/go-gorp/gorp/select.go
+++ b/vendor/github.com/mattermost/gorp/select.go
@@ -12,6 +12,7 @@
package gorp
import (
+ "context"
"database/sql"
"fmt"
"reflect"
@@ -154,15 +155,28 @@ func SelectOne(m *DbMap, e SqlExecutor, holder interface{}, query string, args .
}
func selectVal(e SqlExecutor, holder interface{}, query string, args ...interface{}) error {
+ var dbMap *DbMap
+ switch m := e.(type) {
+ case *DbMap:
+ dbMap = m
+ case *Transaction:
+ dbMap = m.dbmap
+ }
+
if len(args) == 1 {
- switch m := e.(type) {
- case *DbMap:
- query, args = maybeExpandNamedQuery(m, query, args)
- case *Transaction:
- query, args = maybeExpandNamedQuery(m.dbmap, query, args)
- }
+ query, args = maybeExpandNamedQuery(dbMap, query, args)
+ }
+
+ var rows *sql.Rows
+ var err error
+ if dbMap.Dialect.Name() != "PostgresDialect" {
+ ctx, cancel := context.WithTimeout(context.Background(), dbMap.QueryTimeout)
+ defer cancel()
+ rows, err = e.QueryContext(ctx, query, args...)
+ } else {
+ rows, err = e.Query(query, args...)
}
- rows, err := e.query(query, args...)
+
if err != nil {
return err
}
@@ -178,14 +192,11 @@ func selectVal(e SqlExecutor, holder interface{}, query string, args ...interfac
func hookedselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
args ...interface{}) ([]interface{}, error) {
- var nonFatalErr error
-
list, err := rawselect(m, exec, i, query, args...)
if err != nil {
if !NonFatalError(err) {
return nil, err
}
- nonFatalErr = err
}
// Determine where the results are: written to i, or returned in list
@@ -209,7 +220,8 @@ func hookedselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
}
}
}
- return list, nonFatalErr
+
+ return list, nil
}
func rawselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
@@ -222,6 +234,13 @@ func rawselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
var nonFatalErr error
+ tableName := ""
+ var dynObj DynamicTable
+ isDynamic := false
+ if dynObj, isDynamic = i.(DynamicTable); isDynamic {
+ tableName = dynObj.TableName()
+ }
+
// get type for i, verifying it's a supported destination
t, err := toType(i)
if err != nil {
@@ -248,7 +267,15 @@ func rawselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
}
// Run the query
- rows, err := exec.query(query, args...)
+ var rows *sql.Rows
+ if m.Dialect.Name() != "PostgresDialect" {
+ ctx, cancel := context.WithTimeout(context.Background(), m.QueryTimeout)
+ defer cancel()
+ rows, err = exec.QueryContext(ctx, query, args...)
+ } else {
+ rows, err = exec.Query(query, args...)
+ }
+
if err != nil {
return nil, err
}
@@ -266,7 +293,7 @@ func rawselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
var colToFieldIndex [][]int
if intoStruct {
- colToFieldIndex, err = columnToFieldIndex(m, t, cols)
+ colToFieldIndex, err = columnToFieldIndex(m, t, tableName, cols)
if err != nil {
if !NonFatalError(err) {
return nil, err
@@ -293,6 +320,11 @@ func rawselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
break
}
v := reflect.New(t)
+
+ if isDynamic {
+ v.Interface().(DynamicTable).SetTableName(tableName)
+ }
+
dest := make([]interface{}, len(cols))
custScan := make([]CustomScanner, 0)
diff --git a/vendor/github.com/go-gorp/gorp/table.go b/vendor/github.com/mattermost/gorp/table.go
index 5c513909a..5c513909a 100644
--- a/vendor/github.com/go-gorp/gorp/table.go
+++ b/vendor/github.com/mattermost/gorp/table.go
diff --git a/vendor/github.com/go-gorp/gorp/table_bindings.go b/vendor/github.com/mattermost/gorp/table_bindings.go
index 5b049a360..5b049a360 100644
--- a/vendor/github.com/go-gorp/gorp/table_bindings.go
+++ b/vendor/github.com/mattermost/gorp/table_bindings.go
diff --git a/vendor/github.com/go-gorp/gorp/test_all.sh b/vendor/github.com/mattermost/gorp/test_all.sh
index f2d16961a..4c99584ef 100755
--- a/vendor/github.com/go-gorp/gorp/test_all.sh
+++ b/vendor/github.com/mattermost/gorp/test_all.sh
@@ -5,6 +5,9 @@
coveralls_testflags="-v -covermode=count -coverprofile=coverage.out"
+echo "Running unit tests"
+ginkgo -r -race -randomizeAllSpecs -keepGoing -- -test.run TestGorp
+
echo "Testing against mysql"
export GORP_TEST_DSN=gorptest/gorptest/gorptest
export GORP_TEST_DIALECT=mysql
diff --git a/vendor/github.com/go-gorp/gorp/transaction.go b/vendor/github.com/mattermost/gorp/transaction.go
index 6430f24f1..a9706ee65 100644
--- a/vendor/github.com/go-gorp/gorp/transaction.go
+++ b/vendor/github.com/mattermost/gorp/transaction.go
@@ -12,6 +12,7 @@
package gorp
import (
+ "context"
"database/sql"
"time"
)
@@ -62,7 +63,16 @@ func (t *Transaction) Exec(query string, args ...interface{}) (sql.Result, error
now := time.Now()
defer t.dbmap.trace(now, query, args...)
}
- return exec(t, query, args...)
+ return exec(t, query, true, args...)
+}
+
+// ExecNoTimeout has the same behavior as DbMap.ExecNoTimeout(), but runs in a transaction.
+func (t *Transaction) ExecNoTimeout(query string, args ...interface{}) (sql.Result, error) {
+ if t.dbmap.logger != nil {
+ now := time.Now()
+ defer t.dbmap.trace(now, query, args...)
+ }
+ return exec(t, query, false, args...)
}
// SelectInt is a convenience wrapper around the gorp.SelectInt function.
@@ -176,7 +186,7 @@ func (t *Transaction) Prepare(query string) (*sql.Stmt, error) {
return t.tx.Prepare(query)
}
-func (t *Transaction) queryRow(query string, args ...interface{}) *sql.Row {
+func (t *Transaction) QueryRow(query string, args ...interface{}) *sql.Row {
if t.dbmap.logger != nil {
now := time.Now()
defer t.dbmap.trace(now, query, args...)
@@ -184,10 +194,26 @@ func (t *Transaction) queryRow(query string, args ...interface{}) *sql.Row {
return t.tx.QueryRow(query, args...)
}
-func (t *Transaction) query(query string, args ...interface{}) (*sql.Rows, error) {
+func (t *Transaction) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
+ if t.dbmap.logger != nil {
+ now := time.Now()
+ defer t.dbmap.trace(now, query, args...)
+ }
+ return t.tx.QueryRowContext(ctx, query, args...)
+}
+
+func (t *Transaction) Query(query string, args ...interface{}) (*sql.Rows, error) {
if t.dbmap.logger != nil {
now := time.Now()
defer t.dbmap.trace(now, query, args...)
}
return t.tx.Query(query, args...)
}
+
+func (t *Transaction) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
+ if t.dbmap.logger != nil {
+ now := time.Now()
+ defer t.dbmap.trace(now, query, args...)
+ }
+ return t.tx.QueryContext(ctx, query, args...)
+}