MM-10934 Update server dependencies. (#8981)

* Changing throttled import path.

* Upgrading dependencies.
Этот коммит содержится в:
Christopher Speller
2018-06-21 13:10:40 -07:00
коммит произвёл Harrison Healey
родитель a59ccaa8b3
Коммит 8526739066
270 изменённых файлов: 31454 добавлений и 13563 удалений

118
Gopkg.lock сгенерированный
Просмотреть файл

@@ -11,7 +11,7 @@
branch = "master" branch = "master"
name = "github.com/armon/go-metrics" name = "github.com/armon/go-metrics"
packages = ["."] packages = ["."]
revision = "783273d703149aaeb9897cf58613d5af48861c25" revision = "58588f401c2cc130a7308a52ca3bc6c0a76db04b"
[[projects]] [[projects]]
branch = "master" branch = "master"
@@ -70,8 +70,8 @@
[[projects]] [[projects]]
name = "github.com/go-ini/ini" name = "github.com/go-ini/ini"
packages = ["."] packages = ["."]
revision = "6529cf7c58879c08d927016dde4477f18a0634cb" revision = "06f5f3d67269ccec1fe5fe4134ba6e982984f7f5"
version = "v1.36.0" version = "v1.37.0"
[[projects]] [[projects]]
name = "github.com/go-ldap/ldap" name = "github.com/go-ldap/ldap"
@@ -91,14 +91,14 @@
"internal/singleflight", "internal/singleflight",
"internal/util" "internal/util"
] ]
revision = "877867d2845fbaf86798befe410b6ceb6f5c29a3" revision = "83fb42932f6145ce52df09860384a4653d2d332a"
version = "v6.10.2" version = "v6.12.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
name = "github.com/go-sql-driver/mysql" name = "github.com/go-sql-driver/mysql"
packages = ["."] packages = ["."]
revision = "3287d94d4c6a48a63e16fffaabf27ab20203af2a" revision = "749ddf1598b47e3cd909414bda735fe790ef3d30"
[[projects]] [[projects]]
branch = "master" branch = "master"
@@ -144,13 +144,13 @@
branch = "master" branch = "master"
name = "github.com/gorilla/websocket" name = "github.com/gorilla/websocket"
packages = ["."] packages = ["."]
revision = "21ab95fa12b9bdd8fecf5fa3586aad941cc98785" revision = "5ed622c449da6d44c3c8329331ff47a9e5844f71"
[[projects]] [[projects]]
branch = "master" branch = "master"
name = "github.com/hako/durafmt" name = "github.com/hako/durafmt"
packages = ["."] packages = ["."]
revision = "fddaacea1c7eb9c0aa2ec13a6f92e0a4ced16618" revision = "7b7ae1e72eade09dbc9c2cfba3e6c4bae7b8bcac"
[[projects]] [[projects]]
branch = "master" branch = "master"
@@ -230,7 +230,7 @@
branch = "master" branch = "master"
name = "github.com/jaytaylor/html2text" name = "github.com/jaytaylor/html2text"
packages = ["."] packages = ["."]
revision = "64a82a6d140778896f13303121a49d8cb8007034" revision = "57d518f124b0cf46ea2021f25a01396b3522e6fb"
[[projects]] [[projects]]
branch = "master" branch = "master"
@@ -245,7 +245,7 @@
".", ".",
"oid" "oid"
] ]
revision = "d34b9ff171c21ad295489235aec8b6626023cd04" revision = "90697d60dd844d5ef6ff15135d0203f65d2f53b8"
[[projects]] [[projects]]
name = "github.com/magiconair/properties" name = "github.com/magiconair/properties"
@@ -262,7 +262,7 @@
"jlexer", "jlexer",
"jwriter" "jwriter"
] ]
revision = "8b799c424f57fa123fc63a99d6383bc6e4c02578" revision = "3fdea8d05856a0c8df22ed4bc71b3219245e4485"
[[projects]] [[projects]]
branch = "master" branch = "master"
@@ -280,6 +280,13 @@
] ]
revision = "bbaefb05eaa0389ea712340066837c8ce4d287f9" revision = "bbaefb05eaa0389ea712340066837c8ce4d287f9"
[[projects]]
branch = "mattermost"
name = "github.com/mattermost/viper"
packages = ["."]
revision = "1b00ce64485c7a2449f239de3cbc9040a9c46aa0"
source = "https://github.com/mattermost/viper"
[[projects]] [[projects]]
name = "github.com/mattn/go-runewidth" name = "github.com/mattn/go-runewidth"
packages = ["."] packages = ["."]
@@ -289,20 +296,20 @@
[[projects]] [[projects]]
name = "github.com/mattn/go-sqlite3" name = "github.com/mattn/go-sqlite3"
packages = ["."] packages = ["."]
revision = "6c771bb9887719704b210e87e934f08be014bdb1" revision = "25ecb14adfc7543176f7d85291ec7dba82c6f7e4"
version = "v1.6.0" version = "v1.9.0"
[[projects]] [[projects]]
name = "github.com/matttproud/golang_protobuf_extensions" name = "github.com/matttproud/golang_protobuf_extensions"
packages = ["pbutil"] packages = ["pbutil"]
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c" revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
version = "v1.0.0" version = "v1.0.1"
[[projects]] [[projects]]
name = "github.com/miekg/dns" name = "github.com/miekg/dns"
packages = ["."] packages = ["."]
revision = "e57bf427e68187a27e22adceac868350d7a7079b" revision = "5a2b9fab83ff0f8bfc99684bd5f43a37abe560f1"
version = "v1.0.7" version = "v1.0.8"
[[projects]] [[projects]]
name = "github.com/minio/minio-go" name = "github.com/minio/minio-go"
@@ -314,14 +321,14 @@
"pkg/s3utils", "pkg/s3utils",
"pkg/set" "pkg/set"
] ]
revision = "c6108c47ba5d86548404ebf9e51c5ca18769fe79" revision = "33b767f5638ccaf7cc30516ec54024d3e58a8209"
version = "6.0.1" version = "v6.0.3"
[[projects]] [[projects]]
branch = "master" branch = "master"
name = "github.com/mitchellh/go-homedir" name = "github.com/mitchellh/go-homedir"
packages = ["."] packages = ["."]
revision = "b8bc1bf767474819792c23f32d8286a45736f1c6" revision = "3864e76763d94a6df2f9960b16a20a33da9f9a66"
[[projects]] [[projects]]
branch = "master" branch = "master"
@@ -355,8 +362,8 @@
[[projects]] [[projects]]
name = "github.com/pelletier/go-toml" name = "github.com/pelletier/go-toml"
packages = ["."] packages = ["."]
revision = "acdc4509485b587f5e675510c4f2c63e90ff68a8" revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194"
version = "v1.1.0" version = "v1.2.0"
[[projects]] [[projects]]
name = "github.com/pkg/errors" name = "github.com/pkg/errors"
@@ -393,7 +400,7 @@
"internal/bitbucket.org/ww/goautoneg", "internal/bitbucket.org/ww/goautoneg",
"model" "model"
] ]
revision = "d811d2e9bf898806ecfb6ef6296774b13ffc314c" revision = "7600349dcfe1abd18d72d3a1770870d9800a7801"
[[projects]] [[projects]]
branch = "master" branch = "master"
@@ -404,7 +411,7 @@
"nfs", "nfs",
"xfs" "xfs"
] ]
revision = "8b1c2da0d56deffdbb9e48d4414b4e674bd8083e" revision = "7d6f385de8bea29190f15ba9931442a0eaef9af7"
[[projects]] [[projects]]
branch = "go1" branch = "go1"
@@ -413,7 +420,7 @@
"exif", "exif",
"tiff" "tiff"
] ]
revision = "fb35d3c3290d09f3524b684b5d42d0063c227158" revision = "8d986c03457a2057c7b0fb0a48113f7dd48f9619"
[[projects]] [[projects]]
branch = "master" branch = "master"
@@ -445,8 +452,8 @@
".", ".",
"mem" "mem"
] ]
revision = "63644898a8da0bc22138abf860edaf5277b6102e" revision = "787d034dfe70e44075ccc060d346146ef53270ad"
version = "v1.1.0" version = "v1.1.1"
[[projects]] [[projects]]
name = "github.com/spf13/cast" name = "github.com/spf13/cast"
@@ -472,13 +479,6 @@
revision = "583c0c0531f06d5278b7d917446061adc344b5cd" revision = "583c0c0531f06d5278b7d917446061adc344b5cd"
version = "v1.0.1" version = "v1.0.1"
[[projects]]
branch = "mattermost"
name = "github.com/mattermost/viper"
packages = ["."]
revision = "1b00ce64485c7a2449f239de3cbc9040a9c46aa0"
source = "https://github.com/mattermost/viper"
[[projects]] [[projects]]
branch = "master" branch = "master"
name = "github.com/ssor/bom" name = "github.com/ssor/bom"
@@ -488,8 +488,8 @@
[[projects]] [[projects]]
name = "github.com/stretchr/objx" name = "github.com/stretchr/objx"
packages = ["."] packages = ["."]
revision = "facf9a85c22f48d2f52f2380e4efce1768749a89" revision = "477a77ecc69700c7cdeb1fa9e129548e1c1c393c"
version = "v0.1" version = "v0.1.1"
[[projects]] [[projects]]
name = "github.com/stretchr/testify" name = "github.com/stretchr/testify"
@@ -499,8 +499,17 @@
"require", "require",
"suite" "suite"
] ]
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71" revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
version = "v1.2.1" version = "v1.2.2"
[[projects]]
name = "github.com/throttled/throttled"
packages = [
".",
"store/memstore"
]
revision = "aeea1c7338e6dd1e1b309afe07fb7bbcfa83c2fa"
version = "v2.2.1"
[[projects]] [[projects]]
name = "github.com/tylerb/graceful" name = "github.com/tylerb/graceful"
@@ -553,7 +562,7 @@
"ed25519/internal/edwards25519", "ed25519/internal/edwards25519",
"ssh/terminal" "ssh/terminal"
] ]
revision = "1a580b3eff7814fc9b40602fd35256c63b50f491" revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602"
[[projects]] [[projects]]
branch = "master" branch = "master"
@@ -565,24 +574,24 @@
"tiff", "tiff",
"tiff/lzw" "tiff/lzw"
] ]
revision = "f315e440302883054d0c2bd85486878cb4f8572c" revision = "af66defab954cb421ca110193eed9477c8541e2a"
[[projects]] [[projects]]
branch = "release-branch.go1.10" branch = "master"
name = "golang.org/x/net" name = "golang.org/x/net"
packages = [ packages = [
"bpf", "bpf",
"html", "html",
"html/atom", "html/atom",
"html/charset", "html/charset",
"http/httpguts",
"idna", "idna",
"internal/iana", "internal/iana",
"internal/socket", "internal/socket",
"ipv4", "ipv4",
"ipv6", "ipv6"
"lex/httplex"
] ]
revision = "0ed95abb35c445290478a5348a7b38bb154135fd" revision = "afe8f62b1d6bbd81f31868121a50b06d8188e1f9"
[[projects]] [[projects]]
branch = "master" branch = "master"
@@ -592,7 +601,7 @@
"unix", "unix",
"windows" "windows"
] ]
revision = "7c87d13f8e835d2fb3a70a2912c811ed0c1d241b" revision = "ad87a3a340fa7f3bed189293fbfa7a9b7e021ae1"
[[projects]] [[projects]]
name = "golang.org/x/text" name = "golang.org/x/text"
@@ -630,8 +639,8 @@
[[projects]] [[projects]]
name = "google.golang.org/appengine" name = "google.golang.org/appengine"
packages = ["cloudsql"] packages = ["cloudsql"]
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a" revision = "b1f26356af11148e710935ed1ac8a7f5702c7612"
version = "v1.0.0" version = "v1.1.0"
[[projects]] [[projects]]
branch = "v3" branch = "v3"
@@ -664,17 +673,8 @@
"config", "config",
"uritemplates" "uritemplates"
] ]
revision = "2562d7254d4655c3bcf34810cdb4ca45e944d53f" revision = "b708306d715bea9b983685e94ab4602cdc9f988b"
version = "v5.0.68" version = "v5.0.69"
[[projects]]
name = "gopkg.in/throttled/throttled.v2"
packages = [
".",
"store/memstore"
]
revision = "b5675e93f9d999b22f92d859a5bf2138d3641af4"
version = "v2.0.3"
[[projects]] [[projects]]
name = "gopkg.in/yaml.v2" name = "gopkg.in/yaml.v2"
@@ -685,6 +685,6 @@
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
inputs-digest = "463ec98eba9cac751c2702ca1ecae98740d7dd9a1dc8b615b484ea4bdb41f6b5" inputs-digest = "76d5a63bc94bc0a75fe311cbc1df579fdd77b5d039a006236c00ee122ab69c1b"
solver-name = "gps-cdcl" solver-name = "gps-cdcl"
solver-version = 1 solver-version = 1

Просмотреть файл

@@ -14,8 +14,8 @@ import (
"github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/utils" "github.com/mattermost/mattermost-server/utils"
"github.com/pkg/errors" "github.com/pkg/errors"
throttled "gopkg.in/throttled/throttled.v2" "github.com/throttled/throttled"
"gopkg.in/throttled/throttled.v2/store/memstore" "github.com/throttled/throttled/store/memstore"
) )
type RateLimiter struct { type RateLimiter struct {

23
vendor/github.com/armon/go-metrics/README.md сгенерированный поставляемый
Просмотреть файл

@@ -7,7 +7,7 @@ expose application metrics, and profile runtime performance in a flexible manner
Current API: [![GoDoc](https://godoc.org/github.com/armon/go-metrics?status.svg)](https://godoc.org/github.com/armon/go-metrics) Current API: [![GoDoc](https://godoc.org/github.com/armon/go-metrics?status.svg)](https://godoc.org/github.com/armon/go-metrics)
Sinks Sinks
===== -----
The `metrics` package makes use of a `MetricSink` interface to support delivery The `metrics` package makes use of a `MetricSink` interface to support delivery
to any type of backend. Currently the following sinks are provided: to any type of backend. Currently the following sinks are provided:
@@ -23,8 +23,26 @@ In addition to the sinks, the `InmemSignal` can be used to catch a signal,
and dump a formatted output of recent metrics. For example, when a process gets and dump a formatted output of recent metrics. For example, when a process gets
a SIGUSR1, it can dump to stderr recent performance metrics for debugging. a SIGUSR1, it can dump to stderr recent performance metrics for debugging.
Labels
------
Most metrics do have an equivalent ending with `WithLabels`, such methods
allow to push metrics with labels and use some features of underlying Sinks
(ex: translated into Prometheus labels).
Since some of these labels may increase greatly cardinality of metrics, the
library allow to filter labels using a blacklist/whitelist filtering system
which is global to all metrics.
* If `Config.AllowedLabels` is not nil, then only labels specified in this value will be sent to underlying Sink, otherwise, all labels are sent by default.
* If `Config.BlockedLabels` is not nil, any label specified in this value will not be sent to underlying Sinks.
By default, both `Config.AllowedLabels` and `Config.BlockedLabels` are nil, meaning that
no tags are filetered at all, but it allow to a user to globally block some tags with high
cardinality at application level.
Examples Examples
======== --------
Here is an example of using the package: Here is an example of using the package:
@@ -71,4 +89,3 @@ When a signal comes in, output like the following will be dumped to stderr:
[2014-01-28 14:57:33.04 -0800 PST][P] 'bar': 30.000 [2014-01-28 14:57:33.04 -0800 PST][P] 'bar': 30.000
[2014-01-28 14:57:33.04 -0800 PST][C] 'baz': Count: 3 Min: 1.000 Mean: 41.000 Max: 80.000 Stddev: 39.509 [2014-01-28 14:57:33.04 -0800 PST][C] 'baz': Count: 3 Min: 1.000 Mean: 41.000 Max: 80.000 Stddev: 39.509
[2014-01-28 14:57:33.04 -0800 PST][S] 'method.wow': Count: 3 Min: 22.000 Mean: 54.667 Max: 100.000 Stddev: 40.513 [2014-01-28 14:57:33.04 -0800 PST][S] 'method.wow': Count: 3 Min: 22.000 Mean: 54.667 Max: 100.000 Stddev: 40.513

88
vendor/github.com/armon/go-metrics/metrics.go сгенерированный поставляемый
Просмотреть файл

@@ -35,10 +35,11 @@ func (m *Metrics) SetGaugeWithLabels(key []string, val float32, labels []Label)
key = insert(0, m.ServiceName, key) key = insert(0, m.ServiceName, key)
} }
} }
if !m.allowMetric(key) { allowed, labelsFiltered := m.allowMetric(key, labels)
if !allowed {
return return
} }
m.sink.SetGaugeWithLabels(key, val, labels) m.sink.SetGaugeWithLabels(key, val, labelsFiltered)
} }
func (m *Metrics) EmitKey(key []string, val float32) { func (m *Metrics) EmitKey(key []string, val float32) {
@@ -48,7 +49,8 @@ func (m *Metrics) EmitKey(key []string, val float32) {
if m.ServiceName != "" { if m.ServiceName != "" {
key = insert(0, m.ServiceName, key) key = insert(0, m.ServiceName, key)
} }
if !m.allowMetric(key) { allowed, _ := m.allowMetric(key, nil)
if !allowed {
return return
} }
m.sink.EmitKey(key, val) m.sink.EmitKey(key, val)
@@ -72,10 +74,11 @@ func (m *Metrics) IncrCounterWithLabels(key []string, val float32, labels []Labe
key = insert(0, m.ServiceName, key) key = insert(0, m.ServiceName, key)
} }
} }
if !m.allowMetric(key) { allowed, labelsFiltered := m.allowMetric(key, labels)
if !allowed {
return return
} }
m.sink.IncrCounterWithLabels(key, val, labels) m.sink.IncrCounterWithLabels(key, val, labelsFiltered)
} }
func (m *Metrics) AddSample(key []string, val float32) { func (m *Metrics) AddSample(key []string, val float32) {
@@ -96,10 +99,11 @@ func (m *Metrics) AddSampleWithLabels(key []string, val float32, labels []Label)
key = insert(0, m.ServiceName, key) key = insert(0, m.ServiceName, key)
} }
} }
if !m.allowMetric(key) { allowed, labelsFiltered := m.allowMetric(key, labels)
if !allowed {
return return
} }
m.sink.AddSampleWithLabels(key, val, labels) m.sink.AddSampleWithLabels(key, val, labelsFiltered)
} }
func (m *Metrics) MeasureSince(key []string, start time.Time) { func (m *Metrics) MeasureSince(key []string, start time.Time) {
@@ -120,23 +124,45 @@ func (m *Metrics) MeasureSinceWithLabels(key []string, start time.Time, labels [
key = insert(0, m.ServiceName, key) key = insert(0, m.ServiceName, key)
} }
} }
if !m.allowMetric(key) { allowed, labelsFiltered := m.allowMetric(key, labels)
if !allowed {
return return
} }
now := time.Now() now := time.Now()
elapsed := now.Sub(start) elapsed := now.Sub(start)
msec := float32(elapsed.Nanoseconds()) / float32(m.TimerGranularity) msec := float32(elapsed.Nanoseconds()) / float32(m.TimerGranularity)
m.sink.AddSampleWithLabels(key, msec, labels) m.sink.AddSampleWithLabels(key, msec, labelsFiltered)
} }
// UpdateFilter overwrites the existing filter with the given rules. // UpdateFilter overwrites the existing filter with the given rules.
func (m *Metrics) UpdateFilter(allow, block []string) { func (m *Metrics) UpdateFilter(allow, block []string) {
m.UpdateFilterAndLabels(allow, block, m.AllowedLabels, m.BlockedLabels)
}
// UpdateFilterAndLabels overwrites the existing filter with the given rules.
func (m *Metrics) UpdateFilterAndLabels(allow, block, allowedLabels, blockedLabels []string) {
m.filterLock.Lock() m.filterLock.Lock()
defer m.filterLock.Unlock() defer m.filterLock.Unlock()
m.AllowedPrefixes = allow m.AllowedPrefixes = allow
m.BlockedPrefixes = block m.BlockedPrefixes = block
if allowedLabels == nil {
// Having a white list means we take only elements from it
m.allowedLabels = nil
} else {
m.allowedLabels = make(map[string]bool)
for _, v := range allowedLabels {
m.allowedLabels[v] = true
}
}
m.blockedLabels = make(map[string]bool)
for _, v := range blockedLabels {
m.blockedLabels[v] = true
}
m.AllowedLabels = allowedLabels
m.BlockedLabels = blockedLabels
m.filter = iradix.New() m.filter = iradix.New()
for _, prefix := range m.AllowedPrefixes { for _, prefix := range m.AllowedPrefixes {
m.filter, _, _ = m.filter.Insert([]byte(prefix), true) m.filter, _, _ = m.filter.Insert([]byte(prefix), true)
@@ -146,20 +172,56 @@ func (m *Metrics) UpdateFilter(allow, block []string) {
} }
} }
// labelIsAllowed return true if a should be included in metric
// the caller should lock m.filterLock while calling this method
func (m *Metrics) labelIsAllowed(label *Label) bool {
labelName := (*label).Name
if m.blockedLabels != nil {
_, ok := m.blockedLabels[labelName]
if ok {
// If present, let's remove this label
return false
}
}
if m.allowedLabels != nil {
_, ok := m.allowedLabels[labelName]
return ok
}
// Allow by default
return true
}
// filterLabels return only allowed labels
// the caller should lock m.filterLock while calling this method
func (m *Metrics) filterLabels(labels []Label) []Label {
if labels == nil {
return nil
}
toReturn := labels[:0]
for _, label := range labels {
if m.labelIsAllowed(&label) {
toReturn = append(toReturn, label)
}
}
return toReturn
}
// Returns whether the metric should be allowed based on configured prefix filters // Returns whether the metric should be allowed based on configured prefix filters
func (m *Metrics) allowMetric(key []string) bool { // Also return the applicable labels
func (m *Metrics) allowMetric(key []string, labels []Label) (bool, []Label) {
m.filterLock.RLock() m.filterLock.RLock()
defer m.filterLock.RUnlock() defer m.filterLock.RUnlock()
if m.filter == nil || m.filter.Len() == 0 { if m.filter == nil || m.filter.Len() == 0 {
return m.Config.FilterDefault return m.Config.FilterDefault, m.filterLabels(labels)
} }
_, allowed, ok := m.filter.Root().LongestPrefix([]byte(strings.Join(key, "."))) _, allowed, ok := m.filter.Root().LongestPrefix([]byte(strings.Join(key, ".")))
if !ok { if !ok {
return m.Config.FilterDefault return m.Config.FilterDefault, m.filterLabels(labels)
} }
return allowed.(bool)
return allowed.(bool), m.filterLabels(labels)
} }
// Periodically collects runtime stats to publish // Periodically collects runtime stats to publish

22
vendor/github.com/armon/go-metrics/start.go сгенерированный поставляемый
Просмотреть файл

@@ -23,6 +23,8 @@ type Config struct {
AllowedPrefixes []string // A list of metric prefixes to allow, with '.' as the separator AllowedPrefixes []string // A list of metric prefixes to allow, with '.' as the separator
BlockedPrefixes []string // A list of metric prefixes to block, with '.' as the separator BlockedPrefixes []string // A list of metric prefixes to block, with '.' as the separator
AllowedLabels []string // A list of metric labels to allow, with '.' as the separator
BlockedLabels []string // A list of metric labels to block, with '.' as the separator
FilterDefault bool // Whether to allow metrics by default FilterDefault bool // Whether to allow metrics by default
} }
@@ -30,10 +32,12 @@ type Config struct {
// be used to emit // be used to emit
type Metrics struct { type Metrics struct {
Config Config
lastNumGC uint32 lastNumGC uint32
sink MetricSink sink MetricSink
filter *iradix.Tree filter *iradix.Tree
filterLock sync.RWMutex allowedLabels map[string]bool
blockedLabels map[string]bool
filterLock sync.RWMutex // Lock filters and allowedLabels/blockedLabels access
} }
// Shared global metrics instance // Shared global metrics instance
@@ -68,7 +72,7 @@ func New(conf *Config, sink MetricSink) (*Metrics, error) {
met := &Metrics{} met := &Metrics{}
met.Config = *conf met.Config = *conf
met.sink = sink met.sink = sink
met.UpdateFilter(conf.AllowedPrefixes, conf.BlockedPrefixes) met.UpdateFilterAndLabels(conf.AllowedPrefixes, conf.BlockedPrefixes, conf.AllowedLabels, conf.BlockedLabels)
// Start the runtime collector // Start the runtime collector
if conf.EnableRuntimeMetrics { if conf.EnableRuntimeMetrics {
@@ -127,3 +131,11 @@ func MeasureSinceWithLabels(key []string, start time.Time, labels []Label) {
func UpdateFilter(allow, block []string) { func UpdateFilter(allow, block []string) {
globalMetrics.Load().(*Metrics).UpdateFilter(allow, block) globalMetrics.Load().(*Metrics).UpdateFilter(allow, block)
} }
// UpdateFilterAndLabels set allow/block prefixes of metrics while allowedLabels
// and blockedLabels - when not nil - allow filtering of labels in order to
// block/allow globally labels (especially useful when having large number of
// values for a given label). See README.md for more information about usage.
func UpdateFilterAndLabels(allow, block, allowedLabels, blockedLabels []string) {
globalMetrics.Load().(*Metrics).UpdateFilterAndLabels(allow, block, allowedLabels, blockedLabels)
}

1
vendor/github.com/go-ini/ini/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -13,4 +13,5 @@ script:
- go get github.com/smartystreets/goconvey - go get github.com/smartystreets/goconvey
- mkdir -p $HOME/gopath/src/gopkg.in - mkdir -p $HOME/gopath/src/gopkg.in
- ln -s $HOME/gopath/src/github.com/go-ini/ini $HOME/gopath/src/gopkg.in/ini.v1 - ln -s $HOME/gopath/src/github.com/go-ini/ini $HOME/gopath/src/gopkg.in/ini.v1
- cd $HOME/gopath/src/gopkg.in/ini.v1
- go test -v -cover -race - go test -v -cover -race

7
vendor/github.com/go-ini/ini/ini.go сгенерированный поставляемый
Просмотреть файл

@@ -32,7 +32,7 @@ const (
// Maximum allowed depth when recursively substituing variable names. // Maximum allowed depth when recursively substituing variable names.
_DEPTH_VALUES = 99 _DEPTH_VALUES = 99
_VERSION = "1.36.0" _VERSION = "1.37.0"
) )
// Version returns current package version literal. // Version returns current package version literal.
@@ -145,6 +145,11 @@ type LoadOptions struct {
// Relevant quote: Values can also span multiple lines, as long as they are indented deeper // Relevant quote: Values can also span multiple lines, as long as they are indented deeper
// than the first line of the value. // than the first line of the value.
AllowPythonMultilineValues bool AllowPythonMultilineValues bool
// SpaceBeforeInlineComment indicates whether to allow comment symbols (\# and \;) inside value.
// Docs: https://docs.python.org/2/library/configparser.html
// Quote: Comments may appear on their own in an otherwise empty line, or may be entered in lines holding values or section names.
// In the latter case, they need to be preceded by a whitespace character to be recognized as a comment.
SpaceBeforeInlineComment bool
// UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format // UnescapeValueDoubleQuotes indicates whether to unescape double quotes inside value to regular format
// when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value" // when value is surrounded by double quotes, e.g. key="a \"value\"" => key=a "value"
UnescapeValueDoubleQuotes bool UnescapeValueDoubleQuotes bool

21
vendor/github.com/go-ini/ini/parser.go сгенерированный поставляемый
Просмотреть файл

@@ -198,7 +198,7 @@ func hasSurroundedQuote(in string, quote byte) bool {
func (p *parser) readValue(in []byte, func (p *parser) readValue(in []byte,
parserBufferSize int, parserBufferSize int,
ignoreContinuation, ignoreInlineComment, unescapeValueDoubleQuotes, unescapeValueCommentSymbols, allowPythonMultilines bool) (string, error) { ignoreContinuation, ignoreInlineComment, unescapeValueDoubleQuotes, unescapeValueCommentSymbols, allowPythonMultilines, spaceBeforeInlineComment bool) (string, error) {
line := strings.TrimLeftFunc(string(in), unicode.IsSpace) line := strings.TrimLeftFunc(string(in), unicode.IsSpace)
if len(line) == 0 { if len(line) == 0 {
@@ -240,11 +240,22 @@ func (p *parser) readValue(in []byte,
// Check if ignore inline comment // Check if ignore inline comment
if !ignoreInlineComment { if !ignoreInlineComment {
i := strings.IndexAny(line, "#;") var i int
if spaceBeforeInlineComment {
i = strings.Index(line, " #")
if i == -1 {
i = strings.Index(line, " ;")
}
} else {
i = strings.IndexAny(line, "#;")
}
if i > -1 { if i > -1 {
p.comment.WriteString(line[i:]) p.comment.WriteString(line[i:])
line = strings.TrimSpace(line[:i]) line = strings.TrimSpace(line[:i])
} }
} }
// Trim single and double quotes // Trim single and double quotes
@@ -429,7 +440,8 @@ func (f *File) parse(reader io.Reader) (err error) {
f.options.IgnoreInlineComment, f.options.IgnoreInlineComment,
f.options.UnescapeValueDoubleQuotes, f.options.UnescapeValueDoubleQuotes,
f.options.UnescapeValueCommentSymbols, f.options.UnescapeValueCommentSymbols,
f.options.AllowPythonMultilineValues) f.options.AllowPythonMultilineValues,
f.options.SpaceBeforeInlineComment)
if err != nil { if err != nil {
return err return err
} }
@@ -458,7 +470,8 @@ func (f *File) parse(reader io.Reader) (err error) {
f.options.IgnoreInlineComment, f.options.IgnoreInlineComment,
f.options.UnescapeValueDoubleQuotes, f.options.UnescapeValueDoubleQuotes,
f.options.UnescapeValueCommentSymbols, f.options.UnescapeValueCommentSymbols,
f.options.AllowPythonMultilineValues) f.options.AllowPythonMultilineValues,
f.options.SpaceBeforeInlineComment)
if err != nil { if err != nil {
return err return err
} }

244
vendor/github.com/go-redis/redis/cluster.go сгенерированный поставляемый
Просмотреть файл

@@ -2,11 +2,13 @@ package redis
import ( import (
"context" "context"
"crypto/tls"
"errors" "errors"
"fmt" "fmt"
"math" "math"
"math/rand" "math/rand"
"net" "net"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@@ -34,6 +36,7 @@ type ClusterOptions struct {
// Enables read-only commands on slave nodes. // Enables read-only commands on slave nodes.
ReadOnly bool ReadOnly bool
// Allows routing read-only commands to the closest master or slave node. // Allows routing read-only commands to the closest master or slave node.
// It automatically enables ReadOnly.
RouteByLatency bool RouteByLatency bool
// Allows routing read-only commands to the random master or slave node. // Allows routing read-only commands to the random master or slave node.
RouteRandomly bool RouteRandomly bool
@@ -56,6 +59,8 @@ type ClusterOptions struct {
PoolTimeout time.Duration PoolTimeout time.Duration
IdleTimeout time.Duration IdleTimeout time.Duration
IdleCheckFrequency time.Duration IdleCheckFrequency time.Duration
TLSConfig *tls.Config
} }
func (opt *ClusterOptions) init() { func (opt *ClusterOptions) init() {
@@ -117,6 +122,8 @@ func (opt *ClusterOptions) clientOptions() *Options {
IdleTimeout: opt.IdleTimeout, IdleTimeout: opt.IdleTimeout,
IdleCheckFrequency: disableIdleCheck, IdleCheckFrequency: disableIdleCheck,
TLSConfig: opt.TLSConfig,
} }
} }
@@ -145,6 +152,10 @@ func newClusterNode(clOpt *ClusterOptions, addr string) *clusterNode {
return &node return &node
} }
func (n *clusterNode) String() string {
return n.Client.String()
}
func (n *clusterNode) Close() error { func (n *clusterNode) Close() error {
return n.Client.Close() return n.Client.Close()
} }
@@ -215,7 +226,7 @@ type clusterNodes struct {
nodeCreateGroup singleflight.Group nodeCreateGroup singleflight.Group
generation uint32 _generation uint32 // atomic
} }
func newClusterNodes(opt *ClusterOptions) *clusterNodes { func newClusterNodes(opt *ClusterOptions) *clusterNodes {
@@ -272,8 +283,7 @@ func (c *clusterNodes) Addrs() ([]string, error) {
} }
func (c *clusterNodes) NextGeneration() uint32 { func (c *clusterNodes) NextGeneration() uint32 {
c.generation++ return atomic.AddUint32(&c._generation, 1)
return c.generation
} }
// GC removes unused nodes. // GC removes unused nodes.
@@ -296,10 +306,9 @@ func (c *clusterNodes) GC(generation uint32) {
} }
} }
func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) { func (c *clusterNodes) Get(addr string) (*clusterNode, error) {
var node *clusterNode var node *clusterNode
var err error var err error
c.mu.RLock() c.mu.RLock()
if c.closed { if c.closed {
err = pool.ErrClosed err = pool.ErrClosed
@@ -307,6 +316,11 @@ func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) {
node = c.allNodes[addr] node = c.allNodes[addr]
} }
c.mu.RUnlock() c.mu.RUnlock()
return node, err
}
func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) {
node, err := c.Get(addr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -371,20 +385,25 @@ func (c *clusterNodes) Random() (*clusterNode, error) {
type clusterState struct { type clusterState struct {
nodes *clusterNodes nodes *clusterNodes
masters []*clusterNode Masters []*clusterNode
slaves []*clusterNode Slaves []*clusterNode
slots [][]*clusterNode slots [][]*clusterNode
generation uint32 generation uint32
createdAt time.Time
} }
func newClusterState(nodes *clusterNodes, slots []ClusterSlot, origin string) (*clusterState, error) { func newClusterState(
nodes *clusterNodes, slots []ClusterSlot, origin string,
) (*clusterState, error) {
c := clusterState{ c := clusterState{
nodes: nodes, nodes: nodes,
generation: nodes.NextGeneration(),
slots: make([][]*clusterNode, hashtag.SlotNumber), slots: make([][]*clusterNode, hashtag.SlotNumber),
generation: nodes.NextGeneration(),
createdAt: time.Now(),
} }
isLoopbackOrigin := isLoopbackAddr(origin) isLoopbackOrigin := isLoopbackAddr(origin)
@@ -392,7 +411,7 @@ func newClusterState(nodes *clusterNodes, slots []ClusterSlot, origin string) (*
var nodes []*clusterNode var nodes []*clusterNode
for i, slotNode := range slot.Nodes { for i, slotNode := range slot.Nodes {
addr := slotNode.Addr addr := slotNode.Addr
if !isLoopbackOrigin && isLoopbackAddr(addr) { if !isLoopbackOrigin && useOriginAddr(origin, addr) {
addr = origin addr = origin
} }
@@ -405,9 +424,9 @@ func newClusterState(nodes *clusterNodes, slots []ClusterSlot, origin string) (*
nodes = append(nodes, node) nodes = append(nodes, node)
if i == 0 { if i == 0 {
c.masters = appendNode(c.masters, node) c.Masters = appendUniqueNode(c.Masters, node)
} else { } else {
c.slaves = appendNode(c.slaves, node) c.Slaves = appendUniqueNode(c.Slaves, node)
} }
} }
@@ -489,6 +508,28 @@ func (c *clusterState) slotNodes(slot int) []*clusterNode {
return nil return nil
} }
func (c *clusterState) IsConsistent() bool {
if len(c.Masters) > len(c.Slaves) {
return false
}
for _, master := range c.Masters {
s := master.Client.Info("replication").Val()
if !strings.Contains(s, "role:master") {
return false
}
}
for _, slave := range c.Slaves {
s := slave.Client.Info("replication").Val()
if !strings.Contains(s, "role:slave") {
return false
}
}
return true
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
type clusterStateHolder struct { type clusterStateHolder struct {
@@ -496,8 +537,8 @@ type clusterStateHolder struct {
state atomic.Value state atomic.Value
lastErrMu sync.RWMutex firstErrMu sync.RWMutex
lastErr error firstErr error
reloading uint32 // atomic reloading uint32 // atomic
} }
@@ -508,12 +549,25 @@ func newClusterStateHolder(fn func() (*clusterState, error)) *clusterStateHolder
} }
} }
func (c *clusterStateHolder) Load() (*clusterState, error) { func (c *clusterStateHolder) Reload() (*clusterState, error) {
state, err := c.reload()
if err != nil {
return nil, err
}
if !state.IsConsistent() {
c.LazyReload()
}
return state, nil
}
func (c *clusterStateHolder) reload() (*clusterState, error) {
state, err := c.load() state, err := c.load()
if err != nil { if err != nil {
c.lastErrMu.Lock() c.firstErrMu.Lock()
c.lastErr = err if c.firstErr == nil {
c.lastErrMu.Unlock() c.firstErr = err
}
c.firstErrMu.Unlock()
return nil, err return nil, err
} }
c.state.Store(state) c.state.Store(state)
@@ -527,9 +581,15 @@ func (c *clusterStateHolder) LazyReload() {
go func() { go func() {
defer atomic.StoreUint32(&c.reloading, 0) defer atomic.StoreUint32(&c.reloading, 0)
_, err := c.Load() for {
if err == nil { state, err := c.reload()
time.Sleep(time.Second) if err != nil {
return
}
time.Sleep(100 * time.Millisecond)
if state.IsConsistent() {
return
}
} }
}() }()
} }
@@ -537,12 +597,16 @@ func (c *clusterStateHolder) LazyReload() {
func (c *clusterStateHolder) Get() (*clusterState, error) { func (c *clusterStateHolder) Get() (*clusterState, error) {
v := c.state.Load() v := c.state.Load()
if v != nil { if v != nil {
return v.(*clusterState), nil state := v.(*clusterState)
if time.Since(state.createdAt) > time.Minute {
c.LazyReload()
}
return state, nil
} }
c.lastErrMu.RLock() c.firstErrMu.RLock()
err := c.lastErr err := c.firstErr
c.lastErrMu.RUnlock() c.firstErrMu.RUnlock()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -576,19 +640,19 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient {
opt.init() opt.init()
c := &ClusterClient{ c := &ClusterClient{
opt: opt, opt: opt,
nodes: newClusterNodes(opt), nodes: newClusterNodes(opt),
cmdsInfoCache: newCmdsInfoCache(),
} }
c.state = newClusterStateHolder(c.loadState) c.state = newClusterStateHolder(c.loadState)
c.cmdsInfoCache = newCmdsInfoCache(c.cmdsInfo)
c.process = c.defaultProcess c.process = c.defaultProcess
c.processPipeline = c.defaultProcessPipeline c.processPipeline = c.defaultProcessPipeline
c.processTxPipeline = c.defaultProcessTxPipeline c.processTxPipeline = c.defaultProcessTxPipeline
c.cmdable.setProcessor(c.Process) c.init()
_, _ = c.state.Load() _, _ = c.state.Reload()
if opt.IdleCheckFrequency > 0 { if opt.IdleCheckFrequency > 0 {
go c.reaper(opt.IdleCheckFrequency) go c.reaper(opt.IdleCheckFrequency)
} }
@@ -596,6 +660,10 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient {
return c return c
} }
func (c *ClusterClient) init() {
c.cmdable.setProcessor(c.Process)
}
func (c *ClusterClient) Context() context.Context { func (c *ClusterClient) Context() context.Context {
if c.ctx != nil { if c.ctx != nil {
return c.ctx return c.ctx
@@ -614,6 +682,7 @@ func (c *ClusterClient) WithContext(ctx context.Context) *ClusterClient {
func (c *ClusterClient) copy() *ClusterClient { func (c *ClusterClient) copy() *ClusterClient {
cp := *c cp := *c
cp.init()
return &cp return &cp
} }
@@ -626,17 +695,39 @@ func (c *ClusterClient) retryBackoff(attempt int) time.Duration {
return internal.RetryBackoff(attempt, c.opt.MinRetryBackoff, c.opt.MaxRetryBackoff) return internal.RetryBackoff(attempt, c.opt.MinRetryBackoff, c.opt.MaxRetryBackoff)
} }
func (c *ClusterClient) cmdInfo(name string) *CommandInfo { func (c *ClusterClient) cmdsInfo() (map[string]*CommandInfo, error) {
cmdsInfo, err := c.cmdsInfoCache.Do(func() (map[string]*CommandInfo, error) { addrs, err := c.nodes.Addrs()
node, err := c.nodes.Random() if err != nil {
return nil, err
}
var firstErr error
for _, addr := range addrs {
node, err := c.nodes.Get(addr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return node.Client.Command().Result() if node == nil {
}) continue
}
info, err := node.Client.Command().Result()
if err == nil {
return info, nil
}
if firstErr == nil {
firstErr = err
}
}
return nil, firstErr
}
func (c *ClusterClient) cmdInfo(name string) *CommandInfo {
cmdsInfo, err := c.cmdsInfoCache.Get()
if err != nil { if err != nil {
return nil return nil
} }
info := cmdsInfo[name] info := cmdsInfo[name]
if info == nil { if info == nil {
internal.Logf("info for cmd=%s not found", name) internal.Logf("info for cmd=%s not found", name)
@@ -700,13 +791,14 @@ func (c *ClusterClient) slotMasterNode(slot int) (*clusterNode, error) {
func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error { func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error {
if len(keys) == 0 { if len(keys) == 0 {
return fmt.Errorf("redis: keys don't hash to the same slot") return fmt.Errorf("redis: Watch requires at least one key")
} }
slot := hashtag.Slot(keys[0]) slot := hashtag.Slot(keys[0])
for _, key := range keys[1:] { for _, key := range keys[1:] {
if hashtag.Slot(key) != slot { if hashtag.Slot(key) != slot {
return fmt.Errorf("redis: Watch requires all keys to be in the same slot") err := fmt.Errorf("redis: Watch requires all keys to be in the same slot")
return err
} }
} }
@@ -812,6 +904,12 @@ func (c *ClusterClient) defaultProcess(cmd Cmder) error {
} }
if internal.IsRetryableError(err, true) { if internal.IsRetryableError(err, true) {
// Firstly retry the same node.
if attempt == 0 {
continue
}
// Secondly try random node.
node, err = c.nodes.Random() node, err = c.nodes.Random()
if err != nil { if err != nil {
break break
@@ -846,14 +944,17 @@ func (c *ClusterClient) defaultProcess(cmd Cmder) error {
// ForEachMaster concurrently calls the fn on each master node in the cluster. // ForEachMaster concurrently calls the fn on each master node in the cluster.
// It returns the first error if any. // It returns the first error if any.
func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error { func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error {
state, err := c.state.Get() state, err := c.state.Reload()
if err != nil { if err != nil {
return err state, err = c.state.Get()
if err != nil {
return err
}
} }
var wg sync.WaitGroup var wg sync.WaitGroup
errCh := make(chan error, 1) errCh := make(chan error, 1)
for _, master := range state.masters { for _, master := range state.Masters {
wg.Add(1) wg.Add(1)
go func(node *clusterNode) { go func(node *clusterNode) {
defer wg.Done() defer wg.Done()
@@ -879,14 +980,17 @@ func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error {
// ForEachSlave concurrently calls the fn on each slave node in the cluster. // ForEachSlave concurrently calls the fn on each slave node in the cluster.
// It returns the first error if any. // It returns the first error if any.
func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error { func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error {
state, err := c.state.Get() state, err := c.state.Reload()
if err != nil { if err != nil {
return err state, err = c.state.Get()
if err != nil {
return err
}
} }
var wg sync.WaitGroup var wg sync.WaitGroup
errCh := make(chan error, 1) errCh := make(chan error, 1)
for _, slave := range state.slaves { for _, slave := range state.Slaves {
wg.Add(1) wg.Add(1)
go func(node *clusterNode) { go func(node *clusterNode) {
defer wg.Done() defer wg.Done()
@@ -912,9 +1016,12 @@ func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error {
// ForEachNode concurrently calls the fn on each known node in the cluster. // ForEachNode concurrently calls the fn on each known node in the cluster.
// It returns the first error if any. // It returns the first error if any.
func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error { func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error {
state, err := c.state.Get() state, err := c.state.Reload()
if err != nil { if err != nil {
return err state, err = c.state.Get()
if err != nil {
return err
}
} }
var wg sync.WaitGroup var wg sync.WaitGroup
@@ -930,11 +1037,11 @@ func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error {
} }
} }
for _, node := range state.masters { for _, node := range state.Masters {
wg.Add(1) wg.Add(1)
go worker(node) go worker(node)
} }
for _, node := range state.slaves { for _, node := range state.Slaves {
wg.Add(1) wg.Add(1)
go worker(node) go worker(node)
} }
@@ -957,7 +1064,7 @@ func (c *ClusterClient) PoolStats() *PoolStats {
return &acc return &acc
} }
for _, node := range state.masters { for _, node := range state.Masters {
s := node.Client.connPool.Stats() s := node.Client.connPool.Stats()
acc.Hits += s.Hits acc.Hits += s.Hits
acc.Misses += s.Misses acc.Misses += s.Misses
@@ -968,7 +1075,7 @@ func (c *ClusterClient) PoolStats() *PoolStats {
acc.StaleConns += s.StaleConns acc.StaleConns += s.StaleConns
} }
for _, node := range state.slaves { for _, node := range state.Slaves {
s := node.Client.connPool.Stats() s := node.Client.connPool.Stats()
acc.Hits += s.Hits acc.Hits += s.Hits
acc.Misses += s.Misses acc.Misses += s.Misses
@@ -1065,7 +1172,7 @@ func (c *ClusterClient) defaultProcessPipeline(cmds []Cmder) error {
failedCmds := make(map[*clusterNode][]Cmder) failedCmds := make(map[*clusterNode][]Cmder)
for node, cmds := range cmdsMap { for node, cmds := range cmdsMap {
cn, _, err := node.Client.getConn() cn, err := node.Client.getConn()
if err != nil { if err != nil {
if err == pool.ErrClosed { if err == pool.ErrClosed {
c.remapCmds(cmds, failedCmds) c.remapCmds(cmds, failedCmds)
@@ -1077,9 +1184,9 @@ func (c *ClusterClient) defaultProcessPipeline(cmds []Cmder) error {
err = c.pipelineProcessCmds(node, cn, cmds, failedCmds) err = c.pipelineProcessCmds(node, cn, cmds, failedCmds)
if err == nil || internal.IsRedisError(err) { if err == nil || internal.IsRedisError(err) {
_ = node.Client.connPool.Put(cn) node.Client.connPool.Put(cn)
} else { } else {
_ = node.Client.connPool.Remove(cn) node.Client.connPool.Remove(cn)
} }
} }
@@ -1229,7 +1336,7 @@ func (c *ClusterClient) defaultProcessTxPipeline(cmds []Cmder) error {
failedCmds := make(map[*clusterNode][]Cmder) failedCmds := make(map[*clusterNode][]Cmder)
for node, cmds := range cmdsMap { for node, cmds := range cmdsMap {
cn, _, err := node.Client.getConn() cn, err := node.Client.getConn()
if err != nil { if err != nil {
if err == pool.ErrClosed { if err == pool.ErrClosed {
c.remapCmds(cmds, failedCmds) c.remapCmds(cmds, failedCmds)
@@ -1241,9 +1348,9 @@ func (c *ClusterClient) defaultProcessTxPipeline(cmds []Cmder) error {
err = c.txPipelineProcessCmds(node, cn, cmds, failedCmds) err = c.txPipelineProcessCmds(node, cn, cmds, failedCmds)
if err == nil || internal.IsRedisError(err) { if err == nil || internal.IsRedisError(err) {
_ = node.Client.connPool.Put(cn) node.Client.connPool.Put(cn)
} else { } else {
_ = node.Client.connPool.Remove(cn) node.Client.connPool.Remove(cn)
} }
} }
@@ -1387,6 +1494,29 @@ func (c *ClusterClient) PSubscribe(channels ...string) *PubSub {
return pubsub return pubsub
} }
func useOriginAddr(originAddr, nodeAddr string) bool {
nodeHost, nodePort, err := net.SplitHostPort(nodeAddr)
if err != nil {
return false
}
nodeIP := net.ParseIP(nodeHost)
if nodeIP == nil {
return false
}
if !nodeIP.IsLoopback() {
return false
}
_, originPort, err := net.SplitHostPort(originAddr)
if err != nil {
return false
}
return nodePort == originPort
}
func isLoopbackAddr(addr string) bool { func isLoopbackAddr(addr string) bool {
host, _, err := net.SplitHostPort(addr) host, _, err := net.SplitHostPort(addr)
if err != nil { if err != nil {
@@ -1401,7 +1531,7 @@ func isLoopbackAddr(addr string) bool {
return ip.IsLoopback() return ip.IsLoopback()
} }
func appendNode(nodes []*clusterNode, node *clusterNode) []*clusterNode { func appendUniqueNode(nodes []*clusterNode, node *clusterNode) []*clusterNode {
for _, n := range nodes { for _, n := range nodes {
if n == node { if n == node {
return nodes return nodes

12
vendor/github.com/go-redis/redis/command.go сгенерированный поставляемый
Просмотреть файл

@@ -1027,17 +1027,21 @@ func (cmd *CommandsInfoCmd) readReply(cn *pool.Conn) error {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
type cmdsInfoCache struct { type cmdsInfoCache struct {
fn func() (map[string]*CommandInfo, error)
once internal.Once once internal.Once
cmds map[string]*CommandInfo cmds map[string]*CommandInfo
} }
func newCmdsInfoCache() *cmdsInfoCache { func newCmdsInfoCache(fn func() (map[string]*CommandInfo, error)) *cmdsInfoCache {
return &cmdsInfoCache{} return &cmdsInfoCache{
fn: fn,
}
} }
func (c *cmdsInfoCache) Do(fn func() (map[string]*CommandInfo, error)) (map[string]*CommandInfo, error) { func (c *cmdsInfoCache) Get() (map[string]*CommandInfo, error) {
err := c.once.Do(func() error { err := c.once.Do(func() error {
cmds, err := fn() cmds, err := c.fn()
if err != nil { if err != nil {
return err return err
} }

8
vendor/github.com/go-redis/redis/commands.go сгенерированный поставляемый
Просмотреть файл

@@ -266,6 +266,8 @@ type Cmdable interface {
GeoDist(key string, member1, member2, unit string) *FloatCmd GeoDist(key string, member1, member2, unit string) *FloatCmd
GeoHash(key string, members ...string) *StringSliceCmd GeoHash(key string, members ...string) *StringSliceCmd
Command() *CommandsInfoCmd Command() *CommandsInfoCmd
ReadOnly() *StatusCmd
ReadWrite() *StatusCmd
} }
type StatefulCmdable interface { type StatefulCmdable interface {
@@ -274,8 +276,6 @@ type StatefulCmdable interface {
Select(index int) *StatusCmd Select(index int) *StatusCmd
SwapDB(index1, index2 int) *StatusCmd SwapDB(index1, index2 int) *StatusCmd
ClientSetName(name string) *BoolCmd ClientSetName(name string) *BoolCmd
ReadOnly() *StatusCmd
ReadWrite() *StatusCmd
} }
var _ Cmdable = (*Client)(nil) var _ Cmdable = (*Client)(nil)
@@ -2054,13 +2054,13 @@ func (c *cmdable) ClusterSlaves(nodeID string) *StringSliceCmd {
return cmd return cmd
} }
func (c *statefulCmdable) ReadOnly() *StatusCmd { func (c *cmdable) ReadOnly() *StatusCmd {
cmd := NewStatusCmd("readonly") cmd := NewStatusCmd("readonly")
c.process(cmd) c.process(cmd)
return cmd return cmd
} }
func (c *statefulCmdable) ReadWrite() *StatusCmd { func (c *cmdable) ReadWrite() *StatusCmd {
cmd := NewStatusCmd("readwrite") cmd := NewStatusCmd("readwrite")
c.process(cmd) c.process(cmd)
return cmd return cmd

205
vendor/github.com/go-redis/redis/internal/pool/pool.go сгенерированный поставляемый
Просмотреть файл

@@ -28,7 +28,8 @@ type Stats struct {
Timeouts uint32 // number of times a wait timeout occurred Timeouts uint32 // number of times a wait timeout occurred
TotalConns uint32 // number of total connections in the pool TotalConns uint32 // number of total connections in the pool
FreeConns uint32 // number of free connections in the pool FreeConns uint32 // deprecated - use IdleConns
IdleConns uint32 // number of idle connections in the pool
StaleConns uint32 // number of stale connections removed from the pool StaleConns uint32 // number of stale connections removed from the pool
} }
@@ -36,12 +37,12 @@ type Pooler interface {
NewConn() (*Conn, error) NewConn() (*Conn, error)
CloseConn(*Conn) error CloseConn(*Conn) error
Get() (*Conn, bool, error) Get() (*Conn, error)
Put(*Conn) error Put(*Conn)
Remove(*Conn) error Remove(*Conn)
Len() int Len() int
FreeLen() int IdleLen() int
Stats() *Stats Stats() *Stats
Close() error Close() error
@@ -70,8 +71,8 @@ type ConnPool struct {
connsMu sync.Mutex connsMu sync.Mutex
conns []*Conn conns []*Conn
freeConnsMu sync.Mutex idleConnsMu sync.RWMutex
freeConns []*Conn idleConns []*Conn
stats Stats stats Stats
@@ -86,15 +87,29 @@ func NewConnPool(opt *Options) *ConnPool {
queue: make(chan struct{}, opt.PoolSize), queue: make(chan struct{}, opt.PoolSize),
conns: make([]*Conn, 0, opt.PoolSize), conns: make([]*Conn, 0, opt.PoolSize),
freeConns: make([]*Conn, 0, opt.PoolSize), idleConns: make([]*Conn, 0, opt.PoolSize),
} }
if opt.IdleTimeout > 0 && opt.IdleCheckFrequency > 0 { if opt.IdleTimeout > 0 && opt.IdleCheckFrequency > 0 {
go p.reaper(opt.IdleCheckFrequency) go p.reaper(opt.IdleCheckFrequency)
} }
return p return p
} }
func (p *ConnPool) NewConn() (*Conn, error) { func (p *ConnPool) NewConn() (*Conn, error) {
cn, err := p.newConn()
if err != nil {
return nil, err
}
p.connsMu.Lock()
p.conns = append(p.conns, cn)
p.connsMu.Unlock()
return cn, nil
}
func (p *ConnPool) newConn() (*Conn, error) {
if p.closed() { if p.closed() {
return nil, ErrClosed return nil, ErrClosed
} }
@@ -112,12 +127,7 @@ func (p *ConnPool) NewConn() (*Conn, error) {
return nil, err return nil, err
} }
cn := NewConn(netConn) return NewConn(netConn), nil
p.connsMu.Lock()
p.conns = append(p.conns, cn)
p.connsMu.Unlock()
return cn, nil
} }
func (p *ConnPool) tryDial() { func (p *ConnPool) tryDial() {
@@ -153,34 +163,20 @@ func (p *ConnPool) getLastDialError() error {
} }
// Get returns existed connection from the pool or creates a new one. // Get returns existed connection from the pool or creates a new one.
func (p *ConnPool) Get() (*Conn, bool, error) { func (p *ConnPool) Get() (*Conn, error) {
if p.closed() { if p.closed() {
return nil, false, ErrClosed return nil, ErrClosed
} }
select { err := p.waitTurn()
case p.queue <- struct{}{}: if err != nil {
default: return nil, err
timer := timers.Get().(*time.Timer)
timer.Reset(p.opt.PoolTimeout)
select {
case p.queue <- struct{}{}:
if !timer.Stop() {
<-timer.C
}
timers.Put(timer)
case <-timer.C:
timers.Put(timer)
atomic.AddUint32(&p.stats.Timeouts, 1)
return nil, false, ErrPoolTimeout
}
} }
for { for {
p.freeConnsMu.Lock() p.idleConnsMu.Lock()
cn := p.popFree() cn := p.popIdle()
p.freeConnsMu.Unlock() p.idleConnsMu.Unlock()
if cn == nil { if cn == nil {
break break
@@ -192,50 +188,89 @@ func (p *ConnPool) Get() (*Conn, bool, error) {
} }
atomic.AddUint32(&p.stats.Hits, 1) atomic.AddUint32(&p.stats.Hits, 1)
return cn, false, nil return cn, nil
} }
atomic.AddUint32(&p.stats.Misses, 1) atomic.AddUint32(&p.stats.Misses, 1)
newcn, err := p.NewConn() newcn, err := p.NewConn()
if err != nil { if err != nil {
<-p.queue p.freeTurn()
return nil, false, err return nil, err
} }
return newcn, true, nil return newcn, nil
} }
func (p *ConnPool) popFree() *Conn { func (p *ConnPool) getTurn() {
if len(p.freeConns) == 0 { p.queue <- struct{}{}
}
func (p *ConnPool) waitTurn() error {
select {
case p.queue <- struct{}{}:
return nil
default:
timer := timers.Get().(*time.Timer)
timer.Reset(p.opt.PoolTimeout)
select {
case p.queue <- struct{}{}:
if !timer.Stop() {
<-timer.C
}
timers.Put(timer)
return nil
case <-timer.C:
timers.Put(timer)
atomic.AddUint32(&p.stats.Timeouts, 1)
return ErrPoolTimeout
}
}
}
func (p *ConnPool) freeTurn() {
<-p.queue
}
func (p *ConnPool) popIdle() *Conn {
if len(p.idleConns) == 0 {
return nil return nil
} }
idx := len(p.freeConns) - 1 idx := len(p.idleConns) - 1
cn := p.freeConns[idx] cn := p.idleConns[idx]
p.freeConns = p.freeConns[:idx] p.idleConns = p.idleConns[:idx]
return cn return cn
} }
func (p *ConnPool) Put(cn *Conn) error { func (p *ConnPool) Put(cn *Conn) {
if data := cn.Rd.PeekBuffered(); data != nil { buf := cn.Rd.PeekBuffered()
internal.Logf("connection has unread data: %q", data) if buf != nil {
return p.Remove(cn) internal.Logf("connection has unread data: %.100q", buf)
p.Remove(cn)
return
} }
p.freeConnsMu.Lock()
p.freeConns = append(p.freeConns, cn) p.idleConnsMu.Lock()
p.freeConnsMu.Unlock() p.idleConns = append(p.idleConns, cn)
<-p.queue p.idleConnsMu.Unlock()
return nil p.freeTurn()
} }
func (p *ConnPool) Remove(cn *Conn) error { func (p *ConnPool) Remove(cn *Conn) {
_ = p.CloseConn(cn) p.removeConn(cn)
<-p.queue p.freeTurn()
return nil _ = p.closeConn(cn)
} }
func (p *ConnPool) CloseConn(cn *Conn) error { func (p *ConnPool) CloseConn(cn *Conn) error {
p.removeConn(cn)
return p.closeConn(cn)
}
func (p *ConnPool) removeConn(cn *Conn) {
p.connsMu.Lock() p.connsMu.Lock()
for i, c := range p.conns { for i, c := range p.conns {
if c == cn { if c == cn {
@@ -244,8 +279,6 @@ func (p *ConnPool) CloseConn(cn *Conn) error {
} }
} }
p.connsMu.Unlock() p.connsMu.Unlock()
return p.closeConn(cn)
} }
func (p *ConnPool) closeConn(cn *Conn) error { func (p *ConnPool) closeConn(cn *Conn) error {
@@ -263,22 +296,24 @@ func (p *ConnPool) Len() int {
return l return l
} }
// FreeLen returns number of free connections. // FreeLen returns number of idle connections.
func (p *ConnPool) FreeLen() int { func (p *ConnPool) IdleLen() int {
p.freeConnsMu.Lock() p.idleConnsMu.RLock()
l := len(p.freeConns) l := len(p.idleConns)
p.freeConnsMu.Unlock() p.idleConnsMu.RUnlock()
return l return l
} }
func (p *ConnPool) Stats() *Stats { func (p *ConnPool) Stats() *Stats {
idleLen := p.IdleLen()
return &Stats{ return &Stats{
Hits: atomic.LoadUint32(&p.stats.Hits), Hits: atomic.LoadUint32(&p.stats.Hits),
Misses: atomic.LoadUint32(&p.stats.Misses), Misses: atomic.LoadUint32(&p.stats.Misses),
Timeouts: atomic.LoadUint32(&p.stats.Timeouts), Timeouts: atomic.LoadUint32(&p.stats.Timeouts),
TotalConns: uint32(p.Len()), TotalConns: uint32(p.Len()),
FreeConns: uint32(p.FreeLen()), FreeConns: uint32(idleLen),
IdleConns: uint32(idleLen),
StaleConns: atomic.LoadUint32(&p.stats.StaleConns), StaleConns: atomic.LoadUint32(&p.stats.StaleConns),
} }
} }
@@ -316,41 +351,45 @@ func (p *ConnPool) Close() error {
p.conns = nil p.conns = nil
p.connsMu.Unlock() p.connsMu.Unlock()
p.freeConnsMu.Lock() p.idleConnsMu.Lock()
p.freeConns = nil p.idleConns = nil
p.freeConnsMu.Unlock() p.idleConnsMu.Unlock()
return firstErr return firstErr
} }
func (p *ConnPool) reapStaleConn() bool { func (p *ConnPool) reapStaleConn() *Conn {
if len(p.freeConns) == 0 { if len(p.idleConns) == 0 {
return false return nil
} }
cn := p.freeConns[0] cn := p.idleConns[0]
if !cn.IsStale(p.opt.IdleTimeout) { if !cn.IsStale(p.opt.IdleTimeout) {
return false return nil
} }
p.CloseConn(cn) p.idleConns = append(p.idleConns[:0], p.idleConns[1:]...)
p.freeConns = append(p.freeConns[:0], p.freeConns[1:]...)
return true return cn
} }
func (p *ConnPool) ReapStaleConns() (int, error) { func (p *ConnPool) ReapStaleConns() (int, error) {
var n int var n int
for { for {
p.queue <- struct{}{} p.getTurn()
p.freeConnsMu.Lock()
reaped := p.reapStaleConn() p.idleConnsMu.Lock()
cn := p.reapStaleConn()
p.idleConnsMu.Unlock()
p.freeConnsMu.Unlock() if cn != nil {
<-p.queue p.removeConn(cn)
}
if reaped { p.freeTurn()
if cn != nil {
p.closeConn(cn)
n++ n++
} else { } else {
break break

12
vendor/github.com/go-redis/redis/internal/pool/pool_single.go сгенерированный поставляемый
Просмотреть файл

@@ -20,29 +20,27 @@ func (p *SingleConnPool) CloseConn(*Conn) error {
panic("not implemented") panic("not implemented")
} }
func (p *SingleConnPool) Get() (*Conn, bool, error) { func (p *SingleConnPool) Get() (*Conn, error) {
return p.cn, false, nil return p.cn, nil
} }
func (p *SingleConnPool) Put(cn *Conn) error { func (p *SingleConnPool) Put(cn *Conn) {
if p.cn != cn { if p.cn != cn {
panic("p.cn != cn") panic("p.cn != cn")
} }
return nil
} }
func (p *SingleConnPool) Remove(cn *Conn) error { func (p *SingleConnPool) Remove(cn *Conn) {
if p.cn != cn { if p.cn != cn {
panic("p.cn != cn") panic("p.cn != cn")
} }
return nil
} }
func (p *SingleConnPool) Len() int { func (p *SingleConnPool) Len() int {
return 1 return 1
} }
func (p *SingleConnPool) FreeLen() int { func (p *SingleConnPool) IdleLen() int {
return 0 return 0
} }

54
vendor/github.com/go-redis/redis/internal/pool/pool_sticky.go сгенерированный поставляемый
Просмотреть файл

@@ -28,55 +28,40 @@ func (p *StickyConnPool) CloseConn(*Conn) error {
panic("not implemented") panic("not implemented")
} }
func (p *StickyConnPool) Get() (*Conn, bool, error) { func (p *StickyConnPool) Get() (*Conn, error) {
p.mu.Lock() p.mu.Lock()
defer p.mu.Unlock() defer p.mu.Unlock()
if p.closed { if p.closed {
return nil, false, ErrClosed return nil, ErrClosed
} }
if p.cn != nil { if p.cn != nil {
return p.cn, false, nil return p.cn, nil
} }
cn, _, err := p.pool.Get() cn, err := p.pool.Get()
if err != nil { if err != nil {
return nil, false, err return nil, err
} }
p.cn = cn p.cn = cn
return cn, true, nil return cn, nil
} }
func (p *StickyConnPool) putUpstream() (err error) { func (p *StickyConnPool) putUpstream() {
err = p.pool.Put(p.cn) p.pool.Put(p.cn)
p.cn = nil p.cn = nil
return err
} }
func (p *StickyConnPool) Put(cn *Conn) error { func (p *StickyConnPool) Put(cn *Conn) {}
p.mu.Lock()
defer p.mu.Unlock()
if p.closed { func (p *StickyConnPool) removeUpstream() {
return ErrClosed p.pool.Remove(p.cn)
}
return nil
}
func (p *StickyConnPool) removeUpstream() error {
err := p.pool.Remove(p.cn)
p.cn = nil p.cn = nil
return err
} }
func (p *StickyConnPool) Remove(cn *Conn) error { func (p *StickyConnPool) Remove(cn *Conn) {
p.mu.Lock() p.removeUpstream()
defer p.mu.Unlock()
if p.closed {
return nil
}
return p.removeUpstream()
} }
func (p *StickyConnPool) Len() int { func (p *StickyConnPool) Len() int {
@@ -89,7 +74,7 @@ func (p *StickyConnPool) Len() int {
return 1 return 1
} }
func (p *StickyConnPool) FreeLen() int { func (p *StickyConnPool) IdleLen() int {
p.mu.Lock() p.mu.Lock()
defer p.mu.Unlock() defer p.mu.Unlock()
@@ -111,13 +96,14 @@ func (p *StickyConnPool) Close() error {
return ErrClosed return ErrClosed
} }
p.closed = true p.closed = true
var err error
if p.cn != nil { if p.cn != nil {
if p.reusable { if p.reusable {
err = p.putUpstream() p.putUpstream()
} else { } else {
err = p.removeUpstream() p.removeUpstream()
} }
} }
return err
return nil
} }

3
vendor/github.com/go-redis/redis/options.go сгенерированный поставляемый
Просмотреть файл

@@ -68,8 +68,7 @@ type Options struct {
// Default is 5 minutes. // Default is 5 minutes.
IdleTimeout time.Duration IdleTimeout time.Duration
// Frequency of idle checks. // Frequency of idle checks.
// Default is 1 minute. // Default is 1 minute. -1 disables idle check.
// When minus value is set, then idle check is disabled.
IdleCheckFrequency time.Duration IdleCheckFrequency time.Duration
// Enables read only queries on slave nodes. // Enables read only queries on slave nodes.

27
vendor/github.com/go-redis/redis/redis.go сгенерированный поставляемый
Просмотреть файл

@@ -60,29 +60,30 @@ func (c *baseClient) newConn() (*pool.Conn, error) {
return cn, nil return cn, nil
} }
func (c *baseClient) getConn() (*pool.Conn, bool, error) { func (c *baseClient) getConn() (*pool.Conn, error) {
cn, isNew, err := c.connPool.Get() cn, err := c.connPool.Get()
if err != nil { if err != nil {
return nil, false, err return nil, err
} }
if !cn.Inited { if !cn.Inited {
if err := c.initConn(cn); err != nil { err := c.initConn(cn)
_ = c.connPool.Remove(cn) if err != nil {
return nil, false, err c.connPool.Remove(cn)
return nil, err
} }
} }
return cn, isNew, nil return cn, nil
} }
func (c *baseClient) releaseConn(cn *pool.Conn, err error) bool { func (c *baseClient) releaseConn(cn *pool.Conn, err error) bool {
if internal.IsBadConn(err, false) { if internal.IsBadConn(err, false) {
_ = c.connPool.Remove(cn) c.connPool.Remove(cn)
return false return false
} }
_ = c.connPool.Put(cn) c.connPool.Put(cn)
return true return true
} }
@@ -137,7 +138,7 @@ func (c *baseClient) defaultProcess(cmd Cmder) error {
time.Sleep(c.retryBackoff(attempt)) time.Sleep(c.retryBackoff(attempt))
} }
cn, _, err := c.getConn() cn, err := c.getConn()
if err != nil { if err != nil {
cmd.setErr(err) cmd.setErr(err)
if internal.IsRetryableError(err, true) { if internal.IsRetryableError(err, true) {
@@ -225,7 +226,7 @@ func (c *baseClient) generalProcessPipeline(cmds []Cmder, p pipelineProcessor) e
time.Sleep(c.retryBackoff(attempt)) time.Sleep(c.retryBackoff(attempt))
} }
cn, _, err := c.getConn() cn, err := c.getConn()
if err != nil { if err != nil {
setCmdsErr(cmds, err) setCmdsErr(cmds, err)
return err return err
@@ -234,10 +235,10 @@ func (c *baseClient) generalProcessPipeline(cmds []Cmder, p pipelineProcessor) e
canRetry, err := p(cn, cmds) canRetry, err := p(cn, cmds)
if err == nil || internal.IsRedisError(err) { if err == nil || internal.IsRedisError(err) {
_ = c.connPool.Put(cn) c.connPool.Put(cn)
break break
} }
_ = c.connPool.Remove(cn) c.connPool.Remove(cn)
if !canRetry || !internal.IsRetryableError(err, true) { if !canRetry || !internal.IsRetryableError(err, true) {
break break

34
vendor/github.com/go-redis/redis/result.go сгенерированный поставляемый
Просмотреть файл

@@ -2,7 +2,7 @@ package redis
import "time" import "time"
// NewCmdResult returns a Cmd initalised with val and err for testing // NewCmdResult returns a Cmd initialised with val and err for testing
func NewCmdResult(val interface{}, err error) *Cmd { func NewCmdResult(val interface{}, err error) *Cmd {
var cmd Cmd var cmd Cmd
cmd.val = val cmd.val = val
@@ -10,7 +10,7 @@ func NewCmdResult(val interface{}, err error) *Cmd {
return &cmd return &cmd
} }
// NewSliceResult returns a SliceCmd initalised with val and err for testing // NewSliceResult returns a SliceCmd initialised with val and err for testing
func NewSliceResult(val []interface{}, err error) *SliceCmd { func NewSliceResult(val []interface{}, err error) *SliceCmd {
var cmd SliceCmd var cmd SliceCmd
cmd.val = val cmd.val = val
@@ -18,7 +18,7 @@ func NewSliceResult(val []interface{}, err error) *SliceCmd {
return &cmd return &cmd
} }
// NewStatusResult returns a StatusCmd initalised with val and err for testing // NewStatusResult returns a StatusCmd initialised with val and err for testing
func NewStatusResult(val string, err error) *StatusCmd { func NewStatusResult(val string, err error) *StatusCmd {
var cmd StatusCmd var cmd StatusCmd
cmd.val = val cmd.val = val
@@ -26,7 +26,7 @@ func NewStatusResult(val string, err error) *StatusCmd {
return &cmd return &cmd
} }
// NewIntResult returns an IntCmd initalised with val and err for testing // NewIntResult returns an IntCmd initialised with val and err for testing
func NewIntResult(val int64, err error) *IntCmd { func NewIntResult(val int64, err error) *IntCmd {
var cmd IntCmd var cmd IntCmd
cmd.val = val cmd.val = val
@@ -34,7 +34,7 @@ func NewIntResult(val int64, err error) *IntCmd {
return &cmd return &cmd
} }
// NewDurationResult returns a DurationCmd initalised with val and err for testing // NewDurationResult returns a DurationCmd initialised with val and err for testing
func NewDurationResult(val time.Duration, err error) *DurationCmd { func NewDurationResult(val time.Duration, err error) *DurationCmd {
var cmd DurationCmd var cmd DurationCmd
cmd.val = val cmd.val = val
@@ -42,7 +42,7 @@ func NewDurationResult(val time.Duration, err error) *DurationCmd {
return &cmd return &cmd
} }
// NewBoolResult returns a BoolCmd initalised with val and err for testing // NewBoolResult returns a BoolCmd initialised with val and err for testing
func NewBoolResult(val bool, err error) *BoolCmd { func NewBoolResult(val bool, err error) *BoolCmd {
var cmd BoolCmd var cmd BoolCmd
cmd.val = val cmd.val = val
@@ -50,7 +50,7 @@ func NewBoolResult(val bool, err error) *BoolCmd {
return &cmd return &cmd
} }
// NewStringResult returns a StringCmd initalised with val and err for testing // NewStringResult returns a StringCmd initialised with val and err for testing
func NewStringResult(val string, err error) *StringCmd { func NewStringResult(val string, err error) *StringCmd {
var cmd StringCmd var cmd StringCmd
cmd.val = []byte(val) cmd.val = []byte(val)
@@ -58,7 +58,7 @@ func NewStringResult(val string, err error) *StringCmd {
return &cmd return &cmd
} }
// NewFloatResult returns a FloatCmd initalised with val and err for testing // NewFloatResult returns a FloatCmd initialised with val and err for testing
func NewFloatResult(val float64, err error) *FloatCmd { func NewFloatResult(val float64, err error) *FloatCmd {
var cmd FloatCmd var cmd FloatCmd
cmd.val = val cmd.val = val
@@ -66,7 +66,7 @@ func NewFloatResult(val float64, err error) *FloatCmd {
return &cmd return &cmd
} }
// NewStringSliceResult returns a StringSliceCmd initalised with val and err for testing // NewStringSliceResult returns a StringSliceCmd initialised with val and err for testing
func NewStringSliceResult(val []string, err error) *StringSliceCmd { func NewStringSliceResult(val []string, err error) *StringSliceCmd {
var cmd StringSliceCmd var cmd StringSliceCmd
cmd.val = val cmd.val = val
@@ -74,7 +74,7 @@ func NewStringSliceResult(val []string, err error) *StringSliceCmd {
return &cmd return &cmd
} }
// NewBoolSliceResult returns a BoolSliceCmd initalised with val and err for testing // NewBoolSliceResult returns a BoolSliceCmd initialised with val and err for testing
func NewBoolSliceResult(val []bool, err error) *BoolSliceCmd { func NewBoolSliceResult(val []bool, err error) *BoolSliceCmd {
var cmd BoolSliceCmd var cmd BoolSliceCmd
cmd.val = val cmd.val = val
@@ -82,7 +82,7 @@ func NewBoolSliceResult(val []bool, err error) *BoolSliceCmd {
return &cmd return &cmd
} }
// NewStringStringMapResult returns a StringStringMapCmd initalised with val and err for testing // NewStringStringMapResult returns a StringStringMapCmd initialised with val and err for testing
func NewStringStringMapResult(val map[string]string, err error) *StringStringMapCmd { func NewStringStringMapResult(val map[string]string, err error) *StringStringMapCmd {
var cmd StringStringMapCmd var cmd StringStringMapCmd
cmd.val = val cmd.val = val
@@ -90,7 +90,7 @@ func NewStringStringMapResult(val map[string]string, err error) *StringStringMap
return &cmd return &cmd
} }
// NewStringIntMapCmdResult returns a StringIntMapCmd initalised with val and err for testing // NewStringIntMapCmdResult returns a StringIntMapCmd initialised with val and err for testing
func NewStringIntMapCmdResult(val map[string]int64, err error) *StringIntMapCmd { func NewStringIntMapCmdResult(val map[string]int64, err error) *StringIntMapCmd {
var cmd StringIntMapCmd var cmd StringIntMapCmd
cmd.val = val cmd.val = val
@@ -98,7 +98,7 @@ func NewStringIntMapCmdResult(val map[string]int64, err error) *StringIntMapCmd
return &cmd return &cmd
} }
// NewZSliceCmdResult returns a ZSliceCmd initalised with val and err for testing // NewZSliceCmdResult returns a ZSliceCmd initialised with val and err for testing
func NewZSliceCmdResult(val []Z, err error) *ZSliceCmd { func NewZSliceCmdResult(val []Z, err error) *ZSliceCmd {
var cmd ZSliceCmd var cmd ZSliceCmd
cmd.val = val cmd.val = val
@@ -106,7 +106,7 @@ func NewZSliceCmdResult(val []Z, err error) *ZSliceCmd {
return &cmd return &cmd
} }
// NewScanCmdResult returns a ScanCmd initalised with val and err for testing // NewScanCmdResult returns a ScanCmd initialised with val and err for testing
func NewScanCmdResult(keys []string, cursor uint64, err error) *ScanCmd { func NewScanCmdResult(keys []string, cursor uint64, err error) *ScanCmd {
var cmd ScanCmd var cmd ScanCmd
cmd.page = keys cmd.page = keys
@@ -115,7 +115,7 @@ func NewScanCmdResult(keys []string, cursor uint64, err error) *ScanCmd {
return &cmd return &cmd
} }
// NewClusterSlotsCmdResult returns a ClusterSlotsCmd initalised with val and err for testing // NewClusterSlotsCmdResult returns a ClusterSlotsCmd initialised with val and err for testing
func NewClusterSlotsCmdResult(val []ClusterSlot, err error) *ClusterSlotsCmd { func NewClusterSlotsCmdResult(val []ClusterSlot, err error) *ClusterSlotsCmd {
var cmd ClusterSlotsCmd var cmd ClusterSlotsCmd
cmd.val = val cmd.val = val
@@ -123,7 +123,7 @@ func NewClusterSlotsCmdResult(val []ClusterSlot, err error) *ClusterSlotsCmd {
return &cmd return &cmd
} }
// NewGeoLocationCmdResult returns a GeoLocationCmd initalised with val and err for testing // NewGeoLocationCmdResult returns a GeoLocationCmd initialised with val and err for testing
func NewGeoLocationCmdResult(val []GeoLocation, err error) *GeoLocationCmd { func NewGeoLocationCmdResult(val []GeoLocation, err error) *GeoLocationCmd {
var cmd GeoLocationCmd var cmd GeoLocationCmd
cmd.locations = val cmd.locations = val
@@ -131,7 +131,7 @@ func NewGeoLocationCmdResult(val []GeoLocation, err error) *GeoLocationCmd {
return &cmd return &cmd
} }
// NewCommandsInfoCmdResult returns a CommandsInfoCmd initalised with val and err for testing // NewCommandsInfoCmdResult returns a CommandsInfoCmd initialised with val and err for testing
func NewCommandsInfoCmdResult(val map[string]*CommandInfo, err error) *CommandsInfoCmd { func NewCommandsInfoCmdResult(val map[string]*CommandInfo, err error) *CommandsInfoCmd {
var cmd CommandsInfoCmd var cmd CommandsInfoCmd
cmd.val = val cmd.val = val

43
vendor/github.com/go-redis/redis/ring.go сгенерированный поставляемый
Просмотреть файл

@@ -304,10 +304,11 @@ func NewRing(opt *RingOptions) *Ring {
opt.init() opt.init()
ring := &Ring{ ring := &Ring{
opt: opt, opt: opt,
shards: newRingShards(), shards: newRingShards(),
cmdsInfoCache: newCmdsInfoCache(),
} }
ring.cmdsInfoCache = newCmdsInfoCache(ring.cmdsInfo)
ring.processPipeline = ring.defaultProcessPipeline ring.processPipeline = ring.defaultProcessPipeline
ring.cmdable.setProcessor(ring.Process) ring.cmdable.setProcessor(ring.Process)
@@ -428,21 +429,23 @@ func (c *Ring) ForEachShard(fn func(client *Client) error) error {
} }
} }
func (c *Ring) cmdInfo(name string) *CommandInfo { func (c *Ring) cmdsInfo() (map[string]*CommandInfo, error) {
cmdsInfo, err := c.cmdsInfoCache.Do(func() (map[string]*CommandInfo, error) { shards := c.shards.List()
shards := c.shards.List() firstErr := errRingShardsDown
firstErr := errRingShardsDown for _, shard := range shards {
for _, shard := range shards { cmdsInfo, err := shard.Client.Command().Result()
cmdsInfo, err := shard.Client.Command().Result() if err == nil {
if err == nil { return cmdsInfo, nil
return cmdsInfo, nil
}
if firstErr == nil {
firstErr = err
}
} }
return nil, firstErr if firstErr == nil {
}) firstErr = err
}
}
return nil, firstErr
}
func (c *Ring) cmdInfo(name string) *CommandInfo {
cmdsInfo, err := c.cmdsInfoCache.Get()
if err != nil { if err != nil {
return nil return nil
} }
@@ -522,7 +525,7 @@ func (c *Ring) defaultProcessPipeline(cmds []Cmder) error {
continue continue
} }
cn, _, err := shard.Client.getConn() cn, err := shard.Client.getConn()
if err != nil { if err != nil {
setCmdsErr(cmds, err) setCmdsErr(cmds, err)
continue continue
@@ -530,10 +533,10 @@ func (c *Ring) defaultProcessPipeline(cmds []Cmder) error {
canRetry, err := shard.Client.pipelineProcessCmds(cn, cmds) canRetry, err := shard.Client.pipelineProcessCmds(cn, cmds)
if err == nil || internal.IsRedisError(err) { if err == nil || internal.IsRedisError(err) {
_ = shard.Client.connPool.Put(cn) shard.Client.connPool.Put(cn)
continue continue
} }
_ = shard.Client.connPool.Remove(cn) shard.Client.connPool.Remove(cn)
if canRetry && internal.IsRetryableError(err, true) { if canRetry && internal.IsRetryableError(err, true) {
if failedCmdsMap == nil { if failedCmdsMap == nil {

34
vendor/github.com/go-redis/redis/sentinel.go сгенерированный поставляемый
Просмотреть файл

@@ -1,6 +1,7 @@
package redis package redis
import ( import (
"crypto/tls"
"errors" "errors"
"net" "net"
"strings" "strings"
@@ -38,6 +39,8 @@ type FailoverOptions struct {
PoolTimeout time.Duration PoolTimeout time.Duration
IdleTimeout time.Duration IdleTimeout time.Duration
IdleCheckFrequency time.Duration IdleCheckFrequency time.Duration
TLSConfig *tls.Config
} }
func (opt *FailoverOptions) options() *Options { func (opt *FailoverOptions) options() *Options {
@@ -59,6 +62,8 @@ func (opt *FailoverOptions) options() *Options {
PoolTimeout: opt.PoolTimeout, PoolTimeout: opt.PoolTimeout,
IdleTimeout: opt.IdleTimeout, IdleTimeout: opt.IdleTimeout,
IdleCheckFrequency: opt.IdleCheckFrequency, IdleCheckFrequency: opt.IdleCheckFrequency,
TLSConfig: opt.TLSConfig,
} }
} }
@@ -94,25 +99,23 @@ func NewFailoverClient(failoverOpt *FailoverOptions) *Client {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
type sentinelClient struct { type SentinelClient struct {
cmdable
baseClient baseClient
} }
func newSentinel(opt *Options) *sentinelClient { func NewSentinelClient(opt *Options) *SentinelClient {
opt.init() opt.init()
c := sentinelClient{ c := &SentinelClient{
baseClient: baseClient{ baseClient: baseClient{
opt: opt, opt: opt,
connPool: newConnPool(opt), connPool: newConnPool(opt),
}, },
} }
c.baseClient.init() c.baseClient.init()
c.cmdable.setProcessor(c.Process) return c
return &c
} }
func (c *sentinelClient) PubSub() *PubSub { func (c *SentinelClient) PubSub() *PubSub {
return &PubSub{ return &PubSub{
opt: c.opt, opt: c.opt,
@@ -123,13 +126,13 @@ func (c *sentinelClient) PubSub() *PubSub {
} }
} }
func (c *sentinelClient) GetMasterAddrByName(name string) *StringSliceCmd { func (c *SentinelClient) GetMasterAddrByName(name string) *StringSliceCmd {
cmd := NewStringSliceCmd("SENTINEL", "get-master-addr-by-name", name) cmd := NewStringSliceCmd("SENTINEL", "get-master-addr-by-name", name)
c.Process(cmd) c.Process(cmd)
return cmd return cmd
} }
func (c *sentinelClient) Sentinels(name string) *SliceCmd { func (c *SentinelClient) Sentinels(name string) *SliceCmd {
cmd := NewSliceCmd("SENTINEL", "sentinels", name) cmd := NewSliceCmd("SENTINEL", "sentinels", name)
c.Process(cmd) c.Process(cmd)
return cmd return cmd
@@ -146,7 +149,7 @@ type sentinelFailover struct {
mu sync.RWMutex mu sync.RWMutex
masterName string masterName string
_masterAddr string _masterAddr string
sentinel *sentinelClient sentinel *SentinelClient
} }
func (d *sentinelFailover) Close() error { func (d *sentinelFailover) Close() error {
@@ -200,7 +203,7 @@ func (d *sentinelFailover) masterAddr() (string, error) {
} }
for i, sentinelAddr := range d.sentinelAddrs { for i, sentinelAddr := range d.sentinelAddrs {
sentinel := newSentinel(&Options{ sentinel := NewSentinelClient(&Options{
Addr: sentinelAddr, Addr: sentinelAddr,
DialTimeout: d.opt.DialTimeout, DialTimeout: d.opt.DialTimeout,
@@ -214,7 +217,8 @@ func (d *sentinelFailover) masterAddr() (string, error) {
masterAddr, err := sentinel.GetMasterAddrByName(d.masterName).Result() masterAddr, err := sentinel.GetMasterAddrByName(d.masterName).Result()
if err != nil { if err != nil {
internal.Logf("sentinel: GetMasterAddrByName master=%q failed: %s", d.masterName, err) internal.Logf("sentinel: GetMasterAddrByName master=%q failed: %s",
d.masterName, err)
sentinel.Close() sentinel.Close()
continue continue
} }
@@ -241,7 +245,7 @@ func (d *sentinelFailover) switchMaster(masterAddr string) {
d._masterAddr = masterAddr d._masterAddr = masterAddr
} }
func (d *sentinelFailover) setSentinel(sentinel *sentinelClient) { func (d *sentinelFailover) setSentinel(sentinel *SentinelClient) {
d.discoverSentinels(sentinel) d.discoverSentinels(sentinel)
d.sentinel = sentinel d.sentinel = sentinel
go d.listen(sentinel) go d.listen(sentinel)
@@ -263,7 +267,7 @@ func (d *sentinelFailover) _resetSentinel() error {
return err return err
} }
func (d *sentinelFailover) discoverSentinels(sentinel *sentinelClient) { func (d *sentinelFailover) discoverSentinels(sentinel *SentinelClient) {
sentinels, err := sentinel.Sentinels(d.masterName).Result() sentinels, err := sentinel.Sentinels(d.masterName).Result()
if err != nil { if err != nil {
internal.Logf("sentinel: Sentinels master=%q failed: %s", d.masterName, err) internal.Logf("sentinel: Sentinels master=%q failed: %s", d.masterName, err)
@@ -287,7 +291,7 @@ func (d *sentinelFailover) discoverSentinels(sentinel *sentinelClient) {
} }
} }
func (d *sentinelFailover) listen(sentinel *sentinelClient) { func (d *sentinelFailover) listen(sentinel *SentinelClient) {
var pubsub *PubSub var pubsub *PubSub
for { for {
if pubsub == nil { if pubsub == nil {

14
vendor/github.com/go-redis/redis/universal.go сгенерированный поставляемый
Просмотреть файл

@@ -1,6 +1,9 @@
package redis package redis
import "time" import (
"crypto/tls"
"time"
)
// UniversalOptions information is required by UniversalClient to establish // UniversalOptions information is required by UniversalClient to establish
// connections. // connections.
@@ -27,6 +30,7 @@ type UniversalOptions struct {
// Common options // Common options
OnConnect func(*Conn) error
MaxRetries int MaxRetries int
Password string Password string
DialTimeout time.Duration DialTimeout time.Duration
@@ -36,6 +40,7 @@ type UniversalOptions struct {
PoolTimeout time.Duration PoolTimeout time.Duration
IdleTimeout time.Duration IdleTimeout time.Duration
IdleCheckFrequency time.Duration IdleCheckFrequency time.Duration
TLSConfig *tls.Config
} }
func (o *UniversalOptions) cluster() *ClusterOptions { func (o *UniversalOptions) cluster() *ClusterOptions {
@@ -49,6 +54,7 @@ func (o *UniversalOptions) cluster() *ClusterOptions {
RouteByLatency: o.RouteByLatency, RouteByLatency: o.RouteByLatency,
ReadOnly: o.ReadOnly, ReadOnly: o.ReadOnly,
OnConnect: o.OnConnect,
MaxRetries: o.MaxRetries, MaxRetries: o.MaxRetries,
Password: o.Password, Password: o.Password,
DialTimeout: o.DialTimeout, DialTimeout: o.DialTimeout,
@@ -58,6 +64,7 @@ func (o *UniversalOptions) cluster() *ClusterOptions {
PoolTimeout: o.PoolTimeout, PoolTimeout: o.PoolTimeout,
IdleTimeout: o.IdleTimeout, IdleTimeout: o.IdleTimeout,
IdleCheckFrequency: o.IdleCheckFrequency, IdleCheckFrequency: o.IdleCheckFrequency,
TLSConfig: o.TLSConfig,
} }
} }
@@ -71,6 +78,7 @@ func (o *UniversalOptions) failover() *FailoverOptions {
MasterName: o.MasterName, MasterName: o.MasterName,
DB: o.DB, DB: o.DB,
OnConnect: o.OnConnect,
MaxRetries: o.MaxRetries, MaxRetries: o.MaxRetries,
Password: o.Password, Password: o.Password,
DialTimeout: o.DialTimeout, DialTimeout: o.DialTimeout,
@@ -80,6 +88,7 @@ func (o *UniversalOptions) failover() *FailoverOptions {
PoolTimeout: o.PoolTimeout, PoolTimeout: o.PoolTimeout,
IdleTimeout: o.IdleTimeout, IdleTimeout: o.IdleTimeout,
IdleCheckFrequency: o.IdleCheckFrequency, IdleCheckFrequency: o.IdleCheckFrequency,
TLSConfig: o.TLSConfig,
} }
} }
@@ -93,6 +102,7 @@ func (o *UniversalOptions) simple() *Options {
Addr: addr, Addr: addr,
DB: o.DB, DB: o.DB,
OnConnect: o.OnConnect,
MaxRetries: o.MaxRetries, MaxRetries: o.MaxRetries,
Password: o.Password, Password: o.Password,
DialTimeout: o.DialTimeout, DialTimeout: o.DialTimeout,
@@ -102,6 +112,7 @@ func (o *UniversalOptions) simple() *Options {
PoolTimeout: o.PoolTimeout, PoolTimeout: o.PoolTimeout,
IdleTimeout: o.IdleTimeout, IdleTimeout: o.IdleTimeout,
IdleCheckFrequency: o.IdleCheckFrequency, IdleCheckFrequency: o.IdleCheckFrequency,
TLSConfig: o.TLSConfig,
} }
} }
@@ -113,6 +124,7 @@ func (o *UniversalOptions) simple() *Options {
// applications locally. // applications locally.
type UniversalClient interface { type UniversalClient interface {
Cmdable Cmdable
Watch(fn func(*Tx) error, keys ...string) error
Process(cmd Cmder) error Process(cmd Cmder) error
WrapProcess(fn func(oldProcess func(cmd Cmder) error) func(cmd Cmder) error) WrapProcess(fn func(oldProcess func(cmd Cmder) error) func(cmd Cmder) error)
Subscribe(channels ...string) *PubSub Subscribe(channels ...string) *PubSub

33
vendor/github.com/go-sql-driver/mysql/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -1,7 +1,6 @@
sudo: false sudo: false
language: go language: go
go: go:
- 1.7.x
- 1.8.x - 1.8.x
- 1.9.x - 1.9.x
- 1.10.x - 1.10.x
@@ -19,6 +18,26 @@ before_script:
matrix: matrix:
include: include:
- env: DB=MYSQL8
sudo: required
dist: trusty
go: 1.10.x
services:
- docker
before_install:
- go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls
- docker pull mysql:8.0
- docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret
mysql:8.0 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB --local-infile=1
- cp .travis/docker.cnf ~/.my.cnf
- .travis/wait_mysql.sh
before_script:
- export MYSQL_TEST_USER=gotest
- export MYSQL_TEST_PASS=secret
- export MYSQL_TEST_ADDR=127.0.0.1:3307
- export MYSQL_TEST_CONCURRENT=1
- env: DB=MYSQL57 - env: DB=MYSQL57
sudo: required sudo: required
dist: trusty dist: trusty
@@ -30,10 +49,8 @@ matrix:
- go get github.com/mattn/goveralls - go get github.com/mattn/goveralls
- docker pull mysql:5.7 - docker pull mysql:5.7
- docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret - docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret
mysql:5.7 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB mysql:5.7 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB --local-infile=1
- sleep 30
- cp .travis/docker.cnf ~/.my.cnf - cp .travis/docker.cnf ~/.my.cnf
- mysql --print-defaults
- .travis/wait_mysql.sh - .travis/wait_mysql.sh
before_script: before_script:
- export MYSQL_TEST_USER=gotest - export MYSQL_TEST_USER=gotest
@@ -52,10 +69,8 @@ matrix:
- go get github.com/mattn/goveralls - go get github.com/mattn/goveralls
- docker pull mariadb:5.5 - docker pull mariadb:5.5
- docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret - docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret
mariadb:5.5 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB mariadb:5.5 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB --local-infile=1
- sleep 30
- cp .travis/docker.cnf ~/.my.cnf - cp .travis/docker.cnf ~/.my.cnf
- mysql --print-defaults
- .travis/wait_mysql.sh - .travis/wait_mysql.sh
before_script: before_script:
- export MYSQL_TEST_USER=gotest - export MYSQL_TEST_USER=gotest
@@ -74,10 +89,8 @@ matrix:
- go get github.com/mattn/goveralls - go get github.com/mattn/goveralls
- docker pull mariadb:10.1 - docker pull mariadb:10.1
- docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret - docker run -d -p 127.0.0.1:3307:3306 --name mysqld -e MYSQL_DATABASE=gotest -e MYSQL_USER=gotest -e MYSQL_PASSWORD=secret -e MYSQL_ROOT_PASSWORD=verysecret
mariadb:10.1 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB mariadb:10.1 --innodb_log_file_size=256MB --innodb_buffer_pool_size=512MB --max_allowed_packet=16MB --local-infile=1
- sleep 30
- cp .travis/docker.cnf ~/.my.cnf - cp .travis/docker.cnf ~/.my.cnf
- mysql --print-defaults
- .travis/wait_mysql.sh - .travis/wait_mysql.sh
before_script: before_script:
- export MYSQL_TEST_USER=gotest - export MYSQL_TEST_USER=gotest

5
vendor/github.com/go-sql-driver/mysql/AUTHORS сгенерированный поставляемый
Просмотреть файл

@@ -20,6 +20,7 @@ Asta Xie <xiemengjun at gmail.com>
Bulat Gaifullin <gaifullinbf at gmail.com> Bulat Gaifullin <gaifullinbf at gmail.com>
Carlos Nieto <jose.carlos at menteslibres.net> Carlos Nieto <jose.carlos at menteslibres.net>
Chris Moos <chris at tech9computers.com> Chris Moos <chris at tech9computers.com>
Craig Wilson <craiggwilson at gmail.com>
Daniel Montoya <dsmontoyam at gmail.com> Daniel Montoya <dsmontoyam at gmail.com>
Daniel Nichter <nil at codenode.com> Daniel Nichter <nil at codenode.com>
Daniël van Eeden <git at myname.nl> Daniël van Eeden <git at myname.nl>
@@ -29,6 +30,7 @@ Egor Smolyakov <egorsmkv at gmail.com>
Evan Shaw <evan at vendhq.com> Evan Shaw <evan at vendhq.com>
Frederick Mayle <frederickmayle at gmail.com> Frederick Mayle <frederickmayle at gmail.com>
Gustavo Kristic <gkristic at gmail.com> Gustavo Kristic <gkristic at gmail.com>
Hajime Nakagami <nakagami at gmail.com>
Hanno Braun <mail at hannobraun.com> Hanno Braun <mail at hannobraun.com>
Henri Yandell <flamefew at gmail.com> Henri Yandell <flamefew at gmail.com>
Hirotaka Yamamoto <ymmt2005 at gmail.com> Hirotaka Yamamoto <ymmt2005 at gmail.com>
@@ -54,7 +56,7 @@ Lion Yang <lion at aosc.xyz>
Luca Looz <luca.looz92 at gmail.com> Luca Looz <luca.looz92 at gmail.com>
Lucas Liu <extrafliu at gmail.com> Lucas Liu <extrafliu at gmail.com>
Luke Scott <luke at webconnex.com> Luke Scott <luke at webconnex.com>
Maciej Zimnoch <maciej.zimnoch@codilime.com> Maciej Zimnoch <maciej.zimnoch at codilime.com>
Michael Woolnough <michael.woolnough at gmail.com> Michael Woolnough <michael.woolnough at gmail.com>
Nicola Peduzzi <thenikso at gmail.com> Nicola Peduzzi <thenikso at gmail.com>
Olivier Mengué <dolmen at cpan.org> Olivier Mengué <dolmen at cpan.org>
@@ -63,6 +65,7 @@ Paul Bonser <misterpib at gmail.com>
Peter Schultz <peter.schultz at classmarkets.com> Peter Schultz <peter.schultz at classmarkets.com>
Rebecca Chin <rchin at pivotal.io> Rebecca Chin <rchin at pivotal.io>
Reed Allman <rdallman10 at gmail.com> Reed Allman <rdallman10 at gmail.com>
Richard Wilkes <wilkes at me.com>
Robert Russell <robert at rrbrussell.com> Robert Russell <robert at rrbrussell.com>
Runrioter Wung <runrioter at gmail.com> Runrioter Wung <runrioter at gmail.com>
Shuode Li <elemount at qq.com> Shuode Li <elemount at qq.com>

48
vendor/github.com/go-sql-driver/mysql/CHANGELOG.md сгенерированный поставляемый
Просмотреть файл

@@ -1,3 +1,51 @@
## Version 1.4 (2018-06-03)
Changes:
- Documentation fixes (#530, #535, #567)
- Refactoring (#575, #579, #580, #581, #603, #615, #704)
- Cache column names (#444)
- Sort the DSN parameters in DSNs generated from a config (#637)
- Allow native password authentication by default (#644)
- Use the default port if it is missing in the DSN (#668)
- Removed the `strict` mode (#676)
- Do not query `max_allowed_packet` by default (#680)
- Dropped support Go 1.6 and lower (#696)
- Updated `ConvertValue()` to match the database/sql/driver implementation (#760)
- Document the usage of `0000-00-00T00:00:00` as the time.Time zero value (#783)
- Improved the compatibility of the authentication system (#807)
New Features:
- Multi-Results support (#537)
- `rejectReadOnly` DSN option (#604)
- `context.Context` support (#608, #612, #627, #761)
- Transaction isolation level support (#619, #744)
- Read-Only transactions support (#618, #634)
- `NewConfig` function which initializes a config with default values (#679)
- Implemented the `ColumnType` interfaces (#667, #724)
- Support for custom string types in `ConvertValue` (#623)
- Implemented `NamedValueChecker`, improving support for uint64 with high bit set (#690, #709, #710)
- `caching_sha2_password` authentication plugin support (#794, #800, #801, #802)
- Implemented `driver.SessionResetter` (#779)
- `sha256_password` authentication plugin support (#808)
Bugfixes:
- Use the DSN hostname as TLS default ServerName if `tls=true` (#564, #718)
- Fixed LOAD LOCAL DATA INFILE for empty files (#590)
- Removed columns definition cache since it sometimes cached invalid data (#592)
- Don't mutate registered TLS configs (#600)
- Make RegisterTLSConfig concurrency-safe (#613)
- Handle missing auth data in the handshake packet correctly (#646)
- Do not retry queries when data was written to avoid data corruption (#302, #736)
- Cache the connection pointer for error handling before invalidating it (#678)
- Fixed imports for appengine/cloudsql (#700)
- Fix sending STMT_LONG_DATA for 0 byte data (#734)
- Set correct capacity for []bytes read from length-encoded strings (#766)
- Make RegisterDial concurrency-safe (#773)
## Version 1.3 (2016-12-01) ## Version 1.3 (2016-12-01)
Changes: Changes:

14
vendor/github.com/go-sql-driver/mysql/README.md сгенерированный поставляемый
Просмотреть файл

@@ -259,6 +259,7 @@ Default: false
``` ```
`parseTime=true` changes the output type of `DATE` and `DATETIME` values to `time.Time` instead of `[]byte` / `string` `parseTime=true` changes the output type of `DATE` and `DATETIME` values to `time.Time` instead of `[]byte` / `string`
The date or datetime like `0000-00-00 00:00:00` is converted into zero value of `time.Time`.
##### `readTimeout` ##### `readTimeout`
@@ -300,6 +301,19 @@ other cases. You should ensure your application will never cause an ERROR 1290
except for `read-only` mode when enabling this option. except for `read-only` mode when enabling this option.
##### `serverPubKey`
```
Type: string
Valid Values: <name>
Default: none
```
Server public keys can be registered with [`mysql.RegisterServerPubKey`](https://godoc.org/github.com/go-sql-driver/mysql#RegisterServerPubKey), which can then be used by the assigned name in the DSN.
Public keys are used to transmit encrypted data, e.g. for authentication.
If the server's public key is known, it should be set manually to avoid expensive and potentially insecure transmissions of the public key from the server to the client each time it is required.
##### `timeout` ##### `timeout`
``` ```

420
vendor/github.com/go-sql-driver/mysql/auth.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,420 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2018 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
"crypto/x509"
"encoding/pem"
"sync"
)
// server pub keys registry
var (
serverPubKeyLock sync.RWMutex
serverPubKeyRegistry map[string]*rsa.PublicKey
)
// RegisterServerPubKey registers a server RSA public key which can be used to
// send data in a secure manner to the server without receiving the public key
// in a potentially insecure way from the server first.
// Registered keys can afterwards be used adding serverPubKey=<name> to the DSN.
//
// Note: The provided rsa.PublicKey instance is exclusively owned by the driver
// after registering it and may not be modified.
//
// data, err := ioutil.ReadFile("mykey.pem")
// if err != nil {
// log.Fatal(err)
// }
//
// block, _ := pem.Decode(data)
// if block == nil || block.Type != "PUBLIC KEY" {
// log.Fatal("failed to decode PEM block containing public key")
// }
//
// pub, err := x509.ParsePKIXPublicKey(block.Bytes)
// if err != nil {
// log.Fatal(err)
// }
//
// if rsaPubKey, ok := pub.(*rsa.PublicKey); ok {
// mysql.RegisterServerPubKey("mykey", rsaPubKey)
// } else {
// log.Fatal("not a RSA public key")
// }
//
func RegisterServerPubKey(name string, pubKey *rsa.PublicKey) {
serverPubKeyLock.Lock()
if serverPubKeyRegistry == nil {
serverPubKeyRegistry = make(map[string]*rsa.PublicKey)
}
serverPubKeyRegistry[name] = pubKey
serverPubKeyLock.Unlock()
}
// DeregisterServerPubKey removes the public key registered with the given name.
func DeregisterServerPubKey(name string) {
serverPubKeyLock.Lock()
if serverPubKeyRegistry != nil {
delete(serverPubKeyRegistry, name)
}
serverPubKeyLock.Unlock()
}
func getServerPubKey(name string) (pubKey *rsa.PublicKey) {
serverPubKeyLock.RLock()
if v, ok := serverPubKeyRegistry[name]; ok {
pubKey = v
}
serverPubKeyLock.RUnlock()
return
}
// Hash password using pre 4.1 (old password) method
// https://github.com/atcurtis/mariadb/blob/master/mysys/my_rnd.c
type myRnd struct {
seed1, seed2 uint32
}
const myRndMaxVal = 0x3FFFFFFF
// Pseudo random number generator
func newMyRnd(seed1, seed2 uint32) *myRnd {
return &myRnd{
seed1: seed1 % myRndMaxVal,
seed2: seed2 % myRndMaxVal,
}
}
// Tested to be equivalent to MariaDB's floating point variant
// http://play.golang.org/p/QHvhd4qved
// http://play.golang.org/p/RG0q4ElWDx
func (r *myRnd) NextByte() byte {
r.seed1 = (r.seed1*3 + r.seed2) % myRndMaxVal
r.seed2 = (r.seed1 + r.seed2 + 33) % myRndMaxVal
return byte(uint64(r.seed1) * 31 / myRndMaxVal)
}
// Generate binary hash from byte string using insecure pre 4.1 method
func pwHash(password []byte) (result [2]uint32) {
var add uint32 = 7
var tmp uint32
result[0] = 1345345333
result[1] = 0x12345671
for _, c := range password {
// skip spaces and tabs in password
if c == ' ' || c == '\t' {
continue
}
tmp = uint32(c)
result[0] ^= (((result[0] & 63) + add) * tmp) + (result[0] << 8)
result[1] += (result[1] << 8) ^ result[0]
add += tmp
}
// Remove sign bit (1<<31)-1)
result[0] &= 0x7FFFFFFF
result[1] &= 0x7FFFFFFF
return
}
// Hash password using insecure pre 4.1 method
func scrambleOldPassword(scramble []byte, password string) []byte {
if len(password) == 0 {
return nil
}
scramble = scramble[:8]
hashPw := pwHash([]byte(password))
hashSc := pwHash(scramble)
r := newMyRnd(hashPw[0]^hashSc[0], hashPw[1]^hashSc[1])
var out [8]byte
for i := range out {
out[i] = r.NextByte() + 64
}
mask := r.NextByte()
for i := range out {
out[i] ^= mask
}
return out[:]
}
// Hash password using 4.1+ method (SHA1)
func scramblePassword(scramble []byte, password string) []byte {
if len(password) == 0 {
return nil
}
// stage1Hash = SHA1(password)
crypt := sha1.New()
crypt.Write([]byte(password))
stage1 := crypt.Sum(nil)
// scrambleHash = SHA1(scramble + SHA1(stage1Hash))
// inner Hash
crypt.Reset()
crypt.Write(stage1)
hash := crypt.Sum(nil)
// outer Hash
crypt.Reset()
crypt.Write(scramble)
crypt.Write(hash)
scramble = crypt.Sum(nil)
// token = scrambleHash XOR stage1Hash
for i := range scramble {
scramble[i] ^= stage1[i]
}
return scramble
}
// Hash password using MySQL 8+ method (SHA256)
func scrambleSHA256Password(scramble []byte, password string) []byte {
if len(password) == 0 {
return nil
}
// XOR(SHA256(password), SHA256(SHA256(SHA256(password)), scramble))
crypt := sha256.New()
crypt.Write([]byte(password))
message1 := crypt.Sum(nil)
crypt.Reset()
crypt.Write(message1)
message1Hash := crypt.Sum(nil)
crypt.Reset()
crypt.Write(message1Hash)
crypt.Write(scramble)
message2 := crypt.Sum(nil)
for i := range message1 {
message1[i] ^= message2[i]
}
return message1
}
func encryptPassword(password string, seed []byte, pub *rsa.PublicKey) ([]byte, error) {
plain := make([]byte, len(password)+1)
copy(plain, password)
for i := range plain {
j := i % len(seed)
plain[i] ^= seed[j]
}
sha1 := sha1.New()
return rsa.EncryptOAEP(sha1, rand.Reader, pub, plain, nil)
}
func (mc *mysqlConn) sendEncryptedPassword(seed []byte, pub *rsa.PublicKey) error {
enc, err := encryptPassword(mc.cfg.Passwd, seed, pub)
if err != nil {
return err
}
return mc.writeAuthSwitchPacket(enc, false)
}
func (mc *mysqlConn) auth(authData []byte, plugin string) ([]byte, bool, error) {
switch plugin {
case "caching_sha2_password":
authResp := scrambleSHA256Password(authData, mc.cfg.Passwd)
return authResp, (authResp == nil), nil
case "mysql_old_password":
if !mc.cfg.AllowOldPasswords {
return nil, false, ErrOldPassword
}
// Note: there are edge cases where this should work but doesn't;
// this is currently "wontfix":
// https://github.com/go-sql-driver/mysql/issues/184
authResp := scrambleOldPassword(authData[:8], mc.cfg.Passwd)
return authResp, true, nil
case "mysql_clear_password":
if !mc.cfg.AllowCleartextPasswords {
return nil, false, ErrCleartextPassword
}
// http://dev.mysql.com/doc/refman/5.7/en/cleartext-authentication-plugin.html
// http://dev.mysql.com/doc/refman/5.7/en/pam-authentication-plugin.html
return []byte(mc.cfg.Passwd), true, nil
case "mysql_native_password":
if !mc.cfg.AllowNativePasswords {
return nil, false, ErrNativePassword
}
// https://dev.mysql.com/doc/internals/en/secure-password-authentication.html
// Native password authentication only need and will need 20-byte challenge.
authResp := scramblePassword(authData[:20], mc.cfg.Passwd)
return authResp, false, nil
case "sha256_password":
if len(mc.cfg.Passwd) == 0 {
return nil, true, nil
}
if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
// write cleartext auth packet
return []byte(mc.cfg.Passwd), true, nil
}
pubKey := mc.cfg.pubKey
if pubKey == nil {
// request public key from server
return []byte{1}, false, nil
}
// encrypted password
enc, err := encryptPassword(mc.cfg.Passwd, authData, pubKey)
return enc, false, err
default:
errLog.Print("unknown auth plugin:", plugin)
return nil, false, ErrUnknownPlugin
}
}
func (mc *mysqlConn) handleAuthResult(oldAuthData []byte, plugin string) error {
// Read Result Packet
authData, newPlugin, err := mc.readAuthResult()
if err != nil {
return err
}
// handle auth plugin switch, if requested
if newPlugin != "" {
// If CLIENT_PLUGIN_AUTH capability is not supported, no new cipher is
// sent and we have to keep using the cipher sent in the init packet.
if authData == nil {
authData = oldAuthData
} else {
// copy data from read buffer to owned slice
copy(oldAuthData, authData)
}
plugin = newPlugin
authResp, addNUL, err := mc.auth(authData, plugin)
if err != nil {
return err
}
if err = mc.writeAuthSwitchPacket(authResp, addNUL); err != nil {
return err
}
// Read Result Packet
authData, newPlugin, err = mc.readAuthResult()
if err != nil {
return err
}
// Do not allow to change the auth plugin more than once
if newPlugin != "" {
return ErrMalformPkt
}
}
switch plugin {
// https://insidemysql.com/preparing-your-community-connector-for-mysql-8-part-2-sha256/
case "caching_sha2_password":
switch len(authData) {
case 0:
return nil // auth successful
case 1:
switch authData[0] {
case cachingSha2PasswordFastAuthSuccess:
if err = mc.readResultOK(); err == nil {
return nil // auth successful
}
case cachingSha2PasswordPerformFullAuthentication:
if mc.cfg.tls != nil || mc.cfg.Net == "unix" {
// write cleartext auth packet
err = mc.writeAuthSwitchPacket([]byte(mc.cfg.Passwd), true)
if err != nil {
return err
}
} else {
pubKey := mc.cfg.pubKey
if pubKey == nil {
// request public key from server
data := mc.buf.takeSmallBuffer(4 + 1)
data[4] = cachingSha2PasswordRequestPublicKey
mc.writePacket(data)
// parse public key
data, err := mc.readPacket()
if err != nil {
return err
}
block, _ := pem.Decode(data[1:])
pkix, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return err
}
pubKey = pkix.(*rsa.PublicKey)
}
// send encrypted password
err = mc.sendEncryptedPassword(oldAuthData, pubKey)
if err != nil {
return err
}
}
return mc.readResultOK()
default:
return ErrMalformPkt
}
default:
return ErrMalformPkt
}
case "sha256_password":
switch len(authData) {
case 0:
return nil // auth successful
default:
block, _ := pem.Decode(authData)
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return err
}
// send encrypted password
err = mc.sendEncryptedPassword(oldAuthData, pub.(*rsa.PublicKey))
if err != nil {
return err
}
return mc.readResultOK()
}
default:
return nil // auth successful
}
return err
}

12
vendor/github.com/go-sql-driver/mysql/buffer.go сгенерированный поставляемый
Просмотреть файл

@@ -130,18 +130,18 @@ func (b *buffer) takeBuffer(length int) []byte {
// smaller than defaultBufSize // smaller than defaultBufSize
// Only one buffer (total) can be used at a time. // Only one buffer (total) can be used at a time.
func (b *buffer) takeSmallBuffer(length int) []byte { func (b *buffer) takeSmallBuffer(length int) []byte {
if b.length == 0 { if b.length > 0 {
return b.buf[:length] return nil
} }
return nil return b.buf[:length]
} }
// takeCompleteBuffer returns the complete existing buffer. // takeCompleteBuffer returns the complete existing buffer.
// This can be used if the necessary buffer size is unknown. // This can be used if the necessary buffer size is unknown.
// Only one buffer (total) can be used at a time. // Only one buffer (total) can be used at a time.
func (b *buffer) takeCompleteBuffer() []byte { func (b *buffer) takeCompleteBuffer() []byte {
if b.length == 0 { if b.length > 0 {
return b.buf return nil
} }
return nil return b.buf
} }

193
vendor/github.com/go-sql-driver/mysql/connection.go сгенерированный поставляемый
Просмотреть файл

@@ -9,6 +9,8 @@
package mysql package mysql
import ( import (
"context"
"database/sql"
"database/sql/driver" "database/sql/driver"
"io" "io"
"net" "net"
@@ -459,3 +461,194 @@ func (mc *mysqlConn) finish() {
case <-mc.closech: case <-mc.closech:
} }
} }
// Ping implements driver.Pinger interface
func (mc *mysqlConn) Ping(ctx context.Context) (err error) {
if mc.closed.IsSet() {
errLog.Print(ErrInvalidConn)
return driver.ErrBadConn
}
if err = mc.watchCancel(ctx); err != nil {
return
}
defer mc.finish()
if err = mc.writeCommandPacket(comPing); err != nil {
return
}
return mc.readResultOK()
}
// BeginTx implements driver.ConnBeginTx interface
func (mc *mysqlConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
if err := mc.watchCancel(ctx); err != nil {
return nil, err
}
defer mc.finish()
if sql.IsolationLevel(opts.Isolation) != sql.LevelDefault {
level, err := mapIsolationLevel(opts.Isolation)
if err != nil {
return nil, err
}
err = mc.exec("SET TRANSACTION ISOLATION LEVEL " + level)
if err != nil {
return nil, err
}
}
return mc.begin(opts.ReadOnly)
}
func (mc *mysqlConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
dargs, err := namedValueToValue(args)
if err != nil {
return nil, err
}
if err := mc.watchCancel(ctx); err != nil {
return nil, err
}
rows, err := mc.query(query, dargs)
if err != nil {
mc.finish()
return nil, err
}
rows.finish = mc.finish
return rows, err
}
func (mc *mysqlConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
dargs, err := namedValueToValue(args)
if err != nil {
return nil, err
}
if err := mc.watchCancel(ctx); err != nil {
return nil, err
}
defer mc.finish()
return mc.Exec(query, dargs)
}
func (mc *mysqlConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
if err := mc.watchCancel(ctx); err != nil {
return nil, err
}
stmt, err := mc.Prepare(query)
mc.finish()
if err != nil {
return nil, err
}
select {
default:
case <-ctx.Done():
stmt.Close()
return nil, ctx.Err()
}
return stmt, nil
}
func (stmt *mysqlStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
dargs, err := namedValueToValue(args)
if err != nil {
return nil, err
}
if err := stmt.mc.watchCancel(ctx); err != nil {
return nil, err
}
rows, err := stmt.query(dargs)
if err != nil {
stmt.mc.finish()
return nil, err
}
rows.finish = stmt.mc.finish
return rows, err
}
func (stmt *mysqlStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
dargs, err := namedValueToValue(args)
if err != nil {
return nil, err
}
if err := stmt.mc.watchCancel(ctx); err != nil {
return nil, err
}
defer stmt.mc.finish()
return stmt.Exec(dargs)
}
func (mc *mysqlConn) watchCancel(ctx context.Context) error {
if mc.watching {
// Reach here if canceled,
// so the connection is already invalid
mc.cleanup()
return nil
}
if ctx.Done() == nil {
return nil
}
mc.watching = true
select {
default:
case <-ctx.Done():
return ctx.Err()
}
if mc.watcher == nil {
return nil
}
mc.watcher <- ctx
return nil
}
func (mc *mysqlConn) startWatcher() {
watcher := make(chan mysqlContext, 1)
mc.watcher = watcher
finished := make(chan struct{})
mc.finished = finished
go func() {
for {
var ctx mysqlContext
select {
case ctx = <-watcher:
case <-mc.closech:
return
}
select {
case <-ctx.Done():
mc.cancel(ctx.Err())
case <-finished:
case <-mc.closech:
return
}
}
}()
}
func (mc *mysqlConn) CheckNamedValue(nv *driver.NamedValue) (err error) {
nv.Value, err = converter{}.ConvertValue(nv.Value)
return
}
// ResetSession implements driver.SessionResetter.
// (From Go 1.10)
func (mc *mysqlConn) ResetSession(ctx context.Context) error {
if mc.closed.IsSet() {
return driver.ErrBadConn
}
return nil
}

202
vendor/github.com/go-sql-driver/mysql/connection_go18.go сгенерированный поставляемый
Просмотреть файл

@@ -1,202 +0,0 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build go1.8
package mysql
import (
"context"
"database/sql"
"database/sql/driver"
)
// Ping implements driver.Pinger interface
func (mc *mysqlConn) Ping(ctx context.Context) error {
if mc.closed.IsSet() {
errLog.Print(ErrInvalidConn)
return driver.ErrBadConn
}
if err := mc.watchCancel(ctx); err != nil {
return err
}
defer mc.finish()
if err := mc.writeCommandPacket(comPing); err != nil {
return err
}
if _, err := mc.readResultOK(); err != nil {
return err
}
return nil
}
// BeginTx implements driver.ConnBeginTx interface
func (mc *mysqlConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
if err := mc.watchCancel(ctx); err != nil {
return nil, err
}
defer mc.finish()
if sql.IsolationLevel(opts.Isolation) != sql.LevelDefault {
level, err := mapIsolationLevel(opts.Isolation)
if err != nil {
return nil, err
}
err = mc.exec("SET TRANSACTION ISOLATION LEVEL " + level)
if err != nil {
return nil, err
}
}
return mc.begin(opts.ReadOnly)
}
func (mc *mysqlConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
dargs, err := namedValueToValue(args)
if err != nil {
return nil, err
}
if err := mc.watchCancel(ctx); err != nil {
return nil, err
}
rows, err := mc.query(query, dargs)
if err != nil {
mc.finish()
return nil, err
}
rows.finish = mc.finish
return rows, err
}
func (mc *mysqlConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
dargs, err := namedValueToValue(args)
if err != nil {
return nil, err
}
if err := mc.watchCancel(ctx); err != nil {
return nil, err
}
defer mc.finish()
return mc.Exec(query, dargs)
}
func (mc *mysqlConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
if err := mc.watchCancel(ctx); err != nil {
return nil, err
}
stmt, err := mc.Prepare(query)
mc.finish()
if err != nil {
return nil, err
}
select {
default:
case <-ctx.Done():
stmt.Close()
return nil, ctx.Err()
}
return stmt, nil
}
func (stmt *mysqlStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
dargs, err := namedValueToValue(args)
if err != nil {
return nil, err
}
if err := stmt.mc.watchCancel(ctx); err != nil {
return nil, err
}
rows, err := stmt.query(dargs)
if err != nil {
stmt.mc.finish()
return nil, err
}
rows.finish = stmt.mc.finish
return rows, err
}
func (stmt *mysqlStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
dargs, err := namedValueToValue(args)
if err != nil {
return nil, err
}
if err := stmt.mc.watchCancel(ctx); err != nil {
return nil, err
}
defer stmt.mc.finish()
return stmt.Exec(dargs)
}
func (mc *mysqlConn) watchCancel(ctx context.Context) error {
if mc.watching {
// Reach here if canceled,
// so the connection is already invalid
mc.cleanup()
return nil
}
if ctx.Done() == nil {
return nil
}
mc.watching = true
select {
default:
case <-ctx.Done():
return ctx.Err()
}
if mc.watcher == nil {
return nil
}
mc.watcher <- ctx
return nil
}
func (mc *mysqlConn) startWatcher() {
watcher := make(chan mysqlContext, 1)
mc.watcher = watcher
finished := make(chan struct{})
mc.finished = finished
go func() {
for {
var ctx mysqlContext
select {
case ctx = <-watcher:
case <-mc.closech:
return
}
select {
case <-ctx.Done():
mc.cancel(ctx.Err())
case <-finished:
case <-mc.closech:
return
}
}
}()
}
func (mc *mysqlConn) CheckNamedValue(nv *driver.NamedValue) (err error) {
nv.Value, err = converter{}.ConvertValue(nv.Value)
return
}

16
vendor/github.com/go-sql-driver/mysql/const.go сгенерированный поставляемый
Просмотреть файл

@@ -9,6 +9,7 @@
package mysql package mysql
const ( const (
defaultAuthPlugin = "mysql_native_password"
defaultMaxAllowedPacket = 4 << 20 // 4 MiB defaultMaxAllowedPacket = 4 << 20 // 4 MiB
minProtocolVersion = 10 minProtocolVersion = 10
maxPacketSize = 1<<24 - 1 maxPacketSize = 1<<24 - 1
@@ -19,10 +20,11 @@ const (
// http://dev.mysql.com/doc/internals/en/client-server-protocol.html // http://dev.mysql.com/doc/internals/en/client-server-protocol.html
const ( const (
iOK byte = 0x00 iOK byte = 0x00
iLocalInFile byte = 0xfb iAuthMoreData byte = 0x01
iEOF byte = 0xfe iLocalInFile byte = 0xfb
iERR byte = 0xff iEOF byte = 0xfe
iERR byte = 0xff
) )
// https://dev.mysql.com/doc/internals/en/capability-flags.html#packet-Protocol::CapabilityFlags // https://dev.mysql.com/doc/internals/en/capability-flags.html#packet-Protocol::CapabilityFlags
@@ -164,3 +166,9 @@ const (
statusInTransReadonly statusInTransReadonly
statusSessionStateChanged statusSessionStateChanged
) )
const (
cachingSha2PasswordRequestPublicKey = 2
cachingSha2PasswordFastAuthSuccess = 3
cachingSha2PasswordPerformFullAuthentication = 4
)

70
vendor/github.com/go-sql-driver/mysql/driver.go сгенерированный поставляемый
Просмотреть файл

@@ -23,11 +23,6 @@ import (
"sync" "sync"
) )
// watcher interface is used for context support (From Go 1.8)
type watcher interface {
startWatcher()
}
// MySQLDriver is exported to make the driver directly accessible. // MySQLDriver is exported to make the driver directly accessible.
// In general the driver is used via the database/sql package. // In general the driver is used via the database/sql package.
type MySQLDriver struct{} type MySQLDriver struct{}
@@ -96,9 +91,7 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
} }
// Call startWatcher for context support (From Go 1.8) // Call startWatcher for context support (From Go 1.8)
if s, ok := interface{}(mc).(watcher); ok { mc.startWatcher()
s.startWatcher()
}
mc.buf = newBuffer(mc.netConn) mc.buf = newBuffer(mc.netConn)
@@ -107,20 +100,31 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
mc.writeTimeout = mc.cfg.WriteTimeout mc.writeTimeout = mc.cfg.WriteTimeout
// Reading Handshake Initialization Packet // Reading Handshake Initialization Packet
cipher, err := mc.readInitPacket() authData, plugin, err := mc.readHandshakePacket()
if err != nil { if err != nil {
mc.cleanup() mc.cleanup()
return nil, err return nil, err
} }
// Send Client Authentication Packet // Send Client Authentication Packet
if err = mc.writeAuthPacket(cipher); err != nil { authResp, addNUL, err := mc.auth(authData, plugin)
if err != nil {
// try the default auth plugin, if using the requested plugin failed
errLog.Print("could not use requested auth plugin '"+plugin+"': ", err.Error())
plugin = defaultAuthPlugin
authResp, addNUL, err = mc.auth(authData, plugin)
if err != nil {
mc.cleanup()
return nil, err
}
}
if err = mc.writeHandshakeResponsePacket(authResp, addNUL, plugin); err != nil {
mc.cleanup() mc.cleanup()
return nil, err return nil, err
} }
// Handle response to auth packet, switch methods if possible // Handle response to auth packet, switch methods if possible
if err = handleAuthResult(mc, cipher); err != nil { if err = mc.handleAuthResult(authData, plugin); err != nil {
// Authentication failed and MySQL has already closed the connection // Authentication failed and MySQL has already closed the connection
// (https://dev.mysql.com/doc/internals/en/authentication-fails.html). // (https://dev.mysql.com/doc/internals/en/authentication-fails.html).
// Do not send COM_QUIT, just cleanup and return the error. // Do not send COM_QUIT, just cleanup and return the error.
@@ -153,50 +157,6 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
return mc, nil return mc, nil
} }
func handleAuthResult(mc *mysqlConn, oldCipher []byte) error {
// Read Result Packet
cipher, err := mc.readResultOK()
if err == nil {
return nil // auth successful
}
if mc.cfg == nil {
return err // auth failed and retry not possible
}
// Retry auth if configured to do so.
if mc.cfg.AllowOldPasswords && err == ErrOldPassword {
// Retry with old authentication method. Note: there are edge cases
// where this should work but doesn't; this is currently "wontfix":
// https://github.com/go-sql-driver/mysql/issues/184
// If CLIENT_PLUGIN_AUTH capability is not supported, no new cipher is
// sent and we have to keep using the cipher sent in the init packet.
if cipher == nil {
cipher = oldCipher
}
if err = mc.writeOldAuthPacket(cipher); err != nil {
return err
}
_, err = mc.readResultOK()
} else if mc.cfg.AllowCleartextPasswords && err == ErrCleartextPassword {
// Retry with clear text password for
// http://dev.mysql.com/doc/refman/5.7/en/cleartext-authentication-plugin.html
// http://dev.mysql.com/doc/refman/5.7/en/pam-authentication-plugin.html
if err = mc.writeClearAuthPacket(); err != nil {
return err
}
_, err = mc.readResultOK()
} else if mc.cfg.AllowNativePasswords && err == ErrNativePassword {
if err = mc.writeNativeAuthPacket(cipher); err != nil {
return err
}
_, err = mc.readResultOK()
}
return err
}
func init() { func init() {
sql.Register("mysql", &MySQLDriver{}) sql.Register("mysql", &MySQLDriver{})
} }

27
vendor/github.com/go-sql-driver/mysql/dsn.go сгенерированный поставляемый
Просмотреть файл

@@ -10,6 +10,7 @@ package mysql
import ( import (
"bytes" "bytes"
"crypto/rsa"
"crypto/tls" "crypto/tls"
"errors" "errors"
"fmt" "fmt"
@@ -41,6 +42,8 @@ type Config struct {
Collation string // Connection collation Collation string // Connection collation
Loc *time.Location // Location for time.Time values Loc *time.Location // Location for time.Time values
MaxAllowedPacket int // Max packet size allowed MaxAllowedPacket int // Max packet size allowed
ServerPubKey string // Server public key name
pubKey *rsa.PublicKey // Server public key
TLSConfig string // TLS configuration name TLSConfig string // TLS configuration name
tls *tls.Config // TLS configuration tls *tls.Config // TLS configuration
Timeout time.Duration // Dial timeout Timeout time.Duration // Dial timeout
@@ -254,6 +257,16 @@ func (cfg *Config) FormatDSN() string {
} }
} }
if len(cfg.ServerPubKey) > 0 {
if hasParam {
buf.WriteString("&serverPubKey=")
} else {
hasParam = true
buf.WriteString("?serverPubKey=")
}
buf.WriteString(url.QueryEscape(cfg.ServerPubKey))
}
if cfg.Timeout > 0 { if cfg.Timeout > 0 {
if hasParam { if hasParam {
buf.WriteString("&timeout=") buf.WriteString("&timeout=")
@@ -512,6 +525,20 @@ func parseDSNParams(cfg *Config, params string) (err error) {
return errors.New("invalid bool value: " + value) return errors.New("invalid bool value: " + value)
} }
// Server public key
case "serverPubKey":
name, err := url.QueryUnescape(value)
if err != nil {
return fmt.Errorf("invalid value for server pub key name: %v", err)
}
if pubKey := getServerPubKey(name); pubKey != nil {
cfg.ServerPubKey = name
cfg.pubKey = pubKey
} else {
return errors.New("invalid value / unknown server pub key name: " + name)
}
// Strict mode // Strict mode
case "strict": case "strict":
panic("strict mode has been removed. See https://github.com/go-sql-driver/mysql/wiki/strict-mode") panic("strict mode has been removed. See https://github.com/go-sql-driver/mysql/wiki/strict-mode")

3
vendor/github.com/go-sql-driver/mysql/infile.go сгенерированный поставляемый
Просмотреть файл

@@ -174,8 +174,7 @@ func (mc *mysqlConn) handleInFileRequest(name string) (err error) {
// read OK packet // read OK packet
if err == nil { if err == nil {
_, err = mc.readResultOK() return mc.readResultOK()
return err
} }
mc.readPacket() mc.readPacket()

235
vendor/github.com/go-sql-driver/mysql/packets.go сгенерированный поставляемый
Просмотреть файл

@@ -149,29 +149,29 @@ func (mc *mysqlConn) writePacket(data []byte) error {
} }
/****************************************************************************** /******************************************************************************
* Initialisation Process * * Initialization Process *
******************************************************************************/ ******************************************************************************/
// Handshake Initialization Packet // Handshake Initialization Packet
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
func (mc *mysqlConn) readInitPacket() ([]byte, error) { func (mc *mysqlConn) readHandshakePacket() ([]byte, string, error) {
data, err := mc.readPacket() data, err := mc.readPacket()
if err != nil { if err != nil {
// for init we can rewrite this to ErrBadConn for sql.Driver to retry, since // for init we can rewrite this to ErrBadConn for sql.Driver to retry, since
// in connection initialization we don't risk retrying non-idempotent actions. // in connection initialization we don't risk retrying non-idempotent actions.
if err == ErrInvalidConn { if err == ErrInvalidConn {
return nil, driver.ErrBadConn return nil, "", driver.ErrBadConn
} }
return nil, err return nil, "", err
} }
if data[0] == iERR { if data[0] == iERR {
return nil, mc.handleErrorPacket(data) return nil, "", mc.handleErrorPacket(data)
} }
// protocol version [1 byte] // protocol version [1 byte]
if data[0] < minProtocolVersion { if data[0] < minProtocolVersion {
return nil, fmt.Errorf( return nil, "", fmt.Errorf(
"unsupported protocol version %d. Version %d or higher is required", "unsupported protocol version %d. Version %d or higher is required",
data[0], data[0],
minProtocolVersion, minProtocolVersion,
@@ -183,7 +183,7 @@ func (mc *mysqlConn) readInitPacket() ([]byte, error) {
pos := 1 + bytes.IndexByte(data[1:], 0x00) + 1 + 4 pos := 1 + bytes.IndexByte(data[1:], 0x00) + 1 + 4
// first part of the password cipher [8 bytes] // first part of the password cipher [8 bytes]
cipher := data[pos : pos+8] authData := data[pos : pos+8]
// (filler) always 0x00 [1 byte] // (filler) always 0x00 [1 byte]
pos += 8 + 1 pos += 8 + 1
@@ -191,13 +191,14 @@ func (mc *mysqlConn) readInitPacket() ([]byte, error) {
// capability flags (lower 2 bytes) [2 bytes] // capability flags (lower 2 bytes) [2 bytes]
mc.flags = clientFlag(binary.LittleEndian.Uint16(data[pos : pos+2])) mc.flags = clientFlag(binary.LittleEndian.Uint16(data[pos : pos+2]))
if mc.flags&clientProtocol41 == 0 { if mc.flags&clientProtocol41 == 0 {
return nil, ErrOldProtocol return nil, "", ErrOldProtocol
} }
if mc.flags&clientSSL == 0 && mc.cfg.tls != nil { if mc.flags&clientSSL == 0 && mc.cfg.tls != nil {
return nil, ErrNoTLS return nil, "", ErrNoTLS
} }
pos += 2 pos += 2
plugin := ""
if len(data) > pos { if len(data) > pos {
// character set [1 byte] // character set [1 byte]
// status flags [2 bytes] // status flags [2 bytes]
@@ -218,32 +219,34 @@ func (mc *mysqlConn) readInitPacket() ([]byte, error) {
// //
// The official Python library uses the fixed length 12 // The official Python library uses the fixed length 12
// which seems to work but technically could have a hidden bug. // which seems to work but technically could have a hidden bug.
cipher = append(cipher, data[pos:pos+12]...) authData = append(authData, data[pos:pos+12]...)
pos += 13
// TODO: Verify string termination
// EOF if version (>= 5.5.7 and < 5.5.10) or (>= 5.6.0 and < 5.6.2) // EOF if version (>= 5.5.7 and < 5.5.10) or (>= 5.6.0 and < 5.6.2)
// \NUL otherwise // \NUL otherwise
// if end := bytes.IndexByte(data[pos:], 0x00); end != -1 {
//if data[len(data)-1] == 0 { plugin = string(data[pos : pos+end])
// return } else {
//} plugin = string(data[pos:])
//return ErrMalformPkt }
// make a memory safe copy of the cipher slice // make a memory safe copy of the cipher slice
var b [20]byte var b [20]byte
copy(b[:], cipher) copy(b[:], authData)
return b[:], nil return b[:], plugin, nil
} }
plugin = defaultAuthPlugin
// make a memory safe copy of the cipher slice // make a memory safe copy of the cipher slice
var b [8]byte var b [8]byte
copy(b[:], cipher) copy(b[:], authData)
return b[:], nil return b[:], plugin, nil
} }
// Client Authentication Packet // Client Authentication Packet
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::HandshakeResponse
func (mc *mysqlConn) writeAuthPacket(cipher []byte) error { func (mc *mysqlConn) writeHandshakeResponsePacket(authResp []byte, addNUL bool, plugin string) error {
// Adjust client flags based on server support // Adjust client flags based on server support
clientFlags := clientProtocol41 | clientFlags := clientProtocol41 |
clientSecureConn | clientSecureConn |
@@ -267,10 +270,19 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
clientFlags |= clientMultiStatements clientFlags |= clientMultiStatements
} }
// User Password // encode length of the auth plugin data
scrambleBuff := scramblePassword(cipher, []byte(mc.cfg.Passwd)) var authRespLEIBuf [9]byte
authRespLEI := appendLengthEncodedInteger(authRespLEIBuf[:0], uint64(len(authResp)))
if len(authRespLEI) > 1 {
// if the length can not be written in 1 byte, it must be written as a
// length encoded integer
clientFlags |= clientPluginAuthLenEncClientData
}
pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 + 1 + len(scrambleBuff) + 21 + 1 pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.User) + 1 + len(authRespLEI) + len(authResp) + 21 + 1
if addNUL {
pktLen++
}
// To specify a db name // To specify a db name
if n := len(mc.cfg.DBName); n > 0 { if n := len(mc.cfg.DBName); n > 0 {
@@ -281,7 +293,7 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
// Calculate packet length and get buffer with that size // Calculate packet length and get buffer with that size
data := mc.buf.takeSmallBuffer(pktLen + 4) data := mc.buf.takeSmallBuffer(pktLen + 4)
if data == nil { if data == nil {
// can not take the buffer. Something must be wrong with the connection // cannot take the buffer. Something must be wrong with the connection
errLog.Print(ErrBusyBuffer) errLog.Print(ErrBusyBuffer)
return errBadConnNoWrite return errBadConnNoWrite
} }
@@ -338,9 +350,13 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
data[pos] = 0x00 data[pos] = 0x00
pos++ pos++
// ScrambleBuffer [length encoded integer] // Auth Data [length encoded integer]
data[pos] = byte(len(scrambleBuff)) pos += copy(data[pos:], authRespLEI)
pos += 1 + copy(data[pos+1:], scrambleBuff) pos += copy(data[pos:], authResp)
if addNUL {
data[pos] = 0x00
pos++
}
// Databasename [null terminated string] // Databasename [null terminated string]
if len(mc.cfg.DBName) > 0 { if len(mc.cfg.DBName) > 0 {
@@ -349,76 +365,32 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
pos++ pos++
} }
// Assume native client during response pos += copy(data[pos:], plugin)
pos += copy(data[pos:], "mysql_native_password")
data[pos] = 0x00 data[pos] = 0x00
// Send Auth packet // Send Auth packet
return mc.writePacket(data) return mc.writePacket(data)
} }
// Client old authentication packet
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse // http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse
func (mc *mysqlConn) writeOldAuthPacket(cipher []byte) error { func (mc *mysqlConn) writeAuthSwitchPacket(authData []byte, addNUL bool) error {
// User password pktLen := 4 + len(authData)
// https://dev.mysql.com/doc/internals/en/old-password-authentication.html if addNUL {
// Old password authentication only need and will need 8-byte challenge. pktLen++
scrambleBuff := scrambleOldPassword(cipher[:8], []byte(mc.cfg.Passwd)) }
data := mc.buf.takeSmallBuffer(pktLen)
// Calculate the packet length and add a tailing 0
pktLen := len(scrambleBuff) + 1
data := mc.buf.takeSmallBuffer(4 + pktLen)
if data == nil { if data == nil {
// can not take the buffer. Something must be wrong with the connection // cannot take the buffer. Something must be wrong with the connection
errLog.Print(ErrBusyBuffer) errLog.Print(ErrBusyBuffer)
return errBadConnNoWrite return errBadConnNoWrite
} }
// Add the scrambled password [null terminated string] // Add the auth data [EOF]
copy(data[4:], scrambleBuff) copy(data[4:], authData)
data[4+pktLen-1] = 0x00 if addNUL {
data[pktLen-1] = 0x00
return mc.writePacket(data)
}
// Client clear text authentication packet
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse
func (mc *mysqlConn) writeClearAuthPacket() error {
// Calculate the packet length and add a tailing 0
pktLen := len(mc.cfg.Passwd) + 1
data := mc.buf.takeSmallBuffer(4 + pktLen)
if data == nil {
// can not take the buffer. Something must be wrong with the connection
errLog.Print(ErrBusyBuffer)
return errBadConnNoWrite
} }
// Add the clear password [null terminated string]
copy(data[4:], mc.cfg.Passwd)
data[4+pktLen-1] = 0x00
return mc.writePacket(data)
}
// Native password authentication method
// http://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::AuthSwitchResponse
func (mc *mysqlConn) writeNativeAuthPacket(cipher []byte) error {
// https://dev.mysql.com/doc/internals/en/secure-password-authentication.html
// Native password authentication only need and will need 20-byte challenge.
scrambleBuff := scramblePassword(cipher[0:20], []byte(mc.cfg.Passwd))
// Calculate the packet length and add a tailing 0
pktLen := len(scrambleBuff)
data := mc.buf.takeSmallBuffer(4 + pktLen)
if data == nil {
// can not take the buffer. Something must be wrong with the connection
errLog.Print(ErrBusyBuffer)
return errBadConnNoWrite
}
// Add the scramble
copy(data[4:], scrambleBuff)
return mc.writePacket(data) return mc.writePacket(data)
} }
@@ -432,7 +404,7 @@ func (mc *mysqlConn) writeCommandPacket(command byte) error {
data := mc.buf.takeSmallBuffer(4 + 1) data := mc.buf.takeSmallBuffer(4 + 1)
if data == nil { if data == nil {
// can not take the buffer. Something must be wrong with the connection // cannot take the buffer. Something must be wrong with the connection
errLog.Print(ErrBusyBuffer) errLog.Print(ErrBusyBuffer)
return errBadConnNoWrite return errBadConnNoWrite
} }
@@ -451,7 +423,7 @@ func (mc *mysqlConn) writeCommandPacketStr(command byte, arg string) error {
pktLen := 1 + len(arg) pktLen := 1 + len(arg)
data := mc.buf.takeBuffer(pktLen + 4) data := mc.buf.takeBuffer(pktLen + 4)
if data == nil { if data == nil {
// can not take the buffer. Something must be wrong with the connection // cannot take the buffer. Something must be wrong with the connection
errLog.Print(ErrBusyBuffer) errLog.Print(ErrBusyBuffer)
return errBadConnNoWrite return errBadConnNoWrite
} }
@@ -472,7 +444,7 @@ func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) error {
data := mc.buf.takeSmallBuffer(4 + 1 + 4) data := mc.buf.takeSmallBuffer(4 + 1 + 4)
if data == nil { if data == nil {
// can not take the buffer. Something must be wrong with the connection // cannot take the buffer. Something must be wrong with the connection
errLog.Print(ErrBusyBuffer) errLog.Print(ErrBusyBuffer)
return errBadConnNoWrite return errBadConnNoWrite
} }
@@ -494,45 +466,50 @@ func (mc *mysqlConn) writeCommandPacketUint32(command byte, arg uint32) error {
* Result Packets * * Result Packets *
******************************************************************************/ ******************************************************************************/
// Returns error if Packet is not an 'Result OK'-Packet func (mc *mysqlConn) readAuthResult() ([]byte, string, error) {
func (mc *mysqlConn) readResultOK() ([]byte, error) {
data, err := mc.readPacket() data, err := mc.readPacket()
if err == nil { if err != nil {
// packet indicator return nil, "", err
switch data[0] {
case iOK:
return nil, mc.handleOkPacket(data)
case iEOF:
if len(data) > 1 {
pluginEndIndex := bytes.IndexByte(data, 0x00)
plugin := string(data[1:pluginEndIndex])
cipher := data[pluginEndIndex+1:]
switch plugin {
case "mysql_old_password":
// using old_passwords
return cipher, ErrOldPassword
case "mysql_clear_password":
// using clear text password
return cipher, ErrCleartextPassword
case "mysql_native_password":
// using mysql default authentication method
return cipher, ErrNativePassword
default:
return cipher, ErrUnknownPlugin
}
}
// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest
return nil, ErrOldPassword
default: // Error otherwise
return nil, mc.handleErrorPacket(data)
}
} }
return nil, err
// packet indicator
switch data[0] {
case iOK:
return nil, "", mc.handleOkPacket(data)
case iAuthMoreData:
return data[1:], "", err
case iEOF:
if len(data) < 1 {
// https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::OldAuthSwitchRequest
return nil, "mysql_old_password", nil
}
pluginEndIndex := bytes.IndexByte(data, 0x00)
if pluginEndIndex < 0 {
return nil, "", ErrMalformPkt
}
plugin := string(data[1:pluginEndIndex])
authData := data[pluginEndIndex+1:]
return authData, plugin, nil
default: // Error otherwise
return nil, "", mc.handleErrorPacket(data)
}
}
// Returns error if Packet is not an 'Result OK'-Packet
func (mc *mysqlConn) readResultOK() error {
data, err := mc.readPacket()
if err != nil {
return err
}
if data[0] == iOK {
return mc.handleOkPacket(data)
}
return mc.handleErrorPacket(data)
} }
// Result Set Header Packet // Result Set Header Packet
@@ -866,7 +843,7 @@ func (stmt *mysqlStmt) writeCommandLongData(paramID int, arg []byte) error {
// 2 bytes paramID // 2 bytes paramID
const dataOffset = 1 + 4 + 2 const dataOffset = 1 + 4 + 2
// Can not use the write buffer since // Cannot use the write buffer since
// a) the buffer is too small // a) the buffer is too small
// b) it is in use // b) it is in use
data := make([]byte, 4+1+4+2+len(arg)) data := make([]byte, 4+1+4+2+len(arg))
@@ -938,7 +915,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
data = mc.buf.takeCompleteBuffer() data = mc.buf.takeCompleteBuffer()
} }
if data == nil { if data == nil {
// can not take the buffer. Something must be wrong with the connection // cannot take the buffer. Something must be wrong with the connection
errLog.Print(ErrBusyBuffer) errLog.Print(ErrBusyBuffer)
return errBadConnNoWrite return errBadConnNoWrite
} }
@@ -1106,7 +1083,7 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error {
paramValues = append(paramValues, b...) paramValues = append(paramValues, b...)
default: default:
return fmt.Errorf("can not convert type: %T", arg) return fmt.Errorf("cannot convert type: %T", arg)
} }
} }
@@ -1284,7 +1261,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
rows.rs.columns[i].decimals, rows.rs.columns[i].decimals,
) )
} }
dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen, true) dest[i], err = formatBinaryTime(data[pos:pos+int(num)], dstlen)
case rows.mc.parseTime: case rows.mc.parseTime:
dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.Loc) dest[i], err = parseBinaryDateTime(num, data[pos:], rows.mc.cfg.Loc)
default: default:
@@ -1304,7 +1281,7 @@ func (rows *binaryRows) readRow(dest []driver.Value) error {
) )
} }
} }
dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen, false) dest[i], err = formatBinaryDateTime(data[pos:pos+int(num)], dstlen)
} }
if err == nil { if err == nil {

409
vendor/github.com/go-sql-driver/mysql/utils.go сгенерированный поставляемый
Просмотреть файл

@@ -9,27 +9,31 @@
package mysql package mysql
import ( import (
"crypto/sha1"
"crypto/tls" "crypto/tls"
"database/sql"
"database/sql/driver" "database/sql/driver"
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"io" "io"
"strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
) )
// Registry for custom tls.Configs
var ( var (
tlsConfigLock sync.RWMutex tlsConfigLock sync.RWMutex
tlsConfigRegister map[string]*tls.Config // Register for custom tls.Configs tlsConfigRegistry map[string]*tls.Config
) )
// RegisterTLSConfig registers a custom tls.Config to be used with sql.Open. // RegisterTLSConfig registers a custom tls.Config to be used with sql.Open.
// Use the key as a value in the DSN where tls=value. // Use the key as a value in the DSN where tls=value.
// //
// Note: The tls.Config provided to needs to be exclusively owned by the driver after registering. // Note: The provided tls.Config is exclusively owned by the driver after
// registering it.
// //
// rootCertPool := x509.NewCertPool() // rootCertPool := x509.NewCertPool()
// pem, err := ioutil.ReadFile("/path/ca-cert.pem") // pem, err := ioutil.ReadFile("/path/ca-cert.pem")
@@ -57,11 +61,11 @@ func RegisterTLSConfig(key string, config *tls.Config) error {
} }
tlsConfigLock.Lock() tlsConfigLock.Lock()
if tlsConfigRegister == nil { if tlsConfigRegistry == nil {
tlsConfigRegister = make(map[string]*tls.Config) tlsConfigRegistry = make(map[string]*tls.Config)
} }
tlsConfigRegister[key] = config tlsConfigRegistry[key] = config
tlsConfigLock.Unlock() tlsConfigLock.Unlock()
return nil return nil
} }
@@ -69,16 +73,16 @@ func RegisterTLSConfig(key string, config *tls.Config) error {
// DeregisterTLSConfig removes the tls.Config associated with key. // DeregisterTLSConfig removes the tls.Config associated with key.
func DeregisterTLSConfig(key string) { func DeregisterTLSConfig(key string) {
tlsConfigLock.Lock() tlsConfigLock.Lock()
if tlsConfigRegister != nil { if tlsConfigRegistry != nil {
delete(tlsConfigRegister, key) delete(tlsConfigRegistry, key)
} }
tlsConfigLock.Unlock() tlsConfigLock.Unlock()
} }
func getTLSConfigClone(key string) (config *tls.Config) { func getTLSConfigClone(key string) (config *tls.Config) {
tlsConfigLock.RLock() tlsConfigLock.RLock()
if v, ok := tlsConfigRegister[key]; ok { if v, ok := tlsConfigRegistry[key]; ok {
config = cloneTLSConfig(v) config = v.Clone()
} }
tlsConfigLock.RUnlock() tlsConfigLock.RUnlock()
return return
@@ -98,119 +102,6 @@ func readBool(input string) (value bool, valid bool) {
return return
} }
/******************************************************************************
* Authentication *
******************************************************************************/
// Encrypt password using 4.1+ method
func scramblePassword(scramble, password []byte) []byte {
if len(password) == 0 {
return nil
}
// stage1Hash = SHA1(password)
crypt := sha1.New()
crypt.Write(password)
stage1 := crypt.Sum(nil)
// scrambleHash = SHA1(scramble + SHA1(stage1Hash))
// inner Hash
crypt.Reset()
crypt.Write(stage1)
hash := crypt.Sum(nil)
// outer Hash
crypt.Reset()
crypt.Write(scramble)
crypt.Write(hash)
scramble = crypt.Sum(nil)
// token = scrambleHash XOR stage1Hash
for i := range scramble {
scramble[i] ^= stage1[i]
}
return scramble
}
// Encrypt password using pre 4.1 (old password) method
// https://github.com/atcurtis/mariadb/blob/master/mysys/my_rnd.c
type myRnd struct {
seed1, seed2 uint32
}
const myRndMaxVal = 0x3FFFFFFF
// Pseudo random number generator
func newMyRnd(seed1, seed2 uint32) *myRnd {
return &myRnd{
seed1: seed1 % myRndMaxVal,
seed2: seed2 % myRndMaxVal,
}
}
// Tested to be equivalent to MariaDB's floating point variant
// http://play.golang.org/p/QHvhd4qved
// http://play.golang.org/p/RG0q4ElWDx
func (r *myRnd) NextByte() byte {
r.seed1 = (r.seed1*3 + r.seed2) % myRndMaxVal
r.seed2 = (r.seed1 + r.seed2 + 33) % myRndMaxVal
return byte(uint64(r.seed1) * 31 / myRndMaxVal)
}
// Generate binary hash from byte string using insecure pre 4.1 method
func pwHash(password []byte) (result [2]uint32) {
var add uint32 = 7
var tmp uint32
result[0] = 1345345333
result[1] = 0x12345671
for _, c := range password {
// skip spaces and tabs in password
if c == ' ' || c == '\t' {
continue
}
tmp = uint32(c)
result[0] ^= (((result[0] & 63) + add) * tmp) + (result[0] << 8)
result[1] += (result[1] << 8) ^ result[0]
add += tmp
}
// Remove sign bit (1<<31)-1)
result[0] &= 0x7FFFFFFF
result[1] &= 0x7FFFFFFF
return
}
// Encrypt password using insecure pre 4.1 method
func scrambleOldPassword(scramble, password []byte) []byte {
if len(password) == 0 {
return nil
}
scramble = scramble[:8]
hashPw := pwHash(password)
hashSc := pwHash(scramble)
r := newMyRnd(hashPw[0]^hashSc[0], hashPw[1]^hashSc[1])
var out [8]byte
for i := range out {
out[i] = r.NextByte() + 64
}
mask := r.NextByte()
for i := range out {
out[i] ^= mask
}
return out[:]
}
/****************************************************************************** /******************************************************************************
* Time related utils * * Time related utils *
******************************************************************************/ ******************************************************************************/
@@ -339,87 +230,104 @@ var zeroDateTime = []byte("0000-00-00 00:00:00.000000")
const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" const digits01 = "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"
const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999" const digits10 = "0000000000111111111122222222223333333333444444444455555555556666666666777777777788888888889999999999"
func formatBinaryDateTime(src []byte, length uint8, justTime bool) (driver.Value, error) { func appendMicrosecs(dst, src []byte, decimals int) []byte {
if decimals <= 0 {
return dst
}
if len(src) == 0 {
return append(dst, ".000000"[:decimals+1]...)
}
microsecs := binary.LittleEndian.Uint32(src[:4])
p1 := byte(microsecs / 10000)
microsecs -= 10000 * uint32(p1)
p2 := byte(microsecs / 100)
microsecs -= 100 * uint32(p2)
p3 := byte(microsecs)
switch decimals {
default:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2], digits01[p2],
digits10[p3], digits01[p3],
)
case 1:
return append(dst, '.',
digits10[p1],
)
case 2:
return append(dst, '.',
digits10[p1], digits01[p1],
)
case 3:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2],
)
case 4:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2], digits01[p2],
)
case 5:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2], digits01[p2],
digits10[p3],
)
}
}
func formatBinaryDateTime(src []byte, length uint8) (driver.Value, error) {
// length expects the deterministic length of the zero value, // length expects the deterministic length of the zero value,
// negative time and 100+ hours are automatically added if needed // negative time and 100+ hours are automatically added if needed
if len(src) == 0 { if len(src) == 0 {
if justTime {
return zeroDateTime[11 : 11+length], nil
}
return zeroDateTime[:length], nil return zeroDateTime[:length], nil
} }
var dst []byte // return value var dst []byte // return value
var pt, p1, p2, p3 byte // current digit pair var p1, p2, p3 byte // current digit pair
var zOffs byte // offset of value in zeroDateTime
if justTime { switch length {
switch length { case 10, 19, 21, 22, 23, 24, 25, 26:
case default:
8, // time (can be up to 10 when negative and 100+ hours) t := "DATE"
10, 11, 12, 13, 14, 15: // time with fractional seconds if length > 10 {
default: t += "TIME"
return nil, fmt.Errorf("illegal TIME length %d", length)
} }
switch len(src) { return nil, fmt.Errorf("illegal %s length %d", t, length)
case 8, 12:
default:
return nil, fmt.Errorf("invalid TIME packet length %d", len(src))
}
// +2 to enable negative time and 100+ hours
dst = make([]byte, 0, length+2)
if src[0] == 1 {
dst = append(dst, '-')
}
if src[1] != 0 {
hour := uint16(src[1])*24 + uint16(src[5])
pt = byte(hour / 100)
p1 = byte(hour - 100*uint16(pt))
dst = append(dst, digits01[pt])
} else {
p1 = src[5]
}
zOffs = 11
src = src[6:]
} else {
switch length {
case 10, 19, 21, 22, 23, 24, 25, 26:
default:
t := "DATE"
if length > 10 {
t += "TIME"
}
return nil, fmt.Errorf("illegal %s length %d", t, length)
}
switch len(src) {
case 4, 7, 11:
default:
t := "DATE"
if length > 10 {
t += "TIME"
}
return nil, fmt.Errorf("illegal %s packet length %d", t, len(src))
}
dst = make([]byte, 0, length)
// start with the date
year := binary.LittleEndian.Uint16(src[:2])
pt = byte(year / 100)
p1 = byte(year - 100*uint16(pt))
p2, p3 = src[2], src[3]
dst = append(dst,
digits10[pt], digits01[pt],
digits10[p1], digits01[p1], '-',
digits10[p2], digits01[p2], '-',
digits10[p3], digits01[p3],
)
if length == 10 {
return dst, nil
}
if len(src) == 4 {
return append(dst, zeroDateTime[10:length]...), nil
}
dst = append(dst, ' ')
p1 = src[4] // hour
src = src[5:]
} }
switch len(src) {
case 4, 7, 11:
default:
t := "DATE"
if length > 10 {
t += "TIME"
}
return nil, fmt.Errorf("illegal %s packet length %d", t, len(src))
}
dst = make([]byte, 0, length)
// start with the date
year := binary.LittleEndian.Uint16(src[:2])
pt := year / 100
p1 = byte(year - 100*uint16(pt))
p2, p3 = src[2], src[3]
dst = append(dst,
digits10[pt], digits01[pt],
digits10[p1], digits01[p1], '-',
digits10[p2], digits01[p2], '-',
digits10[p3], digits01[p3],
)
if length == 10 {
return dst, nil
}
if len(src) == 4 {
return append(dst, zeroDateTime[10:length]...), nil
}
dst = append(dst, ' ')
p1 = src[4] // hour
src = src[5:]
// p1 is 2-digit hour, src is after hour // p1 is 2-digit hour, src is after hour
p2, p3 = src[0], src[1] p2, p3 = src[0], src[1]
dst = append(dst, dst = append(dst,
@@ -427,51 +335,49 @@ func formatBinaryDateTime(src []byte, length uint8, justTime bool) (driver.Value
digits10[p2], digits01[p2], ':', digits10[p2], digits01[p2], ':',
digits10[p3], digits01[p3], digits10[p3], digits01[p3],
) )
if length <= byte(len(dst)) { return appendMicrosecs(dst, src[2:], int(length)-20), nil
return dst, nil }
}
src = src[2:] func formatBinaryTime(src []byte, length uint8) (driver.Value, error) {
// length expects the deterministic length of the zero value,
// negative time and 100+ hours are automatically added if needed
if len(src) == 0 { if len(src) == 0 {
return append(dst, zeroDateTime[19:zOffs+length]...), nil return zeroDateTime[11 : 11+length], nil
} }
microsecs := binary.LittleEndian.Uint32(src[:4]) var dst []byte // return value
p1 = byte(microsecs / 10000)
microsecs -= 10000 * uint32(p1) switch length {
p2 = byte(microsecs / 100) case
microsecs -= 100 * uint32(p2) 8, // time (can be up to 10 when negative and 100+ hours)
p3 = byte(microsecs) 10, 11, 12, 13, 14, 15: // time with fractional seconds
switch decimals := zOffs + length - 20; decimals {
default: default:
return append(dst, '.', return nil, fmt.Errorf("illegal TIME length %d", length)
digits10[p1], digits01[p1],
digits10[p2], digits01[p2],
digits10[p3], digits01[p3],
), nil
case 1:
return append(dst, '.',
digits10[p1],
), nil
case 2:
return append(dst, '.',
digits10[p1], digits01[p1],
), nil
case 3:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2],
), nil
case 4:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2], digits01[p2],
), nil
case 5:
return append(dst, '.',
digits10[p1], digits01[p1],
digits10[p2], digits01[p2],
digits10[p3],
), nil
} }
switch len(src) {
case 8, 12:
default:
return nil, fmt.Errorf("invalid TIME packet length %d", len(src))
}
// +2 to enable negative time and 100+ hours
dst = make([]byte, 0, length+2)
if src[0] == 1 {
dst = append(dst, '-')
}
days := binary.LittleEndian.Uint32(src[1:5])
hours := int64(days)*24 + int64(src[5])
if hours >= 100 {
dst = strconv.AppendInt(dst, hours, 10)
} else {
dst = append(dst, digits10[hours], digits01[hours])
}
min, sec := src[6], src[7]
dst = append(dst, ':',
digits10[min], digits01[min], ':',
digits10[sec], digits01[sec],
)
return appendMicrosecs(dst, src[8:], int(length)-9), nil
} }
/****************************************************************************** /******************************************************************************
@@ -820,3 +726,30 @@ func (ae *atomicError) Value() error {
} }
return nil return nil
} }
func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) {
dargs := make([]driver.Value, len(named))
for n, param := range named {
if len(param.Name) > 0 {
// TODO: support the use of Named Parameters #561
return nil, errors.New("mysql: driver does not support the use of Named Parameters")
}
dargs[n] = param.Value
}
return dargs, nil
}
func mapIsolationLevel(level driver.IsolationLevel) (string, error) {
switch sql.IsolationLevel(level) {
case sql.LevelRepeatableRead:
return "REPEATABLE READ", nil
case sql.LevelReadCommitted:
return "READ COMMITTED", nil
case sql.LevelReadUncommitted:
return "READ UNCOMMITTED", nil
case sql.LevelSerializable:
return "SERIALIZABLE", nil
default:
return "", fmt.Errorf("mysql: unsupported isolation level: %v", level)
}
}

40
vendor/github.com/go-sql-driver/mysql/utils_go17.go сгенерированный поставляемый
Просмотреть файл

@@ -1,40 +0,0 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build go1.7
// +build !go1.8
package mysql
import "crypto/tls"
func cloneTLSConfig(c *tls.Config) *tls.Config {
return &tls.Config{
Rand: c.Rand,
Time: c.Time,
Certificates: c.Certificates,
NameToCertificate: c.NameToCertificate,
GetCertificate: c.GetCertificate,
RootCAs: c.RootCAs,
NextProtos: c.NextProtos,
ServerName: c.ServerName,
ClientAuth: c.ClientAuth,
ClientCAs: c.ClientCAs,
InsecureSkipVerify: c.InsecureSkipVerify,
CipherSuites: c.CipherSuites,
PreferServerCipherSuites: c.PreferServerCipherSuites,
SessionTicketsDisabled: c.SessionTicketsDisabled,
SessionTicketKey: c.SessionTicketKey,
ClientSessionCache: c.ClientSessionCache,
MinVersion: c.MinVersion,
MaxVersion: c.MaxVersion,
CurvePreferences: c.CurvePreferences,
DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
Renegotiation: c.Renegotiation,
}
}

50
vendor/github.com/go-sql-driver/mysql/utils_go18.go сгенерированный поставляемый
Просмотреть файл

@@ -1,50 +0,0 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2017 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
// +build go1.8
package mysql
import (
"crypto/tls"
"database/sql"
"database/sql/driver"
"errors"
"fmt"
)
func cloneTLSConfig(c *tls.Config) *tls.Config {
return c.Clone()
}
func namedValueToValue(named []driver.NamedValue) ([]driver.Value, error) {
dargs := make([]driver.Value, len(named))
for n, param := range named {
if len(param.Name) > 0 {
// TODO: support the use of Named Parameters #561
return nil, errors.New("mysql: driver does not support the use of Named Parameters")
}
dargs[n] = param.Value
}
return dargs, nil
}
func mapIsolationLevel(level driver.IsolationLevel) (string, error) {
switch sql.IsolationLevel(level) {
case sql.LevelRepeatableRead:
return "REPEATABLE READ", nil
case sql.LevelReadCommitted:
return "READ COMMITTED", nil
case sql.LevelReadUncommitted:
return "READ UNCOMMITTED", nil
case sql.LevelSerializable:
return "SERIALIZABLE", nil
default:
return "", fmt.Errorf("mysql: unsupported isolation level: %v", level)
}
}

1
vendor/github.com/gorilla/websocket/AUTHORS сгенерированный поставляемый
Просмотреть файл

@@ -4,5 +4,6 @@
# Please keep the list sorted. # Please keep the list sorted.
Gary Burd <gary@beagledreams.com> Gary Burd <gary@beagledreams.com>
Google LLC (https://opensource.google.com/)
Joachim Bauch <mail@joachim-bauch.de> Joachim Bauch <mail@joachim-bauch.de>

4
vendor/github.com/jaytaylor/html2text/README.md сгенерированный поставляемый
Просмотреть файл

@@ -23,7 +23,7 @@ It requires go 1.x or newer ;)
## Download the package ## Download the package
```bash ```bash
go get github.com/jaytaylor/html2text go get jaytaylor.com/html2text
``` ```
## Example usage ## Example usage
@@ -34,7 +34,7 @@ package main
import ( import (
"fmt" "fmt"
"github.com/jaytaylor/html2text" "jaytaylor.com/html2text"
) )
func main() { func main() {

13
vendor/github.com/lib/pq/README.md сгенерированный поставляемый
Просмотреть файл

@@ -14,18 +14,7 @@ documentation at <http://godoc.org/github.com/lib/pq>.
## Tests ## Tests
`go test` is used for testing. A running PostgreSQL server is `go test` is used for testing. See [TESTS.md](TESTS.md) for more details.
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 ## Features

33
vendor/github.com/lib/pq/TESTS.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,33 @@
# Tests
## Running Tests
`go test` is used for testing. A running PostgreSQL
server is required, with the ability to log in. The
database to connect to test with is "pqgotest," on
"localhost" but these can be overridden using [environment
variables](https://www.postgresql.org/docs/9.3/static/libpq-envars.html).
Example:
PGHOST=/run/postgresql go test
## Benchmarks
A benchmark suite can be run as part of the tests:
go test -bench .
## Example setup (Docker)
Run a postgres container:
```
docker run --expose 5432:5432 postgres
```
Run tests:
```
PGHOST=localhost PGPORT=5432 PGUSER=postgres PGSSLMODE=disable PGDATABASE=postgres go test
```

43
vendor/github.com/lib/pq/connector.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,43 @@
// +build go1.10
package pq
import (
"context"
"database/sql/driver"
)
// Connector represents a fixed configuration for the pq driver with a given
// name. Connector satisfies the database/sql/driver Connector interface and
// can be used to create any number of DB Conn's via the database/sql OpenDB
// function.
//
// See https://golang.org/pkg/database/sql/driver/#Connector.
// See https://golang.org/pkg/database/sql/#OpenDB.
type connector struct {
name string
}
// Connect returns a connection to the database using the fixed configuration
// of this Connector. Context is not used.
func (c *connector) Connect(_ context.Context) (driver.Conn, error) {
return (&Driver{}).Open(c.name)
}
// Driver returnst the underlying driver of this Connector.
func (c *connector) Driver() driver.Driver {
return &Driver{}
}
var _ driver.Connector = &connector{}
// NewConnector returns a connector for the pq driver in a fixed configuration
// with the given name. The returned connector can be used to create any number
// of equivalent Conn's. The returned connector is intended to be used with
// database/sql.OpenDB.
//
// See https://golang.org/pkg/database/sql/driver/#Connector.
// See https://golang.org/pkg/database/sql/#OpenDB.
func NewConnector(name string) (driver.Connector, error) {
return &connector{name: name}, nil
}

1
vendor/github.com/mailru/easyjson/.gitignore сгенерированный поставляемый
Просмотреть файл

@@ -2,3 +2,4 @@
*_easyjson.go *_easyjson.go
*.iml *.iml
.idea .idea
*.swp

1
vendor/github.com/mailru/easyjson/Makefile сгенерированный поставляемый
Просмотреть файл

@@ -37,6 +37,7 @@ generate: root build
.root/bin/easyjson .root/src/$(PKG)/tests/named_type.go .root/bin/easyjson .root/src/$(PKG)/tests/named_type.go
.root/bin/easyjson .root/src/$(PKG)/tests/custom_map_key_type.go .root/bin/easyjson .root/src/$(PKG)/tests/custom_map_key_type.go
.root/bin/easyjson .root/src/$(PKG)/tests/embedded_type.go .root/bin/easyjson .root/src/$(PKG)/tests/embedded_type.go
.root/bin/easyjson -disallow_unknown_fields .root/src/$(PKG)/tests/disallow_unknown.go
test: generate root test: generate root
go test \ go test \

2
vendor/github.com/mailru/easyjson/README.md сгенерированный поставляемый
Просмотреть файл

@@ -53,6 +53,8 @@ Usage of easyjson:
use lowerCamelCase instead of CamelCase by default use lowerCamelCase instead of CamelCase by default
-stubs -stubs
only generate stubs for marshaler/unmarshaler funcs only generate stubs for marshaler/unmarshaler funcs
-disallow_unknown_fields
return error if some unknown field in json appeared
``` ```
Using `-all` will generate marshalers/unmarshalers for all Go structs in the Using `-all` will generate marshalers/unmarshalers for all Go structs in the

65
vendor/github.com/mattermost/viper/flags_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,65 +0,0 @@
package viper
import (
"testing"
"github.com/spf13/pflag"
"github.com/stretchr/testify/assert"
)
func TestBindFlagValueSet(t *testing.T) {
flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
var testValues = map[string]*string{
"host": nil,
"port": nil,
"endpoint": nil,
}
var mutatedTestValues = map[string]string{
"host": "localhost",
"port": "6060",
"endpoint": "/public",
}
for name := range testValues {
testValues[name] = flagSet.String(name, "", "test")
}
flagValueSet := pflagValueSet{flagSet}
err := BindFlagValues(flagValueSet)
if err != nil {
t.Fatalf("error binding flag set, %v", err)
}
flagSet.VisitAll(func(flag *pflag.Flag) {
flag.Value.Set(mutatedTestValues[flag.Name])
flag.Changed = true
})
for name, expected := range mutatedTestValues {
assert.Equal(t, Get(name), expected)
}
}
func TestBindFlagValue(t *testing.T) {
var testString = "testing"
var testValue = newStringValue(testString, &testString)
flag := &pflag.Flag{
Name: "testflag",
Value: testValue,
Changed: false,
}
flagValue := pflagValue{flag}
BindFlagValue("testvalue", flagValue)
assert.Equal(t, testString, Get("testvalue"))
flag.Value.Set("testing_mutate")
flag.Changed = true //hack for pflag usage
assert.Equal(t, "testing_mutate", Get("testvalue"))
}

173
vendor/github.com/mattermost/viper/overrides_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,173 +0,0 @@
package viper
import (
"fmt"
"strings"
"testing"
"github.com/spf13/cast"
"github.com/stretchr/testify/assert"
)
type layer int
const (
defaultLayer layer = iota + 1
overrideLayer
)
func TestNestedOverrides(t *testing.T) {
assert := assert.New(t)
var v *Viper
// Case 0: value overridden by a value
overrideDefault(assert, "tom", 10, "tom", 20) // "tom" is first given 10 as default value, then overridden by 20
override(assert, "tom", 10, "tom", 20) // "tom" is first given value 10, then overridden by 20
overrideDefault(assert, "tom.age", 10, "tom.age", 20)
override(assert, "tom.age", 10, "tom.age", 20)
overrideDefault(assert, "sawyer.tom.age", 10, "sawyer.tom.age", 20)
override(assert, "sawyer.tom.age", 10, "sawyer.tom.age", 20)
// Case 1: key:value overridden by a value
v = overrideDefault(assert, "tom.age", 10, "tom", "boy") // "tom.age" is first given 10 as default value, then "tom" is overridden by "boy"
assert.Nil(v.Get("tom.age")) // "tom.age" should not exist anymore
v = override(assert, "tom.age", 10, "tom", "boy")
assert.Nil(v.Get("tom.age"))
// Case 2: value overridden by a key:value
overrideDefault(assert, "tom", "boy", "tom.age", 10) // "tom" is first given "boy" as default value, then "tom" is overridden by map{"age":10}
override(assert, "tom.age", 10, "tom", "boy")
// Case 3: key:value overridden by a key:value
v = overrideDefault(assert, "tom.size", 4, "tom.age", 10)
assert.Equal(4, v.Get("tom.size")) // value should still be reachable
v = override(assert, "tom.size", 4, "tom.age", 10)
assert.Equal(4, v.Get("tom.size"))
deepCheckValue(assert, v, overrideLayer, []string{"tom", "size"}, 4)
// Case 4: key:value overridden by a map
v = overrideDefault(assert, "tom.size", 4, "tom", map[string]interface{}{"age": 10}) // "tom.size" is first given "4" as default value, then "tom" is overridden by map{"age":10}
assert.Equal(4, v.Get("tom.size")) // "tom.size" should still be reachable
assert.Equal(10, v.Get("tom.age")) // new value should be there
deepCheckValue(assert, v, overrideLayer, []string{"tom", "age"}, 10) // new value should be there
v = override(assert, "tom.size", 4, "tom", map[string]interface{}{"age": 10})
assert.Nil(v.Get("tom.size"))
assert.Equal(10, v.Get("tom.age"))
deepCheckValue(assert, v, overrideLayer, []string{"tom", "age"}, 10)
// Case 5: array overridden by a value
overrideDefault(assert, "tom", []int{10, 20}, "tom", 30)
override(assert, "tom", []int{10, 20}, "tom", 30)
overrideDefault(assert, "tom.age", []int{10, 20}, "tom.age", 30)
override(assert, "tom.age", []int{10, 20}, "tom.age", 30)
// Case 6: array overridden by an array
overrideDefault(assert, "tom", []int{10, 20}, "tom", []int{30, 40})
override(assert, "tom", []int{10, 20}, "tom", []int{30, 40})
overrideDefault(assert, "tom.age", []int{10, 20}, "tom.age", []int{30, 40})
v = override(assert, "tom.age", []int{10, 20}, "tom.age", []int{30, 40})
// explicit array merge:
s, ok := v.Get("tom.age").([]int)
if assert.True(ok, "tom[\"age\"] is not a slice") {
v.Set("tom.age", append(s, []int{50, 60}...))
assert.Equal([]int{30, 40, 50, 60}, v.Get("tom.age"))
deepCheckValue(assert, v, overrideLayer, []string{"tom", "age"}, []int{30, 40, 50, 60})
}
}
func overrideDefault(assert *assert.Assertions, firstPath string, firstValue interface{}, secondPath string, secondValue interface{}) *Viper {
return overrideFromLayer(defaultLayer, assert, firstPath, firstValue, secondPath, secondValue)
}
func override(assert *assert.Assertions, firstPath string, firstValue interface{}, secondPath string, secondValue interface{}) *Viper {
return overrideFromLayer(overrideLayer, assert, firstPath, firstValue, secondPath, secondValue)
}
// overrideFromLayer performs the sequential override and low-level checks.
//
// First assignment is made on layer l for path firstPath with value firstValue,
// the second one on the override layer (i.e., with the Set() function)
// for path secondPath with value secondValue.
//
// firstPath and secondPath can include an arbitrary number of dots to indicate
// a nested element.
//
// After each assignment, the value is checked, retrieved both by its full path
// and by its key sequence (successive maps).
func overrideFromLayer(l layer, assert *assert.Assertions, firstPath string, firstValue interface{}, secondPath string, secondValue interface{}) *Viper {
v := New()
firstKeys := strings.Split(firstPath, v.keyDelim)
if assert == nil ||
len(firstKeys) == 0 || len(firstKeys[0]) == 0 {
return v
}
// Set and check first value
switch l {
case defaultLayer:
v.SetDefault(firstPath, firstValue)
case overrideLayer:
v.Set(firstPath, firstValue)
default:
return v
}
assert.Equal(firstValue, v.Get(firstPath))
deepCheckValue(assert, v, l, firstKeys, firstValue)
// Override and check new value
secondKeys := strings.Split(secondPath, v.keyDelim)
if len(secondKeys) == 0 || len(secondKeys[0]) == 0 {
return v
}
v.Set(secondPath, secondValue)
assert.Equal(secondValue, v.Get(secondPath))
deepCheckValue(assert, v, overrideLayer, secondKeys, secondValue)
return v
}
// deepCheckValue checks that all given keys correspond to a valid path in the
// configuration map of the given layer, and that the final value equals the one given
func deepCheckValue(assert *assert.Assertions, v *Viper, l layer, keys []string, value interface{}) {
if assert == nil || v == nil ||
len(keys) == 0 || len(keys[0]) == 0 {
return
}
// init
var val interface{}
var ms string
switch l {
case defaultLayer:
val = v.defaults
ms = "v.defaults"
case overrideLayer:
val = v.override
ms = "v.override"
}
// loop through map
var m map[string]interface{}
err := false
for _, k := range keys {
if val == nil {
assert.Fail(fmt.Sprintf("%s is not a map[string]interface{}", ms))
return
}
// deep scan of the map to get the final value
switch val.(type) {
case map[interface{}]interface{}:
m = cast.ToStringMap(val)
case map[string]interface{}:
m = val.(map[string]interface{})
default:
assert.Fail(fmt.Sprintf("%s is not a map[string]interface{}", ms))
return
}
ms = ms + "[\"" + k + "\"]"
val = m[k]
}
if !err {
assert.Equal(value, val)
}
}

105
vendor/github.com/mattermost/viper/remote/remote.go сгенерированный поставляемый
Просмотреть файл

@@ -1,105 +0,0 @@
// Copyright © 2015 Steve Francia <spf@spf13.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// Package remote integrates the remote features of Viper.
package remote
import (
"bytes"
"io"
"os"
"github.com/spf13/viper"
crypt "github.com/xordataexchange/crypt/config"
)
type remoteConfigProvider struct{}
func (rc remoteConfigProvider) Get(rp viper.RemoteProvider) (io.Reader, error) {
cm, err := getConfigManager(rp)
if err != nil {
return nil, err
}
b, err := cm.Get(rp.Path())
if err != nil {
return nil, err
}
return bytes.NewReader(b), nil
}
func (rc remoteConfigProvider) Watch(rp viper.RemoteProvider) (io.Reader, error) {
cm, err := getConfigManager(rp)
if err != nil {
return nil, err
}
resp, err := cm.Get(rp.Path())
if err != nil {
return nil, err
}
return bytes.NewReader(resp), nil
}
func (rc remoteConfigProvider) WatchChannel(rp viper.RemoteProvider) (<-chan *viper.RemoteResponse, chan bool) {
cm, err := getConfigManager(rp)
if err != nil {
return nil, nil
}
quit := make(chan bool)
quitwc := make(chan bool)
viperResponsCh := make(chan *viper.RemoteResponse)
cryptoResponseCh := cm.Watch(rp.Path(), quit)
// need this function to convert the Channel response form crypt.Response to viper.Response
go func(cr <-chan *crypt.Response, vr chan<- *viper.RemoteResponse, quitwc <-chan bool, quit chan<- bool) {
for {
select {
case <-quitwc:
quit <- true
return
case resp := <-cr:
vr <- &viper.RemoteResponse{
Error: resp.Error,
Value: resp.Value,
}
}
}
}(cryptoResponseCh, viperResponsCh, quitwc, quit)
return viperResponsCh, quitwc
}
func getConfigManager(rp viper.RemoteProvider) (crypt.ConfigManager, error) {
var cm crypt.ConfigManager
var err error
if rp.SecretKeyring() != "" {
kr, err := os.Open(rp.SecretKeyring())
defer kr.Close()
if err != nil {
return nil, err
}
if rp.Provider() == "etcd" {
cm, err = crypt.NewEtcdConfigManager([]string{rp.Endpoint()}, kr)
} else {
cm, err = crypt.NewConsulConfigManager([]string{rp.Endpoint()}, kr)
}
} else {
if rp.Provider() == "etcd" {
cm, err = crypt.NewStandardEtcdConfigManager([]string{rp.Endpoint()})
} else {
cm, err = crypt.NewStandardConsulConfigManager([]string{rp.Endpoint()})
}
}
if err != nil {
return nil, err
}
return cm, nil
}
func init() {
viper.RemoteConfig = &remoteConfigProvider{}
}

54
vendor/github.com/mattermost/viper/util_test.go сгенерированный поставляемый
Просмотреть файл

@@ -1,54 +0,0 @@
// Copyright © 2016 Steve Francia <spf@spf13.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// Viper is a application configuration system.
// It believes that applications can be configured a variety of ways
// via flags, ENVIRONMENT variables, configuration files retrieved
// from the file system, or a remote key/value store.
package viper
import (
"reflect"
"testing"
)
func TestCopyAndInsensitiviseMap(t *testing.T) {
var (
given = map[string]interface{}{
"Foo": 32,
"Bar": map[interface{}]interface {
}{
"ABc": "A",
"cDE": "B"},
}
expected = map[string]interface{}{
"foo": 32,
"bar": map[string]interface {
}{
"abc": "A",
"cde": "B"},
}
)
got := copyAndInsensitiviseMap(given)
if !reflect.DeepEqual(got, expected) {
t.Fatalf("Got %q\nexpected\n%q", got, expected)
}
if _, ok := given["foo"]; ok {
t.Fatal("Input map changed")
}
if _, ok := given["bar"]; ok {
t.Fatal("Input map changed")
}
m := given["Bar"].(map[interface{}]interface{})
if _, ok := m["ABc"]; !ok {
t.Fatal("Input map changed")
}
}

1421
vendor/github.com/mattermost/viper/viper_test.go сгенерированный поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

10
vendor/github.com/mattn/go-sqlite3/.gitignore сгенерированный поставляемый
Просмотреть файл

@@ -2,3 +2,13 @@
*.exe *.exe
*.dll *.dll
*.o *.o
# VSCode
.vscode
# Exclude from upgrade
upgrade/*.c
upgrade/*.h
# Exclude upgrade binary
upgrade/upgrade

48
vendor/github.com/mattn/go-sqlite3/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -1,19 +1,41 @@
language: go language: go
sudo: required
dist: trusty os:
- linux
- osx
addons:
apt:
update: true
env: env:
- GOTAGS= matrix:
- GOTAGS=libsqlite3 - GOTAGS=
- GOTAGS=trace - GOTAGS=libsqlite3
- GOTAGS=vtable - GOTAGS="sqlite_allow_uri_authority sqlite_app_armor sqlite_foreign_keys sqlite_fts5 sqlite_icu sqlite_introspect sqlite_json sqlite_secure_delete sqlite_see sqlite_stat4 sqlite_trace sqlite_userauth sqlite_vacuum_incr sqlite_vtable"
- GOTAGS=sqlite_vacuum_full
go: go:
- 1.7.x
- 1.8.x
- 1.9.x - 1.9.x
- master - 1.10.x
before_install: before_install:
- go get github.com/mattn/goveralls - |
- go get golang.org/x/tools/cmd/cover if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
brew update
brew upgrade icu4c
fi
- |
go get github.com/smartystreets/goconvey
if [[ "${GOOS}" != "windows" ]]; then
go get github.com/mattn/goveralls
go get golang.org/x/tools/cmd/cover
fi
script: script:
- $HOME/gopath/bin/goveralls -repotoken 3qJVUE0iQwqnCbmNcDsjYu1nh4J4KIFXx - GOOS=$(go env GOOS) GOARCH=$(go env GOARCH) go build -v -tags "${GOTAGS}" .
- go test -race -v . -tags "$GOTAGS" - |
if [[ "${GOOS}" != "windows" ]]; then
$HOME/gopath/bin/goveralls -repotoken 3qJVUE0iQwqnCbmNcDsjYu1nh4J4KIFXx
go test -race -v . -tags "${GOTAGS}"
fi

485
vendor/github.com/mattn/go-sqlite3/README.md сгенерированный поставляемый
Просмотреть файл

@@ -6,13 +6,43 @@ go-sqlite3
[![Coverage Status](https://coveralls.io/repos/mattn/go-sqlite3/badge.svg?branch=master)](https://coveralls.io/r/mattn/go-sqlite3?branch=master) [![Coverage Status](https://coveralls.io/repos/mattn/go-sqlite3/badge.svg?branch=master)](https://coveralls.io/r/mattn/go-sqlite3?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-sqlite3)](https://goreportcard.com/report/github.com/mattn/go-sqlite3) [![Go Report Card](https://goreportcard.com/badge/github.com/mattn/go-sqlite3)](https://goreportcard.com/report/github.com/mattn/go-sqlite3)
Description # Description
-----------
sqlite3 driver conforming to the built-in database/sql interface sqlite3 driver conforming to the built-in database/sql interface
Installation Supported Golang version:
------------ - 1.9.x
- 1.10.x
[This package follows the official Golang Release Policy.](https://golang.org/doc/devel/release.html#policy)
### Overview
- [Installation](#installation)
- [API Reference](#api-reference)
- [Connection String](#connection-string)
- [Features](#features)
- [Compilation](#compilation)
- [Android](#android)
- [ARM](#arm)
- [Cross Compile](#cross-compile)
- [Google Cloud Platform](#google-cloud-platform)
- [Linux](#linux)
- [Alpine](#alpine)
- [Fedora](#fedora)
- [Ubuntu](#ubuntu)
- [Mac OSX](#mac-osx)
- [Windows](#windows)
- [Errors](#errors)
- [User Authentication](#user-authentication)
- [Compile](#compile)
- [Usage](#usage)
- [Extensions](#extensions)
- [Spatialite](#spatialite)
- [FAQ](#faq)
- [License](#license)
# Installation
This package can be installed with the go get command: This package can be installed with the go get command:
@@ -20,70 +50,460 @@ This package can be installed with the go get command:
_go-sqlite3_ is *cgo* package. _go-sqlite3_ is *cgo* package.
If you want to build your app using go-sqlite3, you need gcc. If you want to build your app using go-sqlite3, you need gcc.
However, if you install _go-sqlite3_ with `go install github.com/mattn/go-sqlite3`, you don't need gcc to build your app anymore. However, after you have built and installed _go-sqlite3_ with `go install github.com/mattn/go-sqlite3` (which requires gcc), you can build your app without relying on gcc in future.
Documentation ***Important: because this is a `CGO` enabled package you are required to set the environment variable `CGO_ENABLED=1` and have a `gcc` compile present within your path.***
-------------
# API Reference
API documentation can be found here: http://godoc.org/github.com/mattn/go-sqlite3 API documentation can be found here: http://godoc.org/github.com/mattn/go-sqlite3
Examples can be found under the `./_example` directory Examples can be found under the [examples](./_example) directory
FAQ # Connection String
---
* Want to build go-sqlite3 with libsqlite3 on my linux. When creating a new SQLite database or connection to an existing one, with the file name additional options can be given.
This is also known as a DSN string. (Data Source Name).
Use `go build --tags "libsqlite3 linux"` Options are append after the filename of the SQLite database.
The database filename and options are seperated by an `?` (Question Mark).
* Want to build go-sqlite3 with libsqlite3 on OS X. This also applies when using an in-memory database instead of a file.
Install sqlite3 from homebrew: `brew install sqlite3` Options can be given using the following format: `KEYWORD=VALUE` and multiple options can be combined with the `&` ampersand.
Use `go build --tags "libsqlite3 darwin"` This library supports dsn options of SQLite itself and provides additional options.
* Want to build go-sqlite3 with icu extension. Boolean values can be one of:
* `0` `no` `false` `off`
* `1` `yes` `true` `on`
Use `go build --tags "icu"` | Name | Key | Value(s) | Description |
|------|-----|----------|-------------|
| UA - Create | `_auth` | - | Create User Authentication, for more information see [User Authentication](#user-authentication) |
| UA - Username | `_auth_user` | `string` | Username for User Authentication, for more information see [User Authentication](#user-authentication) |
| UA - Password | `_auth_pass` | `string` | Password for User Authentication, for more information see [User Authentication](#user-authentication) |
| UA - Crypt | `_auth_crypt` | <ul><li>SHA1</li><li>SSHA1</li><li>SHA256</li><li>SSHA256</li><li>SHA384</li><li>SSHA384</li><li>SHA512</li><li>SSHA512</li></ul> | Password encoder to use for User Authentication, for more information see [User Authentication](#user-authentication) |
| UA - Salt | `_auth_salt` | `string` | Salt to use if the configure password encoder requires a salt, for User Authentication, for more information see [User Authentication](#user-authentication) |
| Auto Vacuum | `_auto_vacuum` \| `_vacuum` | <ul><li>`0` \| `none`</li><li>`1` \| `full`</li><li>`2` \| `incremental`</li></ul> | For more information see [PRAGMA auto_vacuum](https://www.sqlite.org/pragma.html#pragma_auto_vacuum) |
| Busy Timeout | `_busy_timeout` \| `_timeout` | `int` | Specify value for sqlite3_busy_timeout. For more information see [PRAGMA busy_timeout](https://www.sqlite.org/pragma.html#pragma_busy_timeout) |
| Case Sensitive LIKE | `_case_sensitive_like` \| `_cslike` | `boolean` | For more information see [PRAGMA case_sensitive_like](https://www.sqlite.org/pragma.html#pragma_case_sensitive_like) |
| Defer Foreign Keys | `_defer_foreign_keys` \| `_defer_fk` | `boolean` | For more information see [PRAGMA defer_foreign_keys](https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys) |
| Foreign Keys | `_foreign_keys` \| `_fk` | `boolean` | For more information see [PRAGMA foreign_keys](https://www.sqlite.org/pragma.html#pragma_foreign_keys) |
| Ignore CHECK Constraints | `_ignore_check_constraints` | `boolean` | For more information see [PRAGMA ignore_check_constraints](https://www.sqlite.org/pragma.html#pragma_ignore_check_constraints) |
| Immutable | `immutable` | `boolean` | For more information see [Immutable](https://www.sqlite.org/c3ref/open.html) |
| Journal Mode | `_journal_mode` \| `_journal` | <ul><li>DELETE</li><li>TRUNCATE</li><li>PERSIST</li><li>MEMORY</li><li>WAL</li><li>OFF</li></ul> | For more information see [PRAGMA journal_mode](https://www.sqlite.org/pragma.html#pragma_journal_mode) |
| Locking Mode | `_locking_mode` \| `_locking` | <ul><li>NORMAL</li><li>EXCLUSIVE</li></ul> | For more information see [PRAGMA locking_mode](https://www.sqlite.org/pragma.html#pragma_locking_mode) |
| Mode | `mode` | <ul><li>ro</li><li>rw</li><li>rwc</li><li>memory</li></ul> | Access Mode of the database. For more information see [SQLite Open](https://www.sqlite.org/c3ref/open.html) |
| Mutex Locking | `_mutex` | <ul><li>no</li><li>full</li></ul> | Specify mutex mode. |
| Query Only | `_query_only` | `boolean` | For more information see [PRAGMA query_only](https://www.sqlite.org/pragma.html#pragma_query_only) |
| Recursive Triggers | `_recursive_triggers` \| `_rt` | `boolean` | For more information see [PRAGMA recursive_triggers](https://www.sqlite.org/pragma.html#pragma_recursive_triggers) |
| Secure Delete | `_secure_delete` | `boolean` \| `FAST` | For more information see [PRAGMA secure_delete](https://www.sqlite.org/pragma.html#pragma_secure_delete) |
| Shared-Cache Mode | `cache` | <ul><li>shared</li><li>private</li></ul> | Set cache mode for more information see [sqlite.org](https://www.sqlite.org/sharedcache.html) |
| Synchronous | `_synchronous` \| `_sync` | <ul><li>0 \| OFF</li><li>1 \| NORMAL</li><li>2 \| FULL</li><li>3 \| EXTRA</li></ul> | For more information see [PRAGMA synchronous](https://www.sqlite.org/pragma.html#pragma_synchronous) |
| Time Zone Location | `_loc` | auto | Specify location of time format. |
| Transaction Lock | `_txlock` | <ul><li>immediate</li><li>deferred</li><li>exclusive</li></ul> | Specify locking behavior for transactions. |
| Writable Schema | `_writable_schema` | `Boolean` | When this pragma is on, the SQLITE_MASTER tables in which database can be changed using ordinary UPDATE, INSERT, and DELETE statements. Warning: misuse of this pragma can easily result in a corrupt database file. |
Available extensions: `json1`, `fts5`, `icu` ## DSN Examples
* Can't build go-sqlite3 on windows 64bit. ```
file:test.db?cache=shared&mode=memory
```
# Features
This package allows additional configuration of features available within SQLite3 to be enabled or disabled by golang build constraints also known as build `tags`.
[Click here for more information about build tags / constraints.](https://golang.org/pkg/go/build/#hdr-Build_Constraints)
### Usage
If you wish to build this library with additional extensions / features.
Use the following command.
```bash
go build --tags "<FEATURE>"
```
For available features see the extension list.
When using multiple build tags, all the different tags should be space delimted.
Example:
```bash
go build --tags "icu json1 fts5 secure_delete"
```
### Feature / Extension List
| Extension | Build Tag | Description |
|-----------|-----------|-------------|
| Additional Statistics | sqlite_stat4 | This option adds additional logic to the ANALYZE command and to the query planner that can help SQLite to chose a better query plan under certain situations. The ANALYZE command is enhanced to collect histogram data from all columns of every index and store that data in the sqlite_stat4 table.<br><br>The query planner will then use the histogram data to help it make better index choices. The downside of this compile-time option is that it violates the query planner stability guarantee making it more difficult to ensure consistent performance in mass-produced applications.<br><br>SQLITE_ENABLE_STAT4 is an enhancement of SQLITE_ENABLE_STAT3. STAT3 only recorded histogram data for the left-most column of each index whereas the STAT4 enhancement records histogram data from all columns of each index.<br><br>The SQLITE_ENABLE_STAT3 compile-time option is a no-op and is ignored if the SQLITE_ENABLE_STAT4 compile-time option is used |
| Allow URI Authority | sqlite_allow_uri_authority | URI filenames normally throws an error if the authority section is not either empty or "localhost".<br><br>However, if SQLite is compiled with the SQLITE_ALLOW_URI_AUTHORITY compile-time option, then the URI is converted into a Uniform Naming Convention (UNC) filename and passed down to the underlying operating system that way |
| App Armor | sqlite_app_armor | When defined, this C-preprocessor macro activates extra code that attempts to detect misuse of the SQLite API, such as passing in NULL pointers to required parameters or using objects after they have been destroyed. <br><br>App Armor is not available under `Windows`. |
| Disable Load Extensions | sqlite_omit_load_extension | Loading of external extensions is enabled by default.<br><br>To disable extension loading add the build tag `sqlite_omit_load_extension`. |
| Foreign Keys | sqlite_foreign_keys | This macro determines whether enforcement of foreign key constraints is enabled or disabled by default for new database connections.<br><br>Each database connection can always turn enforcement of foreign key constraints on and off and run-time using the foreign_keys pragma.<br><br>Enforcement of foreign key constraints is normally off by default, but if this compile-time parameter is set to 1, enforcement of foreign key constraints will be on by default |
| Full Auto Vacuum | sqlite_vacuum_full | Set the default auto vacuum to full |
| Incremental Auto Vacuum | sqlite_vacuum_incr | Set the default auto vacuum to incremental |
| Full Text Search Engine | sqlite_fts5 | When this option is defined in the amalgamation, versions 5 of the full-text search engine (fts5) is added to the build automatically |
| International Components for Unicode | sqlite_icu | This option causes the International Components for Unicode or "ICU" extension to SQLite to be added to the build |
| Introspect PRAGMAS | sqlite_introspect | This option adds some extra PRAGMA statements. <ul><li>PRAGMA function_list</li><li>PRAGMA module_list</li><li>PRAGMA pragma_list</li></ul> |
| JSON SQL Functions | sqlite_json | When this option is defined in the amalgamation, the JSON SQL functions are added to the build automatically |
| Secure Delete | sqlite_secure_delete | This compile-time option changes the default setting of the secure_delete pragma.<br><br>When this option is not used, secure_delete defaults to off. When this option is present, secure_delete defaults to on.<br><br>The secure_delete setting causes deleted content to be overwritten with zeros. There is a small performance penalty since additional I/O must occur.<br><br>On the other hand, secure_delete can prevent fragments of sensitive information from lingering in unused parts of the database file after it has been deleted. See the documentation on the secure_delete pragma for additional information |
| Secure Delete (FAST) | sqlite_secure_delete_fast | For more information see [PRAGMA secure_delete](https://www.sqlite.org/pragma.html#pragma_secure_delete) |
| Tracing / Debug | sqlite_trace | Activate trace functions |
| User Authentication | sqlite_userauth | SQLite User Authentication see [User Authentication](#user-authentication) for more information. |
# Compilation
This package requires `CGO_ENABLED=1` ennvironment variable if not set by default, and the presence of the `gcc` compiler.
If you need to add additional CFLAGS or LDFLAGS to the build command, and do not want to modify this package. Then this can be achieved by using the `CGO_CFLAGS` and `CGO_LDFLAGS` environment variables.
## Android
This package can be compiled for android.
Compile with:
```bash
go build --tags "android"
```
For more information see [#201](https://github.com/mattn/go-sqlite3/issues/201)
# ARM
To compile for `ARM` use the following environment.
```bash
env CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ \
CGO_ENABLED=1 GOOS=linux GOARCH=arm GOARM=7 \
go build -v
```
Additional information:
- [#242](https://github.com/mattn/go-sqlite3/issues/242)
- [#504](https://github.com/mattn/go-sqlite3/issues/504)
# Cross Compile
This library can be cross-compiled.
In some cases you are required to the `CC` environment variable with the cross compiler.
Additional information:
- [#491](https://github.com/mattn/go-sqlite3/issues/491)
- [#560](https://github.com/mattn/go-sqlite3/issues/560)
# Google Cloud Platform
Building on GCP is not possible because `Google Cloud Platform does not allow `gcc` to be executed.
Please work only with compiled final binaries.
## Linux
To compile this package on Linux you must install the development tools for your linux distribution.
To compile under linux use the build tag `linux`.
```bash
go build --tags "linux"
```
If you wish to link directly to libsqlite3 then you can use the `libsqlite3` build tag.
```
go build --tags "libsqlite3 linux"
```
### Alpine
When building in an `alpine` container run the following command before building.
```
apk add --update gcc musl-dev
```
### Fedora
```bash
sudo yum groupinstall "Development Tools" "Development Libraries"
```
### Ubuntu
```bash
sudo apt-get install build-essential
```
## Mac OSX
OSX should have all the tools present to compile this package, if not install XCode this will add all the developers tools.
Required dependency
```bash
brew install sqlite3
```
For OSX there is an additional package install which is required if you whish to build the `icu` extension.
This additional package can be installed with `homebrew`.
```bash
brew upgrade icu4c
```
To compile for Mac OSX.
```bash
go build --tags "darwin"
```
If you wish to link directly to libsqlite3 then you can use the `libsqlite3` build tag.
```
go build --tags "libsqlite3 darwin"
```
Additional information:
- [#206](https://github.com/mattn/go-sqlite3/issues/206)
- [#404](https://github.com/mattn/go-sqlite3/issues/404)
## Windows
To compile this package on Windows OS you must have the `gcc` compiler installed.
1) Install a Windows `gcc` toolchain.
2) Add the `bin` folders to the Windows path if the installer did not do this by default.
3) Open a terminal for the TDM-GCC toolchain, can be found in the Windows Start menu.
4) Navigate to your project folder and run the `go build ...` command for this package.
For example the TDM-GCC Toolchain can be found [here](ttps://sourceforge.net/projects/tdm-gcc/).
## Errors
- Compile error: `can not be used when making a shared object; recompile with -fPIC`
When receiving a compile time error referencing recompile with `-FPIC` then you
are probably using a hardend system.
You can copile the library on a hardend system with the following command.
```bash
go build -ldflags '-extldflags=-fno-PIC'
```
More details see [#120](https://github.com/mattn/go-sqlite3/issues/120)
- Can't build go-sqlite3 on windows 64bit.
> Probably, you are using go 1.0, go1.0 has a problem when it comes to compiling/linking on windows 64bit. > Probably, you are using go 1.0, go1.0 has a problem when it comes to compiling/linking on windows 64bit.
> See: [#27](https://github.com/mattn/go-sqlite3/issues/27) > See: [#27](https://github.com/mattn/go-sqlite3/issues/27)
* Getting insert error while query is opened. - `go get github.com/mattn/go-sqlite3` throws compilation error.
`gcc` throws: `internal compiler error`
Remove the download repository from your disk and try re-install with:
```bash
go install github.com/mattn/go-sqlite3
```
# User Authentication
This package supports the SQLite User Authentication module.
## Compile
To use the User authentication module the package has to be compiled with the tag `sqlite_userauth`. See [Features](#features).
## Usage
### Create protected database
To create a database protected by user authentication provide the following argument to the connection string `_auth`.
This will enable user authentication within the database. This option however requires two additional arguments:
- `_auth_user`
- `_auth_pass`
When `_auth` is present on the connection string user authentication will be enabled and the provided user will be created
as an `admin` user. After initial creation, the parameter `_auth` has no effect anymore and can be omitted from the connection string.
Example connection string:
Create an user authentication database with user `admin` and password `admin`.
`file:test.s3db?_auth&_auth_user=admin&_auth_pass=admin`
Create an user authentication database with user `admin` and password `admin` and use `SHA1` for the password encoding.
`file:test.s3db?_auth&_auth_user=admin&_auth_pass=admin&_auth_crypt=sha1`
### Password Encoding
The passwords within the user authentication module of SQLite are encoded with the SQLite function `sqlite_cryp`.
This function uses a ceasar-cypher which is quite insecure.
This library provides several additional password encoders which can be configured through the connection string.
The password cypher can be configured with the key `_auth_crypt`. And if the configured password encoder also requires an
salt this can be configured with `_auth_salt`.
#### Available Encoders
- SHA1
- SSHA1 (Salted SHA1)
- SHA256
- SSHA256 (salted SHA256)
- SHA384
- SSHA384 (salted SHA384)
- SHA512
- SSHA512 (salted SHA512)
### Restrictions
Operations on the database regarding to user management can only be preformed by an administrator user.
### Support
The user authentication supports two kinds of users
- administrators
- regular users
### User Management
User management can be done by directly using the `*SQLiteConn` or by SQL.
#### SQL
The following sql functions are available for user management.
| Function | Arguments | Description |
|----------|-----------|-------------|
| `authenticate` | username `string`, password `string` | Will authenticate an user, this is done by the connection; and should not be used manually. |
| `auth_user_add` | username `string`, password `string`, admin `int` | This function will add an user to the database.<br>if the database is not protected by user authentication it will enable it. Argument `admin` is an integer identifying if the added user should be an administrator. Only Administrators can add administrators. |
| `auth_user_change` | username `string`, password `string`, admin `int` | Function to modify an user. Users can change their own password, but only an administrator can change the administrator flag. |
| `authUserDelete` | username `string` | Delete an user from the database. Can only be used by an administrator. The current logged in administrator cannot be deleted. This is to make sure their is always an administrator remaining. |
These functions will return an integer.
- 0 (SQLITE_OK)
- 23 (SQLITE_AUTH) Failed to perform due to authentication or insufficient privileges
##### Examples
```sql
// Autheticate user
// Create Admin User
SELECT auth_user_add('admin2', 'admin2', 1);
// Change password for user
SELECT auth_user_change('user', 'userpassword', 0);
// Delete user
SELECT user_delete('user');
```
#### *SQLiteConn
The following functions are available for User authentication from the `*SQLiteConn`.
| Function | Description |
|----------|-------------|
| `Authenticate(username, password string) error` | Authenticate user |
| `AuthUserAdd(username, password string, admin bool) error` | Add user |
| `AuthUserChange(username, password string, admin bool) error` | Modify user |
| `AuthUserDelete(username string) error` | Delete user |
### Attached database
When using attached databases. SQLite will use the authentication from the `main` database for the attached database(s).
# Extensions
If you want your own extension to be listed here or you want to add a reference to an extension; please submit an Issue for this.
## Spatialite
Spatialite is available as an extension to SQLite, and can be used in combination with this repository.
For an example see [shaxbee/go-spatialite](https://github.com/shaxbee/go-spatialite).
# FAQ
- Getting insert error while query is opened.
> You can pass some arguments into the connection string, for example, a URI. > You can pass some arguments into the connection string, for example, a URI.
> See: [#39](https://github.com/mattn/go-sqlite3/issues/39) > See: [#39](https://github.com/mattn/go-sqlite3/issues/39)
* Do you want to cross compile? mingw on Linux or Mac? - Do you want to cross compile? mingw on Linux or Mac?
> See: [#106](https://github.com/mattn/go-sqlite3/issues/106) > See: [#106](https://github.com/mattn/go-sqlite3/issues/106)
> See also: http://www.limitlessfx.com/cross-compile-golang-app-for-windows-from-linux.html > See also: http://www.limitlessfx.com/cross-compile-golang-app-for-windows-from-linux.html
* Want to get time.Time with current locale - Want to get time.Time with current locale
Use `_loc=auto` in SQLite3 filename schema like `file:foo.db?_loc=auto`. Use `_loc=auto` in SQLite3 filename schema like `file:foo.db?_loc=auto`.
* Can I use this in multiple routines concurrently? - Can I use this in multiple routines concurrently?
Yes for readonly. But, No for writable. See [#50](https://github.com/mattn/go-sqlite3/issues/50), [#51](https://github.com/mattn/go-sqlite3/issues/51), [#209](https://github.com/mattn/go-sqlite3/issues/209). Yes for readonly. But, No for writable. See [#50](https://github.com/mattn/go-sqlite3/issues/50), [#51](https://github.com/mattn/go-sqlite3/issues/51), [#209](https://github.com/mattn/go-sqlite3/issues/209), [#274](https://github.com/mattn/go-sqlite3/issues/274).
* Why is it racy if I use a `sql.Open("sqlite3", ":memory:")` database? - Why I'm getting `no such table` error?
Why is it racy if I use a `sql.Open("sqlite3", ":memory:")` database?
Each connection to :memory: opens a brand new in-memory sql database, so if Each connection to :memory: opens a brand new in-memory sql database, so if
the stdlib's sql engine happens to open another connection and you've only the stdlib's sql engine happens to open another connection and you've only
specified ":memory:", that connection will see a brand new database. A specified ":memory:", that connection will see a brand new database. A
workaround is to use "file::memory:?mode=memory&cache=shared". Every workaround is to use "file::memory:?mode=memory&cache=shared". Every
connection to this string will point to the same in-memory database. See connection to this string will point to the same in-memory database.
[#204](https://github.com/mattn/go-sqlite3/issues/204) for more info.
License For more information see
------- * [#204](https://github.com/mattn/go-sqlite3/issues/204)
* [#511](https://github.com/mattn/go-sqlite3/issues/511)
MIT: http://mattn.mit-license.org/2012 - Reading from database with large amount of goroutines fails on OSX.
OS X limits OS-wide to not have more than 1000 files open simultaneously by default.
For more information see [#289](https://github.com/mattn/go-sqlite3/issues/289)
- Trying to execure a `.` (dot) command throws an error.
Error: `Error: near ".": syntax error`
Dot command are part of SQLite3 CLI not of this library.
You need to implement the feature or call the sqlite3 cli.
More infomation see [#305](https://github.com/mattn/go-sqlite3/issues/305)
- Error: `database is locked`
When you get an database is locked. Please use the following options.
Add to DSN: `cache=shared`
Example:
```go
db, err := sql.Open("sqlite3", "file:locked.sqlite?cache=shared")
```
Second please set the database connections of the SQL package to 1.
```go
db.SetMaxOpenConn(1)
```
More information see [#209](https://github.com/mattn/go-sqlite3/issues/209)
# License
MIT: http://mattn.mit-license.org/2018
sqlite3-binding.c, sqlite3-binding.h, sqlite3ext.h sqlite3-binding.c, sqlite3-binding.h, sqlite3ext.h
@@ -91,7 +511,8 @@ The -binding suffix was added to avoid build failures under gccgo.
In this repository, those files are an amalgamation of code that was copied from SQLite3. The license of that code is the same as the license of SQLite3. In this repository, those files are an amalgamation of code that was copied from SQLite3. The license of that code is the same as the license of SQLite3.
Author # Author
------
Yasuhiro Matsumoto (a.k.a mattn) Yasuhiro Matsumoto (a.k.a mattn)
G.J.R. Timmer

10
vendor/github.com/mattn/go-sqlite3/callback.go сгенерированный поставляемый
Просмотреть файл

@@ -331,8 +331,18 @@ func callbackRetText(ctx *C.sqlite3_context, v reflect.Value) error {
return nil return nil
} }
func callbackRetNil(ctx *C.sqlite3_context, v reflect.Value) error {
return nil
}
func callbackRet(typ reflect.Type) (callbackRetConverter, error) { func callbackRet(typ reflect.Type) (callbackRetConverter, error) {
switch typ.Kind() { switch typ.Kind() {
case reflect.Interface:
errorInterface := reflect.TypeOf((*error)(nil)).Elem()
if typ.Implements(errorInterface) {
return callbackRetNil, nil
}
fallthrough
case reflect.Slice: case reflect.Slice:
if typ.Elem().Kind() != reflect.Uint8 { if typ.Elem().Kind() != reflect.Uint8 {
return nil, errors.New("the only supported slice type is []byte") return nil, errors.New("the only supported slice type is []byte")

17313
vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c сгенерированный поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1011
vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h сгенерированный поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

805
vendor/github.com/mattn/go-sqlite3/sqlite3.go сгенерированный поставляемый
Просмотреть файл

@@ -1,17 +1,28 @@
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>. // Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
// //
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build cgo
package sqlite3 package sqlite3
/* /*
#cgo CFLAGS: -std=gnu99 #cgo CFLAGS: -std=gnu99
#cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE=1 #cgo CFLAGS: -DSQLITE_ENABLE_RTREE
#cgo CFLAGS: -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS4_UNICODE61 #cgo CFLAGS: -DSQLITE_THREADSAFE=1
#cgo CFLAGS: -DHAVE_USLEEP=1
#cgo CFLAGS: -DSQLITE_ENABLE_FTS3
#cgo CFLAGS: -DSQLITE_ENABLE_FTS3_PARENTHESIS
#cgo CFLAGS: -DSQLITE_ENABLE_FTS4_UNICODE61
#cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15 #cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15
#cgo CFLAGS: -DSQLITE_OMIT_DEPRECATED
#cgo CFLAGS: -DSQLITE_DISABLE_INTRINSIC #cgo CFLAGS: -DSQLITE_DISABLE_INTRINSIC
#cgo CFLAGS: -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1
#cgo CFLAGS: -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT
#cgo CFLAGS: -Wno-deprecated-declarations #cgo CFLAGS: -Wno-deprecated-declarations
#cgo linux,!android CFLAGS: -DHAVE_PREAD64=1 -DHAVE_PWRITE64=1
#ifndef USE_LIBSQLITE3 #ifndef USE_LIBSQLITE3
#include <sqlite3-binding.h> #include <sqlite3-binding.h>
#else #else
@@ -170,6 +181,12 @@ var SQLiteTimestampFormats = []string{
"2006-01-02", "2006-01-02",
} }
const (
columnDate string = "date"
columnDatetime string = "datetime"
columnTimestamp string = "timestamp"
)
func init() { func init() {
sql.Register("sqlite3", &SQLiteDriver{}) sql.Register("sqlite3", &SQLiteDriver{})
} }
@@ -389,7 +406,7 @@ func (c *SQLiteConn) RegisterCommitHook(callback func() int) {
if callback == nil { if callback == nil {
C.sqlite3_commit_hook(c.db, nil, nil) C.sqlite3_commit_hook(c.db, nil, nil)
} else { } else {
C.sqlite3_commit_hook(c.db, (*[0]byte)(unsafe.Pointer(C.commitHookTrampoline)), unsafe.Pointer(newHandle(c, callback))) C.sqlite3_commit_hook(c.db, (*[0]byte)(C.commitHookTrampoline), unsafe.Pointer(newHandle(c, callback)))
} }
} }
@@ -402,7 +419,7 @@ func (c *SQLiteConn) RegisterRollbackHook(callback func()) {
if callback == nil { if callback == nil {
C.sqlite3_rollback_hook(c.db, nil, nil) C.sqlite3_rollback_hook(c.db, nil, nil)
} else { } else {
C.sqlite3_rollback_hook(c.db, (*[0]byte)(unsafe.Pointer(C.rollbackHookTrampoline)), unsafe.Pointer(newHandle(c, callback))) C.sqlite3_rollback_hook(c.db, (*[0]byte)(C.rollbackHookTrampoline), unsafe.Pointer(newHandle(c, callback)))
} }
} }
@@ -419,7 +436,7 @@ func (c *SQLiteConn) RegisterUpdateHook(callback func(int, string, string, int64
if callback == nil { if callback == nil {
C.sqlite3_update_hook(c.db, nil, nil) C.sqlite3_update_hook(c.db, nil, nil)
} else { } else {
C.sqlite3_update_hook(c.db, (*[0]byte)(unsafe.Pointer(C.updateHookTrampoline)), unsafe.Pointer(newHandle(c, callback))) C.sqlite3_update_hook(c.db, (*[0]byte)(C.updateHookTrampoline), unsafe.Pointer(newHandle(c, callback)))
} }
} }
@@ -501,7 +518,7 @@ func (c *SQLiteConn) RegisterFunc(name string, impl interface{}, pure bool) erro
} }
func sqlite3CreateFunction(db *C.sqlite3, zFunctionName *C.char, nArg C.int, eTextRep C.int, pApp uintptr, xFunc unsafe.Pointer, xStep unsafe.Pointer, xFinal unsafe.Pointer) C.int { func sqlite3CreateFunction(db *C.sqlite3, zFunctionName *C.char, nArg C.int, eTextRep C.int, pApp uintptr, xFunc unsafe.Pointer, xStep unsafe.Pointer, xFinal unsafe.Pointer) C.int {
return C._sqlite3_create_function(db, zFunctionName, nArg, eTextRep, C.uintptr_t(pApp), (*[0]byte)(unsafe.Pointer(xFunc)), (*[0]byte)(unsafe.Pointer(xStep)), (*[0]byte)(unsafe.Pointer(xFinal))) return C._sqlite3_create_function(db, zFunctionName, nArg, eTextRep, C.uintptr_t(pApp), (*[0]byte)(xFunc), (*[0]byte)(xStep), (*[0]byte)(xFinal))
} }
// RegisterAggregator makes a Go type available as a SQLite aggregation function. // RegisterAggregator makes a Go type available as a SQLite aggregation function.
@@ -763,33 +780,140 @@ func errorString(err Error) string {
} }
// Open database and return a new connection. // Open database and return a new connection.
//
// A pragma can take either zero or one argument.
// The argument is may be either in parentheses or it may be separated from
// the pragma name by an equal sign. The two syntaxes yield identical results.
// In many pragmas, the argument is a boolean. The boolean can be one of:
// 1 yes true on
// 0 no false off
//
// You can specify a DSN string using a URI as the filename. // You can specify a DSN string using a URI as the filename.
// test.db // test.db
// file:test.db?cache=shared&mode=memory // file:test.db?cache=shared&mode=memory
// :memory: // :memory:
// file::memory: // file::memory:
//
// mode
// Access mode of the database.
// https://www.sqlite.org/c3ref/open.html
// Values:
// - ro
// - rw
// - rwc
// - memory
//
// shared
// SQLite Shared-Cache Mode
// https://www.sqlite.org/sharedcache.html
// Values:
// - shared
// - private
//
// immutable=Boolean
// The immutable parameter is a boolean query parameter that indicates
// that the database file is stored on read-only media. When immutable is set,
// SQLite assumes that the database file cannot be changed,
// even by a process with higher privilege,
// and so the database is opened read-only and all locking and change detection is disabled.
// Caution: Setting the immutable property on a database file that
// does in fact change can result in incorrect query results and/or SQLITE_CORRUPT errors.
//
// go-sqlite3 adds the following query parameters to those used by SQLite: // go-sqlite3 adds the following query parameters to those used by SQLite:
// _loc=XXX // _loc=XXX
// Specify location of time format. It's possible to specify "auto". // Specify location of time format. It's possible to specify "auto".
// _busy_timeout=XXX //
// Specify value for sqlite3_busy_timeout. // _mutex=XXX
// Specify mutex mode. XXX can be "no", "full".
//
// _txlock=XXX // _txlock=XXX
// Specify locking behavior for transactions. XXX can be "immediate", // Specify locking behavior for transactions. XXX can be "immediate",
// "deferred", "exclusive". // "deferred", "exclusive".
// _foreign_keys=X //
// Enable or disable enforcement of foreign keys. X can be 1 or 0. // _auto_vacuum=X | _vacuum=X
// _recursive_triggers=X // 0 | none - Auto Vacuum disabled
// Enable or disable recursive triggers. X can be 1 or 0. // 1 | full - Auto Vacuum FULL
// 2 | incremental - Auto Vacuum Incremental
//
// _busy_timeout=XXX"| _timeout=XXX
// Specify value for sqlite3_busy_timeout.
//
// _case_sensitive_like=Boolean | _cslike=Boolean
// https://www.sqlite.org/pragma.html#pragma_case_sensitive_like
// Default or disabled the LIKE operation is case-insensitive.
// When enabling this options behaviour of LIKE will become case-sensitive.
//
// _defer_foreign_keys=Boolean | _defer_fk=Boolean
// Defer Foreign Keys until outermost transaction is committed.
//
// _foreign_keys=Boolean | _fk=Boolean
// Enable or disable enforcement of foreign keys.
//
// _ignore_check_constraints=Boolean
// This pragma enables or disables the enforcement of CHECK constraints.
// The default setting is off, meaning that CHECK constraints are enforced by default.
//
// _journal_mode=MODE | _journal=MODE
// Set journal mode for the databases associated with the current connection.
// https://www.sqlite.org/pragma.html#pragma_journal_mode
//
// _locking_mode=X | _locking=X
// Sets the database connection locking-mode.
// The locking-mode is either NORMAL or EXCLUSIVE.
// https://www.sqlite.org/pragma.html#pragma_locking_mode
//
// _query_only=Boolean
// The query_only pragma prevents all changes to database files when enabled.
//
// _recursive_triggers=Boolean | _rt=Boolean
// Enable or disable recursive triggers.
//
// _secure_delete=Boolean|FAST
// When secure_delete is on, SQLite overwrites deleted content with zeros.
// https://www.sqlite.org/pragma.html#pragma_secure_delete
//
// _synchronous=X | _sync=X
// Change the setting of the "synchronous" flag.
// https://www.sqlite.org/pragma.html#pragma_synchronous
//
// _writable_schema=Boolean
// When this pragma is on, the SQLITE_MASTER tables in which database
// can be changed using ordinary UPDATE, INSERT, and DELETE statements.
// Warning: misuse of this pragma can easily result in a corrupt database file.
//
//
func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
if C.sqlite3_threadsafe() == 0 { if C.sqlite3_threadsafe() == 0 {
return nil, errors.New("sqlite library was not compiled for thread-safe operation") return nil, errors.New("sqlite library was not compiled for thread-safe operation")
} }
var pkey string
// Options
var loc *time.Location var loc *time.Location
authCreate := false
authUser := ""
authPass := ""
authCrypt := ""
authSalt := ""
mutex := C.int(C.SQLITE_OPEN_FULLMUTEX)
txlock := "BEGIN" txlock := "BEGIN"
// PRAGMA's
autoVacuum := -1
busyTimeout := 5000 busyTimeout := 5000
caseSensitiveLike := -1
deferForeignKeys := -1
foreignKeys := -1 foreignKeys := -1
ignoreCheckConstraints := -1
journalMode := "DELETE"
lockingMode := "NORMAL"
queryOnly := -1
recursiveTriggers := -1 recursiveTriggers := -1
secureDelete := "DEFAULT"
synchronousMode := "NORMAL"
writableSchema := -1
pos := strings.IndexRune(dsn, '?') pos := strings.IndexRune(dsn, '?')
if pos >= 1 { if pos >= 1 {
params, err := url.ParseQuery(dsn[pos+1:]) params, err := url.ParseQuery(dsn[pos+1:])
@@ -797,11 +921,29 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
return nil, err return nil, err
} }
// Authentication
if _, ok := params["_auth"]; ok {
authCreate = true
}
if val := params.Get("_auth_user"); val != "" {
authUser = val
}
if val := params.Get("_auth_pass"); val != "" {
authPass = val
}
if val := params.Get("_auth_crypt"); val != "" {
authCrypt = val
}
if val := params.Get("_auth_salt"); val != "" {
authSalt = val
}
// _loc // _loc
if val := params.Get("_loc"); val != "" { if val := params.Get("_loc"); val != "" {
if val == "auto" { switch strings.ToLower(val) {
case "auto":
loc = time.Local loc = time.Local
} else { default:
loc, err = time.LoadLocation(val) loc, err = time.LoadLocation(val)
if err != nil { if err != nil {
return nil, fmt.Errorf("Invalid _loc: %v: %v", val, err) return nil, fmt.Errorf("Invalid _loc: %v: %v", val, err)
@@ -809,18 +951,21 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
} }
} }
// _busy_timeout // _mutex
if val := params.Get("_busy_timeout"); val != "" { if val := params.Get("_mutex"); val != "" {
iv, err := strconv.ParseInt(val, 10, 64) switch strings.ToLower(val) {
if err != nil { case "no":
return nil, fmt.Errorf("Invalid _busy_timeout: %v: %v", val, err) mutex = C.SQLITE_OPEN_NOMUTEX
case "full":
mutex = C.SQLITE_OPEN_FULLMUTEX
default:
return nil, fmt.Errorf("Invalid _mutex: %v", val)
} }
busyTimeout = int(iv)
} }
// _txlock // _txlock
if val := params.Get("_txlock"); val != "" { if val := params.Get("_txlock"); val != "" {
switch val { switch strings.ToLower(val) {
case "immediate": case "immediate":
txlock = "BEGIN IMMEDIATE" txlock = "BEGIN IMMEDIATE"
case "exclusive": case "exclusive":
@@ -832,27 +977,262 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
} }
} }
// _foreign_keys // Auto Vacuum (_vacuum)
if val := params.Get("_foreign_keys"); val != "" { //
switch val { // https://www.sqlite.org/pragma.html#pragma_auto_vacuum
case "1": //
foreignKeys = 1 pkey = "" // Reset pkey
case "0": if _, ok := params["_auto_vacuum"]; ok {
foreignKeys = 0 pkey = "_auto_vacuum"
}
if _, ok := params["_vacuum"]; ok {
pkey = "_vacuum"
}
if val := params.Get(pkey); val != "" {
switch strings.ToLower(val) {
case "0", "none":
autoVacuum = 0
case "1", "full":
autoVacuum = 1
case "2", "incremental":
autoVacuum = 2
default: default:
return nil, fmt.Errorf("Invalid _foreign_keys: %v", val) return nil, fmt.Errorf("Invalid _auto_vacuum: %v, expecting value of '0 NONE 1 FULL 2 INCREMENTAL'", val)
} }
} }
// _recursive_triggers // Busy Timeout (_busy_timeout)
if val := params.Get("_recursive_triggers"); val != "" { //
switch val { // https://www.sqlite.org/pragma.html#pragma_busy_timeout
case "1": //
recursiveTriggers = 1 pkey = "" // Reset pkey
case "0": if _, ok := params["_busy_timeout"]; ok {
recursiveTriggers = 0 pkey = "_busy_timeout"
}
if _, ok := params["_timeout"]; ok {
pkey = "_timeout"
}
if val := params.Get(pkey); val != "" {
iv, err := strconv.ParseInt(val, 10, 64)
if err != nil {
return nil, fmt.Errorf("Invalid _busy_timeout: %v: %v", val, err)
}
busyTimeout = int(iv)
}
// Case Sensitive Like (_cslike)
//
// https://www.sqlite.org/pragma.html#pragma_case_sensitive_like
//
pkey = "" // Reset pkey
if _, ok := params["_case_sensitive_like"]; ok {
pkey = "_case_sensitive_like"
}
if _, ok := params["_cslike"]; ok {
pkey = "_cslike"
}
if val := params.Get(pkey); val != "" {
switch strings.ToLower(val) {
case "0", "no", "false", "off":
caseSensitiveLike = 0
case "1", "yes", "true", "on":
caseSensitiveLike = 1
default: default:
return nil, fmt.Errorf("Invalid _recursive_triggers: %v", val) return nil, fmt.Errorf("Invalid _case_sensitive_like: %v, expecting boolean value of '0 1 false true no yes off on'", val)
}
}
// Defer Foreign Keys (_defer_foreign_keys | _defer_fk)
//
// https://www.sqlite.org/pragma.html#pragma_defer_foreign_keys
//
pkey = "" // Reset pkey
if _, ok := params["_defer_foreign_keys"]; ok {
pkey = "_defer_foreign_keys"
}
if _, ok := params["_defer_fk"]; ok {
pkey = "_defer_fk"
}
if val := params.Get(pkey); val != "" {
switch strings.ToLower(val) {
case "0", "no", "false", "off":
deferForeignKeys = 0
case "1", "yes", "true", "on":
deferForeignKeys = 1
default:
return nil, fmt.Errorf("Invalid _defer_foreign_keys: %v, expecting boolean value of '0 1 false true no yes off on'", val)
}
}
// Foreign Keys (_foreign_keys | _fk)
//
// https://www.sqlite.org/pragma.html#pragma_foreign_keys
//
pkey = "" // Reset pkey
if _, ok := params["_foreign_keys"]; ok {
pkey = "_foreign_keys"
}
if _, ok := params["_fk"]; ok {
pkey = "_fk"
}
if val := params.Get(pkey); val != "" {
switch strings.ToLower(val) {
case "0", "no", "false", "off":
foreignKeys = 0
case "1", "yes", "true", "on":
foreignKeys = 1
default:
return nil, fmt.Errorf("Invalid _foreign_keys: %v, expecting boolean value of '0 1 false true no yes off on'", val)
}
}
// Ignore CHECK Constrains (_ignore_check_constraints)
//
// https://www.sqlite.org/pragma.html#pragma_ignore_check_constraints
//
if val := params.Get("_ignore_check_constraints"); val != "" {
switch strings.ToLower(val) {
case "0", "no", "false", "off":
ignoreCheckConstraints = 0
case "1", "yes", "true", "on":
ignoreCheckConstraints = 1
default:
return nil, fmt.Errorf("Invalid _ignore_check_constraints: %v, expecting boolean value of '0 1 false true no yes off on'", val)
}
}
// Journal Mode (_journal_mode | _journal)
//
// https://www.sqlite.org/pragma.html#pragma_journal_mode
//
pkey = "" // Reset pkey
if _, ok := params["_journal_mode"]; ok {
pkey = "_journal_mode"
}
if _, ok := params["_journal"]; ok {
pkey = "_journal"
}
if val := params.Get(pkey); val != "" {
switch strings.ToUpper(val) {
case "DELETE", "TRUNCATE", "PERSIST", "MEMORY", "OFF":
journalMode = strings.ToUpper(val)
case "WAL":
journalMode = strings.ToUpper(val)
// For WAL Mode set Synchronous Mode to 'NORMAL'
// See https://www.sqlite.org/pragma.html#pragma_synchronous
synchronousMode = "NORMAL"
default:
return nil, fmt.Errorf("Invalid _journal: %v, expecting value of 'DELETE TRUNCATE PERSIST MEMORY WAL OFF'", val)
}
}
// Locking Mode (_locking)
//
// https://www.sqlite.org/pragma.html#pragma_locking_mode
//
pkey = "" // Reset pkey
if _, ok := params["_locking_mode"]; ok {
pkey = "_locking_mode"
}
if _, ok := params["_locking"]; ok {
pkey = "_locking"
}
if val := params.Get("_locking"); val != "" {
switch strings.ToUpper(val) {
case "NORMAL", "EXCLUSIVE":
lockingMode = strings.ToUpper(val)
default:
return nil, fmt.Errorf("Invalid _locking_mode: %v, expecting value of 'NORMAL EXCLUSIVE", val)
}
}
// Query Only (_query_only)
//
// https://www.sqlite.org/pragma.html#pragma_query_only
//
if val := params.Get("_query_only"); val != "" {
switch strings.ToLower(val) {
case "0", "no", "false", "off":
queryOnly = 0
case "1", "yes", "true", "on":
queryOnly = 1
default:
return nil, fmt.Errorf("Invalid _query_only: %v, expecting boolean value of '0 1 false true no yes off on'", val)
}
}
// Recursive Triggers (_recursive_triggers)
//
// https://www.sqlite.org/pragma.html#pragma_recursive_triggers
//
pkey = "" // Reset pkey
if _, ok := params["_recursive_triggers"]; ok {
pkey = "_recursive_triggers"
}
if _, ok := params["_rt"]; ok {
pkey = "_rt"
}
if val := params.Get(pkey); val != "" {
switch strings.ToLower(val) {
case "0", "no", "false", "off":
recursiveTriggers = 0
case "1", "yes", "true", "on":
recursiveTriggers = 1
default:
return nil, fmt.Errorf("Invalid _recursive_triggers: %v, expecting boolean value of '0 1 false true no yes off on'", val)
}
}
// Secure Delete (_secure_delete)
//
// https://www.sqlite.org/pragma.html#pragma_secure_delete
//
if val := params.Get("_secure_delete"); val != "" {
switch strings.ToLower(val) {
case "0", "no", "false", "off":
secureDelete = "OFF"
case "1", "yes", "true", "on":
secureDelete = "ON"
case "fast":
secureDelete = "FAST"
default:
return nil, fmt.Errorf("Invalid _secure_delete: %v, expecting boolean value of '0 1 false true no yes off on fast'", val)
}
}
// Synchronous Mode (_synchronous | _sync)
//
// https://www.sqlite.org/pragma.html#pragma_synchronous
//
pkey = "" // Reset pkey
if _, ok := params["_synchronous"]; ok {
pkey = "_synchronous"
}
if _, ok := params["_sync"]; ok {
pkey = "_sync"
}
if val := params.Get(pkey); val != "" {
switch strings.ToUpper(val) {
case "0", "OFF", "1", "NORMAL", "2", "FULL", "3", "EXTRA":
synchronousMode = strings.ToUpper(val)
default:
return nil, fmt.Errorf("Invalid _synchronous: %v, expecting value of '0 OFF 1 NORMAL 2 FULL 3 EXTRA'", val)
}
}
// Writable Schema (_writeable_schema)
//
// https://www.sqlite.org/pragma.html#pragma_writeable_schema
//
if val := params.Get("_writable_schema"); val != "" {
switch strings.ToLower(val) {
case "0", "no", "false", "off":
writableSchema = 0
case "1", "yes", "true", "on":
writableSchema = 1
default:
return nil, fmt.Errorf("Invalid _writable_schema: %v, expecting boolean value of '0 1 false true no yes off on'", val)
} }
} }
@@ -865,9 +1245,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
name := C.CString(dsn) name := C.CString(dsn)
defer C.free(unsafe.Pointer(name)) defer C.free(unsafe.Pointer(name))
rv := C._sqlite3_open_v2(name, &db, rv := C._sqlite3_open_v2(name, &db,
C.SQLITE_OPEN_FULLMUTEX| mutex|C.SQLITE_OPEN_READWRITE|C.SQLITE_OPEN_CREATE,
C.SQLITE_OPEN_READWRITE|
C.SQLITE_OPEN_CREATE,
nil) nil)
if rv != 0 { if rv != 0 {
return nil, Error{Code: ErrNo(rv)} return nil, Error{Code: ErrNo(rv)}
@@ -891,30 +1269,268 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
} }
return nil return nil
} }
if foreignKeys == 0 {
if err := exec("PRAGMA foreign_keys = OFF;"); err != nil { // USER AUTHENTICATION
C.sqlite3_close_v2(db) //
return nil, err // User Authentication is always performed even when
} // sqlite_userauth is not compiled in, because without user authentication
} else if foreignKeys == 1 { // the authentication is a no-op.
if err := exec("PRAGMA foreign_keys = ON;"); err != nil { //
C.sqlite3_close_v2(db) // Workflow
return nil, err // - Authenticate
// ON::SUCCESS => Continue
// ON::SQLITE_AUTH => Return error and exit Open(...)
//
// - Activate User Authentication
// Check if the user wants to activate User Authentication.
// If so then first create a temporary AuthConn to the database
// This is possible because we are already succesfully authenticated.
//
// - Check if `sqlite_user`` table exists
// YES => Add the provided user from DSN as Admin User and
// activate user authentication.
// NO => Continue
//
// Create connection to SQLite
conn := &SQLiteConn{db: db, loc: loc, txlock: txlock}
// Password Cipher has to be registerd before authentication
if len(authCrypt) > 0 {
switch strings.ToUpper(authCrypt) {
case "SHA1":
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA1, true); err != nil {
return nil, fmt.Errorf("CryptEncoderSHA1: %s", err)
}
case "SSHA1":
if len(authSalt) == 0 {
return nil, fmt.Errorf("_auth_crypt=ssha1, requires _auth_salt")
}
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA1(authSalt), true); err != nil {
return nil, fmt.Errorf("CryptEncoderSSHA1: %s", err)
}
case "SHA256":
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA256, true); err != nil {
return nil, fmt.Errorf("CryptEncoderSHA256: %s", err)
}
case "SSHA256":
if len(authSalt) == 0 {
return nil, fmt.Errorf("_auth_crypt=ssha256, requires _auth_salt")
}
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA256(authSalt), true); err != nil {
return nil, fmt.Errorf("CryptEncoderSSHA256: %s", err)
}
case "SHA384":
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA384, true); err != nil {
return nil, fmt.Errorf("CryptEncoderSHA384: %s", err)
}
case "SSHA384":
if len(authSalt) == 0 {
return nil, fmt.Errorf("_auth_crypt=ssha384, requires _auth_salt")
}
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA384(authSalt), true); err != nil {
return nil, fmt.Errorf("CryptEncoderSSHA384: %s", err)
}
case "SHA512":
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA512, true); err != nil {
return nil, fmt.Errorf("CryptEncoderSHA512: %s", err)
}
case "SSHA512":
if len(authSalt) == 0 {
return nil, fmt.Errorf("_auth_crypt=ssha512, requires _auth_salt")
}
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA512(authSalt), true); err != nil {
return nil, fmt.Errorf("CryptEncoderSSHA512: %s", err)
}
} }
} }
if recursiveTriggers == 0 {
if err := exec("PRAGMA recursive_triggers = OFF;"); err != nil { // Preform Authentication
C.sqlite3_close_v2(db) if err := conn.Authenticate(authUser, authPass); err != nil {
return nil, err return nil, err
} }
} else if recursiveTriggers == 1 {
if err := exec("PRAGMA recursive_triggers = ON;"); err != nil { // Register: authenticate
// Authenticate will perform an authentication of the provided username
// and password against the database.
//
// If a database contains the SQLITE_USER table, then the
// call to Authenticate must be invoked with an
// appropriate username and password prior to enable read and write
//access to the database.
//
// Return SQLITE_OK on success or SQLITE_ERROR if the username/password
// combination is incorrect or unknown.
//
// If the SQLITE_USER table is not present in the database file, then
// this interface is a harmless no-op returnning SQLITE_OK.
if err := conn.RegisterFunc("authenticate", conn.authenticate, true); err != nil {
return nil, err
}
//
// Register: auth_user_add
// auth_user_add can be used (by an admin user only)
// to create a new user. When called on a no-authentication-required
// database, this routine converts the database into an authentication-
// required database, automatically makes the added user an
// administrator, and logs in the current connection as that user.
// The AuthUserAdd only works for the "main" database, not
// for any ATTACH-ed databases. Any call to AuthUserAdd by a
// non-admin user results in an error.
if err := conn.RegisterFunc("auth_user_add", conn.authUserAdd, true); err != nil {
return nil, err
}
//
// Register: auth_user_change
// auth_user_change can be used to change a users
// login credentials or admin privilege. Any user can change their own
// login credentials. Only an admin user can change another users login
// credentials or admin privilege setting. No user may change their own
// admin privilege setting.
if err := conn.RegisterFunc("auth_user_change", conn.authUserChange, true); err != nil {
return nil, err
}
//
// Register: auth_user_delete
// auth_user_delete can be used (by an admin user only)
// to delete a user. The currently logged-in user cannot be deleted,
// which guarantees that there is always an admin user and hence that
// the database cannot be converted into a no-authentication-required
// database.
if err := conn.RegisterFunc("auth_user_delete", conn.authUserDelete, true); err != nil {
return nil, err
}
// Register: auth_enabled
// auth_enabled can be used to check if user authentication is enabled
if err := conn.RegisterFunc("auth_enabled", conn.authEnabled, true); err != nil {
return nil, err
}
// Auto Vacuum
// Moved auto_vacuum command, the user preference for auto_vacuum needs to be implemented directly after
// the authentication and before the sqlite_user table gets created if the user
// decides to activate User Authentication because
// auto_vacuum needs to be set before any tables are created
// and activating user authentication creates the internal table `sqlite_user`.
if autoVacuum > -1 {
if err := exec(fmt.Sprintf("PRAGMA auto_vacuum = %d;", autoVacuum)); err != nil {
C.sqlite3_close_v2(db) C.sqlite3_close_v2(db)
return nil, err return nil, err
} }
} }
conn := &SQLiteConn{db: db, loc: loc, txlock: txlock} // Check if user wants to activate User Authentication
if authCreate {
// Before going any further, we need to check that the user
// has provided an username and password within the DSN.
// We are not allowed to continue.
if len(authUser) < 0 {
return nil, fmt.Errorf("Missing '_auth_user' while user authentication was requested with '_auth'")
}
if len(authPass) < 0 {
return nil, fmt.Errorf("Missing '_auth_pass' while user authentication was requested with '_auth'")
}
// Check if User Authentication is Enabled
authExists := conn.AuthEnabled()
if !authExists {
if err := conn.AuthUserAdd(authUser, authPass, true); err != nil {
return nil, err
}
}
}
// Case Sensitive LIKE
if caseSensitiveLike > -1 {
if err := exec(fmt.Sprintf("PRAGMA case_sensitive_like = %d;", caseSensitiveLike)); err != nil {
C.sqlite3_close_v2(db)
return nil, err
}
}
// Defer Foreign Keys
if deferForeignKeys > -1 {
if err := exec(fmt.Sprintf("PRAGMA defer_foreign_keys = %d;", deferForeignKeys)); err != nil {
C.sqlite3_close_v2(db)
return nil, err
}
}
// Forgein Keys
if foreignKeys > -1 {
if err := exec(fmt.Sprintf("PRAGMA foreign_keys = %d;", foreignKeys)); err != nil {
C.sqlite3_close_v2(db)
return nil, err
}
}
// Ignore CHECK Constraints
if ignoreCheckConstraints > -1 {
if err := exec(fmt.Sprintf("PRAGMA ignore_check_constraints = %d;", ignoreCheckConstraints)); err != nil {
C.sqlite3_close_v2(db)
return nil, err
}
}
// Journal Mode
// Because default Journal Mode is DELETE this PRAGMA can always be executed.
if err := exec(fmt.Sprintf("PRAGMA journal_mode = %s;", journalMode)); err != nil {
C.sqlite3_close_v2(db)
return nil, err
}
// Locking Mode
// Because the default is NORMAL and this is not changed in this package
// by using the compile time SQLITE_DEFAULT_LOCKING_MODE this PRAGMA can always be executed
if err := exec(fmt.Sprintf("PRAGMA locking_mode = %s;", lockingMode)); err != nil {
C.sqlite3_close_v2(db)
return nil, err
}
// Query Only
if queryOnly > -1 {
if err := exec(fmt.Sprintf("PRAGMA query_only = %d;", queryOnly)); err != nil {
C.sqlite3_close_v2(db)
return nil, err
}
}
// Recursive Triggers
if recursiveTriggers > -1 {
if err := exec(fmt.Sprintf("PRAGMA recursive_triggers = %d;", recursiveTriggers)); err != nil {
C.sqlite3_close_v2(db)
return nil, err
}
}
// Secure Delete
//
// Because this package can set the compile time flag SQLITE_SECURE_DELETE with a build tag
// the default value for secureDelete var is 'DEFAULT' this way
// you can compile with secure_delete 'ON' and disable it for a specific database connection.
if secureDelete != "DEFAULT" {
if err := exec(fmt.Sprintf("PRAGMA secure_delete = %s;", secureDelete)); err != nil {
C.sqlite3_close_v2(db)
return nil, err
}
}
// Synchronous Mode
//
// Because default is NORMAL this statement is always executed
if err := exec(fmt.Sprintf("PRAGMA synchronous = %s;", synchronousMode)); err != nil {
C.sqlite3_close_v2(db)
return nil, err
}
// Writable Schema
if writableSchema > -1 {
if err := exec(fmt.Sprintf("PRAGMA writable_schema = %d;", writableSchema)); err != nil {
C.sqlite3_close_v2(db)
return nil, err
}
}
if len(d.Extensions) > 0 { if len(d.Extensions) > 0 {
if err := conn.loadExtensions(d.Extensions); err != nil { if err := conn.loadExtensions(d.Extensions); err != nil {
@@ -996,6 +1612,17 @@ const (
SQLITE_LIMIT_WORKER_THREADS = C.SQLITE_LIMIT_WORKER_THREADS SQLITE_LIMIT_WORKER_THREADS = C.SQLITE_LIMIT_WORKER_THREADS
) )
// GetFilename returns the absolute path to the file containing
// the requested schema. When passed an empty string, it will
// instead use the database's default schema: "main".
// See: sqlite3_db_filename, https://www.sqlite.org/c3ref/db_filename.html
func (c *SQLiteConn) GetFilename(schemaName string) string {
if schemaName == "" {
schemaName = "main"
}
return C.GoString(C.sqlite3_db_filename(c.db, C.CString(schemaName)))
}
// GetLimit returns the current value of a run-time limit. // GetLimit returns the current value of a run-time limit.
// See: sqlite3_limit, http://www.sqlite.org/c3ref/limit.html // See: sqlite3_limit, http://www.sqlite.org/c3ref/limit.html
func (c *SQLiteConn) GetLimit(id int) int { func (c *SQLiteConn) GetLimit(id int) int {
@@ -1070,7 +1697,7 @@ func (s *SQLiteStmt) bind(args []namedValue) error {
case int64: case int64:
rv = C.sqlite3_bind_int64(s.s, n, C.sqlite3_int64(v)) rv = C.sqlite3_bind_int64(s.s, n, C.sqlite3_int64(v))
case bool: case bool:
if bool(v) { if v {
rv = C.sqlite3_bind_int(s.s, n, 1) rv = C.sqlite3_bind_int(s.s, n, 1)
} else { } else {
rv = C.sqlite3_bind_int(s.s, n, 0) rv = C.sqlite3_bind_int(s.s, n, 0)
@@ -1078,11 +1705,15 @@ func (s *SQLiteStmt) bind(args []namedValue) error {
case float64: case float64:
rv = C.sqlite3_bind_double(s.s, n, C.double(v)) rv = C.sqlite3_bind_double(s.s, n, C.double(v))
case []byte: case []byte:
ln := len(v) if v == nil {
if ln == 0 { rv = C.sqlite3_bind_null(s.s, n)
v = placeHolder } else {
ln := len(v)
if ln == 0 {
v = placeHolder
}
rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(ln))
} }
rv = C._sqlite3_bind_blob(s.s, n, unsafe.Pointer(&v[0]), C.int(ln))
case time.Time: case time.Time:
b := []byte(v.Format(SQLiteTimestampFormats[0])) b := []byte(v.Format(SQLiteTimestampFormats[0]))
rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) rv = C._sqlite3_bind_text(s.s, n, (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b)))
@@ -1121,18 +1752,20 @@ func (s *SQLiteStmt) query(ctx context.Context, args []namedValue) (driver.Rows,
done: make(chan struct{}), done: make(chan struct{}),
} }
go func(db *C.sqlite3) { if ctxdone := ctx.Done(); ctxdone != nil {
select { go func(db *C.sqlite3) {
case <-ctx.Done():
select { select {
case <-ctxdone:
select {
case <-rows.done:
default:
C.sqlite3_interrupt(db)
rows.Close()
}
case <-rows.done: case <-rows.done:
default:
C.sqlite3_interrupt(db)
rows.Close()
} }
case <-rows.done: }(s.c.db)
} }
}(s.c.db)
return rows, nil return rows, nil
} }
@@ -1166,19 +1799,21 @@ func (s *SQLiteStmt) exec(ctx context.Context, args []namedValue) (driver.Result
return nil, err return nil, err
} }
done := make(chan struct{}) if ctxdone := ctx.Done(); ctxdone != nil {
defer close(done) done := make(chan struct{})
go func(db *C.sqlite3) { defer close(done)
select { go func(db *C.sqlite3) {
case <-done:
case <-ctx.Done():
select { select {
case <-done: case <-done:
default: case <-ctxdone:
C.sqlite3_interrupt(db) select {
case <-done:
default:
C.sqlite3_interrupt(db)
}
} }
} }(s.c.db)
}(s.c.db) }
var rowid, changes C.longlong var rowid, changes C.longlong
rv := C._sqlite3_step(s.s, &rowid, &changes) rv := C._sqlite3_step(s.s, &rowid, &changes)
@@ -1272,7 +1907,7 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error {
case C.SQLITE_INTEGER: case C.SQLITE_INTEGER:
val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i))) val := int64(C.sqlite3_column_int64(rc.s.s, C.int(i)))
switch rc.decltype[i] { switch rc.decltype[i] {
case "timestamp", "datetime", "date": case columnTimestamp, columnDatetime, columnDate:
var t time.Time var t time.Time
// Assume a millisecond unix timestamp if it's 13 digits -- too // Assume a millisecond unix timestamp if it's 13 digits -- too
// large to be a reasonable timestamp in seconds. // large to be a reasonable timestamp in seconds.
@@ -1302,11 +1937,9 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error {
} }
n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i))) n := int(C.sqlite3_column_bytes(rc.s.s, C.int(i)))
switch dest[i].(type) { switch dest[i].(type) {
case sql.RawBytes:
dest[i] = (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]
default: default:
slice := make([]byte, n) slice := make([]byte, n)
copy(slice[:], (*[1 << 30]byte)(unsafe.Pointer(p))[0:n]) copy(slice[:], (*[1 << 30]byte)(p)[0:n])
dest[i] = slice dest[i] = slice
} }
case C.SQLITE_NULL: case C.SQLITE_NULL:
@@ -1319,7 +1952,7 @@ func (rc *SQLiteRows) Next(dest []driver.Value) error {
s := C.GoStringN((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))), C.int(n)) s := C.GoStringN((*C.char)(unsafe.Pointer(C.sqlite3_column_text(rc.s.s, C.int(i)))), C.int(n))
switch rc.decltype[i] { switch rc.decltype[i] {
case "timestamp", "datetime", "date": case columnTimestamp, columnDatetime, columnDate:
var t time.Time var t time.Time
s = strings.TrimSuffix(s, "Z") s = strings.TrimSuffix(s, "Z")
for _, format := range SQLiteTimestampFormats { for _, format := range SQLiteTimestampFormats {

120
vendor/github.com/mattn/go-sqlite3/sqlite3_func_crypt.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,120 @@
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package sqlite3
import (
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
)
// This file provides several different implementations for the
// default embedded sqlite_crypt function.
// This function is uses a ceasar-cypher by default
// and is used within the UserAuthentication module to encode
// the password.
//
// The provided functions can be used as an overload to the sqlite_crypt
// function through the use of the RegisterFunc on the connection.
//
// Because the functions can serv a purpose to an end-user
// without using the UserAuthentication module
// the functions are default compiled in.
//
// From SQLITE3 - user-auth.txt
// The sqlite_user.pw field is encoded by a built-in SQL function
// "sqlite_crypt(X,Y)". The two arguments are both BLOBs. The first argument
// is the plaintext password supplied to the sqlite3_user_authenticate()
// interface. The second argument is the sqlite_user.pw value and is supplied
// so that the function can extract the "salt" used by the password encoder.
// The result of sqlite_crypt(X,Y) is another blob which is the value that
// ends up being stored in sqlite_user.pw. To verify credentials X supplied
// by the sqlite3_user_authenticate() routine, SQLite runs:
//
// sqlite_user.pw == sqlite_crypt(X, sqlite_user.pw)
//
// To compute an appropriate sqlite_user.pw value from a new or modified
// password X, sqlite_crypt(X,NULL) is run. A new random salt is selected
// when the second argument is NULL.
//
// The built-in version of of sqlite_crypt() uses a simple Ceasar-cypher
// which prevents passwords from being revealed by searching the raw database
// for ASCII text, but is otherwise trivally broken. For better password
// security, the database should be encrypted using the SQLite Encryption
// Extension or similar technology. Or, the application can use the
// sqlite3_create_function() interface to provide an alternative
// implementation of sqlite_crypt() that computes a stronger password hash,
// perhaps using a cryptographic hash function like SHA1.
// CryptEncoderSHA1 encodes a password with SHA1
func CryptEncoderSHA1(pass []byte, hash interface{}) []byte {
h := sha1.Sum(pass)
return h[:]
}
// CryptEncoderSSHA1 encodes a password with SHA1 with the
// configured salt.
func CryptEncoderSSHA1(salt string) func(pass []byte, hash interface{}) []byte {
return func(pass []byte, hash interface{}) []byte {
s := []byte(salt)
p := append(pass, s...)
h := sha1.Sum(p)
return h[:]
}
}
// CryptEncoderSHA256 encodes a password with SHA256
func CryptEncoderSHA256(pass []byte, hash interface{}) []byte {
h := sha256.Sum256(pass)
return h[:]
}
// CryptEncoderSSHA256 encodes a password with SHA256
// with the configured salt
func CryptEncoderSSHA256(salt string) func(pass []byte, hash interface{}) []byte {
return func(pass []byte, hash interface{}) []byte {
s := []byte(salt)
p := append(pass, s...)
h := sha256.Sum256(p)
return h[:]
}
}
// CryptEncoderSHA384 encodes a password with SHA256
func CryptEncoderSHA384(pass []byte, hash interface{}) []byte {
h := sha512.Sum384(pass)
return h[:]
}
// CryptEncoderSSHA384 encodes a password with SHA256
// with the configured salt
func CryptEncoderSSHA384(salt string) func(pass []byte, hash interface{}) []byte {
return func(pass []byte, hash interface{}) []byte {
s := []byte(salt)
p := append(pass, s...)
h := sha512.Sum384(p)
return h[:]
}
}
// CryptEncoderSHA512 encodes a password with SHA256
func CryptEncoderSHA512(pass []byte, hash interface{}) []byte {
h := sha512.Sum512(pass)
return h[:]
}
// CryptEncoderSSHA512 encodes a password with SHA256
// with the configured salt
func CryptEncoderSSHA512(salt string) func(pass []byte, hash interface{}) []byte {
return func(pass []byte, hash interface{}) []byte {
s := []byte(salt)
p := append(pass, s...)
h := sha512.Sum512(p)
return h[:]
}
}
// EOF

1
vendor/github.com/mattn/go-sqlite3/sqlite3_go18.go сгенерированный поставляемый
Просмотреть файл

@@ -3,6 +3,7 @@
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build cgo
// +build go1.8 // +build go1.8
package sqlite3 package sqlite3

2
vendor/github.com/mattn/go-sqlite3/sqlite3_libsqlite3.go сгенерированный поставляемый
Просмотреть файл

@@ -2,6 +2,7 @@
// //
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build libsqlite3 // +build libsqlite3
package sqlite3 package sqlite3
@@ -10,6 +11,7 @@ package sqlite3
#cgo CFLAGS: -DUSE_LIBSQLITE3 #cgo CFLAGS: -DUSE_LIBSQLITE3
#cgo linux LDFLAGS: -lsqlite3 #cgo linux LDFLAGS: -lsqlite3
#cgo darwin LDFLAGS: -L/usr/local/opt/sqlite/lib -lsqlite3 #cgo darwin LDFLAGS: -L/usr/local/opt/sqlite/lib -lsqlite3
#cgo openbsd LDFLAGS: -lsqlite3
#cgo solaris LDFLAGS: -lsqlite3 #cgo solaris LDFLAGS: -lsqlite3
*/ */
import "C" import "C"

1
vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go сгенерированный поставляемый
Просмотреть файл

@@ -2,6 +2,7 @@
// //
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build !sqlite_omit_load_extension // +build !sqlite_omit_load_extension
package sqlite3 package sqlite3

Просмотреть файл

@@ -2,6 +2,7 @@
// //
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build sqlite_omit_load_extension // +build sqlite_omit_load_extension
package sqlite3 package sqlite3

15
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_allow_uri_authority.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,15 @@
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build sqlite_allow_uri_authority
package sqlite3
/*
#cgo CFLAGS: -DSQLITE_ALLOW_URI_AUTHORITY
#cgo LDFLAGS: -lm
*/
import "C"

16
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_app_armor.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,16 @@
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build !windows
// +build sqlite_app_armor
package sqlite3
/*
#cgo CFLAGS: -DSQLITE_ENABLE_API_ARMOR
#cgo LDFLAGS: -lm
*/
import "C"

15
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_foreign_keys.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,15 @@
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build sqlite_foreign_keys
package sqlite3
/*
#cgo CFLAGS: -DSQLITE_DEFAULT_FOREIGN_KEYS=1
#cgo LDFLAGS: -lm
*/
import "C"

Просмотреть файл

@@ -2,7 +2,8 @@
// //
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build fts5
// +build sqlite_fts5 fts5
package sqlite3 package sqlite3

Просмотреть файл

@@ -2,12 +2,16 @@
// //
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build icu
// +build sqlite_icu icu
package sqlite3 package sqlite3
/* /*
#cgo LDFLAGS: -licuuc -licui18n #cgo LDFLAGS: -licuuc -licui18n
#cgo CFLAGS: -DSQLITE_ENABLE_ICU #cgo CFLAGS: -DSQLITE_ENABLE_ICU
#cgo darwin CFLAGS: -I/usr/local/opt/icu4c/include
#cgo darwin LDFLAGS: -L/usr/local/opt/icu4c/lib
#cgo openbsd LDFLAGS: -lsqlite3
*/ */
import "C" import "C"

15
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_introspect.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,15 @@
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build sqlite_introspect
package sqlite3
/*
#cgo CFLAGS: -DSQLITE_INTROSPECTION_PRAGMAS
#cgo LDFLAGS: -lm
*/
import "C"

Просмотреть файл

@@ -2,7 +2,8 @@
// //
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build json1
// +build sqlite_json sqlite_json1 json1
package sqlite3 package sqlite3

15
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,15 @@
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build sqlite_secure_delete
package sqlite3
/*
#cgo CFLAGS: -DSQLITE_SECURE_DELETE=1
#cgo LDFLAGS: -lm
*/
import "C"

15
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_secure_delete_fast.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,15 @@
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build sqlite_secure_delete_fast
package sqlite3
/*
#cgo CFLAGS: -DSQLITE_SECURE_DELETE=FAST
#cgo LDFLAGS: -lm
*/
import "C"

15
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_stat4.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,15 @@
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build sqlite_stat4
package sqlite3
/*
#cgo CFLAGS: -DSQLITE_ENABLE_STAT4
#cgo LDFLAGS: -lm
*/
import "C"

289
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,289 @@
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build sqlite_userauth
package sqlite3
/*
#cgo CFLAGS: -DSQLITE_USER_AUTHENTICATION
#cgo LDFLAGS: -lm
#ifndef USE_LIBSQLITE3
#include <sqlite3-binding.h>
#else
#include <sqlite3.h>
#endif
#include <stdlib.h>
static int
_sqlite3_user_authenticate(sqlite3* db, const char* zUsername, const char* aPW, int nPW)
{
return sqlite3_user_authenticate(db, zUsername, aPW, nPW);
}
static int
_sqlite3_user_add(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin)
{
return sqlite3_user_add(db, zUsername, aPW, nPW, isAdmin);
}
static int
_sqlite3_user_change(sqlite3* db, const char* zUsername, const char* aPW, int nPW, int isAdmin)
{
return sqlite3_user_change(db, zUsername, aPW, nPW, isAdmin);
}
static int
_sqlite3_user_delete(sqlite3* db, const char* zUsername)
{
return sqlite3_user_delete(db, zUsername);
}
static int
_sqlite3_auth_enabled(sqlite3* db)
{
int exists = -1;
sqlite3_stmt *stmt;
sqlite3_prepare_v2(db, "select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';", -1, &stmt, NULL);
while ( sqlite3_step(stmt) == SQLITE_ROW) {
exists = sqlite3_column_int(stmt, 0);
}
sqlite3_finalize(stmt);
return exists;
}
*/
import "C"
import (
"errors"
"unsafe"
)
const (
SQLITE_AUTH = C.SQLITE_AUTH
)
var (
ErrUnauthorized = errors.New("SQLITE_AUTH: Unauthorized")
ErrAdminRequired = errors.New("SQLITE_AUTH: Unauthorized; Admin Privileges Required")
)
// Authenticate will perform an authentication of the provided username
// and password against the database.
//
// If a database contains the SQLITE_USER table, then the
// call to Authenticate must be invoked with an
// appropriate username and password prior to enable read and write
//access to the database.
//
// Return SQLITE_OK on success or SQLITE_ERROR if the username/password
// combination is incorrect or unknown.
//
// If the SQLITE_USER table is not present in the database file, then
// this interface is a harmless no-op returnning SQLITE_OK.
func (c *SQLiteConn) Authenticate(username, password string) error {
rv := c.authenticate(username, password)
switch rv {
case C.SQLITE_ERROR, C.SQLITE_AUTH:
return ErrUnauthorized
case C.SQLITE_OK:
return nil
default:
return c.lastError()
}
}
// authenticate provides the actual authentication to SQLite.
// This is not exported for usage in Go.
// It is however exported for usage within SQL by the user.
//
// Returns:
// C.SQLITE_OK (0)
// C.SQLITE_ERROR (1)
// C.SQLITE_AUTH (23)
func (c *SQLiteConn) authenticate(username, password string) int {
// Allocate C Variables
cuser := C.CString(username)
cpass := C.CString(password)
// Free C Variables
defer func() {
C.free(unsafe.Pointer(cuser))
C.free(unsafe.Pointer(cpass))
}()
return int(C._sqlite3_user_authenticate(c.db, cuser, cpass, C.int(len(password))))
}
// AuthUserAdd can be used (by an admin user only)
// to create a new user. When called on a no-authentication-required
// database, this routine converts the database into an authentication-
// required database, automatically makes the added user an
// administrator, and logs in the current connection as that user.
// The AuthUserAdd only works for the "main" database, not
// for any ATTACH-ed databases. Any call to AuthUserAdd by a
// non-admin user results in an error.
func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error {
isAdmin := 0
if admin {
isAdmin = 1
}
rv := c.authUserAdd(username, password, isAdmin)
switch rv {
case C.SQLITE_ERROR, C.SQLITE_AUTH:
return ErrAdminRequired
case C.SQLITE_OK:
return nil
default:
return c.lastError()
}
}
// authUserAdd enables the User Authentication if not enabled.
// Otherwise it will add a user.
//
// When user authentication is already enabled then this function
// can only be called by an admin.
//
// This is not exported for usage in Go.
// It is however exported for usage within SQL by the user.
//
// Returns:
// C.SQLITE_OK (0)
// C.SQLITE_ERROR (1)
// C.SQLITE_AUTH (23)
func (c *SQLiteConn) authUserAdd(username, password string, admin int) int {
// Allocate C Variables
cuser := C.CString(username)
cpass := C.CString(password)
// Free C Variables
defer func() {
C.free(unsafe.Pointer(cuser))
C.free(unsafe.Pointer(cpass))
}()
return int(C._sqlite3_user_add(c.db, cuser, cpass, C.int(len(password)), C.int(admin)))
}
// AuthUserChange can be used to change a users
// login credentials or admin privilege. Any user can change their own
// login credentials. Only an admin user can change another users login
// credentials or admin privilege setting. No user may change their own
// admin privilege setting.
func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error {
isAdmin := 0
if admin {
isAdmin = 1
}
rv := c.authUserChange(username, password, isAdmin)
switch rv {
case C.SQLITE_ERROR, C.SQLITE_AUTH:
return ErrAdminRequired
case C.SQLITE_OK:
return nil
default:
return c.lastError()
}
}
// authUserChange allows to modify a user.
// Users can change their own password.
//
// Only admins can change passwords for other users
// and modify the admin flag.
//
// The admin flag of the current logged in user cannot be changed.
// THis ensures that their is always an admin.
//
// This is not exported for usage in Go.
// It is however exported for usage within SQL by the user.
//
// Returns:
// C.SQLITE_OK (0)
// C.SQLITE_ERROR (1)
// C.SQLITE_AUTH (23)
func (c *SQLiteConn) authUserChange(username, password string, admin int) int {
// Allocate C Variables
cuser := C.CString(username)
cpass := C.CString(password)
// Free C Variables
defer func() {
C.free(unsafe.Pointer(cuser))
C.free(unsafe.Pointer(cpass))
}()
return int(C._sqlite3_user_change(c.db, cuser, cpass, C.int(len(password)), C.int(admin)))
}
// AuthUserDelete can be used (by an admin user only)
// to delete a user. The currently logged-in user cannot be deleted,
// which guarantees that there is always an admin user and hence that
// the database cannot be converted into a no-authentication-required
// database.
func (c *SQLiteConn) AuthUserDelete(username string) error {
rv := c.authUserDelete(username)
switch rv {
case C.SQLITE_ERROR, C.SQLITE_AUTH:
return ErrAdminRequired
case C.SQLITE_OK:
return nil
default:
return c.lastError()
}
}
// authUserDelete can be used to delete a user.
//
// This function can only be executed by an admin.
//
// This is not exported for usage in Go.
// It is however exported for usage within SQL by the user.
//
// Returns:
// C.SQLITE_OK (0)
// C.SQLITE_ERROR (1)
// C.SQLITE_AUTH (23)
func (c *SQLiteConn) authUserDelete(username string) int {
// Allocate C Variables
cuser := C.CString(username)
// Free C Variables
defer func() {
C.free(unsafe.Pointer(cuser))
}()
return int(C._sqlite3_user_delete(c.db, cuser))
}
// AuthEnabled checks if the database is protected by user authentication
func (c *SQLiteConn) AuthEnabled() (exists bool) {
rv := c.authEnabled()
if rv == 1 {
exists = true
}
return
}
// authEnabled perform the actual check for user authentication.
//
// This is not exported for usage in Go.
// It is however exported for usage within SQL by the user.
//
// Returns:
// 0 - Disabled
// 1 - Enabled
func (c *SQLiteConn) authEnabled() int {
return int(C._sqlite3_auth_enabled(c.db))
}
// EOF

152
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_userauth_omit.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,152 @@
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build !sqlite_userauth
package sqlite3
import (
"C"
)
// Authenticate will perform an authentication of the provided username
// and password against the database.
//
// If a database contains the SQLITE_USER table, then the
// call to Authenticate must be invoked with an
// appropriate username and password prior to enable read and write
//access to the database.
//
// Return SQLITE_OK on success or SQLITE_ERROR if the username/password
// combination is incorrect or unknown.
//
// If the SQLITE_USER table is not present in the database file, then
// this interface is a harmless no-op returnning SQLITE_OK.
func (c *SQLiteConn) Authenticate(username, password string) error {
// NOOP
return nil
}
// authenticate provides the actual authentication to SQLite.
// This is not exported for usage in Go.
// It is however exported for usage within SQL by the user.
//
// Returns:
// C.SQLITE_OK (0)
// C.SQLITE_ERROR (1)
// C.SQLITE_AUTH (23)
func (c *SQLiteConn) authenticate(username, password string) int {
// NOOP
return 0
}
// AuthUserAdd can be used (by an admin user only)
// to create a new user. When called on a no-authentication-required
// database, this routine converts the database into an authentication-
// required database, automatically makes the added user an
// administrator, and logs in the current connection as that user.
// The AuthUserAdd only works for the "main" database, not
// for any ATTACH-ed databases. Any call to AuthUserAdd by a
// non-admin user results in an error.
func (c *SQLiteConn) AuthUserAdd(username, password string, admin bool) error {
// NOOP
return nil
}
// authUserAdd enables the User Authentication if not enabled.
// Otherwise it will add a user.
//
// When user authentication is already enabled then this function
// can only be called by an admin.
//
// This is not exported for usage in Go.
// It is however exported for usage within SQL by the user.
//
// Returns:
// C.SQLITE_OK (0)
// C.SQLITE_ERROR (1)
// C.SQLITE_AUTH (23)
func (c *SQLiteConn) authUserAdd(username, password string, admin int) int {
// NOOP
return 0
}
// AuthUserChange can be used to change a users
// login credentials or admin privilege. Any user can change their own
// login credentials. Only an admin user can change another users login
// credentials or admin privilege setting. No user may change their own
// admin privilege setting.
func (c *SQLiteConn) AuthUserChange(username, password string, admin bool) error {
// NOOP
return nil
}
// authUserChange allows to modify a user.
// Users can change their own password.
//
// Only admins can change passwords for other users
// and modify the admin flag.
//
// The admin flag of the current logged in user cannot be changed.
// THis ensures that their is always an admin.
//
// This is not exported for usage in Go.
// It is however exported for usage within SQL by the user.
//
// Returns:
// C.SQLITE_OK (0)
// C.SQLITE_ERROR (1)
// C.SQLITE_AUTH (23)
func (c *SQLiteConn) authUserChange(username, password string, admin int) int {
// NOOP
return 0
}
// AuthUserDelete can be used (by an admin user only)
// to delete a user. The currently logged-in user cannot be deleted,
// which guarantees that there is always an admin user and hence that
// the database cannot be converted into a no-authentication-required
// database.
func (c *SQLiteConn) AuthUserDelete(username string) error {
// NOOP
return nil
}
// authUserDelete can be used to delete a user.
//
// This function can only be executed by an admin.
//
// This is not exported for usage in Go.
// It is however exported for usage within SQL by the user.
//
// Returns:
// C.SQLITE_OK (0)
// C.SQLITE_ERROR (1)
// C.SQLITE_AUTH (23)
func (c *SQLiteConn) authUserDelete(username string) int {
// NOOP
return 0
}
// AuthEnabled checks if the database is protected by user authentication
func (c *SQLiteConn) AuthEnabled() (exists bool) {
// NOOP
return false
}
// authEnabled perform the actual check for user authentication.
//
// This is not exported for usage in Go.
// It is however exported for usage within SQL by the user.
//
// Returns:
// 0 - Disabled
// 1 - Enabled
func (c *SQLiteConn) authEnabled() int {
// NOOP
return 0
}
// EOF

15
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_full.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,15 @@
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build sqlite_vacuum_full
package sqlite3
/*
#cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=1
#cgo LDFLAGS: -lm
*/
import "C"

15
vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vacuum_incr.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,15 @@
// Copyright (C) 2014 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build sqlite_vacuum_incr
package sqlite3
/*
#cgo CFLAGS: -DSQLITE_DEFAULT_AUTOVACUUM=2
#cgo LDFLAGS: -lm
*/
import "C"

Просмотреть файл

@@ -2,14 +2,18 @@
// //
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build vtable
// +build sqlite_vtable vtable
package sqlite3 package sqlite3
/* /*
#cgo CFLAGS: -std=gnu99 #cgo CFLAGS: -std=gnu99
#cgo CFLAGS: -DSQLITE_ENABLE_RTREE -DSQLITE_THREADSAFE #cgo CFLAGS: -DSQLITE_ENABLE_RTREE
#cgo CFLAGS: -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS4_UNICODE61 #cgo CFLAGS: -DSQLITE_THREADSAFE
#cgo CFLAGS: -DSQLITE_ENABLE_FTS3
#cgo CFLAGS: -DSQLITE_ENABLE_FTS3_PARENTHESIS
#cgo CFLAGS: -DSQLITE_ENABLE_FTS4_UNICODE61
#cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15 #cgo CFLAGS: -DSQLITE_TRACE_SIZE_LIMIT=15
#cgo CFLAGS: -DSQLITE_ENABLE_COLUMN_METADATA=1 #cgo CFLAGS: -DSQLITE_ENABLE_COLUMN_METADATA=1
#cgo CFLAGS: -Wno-deprecated-declarations #cgo CFLAGS: -Wno-deprecated-declarations

2
vendor/github.com/mattn/go-sqlite3/sqlite3_other.go сгенерированный поставляемый
Просмотреть файл

@@ -2,6 +2,7 @@
// //
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build !windows // +build !windows
package sqlite3 package sqlite3
@@ -9,6 +10,5 @@ package sqlite3
/* /*
#cgo CFLAGS: -I. #cgo CFLAGS: -I.
#cgo linux LDFLAGS: -ldl #cgo linux LDFLAGS: -ldl
#cgo solaris LDFLAGS: -lc
*/ */
import "C" import "C"

14
vendor/github.com/mattn/go-sqlite3/sqlite3_solaris.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,14 @@
// Copyright (C) 2018 Yasuhiro Matsumoto <mattn.jp@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build solaris
package sqlite3
/*
#cgo CFLAGS: -D__EXTENSIONS__=1
#cgo LDFLAGS: -lc
*/
import "C"

25
vendor/github.com/mattn/go-sqlite3/sqlite3_trace.go сгенерированный поставляемый
Просмотреть файл

@@ -2,7 +2,8 @@
// //
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build trace
// +build sqlite_trace trace
package sqlite3 package sqlite3
@@ -28,10 +29,10 @@ import (
// Trace... constants identify the possible events causing callback invocation. // Trace... constants identify the possible events causing callback invocation.
// Values are same as the corresponding SQLite Trace Event Codes. // Values are same as the corresponding SQLite Trace Event Codes.
const ( const (
TraceStmt = C.SQLITE_TRACE_STMT TraceStmt = uint32(C.SQLITE_TRACE_STMT)
TraceProfile = C.SQLITE_TRACE_PROFILE TraceProfile = uint32(C.SQLITE_TRACE_PROFILE)
TraceRow = C.SQLITE_TRACE_ROW TraceRow = uint32(C.SQLITE_TRACE_ROW)
TraceClose = C.SQLITE_TRACE_CLOSE TraceClose = uint32(C.SQLITE_TRACE_CLOSE)
) )
type TraceInfo struct { type TraceInfo struct {
@@ -71,7 +72,7 @@ type TraceUserCallback func(TraceInfo) int
type TraceConfig struct { type TraceConfig struct {
Callback TraceUserCallback Callback TraceUserCallback
EventMask C.uint EventMask uint32
WantExpandedSQL bool WantExpandedSQL bool
} }
@@ -105,6 +106,8 @@ func traceCallbackTrampoline(
// Parameter named 'X' in SQLite docs (eXtra event data?): // Parameter named 'X' in SQLite docs (eXtra event data?):
xValue unsafe.Pointer) C.int { xValue unsafe.Pointer) C.int {
eventCode := uint32(traceEventCode)
if ctx == nil { if ctx == nil {
panic(fmt.Sprintf("No context (ev 0x%x)", traceEventCode)) panic(fmt.Sprintf("No context (ev 0x%x)", traceEventCode))
} }
@@ -114,7 +117,7 @@ func traceCallbackTrampoline(
var traceConf TraceConfig var traceConf TraceConfig
var found bool var found bool
if traceEventCode == TraceClose { if eventCode == TraceClose {
// clean up traceMap: 'pop' means get and delete // clean up traceMap: 'pop' means get and delete
traceConf, found = popTraceMapping(connHandle) traceConf, found = popTraceMapping(connHandle)
} else { } else {
@@ -123,16 +126,16 @@ func traceCallbackTrampoline(
if !found { if !found {
panic(fmt.Sprintf("Mapping not found for handle 0x%x (ev 0x%x)", panic(fmt.Sprintf("Mapping not found for handle 0x%x (ev 0x%x)",
connHandle, traceEventCode)) connHandle, eventCode))
} }
var info TraceInfo var info TraceInfo
info.EventCode = uint32(traceEventCode) info.EventCode = eventCode
info.AutoCommit = (int(C.sqlite3_get_autocommit(contextDB)) != 0) info.AutoCommit = (int(C.sqlite3_get_autocommit(contextDB)) != 0)
info.ConnHandle = connHandle info.ConnHandle = connHandle
switch traceEventCode { switch eventCode {
case TraceStmt: case TraceStmt:
info.StmtHandle = uintptr(p) info.StmtHandle = uintptr(p)
@@ -183,7 +186,7 @@ func traceCallbackTrampoline(
// registering this callback trampoline with SQLite --- for cleanup. // registering this callback trampoline with SQLite --- for cleanup.
// In the future there may be more events forced to "selected" in SQLite // In the future there may be more events forced to "selected" in SQLite
// for the driver's needs. // for the driver's needs.
if traceConf.EventMask&traceEventCode == 0 { if traceConf.EventMask&eventCode == 0 {
return 0 return 0
} }

39
vendor/github.com/mattn/go-sqlite3/sqlite3_usleep_windows.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,39 @@
// Copyright (C) 2018 G.J.R. Timmer <gjr.timmer@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
// +build cgo
package sqlite3
// usleep is a function available on *nix based systems.
// This function is not present in Windows.
// Windows has a sleep function but this works with seconds
// and not with microseconds as usleep.
//
// This code should improve performance on windows because
// without the presence of usleep SQLite waits 1 second.
//
// Source: https://stackoverflow.com/questions/5801813/c-usleep-is-obsolete-workarounds-for-windows-mingw?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa
/*
#include <windows.h>
void usleep(__int64 usec)
{
HANDLE timer;
LARGE_INTEGER ft;
// Convert to 100 nanosecond interval, negative value indicates relative time
ft.QuadPart = -(10*usec);
timer = CreateWaitableTimer(NULL, TRUE, NULL);
SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
WaitForSingleObject(timer, INFINITE);
CloseHandle(timer);
}
*/
import "C"
// EOF

8
vendor/github.com/mattn/go-sqlite3/sqlite3_windows.go сгенерированный поставляемый
Просмотреть файл

@@ -2,13 +2,17 @@
// //
// Use of this source code is governed by an MIT-style // Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build windows // +build windows
package sqlite3 package sqlite3
/* /*
#cgo CFLAGS: -I. -fno-stack-check -fno-stack-protector -mno-stack-arg-probe #cgo CFLAGS: -I.
#cgo windows,386 CFLAGS: -D_USE_32BIT_TIME_T #cgo CFLAGS: -fno-stack-check
#cgo CFLAGS: -fno-stack-protector
#cgo CFLAGS: -mno-stack-arg-probe
#cgo LDFLAGS: -lmingwex -lmingw32 #cgo LDFLAGS: -lmingwex -lmingw32
#cgo windows,386 CFLAGS: -D_USE_32BIT_TIME_T
*/ */
import "C" import "C"

37
vendor/github.com/mattn/go-sqlite3/sqlite3ext.h сгенерированный поставляемый
Просмотреть файл

@@ -293,6 +293,24 @@ struct sqlite3_api_routines {
int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*)); int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*)); void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
void *(*value_pointer)(sqlite3_value*,const char*); void *(*value_pointer)(sqlite3_value*,const char*);
int (*vtab_nochange)(sqlite3_context*);
int (*value_nochange)(sqlite3_value*);
const char *(*vtab_collation)(sqlite3_index_info*,int);
/* Version 3.24.0 and later */
int (*keyword_count)(void);
int (*keyword_name)(int,const char**,int*);
int (*keyword_check)(const char*,int);
sqlite3_str *(*str_new)(sqlite3*);
char *(*str_finish)(sqlite3_str*);
void (*str_appendf)(sqlite3_str*, const char *zFormat, ...);
void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list);
void (*str_append)(sqlite3_str*, const char *zIn, int N);
void (*str_appendall)(sqlite3_str*, const char *zIn);
void (*str_appendchar)(sqlite3_str*, int N, char C);
void (*str_reset)(sqlite3_str*);
int (*str_errcode)(sqlite3_str*);
int (*str_length)(sqlite3_str*);
char *(*str_value)(sqlite3_str*);
}; };
/* /*
@@ -559,6 +577,25 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_bind_pointer sqlite3_api->bind_pointer #define sqlite3_bind_pointer sqlite3_api->bind_pointer
#define sqlite3_result_pointer sqlite3_api->result_pointer #define sqlite3_result_pointer sqlite3_api->result_pointer
#define sqlite3_value_pointer sqlite3_api->value_pointer #define sqlite3_value_pointer sqlite3_api->value_pointer
/* Version 3.22.0 and later */
#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
#define sqlite3_value_nochange sqlite3_api->value_nochange
#define sqlite3_vtab_collation sqlite3_api->vtab_collation
/* Version 3.24.0 and later */
#define sqlite3_keyword_count sqlite3_api->keyword_count
#define sqlite3_keyword_name sqlite3_api->keyword_name
#define sqlite3_keyword_check sqlite3_api->keyword_check
#define sqlite3_str_new sqlite3_api->str_new
#define sqlite3_str_finish sqlite3_api->str_finish
#define sqlite3_str_appendf sqlite3_api->str_appendf
#define sqlite3_str_vappendf sqlite3_api->str_vappendf
#define sqlite3_str_append sqlite3_api->str_append
#define sqlite3_str_appendall sqlite3_api->str_appendall
#define sqlite3_str_appendchar sqlite3_api->str_appendchar
#define sqlite3_str_reset sqlite3_api->str_reset
#define sqlite3_str_errcode sqlite3_api->str_errcode
#define sqlite3_str_length sqlite3_api->str_length
#define sqlite3_str_value sqlite3_api->str_value
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)

21
vendor/github.com/mattn/go-sqlite3/static_mock.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,21 @@
// +build !cgo
package sqlite3
import (
"database/sql"
"database/sql/driver"
"errors"
)
func init() {
sql.Register("sqlite3", &SQLiteDriverMock{})
}
type SQLiteDriverMock struct{}
var errorMsg = errors.New("Binary was compiled with 'CGO_ENABLED=0', go-sqlite3 requires cgo to work. This is a stub")
func (SQLiteDriverMock) Open(s string) (driver.Conn, error) {
return nil, errorMsg
}

1
vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/.gitignore сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1 @@
cover.dat

7
vendor/github.com/matttproud/golang_protobuf_extensions/pbutil/Makefile сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,7 @@
all:
cover:
go test -cover -v -coverprofile=cover.dat ./...
go tool cover -func cover.dat
.PHONY: cover

28
vendor/github.com/miekg/dns/client.go сгенерированный поставляемый
Просмотреть файл

@@ -12,15 +12,16 @@ import (
"io/ioutil" "io/ioutil"
"net" "net"
"net/http" "net/http"
"net/url"
"strings" "strings"
"time" "time"
) )
const dnsTimeout time.Duration = 2 * time.Second const (
const tcpIdleTimeout time.Duration = 8 * time.Second dnsTimeout time.Duration = 2 * time.Second
tcpIdleTimeout time.Duration = 8 * time.Second
const dohMimeType = "application/dns-udpwireformat" dohMimeType = "application/dns-message"
)
// A Conn represents a connection to a DNS server. // A Conn represents a connection to a DNS server.
type Conn struct { type Conn struct {
@@ -88,11 +89,10 @@ func (c *Client) Dial(address string) (conn *Conn, err error) {
// create a new dialer with the appropriate timeout // create a new dialer with the appropriate timeout
var d net.Dialer var d net.Dialer
if c.Dialer == nil { if c.Dialer == nil {
d = net.Dialer{} d = net.Dialer{Timeout:c.getTimeoutForRequest(c.dialTimeout())}
} else { } else {
d = net.Dialer(*c.Dialer) d = net.Dialer(*c.Dialer)
} }
d.Timeout = c.getTimeoutForRequest(c.writeTimeout())
network := "udp" network := "udp"
useTLS := false useTLS := false
@@ -214,17 +214,7 @@ func (c *Client) exchangeDOH(ctx context.Context, m *Msg, a string) (r *Msg, rtt
return nil, 0, err return nil, 0, err
} }
// TODO(tmthrgd): Allow the path to be customised? req, err := http.NewRequest(http.MethodPost, a, bytes.NewReader(p))
u := &url.URL{
Scheme: "https",
Host: a,
Path: "/.well-known/dns-query",
}
if u.Port() == "443" {
u.Host = u.Hostname()
}
req, err := http.NewRequest(http.MethodPost, u.String(), bytes.NewReader(p))
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
@@ -232,8 +222,6 @@ func (c *Client) exchangeDOH(ctx context.Context, m *Msg, a string) (r *Msg, rtt
req.Header.Set("Content-Type", dohMimeType) req.Header.Set("Content-Type", dohMimeType)
req.Header.Set("Accept", dohMimeType) req.Header.Set("Accept", dohMimeType)
t := time.Now()
hc := http.DefaultClient hc := http.DefaultClient
if c.HTTPClient != nil { if c.HTTPClient != nil {
hc = c.HTTPClient hc = c.HTTPClient
@@ -243,6 +231,8 @@ func (c *Client) exchangeDOH(ctx context.Context, m *Msg, a string) (r *Msg, rtt
req = req.WithContext(ctx) req = req.WithContext(ctx)
} }
t := time.Now()
resp, err := hc.Do(req) resp, err := hc.Do(req)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err

18
vendor/github.com/miekg/dns/dnssec.go сгенерированный поставляемый
Просмотреть файл

@@ -542,20 +542,20 @@ func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey {
explen = uint16(keybuf[1])<<8 | uint16(keybuf[2]) explen = uint16(keybuf[1])<<8 | uint16(keybuf[2])
keyoff = 3 keyoff = 3
} }
if explen > 4 {
// Larger exponent than supported by the crypto package.
return nil
}
pubkey := new(rsa.PublicKey) pubkey := new(rsa.PublicKey)
pubkey.N = big.NewInt(0) pubkey.N = big.NewInt(0)
shift := uint64((explen - 1) * 8)
expo := uint64(0) expo := uint64(0)
for i := int(explen - 1); i > 0; i-- { for i := 0; i < int(explen); i++ {
expo += uint64(keybuf[keyoff+i]) << shift expo <<= 8
shift -= 8 expo |= uint64(keybuf[keyoff+i])
} }
// Remainder if expo > 1<<31-1 {
expo += uint64(keybuf[keyoff]) // Larger exponent than supported by the crypto package.
if expo > (2<<31)+1 {
// Larger expo than supported.
// println("dns: F5 primes (or larger) are not supported")
return nil return nil
} }
pubkey.E = int(expo) pubkey.E = int(expo)

7
vendor/github.com/miekg/dns/edns.go сгенерированный поставляемый
Просмотреть файл

@@ -102,12 +102,15 @@ func (rr *OPT) SetVersion(v uint8) {
// ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL). // ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL).
func (rr *OPT) ExtendedRcode() int { func (rr *OPT) ExtendedRcode() int {
return int((rr.Hdr.Ttl & 0xFF000000) >> 24) return int((rr.Hdr.Ttl&0xFF000000)>>24) + 15
} }
// SetExtendedRcode sets the EDNS extended RCODE field. // SetExtendedRcode sets the EDNS extended RCODE field.
func (rr *OPT) SetExtendedRcode(v uint8) { func (rr *OPT) SetExtendedRcode(v uint8) {
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v) << 24) if v < RcodeBadVers { // Smaller than 16.. Use the 4 bits you have!
return
}
rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | (uint32(v-15) << 24)
} }
// UDPSize returns the UDP buffer size. // UDPSize returns the UDP buffer size.

10
vendor/github.com/miekg/dns/msg_helpers.go сгенерированный поставляемый
Просмотреть файл

@@ -141,20 +141,24 @@ func truncateMsgFromRdlength(msg []byte, off int, rdlength uint16) (truncmsg []b
return msg[:lenrd], nil return msg[:lenrd], nil
} }
var base32HexNoPadEncoding = base32.HexEncoding.WithPadding(base32.NoPadding)
func fromBase32(s []byte) (buf []byte, err error) { func fromBase32(s []byte) (buf []byte, err error) {
for i, b := range s { for i, b := range s {
if b >= 'a' && b <= 'z' { if b >= 'a' && b <= 'z' {
s[i] = b - 32 s[i] = b - 32
} }
} }
buflen := base32.HexEncoding.DecodedLen(len(s)) buflen := base32HexNoPadEncoding.DecodedLen(len(s))
buf = make([]byte, buflen) buf = make([]byte, buflen)
n, err := base32.HexEncoding.Decode(buf, s) n, err := base32HexNoPadEncoding.Decode(buf, s)
buf = buf[:n] buf = buf[:n]
return return
} }
func toBase32(b []byte) string { return base32.HexEncoding.EncodeToString(b) } func toBase32(b []byte) string {
return base32HexNoPadEncoding.EncodeToString(b)
}
func fromBase64(s []byte) (buf []byte, err error) { func fromBase64(s []byte) (buf []byte, err error) {
buflen := base64.StdEncoding.DecodedLen(len(s)) buflen := base64.StdEncoding.DecodedLen(len(s))

2
vendor/github.com/miekg/dns/version.go сгенерированный поставляемый
Просмотреть файл

@@ -3,7 +3,7 @@ package dns
import "fmt" import "fmt"
// Version is current version of this library. // Version is current version of this library.
var Version = V{1, 0, 7} var Version = V{1, 0, 8}
// V holds the version of this library. // V holds the version of this library.
type V struct { type V struct {

2
vendor/github.com/minio/minio-go/README.md сгенерированный поставляемый
Просмотреть файл

@@ -139,7 +139,7 @@ The full API Reference is available here.
### API Reference : File Object Operations ### API Reference : File Object Operations
* [`FPutObject`](https://docs.minio.io/docs/golang-client-api-reference#FPutObject) * [`FPutObject`](https://docs.minio.io/docs/golang-client-api-reference#FPutObject)
* [`FGetObject`](https://docs.minio.io/docs/golang-client-api-reference#FPutObject) * [`FGetObject`](https://docs.minio.io/docs/golang-client-api-reference#FGetObject)
* [`FPutObjectWithContext`](https://docs.minio.io/docs/golang-client-api-reference#FPutObjectWithContext) * [`FPutObjectWithContext`](https://docs.minio.io/docs/golang-client-api-reference#FPutObjectWithContext)
* [`FGetObjectWithContext`](https://docs.minio.io/docs/golang-client-api-reference#FGetObjectWithContext) * [`FGetObjectWithContext`](https://docs.minio.io/docs/golang-client-api-reference#FGetObjectWithContext)

27
vendor/github.com/minio/minio-go/api-list.go сгенерированный поставляемый
Просмотреть файл

@@ -118,7 +118,7 @@ func (c Client) ListObjectsV2(bucketName, objectPrefix string, recursive bool, d
var continuationToken string var continuationToken string
for { for {
// Get list of objects a maximum of 1000 per request. // Get list of objects a maximum of 1000 per request.
result, err := c.listObjectsV2Query(bucketName, objectPrefix, continuationToken, fetchOwner, delimiter, 1000) result, err := c.listObjectsV2Query(bucketName, objectPrefix, continuationToken, fetchOwner, delimiter, 1000, "")
if err != nil { if err != nil {
objectStatCh <- ObjectInfo{ objectStatCh <- ObjectInfo{
Err: err, Err: err,
@@ -171,11 +171,12 @@ func (c Client) ListObjectsV2(bucketName, objectPrefix string, recursive bool, d
// You can use the request parameters as selection criteria to return a subset of the objects in a bucket. // You can use the request parameters as selection criteria to return a subset of the objects in a bucket.
// request parameters :- // request parameters :-
// --------- // ---------
// ?continuation-token - Specifies the key to start with when listing objects in a bucket. // ?continuation-token - Used to continue iterating over a set of objects
// ?delimiter - A delimiter is a character you use to group keys. // ?delimiter - A delimiter is a character you use to group keys.
// ?prefix - Limits the response to keys that begin with the specified prefix. // ?prefix - Limits the response to keys that begin with the specified prefix.
// ?max-keys - Sets the maximum number of keys returned in the response body. // ?max-keys - Sets the maximum number of keys returned in the response body.
func (c Client) listObjectsV2Query(bucketName, objectPrefix, continuationToken string, fetchOwner bool, delimiter string, maxkeys int) (ListBucketV2Result, error) { // ?start-after - Specifies the key to start after when listing objects in a bucket.
func (c Client) listObjectsV2Query(bucketName, objectPrefix, continuationToken string, fetchOwner bool, delimiter string, maxkeys int, startAfter string) (ListBucketV2Result, error) {
// Validate bucket name. // Validate bucket name.
if err := s3utils.CheckValidBucketName(bucketName); err != nil { if err := s3utils.CheckValidBucketName(bucketName); err != nil {
return ListBucketV2Result{}, err return ListBucketV2Result{}, err
@@ -216,6 +217,11 @@ func (c Client) listObjectsV2Query(bucketName, objectPrefix, continuationToken s
// Set max keys. // Set max keys.
urlValues.Set("max-keys", fmt.Sprintf("%d", maxkeys)) urlValues.Set("max-keys", fmt.Sprintf("%d", maxkeys))
// Set start-after
if startAfter != "" {
urlValues.Set("start-after", startAfter)
}
// Execute GET on bucket to list objects. // Execute GET on bucket to list objects.
resp, err := c.executeMethod(context.Background(), "GET", requestMetadata{ resp, err := c.executeMethod(context.Background(), "GET", requestMetadata{
bucketName: bucketName, bucketName: bucketName,
@@ -627,30 +633,27 @@ func (c Client) listObjectParts(bucketName, objectName, uploadID string) (partsI
return partsInfo, nil return partsInfo, nil
} }
// findUploadID lists all incomplete uploads and finds the uploadID of the matching object name. // findUploadIDs lists all incomplete uploads and find the uploadIDs of the matching object name.
func (c Client) findUploadID(bucketName, objectName string) (uploadID string, err error) { func (c Client) findUploadIDs(bucketName, objectName string) ([]string, error) {
var uploadIDs []string
// Make list incomplete uploads recursive. // Make list incomplete uploads recursive.
isRecursive := true isRecursive := true
// Turn off size aggregation of individual parts, in this request. // Turn off size aggregation of individual parts, in this request.
isAggregateSize := false isAggregateSize := false
// latestUpload to track the latest multipart info for objectName.
var latestUpload ObjectMultipartInfo
// Create done channel to cleanup the routine. // Create done channel to cleanup the routine.
doneCh := make(chan struct{}) doneCh := make(chan struct{})
defer close(doneCh) defer close(doneCh)
// List all incomplete uploads. // List all incomplete uploads.
for mpUpload := range c.listIncompleteUploads(bucketName, objectName, isRecursive, isAggregateSize, doneCh) { for mpUpload := range c.listIncompleteUploads(bucketName, objectName, isRecursive, isAggregateSize, doneCh) {
if mpUpload.Err != nil { if mpUpload.Err != nil {
return "", mpUpload.Err return nil, mpUpload.Err
} }
if objectName == mpUpload.Key { if objectName == mpUpload.Key {
if mpUpload.Initiated.Sub(latestUpload.Initiated) > 0 { uploadIDs = append(uploadIDs, mpUpload.UploadID)
latestUpload = mpUpload
}
} }
} }
// Return the latest upload id. // Return the latest upload id.
return latestUpload.UploadID, nil return uploadIDs, nil
} }
// getTotalMultipartSize - calculate total uploaded size for the a given multipart object. // getTotalMultipartSize - calculate total uploaded size for the a given multipart object.

6
vendor/github.com/minio/minio-go/api-put-object.go сгенерированный поставляемый
Просмотреть файл

@@ -28,7 +28,7 @@ import (
"github.com/minio/minio-go/pkg/encrypt" "github.com/minio/minio-go/pkg/encrypt"
"github.com/minio/minio-go/pkg/s3utils" "github.com/minio/minio-go/pkg/s3utils"
"golang.org/x/net/lex/httplex" "golang.org/x/net/http/httpguts"
) )
// PutObjectOptions represents options specified by user for PutObject call // PutObjectOptions represents options specified by user for PutObject call
@@ -101,10 +101,10 @@ func (opts PutObjectOptions) Header() (header http.Header) {
// validate() checks if the UserMetadata map has standard headers or and raises an error if so. // validate() checks if the UserMetadata map has standard headers or and raises an error if so.
func (opts PutObjectOptions) validate() (err error) { func (opts PutObjectOptions) validate() (err error) {
for k, v := range opts.UserMetadata { for k, v := range opts.UserMetadata {
if !httplex.ValidHeaderFieldName(k) || isStandardHeader(k) || isSSEHeader(k) || isStorageClassHeader(k) { if !httpguts.ValidHeaderFieldName(k) || isStandardHeader(k) || isSSEHeader(k) || isStorageClassHeader(k) {
return ErrInvalidArgument(k + " unsupported user defined metadata name") return ErrInvalidArgument(k + " unsupported user defined metadata name")
} }
if !httplex.ValidHeaderFieldValue(v) { if !httpguts.ValidHeaderFieldValue(v) {
return ErrInvalidArgument(v + " unsupported user defined metadata value") return ErrInvalidArgument(v + " unsupported user defined metadata value")
} }
} }

10
vendor/github.com/minio/minio-go/api-remove.go сгенерированный поставляемый
Просмотреть файл

@@ -233,18 +233,20 @@ func (c Client) RemoveIncompleteUpload(bucketName, objectName string) error {
if err := s3utils.CheckValidObjectName(objectName); err != nil { if err := s3utils.CheckValidObjectName(objectName); err != nil {
return err return err
} }
// Find multipart upload id of the object to be aborted. // Find multipart upload ids of the object to be aborted.
uploadID, err := c.findUploadID(bucketName, objectName) uploadIDs, err := c.findUploadIDs(bucketName, objectName)
if err != nil { if err != nil {
return err return err
} }
if uploadID != "" {
// Upload id found, abort the incomplete multipart upload. for _, uploadID := range uploadIDs {
// abort incomplete multipart upload, based on the upload id passed.
err := c.abortMultipartUpload(context.Background(), bucketName, objectName, uploadID) err := c.abortMultipartUpload(context.Background(), bucketName, objectName, uploadID)
if err != nil { if err != nil {
return err return err
} }
} }
return nil return nil
} }

2
vendor/github.com/minio/minio-go/api.go сгенерированный поставляемый
Просмотреть файл

@@ -99,7 +99,7 @@ type Options struct {
// Global constants. // Global constants.
const ( const (
libraryName = "minio-go" libraryName = "minio-go"
libraryVersion = "6.0.1" libraryVersion = "v6.0.3"
) )
// User Agent should always following the below style. // User Agent should always following the below style.

6
vendor/github.com/minio/minio-go/core.go сгенерированный поставляемый
Просмотреть файл

@@ -48,9 +48,9 @@ func (c Core) ListObjects(bucket, prefix, marker, delimiter string, maxKeys int)
} }
// ListObjectsV2 - Lists all the objects at a prefix, similar to ListObjects() but uses // ListObjectsV2 - Lists all the objects at a prefix, similar to ListObjects() but uses
// continuationToken instead of marker to further filter the results. // continuationToken instead of marker to support iteration over the results.
func (c Core) ListObjectsV2(bucketName, objectPrefix, continuationToken string, fetchOwner bool, delimiter string, maxkeys int) (ListBucketV2Result, error) { func (c Core) ListObjectsV2(bucketName, objectPrefix, continuationToken string, fetchOwner bool, delimiter string, maxkeys int, startAfter string) (ListBucketV2Result, error) {
return c.listObjectsV2Query(bucketName, objectPrefix, continuationToken, fetchOwner, delimiter, maxkeys) return c.listObjectsV2Query(bucketName, objectPrefix, continuationToken, fetchOwner, delimiter, maxkeys, startAfter)
} }
// CopyObject - copies an object from source object to destination object on server side. // CopyObject - copies an object from source object to destination object on server side.

44
vendor/github.com/minio/minio-go/functional_tests.go сгенерированный поставляемый
Просмотреть файл

@@ -2623,8 +2623,14 @@ func testCopyObject() {
return return
} }
oi, err := c.StatObject(bucketName, objectName, minio.StatObjectOptions{})
if err != nil {
logError(testName, function, args, startTime, "", "StatObject failed", err)
return
}
stOpts := minio.StatObjectOptions{} stOpts := minio.StatObjectOptions{}
stOpts.SetMatchETag(objInfo.ETag) stOpts.SetMatchETag(oi.ETag)
objInfo, err = c.StatObject(bucketName, objectName, stOpts) objInfo, err = c.StatObject(bucketName, objectName, stOpts)
if err != nil { if err != nil {
logError(testName, function, args, startTime, "", "CopyObject ETag should match and not fail", err) logError(testName, function, args, startTime, "", "CopyObject ETag should match and not fail", err)
@@ -3491,15 +3497,11 @@ func testFunctional() {
args = map[string]interface{}{ args = map[string]interface{}{
"bucketName": bucketName, "bucketName": bucketName,
} }
readOnlyPolicyRet, err := c.GetBucketPolicy(bucketName) _, err = c.GetBucketPolicy(bucketName)
if err != nil { if err != nil {
logError(testName, function, args, startTime, "", "GetBucketPolicy failed", err) logError(testName, function, args, startTime, "", "GetBucketPolicy failed", err)
return return
} }
if readOnlyPolicyRet == "" {
logError(testName, function, args, startTime, "", "policy should be set", err)
return
}
// Make the bucket 'public writeonly'. // Make the bucket 'public writeonly'.
function = "SetBucketPolicy(bucketName, writeOnlyPolicy)" function = "SetBucketPolicy(bucketName, writeOnlyPolicy)"
@@ -3523,17 +3525,12 @@ func testFunctional() {
"bucketName": bucketName, "bucketName": bucketName,
} }
writeOnlyPolicyRet, err := c.GetBucketPolicy(bucketName) _, err = c.GetBucketPolicy(bucketName)
if err != nil { if err != nil {
logError(testName, function, args, startTime, "", "GetBucketPolicy failed", err) logError(testName, function, args, startTime, "", "GetBucketPolicy failed", err)
return return
} }
if writeOnlyPolicyRet == "" {
logError(testName, function, args, startTime, "", "policy should be set", err)
return
}
// Make the bucket 'public read/write'. // Make the bucket 'public read/write'.
function = "SetBucketPolicy(bucketName, readWritePolicy)" function = "SetBucketPolicy(bucketName, readWritePolicy)"
functionAll += ", " + function functionAll += ", " + function
@@ -3556,17 +3553,12 @@ func testFunctional() {
args = map[string]interface{}{ args = map[string]interface{}{
"bucketName": bucketName, "bucketName": bucketName,
} }
readWritePolicyRet, err := c.GetBucketPolicy(bucketName) _, err = c.GetBucketPolicy(bucketName)
if err != nil { if err != nil {
logError(testName, function, args, startTime, "", "GetBucketPolicy failed", err) logError(testName, function, args, startTime, "", "GetBucketPolicy failed", err)
return return
} }
if readWritePolicyRet == "" {
logError(testName, function, args, startTime, "", "policy should be set", err)
return
}
// List all buckets. // List all buckets.
function = "ListBuckets()" function = "ListBuckets()"
functionAll += ", " + function functionAll += ", " + function
@@ -7389,12 +7381,12 @@ func testListObjects() {
return return
} }
if objInfo.Key == objectName1 && objInfo.StorageClass != "STANDARD" { if objInfo.Key == objectName1 && objInfo.StorageClass != "STANDARD" {
logError(testName, function, args, startTime, "", "ListObjects doesn't return expected storage class", err) // Ignored as Gateways (Azure/GCS etc) wont return storage class
return ignoredLog(testName, function, args, startTime, "ListObjects doesn't return expected storage class").Info()
} }
if objInfo.Key == objectName2 && objInfo.StorageClass != "REDUCED_REDUNDANCY" { if objInfo.Key == objectName2 && objInfo.StorageClass != "REDUCED_REDUNDANCY" {
logError(testName, function, args, startTime, "", "ListObjects doesn't return expected storage class", err) // Ignored as Gateways (Azure/GCS etc) wont return storage class
return ignoredLog(testName, function, args, startTime, "ListObjects doesn't return expected storage class").Info()
} }
} }
@@ -7405,12 +7397,12 @@ func testListObjects() {
return return
} }
if objInfo.Key == objectName1 && objInfo.StorageClass != "STANDARD" { if objInfo.Key == objectName1 && objInfo.StorageClass != "STANDARD" {
logError(testName, function, args, startTime, "", "ListObjectsV2 doesn't return expected storage class", err) // Ignored as Gateways (Azure/GCS etc) wont return storage class
return ignoredLog(testName, function, args, startTime, "ListObjectsV2 doesn't return expected storage class").Info()
} }
if objInfo.Key == objectName2 && objInfo.StorageClass != "REDUCED_REDUNDANCY" { if objInfo.Key == objectName2 && objInfo.StorageClass != "REDUCED_REDUNDANCY" {
logError(testName, function, args, startTime, "", "ListObjectsV2 doesn't return expected storage class", err) // Ignored as Gateways (Azure/GCS etc) wont return storage class
return ignoredLog(testName, function, args, startTime, "ListObjectsV2 doesn't return expected storage class").Info()
} }
} }

46
vendor/github.com/mitchellh/go-homedir/homedir.go сгенерированный поставляемый
Просмотреть файл

@@ -77,33 +77,51 @@ func Expand(path string) (string, error) {
} }
func dirUnix() (string, error) { func dirUnix() (string, error) {
homeEnv := "HOME"
if runtime.GOOS == "plan9" {
// On plan9, env vars are lowercase.
homeEnv = "home"
}
// First prefer the HOME environmental variable // First prefer the HOME environmental variable
if home := os.Getenv("HOME"); home != "" { if home := os.Getenv(homeEnv); home != "" {
return home, nil return home, nil
} }
// If that fails, try getent
var stdout bytes.Buffer var stdout bytes.Buffer
cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid()))
cmd.Stdout = &stdout // If that fails, try OS specific commands
if err := cmd.Run(); err != nil { if runtime.GOOS == "darwin" {
// If the error is ErrNotFound, we ignore it. Otherwise, return it. cmd := exec.Command("sh", "-c", `dscl -q . -read /Users/"$(whoami)" NFSHomeDirectory | sed 's/^[^ ]*: //'`)
if err != exec.ErrNotFound { cmd.Stdout = &stdout
return "", err if err := cmd.Run(); err == nil {
result := strings.TrimSpace(stdout.String())
if result != "" {
return result, nil
}
} }
} else { } else {
if passwd := strings.TrimSpace(stdout.String()); passwd != "" { cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid()))
// username:password:uid:gid:gecos:home:shell cmd.Stdout = &stdout
passwdParts := strings.SplitN(passwd, ":", 7) if err := cmd.Run(); err != nil {
if len(passwdParts) > 5 { // If the error is ErrNotFound, we ignore it. Otherwise, return it.
return passwdParts[5], nil if err != exec.ErrNotFound {
return "", err
}
} else {
if passwd := strings.TrimSpace(stdout.String()); passwd != "" {
// username:password:uid:gid:gecos:home:shell
passwdParts := strings.SplitN(passwd, ":", 7)
if len(passwdParts) > 5 {
return passwdParts[5], nil
}
} }
} }
} }
// If all else fails, try the shell // If all else fails, try the shell
stdout.Reset() stdout.Reset()
cmd = exec.Command("sh", "-c", "cd && pwd") cmd := exec.Command("sh", "-c", "cd && pwd")
cmd.Stdout = &stdout cmd.Stdout = &stdout
if err := cmd.Run(); err != nil { if err := cmd.Run(); err != nil {
return "", err return "", err

5
vendor/github.com/pelletier/go-toml/.travis.yml сгенерированный поставляемый
Просмотреть файл

@@ -1,8 +1,9 @@
sudo: false sudo: false
language: go language: go
go: go:
- 1.8.5 - 1.8.x
- 1.9.2 - 1.9.x
- 1.10.x
- tip - tip
matrix: matrix:
allow_failures: allow_failures:

15
vendor/github.com/pelletier/go-toml/marshal.go сгенерированный поставляемый
Просмотреть файл

@@ -11,10 +11,13 @@ import (
"time" "time"
) )
const tagKeyMultiline = "multiline"
type tomlOpts struct { type tomlOpts struct {
name string name string
comment string comment string
commented bool commented bool
multiline bool
include bool include bool
omitempty bool omitempty bool
} }
@@ -187,7 +190,7 @@ func (e *Encoder) QuoteMapKeys(v bool) *Encoder {
// A = [ // A = [
// 1, // 1,
// 2, // 2,
// 3 // 3,
// ] // ]
func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder { func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder {
e.arraysOneElementPerLine = v e.arraysOneElementPerLine = v
@@ -230,7 +233,12 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er
if err != nil { if err != nil {
return nil, err return nil, err
} }
tval.SetWithComment(opts.name, opts.comment, opts.commented, val)
tval.SetWithOptions(opts.name, SetOptions{
Comment: opts.comment,
Commented: opts.commented,
Multiline: opts.multiline,
}, val)
} }
} }
case reflect.Map: case reflect.Map:
@@ -559,7 +567,8 @@ func tomlOptions(vf reflect.StructField) tomlOpts {
comment = c comment = c
} }
commented, _ := strconv.ParseBool(vf.Tag.Get("commented")) commented, _ := strconv.ParseBool(vf.Tag.Get("commented"))
result := tomlOpts{name: vf.Name, comment: comment, commented: commented, include: true, omitempty: false} multiline, _ := strconv.ParseBool(vf.Tag.Get(tagKeyMultiline))
result := tomlOpts{name: vf.Name, comment: comment, commented: commented, multiline: multiline, include: true, omitempty: false}
if parse[0] != "" { if parse[0] != "" {
if parse[0] == "-" && len(parse) == 1 { if parse[0] == "-" && len(parse) == 1 {
result.include = false result.include = false

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше