0

I have this function that is returning an error sql: Rows are closed. I can't figure out why...

Here is the function :

func GetUserFromToken(db *sql.DB, token string) User {
    query := `
        SELECT id, token, name, surname, phone, email FROM users WHERE token=$1
        `

    rows, err := db.Query(query, token)
    if err != nil {
        fmt.Println("query error : " + err.Error())
    }

    var user User
    rows.Next()
    err = rows.Scan(&user.ID, &user.Token, &user.Name, &user.Surname, &user.Phone, &user.Email)
    if err != nil {
        fmt.Println("scan error : " + err.Error())
    }

    return user
}

When I log the token it's the proper token. When I hard code the token in the query for testing purposes, it works fine. For instance :

query := `
        SELECT id, token, name, surname, phone, email FROM users WHERE token='abcdefg12345'
        `

Tried also to set the query such as :

query := "SELECT id, token, name, surname, phone, email FROM users WHERE token = $1"

row := db.QueryRow(query, "abcdefg12345")

It works fine. fmt.Println(token) prints abcdefg12345.

Would someone help me understand what I'm missing ?


UPDATE : found my fail.

So the token I had was the bearer token extracted from the header with the following function :

func GetBearerToken(r *http.Request) string {
    reqToken := r.Header.Get("Authorization")
    splitToken := strings.Split(reqToken, "Bearer")
    reqToken = splitToken[1]
    return reqToken
}

Had a leading whitespace that I did not notice in my fmt.Println. After a good night of sleep thinking about @RayfenWindspear's comment I had this urging to check string length then I saw the fail. Feeling a bit idiotic and amused at the same time that I didn't catch it.

So my simple fix : from: reqToken = splitToken[1] to : strings.TrimSpace(splitToken[1])

4
  • If you are only looking for a single row, perhaps you should be using golang.org/pkg/database/sql/#DB.QueryRow which wouldn't give you this issue as a *sql.Row doesn't need to be closed. Also note that rows.Next() returns an error you aren't bothering to check. Commented Nov 8, 2018 at 22:09
  • Ok switched to QueryRow. I now face sql: no rows in result set. I don't quite understand since the token passed is the relevant one (I checked by adding a fmt.Println(token) at start). Commented Nov 8, 2018 at 22:24
  • 1
    Odd. You might want to take a look at what charset your postgres instance is using as well as what charset could possibly be coming from user input (or wherever this function is being called from). Aside from that, I leave it to the rest of the community... :( Commented Nov 8, 2018 at 22:53
  • Thanks RayfenWindspear I updated my post. Your comment lead me in the proper direction! Commented Nov 9, 2018 at 8:03

1 Answer 1

3

Here's how you'd write this code. The err returned will be sql.ErrNoRows if nothing was returned. Let me know how this works, and then maybe I can give other debugging steps.

func GetUserFromToken(db *sql.DB, token string) (u User, err error) {
  err = db.QueryRow(
    "SELECT id, token, name, surname, phone, email FROM users WHERE token=$1",
    token,
  ).Scan(
    &u.ID,
    &u.Token,
    &u.Name,
    &u.Surname,
    &u.Phone,
    &u.Email)
  return
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your answer, even tho it is not what helped fixed the issue it's much more clean and I can return an error. I edited my question in which I explain what was my mistake.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.