if queryuser, err = db.Prepare("select UserID, CurrentDB from optUsers where LoginHash = '?'"); err != nil {
println(err)
panic( "queryuser Statement failed to create" )
}
var1 := req.URL.Query().Get("hash")
row := queryuser.QueryRow( var1 )
var userinfo user
row.Scan(&userinfo.UserID, &userinfo.CurrentDB)
The problem is if I use a statement to execute my query I get back no results. But if I use a db.QueryRow() and just execute the query inline I get back my results. Does anyone see anything wrong with my statement code?
Hey Glen! I ran into some trouble with MySql & the db.prepare statement as well. You can take a look at my code to see how I worked around it (Im fairly new with Go & development in general, so the code needs to be cleaned up quite a bit. However, you can see how I executed my queries)
Iām not sure if I understand what your problem is?
If by āexecutingā the statement you mean to call Exec() on the statement, then yes, you do not get any database items back, as Exec() is meant for write operations.
If you want to read, then you use QueryRow() and iterate over the result set until it is empty.
NobbZ, where do you see me doing an exec? Iām doing a queryrow and not getting results back. But if I switch to regular db.QueryRow without using the statement it works just fine.
First off Iām surprised by the fact that Scan returns error and didnāt make me catch it. I thought you had to put _ any time you didnāt want to use a return var. So I had no idea this function returned anything.
Secondly, the return Iām getting says āsql: expected 0 arguments, got 1ā But in my statement I created it has 1 argument so Iām still not sure what is wrong. Am I passing the var in wrong or something?
Youāre not using statements but instead using what I stated works for me as well which is to just run the query directly. However, I wanted to point out a few things you might want to consider.
You are creating your db connection within each function. From what Iāve been told you really only need one db connection created in main and then used as a global variable in the other functions. This will speed things up dramatically.
I think you might be using defer too late. The reason for having a defer statement is to make sure something happens no matter what. Closing the db connection is your example but what happens if your code dies before it gets down to the bottom of the function to close the connection. So instead what you want to do is create the connection and immediately tell it to defer close. Then if something happens before it gets to the bottom it will still close the connection for you. The way youāre using it you might as well just replace it with a close and remove the defer.
Ok, so that got rid of that error now I get āno rows in result setā But again, if I run this with db.QueryRow it works perfectly. So it is something with the statement that it thinks nothing was found.
Also, do I need to be doing anything about sql injection here? I am not sure if things are getting slashed out by default or if I need to be running through other measures to insure no one can mess with my queries.
Iām also assuming it is adding the ticks for strings and stuff automatically? Since removing the ticks did away with the error but Iām passing in a string for that parameter that definitely needs one for a proper query.
I also donāt seem to have an error response from the QueryRow itself so not totally sure it is executing properly or not.
There is no real purpose in this call btw: Just trying to write a simple test in go to get my head wrapped around all the processes. Iām considering writing a huge PHP application in go in the future and just using this program to work out the details.
You shouldnāt do this! This is vulnerable to SQL injections.
Have you inspected the actual value of var1, maybe it is not exactly what you expect it to be? Have you tried hardcoding it to a value you know it does exist in the database? Have you tried the sugared version of prepared statements? db.Query("select UserID, CurrentDB from optUsers where LoginHash = ?", var1)
I can not currently set up a testprogram on my own, as this computer is rather limited in its ressources and installing more would probably spill the disk
I had multiple problems and still looking into the last one. Originally I was using the default http processes and recently changed to gorilla mux to try it out. In the process I changed my var1 to use
vars := mux.Vars( req ) as it said it would put my vars into a map but apparently accessing vars[āhashā] isnāt the correct way to do that. I hard coded my hash in and it works. So my issue related to this thread was answered with removing the ticks from around ?.
However, am I safe in thinking this method is safe to use to protect against sql injection? I know my other example was not which was why I was trying to figure out the statement stuff.
mux.Vars() returns variables from the routes, not from the query string.
To get the querystring and its values, you still need to it the way you did before, at least from quickly glancing the mux-docs.
And prepared statements are as safe as prepared statements in the RDBMS you are using are.
Go literally tells your RDBMS this:
GO: Hey, in the near future, someone might ask you about this query: āselect UserID, CurrentDB from optUsers where LoginHash = ?ā RDBMS: Okay, Iāll remember that query as ā1ā GO: Hey, do you remember Query 1? Here is the missing argument: "deadb33f", its a string. RDBMS: Okay, here is your result. ā¦
From a language/DB-driver perspective you can not do much anymore to make it more or less secure against SQL-Injection. This is independent from whether or not you use them in PHP, Go, Rust or any other language.