Performing an SQL "dry run" (from Go application) - mysql

I have a tool in Go which generates SQL scripts from a YAML file. To minimize the risk that the generated scripts will fail I'd like to do something like a "dry run", either by means of SQL or the Go application.
My first thought was using the ROLLBACK statement but then the generated script would also include a rollback instead of a commit.
Does SQL or Go provide something like this?

Have you considered running the 'Dry Run' statements inside of a transaction, provided by the *DB.Conn?
db, err = sql.Open(...)
txn, err = db.BeginTx(...)
defer txn.Rollback
rows, err = txn.Query(...)

Related

MySQL executes sleep command when UPDATE query is used

I have created a discord bot that interacts with a mysql database but when you run a command that uses the UPDATE query it doesnt execute the update query but executes sleep , meaning the data in the DB isnt chnaged.
(from comment)
#client.command()
async def SetJob(ctx, uid: str, rank: str):
disout = exec("UPDATE users SET 'job'='{0}' WHERE identifier='{1}'".format(rank,uid))
if ctx.message.author == client.user:
return
if ctx.message.author.id not in whitelisted:
await ctx.send(embed=discord.Embed(title="You are not authorized to use this bot", description='Please contact Not Soviet Bear to add you to the whitelisted members list', color=discord.Color.red()))
return
else:
await ctx.send(embed=discord.Embed(title="Job Change", description="Job changed to '{0}' for Identifier'{1}'".format(rank,uid), color=discord.Color.blue()))
I assume your "bot" is periodically doing SHOW PROCESSLIST? Well, the UPDATE probably finished so fast that it did not see the query.
The Sleep says that the connection is still sitting there, but doing nothing. (There is no "sleep command"; "Sleep" indicates that no query is running at the instant.)
So, perhaps the question is "why did my update not do anything?". In order to debug that (or get help from us),
Check for errors after running the update. (You should always do this.)
Figure out the exact text of the generated SQL. (Sometimes there is an obvious syntax error or failure to escape, say, quotes.)

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

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

Autohotkey close database connection

I have made a script using the following library;
http://www.autohotkey.com/board/topic/72629-mysql-library-functions/
to connect to my non-local database. However I'm issuing some max_user_connections problems and I think this is due to the fact that I never close the database connection.
I can't seem to find a way to do that using this library but I am not certain, maybe theres a way to close any connection to the internet or any database or whatever that would work build-in in AHK?
Script:
hi() {
mysql := new mysql
db := mysql.connect("x","x","x","x") ; host,user,password,database
if db =
return
sql =
(
UPDATE something
SET yo = yo+1
WHERE id = 1
)
result := mysql.query(db, sql)
}
Thanks in advance
The DLL of the AHK script has the mysql_close function, but it's not coded into the AHK library.
You can technically manually call the DLL just like the AHK and see if it'll work.
Since I also need to connect to a MySQL DB via AHK, I'll update this answer when a full solution is available.

"foreach" loop : Using all cores in R (especially if we are sending sql queries inside foreach loop)

I intend to use "foreach" to uitlize all the cores in my CPU. The catch is i need to send a sql query inside the loop. The script is working fine with normal 'for' loop, but it is giving following error when i change it to 'foreach'.
The error is :
select: Interrupted system call
select: Interrupted system call
select: Interrupted system call
Error in { : task 1 failed - "expired MySQLConnection"
The code i used is :
library(foreach)
library(doMC)
library(RMySQL)
library(multicore)
registerDoMC(cores=6)
m <- dbDriver("MySQL", max.con = 100)
con <- dbConnect(m, user="*****", password = "******", host ="**.**.***",dbname="dbname")
list<-dbListTables(con)
foreach(i = 1:(length(list))%dopar%{
query<-paste("SELECT * FROM ",list[i]," WHERE `CLOSE` BETWEEN 1 AND 100",sep="")
t<-dbGetQuery(con,query)
}
Though 'foreach' is working fine in my system for all other purposes, it is giving error only in case of sql queries. Is there a way to send sql queries inside 'foreach' loop?
My suggestion is this:
Move the database queries outside the loop, and lock access so you dont do parallel database queries. I think that will speed things up too, as you won't have parallel disk access, while still being able to do parallel processing.
Meaning (pseudo code)
db = connect to database
threadlock = lock();
parfor {
threadlock.lock
result = db query (pull all data here, as you cant process while you load without keeping the database locked)
thread.unlock
process resulting data (which is now just data, and not a sql object).
}