Home > other >  Build query conditionally and keeping the common part to execute differently
Build query conditionally and keeping the common part to execute differently

Time:11-05

Trying to figure out how can I build query conditionally using gorm, save the common query part and execute it.

Suppose I am querying list of courses like below.

common_query_part := app.GetDB(). // <= this returns *gorm.DB
        Model(&models.Course{}).
        Where("status=?", models.CourseStatusPublished) //models.CourseStatusPublished is a constant

Now I would like to get the list of published courses. And also get its count. So I tried it like so.

published_course_count := *common_query_part

and then for the course list

   result := common_query_part.
                 Offset(offset).
                 Limit(limit).
                 find(&courses)
   
       if result.Error !=nil {
         //handle error
       } 

and for the count

result = published_course_count.Count(&total)
       
if result.Error !=nil {
             //handle error
           } 

The first part works perfectly. But second part of the query does not work, nor even generate any error. What should I do in this case? The common query part can be huge and complex. So rewriting it again just for getting the count can be error prone. So is there a way where I will keep the common query part and execute it sometimes for published courses.. sometimes for published courses count?

CodePudding user response:

I don't believe GORM intends you to reuse your query that way. It is hard to say definitively but it most likely doesn't work because there is some state that is still shared.

This: published_course_count := *common_query_part does a copy by value of the gorm.DB struct, but if that struct contain any pointers(it does) then those are copied as well resulting in two separate struct with pointer to the same objects and thus still being "linked". You need a dedicated clone function, which does exist in gorm but is not exposed.

I would advise you to put the generation of the common part inside a function and call it twice, that way you don't have to copy-paste the same query.

func common_query_part() *gorm.DB {
    return app.GetDB().
        Model(&models.Course{}).
        Where("status=?", models.CourseStatusPublished)
}
  • Related