mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 22:49:58 +00:00
STOR-519: Add db-connect, a SQL over HTTPS server
This commit is contained in:
2
vendor/github.com/xo/dburl/.gitignore
generated
vendored
Normal file
2
vendor/github.com/xo/dburl/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
example/example
|
||||
coverage.out
|
10
vendor/github.com/xo/dburl/.travis.yml
generated
vendored
Normal file
10
vendor/github.com/xo/dburl/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.10.x
|
||||
- 1.11.x
|
||||
- tip
|
||||
before_install:
|
||||
- go get github.com/mattn/goveralls
|
||||
script:
|
||||
- go test -v -coverprofile=coverage.out
|
||||
- goveralls -service=travis-ci -coverprofile=coverage.out
|
21
vendor/github.com/xo/dburl/LICENSE
generated
vendored
Normal file
21
vendor/github.com/xo/dburl/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2016 Kenneth Shaw
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
211
vendor/github.com/xo/dburl/README.md
generated
vendored
Normal file
211
vendor/github.com/xo/dburl/README.md
generated
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
# About dburl
|
||||
|
||||
Package dburl provides a standard, URL style mechanism for parsing and
|
||||
opening SQL database connection strings for [Go](https://golang.org/project),
|
||||
supporting standard URLs for the standard databases PostgreSQL, MySQL, SQLite3,
|
||||
Oracle, Microsoft SQL Server, and most other databases with a publicly
|
||||
available Go driver.
|
||||
|
||||
## Database URL Connection Strings
|
||||
|
||||
Supported database URLs are of the form:
|
||||
|
||||
```
|
||||
protocol+transport://user:pass@host/dbname?opt1=a&opt2=b
|
||||
protocol:/path/to/file
|
||||
```
|
||||
|
||||
Where:
|
||||
|
||||
| Component | Description |
|
||||
|--------------------|--------------------------------------------------------------------------------------|
|
||||
| protocol | driver name or alias (see below) |
|
||||
| transport | "tcp", "udp", "unix" or driver name (odbc/oleodbc) |
|
||||
| user | username |
|
||||
| pass | password |
|
||||
| host | host |
|
||||
| dbname<sup>*</sup> | database, instance, or service name/ID to connect to |
|
||||
| ?opt1=... | additional database driver options (see respective SQL driver for available options) |
|
||||
|
||||
<i><sup><b>*</b></sup> for Microsoft SQL Server, the syntax to supply an
|
||||
instance and database name is `/instance/dbname`, where `/instance` is
|
||||
optional. For Oracle databases, `/dbname` is the unique database ID (SID).
|
||||
Please see below for examples.</i>
|
||||
|
||||
## Quickstart
|
||||
|
||||
Database connection URLs (as described below) can be parsed with `Parse` as such:
|
||||
|
||||
```go
|
||||
u, err := dburl.Parse("postgresql://user:pass@localhost/mydatabase/?sslmode=disable")
|
||||
if err != nil { /* ... */ }
|
||||
```
|
||||
|
||||
Additionally, a simple helper func `Open`, is available to quickly parse, open,
|
||||
and return a standard SQL database connection:
|
||||
|
||||
```go
|
||||
db, err := dburl.Open("sqlite:mydatabase.sqlite3?loc=auto")
|
||||
if err != nil { /* ... */ }
|
||||
```
|
||||
|
||||
## Example URLs ##
|
||||
|
||||
The following are URLs that can be handled with a call to `Open` or `Parse`:
|
||||
|
||||
```
|
||||
postgres://user:pass@localhost/dbname
|
||||
pg://user:pass@localhost/dbname?sslmode=disable
|
||||
mysql://user:pass@localhost/dbname
|
||||
mysql:/var/run/mysqld/mysqld.sock
|
||||
sqlserver://user:pass@remote-host.com/dbname
|
||||
mssql://user:pass@remote-host.com/instance/dbname
|
||||
ms://user:pass@remote-host.com:port/instance/dbname?keepAlive=10
|
||||
oracle://user:pass@somehost.com/oracledb
|
||||
sap://user:pass@localhost/dbname
|
||||
sqlite:/path/to/file.db
|
||||
file:myfile.sqlite3?loc=auto
|
||||
odbc+postgres://user:pass@localhost:port/dbname?option1=
|
||||
```
|
||||
|
||||
## Protocol Schemes and Aliases
|
||||
|
||||
The following protocols schemes (ie, driver) and their associated aliases are
|
||||
supported out of the box:
|
||||
|
||||
| Database (scheme/driver) | Protocol Aliases [real driver] |
|
||||
|------------------------------|---------------------------------------|
|
||||
| Microsoft SQL Server (mssql) | ms, sqlserver |
|
||||
| MySQL (mysql) | my, mariadb, maria, percona, aurora |
|
||||
| Oracle (ora) | or, oracle, oci8, oci |
|
||||
| PostgreSQL (postgres) | pg, postgresql, pgsql |
|
||||
| SQLite3 (sqlite3) | sq, sqlite, file |
|
||||
| | |
|
||||
| Amazon Redshift (redshift) | rs [postgres] |
|
||||
| CockroachDB (cockroachdb) | cr, cockroach, crdb, cdb [postgres] |
|
||||
| MemSQL (memsql) | me [mysql] |
|
||||
| TiDB (tidb) | ti [mysql] |
|
||||
| Vitess (vitess) | vt [mysql] |
|
||||
| | |
|
||||
| Google Spanner (spanner) | gs, google, span (not yet public) |
|
||||
| | |
|
||||
| MySQL (mymysql) | zm, mymy |
|
||||
| PostgreSQL (pgx) | px |
|
||||
| | |
|
||||
| Apache Avatica (avatica) | av, phoenix |
|
||||
| Apache Ignite (ignite) | ig, gridgain |
|
||||
| Cassandra (cql) | ca, cassandra, datastax, scy, scylla |
|
||||
| ClickHouse (clickhouse) | ch |
|
||||
| Couchbase (n1ql) | n1, couchbase |
|
||||
| Cznic QL (ql) | ql, cznic, cznicql |
|
||||
| Firebird SQL (firebirdsql) | fb, firebird |
|
||||
| Microsoft ADODB (adodb) | ad, ado |
|
||||
| ODBC (odbc) | od |
|
||||
| OLE ODBC (oleodbc) | oo, ole, oleodbc [adodb] |
|
||||
| Presto (presto) | pr, prestodb, prestos, prs, prestodbs |
|
||||
| SAP ASE (tds) | ax, ase, sapase |
|
||||
| SAP HANA (hdb) | sa, saphana, sap, hana |
|
||||
| Snowflake (snowflake) | sf |
|
||||
| VoltDB (voltdb) | vo, volt, vdb |
|
||||
|
||||
Any protocol scheme `alias://` can be used in place of `protocol://`, and will work
|
||||
identically with `Parse`/`Open`.
|
||||
|
||||
## Installation
|
||||
|
||||
Install in the usual Go fashion:
|
||||
|
||||
```sh
|
||||
go get -u github.com/xo/dburl
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Please note that the dburl package does not import actual SQL drivers, and only
|
||||
provides a standard way to parse/open respective database connection URLs.
|
||||
|
||||
For reference, these are the following "expected" SQL drivers that would need
|
||||
to be imported:
|
||||
|
||||
| Database (driver) | Package |
|
||||
|------------------------------|---------------------------------------------------------------------------------------------|
|
||||
| Microsoft SQL Server (mssql) | [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb) |
|
||||
| MySQL (mysql) | [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) |
|
||||
| Oracle (ora) | [gopkg.in/rana/ora.v4](https://gopkg.in/rana/ora.v4) |
|
||||
| PostgreSQL (postgres) | [github.com/lib/pq](https://github.com/lib/pq) |
|
||||
| SQLite3 (sqlite3) | [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) |
|
||||
| | |
|
||||
| Amazon Redshift (redshift) | [github.com/lib/pq](https://github.com/lib/pq) |
|
||||
| CockroachDB (cockroachdb) | [github.com/lib/pq](https://github.com/lib/pq) |
|
||||
| MemSQL (memsql) | [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) |
|
||||
| TiDB (tidb) | [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) |
|
||||
| Vitess (vitess) | [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) |
|
||||
| | |
|
||||
| Google Spanner (spanner) | github.com/xo/spanner (not yet public) |
|
||||
| | |
|
||||
| MySQL (mymysql) | [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql) |
|
||||
| PostgreSQL (pgx) | [github.com/jackc/pgx/stdlib](https://github.com/jackc/pgx) |
|
||||
| | |
|
||||
| Apache Avatica (avatica) | [github.com/Boostport/avatica](https://github.com/Boostport/avatica) |
|
||||
| Apache Ignite (ignite) | [github.com/amsokol/ignite-go-client/sql](https://github.com/amsokol/ignite-go-client) |
|
||||
| Cassandra (cql) | [github.com/MichaelS11/go-cql-driver](https://github.com/MichaelS11/go-cql-driver) |
|
||||
| ClickHouse (clickhouse) | [github.com/kshvakov/clickhouse](https://github.com/kshvakov/clickhouse) |
|
||||
| Couchbase (n1ql) | [github.com/couchbase/go_n1ql](https://github.com/couchbase/go_n1ql) |
|
||||
| Cznic QL (ql) | [github.com/cznic/ql](https://github.com/cznic/ql) |
|
||||
| Firebird SQL (firebirdsql) | [github.com/nakagami/firebirdsql](https://github.com/nakagami/firebirdsql) |
|
||||
| Microsoft ADODB (adodb) | [github.com/mattn/go-adodb](https://github.com/mattn/go-adodb) |
|
||||
| ODBC (odbc) | [github.com/alexbrainman/odbc](https://github.com/alexbrainman/odbc) |
|
||||
| OLE ODBC (oleodbc) | [github.com/mattn/go-adodb](https://github.com/mattn/go-adodb) |
|
||||
| Presto (presto) | [github.com/prestodb/presto-go-client/presto](https://github.com/prestodb/presto-go-client) |
|
||||
| SAP ASE (tds) | [github.com/thda/tds](https://github.com/thda/tds) |
|
||||
| SAP HANA (hdb) | [github.com/SAP/go-hdb/driver](https://github.com/SAP/go-hdb) |
|
||||
| Snowflake (snowflake) | [github.com/snowflakedb/gosnowflake](https://github.com/snowflakedb/gosnowflake) |
|
||||
| VoltDB (voltdb) | [github.com/VoltDB/voltdb-client-go/voltdbclient](github.com/VoltDB/voltdb-client-go]) |
|
||||
|
||||
Please see [the GoDoc API page](http://godoc.org/github.com/xo/dburl) for a
|
||||
full API listing.
|
||||
|
||||
### URL Parsing Rules
|
||||
|
||||
`Parse` and `Open` rely heavily on the standard `net/url.URL` type, as such
|
||||
parsing rules have the same conventions/semantics as any URL parsed by the
|
||||
standard library's `net/url.Parse`.
|
||||
|
||||
## Full Example
|
||||
|
||||
A full example for reference:
|
||||
|
||||
```go
|
||||
// _example/example.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
_ "github.com/denisenkom/go-mssqldb"
|
||||
"github.com/xo/dburl"
|
||||
)
|
||||
|
||||
func main() {
|
||||
db, err := dburl.Open("sqlserver://user:pass@localhost/dbname")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var name string
|
||||
err = db.QueryRow(`SELECT name FROM mytable WHERE id=10`).Scan(&name)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Printf(">> got: %s\n", name)
|
||||
}
|
||||
```
|
||||
|
||||
## Related Projects
|
||||
|
||||
The dburl package was built primarily to support these projects:
|
||||
|
||||
* [usql](https://github.com/xo/usql) - a universal command-line interface for SQL databases
|
||||
* [xo](https://github.com/xo/xo) - a command-line tool to generate Go code from a database schema
|
206
vendor/github.com/xo/dburl/dburl.go
generated
vendored
Normal file
206
vendor/github.com/xo/dburl/dburl.go
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
// Package dburl provides a standard, URL style mechanism for parsing and
|
||||
// opening SQL database connection strings.
|
||||
//
|
||||
// Database URL Connection Strings
|
||||
//
|
||||
// Supported database URLs are of the form:
|
||||
//
|
||||
// protocol+transport://user:pass@host/dbname?opt1=a&opt2=b
|
||||
// protocol:/path/to/file
|
||||
//
|
||||
// Where:
|
||||
//
|
||||
// protocol - driver name or alias (see below)
|
||||
// transport - "tcp", "udp", "unix" or driver name (odbc/oleodbc) |
|
||||
// user - username
|
||||
// pass - password
|
||||
// host - host
|
||||
// dbname* - database, instance, or service name/id to connect to
|
||||
// ?opt1=... - additional database driver options
|
||||
// (see respective SQL driver for available options)
|
||||
//
|
||||
// * for Microsoft SQL Server, the syntax to supply an instance and database
|
||||
// name is /instance/dbname, where /instance is optional. For Oracle databases,
|
||||
// /dbname is the unique database ID (SID). Please see below for examples.
|
||||
//
|
||||
// Quickstart
|
||||
//
|
||||
// URLs in the above format can be parsed with Parse as such:
|
||||
//
|
||||
// u, err := dburl.Parse("postgresql://user:pass@localhost/mydatabase/?sslmode=disable")
|
||||
// if err != nil { /* ... */ }
|
||||
//
|
||||
// Additionally, a simple helper func, Open, is available to quickly parse,
|
||||
// open, and return a standard SQL database connection:
|
||||
//
|
||||
// db, err := dburl.Open("sqlite:mydatabase.sqlite3?loc=auto")
|
||||
// if err != nil { /* ... */ }
|
||||
//
|
||||
// Example URLs
|
||||
//
|
||||
// The following are URLs that can be handled with a call to Open or Parse:
|
||||
//
|
||||
// postgres://user:pass@localhost/dbname
|
||||
// pg://user:pass@localhost/dbname?sslmode=disable
|
||||
// mysql://user:pass@localhost/dbname
|
||||
// mysql:/var/run/mysqld/mysqld.sock
|
||||
// sqlserver://user:pass@remote-host.com/dbname
|
||||
// mssql://user:pass@remote-host.com/instance/dbname
|
||||
// ms://user:pass@remote-host.com:port/instance/dbname?keepAlive=10
|
||||
// oracle://user:pass@somehost.com/oracledb
|
||||
// sap://user:pass@localhost/dbname
|
||||
// sqlite:/path/to/file.db
|
||||
// file:myfile.sqlite3?loc=auto
|
||||
// odbc+postgres://user:pass@localhost:port/dbname?option1=
|
||||
//
|
||||
// Protocol Schemes and Aliases
|
||||
//
|
||||
// The following protocols schemes (ie, driver) and their associated aliases
|
||||
// are supported out of the box:
|
||||
//
|
||||
// Database (scheme/driver) | Protocol Aliases [real driver]
|
||||
// -----------------------------|-------------------------------------------
|
||||
// Microsoft SQL Server (mssql) | ms, sqlserver
|
||||
// MySQL (mysql) | my, mariadb, maria, percona, aurora
|
||||
// Oracle (ora) | or, oracle, oci8, oci
|
||||
// PostgreSQL (postgres) | pg, postgresql, pgsql
|
||||
// SQLite3 (sqlite3) | sq, sqlite, file
|
||||
// -----------------------------|-------------------------------------------
|
||||
// Amazon Redshift (redshift) | rs [postgres]
|
||||
// CockroachDB (cockroachdb) | cr, cockroach, crdb, cdb [postgres]
|
||||
// MemSQL (memsql) | me [mysql]
|
||||
// TiDB (tidb) | ti [mysql]
|
||||
// Vitess (vitess) | vt [mysql]
|
||||
// -----------------------------|-------------------------------------------
|
||||
// Google Spanner (spanner) | gs, google, span (not yet public)
|
||||
// -----------------------------|-------------------------------------------
|
||||
// MySQL (mymysql) | zm, mymy
|
||||
// PostgreSQL (pgx) | px
|
||||
// -----------------------------|-------------------------------------------
|
||||
// Apache Avatica (avatica) | av, phoenix
|
||||
// Apache Ignite (ignite) | ig, gridgain
|
||||
// Cassandra (cql) | ca, cassandra, datastax, scy, scylla
|
||||
// ClickHouse (clickhouse) | ch
|
||||
// Couchbase (n1ql) | n1, couchbase
|
||||
// Cznic QL (ql) | ql, cznic, cznicql
|
||||
// Firebird SQL (firebirdsql) | fb, firebird
|
||||
// Microsoft ADODB (adodb) | ad, ado
|
||||
// ODBC (odbc) | od
|
||||
// OLE ODBC (oleodbc) | oo, ole, oleodbc [adodb]
|
||||
// Presto (presto) | pr, prestodb, prestos, prs, prestodbs
|
||||
// SAP ASE (tds) | ax, ase, sapase
|
||||
// SAP HANA (hdb) | sa, saphana, sap, hana
|
||||
// Snowflake (snowflake) | sf
|
||||
// VoltDB (voltdb) | vo, volt, vdb
|
||||
//
|
||||
// Any protocol scheme alias:// can be used in place of protocol://, and will
|
||||
// work identically with Parse/Open.
|
||||
//
|
||||
// Usage
|
||||
//
|
||||
// Please note that the dburl package does not import actual SQL drivers, and
|
||||
// only provides a standard way to parse/open respective database connection URLs.
|
||||
//
|
||||
// For reference, these are the following "expected" SQL drivers that would need
|
||||
// to be imported:
|
||||
//
|
||||
// Database (scheme/driver) | Package
|
||||
// -----------------------------|-------------------------------------------------
|
||||
// Microsoft SQL Server (mssql) | github.com/denisenkom/go-mssqldb
|
||||
// MySQL (mysql) | github.com/go-sql-driver/mysql
|
||||
// Oracle (ora) | gopkg.in/rana/ora.v4
|
||||
// PostgreSQL (postgres) | github.com/lib/pq
|
||||
// SQLite3 (sqlite3) | github.com/mattn/go-sqlite3
|
||||
// -----------------------------|-------------------------------------------------
|
||||
// Amazon Redshift (redshift) | github.com/lib/pq
|
||||
// CockroachDB (cockroachdb) | github.com/lib/pq
|
||||
// MemSQL (memsql) | github.com/go-sql-driver/mysql
|
||||
// TiDB (tidb) | github.com/go-sql-driver/mysql
|
||||
// Vitess (vitess) | github.com/go-sql-driver/mysql
|
||||
// -----------------------------|-------------------------------------------------
|
||||
// Google Spanner (spanner) | github.com/xo/spanner (not yet public)
|
||||
// -----------------------------|-------------------------------------------------
|
||||
// MySQL (mymysql) | github.com/ziutek/mymysql/godrv
|
||||
// PostgreSQL (pgx) | github.com/jackc/pgx/stdlib
|
||||
// -----------------------------|-------------------------------------------------
|
||||
// Apache Avatica (avatica) | github.com/Boostport/avatica
|
||||
// Apache Ignite (ignite) | github.com/amsokol/ignite-go-client/sql
|
||||
// Cassandra (cql) | github.com/MichaelS11/go-cql-driver
|
||||
// ClickHouse (clickhouse) | github.com/kshvakov/clickhouse
|
||||
// Couchbase (n1ql) | github.com/couchbase/go_n1ql
|
||||
// Cznic QL (ql) | github.com/cznic/ql
|
||||
// Firebird SQL (firebirdsql) | github.com/nakagami/firebirdsql
|
||||
// Microsoft ADODB (adodb) | github.com/mattn/go-adodb
|
||||
// ODBC (odbc) | github.com/alexbrainman/odbc
|
||||
// OLE ODBC (oleodbc)* | github.com/mattn/go-adodb
|
||||
// Presto (presto) | github.com/prestodb/presto-go-client
|
||||
// SAP ASE (tds) | github.com/thda/tds
|
||||
// SAP HANA (hdb) | github.com/SAP/go-hdb/driver
|
||||
// Snowflake (snowflake) | github.com/snowflakedb/gosnowflake
|
||||
// VoltDB (voltdb) | github.com/VoltDB/voltdb-client-go/voltdbclient
|
||||
//
|
||||
// * OLE ODBC is not an actual protocol, but instead is an alias for using the
|
||||
// "MSDASQL.1" OLE provider with the ADODB driver, and the DSN will be an
|
||||
// ADODB DSN, but with "Extended Properties" for the respective ODBC
|
||||
// parameters, including the underlying transport prootocol. As such,
|
||||
// "oleodbc+protocol://user:pass@host/dbname" URLs are equivalent to
|
||||
// "adodb://MSDASQL.1/?Extended+Properties=...". Please see the
|
||||
// documentation for GenOLEODBC for information regarding how URL components
|
||||
// are mapped/passed to ADODB's Extended Properties parameter.
|
||||
//
|
||||
// URL Parsing Rules
|
||||
//
|
||||
// Parse and Open rely heavily on the standard net/url.URL type, as such
|
||||
// parsing rules have the same conventions/semantics as any URL parsed by the
|
||||
// standard library's net/url.Parse.
|
||||
//
|
||||
// Related Projects
|
||||
//
|
||||
// This package was written mainly to support xo (https://github.com/xo/xo)
|
||||
// and usql (https://github.com/xo/usql).
|
||||
package dburl
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
// Error is a dburl error.
|
||||
type Error string
|
||||
|
||||
// Error satisfies the error interface.
|
||||
func (err Error) Error() string {
|
||||
return string(err)
|
||||
}
|
||||
|
||||
const (
|
||||
// ErrInvalidDatabaseScheme is the invalid database scheme error.
|
||||
ErrInvalidDatabaseScheme Error = "invalid database scheme"
|
||||
|
||||
// ErrUnknownDatabaseScheme is the unknown database type error.
|
||||
ErrUnknownDatabaseScheme Error = "unknown database scheme"
|
||||
|
||||
// ErrInvalidTransportProtocol is the invalid transport protocol error.
|
||||
ErrInvalidTransportProtocol Error = "invalid transport protocol"
|
||||
|
||||
// ErrRelativePathNotSupported is the relative paths not supported error.
|
||||
ErrRelativePathNotSupported Error = "relative path not supported"
|
||||
|
||||
// ErrMissingHost is the missing host error.
|
||||
ErrMissingHost Error = "missing host"
|
||||
|
||||
// ErrMissingPath is the missing path error.
|
||||
ErrMissingPath Error = "missing path"
|
||||
)
|
||||
|
||||
// Open takes a urlstr like "protocol+transport://user:pass@host/dbname?option1=a&option2=b"
|
||||
// and creates a standard sql.DB connection.
|
||||
//
|
||||
// See Parse for information on formatting URLs to work properly with Open.
|
||||
func Open(urlstr string) (*sql.DB, error) {
|
||||
u, err := Parse(urlstr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sql.Open(u.Driver, u.DSN)
|
||||
}
|
596
vendor/github.com/xo/dburl/dsn.go
generated
vendored
Normal file
596
vendor/github.com/xo/dburl/dsn.go
generated
vendored
Normal file
@@ -0,0 +1,596 @@
|
||||
package dburl
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
stdpath "path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GenScheme returns a func that generates a scheme:// style DSN from the
|
||||
// passed URL.
|
||||
func GenScheme(scheme string) func(*URL) (string, error) {
|
||||
return func(u *URL) (string, error) {
|
||||
z := &url.URL{
|
||||
Scheme: scheme,
|
||||
Opaque: u.Opaque,
|
||||
User: u.User,
|
||||
Host: u.Host,
|
||||
Path: u.Path,
|
||||
RawPath: u.RawPath,
|
||||
RawQuery: u.RawQuery,
|
||||
Fragment: u.Fragment,
|
||||
}
|
||||
|
||||
return z.String(), nil
|
||||
}
|
||||
}
|
||||
|
||||
// GenFromURL returns a func that generates a DSN using urlstr as the default
|
||||
// URL parameters, overriding the values only if when in the passed URL.
|
||||
func GenFromURL(urlstr string) func(*URL) (string, error) {
|
||||
z, err := url.Parse(urlstr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return func(u *URL) (string, error) {
|
||||
opaque := z.Opaque
|
||||
if u.Opaque != "" {
|
||||
opaque = u.Opaque
|
||||
}
|
||||
|
||||
user := z.User
|
||||
if u.User != nil {
|
||||
user = u.User
|
||||
}
|
||||
|
||||
host, port := hostname(z.Host), hostport(z.Host)
|
||||
if h := hostname(u.Host); h != "" {
|
||||
host = h
|
||||
}
|
||||
if p := hostport(u.Host); p != "" {
|
||||
port = p
|
||||
}
|
||||
if port != "" {
|
||||
host += ":" + port
|
||||
}
|
||||
|
||||
path := z.Path
|
||||
if u.Path != "" {
|
||||
path = u.Path
|
||||
}
|
||||
|
||||
rawPath := z.RawPath
|
||||
if u.RawPath != "" {
|
||||
rawPath = u.RawPath
|
||||
}
|
||||
|
||||
q := z.Query()
|
||||
for k, v := range u.Query() {
|
||||
q.Set(k, strings.Join(v, " "))
|
||||
}
|
||||
|
||||
fragment := z.Fragment
|
||||
if u.Fragment != "" {
|
||||
fragment = u.Fragment
|
||||
}
|
||||
|
||||
y := &url.URL{
|
||||
Scheme: z.Scheme,
|
||||
Opaque: opaque,
|
||||
User: user,
|
||||
Host: host,
|
||||
Path: path,
|
||||
RawPath: rawPath,
|
||||
RawQuery: q.Encode(),
|
||||
Fragment: fragment,
|
||||
}
|
||||
|
||||
return y.String(), nil
|
||||
}
|
||||
}
|
||||
|
||||
// GenOpaque generates a opaque file path DSN from the passed URL.
|
||||
func GenOpaque(u *URL) (string, error) {
|
||||
if u.Opaque == "" {
|
||||
return "", ErrMissingPath
|
||||
}
|
||||
|
||||
return u.Opaque + genQueryOptions(u.Query()), nil
|
||||
}
|
||||
|
||||
// GenPostgres generates a postgres DSN from the passed URL.
|
||||
func GenPostgres(u *URL) (string, error) {
|
||||
host, port, dbname := hostname(u.Host), hostport(u.Host), strings.TrimPrefix(u.Path, "/")
|
||||
if host == "." {
|
||||
return "", ErrRelativePathNotSupported
|
||||
}
|
||||
|
||||
// resolve path
|
||||
if u.Proto == "unix" {
|
||||
if host == "" {
|
||||
dbname = "/" + dbname
|
||||
}
|
||||
|
||||
host, port, dbname = resolveDir(stdpath.Join(host, dbname))
|
||||
}
|
||||
|
||||
q := u.Query()
|
||||
q.Set("host", host)
|
||||
q.Set("port", port)
|
||||
q.Set("dbname", dbname)
|
||||
|
||||
// add user/pass
|
||||
if u.User != nil {
|
||||
q.Set("user", u.User.Username())
|
||||
pass, _ := u.User.Password()
|
||||
q.Set("password", pass)
|
||||
}
|
||||
|
||||
// save host, port, dbname
|
||||
if u.hostPortDB == nil {
|
||||
u.hostPortDB = []string{host, port, dbname}
|
||||
}
|
||||
|
||||
return genOptions(q, "", "=", " ", ",", true), nil
|
||||
}
|
||||
|
||||
// GenSQLServer generates a mssql DSN from the passed URL.
|
||||
func GenSQLServer(u *URL) (string, error) {
|
||||
host, port, dbname := hostname(u.Host), hostport(u.Host), strings.TrimPrefix(u.Path, "/")
|
||||
|
||||
// add instance name to host if present
|
||||
if i := strings.Index(dbname, "/"); i != -1 {
|
||||
host = host + `\` + dbname[:i]
|
||||
dbname = dbname[i+1:]
|
||||
}
|
||||
|
||||
q := u.Query()
|
||||
q.Set("Server", host)
|
||||
q.Set("Port", port)
|
||||
q.Set("Database", dbname)
|
||||
|
||||
// add user/pass
|
||||
if u.User != nil {
|
||||
q.Set("User ID", u.User.Username())
|
||||
pass, _ := u.User.Password()
|
||||
q.Set("Password", pass)
|
||||
}
|
||||
|
||||
// save host, port, dbname
|
||||
if u.hostPortDB == nil {
|
||||
u.hostPortDB = []string{host, port, dbname}
|
||||
}
|
||||
|
||||
return genOptionsODBC(q, true), nil
|
||||
}
|
||||
|
||||
// // GenSybase generates a sqlany DSN from the passed URL.
|
||||
// func GenSybase(u *URL) (string, error) {
|
||||
// // of format "UID=DBA;PWD=sql;Host=demo12;DatabaseName=demo;ServerName=myserver"
|
||||
// host, port, dbname := hostname(u.Host), hostport(u.Host), strings.TrimPrefix(u.Path, "/")
|
||||
//
|
||||
// // add instance name to host if present
|
||||
// if i := strings.Index(dbname, "/"); i != -1 {
|
||||
// host = host + `\` + dbname[:i]
|
||||
// dbname = dbname[i+1:]
|
||||
// }
|
||||
//
|
||||
// q := u.Query()
|
||||
// q.Set("Host", host)
|
||||
// if port != "" {
|
||||
// q.Set("LINKS", "tcpip(PORT="+port+")")
|
||||
// }
|
||||
// q.Set("DatabaseName", dbname)
|
||||
//
|
||||
// // add user/pass
|
||||
// if u.User != nil {
|
||||
// q.Set("UID", u.User.Username())
|
||||
// pass, _ := u.User.Password()
|
||||
// q.Set("PWD", pass)
|
||||
// }
|
||||
//
|
||||
// // save host, port, dbname
|
||||
// if u.hostPortDB == nil {
|
||||
// u.hostPortDB = []string{host, port, dbname}
|
||||
// }
|
||||
//
|
||||
// return genOptionsODBC(q, true), nil
|
||||
// }
|
||||
|
||||
// GenMySQL generates a mysql DSN from the passed URL.
|
||||
func GenMySQL(u *URL) (string, error) {
|
||||
host, port, dbname := hostname(u.Host), hostport(u.Host), strings.TrimPrefix(u.Path, "/")
|
||||
|
||||
var dsn string
|
||||
|
||||
// build user/pass
|
||||
if u.User != nil {
|
||||
if un := u.User.Username(); len(un) > 0 {
|
||||
if up, ok := u.User.Password(); ok {
|
||||
un += ":" + up
|
||||
}
|
||||
dsn += un + "@"
|
||||
}
|
||||
}
|
||||
|
||||
// resolve path
|
||||
if u.Proto == "unix" {
|
||||
if host == "" {
|
||||
dbname = "/" + dbname
|
||||
}
|
||||
host, dbname = resolveSocket(stdpath.Join(host, dbname))
|
||||
port = ""
|
||||
}
|
||||
|
||||
// save host, port, dbname
|
||||
if u.hostPortDB == nil {
|
||||
u.hostPortDB = []string{host, port, dbname}
|
||||
}
|
||||
|
||||
// if host or proto is not empty
|
||||
if u.Proto != "unix" {
|
||||
if host == "" {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
if port == "" {
|
||||
port = "3306"
|
||||
}
|
||||
}
|
||||
if port != "" {
|
||||
port = ":" + port
|
||||
}
|
||||
|
||||
dsn += u.Proto + "(" + host + port + ")"
|
||||
|
||||
// add database name
|
||||
dsn += "/" + dbname
|
||||
|
||||
return dsn + genQueryOptions(u.Query()), nil
|
||||
}
|
||||
|
||||
// GenMyMySQL generates a MyMySQL MySQL DSN from the passed URL.
|
||||
func GenMyMySQL(u *URL) (string, error) {
|
||||
host, port, dbname := hostname(u.Host), hostport(u.Host), strings.TrimPrefix(u.Path, "/")
|
||||
|
||||
// resolve path
|
||||
if u.Proto == "unix" {
|
||||
if host == "" {
|
||||
dbname = "/" + dbname
|
||||
}
|
||||
host, dbname = resolveSocket(stdpath.Join(host, dbname))
|
||||
port = ""
|
||||
}
|
||||
|
||||
// save host, port, dbname
|
||||
if u.hostPortDB == nil {
|
||||
u.hostPortDB = []string{host, port, dbname}
|
||||
}
|
||||
|
||||
// if host or proto is not empty
|
||||
if u.Proto != "unix" {
|
||||
if host == "" {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
if port == "" {
|
||||
port = "3306"
|
||||
}
|
||||
}
|
||||
if port != "" {
|
||||
port = ":" + port
|
||||
}
|
||||
|
||||
dsn := u.Proto + ":" + host + port
|
||||
|
||||
// add opts
|
||||
dsn += genOptions(
|
||||
convertOptions(u.Query(), "true", ""),
|
||||
",", "=", ",", " ", false,
|
||||
)
|
||||
|
||||
// add dbname
|
||||
dsn += "*" + dbname
|
||||
|
||||
// add user/pass
|
||||
if u.User != nil {
|
||||
pass, _ := u.User.Password()
|
||||
dsn += "/" + u.User.Username() + "/" + pass
|
||||
} else if strings.HasSuffix(dsn, "*") {
|
||||
dsn += "//"
|
||||
}
|
||||
|
||||
return dsn, nil
|
||||
}
|
||||
|
||||
// GenOracle generates a ora DSN from the passed URL.
|
||||
func GenOracle(u *URL) (string, error) {
|
||||
// create dsn
|
||||
dsn := u.Host + u.Path
|
||||
|
||||
// build user/pass
|
||||
var un string
|
||||
if u.User != nil {
|
||||
if un = u.User.Username(); len(un) > 0 {
|
||||
if up, ok := u.User.Password(); ok {
|
||||
un += "/" + up
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return un + "@" + dsn, nil
|
||||
}
|
||||
|
||||
// GenFirebird generates a firebirdsql DSN from the passed URL.
|
||||
func GenFirebird(u *URL) (string, error) {
|
||||
z := &url.URL{
|
||||
User: u.User,
|
||||
Host: u.Host,
|
||||
Path: u.Path,
|
||||
RawPath: u.RawPath,
|
||||
RawQuery: u.RawQuery,
|
||||
Fragment: u.Fragment,
|
||||
}
|
||||
return strings.TrimPrefix(z.String(), "//"), nil
|
||||
}
|
||||
|
||||
// GenADODB generates a adodb DSN from the passed URL.
|
||||
func GenADODB(u *URL) (string, error) {
|
||||
// grab data source
|
||||
host, port := hostname(u.Host), hostport(u.Host)
|
||||
dsname, dbname := strings.TrimPrefix(u.Path, "/"), ""
|
||||
if dsname == "" {
|
||||
dsname = "."
|
||||
}
|
||||
|
||||
// check if data source is not a path on disk
|
||||
if mode(dsname) == 0 {
|
||||
if i := strings.IndexAny(dsname, `\/`); i != -1 {
|
||||
dbname = dsname[i+1:]
|
||||
dsname = dsname[:i]
|
||||
}
|
||||
}
|
||||
|
||||
q := u.Query()
|
||||
q.Set("Provider", host)
|
||||
q.Set("Port", port)
|
||||
q.Set("Data Source", dsname)
|
||||
q.Set("Database", dbname)
|
||||
|
||||
// add user/pass
|
||||
if u.User != nil {
|
||||
q.Set("User ID", u.User.Username())
|
||||
pass, _ := u.User.Password()
|
||||
q.Set("Password", pass)
|
||||
}
|
||||
|
||||
// save host, port, dbname
|
||||
if u.hostPortDB == nil {
|
||||
n := dsname
|
||||
if dbname != "" {
|
||||
n += "/" + dbname
|
||||
}
|
||||
u.hostPortDB = []string{host, port, n}
|
||||
}
|
||||
|
||||
return genOptionsODBC(q, true), nil
|
||||
}
|
||||
|
||||
// GenODBC generates a odbc DSN from the passed URL.
|
||||
func GenODBC(u *URL) (string, error) {
|
||||
q := u.Query()
|
||||
|
||||
host, port, dbname := hostname(u.Host), hostport(u.Host), strings.TrimPrefix(u.Path, "/")
|
||||
|
||||
// save host, port, dbname
|
||||
if u.hostPortDB == nil {
|
||||
u.hostPortDB = []string{host, port, dbname}
|
||||
}
|
||||
|
||||
q.Set("Driver", "{"+strings.Replace(u.Proto, "+", " ", -1)+"}")
|
||||
q.Set("Server", host)
|
||||
|
||||
if port == "" {
|
||||
proto := strings.ToLower(u.Proto)
|
||||
switch {
|
||||
case strings.Contains(proto, "mysql"):
|
||||
q.Set("Port", "3306")
|
||||
case strings.Contains(proto, "postgres"):
|
||||
q.Set("Port", "5432")
|
||||
case strings.Contains(proto, "db2") || strings.Contains(proto, "ibm"):
|
||||
q.Set("ServiceName", "50000")
|
||||
default:
|
||||
q.Set("Port", "1433")
|
||||
}
|
||||
} else {
|
||||
q.Set("Port", port)
|
||||
}
|
||||
q.Set("Database", dbname)
|
||||
|
||||
// add user/pass
|
||||
if u.User != nil {
|
||||
q.Set("UID", u.User.Username())
|
||||
p, _ := u.User.Password()
|
||||
q.Set("PWD", p)
|
||||
}
|
||||
|
||||
return genOptionsODBC(q, true), nil
|
||||
}
|
||||
|
||||
// GenOLEODBC generates a oleodbc DSN from the passed URL.
|
||||
func GenOLEODBC(u *URL) (string, error) {
|
||||
props, err := GenODBC(u)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return `Provider=MSDASQL.1;Extended Properties="` + props + `"`, nil
|
||||
}
|
||||
|
||||
// GenClickhouse generates a clickhouse DSN from the passed URL.
|
||||
func GenClickhouse(u *URL) (string, error) {
|
||||
z := &url.URL{
|
||||
Scheme: "tcp",
|
||||
Opaque: u.Opaque,
|
||||
Host: u.Host,
|
||||
Path: u.Path,
|
||||
RawPath: u.RawPath,
|
||||
RawQuery: u.RawQuery,
|
||||
Fragment: u.Fragment,
|
||||
}
|
||||
|
||||
if hostport(z.Host) == "" {
|
||||
z.Host += ":9000"
|
||||
}
|
||||
|
||||
// add parameters
|
||||
q := z.Query()
|
||||
if u.User != nil {
|
||||
if user := u.User.Username(); len(user) > 0 {
|
||||
q.Set("username", user)
|
||||
}
|
||||
if pass, ok := u.User.Password(); ok {
|
||||
q.Set("password", pass)
|
||||
}
|
||||
}
|
||||
z.RawQuery = q.Encode()
|
||||
|
||||
return z.String(), nil
|
||||
}
|
||||
|
||||
// GenVoltDB generates a VoltDB DSN from the passed URL.
|
||||
func GenVoltDB(u *URL) (string, error) {
|
||||
host, port := "localhost", "21212"
|
||||
if h := hostname(u.Host); h != "" {
|
||||
host = h
|
||||
}
|
||||
if p := hostport(u.Host); p != "" {
|
||||
port = p
|
||||
}
|
||||
return host + ":" + port, nil
|
||||
}
|
||||
|
||||
// GenPresto generates a Presto DSN from the passed URL.
|
||||
func GenPresto(u *URL) (string, error) {
|
||||
z := &url.URL{
|
||||
Scheme: "http",
|
||||
Opaque: u.Opaque,
|
||||
User: u.User,
|
||||
Host: u.Host,
|
||||
RawQuery: u.RawQuery,
|
||||
Fragment: u.Fragment,
|
||||
}
|
||||
|
||||
// change to https
|
||||
if strings.HasSuffix(u.OriginalScheme, "s") {
|
||||
z.Scheme = "https"
|
||||
}
|
||||
|
||||
// force user
|
||||
if z.User == nil {
|
||||
z.User = url.User("user")
|
||||
}
|
||||
|
||||
// force host
|
||||
if z.Host == "" {
|
||||
z.Host = "localhost"
|
||||
}
|
||||
|
||||
// force port
|
||||
if hostport(z.Host) == "" {
|
||||
if z.Scheme == "http" {
|
||||
z.Host += ":8080"
|
||||
} else if z.Scheme == "https" {
|
||||
z.Host += ":8443"
|
||||
}
|
||||
}
|
||||
|
||||
// add parameters
|
||||
q := z.Query()
|
||||
dbname, schema := strings.TrimPrefix(u.Path, "/"), ""
|
||||
if dbname == "" {
|
||||
dbname = "default"
|
||||
} else if i := strings.Index(dbname, "/"); i != -1 {
|
||||
schema, dbname = dbname[i+1:], dbname[:i]
|
||||
}
|
||||
q.Set("catalog", dbname)
|
||||
if schema != "" {
|
||||
q.Set("schema", schema)
|
||||
}
|
||||
z.RawQuery = q.Encode()
|
||||
|
||||
return z.String(), nil
|
||||
}
|
||||
|
||||
// GenCassandra generates a cassandra DSN from the passed URL.
|
||||
func GenCassandra(u *URL) (string, error) {
|
||||
host, port, dbname := "localhost", "9042", strings.TrimPrefix(u.Path, "/")
|
||||
if h := hostname(u.Host); h != "" {
|
||||
host = h
|
||||
}
|
||||
if p := hostport(u.Host); p != "" {
|
||||
port = p
|
||||
}
|
||||
q := u.Query()
|
||||
// add user/pass
|
||||
if u.User != nil {
|
||||
q.Set("username", u.User.Username())
|
||||
if pass, _ := u.User.Password(); pass != "" {
|
||||
q.Set("password", pass)
|
||||
}
|
||||
}
|
||||
// add dbname
|
||||
if dbname != "" {
|
||||
q.Set("keyspace", dbname)
|
||||
}
|
||||
return host + ":" + port + genQueryOptions(q), nil
|
||||
}
|
||||
|
||||
// GenIgnite generates an ignite DSN from the passed URL.
|
||||
func GenIgnite(u *URL) (string, error) {
|
||||
host, port, dbname := "localhost", "10800", strings.TrimPrefix(u.Path, "/")
|
||||
if h := hostname(u.Host); h != "" {
|
||||
host = h
|
||||
}
|
||||
if p := hostport(u.Host); p != "" {
|
||||
port = p
|
||||
}
|
||||
q := u.Query()
|
||||
// add user/pass
|
||||
if u.User != nil {
|
||||
q.Set("username", u.User.Username())
|
||||
if pass, _ := u.User.Password(); pass != "" {
|
||||
q.Set("password", pass)
|
||||
}
|
||||
}
|
||||
// add dbname
|
||||
if dbname != "" {
|
||||
dbname = "/" + dbname
|
||||
}
|
||||
return "tcp://" + host + ":" + port + dbname + genQueryOptions(q), nil
|
||||
}
|
||||
|
||||
// GenSnowflake generates a snowflake DSN from the passed URL.
|
||||
func GenSnowflake(u *URL) (string, error) {
|
||||
host, port, dbname := hostname(u.Host), hostport(u.Host), strings.TrimPrefix(u.Path, "/")
|
||||
if host == "" {
|
||||
return "", ErrMissingHost
|
||||
}
|
||||
if dbname == "" {
|
||||
return "", ErrMissingPath
|
||||
}
|
||||
if port != "" {
|
||||
port = ":" + port
|
||||
}
|
||||
|
||||
// add user/pass
|
||||
var user string
|
||||
if u.User != nil {
|
||||
user = u.User.Username()
|
||||
if pass, _ := u.User.Password(); pass != "" {
|
||||
user += ":" + pass
|
||||
}
|
||||
user += "@"
|
||||
}
|
||||
|
||||
return user + host + port + "/" + dbname + genQueryOptions(u.Query()), nil
|
||||
}
|
1
vendor/github.com/xo/dburl/go.mod
generated
vendored
Normal file
1
vendor/github.com/xo/dburl/go.mod
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module github.com/xo/dburl
|
0
vendor/github.com/xo/dburl/go.sum
generated
vendored
Normal file
0
vendor/github.com/xo/dburl/go.sum
generated
vendored
Normal file
250
vendor/github.com/xo/dburl/scheme.go
generated
vendored
Normal file
250
vendor/github.com/xo/dburl/scheme.go
generated
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
package dburl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Proto are the allowed transport protocol types in a database URL scheme.
|
||||
type Proto uint
|
||||
|
||||
// Proto types.
|
||||
const (
|
||||
ProtoNone Proto = 0
|
||||
ProtoTCP Proto = 1
|
||||
ProtoUDP Proto = 2
|
||||
ProtoUnix Proto = 4
|
||||
ProtoAny Proto = 8
|
||||
)
|
||||
|
||||
// Scheme wraps information used for registering a URL scheme with
|
||||
// Parse/Open.
|
||||
type Scheme struct {
|
||||
// Driver is the name of the SQL driver that will set as the Scheme in
|
||||
// Parse'd URLs, and is the driver name expected by the standard sql.Open
|
||||
// calls.
|
||||
//
|
||||
// Note: a 2 letter alias will always be registered for the Driver as the
|
||||
// first 2 characters of the Driver, unless one of the Aliases includes an
|
||||
// alias that is 2 characters.
|
||||
Driver string
|
||||
|
||||
// Generator is the func responsible for generating a DSN based on parsed
|
||||
// URL information.
|
||||
//
|
||||
// Note: this func should not modify the passed URL.
|
||||
Generator func(*URL) (string, error)
|
||||
|
||||
// Proto are allowed protocol types for the scheme.
|
||||
Proto Proto
|
||||
|
||||
// Opaque toggles Parse to not re-process URLs with an "opaque" component.
|
||||
Opaque bool
|
||||
|
||||
// Aliases are any additional aliases for the scheme.
|
||||
Aliases []string
|
||||
|
||||
// Override is the Go SQL driver to use instead of Driver.
|
||||
Override string
|
||||
}
|
||||
|
||||
// BaseSchemes returns the supported base schemes.
|
||||
func BaseSchemes() []Scheme {
|
||||
return []Scheme{
|
||||
// core databases
|
||||
{"mssql", GenSQLServer, 0, false, []string{"sqlserver"}, ""},
|
||||
{"mysql", GenMySQL, ProtoTCP | ProtoUDP | ProtoUnix, false, []string{"mariadb", "maria", "percona", "aurora"}, ""},
|
||||
{"ora", GenOracle, 0, false, []string{"oracle", "oci8", "oci"}, ""},
|
||||
{"postgres", GenPostgres, ProtoUnix, false, []string{"pg", "postgresql", "pgsql"}, ""},
|
||||
{"sqlite3", GenOpaque, 0, true, []string{"sqlite", "file"}, ""},
|
||||
|
||||
// wire compatibles
|
||||
{"cockroachdb", GenFromURL("postgres://localhost:26257/?sslmode=disable"), 0, false, []string{"cr", "cockroach", "crdb", "cdb"}, "postgres"},
|
||||
{"memsql", GenMySQL, 0, false, nil, "mysql"},
|
||||
{"redshift", GenFromURL("postgres://localhost:5439/"), 0, false, []string{"rs"}, "postgres"},
|
||||
{"tidb", GenMySQL, 0, false, nil, "mysql"},
|
||||
{"vitess", GenMySQL, 0, false, []string{"vt"}, "mysql"},
|
||||
|
||||
// testing
|
||||
{"spanner", GenScheme("spanner"), 0, false, []string{"gs", "google", "span"}, ""},
|
||||
|
||||
// alternates implementations
|
||||
{"mymysql", GenMyMySQL, ProtoTCP | ProtoUDP | ProtoUnix, false, []string{"zm", "mymy"}, ""},
|
||||
{"pgx", GenScheme("postgres"), ProtoUnix, false, []string{"px"}, ""},
|
||||
|
||||
// other databases
|
||||
{"adodb", GenADODB, 0, false, []string{"ado"}, ""},
|
||||
{"avatica", GenFromURL("http://localhost:8765/"), 0, false, []string{"phoenix"}, ""},
|
||||
{"cql", GenCassandra, 0, false, []string{"ca", "cassandra", "datastax", "scy", "scylla"}, ""},
|
||||
{"clickhouse", GenClickhouse, 0, false, []string{"ch"}, ""},
|
||||
{"firebirdsql", GenFirebird, 0, false, []string{"fb", "firebird"}, ""},
|
||||
{"hdb", GenScheme("hdb"), 0, false, []string{"sa", "saphana", "sap", "hana"}, ""},
|
||||
{"ignite", GenIgnite, 0, false, []string{"ig", "gridgain"}, ""},
|
||||
{"n1ql", GenFromURL("http://localhost:9000/"), 0, false, []string{"couchbase"}, ""},
|
||||
{"odbc", GenODBC, ProtoAny, false, nil, ""},
|
||||
{"oleodbc", GenOLEODBC, ProtoAny, false, []string{"oo", "ole"}, "adodb"},
|
||||
{"presto", GenPresto, 0, false, []string{"prestodb", "prestos", "prs", "prestodbs"}, ""},
|
||||
{"ql", GenOpaque, 0, true, []string{"ql", "cznic", "cznicql"}, ""},
|
||||
{"snowflake", GenSnowflake, 0, false, []string{"sf"}, ""},
|
||||
{"tds", GenFromURL("http://localhost:5000/"), 0, false, []string{"ax", "ase", "sapase"}, ""},
|
||||
{"voltdb", GenVoltDB, 0, false, []string{"volt", "vdb"}, ""},
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
schemes := BaseSchemes()
|
||||
schemeMap = make(map[string]*Scheme, len(schemes))
|
||||
|
||||
// register
|
||||
for _, scheme := range schemes {
|
||||
Register(scheme)
|
||||
}
|
||||
}
|
||||
|
||||
// schemeMap is the map of registered schemes.
|
||||
var schemeMap map[string]*Scheme
|
||||
|
||||
// registerAlias registers a alias for an already registered Scheme.
|
||||
func registerAlias(name, alias string, doSort bool) {
|
||||
scheme, ok := schemeMap[name]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("scheme %s not registered", name))
|
||||
}
|
||||
|
||||
if doSort && has(scheme.Aliases, alias) {
|
||||
panic(fmt.Sprintf("scheme %s already has alias %s", name, alias))
|
||||
}
|
||||
|
||||
if _, ok := schemeMap[alias]; ok {
|
||||
panic(fmt.Sprintf("scheme %s already registered", alias))
|
||||
}
|
||||
|
||||
scheme.Aliases = append(scheme.Aliases, alias)
|
||||
if doSort {
|
||||
sort.Sort(ss(scheme.Aliases))
|
||||
}
|
||||
|
||||
schemeMap[alias] = scheme
|
||||
}
|
||||
|
||||
// Register registers a Scheme.
|
||||
func Register(scheme Scheme) {
|
||||
if scheme.Generator == nil {
|
||||
panic("must specify Generator when registering Scheme")
|
||||
}
|
||||
|
||||
if scheme.Opaque && scheme.Proto&ProtoUnix != 0 {
|
||||
panic("scheme must support only Opaque or Unix protocols, not both")
|
||||
}
|
||||
|
||||
// register
|
||||
if _, ok := schemeMap[scheme.Driver]; ok {
|
||||
panic(fmt.Sprintf("scheme %s already registered", scheme.Driver))
|
||||
}
|
||||
|
||||
sz := &Scheme{
|
||||
Driver: scheme.Driver,
|
||||
Generator: scheme.Generator,
|
||||
Proto: scheme.Proto,
|
||||
Opaque: scheme.Opaque,
|
||||
Override: scheme.Override,
|
||||
}
|
||||
|
||||
schemeMap[scheme.Driver] = sz
|
||||
|
||||
// add aliases
|
||||
var hasShort bool
|
||||
for _, alias := range scheme.Aliases {
|
||||
if len(alias) == 2 {
|
||||
hasShort = true
|
||||
}
|
||||
if scheme.Driver != alias {
|
||||
registerAlias(scheme.Driver, alias, false)
|
||||
}
|
||||
}
|
||||
|
||||
if !hasShort && len(scheme.Driver) > 2 {
|
||||
registerAlias(scheme.Driver, scheme.Driver[:2], false)
|
||||
}
|
||||
|
||||
// ensure always at least one alias, and that if Driver is 2 characters,
|
||||
// that it gets added as well
|
||||
if len(sz.Aliases) == 0 || len(scheme.Driver) == 2 {
|
||||
sz.Aliases = append(sz.Aliases, scheme.Driver)
|
||||
}
|
||||
|
||||
// sort
|
||||
sort.Sort(ss(sz.Aliases))
|
||||
}
|
||||
|
||||
// Unregister unregisters a Scheme and all associated aliases.
|
||||
func Unregister(name string) *Scheme {
|
||||
scheme, ok := schemeMap[name]
|
||||
if ok {
|
||||
for _, alias := range scheme.Aliases {
|
||||
delete(schemeMap, alias)
|
||||
}
|
||||
delete(schemeMap, name)
|
||||
return scheme
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterAlias registers a alias for an already registered Scheme.h
|
||||
func RegisterAlias(name, alias string) {
|
||||
registerAlias(name, alias, true)
|
||||
}
|
||||
|
||||
// has is a util func to determine if a contains b.
|
||||
func has(a []string, b string) bool {
|
||||
for _, s := range a {
|
||||
if s == b {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SchemeDriverAndAliases returns the registered driver and aliases for a
|
||||
// database scheme.
|
||||
func SchemeDriverAndAliases(name string) (string, []string) {
|
||||
if scheme, ok := schemeMap[name]; ok {
|
||||
driver := scheme.Driver
|
||||
if scheme.Override != "" {
|
||||
driver = scheme.Override
|
||||
}
|
||||
|
||||
var aliases []string
|
||||
for _, alias := range scheme.Aliases {
|
||||
if alias == driver {
|
||||
continue
|
||||
}
|
||||
aliases = append(aliases, alias)
|
||||
}
|
||||
|
||||
sort.Sort(ss(aliases))
|
||||
|
||||
return driver, aliases
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// ss is a util type to provide sorting of a string slice (used for sorting
|
||||
// aliases).
|
||||
type ss []string
|
||||
|
||||
func (s ss) Len() int { return len(s) }
|
||||
func (s ss) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s ss) Less(i, j int) bool {
|
||||
if len(s[i]) <= len(s[j]) {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(s[j]) < len(s[i]) {
|
||||
return false
|
||||
}
|
||||
|
||||
return s[i] < s[j]
|
||||
}
|
235
vendor/github.com/xo/dburl/url.go
generated
vendored
Normal file
235
vendor/github.com/xo/dburl/url.go
generated
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
package dburl
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// URL wraps the standard net/url.URL type, adding OriginalScheme, Proto,
|
||||
// Driver, and DSN strings.
|
||||
type URL struct {
|
||||
// URL is the base net/url/URL.
|
||||
url.URL
|
||||
|
||||
// OriginalScheme is the original parsed scheme (ie, "sq", "mysql+unix", "sap", etc).
|
||||
OriginalScheme string
|
||||
|
||||
// Proto is the specified protocol (ie, "tcp", "udp", "unix"), if provided.
|
||||
Proto string
|
||||
|
||||
// Driver is the non-aliased SQL driver name that should be used in a call
|
||||
// to sql/Open.
|
||||
Driver string
|
||||
|
||||
// Unaliased is the unaliased driver name.
|
||||
Unaliased string
|
||||
|
||||
// DSN is the built connection "data source name" that can be used in a
|
||||
// call to sql/Open.
|
||||
DSN string
|
||||
|
||||
// hostPortDB will be set by Gen*() funcs after determining the host, port,
|
||||
// database.
|
||||
//
|
||||
// when empty, indicates that these values are not special, and can be
|
||||
// retrieved as the host, port, and path[1:] as usual.
|
||||
hostPortDB []string
|
||||
}
|
||||
|
||||
// Parse parses urlstr, returning a URL with the OriginalScheme, Proto, Driver,
|
||||
// Unaliased, and DSN fields populated.
|
||||
//
|
||||
// Note: if urlstr has a Opaque component (ie, URLs not specified as "scheme://"
|
||||
// but "scheme:"), and the database scheme does not support opaque components,
|
||||
// then Parse will attempt to re-process the URL as "scheme://<opaque>" using
|
||||
// the OriginalScheme.
|
||||
func Parse(urlstr string) (*URL, error) {
|
||||
// parse url
|
||||
u, err := url.Parse(urlstr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if u.Scheme == "" {
|
||||
return nil, ErrInvalidDatabaseScheme
|
||||
}
|
||||
|
||||
// create url
|
||||
v := &URL{URL: *u, OriginalScheme: urlstr[:len(u.Scheme)], Proto: "tcp"}
|
||||
|
||||
// check for +protocol in scheme
|
||||
var checkProto bool
|
||||
if i := strings.IndexRune(v.Scheme, '+'); i != -1 {
|
||||
v.Proto = urlstr[i+1 : len(u.Scheme)]
|
||||
v.Scheme = v.Scheme[:i]
|
||||
checkProto = true
|
||||
}
|
||||
|
||||
// get dsn generator
|
||||
scheme, ok := schemeMap[v.Scheme]
|
||||
if !ok {
|
||||
return nil, ErrUnknownDatabaseScheme
|
||||
}
|
||||
|
||||
// if scheme does not understand opaque URLs, retry parsing after making a fully
|
||||
// qualified URL
|
||||
if !scheme.Opaque && v.Opaque != "" {
|
||||
q := ""
|
||||
if v.RawQuery != "" {
|
||||
q = "?" + v.RawQuery
|
||||
}
|
||||
f := ""
|
||||
if v.Fragment != "" {
|
||||
f = "#" + v.Fragment
|
||||
}
|
||||
|
||||
return Parse(v.OriginalScheme + "://" + v.Opaque + q + f)
|
||||
}
|
||||
|
||||
if scheme.Opaque && v.Opaque == "" {
|
||||
// force Opaque
|
||||
v.Opaque, v.Host, v.Path, v.RawPath = v.Host+v.Path, "", "", ""
|
||||
} else if v.Host == "." || (v.Host == "" && strings.TrimPrefix(v.Path, "/") != "") {
|
||||
// force unix proto
|
||||
v.Proto = "unix"
|
||||
}
|
||||
|
||||
// check proto
|
||||
if checkProto || v.Proto != "tcp" {
|
||||
if scheme.Proto == ProtoNone {
|
||||
return nil, ErrInvalidTransportProtocol
|
||||
}
|
||||
|
||||
switch {
|
||||
case scheme.Proto&ProtoAny != 0 && v.Proto != "":
|
||||
case scheme.Proto&ProtoTCP != 0 && v.Proto == "tcp":
|
||||
case scheme.Proto&ProtoUDP != 0 && v.Proto == "udp":
|
||||
case scheme.Proto&ProtoUnix != 0 && v.Proto == "unix":
|
||||
|
||||
default:
|
||||
return nil, ErrInvalidTransportProtocol
|
||||
}
|
||||
}
|
||||
|
||||
// set driver
|
||||
v.Driver = scheme.Driver
|
||||
v.Unaliased = scheme.Driver
|
||||
if scheme.Override != "" {
|
||||
v.Driver = scheme.Override
|
||||
}
|
||||
|
||||
// generate dsn
|
||||
v.DSN, err = scheme.Generator(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return v, nil
|
||||
}
|
||||
|
||||
// String satisfies the stringer interface.
|
||||
func (u *URL) String() string {
|
||||
p := &url.URL{
|
||||
Scheme: u.OriginalScheme,
|
||||
Opaque: u.Opaque,
|
||||
User: u.User,
|
||||
Host: u.Host,
|
||||
Path: u.Path,
|
||||
RawPath: u.RawPath,
|
||||
RawQuery: u.RawQuery,
|
||||
Fragment: u.Fragment,
|
||||
}
|
||||
|
||||
return p.String()
|
||||
}
|
||||
|
||||
// Short provides a short description of the user, host, and database.
|
||||
func (u *URL) Short() string {
|
||||
if u.Scheme == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
s := schemeMap[u.Scheme].Aliases[0]
|
||||
|
||||
if u.Scheme == "odbc" || u.Scheme == "oleodbc" {
|
||||
n := u.Proto
|
||||
if v, ok := schemeMap[n]; ok {
|
||||
n = v.Aliases[0]
|
||||
}
|
||||
s += "+" + n
|
||||
} else if u.Proto != "tcp" {
|
||||
s += "+" + u.Proto
|
||||
}
|
||||
|
||||
s += ":"
|
||||
|
||||
if u.User != nil {
|
||||
if un := u.User.Username(); un != "" {
|
||||
s += un + "@"
|
||||
}
|
||||
}
|
||||
|
||||
if u.Host != "" {
|
||||
s += u.Host
|
||||
}
|
||||
|
||||
if u.Path != "" && u.Path != "/" {
|
||||
s += u.Path
|
||||
}
|
||||
|
||||
if u.Opaque != "" {
|
||||
s += u.Opaque
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// Normalize returns the driver, host, port, database, and user name of a URL,
|
||||
// joined with sep, populating blank fields with empty.
|
||||
func (u *URL) Normalize(sep, empty string, cut int) string {
|
||||
s := make([]string, 5)
|
||||
|
||||
s[0] = u.Unaliased
|
||||
if u.Proto != "tcp" && u.Proto != "unix" {
|
||||
s[0] += "+" + u.Proto
|
||||
}
|
||||
|
||||
// set host port dbname fields
|
||||
if u.hostPortDB == nil {
|
||||
if u.Opaque != "" {
|
||||
u.hostPortDB = []string{u.Opaque, "", ""}
|
||||
} else {
|
||||
u.hostPortDB = []string{
|
||||
hostname(u.Host),
|
||||
hostport(u.Host),
|
||||
strings.TrimPrefix(u.Path, "/"),
|
||||
}
|
||||
}
|
||||
}
|
||||
copy(s[1:], u.hostPortDB)
|
||||
|
||||
// set user
|
||||
if u.User != nil {
|
||||
s[4] = u.User.Username()
|
||||
}
|
||||
|
||||
// replace blank entries ...
|
||||
for i := 0; i < len(s); i++ {
|
||||
if s[i] == "" {
|
||||
s[i] = empty
|
||||
}
|
||||
}
|
||||
|
||||
if cut > 0 {
|
||||
// cut to only populated fields
|
||||
i := len(s) - 1
|
||||
for ; i > cut; i-- {
|
||||
if s[i] != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
s = s[:i]
|
||||
}
|
||||
|
||||
// join
|
||||
return strings.Join(s, sep)
|
||||
}
|
179
vendor/github.com/xo/dburl/util.go
generated
vendored
Normal file
179
vendor/github.com/xo/dburl/util.go
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
package dburl
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"os"
|
||||
stdpath "path"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// contains code taken from go1.8, for purposes of backwards compatability with
|
||||
// older go versions.
|
||||
|
||||
// hostname returns u.Host, without any port number.
|
||||
//
|
||||
// If Host is an IPv6 literal with a port number, Hostname returns the
|
||||
// IPv6 literal without the square brackets. IPv6 literals may include
|
||||
// a zone identifier.
|
||||
func hostname(hostport string) string {
|
||||
colon := strings.IndexByte(hostport, ':')
|
||||
if colon == -1 {
|
||||
return hostport
|
||||
}
|
||||
if i := strings.IndexByte(hostport, ']'); i != -1 {
|
||||
return strings.TrimPrefix(hostport[:i], "[")
|
||||
}
|
||||
return hostport[:colon]
|
||||
}
|
||||
|
||||
// hostport returns the port part of u.Host, without the leading colon.
|
||||
// If u.Host doesn't contain a port, Port returns an empty string.
|
||||
func hostport(hostport string) string {
|
||||
colon := strings.IndexByte(hostport, ':')
|
||||
if colon == -1 {
|
||||
return ""
|
||||
}
|
||||
if i := strings.Index(hostport, "]:"); i != -1 {
|
||||
return hostport[i+len("]:"):]
|
||||
}
|
||||
if strings.Contains(hostport, "]") {
|
||||
return ""
|
||||
}
|
||||
return hostport[colon+len(":"):]
|
||||
}
|
||||
|
||||
// genOptions takes URL values and generates options, joining together with
|
||||
// joiner, and separated by sep, with any multi URL values joined by valSep,
|
||||
// ignoring any values with keys in ignore.
|
||||
//
|
||||
// For example, to build a "ODBC" style connection string, use like the following:
|
||||
// genOptions(u.Query(), "", "=", ";", ",")
|
||||
func genOptions(q url.Values, joiner, assign, sep, valSep string, skipWhenEmpty bool, ignore ...string) string {
|
||||
qlen := len(q)
|
||||
if qlen == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
// make ignore map
|
||||
ig := make(map[string]bool, len(ignore))
|
||||
for _, v := range ignore {
|
||||
ig[strings.ToLower(v)] = true
|
||||
}
|
||||
|
||||
// sort keys
|
||||
s := make([]string, len(q))
|
||||
var i int
|
||||
for k := range q {
|
||||
s[i] = k
|
||||
i++
|
||||
}
|
||||
sort.Strings(s)
|
||||
|
||||
var opts []string
|
||||
for _, k := range s {
|
||||
if !ig[strings.ToLower(k)] {
|
||||
val := strings.Join(q[k], valSep)
|
||||
if !skipWhenEmpty || val != "" {
|
||||
if val != "" {
|
||||
val = assign + val
|
||||
}
|
||||
opts = append(opts, k+val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(opts) != 0 {
|
||||
return joiner + strings.Join(opts, sep)
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// genOptionsODBC is a util wrapper around genOptions that uses the fixed settings
|
||||
// for ODBC style connection strings.
|
||||
func genOptionsODBC(q url.Values, skipWhenEmpty bool, ignore ...string) string {
|
||||
return genOptions(q, "", "=", ";", ",", skipWhenEmpty, ignore...)
|
||||
}
|
||||
|
||||
// genQueryOptions generates standard query options.
|
||||
func genQueryOptions(q url.Values) string {
|
||||
if s := q.Encode(); s != "" {
|
||||
return "?" + s
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// convertOptions converts an option value based on name, value pairs.
|
||||
func convertOptions(q url.Values, pairs ...string) url.Values {
|
||||
n := make(url.Values)
|
||||
for k, v := range q {
|
||||
x := make([]string, len(v))
|
||||
for i, z := range v {
|
||||
for j := 0; j < len(pairs); j += 2 {
|
||||
if pairs[j] == z {
|
||||
z = pairs[j+1]
|
||||
}
|
||||
}
|
||||
x[i] = z
|
||||
}
|
||||
n[k] = x
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
// mode returns the mode of the path.
|
||||
func mode(path string) os.FileMode {
|
||||
if fi, err := os.Stat(path); err == nil {
|
||||
return fi.Mode()
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// resolveSocket tries to resolve a path to a Unix domain socket based on the
|
||||
// form "/path/to/socket/dbname" returning either the original path and the
|
||||
// empty string, or the components "/path/to/socket" and "dbname", when
|
||||
// /path/to/socket/dbname is reported by os.Stat as a socket.
|
||||
//
|
||||
// Used for MySQL DSNs.
|
||||
func resolveSocket(path string) (string, string) {
|
||||
dir, dbname := path, ""
|
||||
for dir != "" && dir != "/" && dir != "." {
|
||||
if m := mode(dir); m&os.ModeSocket != 0 {
|
||||
return dir, dbname
|
||||
}
|
||||
dir, dbname = stdpath.Dir(dir), stdpath.Base(dir)
|
||||
}
|
||||
|
||||
return path, ""
|
||||
}
|
||||
|
||||
// resolveDir resolves a directory with a :port list.
|
||||
//
|
||||
// Used for PostgreSQL DSNs.
|
||||
func resolveDir(path string) (string, string, string) {
|
||||
dir := path
|
||||
for dir != "" && dir != "/" && dir != "." {
|
||||
port := ""
|
||||
i, j := strings.LastIndex(dir, ":"), strings.LastIndex(dir, "/")
|
||||
if i != -1 && i > j {
|
||||
port = dir[i+1:]
|
||||
dir = dir[:i]
|
||||
}
|
||||
|
||||
if mode(dir)&os.ModeDir != 0 {
|
||||
rest := strings.TrimPrefix(strings.TrimPrefix(strings.TrimPrefix(path, dir), ":"+port), "/")
|
||||
return dir, port, rest
|
||||
}
|
||||
|
||||
if j != -1 {
|
||||
dir = dir[:j]
|
||||
} else {
|
||||
dir = ""
|
||||
}
|
||||
}
|
||||
|
||||
return path, "", ""
|
||||
}
|
Reference in New Issue
Block a user