Search code examples
mysqlgoogle-app-enginegoogle-cloud-sql

How do I select the database to query when using Cloud SQL through App Engine?


I get the following error:

Could not query db: Error 1046: No database selected

I understand what the error message means. But I haven't been able to find the documentation where it says how to select a database.

Here is my code:

package main

import (
    "database/sql"
    "fmt"
    "log"
    "net/http"
    "os"
    "time"

    "google.golang.org/appengine"

    _ "github.com/go-sql-driver/mysql"
)

var db *sql.DB

func main() {
    var (
        connectionName = mustGetenv("CLOUDSQL_CONNECTION_NAME")
        user           = mustGetenv("CLOUDSQL_USER")
        password       = os.Getenv("CLOUDSQL_PASSWORD")
    )

    var err error
    db, err = sql.Open("mysql ", fmt.Sprintf("%s:%s@cloudsql(%s)/", user, password, connectionName))
    if err != nil {
        log.Fatalf("Could not open db: %v", err)
    }

    http.HandleFunc("/", handler)
    appengine.Main()
}

func handler(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/" {
        http.NotFound(w, r)
        return
    }

    w.Header().Set("Content-Type", "text/plain")

    rows, err := db.Query("INSERT INTO ping ( ping ) VALUES ( '" + time.Now().Format("2006-01-02 03:04:05") + "' );")
    if err != nil {
        http.Error(w, fmt.Sprintf("Could not query db: %v", err), 500)
        return
    }
    defer rows.Close()

    w.Write([]byte("OK"))
}

func mustGetenv(k string) string {
    v := os.Getenv(k)
    if v == "" {
        log.Panicf("%s environment variable not set.", k)
    }
    return v
}

Solution

  • It looks like you specified the CONNECTION_NAME, but not the DB_NAME. According to the documentation (scroll down to the "GO > Companion process" section), you should open the connection as:

    import (
            "github.com/go-sql-driver/mysql"
    )
    
    dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s",
           dbUser,
           dbPassword,
           "127.0.0.1:3306",
           dbName)
    db, err := sql.Open("mysql", dsn)
    

    This piece of code resembles yours, but you did not specify the dbName parameter. Bear in mind that the rest of the configuration should remain the same as you shared in your code, but you should just append the name of your database to the second parameter of the sql.Open() function.

    In the example of connecting from App Engine Flexible to Cloud SQL using GO, the same procedure is identified:

    db, err = sql.Open("mysql", dbName)
    

    So I guess you should try with this change:

    // Old connection opening
    db, err = sql.Open("mysql ", fmt.Sprintf("%s:%s@cloudsql(%s)/", user, password, connectionName))
    // New connection opening, including dbName
    db, err = sql.Open("mysql ", fmt.Sprintf("%s:%s@cloudsql(%s)/%s", user, password, connectionName, dbName))
    

    I am not really familiar with GoLang myself, but according to the documentation, that should work.