Checking if a value exists in sqlite db with Go - sql

I'm writing code to manage users in a sqlite database with Go.
I'm trying to check if a username is taken, but my code is ugly.
My table looks like:
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE,
password TEXT
And I check if a username is taken with:
func UserExists(db * sql.DB, username string) bool {
sqlStmt := `SELECT username FROM userinfo WHERE username = ?`
count := 0
rows, err := db.Query(sqlStmt, username)
Check(err)
for rows.Next() { // Can I just check if rows is non-zero somehow?
count++
}
return len(rows) != 0
}
Is there a better query I could use that would tell me if the username value exists in the table in a more staight forward way? Or is there a nicer way to check if rows is non-zero?

Use QueryRow to query at most one row. If the query doesn't return any row, it returns sql.ErrNoRows.
func UserExists(db * sql.DB, username string) bool {
sqlStmt := `SELECT username FROM userinfo WHERE username = ?`
err := db.QueryRow(sqlStmt, username).Scan(&username)
if err != nil {
if err != sql.ErrNoRows {
// a real error happened! you should change your function return
// to "(bool, error)" and return "false, err" here
log.Print(err)
}
return false
}
return true
}

I know this is a bit old, but I don't see any clean answers here. Notice below the if rows.Next() statement which will return a boolean if there are any rows or not:
package main
import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
"log"
)
func main() {
exists, _ := SelectDBRowExists(`SELECT * FROM GEO_VELOCITY_EVENTS WHERE USERNAME='bob'`)
log.Println(exists)
}
func SelectDBRowExists(query string) (bool, error) {
DbConn, err := sql.Open("sqlite3", "/path/to/your/sql.sqlite3")
if err != nil {
return false, err
}
defer DbConn.Close()
err = DbConn.Ping()
if err != nil {
return false, err
}
rows, err := DbConn.Query(query)
if rows.Next() {
return true, nil
} else {
return false, nil
}
defer rows.Close()
return false, nil
}

as long as you are only concerned about the existence of one single information in the Database. I found that this method is quite simpler and efficient.
func emailExists(email string) bool {
row := db.QueryRow("select user_email from users where user_email= ?", email)
checkErr(err)
temp := ""
row.Scan(&temp)
if temp != "" {
return true
}
return false
}
if u noticed am only getting a single row.
the result of my Query gets scanned in a temp Variable.
then I check whether the temp Variable is empty or not.
if it is not empty, true is returned.

i think we can use above function to check that condition is already exist at database.
if helper.UserExists(db, username) {
return username, errors.New("data already exist")
}
because that function returned bool that means if that function is called return will return by default is true.
i hope this usefull.

Related

Not in condition using gorm in golang - dynamic not in condition for select statement

I have two databases Booking and Room. Booking has roomid as one of its field. I wrote a select statement which saves the rows retrieved in result variable as stated below.
var result models.Booking
rows, err := utils.DB.Model(&currRequest).Where("check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?", currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select("room_id").Rows()
for rows.Next() {
utils.DB.ScanRows(rows, &result)
fmt.Println(result.RoomID)
}
Now my result.roomid has values of roomids that satisfy the select statement from the bookings table
My result variable may have multiple room id values. I am able to retrieve the roomid values by looping through the result variable. Now I have to check in my main room database called Room and get those room ids that are not in the result struct. By using the below statement, I am only able to access the first value in result.roomid so the not in condition only considers the first values in result.roomid. How do I do the not in condition for all the values in result.roomid?
rows, err := utils.DB.Model(&models.Room{}).Not(result.RoomID).Select("room_id").Rows()
Full code:
package handlers
import (
"encoding/json"
"fmt"
"net/http"
"server/models"
"server/utils"
"strings"
)
func AvailableRoomsHandler(w http.ResponseWriter, r *http.Request) {
currRequest := &models.Booking{}
err := json.NewDecoder(r.Body).Decode(currRequest)
//check if a valid request has been sent from front end
if err != nil {
//fmt.Println(err)
var resp = map[string]interface{}{"status": false, "message": "Invalid json request"}
json.NewEncoder(w).Encode(resp)
return
}
noOfRoomsOccupied := 0
var notinrooms string
// Use GORM API build SQL
//check if any rooms are available which havent been booked yet in the requested check-in and check-out dates
var result models.Booking
rows, err := utils.DB.Model(&currRequest).Where("check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?", currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select("room_id").Rows()
if err != nil {
json.NewEncoder(w).Encode(err)
fmt.Print("error occured in select statement")
return
} else {
defer rows.Close()
for rows.Next() {
noOfRoomsOccupied = noOfRoomsOccupied + 1
utils.DB.ScanRows(rows, &result)
fmt.Println(result.RoomID)
notinrooms = notinrooms + result.RoomID + ","
}
notinrooms = strings.TrimRight(notinrooms, ",")
fmt.Println(notinrooms)
//calculate the number of rooms in the database
//rows, err := utils.DB.Model(&models.Room{}).Select("room_id").Rows()
res := utils.DB.Find(&models.Room{})
rowcount := res.RowsAffected
fmt.Println(rowcount)
if noOfRoomsOccupied == int(rowcount) {
var resp = map[string]interface{}{"status": false, "message": "no rooms available in the specified time period"}
json.NewEncoder(w).Encode(resp)
return
} else {
noOfRooms := (currRequest.NoOfGuests + currRequest.NoOfChildren) / 2
if (currRequest.NoOfGuests+currRequest.NoOfChildren)%2 == 1 {
noOfRooms = noOfRooms + 1
}
if int(noOfRooms) < int(rowcount)-noOfRoomsOccupied {
fmt.Println("number of rooms to book : ", noOfRooms)
//assign rooms if available
var roomids models.Room
//rows, err := utils.DB.Model(&models.Room{}).Not(result.RoomID).Select("room_id").Rows()
fmt.Println("rooms that can be booked")
rows, err := utils.DB.Model(&models.Room{}).Not(result.RoomID).Select("room_id").Rows()
//rows, err := utils.DB.Model(&models.Room{}).Not([]string{notinrooms}).Select("room_id").Rows()
//map[string]interface{}{"name": []string{"jinzhu", "jinzhu 2"}}
if err != nil {
json.NewEncoder(w).Encode(err)
fmt.Print("error occured in select statement to get room ids to assign")
return
} else {
defer rows.Close()
for rows.Next() {
noOfRoomsOccupied = noOfRoomsOccupied + 1
utils.DB.ScanRows(rows, &roomids)
fmt.Println(roomids.RoomID)
}
}
var success = map[string]interface{}{"message": "Select statement worked well"}
json.NewEncoder(w).Encode(success)
return
}
}
}
}
When I do result.roomid, it only gives the first room id and eliminates only that room id in the above select statement. How do I eliminate all the room ids I found in the booking table in the rooms table data?
I tried splitting the result.roomid values and tried to form a string and gave it in the select statement but that didn't work. I tried looping through every result.roomid and ran the not in a statement but that will not make any sense.
With this code:
var result models.Booking
rows, err := utils.DB.Model(&currRequest).Where("check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?", currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select("room_id").Rows()
if err != nil {
json.NewEncoder(w).Encode(err)
fmt.Print("error occured in select statement")
return
} else {
defer rows.Close()
for rows.Next() {
noOfRoomsOccupied = noOfRoomsOccupied + 1
utils.DB.ScanRows(rows, &result)
//rest of the code
}
}
you only get one row of potentially many rows from the result set. To get all the rows and extract their values, you should use []models.Booking.
result := []models.Booking{}
rows, err := utils.DB.Model(&currRequest).Where("check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?", currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select("room_id").Rows()
if err != nil {
json.NewEncoder(w).Encode(err)
fmt.Print("error occured in select statement")
return
} else {
defer rows.Close()
for rows.Next() {
var b models.Booking
noOfRoomsOccupied = noOfRoomsOccupied + 1
utils.DB.ScanRows(rows, &b)
result = append(result, b)
//rest of the code
}
}
However, since you only need roomid anyway, you could make it easier by using []uint (assuming roomid is of type uint).
result := []uint{}
rows, err := utils.DB.Model(&currRequest).Where("check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?", currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select("room_id").Rows()
if err != nil {
json.NewEncoder(w).Encode(err)
fmt.Print("error occured in select statement")
return
} else {
defer rows.Close()
for rows.Next() {
var rid uint
noOfRoomsOccupied = noOfRoomsOccupied + 1
utils.DB.ScanRows(rows, &rid)
result = append(result, rid)
//rest of the code
}
}
With the result being of type []uint, it would be easier to use it with the Not function (per documentation):
rows, err := utils.DB.Model(&models.Room{}).Not(result).Select("room_id").Rows()

How do I create a structure for a dynamic SQL query?

In my Golang application I make SQL request to the database. Usually, in the SQL query, I specify the columns that I want to get from the table and create a structure based on it. You can see an example of the working code below.
QUESTION:
What should I do if I don't know the number and name of columns in the table? For example, I make the SQL request like SELECT * from filters; instead of SELECT FILTER_ID, FILTER_NAME FROM filters;. How do I create a structure in this case?
var GetFilters = func(responseWriter http.ResponseWriter, request *http.Request) {
rows, err := database.ClickHouse.Query("SELECT * FROM filters;"); if err != nil {
fmt.Println(err)
return
}
defer rows.Close()
columns, err := rows.Columns(); if err != nil {
fmt.Println(err)
return
}
filters := make([]interface{}, len(columns))
for i, _ := range columns {
filters[i] = new(sql.RawBytes)
}
for rows.Next() {
if err = rows.Scan(filters...); err != nil {
fmt.Println(err)
return
}
}
utils.Response(responseWriter, http.StatusOK, filters)
}
Well, finally I found the solution. As you can see from the code below first I make SQL request where I do not specify the name of the columns. Then I take information about columns by ColumnTypes() function. This function returns column information such as column type, length and nullable. Next I will learn the name and type of columns, fill interface with these data:
for i, column := range columns {
object[column.Name()] = reflect.New(column.ScanType()).Interface()
values[i] = object[column.Name()]
}
The full code which I use looks like this:
var GetFilters = func(responseWriter http.ResponseWriter, request *http.Request) {
rows, err := database.ClickHouse.Query("SELECT * FROM table_name;"); if err != nil {
fmt.Println(err)
return
}
defer rows.Close()
var objects []map[string]interface{}
for rows.Next() {
columns, err := rows.ColumnTypes(); if err != nil {
fmt.Println(err)
return
}
values := make([]interface{}, len(columns))
object := map[string]interface{}{}
for i, column := range columns {
object[column.Name()] = reflect.New(column.ScanType()).Interface()
values[i] = object[column.Name()]
}
if err = rows.Scan(values...); err != nil {
fmt.Println(err)
return
}
objects = append(objects, object)
}
utils.Response(responseWriter, http.StatusOK, objects)
}
Use the USER_TAB_COLUMNS table to get the list of columns in the executing table query store it an array or collection. later execute the query and Scan the columns that you already know from the previous Query.

Beego update & get 1 by ID

I'm absolutely stuck at Beego, update & get. I already done getall, delete,
Problem is my ID is the primary key. I convert into a string to equal at the model. How to search from Ticket table by using ID and in model how to take as []array and return it.
controller
func (i *TicketController) GetTicket() {
ID := i.GetInt("ID")
stringID := strconv.Itoa(ID)
if ID != "" {
ticket := models.GetTicketById(stringID)
fmt.Println(ticket)
i.Data["json"] = ticket
}
i.ServeJSON()
}
model
func GetTicketById(id int64) Ticket {
t := Ticket{ID: id}
o := orm.NewOrm()
err := o.Read(&t)
if err == orm.ErrNoRows {
fmt.Println("no result")
} else if err == orm.ErrMissPK {
fmt.Println("can't find PK")
}
return t
}
I think you are misunderstand many things. I fixed your code on this link.
Assign as ID,err := i.GetInt64("ID")
Check error as if err == nil && ID > 0 {}
https://play.golang.org/p/PY-lc3AfhPw

Scan array typed DB field into array/slice in Golang

tl; dr
I have an sql table users which includes an array field. How can I Scan it to variable in golang? My approach:
var id int
var username string
var activites []string
row := db.QueryRow("SELECT id, username, activities FROM users WHERE id = 1")
err := row.Scan(&id, &username, &activites)
Works fine for id, username.
As #mkopriva already pointed out, this can either be accomplished using the StringArray method or with the more flexible Array method (as it accepts an interface as the argument), both found within the "github.com/lib/pq" package.
As an aside, it is also a good practice to use prepared statements.
Full example:
var id int
var username string
var activities []string
sqlStatement := `
SELECT
id,
username,
activities
FROM
users
WHERE
id = $1
`
stmt, err := db.Prepare(sqlStatement)
if err != nil {
// handle err
}
defer stmt.Close()
row := stmt.QueryRow(1)
err = row.Scan(
&id,
&username,
pq.Array(&activities) // used here
)
if err == sql.ErrNoRows {
// handle err
}
if err != nil {
// handle err
}

Convert query result from struct to string for another Golang package

I have searched for a solution on the net and in SO, but found nothing that apply to return values. It is a simple sql query with several rows that I want to return. Error handling not included:
func Fetch(query string) (string) {
type User struct{
id string
name string
}
rows, err := db.Query(query)
users := make([]*User, 0)
for rows.Next() {
user := new(User)
err := rows.Scan(&user.id, &user.name)
users = append(users, user)
}
return(users)
}
I get this error when compiling:
cannot use users (type []*User) as type string in return argument
How should I do to get a correct return value?
The expected input is
JD John Doe --OR-- {id:"JD",name:"John Doe"}
Add this to your code:
type userSlice []*User
func (us userSlice) String() string{
var s []string
for _, u := range us {
if u != nil {
s = append(s, fmt.Sprintf("%s %s", u.id, u.name))
}
}
return strings.Join(s, "\n")
}
type User struct{
id string
name string
}
In your Fetch function replace the last return statement like this:
func Fetch(query string) (string) {
// Note that we declare the User type outside the function.
rows, err := db.Query(query)
users := make([]*User, 0)
for rows.Next() {
user := new(User)
err := rows.Scan(&user.id, &user.name)
users = append(users, user)
}
return(userSlice(users).String()) // Replace this line in your code
}
If you have to return a String you can use the encoding/json package to serialize your user object, but you have to use fields that begin with capital letters for them to be exported. See the full example:
import (
"encoding/json"
)
func Fetch(query string) (string) {
type User struct{
Id string // <-- CHANGED THIS LINE
Name string // <-- CHANGED THIS LINE
}
rows, err := db.Query(query)
users := make([]*User, 0)
for rows.Next() {
user := new(User)
err := rows.Scan(&user.id, &user.name)
users = append(users, user)
}
return(ToJSON(users)) // <-- CHANGED THIS LINE
}
func ToJSON(obj interface{}) (string) {
res, err := json.Marshal(obj)
if err != nil {
panic("error with json serialization " + err.Error())
}
return string(res)
}