After connecting to a Planetscale database using DSN with the following structure:
user:password#tcp(host)/database?tls=true
I decided to test it by running a simple query. Here's my main.go file:
package main
import (
"database/sql"
"fmt"
"os"
_ "github.com/go-sql-driver/mysql"
)
func GetDatabase() (*sql.DB, error) {
db, err := sql.Open("mysql", os.Getenv("DSN"))
return db, err
}
func main() {
db, err := GetDatabase()
if err != nil {
panic(err)
}
if err := db.Ping(); err != nil {
panic(err)
}
// ---
query, err := db.Query("SELECT name FROM status;")
if err != nil {
panic(err.Error())
}
var name string
for query.Next() {
err = query.Scan(&name)
if err != nil {
panic(err.Error())
}
fmt.Println(name)
}
// ---
fmt.Println("Successfully connected to PlanetScale!")
}
If I remove the section between the two comment lines, it will print out the 'successfully connected' message; however, if I try to run it including the query part, the outcome changes to:
panic: Error 1046: No database selected
Well, I decided to try with the query:
"USE database; SELECT name FROM status;"
However, the default driver won't take multiple statements and returns syntax error.
I know it seems like a simple question, but I already read the documentation from planetscale, from the go mysql driver, and I haven't been able to overcome this little issue. Any help will be greatly appreciated.
Looks like the problem is with the .env file. If I save the same information to a string variable within the same GetDatabase() function, and then pass it as argument instead of os.Getenv(), it connects normally. Can't tell exactly why that happens, but if someone can provide further information, I'll be thankful.
Edit:
when saving my credentials to an .env file, and using the built-in function os.Getenv("DSN"), the program will indeed connect to planetscale, but it won't select the given database in the DSN string. As mentioned in the question, selecting the database first and then running statements / queries doesn't work because of the constraints of the driver.
If I hard code the variables to a string variable, eg:
dsn := "root:mlc#tcp(127.0.0.1:3306)/app"
and then use that to open the connection, this time the program will use the desired database with any problem.
Related
I'm trying to setup a connection with MySQL server. As you can see I'm trying to make a simple insert but every time I run my program, it seems that it has run the INSERT query two times.
I run my program via command line go run test_sql.go.
package main
import (
"fmt"
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func main() {
fmt.Println("Go MySQL Tutorial")
// Open up our database connection.
// I've set up a database on my local machine using phpmyadmin.
// The database is called testDb
db, err := sql.Open("mysql", "root:PASSWORD#tcp(127.0.0.1:3306)/test1")
// if there is an error opening the connection, handle it
if err != nil {
panic(err.Error())
}
// perform a db.Query insert
insert, err := db.Query("INSERT INTO TEST VALUES ( 1, 'TEST' )")
// if there is an error inserting, handle it
if err != nil {
panic(err.Error())
}
// be careful deferring Queries if you are using transactions
defer insert.Close()
// defer the close till after the main function has finished
// executing
defer db.Close()
}
github.com/ory/ladon is a library to manage role based access, written in golang. It contains a manager that is supposed to persist policies in the database and work with the database. The manager works fine for the in-memory case. When I use the manager to interface with sql, the required tables are not getting created.
db, err := sqlx.Open("mysql", "tx81:#tcp(127.0.0.1:3306)/policies")
......
err=db.Ping()
if err == nil {
fmt.Printf("Database is up")
}
warden := ladon.Ladon{
Manager: manager.NewSQLManager(db, nil),
}
var pol = &ladon.DefaultPolicy{
......
}
err = warden.Manager.Create(pol)
fmt.Printf("%s", err)
The error is printed as:
Table 'policies.ladon_policy' doesn't exist.
Why aren't the tables getting created?
Resources: https://github.com/ory/ladon#persistence
You need to call manager.CreateSchemas, which is never done by the manager itself.
You provide it with the schema name (postgresql only I believe) and table name to keep track of migration info.
eg:
if num, err := m.CreateSchemas("", "my_migration_table"); err != nil {
panic(err)
} else {
log.Infof("ran %d migrations", num)
}
It could probably use more documentation, you may want to file an issue with the author.
All the answers for something like this are in Javascript, and I'm not sure if it applies in Go.
I've done this
func main() {
db, err := sql.Open("mysql", "db_details")
err = db.Ping()
if err != nil {
fmt.Println("Failed to prepare connection to database")
// log.Fatal("Error:", err.Error())
}
apex.HandleFunc(func(event json.RawMessage, ctx *apex.Context) (interface{}, error) {
fmt.Println(ctx)
return map[string]string{"hello": "world"}, nil
})
}
So I'm trying to hit my Amazon RDS MySql db using golang's sql driver.
I get this error
Error: function response: Response Id: <some_id> Process exited before completing request
From looking around, there are two causes - 1. I need Go's equivalent of context.done, or 2. I need to raise the timeout.
As I'm using Apex, I raised the timeout to be 300s, which is the maximum. No luck there.
I then tried going through the Apex code to see if there was a Context.Done defined or used anywhere - there isn't.
How do I get around this?
I'm trying to work out a bit of code to pull in config from a JSON file.
When I attempt to build, I get this error
type ConfigVars is not an expression
Below is the config and program code I'm trying to work with. Every example I've found so far is similar to the below code. Any suggestion of what I'm doing incorrectly?
-- Config File
{"beaconUrl":"http://test.com/?id=1"}
-- Program Code
package main
import (
"encoding/json"
"fmt"
"os"
)
type ConfigVars struct {
BeaconUrl string
}
func main() {
configFile, err := os.Open("config.json")
defer configFile.Close()
if err != nil {
fmt.Println("Opening config file", err.Error())
}
jsonParser := json.NewDecoder(configFile)
if err = jsonParser.Decode(&ConfigVars); err != nil {
fmt.Println("Parsing config file", err.Error())
}
}
What you're doing there is trying to pass a pointer to the ConfigVars type (which obviously doesn't really mean anything). What you want to do is make a variable whose type is ConfigVars and pass a pointer to that instead:
var cfg ConfigVars
err = jsonParser.Decode(&cfg)
...
For others who come onto this problem, you may find that you've forgotten to initialize the variable during assignment using the := operator, as described in Point 3 at the end of this GoLang tutorial.
var cfg ConfigVars
err := jsonParser.Decode(&cfg)
I am trying to connect to a mysql database.
I tried to see if I would get an error if I gave it wrong connection information but it still returns nil as error. Even If I shut down mysql completely it still does not return an error. What is the point of check for errors after this function if it does not return errors?
This is on Windows, I am using XAMPP and I don't have a password for the database. Username is "root".
import (
"database/sql"
"log"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "root#tcp(127.0.0.1:3306)/dbname?charset=utf8")
if err != nil {
log.Fatal(err)
}
defer db.Close()
}
SQL.Open only creates the DB object, but does not open any connections to the database. If you want to test your connections you have to execute a query to force opening a connection. The common way for this is to call Ping() on your DB object.
See http://golang.org/pkg/database/sql/#Open and http://golang.org/pkg/database/sql/#DB.Ping
Quoting from the doc of sql.Open():
Open may just validate its arguments without creating a connection to the database. To verify that the data source name is valid, call Ping.
As stated, Open() may not open any physical connection to the database server, but it will validate its arguments. That being said if arguments are valid, it may return nil error even if the database server is not reachable, or even if the host denoted by dataSourceName does not exist.
To answer your other question:
What is the point of check for errors after this function if it does not return errors?
You have to check returned errors because it can return errors. For example if the specified driverName is invalid, a non-nil error will be returned (see below).
To test if the database server is reachable, use DB.Ping(). But you can only use this if the returned error is nil, else the returned DB might also be nil (and thus calling the Ping() method on it may result in run-time panic):
if db, err := sql.Open("nonexistingdriver", "somesource"); err != nil {
fmt.Println("Error creating DB:", err)
fmt.Println("To verify, db is:", db)
} else {
err = db.Ping()
if err != nil {
fmt.Println("db.Ping failed:", err)
}
}
Output (try it on the Go Playground):
Error creating DB: sql: unknown driver "nonexistingdriver" (forgotten import?)
To verify, db is: <nil>
It turns out that this does not actually connect to the database right away.
Source: http://go-database-sql.org/accessing.html
To check the validity of connection, we can do this:
db, err := sql.Open("mysql", "root#tcp(127.0.0.1:3306)/dbname?charset=utf8")
err = db.Ping() // Need to do this to check that the connection is valid
if err != nil {
log.Fatal(err)
}