Support passing JDBC username and password to backing database via DSN

Project: http://git-wip-us.apache.org/repos/asf/calcite-avatica-go/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/calcite-avatica-go/commit/b1a6e6b4
Tree: http://git-wip-us.apache.org/repos/asf/calcite-avatica-go/tree/b1a6e6b4
Diff: http://git-wip-us.apache.org/repos/asf/calcite-avatica-go/diff/b1a6e6b4

Branch: refs/heads/master
Commit: b1a6e6b41b435affecb621827d65c97a51e32246
Parents: 28cd280
Author: Francis Chuang <francis.chu...@boostport.com>
Authored: Mon May 22 09:07:49 2017 +1000
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Aug 10 18:47:11 2017 -0700

----------------------------------------------------------------------
 README.md   | 10 +++++++++-
 driver.go   | 19 +++++++++++++++----
 dsn.go      | 15 +++++++++++++++
 dsn_test.go | 18 +++++++++++++++++-
 4 files changed, 56 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite-avatica-go/blob/b1a6e6b4/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 8d701c5..e211292 100644
--- a/README.md
+++ b/README.md
@@ -35,11 +35,19 @@ rows := db.Query("SELECT COUNT(*) FROM test")
 The DSN has the following format (optional parts are marked by square 
brackets):
 
 ```
-http://address:port[/schema][?parameter1=value&...parameterN=value]
+http://[username:password@]address:port[/schema][?parameter1=value&...parameterN=value]
 ```
 
 In other words, the scheme (http), address and port is mandatory, but the 
schema and parameters are optional.
 
+#### username
+This is the JDBC username that is passed directly to the backing database. It 
is *NOT* used for authenticating
+against Avatica.
+
+#### password
+This is the JDBC password that is passed directly to the backing database. It 
is *NOT* used for authenticating
+against Avatica.
+
 #### schema
 The `schema` path sets the default schema to use for this connection. For 
example, if you set it to `myschema`,
 then executing the query `SELECT * FROM my_table` will have the equivalence of 
`SELECT * FROM myschema.my_table`.

http://git-wip-us.apache.org/repos/asf/calcite-avatica-go/blob/b1a6e6b4/driver.go
----------------------------------------------------------------------
diff --git a/driver.go b/driver.go
index 509ed79..537aa16 100644
--- a/driver.go
+++ b/driver.go
@@ -18,6 +18,7 @@ import (
        "database/sql"
        "database/sql/driver"
        "fmt"
+
        "github.com/Boostport/avatica/message"
        "github.com/satori/go.uuid"
        "golang.org/x/net/context"
@@ -40,13 +41,23 @@ func (a *Driver) Open(dsn string) (driver.Conn, error) {
        httpClient := NewHTTPClient(config.endpoint)
        connectionId := uuid.NewV4().String()
 
+       info := map[string]string{
+               "AutoCommit":  "true",
+               "Consistency": "8",
+       }
+
+       if config.user != "" {
+               info["user"] = config.user
+       }
+
+       if config.password != "" {
+               info["password"] = config.password
+       }
+
        // Open a connection to the server
        req := &message.OpenConnectionRequest{
                ConnectionId: connectionId,
-               Info: map[string]string{
-                       "AutoCommit":  "true",
-                       "Consistency": "8",
-               },
+               Info:         info,
        }
 
        if config.schema != "" {

http://git-wip-us.apache.org/repos/asf/calcite-avatica-go/blob/b1a6e6b4/dsn.go
----------------------------------------------------------------------
diff --git a/dsn.go b/dsn.go
index d1cbad0..1311026 100644
--- a/dsn.go
+++ b/dsn.go
@@ -16,6 +16,8 @@ type Config struct {
        location             *time.Location
        schema               string
        transactionIsolation uint32
+       user                 string
+       password             string
 }
 
 // ParseDSN parses a DSN string to a Config
@@ -34,6 +36,18 @@ func ParseDSN(dsn string) (*Config, error) {
                return nil, fmt.Errorf("Unable to parse DSN: %s", err)
        }
 
+       userInfo := parsed.User
+
+       if userInfo != nil {
+               if userInfo.Username() != "" {
+                       conf.user = userInfo.Username()
+               }
+
+               if pass, ok := userInfo.Password(); ok {
+                       conf.password = pass
+               }
+       }
+
        queries := parsed.Query()
 
        if v := queries.Get("maxRowsTotal"); v != "" {
@@ -88,6 +102,7 @@ func ParseDSN(dsn string) (*Config, error) {
                conf.transactionIsolation = uint32(isolation)
        }
 
+       parsed.User = nil
        parsed.RawQuery = ""
        parsed.Fragment = ""
 

http://git-wip-us.apache.org/repos/asf/calcite-avatica-go/blob/b1a6e6b4/dsn_test.go
----------------------------------------------------------------------
diff --git a/dsn_test.go b/dsn_test.go
index 6fce9da..8d10f7d 100644
--- a/dsn_test.go
+++ b/dsn_test.go
@@ -8,12 +8,20 @@ import (
 
 func TestParseDSN(t *testing.T) {
 
-       config, err := 
ParseDSN("http://localhost:8765/myschema?maxRowsTotal=1&frameMaxSize=1&location=Australia/Melbourne&transactionIsolation=8";)
+       config, err := 
ParseDSN("http://username:password@localhost:8765/myschema?maxRowsTotal=1&frameMaxSize=1&location=Australia/Melbourne&transactionIsolation=8";)
 
        if err != nil {
                t.Fatalf("Unexpected error: %s", err)
        }
 
+       if config.user != "username"{
+               t.Errorf("Expected username to be %s, got %s", "username", 
config.user)
+       }
+
+       if config.password != "password"{
+               t.Errorf("Expected password to be %s, got %s", "password", 
config.password)
+       }
+
        if config.endpoint != "http://localhost:8765/myschema"; {
                t.Errorf("Expected endpoint to be %s, got %s", 
"http://localhost:8765/myschema";, config.endpoint)
        }
@@ -56,6 +64,14 @@ func TestDSNDefaults(t *testing.T) {
                t.Fatalf("Unexpected error: %s", err)
        }
 
+       if config.user != ""{
+               t.Errorf("Default username should be empty, got %s", 
config.user)
+       }
+
+       if config.password != ""{
+               t.Errorf("Default password should be empty, got %s", 
config.password)
+       }
+
        if config.location.String() == "" {
                t.Error("There was no timezone set.")
        }

Reply via email to