Can't connect Go to XAMPP MySQL - mysql

I'm new to Go.
I'm trying to use MySQL with Go.
I have installed XAMPP which has Apache and MySQL.
I'm also using the database/sql package and github.com/go-sql-driver/mysql driver.
I can't figure out the error. I'm using LiteIDE which doesn't show any error but the record is not inserted to my database.
My code is:
// RESTAPI project main.go
package main
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
_ "github.com/go-sql-driver/mysql"
"github.com/gorilla/mux"
)
type API struct {
Message string "json:message"
}
type User struct {
ID int "json:id"
Name string "json:username"
Email string "json:email"
First string "json:first"
Last string "json:last"
}
func CreateUser(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln("Create file")
NewUser := User{}
NewUser.Name = r.FormValue("user")
NewUser.Email = r.FormValue("email")
NewUser.First = r.FormValue("first")
NewUser.Last = r.FormValue("last")
output, err := json.Marshal(NewUser)
fmt.Println(string(output))
if err != nil {
fmt.Println("Something went wrong!")
}
dsn := "root:password#/dbname"
db, err := sql.Open("mysql", dsn)
sql := "INSERT INTO users set user_nickname='" + NewUser.Name + "', user_first='" + NewUser.First + "', user_last='" + NewUser.Last + "', user_email='" + NewUser.Email + "'"
q, err := db.Exec(sql)
if err != nil {
log.Fatal(err)
}
fmt.Println(q)
fmt.Println("User is created")
}
func main() {
routes := mux.NewRouter()
routes.HandleFunc("/api/user/create", CreateUser).Methods("GET")
http.ListenAndServe(":8080", nil)
}

As Tom mentioned, you should check for an error after sql.Open:
db, err := sql.Open("mysql", dsn)
if err != nil {
log.Fatal(err)
}
PS. Never use string concatenations in SQL.
To prevent SQL injections you should use prepared statements:
sql := "INSERT INTO users set user_nickname='?', user_first='?', user_last='?', user_email='?'"
q, err := db.Exec(sql, NewUser.Name, NewUser.First, NewUser.Last, NewUser.Email)

Related

Calling Stored Procedure in GoLang with QueryRowContent

Im trying to run the below code segment and keeps throwing the below error from QueryRowContext
sql: expected 0 arguments, got 2
This approach works with plain SQL queries and I keep getting the issue when I try to call a Stored Prod to the query param with the CALL keyword.
import (
"database/sql"
"net/http"
)
func VerifyUser(user User) (*User, string, error) {
db, ctx := db.GetDB()
query := "CALL usp_GetUserByUsername(#Email)"
stmt, err := db.Prepare(query)
if err != nil {
log.Errorln("Error in preparing statement. " + err.Error())
return nil, "Error in preparing statement.", err
}
defer stmt.Close()
row := stmt.QueryRowContext(ctx, sql.Named("Email", user.Email))
var retUser User
err = row.Scan(&retUser.ID, &retUser.Email, &retUser.Password, &retUser.Status)
if err != nil {
log.Warningln("Unknown Email: " + user.Email + ". " + err.Error())
return nil, "Invalid user.", err
}
What seems to be wrong here? Thanks in advance.
import (
"database/sql"
"net/http"
)
func VerifyUser(user User) (*User, string, error) {
db, ctx := db.GetDB()
query := "CALL usp_GetUserByUsername(?)"
stmt, err := db.Prepare(query)
if err != nil {
log.Errorln("Error in preparing statement. " + err.Error())
return nil, "Error in preparing statement.", err
}
defer stmt.Close()
row := stmt.QueryRowContext(ctx, user.Email)
var retUser User
err = row.Scan(&retUser.ID, &retUser.Email, &retUser.Password, &retUser.Status)
if err != nil {
log.Warningln("Unknown Email: " + user.Email + ". " + err.Error())
return nil, "Invalid user.", err
}
Replace #Email in your query with ? and pass the email into QueryRowContext not named statement

golang sql.open() expects 0 arguments got 1

I am trying to connect to a mysql database I have locally, using golang, it builds just fine but running it gives me the following error:
panic: sql: expected 0 arguments, got 1
My connection looks like this:
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func DBConn() {
team := "software"
db, err := sql.Open("mysql", "root:12345678#tcp(localhost:3306)/flexlocal")
if err != nil {
fmt.Println("this is where it all went wrong")
fmt.Printf(err.Error())
panic(err)
}
}
According to my research this is how it works however it just isn't working for me.
Please try dbconn function to connect with mysql in go
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func dbConn(setDatbaseInstance string) (db *sql.DB) {
dbDriver := "mysql"
dbUser := "*****"
dbPass := "*****"
dbName := "*****"
db, err := sql.Open(dbDriver, dbUser+":"+dbPass+"#tcp("+setDatbaseInstance+":3306)/"+dbName)
if err != nil {
fmt.Printf("%#v\n DB_ERROR_CONNECTION\n", err.Error());
// return err.Error()
}else{
fmt.Println("Connection Established")
}
erro:=db.Ping()
if erro!=nil {
//do something here
fmt.Printf("%#v\n DB_PING_ERROR_CONNECTION\n", erro.Error());
}
return db
}

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
}
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.

How to ping remote mysql using golang

I am using go to ping some Linux machines.
But it is not work accurate, because it always needs almost 10 seconds to connect the remote mysql.
I use this command:
mysql -u USER -p PASSWORD -h REMOTE_IP
So i want to know how to use linux command to know whether it open or not.
Then I will use golang 's exec.Command to do that .
Here is my ping code:
package main
import (
"errors"
"fmt"
"github.com/tatsushid/go-fastping"
"net"
"net/smtp"
"strings"
"time"
)
func main(){
err := ping("192.168.2.1")
if err != nil{
fmt.Println("WARNING!!!!!!")
}
}
func ping(ip string) error {
p := fastping.NewPinger()
ra, err := net.ResolveIPAddr("ip", ip)
if err != nil {
return err
}
p.AddIPAddr(ra)
found := false
p.OnRecv = func(addr *net.IPAddr, rtt time.Duration) {
found = true
}
err = p.Run()
if err != nil {
return err
}
if !found {
return errors.New("response error")
}
return nil
}
I assume you want to know if mysql is reachable or not. You can use following example:
package main
import (
"database/sql"
"flag"
"fmt"
"log"
_ "github.com/go-sql-driver/mysql"
)
func main() {
var (
server = flag.String("mysql", "localhost:3306", "mysql server")
user = flag.String("user", "root", "mysql user")
pass = flag.String("password", "", "mysql password")
)
flag.Parse()
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s#tcp(%s)/", *user, *pass, *server))
if err != nil {
log.Fatalln(err)
}
defer db.Close()
err = db.Ping()
if err != nil {
log.Fatalln(err)
} else {
log.Println("mysqld is alive")
}
}
If you just need to check connection to a specific host & port, you can do this as:
package main
import (
"fmt"
"net"
)
const (
host = "192.168.2.1"
port = "3306" // default MySQL port
)
func main() {
conn, err := net.Dial("tcp", host+":"+port)
if err != nil {
panic(err)
}
defer conn.Close()
fmt.Printf("Connected to %s \n", conn.RemoteAddr().String())
}

Neo4j cq driver failed with "Unrecognized transaction id. Transaction may have timed out and been rolled back."

I have recently moved our staging environment from a neo4j 2.2.2 community edition docker container to a 2.3.0-RC1 HA cluster.
This go script provides an API end-point for authenticated users to upload a csv file which then gets processed in a way that it matches the id of a product (upc) with the existing product data. On a match the user's associated distributor creates a relationship to the found product and adds information available in the csv file onto that created relationship.
My problem is that I'm getting a failure from Neo4j in the new environment that I can't track down: "Unrecognized transaction id. Transaction may have timed out and been rolled back." when the user tries to upload the file.
Here's the complete script (my second golang script, so pointers on style are welcome, too).
package main
import (
"database/sql"
"encoding/csv"
"fmt"
_ "gopkg.in/cq.v1"
_ "gopkg.in/cq.v1/types"
"net/http"
"os"
"strconv"
"strings"
)
type ProductInfo struct {
Upc uint64
InStock uint64
BasePrice float64
LeadMin uint64
LeadMax uint64
Sku string
}
func uploadHandler(w http.ResponseWriter, r *http.Request) {
file, _, err := r.FormFile("file")
if err != nil {
fmt.Fprintln(w, err)
return
}
defer file.Close()
distributor := strings.Split(r.URL.Path, "/")[2]
reader := csv.NewReader(file)
reader.FieldsPerRecord = 6
reader.TrimLeadingSpace = true
rawCSVdata, err := reader.ReadAll()
if err != nil {
fmt.Fprintln(w, err)
return
}
db, err := sql.Open("neo4j-cypher", os.Getenv("MINAMI_NEO4J_URL"))
if err != nil {
fmt.Fprintln(w, err)
return
}
defer db.Close()
tx, err := db.Begin()
if err != nil {
fmt.Fprintln(w, err)
return
}
stmt, err := tx.Prepare(`
MATCH (d:Distributor {slug:'` + distributor + `'})
MATCH (p:Product {upc: {0}})
MERGE (d)-[r:SELLS]->(p)
SET r.inStock = {1}, r.sellsFor = {2}, r.leadMin = {3}, r.leadMax = {4}, r.sku = {5}
RETURN p LIMIT 1
`)
if err != nil {
fmt.Fprintln(w, err)
return
}
var Row ProductInfo
for _, each := range rawCSVdata {
Row.Upc, _ = strconv.ParseUint(each[0], 10, 0)
Row.InStock, _ = strconv.ParseUint(each[1], 10, 0)
Row.BasePrice, _ = strconv.ParseFloat(each[2], 0)
Row.LeadMin, _ = strconv.ParseUint(each[3], 10, 0)
Row.LeadMax, _ = strconv.ParseUint(each[4], 10, 0)
Row.Sku = each[5]
stmt.Exec(Row.Upc, Row.InStock, Row.BasePrice, Row.LeadMin, Row.LeadMax, Row.Sku)
}
err = tx.Commit()
if err != nil {
fmt.Fprintln(w, err)
return
}
fmt.Fprintf(w, "File uploaded and products in store updated.")
}
func main() {
http.HandleFunc("/", uploadHandler)
http.ListenAndServe(":8888", nil)
}
I'm using haproxy to know who's master and who are the slaves in the HA cluster. The environment variable MINAMI_NEO4J_URL is set to the master via haproxy in this form: http://{haproxyip}:{masterport}