diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 97030eda95..dd584c3cb3 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,6 +1,7 @@ { "ImportPath": "github.com/docker/notary", - "GoVersion": "go1.6.1", + "GoVersion": "go1.6", + "GodepVersion": "v62", "Packages": [ "./..." ], @@ -180,24 +181,24 @@ "Rev": "71acacd42f85e5e82f70a55327789582a5200a90" }, { - "ImportPath": "github.com/dancannon/gorethink", - "Comment": "v1.4.0", - "Rev": "ef48c048b4f1f4d923de4197e78c1b206c14fa4c" + "ImportPath": "gopkg.in/dancannon/gorethink.v2", + "Comment": "v2.0.0", + "Rev": "ad28ba0b1cbf0aa5bbae1ea71941564cc08abfe4" }, { - "ImportPath": "github.com/dancannon/gorethink/encoding", - "Comment": "v1.4.0", - "Rev": "ef48c048b4f1f4d923de4197e78c1b206c14fa4c" + "ImportPath": "gopkg.in/dancannon/gorethink.v2/encoding", + "Comment": "v2.0.0", + "Rev": "ad28ba0b1cbf0aa5bbae1ea71941564cc08abfe4" }, { - "ImportPath": "github.com/dancannon/gorethink/ql2", - "Comment": "v1.4.0", - "Rev": "ef48c048b4f1f4d923de4197e78c1b206c14fa4c" + "ImportPath": "gopkg.in/dancannon/gorethink.v2/ql2", + "Comment": "v2.0.0", + "Rev": "ad28ba0b1cbf0aa5bbae1ea71941564cc08abfe4" }, { - "ImportPath": "github.com/dancannon/gorethink/types", - "Comment": "v1.4.0", - "Rev": "ef48c048b4f1f4d923de4197e78c1b206c14fa4c" + "ImportPath": "gopkg.in/dancannon/gorethink.v2/types", + "Comment": "v2.0.0", + "Rev": "ad28ba0b1cbf0aa5bbae1ea71941564cc08abfe4" }, { "ImportPath": "github.com/denisenkom/go-mssqldb", diff --git a/cmd/notary-server/config.go b/cmd/notary-server/config.go index 61e9d5f722..9ecf2c5cc0 100644 --- a/cmd/notary-server/config.go +++ b/cmd/notary-server/config.go @@ -7,7 +7,6 @@ import ( "time" "github.com/Sirupsen/logrus" - "github.com/dancannon/gorethink" _ "github.com/docker/distribution/registry/auth/htpasswd" _ "github.com/docker/distribution/registry/auth/token" "github.com/docker/go-connections/tlsconfig" @@ -22,6 +21,7 @@ import ( _ "github.com/go-sql-driver/mysql" "github.com/spf13/viper" "golang.org/x/net/context" + "gopkg.in/dancannon/gorethink.v2" ) // get the address for the HTTP server, and parses the optional TLS diff --git a/cmd/notary-signer/config.go b/cmd/notary-signer/config.go index 292555874e..e6e6d1a626 100644 --- a/cmd/notary-signer/config.go +++ b/cmd/notary-signer/config.go @@ -14,7 +14,6 @@ import ( "google.golang.org/grpc/credentials" "github.com/Sirupsen/logrus" - "github.com/dancannon/gorethink" "github.com/docker/distribution/health" "github.com/docker/notary" "github.com/docker/notary/cryptoservice" @@ -29,6 +28,7 @@ import ( "github.com/docker/notary/tuf/data" "github.com/docker/notary/utils" "github.com/spf13/viper" + "gopkg.in/dancannon/gorethink.v2" ) const ( diff --git a/development.rethink.yml b/development.rethink.yml index 2e3945847d..2e9456e549 100644 --- a/development.rethink.yml +++ b/development.rethink.yml @@ -39,7 +39,7 @@ services: depends_on: - rdb-proxy rdb-01: - image: jlhawn/rethinkdb-tls + image: jlhawn/rethinkdb:2.3.0 volumes: - ./fixtures/rethinkdb:/tls - rdb-01-data:/var/data @@ -49,9 +49,9 @@ services: - rdb - rdb.rdb - rdb-01.rdb - command: "--bind all --no-http-admin --server-name rdb_01 --canonical-address rdb-01.rdb --directory /var/data/rethinkdb --join rdb.rdb --driver-tls --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" + command: "--bind all --no-http-admin --server-name rdb_01 --canonical-address rdb-01.rdb --directory /var/data/rethinkdb --join rdb.rdb --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" rdb-02: - image: jlhawn/rethinkdb-tls + image: jlhawn/rethinkdb:2.3.0 volumes: - ./fixtures/rethinkdb:/tls - rdb-02-data:/var/data @@ -61,9 +61,9 @@ services: - rdb - rdb.rdb - rdb-02.rdb - command: "--bind all --no-http-admin --server-name rdb_02 --canonical-address rdb-02.rdb --directory /var/data/rethinkdb --join rdb.rdb --driver-tls --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" + command: "--bind all --no-http-admin --server-name rdb_02 --canonical-address rdb-02.rdb --directory /var/data/rethinkdb --join rdb.rdb --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" rdb-03: - image: jlhawn/rethinkdb-tls + image: jlhawn/rethinkdb:2.3.0 volumes: - ./fixtures/rethinkdb:/tls - rdb-03-data:/var/data @@ -73,9 +73,9 @@ services: - rdb - rdb.rdb - rdb-03.rdb - command: "--bind all --no-http-admin --server-name rdb_03 --canonical-address rdb-03.rdb --directory /var/data/rethinkdb --join rdb.rdb --driver-tls --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" + command: "--bind all --no-http-admin --server-name rdb_03 --canonical-address rdb-03.rdb --directory /var/data/rethinkdb --join rdb.rdb --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" rdb-proxy: - image: jlhawn/rethinkdb-tls + image: jlhawn/rethinkdb:2.3.0 ports: - "8080:8080" volumes: @@ -85,7 +85,7 @@ services: aliases: - rdb-proxy - rdb-proxy.rdp - command: "proxy --bind all --join rdb.rdb --web-tls --web-tls-key /tls/key.pem --web-tls-cert /tls/cert.pem --driver-tls --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" + command: "proxy --bind all --join rdb.rdb --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" depends_on: - rdb-01 - rdb-02 diff --git a/docker-compose.rethink.yml b/docker-compose.rethink.yml index dbe6d898e6..4197b9e6d0 100644 --- a/docker-compose.rethink.yml +++ b/docker-compose.rethink.yml @@ -39,7 +39,7 @@ services: depends_on: - rdb-proxy rdb-01: - image: jlhawn/rethinkdb-tls + image: jlhawn/rethinkdb:2.3.0 volumes: - ./fixtures/rethinkdb:/tls - rdb-01-data:/var/data @@ -49,9 +49,9 @@ services: - rdb - rdb.rdb - rdb-01.rdb - command: "--bind all --no-http-admin --server-name rdb_01 --canonical-address rdb-01.rdb --directory /var/data/rethinkdb --join rdb.rdb --driver-tls --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" + command: "--bind all --no-http-admin --server-name rdb_01 --canonical-address rdb-01.rdb --directory /var/data/rethinkdb --join rdb.rdb --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" rdb-02: - image: jlhawn/rethinkdb-tls + image: jlhawn/rethinkdb:2.3.0 volumes: - ./fixtures/rethinkdb:/tls - rdb-02-data:/var/data @@ -61,9 +61,9 @@ services: - rdb - rdb.rdb - rdb-02.rdb - command: "--bind all --no-http-admin --server-name rdb_02 --canonical-address rdb-02.rdb --directory /var/data/rethinkdb --join rdb.rdb --driver-tls --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" + command: "--bind all --no-http-admin --server-name rdb_02 --canonical-address rdb-02.rdb --directory /var/data/rethinkdb --join rdb.rdb --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" rdb-03: - image: jlhawn/rethinkdb-tls + image: jlhawn/rethinkdb:2.3.0 volumes: - ./fixtures/rethinkdb:/tls - rdb-03-data:/var/data @@ -73,9 +73,9 @@ services: - rdb - rdb.rdb - rdb-03.rdb - command: "--bind all --no-http-admin --server-name rdb_03 --canonical-address rdb-03.rdb --directory /var/data/rethinkdb --join rdb.rdb --driver-tls --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" + command: "--bind all --no-http-admin --server-name rdb_03 --canonical-address rdb-03.rdb --directory /var/data/rethinkdb --join rdb.rdb --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" rdb-proxy: - image: jlhawn/rethinkdb-tls + image: jlhawn/rethinkdb:2.3.0 ports: - "8080:8080" volumes: @@ -85,7 +85,7 @@ services: aliases: - rdb-proxy - rdb-proxy.rdp - command: "proxy --bind all --join rdb.rdb --web-tls --web-tls-key /tls/key.pem --web-tls-cert /tls/cert.pem --driver-tls --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" + command: "proxy --bind all --join rdb.rdb --driver-tls-key /tls/key.pem --driver-tls-cert /tls/cert.pem --cluster-tls-key /tls/key.pem --cluster-tls-cert /tls/cert.pem --cluster-tls-ca /tls/ca.pem" depends_on: - rdb-01 - rdb-02 diff --git a/server/storage/rethinkdb.go b/server/storage/rethinkdb.go index 78b17144a8..964a4eb31f 100644 --- a/server/storage/rethinkdb.go +++ b/server/storage/rethinkdb.go @@ -7,9 +7,9 @@ import ( "sort" "time" - "github.com/dancannon/gorethink" "github.com/docker/notary/storage/rethinkdb" "github.com/docker/notary/tuf/data" + "gopkg.in/dancannon/gorethink.v2" ) // RDBTUFFile is a tuf file record diff --git a/signer/keydbstore/rethink_keydbstore.go b/signer/keydbstore/rethink_keydbstore.go index 83995e750c..3d8f51f678 100644 --- a/signer/keydbstore/rethink_keydbstore.go +++ b/signer/keydbstore/rethink_keydbstore.go @@ -6,13 +6,13 @@ import ( "sync" "time" - "github.com/dancannon/gorethink" "github.com/docker/notary/passphrase" "github.com/docker/notary/storage/rethinkdb" "github.com/docker/notary/trustmanager" "github.com/docker/notary/tuf/data" "github.com/docker/notary/tuf/utils" jose "github.com/dvsekhvalnov/jose2go" + "gopkg.in/dancannon/gorethink.v2" ) // RethinkDBKeyStore persists and manages private keys on a RethinkDB database diff --git a/storage/rethinkdb/bootstrap.go b/storage/rethinkdb/bootstrap.go index 0b96fa6680..fcc08e4c05 100644 --- a/storage/rethinkdb/bootstrap.go +++ b/storage/rethinkdb/bootstrap.go @@ -4,7 +4,8 @@ import ( "fmt" "strings" - "github.com/dancannon/gorethink" + "github.com/Sirupsen/logrus" + "gopkg.in/dancannon/gorethink.v2" ) func makeDB(session *gorethink.Session, name string) error { @@ -16,7 +17,6 @@ func makeDB(session *gorethink.Session, name string) error { return err } - // Note: Wait() not supported by RethinkDB 2.3+ resp, err := gorethink.DB(name).Wait().Run(session) if resp != nil { resp.Close() @@ -41,7 +41,6 @@ func (t Table) term(dbName string) gorethink.Term { } func (t Table) wait(session *gorethink.Session, dbName string) error { - // Note: Wait() not supported by RethinkDB 2.3+ resp, err := t.term(dbName).Wait().Run(session) if resp != nil { @@ -58,6 +57,7 @@ func (t Table) create(session *gorethink.Session, dbName string, numReplicas uin } if _, err := gorethink.DB(dbName).TableCreate(t.Name, createOpts).RunWrite(session); err != nil { + logrus.Debugf("error when creating database: %s", err) if !strings.Contains(err.Error(), "already exists") { return fmt.Errorf("unable to run table creation: %s", err) } @@ -68,6 +68,10 @@ func (t Table) create(session *gorethink.Session, dbName string, numReplicas uin Replicas: numReplicas, } + if err := t.wait(session, dbName); err != nil { + return fmt.Errorf("unable to wait for table to be ready after creation: %s", err) + } + if _, err := t.term(dbName).Reconfigure(reconfigureOpts).RunWrite(session); err != nil { return fmt.Errorf("unable to reconfigure table replication: %s", err) } diff --git a/storage/rethinkdb/rethinkdb.go b/storage/rethinkdb/rethinkdb.go index d272f2c806..6ef25bff7f 100644 --- a/storage/rethinkdb/rethinkdb.go +++ b/storage/rethinkdb/rethinkdb.go @@ -3,8 +3,8 @@ package rethinkdb import ( "time" - "github.com/dancannon/gorethink" "github.com/docker/go-connections/tlsconfig" + "gopkg.in/dancannon/gorethink.v2" ) var session *gorethink.Session diff --git a/vendor/github.com/dancannon/gorethink/connection_helper.go b/vendor/github.com/dancannon/gorethink/connection_helper.go deleted file mode 100644 index 134f475737..0000000000 --- a/vendor/github.com/dancannon/gorethink/connection_helper.go +++ /dev/null @@ -1,100 +0,0 @@ -package gorethink - -import ( - "bufio" - "encoding/binary" - "fmt" - "io" - "strings" - - p "github.com/dancannon/gorethink/ql2" -) - -// Write 'data' to conn -func (c *Connection) writeData(data []byte) error { - _, err := c.Conn.Write(data[:]) - if err != nil { - return err - } - - return nil -} - -func (c *Connection) writeHandshakeReq() error { - pos := 0 - dataLen := 4 + 4 + len(c.opts.AuthKey) + 4 - data := make([]byte, dataLen) - - // Send the protocol version to the server as a 4-byte little-endian-encoded integer - binary.LittleEndian.PutUint32(data[pos:], uint32(p.VersionDummy_V0_4)) - pos += 4 - - // Send the length of the auth key to the server as a 4-byte little-endian-encoded integer - binary.LittleEndian.PutUint32(data[pos:], uint32(len(c.opts.AuthKey))) - pos += 4 - - // Send the auth key as an ASCII string - if len(c.opts.AuthKey) > 0 { - pos += copy(data[pos:], c.opts.AuthKey) - } - - // Send the protocol type as a 4-byte little-endian-encoded integer - binary.LittleEndian.PutUint32(data[pos:], uint32(p.VersionDummy_JSON)) - pos += 4 - - return c.writeData(data) -} - -func (c *Connection) readHandshakeSuccess() error { - reader := bufio.NewReader(c.Conn) - line, err := reader.ReadBytes('\x00') - if err != nil { - if err == io.EOF { - return fmt.Errorf("Unexpected EOF: %s", string(line)) - } - return err - } - // convert to string and remove trailing NUL byte - response := string(line[:len(line)-1]) - if response != "SUCCESS" { - response = strings.TrimSpace(response) - // we failed authorization or something else terrible happened - return RQLDriverError{rqlError(fmt.Sprintf("Server dropped connection with message: \"%s\"", response))} - } - - return nil -} - -func (c *Connection) read(buf []byte, length int) (total int, err error) { - var n int - for total < length { - if n, err = c.Conn.Read(buf[total:length]); err != nil { - break - } - total += n - } - if err != nil { - return total, err - } - - return total, nil -} - -func (c *Connection) writeQuery(token int64, q []byte) error { - pos := 0 - dataLen := 8 + 4 + len(q) - data := make([]byte, dataLen) - - // Send the protocol version to the server as a 4-byte little-endian-encoded integer - binary.LittleEndian.PutUint64(data[pos:], uint64(token)) - pos += 8 - - // Send the length of the auth key to the server as a 4-byte little-endian-encoded integer - binary.LittleEndian.PutUint32(data[pos:], uint32(len(q))) - pos += 4 - - // Send the auth key as an ASCII string - pos += copy(data[pos:], q) - - return c.writeData(data) -} diff --git a/vendor/github.com/dancannon/gorethink/.gitignore b/vendor/gopkg.in/dancannon/gorethink.v2/.gitignore similarity index 100% rename from vendor/github.com/dancannon/gorethink/.gitignore rename to vendor/gopkg.in/dancannon/gorethink.v2/.gitignore diff --git a/vendor/github.com/dancannon/gorethink/.travis.yml b/vendor/gopkg.in/dancannon/gorethink.v2/.travis.yml similarity index 93% rename from vendor/github.com/dancannon/gorethink/.travis.yml rename to vendor/gopkg.in/dancannon/gorethink.v2/.travis.yml index 2870132f8f..342c4dbcdc 100644 --- a/vendor/github.com/dancannon/gorethink/.travis.yml +++ b/vendor/gopkg.in/dancannon/gorethink.v2/.travis.yml @@ -6,6 +6,8 @@ go: cache: apt +go_import_path: gopkg.in/dancannon/gorethink.v2 + before_script: - source /etc/lsb-release && echo "deb http://download.rethinkdb.com/apt $DISTRIB_CODENAME main" | sudo tee /etc/apt/sources.list.d/rethinkdb.list - wget -qO- http://download.rethinkdb.com/apt/pubkey.gpg | sudo apt-key add - diff --git a/vendor/github.com/dancannon/gorethink/CHANGELOG.md b/vendor/gopkg.in/dancannon/gorethink.v2/CHANGELOG.md similarity index 91% rename from vendor/github.com/dancannon/gorethink/CHANGELOG.md rename to vendor/gopkg.in/dancannon/gorethink.v2/CHANGELOG.md index 988f998f3f..1fc67ed28d 100644 --- a/vendor/github.com/dancannon/gorethink/CHANGELOG.md +++ b/vendor/gopkg.in/dancannon/gorethink.v2/CHANGELOG.md @@ -2,9 +2,49 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## v2.0.0 - 2016-04-13 + +### Changed + + - GoRethink now uses the v1.0 RethinkDB protocol which supports RethinkDB v2.3 and above. If you are using RethinkDB 2.2 or older please set `HandshakeVersion` when creating a session. For example: +```go +r.Connect( + ... + HandshakeVersion: r.HandshakeV0_4, + ... +) +``` + +### Added + - Added support for username/password authentication. To login pass your username and password when creating a session using the `Username` and `Password` fields in the `ConnectOpts`. + - Added the `Grant` term + - Added the `Ordered` optional argument to `EqJoin` + - Added the `Fold` term and examples + - Added the `ReadOne` and `ReadAll` helper functions for quickly executing a query and scanning the result into a variable. For examples see the godocs. + - Added the `Peek` and `Skip` functions to the `Cursor`. + - Added support for referential arrays in structs + - Added the `Durability` argument to `RunOpts`/`ExecOpts` + +### Deprecated + - Deprecated the root `Wait` term, `r.Table(...).Wait()` should now be used instead. + - Deprecated session authentication using `AuthKey` + +### Fixed + - Fixed issue with `ReconfigureOpts` field `PrimaryTag` + +## v1.4.1 - 2016-04-02 + +### Fixed + + - Fixed panic when closing a connection at the same time as using a changefeed. + - Update imports to correctly use gopkg.in + - Fixed race condition when using anonymous functions + - Fixed IsConflictErr and IsTypeErr panicking when passed nil errors + - RunWrite no longer misformats errors with formatting directives in them + ## v1.4.0 - 2016-03-15 -## Added +### Added - Added the ability to reference subdocuments when inserting new documents, for more information see the documentation in the readme. - Added the `SetTags` function which allows GoRethink to override which tags are used when working with structs. For example to support the `json` add the following call `SetTags("gorethink", "json")`. - Added helper functions for checking the error type of a write query, this is useful when calling `RunWrite`. @@ -14,7 +54,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Added the `NextResponse` function to `Cursor` which will return the next raw JSON response in the result set. - Added ability to set the keep alive period by setting the `KeepAlivePeriod` field in `ConnectOpts`. -## Fixed +### Fixed - Fixed an issue that could prevent bad connections from being removed from the connection pool. - Fixed certain connection errors not being returned as `RqlConnectionError` when calling `Run`, `Exec` or `RunWrite`. - Fixed potential dead lock in connection code caused when building the query. diff --git a/vendor/github.com/dancannon/gorethink/LICENSE b/vendor/gopkg.in/dancannon/gorethink.v2/LICENSE similarity index 100% rename from vendor/github.com/dancannon/gorethink/LICENSE rename to vendor/gopkg.in/dancannon/gorethink.v2/LICENSE diff --git a/vendor/github.com/dancannon/gorethink/README.md b/vendor/gopkg.in/dancannon/gorethink.v2/README.md similarity index 99% rename from vendor/github.com/dancannon/gorethink/README.md rename to vendor/gopkg.in/dancannon/gorethink.v2/README.md index 6d3814e29e..7d9bac5fb8 100644 --- a/vendor/github.com/dancannon/gorethink/README.md +++ b/vendor/gopkg.in/dancannon/gorethink.v2/README.md @@ -8,7 +8,7 @@ ![GoRethink Logo](https://raw.github.com/wiki/dancannon/gorethink/gopher-and-thinker-s.png "Golang Gopher and RethinkDB Thinker") -Current version: v1.4.0 (RethinkDB v2.2) +Current version: v2.0.0 (RethinkDB v2.3) Please note that this version of the driver only supports versions of RethinkDB using the v0.4 protocol (any versions of the driver older than RethinkDB 2.0 will not work). @@ -22,7 +22,7 @@ go get -u github.com/dancannon/gorethink Or (pinned to the v1.x.x tag) ``` -go get gopkg.in/dancannon/gorethink.v1 +go get gopkg.in/dancannon/gorethink.v2 ``` ## Connection diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/benchmarks_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/benchmarks_test.go new file mode 100644 index 0000000000..e01ba0d023 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/benchmarks_test.go @@ -0,0 +1,284 @@ +package gorethink + +import ( + "math/rand" + "strconv" + "sync" + "testing" + "time" +) + +func BenchmarkBatch200RandomWrites(b *testing.B) { + + var term Term + var data []map[string]interface{} + + for i := 0; i < b.N; i++ { + + for is := 0; is < 200; is++ { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + cid := map[string]interface{}{ + "customer_id": strconv.FormatInt(r.Int63(), 10), + } + data = append(data, cid) + } + + // Insert the new item into the database + term = DB("benchmarks").Table("benchmarks").Insert(data) + + // Insert the new item into the database + _, err := term.RunWrite(session, RunOpts{ + MinBatchRows: 200, + MaxBatchRows: 200, + }) + if err != nil { + b.Errorf("insert failed [%s] ", err) + } + } + +} + +func BenchmarkBatch200RandomWritesParallel10(b *testing.B) { + + var term Term + var data []map[string]interface{} + + b.SetParallelism(10) + + b.RunParallel(func(pb *testing.PB) { + + for pb.Next() { + for is := 0; is < 200; is++ { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + cid := map[string]interface{}{ + "customer_id": strconv.FormatInt(r.Int63(), 10), + } + data = append(data, cid) + } + + // Insert the new item into the database + term = DB("benchmarks").Table("benchmarks").Insert(data) + + // Insert the new item into the database + _, err := term.RunWrite(session, RunOpts{ + MinBatchRows: 200, + MaxBatchRows: 200, + }) + if err != nil { + b.Errorf("insert failed [%s] ", err) + } + } + }) + +} + +func BenchmarkBatch200SoftRandomWritesParallel10(b *testing.B) { + + var term Term + var data []map[string]interface{} + + b.SetParallelism(10) + + b.RunParallel(func(pb *testing.PB) { + + for pb.Next() { + + opts := InsertOpts{Durability: "soft"} + + for is := 0; is < 200; is++ { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + cid := map[string]interface{}{ + "customer_id": strconv.FormatInt(r.Int63(), 10), + } + data = append(data, cid) + } + + // Insert the new item into the database + term = DB("benchmarks").Table("benchmarks").Insert(data, opts) + + // Insert the new item into the database + _, err := term.RunWrite(session, RunOpts{ + MinBatchRows: 200, + MaxBatchRows: 200, + }) + if err != nil { + b.Errorf("insert failed [%s] ", err) + } + } + }) + +} + +func BenchmarkRandomWrites(b *testing.B) { + + for i := 0; i < b.N; i++ { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + data := map[string]interface{}{ + "customer_id": strconv.FormatInt(r.Int63(), 10), + } + // Insert the new item into the database + _, err := DB("benchmarks").Table("benchmarks").Insert(data).RunWrite(session) + if err != nil { + b.Errorf("insert failed [%s] ", err) + } + } + +} + +func BenchmarkRandomWritesParallel10(b *testing.B) { + + // p*GOMAXPROCS + b.SetParallelism(10) + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + data := map[string]interface{}{ + "customer_id": strconv.FormatInt(r.Int63(), 10), + } + // Insert the new item into the database + _, err := DB("benchmarks").Table("benchmarks").Insert(data).RunWrite(session) + if err != nil { + b.Errorf("insert failed [%s] ", err) + } + } + }) + +} + +func BenchmarkRandomSoftWrites(b *testing.B) { + + for i := 0; i < b.N; i++ { + data := map[string]interface{}{ + "customer_id": strconv.FormatInt(rand.Int63(), 10), + } + // Insert the new item into the database + opts := InsertOpts{Durability: "soft"} + _, err := DB("benchmarks").Table("benchmarks").Insert(data, opts).RunWrite(session) + if err != nil { + b.Errorf("insert failed [%s] ", err) + } + } + +} + +func BenchmarkRandomSoftWritesParallel10(b *testing.B) { + + // p*GOMAXPROCS + b.SetParallelism(10) + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + data := map[string]interface{}{ + "customer_id": strconv.FormatInt(r.Int63(), 10), + } + + // Insert the new item into the database + opts := InsertOpts{Durability: "soft"} + _, err := DB("benchmarks").Table("benchmarks").Insert(data, opts).RunWrite(session) + if err != nil { + b.Errorf("insert failed [%s] ", err) + } + } + }) + +} + +func BenchmarkSequentialWrites(b *testing.B) { + + si := 0 + for i := 0; i < b.N; i++ { + si++ + data := map[string]interface{}{ + "customer_id": si, + } + + // Insert the new item into the database + _, err := DB("benchmarks").Table("benchmarks").Insert(data).RunWrite(session) + if err != nil { + b.Errorf("insert failed [%s] ", err) + return + } + } +} + +func BenchmarkSequentialWritesParallel10(b *testing.B) { + + var mu sync.Mutex + si := 0 + + // p*GOMAXPROCS + b.SetParallelism(10) + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + mu.Lock() + si++ + mu.Unlock() + + data := map[string]interface{}{ + "customer_id": si, + } + + // Insert the new item into the database + _, err := DB("benchmarks").Table("benchmarks").Insert(data).RunWrite(session) + if err != nil { + b.Errorf("insert failed [%s] ", err) + return + } + } + }) + +} + +func BenchmarkSequentialSoftWrites(b *testing.B) { + + opts := InsertOpts{Durability: "soft"} + si := 0 + + for i := 0; i < b.N; i++ { + si++ + data := map[string]interface{}{ + "customer_id": si, + } + + // Insert the new item into the database + _, err := Table("benchmarks").Insert(data, opts).RunWrite(session) + if err != nil { + b.Errorf("insert failed [%s] ", err) + return + } + } +} + +func BenchmarkSequentialSoftWritesParallel10(b *testing.B) { + + var mu sync.Mutex + si := 0 + + // p*GOMAXPROCS + b.SetParallelism(10) + + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + mu.Lock() + si++ + mu.Unlock() + + data := map[string]interface{}{ + "customer_id": si, + } + + opts := InsertOpts{Durability: "soft"} + + // Insert the new item into the database + _, err := Table("benchmarks").Insert(data, opts).RunWrite(session) + if err != nil { + b.Errorf("insert failed [%s] ", err) + return + } + } + }) + +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/checkers_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/checkers_test.go new file mode 100644 index 0000000000..ab10fa91c4 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/checkers_test.go @@ -0,0 +1,168 @@ +package gorethink + +import ( + "encoding/json" + "fmt" + + test "gopkg.in/check.v1" + + "gopkg.in/dancannon/gorethink.v2/types" +) + +type jsonChecker struct { + *test.CheckerInfo +} + +func (j jsonChecker) Check(params []interface{}, names []string) (result bool, error string) { + var jsonParams []interface{} + for _, param := range params { + jsonParam, err := json.Marshal(param) + if err != nil { + return false, err.Error() + } + jsonParams = append(jsonParams, jsonParam) + } + return test.DeepEquals.Check(jsonParams, names) +} + +// jsonEquals compares two interface{} objects by converting them to JSON and +// seeing if the strings match +var jsonEquals = &jsonChecker{ + &test.CheckerInfo{Name: "jsonEquals", Params: []string{"obtained", "expected"}}, +} + +type geometryChecker struct { + *test.CheckerInfo +} + +func (j geometryChecker) Check(params []interface{}, names []string) (result bool, error string) { + obtained, ok := params[0].(types.Geometry) + if !ok { + return false, "obtained must be a Geometry" + } + expectedType, ok := params[1].(string) + if !ok { + return false, "expectedType must be a string" + } + + switch expectedType { + case "Polygon": + expectedCoords, ok := params[2].([][][]float64) + if !ok { + return false, "expectedCoords must be a [][][]float64" + } + + return comparePolygon(expectedCoords, obtained) + case "LineString": + expectedCoords, ok := params[2].([][]float64) + if !ok { + return false, "expectedCoords must be a [][]float64" + } + + return compareLineString(expectedCoords, obtained) + case "Point": + expectedCoords, ok := params[2].([]float64) + if !ok { + return false, "expectedCoords must be a []float64" + } + + return comparePoint(expectedCoords, obtained) + default: + return false, "unknown expectedType" + } +} + +// geometryEquals compares two geometry values, all coordinates are compared with a small amount of tolerance +var geometryEquals = &geometryChecker{ + &test.CheckerInfo{Name: "geometryEquals", Params: []string{"obtained", "expectedType", "expectedCoords"}}, +} + +/* BEGIN FLOAT HELPERS */ + +// totally ripped off from math/all_test.go +// https://github.com/golang/go/blob/master/src/math/all_test.go#L1723-L1749 +func tolerance(a, b, e float64) bool { + d := a - b + if d < 0 { + d = -d + + } + + if a != 0 { + e = e * a + if e < 0 { + e = -e + + } + + } + return d < e +} + +func mehclose(a, b float64) bool { return tolerance(a, b, 1e-2) } +func kindaclose(a, b float64) bool { return tolerance(a, b, 1e-8) } +func prettyclose(a, b float64) bool { return tolerance(a, b, 1e-14) } +func veryclose(a, b float64) bool { return tolerance(a, b, 4e-16) } +func soclose(a, b, e float64) bool { return tolerance(a, b, e) } + +func comparePolygon(expected [][][]float64, obtained types.Geometry) (result bool, error string) { + if obtained.Type != "Polygon" { + return false, fmt.Sprintf("obtained geometry has incorrect type, has %s but expected Polygon", obtained.Type) + } + + for i, line := range obtained.Lines { + for j, point := range line { + ok, err := assertPointsEqual( + expected[i][j][0], point.Lon, // Lon + expected[i][j][1], point.Lat, // Lat + ) + if !ok { + return false, err + } + } + } + + return true, "" +} + +func compareLineString(expected [][]float64, obtained types.Geometry) (result bool, error string) { + if obtained.Type != "LineString" { + return false, fmt.Sprintf("obtained geometry has incorrect type, has %s but expected LineString", obtained.Type) + } + + for j, point := range obtained.Line { + ok, err := assertPointsEqual( + expected[j][0], point.Lon, // Lon + expected[j][1], point.Lat, // Lat + ) + if !ok { + return false, err + } + } + + return true, "" +} + +func comparePoint(expected []float64, obtained types.Geometry) (result bool, error string) { + if obtained.Type != "Point" { + return false, fmt.Sprintf("obtained geometry has incorrect type, has %s but expected Point", obtained.Type) + } + + return assertPointsEqual( + expected[0], obtained.Point.Lon, // Lon + expected[1], obtained.Point.Lat, // Lat + ) +} + +func assertPointsEqual(expectedLon, obtainedLon, expectedLat, obtainedLat float64) (result bool, error string) { + if !kindaclose(expectedLon, obtainedLon) { + return false, fmt.Sprintf("the deviation between the compared floats is too great [%v:%v]", expectedLon, obtainedLon) + } + if !kindaclose(expectedLat, obtainedLat) { + return false, fmt.Sprintf("the deviation between the compared floats is too great [%v:%v]", expectedLat, obtainedLat) + } + + return true, "" +} + +/* END FLOAT HELPERS */ diff --git a/vendor/github.com/dancannon/gorethink/cluster.go b/vendor/gopkg.in/dancannon/gorethink.v2/cluster.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/cluster.go rename to vendor/gopkg.in/dancannon/gorethink.v2/cluster.go diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/cluster_integration_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/cluster_integration_test.go new file mode 100644 index 0000000000..201c2d06e4 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/cluster_integration_test.go @@ -0,0 +1,99 @@ +// +build cluster +// +build integration + +package gorethink + +import ( + "time" + + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestClusterDetectNewNode(c *test.C) { + session, err := Connect(ConnectOpts{ + Addresses: []string{url, url2}, + DiscoverHosts: true, + NodeRefreshInterval: time.Second, + }) + c.Assert(err, test.IsNil) + + t := time.NewTimer(time.Second * 30) + for { + select { + // Fail if deadline has passed + case <-t.C: + c.Fatal("No node was added to the cluster") + default: + // Pass if another node was added + if len(session.cluster.GetNodes()) >= 3 { + return + } + } + } +} + +func (s *RethinkSuite) TestClusterRecoverAfterNoNodes(c *test.C) { + session, err := Connect(ConnectOpts{ + Addresses: []string{url, url2}, + DiscoverHosts: true, + NodeRefreshInterval: time.Second, + }) + c.Assert(err, test.IsNil) + + t := time.NewTimer(time.Second * 30) + hasHadZeroNodes := false + for { + select { + // Fail if deadline has passed + case <-t.C: + c.Fatal("No node was added to the cluster") + default: + // Check if there are no nodes + if len(session.cluster.GetNodes()) == 0 { + hasHadZeroNodes = true + } + + // Pass if another node was added + if len(session.cluster.GetNodes()) >= 1 && hasHadZeroNodes { + return + } + } + } +} + +func (s *RethinkSuite) TestClusterNodeHealth(c *test.C) { + session, err := Connect(ConnectOpts{ + Addresses: []string{url1, url2, url3}, + DiscoverHosts: true, + NodeRefreshInterval: time.Second, + MaxIdle: 50, + MaxOpen: 200, + }) + c.Assert(err, test.IsNil) + + attempts := 0 + failed := 0 + seconds := 0 + + t := time.NewTimer(time.Second * 30) + tick := time.NewTicker(time.Second) + for { + select { + // Fail if deadline has passed + case <-tick.C: + seconds++ + c.Logf("%ds elapsed", seconds) + case <-t.C: + // Execute queries for 10s and check that at most 5% of the queries fail + c.Logf("%d of the %d(%d%%) queries failed", failed, attempts, (failed / attempts)) + c.Assert(failed <= 100, test.Equals, true) + return + default: + attempts++ + if err := Expr(1).Exec(session); err != nil { + c.Logf("Query failed, %s", err) + failed++ + } + } + } +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/cluster_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/cluster_test.go new file mode 100644 index 0000000000..376444d8a5 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/cluster_test.go @@ -0,0 +1,63 @@ +// +build cluster + +package gorethink + +import ( + "fmt" + "time" + + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestClusterConnect(c *test.C) { + session, err := Connect(ConnectOpts{ + Addresses: []string{url1, url2, url3}, + }) + c.Assert(err, test.IsNil) + + row, err := Expr("Hello World").Run(session) + c.Assert(err, test.IsNil) + + var response string + err = row.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "Hello World") +} + +func (s *RethinkSuite) TestClusterMultipleQueries(c *test.C) { + session, err := Connect(ConnectOpts{ + Addresses: []string{url1, url2, url3}, + }) + c.Assert(err, test.IsNil) + + for i := 0; i < 1000; i++ { + row, err := Expr(fmt.Sprintf("Hello World", i)).Run(session) + c.Assert(err, test.IsNil) + + var response string + err = row.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, fmt.Sprintf("Hello World", i)) + } +} + +func (s *RethinkSuite) TestClusterConnectError(c *test.C) { + var err error + _, err = Connect(ConnectOpts{ + Addresses: []string{"nonexistanturl"}, + Timeout: time.Second, + }) + c.Assert(err, test.NotNil) +} + +func (s *RethinkSuite) TestClusterConnectDatabase(c *test.C) { + session, err := Connect(ConnectOpts{ + Addresses: []string{url1, url2, url3}, + Database: "test2", + }) + c.Assert(err, test.IsNil) + + _, err = Table("test2").Run(session) + c.Assert(err, test.NotNil) + c.Assert(err.Error(), test.Equals, "gorethink: Database `test2` does not exist. in: \nr.Table(\"test2\")") +} diff --git a/vendor/github.com/dancannon/gorethink/connection.go b/vendor/gopkg.in/dancannon/gorethink.v2/connection.go similarity index 95% rename from vendor/github.com/dancannon/gorethink/connection.go rename to vendor/gopkg.in/dancannon/gorethink.v2/connection.go index 97952d3ed8..93b71d0d33 100644 --- a/vendor/github.com/dancannon/gorethink/connection.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/connection.go @@ -9,7 +9,7 @@ import ( "sync/atomic" "time" - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) const ( @@ -41,6 +41,7 @@ type Connection struct { token int64 cursors map[int64]*Cursor bad bool + closed bool } // NewConnection creates a new connection to the database server @@ -62,16 +63,14 @@ func NewConnection(address string, opts *ConnectOpts) (*Connection, error) { return nil, RQLConnectionError{rqlError(err.Error())} } - // Send handshake request - if err = c.writeHandshakeReq(); err != nil { - c.Close() - return nil, RQLConnectionError{rqlError(err.Error())} - } - // Read handshake response - err = c.readHandshakeSuccess() + // Send handshake + handshake, err := c.handshake(opts.HandshakeVersion) if err != nil { - c.Close() - return nil, RQLConnectionError{rqlError(err.Error())} + return nil, err + } + + if err = handshake.Send(); err != nil { + return nil, err } return c, nil @@ -82,14 +81,15 @@ func (c *Connection) Close() error { c.mu.Lock() defer c.mu.Unlock() - if c.Conn != nil { - c.Conn.Close() - c.Conn = nil + var err error + + if !c.closed { + err = c.Conn.Close() + c.closed = true + c.cursors = make(map[int64]*Cursor) } - c.cursors = nil - - return nil + return err } // Query sends a Query to the database, returning both the raw Response and a diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/connection_handshake.go b/vendor/gopkg.in/dancannon/gorethink.v2/connection_handshake.go new file mode 100644 index 0000000000..c825674110 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/connection_handshake.go @@ -0,0 +1,450 @@ +package gorethink + +import ( + "bufio" + "crypto/hmac" + "crypto/rand" + "crypto/sha256" + "encoding/base64" + "encoding/binary" + "encoding/json" + "fmt" + "hash" + "io" + "strconv" + "strings" + + "golang.org/x/crypto/pbkdf2" + + p "gopkg.in/dancannon/gorethink.v2/ql2" +) + +type HandshakeVersion int + +const ( + HandshakeV1_0 HandshakeVersion = iota + HandshakeV0_4 +) + +type connectionHandshake interface { + Send() error +} + +func (c *Connection) handshake(version HandshakeVersion) (connectionHandshake, error) { + switch version { + case HandshakeV0_4: + return &connectionHandshakeV0_4{conn: c}, nil + case HandshakeV1_0: + return &connectionHandshakeV1_0{conn: c}, nil + default: + return nil, fmt.Errorf("Unrecognised handshake version") + } +} + +type connectionHandshakeV0_4 struct { + conn *Connection +} + +func (c *connectionHandshakeV0_4) Send() error { + // Send handshake request + if err := c.writeHandshakeReq(); err != nil { + c.conn.Close() + return RQLConnectionError{rqlError(err.Error())} + } + // Read handshake response + if err := c.readHandshakeSuccess(); err != nil { + c.conn.Close() + return RQLConnectionError{rqlError(err.Error())} + } + + return nil +} + +func (c *connectionHandshakeV0_4) writeHandshakeReq() error { + pos := 0 + dataLen := 4 + 4 + len(c.conn.opts.AuthKey) + 4 + data := make([]byte, dataLen) + + // Send the protocol version to the server as a 4-byte little-endian-encoded integer + binary.LittleEndian.PutUint32(data[pos:], uint32(p.VersionDummy_V0_4)) + pos += 4 + + // Send the length of the auth key to the server as a 4-byte little-endian-encoded integer + binary.LittleEndian.PutUint32(data[pos:], uint32(len(c.conn.opts.AuthKey))) + pos += 4 + + // Send the auth key as an ASCII string + if len(c.conn.opts.AuthKey) > 0 { + pos += copy(data[pos:], c.conn.opts.AuthKey) + } + + // Send the protocol type as a 4-byte little-endian-encoded integer + binary.LittleEndian.PutUint32(data[pos:], uint32(p.VersionDummy_JSON)) + pos += 4 + + return c.conn.writeData(data) +} + +func (c *connectionHandshakeV0_4) readHandshakeSuccess() error { + reader := bufio.NewReader(c.conn.Conn) + line, err := reader.ReadBytes('\x00') + if err != nil { + if err == io.EOF { + return fmt.Errorf("Unexpected EOF: %s", string(line)) + } + return err + } + // convert to string and remove trailing NUL byte + response := string(line[:len(line)-1]) + if response != "SUCCESS" { + response = strings.TrimSpace(response) + // we failed authorization or something else terrible happened + return RQLDriverError{rqlError(fmt.Sprintf("Server dropped connection with message: \"%s\"", response))} + } + + return nil +} + +const ( + handshakeV1_0_protocolVersionNumber = 0 + handshakeV1_0_authenticationMethod = "SCRAM-SHA-256" +) + +type connectionHandshakeV1_0 struct { + conn *Connection + reader *bufio.Reader + + authMsg string +} + +func (c *connectionHandshakeV1_0) Send() error { + c.reader = bufio.NewReader(c.conn.Conn) + + // Generate client nonce + clientNonce, err := c.generateNonce() + if err != nil { + c.conn.Close() + return RQLDriverError{rqlError(fmt.Sprintf("Failed to generate client nonce: %s", err))} + } + // Send client first message + if err := c.writeFirstMessage(clientNonce); err != nil { + c.conn.Close() + return err + } + // Read status + if err := c.checkServerVersions(); err != nil { + c.conn.Close() + return err + } + + // Read server first message + i, salt, serverNonce, err := c.readFirstMessage() + if err != nil { + c.conn.Close() + return err + } + + // Check server nonce + if !strings.HasPrefix(serverNonce, clientNonce) { + return RQLAuthError{RQLDriverError{rqlError("Invalid nonce from server")}} + } + + // Generate proof + saltedPass := c.saltPassword(i, salt) + clientProof := c.calculateProof(saltedPass, clientNonce, serverNonce) + serverSignature := c.serverSignature(saltedPass) + + // Send client final message + if err := c.writeFinalMessage(serverNonce, clientProof); err != nil { + c.conn.Close() + return err + } + // Read server final message + if err := c.readFinalMessage(serverSignature); err != nil { + c.conn.Close() + return err + } + + return nil +} + +func (c *connectionHandshakeV1_0) writeFirstMessage(clientNonce string) error { + // Default username to admin if not set + username := "admin" + if c.conn.opts.Username != "" { + username = c.conn.opts.Username + } + + c.authMsg = fmt.Sprintf("n=%s,r=%s", username, clientNonce) + msg := fmt.Sprintf( + `{"protocol_version": %d,"authentication": "n,,%s","authentication_method": "%s"}`, + handshakeV1_0_protocolVersionNumber, c.authMsg, handshakeV1_0_authenticationMethod, + ) + + pos := 0 + dataLen := 4 + len(msg) + 1 + data := make([]byte, dataLen) + + // Send the protocol version to the server as a 4-byte little-endian-encoded integer + binary.LittleEndian.PutUint32(data[pos:], uint32(p.VersionDummy_V1_0)) + pos += 4 + + // Send the auth message as an ASCII string + pos += copy(data[pos:], msg) + + // Add null terminating byte + data[pos] = '\x00' + + return c.writeData(data) +} + +func (c *connectionHandshakeV1_0) checkServerVersions() error { + b, err := c.readResponse() + if err != nil { + return err + } + + // Read status + type versionsResponse struct { + Success bool `json:"success"` + MinProtocolVersion int `json:"min_protocol_version"` + MaxProtocolVersion int `json:"max_protocol_version"` + ServerVersion string `json:"server_version"` + ErrorCode int `json:"error_code"` + Error string `json:"error"` + } + var rsp *versionsResponse + statusStr := string(b) + + if err := json.Unmarshal(b, &rsp); err != nil { + if strings.HasPrefix(statusStr, "ERROR: ") { + statusStr = strings.TrimPrefix(statusStr, "ERROR: ") + return RQLConnectionError{rqlError(statusStr)} + } + + return RQLDriverError{rqlError(fmt.Sprintf("Error reading versions: %s", err))} + } + + if !rsp.Success { + return c.handshakeError(rsp.ErrorCode, rsp.Error) + } + if rsp.MinProtocolVersion > handshakeV1_0_protocolVersionNumber || + rsp.MaxProtocolVersion < handshakeV1_0_protocolVersionNumber { + return RQLDriverError{rqlError( + fmt.Sprintf( + "Unsupported protocol version %d, expected between %d and %d.", + handshakeV1_0_protocolVersionNumber, + rsp.MinProtocolVersion, + rsp.MaxProtocolVersion, + ), + )} + } + + return nil +} + +func (c *connectionHandshakeV1_0) readFirstMessage() (i int64, salt []byte, serverNonce string, err error) { + b, err2 := c.readResponse() + if err2 != nil { + err = err2 + return + } + + // Read server message + type firstMessageResponse struct { + Success bool `json:"success"` + Authentication string `json:"authentication"` + ErrorCode int `json:"error_code"` + Error string `json:"error"` + } + var rsp *firstMessageResponse + + if err2 := json.Unmarshal(b, &rsp); err2 != nil { + err = RQLDriverError{rqlError(fmt.Sprintf("Error parsing auth response: %s", err2))} + return + } + if !rsp.Success { + err = c.handshakeError(rsp.ErrorCode, rsp.Error) + return + } + + c.authMsg += "," + c.authMsg += rsp.Authentication + + // Parse authentication field + auth := map[string]string{} + parts := strings.Split(rsp.Authentication, ",") + for _, part := range parts { + i := strings.Index(part, "=") + if i != -1 { + auth[part[:i]] = part[i+1:] + } + } + + // Extract return values + if v, ok := auth["i"]; ok { + i, err = strconv.ParseInt(v, 10, 64) + if err != nil { + return + } + } + if v, ok := auth["s"]; ok { + salt, err = base64.StdEncoding.DecodeString(v) + if err != nil { + return + } + } + if v, ok := auth["r"]; ok { + serverNonce = v + } + + return +} + +func (c *connectionHandshakeV1_0) writeFinalMessage(serverNonce, clientProof string) error { + authMsg := "c=biws,r=" + authMsg += serverNonce + authMsg += ",p=" + authMsg += clientProof + + msg := fmt.Sprintf(`{"authentication": "%s"}`, authMsg) + + pos := 0 + dataLen := len(msg) + 1 + data := make([]byte, dataLen) + + // Send the auth message as an ASCII string + pos += copy(data[pos:], msg) + + // Add null terminating byte + data[pos] = '\x00' + + return c.writeData(data) +} + +func (c *connectionHandshakeV1_0) readFinalMessage(serverSignature string) error { + b, err := c.readResponse() + if err != nil { + return err + } + + // Read server message + type finalMessageResponse struct { + Success bool `json:"success"` + Authentication string `json:"authentication"` + ErrorCode int `json:"error_code"` + Error string `json:"error"` + } + var rsp *finalMessageResponse + + if err := json.Unmarshal(b, &rsp); err != nil { + return RQLDriverError{rqlError(fmt.Sprintf("Error parsing auth response: %s", err))} + } + if !rsp.Success { + return c.handshakeError(rsp.ErrorCode, rsp.Error) + } + + // Parse authentication field + auth := map[string]string{} + parts := strings.Split(rsp.Authentication, ",") + for _, part := range parts { + i := strings.Index(part, "=") + if i != -1 { + auth[part[:i]] = part[i+1:] + } + } + + // Validate server response + if serverSignature != auth["v"] { + return RQLAuthError{RQLDriverError{rqlError("Invalid server signature")}} + } + + return nil +} + +func (c *connectionHandshakeV1_0) writeData(data []byte) error { + + if err := c.conn.writeData(data); err != nil { + return RQLConnectionError{rqlError(err.Error())} + } + + return nil +} + +func (c *connectionHandshakeV1_0) readResponse() ([]byte, error) { + line, err := c.reader.ReadBytes('\x00') + if err != nil { + if err == io.EOF { + return nil, RQLConnectionError{rqlError(fmt.Sprintf("Unexpected EOF: %s", string(line)))} + } + return nil, RQLConnectionError{rqlError(err.Error())} + } + + // Strip null byte and return + return line[:len(line)-1], nil +} + +func (c *connectionHandshakeV1_0) generateNonce() (string, error) { + const nonceSize = 24 + + b := make([]byte, nonceSize) + _, err := rand.Read(b) + if err != nil { + return "", err + } + + return base64.StdEncoding.EncodeToString(b), nil +} + +func (c *connectionHandshakeV1_0) saltPassword(iter int64, salt []byte) []byte { + pass := []byte(c.conn.opts.Password) + + return pbkdf2.Key(pass, salt, int(iter), sha256.Size, sha256.New) +} + +func (c *connectionHandshakeV1_0) calculateProof(saltedPass []byte, clientNonce, serverNonce string) string { + // Generate proof + c.authMsg += ",c=biws,r=" + serverNonce + + mac := hmac.New(c.hashFunc(), saltedPass) + mac.Write([]byte("Client Key")) + clientKey := mac.Sum(nil) + + hash := c.hashFunc()() + hash.Write(clientKey) + storedKey := hash.Sum(nil) + + mac = hmac.New(c.hashFunc(), storedKey) + mac.Write([]byte(c.authMsg)) + clientSignature := mac.Sum(nil) + clientProof := make([]byte, len(clientKey)) + for i, _ := range clientKey { + clientProof[i] = clientKey[i] ^ clientSignature[i] + } + + return base64.StdEncoding.EncodeToString(clientProof) +} + +func (c *connectionHandshakeV1_0) serverSignature(saltedPass []byte) string { + mac := hmac.New(c.hashFunc(), saltedPass) + mac.Write([]byte("Server Key")) + serverKey := mac.Sum(nil) + + mac = hmac.New(c.hashFunc(), serverKey) + mac.Write([]byte(c.authMsg)) + serverSignature := mac.Sum(nil) + + return base64.StdEncoding.EncodeToString(serverSignature) +} + +func (c *connectionHandshakeV1_0) handshakeError(code int, message string) error { + if code >= 10 || code <= 20 { + return RQLAuthError{RQLDriverError{rqlError(message)}} + } else { + return RQLDriverError{rqlError(message)} + } +} + +func (c *connectionHandshakeV1_0) hashFunc() func() hash.Hash { + return sha256.New +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/connection_helper.go b/vendor/gopkg.in/dancannon/gorethink.v2/connection_helper.go new file mode 100644 index 0000000000..a35522c422 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/connection_helper.go @@ -0,0 +1,47 @@ +package gorethink + +import "encoding/binary" + +// Write 'data' to conn +func (c *Connection) writeData(data []byte) error { + _, err := c.Conn.Write(data[:]) + if err != nil { + return err + } + + return nil +} + +func (c *Connection) read(buf []byte, length int) (total int, err error) { + var n int + for total < length { + if n, err = c.Conn.Read(buf[total:length]); err != nil { + break + } + total += n + } + if err != nil { + return total, err + } + + return total, nil +} + +func (c *Connection) writeQuery(token int64, q []byte) error { + pos := 0 + dataLen := 8 + 4 + len(q) + data := make([]byte, dataLen) + + // Send the protocol version to the server as a 4-byte little-endian-encoded integer + binary.LittleEndian.PutUint64(data[pos:], uint64(token)) + pos += 8 + + // Send the length of the auth key to the server as a 4-byte little-endian-encoded integer + binary.LittleEndian.PutUint32(data[pos:], uint32(len(q))) + pos += 4 + + // Send the auth key as an ASCII string + pos += copy(data[pos:], q) + + return c.writeData(data) +} diff --git a/vendor/github.com/dancannon/gorethink/cursor.go b/vendor/gopkg.in/dancannon/gorethink.v2/cursor.go similarity index 62% rename from vendor/github.com/dancannon/gorethink/cursor.go rename to vendor/gopkg.in/dancannon/gorethink.v2/cursor.go index 4732f8ae8c..29c53f4cf4 100644 --- a/vendor/github.com/dancannon/gorethink/cursor.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/cursor.go @@ -7,8 +7,8 @@ import ( "reflect" "sync" - "github.com/dancannon/gorethink/encoding" - p "github.com/dancannon/gorethink/ql2" + "gopkg.in/dancannon/gorethink.v2/encoding" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) var ( @@ -57,15 +57,16 @@ type Cursor struct { term *Term opts map[string]interface{} - mu sync.RWMutex - lastErr error - fetching bool - closed bool - finished bool - isAtom bool - buffer []interface{} - responses []json.RawMessage - profile interface{} + mu sync.RWMutex + lastErr error + fetching bool + closed bool + finished bool + isAtom bool + pendingSkips int + buffer []interface{} + responses []json.RawMessage + profile interface{} } // Profile returns the information returned from the query profiler. @@ -163,7 +164,7 @@ func (c *Cursor) Next(dest interface{}) bool { return false } - hasMore, err := c.nextLocked(dest) + hasMore, err := c.nextLocked(dest, true) if c.handleErrorLocked(err) != nil { c.mu.Unlock() c.Close() @@ -178,68 +179,21 @@ func (c *Cursor) Next(dest interface{}) bool { return hasMore } -func (c *Cursor) nextLocked(dest interface{}) (bool, error) { +func (c *Cursor) nextLocked(dest interface{}, progressCursor bool) (bool, error) { for { - if c.lastErr != nil { - return false, c.lastErr + if err := c.seekCursor(true); err != nil { + return false, err } - // Check if response is closed/finished - if len(c.buffer) == 0 && len(c.responses) == 0 && c.closed { - return false, errCursorClosed - } - - if len(c.buffer) == 0 && len(c.responses) == 0 && !c.finished { - c.mu.Unlock() - err := c.fetchMore() - c.mu.Lock() - if err != nil { - return false, err - } - // Check if cursor was closed while fetching results - if c.closed { - return false, nil - } - } - - if len(c.buffer) == 0 && len(c.responses) == 0 && c.finished { + if len(c.buffer) == 0 && c.finished { return false, nil } - if len(c.buffer) == 0 && len(c.responses) > 0 { - var response json.RawMessage - response, c.responses = c.responses[0], c.responses[1:] - - var value interface{} - decoder := json.NewDecoder(bytes.NewBuffer(response)) - if c.conn.opts.UseJSONNumber { - decoder.UseNumber() - } - err := decoder.Decode(&value) - if err != nil { - return false, err - } - - value, err = recursivelyConvertPseudotype(value, c.opts) - if err != nil { - return false, err - } - - // If response is an ATOM then try and convert to an array - if data, ok := value.([]interface{}); ok && c.isAtom { - for _, v := range data { - c.buffer = append(c.buffer, v) - } - } else if value == nil { - c.buffer = append(c.buffer, nil) - } else { - c.buffer = append(c.buffer, value) - } - } - if len(c.buffer) > 0 { - var data interface{} - data, c.buffer = c.buffer[0], c.buffer[1:] + data := c.buffer[0] + if progressCursor { + c.buffer = c.buffer[1:] + } err := encoding.Decode(dest, data) if err != nil { @@ -251,7 +205,56 @@ func (c *Cursor) nextLocked(dest interface{}) (bool, error) { } } -// Next retrieves the next raw response from the result set, blocking if necessary. +// Peek behaves similarly to Next, retreiving the next document from the result set +// and blocking if necessary. Peek, however, does not progress the position of the cursor. +// This can be useful for expressions which can return different types to attempt to +// decode them into different interfaces. +// +// Like Next, it will also automatically retrieve another batch of documents from +// the server when the current one is exhausted, or before that in background +// if possible. +// +// Unlike Next, Peek does not progress the position of the cursor. Peek +// will return errors from decoding, but they will not be persisted in the cursor +// and therefore will not be available on cursor.Err(). This can be useful for +// expressions that can return different types to attempt to decode them into +// different interfaces. +// +// Peek returns true if a document was successfully unmarshalled onto result, +// and false at the end of the result set or if an error happened. Peek also +// returns the error (if any) that occured +func (c *Cursor) Peek(dest interface{}) (bool, error) { + c.mu.Lock() + if c.closed { + c.mu.Unlock() + return false, nil + } + + hasMore, err := c.nextLocked(dest, false) + if _, isDecodeErr := err.(*encoding.DecodeTypeError); isDecodeErr { + c.mu.Unlock() + return false, err + } + + if c.handleErrorLocked(err) != nil { + c.mu.Unlock() + c.Close() + return false, err + } + c.mu.Unlock() + + return hasMore, nil +} + +// Skip progresses the cursor by one record. It is useful after a successful +// Peek to avoid duplicate decoding work. +func (c *Cursor) Skip() { + c.mu.Lock() + defer c.mu.Unlock() + c.pendingSkips++ +} + +// NextResponse retrieves the next raw response from the result set, blocking if necessary. // Unlike Next the returned response is the raw JSON document returned from the // database. // @@ -281,26 +284,8 @@ func (c *Cursor) NextResponse() ([]byte, bool) { func (c *Cursor) nextResponseLocked() ([]byte, bool, error) { for { - if c.lastErr != nil { - return nil, false, c.lastErr - } - - // Check if response is closed/finished - if len(c.responses) == 0 && c.closed { - return nil, false, errCursorClosed - } - - if len(c.responses) == 0 && !c.finished { - c.mu.Unlock() - err := c.fetchMore() - c.mu.Lock() - if err != nil { - return nil, false, err - } - // Check if cursor was closed while fetching results - if c.closed { - return nil, false, nil - } + if err := c.seekCursor(false); err != nil { + return nil, false, err } if len(c.responses) == 0 && c.finished { @@ -467,13 +452,11 @@ func (c *Cursor) IsNil() bool { func (c *Cursor) fetchMore() error { var err error - c.mu.Lock() fetching := c.fetching closed := c.closed if !fetching { c.fetching = true - c.mu.Unlock() if closed { return errCursorClosed @@ -484,9 +467,9 @@ func (c *Cursor) fetchMore() error { Token: c.token, } - _, _, err = c.conn.Query(q) - } else { c.mu.Unlock() + _, _, err = c.conn.Query(q) + c.mu.Lock() } return err @@ -527,3 +510,110 @@ func (c *Cursor) extendLocked(response *Response) { putResponse(response) } + +// seekCursor takes care of loading more data if needed and applying pending skips +// +// bufferResponse determines whether the response will be parsed into the buffer +func (c *Cursor) seekCursor(bufferResponse bool) error { + if c.lastErr != nil { + return c.lastErr + } + + if len(c.buffer) == 0 && len(c.responses) == 0 && c.closed { + return errCursorClosed + } + + // Loop over loading data, applying skips as necessary and loading more data as needed + // until either the cursor is closed or finished, or we have applied all outstanding + // skips and data is available + for { + c.applyPendingSkips(bufferResponse) // if we are buffering the responses, skip can drain from the buffer + + if bufferResponse && len(c.buffer) == 0 && len(c.responses) > 0 { + if err := c.bufferNextResponse(); err != nil { + return err + } + continue // go around the loop again to re-apply pending skips + } else if len(c.buffer) == 0 && len(c.responses) == 0 && !c.finished && !c.closed { + // We skipped all of our data, load some more + if err := c.fetchMore(); err != nil { + return err + } + continue // go around the loop again to re-apply pending skips + } + return nil + } +} + +// applyPendingSkips applies all pending skips to the buffer and +// returns whether there are more pending skips to be applied +// +// if drainFromBuffer is true, we will drain from the buffer, otherwise +// we drain from the responses +func (c *Cursor) applyPendingSkips(drainFromBuffer bool) (stillPending bool) { + if c.pendingSkips == 0 { + return false + } + + if drainFromBuffer { + if len(c.buffer) > c.pendingSkips { + c.buffer = c.buffer[c.pendingSkips:] + c.pendingSkips = 0 + return false + } + + c.pendingSkips -= len(c.buffer) + c.buffer = c.buffer[:0] + return c.pendingSkips > 0 + } + + if len(c.responses) > c.pendingSkips { + c.responses = c.responses[c.pendingSkips:] + c.pendingSkips = 0 + return false + } + + c.pendingSkips -= len(c.responses) + c.responses = c.responses[:0] + return c.pendingSkips > 0 +} + +// bufferResponse reads a single response and stores the result into the buffer +// if the response is from an atomic response, it will check if the +// response contains multiple records and store them all into the buffer +func (c *Cursor) bufferNextResponse() error { + // If there are no responses, nothing to do + if len(c.responses) == 0 { + return nil + } + + response := c.responses[0] + c.responses = c.responses[1:] + + var value interface{} + decoder := json.NewDecoder(bytes.NewBuffer(response)) + if c.conn.opts.UseJSONNumber { + decoder.UseNumber() + } + err := decoder.Decode(&value) + if err != nil { + return err + } + + value, err = recursivelyConvertPseudotype(value, c.opts) + if err != nil { + return err + } + + // If response is an ATOM then try and convert to an array + if data, ok := value.([]interface{}); ok && c.isAtom { + for _, v := range data { + c.buffer = append(c.buffer, v) + } + } else if value == nil { + c.buffer = append(c.buffer, nil) + } else { + c.buffer = append(c.buffer, value) + } + return nil +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/cursor_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/cursor_test.go new file mode 100644 index 0000000000..be1d83e04d --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/cursor_test.go @@ -0,0 +1,530 @@ +package gorethink + +import ( + "fmt" + "time" + + test "gopkg.in/check.v1" +) + +type object struct { + ID int64 `gorethink:"id,omitempty"` + Name string `gorethink:"name"` + Attrs []attr +} + +type attr struct { + Name string + Value interface{} +} + +func (s *RethinkSuite) TestCursorLiteral(c *test.C) { + res, err := Expr(5).Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.Type(), test.Equals, "Cursor") + + var response interface{} + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, 5) +} + +func (s *RethinkSuite) TestCursorSlice(c *test.C) { + res, err := Expr([]interface{}{1, 2, 3, 4, 5}).Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.Type(), test.Equals, "Cursor") + + var response []interface{} + err = res.All(&response) + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2, 3, 4, 5}) +} + +func (s *RethinkSuite) TestCursorPartiallyNilSlice(c *test.C) { + res, err := Expr(map[string]interface{}{ + "item": []interface{}{ + map[string]interface{}{"num": 1}, + nil, + }, + }).Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.Type(), test.Equals, "Cursor") + + var response map[string]interface{} + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{ + "item": []interface{}{ + map[string]interface{}{"num": 1}, + nil, + }, + }) +} + +func (s *RethinkSuite) TestCursorMap(c *test.C) { + res, err := Expr(map[string]interface{}{ + "id": 2, + "name": "Object 1", + }).Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.Type(), test.Equals, "Cursor") + + var response map[string]interface{} + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{ + "id": 2, + "name": "Object 1", + }) +} + +func (s *RethinkSuite) TestCursorMapIntoInterface(c *test.C) { + res, err := Expr(map[string]interface{}{ + "id": 2, + "name": "Object 1", + }).Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.Type(), test.Equals, "Cursor") + + var response interface{} + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{ + "id": 2, + "name": "Object 1", + }) +} + +func (s *RethinkSuite) TestCursorMapNested(c *test.C) { + res, err := Expr(map[string]interface{}{ + "id": 2, + "name": "Object 1", + "attr": []interface{}{map[string]interface{}{ + "name": "attr 1", + "value": "value 1", + }}, + }).Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.Type(), test.Equals, "Cursor") + + var response interface{} + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{ + "id": 2, + "name": "Object 1", + "attr": []interface{}{map[string]interface{}{ + "name": "attr 1", + "value": "value 1", + }}, + }) +} + +func (s *RethinkSuite) TestCursorStruct(c *test.C) { + res, err := Expr(map[string]interface{}{ + "id": 2, + "name": "Object 1", + "Attrs": []interface{}{map[string]interface{}{ + "Name": "attr 1", + "Value": "value 1", + }}, + }).Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.Type(), test.Equals, "Cursor") + + var response object + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.DeepEquals, object{ + ID: 2, + Name: "Object 1", + Attrs: []attr{attr{ + Name: "attr 1", + Value: "value 1", + }}, + }) +} + +func (s *RethinkSuite) TestCursorStructPseudoTypes(c *test.C) { + var zeroTime time.Time + t := time.Now() + + res, err := Expr(map[string]interface{}{ + "T": time.Unix(t.Unix(), 0).In(time.UTC), + "Z": zeroTime, + "B": []byte("hello"), + }).Run(session) + c.Assert(err, test.IsNil) + + var response PseudoTypes + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(res.Type(), test.Equals, "Cursor") + + c.Assert(response.T.Equal(time.Unix(t.Unix(), 0)), test.Equals, true) + c.Assert(response.Z.Equal(zeroTime), test.Equals, true) + c.Assert(response.B, jsonEquals, []byte("hello")) +} + +func (s *RethinkSuite) TestCursorAtomString(c *test.C) { + res, err := Expr("a").Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.Type(), test.Equals, "Cursor") + + var response string + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "a") +} + +func (s *RethinkSuite) TestCursorAtomArray(c *test.C) { + res, err := Expr([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}).Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.Type(), test.Equals, "Cursor") + + var response []int + err = res.All(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.DeepEquals, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}) +} + +func (s *RethinkSuite) TestEmptyResults(c *test.C) { + DBCreate("test").Exec(session) + DB("test").TableCreate("test").Exec(session) + res, err := DB("test").Table("test").Get("missing value").Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.IsNil(), test.Equals, true) + + res, err = DB("test").Table("test").Get("missing value").Run(session) + c.Assert(err, test.IsNil) + var response interface{} + err = res.One(&response) + c.Assert(err, test.Equals, ErrEmptyResult) + c.Assert(res.IsNil(), test.Equals, true) + + res, err = Expr(nil).Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.IsNil(), test.Equals, true) + + res, err = DB("test").Table("test").Get("missing value").Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.IsNil(), test.Equals, true) + + res, err = DB("test").Table("test").GetAll("missing value", "another missing value").Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.Next(&response), test.Equals, false) + + var obj object + obj.Name = "missing value" + res, err = DB("test").Table("test").Filter(obj).Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.IsNil(), test.Equals, true) + + var objP *object + + res, err = DB("test").Table("test").Get("missing value").Run(session) + res.Next(&objP) + c.Assert(err, test.IsNil) + c.Assert(objP, test.IsNil) +} + +func (s *RethinkSuite) TestCursorAll(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableDrop("Table3").Exec(session) + DB("test").TableCreate("Table3").Exec(session) + DB("test").Table("Table3").IndexCreate("num").Exec(session) + DB("test").Table("Table3").IndexWait().Exec(session) + + // Insert rows + DB("test").Table("Table3").Insert([]interface{}{ + map[string]interface{}{ + "id": 2, + "name": "Object 1", + "Attrs": []interface{}{map[string]interface{}{ + "Name": "attr 1", + "Value": "value 1", + }}, + }, + map[string]interface{}{ + "id": 3, + "name": "Object 2", + "Attrs": []interface{}{map[string]interface{}{ + "Name": "attr 1", + "Value": "value 1", + }}, + }, + }).Exec(session) + + // Test query + query := DB("test").Table("Table3").OrderBy("id") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + var response []object + err = res.All(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.HasLen, 2) + c.Assert(response, test.DeepEquals, []object{ + object{ + ID: 2, + Name: "Object 1", + Attrs: []attr{attr{ + Name: "attr 1", + Value: "value 1", + }}, + }, + object{ + ID: 3, + Name: "Object 2", + Attrs: []attr{attr{ + Name: "attr 1", + Value: "value 1", + }}, + }, + }) +} + +func (s *RethinkSuite) TestCursorListen(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableDrop("Table3").Exec(session) + DB("test").TableCreate("Table3").Exec(session) + DB("test").Table("Table3").IndexCreate("num").Exec(session) + DB("test").Table("Table3").IndexWait().Exec(session) + + // Insert rows + DB("test").Table("Table3").Insert([]interface{}{ + map[string]interface{}{ + "id": 2, + "name": "Object 1", + "Attrs": []interface{}{map[string]interface{}{ + "Name": "attr 1", + "Value": "value 1", + }}, + }, + map[string]interface{}{ + "id": 3, + "name": "Object 2", + "Attrs": []interface{}{map[string]interface{}{ + "Name": "attr 1", + "Value": "value 1", + }}, + }, + }).Exec(session) + + // Test query + query := DB("test").Table("Table3").OrderBy("id") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + ch := make(chan object) + res.Listen(ch) + var response []object + for v := range ch { + response = append(response, v) + } + + c.Assert(response, test.HasLen, 2) + c.Assert(response, test.DeepEquals, []object{ + object{ + ID: 2, + Name: "Object 1", + Attrs: []attr{attr{ + Name: "attr 1", + Value: "value 1", + }}, + }, + object{ + ID: 3, + Name: "Object 2", + Attrs: []attr{attr{ + Name: "attr 1", + Value: "value 1", + }}, + }, + }) +} + +func (s *RethinkSuite) TestCursorChangesClose(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableDrop("Table3").Exec(session) + DB("test").TableCreate("Table3").Exec(session) + + // Test query + // res, err := DB("test").Table("Table3").Changes().Run(session) + res, err := DB("test").Table("Table3").Changes().Run(session) + c.Assert(err, test.IsNil) + c.Assert(res, test.NotNil) + + // Ensure that the cursor can be closed + err = res.Close() + c.Assert(err, test.IsNil) +} + +func (s *RethinkSuite) TestCursorReuseResult(c *test.C) { + // Test query + query := Expr([]interface{}{ + map[string]interface{}{ + "A": "a", + }, + map[string]interface{}{ + "B": 1, + }, + map[string]interface{}{ + "A": "a", + }, + map[string]interface{}{ + "B": 1, + }, + map[string]interface{}{ + "A": "a", + "B": 1, + }, + }) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + var i int + var result SimpleT + for res.Next(&result) { + switch i { + case 0: + c.Assert(result, test.DeepEquals, SimpleT{ + A: "a", + B: 0, + }) + case 1: + c.Assert(result, test.DeepEquals, SimpleT{ + A: "", + B: 1, + }) + case 2: + c.Assert(result, test.DeepEquals, SimpleT{ + A: "a", + B: 0, + }) + case 3: + c.Assert(result, test.DeepEquals, SimpleT{ + A: "", + B: 1, + }) + case 4: + c.Assert(result, test.DeepEquals, SimpleT{ + A: "a", + B: 1, + }) + default: + c.Fatalf("Unexpected number of results") + } + + i++ + } + c.Assert(res.Err(), test.IsNil) +} + +func (s *RethinkSuite) TestCursorNextResponse(c *test.C) { + res, err := Expr(5).Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.Type(), test.Equals, "Cursor") + + b, ok := res.NextResponse() + c.Assert(ok, test.Equals, true) + c.Assert(b, jsonEquals, []byte(`5`)) +} + +func (s *RethinkSuite) TestCursorNextResponse_object(c *test.C) { + res, err := Expr(map[string]string{"foo": "bar"}).Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.Type(), test.Equals, "Cursor") + + b, ok := res.NextResponse() + c.Assert(ok, test.Equals, true) + c.Assert(b, jsonEquals, []byte(`{"foo":"bar"}`)) +} + +func (s *RethinkSuite) TestCursorPeek_idempotency(c *test.C) { + res, err := Expr([]int{1, 2, 3}).Run(session) + c.Assert(err, test.IsNil) + + var result int + + // Test idempotency + for i := 0; i < 2; i++ { + hasMore, err := res.Peek(&result) + c.Assert(err, test.IsNil) + c.Assert(result, test.Equals, 1) + c.Assert(hasMore, test.Equals, true) + } + +} + +func (s *RethinkSuite) TestCursorPeek_wrong_type(c *test.C) { + res, err := Expr([]int{1, 2, 3}).Run(session) + c.Assert(err, test.IsNil) + + // Test that wrongType doesn't break the cursor + wrongType := struct { + Name string + Age int + }{} + + hasMore, err := res.Peek(&wrongType) + c.Assert(err, test.NotNil) + c.Assert(hasMore, test.Equals, false) + c.Assert(res.Err(), test.IsNil) +} + +func (s *RethinkSuite) TestCursorPeek_usage(c *test.C) { + res, err := Expr([]int{1, 2, 3}).Run(session) + c.Assert(err, test.IsNil) + + var result int + + // Test that Skip progresses our cursor + res.Skip() + hasMore, err := res.Peek(&result) + c.Assert(err, test.IsNil) + c.Assert(result, test.Equals, 2) + c.Assert(hasMore, test.Equals, true) + + // Test that we can use Next afterwards and we get the same result + hasMore = res.Next(&result) + c.Assert(result, test.Equals, 2) + c.Assert(hasMore, test.Equals, true) +} + +func (s *RethinkSuite) TestCursorSkip(c *test.C) { + res, err := Expr([]int{1, 2, 3}).Run(session) + c.Assert(err, test.IsNil) + + res.Skip() + + var result int + hasMore := res.Next(&result) + c.Assert(result, test.Equals, 2) + c.Assert(hasMore, test.Equals, true) +} + +func ExampleCursor_Peek() { + res, err := Expr([]int{1, 2, 3}).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var result, altResult int + wasRead, err := res.Peek(&result) // Result is now 1 + if err != nil { + fmt.Print(err) + return + } else if !wasRead { + fmt.Print("No data to read!") + } + + res.Next(&altResult) // altResult is also 1, peek didn't progress the cursor + + res.Skip() // progress the cursor, skipping 2 + res.Peek(&result) // result is now 3 +} diff --git a/vendor/github.com/dancannon/gorethink/doc.go b/vendor/gopkg.in/dancannon/gorethink.v2/doc.go similarity index 81% rename from vendor/github.com/dancannon/gorethink/doc.go rename to vendor/gopkg.in/dancannon/gorethink.v2/doc.go index 26fd762feb..daa47c46bb 100644 --- a/vendor/github.com/dancannon/gorethink/doc.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/doc.go @@ -1,6 +1,6 @@ // Package gorethink implements a Go driver for RethinkDB // -// Current version: v1.4.0 (RethinkDB v2.2) +// Current version: v2.0.0 (RethinkDB v2.3) // For more in depth information on how to use RethinkDB check out the API docs // at http://rethinkdb.com/api package gorethink diff --git a/vendor/github.com/dancannon/gorethink/encoding/cache.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/cache.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/encoding/cache.go rename to vendor/gopkg.in/dancannon/gorethink.v2/encoding/cache.go diff --git a/vendor/github.com/dancannon/gorethink/encoding/decoder.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/decoder.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/encoding/decoder.go rename to vendor/gopkg.in/dancannon/gorethink.v2/encoding/decoder.go diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/encoding/decoder_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/decoder_test.go new file mode 100644 index 0000000000..e441927d0e --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/decoder_test.go @@ -0,0 +1,466 @@ +package encoding + +import ( + "bytes" + "encoding/json" + "image" + "reflect" + "testing" +) + +type T struct { + X string + Y int + Z int `gorethink:"-"` +} + +type U struct { + Alphabet string `gorethink:"alpha"` +} + +type V struct { + F1 interface{} + F2 int32 + F3 string +} + +type tx struct { + x int +} + +var txType = reflect.TypeOf((*tx)(nil)).Elem() + +// Test data structures for anonymous fields. + +type Point struct { + Z int +} + +type Top struct { + Level0 int + Embed0 + *Embed0a + *Embed0b `gorethink:"e,omitempty"` // treated as named + Embed0c `gorethink:"-"` // ignored + Loop + Embed0p // has Point with X, Y, used + Embed0q // has Point with Z, used +} + +type Embed0 struct { + Level1a int // overridden by Embed0a's Level1a with tag + Level1b int // used because Embed0a's Level1b is renamed + Level1c int // used because Embed0a's Level1c is ignored + Level1d int // annihilated by Embed0a's Level1d + Level1e int `gorethink:"x"` // annihilated by Embed0a.Level1e +} + +type Embed0a struct { + Level1a int `gorethink:"Level1a,omitempty"` + Level1b int `gorethink:"LEVEL1B,omitempty"` + Level1c int `gorethink:"-"` + Level1d int // annihilated by Embed0's Level1d + Level1f int `gorethink:"x"` // annihilated by Embed0's Level1e +} + +type Embed0b Embed0 + +type Embed0c Embed0 + +type Embed0p struct { + image.Point +} + +type Embed0q struct { + Point +} + +type Loop struct { + Loop1 int `gorethink:",omitempty"` + Loop2 int `gorethink:",omitempty"` + *Loop +} + +// From reflect test: +// The X in S6 and S7 annihilate, but they also block the X in S8.S9. +type S5 struct { + S6 + S7 + S8 +} + +type S6 struct { + X int +} + +type S7 S6 + +type S8 struct { + S9 +} + +type S9 struct { + X int + Y int +} + +// From reflect test: +// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9. +type S10 struct { + S11 + S12 + S13 +} + +type S11 struct { + S6 +} + +type S12 struct { + S6 +} + +type S13 struct { + S8 +} + +type PointerBasic struct { + X int + Y *int +} + +type Pointer struct { + PPoint *Point + Point Point +} + +type decodeTest struct { + in interface{} + ptr interface{} + out interface{} + err error +} + +type Ambig struct { + // Given "hello", the first match should win. + First int `gorethink:"HELLO"` + Second int `gorethink:"Hello"` +} + +// Decode test helper vars +var ( + sampleInt = 2 +) + +var decodeTests = []decodeTest{ + // basic types + {in: true, ptr: new(bool), out: true}, + {in: 1, ptr: new(int), out: 1}, + {in: 1.2, ptr: new(float64), out: 1.2}, + {in: -5, ptr: new(int16), out: int16(-5)}, + {in: 2, ptr: new(string), out: string("2")}, + {in: float64(2.0), ptr: new(interface{}), out: float64(2.0)}, + {in: string("2"), ptr: new(interface{}), out: string("2")}, + {in: "a\u1234", ptr: new(string), out: "a\u1234"}, + {in: []interface{}{}, ptr: new([]string), out: []string{}}, + {in: map[string]interface{}{"X": []interface{}{1, 2, 3}, "Y": 4}, ptr: new(T), out: T{}, err: &DecodeTypeError{reflect.TypeOf(""), reflect.TypeOf([]interface{}{}), ""}}, + {in: map[string]interface{}{"x": 1}, ptr: new(tx), out: tx{}}, + {in: map[string]interface{}{"F1": float64(1), "F2": 2, "F3": 3}, ptr: new(V), out: V{F1: float64(1), F2: int32(2), F3: string("3")}}, + {in: map[string]interface{}{"F1": string("1"), "F2": 2, "F3": 3}, ptr: new(V), out: V{F1: string("1"), F2: int32(2), F3: string("3")}}, + { + in: map[string]interface{}{"k1": int64(1), "k2": "s", "k3": []interface{}{int64(1), 2.0, 3e-3}, "k4": map[string]interface{}{"kk1": "s", "kk2": int64(2)}}, + out: map[string]interface{}{"k1": int64(1), "k2": "s", "k3": []interface{}{int64(1), 2.0, 3e-3}, "k4": map[string]interface{}{"kk1": "s", "kk2": int64(2)}}, + ptr: new(interface{}), + }, + + // Z has a "-" tag. + {in: map[string]interface{}{"Y": 1, "Z": 2}, ptr: new(T), out: T{Y: 1}}, + + {in: map[string]interface{}{"alpha": "abc", "alphabet": "xyz"}, ptr: new(U), out: U{Alphabet: "abc"}}, + {in: map[string]interface{}{"alpha": "abc"}, ptr: new(U), out: U{Alphabet: "abc"}}, + {in: map[string]interface{}{"alphabet": "xyz"}, ptr: new(U), out: U{}}, + + // array tests + {in: []interface{}{1, 2, 3}, ptr: new([3]int), out: [3]int{1, 2, 3}}, + {in: []interface{}{1, 2, 3}, ptr: new([1]int), out: [1]int{1}}, + {in: []interface{}{1, 2, 3}, ptr: new([5]int), out: [5]int{1, 2, 3, 0, 0}}, + + // empty array to interface test + {in: map[string]interface{}{"T": []interface{}{}}, ptr: new(map[string]interface{}), out: map[string]interface{}{"T": []interface{}{}}}, + + { + in: map[string]interface{}{ + "Level0": 1, + "Level1b": 2, + "Level1c": 3, + "level1d": 4, + "Level1a": 5, + "LEVEL1B": 6, + "e": map[string]interface{}{ + "Level1a": 8, + "Level1b": 9, + "Level1c": 10, + "Level1d": 11, + "x": 12, + }, + "Loop1": 13, + "Loop2": 14, + "X": 15, + "Y": 16, + "Z": 17, + }, + ptr: new(Top), + out: Top{ + Level0: 1, + Embed0: Embed0{ + Level1b: 2, + Level1c: 3, + }, + Embed0a: &Embed0a{ + Level1a: 5, + Level1b: 6, + }, + Embed0b: &Embed0b{ + Level1a: 8, + Level1b: 9, + Level1c: 10, + Level1d: 11, + }, + Loop: Loop{ + Loop1: 13, + Loop2: 14, + }, + Embed0p: Embed0p{ + Point: image.Point{X: 15, Y: 16}, + }, + Embed0q: Embed0q{ + Point: Point{Z: 17}, + }, + }, + }, + { + in: map[string]interface{}{"hello": 1}, + ptr: new(Ambig), + out: Ambig{First: 1}, + }, + { + in: map[string]interface{}{"X": 1, "Y": 2}, + ptr: new(S5), + out: S5{S8: S8{S9: S9{Y: 2}}}, + }, + { + in: map[string]interface{}{"X": 1, "Y": 2}, + ptr: new(S10), + out: S10{S13: S13{S8: S8{S9: S9{Y: 2}}}}, + }, + { + in: map[string]interface{}{"PPoint": map[string]interface{}{"Z": 1}, "Point": map[string]interface{}{"Z": 2}}, + ptr: new(Pointer), + out: Pointer{PPoint: &Point{Z: 1}, Point: Point{Z: 2}}, + }, + { + in: map[string]interface{}{"Point": map[string]interface{}{"Z": 2}}, + ptr: new(Pointer), + out: Pointer{PPoint: nil, Point: Point{Z: 2}}, + }, + { + in: map[string]interface{}{"x": 2}, + ptr: new(PointerBasic), + out: PointerBasic{X: 2, Y: nil}, + }, + { + in: map[string]interface{}{"x": 2, "y": 2}, + ptr: new(PointerBasic), + out: PointerBasic{X: 2, Y: &sampleInt}, + }, +} + +func TestDecode(t *testing.T) { + for i, tt := range decodeTests { + if tt.ptr == nil { + continue + } + + // v = new(right-type) + v := reflect.New(reflect.TypeOf(tt.ptr).Elem()) + + err := Decode(v.Interface(), tt.in) + if !jsonEqual(err, tt.err) { + t.Errorf("#%d: got error %v want %v", i, err, tt.err) + continue + } + + if tt.err == nil && !jsonEqual(v.Elem().Interface(), tt.out) { + t.Errorf("#%d: mismatch\nhave: %+v\nwant: %+v", i, v.Elem().Interface(), tt.out) + continue + } + + // Check round trip. + if tt.err == nil { + enc, err := Encode(v.Interface()) + if err != nil { + t.Errorf("#%d: error re-marshaling: %v", i, err) + continue + } + vv := reflect.New(reflect.TypeOf(tt.ptr).Elem()) + + if err := Decode(vv.Interface(), enc); err != nil { + t.Errorf("#%d: error re-decodeing: %v", i, err) + continue + } + if !jsonEqual(v.Elem().Interface(), vv.Elem().Interface()) { + t.Errorf("#%d: mismatch\nhave: %#+v\nwant: %#+v", i, v.Elem().Interface(), vv.Elem().Interface()) + continue + } + } + } +} + +func TestStringKind(t *testing.T) { + type aMap map[string]int + + var m1, m2 map[string]int + m1 = map[string]int{ + "foo": 42, + } + + data, err := Encode(m1) + if err != nil { + t.Errorf("Unexpected error encoding: %v", err) + } + + err = Decode(&m2, data) + if err != nil { + t.Errorf("Unexpected error decoding: %v", err) + } + + if !jsonEqual(m1, m2) { + t.Error("Items should be equal after encoding and then decoding") + } + +} + +// Test handling of unexported fields that should be ignored. +type unexportedFields struct { + Name string + m map[string]interface{} `gorethink:"-"` + m2 map[string]interface{} `gorethink:"abcd"` +} + +func TestDecodeUnexported(t *testing.T) { + input := map[string]interface{}{ + "Name": "Bob", + "m": map[string]interface{}{ + "x": 123, + }, + "m2": map[string]interface{}{ + "y": 123, + }, + "abcd": map[string]interface{}{ + "z": 789, + }, + } + want := &unexportedFields{Name: "Bob"} + + out := &unexportedFields{} + err := Decode(out, input) + if err != nil { + t.Errorf("got error %v, expected nil", err) + } + if !jsonEqual(out, want) { + t.Errorf("got %q, want %q", out, want) + } +} + +type Foo struct { + FooBar interface{} `gorethink:"foobar"` +} +type Bar struct { + Baz int `gorethink:"baz"` +} + +type UnmarshalerPointer struct { + Value *UnmarshalerValue +} + +type UnmarshalerValue struct { + ValueInt int64 + ValueString string +} + +func (v *UnmarshalerValue) MarshalRQL() (interface{}, error) { + if v.ValueInt != int64(0) { + return Encode(v.ValueInt) + } + if v.ValueString != "" { + return Encode(v.ValueString) + } + + return Encode(nil) +} + +func (v *UnmarshalerValue) UnmarshalRQL(b interface{}) (err error) { + n, s := int64(0), "" + + if err = Decode(&s, b); err == nil { + v.ValueString = s + return + } + if err = Decode(&n, b); err == nil { + v.ValueInt = n + + } + + return +} + +func TestDecodeUnmarshalerPointer(t *testing.T) { + input := map[string]interface{}{ + "Value": "abc", + } + want := &UnmarshalerPointer{ + Value: &UnmarshalerValue{ValueString: "abc"}, + } + + out := &UnmarshalerPointer{} + err := Decode(out, input) + if err != nil { + t.Errorf("got error %v, expected nil", err) + } + if !jsonEqual(out, want) { + t.Errorf("got %q, want %q", out, want) + } +} + +func TestDecodeMapIntKeys(t *testing.T) { + input := map[string]int{"1": 1, "2": 2, "3": 3} + want := map[int]int{1: 1, 2: 2, 3: 3} + + out := map[int]int{} + err := Decode(&out, input) + if err != nil { + t.Errorf("got error %v, expected nil", err) + } + if !jsonEqual(out, want) { + t.Errorf("got %q, want %q", out, want) + } +} + +func jsonEqual(a, b interface{}) bool { + // First check using reflect.DeepEqual + if reflect.DeepEqual(a, b) { + return true + } + + // Then use jsonEqual + ba, err := json.Marshal(a) + if err != nil { + panic(err) + } + bb, err := json.Marshal(b) + if err != nil { + panic(err) + } + + return bytes.Compare(ba, bb) == 0 +} diff --git a/vendor/github.com/dancannon/gorethink/encoding/decoder_types.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/decoder_types.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/encoding/decoder_types.go rename to vendor/gopkg.in/dancannon/gorethink.v2/encoding/decoder_types.go diff --git a/vendor/github.com/dancannon/gorethink/encoding/encoder.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoder.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/encoding/encoder.go rename to vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoder.go diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoder_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoder_test.go new file mode 100644 index 0000000000..560a042d49 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoder_test.go @@ -0,0 +1,349 @@ +package encoding + +import ( + "image" + "reflect" + "testing" + "time" +) + +var encodeExpected = map[string]interface{}{ + "Level0": int64(1), + "Level1b": int64(2), + "Level1c": int64(3), + "Level1a": int64(5), + "LEVEL1B": int64(6), + "e": map[string]interface{}{ + "Level1a": int64(8), + "Level1b": int64(9), + "Level1c": int64(10), + "Level1d": int64(11), + "x": int64(12), + }, + "Loop1": int64(13), + "Loop2": int64(14), + "X": int64(15), + "Y": int64(16), + "Z": int64(17), +} + +func TestEncode(t *testing.T) { + // Top is defined in decoder_test.go + var in = Top{ + Level0: 1, + Embed0: Embed0{ + Level1b: 2, + Level1c: 3, + }, + Embed0a: &Embed0a{ + Level1a: 5, + Level1b: 6, + }, + Embed0b: &Embed0b{ + Level1a: 8, + Level1b: 9, + Level1c: 10, + Level1d: 11, + Level1e: 12, + }, + Loop: Loop{ + Loop1: 13, + Loop2: 14, + }, + Embed0p: Embed0p{ + Point: image.Point{X: 15, Y: 16}, + }, + Embed0q: Embed0q{ + Point: Point{Z: 17}, + }, + } + + got, err := Encode(&in) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(got, encodeExpected) { + t.Errorf(" got: %v\nwant: %v\n", got, encodeExpected) + } +} + +type Optionals struct { + Sr string `gorethink:"sr"` + So string `gorethink:"so,omitempty"` + Sw string `gorethink:"-"` + + Ir int `gorethink:"omitempty"` // actually named omitempty, not an option + Io int `gorethink:"io,omitempty"` + + Tr time.Time `gorethink:"tr"` + To time.Time `gorethink:"to,omitempty"` + + Slr []string `gorethink:"slr"` + Slo []string `gorethink:"slo,omitempty"` + + Mr map[string]interface{} `gorethink:"mr"` + Mo map[string]interface{} `gorethink:",omitempty"` +} + +var optionalsExpected = map[string]interface{}{ + "sr": "", + "omitempty": int64(0), + "tr": map[string]interface{}{"$reql_type$": "TIME", "epoch_time": 0, "timezone": "+00:00"}, + "slr": []interface{}{}, + "mr": map[string]interface{}{}, +} + +func TestOmitEmpty(t *testing.T) { + var o Optionals + o.Sw = "something" + o.Tr = time.Unix(0, 0).In(time.UTC) + o.Mr = map[string]interface{}{} + o.Mo = map[string]interface{}{} + + got, err := Encode(&o) + if err != nil { + t.Fatal(err) + } + if !jsonEqual(got, optionalsExpected) { + t.Errorf("\ngot: %#v\nwant: %#v\n", got, optionalsExpected) + } +} + +type IntType int + +type MyStruct struct { + IntType +} + +func TestAnonymousNonstruct(t *testing.T) { + var i IntType = 11 + a := MyStruct{i} + var want = map[string]interface{}{"IntType": int64(11)} + + got, err := Encode(a) + if err != nil { + t.Fatalf("Encode: %v", err) + } + if !reflect.DeepEqual(got, want) { + t.Errorf("got %v, want %v", got, want) + } +} + +func TestEncodePointer(t *testing.T) { + v := Pointer{PPoint: &Point{Z: 1}, Point: Point{Z: 2}} + var want = map[string]interface{}{ + "PPoint": map[string]interface{}{"Z": int64(1)}, + "Point": map[string]interface{}{"Z": int64(2)}, + } + + got, err := Encode(v) + if err != nil { + t.Fatalf("Encode: %v", err) + } + if !reflect.DeepEqual(got, want) { + t.Errorf("got %v, want %v", got, want) + } +} + +func TestEncodeNilPointer(t *testing.T) { + v := Pointer{PPoint: nil, Point: Point{Z: 2}} + var want = map[string]interface{}{ + "PPoint": nil, + "Point": map[string]interface{}{"Z": int64(2)}, + } + + got, err := Encode(v) + if err != nil { + t.Fatalf("Encode: %v", err) + } + if !reflect.DeepEqual(got, want) { + t.Errorf("got %v, want %v", got, want) + } +} + +type BugA struct { + S string +} + +type BugB struct { + BugA + S string +} + +type BugC struct { + S string +} + +// Legal Go: We never use the repeated embedded field (S). +type BugX struct { + A int + BugA + BugB +} + +// Issue 5245. +func TestEmbeddedBug(t *testing.T) { + v := BugB{ + BugA{"A"}, + "B", + } + got, err := Encode(v) + if err != nil { + t.Fatal("Encode:", err) + } + want := map[string]interface{}{"S": "B"} + if !reflect.DeepEqual(got, want) { + t.Fatalf("Encode: got %v want %v", got, want) + } + // Now check that the duplicate field, S, does not appear. + x := BugX{ + A: 23, + } + got, err = Encode(x) + if err != nil { + t.Fatal("Encode:", err) + } + want = map[string]interface{}{"A": int64(23)} + if !reflect.DeepEqual(got, want) { + t.Fatalf("Encode: got %v want %v", got, want) + } +} + +type BugD struct { // Same as BugA after tagging. + XXX string `gorethink:"S"` +} + +// BugD's tagged S field should dominate BugA's. +type BugY struct { + BugA + BugD +} + +// Test that a field with a tag dominates untagged fields. +func TestTaggedFieldDominates(t *testing.T) { + v := BugY{ + BugA{"BugA"}, + BugD{"BugD"}, + } + got, err := Encode(v) + if err != nil { + t.Fatal("Encode:", err) + } + want := map[string]interface{}{"S": "BugD"} + if !reflect.DeepEqual(got, want) { + t.Fatalf("Encode: got %v want %v", got, want) + } +} + +// There are no tags here, so S should not appear. +type BugZ struct { + BugA + BugC + BugY // Contains a tagged S field through BugD; should not dominate. +} + +func TestDuplicatedFieldDisappears(t *testing.T) { + v := BugZ{ + BugA{"BugA"}, + BugC{"BugC"}, + BugY{ + BugA{"nested BugA"}, + BugD{"nested BugD"}, + }, + } + got, err := Encode(v) + if err != nil { + t.Fatal("Encode:", err) + } + want := map[string]interface{}{} + if !reflect.DeepEqual(got, want) { + t.Fatalf("Encode: got %v want %v", got, want) + } +} + +func TestEncodeMapIntKeys(t *testing.T) { + input := map[int]int{1: 1, 2: 2, 3: 3} + want := map[string]int{"1": 1, "2": 2, "3": 3} + + out, err := Encode(input) + if err != nil { + t.Errorf("got error %v, expected nil", err) + } + if !jsonEqual(out, want) { + t.Errorf("got %q, want %q", out, want) + } +} + +type RefA struct { + ID string `gorethink:"id,omitempty"` + B *RefB `gorethink:"b_id,reference" gorethink_ref:"id"` +} + +type RefB struct { + ID string `gorethink:"id,omitempty"` + Name string `gorethink:"name"` +} + +func TestReferenceField(t *testing.T) { + input := RefA{"1", &RefB{"2", "Name"}} + want := map[string]interface{}{"id": "1", "b_id": "2"} + + out, err := Encode(input) + if err != nil { + t.Errorf("got error %v, expected nil", err) + } + if !jsonEqual(out, want) { + t.Errorf("got %q, want %q", out, want) + } +} + +type RefC struct { + ID string `gorethink:"id,omitempty"` + B *RefB `gorethink:"b_id,reference" gorethink_ref:"b_id"` +} + +func TestReferenceFieldMissing(t *testing.T) { + input := RefC{"1", &RefB{"2", "Name"}} + + _, err := Encode(input) + if err == nil { + t.Errorf("expected non-nil error but got nil") + } +} + +type RefD struct { + ID string `gorethink:"id,omitempty"` + B string `gorethink:"b_id,reference" gorethink_ref:"b_id"` +} + +func TestReferenceFieldInvalid(t *testing.T) { + input := RefD{"1", "B"} + + _, err := Encode(input) + if err == nil { + t.Errorf("expected non-nil error but got nil") + } +} + +type RefE struct { + ID string `gorethink:"id,omitempty"` + FIDs *[]RefF `gorethink:"f_ids,reference" gorethink_ref:"id"` +} + +type RefF struct { + ID string `gorethink:"id,omitempty"` + Name string `gorethink:"name"` +} + +func TestReferenceFieldArray(t *testing.T) { + input := RefE{"1", &[]RefF{RefF{"2", "Name2"}, RefF{"3", "Name3"}}} + want := map[string]interface{}{"id": "1", "f_ids": []string{"2", "3"}} + + out, err := Encode(input) + if err != nil { + t.Errorf("got error %v, expected nil", err) + } + if !jsonEqual(out, want) { + t.Errorf("got %q, want %q", out, want) + } +} diff --git a/vendor/github.com/dancannon/gorethink/encoding/encoder_types.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoder_types.go similarity index 82% rename from vendor/github.com/dancannon/gorethink/encoding/encoder_types.go rename to vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoder_types.go index 8ef187b6af..bf5080e2d3 100644 --- a/vendor/github.com/dancannon/gorethink/encoding/encoder_types.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoder_types.go @@ -49,6 +49,12 @@ func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc { return newArrayEncoder(t) case reflect.Ptr: return newPtrEncoder(t) + case reflect.Func: + // functions are a special case as they can be used internally for + // optional arguments. Just return the raw function, if somebody tries + // to pass a function to the database the JSON marshaller will catch this + // anyway. + return funcEncoder default: return unsupportedTypeEncoder } @@ -120,6 +126,13 @@ func interfaceEncoder(v reflect.Value) interface{} { return encode(v.Elem()) } +func funcEncoder(v reflect.Value) interface{} { + if v.IsNil() { + return nil + } + return v.Interface() +} + func asStringEncoder(v reflect.Value) interface{} { return fmt.Sprintf("%v", v.Interface()) } @@ -135,7 +148,6 @@ type structEncoder struct { func (se *structEncoder) encode(v reflect.Value) interface{} { m := make(map[string]interface{}) - for i, f := range se.fields { fv := fieldByIndex(v, f.index) if !fv.IsValid() || f.omitEmpty && se.isEmptyValue(fv) { @@ -146,27 +158,8 @@ func (se *structEncoder) encode(v reflect.Value) interface{} { // If this field is a referenced field then attempt to extract the value. if f.reference { - refName := f.name - if f.refName != "" { - refName = f.refName - } - - // referenced fields can only handle maps so return an error if the - // encoded field is of a different type - m, ok := encField.(map[string]interface{}) - if !ok { - err := fmt.Errorf("Error referencing field %s in %s, expected object but got %t", refName, f.name, encField) - panic(&MarshalerError{v.Type(), err}) - } - - refVal, ok := m[refName] - if !ok { - err := fmt.Errorf("Error referencing field %s in %s, could not find referenced field", refName, f.name) - panic(&MarshalerError{v.Type(), err}) - } - // Override the encoded field with the referenced field - encField = refVal + encField = getReferenceField(f, v, encField) } m[f.name] = encField @@ -175,6 +168,40 @@ func (se *structEncoder) encode(v reflect.Value) interface{} { return m } +func getReferenceField(f field, v reflect.Value, encField interface{}) interface{} { + refName := f.name + if f.refName != "" { + refName = f.refName + } + + encFields, isArray := encField.([]interface{}) + if isArray { + refVals := make([]interface{}, len(encFields)) + for i, e := range encFields { + refVals[i] = extractValue(e, v, f.name, refName) + } + return refVals + } + refVal := extractValue(encField, v, f.name, refName) + return refVal +} + +func extractValue(encField interface{}, v reflect.Value, name string, refName string) interface{} { + // referenced fields can only handle maps so return an error if the + // encoded field is of a different type + m, ok := encField.(map[string]interface{}) + if !ok { + err := fmt.Errorf("Error refing field %s in %s, expected object but got %t", refName, name, encField) + panic(&MarshalerError{v.Type(), err}) + } + refVal, ok := m[refName] + if !ok { + err := fmt.Errorf("Error refing field %s in %s, could not find referenced field", refName, name) + panic(&MarshalerError{v.Type(), err}) + } + return refVal +} + func (se *structEncoder) isEmptyValue(v reflect.Value) bool { if v.Type() == timeType { return v.Interface().(time.Time) == time.Time{} diff --git a/vendor/github.com/dancannon/gorethink/encoding/encoding.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoding.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/encoding/encoding.go rename to vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoding.go diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoding_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoding_test.go new file mode 100644 index 0000000000..091b3a750c --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/encoding_test.go @@ -0,0 +1,6 @@ +package encoding + +import ( + // Import gocheck so that flag are setup (but unused) + _ "gopkg.in/check.v1" +) diff --git a/vendor/github.com/dancannon/gorethink/encoding/errors.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/errors.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/encoding/errors.go rename to vendor/gopkg.in/dancannon/gorethink.v2/encoding/errors.go diff --git a/vendor/github.com/dancannon/gorethink/encoding/fold.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/fold.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/encoding/fold.go rename to vendor/gopkg.in/dancannon/gorethink.v2/encoding/fold.go diff --git a/vendor/github.com/dancannon/gorethink/encoding/tags.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/tags.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/encoding/tags.go rename to vendor/gopkg.in/dancannon/gorethink.v2/encoding/tags.go diff --git a/vendor/github.com/dancannon/gorethink/encoding/utils.go b/vendor/gopkg.in/dancannon/gorethink.v2/encoding/utils.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/encoding/utils.go rename to vendor/gopkg.in/dancannon/gorethink.v2/encoding/utils.go diff --git a/vendor/github.com/dancannon/gorethink/errors.go b/vendor/gopkg.in/dancannon/gorethink.v2/errors.go similarity index 97% rename from vendor/github.com/dancannon/gorethink/errors.go rename to vendor/gopkg.in/dancannon/gorethink.v2/errors.go index 84ff8627a0..ded750d9d7 100644 --- a/vendor/github.com/dancannon/gorethink/errors.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/errors.go @@ -7,7 +7,7 @@ import ( "fmt" "strings" - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) var ( @@ -164,11 +164,19 @@ func createRuntimeError(errorType p.Response_ErrorType, response *Response, term // IsConflictErr returns true if the error is non-nil and the query failed // due to a duplicate primary key. func IsConflictErr(err error) bool { + if err == nil { + return false + } + return strings.HasPrefix(err.Error(), "Duplicate primary key") } // IsTypeErr returns true if the error is non-nil and the query failed due // to a type error. func IsTypeErr(err error) bool { + if err == nil { + return false + } + return strings.HasPrefix(err.Error(), "Expected type") } diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/example_query_aggregation_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_aggregation_test.go new file mode 100644 index 0000000000..1e616c7aa7 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_aggregation_test.go @@ -0,0 +1,135 @@ +package gorethink + +import ( + "fmt" +) + +// Group games by player. +func ExampleTerm_Group() { + cur, err := DB("examples").Table("games").Group("player").Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res []interface{} + err = cur.All(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) +} + +// Group games by the index type. +func ExampleTerm_GroupByIndex() { + cur, err := DB("examples").Table("games").GroupByIndex("type").Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res []interface{} + err = cur.All(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) +} + +// Suppose that the table games2 has the following data: +// +// [ +// { id: 1, matches: {'a': [1, 2, 3], 'b': [4, 5, 6]} }, +// { id: 2, matches: {'b': [100], 'c': [7, 8, 9]} }, +// { id: 3, matches: {'a': [10, 20], 'c': [70, 80]} } +// ] +// Using MultiGroup we can group data by match A, B or C. +func ExampleTerm_MultiGroup() { + cur, err := DB("examples").Table("games2").MultiGroup(Row.Field("matches").Keys()).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res []interface{} + err = cur.All(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) +} + +// Ungrouping grouped data. +func ExampleTerm_Ungroup() { + cur, err := DB("examples").Table("games"). + Group("player"). + Max("points").Field("points"). + Ungroup(). + Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res []interface{} + err = cur.All(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) +} + +// Return the number of documents in the table posts. +func ExampleTerm_Reduce() { + cur, err := DB("examples").Table("posts"). + Map(func(doc Term) interface{} { + return 1 + }). + Reduce(func(left, right Term) interface{} { + return left.Add(right) + }). + Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res int + err = cur.One(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) +} + +// Concatenate words from a list. +func ExampleTerm_Fold() { + cur, err := Expr([]string{"a", "b", "c"}).Fold("", func(acc, word Term) Term { + return acc.Add(Branch(acc.Eq(""), "", ", ")).Add(word) + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res string + err = cur.One(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) + // Output: + // a, b, c +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/example_query_control_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_control_test.go new file mode 100644 index 0000000000..b927ef775c --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_control_test.go @@ -0,0 +1,240 @@ +package gorethink + +import ( + "fmt" +) + +// Return heroes and superheroes. +func ExampleBranch() { + cur, err := DB("examples").Table("marvel").OrderBy("name").Map(Branch( + Row.Field("victories").Gt(100), + Row.Field("name").Add(" is a superhero"), + Row.Field("name").Add(" is a hero"), + )).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var strs []string + err = cur.All(&strs) + if err != nil { + fmt.Print(err) + return + } + + for _, str := range strs { + fmt.Println(str) + } + + // Output: + // Iron Man is a superhero + // Jubilee is a hero +} + +// Return an error +func ExampleError() { + err := Error("this is a runtime error").Exec(session) + fmt.Println(err) +} + +// Suppose we want to retrieve the titles and authors of the table posts. In the +// case where the author field is missing or null, we want to retrieve the +// string "Anonymous". +func ExampleTerm_Default() { + cur, err := DB("examples").Table("posts").Map(map[string]interface{}{ + "title": Row.Field("title"), + "author": Row.Field("author").Default("Anonymous"), + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res map[string]interface{} + err = cur.One(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) +} + +// Convert a Go integer to a ReQL object +func ExampleExpr_int() { + cur, err := Expr(1).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res interface{} + err = cur.One(&res) + if err != nil { + fmt.Print(err) + return + } + + jsonPrint(res) + + // Output: 1 +} + +// Convert a Go slice to a ReQL object +func ExampleExpr_slice() { + cur, err := Expr([]int{1, 2, 3}).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res []interface{} + err = cur.All(&res) + if err != nil { + fmt.Print(err) + return + } + + jsonPrint(res) + + // Output: + // [ + // 1, + // 2, + // 3 + // ] +} + +// Convert a Go slice to a ReQL object +func ExampleExpr_map() { + cur, err := Expr(map[string]interface{}{ + "a": 1, + "b": "b", + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res interface{} + err = cur.One(&res) + if err != nil { + fmt.Print(err) + return + } + + jsonPrint(res) + + // Output: + // { + // "a": 1, + // "b": "b" + // } +} + +// Convert a Go slice to a ReQL object +func ExampleExpr_struct() { + type ExampleTypeNested struct { + N int + } + + type ExampleTypeEmbed struct { + C string + } + + type ExampleTypeA struct { + ExampleTypeEmbed + + A int + B string + Nested ExampleTypeNested + } + + cur, err := Expr(ExampleTypeA{ + A: 1, + B: "b", + ExampleTypeEmbed: ExampleTypeEmbed{ + C: "c", + }, + Nested: ExampleTypeNested{ + N: 2, + }, + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res interface{} + err = cur.One(&res) + if err != nil { + fmt.Print(err) + return + } + + jsonPrint(res) + + // Output: + // { + // "A": 1, + // "B": "b", + // "C": "c", + // "Nested": { + // "N": 2 + // } + // } +} + +// Convert a Go struct (with gorethink tags) to a ReQL object. The tags allow +// the field names to be changed. +func ExampleExpr_structTags() { + type ExampleType struct { + A int `gorethink:"field_a"` + B string `gorethink:"field_b"` + } + + cur, err := Expr(ExampleType{ + A: 1, + B: "b", + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res interface{} + err = cur.One(&res) + if err != nil { + fmt.Print(err) + return + } + + jsonPrint(res) + + // Output: + // { + // "field_a": 1, + // "field_b": "b" + // } +} + +// Execute a raw JSON query +func ExampleRawQuery() { + cur, err := RawQuery([]byte(`"hello world"`)).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res interface{} + err = cur.One(&res) + if err != nil { + fmt.Print(err) + return + } + + jsonPrint(res) + + // Output: "hello world" +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/example_query_db_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_db_test.go new file mode 100644 index 0000000000..afe0382a69 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_db_test.go @@ -0,0 +1,34 @@ +package gorethink + +import ( + "fmt" +) + +// Create a database named ’superheroes’. +func ExampleDBCreate() { + resp, err := DBCreate("superheroes").RunWrite(session) + if err != nil { + fmt.Print(err) + } + + fmt.Printf("%d DB created", resp.DBsCreated) + // Output: + // 1 DB created +} + +// Drop a database named ‘superheroes’. +func ExampleDBDrop() { + // Setup database + tables + DBCreate("superheroes").Exec(session) + DB("superheroes").TableCreate("superheroes").Exec(session) + DB("superheroes").TableCreate("battles").Exec(session) + + resp, err := DBDrop("superheroes").RunWrite(session) + if err != nil { + fmt.Print(err) + } + + fmt.Printf("%d DB dropped, %d tables dropped", resp.DBsDropped, resp.TablesDropped) + // Output: + // 1 DB dropped, 2 tables dropped +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/example_query_manipulation_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_manipulation_test.go new file mode 100644 index 0000000000..51616c9b76 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_manipulation_test.go @@ -0,0 +1,25 @@ +package gorethink + +import ( + "fmt" +) + +// Get john's age +func ExampleTerm_Field() { + cur, err := DB("examples").Table("users").Get("john").Field("age").Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res int + err = cur.One(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) + + // Output: 19 +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/example_query_select_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_select_test.go new file mode 100644 index 0000000000..b39fec5e3e --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_select_test.go @@ -0,0 +1,202 @@ +package gorethink + +import ( + "fmt" +) + +// Find a document by ID. +func ExampleTerm_Get() { + // Fetch the row from the database + res, err := DB("examples").Table("heroes").Get(2).Run(session) + if err != nil { + fmt.Print(err) + return + } + defer res.Close() + + if res.IsNil() { + fmt.Print("Row not found") + return + } + + var hero map[string]interface{} + err = res.One(&hero) + if err != nil { + fmt.Printf("Error scanning database result: %s", err) + return + } + fmt.Print(hero["name"]) + + // Output: Superman +} + +// Find a document by ID. +func ExampleTerm_GetAll() { + // Fetch the row from the database + res, err := DB("examples").Table("heroes").GetAll(2).Run(session) + if err != nil { + fmt.Print(err) + return + } + defer res.Close() + + if res.IsNil() { + fmt.Print("Row not found") + return + } + + var hero map[string]interface{} + err = res.One(&hero) + if err != nil { + fmt.Printf("Error scanning database result: %s", err) + return + } + fmt.Print(hero["name"]) + + // Output: Superman +} + +// Find a document by ID. +func ExampleTerm_GetAll_multiple() { + // Fetch the row from the database + res, err := DB("examples").Table("heroes").GetAll(1, 2).Run(session) + if err != nil { + fmt.Print(err) + return + } + defer res.Close() + + var heroes []map[string]interface{} + err = res.All(&heroes) + if err != nil { + fmt.Printf("Error scanning database result: %s", err) + return + } + fmt.Print(heroes[0]["name"]) + + // Output: Superman +} + +// Find all document with an indexed value. +func ExampleTerm_GetAllByIndex() { + // Fetch the row from the database + res, err := DB("examples").Table("heroes").GetAllByIndex("code_name", "man_of_steel").Run(session) + if err != nil { + fmt.Print(err) + return + } + defer res.Close() + + if res.IsNil() { + fmt.Print("Row not found") + return + } + + var hero map[string]interface{} + err = res.One(&hero) + if err != nil { + fmt.Printf("Error scanning database result: %s", err) + return + } + fmt.Print(hero["name"]) + + // Output: Superman +} + +// Find a document and merge another document with it. +func ExampleTerm_Get_merge() { + // Fetch the row from the database + res, err := DB("examples").Table("heroes").Get(4).Merge(map[string]interface{}{ + "powers": []string{"speed"}, + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + defer res.Close() + + if res.IsNil() { + fmt.Print("Row not found") + return + } + + var hero map[string]interface{} + err = res.One(&hero) + if err != nil { + fmt.Printf("Error scanning database result: %s", err) + return + } + fmt.Printf("%s: %v", hero["name"], hero["powers"]) + + // Output: The Flash: [speed] +} + +// Get all users who are 30 years old. +func ExampleTerm_Filter() { + // Fetch the row from the database + res, err := DB("examples").Table("users").Filter(map[string]interface{}{ + "age": 30, + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + defer res.Close() + + // Scan query result into the person variable + var users []interface{} + err = res.All(&users) + if err != nil { + fmt.Printf("Error scanning database result: %s", err) + return + } + fmt.Printf("%d users", len(users)) + + // Output: 2 users +} + +// Get all users who are more than 25 years old. +func ExampleTerm_Filter_row() { + // Fetch the row from the database + res, err := DB("examples").Table("users").Filter(Row.Field("age").Gt(25)).Run(session) + if err != nil { + fmt.Print(err) + return + } + defer res.Close() + + // Scan query result into the person variable + var users []interface{} + err = res.All(&users) + if err != nil { + fmt.Printf("Error scanning database result: %s", err) + return + } + fmt.Printf("%d users", len(users)) + + // Output: 3 users +} + +// Retrieve all users who have a gmail account (whose field email ends with @gmail.com). +func ExampleTerm_Filter_function() { + // Fetch the row from the database + res, err := DB("examples").Table("users").Filter(func(user Term) Term { + return user.Field("email").Match("@gmail.com$") + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + defer res.Close() + + // Scan query result into the person variable + var users []interface{} + err = res.All(&users) + if err != nil { + fmt.Printf("Error scanning database result: %s", err) + return + } + fmt.Printf("%d users", len(users)) + + // Output: 1 users +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/example_query_table_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_table_test.go new file mode 100644 index 0000000000..8c1457d408 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_table_test.go @@ -0,0 +1,57 @@ +package gorethink + +import ( + "fmt" +) + +// Create a table named "table" with the default settings. +func ExampleTerm_TableCreate() { + // Setup database + DB("examples").TableDrop("table").Run(session) + + response, err := DB("examples").TableCreate("table").RunWrite(session) + if err != nil { + Log.Fatalf("Error creating table: %s", err) + } + + fmt.Printf("%d table created", response.TablesCreated) + + // Output: + // 1 table created +} + +// Create a simple index based on the field name. +func ExampleTerm_IndexCreate() { + // Setup database + DB("examples").TableDrop("table").Run(session) + DB("examples").TableCreate("table").Run(session) + + response, err := DB("examples").Table("table").IndexCreate("name").RunWrite(session) + if err != nil { + Log.Fatalf("Error creating index: %s", err) + } + + fmt.Printf("%d index created", response.Created) + + // Output: + // 1 index created +} + +// Create a compound index based on the fields first_name and last_name. +func ExampleTerm_IndexCreate_compound() { + // Setup database + DB("examples").TableDrop("table").Run(session) + DB("examples").TableCreate("table").Run(session) + + response, err := DB("examples").Table("table").IndexCreateFunc("full_name", func(row Term) interface{} { + return []interface{}{row.Field("first_name"), row.Field("last_name")} + }).RunWrite(session) + if err != nil { + Log.Fatalf("Error creating index: %s", err) + } + + fmt.Printf("%d index created", response.Created) + + // Output: + // 1 index created +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/example_query_transformation_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_transformation_test.go new file mode 100644 index 0000000000..6ec80ee2a2 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_transformation_test.go @@ -0,0 +1,161 @@ +package gorethink + +import ( + "fmt" +) + +// Return the first five squares. +func ExampleTerm_Map() { + cur, err := Expr([]int{1, 2, 3, 4, 5}).Map(func(val Term) Term { + return val.Mul(val) + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res []int + err = cur.All(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) + + // Output: + // [1 4 9 16 25] +} + +// Sum the elements of three sequences. +func ExampleMap_multipleSequences() { + var sequence1 = []int{100, 200, 300, 400} + var sequence2 = []int{10, 20, 30, 40} + var sequence3 = []int{1, 2, 3, 4} + + cur, err := Map(sequence1, sequence2, sequence3, func(val1, val2, val3 Term) Term { + return val1.Add(val2).Add(val3) + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res []int + err = cur.All(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) + + // Output: + // [111 222 333 444] +} + +// Order all the posts using the index date. +func ExampleTerm_OrderBy_index() { + cur, err := DB("examples").Table("posts").OrderBy(OrderByOpts{ + Index: "date", + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res []interface{} + err = cur.All(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) +} + +// Order all the posts using the index date in descending order. +func ExampleTerm_OrderBy_indexDesc() { + cur, err := DB("examples").Table("posts").OrderBy(OrderByOpts{ + Index: Desc("date"), + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res []interface{} + err = cur.All(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) +} + +// You can efficiently order using multiple fields by using a compound index. +// For example order by date and title. +func ExampleTerm_OrderBy_compound() { + cur, err := DB("examples").Table("posts").OrderBy(OrderByOpts{ + Index: Desc("dateAndTitle"), + }).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res []interface{} + err = cur.All(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) +} + +// If you have a sequence with fewer documents than the arrayLimit, you can order +// it by multiple fields without an index. +func ExampleTerm_OrderBy_multiple() { + cur, err := DB("examples").Table("posts").OrderBy( + "title", + OrderByOpts{Index: Desc("date")}, + ).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res []interface{} + err = cur.All(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) +} + +// Notice that an index ordering always has highest precedence. The following +// query orders posts by date, and if multiple posts were published on the same +// date, they will be ordered by title. +func ExampleTerm_OrderBy_multipleWithIndex() { + cur, err := DB("examples").Table("posts").OrderBy( + "title", + OrderByOpts{Index: Desc("date")}, + ).Run(session) + if err != nil { + fmt.Print(err) + return + } + + var res []interface{} + err = cur.All(&res) + if err != nil { + fmt.Print(err) + return + } + + fmt.Print(res) +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/example_query_write_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_write_test.go new file mode 100644 index 0000000000..4fb3c56a24 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/example_query_write_test.go @@ -0,0 +1,228 @@ +package gorethink + +import ( + "fmt" +) + +// Insert a document into the table posts using a struct. +func ExampleTerm_Insert_struct() { + type Post struct { + ID int `gorethink:"id"` + Title string `gorethink:"title"` + Content string `gorethink:"content"` + } + + resp, err := DB("examples").Table("posts").Insert(Post{ + ID: 1, + Title: "Lorem ipsum", + Content: "Dolor sit amet", + }).RunWrite(session) + if err != nil { + fmt.Print(err) + return + } + + fmt.Printf("%d row inserted", resp.Inserted) + + // Output: + // 1 row inserted +} + +// Insert a document without a defined primary key into the table posts where +// the primary key is id. +func ExampleTerm_Insert_generatedKey() { + type Post struct { + Title string `gorethink:"title"` + Content string `gorethink:"content"` + } + + resp, err := DB("examples").Table("posts").Insert(map[string]interface{}{ + "title": "Lorem ipsum", + "content": "Dolor sit amet", + }).RunWrite(session) + if err != nil { + fmt.Print(err) + return + } + + fmt.Printf("%d row inserted, %d key generated", resp.Inserted, len(resp.GeneratedKeys)) + + // Output: + // 1 row inserted, 1 key generated +} + +// Insert a document into the table posts using a map. +func ExampleTerm_Insert_map() { + resp, err := DB("examples").Table("posts").Insert(map[string]interface{}{ + "id": 2, + "title": "Lorem ipsum", + "content": "Dolor sit amet", + }).RunWrite(session) + if err != nil { + fmt.Print(err) + return + } + + fmt.Printf("%d row inserted", resp.Inserted) + + // Output: + // 1 row inserted +} + +// Insert multiple documents into the table posts. +func ExampleTerm_Insert_multiple() { + resp, err := DB("examples").Table("posts").Insert([]interface{}{ + map[string]interface{}{ + "title": "Lorem ipsum", + "content": "Dolor sit amet", + }, + map[string]interface{}{ + "title": "Lorem ipsum", + "content": "Dolor sit amet", + }, + }).RunWrite(session) + if err != nil { + fmt.Print(err) + return + } + + fmt.Printf("%d rows inserted", resp.Inserted) + + // Output: + // 2 rows inserted +} + +// Insert a document into the table posts, replacing the document if it already +// exists. +func ExampleTerm_Insert_upsert() { + resp, err := DB("examples").Table("posts").Insert(map[string]interface{}{ + "id": 1, + "title": "Lorem ipsum 2", + }, InsertOpts{ + Conflict: "replace", + }).RunWrite(session) + if err != nil { + fmt.Print(err) + return + } + + fmt.Printf("%d row replaced", resp.Replaced) + + // Output: + // 1 row replaced +} + +// Update the status of the post with id of 1 to published. +func ExampleTerm_Update() { + resp, err := DB("examples").Table("posts").Get(2).Update(map[string]interface{}{ + "status": "published", + }).RunWrite(session) + if err != nil { + fmt.Print(err) + return + } + + fmt.Printf("%d row replaced", resp.Replaced) + + // Output: + // 1 row replaced +} + +// Update bob's cell phone number. +func ExampleTerm_Update_nested() { + resp, err := DB("examples").Table("users").Get("bob").Update(map[string]interface{}{ + "contact": map[string]interface{}{ + "phone": "408-555-4242", + }, + }).RunWrite(session) + if err != nil { + fmt.Print(err) + return + } + + fmt.Printf("%d row replaced", resp.Replaced) + + // Output: + // 1 row replaced +} + +// Update the status of all posts to published. +func ExampleTerm_Update_all() { + resp, err := DB("examples").Table("posts").Update(map[string]interface{}{ + "status": "published", + }).RunWrite(session) + if err != nil { + fmt.Print(err) + return + } + + fmt.Printf("%d row replaced", resp.Replaced) + + // Output: + // 4 row replaced +} + +// Increment the field view of the post with id of 1. If the field views does not +// exist, it will be set to 0. +func ExampleTerm_Update_increment() { + resp, err := DB("examples").Table("posts").Get(1).Update(map[string]interface{}{ + "views": Row.Field("views").Add(1).Default(0), + }).RunWrite(session) + if err != nil { + fmt.Print(err) + return + } + + fmt.Printf("%d row replaced", resp.Replaced) + + // Output: + // 1 row replaced +} + +// Update the status of the post with id of 1 using soft durability. +func ExampleTerm_Update_softDurability() { + resp, err := DB("examples").Table("posts").Get(2).Update(map[string]interface{}{ + "status": "draft", + }, UpdateOpts{ + Durability: "soft", + }).RunWrite(session) + if err != nil { + fmt.Print(err) + return + } + + fmt.Printf("%d row replaced", resp.Replaced) + + // Output: + // 1 row replaced +} + +// Delete a single document from the table posts. +func ExampleTerm_Delete() { + resp, err := DB("examples").Table("posts").Get(2).Delete().RunWrite(session) + if err != nil { + fmt.Print(err) + return + } + + fmt.Printf("%d row deleted", resp.Deleted) + + // Output: + // 1 row deleted +} + +// Delete all comments where the field status is published +func ExampleTerm_Delete_many() { + resp, err := DB("examples").Table("posts").Filter(map[string]interface{}{ + "status": "published", + }).Delete().RunWrite(session) + if err != nil { + fmt.Print(err) + return + } + + fmt.Printf("%d rows deleted", resp.Deleted) + + // Output: + // 4 rows deleted +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/example_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/example_test.go new file mode 100644 index 0000000000..12bcbbf68b --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/example_test.go @@ -0,0 +1,30 @@ +package gorethink + +import ( + "fmt" +) + +func Example() { + session, err := Connect(ConnectOpts{ + Address: url, + }) + if err != nil { + Log.Fatalln(err.Error()) + } + + res, err := Expr("Hello World").Run(session) + if err != nil { + Log.Fatalln(err.Error()) + } + + var response string + err = res.One(&response) + if err != nil { + Log.Fatalln(err.Error()) + } + + fmt.Println(response) + + // Output: + // Hello World +} diff --git a/vendor/github.com/dancannon/gorethink/gorethink.go b/vendor/gopkg.in/dancannon/gorethink.v2/gorethink.go similarity index 94% rename from vendor/github.com/dancannon/gorethink/gorethink.go rename to vendor/gopkg.in/dancannon/gorethink.v2/gorethink.go index f7a5a1e3a5..15fe176076 100644 --- a/vendor/github.com/dancannon/gorethink/gorethink.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/gorethink.go @@ -5,7 +5,7 @@ import ( "github.com/Sirupsen/logrus" - "github.com/dancannon/gorethink/encoding" + "gopkg.in/dancannon/gorethink.v2/encoding" ) var ( diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/gorethink_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/gorethink_test.go new file mode 100644 index 0000000000..e33a41c713 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/gorethink_test.go @@ -0,0 +1,448 @@ +package gorethink + +import ( + "encoding/json" + "flag" + "fmt" + "math/rand" + "os" + "runtime" + "sync" + "testing" + "time" + + test "gopkg.in/check.v1" +) + +var session *Session +var debug = flag.Bool("gorethink.debug", false, "print query trees") +var testdata = flag.Bool("gorethink.testdata", true, "create test data") +var url, url1, url2, url3, db, authKey string + +func init() { + flag.Parse() + SetVerbose(true) + + // If the test is being run by wercker look for the rethink url + url = os.Getenv("RETHINKDB_URL") + if url == "" { + url = "localhost:28015" + } + + url1 = os.Getenv("RETHINKDB_URL_1") + if url1 == "" { + url1 = "localhost:28016" + } + + url2 = os.Getenv("RETHINKDB_URL_2") + if url2 == "" { + url2 = "localhost:28017" + } + + url3 = os.Getenv("RETHINKDB_URL_3") + if url3 == "" { + url3 = "localhost:28018" + } + + db = os.Getenv("RETHINKDB_DB") + if db == "" { + db = "test" + } +} + +// +// Begin TestMain(), Setup, Teardown +// +func testSetup(m *testing.M) { + var err error + session, err = Connect(ConnectOpts{ + Address: url, + }) + if err != nil { + Log.Fatalln(err.Error()) + } + + setupTestData() +} +func testTeardown(m *testing.M) { + session.Close() +} + +func testBenchmarkSetup() { + DBDrop("benchmarks").Exec(session) + DBCreate("benchmarks").Exec(session) + + DB("benchmarks").TableDrop("benchmarks").Run(session) + DB("benchmarks").TableCreate("benchmarks").Run(session) +} + +func testBenchmarkTeardown() { + DBDrop("benchmarks").Run(session) +} + +func TestMain(m *testing.M) { + // seed randomness for use with tests + rand.Seed(time.Now().UTC().UnixNano()) + + testSetup(m) + testBenchmarkSetup() + res := m.Run() + testBenchmarkTeardown() + testTeardown(m) + + os.Exit(res) +} + +// +// End TestMain(), Setup, Teardown +// + +// Hook up gocheck into the gotest runner. +func Test(t *testing.T) { test.TestingT(t) } + +type RethinkSuite struct{} + +var _ = test.Suite(&RethinkSuite{}) + +// Expressions used in tests +var now = time.Now() +var arr = []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9} +var darr = []interface{}{1, 1, 2, 2, 3, 3, 5, 5, 6} +var narr = []interface{}{ + 1, 2, 3, 4, 5, 6, []interface{}{ + 7.1, 7.2, 7.3, + }, +} +var obj = map[string]interface{}{"a": 1, "b": 2, "c": 3} +var nobj = map[string]interface{}{ + "A": 1, + "B": 2, + "C": map[string]interface{}{ + "1": 3, + "2": 4, + }, +} +var noDupNumObjList = []interface{}{ + map[string]interface{}{"id": 1, "g1": 1, "g2": 1, "num": 0}, + map[string]interface{}{"id": 2, "g1": 2, "g2": 2, "num": 5}, + map[string]interface{}{"id": 3, "g1": 3, "g2": 2, "num": 10}, + map[string]interface{}{"id": 5, "g1": 2, "g2": 3, "num": 100}, + map[string]interface{}{"id": 6, "g1": 1, "g2": 1, "num": 15}, + map[string]interface{}{"id": 8, "g1": 4, "g2": 2, "num": 50}, + map[string]interface{}{"id": 9, "g1": 2, "g2": 3, "num": 25}, +} +var objList = []interface{}{ + map[string]interface{}{"id": 1, "g1": 1, "g2": 1, "num": 0}, + map[string]interface{}{"id": 2, "g1": 2, "g2": 2, "num": 5}, + map[string]interface{}{"id": 3, "g1": 3, "g2": 2, "num": 10}, + map[string]interface{}{"id": 4, "g1": 2, "g2": 3, "num": 0}, + map[string]interface{}{"id": 5, "g1": 2, "g2": 3, "num": 100}, + map[string]interface{}{"id": 6, "g1": 1, "g2": 1, "num": 15}, + map[string]interface{}{"id": 7, "g1": 1, "g2": 2, "num": 0}, + map[string]interface{}{"id": 8, "g1": 4, "g2": 2, "num": 50}, + map[string]interface{}{"id": 9, "g1": 2, "g2": 3, "num": 25}, +} +var nameList = []interface{}{ + map[string]interface{}{"id": 1, "first_name": "John", "last_name": "Smith", "gender": "M"}, + map[string]interface{}{"id": 2, "first_name": "Jane", "last_name": "Smith", "gender": "F"}, +} +var defaultObjList = []interface{}{ + map[string]interface{}{"a": 1}, + map[string]interface{}{}, +} +var joinTable1 = []interface{}{ + map[string]interface{}{"id": 0, "name": "bob"}, + map[string]interface{}{"id": 1, "name": "tom"}, + map[string]interface{}{"id": 2, "name": "joe"}, +} +var joinTable2 = []interface{}{ + map[string]interface{}{"id": 0, "title": "goof"}, + map[string]interface{}{"id": 2, "title": "lmoe"}, +} +var joinTable3 = []interface{}{ + map[string]interface{}{"it": 0, "title": "goof"}, + map[string]interface{}{"it": 2, "title": "lmoe"}, +} + +type TStr string +type TMap map[string]interface{} + +type T struct { + A string `gorethink:"id, omitempty"` + B int + C int `gorethink:"-"` + D map[string]interface{} + E []interface{} + F X +} + +type SimpleT struct { + A string + B int +} + +type X struct { + XA int + XB string + XC []string + XD Y + XE TStr + XF []TStr +} + +type Y struct { + YA int + YB map[string]interface{} + YC map[string]string + YD TMap +} + +type PseudoTypes struct { + T time.Time + Z time.Time + B []byte +} + +var str = T{ + A: "A", + B: 1, + C: 1, + D: map[string]interface{}{ + "D1": 1, + "D2": "2", + }, + E: []interface{}{ + "E1", "E2", "E3", 4, + }, + F: X{ + XA: 2, + XB: "B", + XC: []string{"XC1", "XC2"}, + XD: Y{ + YA: 3, + YB: map[string]interface{}{ + "1": "1", + "2": "2", + "3": 3, + }, + YC: map[string]string{ + "YC1": "YC1", + }, + YD: TMap{ + "YD1": "YD1", + }, + }, + XE: "XE", + XF: []TStr{ + "XE1", "XE2", + }, + }, +} + +type Author struct { + ID string `gorethink:"id,omitempty"` + Name string `gorethink:"name"` +} + +type Book struct { + ID string `gorethink:"id,omitempty"` + Title string `gorethink:"title"` + Author Author `gorethink:"author_id,reference" gorethink_ref:"id"` +} + +type TagsTest struct { + A string `gorethink:"a"` + B string `json:"b"` + C string `gorethink:"c1" json:"c2"` +} + +func (s *RethinkSuite) BenchmarkExpr(c *test.C) { + for i := 0; i < c.N; i++ { + // Test query + query := Expr(true) + err := query.Exec(session) + c.Assert(err, test.IsNil) + } +} + +func (s *RethinkSuite) BenchmarkNoReplyExpr(c *test.C) { + for i := 0; i < c.N; i++ { + // Test query + query := Expr(true) + err := query.Exec(session, ExecOpts{NoReply: true}) + c.Assert(err, test.IsNil) + } +} + +func (s *RethinkSuite) BenchmarkGet(c *test.C) { + // Ensure table + database exist + DBCreate("test").RunWrite(session) + DB("test").TableCreate("TestMany").RunWrite(session) + DB("test").Table("TestMany").Delete().RunWrite(session) + + // Insert rows + data := []interface{}{} + for i := 0; i < 100; i++ { + data = append(data, map[string]interface{}{ + "id": i, + }) + } + DB("test").Table("TestMany").Insert(data).Run(session) + + for i := 0; i < c.N; i++ { + n := rand.Intn(100) + + // Test query + var response interface{} + query := DB("test").Table("TestMany").Get(n) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{"id": n}) + } +} + +func (s *RethinkSuite) BenchmarkGetStruct(c *test.C) { + // Ensure table + database exist + DBCreate("test").RunWrite(session) + DB("test").TableCreate("TestMany").RunWrite(session) + DB("test").Table("TestMany").Delete().RunWrite(session) + + // Insert rows + data := []interface{}{} + for i := 0; i < 100; i++ { + data = append(data, map[string]interface{}{ + "id": i, + "name": "Object 1", + "Attrs": []interface{}{map[string]interface{}{ + "Name": "attr 1", + "Value": "value 1", + }}, + }) + } + DB("test").Table("TestMany").Insert(data).Run(session) + + for i := 0; i < c.N; i++ { + n := rand.Intn(100) + + // Test query + var resObj object + query := DB("test").Table("TestMany").Get(n) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&resObj) + + c.Assert(err, test.IsNil) + } +} + +func (s *RethinkSuite) BenchmarkSelectMany(c *test.C) { + // Ensure table + database exist + DBCreate("test").RunWrite(session) + DB("test").TableCreate("TestMany").RunWrite(session) + DB("test").Table("TestMany").Delete().RunWrite(session) + + // Insert rows + data := []interface{}{} + for i := 0; i < 100; i++ { + data = append(data, map[string]interface{}{ + "id": i, + }) + } + DB("test").Table("TestMany").Insert(data).Run(session) + + for i := 0; i < c.N; i++ { + // Test query + res, err := DB("test").Table("TestMany").Run(session) + c.Assert(err, test.IsNil) + + var response []map[string]interface{} + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.HasLen, 100) + } +} + +func (s *RethinkSuite) BenchmarkSelectManyStruct(c *test.C) { + // Ensure table + database exist + DBCreate("test").RunWrite(session) + DB("test").TableCreate("TestMany").RunWrite(session) + DB("test").Table("TestMany").Delete().RunWrite(session) + + // Insert rows + data := []interface{}{} + for i := 0; i < 100; i++ { + data = append(data, map[string]interface{}{ + "id": i, + "name": "Object 1", + "Attrs": []interface{}{map[string]interface{}{ + "Name": "attr 1", + "Value": "value 1", + }}, + }) + } + DB("test").Table("TestMany").Insert(data).Run(session) + + for i := 0; i < c.N; i++ { + // Test query + res, err := DB("test").Table("TestMany").Run(session) + c.Assert(err, test.IsNil) + + var response []object + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.HasLen, 100) + } +} + +func doConcurrentTest(c *test.C, ct func()) { + maxProcs, numReqs := 1, 150 + if testing.Short() { + maxProcs, numReqs = 4, 50 + } + defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs)) + + var wg sync.WaitGroup + wg.Add(numReqs) + + reqs := make(chan bool) + defer close(reqs) + + for i := 0; i < maxProcs*2; i++ { + go func() { + for _ = range reqs { + ct() + if c.Failed() { + wg.Done() + continue + } + wg.Done() + } + }() + } + + for i := 0; i < numReqs; i++ { + reqs <- true + } + + wg.Wait() +} + +// Test utils + +// Print variable as JSON +func jsonPrint(v interface{}) { + b, err := json.MarshalIndent(v, "", " ") + if err != nil { + fmt.Println(err) + return + } + + fmt.Println(string(b)) +} diff --git a/vendor/github.com/dancannon/gorethink/host.go b/vendor/gopkg.in/dancannon/gorethink.v2/host.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/host.go rename to vendor/gopkg.in/dancannon/gorethink.v2/host.go diff --git a/vendor/github.com/dancannon/gorethink/node.go b/vendor/gopkg.in/dancannon/gorethink.v2/node.go similarity index 98% rename from vendor/github.com/dancannon/gorethink/node.go rename to vendor/gopkg.in/dancannon/gorethink.v2/node.go index 665e622bcd..b2a76379a4 100644 --- a/vendor/github.com/dancannon/gorethink/node.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/node.go @@ -3,8 +3,8 @@ package gorethink import ( "sync" - p "github.com/dancannon/gorethink/ql2" "github.com/hailocab/go-hostpool" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // Node represents a database server in the cluster diff --git a/vendor/github.com/dancannon/gorethink/pool.go b/vendor/gopkg.in/dancannon/gorethink.v2/pool.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/pool.go rename to vendor/gopkg.in/dancannon/gorethink.v2/pool.go diff --git a/vendor/github.com/dancannon/gorethink/pseudotypes.go b/vendor/gopkg.in/dancannon/gorethink.v2/pseudotypes.go similarity index 99% rename from vendor/github.com/dancannon/gorethink/pseudotypes.go rename to vendor/gopkg.in/dancannon/gorethink.v2/pseudotypes.go index 17b16dd6b4..fc80cc7b61 100644 --- a/vendor/github.com/dancannon/gorethink/pseudotypes.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/pseudotypes.go @@ -6,7 +6,7 @@ import ( "strconv" "time" - "github.com/dancannon/gorethink/types" + "gopkg.in/dancannon/gorethink.v2/types" "fmt" ) diff --git a/vendor/github.com/dancannon/gorethink/ql2/generate.go b/vendor/gopkg.in/dancannon/gorethink.v2/ql2/generate.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/ql2/generate.go rename to vendor/gopkg.in/dancannon/gorethink.v2/ql2/generate.go diff --git a/vendor/github.com/dancannon/gorethink/ql2/ql2.pb.go b/vendor/gopkg.in/dancannon/gorethink.v2/ql2/ql2.pb.go similarity index 99% rename from vendor/github.com/dancannon/gorethink/ql2/ql2.pb.go rename to vendor/gopkg.in/dancannon/gorethink.v2/ql2/ql2.pb.go index 2d575f5f0b..759849f48b 100644 --- a/vendor/github.com/dancannon/gorethink/ql2/ql2.pb.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/ql2/ql2.pb.go @@ -38,6 +38,7 @@ const ( VersionDummy_V0_2 VersionDummy_Version = 1915781601 VersionDummy_V0_3 VersionDummy_Version = 1601562686 VersionDummy_V0_4 VersionDummy_Version = 1074539808 + VersionDummy_V1_0 VersionDummy_Version = 885177795 ) var VersionDummy_Version_name = map[int32]string{ @@ -45,12 +46,14 @@ var VersionDummy_Version_name = map[int32]string{ 1915781601: "V0_2", 1601562686: "V0_3", 1074539808: "V0_4", + 885177795: "V1_0", } var VersionDummy_Version_value = map[string]int32{ "V0_1": 1063369270, "V0_2": 1915781601, "V0_3": 1601562686, "V0_4": 1074539808, + "V1_0": 885177795, } func (x VersionDummy_Version) Enum() *VersionDummy_Version { @@ -268,6 +271,7 @@ const ( Response_OP_FAILED Response_ErrorType = 4100000 Response_OP_INDETERMINATE Response_ErrorType = 4200000 Response_USER Response_ErrorType = 5000000 + Response_PERMISSION_ERROR Response_ErrorType = 6000000 ) var Response_ErrorType_name = map[int32]string{ @@ -278,6 +282,7 @@ var Response_ErrorType_name = map[int32]string{ 4100000: "OP_FAILED", 4200000: "OP_INDETERMINATE", 5000000: "USER", + 6000000: "PERMISSION_ERROR", } var Response_ErrorType_value = map[string]int32{ "INTERNAL": 1000000, @@ -287,6 +292,7 @@ var Response_ErrorType_value = map[string]int32{ "OP_FAILED": 4100000, "OP_INDETERMINATE": 4200000, "USER": 5000000, + "PERMISSION_ERROR": 6000000, } func (x Response_ErrorType) Enum() *Response_ErrorType { @@ -536,6 +542,7 @@ const ( Term_BETWEEN Term_TermType = 182 Term_REDUCE Term_TermType = 37 Term_MAP Term_TermType = 38 + Term_FOLD Term_TermType = 187 // Filter a sequence with either a function or a shortcut // object (see API docs for details). The body of FILTER is // wrapped in an implicit `.default(false)`, and you can @@ -656,6 +663,8 @@ const ( // Ensures that previously issued soft-durability writes are complete and // written to disk. Term_SYNC Term_TermType = 138 + // Set global, database, or table-specific permissions + Term_GRANT Term_TermType = 188 // * Secondary indexes OPs // Creates a new secondary index with a particular name and definition. Term_INDEX_CREATE Term_TermType = 75 @@ -901,6 +910,7 @@ var Term_TermType_name = map[int32]string{ 182: "BETWEEN", 37: "REDUCE", 38: "MAP", + 187: "FOLD", 39: "FILTER", 40: "CONCAT_MAP", 41: "ORDER_BY", @@ -937,6 +947,7 @@ var Term_TermType_name = map[int32]string{ 176: "RECONFIGURE", 179: "REBALANCE", 138: "SYNC", + 188: "GRANT", 75: "INDEX_CREATE", 76: "INDEX_DROP", 77: "INDEX_LIST", @@ -1079,6 +1090,7 @@ var Term_TermType_value = map[string]int32{ "BETWEEN": 182, "REDUCE": 37, "MAP": 38, + "FOLD": 187, "FILTER": 39, "CONCAT_MAP": 40, "ORDER_BY": 41, @@ -1115,6 +1127,7 @@ var Term_TermType_value = map[string]int32{ "RECONFIGURE": 176, "REBALANCE": 179, "SYNC": 138, + "GRANT": 188, "INDEX_CREATE": 75, "INDEX_DROP": 76, "INDEX_LIST": 77, @@ -1392,7 +1405,7 @@ type Response struct { Response []*Datum `protobuf:"bytes,3,rep,name=response" json:"response,omitempty"` // If [type] is [CLIENT_ERROR], [TYPE_ERROR], or [RUNTIME_ERROR], then a // backtrace will be provided. The backtrace says where in the query the - // error occured. Ideally this information will be presented to the user as + // error occurred. Ideally this information will be presented to the user as // a pretty-printed version of their query with the erroneous section // underlined. A backtrace is a series of 0 or more [Frame]s, each of which // specifies either the index of a positional argument or the name of an diff --git a/vendor/github.com/dancannon/gorethink/ql2/ql2.proto b/vendor/gopkg.in/dancannon/gorethink.v2/ql2/ql2.proto similarity index 98% rename from vendor/github.com/dancannon/gorethink/ql2/ql2.proto rename to vendor/gopkg.in/dancannon/gorethink.v2/ql2/ql2.proto index 95e6d6a93e..e40c5be56f 100644 --- a/vendor/github.com/dancannon/gorethink/ql2/ql2.proto +++ b/vendor/gopkg.in/dancannon/gorethink.v2/ql2/ql2.proto @@ -48,6 +48,7 @@ message VersionDummy { // We need to wrap it like this for some V0_2 = 0x723081e1; // Authorization key during handshake V0_3 = 0x5f75e83e; // Authorization key and protocol during handshake V0_4 = 0x400c2d20; // Queries execute in parallel + V1_0 = 0x34c2bdc3; // Users and permissions } // The protocol to use after the handshake, specified in V0_3 @@ -98,8 +99,8 @@ message Query { // A backtrace frame (see `backtrace` in Response below) message Frame { enum FrameType { - POS = 1; // Error occured in a positional argument. - OPT = 2; // Error occured in an optional argument. + POS = 1; // Error occurred in a positional argument. + OPT = 2; // Error occurred in an optional argument. } optional FrameType type = 1; optional int64 pos = 2; // The index of the positional argument. @@ -149,6 +150,7 @@ message Response { OP_FAILED = 4100000; OP_INDETERMINATE = 4200000; USER = 5000000; + PERMISSION_ERROR = 6000000; } optional ErrorType error_type = 7; @@ -186,7 +188,7 @@ message Response { // If [type] is [CLIENT_ERROR], [TYPE_ERROR], or [RUNTIME_ERROR], then a // backtrace will be provided. The backtrace says where in the query the - // error occured. Ideally this information will be presented to the user as + // error occurred. Ideally this information will be presented to the user as // a pretty-printed version of their query with the erroneous section // underlined. A backtrace is a series of 0 or more [Frame]s, each of which // specifies either the index of a positional argument or the name of an @@ -418,6 +420,8 @@ message Term { // The arity of the function should be // Sequence..., Function(sizeof...(Sequence)) -> Sequence + FOLD = 187; // Sequence, Datum, Function(2), {Function(3), Function(1) + // Filter a sequence with either a function or a shortcut // object (see API docs for details). The body of FILTER is // wrapped in an implicit `.default(false)`, and you can @@ -550,6 +554,11 @@ message Term { // written to disk. SYNC = 138; // Table -> OBJECT + // Set global, database, or table-specific permissions + GRANT = 188; // -> OBJECT + // Database -> OBJECT + // Table -> OBJECT + // * Secondary indexes OPs // Creates a new secondary index with a particular name and definition. INDEX_CREATE = 75; // Table, STRING, Function(1), {multi:BOOL} -> OBJECT diff --git a/vendor/github.com/dancannon/gorethink/query.go b/vendor/gopkg.in/dancannon/gorethink.v2/query.go similarity index 90% rename from vendor/github.com/dancannon/gorethink/query.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query.go index d7a94517e2..1bd88a3691 100644 --- a/vendor/github.com/dancannon/gorethink/query.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query.go @@ -5,7 +5,7 @@ import ( "strconv" "strings" - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // A Query represents a query ready to be sent to the database, A Query differs @@ -156,6 +156,11 @@ func (t Term) String() string { if t.rootTerm { return fmt.Sprintf("r.%s(%s)", t.name, strings.Join(allArgsToStringSlice(t.args, t.optArgs), ", ")) } + + if t.args == nil { + return "r" + } + return fmt.Sprintf("%s.%s(%s)", t.args[0].String(), t.name, strings.Join(allArgsToStringSlice(t.args[1:], t.optArgs), ", ")) } @@ -201,6 +206,7 @@ type RunOpts struct { DB interface{} `gorethink:"db,omitempty"` Db interface{} `gorethink:"db,omitempty"` // Deprecated Profile interface{} `gorethink:"profile,omitempty"` + Durability interface{} `gorethink:"durability,omitempty"` UseOutdated interface{} `gorethink:"use_outdated,omitempty"` // Deprecated ArrayLimit interface{} `gorethink:"array_limit,omitempty"` TimeFormat interface{} `gorethink:"time_format,omitempty"` @@ -265,12 +271,36 @@ func (t Term) RunWrite(s *Session, optArgs ...RunOpts) (WriteResponse, error) { } if response.Errors > 0 { - return response, fmt.Errorf(response.FirstError) + return response, fmt.Errorf("%s", response.FirstError) } return response, nil } +// ReadOne is a shortcut method that runs the query on the given connection +// and reads one response from the cursor before closing it. +// +// It returns any errors encountered from running the query or reading the response +func (t Term) ReadOne(dest interface{}, s *Session, optArgs ...RunOpts) error { + res, err := t.Run(s, optArgs...) + if err != nil { + return err + } + return res.One(dest) +} + +// ReadAll is a shortcut method that runs the query on the given connection +// and reads all of the responses from the cursor before closing it. +// +// It returns any errors encountered from running the query or reading the responses +func (t Term) ReadAll(dest interface{}, s *Session, optArgs ...RunOpts) error { + res, err := t.Run(s, optArgs...) + if err != nil { + return err + } + return res.All(dest) +} + // ExecOpts contains the optional arguments for the Exec function and inherits // its options from RunOpts, the only difference is the addition of the NoReply // field. @@ -281,6 +311,7 @@ type ExecOpts struct { DB interface{} `gorethink:"db,omitempty"` Db interface{} `gorethink:"db,omitempty"` // Deprecated Profile interface{} `gorethink:"profile,omitempty"` + Durability interface{} `gorethink:"durability,omitempty"` UseOutdated interface{} `gorethink:"use_outdated,omitempty"` // Deprecated ArrayLimit interface{} `gorethink:"array_limit,omitempty"` TimeFormat interface{} `gorethink:"time_format,omitempty"` diff --git a/vendor/github.com/dancannon/gorethink/query_admin.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_admin.go similarity index 85% rename from vendor/github.com/dancannon/gorethink/query_admin.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_admin.go index 3161aaa067..8c78c1607e 100644 --- a/vendor/github.com/dancannon/gorethink/query_admin.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_admin.go @@ -1,7 +1,7 @@ package gorethink import ( - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // Config can be used to read and/or update the configurations for individual @@ -20,7 +20,7 @@ func (t Term) Rebalance() Term { type ReconfigureOpts struct { Shards interface{} `gorethink:"shards,omitempty"` Replicas interface{} `gorethink:"replicas,omitempty"` - PrimaryTag interface{} `gorethink:"primary_replicas_tag,omitempty"` + PrimaryTag interface{} `gorethink:"primary_replica_tag,omitempty"` DryRun interface{} `gorethink:"dry_run,omitempty"` EmergencyRepair interface{} `gorethink:"emergency_repair,omitempty"` NonVotingReplicaTags interface{} `gorethink:"nonvoting_replica_tags,omitempty"` @@ -53,6 +53,8 @@ func (o *WaitOpts) toMap() map[string]interface{} { // Wait for a table or all the tables in a database to be ready. A table may be // temporarily unavailable after creation, rebalancing or reconfiguring. The // wait command blocks until the given table (or database) is fully up to date. +// +// Deprecated: This function is not supported by RethinkDB 2.3 and above. func Wait(optArgs ...WaitOpts) Term { opts := map[string]interface{}{} if len(optArgs) >= 1 { @@ -71,3 +73,9 @@ func (t Term) Wait(optArgs ...WaitOpts) Term { } return constructMethodTerm(t, "Wait", p.Term_WAIT, []interface{}{}, opts) } + +// Grant modifies access permissions for a user account, globally or on a +// per-database or per-table basis. +func (t Term) Grant(args ...interface{}) Term { + return constructMethodTerm(t, "Grant", p.Term_GRANT, args, map[string]interface{}{}) +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_admin_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_admin_test.go new file mode 100644 index 0000000000..507f06b336 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_admin_test.go @@ -0,0 +1,108 @@ +package gorethink + +import ( + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestAdminDbConfig(c *test.C) { + DB("test").TableDrop("test").Exec(session) + DB("test").TableCreate("test").Exec(session) + + // Test index rename + query := DB("test").Table("test").Config() + + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + var response map[string]interface{} + err = res.One(&response) + c.Assert(err, test.IsNil) + + c.Assert(response["name"], test.Equals, "test") +} + +func (s *RethinkSuite) TestAdminTableConfig(c *test.C) { + DB("test").TableDrop("test").Exec(session) + DB("test").TableCreate("test").Exec(session) + + // Test index rename + query := DB("test").Config() + + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + var response map[string]interface{} + err = res.One(&response) + c.Assert(err, test.IsNil) + + c.Assert(response["name"], test.Equals, "test") +} + +func (s *RethinkSuite) TestAdminTableStatus(c *test.C) { + DB("test").TableDrop("test").Exec(session) + DB("test").TableCreate("test").Exec(session) + + // Test index rename + query := DB("test").Table("test").Status() + + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + var response map[string]interface{} + err = res.One(&response) + c.Assert(err, test.IsNil) + + c.Assert(response["name"], test.Equals, "test") + c.Assert(response["status"], test.NotNil) +} + +func (s *RethinkSuite) TestAdminWaitOpts(c *test.C) { + DB("test").TableDrop("test").Exec(session) + DB("test").TableCreate("test").Exec(session) + + query := DB("test").Table("test").Wait(WaitOpts{ + WaitFor: "all_replicas_ready", + Timeout: 10, + }) + + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + var response map[string]interface{} + err = res.One(&response) + c.Assert(err, test.IsNil) + + c.Assert(response["ready"].(float64) > 0, test.Equals, true) +} + +func (s *RethinkSuite) TestAdminStatus(c *test.C) { + DB("test").TableDrop("test").Exec(session) + DB("test").TableCreate("test").Exec(session) + + // Test index rename + query := DB("test").Table("test").Wait() + + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + var response map[string]interface{} + err = res.One(&response) + c.Assert(err, test.IsNil) + + c.Assert(response["ready"], test.Equals, float64(1)) +} + +func (s *RethinkSuite) TestAdminGrantDatabase(c *test.C) { + DB("rethinkdb").Table("users").Insert(map[string]string{ + "id": "test_user", + "password": "password", + }).Exec(session) + + DB("test").TableDrop("test_grant").Exec(session) + DB("test").TableCreate("test_grant").Exec(session) + + err := DB("test").Table("test_grant").Grant("test_user", map[string]bool{ + "read": true, "write": true, "config": true, + }).Exec(session) + c.Assert(err, test.IsNil) +} diff --git a/vendor/github.com/dancannon/gorethink/query_aggregation.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_aggregation.go similarity index 81% rename from vendor/github.com/dancannon/gorethink/query_aggregation.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_aggregation.go index 1dca1a54a1..ec81c58ef3 100644 --- a/vendor/github.com/dancannon/gorethink/query_aggregation.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_aggregation.go @@ -1,8 +1,6 @@ package gorethink -import ( - p "github.com/dancannon/gorethink/ql2" -) +import p "gopkg.in/dancannon/gorethink.v2/ql2" // Aggregation // These commands are used to compute smaller values from large sequences. @@ -167,3 +165,43 @@ func (t Term) MaxIndex(index interface{}, args ...interface{}) Term { "index": index, }) } + +// FoldOpts contains the optional arguments for the Fold term +type FoldOpts struct { + Emit interface{} `gorethink:"emit,omitempty"` + FinalEmit interface{} `gorethink:"finalEmit,omitempty"` +} + +func (o *FoldOpts) toMap() map[string]interface{} { + return optArgsToMap(o) +} + +// Fold applies a function to a sequence in order, maintaining state via an +// accumulator. The Fold command returns either a single value or a new sequence. +// +// In its first form, Fold operates like Reduce, returning a value by applying a +// combining function to each element in a sequence, passing the current element +// and the previous reduction result to the function. However, Fold has the +// following differences from Reduce: +// - it is guaranteed to proceed through the sequence from first element to last. +// - it passes an initial base value to the function with the first element in +// place of the previous reduction result. +// +// In its second form, Fold operates like ConcatMap, returning a new sequence +// rather than a single value. When an emit function is provided, Fold will: +// - proceed through the sequence in order and take an initial base value, as above. +// - for each element in the sequence, call both the combining function and a +// separate emitting function with the current element and previous reduction result. +// - optionally pass the result of the combining function to the emitting function. +// +// If provided, the emitting function must return a list. +func (t Term) Fold(base, fn interface{}, optArgs ...FoldOpts) Term { + opts := map[string]interface{}{} + if len(optArgs) >= 1 { + opts = optArgs[0].toMap() + } + + args := []interface{}{base, funcWrap(fn)} + + return constructMethodTerm(t, "Fold", p.Term_FOLD, args, opts) +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_aggregation_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_aggregation_test.go new file mode 100644 index 0000000000..abf84e03f2 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_aggregation_test.go @@ -0,0 +1,357 @@ +package gorethink + +import test "gopkg.in/check.v1" + +func (s *RethinkSuite) TestAggregationReduce(c *test.C) { + var response int + query := Expr(arr).Reduce(func(acc, val Term) Term { + return acc.Add(val) + }) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 45) +} + +func (s *RethinkSuite) TestAggregationExprCount(c *test.C) { + var response int + query := Expr(arr).Count() + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 9) +} + +func (s *RethinkSuite) TestAggregationDistinct(c *test.C) { + var response []int + query := Expr(darr).Distinct() + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.HasLen, 5) +} + +func (s *RethinkSuite) TestAggregationGroupMapReduce(c *test.C) { + var response []interface{} + query := Expr(objList).Group(func(row Term) Term { + return row.Field("id").Mod(2).Eq(0) + }).Map(func(row Term) Term { + return row.Field("num") + }).Reduce(func(acc, num Term) Term { + return acc.Add(num) + }) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"reduction": 135, "group": false}, + map[string]interface{}{"reduction": 70, "group": true}, + }) +} + +func (s *RethinkSuite) TestAggregationGroupMapReduceUngroup(c *test.C) { + var response []interface{} + query := Expr(objList).Group(func(row Term) Term { + return row.Field("id").Mod(2).Eq(0) + }).Map(func(row Term) Term { + return row.Field("num") + }).Reduce(func(acc, num Term) Term { + return acc.Add(num) + }).Ungroup().OrderBy("reduction") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"reduction": 70, "group": true}, + map[string]interface{}{"reduction": 135, "group": false}, + }) +} + +func (s *RethinkSuite) TestAggregationGroupMapReduceTable(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("TestAggregationGroupedMapReduceTable").Exec(session) + + // Insert rows + err := DB("test").Table("TestAggregationGroupedMapReduceTable").Insert(objList).Exec(session) + c.Assert(err, test.IsNil) + + var response []interface{} + query := DB("test").Table("TestAggregationGroupedMapReduceTable").Group(func(row Term) Term { + return row.Field("id").Mod(2).Eq(0) + }).Map(func(row Term) Term { + return row.Field("num") + }).Reduce(func(acc, num Term) Term { + return acc.Add(num) + }) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"reduction": 135, "group": false}, + map[string]interface{}{"reduction": 70, "group": true}, + }) +} + +func (s *RethinkSuite) TestAggregationGroupCount(c *test.C) { + var response []interface{} + query := Expr(objList).Group("g1") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"group": 1, "reduction": []interface{}{ + map[string]interface{}{"id": 1, "num": 0, "g1": 1, "g2": 1}, + map[string]interface{}{"num": 15, "g1": 1, "g2": 1, "id": 6}, + map[string]interface{}{"id": 7, "num": 0, "g1": 1, "g2": 2}, + }}, + map[string]interface{}{"group": 2, "reduction": []interface{}{ + map[string]interface{}{"g1": 2, "g2": 2, "id": 2, "num": 5}, + map[string]interface{}{"num": 0, "g1": 2, "g2": 3, "id": 4}, + map[string]interface{}{"num": 100, "g1": 2, "g2": 3, "id": 5}, + map[string]interface{}{"g2": 3, "id": 9, "num": 25, "g1": 2}, + }}, + map[string]interface{}{"group": 3, "reduction": []interface{}{ + map[string]interface{}{"num": 10, "g1": 3, "g2": 2, "id": 3}, + }}, + map[string]interface{}{"group": 4, "reduction": []interface{}{ + map[string]interface{}{"id": 8, "num": 50, "g1": 4, "g2": 2}, + }}, + }) +} + +func (s *RethinkSuite) TestAggregationGroupSum(c *test.C) { + var response []interface{} + query := Expr(objList).Group("g1").Sum("num") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"group": 1, "reduction": 15}, + map[string]interface{}{"reduction": 130, "group": 2}, + map[string]interface{}{"reduction": 10, "group": 3}, + map[string]interface{}{"group": 4, "reduction": 50}, + }) +} + +func (s *RethinkSuite) TestAggregationGroupAvg(c *test.C) { + var response []interface{} + query := Expr(objList).Group("g1").Avg("num") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"group": 1, "reduction": 5}, + map[string]interface{}{"group": 2, "reduction": 32.5}, + map[string]interface{}{"group": 3, "reduction": 10}, + map[string]interface{}{"group": 4, "reduction": 50}, + }) +} + +func (s *RethinkSuite) TestAggregationGroupMin(c *test.C) { + var response []interface{} + query := Expr(objList).Group("g1").Min("num") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"group": 1, "reduction": map[string]interface{}{"id": 1, "num": 0, "g1": 1, "g2": 1}}, + map[string]interface{}{"reduction": map[string]interface{}{"num": 0, "g1": 2, "g2": 3, "id": 4}, "group": 2}, + map[string]interface{}{"group": 3, "reduction": map[string]interface{}{"num": 10, "g1": 3, "g2": 2, "id": 3}}, + map[string]interface{}{"group": 4, "reduction": map[string]interface{}{"g2": 2, "id": 8, "num": 50, "g1": 4}}, + }) +} + +func (s *RethinkSuite) TestAggregationGroupMax(c *test.C) { + var response []interface{} + query := Expr(objList).Group("g1").Max("num") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"reduction": map[string]interface{}{"num": 15, "g1": 1, "g2": 1, "id": 6}, "group": 1}, + map[string]interface{}{"group": 2, "reduction": map[string]interface{}{"num": 100, "g1": 2, "g2": 3, "id": 5}}, + map[string]interface{}{"group": 3, "reduction": map[string]interface{}{"num": 10, "g1": 3, "g2": 2, "id": 3}}, + map[string]interface{}{"group": 4, "reduction": map[string]interface{}{"g2": 2, "id": 8, "num": 50, "g1": 4}}, + }) +} + +func (s *RethinkSuite) TestAggregationMin(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table2").Exec(session) + DB("test").Table("Table2").IndexCreate("num").Exec(session) + DB("test").Table("Table2").IndexWait().Exec(session) + + // Insert rows + DB("test").Table("Table2").Insert(objList).Exec(session) + + // Test query + var response interface{} + query := DB("test").Table("Table2").MinIndex("num") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{"id": 1, "g1": 1, "g2": 1, "num": 0}) +} + +func (s *RethinkSuite) TestAggregationMaxIndex(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table2").Exec(session) + DB("test").Table("Table2").IndexCreate("num").Exec(session) + DB("test").Table("Table2").IndexWait().Exec(session) + + // Insert rows + DB("test").Table("Table2").Insert(objList).Exec(session) + + // Test query + var response interface{} + query := DB("test").Table("Table2").MaxIndex("num") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{"id": 5, "g1": 2, "g2": 3, "num": 100}) +} + +func (s *RethinkSuite) TestAggregationMultipleGroupSum(c *test.C) { + var response []interface{} + query := Expr(objList).Group("g1", "g2").Sum("num") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"group": []interface{}{1, 1}, "reduction": 15}, + map[string]interface{}{"reduction": 0, "group": []interface{}{1, 2}}, + map[string]interface{}{"group": []interface{}{2, 2}, "reduction": 5}, + map[string]interface{}{"reduction": 125, "group": []interface{}{2, 3}}, + map[string]interface{}{"group": []interface{}{3, 2}, "reduction": 10}, + map[string]interface{}{"group": []interface{}{4, 2}, "reduction": 50}, + }) +} + +func (s *RethinkSuite) TestAggregationGroupChained(c *test.C) { + var response []interface{} + query := Expr(objList).Group("g1").Max("num").Field("g2") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"group": 1, "reduction": 1}, + map[string]interface{}{"group": 2, "reduction": 3}, + map[string]interface{}{"group": 3, "reduction": 2}, + map[string]interface{}{"group": 4, "reduction": 2}, + }) +} + +func (s *RethinkSuite) TestAggregationGroupUngroup(c *test.C) { + var response []interface{} + query := Expr(objList).Group("g1", "g2").Max("num").Ungroup() + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"group": []interface{}{1, 1}, "reduction": map[string]interface{}{"g1": 1, "g2": 1, "id": 6, "num": 15}}, + map[string]interface{}{"group": []interface{}{1, 2}, "reduction": map[string]interface{}{"g1": 1, "g2": 2, "id": 7, "num": 0}}, + map[string]interface{}{"group": []interface{}{2, 2}, "reduction": map[string]interface{}{"g1": 2, "g2": 2, "id": 2, "num": 5}}, + map[string]interface{}{"group": []interface{}{2, 3}, "reduction": map[string]interface{}{"g1": 2, "g2": 3, "id": 5, "num": 100}}, + map[string]interface{}{"group": []interface{}{3, 2}, "reduction": map[string]interface{}{"g2": 2, "id": 3, "num": 10, "g1": 3}}, + map[string]interface{}{"reduction": map[string]interface{}{"num": 50, "g1": 4, "g2": 2, "id": 8}, "group": []interface{}{4, 2}}, + }) +} + +func (s *RethinkSuite) TestAggregationContains(c *test.C) { + var response interface{} + query := Expr(arr).Contains(2) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestAggregationFold(c *test.C) { + var response int + query := Expr(arr).Reduce(func(acc, val Term) Term { + return acc.Add(val) + }) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 45) +} + +func (s *RethinkSuite) TestAggregationFoldEmit(c *test.C) { + var response []interface{} + query := Expr(objList).Fold(0, func(acc, row Term) Term { + return acc.Add(1) + }, FoldOpts{ + Emit: func(acc, row, cur Term) Term { + return Branch(acc.Mod(2).Eq(0), []interface{}{row}, []interface{}{}) + }, + }) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"id": 1, "g1": 1, "g2": 1, "num": 0}, + map[string]interface{}{"id": 3, "g1": 3, "g2": 2, "num": 10}, + map[string]interface{}{"id": 5, "g1": 2, "g2": 3, "num": 100}, + map[string]interface{}{"id": 7, "g1": 1, "g2": 2, "num": 0}, + map[string]interface{}{"id": 9, "g1": 2, "g2": 3, "num": 25}, + }) +} diff --git a/vendor/github.com/dancannon/gorethink/query_control.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_control.go similarity index 99% rename from vendor/github.com/dancannon/gorethink/query_control.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_control.go index da1907f7de..f02aa7983d 100644 --- a/vendor/github.com/dancannon/gorethink/query_control.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_control.go @@ -6,7 +6,7 @@ import ( "reflect" - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // Expr converts any value to an expression and is also used by many other terms diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_control_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_control_test.go new file mode 100644 index 0000000000..439459e3f8 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_control_test.go @@ -0,0 +1,521 @@ +package gorethink + +import ( + "bytes" + "testing" + "time" + + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestControlExprNil(c *test.C) { + var response interface{} + query := Expr(nil) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.Equals, ErrEmptyResult) + c.Assert(response, test.Equals, nil) +} + +func (s *RethinkSuite) TestControlExprSimple(c *test.C) { + var response int + query := Expr(1) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 1) +} + +func (s *RethinkSuite) TestControlExprList(c *test.C) { + var response []interface{} + query := Expr(narr) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + 1, 2, 3, 4, 5, 6, []interface{}{ + 7.1, 7.2, 7.3, + }, + }) +} + +func (s *RethinkSuite) TestControlExprObj(c *test.C) { + var response map[string]interface{} + query := Expr(nobj) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{ + "A": 1, + "B": 2, + "C": map[string]interface{}{ + "1": 3, + "2": 4, + }, + }) +} + +func (s *RethinkSuite) TestControlStruct(c *test.C) { + var response map[string]interface{} + query := Expr(str) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{ + "id": "A", + "B": 1, + "D": map[string]interface{}{"D2": "2", "D1": 1}, + "E": []interface{}{"E1", "E2", "E3", 4}, + "F": map[string]interface{}{ + "XA": 2, + "XB": "B", + "XC": []interface{}{"XC1", "XC2"}, + "XD": map[string]interface{}{ + "YA": 3, + "YB": map[string]interface{}{ + "1": "1", + "2": "2", + "3": 3, + }, + "YC": map[string]interface{}{ + "YC1": "YC1", + }, + "YD": map[string]interface{}{ + "YD1": "YD1", + }, + }, + "XE": "XE", + "XF": []interface{}{"XE1", "XE2"}, + }, + }) +} + +func (s *RethinkSuite) TestControlStructTags(c *test.C) { + SetTags("gorethink", "json") + defer SetTags() + + var response map[string]interface{} + query := Expr(TagsTest{"1", "2", "3"}) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{ + "a": "1", "b": "2", "c1": "3", + }) + +} + +func (s *RethinkSuite) TestControlMapTypeAlias(c *test.C) { + var response TMap + query := Expr(TMap{"A": 1, "B": 2}) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, TMap{"A": 1, "B": 2}) +} + +func (s *RethinkSuite) TestControlStringTypeAlias(c *test.C) { + var response TStr + query := Expr(TStr("Hello")) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, TStr("Hello")) +} + +func (s *RethinkSuite) TestControlExprTypes(c *test.C) { + var response []interface{} + query := Expr([]interface{}{int64(1), uint64(1), float64(1.0), int32(1), uint32(1), float32(1), "1", true, false}) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{int64(1), uint64(1), float64(1.0), int32(1), uint32(1), float32(1), "1", true, false}) +} + +func (s *RethinkSuite) TestControlJs(c *test.C) { + var response int + query := JS("1;") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 1) +} + +func (s *RethinkSuite) TestControlHttp(c *test.C) { + if testing.Short() { + c.Skip("-short set") + } + + var response map[string]interface{} + query := HTTP("httpbin.org/get?data=1") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response["args"], jsonEquals, map[string]interface{}{ + "data": "1", + }) +} + +func (s *RethinkSuite) TestControlJson(c *test.C) { + var response []int + query := JSON("[1,2,3]") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2, 3}) +} + +func (s *RethinkSuite) TestControlError(c *test.C) { + query := Error("An error occurred") + err := query.Exec(session) + c.Assert(err, test.NotNil) + + c.Assert(err, test.NotNil) + c.Assert(err, test.FitsTypeOf, RQLUserError{}) + + c.Assert(err.Error(), test.Equals, "gorethink: An error occurred in: \nr.Error(\"An error occurred\")") +} + +func (s *RethinkSuite) TestControlDoNothing(c *test.C) { + var response []interface{} + query := Do([]interface{}{map[string]interface{}{"a": 1}, map[string]interface{}{"a": 2}, map[string]interface{}{"a": 3}}) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{map[string]interface{}{"a": 1}, map[string]interface{}{"a": 2}, map[string]interface{}{"a": 3}}) +} + +func (s *RethinkSuite) TestControlArgs(c *test.C) { + var response time.Time + query := Time(Args(Expr([]interface{}{2014, 7, 12, "Z"}))) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response.Unix(), test.Equals, int64(1405123200)) +} + +func (s *RethinkSuite) TestControlBinaryByteArray(c *test.C) { + var response []byte + + query := Binary([]byte("Hello World")) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(bytes.Equal(response, []byte("Hello World")), test.Equals, true) +} + +type byteArray []byte + +func (s *RethinkSuite) TestControlBinaryByteArrayAlias(c *test.C) { + var response []byte + + query := Binary(byteArray("Hello World")) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(bytes.Equal(response, []byte("Hello World")), test.Equals, true) +} + +func (s *RethinkSuite) TestControlBinaryExpr(c *test.C) { + var response []byte + + query := Expr([]byte("Hello World")) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(bytes.Equal(response, []byte("Hello World")), test.Equals, true) +} + +func (s *RethinkSuite) TestControlBinaryExprAlias(c *test.C) { + var response []byte + + query := Expr(byteArray("Hello World")) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(bytes.Equal(response, []byte("Hello World")), test.Equals, true) +} + +func (s *RethinkSuite) TestControlBinaryTerm(c *test.C) { + var response []byte + + query := Binary(Expr([]byte("Hello World"))) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(bytes.Equal(response, []byte("Hello World")), test.Equals, true) +} + +func (s *RethinkSuite) TestControlBinaryElemTerm(c *test.C) { + var response map[string]interface{} + + query := Expr(map[string]interface{}{ + "bytes": []byte("Hello World"), + }) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(bytes.Equal(response["bytes"].([]byte), []byte("Hello World")), test.Equals, true) +} + +func (s *RethinkSuite) TestControlDo(c *test.C) { + var response []interface{} + query := Do([]interface{}{ + map[string]interface{}{"a": 1}, + map[string]interface{}{"a": 2}, + map[string]interface{}{"a": 3}, + }, func(row Term) Term { + return row.Field("a") + }) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2, 3}) +} + +func (s *RethinkSuite) TestControlDoWithExpr(c *test.C) { + var response []interface{} + query := Expr([]interface{}{ + map[string]interface{}{"a": 1}, + map[string]interface{}{"a": 2}, + map[string]interface{}{"a": 3}, + }).Do(func(row Term) Term { + return row.Field("a") + }) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2, 3}) +} + +func (s *RethinkSuite) TestControlBranchSimple(c *test.C) { + var response int + query := Branch( + true, + 1, + 2, + ) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 1) +} + +func (s *RethinkSuite) TestControlBranchWithMapExpr(c *test.C) { + var response []interface{} + query := Expr([]interface{}{1, 2, 3}).Map(Branch( + Row.Eq(2), + Row.Sub(1), + Row.Add(1), + )) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{2, 1, 4}) +} + +func (s *RethinkSuite) TestControlDefault(c *test.C) { + var response []interface{} + query := Expr(defaultObjList).Map(func(row Term) Term { + return row.Field("a").Default(1) + }) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 1}) +} + +func (s *RethinkSuite) TestControlCoerceTo(c *test.C) { + var response string + query := Expr(1).CoerceTo("STRING") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "1") +} + +func (s *RethinkSuite) TestControlTypeOf(c *test.C) { + var response string + query := Expr(1).TypeOf() + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "NUMBER") +} + +func (s *RethinkSuite) TestControlRangeNoArgs(c *test.C) { + var response []int + query := Range().Limit(100) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(len(response), test.Equals, 100) +} + +func (s *RethinkSuite) TestControlRangeSingleArgs(c *test.C) { + var response []int + query := Range(4) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.DeepEquals, []int{0, 1, 2, 3}) +} + +func (s *RethinkSuite) TestControlRangeTwoArgs(c *test.C) { + var response []int + query := Range(4, 6) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.DeepEquals, []int{4, 5}) +} + +func (s *RethinkSuite) TestControlToJSON(c *test.C) { + var response string + query := Expr([]int{4, 5}).ToJSON() + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "[4,5]") +} + +func (s *RethinkSuite) TestControlUUID(c *test.C) { + var response string + query := UUID() + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(len(response) == 36, test.Equals, true) +} + +func (s *RethinkSuite) TestControlUUIDString(c *test.C) { + var response string + query := UUID("rethinkdb") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(len(response) == 36, test.Equals, true) +} + +func (s *RethinkSuite) TestControlInvalidType(c *test.C) { + query := Expr(map[struct{ string }]string{}) + _, err := query.Run(session) + c.Assert(err, test.NotNil) +} + +func (s *RethinkSuite) TestControlRawQuery(c *test.C) { + var response int + query := RawQuery([]byte(`1`)) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 1) +} + +func (s *RethinkSuite) TestControlRawQuery_advanced(c *test.C) { + var response []int + // r.expr([1,2,3]).map(function(v) { return v.add(1)}) + query := RawQuery([]byte(`[38,[[2,[1,2,3]],[69,[[2,[25]],[24,[[10,[25]],1]]]]]]`)) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []int{2, 3, 4}) +} diff --git a/vendor/github.com/dancannon/gorethink/query_db.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_db.go similarity index 95% rename from vendor/github.com/dancannon/gorethink/query_db.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_db.go index ff9aeca28e..0fd21c8e07 100644 --- a/vendor/github.com/dancannon/gorethink/query_db.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_db.go @@ -1,7 +1,7 @@ package gorethink import ( - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // DBCreate creates a database. A RethinkDB database is a collection of tables, diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_db_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_db_test.go new file mode 100644 index 0000000000..48275c3962 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_db_test.go @@ -0,0 +1,57 @@ +package gorethink + +import ( + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestDbCreate(c *test.C) { + // Delete the test2 database if it already exists + DBDrop("test").Exec(session) + + // Test database creation + query := DBCreate("test") + + response, err := query.RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(response.DBsCreated, jsonEquals, 1) +} + +func (s *RethinkSuite) TestDbList(c *test.C) { + var response []interface{} + + // create database + DBCreate("test").Exec(session) + + // Try and find it in the list + success := false + res, err := DBList().Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.FitsTypeOf, []interface{}{}) + + for _, db := range response { + if db == "test" { + success = true + } + } + + c.Assert(success, test.Equals, true) +} + +func (s *RethinkSuite) TestDbDelete(c *test.C) { + // Delete the test2 database if it already exists + DBCreate("test").Exec(session) + + // Test database creation + query := DBDrop("test") + + response, err := query.RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(response.DBsDropped, jsonEquals, 1) + + // Ensure that there is still a test DB after the test has finished + DBCreate("test").Exec(session) +} diff --git a/vendor/github.com/dancannon/gorethink/query_geospatial.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_geospatial.go similarity index 99% rename from vendor/github.com/dancannon/gorethink/query_geospatial.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_geospatial.go index 868c9303b4..ba928d7243 100644 --- a/vendor/github.com/dancannon/gorethink/query_geospatial.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_geospatial.go @@ -1,7 +1,7 @@ package gorethink import ( - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // CircleOpts contains the optional arguments for the Circle term. diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_geospatial_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_geospatial_test.go new file mode 100644 index 0000000000..ed0b784474 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_geospatial_test.go @@ -0,0 +1,519 @@ +package gorethink + +import ( + test "gopkg.in/check.v1" + + "gopkg.in/dancannon/gorethink.v2/types" +) + +func (s *RethinkSuite) TestGeospatialDecodeGeometryPseudoType(c *test.C) { + var response types.Geometry + + // setup coordinates + coords := [][][]float64{ + { + {-122.423246, 37.779388}, + {-122.423246, 37.329898}, + {-121.88642, 37.329898}, + {-121.88642, 37.329898}, + {-122.423246, 37.779388}, + }, + } + + gt := "Polygon" + res, err := Expr(map[string]interface{}{ + "$reql_type$": "GEOMETRY", + "type": "Polygon", + "coordinates": coords, + }).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + + // test shape + if response.Type != gt { + c.Errorf("expected [%v], instead [%v]", gt, response.Type) + } + + // assert points are within threshold + c.Assert(response, geometryEquals, "Polygon", coords) +} + +func (s *RethinkSuite) TestGeospatialEncodeGeometryPseudoType(c *test.C) { + encoded, err := encode(types.Geometry{ + Type: "Polygon", + Lines: types.Lines{ + types.Line{ + types.Point{Lon: -122.423246, Lat: 37.779388}, + types.Point{Lon: -122.423246, Lat: 37.329898}, + types.Point{Lon: -121.88642, Lat: 37.329898}, + types.Point{Lon: -121.88642, Lat: 37.779388}, + types.Point{Lon: -122.423246, Lat: 37.779388}, + }, + }, + }) + c.Assert(err, test.IsNil) + c.Assert(encoded, jsonEquals, map[string]interface{}{ + "$reql_type$": "GEOMETRY", + "type": "Polygon", + "coordinates": []interface{}{ + []interface{}{ + []interface{}{-122.423246, 37.779388}, + []interface{}{-122.423246, 37.329898}, + []interface{}{-121.88642, 37.329898}, + []interface{}{-121.88642, 37.779388}, + []interface{}{-122.423246, 37.779388}, + }, + }, + }) +} + +func (s *RethinkSuite) TestGeospatialCircle(c *test.C) { + var response types.Geometry + res, err := Circle([]float64{-122.423246, 37.779388}, 10).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, geometryEquals, "Polygon", [][][]float64{ + { + {-122.423246, 37.77929790366427}, + {-122.42326814543915, 37.77929963483801}, + {-122.4232894398445, 37.779304761831504}, + {-122.42330906488651, 37.77931308761787}, + {-122.42332626638755, 37.77932429224285}, + {-122.42334038330416, 37.77933794512014}, + {-122.42335087313059, 37.77935352157849}, + {-122.42335733274696, 37.77937042302436}, + {-122.4233595139113, 37.77938799994533}, + {-122.42335733279968, 37.7794055768704}, + {-122.42335087322802, 37.779422478327966}, + {-122.42334038343147, 37.77943805480385}, + {-122.42332626652532, 37.779451707701796}, + {-122.42330906501378, 37.77946291234741}, + {-122.42328943994191, 37.77947123815131}, + {-122.42326814549187, 37.77947636515649}, + {-122.423246, 37.779478096334365}, + {-122.42322385450814, 37.77947636515649}, + {-122.4232025600581, 37.77947123815131}, + {-122.42318293498623, 37.77946291234741}, + {-122.42316573347469, 37.779451707701796}, + {-122.42315161656855, 37.77943805480385}, + {-122.423141126772, 37.779422478327966}, + {-122.42313466720033, 37.7794055768704}, + {-122.42313248608872, 37.77938799994533}, + {-122.42313466725305, 37.77937042302436}, + {-122.42314112686942, 37.77935352157849}, + {-122.42315161669585, 37.77933794512014}, + {-122.42316573361246, 37.77932429224285}, + {-122.4231829351135, 37.77931308761787}, + {-122.42320256015552, 37.779304761831504}, + {-122.42322385456086, 37.77929963483801}, + {-122.423246, 37.77929790366427}, + }, + }) +} + +func (s *RethinkSuite) TestGeospatialCirclePoint(c *test.C) { + var response types.Geometry + res, err := Circle(Point(-122.423246, 37.779388), 10).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, geometryEquals, "Polygon", [][][]float64{ + { + {-122.423246, 37.77929790366427}, + {-122.42326814543915, 37.77929963483801}, + {-122.4232894398445, 37.779304761831504}, + {-122.42330906488651, 37.77931308761787}, + {-122.42332626638755, 37.77932429224285}, + {-122.42334038330416, 37.77933794512014}, + {-122.42335087313059, 37.77935352157849}, + {-122.42335733274696, 37.77937042302436}, + {-122.4233595139113, 37.77938799994533}, + {-122.42335733279968, 37.7794055768704}, + {-122.42335087322802, 37.779422478327966}, + {-122.42334038343147, 37.77943805480385}, + {-122.42332626652532, 37.779451707701796}, + {-122.42330906501378, 37.77946291234741}, + {-122.42328943994191, 37.77947123815131}, + {-122.42326814549187, 37.77947636515649}, + {-122.423246, 37.779478096334365}, + {-122.42322385450814, 37.77947636515649}, + {-122.4232025600581, 37.77947123815131}, + {-122.42318293498623, 37.77946291234741}, + {-122.42316573347469, 37.779451707701796}, + {-122.42315161656855, 37.77943805480385}, + {-122.423141126772, 37.779422478327966}, + {-122.42313466720033, 37.7794055768704}, + {-122.42313248608872, 37.77938799994533}, + {-122.42313466725305, 37.77937042302436}, + {-122.42314112686942, 37.77935352157849}, + {-122.42315161669585, 37.77933794512014}, + {-122.42316573361246, 37.77932429224285}, + {-122.4231829351135, 37.77931308761787}, + {-122.42320256015552, 37.779304761831504}, + {-122.42322385456086, 37.77929963483801}, + {-122.423246, 37.77929790366427}, + }, + }) +} + +func (s *RethinkSuite) TestGeospatialCirclePointFill(c *test.C) { + var response types.Geometry + res, err := Circle(Point(-122.423246, 37.779388), 10, CircleOpts{Fill: true}).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, geometryEquals, "Polygon", [][][]float64{ + { + {-122.423246, 37.77929790366427}, + {-122.42326814543915, 37.77929963483801}, + {-122.4232894398445, 37.779304761831504}, + {-122.42330906488651, 37.77931308761787}, + {-122.42332626638755, 37.77932429224285}, + {-122.42334038330416, 37.77933794512014}, + {-122.42335087313059, 37.77935352157849}, + {-122.42335733274696, 37.77937042302436}, + {-122.4233595139113, 37.77938799994533}, + {-122.42335733279968, 37.7794055768704}, + {-122.42335087322802, 37.779422478327966}, + {-122.42334038343147, 37.77943805480385}, + {-122.42332626652532, 37.779451707701796}, + {-122.42330906501378, 37.77946291234741}, + {-122.42328943994191, 37.77947123815131}, + {-122.42326814549187, 37.77947636515649}, + {-122.423246, 37.779478096334365}, + {-122.42322385450814, 37.77947636515649}, + {-122.4232025600581, 37.77947123815131}, + {-122.42318293498623, 37.77946291234741}, + {-122.42316573347469, 37.779451707701796}, + {-122.42315161656855, 37.77943805480385}, + {-122.423141126772, 37.779422478327966}, + {-122.42313466720033, 37.7794055768704}, + {-122.42313248608872, 37.77938799994533}, + {-122.42313466725305, 37.77937042302436}, + {-122.42314112686942, 37.77935352157849}, + {-122.42315161669585, 37.77933794512014}, + {-122.42316573361246, 37.77932429224285}, + {-122.4231829351135, 37.77931308761787}, + {-122.42320256015552, 37.779304761831504}, + {-122.42322385456086, 37.77929963483801}, + {-122.423246, 37.77929790366427}, + }, + }) + +} + +func (s *RethinkSuite) TestGeospatialPointDistanceMethod(c *test.C) { + var response float64 + f := 734125.249602186 + res, err := Point(-122.423246, 37.779388).Distance(Point(-117.220406, 32.719464)).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + if !kindaclose(response, f) { + c.Errorf("the deviation between the compared floats is too great [%v:%v]", response, f) + } +} + +func (s *RethinkSuite) TestGeospatialPointDistanceRoot(c *test.C) { + var response float64 + f := 734125.249602186 + res, err := Distance(Point(-122.423246, 37.779388), Point(-117.220406, 32.719464)).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + if !kindaclose(response, f) { + c.Errorf("the deviation between the compared floats is too great [%v:%v]", response, f) + } +} + +func (s *RethinkSuite) TestGeospatialPointDistanceRootKm(c *test.C) { + var response float64 + f := 734.125249602186 + res, err := Distance(Point(-122.423246, 37.779388), Point(-117.220406, 32.719464), DistanceOpts{Unit: "km"}).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + if !kindaclose(response, f) { + c.Errorf("the deviation between the compared floats is too great [%v:%v]", response, f) + } +} + +func (s *RethinkSuite) TestGeospatialFill(c *test.C) { + var response types.Geometry + res, err := Line( + []float64{-122.423246, 37.779388}, + []float64{-122.423246, 37.329898}, + []float64{-121.886420, 37.329898}, + []float64{-121.886420, 37.779388}, + ).Fill().Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, geometryEquals, "Polygon", [][][]float64{ + { + {-122.423246, 37.779388}, + {-122.423246, 37.329898}, + {-121.88642, 37.329898}, + {-121.88642, 37.779388}, + {-122.423246, 37.779388}, + }, + }) +} + +func (s *RethinkSuite) TestGeospatialGeoJSON(c *test.C) { + var response types.Geometry + res, err := GeoJSON(map[string]interface{}{ + "type": "Point", + "coordinates": []interface{}{-122.423246, 37.779388}, + }).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, geometryEquals, "Point", []float64{-122.423246, 37.779388}) +} + +func (s *RethinkSuite) TestGeospatialToGeoJSON(c *test.C) { + var response map[string]interface{} + res, err := Point(-122.423246, 37.779388).ToGeoJSON().Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{ + "type": "Point", + "coordinates": []interface{}{-122.423246, 37.779388}, + }) +} + +func (s *RethinkSuite) TestGeospatialGetIntersecting(c *test.C) { + // Setup table + DB("test").TableDrop("geospatial").Exec(session) + DB("test").TableCreate("geospatial").Exec(session) + DB("test").Table("geospatial").IndexCreate("area", IndexCreateOpts{ + Geo: true, + }).Exec(session) + DB("test").Table("geospatial").IndexWait().Exec(session) + + DB("test").Table("geospatial").Insert([]interface{}{ + map[string]interface{}{"area": Circle(Point(-117.220406, 32.719464), 100000)}, + map[string]interface{}{"area": Circle(Point(-100.220406, 20.719464), 100000)}, + map[string]interface{}{"area": Circle(Point(-117.200406, 32.723464), 100000)}, + }).Exec(session) + + var response []interface{} + res, err := DB("test").Table("geospatial").GetIntersecting( + Circle(Point(-117.220406, 32.719464), 100000), + GetIntersectingOpts{ + Index: "area", + }, + ).Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.HasLen, 2) +} + +func (s *RethinkSuite) TestGeospatialGetNearest(c *test.C) { + // Setup table + DB("test").TableDrop("geospatial").Exec(session) + DB("test").TableCreate("geospatial").Exec(session) + DB("test").Table("geospatial").IndexCreate("area", IndexCreateOpts{ + Geo: true, + }).Exec(session) + DB("test").Table("geospatial").IndexWait().Exec(session) + + DB("test").Table("geospatial").Insert([]interface{}{ + map[string]interface{}{"area": Circle(Point(-117.220406, 32.719464), 100000)}, + map[string]interface{}{"area": Circle(Point(-100.220406, 20.719464), 100000)}, + map[string]interface{}{"area": Circle(Point(-115.210306, 32.733364), 100000)}, + }).Exec(session) + + var response []interface{} + res, err := DB("test").Table("geospatial").GetNearest( + Point(-117.220406, 32.719464), + GetNearestOpts{ + Index: "area", + MaxDist: 1, + }, + ).Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.HasLen, 1) +} + +func (s *RethinkSuite) TestGeospatialIncludesTrue(c *test.C) { + var response bool + res, err := Polygon( + Point(-122.4, 37.7), + Point(-122.4, 37.3), + Point(-121.8, 37.3), + Point(-121.8, 37.7), + ).Includes(Point(-122.3, 37.4)).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestGeospatialIncludesFalse(c *test.C) { + var response bool + res, err := Polygon( + Point(-122.4, 37.7), + Point(-122.4, 37.3), + Point(-121.8, 37.3), + Point(-121.8, 37.7), + ).Includes(Point(100.3, 37.4)).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, false) +} + +func (s *RethinkSuite) TestGeospatialIntersectsTrue(c *test.C) { + var response bool + res, err := Polygon( + Point(-122.4, 37.7), + Point(-122.4, 37.3), + Point(-121.8, 37.3), + Point(-121.8, 37.7), + ).Intersects(Polygon( + Point(-122.3, 37.4), + Point(-122.4, 37.3), + Point(-121.8, 37.3), + Point(-121.8, 37.4), + )).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestGeospatialIntersectsFalse(c *test.C) { + var response bool + res, err := Polygon( + Point(-122.4, 37.7), + Point(-122.4, 37.3), + Point(-121.8, 37.3), + Point(-121.8, 37.7), + ).Intersects(Polygon( + Point(-102.4, 37.7), + Point(-102.4, 37.3), + Point(-101.8, 37.3), + Point(-101.8, 37.7), + )).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, false) +} + +func (s *RethinkSuite) TestGeospatialLineLatLon(c *test.C) { + var response types.Geometry + res, err := Line([]float64{-122.423246, 37.779388}, []float64{-121.886420, 37.329898}).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, geometryEquals, "LineString", [][]float64{ + {-122.423246, 37.779388}, + {-121.886420, 37.329898}, + }) +} + +func (s *RethinkSuite) TestGeospatialLinePoint(c *test.C) { + var response types.Geometry + res, err := Line(Point(-122.423246, 37.779388), Point(-121.886420, 37.329898)).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, geometryEquals, "LineString", [][]float64{ + {-122.423246, 37.779388}, + {-121.886420, 37.329898}, + }) +} + +func (s *RethinkSuite) TestGeospatialPoint(c *test.C) { + var response types.Geometry + res, err := Point(-122.423246, 37.779388).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, types.Geometry{ + Type: "Point", + Point: types.Point{Lon: -122.423246, Lat: 37.779388}, + }) + c.Assert(response, geometryEquals, "Point", []float64{-122.423246, 37.779388}) +} + +func (s *RethinkSuite) TestGeospatialPolygon(c *test.C) { + var response types.Geometry + res, err := Polygon(Point(-122.423246, 37.779388), Point(-122.423246, 37.329898), Point(-121.886420, 37.329898)).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, geometryEquals, "Polygon", [][][]float64{ + { + {-122.423246, 37.779388}, + {-122.423246, 37.329898}, + {-121.88642, 37.329898}, + {-122.423246, 37.779388}, + }, + }) +} + +func (s *RethinkSuite) TestGeospatialPolygonSub(c *test.C) { + var response types.Geometry + res, err := Polygon( + Point(-122.4, 37.7), + Point(-122.4, 37.3), + Point(-121.8, 37.3), + Point(-121.8, 37.7), + ).PolygonSub(Polygon( + Point(-122.3, 37.4), + Point(-122.3, 37.6), + Point(-122.0, 37.6), + Point(-122.0, 37.4), + )).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, geometryEquals, "Polygon", [][][]float64{ + { + {-122.4, 37.7}, + {-122.4, 37.3}, + {-121.8, 37.3}, + {-121.8, 37.7}, + {-122.4, 37.7}, + }, + { + {-122.3, 37.4}, + {-122.3, 37.6}, + {-122, 37.6}, + {-122, 37.4}, + {-122.3, 37.4}, + }, + }) +} diff --git a/vendor/github.com/dancannon/gorethink/query_join.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_join.go similarity index 92% rename from vendor/github.com/dancannon/gorethink/query_join.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_join.go index 57487d31f6..93fa704acd 100644 --- a/vendor/github.com/dancannon/gorethink/query_join.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_join.go @@ -1,7 +1,7 @@ package gorethink import ( - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // InnerJoin returns the inner product of two sequences (e.g. a table, a filter result) @@ -21,7 +21,8 @@ func (t Term) OuterJoin(args ...interface{}) Term { // EqJoinOpts contains the optional arguments for the EqJoin term. type EqJoinOpts struct { - Index interface{} `gorethink:"index,omitempty"` + Index interface{} `gorethink:"index,omitempty"` + Ordered interface{} `gorethink:"ordered,omitempty"` } func (o *EqJoinOpts) toMap() map[string]interface{} { diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_join_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_join_test.go new file mode 100644 index 0000000000..dff3d235e3 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_join_test.go @@ -0,0 +1,181 @@ +package gorethink + +import ( + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestJoinInnerJoin(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Join1").Exec(session) + DB("test").TableCreate("Join2").Exec(session) + + // Insert rows + DB("test").Table("Join1").Insert(joinTable1).Exec(session) + DB("test").Table("Join2").Insert(joinTable2).Exec(session) + + // Test query + var response []interface{} + query := DB("test").Table("Join1").InnerJoin(DB("test").Table("Join2"), func(a, b Term) Term { + return a.Field("id").Eq(b.Field("id")) + }) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + err = res.All(&response) + + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{ + "right": map[string]interface{}{"title": "goof", "id": 0}, + "left": map[string]interface{}{"name": "bob", "id": 0}, + }, + map[string]interface{}{ + "right": map[string]interface{}{"title": "lmoe", "id": 2}, + "left": map[string]interface{}{"name": "joe", "id": 2}, + }, + }) +} + +func (s *RethinkSuite) TestJoinInnerJoinZip(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Join1").Exec(session) + DB("test").TableCreate("Join2").Exec(session) + + // Insert rows + DB("test").Table("Join1").Insert(joinTable1).Exec(session) + DB("test").Table("Join2").Insert(joinTable2).Exec(session) + + // Test query + var response []interface{} + query := DB("test").Table("Join1").InnerJoin(DB("test").Table("Join2"), func(a, b Term) Term { + return a.Field("id").Eq(b.Field("id")) + }).Zip() + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"title": "goof", "name": "bob", "id": 0}, + map[string]interface{}{"title": "lmoe", "name": "joe", "id": 2}, + }) +} + +func (s *RethinkSuite) TestJoinOuterJoinZip(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Join1").Exec(session) + DB("test").TableCreate("Join2").Exec(session) + + // Insert rows + DB("test").Table("Join1").Insert(joinTable1).Exec(session) + DB("test").Table("Join2").Insert(joinTable2).Exec(session) + + // Test query + var response []interface{} + query := DB("test").Table("Join1").OuterJoin(DB("test").Table("Join2"), func(a, b Term) Term { + return a.Field("id").Eq(b.Field("id")) + }).Zip().OrderBy("id") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"title": "goof", "name": "bob", "id": 0}, + map[string]interface{}{"name": "tom", "id": 1}, + map[string]interface{}{"title": "lmoe", "name": "joe", "id": 2}, + }) +} + +func (s *RethinkSuite) TestJoinEqJoinZip(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Join1").Exec(session) + DB("test").TableCreate("Join2").Exec(session) + + // Insert rows + DB("test").Table("Join1").Insert(joinTable1).Exec(session) + DB("test").Table("Join2").Insert(joinTable2).Exec(session) + + // Test query + var response []interface{} + query := DB("test").Table("Join1").EqJoin("id", DB("test").Table("Join2"), EqJoinOpts{ + Ordered: true, + }).Zip() + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"title": "goof", "name": "bob", "id": 0}, + map[string]interface{}{"title": "lmoe", "name": "joe", "id": 2}, + }) +} + +func (s *RethinkSuite) TestJoinEqJoinDiffIdsZip(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Join1").Exec(session) + err := DB("test").TableCreate("Join3", TableCreateOpts{ + PrimaryKey: "it", + }).Exec(session) + c.Assert(err, test.IsNil) + DB("test").Table("Join3").IndexCreate("it").Exec(session) + DB("test").Table("Join3").IndexWait().Exec(session) + + // Insert rows + DB("test").Table("Join1").Delete().Exec(session) + DB("test").Table("Join3").Delete().Exec(session) + DB("test").Table("Join1").Insert(joinTable1).Exec(session) + DB("test").Table("Join3").Insert(joinTable3).Exec(session) + + // Test query + var response []interface{} + query := DB("test").Table("Join1").EqJoin("id", DB("test").Table("Join3"), EqJoinOpts{ + Index: "it", + Ordered: true, + }).Zip() + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"title": "goof", "name": "bob", "id": 0, "it": 0}, + map[string]interface{}{"title": "lmoe", "name": "joe", "id": 2, "it": 2}, + }) +} + +func (s *RethinkSuite) TestOrderByJoinEq(c *test.C) { + type Map map[string]interface{} + var err error + + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("test").Exec(session) + DB("test").TableCreate("test2").Exec(session) + tab := DB("test").Table("test") + tab2 := DB("test").Table("test2") + + // insert rows + err = tab.Insert(Map{"S": "s1", "T": 2}).Exec(session) + err = tab.Insert(Map{"S": "s1", "T": 1}).Exec(session) + err = tab.Insert(Map{"S": "s1", "T": 3}).Exec(session) + err = tab.Insert(Map{"S": "s2", "T": 3}).Exec(session) + c.Assert(err, test.IsNil) + + err = tab2.Insert(Map{"id": "s1", "N": "Rob"}).Exec(session) + err = tab2.Insert(Map{"id": "s2", "N": "Zar"}).Exec(session) + c.Assert(err, test.IsNil) + + // Test query + var response []Map + res, err := tab.OrderBy("T").EqJoin("S", tab2).Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + c.Assert(err, test.IsNil) + c.Check(len(response), test.Equals, 4, test.Commentf("%v", response)) +} diff --git a/vendor/github.com/dancannon/gorethink/query_manipulation.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_manipulation.go similarity index 99% rename from vendor/github.com/dancannon/gorethink/query_manipulation.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_manipulation.go index 00addce014..62d0ffb77f 100644 --- a/vendor/github.com/dancannon/gorethink/query_manipulation.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_manipulation.go @@ -1,7 +1,7 @@ package gorethink import ( - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // Row returns the currently visited document. Note that Row does not work within diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_manipulation_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_manipulation_test.go new file mode 100644 index 0000000000..03ac8b177e --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_manipulation_test.go @@ -0,0 +1,331 @@ +package gorethink + +import ( + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestManipulationDocField(c *test.C) { + query := Expr(map[string]interface{}{"a": 1}).Do(Row.Field("a")) + + var response int + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 1) +} + +func (s *RethinkSuite) TestManipulationPluck(c *test.C) { + query := Expr(map[string]interface{}{"a": 1, "b": 2, "c": 3}).Pluck("a", "c") + + var response map[string]interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{"a": 1, "c": 3}) +} + +func (s *RethinkSuite) TestManipulationWithout(c *test.C) { + query := Expr(map[string]interface{}{"a": 1, "b": 2, "c": 3}).Pluck("a", "c") + + var response map[string]interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{"a": 1, "c": 3}) +} + +func (s *RethinkSuite) TestManipulationMerge(c *test.C) { + query := Expr(map[string]interface{}{"a": 1, "c": 3}).Merge(map[string]interface{}{"b": 2}) + + var response map[string]interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{"a": 1, "b": 2, "c": 3}) +} + +func (s *RethinkSuite) TestManipulationMergeLiteral(c *test.C) { + query := Expr(map[string]interface{}{ + "a": map[string]interface{}{ + "aa": map[string]interface{}{ + "aaa": 1, + "aab": 2, + }, + "ab": map[string]interface{}{ + "aba": 3, + "abb": 4, + }, + }, + }).Merge(map[string]interface{}{"a": map[string]interface{}{"ab": Literal()}}) + + var response map[string]interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{"a": map[string]interface{}{"aa": map[string]interface{}{"aab": 2, "aaa": 1}}}) +} + +func (s *RethinkSuite) TestManipulationAppend(c *test.C) { + query := Expr([]interface{}{1, 2, 3}).Append(4).Append(5) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2, 3, 4, 5}) +} + +func (s *RethinkSuite) TestManipulationPrepend(c *test.C) { + query := Expr([]interface{}{3, 4, 5}).Prepend(2).Prepend(1) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2, 3, 4, 5}) +} + +func (s *RethinkSuite) TestManipulationDifference(c *test.C) { + query := Expr([]interface{}{3, 4, 5}).Difference([]interface{}{3, 4}) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{5}) +} + +func (s *RethinkSuite) TestManipulationSetInsert(c *test.C) { + query := Expr([]interface{}{1, 2, 3}).SetInsert(3).SetInsert(4) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2, 3, 4}) +} + +func (s *RethinkSuite) TestManipulationSetUnion(c *test.C) { + query := Expr([]interface{}{1, 2, 3}).SetUnion([]interface{}{3, 4}) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2, 3, 4}) +} + +func (s *RethinkSuite) TestManipulationSetIntersection(c *test.C) { + query := Expr([]interface{}{1, 2, 3}).SetIntersection([]interface{}{2, 3, 3, 4}) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{2, 3}) +} + +func (s *RethinkSuite) TestManipulationSetDifference(c *test.C) { + query := Expr([]interface{}{1, 2, 3}).SetDifference([]interface{}{2, 3, 4, 4}) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1}) +} + +func (s *RethinkSuite) TestManipulationHasFieldsTrue(c *test.C) { + query := Expr(map[string]interface{}{"a": 1}).HasFields("a") + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestManipulationHasFieldsNested(c *test.C) { + query := Expr(map[string]interface{}{"a": map[string]interface{}{"b": 1}}).HasFields(map[string]interface{}{"a": map[string]interface{}{"b": true}}) + + var response bool + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestManipulationHasFieldsNestedShort(c *test.C) { + query := Expr(map[string]interface{}{"a": map[string]interface{}{"b": 1}}).HasFields(map[string]interface{}{"a": "b"}) + + var response bool + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestManipulationHasFieldsFalse(c *test.C) { + query := Expr(map[string]interface{}{"a": 1}).HasFields("b") + + var response bool + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, false) +} + +func (s *RethinkSuite) TestManipulationInsertAt(c *test.C) { + query := Expr([]interface{}{1, 2, 3}).InsertAt(1, 1.5) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 1.5, 2, 3}) +} + +func (s *RethinkSuite) TestManipulationSpliceAt(c *test.C) { + query := Expr([]interface{}{1, 2, 3}).SpliceAt(1, []interface{}{1.25, 1.5, 1.75}) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 1.25, 1.5, 1.75, 2, 3}) +} + +func (s *RethinkSuite) TestManipulationDeleteAt(c *test.C) { + query := Expr([]interface{}{1, 2, 3}).DeleteAt(1) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 3}) +} + +func (s *RethinkSuite) TestManipulationDeleteAtRange(c *test.C) { + query := Expr([]interface{}{1, 2, 3, 4}).DeleteAt(1, 3) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 4}) +} + +func (s *RethinkSuite) TestManipulationChangeAt(c *test.C) { + query := Expr([]interface{}{1, 5, 3, 4}).ChangeAt(1, 2) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2, 3, 4}) +} + +func (s *RethinkSuite) TestManipulationKeys(c *test.C) { + query := Expr(map[string]interface{}{"a": 1, "b": 2, "c": 3}).Keys() + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{"a", "b", "c"}) +} + +func (s *RethinkSuite) TestManipulationValues(c *test.C) { + query := Expr(map[string]interface{}{"a": 1, "b": 2, "c": 3}).Values() + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2, 3}) +} + +func (s *RethinkSuite) TestManipulationObject(c *test.C) { + query := Object("a", 1, "b", 2) + + var response interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{ + "a": 1, + "b": 2, + }) +} diff --git a/vendor/github.com/dancannon/gorethink/query_math.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_math.go similarity index 99% rename from vendor/github.com/dancannon/gorethink/query_math.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_math.go index e02200cc64..b16ffabbde 100644 --- a/vendor/github.com/dancannon/gorethink/query_math.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_math.go @@ -1,7 +1,7 @@ package gorethink import ( - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) var ( diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_math_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_math_test.go new file mode 100644 index 0000000000..6dc999c437 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_math_test.go @@ -0,0 +1,330 @@ +package gorethink + +import ( + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestMathAdd(c *test.C) { + query := Expr(1).Add(2) + + var response int + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 3) +} + +func (s *RethinkSuite) TestMathSub(c *test.C) { + query := Expr(2).Sub(1) + + var response int + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 1) +} + +func (s *RethinkSuite) TestMathSubNegative(c *test.C) { + query := Expr(1).Sub(2) + + var response int + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, -1) +} + +func (s *RethinkSuite) TestMathMul(c *test.C) { + query := Expr(5).Mul(4) + + var response int + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 20) +} + +func (s *RethinkSuite) TestMathDiv(c *test.C) { + query := Expr(8).Div(4) + + var response int + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 2) +} + +func (s *RethinkSuite) TestMathMod(c *test.C) { + query := Expr(7).Mod(2) + + var response int + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 1) +} + +func (s *RethinkSuite) TestMathEqTrue(c *test.C) { + query := Expr(1).Eq(1) + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestMathEqFalse(c *test.C) { + query := Expr(1).Eq(2) + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, false) +} + +func (s *RethinkSuite) TestMathEqStringTrue(c *test.C) { + query := Expr("test").Eq("test") + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestCompareLt(c *test.C) { + query := Expr(2).Lt(1) + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, false) +} + +func (s *RethinkSuite) TestCompareLe(c *test.C) { + query := Expr(2).Le(1) + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, false) +} + +func (s *RethinkSuite) TestCompareLeEqual(c *test.C) { + query := Expr(2).Le(2) + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestCompareGt(c *test.C) { + query := Expr(2).Gt(1) + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestCompareGe(c *test.C) { + query := Expr(2).Ge(1) + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestCompareGeEqual(c *test.C) { + query := Expr(2).Le(2) + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestBoolNotTrue(c *test.C) { + query := Expr(true).Not() + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, false) +} + +func (s *RethinkSuite) TestBoolAnd(c *test.C) { + query := Expr(true).And(true) + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestBoolOr(c *test.C) { + query := Expr(true).Or(false) + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestBoolDeMorgan(c *test.C) { + query := Expr(true).And(false).Eq(Expr(true).Not().Or(Expr(false).Not()).Not()) + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestMathRootRound(c *test.C) { + query := Round(2.1) + + var response int + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 2) +} + +func (s *RethinkSuite) TestMathMethodRound(c *test.C) { + query := Expr(2.1).Round() + + var response int + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 2) +} + +func (s *RethinkSuite) TestMathRootCeil(c *test.C) { + query := Ceil(2.1) + + var response int + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 3) +} + +func (s *RethinkSuite) TestMathMethodCeil(c *test.C) { + query := Expr(2.1).Ceil() + + var response int + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 3) +} + +func (s *RethinkSuite) TestMathRootFloor(c *test.C) { + query := Floor(2.1) + + var response int + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 2) +} + +func (s *RethinkSuite) TestMathMethodFloor(c *test.C) { + query := Expr(2.1).Floor() + + var response int + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, 2) +} diff --git a/vendor/github.com/dancannon/gorethink/query_select.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_select.go similarity index 99% rename from vendor/github.com/dancannon/gorethink/query_select.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_select.go index 7ad619788b..c0589d212e 100644 --- a/vendor/github.com/dancannon/gorethink/query_select.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_select.go @@ -1,7 +1,7 @@ package gorethink import ( - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // DB references a database. diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_select_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_select_test.go new file mode 100644 index 0000000000..2190e5bd8c --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_select_test.go @@ -0,0 +1,527 @@ +package gorethink + +import ( + "encoding/json" + "fmt" + "math/rand" + "testing" + "time" + + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestSelectGet(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table1").Exec(session) + + // Insert rows + DB("test").Table("Table1").Insert(objList).Exec(session) + + // Test query + var response interface{} + query := DB("test").Table("Table1").Get(6) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{"id": 6, "g1": 1, "g2": 1, "num": 15}) + + res.Close() +} + +func (s *RethinkSuite) TestSelectJSONNumbers(c *test.C) { + session, err := Connect(ConnectOpts{ + Address: url, + UseJSONNumber: true, + }) + c.Assert(err, test.IsNil) + defer session.Close() + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table1").Exec(session) + + // Insert rows + DB("test").Table("Table1").Insert(objList).Exec(session) + + // Test query + var response interface{} + query := DB("test").Table("Table1").Get(6) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{"id": json.Number("6"), "g1": json.Number("1"), "g2": json.Number("1"), "num": json.Number("15")}) + + res.Close() +} + +func (s *RethinkSuite) TestSelectGetAll(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table1").Exec(session) + DB("test").Table("Table1").IndexCreate("num").Exec(session) + DB("test").Table("Table1").IndexWait().Exec(session) + + // Insert rows + DB("test").Table("Table1").Insert(objList).Exec(session) + + // Test query + var response []interface{} + query := DB("test").Table("Table1").GetAll(6).OrderBy("id") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 15, "id": 6, "g2": 1, "g1": 1}, + }) + + res.Close() +} + +func (s *RethinkSuite) TestSelectGetAllMultiple(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table1").Exec(session) + DB("test").Table("Table1").IndexCreate("num").Exec(session) + DB("test").Table("Table1").IndexWait().Exec(session) + + // Insert rows + DB("test").Table("Table1").Insert(objList).Exec(session) + + // Test query + var response []interface{} + query := DB("test").Table("Table1").GetAll(1, 2, 3).OrderBy("id") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 0, "id": 1, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 5, "id": 2, "g2": 2, "g1": 2}, + map[string]interface{}{"num": 10, "id": 3, "g2": 2, "g1": 3}, + }) + + res.Close() +} + +func (s *RethinkSuite) TestSelectGetAllByIndex(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table1").Exec(session) + DB("test").Table("Table1").IndexCreate("num").Exec(session) + DB("test").Table("Table1").IndexWait().Exec(session) + + // Insert rows + DB("test").Table("Table1").Insert(objList).Exec(session) + + // Test query + var response interface{} + query := DB("test").Table("Table1").GetAllByIndex("num", 15).OrderBy("id") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{"id": 6, "g1": 1, "g2": 1, "num": 15}) + + res.Close() +} + +func (s *RethinkSuite) TestSelectGetAllMultipleByIndex(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table2").Exec(session) + DB("test").Table("Table2").IndexCreate("num").Exec(session) + DB("test").Table("Table2").IndexWait().Exec(session) + + // Insert rows + DB("test").Table("Table2").Insert(objList).Exec(session) + + // Test query + var response interface{} + query := DB("test").Table("Table2").GetAllByIndex("num", 15).OrderBy("id") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{"id": 6, "g1": 1, "g2": 1, "num": 15}) + + res.Close() +} + +func (s *RethinkSuite) TestSelectGetAllCompoundIndex(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableDrop("TableCompound").Exec(session) + DB("test").TableCreate("TableCompound").Exec(session) + write, err := DB("test").Table("TableCompound").IndexCreateFunc("full_name", func(row Term) interface{} { + return []interface{}{row.Field("first_name"), row.Field("last_name")} + }).RunWrite(session) + DB("test").Table("TableCompound").IndexWait().Exec(session) + c.Assert(err, test.IsNil) + c.Assert(write.Created, test.Equals, 1) + + // Insert rows + DB("test").Table("TableCompound").Insert(nameList).Exec(session) + + // Test query + var response interface{} + query := DB("test").Table("TableCompound").GetAllByIndex("full_name", []interface{}{"John", "Smith"}) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, map[string]interface{}{"id": 1, "first_name": "John", "last_name": "Smith", "gender": "M"}) + + res.Close() +} + +func (s *RethinkSuite) TestSelectBetween(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table1").Exec(session) + + // Insert rows + DB("test").Table("Table1").Insert(objList).Exec(session) + + // Test query + var response []interface{} + query := DB("test").Table("Table1").Between(1, 3).OrderBy("id") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 0, "id": 1, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 5, "id": 2, "g2": 2, "g1": 2}, + }) + + res.Close() +} + +func (s *RethinkSuite) TestSelectBetweenWithIndex(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table2").Exec(session) + DB("test").Table("Table2").IndexCreate("num").Exec(session) + DB("test").Table("Table2").IndexWait().Exec(session) + + // Insert rows + DB("test").Table("Table2").Insert(objList).Exec(session) + + // Test query + var response []interface{} + query := DB("test").Table("Table2").Between(10, 50, BetweenOpts{ + Index: "num", + }).OrderBy("id") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 10, "id": 3, "g2": 2, "g1": 3}, + map[string]interface{}{"num": 15, "id": 6, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 25, "id": 9, "g2": 3, "g1": 2}, + }) + + res.Close() +} + +func (s *RethinkSuite) TestSelectBetweenWithOptions(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table2").Exec(session) + DB("test").Table("Table2").IndexCreate("num").Exec(session) + DB("test").Table("Table2").IndexWait().Exec(session) + + // Insert rows + DB("test").Table("Table2").Insert(objList).Exec(session) + + // Test query + var response []interface{} + query := DB("test").Table("Table2").Between(10, 50, BetweenOpts{ + Index: "num", + RightBound: "closed", + }).OrderBy("id") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 10, "id": 3, "g2": 2, "g1": 3}, + map[string]interface{}{"num": 15, "id": 6, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 50, "id": 8, "g2": 2, "g1": 4}, + map[string]interface{}{"num": 25, "id": 9, "g2": 3, "g1": 2}, + }) + + res.Close() +} + +func (s *RethinkSuite) TestSelectFilterImplicit(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table1").Exec(session) + + // Insert rows + DB("test").Table("Table1").Insert(objList).Exec(session) + + // Test query + var response []interface{} + query := DB("test").Table("Table1").Filter(Row.Field("num").Ge(50)).OrderBy("id") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 100, "id": 5, "g2": 3, "g1": 2}, + map[string]interface{}{"num": 50, "id": 8, "g2": 2, "g1": 4}, + }) + + res.Close() +} + +func (s *RethinkSuite) TestSelectFilterFunc(c *test.C) { + // Ensure table + database exist + DBCreate("test").Exec(session) + DB("test").TableCreate("Table1").Exec(session) + + // Insert rows + DB("test").Table("Table1").Insert(objList).Exec(session) + + // Test query + var response []interface{} + query := DB("test").Table("Table1").Filter(func(row Term) Term { + return row.Field("num").Ge(50) + }).OrderBy("id") + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 100, "id": 5, "g2": 3, "g1": 2}, + map[string]interface{}{"num": 50, "id": 8, "g2": 2, "g1": 4}, + }) + + res.Close() +} + +func (s *RethinkSuite) TestSelectManyRows(c *test.C) { + // Ensure table + database exist + DBCreate("test").RunWrite(session) + DB("test").TableCreate("TestMany").RunWrite(session) + DB("test").Table("TestMany").Delete().RunWrite(session) + + // Insert rows + for i := 0; i < 100; i++ { + data := []interface{}{} + + for j := 0; j < 100; j++ { + data = append(data, map[string]interface{}{ + "i": i, + "j": j, + }) + } + + DB("test").Table("TestMany").Insert(data).RunWrite(session) + } + + // Test query + res, err := DB("test").Table("TestMany").Run(session, RunOpts{ + MaxBatchRows: 1, + }) + c.Assert(err, test.IsNil) + + var n int + var response map[string]interface{} + for res.Next(&response) { + n++ + } + + c.Assert(res.Err(), test.IsNil) + c.Assert(n, test.Equals, 10000) + + res.Close() +} + +func (s *RethinkSuite) TestConcurrentSelectManyWorkers(c *test.C) { + if testing.Short() { + c.Skip("Skipping long test") + } + + rand.Seed(time.Now().UnixNano()) + sess, _ := Connect(ConnectOpts{ + Address: url, + MaxOpen: 200, + MaxIdle: 200, + }) + + // Ensure table + database exist + DBCreate("test").RunWrite(sess) + DB("test").TableDrop("TestConcurrent").RunWrite(sess) + DB("test").TableCreate("TestConcurrent").RunWrite(sess) + DB("test").TableDrop("TestConcurrent2").RunWrite(sess) + DB("test").TableCreate("TestConcurrent2").RunWrite(sess) + + // Insert rows + for j := 0; j < 200; j++ { + DB("test").Table("TestConcurrent").Insert(map[string]interface{}{ + "id": j, + "i": j, + }).Exec(sess) + DB("test").Table("TestConcurrent2").Insert(map[string]interface{}{ + "j": j, + "k": j * 2, + }).Exec(sess) + } + + // Test queries concurrently + numQueries := 1000 + numWorkers := 10 + queryChan := make(chan int) + doneChan := make(chan error) + + // Start workers + for i := 0; i < numWorkers; i++ { + go func() { + for _ = range queryChan { + res, err := DB("test").Table("TestConcurrent2").EqJoin("j", DB("test").Table("TestConcurrent")).Zip().Run(sess) + if err != nil { + doneChan <- err + return + } + + var response []map[string]interface{} + err = res.All(&response) + if err != nil { + doneChan <- err + return + } + if err := res.Close(); err != nil { + doneChan <- err + return + } + + if len(response) != 200 { + doneChan <- fmt.Errorf("expected response length 200, received %d", len(response)) + return + } + + res, err = DB("test").Table("TestConcurrent").Get(response[rand.Intn(len(response))]["id"]).Run(sess) + if err != nil { + doneChan <- err + return + } + + err = res.All(&response) + if err != nil { + doneChan <- err + return + } + if err := res.Close(); err != nil { + doneChan <- err + return + } + + if len(response) != 1 { + doneChan <- fmt.Errorf("expected response length 1, received %d", len(response)) + return + } + + doneChan <- nil + } + }() + } + + go func() { + for i := 0; i < numQueries; i++ { + queryChan <- i + } + }() + + for i := 0; i < numQueries; i++ { + ret := <-doneChan + if ret != nil { + c.Fatalf("non-nil error returned (%s)", ret) + } + } +} + +func (s *RethinkSuite) TestConcurrentSelectManyRows(c *test.C) { + if testing.Short() { + c.Skip("Skipping long test") + } + + // Ensure table + database exist + DBCreate("test").RunWrite(session) + DB("test").TableCreate("TestMany").RunWrite(session) + DB("test").Table("TestMany").Delete().RunWrite(session) + + // Insert rows + for i := 0; i < 100; i++ { + DB("test").Table("TestMany").Insert(map[string]interface{}{ + "i": i, + }).Exec(session) + } + + // Test queries concurrently + attempts := 10 + waitChannel := make(chan error, attempts) + + for i := 0; i < attempts; i++ { + go func(i int, ch chan error) { + res, err := DB("test").Table("TestMany").Run(session) + if err != nil { + ch <- err + return + } + + var response []map[string]interface{} + err = res.All(&response) + if err != nil { + ch <- err + return + } + + if len(response) != 100 { + ch <- fmt.Errorf("expected response length 100, received %d", len(response)) + return + } + + res.Close() + + ch <- nil + }(i, waitChannel) + } + + for i := 0; i < attempts; i++ { + ret := <-waitChannel + if ret != nil { + c.Fatalf("non-nil error returned (%s)", ret) + } + } +} diff --git a/vendor/github.com/dancannon/gorethink/query_string.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_string.go similarity index 97% rename from vendor/github.com/dancannon/gorethink/query_string.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_string.go index 9227137c8c..12ca2221c6 100644 --- a/vendor/github.com/dancannon/gorethink/query_string.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_string.go @@ -1,7 +1,7 @@ package gorethink import ( - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // Match matches against a regular expression. If no match is found, returns diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_string_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_string_test.go new file mode 100644 index 0000000000..d493981a80 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_string_test.go @@ -0,0 +1,91 @@ +package gorethink + +import ( + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestStringMatchSuccess(c *test.C) { + query := Expr("id:0,name:mlucy,foo:bar").Match("name:(\\w+)").Field("groups").Nth(0).Field("str") + + var response string + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "mlucy") +} + +func (s *RethinkSuite) TestStringMatchFail(c *test.C) { + query := Expr("id:0,foo:bar").Match("name:(\\w+)") + + res, err := query.Run(session) + c.Assert(err, test.IsNil) + c.Assert(res.IsNil(), test.Equals, true) +} + +func (s *RethinkSuite) TestStringSplit(c *test.C) { + query := Expr("a,b,c").Split(",") + + var response []string + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.DeepEquals, []string{"a", "b", "c"}) +} + +func (s *RethinkSuite) TestStringSplitMax(c *test.C) { + query := Expr("a,b,c").Split(",", 1) + + var response []string + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.DeepEquals, []string{"a", "b,c"}) +} + +func (s *RethinkSuite) TestStringSplitWhitespace(c *test.C) { + query := Expr("a b c").Split() + + var response []string + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.DeepEquals, []string{"a", "b", "c"}) +} + +func (s *RethinkSuite) TestStringMatchUpcase(c *test.C) { + query := Expr("tESt").Upcase() + + var response string + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "TEST") +} + +func (s *RethinkSuite) TestStringMatchDowncase(c *test.C) { + query := Expr("tESt").Downcase() + + var response string + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "test") +} diff --git a/vendor/github.com/dancannon/gorethink/query_table.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_table.go similarity index 92% rename from vendor/github.com/dancannon/gorethink/query_table.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_table.go index 157fa46cce..2a7f4f3898 100644 --- a/vendor/github.com/dancannon/gorethink/query_table.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_table.go @@ -1,7 +1,7 @@ package gorethink import ( - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // TableCreateOpts contains the optional arguments for the TableCreate term @@ -78,9 +78,8 @@ func (o *IndexCreateOpts) toMap() map[string]interface{} { // IndexCreate supports the creation of the following types of indexes, to create // indexes using arbitrary expressions use IndexCreateFunc. // - Simple indexes based on the value of a single field. -// - Compound indexes based on multiple fields. -// - Multi indexes based on arrays of values, created when the multi optional argument is true. -// - Geospatial indexes based on indexes of geometry objects, created when the geo optional argument is true. +// - Geospatial indexes based on indexes of geometry objects, created when the +// geo optional argument is true. func (t Term) IndexCreate(name interface{}, optArgs ...IndexCreateOpts) Term { opts := map[string]interface{}{} if len(optArgs) >= 1 { @@ -91,10 +90,15 @@ func (t Term) IndexCreate(name interface{}, optArgs ...IndexCreateOpts) Term { // IndexCreateFunc creates a new secondary index on a table. Secondary indexes // improve the speed of many read queries at the slight cost of increased -// storage space and decreased write performance. +// storage space and decreased write performance. The function takes a index +// name and RQL term as the index value , the term can be an anonymous function +// or a binary representation obtained from the function field of indexStatus. // -// The indexFunction can be an anonymous function or a binary representation -// obtained from the function field of indexStatus. +// It supports the creation of the following types of indexes. +// - Simple indexes based on the value of a single field where the index has a +// different name to the field. +// - Compound indexes based on multiple fields. +// - Multi indexes based on arrays of values, created when the multi optional argument is true. func (t Term) IndexCreateFunc(name, indexFunction interface{}, optArgs ...IndexCreateOpts) Term { opts := map[string]interface{}{} if len(optArgs) >= 1 { diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_table_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_table_test.go new file mode 100644 index 0000000000..dc16e6f713 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_table_test.go @@ -0,0 +1,344 @@ +package gorethink + +import ( + "sync" + "time" + + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestTableCreate(c *test.C) { + DB("test").TableDrop("test").Exec(session) + + // Test database creation + query := DB("test").TableCreate("test") + + response, err := query.RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(response.TablesCreated, jsonEquals, 1) +} + +func (s *RethinkSuite) TestTableCreateSessionDatabase(c *test.C) { + session, err := Connect(ConnectOpts{ + Address: url, + }) + c.Assert(err, test.IsNil) + TableDrop("test").Exec(session) + + // Test database creation + response, err := TableCreate("test").RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(response.TablesCreated, jsonEquals, 1) +} + +func (s *RethinkSuite) TestTableCreatePrimaryKey(c *test.C) { + DB("test").TableDrop("testOpts").Exec(session) + + // Test database creation + query := DB("test").TableCreate("testOpts", TableCreateOpts{ + PrimaryKey: "it", + }) + + response, err := query.RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(response.TablesCreated, jsonEquals, 1) +} + +func (s *RethinkSuite) TestTableCreateSoftDurability(c *test.C) { + DB("test").TableDrop("testOpts").Exec(session) + + // Test database creation + query := DB("test").TableCreate("testOpts", TableCreateOpts{ + Durability: "soft", + }) + + response, err := query.RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(response.TablesCreated, jsonEquals, 1) +} + +func (s *RethinkSuite) TestTableCreateSoftMultipleOpts(c *test.C) { + DB("test").TableDrop("testOpts").Exec(session) + + // Test database creation + query := DB("test").TableCreate("testOpts", TableCreateOpts{ + PrimaryKey: "it", + Durability: "soft", + }) + + response, err := query.RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(response.TablesCreated, jsonEquals, 1) + + DB("test").TableDrop("test").Exec(session) +} + +func (s *RethinkSuite) TestTableList(c *test.C) { + var response []interface{} + + DB("test").TableCreate("test").Exec(session) + + // Try and find it in the list + success := false + res, err := DB("test").TableList().Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.FitsTypeOf, []interface{}{}) + + for _, db := range response { + if db == "test" { + success = true + } + } + + c.Assert(success, test.Equals, true) +} + +func (s *RethinkSuite) TestTableDelete(c *test.C) { + DB("test").TableCreate("test").Exec(session) + + // Test database creation + query := DB("test").TableDrop("test") + + response, err := query.RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(response.TablesDropped, jsonEquals, 1) +} + +func (s *RethinkSuite) TestTableIndexCreate(c *test.C) { + DB("test").TableCreate("test").Exec(session) + DB("test").Table("test").IndexDrop("test").Exec(session) + + // Test database creation + query := DB("test").Table("test").IndexCreate("test", IndexCreateOpts{ + Multi: true, + }) + + response, err := query.RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(response.Created, jsonEquals, 1) +} + +func (s *RethinkSuite) TestTableCompoundIndexCreate(c *test.C) { + DBCreate("test").Exec(session) + DB("test").TableDrop("TableCompound").Exec(session) + DB("test").TableCreate("TableCompound").Exec(session) + response, err := DB("test").Table("TableCompound").IndexCreateFunc("full_name", func(row Term) interface{} { + return []interface{}{row.Field("first_name"), row.Field("last_name")} + }).RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(response.Created, test.Equals, 1) +} + +func (s *RethinkSuite) TestTableIndexList(c *test.C) { + var response []interface{} + + DB("test").TableCreate("test").Exec(session) + DB("test").Table("test").IndexCreate("test").Exec(session) + DB("test").Table("test").IndexWait().Exec(session) + + // Try and find it in the list + success := false + res, err := DB("test").Table("test").IndexList().Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.FitsTypeOf, []interface{}{}) + + for _, db := range response { + if db == "test" { + success = true + } + } + + c.Assert(success, test.Equals, true) +} + +func (s *RethinkSuite) TestTableIndexDelete(c *test.C) { + DB("test").TableCreate("test").Exec(session) + DB("test").Table("test").IndexCreate("test").Exec(session) + DB("test").Table("test").IndexWait().Exec(session) + + // Test database creation + query := DB("test").Table("test").IndexDrop("test") + + response, err := query.RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(response.Dropped, jsonEquals, 1) +} + +func (s *RethinkSuite) TestTableIndexRename(c *test.C) { + DB("test").TableDrop("test").Exec(session) + DB("test").TableCreate("test").Exec(session) + DB("test").Table("test").IndexCreate("test").Exec(session) + DB("test").Table("test").IndexWait().Exec(session) + + // Test index rename + query := DB("test").Table("test").IndexRename("test", "test2") + + response, err := query.RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(response.Renamed, jsonEquals, 1) +} + +func (s *RethinkSuite) TestTableChanges(c *test.C) { + DB("test").TableDrop("changes").Exec(session) + DB("test").TableCreate("changes").Exec(session) + + var n int + + res, err := DB("test").Table("changes").Changes().Run(session) + if err != nil { + c.Fatal(err.Error()) + } + c.Assert(res.Type(), test.Equals, "Feed") + + wg := &sync.WaitGroup{} + wg.Add(1) + + // Use goroutine to wait for changes. Prints the first 10 results + go func() { + var response interface{} + for n < 10 && res.Next(&response) { + n++ + } + + if res.Err() != nil { + c.Fatal(res.Err()) + } + + wg.Done() + }() + + DB("test").Table("changes").Insert(map[string]interface{}{"n": 1}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 2}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 3}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 4}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 5}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 6}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 7}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 8}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 9}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 10}).Exec(session) + + wg.Wait() + + c.Assert(n, test.Equals, 10) +} + +func (s *RethinkSuite) TestTableChangesExit(c *test.C) { + DB("test").TableDrop("changes").Exec(session) + DB("test").TableCreate("changes").Exec(session) + + var n int + + res, err := DB("test").Table("changes").Changes().Run(session) + if err != nil { + c.Fatal(err.Error()) + } + c.Assert(res.Type(), test.Equals, "Feed") + + change := make(chan ChangeResponse) + + // Close cursor after one second + go func() { + <-time.After(time.Second) + res.Close() + }() + + // Insert 5 docs + DB("test").Table("changes").Insert(map[string]interface{}{"n": 1}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 2}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 3}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 4}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 5}).Exec(session) + + // Listen for changes + res.Listen(change) + for _ = range change { + n++ + } + + c.Assert(n, test.Equals, 5) +} + +func (s *RethinkSuite) TestTableChangesExitNoResults(c *test.C) { + DB("test").TableDrop("changes").Exec(session) + DB("test").TableCreate("changes").Exec(session) + + var n int + + res, err := DB("test").Table("changes").Changes().Run(session) + if err != nil { + c.Fatal(err.Error()) + } + c.Assert(res.Type(), test.Equals, "Feed") + + change := make(chan ChangeResponse) + + // Close cursor after one second + go func() { + <-time.After(time.Second) + res.Close() + }() + + // Listen for changes + res.Listen(change) + for _ = range change { + n++ + } + + c.Assert(n, test.Equals, 0) +} + +func (s *RethinkSuite) TestTableChangesIncludeInitial(c *test.C) { + DB("test").TableDrop("changes").Exec(session) + DB("test").TableCreate("changes").Exec(session) + + // Insert 5 documents to table initially + DB("test").Table("changes").Insert(map[string]interface{}{"n": 1}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 2}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 3}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 4}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 5}).Exec(session) + + var n int + + res, err := DB("test").Table("changes").Changes(ChangesOpts{IncludeInitial: true}).Run(session) + if err != nil { + c.Fatal(err.Error()) + } + c.Assert(res.Type(), test.Equals, "Feed") + + wg := &sync.WaitGroup{} + wg.Add(1) + + // Use goroutine to wait for changes. Prints the first 10 results + go func() { + var response interface{} + for n < 10 && res.Next(&response) { + n++ + } + + if res.Err() != nil { + c.Fatal(res.Err()) + } + + wg.Done() + }() + + DB("test").Table("changes").Insert(map[string]interface{}{"n": 6}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 7}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 8}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 9}).Exec(session) + DB("test").Table("changes").Insert(map[string]interface{}{"n": 10}).Exec(session) + + wg.Wait() + + c.Assert(n, test.Equals, 10) +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_test.go new file mode 100644 index 0000000000..486be1318e --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_test.go @@ -0,0 +1,67 @@ +package gorethink + +import test "gopkg.in/check.v1" + +func (s *RethinkSuite) TestQueryRun(c *test.C) { + var response string + + res, err := Expr("Test").Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "Test") +} + +func (s *RethinkSuite) TestQueryReadOne(c *test.C) { + var response string + + err := Expr("Test").ReadOne(&response, session) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "Test") +} + +func (s *RethinkSuite) TestQueryReadAll(c *test.C) { + var response []int + + err := Expr([]int{1, 2, 3}).ReadAll(&response, session) + c.Assert(err, test.IsNil) + c.Assert(response, test.HasLen, 3) + c.Assert(response, test.DeepEquals, []int{1, 2, 3}) +} + +func (s *RethinkSuite) TestQueryExec(c *test.C) { + err := Expr("Test").Exec(session) + c.Assert(err, test.IsNil) +} + +func (s *RethinkSuite) TestQueryProfile(c *test.C) { + var response string + + res, err := Expr("Test").Run(session, RunOpts{ + Profile: true, + }) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(res.Profile(), test.NotNil) + c.Assert(response, test.Equals, "Test") +} + +func (s *RethinkSuite) TestQueryRunRawTime(c *test.C) { + var response map[string]interface{} + + res, err := Now().Run(session, RunOpts{ + TimeFormat: "raw", + }) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response["$reql_type$"], test.NotNil) + c.Assert(response["$reql_type$"], test.Equals, "TIME") +} diff --git a/vendor/github.com/dancannon/gorethink/query_time.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_time.go similarity index 99% rename from vendor/github.com/dancannon/gorethink/query_time.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_time.go index 78ba9e1d12..1205da4947 100644 --- a/vendor/github.com/dancannon/gorethink/query_time.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_time.go @@ -1,7 +1,7 @@ package gorethink import ( - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // Now returns a time object representing the current time in UTC diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_time_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_time_test.go new file mode 100644 index 0000000000..0337ca99d0 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_time_test.go @@ -0,0 +1,135 @@ +package gorethink + +import ( + "time" + + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestTimeTime(c *test.C) { + var response time.Time + res, err := Time(1986, 11, 3, 12, 30, 15, "Z").Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response.Equal(time.Date(1986, 11, 3, 12, 30, 15, 0, time.UTC)), test.Equals, true) +} + +func (s *RethinkSuite) TestTimeTimeMillisecond(c *test.C) { + var response time.Time + res, err := Time(1986, 11, 3, 12, 30, 15.6790123, "Z").Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response.Equal(time.Date(1986, 11, 3, 12, 30, 15, 679*1000*1000, time.UTC)), test.Equals, true) +} + +func (s *RethinkSuite) TestTimeEpochTime(c *test.C) { + var response time.Time + res, err := EpochTime(531360000).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response.Equal(time.Date(1986, 11, 3, 0, 0, 0, 0, time.UTC)), test.Equals, true) +} + +func (s *RethinkSuite) TestTimeExpr(c *test.C) { + var response time.Time + t := time.Unix(531360000, 0) + res, err := Expr(Expr(t)).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) +} + +func (s *RethinkSuite) TestTimeExprMillisecond(c *test.C) { + var response time.Time + t := time.Unix(531360000, 679000000) + res, err := Expr(t).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + c.Assert(err, test.IsNil) + c.Assert(float64(response.UnixNano()), test.Equals, float64(t.UnixNano())) +} + +func (s *RethinkSuite) TestTimeISO8601(c *test.C) { + var t1, t2 time.Time + t2, _ = time.Parse("2006-01-02T15:04:05-07:00", "1986-11-03T08:30:00-07:00") + res, err := ISO8601("1986-11-03T08:30:00-07:00").Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&t1) + c.Assert(err, test.IsNil) + c.Assert(t1.Equal(t2), test.Equals, true) +} + +func (s *RethinkSuite) TestTimeInTimezone(c *test.C) { + var response []time.Time + res, err := Expr([]interface{}{Now(), Now().InTimezone("-07:00")}).Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + c.Assert(err, test.IsNil) + c.Assert(response[1].Equal(response[0]), test.Equals, true) +} + +func (s *RethinkSuite) TestTimeBetween(c *test.C) { + var response interface{} + + times := Expr([]interface{}{ + Time(1986, 9, 3, 12, 30, 15, "Z"), + Time(1986, 10, 3, 12, 30, 15, "Z"), + Time(1986, 11, 3, 12, 30, 15, "Z"), + Time(1986, 12, 3, 12, 30, 15, "Z"), + }) + res, err := times.Filter(func(row Term) Term { + return row.During(Time(1986, 9, 3, 12, 30, 15, "Z"), Time(1986, 11, 3, 12, 30, 15, "Z")) + }).Count().Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(int(response.(float64)), test.Equals, 2) +} + +func (s *RethinkSuite) TestTimeYear(c *test.C) { + var response interface{} + + res, err := Time(1986, 12, 3, 12, 30, 15, "Z").Year().Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(int(response.(float64)), test.Equals, 1986) +} + +func (s *RethinkSuite) TestTimeMonth(c *test.C) { + var response interface{} + + res, err := Time(1986, 12, 3, 12, 30, 15, "Z").Month().Eq(December).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response.(bool), test.Equals, true) +} + +func (s *RethinkSuite) TestTimeDay(c *test.C) { + var response interface{} + + res, err := Time(1986, 12, 3, 12, 30, 15, "Z").Day().Eq(Wednesday).Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response.(bool), test.Equals, true) +} diff --git a/vendor/github.com/dancannon/gorethink/query_transformation.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_transformation.go similarity index 99% rename from vendor/github.com/dancannon/gorethink/query_transformation.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_transformation.go index 2eccf4a5c3..4960f01284 100644 --- a/vendor/github.com/dancannon/gorethink/query_transformation.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_transformation.go @@ -1,6 +1,6 @@ package gorethink -import p "github.com/dancannon/gorethink/ql2" +import p "gopkg.in/dancannon/gorethink.v2/ql2" // Map transform each element of the sequence by applying the given mapping // function. It takes two arguments, a sequence and a function of type diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_transformation_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_transformation_test.go new file mode 100644 index 0000000000..a90b03563a --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_transformation_test.go @@ -0,0 +1,441 @@ +package gorethink + +import ( + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestTransformationMapImplicit(c *test.C) { + query := Expr(arr).Map(Row.Add(1)) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{2, 3, 4, 5, 6, 7, 8, 9, 10}) +} + +func (s *RethinkSuite) TestTransformationMapFunc(c *test.C) { + query := Expr(arr).Map(func(row Term) Term { + return row.Add(1) + }) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{2, 3, 4, 5, 6, 7, 8, 9, 10}) +} + +func (s *RethinkSuite) TestTransformationWithFields(c *test.C) { + query := Expr(objList).WithFields("id", "num").OrderBy("id") + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 0, "id": 1}, + map[string]interface{}{"num": 5, "id": 2}, + map[string]interface{}{"num": 10, "id": 3}, + map[string]interface{}{"num": 0, "id": 4}, + map[string]interface{}{"num": 100, "id": 5}, + map[string]interface{}{"num": 15, "id": 6}, + map[string]interface{}{"num": 0, "id": 7}, + map[string]interface{}{"num": 50, "id": 8}, + map[string]interface{}{"num": 25, "id": 9}, + }) +} + +func (s *RethinkSuite) TestTransformationConcatMap(c *test.C) { + query := Expr(objList).ConcatMap(func(row Term) Term { + return Expr([]interface{}{row.Field("num")}) + }) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{0, 5, 10, 0, 100, 15, 0, 50, 25}) +} + +func (s *RethinkSuite) TestTransformationVariadicMap(c *test.C) { + query := Range(5).Map(Range(5), func(a, b Term) interface{} { + return []interface{}{a, b} + }) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, [][]int{ + {0, 0}, + {1, 1}, + {2, 2}, + {3, 3}, + {4, 4}, + }) +} + +func (s *RethinkSuite) TestTransformationVariadicRootMap(c *test.C) { + query := Map(Range(5), Range(5), func(a, b Term) interface{} { + return []interface{}{a, b} + }) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, [][]int{ + {0, 0}, + {1, 1}, + {2, 2}, + {3, 3}, + {4, 4}, + }) +} + +func (s *RethinkSuite) TestTransformationOrderByDesc(c *test.C) { + query := Expr(noDupNumObjList).OrderBy(Desc("num")) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 100, "id": 5, "g2": 3, "g1": 2}, + map[string]interface{}{"num": 50, "id": 8, "g2": 2, "g1": 4}, + map[string]interface{}{"num": 25, "id": 9, "g2": 3, "g1": 2}, + map[string]interface{}{"num": 15, "id": 6, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 10, "id": 3, "g2": 2, "g1": 3}, + map[string]interface{}{"num": 5, "id": 2, "g2": 2, "g1": 2}, + map[string]interface{}{"num": 0, "id": 1, "g2": 1, "g1": 1}, + }) +} + +func (s *RethinkSuite) TestTransformationOrderByAsc(c *test.C) { + query := Expr(noDupNumObjList).OrderBy(Asc("num")) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 0, "id": 1, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 5, "id": 2, "g2": 2, "g1": 2}, + map[string]interface{}{"num": 10, "id": 3, "g2": 2, "g1": 3}, + map[string]interface{}{"num": 15, "id": 6, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 25, "id": 9, "g2": 3, "g1": 2}, + map[string]interface{}{"num": 50, "id": 8, "g2": 2, "g1": 4}, + map[string]interface{}{"num": 100, "id": 5, "g2": 3, "g1": 2}, + }) +} + +func (s *RethinkSuite) TestTransformationOrderByIndex(c *test.C) { + DB("test").TableCreate("OrderByIndex").Exec(session) + DB("test").Table("test").IndexDrop("OrderByIndex").Exec(session) + + // Test database creation + DB("test").Table("OrderByIndex").IndexCreateFunc("test", Row.Field("num")).Exec(session) + DB("test").Table("OrderByIndex").IndexWait().Exec(session) + DB("test").Table("OrderByIndex").Insert(noDupNumObjList).Exec(session) + + query := DB("test").Table("OrderByIndex").OrderBy(OrderByOpts{ + Index: "test", + }) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 0, "id": 1, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 5, "id": 2, "g2": 2, "g1": 2}, + map[string]interface{}{"num": 10, "id": 3, "g2": 2, "g1": 3}, + map[string]interface{}{"num": 15, "id": 6, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 25, "id": 9, "g2": 3, "g1": 2}, + map[string]interface{}{"num": 50, "id": 8, "g2": 2, "g1": 4}, + map[string]interface{}{"num": 100, "id": 5, "g2": 3, "g1": 2}, + }) +} + +func (s *RethinkSuite) TestTransformationOrderByIndexAsc(c *test.C) { + DB("test").TableCreate("OrderByIndex").Exec(session) + DB("test").Table("test").IndexDrop("OrderByIndex").Exec(session) + + // Test database creation + DB("test").Table("OrderByIndex").IndexCreateFunc("test", Row.Field("num")).Exec(session) + DB("test").Table("OrderByIndex").IndexWait().Exec(session) + DB("test").Table("OrderByIndex").Insert(noDupNumObjList).Exec(session) + + query := DB("test").Table("OrderByIndex").OrderBy(OrderByOpts{ + Index: Asc("test"), + }) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 0, "id": 1, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 5, "id": 2, "g2": 2, "g1": 2}, + map[string]interface{}{"num": 10, "id": 3, "g2": 2, "g1": 3}, + map[string]interface{}{"num": 15, "id": 6, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 25, "id": 9, "g2": 3, "g1": 2}, + map[string]interface{}{"num": 50, "id": 8, "g2": 2, "g1": 4}, + map[string]interface{}{"num": 100, "id": 5, "g2": 3, "g1": 2}, + }) +} + +func (s *RethinkSuite) TestTransformationOrderByMultiple(c *test.C) { + query := Expr(objList).OrderBy(Desc("num"), Asc("id")) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 100, "id": 5, "g2": 3, "g1": 2}, + map[string]interface{}{"num": 50, "id": 8, "g2": 2, "g1": 4}, + map[string]interface{}{"num": 25, "id": 9, "g2": 3, "g1": 2}, + map[string]interface{}{"num": 15, "id": 6, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 10, "id": 3, "g2": 2, "g1": 3}, + map[string]interface{}{"num": 5, "id": 2, "g2": 2, "g1": 2}, + map[string]interface{}{"num": 0, "id": 1, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 0, "id": 4, "g2": 3, "g1": 2}, + map[string]interface{}{"num": 0, "id": 7, "g2": 2, "g1": 1}, + }) +} + +func (s *RethinkSuite) TestTransformationOrderByFunc(c *test.C) { + query := Expr(objList).OrderBy(func(row Term) Term { + return row.Field("num").Add(row.Field("id")) + }) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{ + map[string]interface{}{"num": 0, "id": 1, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 0, "id": 4, "g2": 3, "g1": 2}, + map[string]interface{}{"num": 5, "id": 2, "g2": 2, "g1": 2}, + map[string]interface{}{"num": 0, "id": 7, "g2": 2, "g1": 1}, + map[string]interface{}{"num": 10, "id": 3, "g2": 2, "g1": 3}, + map[string]interface{}{"num": 15, "id": 6, "g2": 1, "g1": 1}, + map[string]interface{}{"num": 25, "id": 9, "g2": 3, "g1": 2}, + map[string]interface{}{"num": 50, "id": 8, "g2": 2, "g1": 4}, + map[string]interface{}{"num": 100, "id": 5, "g2": 3, "g1": 2}, + }) +} + +func (s *RethinkSuite) TestTransformationSkip(c *test.C) { + query := Expr(arr).Skip(7) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{8, 9}) +} + +func (s *RethinkSuite) TestTransformationLimit(c *test.C) { + query := Expr(arr).Limit(2) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2}) +} + +func (s *RethinkSuite) TestTransformationSlice(c *test.C) { + query := Expr(arr).Slice(4) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{5, 6, 7, 8, 9}) +} + +func (s *RethinkSuite) TestTransformationSliceRight(c *test.C) { + query := Expr(arr).Slice(5, 6) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{6}) +} + +func (s *RethinkSuite) TestTransformationSliceOpts(c *test.C) { + query := Expr(arr).Slice(4, SliceOpts{LeftBound: "open"}) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{6, 7, 8, 9}) +} + +func (s *RethinkSuite) TestTransformationSliceRightOpts(c *test.C) { + query := Expr(arr).Slice(5, 6, SliceOpts{RightBound: "closed"}) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{6, 7}) +} + +func (s *RethinkSuite) TestTransformationNth(c *test.C) { + query := Expr(arr).Nth(2) + + var response interface{} + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, 3) +} + +func (s *RethinkSuite) TestTransformationAtIndexNth(c *test.C) { + query := Expr([]interface{}{1}).AtIndex(Expr(0)) + + var response interface{} + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, 1) +} + +func (s *RethinkSuite) TestTransformationAtIndexField(c *test.C) { + query := Expr(map[string]interface{}{"foo": 1}).AtIndex(Expr("foo")) + + var response interface{} + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, 1) +} + +func (s *RethinkSuite) TestTransformationAtIndexArrayField(c *test.C) { + query := Expr([]interface{}{1}).AtIndex(Expr("foo")) + + _, err := query.Run(session) + c.Assert(err, test.NotNil) +} + +func (s *RethinkSuite) TestTransformationOffsetsOf(c *test.C) { + query := Expr(arr).OffsetsOf(2) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1}) +} + +func (s *RethinkSuite) TestTransformationIsEmpty(c *test.C) { + query := Expr([]interface{}{}).IsEmpty() + + var response bool + r, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = r.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, true) +} + +func (s *RethinkSuite) TestTransformationUnion(c *test.C) { + query := Expr(arr).Union(arr) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9}) +} + +func (s *RethinkSuite) TestTransformationUnionRoot(c *test.C) { + query := Union(arr, arr) + + var response []interface{} + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.All(&response) + + c.Assert(err, test.IsNil) + c.Assert(response, jsonEquals, []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9}) +} diff --git a/vendor/github.com/dancannon/gorethink/query_write.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_write.go similarity index 98% rename from vendor/github.com/dancannon/gorethink/query_write.go rename to vendor/gopkg.in/dancannon/gorethink.v2/query_write.go index fa92cb1155..b8fcd413ff 100644 --- a/vendor/github.com/dancannon/gorethink/query_write.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_write.go @@ -1,7 +1,7 @@ package gorethink import ( - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // InsertOpts contains the optional arguments for the Insert term diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/query_write_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/query_write_test.go new file mode 100644 index 0000000000..f889395229 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/query_write_test.go @@ -0,0 +1,148 @@ +package gorethink + +import ( + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestWriteInsert(c *test.C) { + query := DB("test").Table("test").Insert(map[string]interface{}{"num": 1}) + _, err := query.Run(session) + c.Assert(err, test.IsNil) +} + +func (s *RethinkSuite) TestWriteInsertChanges(c *test.C) { + query := DB("test").Table("test").Insert([]interface{}{ + map[string]interface{}{"num": 1}, + map[string]interface{}{"num": 2}, + }, InsertOpts{ReturnChanges: true}) + res, err := query.RunWrite(session) + c.Assert(err, test.IsNil) + c.Assert(res.Inserted, test.Equals, 2) + c.Assert(len(res.Changes), test.Equals, 2) +} + +func (s *RethinkSuite) TestWriteInsertStruct(c *test.C) { + var response map[string]interface{} + o := object{ + Name: "map[string]interface{}ect 3", + Attrs: []attr{ + attr{ + Name: "Attr 2", + Value: "Value", + }, + }, + } + + query := DB("test").Table("test").Insert(o) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response["inserted"], test.Equals, float64(1)) +} + +func (s *RethinkSuite) TestWriteInsertStructPointer(c *test.C) { + var response map[string]interface{} + o := object{ + Name: "map[string]interface{}ect 3", + Attrs: []attr{ + attr{ + Name: "Attr 2", + Value: "Value", + }, + }, + } + + query := DB("test").Table("test").Insert(&o) + res, err := query.Run(session) + c.Assert(err, test.IsNil) + + err = res.One(&response) + + c.Assert(err, test.IsNil) + c.Assert(response["inserted"], test.Equals, float64(1)) +} + +func (s *RethinkSuite) TestWriteUpdate(c *test.C) { + query := DB("test").Table("test").Insert(map[string]interface{}{"num": 1}) + _, err := query.Run(session) + c.Assert(err, test.IsNil) + + // Update the first row in the table + query = DB("test").Table("test").Sample(1).Update(map[string]interface{}{"num": 2}) + _, err = query.Run(session) + c.Assert(err, test.IsNil) +} + +func (s *RethinkSuite) TestWriteReplace(c *test.C) { + query := DB("test").Table("test").Insert(map[string]interface{}{"num": 1}) + _, err := query.Run(session) + c.Assert(err, test.IsNil) + + // Replace the first row in the table + query = DB("test").Table("test").Sample(1).Update(map[string]interface{}{"num": 2}) + _, err = query.Run(session) + c.Assert(err, test.IsNil) +} + +func (s *RethinkSuite) TestWriteDelete(c *test.C) { + query := DB("test").Table("test").Insert(map[string]interface{}{"num": 1}) + _, err := query.Run(session) + c.Assert(err, test.IsNil) + + // Delete the first row in the table + query = DB("test").Table("test").Sample(1).Delete() + _, err = query.Run(session) + c.Assert(err, test.IsNil) +} + +func (s *RethinkSuite) TestWriteReference(c *test.C) { + author := Author{ + ID: "1", + Name: "JRR Tolkien", + } + + book := Book{ + ID: "1", + Title: "The Lord of the Rings", + Author: author, + } + + DB("test").TableDrop("authors").Exec(session) + DB("test").TableDrop("books").Exec(session) + DB("test").TableCreate("authors").Exec(session) + DB("test").TableCreate("books").Exec(session) + + _, err := DB("test").Table("authors").Insert(author).RunWrite(session) + c.Assert(err, test.IsNil) + + _, err = DB("test").Table("books").Insert(book).RunWrite(session) + c.Assert(err, test.IsNil) + + // Read back book + author and check result + cursor, err := DB("test").Table("books").Get("1").Merge(func(p Term) interface{} { + return map[string]interface{}{ + "author_id": DB("test").Table("authors").Get(p.Field("author_id")), + } + }).Run(session) + c.Assert(err, test.IsNil) + + var out Book + err = cursor.One(&out) + c.Assert(err, test.IsNil) + + c.Assert(out.Title, test.Equals, "The Lord of the Rings") + c.Assert(out.Author.Name, test.Equals, "JRR Tolkien") +} + +func (s *RethinkSuite) TestWriteConflict(c *test.C) { + query := DB("test").Table("test").Insert(map[string]interface{}{"id": "a"}) + _, err := query.RunWrite(session) + c.Assert(err, test.IsNil) + + query = DB("test").Table("test").Insert(map[string]interface{}{"id": "a"}) + _, err = query.RunWrite(session) + c.Assert(IsConflictErr(err), test.Equals, true) +} diff --git a/vendor/github.com/dancannon/gorethink/session.go b/vendor/gopkg.in/dancannon/gorethink.v2/session.go similarity index 93% rename from vendor/github.com/dancannon/gorethink/session.go rename to vendor/gopkg.in/dancannon/gorethink.v2/session.go index 586111483f..63ab60d81c 100644 --- a/vendor/github.com/dancannon/gorethink/session.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/session.go @@ -5,7 +5,7 @@ import ( "sync" "time" - p "github.com/dancannon/gorethink/ql2" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // A Session represents a connection to a RethinkDB cluster and should be used @@ -24,13 +24,16 @@ type ConnectOpts struct { Address string `gorethink:"address,omitempty"` Addresses []string `gorethink:"addresses,omitempty"` Database string `gorethink:"database,omitempty"` - AuthKey string `gorethink:"authkey,omitempty"` + Username string `gorethink:"username,omitempty"` + Password string `gorethink:"password,omitempty"` + AuthKey string `gorethink:"authkey,omitempty"` // Deprecated Timeout time.Duration `gorethink:"timeout,omitempty"` WriteTimeout time.Duration `gorethink:"write_timeout,omitempty"` ReadTimeout time.Duration `gorethink:"read_timeout,omitempty"` // The duration in which a connection should send a keep-alive. - KeepAlivePeriod time.Duration `gorethink:"keep_alive_timeout,omitempty"` - TLSConfig *tls.Config `gorethink:"tlsconfig,omitempty"` + KeepAlivePeriod time.Duration `gorethink:"keep_alive_timeout,omitempty"` + TLSConfig *tls.Config `gorethink:"tlsconfig,omitempty"` + HandshakeVersion HandshakeVersion `gorethink:"handshake_version,omitempty"` MaxIdle int `gorethink:"max_idle,omitempty"` // By default a maximum of 2 connections are opened per host. diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/session_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/session_test.go new file mode 100644 index 0000000000..59503823f9 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/session_test.go @@ -0,0 +1,131 @@ +package gorethink + +import ( + "os" + "time" + + test "gopkg.in/check.v1" +) + +func (s *RethinkSuite) TestSessionConnect(c *test.C) { + session, err := Connect(ConnectOpts{ + Address: url, + }) + c.Assert(err, test.IsNil) + + row, err := Expr("Hello World").Run(session) + c.Assert(err, test.IsNil) + + var response string + err = row.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "Hello World") +} + +func (s *RethinkSuite) TestSessionConnectHandshakeV1_0(c *test.C) { + session, err := Connect(ConnectOpts{ + Address: url, + HandshakeVersion: HandshakeV1_0, + }) + c.Assert(err, test.IsNil) + + row, err := Expr("Hello World").Run(session) + c.Assert(err, test.IsNil) + + var response string + err = row.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "Hello World") +} + +func (s *RethinkSuite) TestSessionConnectHandshakeV0_4(c *test.C) { + session, err := Connect(ConnectOpts{ + Address: url, + HandshakeVersion: HandshakeV0_4, + }) + c.Assert(err, test.IsNil) + + row, err := Expr("Hello World").Run(session) + c.Assert(err, test.IsNil) + + var response string + err = row.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "Hello World") +} + +func (s *RethinkSuite) TestSessionReconnect(c *test.C) { + session, err := Connect(ConnectOpts{ + Address: url, + }) + c.Assert(err, test.IsNil) + + row, err := Expr("Hello World").Run(session) + c.Assert(err, test.IsNil) + + var response string + err = row.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "Hello World") + + err = session.Reconnect() + c.Assert(err, test.IsNil) + + row, err = Expr("Hello World 2").Run(session) + c.Assert(err, test.IsNil) + + err = row.One(&response) + c.Assert(err, test.IsNil) + c.Assert(response, test.Equals, "Hello World 2") +} + +func (s *RethinkSuite) TestSessionConnectError(c *test.C) { + var err error + _, err = Connect(ConnectOpts{ + Address: "nonexistanturl", + Timeout: time.Second, + }) + c.Assert(err, test.NotNil) +} + +func (s *RethinkSuite) TestSessionClose(c *test.C) { + session, err := Connect(ConnectOpts{ + Address: url, + }) + c.Assert(err, test.IsNil) + + _, err = Expr("Hello World").Run(session) + c.Assert(err, test.IsNil) + + err = session.Close() + c.Assert(err, test.IsNil) + + _, err = Expr("Hello World").Run(session) + c.Assert(err, test.NotNil) +} + +func (s *RethinkSuite) TestSessionServer(c *test.C) { + session, err := Connect(ConnectOpts{ + Address: url, + }) + c.Assert(err, test.IsNil) + + server, err := session.Server() + c.Assert(err, test.IsNil) + + c.Assert(len(server.ID) > 0, test.Equals, true) + c.Assert(len(server.Name) > 0, test.Equals, true) +} + +func (s *RethinkSuite) TestSessionConnectDatabase(c *test.C) { + session, err := Connect(ConnectOpts{ + Address: url, + AuthKey: os.Getenv("RETHINKDB_AUTHKEY"), + Database: "test2", + }) + c.Assert(err, test.IsNil) + + _, err = Table("test2").Run(session) + c.Assert(err, test.NotNil) + c.Assert(err.Error(), test.Equals, "gorethink: Database `test2` does not exist. in: \nr.Table(\"test2\")") +} diff --git a/vendor/gopkg.in/dancannon/gorethink.v2/testdata_test.go b/vendor/gopkg.in/dancannon/gorethink.v2/testdata_test.go new file mode 100644 index 0000000000..345bde9471 --- /dev/null +++ b/vendor/gopkg.in/dancannon/gorethink.v2/testdata_test.go @@ -0,0 +1,112 @@ +package gorethink + +func setupTestData() { + if *testdata { + // Delete any preexisting databases + DBDrop("test").Exec(session) + DBDrop("examples").Exec(session) + DBDrop("superheroes").Exec(session) + + DBCreate("test").Exec(session) + DBCreate("examples").Exec(session) + + DB("examples").TableCreate("posts").Exec(session) + DB("examples").TableCreate("heroes").Exec(session) + DB("examples").TableCreate("users").Exec(session) + DB("examples").TableCreate("games").Exec(session) + DB("examples").TableCreate("games2").Exec(session) + DB("examples").TableCreate("marvel").Exec(session) + + DB("examples").Table("posts").IndexCreate("date").Exec(session) + DB("examples").Table("posts").IndexWait().Exec(session) + DB("examples").Table("posts").IndexCreateFunc( + "dateAndTitle", + []interface{}{Row.Field("date"), Row.Field("title")}, + ).Exec(session) + + DB("examples").Table("heroes").IndexCreate("code_name").Exec(session) + DB("examples").Table("heroes").IndexWait().Exec(session) + + DB("examples").Table("games").IndexCreate("type").Exec(session) + DB("examples").Table("games").IndexWait().Exec(session) + + // Create heroes table + DB("examples").Table("heroes").Insert([]interface{}{ + map[string]interface{}{ + "id": 1, + "code_name": "batman", + "name": "Batman", + }, + map[string]interface{}{ + "id": 2, + "code_name": "man_of_steel", + "name": "Superman", + }, + map[string]interface{}{ + "id": 3, + "code_name": "ant_man", + "name": "Ant Man", + }, + map[string]interface{}{ + "id": 4, + "code_name": "flash", + "name": "The Flash", + }, + }).Exec(session) + + // Create users table + DB("examples").Table("users").Insert([]interface{}{ + map[string]interface{}{ + "id": "william", + "email": "william@rethinkdb.com", + "age": 30, + }, + map[string]interface{}{ + "id": "lara", + "email": "lara@rethinkdb.com", + "age": 30, + }, + map[string]interface{}{ + "id": "john", + "email": "john@rethinkdb.com", + "age": 19, + }, + map[string]interface{}{ + "id": "jane", + "email": "jane@rethinkdb.com", + "age": 45, + }, + map[string]interface{}{ + "id": "bob", + "email": "bob@rethinkdb.com", + "age": 24, + }, + map[string]interface{}{ + "id": "brad", + "email": "brad@gmail.com", + "age": 15, + }, + }).Exec(session) + + // Create games table + DB("examples").Table("games").Insert([]interface{}{ + map[string]interface{}{"id": 2, "player": "Bob", "points": 15, "type": "ranked"}, + map[string]interface{}{"id": 5, "player": "Alice", "points": 7, "type": "free"}, + map[string]interface{}{"id": 11, "player": "Bob", "points": 10, "type": "free"}, + map[string]interface{}{"id": 12, "player": "Alice", "points": 2, "type": "free"}, + }).Exec(session) + + // Create games2 table + DB("examples").Table("games2").Insert([]interface{}{ + map[string]interface{}{"id": 1, "matches": map[string]interface{}{"a": []int{1, 2, 3}, "b": []int{4, 5, 6}}}, + map[string]interface{}{"id": 2, "matches": map[string]interface{}{"b": []int{100}, "c": []int{7, 8, 9}}}, + map[string]interface{}{"id": 3, "matches": map[string]interface{}{"a": []int{10, 20}, "c": []int{70, 80}}}, + }).Exec(session) + + // Create marvel table + DB("examples").Table("marvel").Insert([]interface{}{ + map[string]interface{}{"name": "Iron Man", "victories": 214}, + map[string]interface{}{"name": "Jubilee", "victories": 9}, + }).Exec(session) + } +} diff --git a/vendor/github.com/dancannon/gorethink/types/geometry.go b/vendor/gopkg.in/dancannon/gorethink.v2/types/geometry.go similarity index 100% rename from vendor/github.com/dancannon/gorethink/types/geometry.go rename to vendor/gopkg.in/dancannon/gorethink.v2/types/geometry.go diff --git a/vendor/github.com/dancannon/gorethink/utils.go b/vendor/gopkg.in/dancannon/gorethink.v2/utils.go similarity index 96% rename from vendor/github.com/dancannon/gorethink/utils.go rename to vendor/gopkg.in/dancannon/gorethink.v2/utils.go index e74d71c3b5..03c1e2da08 100644 --- a/vendor/github.com/dancannon/gorethink/utils.go +++ b/vendor/gopkg.in/dancannon/gorethink.v2/utils.go @@ -6,9 +6,8 @@ import ( "strings" "sync/atomic" - "github.com/dancannon/gorethink/encoding" - - p "github.com/dancannon/gorethink/ql2" + "gopkg.in/dancannon/gorethink.v2/encoding" + p "gopkg.in/dancannon/gorethink.v2/ql2" ) // Helper functions for constructing terms @@ -98,9 +97,9 @@ func makeFunc(f interface{}) Term { var args = make([]reflect.Value, valueType.NumIn()) for i := 0; i < valueType.NumIn(); i++ { // Get a slice of the VARs to use as the function arguments - args[i] = reflect.ValueOf(constructRootTerm("var", p.Term_VAR, []interface{}{nextVarID}, map[string]interface{}{})) - argNums[i] = nextVarID - atomic.AddInt64(&nextVarID, 1) + varID := atomic.AddInt64(&nextVarID, 1) + args[i] = reflect.ValueOf(constructRootTerm("var", p.Term_VAR, []interface{}{varID}, map[string]interface{}{})) + argNums[i] = varID // make sure all input arguments are of type Term if valueType.In(i).String() != "gorethink.Term" { diff --git a/vendor/github.com/dancannon/gorethink/wercker.yml b/vendor/gopkg.in/dancannon/gorethink.v2/wercker.yml similarity index 100% rename from vendor/github.com/dancannon/gorethink/wercker.yml rename to vendor/gopkg.in/dancannon/gorethink.v2/wercker.yml