Multiple rows.Next() in the same time golang sql/database - mysql

I am working on a function which gets users. My problem is that I have to return the result of two queries as one result in the rows.Next() and rows1.Next() like user_id, subject, phone.
Here is what I have but it doesn't work. Could you please help me out with some suggestions:
func GetUsers() (users []Users, err error) {
users = make([]Users, 0)
rows, err := db1.Query("SELECT user_id, subject,phone FROM users limit 11")
rows1, err := db1.Query("Select body from users limit 11")
defer rows.Close()
if err != nil {
// handle this error better than this
log.Fatal(err)
//return
}
var user Users
for rows.Next() {
rows.Scan(&user.ID, &user.Subject, &user.Phone)
users = append(users, user)
}
for rows1.Next() {
rows1.Scan(&user.Body)
users = append(users, user)
}
return
}
I have a table called users which has no primary key, basically:
user_id . name . body
-----------------------
1 . model . 2
1 . brand . 1
1 . fuel . 3
1 . date . 1
1 . year . 1
I have to have a result:
userid . model . brand . fuel . date . year
1 . 2 . 1 . 3 . 1 . 1
so the values in the column name gonna be as rows. I have already defined my struct which contains all the fields needed.

Looking at the example code it's clear that you should do whatever you're doing in one query instead of two. Even if your real code is a little different, say you need to query more than one table, you should still probably do only one query using JOINs.
users := make([]*User, 0)
rows, err := db1.Query("SELECT user_id, subject,phone, body FROM users limit 11")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
user := new(User)
if err := rows.Scan(&user.ID, &user.Subject, &user.Phone, &user.Body); err != nil {
panic(err)
}
users = append(users, user)
}
if err := rows.Err(); err != nil {
panic(err)
}
That said, if you want to do it the way you illustrated in your question you can do that like this.
(this probably not what you should do)
users := make([]*User, 0)
rows, err := db1.Query("SELECT user_id, subject,phone FROM users limit 11")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
rows1, err := db1.Query("Select body from users limit 11")
if err != nil {
panic(err)
}
defer rows1.Close()
for rows.Next() {
user := new(User)
if err := rows.Scan(&user.ID, &user.Subject, &user.Phone); err != nil {
panic(err)
}
if !rows1.Next() {
panic("no next body row")
}
if err := rows1.Scan(&user.Body); err != nil {
panic(err)
}
users = append(users, user)
}
if err := rows.Err(); err != nil {
panic(err)
}
if err := rows1.Err(); err != nil {
panic(err)
}

const maxPerPage = 100
type Scanable interface {
GetScans() []interface{}
}
type User struct {
ID int
Subject string
Phone string
Body string
}
func (s *User) GetScans() []interface{} {
return []interface{}{&s.ID, &s.Subject, &s.Phone, &s.Body}
}
func getNewUserList() []*User {
users := make([]*User, maxPerPage)
for i := 0; i < maxPerPage; i++ {
users[i] = new(User)
}
return users
}
var usersPool = sync.Pool{
New: func() interface{} {
return getNewUserList()
},
}
func getUsers() (b []*User) {
ifc := usersPool.Get()
if ifc != nil {
b = ifc.([]*User)
} else {
b = getNewUserList()
}
return
}
func putUsers(b []*User) {
// if cap(b) <= maxPerPage {
// b = b[:0] // reset
// usersPool.Put(&b)
// }
usersPool.Put(&b)
}
func TestUsers(t *testing.T) {
users := getUsers()
rows, err := PostgresConnection.Query("SELECT user_id, subject,phone, body FROM users limit 11")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
length := 0
for rows.Next() {
if err := rows.Scan(users[i].GetScans()...); err != nil {
panic(err)
}
if err := rows.Err(); err != nil {
panic(err)
}
length++
}
result := users[:length]
fmt.Println(result)
putUsers(users)
}

this is the sample function to get multiple document from db using golang sqlx library.
func GetDocuments() ([]SupportedDocument, error) {
var documents []SupportedDocument
query := `SELECT * FROM documents limit 10`
err := database.Select(&documents, query)
return documents, err
}

Related

How to edit only some fields in the database instead of all?

I have an application in go, and there is an endpoint for editing user information. But I found a problem, if in json it sees blank information (let's assume the user just wants to edit the name, and leaves the other fields blank), the data will be edited in the DB and the information that came blank will overwrite the information that are DB, even if the user didn't want to edit them.
How can I make only the fields that arrive in json to be effectively edited in the DB? Or is there a better way?
I'm looking forward to knowing!
My controller
func EditUser(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
userID, err := strconv.ParseUint(params["userID"], 10, 64)
if err != nil {
returns.ERROR(w, http.StatusInternalServerError, err)
return
}
userIDInToken, err := auth.ExtractUserID(r)
if err != nil {
returns.ERROR(w, http.StatusInternalServerError, err)
return
}
if userIDInToken != userID {
returns.ERROR(w, http.StatusForbidden, errors.New("you can't update other user"))
return
}
bodyRequest, err := ioutil.ReadAll(r.Body)
if err != nil {
returns.ERROR(w, http.StatusBadRequest, err)
return
}
var user models.User
if err := json.Unmarshal(bodyRequest, &user); err != nil {
returns.ERROR(w, http.StatusUnprocessableEntity, err)
return
}
db, err := db.ConnectToDB()
if err != nil {
returns.ERROR(w, http.StatusInternalServerError, err)
return
}
defer db.Close()
repository := repositories.NewUsersRepository(db)
if err := repository.UpdateUserInfo(userID, user); err != nil {
returns.ERROR(w, http.StatusInternalServerError, err)
return
}
returns.JSON_RESPONSE(w, http.StatusOK, nil)
}
My repository (that access DB)
func (repository Users) UpdateUserInfo(userID uint64, user models.User) error {
stmt, err := repository.db.Prepare(
"UPDATE user SET name = ?, cpf = ?, email = ?, password = ?, city = ?, state = ? WHERE id = ?")
if err != nil {
return err
}
defer stmt.Close()
if _, err := stmt.Exec(
user.Name,
user.CPF,
user.Email,
user.Password,
user.City,
user.State,
userID,
); err != nil {
return err
}
return nil
}
Model for user
type User struct {
ID uint64 `json:"id,omitempty"`
Name string `json:"name,omitempty"`
CPF string `json:"cpf,omitempty"`
Email string `json:"email,omitempty"`
Password string `json:"password,omitempty"`
City string `json:"city,omitempty"`
State string `json:"state,omitempty"`
}
I would dynamically construct the UPDATE statement as well as a slice of the fields that need to be edited by checking if the field is not empty before adding it to the slice.
Something like this:
func (repository Users) UpdateUserInfo(userID uint64, user User) error {
fields := make([]string, 0)
values := make([]string, 0)
if user.Name != "" {
values = append(values, user.Name)
fields = append(fields, "name = ?")
}
if user.CPF != "" {
values = append(values, user.CPF)
fields = append(fields, "cpf = ?")
}
if user.Email != "" {
values = append(values, user.Email)
fields = append(fields, "email = ?")
}
if user.Password != "" {
values = append(values, user.Password)
fields = append(fields, "password = ?")
}
if user.City != "" {
values = append(values, user.City)
fields = append(fields, "city = ?")
}
if user.State != "" {
values = append(values, user.State)
fields = append(fields, "state = ?")
}
if len(fields) != 0 {
return errors.New("no fields to update")
}
updateString := fmt.Sprintf("UPDATE user SET %s WHERE id = ?", strings.Join(fields, ","))
stmt, err := repository.db.Prepare(updateString)
if err != nil {
return err
}
defer stmt.Close()
if _, err := stmt.Exec(values...,userID); err != nil {
return err
}
return nil
}
For cleaner code, I'd recommend maybe extracting the "if statements"/validation into a separate function.

Does gorm shares an ID from previous transaction Create

I have a query, that requires ID from the previous insert. Does gorm gives away the ID in transaction mode:
Example:
err := db.Transaction(func(tx *gorm.DB) error {
if err := tx.Model(&model.user).Create(&user).Error; err != nil {
tx.Rollback()
}
// if user inserted get the user ID from previous user insert of DB
for _, v := profiles {
v.UserID = user.ID // Can I get this ID from previous Create operation?
}
if err := tx.Model(&model.profile).Create(&profiles).Error; err != nil {
tx.Rollback()
}
})
Yes, you can use the Find function toget the data that you created.
if err := tx.Model(&model.profile).Create(&profiles).Find(&profiles).Error; err != nil {
tx.Rollback()
}

Add two json files in one with the same files

I have this version of my code: What i need it to change some part of code or just help me, because I checked all links in google.
data, err := ioutil.ReadFile("firstfile.json")
if err != nil {
fmt.Print(err)
}
data1, err := ioutil.ReadFile("secondfile.json")
if err != nil {
fmt.Print(err)
}
var migrations map[string]interface{}
var migrations1 map[string]interface{}
err = json.Unmarshal([]byte(data), &migrations)
err = json.Unmarshal([]byte(data1), &migrations1)
if err != nil {
log.Println("Error:", err)
}
//fmt.Println(migrations)
//fmt.Println(migrations1)
mig := migrations["date"]
mig1 := migrations1["date"]
layout := "2006-01-02T15:04:05.000Z"
str := fmt.Sprint(mig)
str1 := fmt.Sprint(mig1)
t, err := time.Parse(layout, str)
t1, err := time.Parse(layout, str1)
if err != nil {
fmt.Println(err)
}
//fmt.Println(t, t1)
firsthour := t.Hour()
secondhour := t1.Hour()
if firsthour == secondhour {
result := []map[string]interface{}{}
migrations3 := make(map[string]interface{})
for k, v := range migrations {
if _, ok := migrations[k]; ok {
migrations3[k] = v
}
}
for k, v := range migrations1 {
if _, ok := migrations1[k]; ok {
migrations3[k] = v
}
}
result = append(result, migrations, migrations1)
fmt.Println(result)
b, err := json.Marshal(result)
if err != nil {
fmt.Println(err)
}
os.Stdout.Write(b)
} else {
err = json.Unmarshal([]byte(data), &migrations)
err = json.Unmarshal([]byte(data1), &migrations1)
fmt.Println(migrations, migrations)
}
}
And in the end I got:
[{"data":"is nice",
"date":"2012-04-23T18:24:59.511Z",
"name":"Kate"},
{"data":"is a good person",
"date":"2012-04-23T18:25:00.511Z",
"name":"Gleison"}]
But what I want to get:
{
"name":["kate","gleison"],
"date":"2012-04-23T18:00:00.000Z",
"data":["is nice","is a good person"]
}
Can you help me to change some parts of my code to fix it?
My 2 json files:
{
"name":"Kate",
"date":"2012-04-23T18:24:59.511Z",
"data":"is nice"
},
{
"name":"Gleison",
"date":"2012-04-23T18:25:00.511Z",
"data":"is a good person"
}
migrations, migrations1 := make(map[string]interface{}), make(map[string]interface{})
data := `{ "name":"Kate", "date":"2012-04-23T18:24:59.511Z", "data":"is nice" }`
data1 := `{ "name":"Gleison", "date":"2012-04-23T18:25:00.511Z", "data":"is a good person" }`
err := json.Unmarshal([]byte(data), &migrations)
if err != nil {
panic(err)
}
err = json.Unmarshal([]byte(data1), &migrations1)
if err != nil {
panic(err)
}
layout := "2006-01-02T15:04:05.000Z"
t, err := time.Parse(layout, fmt.Sprint(migrations["date"]))
t1, err := time.Parse(layout, fmt.Sprint(migrations1["date"]))
if err != nil {
fmt.Println(err)
}
firsthour := t.Hour()
secondhour := t1.Hour()
if firsthour == secondhour {
result := make(map[string][]interface{})
for k, v := range migrations {
result[k] = append(result[k], v)
}
for k, v := range migrations1 {
result[k] = append(result[k], v)
}
fmt.Println(result)
b, err := json.Marshal(result)
if err != nil {
fmt.Println(err)
}
os.Stdout.Write(b)
} else {
err = json.Unmarshal([]byte(data), &migrations)
if err != nil {
panic(err)
}
err = json.Unmarshal([]byte(data1), &migrations1)
if err != nil {
panic(err)
}
fmt.Println(migrations, migrations)
}

Function in Go to execute select query on database and return json output

I am writing a function in Go to execute select query on database.
Input: String e.g. "Select id, name, age from sometable"
This query changes everytime.
Output: Output of select query in json format.
Sample Expected output: {"Data":[{"id":1,"name":"abc", "age":40},{"id":2,"name":"xyz", "age":45}]}
Sample Actual output: {"Data":[[1,"abc",40],[2,"xyz",45]]}
Instead of i.e. column_name:value, I get only values.
How do I get the expected output?
func executeSQL(queryStr string) []byte {
connString := createConnectString()
conn, err := sql.Open("mssql", connString)
if err != nil {
log.Fatal("Error while opening database connection:", err.Error())
}
defer conn.Close()
rows, err := conn.Query(queryStr)
if err != nil {
log.Fatal("Query failed:", err.Error())
}
defer rows.Close()
columns, _ := rows.Columns()
count := len(columns)
var v struct {
Data []interface{} // `json:"data"`
}
for rows.Next() {
values := make([]interface{}, count)
valuePtrs := make([]interface{}, count)
for i, _ := range columns {
valuePtrs[i] = &values[i]
}
if err := rows.Scan(valuePtrs...); err != nil {
log.Fatal(err)
}
v.Data = append(v.Data, values)
}
jsonMsg, err := json.Marshal(v)
return jsonMsg
}
Got the solution. Here is what I did.
func executeSQL(queryStr string) []byte {
connString := createConnectString()
conn, err := sql.Open("mssql", connString)
if err != nil {
log.Fatal("Error while opening database connection:", err.Error())
}
defer conn.Close()
rows, err := conn.Query(queryStr)
if err != nil {
log.Fatal("Query failed:", err.Error())
}
defer rows.Close()
columns, _ := rows.Columns()
count := len(columns)
var v struct {
Data []interface{} // `json:"data"`
}
for rows.Next() {
values := make([]interface{}, count)
valuePtrs := make([]interface{}, count)
for i, _ := range columns {
valuePtrs[i] = &values[i]
}
if err := rows.Scan(valuePtrs...); err != nil {
log.Fatal(err)
}
//Created a map to handle the issue
var m map[string]interface{}
m = make(map[string]interface{})
for i := range columns {
m[columns[i]] = values[i]
}
v.Data = append(v.Data, m)
}
jsonMsg, err := json.Marshal(v)
return jsonMsg
}
Let me know if there exists a better solution.
This code is directly from my "sandbox" for MsSQL (using denisenkom/go-mssqldb and jmoiron/sqlx) - I think it helps showing different approaches and probably QueryIntoMap is what you were looking for:
package main
import (
"log"
"fmt"
_ "github.com/denisenkom/go-mssqldb"
"time"
"github.com/jmoiron/sqlx"
"encoding/json"
)
type Customer struct {
CustomerId string `db:"customerID" json:"customer_id"`
Company interface{} `db:"companyName" json:"company_name"`
Contact interface{} `db:"contactName" json:"contact_name"`
}
func main() {
connection := "server=192.168.55.3\\SqlExpress2012;database=Northwind;user id=me;Password=secret"
//QueryIntoMap(connection)
ScanIntoSlice(connection)
}
func QueryIntoMap(connection string) {
fmt.Println("QueryIntoMap sample")
fmt.Println("--------------------")
sel := `select customerId, companyName, contactName
from customers
where customerId = :id`
values := make(map[string]interface{})
db, err := sqlx.Open("mssql", connection)
//db.MapperFunc(strings.ToUpper)
e(err)
defer db.Close()
tx := db.MustBegin()
stmt, err := tx.PrepareNamed(sel)
e(err)
stmt.QueryRowx(map[string]interface{}{"id": "BONAP"}).MapScan(values)
tx.Commit()
for k, v := range values {
fmt.Printf("%s %v\n", k, v)
}
js, err := json.Marshal(values)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(js))
fmt.Println("--------------------")
}
func ScanIntoStruct(connection string) {
fmt.Println("Scan into struct sample")
fmt.Println("--------------------")
db, err := sqlx.Open("mssql", connection)
e(err)
defer db.Close()
customer := Customer{}
rows, err := db.Queryx(`select customerID, companyName, contactName
from Customers`)
for rows.Next() {
err = rows.StructScan(&customer)
if err != nil {
log.Fatalln(err)
}
//fmt.Printf("%#v\n", user)
fmt.Printf("%-10s %-50v %-50v\n",
customer.CustomerId,
customer.Company,
customer.Contact)
js, err := json.Marshal(customer)
e(err)
fmt.Println(string(js))
}
fmt.Println("--------------------")
}
func ScanIntoSlice(connection string) {
fmt.Println("Scan into slice sample")
fmt.Println("--------------------")
start := time.Now()
db, err := sqlx.Open("mssql", connection)
e(err)
defer db.Close()
customers := []Customer{}
err = db.Select(&customers, `select customerID, companyName, contactName from customers`)
e(err)
for i, customer := range customers {
fmt.Printf("%3d. %-10s %-50v %-50v\n",
i,
customer.CustomerId,
customer.Company,
customer.Contact)
}
js, err := json.Marshal(customers)
e(err)
fmt.Println(string(js))
fmt.Printf("%s", time.Since(start))
fmt.Println("--------------------")
}
func e(err error) {
if err != nil {
log.Fatal(err)
}
}

Retrieve a record from mysql in golang using database/sql

I'm trying to retrieve a record from mysql table and marshal it to json.
But i gotted the error that says : ".\main.go:67: no new variables on left sife of :="
I'm new in Golang Plz! help me to solve out this error!
My Code is :
func GetUser(w http.ResponseWriter, r *http.Request) {
urlParams := mux.Vars(r)
id := urlParams["id"]
ReadUser := User{}
con, err := sql.Open("mysql", "root:YES#/social_network?charset=utf8")
err := con.QueryRow("select * from users where user_id=?",id).Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email )
switch {
case err == sql.ErrNoRows:
fmt.Fprintf(w,"No such user")
case err != nil:
log.Fatal(err)
default:
output, _ := json.Marshal(ReadUser)
fmt.Fprintf(w,string(output))
}
}
and Routes in main:
func main() {
gorillaRoute := mux.NewRouter()
gorillaRoute.HandleFunc("/api/user/create", CreateUser)
gorillaRoute.HandleFunc("/api/user/read/:id", GetUser)
http.Handle("/", gorillaRoute)
http.ListenAndServe(":8080", nil)
}
Here is my new Code , but again not able to get record from database table, plz help me to figure out the error OR what things i do wrong?
package main
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
_ "github.com/go-sql-driver/mysql"
"github.com/gorilla/mux"
)
type API struct {
Message string "json:message"
}
type User struct {
ID int "json:id"
Name string "json:username"
Email string "json:email"
First string "json:first"
Last string "json:last"
}
func Hello(w http.ResponseWriter, r *http.Request) {
// urlParams := mux.Vars(r)
// name := urlParams["user"]
HelloMessage := "User Creation page"
message := API{HelloMessage}
output, err := json.Marshal(message)
if err != nil {
fmt.Println("Something went wrong!")
}
fmt.Fprintf(w, string(output))
}
//POST A USER INTO DB
func CreateUser(w http.ResponseWriter, r *http.Request) {
NewUser := User{}
NewUser.Name = r.FormValue("user")
NewUser.Email = r.FormValue("email")
NewUser.First = r.FormValue("first")
NewUser.Last = r.FormValue("last")
output, err := json.Marshal(NewUser)
fmt.Println(string(output))
if err != nil {
fmt.Println("Something went wrong!")
}
con, err := sql.Open("mysql", "root:YES#/social_network?charset=utf8")
sqlQuery := "INSERT INTO users set user_nickname='" + NewUser.Name + "', user_first='" + NewUser.First + "', user_last='" + NewUser.Last + "', user_email='" + NewUser.Email + "'"
q, err := con.Exec(sqlQuery)
if err != nil {
fmt.Println(err)
}
fmt.Println(q)
}
//GET USERS FROM DB
func GetUsers(w http.ResponseWriter, r *http.Request) {
db, err := sql.Open("mysql", "root:YES#/social_network?charset=utf8")
if err != nil {
panic(err)
}
err = db.Ping()
if err != nil {
panic(err)
}
defer db.Close()
rows, err := db.Query("select * from users ")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
var rowBuf, _ = rows.Columns()
var cols = make([]string, len(rowBuf))
copy(cols, rowBuf)
fmt.Println(rowBuf)
var vals = make([]interface{}, len(rowBuf))
for i, _ := range rowBuf {
vals[i] = &rowBuf[i]
}
for rows.Next() {
err := rows.Scan(vals...)
if err != nil {
log.Fatal(err)
}
var m = map[string]interface{}{}
for i, col := range cols {
m[col] = vals[i]
}
obj, _ := json.Marshal(m)
//
fmt.Fprintf(w, string(obj))
}
err = rows.Err()
if err != nil {
log.Fatal(err)
}
}
func GetUser(w http.ResponseWriter, r *http.Request) {
urlParams := mux.Vars(r)
id := urlParams["id"]
ReadUser := User{}
db, err := sql.Open("mysql", "root:YES#/social_network?charset=utf8")
stmt := db.QueryRow("select * from users where id = ?", id)
if err != nil {
log.Fatal(err)
}
err = stmt.Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email)
if err != nil {
log.Fatal(err)
}
result, err := json.Marshal(ReadUser)
fmt.Fprintf(w, string(result))
}
func main() {
gorillaRoute := mux.NewRouter()
gorillaRoute.HandleFunc("/api/user/create", CreateUser)
gorillaRoute.HandleFunc("/api/user/read", GetUsers)
gorillaRoute.HandleFunc("/api/user/:id", GetUser)
http.Handle("/", gorillaRoute)
http.ListenAndServe(":8080", nil)
}
Remove the colon : from err := as you are assigning a new value to existing variable.