Skip to content

Added a method to create a mysql database from a connection object - #583

Merged
dhui merged 4 commits into
golang-migrate:masterfrom
Seb-C:mysqlWithConnection
Jul 6, 2021
Merged

dhui merged 4 commits into
golang-migrate:masterfrom
Seb-C:mysqlWithConnection

Conversation

@Seb-C

@Seb-C Seb-C commented Jun 17, 2021

Copy link
Copy Markdown
Contributor

This PR implements #578 by adding the WithConnection method to the MySQL driver.

I could test and verify that it works. However, I don't have the environment or time to provide and test the same change on all other drivers, so it creates a small inconsistency. How do you want to proceed?

@coveralls

coveralls commented Jun 17, 2021 •

Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 492

  • 24 of 28 (85.71%) changed or added relevant lines in 1 file are covered.
  • 578 unchanged lines in 14 files lost coverage.
  • Overall coverage increased (+0.3%) to 57.462%

Changes Missing Coverage Covered Lines Changed/Added Lines %
database/mysql/mysql.go 24 28 85.71%
Files with Coverage Reduction New Missed Lines %
database/stub/stub.go 6 71.93%
database/ql/ql.go 25 62.65%
database/sqlcipher/sqlcipher.go 25 66.48%
database/sqlite3/sqlite3.go 25 66.48%
database/sqlite/sqlite.go 25 66.48%
database/firebird/firebird.go 30 75.3%
database/cassandra/cassandra.go 42 45.89%
database/redshift/redshift.go 45 67.43%
database/sqlserver/sqlserver.go 47 67.76%
database/mongodb/mongodb.go 55 73.83%
Totals Coverage Status
Change from base Build 468: 0.3%
Covered Lines: 3623
Relevant Lines: 6305

💛 - Coveralls

@dhui dhui left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the PR!

Comment thread database/mysql/mysql.go Outdated
return mx, nil
}

func (m *Mysql) setupDefaultConfig() error {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you move all of this logic to WithConnection(). Then inside WithInstance() we can call WithConnection() and set m.db = instance.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Aha, I considered both designs and I seem to have picked the wrong one 😭
I'll change this ASAP, thanks for your review.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done!
By the way, I just reminded why I chose the previous pattern: It's because now I need WithConnection to return a *Mysql type instead of database.Driver.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do you need a *Mysql?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Because WithInstance needs to set mx.db

@dhui

dhui commented Jun 25, 2021

Copy link
Copy Markdown
Member

I could test and verify that it works. However, I don't have the environment or time to provide and test the same change on all other drivers, so it creates a small inconsistency. How do you want to proceed?

This is fine. We can add WithConnection() to other DB drivers as needed/requested.

@Seb-C
Seb-C force-pushed the mysqlWithConnection branch from 1b8c309 to 394279a Compare June 29, 2021 07:30

@dhui dhui left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for addressing my feedback!

Comment thread database/mysql/mysql.go

// instance must have `multiStatements` set to true
func WithInstance(instance *sql.DB, config *Config) (database.Driver, error) {
if err := instance.Ping(); err != nil {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Move this to WithConnection() and use conn.PingContext(). DB.Ping() will create a connection to ping anyways

@Seb-C Seb-C Jun 30, 2021 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The problem I am trying to solve is that this class does unexpected stuff to my connection pool.
If I inject an active pool with n idle connections to this class, do my stuff and close it, I expect my pool to be returned to it's initial state, which means an active pool with n idle connections.
But currently I can only choose between ending-up with a closed pool (because Close not only returns the connection to the pool, but also closes the pool itself), or (if I don't call Close) a pool with n-1 idle connections and 1 allocated connection that will be stuck forever

So the last thing I want is for WithConnection to create new connections in a pool that I did not even inject in the first place.

If the connection I inject is not working, I expect the process to fail without side-effects on my pool.

If the connection is not working, doing conn.PingContext().DB.Ping() would create a new connection in the pool and ping the new connection, which does not test or fix the injected one anyway.

@dhui dhui Jun 30, 2021 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My understanding is that connections are pooled at the sql.DB instance level so conn.PingContext() shouldn't create a new connection e.g. connections won't create new connections

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I was misunderstanding your question.
I added the context to WithConnection, as well as calling PingContext.
I cannot add it as a parameter in WithInstance without breaking change, so it should be done along with #14.

Comment thread database/mysql/mysql.go Outdated
// instance must have `multiStatements` set to true
func WithInstance(instance *sql.DB, config *Config) (database.Driver, error) {
// connection instance must have `multiStatements` set to true
func WithConnection(conn *sql.Conn, config *Config) (*Mysql, error) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thoughts on making this context aware? Eventually, we want most DB driver methods to be context aware. I'm thinking that new methods should be context aware.

Also, unfortunately, these functions that create DB drivers currently return interfaces instead of concrete times. I'm thinking returning a concrete type as you're doing now is a cleaner pattern. Can you add a type check? e.g. var _ database.Driver = (*Mysql)(nil) // explicit compile time type check

@Seb-C Seb-C Jun 30, 2021 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

If it's consistent across all drivers, then it would be a good thing. But it seems out of scope for this PR.

Can you add a type check?

Sorry, I don't understand what you are asking. Where do you want this check?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If it's consistent across all drivers, then it would be a good thing. But it seems out of scope for this PR.

Oh yeah, making the db drivers consistent is not in the scope of the PR. But new code should fit within the future plans/vision if possible. In this case, we should add a ctx context.Context parameter to WithConnection()

Can you add a type check?

Sorry, I don't understand what you are asking. Where do you want this check?

Add var _ database.Driver = (*Mysql)(nil) // explicit compile time type check as a package level ignored variable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

OK, I understood your point.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done (both of it).

@dhui dhui mentioned this pull request Jun 29, 2021

@dhui dhui left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks again for the PR and for addressing my feedback!

@dhui
dhui merged commit 31cedbb into golang-migrate:master Jul 6, 2021
@Seb-C

Seb-C commented Jul 8, 2021

Copy link
Copy Markdown
Contributor Author

@dhui Thanks for merging my PR 🎉
Do you have any timeline about the next version release?
I need to plan if I reference the commit hash in my go.mod file or wait for the v4.14.2 being released.

@dhui

dhui commented Jul 8, 2021

Copy link
Copy Markdown
Member

Release are blocked, so use the commit hash

@dhui

dhui commented Aug 6, 2021

Copy link
Copy Markdown
Member

v4.15.0-beta.1 was released recently. v4.15.0 to follow soon.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants