Unable to scan type of uuid.UUID into UUID in sqlmock Golang - go

I have the following test function.
func (s *Suite) Test_delete() {
var (
id = uuid.New()
name = "test"
quantity = 2
)
s.mock.ExpectQuery(regexp.QuoteMeta(
`SELECT * FROM "items" WHERE code = $1 AND "items"."deleted_at" IS NULL`,
)).
WithArgs(id).
WillReturnRows(sqlmock.NewRows([]string{"code", "name", "quantity"}).
AddRow(id, name, quantity))
err := s.repository.DeleteItem(id.String())
require.NoError(s.T(), err)
}
Now the problem is trying to scan the id variable into the row for the column code. In my Product struct, I have code defined as follows.
type Item struct {
Code uuid.UUID `gorm:"type:uuid;primaryKey" json:"code"`
Name string `json:"name" validate:"required"`
Quantity int `json:"qty" validate:"required,min=0"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
}
func (i *Item) BeforeCreate(tx *gorm.DB) (err error) {
if i.Code == uuid.Nil {
i.Code = uuid.New()
}
return
}
Now the problem is when I try to run the test function, it is somehow unable to scan uuid.UUID into UUID even though they are both the same types. Here is the exact error message.
msql: Scan error on column index 0, name "code": Scan: unable to scan type uuid.UUID into UUID
Could someone help me on this part?

Read this. I assume there is type casting error. Changing WillReturnRows(sqlmock.NewRows([]string{"code", "name", "quantity"}).AddRow(id, name, quantity))->WillReturnRows(sqlmock.NewRows([]string{"code", "name", "quantity"}).AddRow(id.String(), name, quantity)) may help.

Related

How to add value before create using gorm?

I have this post.go model
package models
type Post struct {
Id uint `json:"ID"`
Name string `json:"Name"`
Message string `gorm:"type:text; index" json:"Message"`
Status string `gorm:"type:varchar(255); index" json:"Status"`
Desc string `gorm:"type:text; index" json:"Desc"`
}
func (p *Post) BeforeCreate() (err error) {
p.Status = "todo"
return nil
}
I need when I create any record by default put the status into the todo value
in my controller:
config.DB.Model(&models.Post{}).Create(&posts)
The result is I got a null value in status in the database
BeforeCreate interface signature is incorrect it should be BeforeCreate(*gorm.DB) error
func (p *Post) BeforeCreate(tx *gorm.DB) (err error) {
p.Status = "todo"
return nil
}
Another way would be to add default-values to the post struct
type Post struct {
Id uint `json:"ID"`
Name string `json:"Name"`
Message string `gorm:"type:text; index" json:"Message"`
Status string `gorm:"type:varchar(255); index; default: todo" json:"Status"`
Desc string `gorm:"type:text; index" json:"Desc"`
}
Output:
db.Create(&Post{}) // INSERT INTO `posts` (`name`,`message`,`status`,`desc`) VALUES ("","","todo","") RETURNING `id`

Golang Pointer Understanding

I am learning go and i need to understand something. I am getting few errors. I have created a Product struct and attached a func with it. I also got a product lists as a slice. Actually I am following one example. I was just trying add different endpoints to it.
I have added question in comment in code. Please explain. I need to return the json single object as a response to user. Please guide me.
package data
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Price float32 `json:"price"`
SKU string `json:"sku"`
CreatedOn string `json:"-"`
UpdatedOn string `json:"-"`
DeletedOn string `json:"-"`
}
type Products []*Product
func (p *Products) ToJSON(w io.Writer) error {
e := json.NewEncoder(w)
return e.Encode(p)
}
func (p *Product) FromJSON(r io.Reader) error {
d := json.NewDecoder(r)
return d.Decode(p)
}
var ErrProductNotFound = fmt.Errorf("Product not found")
func GetProduct(id int) (*Product, error) { // this is returning *Product & err. When I use this in GetProduct in handler func it is giving error
for _, p := range productList {
if p.ID == id {
fmt.Println(p)
return p, nil
}
}
return nil, ErrProductNotFound
}
var productList = []*Product{ **// Why in example the teacher doing it like this.** []*Product{&Product{}, &Product{}} **what it the reason? Please explain.
&Product{ // this gives warning : redundant type from array, slice, or map composite literal. need to understand why**
ID: 1,
Name: "Latte",
Description: "chai",
Price: 2.45,
SKU: "abc123",
CreatedOn: time.Now().UTC().String(),
UpdatedOn: time.Now().UTC().String(),
},
&Product{
ID: 2,
Name: "Tea",
Description: "chai",
Price: 1.45,
SKU: "abc1234",
CreatedOn: time.Now().UTC().String(),
UpdatedOn: time.Now().UTC().String(),
},
}
package handlers
func (p *Product) GetProduct(rw http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, _ := strconv.Atoi(vars["id"])
p, errr := data.GetProduct(id) **// cannot use data.GetProduct(id) (value of type *data.Product) as *Product value in assignment**
errr = p.ToJSON(rw) // **p.ToJSON undefined (type *Product has no field or method ToJSON)**
if errr != nil {
http.Error(rw, "could not locate the product", http.StatusBadGateway)
}
}
cannot use data.GetProduct(id) (value of type *data.Product) as *Product value in assignment
p.ToJSON undefined (type *Product has no field or method ToJSON)
The problem here is that inside the GetProduct handler the variable p already has a type (*handlers.Product) that is different from the one returned by the data.GetProduct function (*data.Product). So what you can do is to use a different name for the variable that will store the result of data.GetProduct.
Why in example the teacher doing it like this. []*Product{&Product{}, &Product{}} what it the reason? Please explain.
In general because that's one of the available methods for how to initialize a slice of structs, as per the language spec. Why the teacher used this method specifically? Unless the teacher confided the reason to someone, then no one would know, I certainly don't.
this gives warning : redundant type from array, slice, or map composite literal. need to understand why
Because it's true, it is redundant, as per the language spec, in a composite literal expression you can elide the types of the elements and keys.
For example a non-redundant version of the following composite literal:
[]*Product{&Product{}, &Product{}}
would look like this:
[]*Product{{}, {}}
and the result of these two expressions would be the same.

Gorm WHERE clause not working on Preload data

This query here below works, where the where clause works becuase it's using values from ResourceUsage struct, but I would love to be able to do something like this, where the where clause is using value from the ResourceMetadata struct.
db.Preload("ResourceMetadata").Where("resource_type = ?", resourceType).Where("timestamp BETWEEN ? AND ?", start, end).Limit(10).Find(&resourceUsage)
But it throws exception:
2019-12-03 11:06:12] Error 1054: Unknown column 'resource_type' in 'where clause'
Code:
// ResourceUsage describes the storage model for resource-usage
type ResourceUsage struct {
ID int64 `json:"-"`
DetailsID int64 `json:"details_id"`
ResourceMetadata *ResourceMetadata `gorm:"foreignkey:DetailsID;association_foreignkey:ID"`
MeasuredType string `json:"measured_type"`
Quantity float64 `json:"quantity"`
Timestamp int64 `json:"timestamp"`
}
// ResourceMetadata describes the storage model for resource-usage
type ResourceMetadata struct {
ID int64 `json:"-"`
ResourceUUID string `json:"resource_uuid"`
ResourceName string `json:"resource_name"`
ResourceDisplayName string `json:"resource_display_name"`
ResourceType string `json:"resource_type"`
}
db.Preload("ResourceMetadata").Where("timestamp BETWEEN ? AND ?", start, end).Limit(10).Find(&resourceUsage)
Can you use a JOIN?
resourceUsages := []ResourceUsage{}
if err := db.Joins("JOIN resource_metadata ON resource_metadata.id=details_id").
Where("resource_metadata.resource_type = ? AND timestamp BETWEEN ? AND ?", resourceType, start, end).
Preload("ResourceMetadata").Limit(10).
Find(&resourceUsages).Error; err != nil {
// ... handle error ...
}

Getting "Not found" when trying to use updateId()

I am very new to golang. I decided to write a simple REST application. I am using MongoDB as a backend.
The POST and GET APIs are working as expected. However, when writing an API on which I want to do a PUT operation by given id, I am getting an error saying the id is "not found"
Any advice?
type Task struct {
ID bson.ObjectId `bson:"_id,omitempty" json:"id"`
Name string `bson:"name" json:"name"`
Desc string `bson:"desc" json:"desc"`
}
var Tasks = new(tasks)
type tasks struct{}
func (tasks) Update(id, name, desc string) error {
if err := common.DB.Tasks.UpdateId(bson.IsObjectIdHex(id),
bson.M{"$set": bson.M{
"name": name,
"desc": desc,
}}); err != nil {
return err
}
return nil
}
package common
import(
"gopkg.in/mgo.v2"
)
type mongo struct {
Tasks *mgo.Collection
}
var DB *mongo

"Has many" relation giving empty result

I am trying to define one to many relation with gorm ORM . I have read all the docs over and over again . Could not find a way to do it.
func GetUser1(c *gin.Context) {
var user models.User
var activities models.UserActivity
query := DB.Debug().Find(&user, 1).Model(&user).Related(&activities).Error
if query != nil {
panic(query)
}
c.JSON(200, &user)
}
My Models are ..
type User struct {
Id int64
Username string
Password string `json:"-"`
Email string `json:",omitempty"`
UserActivities []UserActivity
}
type UserActivity struct {
Id int64
UserId int64 `json:"-"`
ActorId int64
CreatedAt time.Time
}
Debug Results are
[2015-11-21 22:21:54] [3.17ms] SELECT * FROM `users` WHERE (`id` = '1')
[2015-11-21 22:21:54] [1.39ms] SELECT * FROM `user_activities` WHERE (`user_id` = '1')
But I am getting null results
{
"Id": 1,
"Username": "test1",
"Email": "test1#friesen.com",
"UserActivities": null
}
All the primary keys and Indexes are right . I have also tried puttin gorm:"primary_key" and sql:"index" in UserActivities no luck so far .
However if I replace UserActivities []UserActivity with UserActivities UserActivity then i get only one row which seems to be right but why UserActivities []UserActivity giving no results
use gorm built in model gorm.Model so that your not messing up the "ID" constant
The solution to your problem is very simple.
Rather than querying
var user models.User
var activities models.UserActivity
query := DB.Debug().Find(&user, 1).Model(&user).Related(&activities).Error
just query
var user models.User
query := DB.Debug().Find(&user, 1).Model(&user).Related(&user.UserActivities).Error

Resources