mirror of
https://github.com/documize/community.git
synced 2025-07-23 23:29:42 +02:00
Sync with Community
This commit is contained in:
parent
df8f650319
commit
989b7cd62c
123 changed files with 5054 additions and 2015 deletions
2
vendor/github.com/lib/pq/.gitignore
generated
vendored
2
vendor/github.com/lib/pq/.gitignore
generated
vendored
|
@ -2,3 +2,5 @@
|
|||
*.test
|
||||
*~
|
||||
*.swp
|
||||
.idea
|
||||
.vscode
|
12
vendor/github.com/lib/pq/.travis.sh
generated
vendored
12
vendor/github.com/lib/pq/.travis.sh
generated
vendored
|
@ -1,17 +1,15 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
set -eux
|
||||
|
||||
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
|
||||
echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list
|
||||
sudo apt-get update
|
||||
}
|
||||
|
||||
postgresql_configure() {
|
||||
|
@ -51,10 +49,10 @@ postgresql_configure() {
|
|||
}
|
||||
|
||||
postgresql_install() {
|
||||
xargs sudo apt-get -y -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confnew' install <<-packages
|
||||
xargs sudo apt-get -y install <<-packages
|
||||
postgresql-$PGVERSION
|
||||
postgresql-client-$PGVERSION
|
||||
postgresql-server-dev-$PGVERSION
|
||||
postgresql-contrib-$PGVERSION
|
||||
packages
|
||||
}
|
||||
|
||||
|
|
5
vendor/github.com/lib/pq/.travis.yml
generated
vendored
5
vendor/github.com/lib/pq/.travis.yml
generated
vendored
|
@ -1,9 +1,9 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.13.x
|
||||
- 1.14.x
|
||||
- master
|
||||
- 1.15.x
|
||||
- 1.16.x
|
||||
|
||||
sudo: true
|
||||
|
||||
|
@ -13,6 +13,7 @@ env:
|
|||
- PQGOSSLTESTS=1
|
||||
- PQSSLCERTTEST_PATH=$PWD/certs
|
||||
- PGHOST=127.0.0.1
|
||||
- GODEBUG=x509ignoreCN=0
|
||||
matrix:
|
||||
- PGVERSION=10
|
||||
- PGVERSION=9.6
|
||||
|
|
1
vendor/github.com/lib/pq/README.md
generated
vendored
1
vendor/github.com/lib/pq/README.md
generated
vendored
|
@ -19,6 +19,7 @@
|
|||
* Unix socket support
|
||||
* Notifications: `LISTEN`/`NOTIFY`
|
||||
* pgpass support
|
||||
* GSS (Kerberos) auth
|
||||
|
||||
## Tests
|
||||
|
||||
|
|
141
vendor/github.com/lib/pq/array.go
generated
vendored
141
vendor/github.com/lib/pq/array.go
generated
vendored
|
@ -22,7 +22,7 @@ var typeSQLScanner = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
|
|||
// 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))
|
||||
// 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.
|
||||
|
@ -35,19 +35,31 @@ func Array(a interface{}) interface {
|
|||
return (*BoolArray)(&a)
|
||||
case []float64:
|
||||
return (*Float64Array)(&a)
|
||||
case []float32:
|
||||
return (*Float32Array)(&a)
|
||||
case []int64:
|
||||
return (*Int64Array)(&a)
|
||||
case []int32:
|
||||
return (*Int32Array)(&a)
|
||||
case []string:
|
||||
return (*StringArray)(&a)
|
||||
case [][]byte:
|
||||
return (*ByteaArray)(&a)
|
||||
|
||||
case *[]bool:
|
||||
return (*BoolArray)(a)
|
||||
case *[]float64:
|
||||
return (*Float64Array)(a)
|
||||
case *[]float32:
|
||||
return (*Float32Array)(a)
|
||||
case *[]int64:
|
||||
return (*Int64Array)(a)
|
||||
case *[]int32:
|
||||
return (*Int32Array)(a)
|
||||
case *[]string:
|
||||
return (*StringArray)(a)
|
||||
case *[][]byte:
|
||||
return (*ByteaArray)(a)
|
||||
}
|
||||
|
||||
return GenericArray{a}
|
||||
|
@ -267,6 +279,70 @@ func (a Float64Array) Value() (driver.Value, error) {
|
|||
return "{}", nil
|
||||
}
|
||||
|
||||
// Float32Array represents a one-dimensional array of the PostgreSQL double
|
||||
// precision type.
|
||||
type Float32Array []float32
|
||||
|
||||
// Scan implements the sql.Scanner interface.
|
||||
func (a *Float32Array) 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 Float32Array", src)
|
||||
}
|
||||
|
||||
func (a *Float32Array) scanBytes(src []byte) error {
|
||||
elems, err := scanLinearArray(src, []byte{','}, "Float32Array")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if *a != nil && len(elems) == 0 {
|
||||
*a = (*a)[:0]
|
||||
} else {
|
||||
b := make(Float32Array, len(elems))
|
||||
for i, v := range elems {
|
||||
var x float64
|
||||
if x, err = strconv.ParseFloat(string(v), 32); err != nil {
|
||||
return fmt.Errorf("pq: parsing array element index %d: %v", i, err)
|
||||
}
|
||||
b[i] = float32(x)
|
||||
}
|
||||
*a = b
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver.Valuer interface.
|
||||
func (a Float32Array) 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, float64(a[0]), 'f', -1, 32)
|
||||
for i := 1; i < n; i++ {
|
||||
b = append(b, ',')
|
||||
b = strconv.AppendFloat(b, float64(a[i]), 'f', -1, 32)
|
||||
}
|
||||
|
||||
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{} }
|
||||
|
@ -483,6 +559,69 @@ func (a Int64Array) Value() (driver.Value, error) {
|
|||
return "{}", nil
|
||||
}
|
||||
|
||||
// Int32Array represents a one-dimensional array of the PostgreSQL integer types.
|
||||
type Int32Array []int32
|
||||
|
||||
// Scan implements the sql.Scanner interface.
|
||||
func (a *Int32Array) 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 Int32Array", src)
|
||||
}
|
||||
|
||||
func (a *Int32Array) scanBytes(src []byte) error {
|
||||
elems, err := scanLinearArray(src, []byte{','}, "Int32Array")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if *a != nil && len(elems) == 0 {
|
||||
*a = (*a)[:0]
|
||||
} else {
|
||||
b := make(Int32Array, len(elems))
|
||||
for i, v := range elems {
|
||||
var x int
|
||||
if x, err = strconv.Atoi(string(v)); err != nil {
|
||||
return fmt.Errorf("pq: parsing array element index %d: %v", i, err)
|
||||
}
|
||||
b[i] = int32(x)
|
||||
}
|
||||
*a = b
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value implements the driver.Valuer interface.
|
||||
func (a Int32Array) 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, int64(a[0]), 10)
|
||||
for i := 1; i < n; i++ {
|
||||
b = append(b, ',')
|
||||
b = strconv.AppendInt(b, int64(a[i]), 10)
|
||||
}
|
||||
|
||||
return string(append(b, '}')), nil
|
||||
}
|
||||
|
||||
return "{}", nil
|
||||
}
|
||||
|
||||
// StringArray represents a one-dimensional array of the PostgreSQL character types.
|
||||
type StringArray []string
|
||||
|
||||
|
|
194
vendor/github.com/lib/pq/conn.go
generated
vendored
194
vendor/github.com/lib/pq/conn.go
generated
vendored
|
@ -18,6 +18,7 @@ import (
|
|||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
|
@ -38,13 +39,18 @@ var (
|
|||
errNoLastInsertID = errors.New("no LastInsertId available after the empty statement")
|
||||
)
|
||||
|
||||
// Compile time validation that our types implement the expected interfaces
|
||||
var (
|
||||
_ driver.Driver = Driver{}
|
||||
)
|
||||
|
||||
// Driver is the Postgres database driver.
|
||||
type Driver struct{}
|
||||
|
||||
// Open opens a new connection to the database. name is a connection string.
|
||||
// Most users should only use it through database/sql package from the standard
|
||||
// library.
|
||||
func (d *Driver) Open(name string) (driver.Conn, error) {
|
||||
func (d Driver) Open(name string) (driver.Conn, error) {
|
||||
return Open(name)
|
||||
}
|
||||
|
||||
|
@ -136,7 +142,7 @@ type conn struct {
|
|||
|
||||
// If true, this connection is bad and all public-facing functions should
|
||||
// return ErrBadConn.
|
||||
bad bool
|
||||
bad *atomic.Value
|
||||
|
||||
// If set, this connection should never use the binary format when
|
||||
// receiving query results from prepared statements. Only provided for
|
||||
|
@ -155,6 +161,9 @@ type conn struct {
|
|||
|
||||
// If not nil, notifications will be synchronously sent here
|
||||
notificationHandler func(*Notification)
|
||||
|
||||
// GSSAPI context
|
||||
gss GSS
|
||||
}
|
||||
|
||||
// Handle driver-side settings in parsed connection string.
|
||||
|
@ -289,11 +298,20 @@ func (c *Connector) open(ctx context.Context) (cn *conn, err error) {
|
|||
// the user.
|
||||
defer errRecoverNoErrBadConn(&err)
|
||||
|
||||
o := c.opts
|
||||
// Create a new values map (copy). This makes it so maps in different
|
||||
// connections do not reference the same underlying data structure, so it
|
||||
// is safe for multiple connections to concurrently write to their opts.
|
||||
o := make(values)
|
||||
for k, v := range c.opts {
|
||||
o[k] = v
|
||||
}
|
||||
|
||||
bad := &atomic.Value{}
|
||||
bad.Store(false)
|
||||
cn = &conn{
|
||||
opts: o,
|
||||
dialer: c.dialer,
|
||||
bad: bad,
|
||||
}
|
||||
err = cn.handleDriverSettings(o)
|
||||
if err != nil {
|
||||
|
@ -335,10 +353,6 @@ func (c *Connector) open(ctx context.Context) (cn *conn, err error) {
|
|||
|
||||
func dial(ctx context.Context, d Dialer, o values) (net.Conn, error) {
|
||||
network, address := network(o)
|
||||
// SSL is not necessary or supported over UNIX domain sockets
|
||||
if network == "unix" {
|
||||
o["sslmode"] = "disable"
|
||||
}
|
||||
|
||||
// Zero or not specified means wait indefinitely.
|
||||
if timeout, ok := o["connect_timeout"]; ok && timeout != "0" {
|
||||
|
@ -502,9 +516,22 @@ func (cn *conn) isInTransaction() bool {
|
|||
cn.txnStatus == txnStatusInFailedTransaction
|
||||
}
|
||||
|
||||
func (cn *conn) setBad() {
|
||||
if cn.bad != nil {
|
||||
cn.bad.Store(true)
|
||||
}
|
||||
}
|
||||
|
||||
func (cn *conn) getBad() bool {
|
||||
if cn.bad != nil {
|
||||
return cn.bad.Load().(bool)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (cn *conn) checkIsInTransaction(intxn bool) {
|
||||
if cn.isInTransaction() != intxn {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected transaction status %v", cn.txnStatus)
|
||||
}
|
||||
}
|
||||
|
@ -514,7 +541,7 @@ func (cn *conn) Begin() (_ driver.Tx, err error) {
|
|||
}
|
||||
|
||||
func (cn *conn) begin(mode string) (_ driver.Tx, err error) {
|
||||
if cn.bad {
|
||||
if cn.getBad() {
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
defer cn.errRecover(&err)
|
||||
|
@ -525,11 +552,11 @@ func (cn *conn) begin(mode string) (_ driver.Tx, err error) {
|
|||
return nil, err
|
||||
}
|
||||
if commandTag != "BEGIN" {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
return nil, fmt.Errorf("unexpected command tag %s", commandTag)
|
||||
}
|
||||
if cn.txnStatus != txnStatusIdleInTransaction {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
return nil, fmt.Errorf("unexpected transaction status %v", cn.txnStatus)
|
||||
}
|
||||
return cn, nil
|
||||
|
@ -543,7 +570,7 @@ func (cn *conn) closeTxn() {
|
|||
|
||||
func (cn *conn) Commit() (err error) {
|
||||
defer cn.closeTxn()
|
||||
if cn.bad {
|
||||
if cn.getBad() {
|
||||
return driver.ErrBadConn
|
||||
}
|
||||
defer cn.errRecover(&err)
|
||||
|
@ -565,12 +592,12 @@ func (cn *conn) Commit() (err error) {
|
|||
_, commandTag, err := cn.simpleExec("COMMIT")
|
||||
if err != nil {
|
||||
if cn.isInTransaction() {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
}
|
||||
return err
|
||||
}
|
||||
if commandTag != "COMMIT" {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
return fmt.Errorf("unexpected command tag %s", commandTag)
|
||||
}
|
||||
cn.checkIsInTransaction(false)
|
||||
|
@ -579,7 +606,7 @@ func (cn *conn) Commit() (err error) {
|
|||
|
||||
func (cn *conn) Rollback() (err error) {
|
||||
defer cn.closeTxn()
|
||||
if cn.bad {
|
||||
if cn.getBad() {
|
||||
return driver.ErrBadConn
|
||||
}
|
||||
defer cn.errRecover(&err)
|
||||
|
@ -591,7 +618,7 @@ func (cn *conn) rollback() (err error) {
|
|||
_, commandTag, err := cn.simpleExec("ROLLBACK")
|
||||
if err != nil {
|
||||
if cn.isInTransaction() {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -631,7 +658,7 @@ func (cn *conn) simpleExec(q string) (res driver.Result, commandTag string, err
|
|||
case 'T', 'D':
|
||||
// ignore any results
|
||||
default:
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unknown response for simple query: %q", t)
|
||||
}
|
||||
}
|
||||
|
@ -653,7 +680,7 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) {
|
|||
// the user can close, though, to avoid connections from being
|
||||
// leaked. A "rows" with done=true works fine for that purpose.
|
||||
if err != nil {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected message %q in simple query execution", t)
|
||||
}
|
||||
if res == nil {
|
||||
|
@ -664,8 +691,11 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) {
|
|||
// Set the result and tag to the last command complete if there wasn't a
|
||||
// query already run. Although queries usually return from here and cede
|
||||
// control to Next, a query with zero results does not.
|
||||
if t == 'C' && res.colNames == nil {
|
||||
if t == 'C' {
|
||||
res.result, res.tag = cn.parseComplete(r.string())
|
||||
if res.colNames != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
res.done = true
|
||||
case 'Z':
|
||||
|
@ -677,7 +707,7 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) {
|
|||
err = parseError(r)
|
||||
case 'D':
|
||||
if res == nil {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected DataRow in simple query execution")
|
||||
}
|
||||
// the query didn't fail; kick off to Next
|
||||
|
@ -692,7 +722,7 @@ func (cn *conn) simpleQuery(q string) (res *rows, err error) {
|
|||
// To work around a bug in QueryRow in Go 1.2 and earlier, wait
|
||||
// until the first DataRow has been received.
|
||||
default:
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unknown response for simple query: %q", t)
|
||||
}
|
||||
}
|
||||
|
@ -785,7 +815,7 @@ func (cn *conn) prepareTo(q, stmtName string) *stmt {
|
|||
}
|
||||
|
||||
func (cn *conn) Prepare(q string) (_ driver.Stmt, err error) {
|
||||
if cn.bad {
|
||||
if cn.getBad() {
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
defer cn.errRecover(&err)
|
||||
|
@ -824,7 +854,7 @@ func (cn *conn) Query(query string, args []driver.Value) (driver.Rows, error) {
|
|||
}
|
||||
|
||||
func (cn *conn) query(query string, args []driver.Value) (_ *rows, err error) {
|
||||
if cn.bad {
|
||||
if cn.getBad() {
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
if cn.inCopy {
|
||||
|
@ -858,7 +888,7 @@ func (cn *conn) query(query string, args []driver.Value) (_ *rows, err error) {
|
|||
|
||||
// Implement the optional "Execer" interface for one-shot queries
|
||||
func (cn *conn) Exec(query string, args []driver.Value) (res driver.Result, err error) {
|
||||
if cn.bad {
|
||||
if cn.getBad() {
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
defer cn.errRecover(&err)
|
||||
|
@ -892,9 +922,20 @@ func (cn *conn) Exec(query string, args []driver.Value) (res driver.Result, err
|
|||
return r, err
|
||||
}
|
||||
|
||||
type safeRetryError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (se *safeRetryError) Error() string {
|
||||
return se.Err.Error()
|
||||
}
|
||||
|
||||
func (cn *conn) send(m *writeBuf) {
|
||||
_, err := cn.c.Write(m.wrap())
|
||||
n, err := cn.c.Write(m.wrap())
|
||||
if err != nil {
|
||||
if n == 0 {
|
||||
err = &safeRetryError{Err: err}
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
@ -919,7 +960,7 @@ func (cn *conn) sendSimpleMessage(typ byte) (err error) {
|
|||
// the message yourself.
|
||||
func (cn *conn) saveMessage(typ byte, buf *readBuf) {
|
||||
if cn.saveMessageType != 0 {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected saveMessageType %d", cn.saveMessageType)
|
||||
}
|
||||
cn.saveMessageType = typ
|
||||
|
@ -1065,7 +1106,7 @@ func isDriverSetting(key string) bool {
|
|||
return true
|
||||
case "password":
|
||||
return true
|
||||
case "sslmode", "sslcert", "sslkey", "sslrootcert":
|
||||
case "sslmode", "sslcert", "sslkey", "sslrootcert", "sslinline":
|
||||
return true
|
||||
case "fallback_application_name":
|
||||
return true
|
||||
|
@ -1075,7 +1116,10 @@ func isDriverSetting(key string) bool {
|
|||
return true
|
||||
case "binary_parameters":
|
||||
return true
|
||||
|
||||
case "krbsrvname":
|
||||
return true
|
||||
case "krbspn":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
@ -1155,6 +1199,59 @@ func (cn *conn) auth(r *readBuf, o values) {
|
|||
if r.int32() != 0 {
|
||||
errorf("unexpected authentication response: %q", t)
|
||||
}
|
||||
case 7: // GSSAPI, startup
|
||||
if newGss == nil {
|
||||
errorf("kerberos error: no GSSAPI provider registered (import github.com/lib/pq/auth/kerberos if you need Kerberos support)")
|
||||
}
|
||||
cli, err := newGss()
|
||||
if err != nil {
|
||||
errorf("kerberos error: %s", err.Error())
|
||||
}
|
||||
|
||||
var token []byte
|
||||
|
||||
if spn, ok := o["krbspn"]; ok {
|
||||
// Use the supplied SPN if provided..
|
||||
token, err = cli.GetInitTokenFromSpn(spn)
|
||||
} else {
|
||||
// Allow the kerberos service name to be overridden
|
||||
service := "postgres"
|
||||
if val, ok := o["krbsrvname"]; ok {
|
||||
service = val
|
||||
}
|
||||
|
||||
token, err = cli.GetInitToken(o["host"], service)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errorf("failed to get Kerberos ticket: %q", err)
|
||||
}
|
||||
|
||||
w := cn.writeBuf('p')
|
||||
w.bytes(token)
|
||||
cn.send(w)
|
||||
|
||||
// Store for GSSAPI continue message
|
||||
cn.gss = cli
|
||||
|
||||
case 8: // GSSAPI continue
|
||||
|
||||
if cn.gss == nil {
|
||||
errorf("GSSAPI protocol error")
|
||||
}
|
||||
|
||||
b := []byte(*r)
|
||||
|
||||
done, tokOut, err := cn.gss.Continue(b)
|
||||
if err == nil && !done {
|
||||
w := cn.writeBuf('p')
|
||||
w.bytes(tokOut)
|
||||
cn.send(w)
|
||||
}
|
||||
|
||||
// Errors fall through and read the more detailed message
|
||||
// from the server..
|
||||
|
||||
case 10:
|
||||
sc := scram.NewClient(sha256.New, o["user"], o["password"])
|
||||
sc.Step(nil)
|
||||
|
@ -1233,7 +1330,7 @@ func (st *stmt) Close() (err error) {
|
|||
if st.closed {
|
||||
return nil
|
||||
}
|
||||
if st.cn.bad {
|
||||
if st.cn.getBad() {
|
||||
return driver.ErrBadConn
|
||||
}
|
||||
defer st.cn.errRecover(&err)
|
||||
|
@ -1247,14 +1344,14 @@ func (st *stmt) Close() (err error) {
|
|||
|
||||
t, _ := st.cn.recv1()
|
||||
if t != '3' {
|
||||
st.cn.bad = true
|
||||
st.cn.setBad()
|
||||
errorf("unexpected close response: %q", t)
|
||||
}
|
||||
st.closed = true
|
||||
|
||||
t, r := st.cn.recv1()
|
||||
if t != 'Z' {
|
||||
st.cn.bad = true
|
||||
st.cn.setBad()
|
||||
errorf("expected ready for query, but got: %q", t)
|
||||
}
|
||||
st.cn.processReadyForQuery(r)
|
||||
|
@ -1263,7 +1360,7 @@ func (st *stmt) Close() (err error) {
|
|||
}
|
||||
|
||||
func (st *stmt) Query(v []driver.Value) (r driver.Rows, err error) {
|
||||
if st.cn.bad {
|
||||
if st.cn.getBad() {
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
defer st.cn.errRecover(&err)
|
||||
|
@ -1276,7 +1373,7 @@ func (st *stmt) Query(v []driver.Value) (r driver.Rows, err error) {
|
|||
}
|
||||
|
||||
func (st *stmt) Exec(v []driver.Value) (res driver.Result, err error) {
|
||||
if st.cn.bad {
|
||||
if st.cn.getBad() {
|
||||
return nil, driver.ErrBadConn
|
||||
}
|
||||
defer st.cn.errRecover(&err)
|
||||
|
@ -1363,7 +1460,7 @@ func (cn *conn) parseComplete(commandTag string) (driver.Result, string) {
|
|||
if affectedRows == nil && strings.HasPrefix(commandTag, "INSERT ") {
|
||||
parts := strings.Split(commandTag, " ")
|
||||
if len(parts) != 3 {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected INSERT command tag %s", commandTag)
|
||||
}
|
||||
affectedRows = &parts[len(parts)-1]
|
||||
|
@ -1375,7 +1472,7 @@ func (cn *conn) parseComplete(commandTag string) (driver.Result, string) {
|
|||
}
|
||||
n, err := strconv.ParseInt(*affectedRows, 10, 64)
|
||||
if err != nil {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("could not parse commandTag: %s", err)
|
||||
}
|
||||
return driver.RowsAffected(n), commandTag
|
||||
|
@ -1442,7 +1539,7 @@ func (rs *rows) Next(dest []driver.Value) (err error) {
|
|||
}
|
||||
|
||||
conn := rs.cn
|
||||
if conn.bad {
|
||||
if conn.getBad() {
|
||||
return driver.ErrBadConn
|
||||
}
|
||||
defer conn.errRecover(&err)
|
||||
|
@ -1467,7 +1564,7 @@ func (rs *rows) Next(dest []driver.Value) (err error) {
|
|||
case 'D':
|
||||
n := rs.rb.int16()
|
||||
if err != nil {
|
||||
conn.bad = true
|
||||
conn.setBad()
|
||||
errorf("unexpected DataRow after error %s", err)
|
||||
}
|
||||
if n < len(dest) {
|
||||
|
@ -1634,10 +1731,9 @@ func (cn *conn) processParameterStatus(r *readBuf) {
|
|||
case "server_version":
|
||||
var major1 int
|
||||
var major2 int
|
||||
var minor int
|
||||
_, err = fmt.Sscanf(r.string(), "%d.%d.%d", &major1, &major2, &minor)
|
||||
_, err = fmt.Sscanf(r.string(), "%d.%d", &major1, &major2)
|
||||
if err == nil {
|
||||
cn.parameterStatus.serverVersion = major1*10000 + major2*100 + minor
|
||||
cn.parameterStatus.serverVersion = major1*10000 + major2*100
|
||||
}
|
||||
|
||||
case "TimeZone":
|
||||
|
@ -1662,7 +1758,7 @@ func (cn *conn) readReadyForQuery() {
|
|||
cn.processReadyForQuery(r)
|
||||
return
|
||||
default:
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected message %q; expected ReadyForQuery", t)
|
||||
}
|
||||
}
|
||||
|
@ -1682,7 +1778,7 @@ func (cn *conn) readParseResponse() {
|
|||
cn.readReadyForQuery()
|
||||
panic(err)
|
||||
default:
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected Parse response %q", t)
|
||||
}
|
||||
}
|
||||
|
@ -1707,7 +1803,7 @@ func (cn *conn) readStatementDescribeResponse() (paramTyps []oid.Oid, colNames [
|
|||
cn.readReadyForQuery()
|
||||
panic(err)
|
||||
default:
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected Describe statement response %q", t)
|
||||
}
|
||||
}
|
||||
|
@ -1725,7 +1821,7 @@ func (cn *conn) readPortalDescribeResponse() rowsHeader {
|
|||
cn.readReadyForQuery()
|
||||
panic(err)
|
||||
default:
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected Describe response %q", t)
|
||||
}
|
||||
panic("not reached")
|
||||
|
@ -1741,7 +1837,7 @@ func (cn *conn) readBindResponse() {
|
|||
cn.readReadyForQuery()
|
||||
panic(err)
|
||||
default:
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected Bind response %q", t)
|
||||
}
|
||||
}
|
||||
|
@ -1768,7 +1864,7 @@ func (cn *conn) postExecuteWorkaround() {
|
|||
cn.saveMessage(t, r)
|
||||
return
|
||||
default:
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected message during extended query execution: %q", t)
|
||||
}
|
||||
}
|
||||
|
@ -1781,7 +1877,7 @@ func (cn *conn) readExecuteResponse(protocolState string) (res driver.Result, co
|
|||
switch t {
|
||||
case 'C':
|
||||
if err != nil {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected CommandComplete after error %s", err)
|
||||
}
|
||||
res, commandTag = cn.parseComplete(r.string())
|
||||
|
@ -1795,7 +1891,7 @@ func (cn *conn) readExecuteResponse(protocolState string) (res driver.Result, co
|
|||
err = parseError(r)
|
||||
case 'T', 'D', 'I':
|
||||
if err != nil {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unexpected %q after error %s", t, err)
|
||||
}
|
||||
if t == 'I' {
|
||||
|
@ -1803,7 +1899,7 @@ func (cn *conn) readExecuteResponse(protocolState string) (res driver.Result, co
|
|||
}
|
||||
// ignore any results
|
||||
default:
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
errorf("unknown %s response: %q", protocolState, t)
|
||||
}
|
||||
}
|
||||
|
|
35
vendor/github.com/lib/pq/conn_go18.go
generated
vendored
35
vendor/github.com/lib/pq/conn_go18.go
generated
vendored
|
@ -7,6 +7,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -89,10 +90,21 @@ func (cn *conn) Ping(ctx context.Context) error {
|
|||
|
||||
func (cn *conn) watchCancel(ctx context.Context) func() {
|
||||
if done := ctx.Done(); done != nil {
|
||||
finished := make(chan struct{})
|
||||
finished := make(chan struct{}, 1)
|
||||
go func() {
|
||||
select {
|
||||
case <-done:
|
||||
select {
|
||||
case finished <- struct{}{}:
|
||||
default:
|
||||
// We raced with the finish func, let the next query handle this with the
|
||||
// context.
|
||||
return
|
||||
}
|
||||
|
||||
// Set the connection state to bad so it does not get reused.
|
||||
cn.setBad()
|
||||
|
||||
// At this point the function level context is canceled,
|
||||
// so it must not be used for the additional network
|
||||
// request to cancel the query.
|
||||
|
@ -101,13 +113,14 @@ func (cn *conn) watchCancel(ctx context.Context) func() {
|
|||
defer cancel()
|
||||
|
||||
_ = cn.cancel(ctxCancel)
|
||||
finished <- struct{}{}
|
||||
case <-finished:
|
||||
}
|
||||
}()
|
||||
return func() {
|
||||
select {
|
||||
case <-finished:
|
||||
cn.setBad()
|
||||
cn.Close()
|
||||
case finished <- struct{}{}:
|
||||
}
|
||||
}
|
||||
|
@ -116,17 +129,29 @@ func (cn *conn) watchCancel(ctx context.Context) func() {
|
|||
}
|
||||
|
||||
func (cn *conn) cancel(ctx context.Context) error {
|
||||
c, err := dial(ctx, cn.dialer, cn.opts)
|
||||
// Create a new values map (copy). This makes sure the connection created
|
||||
// in this method cannot write to the same underlying data, which could
|
||||
// cause a concurrent map write panic. This is necessary because cancel
|
||||
// is called from a goroutine in watchCancel.
|
||||
o := make(values)
|
||||
for k, v := range cn.opts {
|
||||
o[k] = v
|
||||
}
|
||||
|
||||
c, err := dial(ctx, cn.dialer, o)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
{
|
||||
bad := &atomic.Value{}
|
||||
bad.Store(false)
|
||||
can := conn{
|
||||
c: c,
|
||||
c: c,
|
||||
bad: bad,
|
||||
}
|
||||
err = can.ssl(cn.opts)
|
||||
err = can.ssl(o)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
7
vendor/github.com/lib/pq/connector.go
generated
vendored
7
vendor/github.com/lib/pq/connector.go
generated
vendored
|
@ -27,7 +27,7 @@ func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) {
|
|||
return c.open(ctx)
|
||||
}
|
||||
|
||||
// Driver returnst the underlying driver of this Connector.
|
||||
// Driver returns the underlying driver of this Connector.
|
||||
func (c *Connector) Driver() driver.Driver {
|
||||
return &Driver{}
|
||||
}
|
||||
|
@ -106,5 +106,10 @@ func NewConnector(dsn string) (*Connector, error) {
|
|||
o["user"] = u
|
||||
}
|
||||
|
||||
// SSL is not necessary or supported over UNIX domain sockets
|
||||
if network, _ := network(o); network == "unix" {
|
||||
o["sslmode"] = "disable"
|
||||
}
|
||||
|
||||
return &Connector{opts: o, dialer: defaultDialer{}}, nil
|
||||
}
|
||||
|
|
29
vendor/github.com/lib/pq/copy.go
generated
vendored
29
vendor/github.com/lib/pq/copy.go
generated
vendored
|
@ -49,6 +49,7 @@ type copyin struct {
|
|||
buffer []byte
|
||||
rowData chan []byte
|
||||
done chan bool
|
||||
driver.Result
|
||||
|
||||
closed bool
|
||||
|
||||
|
@ -151,6 +152,8 @@ func (ci *copyin) resploop() {
|
|||
switch t {
|
||||
case 'C':
|
||||
// complete
|
||||
res, _ := ci.cn.parseComplete(r.string())
|
||||
ci.setResult(res)
|
||||
case 'N':
|
||||
if n := ci.cn.noticeHandler; n != nil {
|
||||
n(parseError(&r))
|
||||
|
@ -173,13 +176,13 @@ func (ci *copyin) resploop() {
|
|||
|
||||
func (ci *copyin) setBad() {
|
||||
ci.Lock()
|
||||
ci.cn.bad = true
|
||||
ci.cn.setBad()
|
||||
ci.Unlock()
|
||||
}
|
||||
|
||||
func (ci *copyin) isBad() bool {
|
||||
ci.Lock()
|
||||
b := ci.cn.bad
|
||||
b := ci.cn.getBad()
|
||||
ci.Unlock()
|
||||
return b
|
||||
}
|
||||
|
@ -201,6 +204,22 @@ func (ci *copyin) setError(err error) {
|
|||
ci.Unlock()
|
||||
}
|
||||
|
||||
func (ci *copyin) setResult(result driver.Result) {
|
||||
ci.Lock()
|
||||
ci.Result = result
|
||||
ci.Unlock()
|
||||
}
|
||||
|
||||
func (ci *copyin) getResult() driver.Result {
|
||||
ci.Lock()
|
||||
result := ci.Result
|
||||
ci.Unlock()
|
||||
if result == nil {
|
||||
return driver.RowsAffected(0)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (ci *copyin) NumInput() int {
|
||||
return -1
|
||||
}
|
||||
|
@ -231,7 +250,11 @@ func (ci *copyin) Exec(v []driver.Value) (r driver.Result, err error) {
|
|||
}
|
||||
|
||||
if len(v) == 0 {
|
||||
return driver.RowsAffected(0), ci.Close()
|
||||
if err := ci.Close(); err != nil {
|
||||
return driver.RowsAffected(0), err
|
||||
}
|
||||
|
||||
return ci.getResult(), nil
|
||||
}
|
||||
|
||||
numValues := len(v)
|
||||
|
|
23
vendor/github.com/lib/pq/doc.go
generated
vendored
23
vendor/github.com/lib/pq/doc.go
generated
vendored
|
@ -241,5 +241,28 @@ bytes by the PostgreSQL server.
|
|||
You can find a complete, working example of Listener usage at
|
||||
https://godoc.org/github.com/lib/pq/example/listen.
|
||||
|
||||
|
||||
Kerberos Support
|
||||
|
||||
|
||||
If you need support for Kerberos authentication, add the following to your main
|
||||
package:
|
||||
|
||||
import "github.com/lib/pq/auth/kerberos"
|
||||
|
||||
func init() {
|
||||
pq.RegisterGSSProvider(func() (pq.Gss, error) { return kerberos.NewGSS() })
|
||||
}
|
||||
|
||||
This package is in a separate module so that users who don't need Kerberos
|
||||
don't have to download unnecessary dependencies.
|
||||
|
||||
When imported, additional connection string parameters are supported:
|
||||
|
||||
* krbsrvname - GSS (Kerberos) service name when constructing the
|
||||
SPN (default is `postgres`). This will be combined with the host
|
||||
to form the full SPN: `krbsrvname/host`.
|
||||
* krbspn - GSS (Kerberos) SPN. This takes priority over
|
||||
`krbsrvname` if present.
|
||||
*/
|
||||
package pq
|
||||
|
|
14
vendor/github.com/lib/pq/encode.go
generated
vendored
14
vendor/github.com/lib/pq/encode.go
generated
vendored
|
@ -200,11 +200,17 @@ func appendEscapedText(buf []byte, text string) []byte {
|
|||
func mustParse(f string, typ oid.Oid, s []byte) time.Time {
|
||||
str := string(s)
|
||||
|
||||
// check for a 30-minute-offset timezone
|
||||
if (typ == oid.T_timestamptz || typ == oid.T_timetz) &&
|
||||
str[len(str)-3] == ':' {
|
||||
f += ":00"
|
||||
// Check for a minute and second offset in the timezone.
|
||||
if typ == oid.T_timestamptz || typ == oid.T_timetz {
|
||||
for i := 3; i <= 6; i += 3 {
|
||||
if str[len(str)-i] == ':' {
|
||||
f += ":00"
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Special case for 24:00 time.
|
||||
// Unfortunately, golang does not parse 24:00 as a proper time.
|
||||
// In this case, we want to try "round to the next day", to differentiate.
|
||||
|
|
11
vendor/github.com/lib/pq/error.go
generated
vendored
11
vendor/github.com/lib/pq/error.go
generated
vendored
|
@ -484,7 +484,7 @@ func (cn *conn) errRecover(err *error) {
|
|||
case nil:
|
||||
// Do nothing
|
||||
case runtime.Error:
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
panic(v)
|
||||
case *Error:
|
||||
if v.Fatal() {
|
||||
|
@ -493,8 +493,11 @@ func (cn *conn) errRecover(err *error) {
|
|||
*err = v
|
||||
}
|
||||
case *net.OpError:
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
*err = v
|
||||
case *safeRetryError:
|
||||
cn.setBad()
|
||||
*err = driver.ErrBadConn
|
||||
case error:
|
||||
if v == io.EOF || v.(error).Error() == "remote error: handshake failure" {
|
||||
*err = driver.ErrBadConn
|
||||
|
@ -503,13 +506,13 @@ func (cn *conn) errRecover(err *error) {
|
|||
}
|
||||
|
||||
default:
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
panic(fmt.Sprintf("unknown error: %#v", e))
|
||||
}
|
||||
|
||||
// Any time we return ErrBadConn, we need to remember it since *Tx doesn't
|
||||
// mark the connection bad in database/sql.
|
||||
if *err == driver.ErrBadConn {
|
||||
cn.bad = true
|
||||
cn.setBad()
|
||||
}
|
||||
}
|
||||
|
|
27
vendor/github.com/lib/pq/krb.go
generated
vendored
Normal file
27
vendor/github.com/lib/pq/krb.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
package pq
|
||||
|
||||
// NewGSSFunc creates a GSS authentication provider, for use with
|
||||
// RegisterGSSProvider.
|
||||
type NewGSSFunc func() (GSS, error)
|
||||
|
||||
var newGss NewGSSFunc
|
||||
|
||||
// RegisterGSSProvider registers a GSS authentication provider. For example, if
|
||||
// you need to use Kerberos to authenticate with your server, add this to your
|
||||
// main package:
|
||||
//
|
||||
// import "github.com/lib/pq/auth/kerberos"
|
||||
//
|
||||
// func init() {
|
||||
// pq.RegisterGSSProvider(func() (pq.GSS, error) { return kerberos.NewGSS() })
|
||||
// }
|
||||
func RegisterGSSProvider(newGssArg NewGSSFunc) {
|
||||
newGss = newGssArg
|
||||
}
|
||||
|
||||
// GSS provides GSSAPI authentication (e.g., Kerberos).
|
||||
type GSS interface {
|
||||
GetInitToken(host string, service string) ([]byte, error)
|
||||
GetInitTokenFromSpn(spn string) ([]byte, error)
|
||||
Continue(inToken []byte) (done bool, outToken []byte, err error)
|
||||
}
|
24
vendor/github.com/lib/pq/ssl.go
generated
vendored
24
vendor/github.com/lib/pq/ssl.go
generated
vendored
|
@ -83,6 +83,16 @@ func ssl(o values) (func(net.Conn) (net.Conn, error), error) {
|
|||
// in the user's home directory. The configured files must exist and have
|
||||
// the correct permissions.
|
||||
func sslClientCertificates(tlsConf *tls.Config, o values) error {
|
||||
sslinline := o["sslinline"]
|
||||
if sslinline == "true" {
|
||||
cert, err := tls.X509KeyPair([]byte(o["sslcert"]), []byte(o["sslkey"]))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tlsConf.Certificates = []tls.Certificate{cert}
|
||||
return nil
|
||||
}
|
||||
|
||||
// user.Current() might fail when cross-compiling. We have to ignore the
|
||||
// error and continue without home directory defaults, since we wouldn't
|
||||
// know from where to load them.
|
||||
|
@ -137,9 +147,17 @@ func sslCertificateAuthority(tlsConf *tls.Config, o values) error {
|
|||
if sslrootcert := o["sslrootcert"]; len(sslrootcert) > 0 {
|
||||
tlsConf.RootCAs = x509.NewCertPool()
|
||||
|
||||
cert, err := ioutil.ReadFile(sslrootcert)
|
||||
if err != nil {
|
||||
return err
|
||||
sslinline := o["sslinline"]
|
||||
|
||||
var cert []byte
|
||||
if sslinline == "true" {
|
||||
cert = []byte(sslrootcert)
|
||||
} else {
|
||||
var err error
|
||||
cert, err = ioutil.ReadFile(sslrootcert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !tlsConf.RootCAs.AppendCertsFromPEM(cert) {
|
||||
|
|
4
vendor/github.com/lib/pq/url.go
generated
vendored
4
vendor/github.com/lib/pq/url.go
generated
vendored
|
@ -40,10 +40,10 @@ func ParseURL(url string) (string, error) {
|
|||
}
|
||||
|
||||
var kvs []string
|
||||
escaper := strings.NewReplacer(` `, `\ `, `'`, `\'`, `\`, `\\`)
|
||||
escaper := strings.NewReplacer(`'`, `\'`, `\`, `\\`)
|
||||
accrue := func(k, v string) {
|
||||
if v != "" {
|
||||
kvs = append(kvs, k+"="+escaper.Replace(v))
|
||||
kvs = append(kvs, k+"='"+escaper.Replace(v)+"'")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
9
vendor/github.com/lib/pq/user_other.go
generated
vendored
Normal file
9
vendor/github.com/lib/pq/user_other.go
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
// Package pq is a pure Go Postgres driver for the database/sql package.
|
||||
|
||||
// +build js android hurd illumos zos
|
||||
|
||||
package pq
|
||||
|
||||
func userCurrent() (string, error) {
|
||||
return "", ErrCouldNotDetectUsername
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue