Go - Connecting to a external mysql database - mysql

I'm rather new to use go and am having issues connecting to an external mysql database.
I'm using the go-sql-driver which seams rather nice. Suggestions to other drivers are welcomed!
this is the whole program:
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
)
const (
DB_HOST = "tcp(http://thedburl.com)"
DB_NAME = "nameofdatabase"
DB_USER = "username"
DB_PW = "password"
)
func main() {
dsn := DB_USER + ":" + DB_PW + "#" + DB_HOST + "/" + DB_NAME + "?charset=uf8"
db, err := sql.Open("mysql", dsn)
if err != nil {
fmt.Println("shiiet didn't work yo! Initialization failed")
}
defer db.Close() // go's purty cool
var str string
q := "SELECT * FROM forums"
err = db.QueryRow(q).Scan(&str)
if err != nil {
fmt.Println(err)
}
fmt.Println(str)
}
On the request I'm recieving the following error
"GetAddrInfoW: The specified class was not found."
Any ideas? I've siting for hours on the webs, and can't seem to solve the problem.
It might be worth noting that I have used the same database service many times in java.

Interestingly, this error can be also caused by spaces in the server port as in server.Run(":8080 ") vs server.Run(":8080")

Thanks for everyones answers.
The mysql drivers for Go are at the current time having a hard time dealing with older mysql versions. Specifically this issue happened due to the incompatibility of mysql's old_password from 2006. Therefore working with older databases is a pain. (source: https://github.com/go-sql-driver/mysql/wiki/old_passwords) - My educated guess also applies to the mymysql driver whom throws the "bad connection" error. Which basicly times out after repetitive attempts of connection.
Special thanks to #Lepidosteus who's answer made me discover the real problem.

Related

How do you use URL.Query().Get() to fill in a SELECT statement using Golang

func startHandler(w http.ResponseWriter, r *http.Request) {
conn_str := dbuser + ":" + dbpass + "#tcp(" + dbhost + ":" + dbport + ")/" + dbdb
log.Println(conn_str)
db, err := sql.Open("mysql", conn_str)
if err != nil {
log.Println("DB Error - Unable to connect:", err)
}
defer db.Close()
table := r.URL.Query().Get("table")
rows, _ := db.Query("SELECT * FROM "+ table) //selects all columns from table
cols, _ := rows.Columns()
fmt.Fprintf(w, "%s\n", cols)
When i try this, it does not fill in the value that i entered from my website. If i log.Println(table) it does show in my terminal. But it will not display on website or fill in the select statement with table...
Assuming you are calling this from an API, there a few things I would add, not mention avoiding wildcard (*) selects.
EDIT: I think I may have misunderstood your question, I will see if I can give a better answer.
You're saying that you have a printed value for table, but no response from the DB? Other commentor is correct, instead of "_", get a real error and fmt.Println(err.Error()).
EDIT 2: Another good point made by #jub0bs is that this is a huge vulnerability. Go supports this very well by allowing you to do:
db.Query("SELECT * FROM ?",table)
instead of what you have currently.
I just ran the following code:
results,err := publicDB.Query("SELECT * FROM "+r.URL.Query().Get("name"))+" LIMIT 1"
if err != nil {
fmt.Println(err.Error())
}
for results.Next(){
fmt.Println(results.Columns())
}
and it worked. I called the URL www.mysite.com/endpoint?name=tablename

Why doesn't the user type get populated with the data values from mysql table? [duplicate]

This question already has an answer here:
Gorm always return structs with nil values
(1 answer)
Closed 3 years ago.
I am trying to get started with GORM and did a simple select SQL query as shown below. The debug logs show that two records were returned but as I try to inspect the users type, it just prints empty. What could be the reason for this? (There is definitely data in the table as shown in the logs which say 2 records returned)
package main
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
)
type User struct {
gorm.Model
username string
password string
}
func main() {
db, err := gorm.Open("mysql","root:1234#(localhost)/database_test")
db.LogMode(true)
defer db.Close()
if err != nil {
panic("failed to connect to the database")
}
var users User
db.Table("user").Find(&users)
fmt.Println("after finding the user")
fmt.Println("user ", users.username)
}
The field names username and password start with a lowercase letter, which makes them unexported. Unexported identifiers cannot be accessed from other packages (in this case github.com/jinzhu/gorm).
Rename them to Username and Password to export them.

Check if database table exists using golang

I am trying to do a simple thing, check if there is a table, if not then create that table in database.
Here this is the logic I used.
test := "June_2019"
sql_query := `select * from ` + test + `;`
read_err := db.QueryRow(sql_query, 5)
error_returned := read_err.Scan(read_err)
defer db.Close()
if error_returned == nil {
fmt.Println("table is there")
} else {
fmt.Println("table not there")
}
In my database I have June_2019 table. But still this code returns me not nil value. I used db.QueryRow(sql_query, 5) 5 as I have five colomns in my table.
What am I missing here? I am still learning golang.
Thanks in advance.
I have solved the problem using golang and MySQL.
_, table_check := db.Query("select * from " + table + ";")
if table_check == nil {
fmt.Println("table is there")
} else {
fmt.Println("table not there")
}
I have used db.Query() which returns values and and error, here I checked only error.
I think most people thought I want to do it in MySQL way, I just wanted to learn how to use golang to do MySQL operations.

golang mysql driver failing at parameter replacement

OS Mojave,
MySQL v8.0.15,
go 1.12.3 darwin/amd64
import (
"database/sql"
// import mysql driver anonymously (just run the init)
_ "github.com/go-sql-driver/mysql"
)
...
_, err = db.db.Exec("USE ?", "test")
if err != nil {
return errors.Wrapf(err, "error selecting database %s", opt.Database)
}
_, err = db.db.Prepare("SELECT value FROM ? WHERE key = ?")
if err != nil {
return errors.Wrap(err, "error generating SELECT statement")
}
The error I get is error selecting database test: Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1
I get the same error (about syntax around '?') for any parameter replacement I attempt to do. I've checked the manual as well as tutorials and examples I've found online and can't quite tell what I'm doing wrong.
If I replace the '?'s with values (strings) then everything works fine.
Question marks ? in prepared statements are for values, not table, database or column names.
Use fmt.Sprintf to fill in the database structure related values.
Example:
_, err := db.db.Prepare(fmt.Sprintf("SELECT value FROM %s WHERE key = ?", table))

Go MySql driver doesn't set time correctly

I have been developing a micro service that interact mysql for a while in golang, and i love this talented language. Anyway have a problem and do not know where is the problem, in my code, in mysql driver else in mysql. So my machine timezone utc+3, i am sharing some result may be it helps
//created_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
mysql> select now();
"2016-11-07 22:43:02", //that is correct.
in go
fmt.PrintLn(time.Now().Local())
"2016-11-07 22:51:02" //that is correct too
But when i added the entity into db, mysql workbench shows me wrong datetime.
"2016-11-07 19:51:02" //
Go code:
func (this *AppLogHandler) addLog(_log *AppLog) (int64, error){
fmt.Println("addLog")
db:= this.Context.DB
stmt, err := db.Prepare("INSERT tbl_logs SET user_id=?,ip_proxy=?, ip_original=?, end_point=?, http_method=?, message=?, status=?, created_date=?")
if(err != nil){
log.Println(err)
return -1, err
}
defer stmt.Close()
res, err := stmt.Exec(&_log.UserID, &_log.IPProxy, &_log.IPOriginal, &_log.Endpoint, &_log.HttpMethod, &_log.Message, &_log.Status, &_log.CreatedDate)
if(err != nil){
log.Println(err)
return -1, err
}
return res.LastInsertId()
}
/// some code here
app_log := AppLog{}
app_log.IPProxy = r.RemoteAddr
app_log.IPOriginal = r.Header.Get("X-Forwarded-For")
app_log.CreatedDate = time.Now().Local()
app_log.UserID = user_id
app_log.Endpoint = r.URL.Path
app_log.HttpMethod = r.Method
fmt.Println(app_log.CreatedDate)
return this.addLog(&app_log)
So guys i need your helps. I couldn't solve the problem for hours.
mysql=> Ver 14.14 Distrib 5.7.15, for osx10.11 (x86_64) using EditLine wrapper
go => 1.7
mysql driver => 1.2, https://github.com/go-sql-driver/mysql/
The mysql driver has a configuration parameter for the default time zone, which you can set to time.Local (the default is time.UTC). When you are saving the value, it first converts the time stamp to the UTC time zone and then sends it off to the database.
As has been already stated in the comments, a much more robust approach would be to accept the default Loc, and standardize on UTC in the database. This greatly simplifies anything having to do with date math further down the line, and doesn't make assumptions about the time zone of the person viewing the data if you just convert it from UTC to local when displaying the value.