how to excute conjunctive query crossing two mysql databases with gorm? - mysql

code like:
addr:=fmt.Sprintf(`%v:%v#tcp(%v:%v)/(%v,%v)?charset=utf8`, dbuser, dbpassword, dbhost, dbport, dbdatabase)
DB, err = gorm.Open("mysql", addr)
sql := "select * from db1.user join db2.salary"
rows, err := DB.Raw(sql).Rows()
it seems the method gorm.Open() only accept one source parameter, and it run error "unknown table name 'db1.user'"
is there a correct way to init the DB to excute the sql or other way to solve the problem?
many thanks

sovled by setting dbdatabase="" , which it means giving null database name connecting to the mysql instance. And database name shoud be presented as prefix on table name in sql.

Related

How to switch between databases using GORM in golang?

I'm new to GORM in golang. I'm stuck at a point. Generally we select the database like this:
DBGorm, err = gorm.Open("mysql", user:password#tcp(host:port)/db_name)
But my problem is I'll get the 'db_name' in the request, which means I don't know which db_name might come and I'll have to query according to that db_name.
So now, I'll create the database pointer in the init function like this:
DBGorm, err = gorm.Open("mysql", user:password#tcp(host:port)/) which is without the db_name.
Now how will I switch to db_name coming to me in request. Because when I try to do DBGorm.Create(&con), it shows No database selected.
If I use 'database/sql', then I can make raw queries like this: "SELECT * FROM db_name.table_name", this can solve my problem. But how to do this in gorm?
You can explicitly specify db_name and table_name using .Table() when doing query or other operation on table.
DBGorm.Table("db_name.table_name").Create(&con)
I saw a related article on Github. https://github.com/go-sql-driver/mysql/issues/173#issuecomment-427721651
All you need to do is
start a transaction,
set you database
run your desired query.
and switch back to your desired DB
commit once you are done.
below is an example
tx := db.Begin() // start transaction
tx.Exec("use " + userDB) // switch to tenant db
tx.Exec("insert into ....") // do some work
tx.Exec("use `no-op-db`") // switch away from tenant db (there is no unuse, so I just use a dummy)
tx.Commit() // end transaction

Is there a right way to connect to MySQL?

I've come across documentation that says:
the sql.DB object is designed to be long-lived. Don’t Open() and
Close() databases frequently. Instead, create one sql.DB object for
each distinct datastore you need to access
source
And doing some poking around I mostly found code opening the connection in the handler file as so
func dbConn() (db *sql.DB) {
dbDriver := "mysql"
dbUser := "root"
dbPass := "root"
dbName := "goblog"
db, err := sql.Open(dbDriver, dbUser+":"+dbPass+"#/"+dbName)
if err != nil {
panic(err.Error())
}
return db
}
source
And to access the db
db := dbConn()
This is called in the functions that need to use it, to my understanding this would open the connection and then close it when it reaches the end of said function.
Wouldn't this be violating the quote above?
The example is simply poorly written, and Yes you shouldn't Open and Close unless its different datastores.
Open returns DB and
DB is a database handle representing a pool of zero or more underlying connections. It's safe for concurrent use by multiple goroutines

Config for GoLang Returns "non-name" error

I am having trouble compiling code Google-Cloud offers on connecting to a mysql database remotely using Golang.
The code is a direct copy-paste from here: https://cloud.google.com/sql/docs/mysql/connect-external-app#go. One may also look here: https://github.com/GoogleCloudPlatform/cloudsql-proxy/blob/master/proxy/dialers/mysql/hook_test.go.
I've tried providing a second variable to the first line below, but there is an error as only one value is returned by the mysql function.
The troublesome code is on the second line, possibly due to the first line.
cfg := mysql.Cfg("haveibeenexploited:us-west1:hibe", "username", "password")
cfg.DBName := "mythril"
db, err := mysql.DialCfg(cfg)
searchcontract/searchcontract.go:67:5: non-name cfg.DBName on left side of := is the error message I get.
Change this line of code:
cfg.DBName := "mythril"
to:
cfg.DBName = "mythril"
The := operator declares a new variable and assigns it a value. This is called "Short Variable Declarations". Since DBName is part of the structure cfg you are using the wrong operator. The correct operator to use is the assignment operator =.

Numbers change when querying MySQL/MariaDB through R (RMariaDB)/ Integer conversion in R

I was able to implement a connection from R through RMariaDB and DBI to a remote MariaDB-database. However, I am currently encountering a strange change of numbers when querying the database through R. I'll explain the differences:
I inserted one simple entry in my database with the following command:
INSERT INTO respondent ( id, name ) VALUES ( 2388793051, 'testuser' )
When I connect to this database directly on the remote server and execute a statement like this:
SELECT * FROM respondent;
it delivers these value
id: 2388793051, name: testuser
So I should also be able to connect to the database via R and receive the same results. So when I execute the following code in R, I expect to receive this inserted and saved information displayed above:
library(DBI)
library(RMariaDB)
conn <- DBI::dbConnect(drv=RMariaDB::MariaDB(), user="myusername", password="mypassword", host="127.0.0.1", port="1111", dbname="mydbname")
res <- dbGetQuery(conn, "SELECT * FROM respondent")
print(res)
However, the result of this query is the following
id name
-1906174245 testuser
As you can see, the id is now -1906174245 instead of the saved 2388793051 in the database. I don't understand this weird conversion of integers in the id-field. Can someone explain how this problem emerges and how I might solve it?
EDIT: I don't expect this to be a problem, but just to inform you: I am using an SSH tunnel to enable a connection via these specified ports from my local to my remote machine.
SOLUTION: What made the difference was to specify the id of a respondent in the database specification already as BIGINT instead of INT. Thanks to #JonnyCrunch

Parse SQL query before it goes to MySQL

In my Go app I want to be able to analyze a SQL query before to execute it.
I want to get:
type (update, insert, delete etc). This is easy, but next steps not.
table to be affected,
columns to be updated (on insert/update)
most important - condition, list of columns and values.
Is there any go library for this?
Something to pass a sql query and get back some structure with info about this query
Yes, you have sqlparser for golang.
Note that the sqlparser is been pulled out from the database clustering system vitess
You can use the sql parser like,
reader := strings.NewReader("INSERT INTO table1 VALUES (1, 'a');")
tokens := sqlparser.NewTokenizer(reader)
for {
stmt, err := sqlparser.ParseNext(tokens)
if err == io.EOF {
break
}
// Do your logics with the statements.
}