added lib/pq to the vendor dir and renamed the go-sqlmock to its version

Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/13fd7151
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/13fd7151
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/13fd7151

Branch: refs/heads/master
Commit: 13fd7151f992081da8cf5b79d262fba5df5de2db
Parents: 9c8f5b5
Author: Dewayne Richardson <dewr...@apache.org>
Authored: Mon Aug 14 13:30:56 2017 -0600
Committer: Dan Kirkwood <dang...@gmail.com>
Committed: Mon Aug 14 14:38:45 2017 -0600

----------------------------------------------------------------------
 .../vendor/github.com/lib/pq/.travis.sh         |   73 +
 .../vendor/github.com/lib/pq/.travis.yml        |   45 +
 .../vendor/github.com/lib/pq/CONTRIBUTING.md    |   29 +
 .../vendor/github.com/lib/pq/LICENSE.md         |    8 +
 .../vendor/github.com/lib/pq/README.md          |  105 +
 .../vendor/github.com/lib/pq/array.go           |  756 ++++++++
 .../vendor/github.com/lib/pq/array_test.go      | 1317 +++++++++++++
 .../vendor/github.com/lib/pq/bench_test.go      |  435 +++++
 .../vendor/github.com/lib/pq/buf.go             |   91 +
 .../vendor/github.com/lib/pq/certs/README       |    3 +
 .../github.com/lib/pq/certs/bogus_root.crt      |   19 +
 .../github.com/lib/pq/certs/postgresql.crt      |   69 +
 .../github.com/lib/pq/certs/postgresql.key      |   15 +
 .../vendor/github.com/lib/pq/certs/root.crt     |   24 +
 .../vendor/github.com/lib/pq/certs/server.crt   |   81 +
 .../vendor/github.com/lib/pq/certs/server.key   |   27 +
 .../vendor/github.com/lib/pq/conn.go            | 1821 ++++++++++++++++++
 .../vendor/github.com/lib/pq/conn_go18.go       |  128 ++
 .../vendor/github.com/lib/pq/conn_test.go       | 1614 ++++++++++++++++
 .../vendor/github.com/lib/pq/copy.go            |  282 +++
 .../vendor/github.com/lib/pq/copy_test.go       |  465 +++++
 .../vendor/github.com/lib/pq/doc.go             |  235 +++
 .../vendor/github.com/lib/pq/encode.go          |  595 ++++++
 .../vendor/github.com/lib/pq/encode_test.go     |  758 ++++++++
 .../vendor/github.com/lib/pq/error.go           |  508 +++++
 .../vendor/github.com/lib/pq/go18_test.go       |  319 +++
 .../vendor/github.com/lib/pq/hstore/hstore.go   |  118 ++
 .../github.com/lib/pq/hstore/hstore_test.go     |  148 ++
 .../vendor/github.com/lib/pq/issues_test.go     |   26 +
 .../github.com/lib/pq/listen_example/doc.go     |   96 +
 .../vendor/github.com/lib/pq/notify.go          |  782 ++++++++
 .../vendor/github.com/lib/pq/notify_test.go     |  564 ++++++
 .../vendor/github.com/lib/pq/oid/doc.go         |    6 +
 .../vendor/github.com/lib/pq/oid/gen.go         |   74 +
 .../vendor/github.com/lib/pq/oid/types.go       |  173 ++
 .../vendor/github.com/lib/pq/ssl.go             |  158 ++
 .../vendor/github.com/lib/pq/ssl_go1.7.go       |   14 +
 .../vendor/github.com/lib/pq/ssl_permissions.go |   20 +
 .../github.com/lib/pq/ssl_renegotiation.go      |    8 +
 .../vendor/github.com/lib/pq/ssl_test.go        |  279 +++
 .../vendor/github.com/lib/pq/ssl_windows.go     |    9 +
 .../vendor/github.com/lib/pq/url.go             |   76 +
 .../vendor/github.com/lib/pq/url_test.go        |   66 +
 .../vendor/github.com/lib/pq/user_posix.go      |   24 +
 .../vendor/github.com/lib/pq/user_windows.go    |   27 +
 .../vendor/github.com/lib/pq/uuid.go            |   23 +
 .../vendor/github.com/lib/pq/uuid_test.go       |   46 +
 .../gopkg.in/DATA-DOG/go-sqlmock.v1/LICENSE     |   28 +
 .../gopkg.in/DATA-DOG/go-sqlmock.v1/README.md   |  223 +++
 .../gopkg.in/DATA-DOG/go-sqlmock.v1/argument.go |   24 +
 .../DATA-DOG/go-sqlmock.v1/argument_test.go     |   58 +
 .../gopkg.in/DATA-DOG/go-sqlmock.v1/driver.go   |   78 +
 .../DATA-DOG/go-sqlmock.v1/driver_test.go       |  112 ++
 .../go-sqlmock.v1/examples/basic/basic.go       |   40 +
 .../go-sqlmock.v1/examples/basic/basic_test.go  |   58 +
 .../go-sqlmock.v1/examples/blog/blog.go         |   81 +
 .../go-sqlmock.v1/examples/blog/blog_test.go    |  102 +
 .../DATA-DOG/go-sqlmock.v1/examples/doc.go      |    1 +
 .../go-sqlmock.v1/examples/orders/orders.go     |  121 ++
 .../examples/orders/orders_test.go              |  108 ++
 .../DATA-DOG/go-sqlmock.v1/expectations.go      |  344 ++++
 .../go-sqlmock.v1/expectations_before_go18.go   |   52 +
 .../DATA-DOG/go-sqlmock.v1/expectations_go18.go |   66 +
 .../go-sqlmock.v1/expectations_go18_test.go     |   64 +
 .../DATA-DOG/go-sqlmock.v1/expectations_test.go |  154 ++
 .../gopkg.in/DATA-DOG/go-sqlmock.v1/result.go   |   39 +
 .../DATA-DOG/go-sqlmock.v1/result_test.go       |   62 +
 .../gopkg.in/DATA-DOG/go-sqlmock.v1/rows.go     |  144 ++
 .../DATA-DOG/go-sqlmock.v1/rows_go18.go         |   20 +
 .../DATA-DOG/go-sqlmock.v1/rows_go18_test.go    |   92 +
 .../DATA-DOG/go-sqlmock.v1/rows_test.go         |  265 +++
 .../gopkg.in/DATA-DOG/go-sqlmock.v1/sqlmock.go  |  525 +++++
 .../DATA-DOG/go-sqlmock.v1/sqlmock_go18.go      |  101 +
 .../DATA-DOG/go-sqlmock.v1/sqlmock_go18_test.go |  426 ++++
 .../DATA-DOG/go-sqlmock.v1/sqlmock_test.go      |  998 ++++++++++
 .../DATA-DOG/go-sqlmock.v1/statement.go         |   27 +
 .../DATA-DOG/go-sqlmock.v1/statement_test.go    |   33 +
 .../DATA-DOG/go-sqlmock.v1/stubs_test.go        |   76 +
 .../gopkg.in/DATA-DOG/go-sqlmock.v1/util.go     |   13 +
 .../DATA-DOG/go-sqlmock.v1/util_test.go         |   21 +
 .../vendor/gopkg.in/DATA-DOG/go-sqlmock/LICENSE |   28 -
 .../gopkg.in/DATA-DOG/go-sqlmock/README.md      |  223 ---
 .../gopkg.in/DATA-DOG/go-sqlmock/argument.go    |   24 -
 .../DATA-DOG/go-sqlmock/argument_test.go        |   58 -
 .../gopkg.in/DATA-DOG/go-sqlmock/driver.go      |   78 -
 .../gopkg.in/DATA-DOG/go-sqlmock/driver_test.go |  112 --
 .../DATA-DOG/go-sqlmock/examples/basic/basic.go |   40 -
 .../go-sqlmock/examples/basic/basic_test.go     |   58 -
 .../DATA-DOG/go-sqlmock/examples/blog/blog.go   |   81 -
 .../go-sqlmock/examples/blog/blog_test.go       |  102 -
 .../DATA-DOG/go-sqlmock/examples/doc.go         |    1 -
 .../go-sqlmock/examples/orders/orders.go        |  121 --
 .../go-sqlmock/examples/orders/orders_test.go   |  108 --
 .../DATA-DOG/go-sqlmock/expectations.go         |  344 ----
 .../go-sqlmock/expectations_before_go18.go      |   52 -
 .../DATA-DOG/go-sqlmock/expectations_go18.go    |   66 -
 .../go-sqlmock/expectations_go18_test.go        |   64 -
 .../DATA-DOG/go-sqlmock/expectations_test.go    |  154 --
 .../gopkg.in/DATA-DOG/go-sqlmock/result.go      |   39 -
 .../gopkg.in/DATA-DOG/go-sqlmock/result_test.go |   62 -
 .../vendor/gopkg.in/DATA-DOG/go-sqlmock/rows.go |  144 --
 .../gopkg.in/DATA-DOG/go-sqlmock/rows_go18.go   |   20 -
 .../DATA-DOG/go-sqlmock/rows_go18_test.go       |   92 -
 .../gopkg.in/DATA-DOG/go-sqlmock/rows_test.go   |  265 ---
 .../gopkg.in/DATA-DOG/go-sqlmock/sqlmock.go     |  525 -----
 .../DATA-DOG/go-sqlmock/sqlmock_go18.go         |  101 -
 .../DATA-DOG/go-sqlmock/sqlmock_go18_test.go    |  426 ----
 .../DATA-DOG/go-sqlmock/sqlmock_test.go         |  998 ----------
 .../gopkg.in/DATA-DOG/go-sqlmock/statement.go   |   27 -
 .../DATA-DOG/go-sqlmock/statement_test.go       |   33 -
 .../gopkg.in/DATA-DOG/go-sqlmock/stubs_test.go  |   76 -
 .../vendor/gopkg.in/DATA-DOG/go-sqlmock/util.go |   13 -
 .../gopkg.in/DATA-DOG/go-sqlmock/util_test.go   |   21 -
 113 files changed, 17115 insertions(+), 4556 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/.travis.sh
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/.travis.sh 
b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/.travis.sh
new file mode 100755
index 0000000..ebf4470
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/.travis.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+set -eu
+
+client_configure() {
+       sudo chmod 600 $PQSSLCERTTEST_PATH/postgresql.key
+}
+
+pgdg_repository() {
+       local sourcelist='sources.list.d/postgresql.list'
+
+       curl -sS 'https://www.postgresql.org/media/keys/ACCC4CF8.asc' | sudo 
apt-key add -
+       echo deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release 
-cs)-pgdg main $PGVERSION | sudo tee "/etc/apt/$sourcelist"
+       sudo apt-get -o Dir::Etc::sourcelist="$sourcelist" -o 
Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0' update
+}
+
+postgresql_configure() {
+       sudo tee /etc/postgresql/$PGVERSION/main/pg_hba.conf > /dev/null 
<<-config
+               local     all         all                               trust
+               hostnossl all         pqgossltest 127.0.0.1/32          reject
+               hostnossl all         pqgosslcert 127.0.0.1/32          reject
+               hostssl   all         pqgossltest 127.0.0.1/32          trust
+               hostssl   all         pqgosslcert 127.0.0.1/32          cert
+               host      all         all         127.0.0.1/32          trust
+               hostnossl all         pqgossltest ::1/128               reject
+               hostnossl all         pqgosslcert ::1/128               reject
+               hostssl   all         pqgossltest ::1/128               trust
+               hostssl   all         pqgosslcert ::1/128               cert
+               host      all         all         ::1/128               trust
+       config
+
+       xargs sudo install -o postgres -g postgres -m 600 -t 
/var/lib/postgresql/$PGVERSION/main/ <<-certificates
+               certs/root.crt
+               certs/server.crt
+               certs/server.key
+       certificates
+
+       sort -VCu <<-versions ||
+               $PGVERSION
+               9.2
+       versions
+       sudo tee -a /etc/postgresql/$PGVERSION/main/postgresql.conf > /dev/null 
<<-config
+               ssl_ca_file   = 'root.crt'
+               ssl_cert_file = 'server.crt'
+               ssl_key_file  = 'server.key'
+       config
+
+       echo 127.0.0.1 postgres | sudo tee -a /etc/hosts > /dev/null
+
+       sudo service postgresql restart
+}
+
+postgresql_install() {
+       xargs sudo apt-get -y -o Dpkg::Options::='--force-confdef' -o 
Dpkg::Options::='--force-confnew' install <<-packages
+               postgresql-$PGVERSION
+               postgresql-server-dev-$PGVERSION
+               postgresql-contrib-$PGVERSION
+       packages
+}
+
+postgresql_uninstall() {
+       sudo service postgresql stop
+       xargs sudo apt-get -y --purge remove <<-packages
+               libpq-dev
+               libpq5
+               postgresql
+               postgresql-client-common
+               postgresql-common
+       packages
+       sudo rm -rf /var/lib/postgresql
+}
+
+$1

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/.travis.yml
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/.travis.yml 
b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/.travis.yml
new file mode 100644
index 0000000..1a4656c
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/.travis.yml
@@ -0,0 +1,45 @@
+language: go
+
+go:
+  - 1.5.x
+  - 1.6.x
+  - 1.7.x
+  - 1.8.x
+  - master
+
+sudo: true
+
+env:
+  global:
+    - PGUSER=postgres
+    - PQGOSSLTESTS=1
+    - PQSSLCERTTEST_PATH=$PWD/certs
+    - PGHOST=127.0.0.1
+  matrix:
+    - PGVERSION=9.6
+    - PGVERSION=9.5
+    - PGVERSION=9.4
+    - PGVERSION=9.3
+    - PGVERSION=9.2
+    - PGVERSION=9.1
+    - PGVERSION=9.0
+
+before_install:
+  - ./.travis.sh postgresql_uninstall
+  - ./.travis.sh pgdg_repository
+  - ./.travis.sh postgresql_install
+  - ./.travis.sh postgresql_configure
+  - ./.travis.sh client_configure
+  - go get golang.org/x/tools/cmd/goimports
+
+before_script:
+  - createdb pqgotest
+  - createuser -DRS pqgossltest
+  - createuser -DRS pqgosslcert
+
+script:
+  - >
+    goimports -d -e $(find -name '*.go') | awk '{ print } END { exit NR == 0 ? 
0 : 1 }'
+  - go vet ./...
+  - PQTEST_BINARY_PARAMETERS=no  go test -race -v ./...
+  - PQTEST_BINARY_PARAMETERS=yes go test -race -v ./...

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/CONTRIBUTING.md
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/CONTRIBUTING.md 
b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/CONTRIBUTING.md
new file mode 100644
index 0000000..84c937f
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/CONTRIBUTING.md
@@ -0,0 +1,29 @@
+## Contributing to pq
+
+`pq` has a backlog of pull requests, but contributions are still very
+much welcome. You can help with patch review, submitting bug reports,
+or adding new functionality. There is no formal style guide, but
+please conform to the style of existing code and general Go formatting
+conventions when submitting patches.
+
+### Patch review
+
+Help review existing open pull requests by commenting on the code or
+proposed functionality.
+
+### Bug reports
+
+We appreciate any bug reports, but especially ones with self-contained
+(doesn't depend on code outside of pq), minimal (can't be simplified
+further) test cases. It's especially helpful if you can submit a pull
+request with just the failing test case (you'll probably want to
+pattern it after the tests in
+[conn_test.go](https://github.com/lib/pq/blob/master/conn_test.go).
+
+### New functionality
+
+There are a number of pending patches for new functionality, so
+additional feature patches will take a while to merge. Still, patches
+are generally reviewed based on usefulness and complexity in addition
+to time-in-queue, so if you have a knockout idea, take a shot. Feel
+free to open an issue discussion your proposed patch beforehand.

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/LICENSE.md
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/LICENSE.md 
b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/LICENSE.md
new file mode 100644
index 0000000..5773904
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/LICENSE.md
@@ -0,0 +1,8 @@
+Copyright (c) 2011-2013, 'pq' Contributors
+Portions Copyright (C) 2011 Blake Mizerany
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
of this software and associated documentation files (the "Software"), to deal 
in the Software without restriction, including without limitation the rights to 
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
of the Software, and to permit persons to whom the Software is furnished to do 
so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all 
copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
SOFTWARE.

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/README.md
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/README.md 
b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/README.md
new file mode 100644
index 0000000..7670fc8
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/README.md
@@ -0,0 +1,105 @@
+# pq - A pure Go postgres driver for Go's database/sql package
+
+[![Build 
Status](https://travis-ci.org/lib/pq.svg?branch=master)](https://travis-ci.org/lib/pq)
+
+## Install
+
+       go get github.com/lib/pq
+
+## Docs
+
+For detailed documentation and basic usage examples, please see the package
+documentation at <http://godoc.org/github.com/lib/pq>.
+
+## Tests
+
+`go test` is used for testing.  A running PostgreSQL server is
+required, with the ability to log in.  The default database to connect
+to test with is "pqgotest," but it can be overridden using environment
+variables.
+
+Example:
+
+       PGHOST=/run/postgresql go test github.com/lib/pq
+
+Optionally, a benchmark suite can be run as part of the tests:
+
+       PGHOST=/run/postgresql go test -bench .
+
+## Features
+
+* SSL
+* Handles bad connections for `database/sql`
+* Scan `time.Time` correctly (i.e. `timestamp[tz]`, `time[tz]`, `date`)
+* Scan binary blobs correctly (i.e. `bytea`)
+* Package for `hstore` support
+* COPY FROM support
+* pq.ParseURL for converting urls to connection strings for sql.Open.
+* Many libpq compatible environment variables
+* Unix socket support
+* Notifications: `LISTEN`/`NOTIFY`
+* pgpass support
+
+## Future / Things you can help with
+
+* Better COPY FROM / COPY TO (see discussion in #181)
+
+## Thank you (alphabetical)
+
+Some of these contributors are from the original library `bmizerany/pq.go` 
whose
+code still exists in here.
+
+* Andy Balholm (andybalholm)
+* Ben Berkert (benburkert)
+* Benjamin Heatwole (bheatwole)
+* Bill Mill (llimllib)
+* Bjørn Madsen (aeons)
+* Blake Gentry (bgentry)
+* Brad Fitzpatrick (bradfitz)
+* Charlie Melbye (cmelbye)
+* Chris Bandy (cbandy)
+* Chris Gilling (cgilling)
+* Chris Walsh (cwds)
+* Dan Sosedoff (sosedoff)
+* Daniel Farina (fdr)
+* Eric Chlebek (echlebek)
+* Eric Garrido (minusnine)
+* Eric Urban (hydrogen18)
+* Everyone at The Go Team
+* Evan Shaw (edsrzf)
+* Ewan Chou (coocood)
+* Fazal Majid (fazalmajid)
+* Federico Romero (federomero)
+* Fumin (fumin)
+* Gary Burd (garyburd)
+* Heroku (heroku)
+* James Pozdena (jpoz)
+* Jason McVetta (jmcvetta)
+* Jeremy Jay (pbnjay)
+* Joakim Sernbrant (serbaut)
+* John Gallagher (jgallagher)
+* Jonathan Rudenberg (titanous)
+* Joël Stemmer (jstemmer)
+* Kamil Kisiel (kisielk)
+* Kelly Dunn (kellydunn)
+* Keith Rarick (kr)
+* Kir Shatrov (kirs)
+* Lann Martin (lann)
+* Maciek Sakrejda (uhoh-itsmaciek)
+* Marc Brinkmann (mbr)
+* Marko Tiikkaja (johto)
+* Matt Newberry (MattNewberry)
+* Matt Robenolt (mattrobenolt)
+* Martin Olsen (martinolsen)
+* Mike Lewis (mikelikespie)
+* Nicolas Patry (Narsil)
+* Oliver Tonnhofer (olt)
+* Patrick Hayes (phayes)
+* Paul Hammond (paulhammond)
+* Ryan Smith (ryandotsmith)
+* Samuel Stauffer (samuel)
+* Timothée Peignier (cyberdelia)
+* Travis Cline (tmc)
+* TruongSinh Tran-Nguyen (truongsinh)
+* Yaismel Miranda (ympons)
+* notedit (notedit)

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/array.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/array.go 
b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/array.go
new file mode 100644
index 0000000..e4933e2
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/array.go
@@ -0,0 +1,756 @@
+package pq
+
+import (
+       "bytes"
+       "database/sql"
+       "database/sql/driver"
+       "encoding/hex"
+       "fmt"
+       "reflect"
+       "strconv"
+       "strings"
+)
+
+var typeByteSlice = reflect.TypeOf([]byte{})
+var typeDriverValuer = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
+var typeSQLScanner = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
+
+// Array returns the optimal driver.Valuer and sql.Scanner for an array or
+// slice of any dimension.
+//
+// For example:
+//  db.Query(`SELECT * FROM t WHERE id = ANY($1)`, pq.Array([]int{235, 401}))
+//
+//  var x []sql.NullInt64
+//  db.QueryRow('SELECT ARRAY[235, 401]').Scan(pq.Array(&x))
+//
+// Scanning multi-dimensional arrays is not supported.  Arrays where the lower
+// bound is not one (such as `[0:0]={1}') are not supported.
+func Array(a interface{}) interface {
+       driver.Valuer
+       sql.Scanner
+} {
+       switch a := a.(type) {
+       case []bool:
+               return (*BoolArray)(&a)
+       case []float64:
+               return (*Float64Array)(&a)
+       case []int64:
+               return (*Int64Array)(&a)
+       case []string:
+               return (*StringArray)(&a)
+
+       case *[]bool:
+               return (*BoolArray)(a)
+       case *[]float64:
+               return (*Float64Array)(a)
+       case *[]int64:
+               return (*Int64Array)(a)
+       case *[]string:
+               return (*StringArray)(a)
+       }
+
+       return GenericArray{a}
+}
+
+// ArrayDelimiter may be optionally implemented by driver.Valuer or sql.Scanner
+// to override the array delimiter used by GenericArray.
+type ArrayDelimiter interface {
+       // ArrayDelimiter returns the delimiter character(s) for this element's 
type.
+       ArrayDelimiter() string
+}
+
+// BoolArray represents a one-dimensional array of the PostgreSQL boolean type.
+type BoolArray []bool
+
+// Scan implements the sql.Scanner interface.
+func (a *BoolArray) Scan(src interface{}) error {
+       switch src := src.(type) {
+       case []byte:
+               return a.scanBytes(src)
+       case string:
+               return a.scanBytes([]byte(src))
+       case nil:
+               *a = nil
+               return nil
+       }
+
+       return fmt.Errorf("pq: cannot convert %T to BoolArray", src)
+}
+
+func (a *BoolArray) scanBytes(src []byte) error {
+       elems, err := scanLinearArray(src, []byte{','}, "BoolArray")
+       if err != nil {
+               return err
+       }
+       if *a != nil && len(elems) == 0 {
+               *a = (*a)[:0]
+       } else {
+               b := make(BoolArray, len(elems))
+               for i, v := range elems {
+                       if len(v) != 1 {
+                               return fmt.Errorf("pq: could not parse boolean 
array index %d: invalid boolean %q", i, v)
+                       }
+                       switch v[0] {
+                       case 't':
+                               b[i] = true
+                       case 'f':
+                               b[i] = false
+                       default:
+                               return fmt.Errorf("pq: could not parse boolean 
array index %d: invalid boolean %q", i, v)
+                       }
+               }
+               *a = b
+       }
+       return nil
+}
+
+// Value implements the driver.Valuer interface.
+func (a BoolArray) Value() (driver.Value, error) {
+       if a == nil {
+               return nil, nil
+       }
+
+       if n := len(a); n > 0 {
+               // There will be exactly two curly brackets, N bytes of values,
+               // and N-1 bytes of delimiters.
+               b := make([]byte, 1+2*n)
+
+               for i := 0; i < n; i++ {
+                       b[2*i] = ','
+                       if a[i] {
+                               b[1+2*i] = 't'
+                       } else {
+                               b[1+2*i] = 'f'
+                       }
+               }
+
+               b[0] = '{'
+               b[2*n] = '}'
+
+               return string(b), nil
+       }
+
+       return "{}", nil
+}
+
+// ByteaArray represents a one-dimensional array of the PostgreSQL bytea type.
+type ByteaArray [][]byte
+
+// Scan implements the sql.Scanner interface.
+func (a *ByteaArray) Scan(src interface{}) error {
+       switch src := src.(type) {
+       case []byte:
+               return a.scanBytes(src)
+       case string:
+               return a.scanBytes([]byte(src))
+       case nil:
+               *a = nil
+               return nil
+       }
+
+       return fmt.Errorf("pq: cannot convert %T to ByteaArray", src)
+}
+
+func (a *ByteaArray) scanBytes(src []byte) error {
+       elems, err := scanLinearArray(src, []byte{','}, "ByteaArray")
+       if err != nil {
+               return err
+       }
+       if *a != nil && len(elems) == 0 {
+               *a = (*a)[:0]
+       } else {
+               b := make(ByteaArray, len(elems))
+               for i, v := range elems {
+                       b[i], err = parseBytea(v)
+                       if err != nil {
+                               return fmt.Errorf("could not parse bytea array 
index %d: %s", i, err.Error())
+                       }
+               }
+               *a = b
+       }
+       return nil
+}
+
+// Value implements the driver.Valuer interface. It uses the "hex" format which
+// is only supported on PostgreSQL 9.0 or newer.
+func (a ByteaArray) Value() (driver.Value, error) {
+       if a == nil {
+               return nil, nil
+       }
+
+       if n := len(a); n > 0 {
+               // There will be at least two curly brackets, 2*N bytes of 
quotes,
+               // 3*N bytes of hex formatting, and N-1 bytes of delimiters.
+               size := 1 + 6*n
+               for _, x := range a {
+                       size += hex.EncodedLen(len(x))
+               }
+
+               b := make([]byte, size)
+
+               for i, s := 0, b; i < n; i++ {
+                       o := copy(s, `,"\\x`)
+                       o += hex.Encode(s[o:], a[i])
+                       s[o] = '"'
+                       s = s[o+1:]
+               }
+
+               b[0] = '{'
+               b[size-1] = '}'
+
+               return string(b), nil
+       }
+
+       return "{}", nil
+}
+
+// Float64Array represents a one-dimensional array of the PostgreSQL double
+// precision type.
+type Float64Array []float64
+
+// Scan implements the sql.Scanner interface.
+func (a *Float64Array) Scan(src interface{}) error {
+       switch src := src.(type) {
+       case []byte:
+               return a.scanBytes(src)
+       case string:
+               return a.scanBytes([]byte(src))
+       case nil:
+               *a = nil
+               return nil
+       }
+
+       return fmt.Errorf("pq: cannot convert %T to Float64Array", src)
+}
+
+func (a *Float64Array) scanBytes(src []byte) error {
+       elems, err := scanLinearArray(src, []byte{','}, "Float64Array")
+       if err != nil {
+               return err
+       }
+       if *a != nil && len(elems) == 0 {
+               *a = (*a)[:0]
+       } else {
+               b := make(Float64Array, len(elems))
+               for i, v := range elems {
+                       if b[i], err = strconv.ParseFloat(string(v), 64); err 
!= nil {
+                               return fmt.Errorf("pq: parsing array element 
index %d: %v", i, err)
+                       }
+               }
+               *a = b
+       }
+       return nil
+}
+
+// Value implements the driver.Valuer interface.
+func (a Float64Array) Value() (driver.Value, error) {
+       if a == nil {
+               return nil, nil
+       }
+
+       if n := len(a); n > 0 {
+               // There will be at least two curly brackets, N bytes of values,
+               // and N-1 bytes of delimiters.
+               b := make([]byte, 1, 1+2*n)
+               b[0] = '{'
+
+               b = strconv.AppendFloat(b, a[0], 'f', -1, 64)
+               for i := 1; i < n; i++ {
+                       b = append(b, ',')
+                       b = strconv.AppendFloat(b, a[i], 'f', -1, 64)
+               }
+
+               return string(append(b, '}')), nil
+       }
+
+       return "{}", nil
+}
+
+// GenericArray implements the driver.Valuer and sql.Scanner interfaces for
+// an array or slice of any dimension.
+type GenericArray struct{ A interface{} }
+
+func (GenericArray) evaluateDestination(rt reflect.Type) (reflect.Type, 
func([]byte, reflect.Value) error, string) {
+       var assign func([]byte, reflect.Value) error
+       var del = ","
+
+       // TODO calculate the assign function for other types
+       // TODO repeat this section on the element type of arrays or slices 
(multidimensional)
+       {
+               if reflect.PtrTo(rt).Implements(typeSQLScanner) {
+                       // dest is always addressable because it is an element 
of a slice.
+                       assign = func(src []byte, dest reflect.Value) (err 
error) {
+                               ss := dest.Addr().Interface().(sql.Scanner)
+                               if src == nil {
+                                       err = ss.Scan(nil)
+                               } else {
+                                       err = ss.Scan(src)
+                               }
+                               return
+                       }
+                       goto FoundType
+               }
+
+               assign = func([]byte, reflect.Value) error {
+                       return fmt.Errorf("pq: scanning to %s is not 
implemented; only sql.Scanner", rt)
+               }
+       }
+
+FoundType:
+
+       if ad, ok := reflect.Zero(rt).Interface().(ArrayDelimiter); ok {
+               del = ad.ArrayDelimiter()
+       }
+
+       return rt, assign, del
+}
+
+// Scan implements the sql.Scanner interface.
+func (a GenericArray) Scan(src interface{}) error {
+       dpv := reflect.ValueOf(a.A)
+       switch {
+       case dpv.Kind() != reflect.Ptr:
+               return fmt.Errorf("pq: destination %T is not a pointer to array 
or slice", a.A)
+       case dpv.IsNil():
+               return fmt.Errorf("pq: destination %T is nil", a.A)
+       }
+
+       dv := dpv.Elem()
+       switch dv.Kind() {
+       case reflect.Slice:
+       case reflect.Array:
+       default:
+               return fmt.Errorf("pq: destination %T is not a pointer to array 
or slice", a.A)
+       }
+
+       switch src := src.(type) {
+       case []byte:
+               return a.scanBytes(src, dv)
+       case string:
+               return a.scanBytes([]byte(src), dv)
+       case nil:
+               if dv.Kind() == reflect.Slice {
+                       dv.Set(reflect.Zero(dv.Type()))
+                       return nil
+               }
+       }
+
+       return fmt.Errorf("pq: cannot convert %T to %s", src, dv.Type())
+}
+
+func (a GenericArray) scanBytes(src []byte, dv reflect.Value) error {
+       dtype, assign, del := a.evaluateDestination(dv.Type().Elem())
+       dims, elems, err := parseArray(src, []byte(del))
+       if err != nil {
+               return err
+       }
+
+       // TODO allow multidimensional
+
+       if len(dims) > 1 {
+               return fmt.Errorf("pq: scanning from multidimensional ARRAY%s 
is not implemented",
+                       strings.Replace(fmt.Sprint(dims), " ", "][", -1))
+       }
+
+       // Treat a zero-dimensional array like an array with a single dimension 
of zero.
+       if len(dims) == 0 {
+               dims = append(dims, 0)
+       }
+
+       for i, rt := 0, dv.Type(); i < len(dims); i, rt = i+1, rt.Elem() {
+               switch rt.Kind() {
+               case reflect.Slice:
+               case reflect.Array:
+                       if rt.Len() != dims[i] {
+                               return fmt.Errorf("pq: cannot convert ARRAY%s 
to %s",
+                                       strings.Replace(fmt.Sprint(dims), " ", 
"][", -1), dv.Type())
+                       }
+               default:
+                       // TODO handle multidimensional
+               }
+       }
+
+       values := reflect.MakeSlice(reflect.SliceOf(dtype), len(elems), 
len(elems))
+       for i, e := range elems {
+               if err := assign(e, values.Index(i)); err != nil {
+                       return fmt.Errorf("pq: parsing array element index %d: 
%v", i, err)
+               }
+       }
+
+       // TODO handle multidimensional
+
+       switch dv.Kind() {
+       case reflect.Slice:
+               dv.Set(values.Slice(0, dims[0]))
+       case reflect.Array:
+               for i := 0; i < dims[0]; i++ {
+                       dv.Index(i).Set(values.Index(i))
+               }
+       }
+
+       return nil
+}
+
+// Value implements the driver.Valuer interface.
+func (a GenericArray) Value() (driver.Value, error) {
+       if a.A == nil {
+               return nil, nil
+       }
+
+       rv := reflect.ValueOf(a.A)
+
+       switch rv.Kind() {
+       case reflect.Slice:
+               if rv.IsNil() {
+                       return nil, nil
+               }
+       case reflect.Array:
+       default:
+               return nil, fmt.Errorf("pq: Unable to convert %T to array", a.A)
+       }
+
+       if n := rv.Len(); n > 0 {
+               // There will be at least two curly brackets, N bytes of values,
+               // and N-1 bytes of delimiters.
+               b := make([]byte, 0, 1+2*n)
+
+               b, _, err := appendArray(b, rv, n)
+               return string(b), err
+       }
+
+       return "{}", nil
+}
+
+// Int64Array represents a one-dimensional array of the PostgreSQL integer 
types.
+type Int64Array []int64
+
+// Scan implements the sql.Scanner interface.
+func (a *Int64Array) Scan(src interface{}) error {
+       switch src := src.(type) {
+       case []byte:
+               return a.scanBytes(src)
+       case string:
+               return a.scanBytes([]byte(src))
+       case nil:
+               *a = nil
+               return nil
+       }
+
+       return fmt.Errorf("pq: cannot convert %T to Int64Array", src)
+}
+
+func (a *Int64Array) scanBytes(src []byte) error {
+       elems, err := scanLinearArray(src, []byte{','}, "Int64Array")
+       if err != nil {
+               return err
+       }
+       if *a != nil && len(elems) == 0 {
+               *a = (*a)[:0]
+       } else {
+               b := make(Int64Array, len(elems))
+               for i, v := range elems {
+                       if b[i], err = strconv.ParseInt(string(v), 10, 64); err 
!= nil {
+                               return fmt.Errorf("pq: parsing array element 
index %d: %v", i, err)
+                       }
+               }
+               *a = b
+       }
+       return nil
+}
+
+// Value implements the driver.Valuer interface.
+func (a Int64Array) Value() (driver.Value, error) {
+       if a == nil {
+               return nil, nil
+       }
+
+       if n := len(a); n > 0 {
+               // There will be at least two curly brackets, N bytes of values,
+               // and N-1 bytes of delimiters.
+               b := make([]byte, 1, 1+2*n)
+               b[0] = '{'
+
+               b = strconv.AppendInt(b, a[0], 10)
+               for i := 1; i < n; i++ {
+                       b = append(b, ',')
+                       b = strconv.AppendInt(b, a[i], 10)
+               }
+
+               return string(append(b, '}')), nil
+       }
+
+       return "{}", nil
+}
+
+// StringArray represents a one-dimensional array of the PostgreSQL character 
types.
+type StringArray []string
+
+// Scan implements the sql.Scanner interface.
+func (a *StringArray) Scan(src interface{}) error {
+       switch src := src.(type) {
+       case []byte:
+               return a.scanBytes(src)
+       case string:
+               return a.scanBytes([]byte(src))
+       case nil:
+               *a = nil
+               return nil
+       }
+
+       return fmt.Errorf("pq: cannot convert %T to StringArray", src)
+}
+
+func (a *StringArray) scanBytes(src []byte) error {
+       elems, err := scanLinearArray(src, []byte{','}, "StringArray")
+       if err != nil {
+               return err
+       }
+       if *a != nil && len(elems) == 0 {
+               *a = (*a)[:0]
+       } else {
+               b := make(StringArray, len(elems))
+               for i, v := range elems {
+                       if b[i] = string(v); v == nil {
+                               return fmt.Errorf("pq: parsing array element 
index %d: cannot convert nil to string", i)
+                       }
+               }
+               *a = b
+       }
+       return nil
+}
+
+// Value implements the driver.Valuer interface.
+func (a StringArray) Value() (driver.Value, error) {
+       if a == nil {
+               return nil, nil
+       }
+
+       if n := len(a); n > 0 {
+               // There will be at least two curly brackets, 2*N bytes of 
quotes,
+               // and N-1 bytes of delimiters.
+               b := make([]byte, 1, 1+3*n)
+               b[0] = '{'
+
+               b = appendArrayQuotedBytes(b, []byte(a[0]))
+               for i := 1; i < n; i++ {
+                       b = append(b, ',')
+                       b = appendArrayQuotedBytes(b, []byte(a[i]))
+               }
+
+               return string(append(b, '}')), nil
+       }
+
+       return "{}", nil
+}
+
+// appendArray appends rv to the buffer, returning the extended buffer and
+// the delimiter used between elements.
+//
+// It panics when n <= 0 or rv's Kind is not reflect.Array nor reflect.Slice.
+func appendArray(b []byte, rv reflect.Value, n int) ([]byte, string, error) {
+       var del string
+       var err error
+
+       b = append(b, '{')
+
+       if b, del, err = appendArrayElement(b, rv.Index(0)); err != nil {
+               return b, del, err
+       }
+
+       for i := 1; i < n; i++ {
+               b = append(b, del...)
+               if b, del, err = appendArrayElement(b, rv.Index(i)); err != nil 
{
+                       return b, del, err
+               }
+       }
+
+       return append(b, '}'), del, nil
+}
+
+// appendArrayElement appends rv to the buffer, returning the extended buffer
+// and the delimiter to use before the next element.
+//
+// When rv's Kind is neither reflect.Array nor reflect.Slice, it is converted
+// using driver.DefaultParameterConverter and the resulting []byte or string
+// is double-quoted.
+//
+// See http://www.postgresql.org/docs/current/static/arrays.html#ARRAYS-IO
+func appendArrayElement(b []byte, rv reflect.Value) ([]byte, string, error) {
+       if k := rv.Kind(); k == reflect.Array || k == reflect.Slice {
+               if t := rv.Type(); t != typeByteSlice && 
!t.Implements(typeDriverValuer) {
+                       if n := rv.Len(); n > 0 {
+                               return appendArray(b, rv, n)
+                       }
+
+                       return b, "", nil
+               }
+       }
+
+       var del = ","
+       var err error
+       var iv interface{} = rv.Interface()
+
+       if ad, ok := iv.(ArrayDelimiter); ok {
+               del = ad.ArrayDelimiter()
+       }
+
+       if iv, err = driver.DefaultParameterConverter.ConvertValue(iv); err != 
nil {
+               return b, del, err
+       }
+
+       switch v := iv.(type) {
+       case nil:
+               return append(b, "NULL"...), del, nil
+       case []byte:
+               return appendArrayQuotedBytes(b, v), del, nil
+       case string:
+               return appendArrayQuotedBytes(b, []byte(v)), del, nil
+       }
+
+       b, err = appendValue(b, iv)
+       return b, del, err
+}
+
+func appendArrayQuotedBytes(b, v []byte) []byte {
+       b = append(b, '"')
+       for {
+               i := bytes.IndexAny(v, `"\`)
+               if i < 0 {
+                       b = append(b, v...)
+                       break
+               }
+               if i > 0 {
+                       b = append(b, v[:i]...)
+               }
+               b = append(b, '\\', v[i])
+               v = v[i+1:]
+       }
+       return append(b, '"')
+}
+
+func appendValue(b []byte, v driver.Value) ([]byte, error) {
+       return append(b, encode(nil, v, 0)...), nil
+}
+
+// parseArray extracts the dimensions and elements of an array represented in
+// text format. Only representations emitted by the backend are supported.
+// Notably, whitespace around brackets and delimiters is significant, and NULL
+// is case-sensitive.
+//
+// See http://www.postgresql.org/docs/current/static/arrays.html#ARRAYS-IO
+func parseArray(src, del []byte) (dims []int, elems [][]byte, err error) {
+       var depth, i int
+
+       if len(src) < 1 || src[0] != '{' {
+               return nil, nil, fmt.Errorf("pq: unable to parse array; 
expected %q at offset %d", '{', 0)
+       }
+
+Open:
+       for i < len(src) {
+               switch src[i] {
+               case '{':
+                       depth++
+                       i++
+               case '}':
+                       elems = make([][]byte, 0)
+                       goto Close
+               default:
+                       break Open
+               }
+       }
+       dims = make([]int, i)
+
+Element:
+       for i < len(src) {
+               switch src[i] {
+               case '{':
+                       if depth == len(dims) {
+                               break Element
+                       }
+                       depth++
+                       dims[depth-1] = 0
+                       i++
+               case '"':
+                       var elem = []byte{}
+                       var escape bool
+                       for i++; i < len(src); i++ {
+                               if escape {
+                                       elem = append(elem, src[i])
+                                       escape = false
+                               } else {
+                                       switch src[i] {
+                                       default:
+                                               elem = append(elem, src[i])
+                                       case '\\':
+                                               escape = true
+                                       case '"':
+                                               elems = append(elems, elem)
+                                               i++
+                                               break Element
+                                       }
+                               }
+                       }
+               default:
+                       for start := i; i < len(src); i++ {
+                               if bytes.HasPrefix(src[i:], del) || src[i] == 
'}' {
+                                       elem := src[start:i]
+                                       if len(elem) == 0 {
+                                               return nil, nil, 
fmt.Errorf("pq: unable to parse array; unexpected %q at offset %d", src[i], i)
+                                       }
+                                       if bytes.Equal(elem, []byte("NULL")) {
+                                               elem = nil
+                                       }
+                                       elems = append(elems, elem)
+                                       break Element
+                               }
+                       }
+               }
+       }
+
+       for i < len(src) {
+               if bytes.HasPrefix(src[i:], del) && depth > 0 {
+                       dims[depth-1]++
+                       i += len(del)
+                       goto Element
+               } else if src[i] == '}' && depth > 0 {
+                       dims[depth-1]++
+                       depth--
+                       i++
+               } else {
+                       return nil, nil, fmt.Errorf("pq: unable to parse array; 
unexpected %q at offset %d", src[i], i)
+               }
+       }
+
+Close:
+       for i < len(src) {
+               if src[i] == '}' && depth > 0 {
+                       depth--
+                       i++
+               } else {
+                       return nil, nil, fmt.Errorf("pq: unable to parse array; 
unexpected %q at offset %d", src[i], i)
+               }
+       }
+       if depth > 0 {
+               err = fmt.Errorf("pq: unable to parse array; expected %q at 
offset %d", '}', i)
+       }
+       if err == nil {
+               for _, d := range dims {
+                       if (len(elems) % d) != 0 {
+                               err = fmt.Errorf("pq: multidimensional arrays 
must have elements with matching dimensions")
+                       }
+               }
+       }
+       return
+}
+
+func scanLinearArray(src, del []byte, typ string) (elems [][]byte, err error) {
+       dims, elems, err := parseArray(src, del)
+       if err != nil {
+               return nil, err
+       }
+       if len(dims) > 1 {
+               return nil, fmt.Errorf("pq: cannot convert ARRAY%s to %s", 
strings.Replace(fmt.Sprint(dims), " ", "][", -1), typ)
+       }
+       return elems, err
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/array_test.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/array_test.go 
b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/array_test.go
new file mode 100644
index 0000000..10b8431
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/array_test.go
@@ -0,0 +1,1317 @@
+package pq
+
+import (
+       "bytes"
+       "database/sql"
+       "database/sql/driver"
+       "math/rand"
+       "reflect"
+       "strings"
+       "testing"
+)
+
+func TestParseArray(t *testing.T) {
+       for _, tt := range []struct {
+               input string
+               delim string
+               dims  []int
+               elems [][]byte
+       }{
+               {`{}`, `,`, nil, [][]byte{}},
+               {`{NULL}`, `,`, []int{1}, [][]byte{nil}},
+               {`{a}`, `,`, []int{1}, [][]byte{{'a'}}},
+               {`{a,b}`, `,`, []int{2}, [][]byte{{'a'}, {'b'}}},
+               {`{{a,b}}`, `,`, []int{1, 2}, [][]byte{{'a'}, {'b'}}},
+               {`{{a},{b}}`, `,`, []int{2, 1}, [][]byte{{'a'}, {'b'}}},
+               {`{{{a,b},{c,d},{e,f}}}`, `,`, []int{1, 3, 2}, [][]byte{
+                       {'a'}, {'b'}, {'c'}, {'d'}, {'e'}, {'f'},
+               }},
+               {`{""}`, `,`, []int{1}, [][]byte{{}}},
+               {`{","}`, `,`, []int{1}, [][]byte{{','}}},
+               {`{",",","}`, `,`, []int{2}, [][]byte{{','}, {','}}},
+               {`{{",",","}}`, `,`, []int{1, 2}, [][]byte{{','}, {','}}},
+               {`{{","},{","}}`, `,`, []int{2, 1}, [][]byte{{','}, {','}}},
+               {`{{{",",","},{",",","},{",",","}}}`, `,`, []int{1, 3, 2}, 
[][]byte{
+                       {','}, {','}, {','}, {','}, {','}, {','},
+               }},
+               {`{"\"}"}`, `,`, []int{1}, [][]byte{{'"', '}'}}},
+               {`{"\"","\""}`, `,`, []int{2}, [][]byte{{'"'}, {'"'}}},
+               {`{{"\"","\""}}`, `,`, []int{1, 2}, [][]byte{{'"'}, {'"'}}},
+               {`{{"\""},{"\""}}`, `,`, []int{2, 1}, [][]byte{{'"'}, {'"'}}},
+               {`{{{"\"","\""},{"\"","\""},{"\"","\""}}}`, `,`, []int{1, 3, 
2}, [][]byte{
+                       {'"'}, {'"'}, {'"'}, {'"'}, {'"'}, {'"'},
+               }},
+               {`{axyzb}`, `xyz`, []int{2}, [][]byte{{'a'}, {'b'}}},
+       } {
+               dims, elems, err := parseArray([]byte(tt.input), 
[]byte(tt.delim))
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %q, got %q", tt.input, 
err)
+               }
+               if !reflect.DeepEqual(dims, tt.dims) {
+                       t.Errorf("Expected %v dimensions for %q, got %v", 
tt.dims, tt.input, dims)
+               }
+               if !reflect.DeepEqual(elems, tt.elems) {
+                       t.Errorf("Expected %v elements for %q, got %v", 
tt.elems, tt.input, elems)
+               }
+       }
+}
+
+func TestParseArrayError(t *testing.T) {
+       for _, tt := range []struct {
+               input, err string
+       }{
+               {``, "expected '{' at offset 0"},
+               {`x`, "expected '{' at offset 0"},
+               {`}`, "expected '{' at offset 0"},
+               {`{`, "expected '}' at offset 1"},
+               {`{{}`, "expected '}' at offset 3"},
+               {`{}}`, "unexpected '}' at offset 2"},
+               {`{,}`, "unexpected ',' at offset 1"},
+               {`{,x}`, "unexpected ',' at offset 1"},
+               {`{x,}`, "unexpected '}' at offset 3"},
+               {`{x,{`, "unexpected '{' at offset 3"},
+               {`{x},`, "unexpected ',' at offset 3"},
+               {`{x}}`, "unexpected '}' at offset 3"},
+               {`{{x}`, "expected '}' at offset 4"},
+               {`{""x}`, "unexpected 'x' at offset 3"},
+               {`{{a},{b,c}}`, "multidimensional arrays must have elements 
with matching dimensions"},
+       } {
+               _, _, err := parseArray([]byte(tt.input), []byte{','})
+
+               if err == nil {
+                       t.Fatalf("Expected error for %q, got none", tt.input)
+               }
+               if !strings.Contains(err.Error(), tt.err) {
+                       t.Errorf("Expected error to contain %q for %q, got %q", 
tt.err, tt.input, err)
+               }
+       }
+}
+
+func TestArrayScanner(t *testing.T) {
+       var s sql.Scanner
+
+       s = Array(&[]bool{})
+       if _, ok := s.(*BoolArray); !ok {
+               t.Errorf("Expected *BoolArray, got %T", s)
+       }
+
+       s = Array(&[]float64{})
+       if _, ok := s.(*Float64Array); !ok {
+               t.Errorf("Expected *Float64Array, got %T", s)
+       }
+
+       s = Array(&[]int64{})
+       if _, ok := s.(*Int64Array); !ok {
+               t.Errorf("Expected *Int64Array, got %T", s)
+       }
+
+       s = Array(&[]string{})
+       if _, ok := s.(*StringArray); !ok {
+               t.Errorf("Expected *StringArray, got %T", s)
+       }
+
+       for _, tt := range []interface{}{
+               &[]sql.Scanner{},
+               &[][]bool{},
+               &[][]float64{},
+               &[][]int64{},
+               &[][]string{},
+       } {
+               s = Array(tt)
+               if _, ok := s.(GenericArray); !ok {
+                       t.Errorf("Expected GenericArray for %T, got %T", tt, s)
+               }
+       }
+}
+
+func TestArrayValuer(t *testing.T) {
+       var v driver.Valuer
+
+       v = Array([]bool{})
+       if _, ok := v.(*BoolArray); !ok {
+               t.Errorf("Expected *BoolArray, got %T", v)
+       }
+
+       v = Array([]float64{})
+       if _, ok := v.(*Float64Array); !ok {
+               t.Errorf("Expected *Float64Array, got %T", v)
+       }
+
+       v = Array([]int64{})
+       if _, ok := v.(*Int64Array); !ok {
+               t.Errorf("Expected *Int64Array, got %T", v)
+       }
+
+       v = Array([]string{})
+       if _, ok := v.(*StringArray); !ok {
+               t.Errorf("Expected *StringArray, got %T", v)
+       }
+
+       for _, tt := range []interface{}{
+               nil,
+               []driver.Value{},
+               [][]bool{},
+               [][]float64{},
+               [][]int64{},
+               [][]string{},
+       } {
+               v = Array(tt)
+               if _, ok := v.(GenericArray); !ok {
+                       t.Errorf("Expected GenericArray for %T, got %T", tt, v)
+               }
+       }
+}
+
+func TestBoolArrayScanUnsupported(t *testing.T) {
+       var arr BoolArray
+       err := arr.Scan(1)
+
+       if err == nil {
+               t.Fatal("Expected error when scanning from int")
+       }
+       if !strings.Contains(err.Error(), "int to BoolArray") {
+               t.Errorf("Expected type to be mentioned when scanning, got %q", 
err)
+       }
+}
+
+func TestBoolArrayScanEmpty(t *testing.T) {
+       var arr BoolArray
+       err := arr.Scan(`{}`)
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if arr == nil || len(arr) != 0 {
+               t.Errorf("Expected empty, got %#v", arr)
+       }
+}
+
+func TestBoolArrayScanNil(t *testing.T) {
+       arr := BoolArray{true, true, true}
+       err := arr.Scan(nil)
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if arr != nil {
+               t.Errorf("Expected nil, got %+v", arr)
+       }
+}
+
+var BoolArrayStringTests = []struct {
+       str string
+       arr BoolArray
+}{
+       {`{}`, BoolArray{}},
+       {`{t}`, BoolArray{true}},
+       {`{f,t}`, BoolArray{false, true}},
+}
+
+func TestBoolArrayScanBytes(t *testing.T) {
+       for _, tt := range BoolArrayStringTests {
+               bytes := []byte(tt.str)
+               arr := BoolArray{true, true, true}
+               err := arr.Scan(bytes)
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %q, got %v", bytes, err)
+               }
+               if !reflect.DeepEqual(arr, tt.arr) {
+                       t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, 
arr)
+               }
+       }
+}
+
+func BenchmarkBoolArrayScanBytes(b *testing.B) {
+       var a BoolArray
+       var x interface{} = []byte(`{t,f,t,f,t,f,t,f,t,f}`)
+
+       for i := 0; i < b.N; i++ {
+               a = BoolArray{}
+               a.Scan(x)
+       }
+}
+
+func TestBoolArrayScanString(t *testing.T) {
+       for _, tt := range BoolArrayStringTests {
+               arr := BoolArray{true, true, true}
+               err := arr.Scan(tt.str)
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %q, got %v", tt.str, 
err)
+               }
+               if !reflect.DeepEqual(arr, tt.arr) {
+                       t.Errorf("Expected %+v for %q, got %+v", tt.arr, 
tt.str, arr)
+               }
+       }
+}
+
+func TestBoolArrayScanError(t *testing.T) {
+       for _, tt := range []struct {
+               input, err string
+       }{
+               {``, "unable to parse array"},
+               {`{`, "unable to parse array"},
+               {`{{t},{f}}`, "cannot convert ARRAY[2][1] to BoolArray"},
+               {`{NULL}`, `could not parse boolean array index 0: invalid 
boolean ""`},
+               {`{a}`, `could not parse boolean array index 0: invalid boolean 
"a"`},
+               {`{t,b}`, `could not parse boolean array index 1: invalid 
boolean "b"`},
+               {`{t,f,cd}`, `could not parse boolean array index 2: invalid 
boolean "cd"`},
+       } {
+               arr := BoolArray{true, true, true}
+               err := arr.Scan(tt.input)
+
+               if err == nil {
+                       t.Fatalf("Expected error for %q, got none", tt.input)
+               }
+               if !strings.Contains(err.Error(), tt.err) {
+                       t.Errorf("Expected error to contain %q for %q, got %q", 
tt.err, tt.input, err)
+               }
+               if !reflect.DeepEqual(arr, BoolArray{true, true, true}) {
+                       t.Errorf("Expected destination not to change for %q, 
got %+v", tt.input, arr)
+               }
+       }
+}
+
+func TestBoolArrayValue(t *testing.T) {
+       result, err := BoolArray(nil).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error for nil, got %v", err)
+       }
+       if result != nil {
+               t.Errorf("Expected nil, got %q", result)
+       }
+
+       result, err = BoolArray([]bool{}).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error for empty, got %v", err)
+       }
+       if expected := `{}`; !reflect.DeepEqual(result, expected) {
+               t.Errorf("Expected empty, got %q", result)
+       }
+
+       result, err = BoolArray([]bool{false, true, false}).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if expected := `{f,t,f}`; !reflect.DeepEqual(result, expected) {
+               t.Errorf("Expected %q, got %q", expected, result)
+       }
+}
+
+func BenchmarkBoolArrayValue(b *testing.B) {
+       rand.Seed(1)
+       x := make([]bool, 10)
+       for i := 0; i < len(x); i++ {
+               x[i] = rand.Intn(2) == 0
+       }
+       a := BoolArray(x)
+
+       for i := 0; i < b.N; i++ {
+               a.Value()
+       }
+}
+
+func TestByteaArrayScanUnsupported(t *testing.T) {
+       var arr ByteaArray
+       err := arr.Scan(1)
+
+       if err == nil {
+               t.Fatal("Expected error when scanning from int")
+       }
+       if !strings.Contains(err.Error(), "int to ByteaArray") {
+               t.Errorf("Expected type to be mentioned when scanning, got %q", 
err)
+       }
+}
+
+func TestByteaArrayScanEmpty(t *testing.T) {
+       var arr ByteaArray
+       err := arr.Scan(`{}`)
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if arr == nil || len(arr) != 0 {
+               t.Errorf("Expected empty, got %#v", arr)
+       }
+}
+
+func TestByteaArrayScanNil(t *testing.T) {
+       arr := ByteaArray{{2}, {6}, {0, 0}}
+       err := arr.Scan(nil)
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if arr != nil {
+               t.Errorf("Expected nil, got %+v", arr)
+       }
+}
+
+var ByteaArrayStringTests = []struct {
+       str string
+       arr ByteaArray
+}{
+       {`{}`, ByteaArray{}},
+       {`{NULL}`, ByteaArray{nil}},
+       {`{"\\xfeff"}`, ByteaArray{{'\xFE', '\xFF'}}},
+       {`{"\\xdead","\\xbeef"}`, ByteaArray{{'\xDE', '\xAD'}, {'\xBE', 
'\xEF'}}},
+}
+
+func TestByteaArrayScanBytes(t *testing.T) {
+       for _, tt := range ByteaArrayStringTests {
+               bytes := []byte(tt.str)
+               arr := ByteaArray{{2}, {6}, {0, 0}}
+               err := arr.Scan(bytes)
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %q, got %v", bytes, err)
+               }
+               if !reflect.DeepEqual(arr, tt.arr) {
+                       t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, 
arr)
+               }
+       }
+}
+
+func BenchmarkByteaArrayScanBytes(b *testing.B) {
+       var a ByteaArray
+       var x interface{} = 
[]byte(`{"\\xfe","\\xff","\\xdead","\\xbeef","\\xfe","\\xff","\\xdead","\\xbeef","\\xfe","\\xff"}`)
+
+       for i := 0; i < b.N; i++ {
+               a = ByteaArray{}
+               a.Scan(x)
+       }
+}
+
+func TestByteaArrayScanString(t *testing.T) {
+       for _, tt := range ByteaArrayStringTests {
+               arr := ByteaArray{{2}, {6}, {0, 0}}
+               err := arr.Scan(tt.str)
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %q, got %v", tt.str, 
err)
+               }
+               if !reflect.DeepEqual(arr, tt.arr) {
+                       t.Errorf("Expected %+v for %q, got %+v", tt.arr, 
tt.str, arr)
+               }
+       }
+}
+
+func TestByteaArrayScanError(t *testing.T) {
+       for _, tt := range []struct {
+               input, err string
+       }{
+               {``, "unable to parse array"},
+               {`{`, "unable to parse array"},
+               {`{{"\\xfeff"},{"\\xbeef"}}`, "cannot convert ARRAY[2][1] to 
ByteaArray"},
+               {`{"\\abc"}`, "could not parse bytea array index 0: could not 
parse bytea value"},
+       } {
+               arr := ByteaArray{{2}, {6}, {0, 0}}
+               err := arr.Scan(tt.input)
+
+               if err == nil {
+                       t.Fatalf("Expected error for %q, got none", tt.input)
+               }
+               if !strings.Contains(err.Error(), tt.err) {
+                       t.Errorf("Expected error to contain %q for %q, got %q", 
tt.err, tt.input, err)
+               }
+               if !reflect.DeepEqual(arr, ByteaArray{{2}, {6}, {0, 0}}) {
+                       t.Errorf("Expected destination not to change for %q, 
got %+v", tt.input, arr)
+               }
+       }
+}
+
+func TestByteaArrayValue(t *testing.T) {
+       result, err := ByteaArray(nil).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error for nil, got %v", err)
+       }
+       if result != nil {
+               t.Errorf("Expected nil, got %q", result)
+       }
+
+       result, err = ByteaArray([][]byte{}).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error for empty, got %v", err)
+       }
+       if expected := `{}`; !reflect.DeepEqual(result, expected) {
+               t.Errorf("Expected empty, got %q", result)
+       }
+
+       result, err = ByteaArray([][]byte{{'\xDE', '\xAD', '\xBE', '\xEF'}, 
{'\xFE', '\xFF'}, {}}).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if expected := `{"\\xdeadbeef","\\xfeff","\\x"}`; 
!reflect.DeepEqual(result, expected) {
+               t.Errorf("Expected %q, got %q", expected, result)
+       }
+}
+
+func BenchmarkByteaArrayValue(b *testing.B) {
+       rand.Seed(1)
+       x := make([][]byte, 10)
+       for i := 0; i < len(x); i++ {
+               x[i] = make([]byte, len(x))
+               for j := 0; j < len(x); j++ {
+                       x[i][j] = byte(rand.Int())
+               }
+       }
+       a := ByteaArray(x)
+
+       for i := 0; i < b.N; i++ {
+               a.Value()
+       }
+}
+
+func TestFloat64ArrayScanUnsupported(t *testing.T) {
+       var arr Float64Array
+       err := arr.Scan(true)
+
+       if err == nil {
+               t.Fatal("Expected error when scanning from bool")
+       }
+       if !strings.Contains(err.Error(), "bool to Float64Array") {
+               t.Errorf("Expected type to be mentioned when scanning, got %q", 
err)
+       }
+}
+
+func TestFloat64ArrayScanEmpty(t *testing.T) {
+       var arr Float64Array
+       err := arr.Scan(`{}`)
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if arr == nil || len(arr) != 0 {
+               t.Errorf("Expected empty, got %#v", arr)
+       }
+}
+
+func TestFloat64ArrayScanNil(t *testing.T) {
+       arr := Float64Array{5, 5, 5}
+       err := arr.Scan(nil)
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if arr != nil {
+               t.Errorf("Expected nil, got %+v", arr)
+       }
+}
+
+var Float64ArrayStringTests = []struct {
+       str string
+       arr Float64Array
+}{
+       {`{}`, Float64Array{}},
+       {`{1.2}`, Float64Array{1.2}},
+       {`{3.456,7.89}`, Float64Array{3.456, 7.89}},
+       {`{3,1,2}`, Float64Array{3, 1, 2}},
+}
+
+func TestFloat64ArrayScanBytes(t *testing.T) {
+       for _, tt := range Float64ArrayStringTests {
+               bytes := []byte(tt.str)
+               arr := Float64Array{5, 5, 5}
+               err := arr.Scan(bytes)
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %q, got %v", bytes, err)
+               }
+               if !reflect.DeepEqual(arr, tt.arr) {
+                       t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, 
arr)
+               }
+       }
+}
+
+func BenchmarkFloat64ArrayScanBytes(b *testing.B) {
+       var a Float64Array
+       var x interface{} = 
[]byte(`{1.2,3.4,5.6,7.8,9.01,2.34,5.67,8.90,1.234,5.678}`)
+
+       for i := 0; i < b.N; i++ {
+               a = Float64Array{}
+               a.Scan(x)
+       }
+}
+
+func TestFloat64ArrayScanString(t *testing.T) {
+       for _, tt := range Float64ArrayStringTests {
+               arr := Float64Array{5, 5, 5}
+               err := arr.Scan(tt.str)
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %q, got %v", tt.str, 
err)
+               }
+               if !reflect.DeepEqual(arr, tt.arr) {
+                       t.Errorf("Expected %+v for %q, got %+v", tt.arr, 
tt.str, arr)
+               }
+       }
+}
+
+func TestFloat64ArrayScanError(t *testing.T) {
+       for _, tt := range []struct {
+               input, err string
+       }{
+               {``, "unable to parse array"},
+               {`{`, "unable to parse array"},
+               {`{{5.6},{7.8}}`, "cannot convert ARRAY[2][1] to Float64Array"},
+               {`{NULL}`, "parsing array element index 0:"},
+               {`{a}`, "parsing array element index 0:"},
+               {`{5.6,a}`, "parsing array element index 1:"},
+               {`{5.6,7.8,a}`, "parsing array element index 2:"},
+       } {
+               arr := Float64Array{5, 5, 5}
+               err := arr.Scan(tt.input)
+
+               if err == nil {
+                       t.Fatalf("Expected error for %q, got none", tt.input)
+               }
+               if !strings.Contains(err.Error(), tt.err) {
+                       t.Errorf("Expected error to contain %q for %q, got %q", 
tt.err, tt.input, err)
+               }
+               if !reflect.DeepEqual(arr, Float64Array{5, 5, 5}) {
+                       t.Errorf("Expected destination not to change for %q, 
got %+v", tt.input, arr)
+               }
+       }
+}
+
+func TestFloat64ArrayValue(t *testing.T) {
+       result, err := Float64Array(nil).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error for nil, got %v", err)
+       }
+       if result != nil {
+               t.Errorf("Expected nil, got %q", result)
+       }
+
+       result, err = Float64Array([]float64{}).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error for empty, got %v", err)
+       }
+       if expected := `{}`; !reflect.DeepEqual(result, expected) {
+               t.Errorf("Expected empty, got %q", result)
+       }
+
+       result, err = Float64Array([]float64{1.2, 3.4, 5.6}).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if expected := `{1.2,3.4,5.6}`; !reflect.DeepEqual(result, expected) {
+               t.Errorf("Expected %q, got %q", expected, result)
+       }
+}
+
+func BenchmarkFloat64ArrayValue(b *testing.B) {
+       rand.Seed(1)
+       x := make([]float64, 10)
+       for i := 0; i < len(x); i++ {
+               x[i] = rand.NormFloat64()
+       }
+       a := Float64Array(x)
+
+       for i := 0; i < b.N; i++ {
+               a.Value()
+       }
+}
+
+func TestInt64ArrayScanUnsupported(t *testing.T) {
+       var arr Int64Array
+       err := arr.Scan(true)
+
+       if err == nil {
+               t.Fatal("Expected error when scanning from bool")
+       }
+       if !strings.Contains(err.Error(), "bool to Int64Array") {
+               t.Errorf("Expected type to be mentioned when scanning, got %q", 
err)
+       }
+}
+
+func TestInt64ArrayScanEmpty(t *testing.T) {
+       var arr Int64Array
+       err := arr.Scan(`{}`)
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if arr == nil || len(arr) != 0 {
+               t.Errorf("Expected empty, got %#v", arr)
+       }
+}
+
+func TestInt64ArrayScanNil(t *testing.T) {
+       arr := Int64Array{5, 5, 5}
+       err := arr.Scan(nil)
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if arr != nil {
+               t.Errorf("Expected nil, got %+v", arr)
+       }
+}
+
+var Int64ArrayStringTests = []struct {
+       str string
+       arr Int64Array
+}{
+       {`{}`, Int64Array{}},
+       {`{12}`, Int64Array{12}},
+       {`{345,678}`, Int64Array{345, 678}},
+}
+
+func TestInt64ArrayScanBytes(t *testing.T) {
+       for _, tt := range Int64ArrayStringTests {
+               bytes := []byte(tt.str)
+               arr := Int64Array{5, 5, 5}
+               err := arr.Scan(bytes)
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %q, got %v", bytes, err)
+               }
+               if !reflect.DeepEqual(arr, tt.arr) {
+                       t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, 
arr)
+               }
+       }
+}
+
+func BenchmarkInt64ArrayScanBytes(b *testing.B) {
+       var a Int64Array
+       var x interface{} = []byte(`{1,2,3,4,5,6,7,8,9,0}`)
+
+       for i := 0; i < b.N; i++ {
+               a = Int64Array{}
+               a.Scan(x)
+       }
+}
+
+func TestInt64ArrayScanString(t *testing.T) {
+       for _, tt := range Int64ArrayStringTests {
+               arr := Int64Array{5, 5, 5}
+               err := arr.Scan(tt.str)
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %q, got %v", tt.str, 
err)
+               }
+               if !reflect.DeepEqual(arr, tt.arr) {
+                       t.Errorf("Expected %+v for %q, got %+v", tt.arr, 
tt.str, arr)
+               }
+       }
+}
+
+func TestInt64ArrayScanError(t *testing.T) {
+       for _, tt := range []struct {
+               input, err string
+       }{
+               {``, "unable to parse array"},
+               {`{`, "unable to parse array"},
+               {`{{5},{6}}`, "cannot convert ARRAY[2][1] to Int64Array"},
+               {`{NULL}`, "parsing array element index 0:"},
+               {`{a}`, "parsing array element index 0:"},
+               {`{5,a}`, "parsing array element index 1:"},
+               {`{5,6,a}`, "parsing array element index 2:"},
+       } {
+               arr := Int64Array{5, 5, 5}
+               err := arr.Scan(tt.input)
+
+               if err == nil {
+                       t.Fatalf("Expected error for %q, got none", tt.input)
+               }
+               if !strings.Contains(err.Error(), tt.err) {
+                       t.Errorf("Expected error to contain %q for %q, got %q", 
tt.err, tt.input, err)
+               }
+               if !reflect.DeepEqual(arr, Int64Array{5, 5, 5}) {
+                       t.Errorf("Expected destination not to change for %q, 
got %+v", tt.input, arr)
+               }
+       }
+}
+
+func TestInt64ArrayValue(t *testing.T) {
+       result, err := Int64Array(nil).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error for nil, got %v", err)
+       }
+       if result != nil {
+               t.Errorf("Expected nil, got %q", result)
+       }
+
+       result, err = Int64Array([]int64{}).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error for empty, got %v", err)
+       }
+       if expected := `{}`; !reflect.DeepEqual(result, expected) {
+               t.Errorf("Expected empty, got %q", result)
+       }
+
+       result, err = Int64Array([]int64{1, 2, 3}).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if expected := `{1,2,3}`; !reflect.DeepEqual(result, expected) {
+               t.Errorf("Expected %q, got %q", expected, result)
+       }
+}
+
+func BenchmarkInt64ArrayValue(b *testing.B) {
+       rand.Seed(1)
+       x := make([]int64, 10)
+       for i := 0; i < len(x); i++ {
+               x[i] = rand.Int63()
+       }
+       a := Int64Array(x)
+
+       for i := 0; i < b.N; i++ {
+               a.Value()
+       }
+}
+
+func TestStringArrayScanUnsupported(t *testing.T) {
+       var arr StringArray
+       err := arr.Scan(true)
+
+       if err == nil {
+               t.Fatal("Expected error when scanning from bool")
+       }
+       if !strings.Contains(err.Error(), "bool to StringArray") {
+               t.Errorf("Expected type to be mentioned when scanning, got %q", 
err)
+       }
+}
+
+func TestStringArrayScanEmpty(t *testing.T) {
+       var arr StringArray
+       err := arr.Scan(`{}`)
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if arr == nil || len(arr) != 0 {
+               t.Errorf("Expected empty, got %#v", arr)
+       }
+}
+
+func TestStringArrayScanNil(t *testing.T) {
+       arr := StringArray{"x", "x", "x"}
+       err := arr.Scan(nil)
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if arr != nil {
+               t.Errorf("Expected nil, got %+v", arr)
+       }
+}
+
+var StringArrayStringTests = []struct {
+       str string
+       arr StringArray
+}{
+       {`{}`, StringArray{}},
+       {`{t}`, StringArray{"t"}},
+       {`{f,1}`, StringArray{"f", "1"}},
+       {`{"a\\b","c d",","}`, StringArray{"a\\b", "c d", ","}},
+}
+
+func TestStringArrayScanBytes(t *testing.T) {
+       for _, tt := range StringArrayStringTests {
+               bytes := []byte(tt.str)
+               arr := StringArray{"x", "x", "x"}
+               err := arr.Scan(bytes)
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %q, got %v", bytes, err)
+               }
+               if !reflect.DeepEqual(arr, tt.arr) {
+                       t.Errorf("Expected %+v for %q, got %+v", tt.arr, bytes, 
arr)
+               }
+       }
+}
+
+func BenchmarkStringArrayScanBytes(b *testing.B) {
+       var a StringArray
+       var x interface{} = []byte(`{a,b,c,d,e,f,g,h,i,j}`)
+       var y interface{} = 
[]byte(`{"\a","\b","\c","\d","\e","\f","\g","\h","\i","\j"}`)
+
+       for i := 0; i < b.N; i++ {
+               a = StringArray{}
+               a.Scan(x)
+               a = StringArray{}
+               a.Scan(y)
+       }
+}
+
+func TestStringArrayScanString(t *testing.T) {
+       for _, tt := range StringArrayStringTests {
+               arr := StringArray{"x", "x", "x"}
+               err := arr.Scan(tt.str)
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %q, got %v", tt.str, 
err)
+               }
+               if !reflect.DeepEqual(arr, tt.arr) {
+                       t.Errorf("Expected %+v for %q, got %+v", tt.arr, 
tt.str, arr)
+               }
+       }
+}
+
+func TestStringArrayScanError(t *testing.T) {
+       for _, tt := range []struct {
+               input, err string
+       }{
+               {``, "unable to parse array"},
+               {`{`, "unable to parse array"},
+               {`{{a},{b}}`, "cannot convert ARRAY[2][1] to StringArray"},
+               {`{NULL}`, "parsing array element index 0: cannot convert nil 
to string"},
+               {`{a,NULL}`, "parsing array element index 1: cannot convert nil 
to string"},
+               {`{a,b,NULL}`, "parsing array element index 2: cannot convert 
nil to string"},
+       } {
+               arr := StringArray{"x", "x", "x"}
+               err := arr.Scan(tt.input)
+
+               if err == nil {
+                       t.Fatalf("Expected error for %q, got none", tt.input)
+               }
+               if !strings.Contains(err.Error(), tt.err) {
+                       t.Errorf("Expected error to contain %q for %q, got %q", 
tt.err, tt.input, err)
+               }
+               if !reflect.DeepEqual(arr, StringArray{"x", "x", "x"}) {
+                       t.Errorf("Expected destination not to change for %q, 
got %+v", tt.input, arr)
+               }
+       }
+}
+
+func TestStringArrayValue(t *testing.T) {
+       result, err := StringArray(nil).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error for nil, got %v", err)
+       }
+       if result != nil {
+               t.Errorf("Expected nil, got %q", result)
+       }
+
+       result, err = StringArray([]string{}).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error for empty, got %v", err)
+       }
+       if expected := `{}`; !reflect.DeepEqual(result, expected) {
+               t.Errorf("Expected empty, got %q", result)
+       }
+
+       result, err = StringArray([]string{`a`, `\b`, `c"`, `d,e`}).Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if expected := `{"a","\\b","c\"","d,e"}`; !reflect.DeepEqual(result, 
expected) {
+               t.Errorf("Expected %q, got %q", expected, result)
+       }
+}
+
+func BenchmarkStringArrayValue(b *testing.B) {
+       x := make([]string, 10)
+       for i := 0; i < len(x); i++ {
+               x[i] = strings.Repeat(`abc"def\ghi`, 5)
+       }
+       a := StringArray(x)
+
+       for i := 0; i < b.N; i++ {
+               a.Value()
+       }
+}
+
+func TestGenericArrayScanUnsupported(t *testing.T) {
+       var s string
+       var ss []string
+       var nsa [1]sql.NullString
+
+       for _, tt := range []struct {
+               src, dest interface{}
+               err       string
+       }{
+               {nil, nil, "destination <nil> is not a pointer to array or 
slice"},
+               {nil, true, "destination bool is not a pointer to array or 
slice"},
+               {nil, &s, "destination *string is not a pointer to array or 
slice"},
+               {nil, ss, "destination []string is not a pointer to array or 
slice"},
+               {nil, &nsa, "<nil> to [1]sql.NullString"},
+               {true, &ss, "bool to []string"},
+               {`{{x}}`, &ss, "multidimensional ARRAY[1][1] is not 
implemented"},
+               {`{{x},{x}}`, &ss, "multidimensional ARRAY[2][1] is not 
implemented"},
+               {`{x}`, &ss, "scanning to string is not implemented"},
+       } {
+               err := GenericArray{tt.dest}.Scan(tt.src)
+
+               if err == nil {
+                       t.Fatalf("Expected error for [%#v %#v]", tt.src, 
tt.dest)
+               }
+               if !strings.Contains(err.Error(), tt.err) {
+                       t.Errorf("Expected error to contain %q for [%#v %#v], 
got %q", tt.err, tt.src, tt.dest, err)
+               }
+       }
+}
+
+func TestGenericArrayScanScannerArrayBytes(t *testing.T) {
+       src, expected, nsa := []byte(`{NULL,abc,"\""}`),
+               [3]sql.NullString{{}, {String: `abc`, Valid: true}, {String: 
`"`, Valid: true}},
+               [3]sql.NullString{{String: ``, Valid: true}, {}, {}}
+
+       if err := (GenericArray{&nsa}).Scan(src); err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if !reflect.DeepEqual(nsa, expected) {
+               t.Errorf("Expected %v, got %v", expected, nsa)
+       }
+}
+
+func TestGenericArrayScanScannerArrayString(t *testing.T) {
+       src, expected, nsa := `{NULL,"\"",xyz}`,
+               [3]sql.NullString{{}, {String: `"`, Valid: true}, {String: 
`xyz`, Valid: true}},
+               [3]sql.NullString{{String: ``, Valid: true}, {}, {}}
+
+       if err := (GenericArray{&nsa}).Scan(src); err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if !reflect.DeepEqual(nsa, expected) {
+               t.Errorf("Expected %v, got %v", expected, nsa)
+       }
+}
+
+func TestGenericArrayScanScannerSliceEmpty(t *testing.T) {
+       var nss []sql.NullString
+
+       if err := (GenericArray{&nss}).Scan(`{}`); err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if nss == nil || len(nss) != 0 {
+               t.Errorf("Expected empty, got %#v", nss)
+       }
+}
+
+func TestGenericArrayScanScannerSliceNil(t *testing.T) {
+       nss := []sql.NullString{{String: ``, Valid: true}, {}}
+
+       if err := (GenericArray{&nss}).Scan(nil); err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if nss != nil {
+               t.Errorf("Expected nil, got %+v", nss)
+       }
+}
+
+func TestGenericArrayScanScannerSliceBytes(t *testing.T) {
+       src, expected, nss := []byte(`{NULL,abc,"\""}`),
+               []sql.NullString{{}, {String: `abc`, Valid: true}, {String: 
`"`, Valid: true}},
+               []sql.NullString{{String: ``, Valid: true}, {}, {}, {}, {}}
+
+       if err := (GenericArray{&nss}).Scan(src); err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if !reflect.DeepEqual(nss, expected) {
+               t.Errorf("Expected %v, got %v", expected, nss)
+       }
+}
+
+func BenchmarkGenericArrayScanScannerSliceBytes(b *testing.B) {
+       var a GenericArray
+       var x interface{} = []byte(`{a,b,c,d,e,f,g,h,i,j}`)
+       var y interface{} = 
[]byte(`{"\a","\b","\c","\d","\e","\f","\g","\h","\i","\j"}`)
+
+       for i := 0; i < b.N; i++ {
+               a = GenericArray{new([]sql.NullString)}
+               a.Scan(x)
+               a = GenericArray{new([]sql.NullString)}
+               a.Scan(y)
+       }
+}
+
+func TestGenericArrayScanScannerSliceString(t *testing.T) {
+       src, expected, nss := `{NULL,"\"",xyz}`,
+               []sql.NullString{{}, {String: `"`, Valid: true}, {String: 
`xyz`, Valid: true}},
+               []sql.NullString{{String: ``, Valid: true}, {}, {}}
+
+       if err := (GenericArray{&nss}).Scan(src); err != nil {
+               t.Fatalf("Expected no error, got %v", err)
+       }
+       if !reflect.DeepEqual(nss, expected) {
+               t.Errorf("Expected %v, got %v", expected, nss)
+       }
+}
+
+type TildeNullInt64 struct{ sql.NullInt64 }
+
+func (TildeNullInt64) ArrayDelimiter() string { return "~" }
+
+func TestGenericArrayScanDelimiter(t *testing.T) {
+       src, expected, tnis := `{12~NULL~76}`,
+               []TildeNullInt64{{sql.NullInt64{Int64: 12, Valid: true}}, {}, 
{sql.NullInt64{Int64: 76, Valid: true}}},
+               []TildeNullInt64{{sql.NullInt64{Int64: 0, Valid: true}}, {}}
+
+       if err := (GenericArray{&tnis}).Scan(src); err != nil {
+               t.Fatalf("Expected no error for %#v, got %v", src, err)
+       }
+       if !reflect.DeepEqual(tnis, expected) {
+               t.Errorf("Expected %v for %#v, got %v", expected, src, tnis)
+       }
+}
+
+func TestGenericArrayScanErrors(t *testing.T) {
+       var sa [1]string
+       var nis []sql.NullInt64
+       var pss *[]string
+
+       for _, tt := range []struct {
+               src, dest interface{}
+               err       string
+       }{
+               {nil, pss, "destination *[]string is nil"},
+               {`{`, &sa, "unable to parse"},
+               {`{}`, &sa, "cannot convert ARRAY[0] to [1]string"},
+               {`{x,x}`, &sa, "cannot convert ARRAY[2] to [1]string"},
+               {`{x}`, &nis, `parsing array element index 0: converting`},
+       } {
+               err := GenericArray{tt.dest}.Scan(tt.src)
+
+               if err == nil {
+                       t.Fatalf("Expected error for [%#v %#v]", tt.src, 
tt.dest)
+               }
+               if !strings.Contains(err.Error(), tt.err) {
+                       t.Errorf("Expected error to contain %q for [%#v %#v], 
got %q", tt.err, tt.src, tt.dest, err)
+               }
+       }
+}
+
+func TestGenericArrayValueUnsupported(t *testing.T) {
+       _, err := GenericArray{true}.Value()
+
+       if err == nil {
+               t.Fatal("Expected error for bool")
+       }
+       if !strings.Contains(err.Error(), "bool to array") {
+               t.Errorf("Expected type to be mentioned, got %q", err)
+       }
+}
+
+type ByteArrayValuer [1]byte
+type ByteSliceValuer []byte
+type FuncArrayValuer struct {
+       delimiter func() string
+       value     func() (driver.Value, error)
+}
+
+func (a ByteArrayValuer) Value() (driver.Value, error) { return a[:], nil }
+func (b ByteSliceValuer) Value() (driver.Value, error) { return []byte(b), nil 
}
+func (f FuncArrayValuer) ArrayDelimiter() string       { return f.delimiter() }
+func (f FuncArrayValuer) Value() (driver.Value, error) { return f.value() }
+
+func TestGenericArrayValue(t *testing.T) {
+       result, err := GenericArray{nil}.Value()
+
+       if err != nil {
+               t.Fatalf("Expected no error for nil, got %v", err)
+       }
+       if result != nil {
+               t.Errorf("Expected nil, got %q", result)
+       }
+
+       for _, tt := range []interface{}{
+               []bool(nil),
+               [][]int(nil),
+               []*int(nil),
+               []sql.NullString(nil),
+       } {
+               result, err := GenericArray{tt}.Value()
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %#v, got %v", tt, err)
+               }
+               if result != nil {
+                       t.Errorf("Expected nil for %#v, got %q", tt, result)
+               }
+       }
+
+       Tilde := func(v driver.Value) FuncArrayValuer {
+               return FuncArrayValuer{
+                       func() string { return "~" },
+                       func() (driver.Value, error) { return v, nil }}
+       }
+
+       for _, tt := range []struct {
+               result string
+               input  interface{}
+       }{
+               {`{}`, []bool{}},
+               {`{true}`, []bool{true}},
+               {`{true,false}`, []bool{true, false}},
+               {`{true,false}`, [2]bool{true, false}},
+
+               {`{}`, [][]int{{}}},
+               {`{}`, [][]int{{}, {}}},
+               {`{{1}}`, [][]int{{1}}},
+               {`{{1},{2}}`, [][]int{{1}, {2}}},
+               {`{{1,2},{3,4}}`, [][]int{{1, 2}, {3, 4}}},
+               {`{{1,2},{3,4}}`, [2][2]int{{1, 2}, {3, 4}}},
+
+               {`{"a","\\b","c\"","d,e"}`, []string{`a`, `\b`, `c"`, `d,e`}},
+               {`{"a","\\b","c\"","d,e"}`, [][]byte{{'a'}, {'\\', 'b'}, {'c', 
'"'}, {'d', ',', 'e'}}},
+
+               {`{NULL}`, []*int{nil}},
+               {`{0,NULL}`, []*int{new(int), nil}},
+
+               {`{NULL}`, []sql.NullString{{}}},
+               {`{"\"",NULL}`, []sql.NullString{{String: `"`, Valid: true}, 
{}}},
+
+               {`{"a","b"}`, []ByteArrayValuer{{'a'}, {'b'}}},
+               {`{{"a","b"},{"c","d"}}`, [][]ByteArrayValuer{{{'a'}, {'b'}}, 
{{'c'}, {'d'}}}},
+
+               {`{"e","f"}`, []ByteSliceValuer{{'e'}, {'f'}}},
+               {`{{"e","f"},{"g","h"}}`, [][]ByteSliceValuer{{{'e'}, {'f'}}, 
{{'g'}, {'h'}}}},
+
+               {`{1~2}`, []FuncArrayValuer{Tilde(int64(1)), Tilde(int64(2))}},
+               {`{{1~2}~{3~4}}`, [][]FuncArrayValuer{{Tilde(int64(1)), 
Tilde(int64(2))}, {Tilde(int64(3)), Tilde(int64(4))}}},
+       } {
+               result, err := GenericArray{tt.input}.Value()
+
+               if err != nil {
+                       t.Fatalf("Expected no error for %q, got %v", tt.input, 
err)
+               }
+               if !reflect.DeepEqual(result, tt.result) {
+                       t.Errorf("Expected %q for %q, got %q", tt.result, 
tt.input, result)
+               }
+       }
+}
+
+func TestGenericArrayValueErrors(t *testing.T) {
+       var v []interface{}
+
+       v = []interface{}{func() {}}
+       if _, err := (GenericArray{v}).Value(); err == nil {
+               t.Errorf("Expected error for %q, got nil", v)
+       }
+
+       v = []interface{}{nil, func() {}}
+       if _, err := (GenericArray{v}).Value(); err == nil {
+               t.Errorf("Expected error for %q, got nil", v)
+       }
+}
+
+func BenchmarkGenericArrayValueBools(b *testing.B) {
+       rand.Seed(1)
+       x := make([]bool, 10)
+       for i := 0; i < len(x); i++ {
+               x[i] = rand.Intn(2) == 0
+       }
+       a := GenericArray{x}
+
+       for i := 0; i < b.N; i++ {
+               a.Value()
+       }
+}
+
+func BenchmarkGenericArrayValueFloat64s(b *testing.B) {
+       rand.Seed(1)
+       x := make([]float64, 10)
+       for i := 0; i < len(x); i++ {
+               x[i] = rand.NormFloat64()
+       }
+       a := GenericArray{x}
+
+       for i := 0; i < b.N; i++ {
+               a.Value()
+       }
+}
+
+func BenchmarkGenericArrayValueInt64s(b *testing.B) {
+       rand.Seed(1)
+       x := make([]int64, 10)
+       for i := 0; i < len(x); i++ {
+               x[i] = rand.Int63()
+       }
+       a := GenericArray{x}
+
+       for i := 0; i < b.N; i++ {
+               a.Value()
+       }
+}
+
+func BenchmarkGenericArrayValueByteSlices(b *testing.B) {
+       x := make([][]byte, 10)
+       for i := 0; i < len(x); i++ {
+               x[i] = bytes.Repeat([]byte(`abc"def\ghi`), 5)
+       }
+       a := GenericArray{x}
+
+       for i := 0; i < b.N; i++ {
+               a.Value()
+       }
+}
+
+func BenchmarkGenericArrayValueStrings(b *testing.B) {
+       x := make([]string, 10)
+       for i := 0; i < len(x); i++ {
+               x[i] = strings.Repeat(`abc"def\ghi`, 5)
+       }
+       a := GenericArray{x}
+
+       for i := 0; i < b.N; i++ {
+               a.Value()
+       }
+}
+
+func TestArrayScanBackend(t *testing.T) {
+       db := openTestConn(t)
+       defer db.Close()
+
+       for _, tt := range []struct {
+               s string
+               d sql.Scanner
+               e interface{}
+       }{
+               {`ARRAY[true, false]`, new(BoolArray), &BoolArray{true, false}},
+               {`ARRAY[E'\\xdead', E'\\xbeef']`, new(ByteaArray), 
&ByteaArray{{'\xDE', '\xAD'}, {'\xBE', '\xEF'}}},
+               {`ARRAY[1.2, 3.4]`, new(Float64Array), &Float64Array{1.2, 3.4}},
+               {`ARRAY[1, 2, 3]`, new(Int64Array), &Int64Array{1, 2, 3}},
+               {`ARRAY['a', E'\\b', 'c"', 'd,e']`, new(StringArray), 
&StringArray{`a`, `\b`, `c"`, `d,e`}},
+       } {
+               err := db.QueryRow(`SELECT ` + tt.s).Scan(tt.d)
+               if err != nil {
+                       t.Errorf("Expected no error when scanning %s into %T, 
got %v", tt.s, tt.d, err)
+               }
+               if !reflect.DeepEqual(tt.d, tt.e) {
+                       t.Errorf("Expected %v when scanning %s into %T, got 
%v", tt.e, tt.s, tt.d, tt.d)
+               }
+       }
+}
+
+func TestArrayValueBackend(t *testing.T) {
+       db := openTestConn(t)
+       defer db.Close()
+
+       for _, tt := range []struct {
+               s string
+               v driver.Valuer
+       }{
+               {`ARRAY[true, false]`, BoolArray{true, false}},
+               {`ARRAY[E'\\xdead', E'\\xbeef']`, ByteaArray{{'\xDE', '\xAD'}, 
{'\xBE', '\xEF'}}},
+               {`ARRAY[1.2, 3.4]`, Float64Array{1.2, 3.4}},
+               {`ARRAY[1, 2, 3]`, Int64Array{1, 2, 3}},
+               {`ARRAY['a', E'\\b', 'c"', 'd,e']`, StringArray{`a`, `\b`, 
`c"`, `d,e`}},
+       } {
+               var x int
+               err := db.QueryRow(`SELECT 1 WHERE `+tt.s+` <> $1`, 
tt.v).Scan(&x)
+               if err != sql.ErrNoRows {
+                       t.Errorf("Expected %v to equal %s, got %v", tt.v, tt.s, 
err)
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/bench_test.go
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/bench_test.go 
b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/bench_test.go
new file mode 100644
index 0000000..e71f41d
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/bench_test.go
@@ -0,0 +1,435 @@
+// +build go1.1
+
+package pq
+
+import (
+       "bufio"
+       "bytes"
+       "database/sql"
+       "database/sql/driver"
+       "io"
+       "math/rand"
+       "net"
+       "runtime"
+       "strconv"
+       "strings"
+       "sync"
+       "testing"
+       "time"
+
+       "github.com/lib/pq/oid"
+)
+
+var (
+       selectStringQuery = "SELECT '" + strings.Repeat("0123456789", 10) + "'"
+       selectSeriesQuery = "SELECT generate_series(1, 100)"
+)
+
+func BenchmarkSelectString(b *testing.B) {
+       var result string
+       benchQuery(b, selectStringQuery, &result)
+}
+
+func BenchmarkSelectSeries(b *testing.B) {
+       var result int
+       benchQuery(b, selectSeriesQuery, &result)
+}
+
+func benchQuery(b *testing.B, query string, result interface{}) {
+       b.StopTimer()
+       db := openTestConn(b)
+       defer db.Close()
+       b.StartTimer()
+
+       for i := 0; i < b.N; i++ {
+               benchQueryLoop(b, db, query, result)
+       }
+}
+
+func benchQueryLoop(b *testing.B, db *sql.DB, query string, result 
interface{}) {
+       rows, err := db.Query(query)
+       if err != nil {
+               b.Fatal(err)
+       }
+       defer rows.Close()
+       for rows.Next() {
+               err = rows.Scan(result)
+               if err != nil {
+                       b.Fatal("failed to scan", err)
+               }
+       }
+}
+
+// reading from circularConn yields content[:prefixLen] once, followed by
+// content[prefixLen:] over and over again. It never returns EOF.
+type circularConn struct {
+       content   string
+       prefixLen int
+       pos       int
+       net.Conn  // for all other net.Conn methods that will never be called
+}
+
+func (r *circularConn) Read(b []byte) (n int, err error) {
+       n = copy(b, r.content[r.pos:])
+       r.pos += n
+       if r.pos >= len(r.content) {
+               r.pos = r.prefixLen
+       }
+       return
+}
+
+func (r *circularConn) Write(b []byte) (n int, err error) { return len(b), nil 
}
+
+func (r *circularConn) Close() error { return nil }
+
+func fakeConn(content string, prefixLen int) *conn {
+       c := &circularConn{content: content, prefixLen: prefixLen}
+       return &conn{buf: bufio.NewReader(c), c: c}
+}
+
+// This benchmark is meant to be the same as BenchmarkSelectString, but takes
+// out some of the factors this package can't control. The numbers are less 
noisy,
+// but also the costs of network communication aren't accurately represented.
+func BenchmarkMockSelectString(b *testing.B) {
+       b.StopTimer()
+       // taken from a recorded run of BenchmarkSelectString
+       // See: 
http://www.postgresql.org/docs/current/static/protocol-message-formats.html
+       const response = "1\x00\x00\x00\x04" +
+               "t\x00\x00\x00\x06\x00\x00" +
+               
"T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00"
 +
+               "Z\x00\x00\x00\x05I" +
+               "2\x00\x00\x00\x04" +
+               
"D\x00\x00\x00n\x00\x01\x00\x00\x00d0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
 +
+               "C\x00\x00\x00\rSELECT 1\x00" +
+               "Z\x00\x00\x00\x05I" +
+               "3\x00\x00\x00\x04" +
+               "Z\x00\x00\x00\x05I"
+       c := fakeConn(response, 0)
+       b.StartTimer()
+
+       for i := 0; i < b.N; i++ {
+               benchMockQuery(b, c, selectStringQuery)
+       }
+}
+
+var seriesRowData = func() string {
+       var buf bytes.Buffer
+       for i := 1; i <= 100; i++ {
+               digits := byte(2)
+               if i >= 100 {
+                       digits = 3
+               } else if i < 10 {
+                       digits = 1
+               }
+               buf.WriteString("D\x00\x00\x00")
+               buf.WriteByte(10 + digits)
+               buf.WriteString("\x00\x01\x00\x00\x00")
+               buf.WriteByte(digits)
+               buf.WriteString(strconv.Itoa(i))
+       }
+       return buf.String()
+}()
+
+func BenchmarkMockSelectSeries(b *testing.B) {
+       b.StopTimer()
+       var response = "1\x00\x00\x00\x04" +
+               "t\x00\x00\x00\x06\x00\x00" +
+               
"T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00"
 +
+               "Z\x00\x00\x00\x05I" +
+               "2\x00\x00\x00\x04" +
+               seriesRowData +
+               "C\x00\x00\x00\x0fSELECT 100\x00" +
+               "Z\x00\x00\x00\x05I" +
+               "3\x00\x00\x00\x04" +
+               "Z\x00\x00\x00\x05I"
+       c := fakeConn(response, 0)
+       b.StartTimer()
+
+       for i := 0; i < b.N; i++ {
+               benchMockQuery(b, c, selectSeriesQuery)
+       }
+}
+
+func benchMockQuery(b *testing.B, c *conn, query string) {
+       stmt, err := c.Prepare(query)
+       if err != nil {
+               b.Fatal(err)
+       }
+       defer stmt.Close()
+       rows, err := stmt.Query(nil)
+       if err != nil {
+               b.Fatal(err)
+       }
+       defer rows.Close()
+       var dest [1]driver.Value
+       for {
+               if err := rows.Next(dest[:]); err != nil {
+                       if err == io.EOF {
+                               break
+                       }
+                       b.Fatal(err)
+               }
+       }
+}
+
+func BenchmarkPreparedSelectString(b *testing.B) {
+       var result string
+       benchPreparedQuery(b, selectStringQuery, &result)
+}
+
+func BenchmarkPreparedSelectSeries(b *testing.B) {
+       var result int
+       benchPreparedQuery(b, selectSeriesQuery, &result)
+}
+
+func benchPreparedQuery(b *testing.B, query string, result interface{}) {
+       b.StopTimer()
+       db := openTestConn(b)
+       defer db.Close()
+       stmt, err := db.Prepare(query)
+       if err != nil {
+               b.Fatal(err)
+       }
+       defer stmt.Close()
+       b.StartTimer()
+
+       for i := 0; i < b.N; i++ {
+               benchPreparedQueryLoop(b, db, stmt, result)
+       }
+}
+
+func benchPreparedQueryLoop(b *testing.B, db *sql.DB, stmt *sql.Stmt, result 
interface{}) {
+       rows, err := stmt.Query()
+       if err != nil {
+               b.Fatal(err)
+       }
+       if !rows.Next() {
+               rows.Close()
+               b.Fatal("no rows")
+       }
+       defer rows.Close()
+       for rows.Next() {
+               err = rows.Scan(&result)
+               if err != nil {
+                       b.Fatal("failed to scan")
+               }
+       }
+}
+
+// See the comment for BenchmarkMockSelectString.
+func BenchmarkMockPreparedSelectString(b *testing.B) {
+       b.StopTimer()
+       const parseResponse = "1\x00\x00\x00\x04" +
+               "t\x00\x00\x00\x06\x00\x00" +
+               
"T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00"
 +
+               "Z\x00\x00\x00\x05I"
+       const responses = parseResponse +
+               "2\x00\x00\x00\x04" +
+               
"D\x00\x00\x00n\x00\x01\x00\x00\x00d0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
 +
+               "C\x00\x00\x00\rSELECT 1\x00" +
+               "Z\x00\x00\x00\x05I"
+       c := fakeConn(responses, len(parseResponse))
+
+       stmt, err := c.Prepare(selectStringQuery)
+       if err != nil {
+               b.Fatal(err)
+       }
+       b.StartTimer()
+
+       for i := 0; i < b.N; i++ {
+               benchPreparedMockQuery(b, c, stmt)
+       }
+}
+
+func BenchmarkMockPreparedSelectSeries(b *testing.B) {
+       b.StopTimer()
+       const parseResponse = "1\x00\x00\x00\x04" +
+               "t\x00\x00\x00\x06\x00\x00" +
+               
"T\x00\x00\x00!\x00\x01?column?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\xc1\xff\xfe\xff\xff\xff\xff\x00\x00"
 +
+               "Z\x00\x00\x00\x05I"
+       var responses = parseResponse +
+               "2\x00\x00\x00\x04" +
+               seriesRowData +
+               "C\x00\x00\x00\x0fSELECT 100\x00" +
+               "Z\x00\x00\x00\x05I"
+       c := fakeConn(responses, len(parseResponse))
+
+       stmt, err := c.Prepare(selectSeriesQuery)
+       if err != nil {
+               b.Fatal(err)
+       }
+       b.StartTimer()
+
+       for i := 0; i < b.N; i++ {
+               benchPreparedMockQuery(b, c, stmt)
+       }
+}
+
+func benchPreparedMockQuery(b *testing.B, c *conn, stmt driver.Stmt) {
+       rows, err := stmt.Query(nil)
+       if err != nil {
+               b.Fatal(err)
+       }
+       defer rows.Close()
+       var dest [1]driver.Value
+       for {
+               if err := rows.Next(dest[:]); err != nil {
+                       if err == io.EOF {
+                               break
+                       }
+                       b.Fatal(err)
+               }
+       }
+}
+
+func BenchmarkEncodeInt64(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               encode(&parameterStatus{}, int64(1234), oid.T_int8)
+       }
+}
+
+func BenchmarkEncodeFloat64(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               encode(&parameterStatus{}, 3.14159, oid.T_float8)
+       }
+}
+
+var testByteString = []byte("abcdefghijklmnopqrstuvwxyz")
+
+func BenchmarkEncodeByteaHex(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               encode(&parameterStatus{serverVersion: 90000}, testByteString, 
oid.T_bytea)
+       }
+}
+func BenchmarkEncodeByteaEscape(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               encode(&parameterStatus{serverVersion: 84000}, testByteString, 
oid.T_bytea)
+       }
+}
+
+func BenchmarkEncodeBool(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               encode(&parameterStatus{}, true, oid.T_bool)
+       }
+}
+
+var testTimestamptz = time.Date(2001, time.January, 1, 0, 0, 0, 0, time.Local)
+
+func BenchmarkEncodeTimestamptz(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               encode(&parameterStatus{}, testTimestamptz, oid.T_timestamptz)
+       }
+}
+
+var testIntBytes = []byte("1234")
+
+func BenchmarkDecodeInt64(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               decode(&parameterStatus{}, testIntBytes, oid.T_int8, formatText)
+       }
+}
+
+var testFloatBytes = []byte("3.14159")
+
+func BenchmarkDecodeFloat64(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               decode(&parameterStatus{}, testFloatBytes, oid.T_float8, 
formatText)
+       }
+}
+
+var testBoolBytes = []byte{'t'}
+
+func BenchmarkDecodeBool(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               decode(&parameterStatus{}, testBoolBytes, oid.T_bool, 
formatText)
+       }
+}
+
+func TestDecodeBool(t *testing.T) {
+       db := openTestConn(t)
+       rows, err := db.Query("select true")
+       if err != nil {
+               t.Fatal(err)
+       }
+       rows.Close()
+}
+
+var testTimestamptzBytes = []byte("2013-09-17 22:15:32.360754-07")
+
+func BenchmarkDecodeTimestamptz(b *testing.B) {
+       for i := 0; i < b.N; i++ {
+               decode(&parameterStatus{}, testTimestamptzBytes, 
oid.T_timestamptz, formatText)
+       }
+}
+
+func BenchmarkDecodeTimestamptzMultiThread(b *testing.B) {
+       oldProcs := runtime.GOMAXPROCS(0)
+       defer runtime.GOMAXPROCS(oldProcs)
+       runtime.GOMAXPROCS(runtime.NumCPU())
+       globalLocationCache = newLocationCache()
+
+       f := func(wg *sync.WaitGroup, loops int) {
+               defer wg.Done()
+               for i := 0; i < loops; i++ {
+                       decode(&parameterStatus{}, testTimestamptzBytes, 
oid.T_timestamptz, formatText)
+               }
+       }
+
+       wg := &sync.WaitGroup{}
+       b.ResetTimer()
+       for j := 0; j < 10; j++ {
+               wg.Add(1)
+               go f(wg, b.N/10)
+       }
+       wg.Wait()
+}
+
+func BenchmarkLocationCache(b *testing.B) {
+       globalLocationCache = newLocationCache()
+       for i := 0; i < b.N; i++ {
+               globalLocationCache.getLocation(rand.Intn(10000))
+       }
+}
+
+func BenchmarkLocationCacheMultiThread(b *testing.B) {
+       oldProcs := runtime.GOMAXPROCS(0)
+       defer runtime.GOMAXPROCS(oldProcs)
+       runtime.GOMAXPROCS(runtime.NumCPU())
+       globalLocationCache = newLocationCache()
+
+       f := func(wg *sync.WaitGroup, loops int) {
+               defer wg.Done()
+               for i := 0; i < loops; i++ {
+                       globalLocationCache.getLocation(rand.Intn(10000))
+               }
+       }
+
+       wg := &sync.WaitGroup{}
+       b.ResetTimer()
+       for j := 0; j < 10; j++ {
+               wg.Add(1)
+               go f(wg, b.N/10)
+       }
+       wg.Wait()
+}
+
+// Stress test the performance of parsing results from the wire.
+func BenchmarkResultParsing(b *testing.B) {
+       b.StopTimer()
+
+       db := openTestConn(b)
+       defer db.Close()
+       _, err := db.Exec("BEGIN")
+       if err != nil {
+               b.Fatal(err)
+       }
+
+       b.StartTimer()
+       for i := 0; i < b.N; i++ {
+               res, err := db.Query("SELECT generate_series(1, 50000)")
+               if err != nil {
+                       b.Fatal(err)
+               }
+               res.Close()
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/buf.go
----------------------------------------------------------------------
diff --git a/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/buf.go 
b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/buf.go
new file mode 100644
index 0000000..666b001
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/buf.go
@@ -0,0 +1,91 @@
+package pq
+
+import (
+       "bytes"
+       "encoding/binary"
+
+       "github.com/lib/pq/oid"
+)
+
+type readBuf []byte
+
+func (b *readBuf) int32() (n int) {
+       n = int(int32(binary.BigEndian.Uint32(*b)))
+       *b = (*b)[4:]
+       return
+}
+
+func (b *readBuf) oid() (n oid.Oid) {
+       n = oid.Oid(binary.BigEndian.Uint32(*b))
+       *b = (*b)[4:]
+       return
+}
+
+// N.B: this is actually an unsigned 16-bit integer, unlike int32
+func (b *readBuf) int16() (n int) {
+       n = int(binary.BigEndian.Uint16(*b))
+       *b = (*b)[2:]
+       return
+}
+
+func (b *readBuf) string() string {
+       i := bytes.IndexByte(*b, 0)
+       if i < 0 {
+               errorf("invalid message format; expected string terminator")
+       }
+       s := (*b)[:i]
+       *b = (*b)[i+1:]
+       return string(s)
+}
+
+func (b *readBuf) next(n int) (v []byte) {
+       v = (*b)[:n]
+       *b = (*b)[n:]
+       return
+}
+
+func (b *readBuf) byte() byte {
+       return b.next(1)[0]
+}
+
+type writeBuf struct {
+       buf []byte
+       pos int
+}
+
+func (b *writeBuf) int32(n int) {
+       x := make([]byte, 4)
+       binary.BigEndian.PutUint32(x, uint32(n))
+       b.buf = append(b.buf, x...)
+}
+
+func (b *writeBuf) int16(n int) {
+       x := make([]byte, 2)
+       binary.BigEndian.PutUint16(x, uint16(n))
+       b.buf = append(b.buf, x...)
+}
+
+func (b *writeBuf) string(s string) {
+       b.buf = append(b.buf, (s + "\000")...)
+}
+
+func (b *writeBuf) byte(c byte) {
+       b.buf = append(b.buf, c)
+}
+
+func (b *writeBuf) bytes(v []byte) {
+       b.buf = append(b.buf, v...)
+}
+
+func (b *writeBuf) wrap() []byte {
+       p := b.buf[b.pos:]
+       binary.BigEndian.PutUint32(p, uint32(len(p)))
+       return b.buf
+}
+
+func (b *writeBuf) next(c byte) {
+       p := b.buf[b.pos:]
+       binary.BigEndian.PutUint32(p, uint32(len(p)))
+       b.pos = len(b.buf) + 1
+       b.buf = append(b.buf, c, 0, 0, 0, 0)
+}

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/certs/README
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/certs/README 
b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/certs/README
new file mode 100644
index 0000000..24ab7b2
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/certs/README
@@ -0,0 +1,3 @@
+This directory contains certificates and private keys for testing some
+SSL-related functionality in Travis.  Do NOT use these certificates for
+anything other than testing.

http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/13fd7151/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/certs/bogus_root.crt
----------------------------------------------------------------------
diff --git 
a/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/certs/bogus_root.crt 
b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/certs/bogus_root.crt
new file mode 100644
index 0000000..1239db3
--- /dev/null
+++ 
b/traffic_ops/traffic_ops_golang/vendor/github.com/lib/pq/certs/bogus_root.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAe6gAwIBAgIQSnDYp/Naet9HOZljF5PuwDANBgkqhkiG9w0BAQsFADAr
+MRIwEAYDVQQKEwlDb2Nrcm9hY2gxFTATBgNVBAMTDENvY2tyb2FjaCBDQTAeFw0x
+NjAyMDcxNjQ0MzdaFw0xNzAyMDYxNjQ0MzdaMCsxEjAQBgNVBAoTCUNvY2tyb2Fj
+aDEVMBMGA1UEAxMMQ29ja3JvYWNoIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxdln3/UdgP7ayA/G1kT7upjLe4ERwQjYQ25q0e1+vgsB5jhiirxJ
+e0+WkhhYu/mwoSAXzvlsbZ2PWFyfdanZeD/Lh6SvIeWXVVaPcWVWL1TEcoN2jr5+
+E85MMHmbbmaT2he8s6br2tM/UZxyTQ2XRprIzApbDssyw1c0Yufcpu3C6267FLEl
+IfcWrzDhnluFhthhtGXv3ToD8IuMScMC5qlKBXtKmD1B5x14ngO/ecNJ+OlEi0HU
+mavK4KWgI2rDXRZ2EnCpyTZdkc3kkRnzKcg653oOjMDRZdrhfIrha+Jq38ACsUmZ
+Su7Sp5jkIHOCO8Zg+l6GKVSq37dKMapD8wIDAQABoyYwJDAOBgNVHQ8BAf8EBAMC
+AuQwEgYDVR0TAQH/BAgwBgEB/wIBATANBgkqhkiG9w0BAQsFAAOCAQEAwZ2Tu0Yu
+rrSVdMdoPEjT1IZd+5OhM/SLzL0ddtvTithRweLHsw2lDQYlXFqr24i3UGZJQ1sp
+cqSrNwswgLUQT3vWyTjmM51HEb2vMYWKmjZ+sBQYAUP1CadrN/+OTfNGnlF1+B4w
+IXOzh7EvQmJJnNybLe4a/aRvj1NE2n8Z898B76SVU9WbfKKz8VwLzuIPDqkKcZda
+lMy5yzthyztV9YjcWs2zVOUGZvGdAhDrvZuUq6mSmxrBEvR2LBOggmVf3tGRT+Ls
+lW7c9Lrva5zLHuqmoPP07A+vuI9a0D1X44jwGDuPWJ5RnTOQ63Uez12mKNjqleHw
+DnkwNanuO8dhAA==
+-----END CERTIFICATE-----


Reply via email to