Skip to content

Implement Connector interface #705

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed

Conversation

agruetz
Copy link

@agruetz agruetz commented Nov 13, 2017

Description

Implemented the connector interface support that is coming out in go 1.10. Moved the connection code in the Open interface to a connectServer method that can be shared while still maintaining the differences between the Open interface that accepts a DSN and the Connect interface that allows for other types of configuration options.

All existing tests are passing. I wanted to get feed back before writing the tests for this. Unsure where/how documentation should change.

fixes #671

Checklist

  • Code compiles correctly
  • Created tests which fail without the change (if possible)
  • All tests passing
  • Extended the README / documentation, if necessary
  • Added myself / the copyright holder to the AUTHORS file

@methane
Copy link
Member

methane commented Nov 14, 2017

I don't like adding new API to MySQLDriver type.
Please add separated type which wraps config object and adding Open() method.

@agruetz
Copy link
Author

agruetz commented Nov 14, 2017

May I ask why you do not like adding it there? Seems like the most logical place to add it give that the connector interface is part of the driver.

I will be happy to make the change just would like to understand the reasoning.

@methane
Copy link
Member

methane commented Nov 14, 2017

MySQLDriver has Open and Connect methods and Cfg member.
And only Connect use Cfg. I feel it's very bad smell.

Adding new Connector type seems better to me.

type Connector {
    Config *Config
}

func (c *Connector) Connect(ctx context.Context) (driver.Conn, error) {
    return connectServer(ctx, c.Config)  // MySQLDriver.Open() can use this function too.
}

func (c *Connector) Driver() driver.Driver {
    return MySQLDriver{}
}

@methane methane changed the title Implement Connector interface #671 Implement Connector interface Nov 14, 2017
@agruetz
Copy link
Author

agruetz commented Nov 22, 2017

Expect the requested changes around 11/27 - 11/28.

@jellevandenhooff
Copy link

Hello, thank you for working on this! It would be great if the Connector API threaded through the context object to the connectServer call so that the initial TCP connection can be given a deadline.

@agruetz
Copy link
Author

agruetz commented Dec 6, 2017

Update to address methane concerns.

@agruetz
Copy link
Author

agruetz commented Feb 21, 2018

I believe this is ready for review. It is at least ready for feed back. Only thing missing is the usage readme.md however I do not want to write that until I am sure there are no major code changes.

@julienschmidt @arnehormann @methane

driver.go Outdated
//Check to see if there was a canelation during creating the connection
select {
case <-cxt.Done():
err = mc.Close()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking ctx.Done() after connectServer() is really required?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do not have to, I debated just doing it once before the connection or just doing it after the connection. Once before is probably the correct/best option. The question really is at what points to do you want to check if there has been a cancelation or deadline hit that this is no longer needed. Ideally you exit as soon as possible as fast as possible. Checking pre-connection is probably adequate.

@agruetz
Copy link
Author

agruetz commented Feb 21, 2018 via email

driver.go Outdated
@@ -73,7 +72,7 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) {
mc.netConn, err = nd.Dial(mc.cfg.Net, mc.cfg.Addr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use nd.DialContext() when context is not nil.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will look at it. I mis-understood this diff on my previous comment. Seems reasonable enough to thread the context thru however I am not sure the best way to do that off hand as the other entry point sql.Open does carry any context and uses this same connectServer function.

@agruetz
Copy link
Author

agruetz commented Feb 22, 2018

@methane feedback incorporated

Copy link
Member

@methane methane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@julienschmidt julienschmidt added this to the v1.5 milestone Mar 3, 2018
@nemith
Copy link
Contributor

nemith commented Mar 17, 2018

Any chance of landing this?

@agruetz
Copy link
Author

agruetz commented Apr 18, 2018

Best I can tell this is complete for the first attempt. I am sure there will be features to add etc... @methane what do you think about finishing this one up and merging it?

@go-sql-driver go-sql-driver deleted a comment from agruetz Apr 19, 2018
errInvalidUser = errors.New("invalid Connection: User is not set or longer than 32 chars")
errInvalidAddr = errors.New("invalid Connection: Addr config is missing")
errInvalidNet = errors.New("invalid Connection: Only tcp is valid for Net")
errInvalidDBName = errors.New("invalid Connection: DBName config is missing")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, "invalid config" is better than "invalid Connection".

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would concur and will make that change.


type MySQLConnector struct {
Cfg *Config
}
Copy link
Member

@methane methane Apr 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer private type and constructor function.

type mysqlConnector *Config

func NewConnector(cfg *Config) (driver.Connector, error) {
    if err := cfg.normalize(); err != nil {
        return nil, err
    }
    // any additional validation here.
    return mysqlConnector(cfg)
}

Then, we can move validation from Connector.Connect() to cfg.normalize().
User can pass config object created by ParseDSN().

//The other optional parameters are not checks
//as GO will automatically enforce proper bool types on the options
if len(c.Cfg.User) > 32 || len(c.Cfg.User) <= 0 {
return nil, errInvalidUser
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this check really needed?
It seems ParseDSN() doesn't check user name length. Empty user name is impossible?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I am aware an empty username will never authenticate. I guess it is not required press as you would just get a return from the server as a bad connection attempt however it does short cut a connection attempt thus using less resources/connections to the mysql server if the user forgets to provide a username. It also gives a very clear error message as to what is wrong.


if len(c.Cfg.DBName) <= 0 {
return nil, errInvalidDBName
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty DB name should be supported.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I concur. I had not thought of the SQL queries that do not require a database. I will correct.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use it when I create monitoring tools. (e.g. SHOW VARIABLES or SHOW FULL PROCESSLIST)


if c.Cfg.Net != "tcp" {
return nil, errInvalidNet
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No "unix"?

@agruetz
Copy link
Author

agruetz commented Apr 27, 2018

@methane just saw all these comments not sure why it said my email address is not monitored. I will review shortly and make appropriate adjustments.

@methane methane mentioned this pull request May 15, 2018
5 tasks
@sheeley
Copy link

sheeley commented May 17, 2018

@agruetz would you like a hand with this? We'd like to adopt this for our own RDS IAM connections as well :)

@agruetz
Copy link
Author

agruetz commented May 18, 2018 via email

@dolmen
Copy link
Contributor

dolmen commented Jun 15, 2018

#778 looks better (with my suggested changes).

@methane
Copy link
Member

methane commented Jun 15, 2018

I prefer connectServer() in this pull request to #778's approach (copy and paste)

@nemith
Copy link
Contributor

nemith commented Jul 11, 2018

What needs to happen on this pull request (or #778) to get it shipped?

Go 1.10 has been released for 145 days already.
Mysql driver is broken for less than trivial username password (#668, #591) with this slated as the fix.

Can we get a core developer to comment on the direction on #778 or this pull request and state the direction to go in? Is there anything I can help out with to push this over (implement requested changes, etc)?

@agruetz
Copy link
Author

agruetz commented Jul 12, 2018

+1 on nemith. I apologize for not having gotten back to this sooner. I have been crazy busy with work and the family. I think we probably just need to sync the two PR's and resolve the merge conflicts and get this merged in. We can always make more features/improvements to it as time goes on. That is my 2 cents. Looks like it is slated for the v1.5 release already. Some direction from what the core dev team like to do would be helpful and we will see what we can do to get this wrapped up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement Connector interface
8 participants