Skip to content

Add Google Cloud SQL support for App Engine. #167

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

Merged
merged 1 commit into from
Nov 14, 2013

Conversation

dalinaum
Copy link
Contributor

@dalinaum dalinaum commented Nov 8, 2013

It uses Cloud SQL as a database if it runs on Google App Engine with using cloudsql DSN.

appengine.go includes a build constraint for GAE to avoid an error outside App Engine.

@@ -0,0 +1,29 @@
// +build appengine
Copy link
Member

Choose a reason for hiding this comment

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

The header should be:

// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// Copyright 2013 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 appengine

package mysql

Same for the other file

@dalinaum
Copy link
Contributor Author

dalinaum commented Nov 8, 2013

OK. I'm fixing my commit. :)

@dalinaum
Copy link
Contributor Author

dalinaum commented Nov 9, 2013

I modified them all.

  • removed appenginedev.go.

  • added a var with a reference to dial function.

    Check my new commit please.

@@ -0,0 +1,30 @@
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
//
// The driver should be used via the database/sql package:
Copy link
Member

Choose a reason for hiding this comment

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

This header is still wrong

@dalinaum
Copy link
Contributor Author

dalinaum commented Nov 9, 2013

Fixed the headers of appengine.go and driver.go. Thanks.

nd := net.Dialer{Timeout: mc.cfg.timeout}
mc.netConn, err = nd.Dial(mc.cfg.net, mc.cfg.addr)
if dialer != nil {
mc.netConn, err = dialer(mc.cfg)
Copy link
Member

Choose a reason for hiding this comment

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

dialershould be named dial since it is a function.

@julienschmidt
Copy link
Member

I'm still not entirely happy with the current approach.
Does anyone have another idea for a clean approach?

@arnehormann
Copy link
Member

Maybe. A var storing the dial function, initialized with the current
implementation. Overwrite it with init in appengine.go - none of this
exported. I'm grocery shopping right now, if the idea is unclear I can
flesh it out later.

Am 09.11.2013 13:16 schrieb "Julien Schmidt" notifications@github.com:

I'm still not entirely happy with the current approach.
Does anyone have another idea for a clean approach?


Reply to this email directly or view it on GitHub.

@dalinaum
Copy link
Contributor Author

dalinaum commented Nov 9, 2013

I tried another approach. I made a Dial map, dials to suppport multiple Dial functions. Adding multiple custom Dials is OK now. It doesn't lead to problems anymore.

If you have another approach let me know. Thanks.

@arnehormann
Copy link
Member

I'd prefer to not export Dial and RegisterDial.
If it's driver-only, we can always export it later - we only have to change the driver.
If it's exported, we can never take it back.
I'd prefer to not get bug reports for external dialers - and motivate pull requests for different implementations.

My other problem with this is that we are not able to test the implementation with Travis. I think that's not really a big deal so far, but it can probably get out of hand.

Maybe we should also store the dial function in the connector, but that's a decision we can still make later.

So for this, LGTM if nothing gets exported and @julienschmidt agrees with me.

@dalinaum
Copy link
Contributor Author

I fixed the commit to not export Dial and RegisterDial. It is replaced by dial and regiterDial. I agree with you.

I don't know how to test the implementation with Travis. Actually I don't know even Travis. I'm wondering what I have to do for advance.

I don't read other part of this library yet. I have to read more later.

Sorry for my poor englih and thanks for your review.

@arnehormann
Copy link
Member

Travis-CI is an integration server. It checks each commit and runs tests on it - it even shows per commit if tests pass. The "build passing" banner underneath the logo in the README are a link to Travis.

It can not be integrated in this case because it doesn't run on Appengine.
Neither I nor - as far as I know - Julien have access to an Appengine, so we can't test whether this does what it says. It sure looks great, but we don't know.

@@ -104,6 +112,10 @@ func (d *MySQLDriver) Open(dsn string) (driver.Conn, error) {
return mc, nil
}

func registerDial(protocol string, d dial) {
Copy link
Member

Choose a reason for hiding this comment

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

Drop this please, assign directly to the map in init.
There are no external users now and a direct assignment is shorter and simpler.

@dalinaum
Copy link
Contributor Author

I fixed again. Dropeed registerDial and assigned directly to the map in init. I tested it locally, got an eror message, tested it on GAE and checked that it works correctly.

@arnehormann
Copy link
Member

LGTM if @julienschmidt agrees

@@ -25,6 +25,9 @@ import (
// This struct is exported to make the driver directly accessible.
// In general the driver is used via the database/sql package.
type MySQLDriver struct{}
type dial func(*config) (net.Conn, error)
Copy link
Member

Choose a reason for hiding this comment

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

Insert a blank line before this type def to seperate it from the previous type def and comment, please

@julienschmidt
Copy link
Member

For most users, the map will never be used. Therefore a lazy initialization of the map would be nice

@dalinaum
Copy link
Contributor Author

Added a blank line before type dial.

Now, I have to modify an initialization of the map.

@dalinaum
Copy link
Contributor Author

Applied a lazy initialization.

)

func init() {
dials = make(map[string]dial)
Copy link
Member

Choose a reason for hiding this comment

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

if dials == nil {
     dials = make(map[string]dial)
}

@dalinaum
Copy link
Contributor Author

I fixed them as you reviewd. Removed an unnecessay type defines and added a condition statement to check if dials is initialized.

@dalinaum
Copy link
Contributor Author

Please let me know what I have to do.

@julienschmidt
Copy link
Member

wait 😃

I don't have time to review you code until tomorrow.

@@ -26,6 +26,8 @@ import (
// In general the driver is used via the database/sql package.
type MySQLDriver struct{}

var dials map[string]func(*config) (net.Conn, error)
Copy link
Member

Choose a reason for hiding this comment

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

Sorry for changing my opinion every day... please reintroduce a type for the dial funcs:

type dialFunc func(*config) (net.Conn, error)
var dials map[string]dialFunc

} else {
nd := net.Dialer{Timeout: mc.cfg.timeout}
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.

if dial, ok := dials[mc.cfg.net]; ok {
        mc.netConn, err = dial(mc.cfg)
} else {
        nd := net.Dialer{Timeout: mc.cfg.timeout}
        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.

Reading from a nil-map is fine, you don't need to check if the map is nil first
http://play.golang.org/p/tBq3LMI0hc

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't know this technique. It's quite interesting. I have to apply it.

It uses Cloud SQL as a database if it runs on Google App Engine with
using cloudsql DSN.

appengine.go includes a build constraint for Google App Engine (GAE)
(http://blog.golang.org/the-app-engine-sdk-and-workspaces-gopath) to
avoid an error outside App Engine and provide an exception. Using
Google Cloud SQL with App Engine GO SDK is not supported yet. It is a
SDK limitation.
@dalinaum
Copy link
Contributor Author

Thanks for your review. I pushed a new commit.

@julienschmidt
Copy link
Member

LGTM now.
Thanks for the PR and your patience!

julienschmidt added a commit that referenced this pull request Nov 14, 2013
Add Google Cloud SQL support for App Engine.
@julienschmidt julienschmidt merged commit c418c1b into go-sql-driver:master Nov 14, 2013
@julienschmidt julienschmidt added this to the v1.2 milestone Apr 1, 2014
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.

3 participants