Update with 0 value using Gorm - mysql

I am trying to update some values using gorm library but bytes and ints with 0 value are not updated
var treatment model.TreatmentDB
err = json.Unmarshal(b, &treatment)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
fmt.Println(&treatment)
db := db.DB.Table("treatment").Where("id = ?", nID).Updates(&treatment)
this print value is {0 3 1 0 0 0 2018-01-01 4001-01-01} and those 0 are the byte value (tinyint(1) in database, if I change to int also not working) which are not updated, the rest of values work fine
if I update them without using Gorm this way it's working perfectly with 0 values
var query = fmt.Sprintf("UPDATE `pharmacy_sh`.`treatment` SET `id_med` = '%d', `morning` = '%d', `afternoon` = '%d', `evening` = '%d', `start_treatment` = '%s', `end_treatment` = '%s' WHERE (`id` = '%s')", treatment.IDMed, treatment.Morning, treatment.Afternoon, treatment.Evening, treatment.StartTreatment, treatment.EndTreatment, nID)
update, err := dbConnector.Exec(query)
and this is my model obj
type TreatmentDB struct {
gorm.Model
ID int `json:"id"`
IDMed int `json:"id_med"`
IDUser int `json:"id_user"`
Morning byte `json:"morning"`
Afternoon byte `json:"afternoon"`
Evening byte `json:"evening"`
StartTreatment string `json:"start_treatment"`
EndTreatment string `json:"end_treatment"`
}
Thanks for any help!!

I found a very tricky way to solve this problem.You just need to change your struct field type into a ptr.
change
type Temp struct{
String string
Bool bool
}
to
type Temp struct{
String *string
Bool *bool
}

if you wish save zero you must to write "Select" and put the column to change
db.Model(&user).Select("Name", "Age").Updates(User{Name: "new_name", Age: 0})
reference: https://gorm.io/docs/update.html#Update-Selected-Fields

Related

How to save a record in a controller to two different tables in go

People, I am trying to save an employee in the employee table, it already saves and everything is fine, the problem is when I try to save the schedule that is related to another table where schedule_id is the foreign of the employee table and is related to the id of the time table, this is the code:
Controlador
func Save(writer http.ResponseWriter, request *http.Request) {
employe := models.Employe{}
db := common.GetConnection()
error := json.NewDecoder(request.Body).Decode(&employe)
if error != nil {
log.Fatal(error)
common.SendError(writer, http.StatusBadRequest)
return
}
randomBytes := make([]byte, 2)
_, err := rand.Read(randomBytes)
if err != nil {
log.Fatal(error)
common.SendError(writer, http.StatusBadRequest)
return
}
employe.PinEmploye = hex.EncodeToString(randomBytes)
horary := models.Employe{Arrival: employe.Arrival, Departure: employe.Departure}
error = db.Save(&horary).Error
if error != nil {
log.Fatal(error)
common.SendError(writer, http.StatusInternalServerError)
return
}
employe.ScheduleId = horary.ID
error = db.Save(&employe).Error
if error != nil {
log.Fatal(error)
common.SendError(writer, http.StatusInternalServerError)
return
}
json, _ := json.Marshal(employe)
common.SendResponse(writer, http.StatusCreated, json)
fmt.Println(employe)
}
structs
type Employe struct {
ID int `json:"id" gorm:"primary_key;auto_increment"`
PinEmploye string `json:"pinEmploye" gorm:"FOREIGNKEY:PinEmploye" `
FirstName string `json:"first_name" `
LastName string `json:"last_name"`
Company string `json:"company"`
Position string `json:"position"`
ScheduleId int `json:"schedule_id"`
// Arrival time.Time `json:"arrival"`
// Departure time.Time `json:"departure"`
CreatedAt time.Time `json:"fechacreacion"`
}
Horary:
type Horary struct {
ID int `json:"id" gorm:"primary_key;auto_increment"`
Arrival time.Time `json:"arrival"`
Departure time.Time `json:"departure"`
}
I tried to do it with entities but I still don't know very well about the subject
type Employe struct {
ID int `json:"id" gorm:"primary_key;auto_increment"`
PinEmploye string `json:"pinEmploye" gorm:"FOREIGNKEY:PinEmploye" `
FirstName string `json:"first_name" `
LastName string `json:"last_name"`
Company string `json:"company"`
Position string `json:"position"`
ScheduleId int `json:"schedule_id"`
CreatedAt time.Time `json:"fechacreacion"`
}
I have tried with entity model but still can't do it, I tried to do it with chatGPT but still can't

MySQL Query returning empty result

I have a simple SELECT statement which calls all of the columns in my coupon table by who_added.
code:
func CouponByUserID(c *gin.Context) {
fmt.Println("CouponByUserID()")
lCoupon := []model.Coupon{}
whoAdded := c.PostForm("whoAdded")
fmt.Println("whoAdded: " + whoAdded)
var sqlSel = ""
sqlSel = sqlSel + " SELECT * FROM coupon WHERE who_added = ? "
fmt.Println("sqlSel")
fmt.Println(sqlSel)
_, err := dbmap.Select(&lCoupon, sqlSel, whoAdded)
if err == nil || lCoupon != nil {
fmt.Println("got result")
fmt.Println(lCoupon)
c.Header("Content-Type", "application/json")
c.JSON(http.StatusOK, lCoupon)
} else {
fmt.Println("coupon not found")
c.JSON(404, gin.H{"error": "coupon not found"})
}
}
Coupon Model:
type Coupon struct {
CouponID int64 `db:"coupon_id, primarykey, autoincrement"`
CouponName string `db:"coupon_name,omitempty"`
CouponCode string `db:"coupon_code,omitempty"`
Description string `db:"description,omitempty"`
Status string `db:"status,omitempty"`
CampaignStart int64 `db:"campaign_start,omitempty"`
CampaignEnd int64 `db:"campaign_end,omitempty"`
SourceType string `db:"source_type,omitempty"`
Preview string `db:"preview,omitempty"`
CouponFormat string `db:"coupon_format,omitempty"`
PreviewType string `db:"preview_format,omitempty"`
Display string `db:"display,omitempty"`
DisplayType string `db:"display_format,omitempty"`
Width float64 `db:"width,omitempty"`
Height float64 `db:"height,omitempty"`
WhoAdded int `db:"who_added,omitempty"`
WhenAdded int `db:"when_added,omitempty"`
WhoUpdated int `db:"who_updated,omitempty"`
WhenUpdated int `db:"when_updated,omitempty"`
TermsAndCondition string `db:"terms_and_condition,omitempty"`
CouponLocation string `db:"coupon_location,omitempty"`
BusID string `db:"bus_id,omitempty"`
ImgCoupon string `db:"img_coupon,omitempty"`
}
Result:
As you can see here it's empty even if my table has data.
Problem: Data on my table is not showing in the result.
I tried to query the same statement on MySQL workbench and it's work just fine.
Where did I go wrong?

sql: Scan error on column index 6, name "scheduled_date": null: cannot scan type []uint8 into null.Time

I get this error and tried everything available in the internet and stackoverlow to solve this. I am trying to run a query after connecting MySQL db using sqlx package and scan through the results. I have tried the solutions shared for similar questions but nothing worked for me.
type Trip struct {
ID int `db:"id"`
Type int `db:"type"`
DID int `db:"did"`
DUID int `db:"duid"`
VID int `db:"vid"`
Sts string `db:"sts"`
AM int `db:"am"`
Sdate null.Time `db:"sdate"`
}
func GetTripByID(db sqlx.Queryer, id int) (*Trip, error) {
row := db.QueryRowx("select ID,Type,DID,DUID,VID,Sts,AM,Sdate from mytbl where ID=123", id)
var t Trip
err := row.StructScan(&t)
if err != nil {
fmt.Println("Error during struct scan")
return nil, err
}
return &t, nil
}
The exact error that I get is
panic: sql: Scan error on column index 6, name "sdate": null:
cannot scan type []uint8 into null.Time: [50 48 49 56 45 49 50 45 48
55 32 48 50 58 48 56 58 53 49]
syntax wise the query is working perfectly fine and I am getting results when I run it in sql workbench. I have also tried ParseTime=true as suggested by one of the one of the links.
Try to use special types for null values in package "database/sql"
For example, when text or varchar can be null in db, use sql.NullString for var type.
As suggested above, I did null handling for the column "Sdate"
// NullTime defining nullTime
type NullTime mysql.NullTime
// Scan implements the Scanner interface for NullTime
func (nt *NullTime) Scan(value interface{}) error {
var t mysql.NullTime
if err := t.Scan(value); err != nil {
return err
}
// if nil then make Valid false
if reflect.TypeOf(value) == nil {
*nt = NullTime{t.Time, false}
} else {
*nt = NullTime{t.Time, true}
}
and changes in the struct
type Trip struct {
ID int `db:"id"`
Type int `db:"type"`
DID int `db:"did"`
DUID int `db:"duid"`
VID int `db:"vid"`
Sts string `db:"sts"`
AM int `db:"am"`
Sdate NullTime `db:"sdate"`
}
so the solution is not just defining the struct for handling null but also implementing the scanner interface.

Golang Mysql scan returns zeros, when data is there?

Having a bit of a head scratcher moment. I've got the following struct:
type Room struct {
ID int
Name string
RoomType int
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt time.Time
GroupId int
BlockId int
ProjectId int
RoomLength float64
RoomWidth float64
CeilingHeight float64
CeilingColorHex string
WallColorHex string
FloorColorHex string
CeilingColorRgb string
WallColorRgb string
FloorColorRgb string
}
Reading it out in rest api with:
database := db.New()
stmt, err := database.Prepare("SELECT * FROM room WHERE block_id = ?")
if err != nil {
panic(err)
}
defer stmt.Close()
rows, err := stmt.Query(c.Param("id"))
if err != nil {
panic(err)
}
defer rows.Close()
var rooms []common.Room
for rows.Next() {
var r common.Room
err := rows.Scan(&r.ID, &r.Name, &r.RoomType, &r.CreatedAt, &r.UpdatedAt, &r.DeletedAt,
&r.GroupId, &r.BlockId, &r.ProjectId, &r.RoomLength, &r.RoomWidth, &r.CeilingHeight,
&r.CeilingColorHex, &r.WallColorHex, &r.FloorColorHex, &r.CeilingColorRgb, &r.WallColorRgb,
&r.FloorColorRgb)
if err = rows.Err(); err != nil {
panic(err)
}
fmt.Printf("Found: %v", r)
rooms = append(rooms, r)
}
Yet, the resulting payload is:
{3 Loki #1 3 2018-09-25 08:42:38 +0000 UTC 2018-09-25 14:52:39 +0000 UTC 0001-01-01 00:00:00 +0000 UTC 0 0 0 0 0 0 }
I'm specifically after the length/width, which (above) are 0. Yet in the db:
mysql> select * from room where id = 3 \G
*************************** 1. row ***************************
id: 3
name: Loki #1
room_type: 3
created_at: 2018-09-25 08:42:38
updated_at: 2018-09-25 14:52:39
deleted_at: NULL
group_id: 0
block_id: 1
project_id: 0
room_length: 10
room_width: 7
ceiling_height: 4
ceiling_color_hex: #c0c0c0
wall_color_hex: #a9a9a9
floor_color_hex: #708090
ceiling_color_rgb: 192,192,192
wall_color_rgb: 169,169,169
floor_color_rgb: 112,128,144
1 row in set (0.00 sec)
I thought it may have something to do with differing types, but after changing them in the db, and then in code, no change. Can anyone explain why .Scan isn't picking up certain values?
Thanks!
First of all, check the error which come from rows.Scan(). You only check the error from rows.Err() which is a different kind of error, and not related to the scan.
err := rows.Scan(&r.ID, &r.Name, &r.RoomType, &r.CreatedAt, &r.UpdatedAt, &r.DeletedAt,
&r.GroupId, &r.BlockId, &r.ProjectId, &r.RoomLength, &r.RoomWidth, &r.CeilingHeight,
&r.CeilingColorHex, &r.WallColorHex, &r.FloorColorHex, &r.CeilingColorRgb, &r.WallColorRgb,
&r.FloorColorRgb)
if err != nil {
panic(err) // Error related to the scan
}
if err = rows.Err(); err != nil {
panic(err) // Error related to the iteration of rows
}
When the value from deleted_at is return as NULL, Scan will return an error such as unsupported Scan, storing driver.Value type <nil> into type *time.Time and the rest of your struct will get zero values.
It means that your room struct has to change to use a pointer to time.
CreatedAt *time.Time
UpdatedAt *time.Time
DeletedAt *time.Time
However, you may need to add into you sql.Open() the parameter parseTime sql.Open("mysql", "user:password#/dbname?parseTime=true) to parse the time correctly for mysql.
You should then received a valid *time.Time when it is set, or nil when it is NULL.

golang grouping in mysql query

I have a mysql query, struct and code like that:
sqlQuery := "SELECT group_concat(Id), Title from Tbl WHERE SomeField = 3 GROUP BY Title ORDER BY Title LIMIT 20;"
type SomeStruct struct {
IDs []int `json:"ids"`
Title string `json:"title"`
SomeField int `json:"somefield"`
}
type SomeMap map[string]interface{}
var SomeObject []SomeMap
row, err := db.Query(sqlQuery)
checkErr(err)
for row.Next() {
var ids []int
var title string
var somefield int
err = row.Scan(&ids, &title, &somefield)
someMap := SomeMap{"ids":ids, "title": title, "somefield": somefield}
someObject = append(SomeObject, someMap)
}
How can I unmashal my object to struct where IDs look like []int type because golang tells that it might be []uint8 ??